commit 42c7dc5ba79becc77d3c9f0faf1e7c62c33ecbca Author: Joey Hines Date: Fri Sep 6 14:31:06 2024 -0600 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/dial.iml b/.idea/dial.iml new file mode 100644 index 0000000..cf84ae4 --- /dev/null +++ b/.idea/dial.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..518fd17 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4262659 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2ba94ae --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,363 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytemuck" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "dial" +version = "0.1.0" +dependencies = [ + "log", + "macroquad", +] + +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + +[[package]] +name = "fontdue" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0793f5137567643cf65ea42043a538804ff0fbf288649e2141442b602d81f9bc" +dependencies = [ + "hashbrown", + "ttf-parser", +] + +[[package]] +name = "glam" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "image" +version = "0.24.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "num-traits", + "png", +] + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "macroquad" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fef16b2d4de22ac372b5d7d76273c0ead0a31f9de9bc649af8f816816db8a8" +dependencies = [ + "fontdue", + "glam", + "image", + "macroquad_macro", + "miniquad", + "quad-rand", + "slotmap", +] + +[[package]] +name = "macroquad_macro" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b1d96218903768c1ce078b657c0d5965465c95a60d2682fd97443c9d2483dd" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "miniquad" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2124e5e6bab86d96f263d78dc763c29e0da4c4f7ff0e1bb33f1d3905d1121262" +dependencies = [ + "libc", + "ndk-sys", + "objc", + "winapi", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "ndk-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.7.4", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quad-rand" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658fa1faf7a4cc5f057c9ee5ef560f717ad9d8dc66d975267f709624d6e1ab88" + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "ttf-parser" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..816a4a3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "dial" +version = "0.1.0" +edition = "2021" + +[dependencies] +macroquad = "0.4.13" +log = "0.4.22" diff --git a/index.html b/index.html new file mode 100644 index 0000000..0d138f4 --- /dev/null +++ b/index.html @@ -0,0 +1,29 @@ + + + + + TITLE + + + + + + + + + + + \ No newline at end of file diff --git a/src/disc.rs b/src/disc.rs new file mode 100644 index 0000000..b2741dc --- /dev/null +++ b/src/disc.rs @@ -0,0 +1,99 @@ +use macroquad::logging::info; +use std::f32::consts::PI; +use std::fmt::Debug; + +#[derive(Debug, Clone)] +pub struct Disc { + pub letter_map: Vec, +} + +impl Default for Disc { + fn default() -> Self { + let mut letters = ('a'..='z').into_iter().collect::>(); + let mut numbers = ('0'..='9').into_iter().collect::>(); + + letters.append(&mut numbers); + + Self { + letter_map: letters, + } + } +} + +#[derive(Debug, Clone, Default)] +pub struct DecoderState { + pub inner_disc: Disc, + pub outer_disc: Disc, + pub outer_disc_index: usize, + pub outer_disc_current_angle: f32, +} + +impl DecoderState { + pub fn set_index(&mut self, index: usize) { + self.outer_disc_index = index; + } + + pub fn change_index(&mut self, diff: i32) { + let new_index = (((self.outer_disc_index as i32) + diff) + .rem_euclid(self.outer_disc.letter_map.len() as i32)) as usize; + + info!("New Index: {}", new_index); + self.set_index(new_index); + } + + pub fn get_angle_per_letter(&self) -> f32 { + (2.0 * PI) / (self.outer_disc.letter_map.len() as f32) + } + + pub fn get_current_target_angle(&self) -> f32 { + self.get_angle_per_letter() * (self.outer_disc_index as f32) + } + + pub fn get_outer_letter_at_index(&self, index: usize) -> char { + let index = (index as i32 - self.outer_disc_index as i32) + .rem_euclid(self.outer_disc.letter_map.len() as i32) as usize; + self.outer_disc.letter_map[index] + } + + pub fn get_index_from_inner_letter(&self, c: char) -> usize { + self.inner_disc + .letter_map + .iter() + .position(|n| *n == c) + .unwrap() + } + + pub fn get_index_from_outer_letter(&self, c: char) -> usize { + let norm_index = self + .outer_disc + .letter_map + .iter() + .position(|n| *n == c) + .unwrap(); + + let index = (norm_index as i32 + self.outer_disc_index as i32) + .rem_euclid(self.outer_disc.letter_map.len() as i32) as usize; + + return index; + } + + pub fn get_inner_letter_at_index(&self, index: usize) -> char { + self.inner_disc.letter_map[index] + } + + pub fn encode(&mut self, in_char: char) -> char { + let index = self.get_index_from_inner_letter(in_char); + + let char = self.get_outer_letter_at_index(index); + + return char; + } + + pub fn decode(&mut self, in_char: char) -> char { + let index = self.get_index_from_outer_letter(in_char); + + let char = self.get_inner_letter_at_index(index); + + return char; + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..380b18b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,564 @@ +mod disc; + +use crate::disc::{DecoderState, Disc}; +use macroquad::prelude::*; +use std::f32::consts::PI; +use std::string::ToString; + +const SHADOW: Color = Color::new(0.25, 0.25, 0.25, 0.5); + +const GAME_NAME: &str = "dial"; + +pub struct Context { + decoder_state: DecoderState, + input_state: DecoderState, + mode: Mode, +} + +#[derive(Eq, PartialEq)] +pub enum Mode { + Encode, + Decode, +} + +pub fn conf() -> Conf { + Conf { + window_title: GAME_NAME.to_string(), + high_dpi: true, + fullscreen: true, + ..Default::default() + } +} + +pub fn game_init() { + info!("Starting {}", GAME_NAME); +} + +pub fn rotate_vec2(vec: Vec2, angle: f32) -> Vec2 { + Mat2::from_angle(angle) * vec +} + +pub fn draw_display(pos: Vec2, size: Vec2, text: &str, font_size: f32) { + let text_center = get_text_center(text, None, font_size as u16, 1.0, 0.0); + + draw_rectangle_ex( + pos.x, + pos.y, + size.x, + size.y, + DrawRectangleParams { + rotation: 0.0, + color: BLACK, + ..Default::default() + }, + ); + + let text_pos = pos + size * 0.5 - text_center; + draw_text(text, text_pos.x, text_pos.y, font_size, SKYBLUE); +} + +pub fn draw_label(pos: Vec2, size: Vec2, text: &str, font_size: f32) { + let text_center = get_text_center(text, None, font_size as u16, 1.0, 0.0); + + draw_rectangle_ex( + pos.x, + pos.y, + size.x, + size.y, + DrawRectangleParams { + rotation: 0.0, + color: BLACK, + ..Default::default() + }, + ); + + let text_pos = pos + size * 0.5 - text_center; + draw_text(text, text_pos.x, text_pos.y, font_size, WHITE); +} + +pub fn draw_disc( + disc: &Disc, + base_pos: Vec2, + text_radius: f32, + radius: f32, + start_angle: f32, + color: Color, +) { + draw_circle( + base_pos.x + radius * 0.05, + base_pos.y + radius * 0.05, + radius, + SHADOW, + ); + draw_circle(base_pos.x, base_pos.y, radius, color); + draw_circle(base_pos.x, base_pos.y, radius * 0.10, BLACK); + draw_circle_lines( + base_pos.x, + base_pos.y, + radius - radius * 0.01, + radius * 0.025, + BLACK, + ); + + let len = disc.letter_map.len(); + + let angle_per_letter = (2.0 * PI) / (len as f32); + + let mut text_pos = Vec2::new(0.0, -text_radius); + let mut line_pos = Vec2::new(0.0, radius); + + let font_size = 30; + + let mut angle = start_angle; + + text_pos = rotate_vec2(text_pos, start_angle); + line_pos = rotate_vec2(line_pos, start_angle); + + for (ndx, letter) in disc.letter_map.iter().enumerate() { + let text_center = get_text_center(letter.to_string().as_str(), None, font_size, 1.0, angle); + let letter_pos = text_pos + base_pos - text_center; + + let mut line_pos_1 = rotate_vec2(line_pos, -angle_per_letter * 0.5); + line_pos_1 = line_pos_1 + base_pos; + let mut line_pos_2 = rotate_vec2(line_pos, angle_per_letter * 0.5); + line_pos_2 = line_pos_2 + base_pos; + + draw_line( + base_pos.x, + base_pos.y, + line_pos_1.x, + line_pos_1.y, + 2.0, + BLACK, + ); + draw_line( + base_pos.x, + base_pos.y, + line_pos_2.x, + line_pos_2.y, + 2.0, + BLACK, + ); + + if ndx == 0 { + draw_circle( + text_pos.x + base_pos.x, + text_pos.y + base_pos.y, + radius * 0.05, + GRAY, + ); + } + + draw_text_ex( + letter.to_string().as_str(), + letter_pos.x, + letter_pos.y, + TextParams { + font_size, + color: WHITE, + rotation: angle, + ..Default::default() + }, + ); + + text_pos = rotate_vec2(text_pos, angle_per_letter); + line_pos = rotate_vec2(line_pos, angle_per_letter); + angle += angle_per_letter; + } +} + +pub fn draw_switch(pos: Vec2, size: Vec2, mut state: bool) -> bool { + draw_circle(pos.x, pos.y, size.x * 0.5, BLACK); + + if is_mouse_in_area(pos - size * 0.5, size) { + state = !state; + } + + let rot = if state { 180.0_f32.to_radians() } else { 0.0 }; + + draw_rectangle_ex( + pos.x + (size.x * 0.07), + pos.y + (size.y * 0.1), + size.x * 0.33, + size.y, + DrawRectangleParams { + rotation: rot, + color: SHADOW, + offset: Vec2::new(0.5, 0.0), + }, + ); + + draw_rectangle_ex( + pos.x, + pos.y, + size.x * 0.33, + size.y, + DrawRectangleParams { + rotation: rot, + color: DARKBLUE, + offset: Vec2::new(0.5, 0.0), + }, + ); + + draw_rectangle_lines_ex( + pos.x, + pos.y, + size.x * 0.33, + size.y, + size.x * 0.025, + DrawRectangleParams { + rotation: rot, + color: BLACK, + offset: Vec2::new(0.5, 0.0), + }, + ); + + return state; +} + +pub fn is_mouse_in_area(pos: Vec2, size: Vec2) -> bool { + //draw_rectangle_lines(pos.x, pos.y, size.x, size.y, 5.0, RED); + + if is_mouse_button_pressed(MouseButton::Left) { + let lower_bound = pos; + let upper_bound = pos + size; + let mouse_pos: Vec2 = mouse_position().into(); + + let lower_bound_check = lower_bound.x <= mouse_pos.x && lower_bound.y <= mouse_pos.y; + let upper_bound_check = upper_bound.x >= mouse_pos.x && upper_bound.y >= mouse_pos.y; + + if lower_bound_check && upper_bound_check { + return true; + } + } + + false +} + +pub fn draw_device(ctx: &mut Context) { + let screen_height = screen_height(); + let screen_width = screen_width(); + + let width = screen_width * 0.33; + let height = screen_height * 0.9; + + let dev_x = screen_width * 0.5 - width * 0.5; + let dev_y = screen_height * 0.5 - height * 0.5; + + let size = Vec2::new(width, height); + let base_pos = Vec2::new(dev_x, dev_y); + + input_dial(&mut ctx.input_state, base_pos, size); + + draw_rectangle_ex( + dev_x, + dev_y, + width, + height, + DrawRectangleParams { + offset: Default::default(), + rotation: 0.0, + color: DARKGREEN, + }, + ); + + draw_rectangle_lines(dev_x, dev_y, width, height, dev_x * 0.005, BLACK); + + draw_rectangle_ex( + dev_x + width * 0.02, + dev_y + height * 0.015, + width * 0.68, + height * 0.05, + DrawRectangleParams { + offset: Default::default(), + rotation: 0.0, + color: LIGHTGRAY, + }, + ); + + draw_text( + "PROPERTY OF Foghaven Guard", + dev_x + width * 0.02, + dev_y + height * 0.05, + 50.0, + RED, + ); + + input_panel(ctx, base_pos, size); + + let next_button_pos = Vec2::new(size.x * 0.9, size.y * 0.4) + base_pos; + let next_button_size = Vec2::new(size.x * 0.1, size.x * 0.1); + + if is_mouse_in_area(next_button_pos - next_button_size * 0.5, next_button_size) { + if ctx.mode == Mode::Encode { + ctx.decoder_state.change_index(1); + } else { + ctx.decoder_state.change_index(-1); + } + } + + draw_circle( + next_button_pos.x + next_button_size.x * 0.05, + next_button_pos.y + next_button_size.y * 0.05, + next_button_size.x * 0.5, + SHADOW, + ); + draw_circle( + next_button_pos.x, + next_button_pos.y, + next_button_size.x * 0.5, + RED, + ); + + let base_pos = Vec2::new(dev_x + width * 0.5, dev_y + height * 0.66); + + if ctx.decoder_state.get_current_target_angle() - ctx.decoder_state.outer_disc_current_angle + > f32::EPSILON + { + ctx.decoder_state.outer_disc_current_angle += 1.0_f32.to_radians() * (get_time() as f32); + } else { + ctx.decoder_state.outer_disc_current_angle = ctx.decoder_state.get_current_target_angle(); + } + + draw_disc( + &ctx.decoder_state.outer_disc, + base_pos, + width * 0.40, + width * 0.45, + ctx.decoder_state.outer_disc_current_angle, + BROWN, + ); + + draw_disc( + &ctx.decoder_state.inner_disc, + base_pos, + width * 0.20, + width * 0.25, + 0.0, + GOLD, + ); + + let surplus_sticker_pos = Vec2::new(dev_x + width * 0.75, dev_y + height * 0.01); + let surplus_sticker_size = Vec2::new(width * 0.24, height * 0.06); + draw_rectangle_ex( + surplus_sticker_pos.x + surplus_sticker_size.x * 0.02, + surplus_sticker_pos.y + surplus_sticker_size.x * 0.02, + surplus_sticker_size.x, + surplus_sticker_size.y, + DrawRectangleParams { + offset: Default::default(), + rotation: 10.0_f32.to_radians(), + color: SHADOW, + }, + ); + + draw_rectangle_ex( + surplus_sticker_pos.x, + surplus_sticker_pos.y, + surplus_sticker_size.x, + surplus_sticker_size.y, + DrawRectangleParams { + offset: Default::default(), + rotation: 10.0_f32.to_radians(), + color: Color::new(0.25, 0.25, 0.25, 1.0), + }, + ); + draw_text_ex( + "(SURPLUS)", + dev_x + width * 0.75, + dev_y + height * 0.05, + TextParams { + font: None, + font_size: 50, + font_scale: 1.0, + font_scale_aspect: 1.0, + rotation: 10.0f32.to_radians(), + color: RED, + }, + ); +} + +fn input_dial(input_disc: &mut DecoderState, base: Vec2, size: Vec2) { + let dial_pos = Vec2::new(base.x + size.x * 0.15, base.y + size.y * 0.3); + + draw_disc( + &input_disc.outer_disc, + dial_pos, + size.y * 0.15, + size.y * 0.2, + input_disc.outer_disc_current_angle, + DARKGREEN, + ); + + let marker_pos = dial_pos + Vec2::new(-size.y * 0.11, 0.0); + draw_circle(marker_pos.x, marker_pos.y, size.y * 0.005, RED); + + if input_disc.get_current_target_angle() - input_disc.outer_disc_current_angle > f32::EPSILON { + input_disc.outer_disc_current_angle += 1.0_f32.to_radians() * (get_time() as f32); + } else { + input_disc.outer_disc_current_angle = input_disc.get_current_target_angle(); + } + + let click_area = Vec2::new(size.y * 0.1, size.y * 0.15); + let upper_click_pos = dial_pos - Vec2::new(size.y * 0.1, 0.0) - click_area; + let lower_click_pos = dial_pos - Vec2::new(size.y * 0.1, -click_area.y) - click_area; + + if is_mouse_in_area(upper_click_pos, click_area) { + input_disc.change_index(1); + } else if is_mouse_in_area(lower_click_pos, click_area) { + input_disc.change_index(-1); + } +} + +fn input_panel(ctx: &mut Context, base: Vec2, size: Vec2) { + let border_pos = Vec2::new(base.x + size.x * 0.05, base.y + size.y * 0.075); + let border_size = Vec2::new(size.x * 0.9, size.y * 0.25); + + draw_rectangle_ex( + border_pos.x + border_size.x * 0.01, + border_pos.y + border_size.y * 0.02, + border_size.x, + border_size.y, + DrawRectangleParams { + offset: Default::default(), + rotation: 0.0, + color: SHADOW, + }, + ); + + draw_rectangle_ex( + border_pos.x, + border_pos.y, + border_size.x, + border_size.y, + DrawRectangleParams { + offset: Default::default(), + rotation: 0.0, + color: GRAY, + }, + ); + + draw_rectangle_lines( + border_pos.x, + border_pos.y, + border_size.x, + border_size.y, + border_size.x * 0.005, + BLACK, + ); + + let input_letter_disp_loc = border_pos + Vec2::new(border_size.x * 0.05, border_size.x * 0.05); + let input_letter_size = Vec2::new(border_size.x * 0.10, border_size.y * 0.3); + + let input_letter = ctx + .input_state + .get_outer_letter_at_index(ctx.input_state.outer_disc.letter_map.len() * 3 / 4); + draw_display( + input_letter_disp_loc, + input_letter_size, + input_letter.to_string().as_str(), + 80.0, + ); + + let input_label_pos = input_letter_disp_loc + + Vec2::new( + input_letter_size.x + border_size.x * 0.05, + input_letter_size.y * 0.25, + ); + let input_label_size = Vec2::new(border_size.x * 0.2, border_size.y * 0.15); + draw_label(input_label_pos, input_label_size, "INPUT", 40.0); + + let index_disp_loc = + input_letter_disp_loc + Vec2::new(0.0, input_letter_size.y + border_size.x * 0.05); + draw_display( + index_disp_loc, + input_letter_size, + ctx.decoder_state.outer_disc_index.to_string().as_str(), + 80.0, + ); + + let index_label_pos = index_disp_loc + + Vec2::new( + input_letter_size.x + border_size.x * 0.05, + input_letter_size.y * 0.25, + ); + + draw_label(index_label_pos, input_label_size, "INDEX", 40.0); + + let output_disp_loc = border_pos + Vec2::new(border_size.x * 0.55, border_size.x * 0.05); + let output_disp_size = Vec2::new(border_size.x * 0.33, border_size.y * 0.6); + + let output_disp = if ctx.mode == Mode::Encode { + ctx.decoder_state.encode(input_letter) + } else { + ctx.decoder_state.decode(input_letter) + }; + + draw_display( + output_disp_loc, + output_disp_size, + output_disp.to_string().as_str(), + 160.0, + ); + + let output_disp_label_loc = output_disp_loc + + Vec2::new( + output_disp_size.x / 2.0 - input_label_size.x / 2.0, + output_disp_size.y + size.y * 0.01, + ); + + draw_label(output_disp_label_loc, input_label_size, "OUTPUT", 40.0); + + let switch_pos = border_pos + border_size * 0.5; + let switch_size = Vec2::new(border_size.x * 0.05, border_size.y * 0.25); + draw_label( + switch_pos + Vec2::new(-border_size.x * 0.05 * 0.5, switch_size.y), + Vec2::new(border_size.x * 0.05, border_size.x * 0.05), + "D", + 40.0, + ); + draw_label( + switch_pos + Vec2::new(-border_size.x * 0.05 * 0.5, -switch_size.y * 1.5), + Vec2::new(border_size.x * 0.05, border_size.x * 0.05), + "E", + 40.0, + ); + + if draw_switch(switch_pos, switch_size, ctx.mode == Mode::Encode) { + if ctx.mode != Mode::Encode { + info!("Mode set to encode!"); + ctx.mode = Mode::Encode + } + } else { + if ctx.mode != Mode::Decode { + info!("Mode set to decode!"); + ctx.mode = Mode::Decode + } + } +} + +#[macroquad::main(conf)] +async fn main() { + game_init(); + + let decoder = DecoderState::default(); + let input_disc = DecoderState::default(); + + let mut context = Context { + decoder_state: decoder, + input_state: input_disc, + mode: Mode::Decode, + }; + + context + .input_state + .set_index(context.input_state.outer_disc.letter_map.len() * 3 / 4); + + loop { + clear_background(WHITE); + + draw_device(&mut context); + + next_frame().await; + } +}