diff --git a/Cargo.lock b/Cargo.lock index 27b6416..e27bf23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,16 +3,13 @@ version = 4 [[package]] -name = "adler2" -version = "2.0.0" +name = "aho-corasick" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] [[package]] name = "arboard" @@ -36,10 +33,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] -name = "bitflags" -version = "1.3.2" +name = "bindgen" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] [[package]] name = "bitflags" @@ -57,16 +68,22 @@ dependencies = [ ] [[package]] -name = "bytemuck" -version = "1.22.0" +name = "cc" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" +dependencies = [ + "shlex", +] [[package]] -name = "byteorder" -version = "1.5.0" +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] [[package]] name = "cfg-if" @@ -74,6 +91,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clipboard-win" version = "5.4.0" @@ -84,25 +112,19 @@ dependencies = [ ] [[package]] -name = "color_quant" -version = "1.1.0" +name = "cmake" +version = "0.1.51" 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" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ - "cfg-if", + "cc", ] [[package]] -name = "equivalent" -version = "1.0.2" +name = "either" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "errno" @@ -120,41 +142,6 @@ version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "flate2" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "fontdue" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e57e16b3fe8ff4364c0661fdaac543fb38b29ea9bc9c2f45612d90adf931d2b" -dependencies = [ - "hashbrown", - "ttf-parser", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -166,33 +153,18 @@ dependencies = [ ] [[package]] -name = "glam" -version = "0.27.0" +name = "glob" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e05e7e6723e3455f4818c7b26e855439f7546cf617ef669d1adedb8669e5cb9" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] -name = "hashbrown" -version = "0.15.2" +name = "itertools" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - -[[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", + "either", ] [[package]] @@ -207,6 +179,16 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -229,41 +211,12 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "macroquad" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2befbae373456143ef55aa93a73594d080adfb111dc32ec96a1123a3e4ff4ae" -dependencies = [ - "fontdue", - "glam", - "image", - "macroquad_macro", - "miniquad", - "quad-rand", -] - -[[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 = "marble-machinations" version = "0.3.3" dependencies = [ "arboard", - "macroquad", + "raylib", "serde", "serde_json", ] @@ -275,49 +228,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "miniquad" -version = "0.4.8" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fb3e758e46dbc45716a8a49ca9edc54b15bcca826277e80b1f690708f67f9e3" -dependencies = [ - "libc", - "ndk-sys", - "objc-rs", - "winapi", -] +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] -name = "miniz_oxide" -version = "0.8.8" +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "adler2", - "simd-adler32", -] - -[[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-rs" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a1e7069a2525126bf12a9f1f7916835fafade384fb27cabf698e745e2a1eb8" -dependencies = [ - "malloc_buf", + "memchr", + "minimal-lexical", ] [[package]] @@ -342,7 +265,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.6.0", + "bitflags", "block2", "libc", "objc2", @@ -358,7 +281,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.6.0", + "bitflags", "block2", "objc2", "objc2-foundation", @@ -388,7 +311,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.6.0", + "bitflags", "block2", "libc", "objc2", @@ -400,7 +323,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.6.0", + "bitflags", "block2", "objc2", "objc2-foundation", @@ -412,7 +335,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.6.0", + "bitflags", "block2", "objc2", "objc2-foundation", @@ -443,16 +366,19 @@ dependencies = [ ] [[package]] -name = "png" -version = "0.17.16" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "prettyplease" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", + "proc-macro2", + "syn", ] [[package]] @@ -464,12 +390,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quad-rand" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a651516ddc9168ebd67b24afd085a718be02f8858fe406591b013d101ce2f40" - [[package]] name = "quote" version = "1.0.37" @@ -479,22 +399,81 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "raylib" +version = "5.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c54335590d1b6e6fbdbccee09dafdfd76a1111fc3c709eca949e71e81f7a8a" +dependencies = [ + "cfg-if", + "paste", + "raylib-sys", + "seq-macro", + "thiserror", +] + +[[package]] +name = "raylib-sys" +version = "5.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ce5adc950b042db67f1f78f24f7e76563652ce24db032afe9ca9e534d8b7a13" +dependencies = [ + "bindgen", + "cc", + "cmake", +] + [[package]] name = "redox_syscall" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -513,6 +492,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + [[package]] name = "serde" version = "1.0.210" @@ -546,10 +531,10 @@ dependencies = [ ] [[package]] -name = "simd-adler32" -version = "0.3.7" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "smallvec" @@ -569,10 +554,24 @@ dependencies = [ ] [[package]] -name = "ttf-parser" -version = "0.21.1" +name = "thiserror" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "unicode-ident" @@ -580,28 +579,6 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[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 = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 96515ff..9fd920c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,7 @@ default-run = "marble-machinations" [dependencies] arboard = { version = "3.4.1", default-features = false } -macroquad = "0.4" -# raylib = "5.5" +raylib = "5.5" serde = { version = "1.0.210", features = ["derive"] } serde_json = "1.0.128" diff --git a/src/board.rs b/src/board.rs index 36b4192..e00a994 100644 --- a/src/board.rs +++ b/src/board.rs @@ -1,4 +1,8 @@ -use macroquad::{color::colors, prelude::*}; +use raylib::{ + color::Color, + drawing::{RaylibDraw, RaylibDrawHandle}, + math::Vector2, +}; use serde::{Deserialize, Serialize}; use crate::{ @@ -67,18 +71,18 @@ impl Board { } } - pub fn draw_comments(&self, offset: Vec2, scale: f32) { - let tile_size = TILE_TEXTURE_SIZE * scale; - let font_size = 10. * scale.max(1.); - let line_space = 12. * scale.max(1.); + pub fn draw_comments(&self, d: &mut RaylibDrawHandle, offset: Vector2, scale: f32) { + let tile_size = (TILE_TEXTURE_SIZE * scale) as i32; + let font_size = 10 * (scale as i32).max(1); + let line_space = 12 * (scale as i32).max(1); for comment in &self.comments { - let x = comment.x as f32 * tile_size + offset.x; - let y = comment.y as f32 * tile_size + offset.y; - let y = y + (tile_size - font_size) / 2.; // center vertically in the grid row + let x = comment.x * tile_size + offset.x as i32; + let y = comment.y * tile_size + offset.y as i32; + let y = y + (tile_size - font_size) / 2; // center vertically in the grid row for (i, line) in comment.text.lines().enumerate() { - let y = y + line_space * i as f32; - draw_text(line, x, y, font_size, colors::ORANGE); + let y = y + line_space * i as i32; + d.draw_text(line, x, y, font_size, Color::ORANGE); } } } diff --git a/src/config.rs b/src/config.rs index 996e1bf..674611f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,4 @@ -use macroquad::{color::colors, prelude::*}; +use raylib::prelude::*; use serde::{Deserialize, Serialize}; use crate::{ @@ -17,7 +17,7 @@ pub struct Config { #[serde(default)] pub show_power_direction: bool, #[serde(skip)] - scroll_offset: f32, + scroll_offset: u32, } pub enum MenuReturn { @@ -29,38 +29,38 @@ pub enum MenuReturn { impl Config { #[must_use] - pub fn draw_edit(&mut self, globals: &mut Globals) -> MenuReturn { + pub fn draw_edit(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals) -> MenuReturn { match globals.mouse.scroll() { - Some(Scroll::Down) => self.scroll_offset += 64., - Some(Scroll::Up) => self.scroll_offset = (self.scroll_offset - 64.).max(0.), + Some(Scroll::Down) => self.scroll_offset += 64, + Some(Scroll::Up) => self.scroll_offset = self.scroll_offset.saturating_sub(64), None => (), } - let mut y = -self.scroll_offset + 15.; - draw_text("Settings", 16., y, 30., FG_CHAPTER_TITLE); - y += 40.; + let mut y = -(self.scroll_offset as i32) + 15; + d.draw_text("Settings", 16, y, 30, FG_CHAPTER_TITLE); + y += 40; - if text_button(&globals.mouse, 10., y, 80., "apply") { + if text_button(d, &globals.mouse, 10, y, 80, "apply") { return MenuReturn::StaySave; } - if text_button(&globals.mouse, 100., y, 80., "done") { + if text_button(d, &globals.mouse, 100, y, 80, "done") { return MenuReturn::ReturnSave; } - if text_button(&globals.mouse, 190., y, 80., "cancel") { + if text_button(d, &globals.mouse, 190, y, 80, "cancel") { return MenuReturn::ReturnCancel; } - y += 40.; + y += 40; let mut toggle = |value, text| { - toggle_button(&globals.mouse, 10., y, 30., 30., value); - draw_text(text, 50., y + 5., 20., colors::WHITE); - y += 40.; + toggle_button((d, &globals.mouse), 10, y, 30, 30, value); + d.draw_text(text, 50, y + 5, 20, Color::WHITE); + y += 40; }; toggle(&mut self.show_power_direction, "show power directions"); toggle(&mut self.show_debug_timing, "show debug timing"); // self.input.update(d); - self.input.draw_edit(globals, y); + self.input.draw_edit(d, globals, y); MenuReturn::Stay } } diff --git a/src/editor.rs b/src/editor.rs index 6248441..e3a34fa 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -5,19 +5,14 @@ use std::{ time::Instant, }; -use macroquad::{color::colors, prelude::*}; +use raylib::prelude::*; use crate::{ blueprint::Blueprint, board::Board, input::ActionId, level::Level, - marble_engine::{ - grid::*, - pos::*, - tile::{self, *}, - Machine, - }, + marble_engine::{grid::*, pos::*, tile::*, Machine}, solution::*, theme::*, ui::*, @@ -25,17 +20,17 @@ use crate::{ Globals, }; -const HEADER_HEIGHT: f32 = 40.; -const FOOTER_HEIGHT: f32 = 95.; -const SIDEBAR_WIDTH: f32 = (200 + 32 * 2 + 5 * 4) as _; -const END_POPUP_WIDTH: f32 = 320.; -const END_POPUP_HEIGHT: f32 = 255.; +const HEADER_HEIGHT: i32 = 40; +const FOOTER_HEIGHT: i32 = 95; +const SIDEBAR_WIDTH: i32 = 200 + 32 * 2 + 5 * 4; +const END_POPUP_WIDTH: i32 = 320; +const END_POPUP_HEIGHT: i32 = 255; const MAX_ZOOM: f32 = 8.; const MIN_ZOOM: f32 = 0.25; const BOARD_MARGIN: usize = 3; const MAX_SPEED_POWER: u8 = 16; -const SPEED_DIGITS: u8 = 5; +const SPEED_DIGITS: i32 = 5; const MAX_FRAME_TIME_MICROS: u128 = 1_000_000 / 30; #[derive(Debug)] @@ -44,13 +39,13 @@ pub struct Editor { level: Level, machine: Machine, sim_state: SimState, - view_offset: Vec2, + view_offset: Vector2, zoom: f32, output_as_text: bool, input_as_text: bool, active_tool: Tool, tool_math: MathOp, - tool_comparator: crate::marble_engine::tile::Comp, + tool_comparator: Comparison, tool_arrow: Direction, tool_mirror: MirrorType, tool_wire: WireType, @@ -146,14 +141,14 @@ impl Editor { input_as_text = i.input().is_text(); machine.set_input(i.input().as_bytes().to_owned()); } - let mut info_text = ShapedText::new(20.); + let mut info_text = ShapedText::new(20); info_text.set_text(level.description()); Self { source_board: solution.board.clone(), machine, sim_state: SimState::Editing, - view_offset: Vec2::ZERO, + view_offset: Vector2::zero(), zoom: 2., active_tool: Tool::None, output_as_text, @@ -165,7 +160,7 @@ impl Editor { sim_speed: 3, time_since_step: 0., tool_math: MathOp::Add, - tool_comparator: tile::Comp::Equal, + tool_comparator: Comparison::Equal, tool_arrow: Direction::Right, tool_mirror: MirrorType::Forward, tool_wire: WireType::Vertical, @@ -281,7 +276,7 @@ impl Editor { self.score.clone() } - fn pos_to_screen(&self, pos: Vec2) -> Vec2 { + fn pos_to_screen(&self, pos: Vector2) -> Vector2 { pos * TILE_TEXTURE_SIZE * self.zoom + self.view_offset } @@ -352,19 +347,19 @@ impl Editor { } } - pub fn center_view(&mut self) { + pub fn center_view(&mut self, d: &RaylibHandle) { let tile_size = TILE_TEXTURE_SIZE * self.zoom; let tile_x = self.source_board.grid.width() as f32 / 2. * tile_size; let tile_y = self.source_board.grid.height() as f32 / 2. * tile_size; - let screen_x = screen_width() / 2.; - let screen_y = screen_height() / 2.; + let screen_x = d.get_screen_width() as f32 / 2.; + let screen_y = d.get_screen_height() as f32 / 2.; self.view_offset.x = (screen_x - tile_x).floor(); self.view_offset.y = (screen_y - tile_y).floor(); } - fn change_zoom_level(&mut self, delta: f32) { + fn change_zoom_level(&mut self, d: &RaylibHandle, delta: f32) { let tile_size = TILE_TEXTURE_SIZE * self.zoom; - let mouse_pos: Vec2 = mouse_position().into(); + let mouse_pos = d.get_mouse_position(); let tile_pos_of_mouse = (mouse_pos - self.view_offset) / tile_size; self.zoom += delta; let tile_size = TILE_TEXTURE_SIZE * self.zoom; @@ -373,15 +368,15 @@ impl Editor { self.view_offset.y = self.view_offset.y.floor(); } - fn zoom_in(&mut self) { + fn zoom_in(&mut self, d: &RaylibHandle) { if self.zoom < MAX_ZOOM { - self.change_zoom_level(self.zoom); + self.change_zoom_level(d, self.zoom); } } - fn zoom_out(&mut self) { + fn zoom_out(&mut self, d: &RaylibHandle) { if self.zoom > MIN_ZOOM { - self.change_zoom_level(self.zoom / -2.); + self.change_zoom_level(d, self.zoom / -2.); } } @@ -436,11 +431,11 @@ impl Editor { self.push_action(Action::SetTile(resize, pos, old_tile, tile)); } - pub fn update(&mut self, globals: &mut Globals) { - self.tooltip.init_frame(); + pub fn update(&mut self, rl: &RaylibHandle, globals: &mut Globals) { + self.tooltip.init_frame(rl); self.mouse.clear(); if self.popup == Popup::None { - self.mouse.update(); + self.mouse.update(rl); } if globals.is_pressed(ActionId::ToggleMenu) { @@ -454,7 +449,7 @@ impl Editor { }; } if self.sim_state == SimState::Running && self.popup == Popup::None { - self.time_since_step += get_frame_time(); + self.time_since_step += rl.get_frame_time(); let step_size = 1. / (1 << self.sim_speed) as f32; let mut steps_taken = 0; let start_time = Instant::now(); @@ -509,26 +504,26 @@ impl Editor { let mouse_pos = self.mouse.pos(); if (self.active_tool != Tool::Blueprint || self.sim_state != SimState::Editing - || mouse_pos.x > SIDEBAR_WIDTH) - && mouse_pos.y > HEADER_HEIGHT - && (mouse_pos.y) < (screen_height() - FOOTER_HEIGHT) + || mouse_pos.x > SIDEBAR_WIDTH as f32) + && mouse_pos.y > HEADER_HEIGHT as f32 + && (mouse_pos.y as i32) < (rl.get_screen_height() - FOOTER_HEIGHT) { match self.mouse.scroll() { - Some(Scroll::Up) => self.zoom_in(), - Some(Scroll::Down) => self.zoom_out(), + Some(Scroll::Up) => self.zoom_in(rl), + Some(Scroll::Down) => self.zoom_out(rl), None => (), } } if self.mouse.right_hold() { - let speed = if is_key_down(KeyCode::LeftShift) { + let speed = if rl.is_key_down(KeyboardKey::KEY_LEFT_SHIFT) { 4. } else { 1. }; - self.view_offset += mouse_delta_position() * speed; + self.view_offset += rl.get_mouse_delta() * speed; } - if is_key_pressed(KeyCode::Home) { - self.center_view(); + if rl.is_key_pressed(KeyboardKey::KEY_HOME) { + self.center_view(rl); } if globals.is_pressed(ActionId::CycleGroup) { @@ -554,11 +549,11 @@ impl Editor { } if !self.machine.debug_subticks.is_empty() { - if is_key_pressed(KeyCode::N) { + if rl.is_key_pressed(KeyboardKey::KEY_N) { self.machine.subtick_index += 1; self.machine.subtick_index %= self.machine.debug_subticks.len(); } - if is_key_pressed(KeyCode::M) { + if rl.is_key_pressed(KeyboardKey::KEY_M) { self.machine.subtick_index = self.machine.subtick_index.saturating_sub(1); } } @@ -580,15 +575,20 @@ impl Editor { } } - fn draw_board(&self, globals: &Globals) { + fn draw_board(&self, d: &mut RaylibDrawHandle, globals: &Globals) { let draw_power = globals.config.show_power_direction && self.draw_overlay; if self.sim_state == SimState::Editing { - self.source_board - .grid - .draw(&globals.textures, self.view_offset, self.zoom, draw_power); + self.source_board.grid.draw( + d, + &globals.textures, + self.view_offset, + self.zoom, + draw_power, + ); } else { if self.machine.debug_subticks.is_empty() { self.machine.grid().draw( + d, &globals.textures, self.view_offset, self.zoom, @@ -596,118 +596,121 @@ impl Editor { ); } else { let subframe = &self.machine.debug_subticks[self.machine.subtick_index]; - subframe - .grid - .draw(&globals.textures, self.view_offset, self.zoom, draw_power); + subframe.grid.draw( + d, + &globals.textures, + self.view_offset, + self.zoom, + draw_power, + ); if let Some(pos) = subframe.pos { let p = self.pos_to_screen(pos.to_vec()); - let tex = globals.get_tex("selection"); - let params = DrawTextureParams { - dest_size: Some(Vec2::new( - tex.width() * self.zoom, - tex.height() * self.zoom, - )), - ..Default::default() - }; - draw_texture_ex(tex, p.x, p.y, colors::ORANGE, params); + d.draw_texture_ex( + globals.get_tex("selection"), + p, + 0., + self.zoom, + Color::ORANGE, + ); } } if self.draw_overlay { self.machine - .draw_marble_values(&globals.textures, self.view_offset, self.zoom); + .draw_marble_values(d, &globals.textures, self.view_offset, self.zoom); } } if self.draw_overlay { - self.source_board.draw_comments(self.view_offset, self.zoom); + self.source_board + .draw_comments(d, self.view_offset, self.zoom); } } - pub fn draw(&mut self, globals: &mut Globals) { - clear_background(BG_WORLD); + pub fn draw(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals) { + d.clear_background(BG_WORLD); if self.draw_overlay && self.zoom >= 0.5 { let tile_size = TILE_TEXTURE_SIZE * self.zoom; let grid_spill_x = (self.view_offset.x).rem(tile_size) - tile_size; let grid_spill_y = (self.view_offset.y).rem(tile_size) - tile_size; - let hlines = (screen_height() / tile_size) as i32 + 3; - let vlines = (screen_width() / tile_size) as i32 + 3; + let hlines = d.get_screen_height() / tile_size as i32 + 3; + let vlines = d.get_screen_width() / tile_size as i32 + 3; for y in 0..hlines { - let y = y as f32 * tile_size + grid_spill_y; - draw_line(0., y, screen_width(), y, 1., FG_GRID); + let y = y * tile_size as i32 + grid_spill_y as i32; + d.draw_line(0, y, d.get_screen_width(), y, FG_GRID); } for x in 0..vlines { - let x = x as f32 * tile_size + grid_spill_x; - draw_line(x, 0., x, screen_height(), 1., FG_GRID); + let x = x * tile_size as i32 + grid_spill_x as i32; + d.draw_line(x, 0, x, d.get_screen_height(), FG_GRID); } } - self.draw_board(globals); - self.board_overlay(globals); - self.draw_bottom_bar(globals); - self.draw_top_bar(globals); + self.draw_board(d, globals); + self.board_overlay(d, globals); + self.draw_bottom_bar(d, globals); + self.draw_top_bar(d, globals); if self.active_tool == Tool::Blueprint { - self.draw_blueprint_sidebar(globals); + self.draw_blueprint_sidebar(d, globals); } - self.mouse.update(); + self.mouse.update(d); if self.popup != Popup::None { self.tooltip.reset(); - draw_rectangle( - 0., - 0., - screen_width(), - screen_height(), - Color::from_rgba(100, 100, 100, 120), + d.draw_rectangle( + 0, + 0, + d.get_screen_width(), + d.get_screen_height(), + Color::new(100, 100, 100, 120), ); } match self.popup { Popup::Success(_) | Popup::Failure => { - self.draw_end_popup(&globals.textures); + self.draw_end_popup(d, &globals.textures); } Popup::LevelInfo => { - let bounds = screen_centered_rect_dyn(100., 100.); - draw_rectangle_rec(bounds, BG_MEDIUM); - draw_text(self.level.name(), 110., 110., 30., LIGHTBLUE); - self.info_text.update_width(bounds.w - 20.); - self.info_text.draw(110., 140.); + let bounds = screen_centered_rect_dyn(d, 100, 100); + d.draw_rectangle_rec(bounds, BG_MEDIUM); + d.draw_text(self.level.name(), 110, 110, 30, Color::LIGHTBLUE); + self.info_text.update_width(d, bounds.width as i32 - 20); + self.info_text.draw(d, 110, 140); } Popup::PauseMenu => { - let bounds = screen_centered_rect(300., 400.); - draw_rectangle_rec(bounds, BG_MEDIUM); - let x = bounds.x; - let y = bounds.y; - draw_text("Menu", x + 10., y + 10., 30., LIGHTBLUE); - if text_button(&self.mouse, x + 10., y + 40., 280., "Resume") { + let bounds = screen_centered_rect(d, 300, 400); + d.draw_rectangle_rec(bounds, BG_MEDIUM); + let x = bounds.x as i32; + let y = bounds.y as i32; + d.draw_text("Menu", x + 10, y + 10, 30, Color::LIGHTBLUE); + if text_button(d, &self.mouse, x + 10, y + 40, 280, "Resume") { self.popup = Popup::None; } - if text_button(&self.mouse, x + 10., y + 80., 280., "Save") { + if text_button(d, &self.mouse, x + 10, y + 80, 280, "Save") { self.exit_state = ExitState::Save; self.popup = Popup::None; } - if text_button(&self.mouse, x + 10., y + 120., 280., "Exit to main menu") { + if text_button(d, &self.mouse, x + 10, y + 120, 280, "Exit to main menu") { self.exit_state = ExitState::ExitAndSave; } } Popup::None => (), } - self.tooltip.draw(); + self.tooltip.draw(d); } - fn draw_blueprint_sidebar(&mut self, globals: &mut Globals) { - let sidebar_height = screen_height() - FOOTER_HEIGHT - HEADER_HEIGHT - 40.; - draw_rectangle( - 0., - HEADER_HEIGHT + 20., + fn draw_blueprint_sidebar(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals) { + let sidebar_height = d.get_screen_height() - FOOTER_HEIGHT - HEADER_HEIGHT - 40; + d.draw_rectangle( + 0, + HEADER_HEIGHT + 20, SIDEBAR_WIDTH, sidebar_height, - Color::from_rgba(32, 32, 32, 255), + Color::new(32, 32, 32, 255), ); - draw_text("Blueprints", 10., HEADER_HEIGHT + 30., 20., colors::WHITE); - let mut y = HEADER_HEIGHT + 60.; + d.draw_text("Blueprints", 10, HEADER_HEIGHT + 30, 20, Color::WHITE); + let mut y = HEADER_HEIGHT + 60; let blueprints_shown = (sidebar_height as usize - 45) / 37; let end = self .blueprints @@ -719,8 +722,8 @@ impl Editor { { let i = i + self.blueprint_scroll; if tex32_button( - &self.mouse, - (5., y), + (d, &self.mouse), + (5, y), globals.get_tex("rubbish"), (&mut self.tooltip, "Delete"), ) { @@ -731,8 +734,9 @@ impl Editor { let is_selected = self.selected_blueprint == i; let mut text_selected = is_selected && self.blueprint_name_selected; text_input( + d, globals, - Rect::new(42., y, 200., 32.), + Rectangle::new(42., y as f32, 200., 32.), &mut b.name, &mut text_selected, 32, @@ -741,79 +745,84 @@ impl Editor { if is_selected { self.blueprint_name_selected = text_selected; } - self.tooltip.add(42. + 205., y, 32., 32., "Select"); + self.tooltip.add(42 + 205, y, 32, 32, "Select"); simple_option_button( - &self.mouse, - Rect::new(42. + 205., y, 32., 32.), + (d, &self.mouse), + rect(42 + 205, y, 32, 32), i, &mut self.selected_blueprint, ); - let color = Color::from_rgba(255, 255, 255, if is_selected { 255 } else { 150 }); - draw_scaled_texture_c( + d.draw_texture_ex( globals.get_tex("blueprint"), - (42 + 205) as f32, - y, + Vector2::new((42 + 205) as f32, y as f32), + 0., 2., - color, + Color::new(255, 255, 255, if is_selected { 255 } else { 150 }), ); - y += 37.; + y += 37; } } - fn draw_end_popup(&mut self, textures: &Textures) { - let bounds = screen_centered_rect(END_POPUP_WIDTH, END_POPUP_HEIGHT); - let x = bounds.x; - let mut y = bounds.y + 10.; - draw_rectangle_rec(bounds, BG_DARK); + fn draw_end_popup(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) { + let bounds = screen_centered_rect(d, END_POPUP_WIDTH, END_POPUP_HEIGHT); + let x = bounds.x as i32; + let mut y = bounds.y as i32 + 10; + d.draw_rectangle_rec(bounds, BG_DARK); if let Popup::Success(score) = &self.popup { - draw_text("Level Complete!", x + 45., y, 30., colors::GREEN); - y += 30.; - draw_text(self.level.name(), x + 10., y, 20., colors::GRAY); - y += 30.; - draw_text("cycles", x + 15., y, 20., colors::WHITE); - draw_usize(textures, score.cycles, (x + 110., y), 9, 2.); - y += 40.; - draw_text("tiles", x + 15., y, 20., colors::WHITE); - draw_usize(textures, score.tiles, (x + 110., y), 9, 2.); - y += 40.; - draw_text("bounds", x + 15., y, 20., colors::WHITE); - draw_usize(textures, score.bounds_area, (x + 110., y), 9, 2.); - y += 40.; - if simple_button(&self.mouse, x + 10., y, 140., 50.) { + d.draw_text("Level Complete!", x + 45, y, 30, Color::LIME); + y += 30; + d.draw_text(self.level.name(), x + 10, y, 20, Color::GRAY); + y += 30; + d.draw_text("cycles", x + 15, y, 20, Color::WHITE); + draw_usize(d, textures, score.cycles, (x + 110, y), 9, 2); + y += 40; + d.draw_text("tiles", x + 15, y, 20, Color::WHITE); + draw_usize(d, textures, score.tiles, (x + 110, y), 9, 2); + y += 40; + d.draw_text("bounds", x + 15, y, 20, Color::WHITE); + draw_usize(d, textures, score.bounds_area, (x + 110, y), 9, 2); + y += 40; + if simple_button((d, &self.mouse), x + 10, y, 140, 50) { self.popup = Popup::None; self.dismissed_end = true; } - draw_text("continue\nediting", x + 15., y + 5., 20., colors::WHITE); + d.draw_text("continue\nediting", x + 15, y + 5, 20, Color::WHITE); - if simple_button(&self.mouse, x + END_POPUP_WIDTH / 2. + 5., y, 140., 50.) { + if simple_button((d, &self.mouse), x + END_POPUP_WIDTH / 2 + 5, y, 140, 50) { self.exit_state = ExitState::ExitAndSave; } - draw_text( + d.draw_text( "return to\nlevel list", - x + END_POPUP_WIDTH / 2. + 10., - y + 5., - 20., - colors::WHITE, + x + END_POPUP_WIDTH / 2 + 10, + y + 5, + 20, + Color::WHITE, ); } else { - draw_text("Level Failed!", x + 45., y + 10., 30., colors::RED); - draw_text("incorrect output", x + 45., y + 45., 20., colors::WHITE); - if simple_button(&self.mouse, x + 10., y + 110., 300., 25.) { + d.draw_text("Level Failed!", x + 45, y + 10, 30, Color::RED); + d.draw_text("incorrect output", x + 45, y + 45, 20, Color::WHITE); + if simple_button((d, &self.mouse), x + 10, y + 110, 300, 25) { self.popup = Popup::None; self.dismissed_end = true; } - draw_text("ok :(", x + 15., y + 115., 20., colors::WHITE); + d.draw_text("ok :(", x + 15, y + 115, 20, Color::WHITE); } } - fn draw_top_bar(&mut self, globals: &mut Globals) { + fn draw_top_bar(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals) { // background - draw_rectangle(0., 0., screen_width(), HEADER_HEIGHT, BG_DARK); + d.draw_rectangle( + 0, + 0, + d.get_screen_width(), + HEADER_HEIGHT, + Color::new(32, 32, 32, 255), + ); if tex32_button( - &self.mouse, - (4., 4.), + (d, &self.mouse), + (4, 4), globals.get_tex("exit"), (&mut self.tooltip, "exit"), ) { @@ -825,16 +834,16 @@ impl Editor { } if self.exit_menu { if tex32_button( - &self.mouse, - (40., 4.), + (d, &self.mouse), + (40, 4), globals.get_tex("cancel"), (&mut self.tooltip, "cancel"), ) { self.exit_menu = false; } } else if tex32_button( - &self.mouse, - (40., 4.), + (d, &self.mouse), + (40, 4), globals.get_tex("save"), (&mut self.tooltip, "save"), ) || globals.is_pressed(ActionId::Save) @@ -842,7 +851,7 @@ impl Editor { self.exit_state = ExitState::Save; } - if text_button(&self.mouse, 76., 5., 50., "info") { + if text_button(d, &self.mouse, 76, 5, 50, "info") { self.popup = Popup::LevelInfo; } @@ -853,8 +862,8 @@ impl Editor { "undo_disabled" }; if tex32_button( - &self.mouse, - (150., 4.), + (d, &self.mouse), + (150, 4), globals.get_tex(undo_icon), (&mut self.tooltip, "Undo"), ) { @@ -867,8 +876,8 @@ impl Editor { "redo_disabled" }; if tex32_button( - &self.mouse, - (186., 4.), + (d, &self.mouse), + (186, 4), globals.get_tex(redo_icon), (&mut self.tooltip, "Redo"), ) { @@ -882,8 +891,8 @@ impl Editor { "marble" }; if tex32_button( - &self.mouse, - (223., 4.), + (d, &self.mouse), + (223, 4), globals.get_tex(overlay_btn_icon), (&mut self.tooltip, "Toggle overlay"), ) { @@ -892,16 +901,16 @@ impl Editor { if self.sim_state == SimState::Running { if tex32_button( - &self.mouse, - (260., 4.), + (d, &self.mouse), + (260, 4), globals.get_tex("pause"), (&mut self.tooltip, "Pause"), ) { self.sim_state = SimState::Stepping; } } else if tex32_button( - &self.mouse, - (260., 4.), + (d, &self.mouse), + (260, 4), globals.get_tex("play"), (&mut self.tooltip, "Start"), ) { @@ -913,8 +922,8 @@ impl Editor { if self.sim_state != SimState::Editing && tex32_button( - &self.mouse, - (296., 4.), + (d, &self.mouse), + (296, 4), globals.get_tex("stop"), (&mut self.tooltip, "Stop"), ) { @@ -923,70 +932,73 @@ impl Editor { } if tex32_button( - &self.mouse, - (332., 4.), + (d, &self.mouse), + (332, 4), globals.get_tex("step"), (&mut self.tooltip, "Step"), ) { self.step_pressed(); } - self.tooltip.add(368., 4., 48., 32., "Speed"); + self.tooltip.add(368, 4, 48, 32, "Speed"); draw_usize( + d, &globals.textures, 1 << self.sim_speed, - (368., 4.), + (368, 4), SPEED_DIGITS, - 1., + 1, ); slider( - &self.mouse, - Rect::new(368., 24., 48., 12.), + (d, &self.mouse), + rect(368, 24, 48, 12), &mut self.sim_speed, 0, MAX_SPEED_POWER, ); - self.tooltip.add(420., 4., 180., 32., "Steps"); + self.tooltip.add(420, 4, 180, 32, "Steps"); draw_usize( + d, &globals.textures, self.machine.step_count(), - (420., 4.), + (420, 4), 9, - 2., + 2, ); if self.stage > Some(0) { - self.tooltip.add(420., 44., 180., 32., "Total steps"); + self.tooltip.add(420, 44, 180, 32, "Total steps"); let total_steps = self.total_steps + self.machine.step_count(); - draw_usize(&globals.textures, total_steps, (420., 44.), 9, 2.); + draw_usize(d, &globals.textures, total_steps, (420, 44), 9, 2); } if globals.config.show_debug_timing { - draw_usize(&globals.textures, self.step_time, (260., 42.), 9, 1.); - draw_usize(&globals.textures, self.max_step_time, (260., 60.), 9, 1.); + draw_usize(d, &globals.textures, self.step_time, (260, 42), 9, 1); + draw_usize(d, &globals.textures, self.max_step_time, (260, 60), 9, 1); #[cfg(debug_assertions)] { draw_usize( + d, &globals.textures, self.machine.subtick_index, - (260., 80.), + (260, 80), 9, - 1., + 1, ); let subtick_count = self.machine.debug_subticks.len(); - draw_usize(&globals.textures, subtick_count, (260., 100.), 9, 1.); + draw_usize(d, &globals.textures, subtick_count, (260, 100), 9, 1); } } - draw_text("input:", 603., 8., 10., colors::WHITE); - if simple_button(&self.mouse, 600., 20., 35., 15.) { + d.draw_text("input:", 603, 8, 10, Color::WHITE); + if simple_button((d, &self.mouse), 600, 20, 35, 15) { self.input_as_text = !self.input_as_text } let input_mode_text = if self.input_as_text { "text" } else { "bytes" }; - draw_text(input_mode_text, 603., 23., 10., colors::WHITE); + d.draw_text(input_mode_text, 603, 23, 10, Color::WHITE); - let input_x = 638.; - let width = screen_width(); + let input_x = 638; + let width = d.get_screen_width(); if self.input_as_text { let mut input_text = String::new(); for &byte in self.machine.input() { @@ -997,8 +1009,9 @@ impl Editor { } } if text_input( + d, globals, - Rect::new(input_x, 5., width - input_x - 5., 30.), + Rectangle::new(input_x as f32, 5., (width - input_x - 5) as f32, 30.), &mut input_text, &mut self.input_text_selected, 256, @@ -1007,39 +1020,39 @@ impl Editor { self.machine.set_input(input_text.into_bytes()); } } else { - let input_cell_width = 43.; - let input_cells = (screen_width() - input_x) as usize / input_cell_width as usize; + let input_cell_width = 43; + let input_cells = (d.get_screen_width() - input_x) as usize / input_cell_width as usize; let input_start = self.machine.input_index().saturating_sub(input_cells); let input_end = input_start + input_cells; for (box_index, index) in (input_start..input_end).enumerate() { - let x = input_x + input_cell_width * box_index as f32; + let x = input_x + input_cell_width * box_index as i32; let byte = self.machine.input().get(index); - draw_rectangle(x, 5., input_cell_width - 5., 30., BG_WIDGET); + d.draw_rectangle(x, 5, input_cell_width - 5, 30, BG_WIDGET); let color = if index < self.machine.input_index() { - draw_rectangle(x + 4., 25., input_cell_width - 13., 8., colors::GREEN); - colors::GREEN + d.draw_rectangle(x + 4, 25, input_cell_width - 13, 8, Color::LIME); + Color::LIGHTGREEN } else { - colors::WHITE + Color::WHITE }; if let Some(&byte) = byte { let top_text = format!("{}", byte); - draw_text(&top_text, x + 2., 5., 20., color); + d.draw_text(&top_text, x + 2, 5, 20, color); } } } } - fn draw_bottom_bar(&mut self, globals: &mut Globals) { - let height = screen_height(); - let footer_top = height - FOOTER_HEIGHT; + fn draw_bottom_bar(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals) { + let height = d.get_screen_height(); + let footer_top = (height - FOOTER_HEIGHT) as f32; // background - draw_rectangle( - 0., + d.draw_rectangle( + 0, height - FOOTER_HEIGHT, - screen_width(), + d.get_screen_width(), FOOTER_HEIGHT, - BG_DARK, + Color::new(32, 32, 32, 255), ); let mut hide_tile_tools = false; @@ -1050,49 +1063,54 @@ impl Editor { { hide_tile_tools = true; text_input( + d, globals, - Rect::new(100., footer_top + 10., 240., 30.), + Rectangle::new(100., footer_top + 10., 240., 30.), &mut self.new_blueprint_name, &mut self.blueprint_name_selected, 32, true, ); - let y = footer_top + 49.; + let y = footer_top as i32 + 49; - self.tooltip.add(100., y, 40., 40., "Cancel"); - if simple_button(&self.mouse, 100., y, 40., 40.) || is_key_pressed(KeyCode::Escape) { + self.tooltip.add(100, y, 40, 40, "Cancel"); + if simple_button((d, &self.mouse), 100, y, 40, 40) + || d.is_key_pressed(KeyboardKey::KEY_ESCAPE) + { self.active_tool = Tool::SelectArea(Selection::default()); } - draw_scaled_texture(globals.get_tex("cancel"), 104., y + 4., 2.); + draw_scaled_texture(d, globals.get_tex("cancel"), 104, y + 4, 2.); - self.tooltip.add(144., y, 40., 40., "Save blueprint"); - if simple_button(&self.mouse, 144., y, 40., 40.) { + self.tooltip.add(144, y, 40, 40, "Save blueprint"); + if simple_button((d, &self.mouse), 144, y, 40, 40) { self.save_blueprint(selection); } - draw_scaled_texture(globals.get_tex("save"), 148., y + 4., 2.); + draw_scaled_texture(d, globals.get_tex("save"), 148, y + 4, 2.); - self.tooltip.add(188., y, 40., 40., "Copy"); + self.tooltip.add(188, y, 40, 40, "Copy"); let mut copy_selection = false; - if simple_button(&self.mouse, 188., y, 40., 40.) || globals.is_pressed(ActionId::Copy) { + if simple_button((d, &self.mouse), 188, y, 40, 40) || globals.is_pressed(ActionId::Copy) + { copy_selection = true; } - draw_scaled_texture(globals.get_tex("copy"), 192., y + 4., 2.); + draw_scaled_texture(d, globals.get_tex("copy"), 192, y + 4, 2.); - self.tooltip.add(232., y, 40., 40., "Cut"); + self.tooltip.add(232, y, 40, 40, "Cut"); let mut erase_selection = false; - if simple_button(&self.mouse, 232., y, 40., 40.) || globals.is_pressed(ActionId::Cut) { + if simple_button((d, &self.mouse), 232, y, 40, 40) || globals.is_pressed(ActionId::Cut) + { copy_selection = true; erase_selection = true; } - draw_scaled_texture(globals.get_tex("cut"), 236., y + 4., 2.); + draw_scaled_texture(d, globals.get_tex("cut"), 236, y + 4, 2.); - self.tooltip.add(276., y, 40., 40., "Delete"); - if simple_button(&self.mouse, 276., y, 40., 40.) + self.tooltip.add(276, y, 40, 40, "Delete"); + if simple_button((d, &self.mouse), 276, y, 40, 40) || globals.is_pressed(ActionId::EraseSelection) { erase_selection = true; } - draw_scaled_texture(globals.get_tex("eraser"), 280., y + 4., 2.); + draw_scaled_texture(d, globals.get_tex("eraser"), 280, y + 4, 2.); if copy_selection { let board = self.get_selected_as_board(selection); @@ -1124,14 +1142,16 @@ impl Editor { let gap = 2.; let button_size = 32. + border * 2.; let grid_size = button_size + gap * 2.; - let pos = Vec2 { + let pos = Vector2 { x: 100. + col as f32 * grid_size - if col < 0 { 10. } else { 0. }, y: footer_top + 5. + row as f32 * grid_size, }; - self.tooltip - .add_rec(Rect::new(pos.x, pos.y, button_size, button_size), tooltip); + self.tooltip.add_rec( + Rectangle::new(pos.x, pos.y, button_size, button_size), + tooltip, + ); scrollable_texture_option_button( - &self.mouse, + (d, &self.mouse), pos, globals.get_tex(texture), tool_option, @@ -1267,23 +1287,23 @@ impl Editor { } } - let y = footer_top + 5.; + let y = footer_top as i32 + 5; if let Some(i) = self.stage { - draw_text("stage", 370., y, 20., colors::GREEN); + d.draw_text("stage", 370, y, 20, Color::GREEN); let shown_stage = if self.sim_state == SimState::Editing { 0 } else { i + 1 }; let text = format!("{shown_stage}/{}", self.level.stages().len()); - draw_text(&text, 370., y + 20., 20., colors::GREEN); + d.draw_text(&text, 370, y + 20, 20, Color::LIGHTGREEN); } - let output_x = 440.; - let output_cell_width = 43.; - let output_cells = (screen_width() - output_x) as usize / output_cell_width as usize; + let output_x = 440; + let output_cell_width = 43; + let output_cells = (d.get_screen_width() - output_x) as usize / output_cell_width as usize; - if simple_button(&self.mouse, output_x, y + 70., 65., 15.) { + if simple_button((d, &self.mouse), output_x, y + 70, 65, 15) { self.output_as_text = !self.output_as_text } let output_mode_text = if self.output_as_text { @@ -1291,12 +1311,12 @@ impl Editor { } else { "show text" }; - draw_text(output_mode_text, output_x + 5., y + 72., 10., colors::WHITE); + d.draw_text(output_mode_text, output_x + 5, y + 72, 10, Color::WHITE); let output_start = self.machine.output().len().saturating_sub(output_cells); let output_end = output_start + output_cells; for (box_index, index) in (output_start..output_end).enumerate() { - let x = output_x + output_cell_width * box_index as f32; + let x = output_x + output_cell_width * box_index as i32; let (mut top_color, mut bottom_color) = (BG_LIGHT, BG_MEDIUM); @@ -1308,12 +1328,12 @@ impl Editor { if let (Some(&real_byte), Some(&expected_byte)) = (real_byte, expected_byte) { (top_color, bottom_color) = if expected_byte == real_byte { - (colors::GREEN, colors::DARKGREEN) + (Color::GREEN, Color::DARKGREEN) } else { - (colors::RED, colors::DARKPURPLE) + (Color::RED, Color::DARKRED) }; } - draw_rectangle(x, y, output_cell_width - 5., 30., top_color); + d.draw_rectangle(x, y, output_cell_width - 5, 30, top_color); if let Some(&expected_byte) = expected_byte { let top_text = if self.output_as_text && (expected_byte.is_ascii_graphic() || expected_byte.is_ascii_whitespace()) @@ -1322,10 +1342,10 @@ impl Editor { } else { format!("{expected_byte}") }; - draw_text(&top_text, x + 2., y + 5., 20., colors::WHITE); + d.draw_text(&top_text, x + 2, y + 5, 20, Color::WHITE); } } - draw_rectangle(x, y + 35., output_cell_width - 5., 30., bottom_color); + d.draw_rectangle(x, y + 35, output_cell_width - 5, 30, bottom_color); if let Some(&real_byte) = real_byte { let bottom_text = if self.output_as_text @@ -1335,23 +1355,23 @@ impl Editor { } else { format!("{real_byte}") }; - draw_text(&bottom_text, x + 2., y + 40., 20., colors::WHITE); + d.draw_text(&bottom_text, x + 2, y + 40, 20, Color::WHITE); } } } - fn board_overlay(&mut self, globals: &Globals) { - let footer_top = screen_height() - FOOTER_HEIGHT; + fn board_overlay(&mut self, d: &mut RaylibDrawHandle, globals: &Globals) { + let footer_top = (d.get_screen_height() - FOOTER_HEIGHT) as f32; let tile_size = TILE_TEXTURE_SIZE * self.zoom; if self.sim_state == SimState::Editing { if let Some(board) = &self.pasting_board { - if is_key_pressed(KeyCode::Escape) { + if d.is_key_pressed(KeyboardKey::KEY_ESCAPE) { self.pasting_board = None; return; } - if self.mouse.pos().y < footer_top && self.mouse.pos().y > HEADER_HEIGHT { - let view_offset = Vec2::new( + if self.mouse.pos().y < footer_top && self.mouse.pos().y > HEADER_HEIGHT as f32 { + let view_offset = Vector2::new( self.view_offset.x.rem(tile_size), self.view_offset.y.rem(tile_size), ); @@ -1359,11 +1379,13 @@ impl Editor { offset.x -= offset.x.rem(tile_size); offset.y -= offset.y.rem(tile_size); offset += view_offset; - board.grid.draw(&globals.textures, offset, self.zoom, false); - board.draw_comments(offset, self.zoom); + board + .grid + .draw(d, &globals.textures, offset, self.zoom, false); + board.draw_comments(d, offset, self.zoom); if self.mouse.left_click() { let tile_pos = (self.mouse.pos() - self.view_offset) / tile_size; - let tile_pos = Vec2::new(tile_pos.x.floor(), tile_pos.y.floor()); + let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor()); let board = self.pasting_board.take().unwrap(); self.set_area(tile_pos.into(), board); } @@ -1372,36 +1394,35 @@ impl Editor { } if let Tool::Digits(Some(pos)) = &mut self.active_tool { let tile_screen_pos = pos.to_vec() * tile_size + self.view_offset; - - draw_scaled_texture_c( + d.draw_texture_ex( globals.get_tex("selection"), - tile_screen_pos.x, - tile_screen_pos.y, + tile_screen_pos, + 0., self.zoom, - Color::from_rgba(255, 180, 20, 255), + Color::new(255, 180, 20, 255), ); - if is_key_pressed(KeyCode::Left) { + if d.is_key_pressed(KeyboardKey::KEY_LEFT) { pos.x -= 1; } - if is_key_pressed(KeyCode::Right) { + if d.is_key_pressed(KeyboardKey::KEY_RIGHT) { pos.x += 1; } - if is_key_pressed(KeyCode::Up) { + if d.is_key_pressed(KeyboardKey::KEY_UP) { pos.y -= 1; } - if is_key_pressed(KeyCode::Down) { + if d.is_key_pressed(KeyboardKey::KEY_DOWN) { pos.y += 1; } let pos = *pos; for n in 0..10 { - if is_key_pressed(unsafe { transmute::(b'0' as u16 + n) }) { + if d.is_key_pressed(unsafe { transmute::(b'0' as u32 + n) }) { self.set_tile(pos, Tile::Open(OpenTile::Digit(n as u8), Claim::Free)); } } } - if self.mouse.pos().y < footer_top && self.mouse.pos().y > HEADER_HEIGHT { + if self.mouse.pos().y < footer_top && self.mouse.pos().y > HEADER_HEIGHT as f32 { let tile_pos = (self.mouse.pos() - self.view_offset) / tile_size; - let tile_pos = Vec2::new(tile_pos.x.floor(), tile_pos.y.floor()); + let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor()); let tile_screen_pos = self.pos_to_screen(tile_pos); @@ -1426,12 +1447,12 @@ impl Editor { Tool::Blueprint => "transparent", }; - draw_scaled_texture_c( + d.draw_texture_ex( globals.get_tex(tex), - tile_screen_pos.x, - tile_screen_pos.y, + tile_screen_pos, + 0., self.zoom, - Color::from_rgba(255, 255, 255, 100), + Color::new(255, 255, 255, 100), ); } if self.mouse.left_click() { @@ -1460,7 +1481,7 @@ impl Editor { } } Tool::Blueprint => { - if self.mouse.pos().x > SIDEBAR_WIDTH { + if self.mouse.pos().x > SIDEBAR_WIDTH as f32 { if let Some(bp) = self.blueprints.get(self.selected_blueprint) { self.set_area(pos, bp.board.clone()); } @@ -1489,7 +1510,7 @@ impl Editor { } if let Tool::Blueprint = self.active_tool { if let Some(bp) = self.blueprints.get(self.selected_blueprint) { - let view_offset = Vec2::new( + let view_offset = Vector2::new( self.view_offset.x.rem(tile_size), self.view_offset.y.rem(tile_size), ); @@ -1499,10 +1520,10 @@ impl Editor { offset += view_offset; bp.board .grid - .draw(&globals.textures, offset, self.zoom, false); - bp.board.draw_comments(offset, self.zoom); + .draw(d, &globals.textures, offset, self.zoom, false); + bp.board.draw_comments(d, offset, self.zoom); } - if self.mouse.pos().x < SIDEBAR_WIDTH { + if self.mouse.pos().x < SIDEBAR_WIDTH as f32 { if self.mouse.scroll() == Some(Scroll::Down) && self.blueprint_scroll < self.blueprints.len().saturating_sub(5) { @@ -1523,14 +1544,14 @@ impl Editor { { let p_min = self.pos_to_screen(start.min(end).to_vec()); let p_max = self.pos_to_screen((start.max(end) + (1, 1).into()).to_vec()); - let x = p_min.x; - let y = p_min.y; - let width = p_max.x - x; - let height = p_max.y - y; - draw_rectangle(x, y, width, 4., colors::WHITE); - draw_rectangle(x, y + height - 4., width, 4., colors::WHITE); - draw_rectangle(x, y, 4., height, colors::WHITE); - draw_rectangle(x + width - 4., y, 4., height, colors::WHITE); + let x = p_min.x as i32; + let y = p_min.y as i32; + let width = p_max.x as i32 - x; + let height = p_max.y as i32 - y; + d.draw_rectangle(x, y, width, 4, Color::WHITE); + d.draw_rectangle(x, y + height - 4, width, 4, Color::WHITE); + d.draw_rectangle(x, y, 4, height, Color::WHITE); + d.draw_rectangle(x + width - 4, y, 4, height, Color::WHITE); } } } diff --git a/src/input.rs b/src/input.rs index bcb5111..a769625 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,12 +1,17 @@ use std::{collections::BTreeMap, mem::transmute, vec}; -use macroquad::{color::colors, prelude::*}; +use raylib::{ + color::Color, + drawing::{RaylibDraw, RaylibDrawHandle}, + ffi::{KeyboardKey, MouseButton}, + RaylibHandle, +}; use serde::{Deserialize, Serialize}; use crate::{ theme::{BG_DARK, BG_LIGHT}, ui::text_button, - util::{draw_rectangle_rec, screen_centered_rect}, + util::{rect, screen_centered_rect}, Globals, }; @@ -127,89 +132,89 @@ enum BindingEdit { } impl Input { - pub fn draw_edit(&mut self, globals: &mut Globals, mut y: f32) { + pub fn draw_edit(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals, mut y: i32) { if self.editing_binding.is_some() { globals.mouse.clear(); } - let buttons_x = 220.; - let binding_text_x = buttons_x + 135.; + let buttons_x = 220; + let binding_text_x = buttons_x + 135; for action_index in 0..ActionId::SIZE { let action = ActionId::from_usize(action_index).unwrap(); // if self.action_states[action_index] == BindingState::Pressed { - // draw_rectangle(200, y, 20, 20, colors::LIMEGREEN); + // d.draw_rectangle(200, y, 20, 20, Color::LIMEGREEN); // } - draw_text(&format!("{action:?}"), 16., y, 20., colors::ORANGE); + d.draw_text(&format!("{action:?}"), 16, y, 20, Color::ORANGE); for (binding_index, binding) in self.action_bindings[action_index].iter().enumerate() { - if text_button(&globals.mouse, buttons_x, y, 80., "remove") { + if text_button(d, &globals.mouse, buttons_x, y, 80, "remove") { self.action_bindings[action_index].remove(binding_index); self.update_modifier_blocks(); return; } - if text_button(&globals.mouse, buttons_x + 85., y, 45., "edit") { + if text_button(d, &globals.mouse, buttons_x + 85, y, 45, "edit") { self.editing_binding = Some((action, binding_index, BindingEdit::Init)); } // let trigger = format!("{:?}", binding.trigger); let mut x = binding_text_x; - draw_text(&trigger, x, y + 5., 20., colors::GREEN); - x += 10. + measure_text(&trigger, None, 20, 1.).width; + d.draw_text(&trigger, x, y + 5, 20, Color::LIMEGREEN); + x += 10 + d.measure_text(&trigger, 20); // let modifiers = format!("{:?}", binding.modifiers); - draw_text(&modifiers, x, y + 5., 20., colors::BLUE); - x += 10. + measure_text(&modifiers, None, 20, 1.).width; + d.draw_text(&modifiers, x, y + 5, 20, Color::LIGHTBLUE); + x += 10 + d.measure_text(&modifiers, 20); // let conflicts = conflicts(&self.action_bindings, binding, action); if !conflicts.is_empty() { let conflict_text = format!("also used by: {conflicts:?}"); - draw_text(&conflict_text, x, y + 5., 20., colors::ORANGE); - x += 10. + measure_text(&conflict_text, None, 20, 1.).width + d.draw_text(&conflict_text, x, y + 5, 20, Color::ORANGERED); + x += 10 + d.measure_text(&conflict_text, 20); } // if !binding.blocking_modifiers.is_empty() { let blocking_text = format!("not while: {:?}", binding.blocking_modifiers); - draw_text(&blocking_text, x, y + 5., 20., colors::GRAY); + d.draw_text(&blocking_text, x, y + 5, 20, Color::GRAY); } - y += 32.; + y += 32; } - if text_button(&globals.mouse, buttons_x, y, 130., "add binding") { + if text_button(d, &globals.mouse, buttons_x, y, 130, "add binding") { self.editing_binding = Some(( action, self.action_bindings[action_index].len(), BindingEdit::Init, )); } - y += 45.; + y += 45; } if let Some((action, binding_index, edit_state)) = &mut self.editing_binding { - globals.mouse.update(); - let border = screen_centered_rect(408., 128.); - draw_rectangle_rec(border, BG_LIGHT); - let bounds = screen_centered_rect(400., 120.); - draw_rectangle_rec(bounds, BG_DARK); - let x = bounds.x; - let y = bounds.y; - draw_text( + globals.mouse.update(d); + let border = screen_centered_rect(d, 408, 128); + d.draw_rectangle_rec(border, BG_LIGHT); + let bounds = screen_centered_rect(d, 400, 120); + d.draw_rectangle_rec(bounds, BG_DARK); + let x = bounds.x as i32; + let y = bounds.y as i32; + d.draw_text( &format!("editing binding for {action:?}"), - x + 10., - y + 5., - 20., - colors::WHITE, + x + 10, + y + 5, + 20, + Color::WHITE, ); - let y = y + 30.; - let ok_btn_x = x + 10.; - let ok_btn_y = y + 40.; - let ok_btn_width = 80.; - let ok_btn_rect = Rect::new(ok_btn_x, ok_btn_y, ok_btn_width, 30.); + let y = y + 30; + let ok_btn_x = x + 10; + let ok_btn_y = y + 40; + let ok_btn_width = 80; + let ok_btn_rect = rect(ok_btn_x, ok_btn_y, ok_btn_width, 30); for key_index in 0..Button::SIZE { let key = Button::from_usize(key_index).unwrap(); match edit_state { BindingEdit::Init => { - if key.just_pressed() { + if key.just_pressed(d) { *edit_state = BindingEdit::Adding(Binding { blocking_modifiers: Vec::new(), modifiers: Vec::new(), @@ -218,12 +223,12 @@ impl Input { } } BindingEdit::Adding(binding) => { - if key.just_pressed() { + if key.just_pressed(d) { if key != binding.trigger && !binding.modifiers.contains(&key) { binding.modifiers.push(binding.trigger); binding.trigger = key; } - } else if key.released() { + } else if key.released(d) { if let Some(i) = binding.modifiers.iter().position(|&k| k == key) { binding.modifiers.remove(i); binding.modifiers.push(binding.trigger); @@ -235,7 +240,7 @@ impl Input { BindingEdit::Releasing(_binding) => { let clicking_ok = globals.mouse.is_over(ok_btn_rect) && key == Button::MouseLeft; - if key.just_pressed() && !clicking_ok { + if key.just_pressed(d) && !clicking_ok { *edit_state = BindingEdit::Adding(Binding { blocking_modifiers: Vec::new(), modifiers: Vec::new(), @@ -248,25 +253,25 @@ impl Input { if let BindingEdit::Adding(b) | BindingEdit::Releasing(b) = &edit_state { let colour = if matches!(edit_state, BindingEdit::Releasing(_)) { - colors::GREEN + Color::GREEN } else { - colors::ORANGE + Color::ORANGE }; let text = format!("{:?} + {:?}", b.modifiers, b.trigger); - draw_text(&text, x + 5., y + 5., 20., colour); + d.draw_text(&text, x + 5, y + 5, 20, colour); let conflicts = conflicts(&self.action_bindings, b, *action); if !conflicts.is_empty() { - draw_text( + d.draw_text( &format!("conflicts: {conflicts:?}"), - x + 200., - y + 40., - 20., - colors::ORANGE, + x + 200, + y + 40, + 20, + Color::ORANGERED, ); } } - if text_button(&globals.mouse, ok_btn_x, ok_btn_y, ok_btn_width, "ok") { + if text_button(d, &globals.mouse, ok_btn_x, ok_btn_y, ok_btn_width, "ok") { if let BindingEdit::Releasing(binding) = edit_state { let binding_list = &mut self.action_bindings[*action as usize]; if *binding_index < binding_list.len() { @@ -278,17 +283,17 @@ impl Input { self.update_modifier_blocks(); } } - if text_button(&globals.mouse, x + 100., y + 40., 80., "cancel") { + if text_button(d, &globals.mouse, x + 100, y + 40, 80, "cancel") { self.editing_binding = None; } } } - pub fn update(&mut self) { + pub fn update(&mut self, rl: &RaylibHandle) { for i in 0..Button::SIZE { let button = Button::from_usize(i).unwrap(); let state = &mut self.key_states[i]; - *state = if button.is_down() { + *state = if button.is_down(rl) { match state { BindingState::Off | BindingState::Released => BindingState::Pressed, BindingState::Pressed | BindingState::Held => BindingState::Held, @@ -459,10 +464,10 @@ enum Button { MouseLeft, MouseRight, MouseMiddle, - // Mouse3, - // Mouse4, - // Mouse5, - // Mouse6, + Mouse3, + Mouse4, + Mouse5, + Mouse6, Apostrophe, Comma, Minus, @@ -569,12 +574,14 @@ enum Button { KpEnter, KpEqual, Back, + VolumeUp, + VolumeDown, // _EnumSize, } enum RlInput { - Key(KeyCode), + Key(KeyboardKey), Mouse(MouseButton), } @@ -589,143 +596,146 @@ impl Button { } } - fn is_down(self) -> bool { + fn is_down(self, rl: &RaylibHandle) -> bool { match self.to_raylib() { - RlInput::Key(key) => is_key_down(key), - RlInput::Mouse(btn) => is_mouse_button_down(btn), + RlInput::Key(key) => rl.is_key_down(key), + RlInput::Mouse(btn) => rl.is_mouse_button_down(btn), } } - fn just_pressed(self) -> bool { + fn just_pressed(self, rl: &RaylibHandle) -> bool { match self.to_raylib() { - RlInput::Key(key) => is_key_pressed(key), - RlInput::Mouse(btn) => is_mouse_button_pressed(btn), + RlInput::Key(key) => rl.is_key_pressed(key), + RlInput::Mouse(btn) => rl.is_mouse_button_pressed(btn), } } - fn released(self) -> bool { + fn released(self, rl: &RaylibHandle) -> bool { match self.to_raylib() { - RlInput::Key(key) => is_key_released(key), - RlInput::Mouse(btn) => is_mouse_button_released(btn), + RlInput::Key(key) => rl.is_key_released(key), + RlInput::Mouse(btn) => rl.is_mouse_button_released(btn), } } fn to_raylib(self) -> RlInput { + use KeyboardKey::*; use RlInput::*; match self { - Button::MouseLeft => Mouse(MouseButton::Left), - Button::MouseRight => Mouse(MouseButton::Right), - Button::MouseMiddle => Mouse(MouseButton::Middle), - // Button::Mouse3 => Mouse(MouseButton::MOUSE_BUTTON_SIDE), - // Button::Mouse4 => Mouse(MouseButton::MOUSE_BUTTON_EXTRA), - // Button::Mouse5 => Mouse(MouseButton::MOUSE_BUTTON_FORWARD), - // Button::Mouse6 => Mouse(MouseButton::MOUSE_BUTTON_BACK), - Button::Apostrophe => Key(KeyCode::Apostrophe), - Button::Comma => Key(KeyCode::Comma), - Button::Minus => Key(KeyCode::Minus), - Button::Period => Key(KeyCode::Period), - Button::Slash => Key(KeyCode::Slash), - Button::Zero => Key(KeyCode::Key0), - Button::One => Key(KeyCode::Key1), - Button::Two => Key(KeyCode::Key2), - Button::Three => Key(KeyCode::Key3), - Button::Four => Key(KeyCode::Key4), - Button::Five => Key(KeyCode::Key5), - Button::Six => Key(KeyCode::Key6), - Button::Seven => Key(KeyCode::Key7), - Button::Eight => Key(KeyCode::Key8), - Button::Nine => Key(KeyCode::Key9), - Button::Semicolon => Key(KeyCode::Semicolon), - Button::Equal => Key(KeyCode::Equal), - Button::A => Key(KeyCode::A), - Button::B => Key(KeyCode::B), - Button::C => Key(KeyCode::C), - Button::D => Key(KeyCode::D), - Button::E => Key(KeyCode::E), - Button::F => Key(KeyCode::F), - Button::G => Key(KeyCode::G), - Button::H => Key(KeyCode::H), - Button::I => Key(KeyCode::I), - Button::J => Key(KeyCode::J), - Button::K => Key(KeyCode::K), - Button::L => Key(KeyCode::L), - Button::M => Key(KeyCode::M), - Button::N => Key(KeyCode::N), - Button::O => Key(KeyCode::O), - Button::P => Key(KeyCode::P), - Button::Q => Key(KeyCode::Q), - Button::R => Key(KeyCode::R), - Button::S => Key(KeyCode::S), - Button::T => Key(KeyCode::T), - Button::U => Key(KeyCode::U), - Button::V => Key(KeyCode::V), - Button::W => Key(KeyCode::W), - Button::X => Key(KeyCode::X), - Button::Y => Key(KeyCode::Y), - Button::Z => Key(KeyCode::Z), - Button::LeftBracket => Key(KeyCode::LeftBracket), - Button::Backslash => Key(KeyCode::Backslash), - Button::RightBracket => Key(KeyCode::RightBracket), - Button::Grave => Key(KeyCode::GraveAccent), - Button::Space => Key(KeyCode::Space), - Button::Escape => Key(KeyCode::Escape), - Button::Enter => Key(KeyCode::Enter), - Button::Tab => Key(KeyCode::Tab), - Button::Backspace => Key(KeyCode::Backspace), - Button::Insert => Key(KeyCode::Insert), - Button::Delete => Key(KeyCode::Delete), - Button::Right => Key(KeyCode::Right), - Button::Left => Key(KeyCode::Left), - Button::Down => Key(KeyCode::Down), - Button::Up => Key(KeyCode::Up), - Button::PageUp => Key(KeyCode::PageUp), - Button::PageDown => Key(KeyCode::PageDown), - Button::Home => Key(KeyCode::Home), - Button::End => Key(KeyCode::End), - Button::CapsLock => Key(KeyCode::CapsLock), - Button::ScrollLock => Key(KeyCode::ScrollLock), - Button::NumLock => Key(KeyCode::NumLock), - Button::PrintScreen => Key(KeyCode::PrintScreen), - Button::Pause => Key(KeyCode::Pause), - Button::F1 => Key(KeyCode::F1), - Button::F2 => Key(KeyCode::F2), - Button::F3 => Key(KeyCode::F3), - Button::F4 => Key(KeyCode::F4), - Button::F5 => Key(KeyCode::F5), - Button::F6 => Key(KeyCode::F6), - Button::F7 => Key(KeyCode::F7), - Button::F8 => Key(KeyCode::F8), - Button::F9 => Key(KeyCode::F9), - Button::F10 => Key(KeyCode::F10), - Button::F11 => Key(KeyCode::F11), - Button::F12 => Key(KeyCode::F12), - Button::LShift => Key(KeyCode::LeftShift), - Button::LCtrl => Key(KeyCode::LeftControl), - Button::LAlt => Key(KeyCode::LeftAlt), - Button::LeftSuper => Key(KeyCode::LeftSuper), - Button::RShift => Key(KeyCode::RightShift), - Button::RCtrl => Key(KeyCode::RightControl), - Button::RAlt => Key(KeyCode::RightAlt), - Button::RightSuper => Key(KeyCode::RightSuper), - Button::Menu => Key(KeyCode::Menu), - Button::Kp0 => Key(KeyCode::Kp0), - Button::Kp1 => Key(KeyCode::Kp1), - Button::Kp2 => Key(KeyCode::Kp2), - Button::Kp3 => Key(KeyCode::Kp3), - Button::Kp4 => Key(KeyCode::Kp4), - Button::Kp5 => Key(KeyCode::Kp5), - Button::Kp6 => Key(KeyCode::Kp6), - Button::Kp7 => Key(KeyCode::Kp7), - Button::Kp8 => Key(KeyCode::Kp8), - Button::Kp9 => Key(KeyCode::Kp9), - Button::KpDecimal => Key(KeyCode::KpDecimal), - Button::KpDivide => Key(KeyCode::KpDivide), - Button::KpMultiply => Key(KeyCode::KpMultiply), - Button::KpSubtract => Key(KeyCode::KpSubtract), - Button::KpAdd => Key(KeyCode::KpAdd), - Button::KpEnter => Key(KeyCode::KpEnter), - Button::KpEqual => Key(KeyCode::KpEqual), - Button::Back => Key(KeyCode::Back), + Button::MouseLeft => Mouse(MouseButton::MOUSE_BUTTON_LEFT), + Button::MouseRight => Mouse(MouseButton::MOUSE_BUTTON_RIGHT), + Button::MouseMiddle => Mouse(MouseButton::MOUSE_BUTTON_MIDDLE), + Button::Mouse3 => Mouse(MouseButton::MOUSE_BUTTON_SIDE), + Button::Mouse4 => Mouse(MouseButton::MOUSE_BUTTON_EXTRA), + Button::Mouse5 => Mouse(MouseButton::MOUSE_BUTTON_FORWARD), + Button::Mouse6 => Mouse(MouseButton::MOUSE_BUTTON_BACK), + Button::Apostrophe => Key(KEY_APOSTROPHE), + Button::Comma => Key(KEY_COMMA), + Button::Minus => Key(KEY_MINUS), + Button::Period => Key(KEY_PERIOD), + Button::Slash => Key(KEY_SLASH), + Button::Zero => Key(KEY_ZERO), + Button::One => Key(KEY_ONE), + Button::Two => Key(KEY_TWO), + Button::Three => Key(KEY_THREE), + Button::Four => Key(KEY_FOUR), + Button::Five => Key(KEY_FIVE), + Button::Six => Key(KEY_SIX), + Button::Seven => Key(KEY_SEVEN), + Button::Eight => Key(KEY_EIGHT), + Button::Nine => Key(KEY_NINE), + Button::Semicolon => Key(KEY_SEMICOLON), + Button::Equal => Key(KEY_EQUAL), + Button::A => Key(KEY_A), + Button::B => Key(KEY_B), + Button::C => Key(KEY_C), + Button::D => Key(KEY_D), + Button::E => Key(KEY_E), + Button::F => Key(KEY_F), + Button::G => Key(KEY_G), + Button::H => Key(KEY_H), + Button::I => Key(KEY_I), + Button::J => Key(KEY_J), + Button::K => Key(KEY_K), + Button::L => Key(KEY_L), + Button::M => Key(KEY_M), + Button::N => Key(KEY_N), + Button::O => Key(KEY_O), + Button::P => Key(KEY_P), + Button::Q => Key(KEY_Q), + Button::R => Key(KEY_R), + Button::S => Key(KEY_S), + Button::T => Key(KEY_T), + Button::U => Key(KEY_U), + Button::V => Key(KEY_V), + Button::W => Key(KEY_W), + Button::X => Key(KEY_X), + Button::Y => Key(KEY_Y), + Button::Z => Key(KEY_Z), + Button::LeftBracket => Key(KEY_LEFT_BRACKET), + Button::Backslash => Key(KEY_BACKSLASH), + Button::RightBracket => Key(KEY_RIGHT_BRACKET), + Button::Grave => Key(KEY_GRAVE), + Button::Space => Key(KEY_SPACE), + Button::Escape => Key(KEY_ESCAPE), + Button::Enter => Key(KEY_ENTER), + Button::Tab => Key(KEY_TAB), + Button::Backspace => Key(KEY_BACKSPACE), + Button::Insert => Key(KEY_INSERT), + Button::Delete => Key(KEY_DELETE), + Button::Right => Key(KEY_RIGHT), + Button::Left => Key(KEY_LEFT), + Button::Down => Key(KEY_DOWN), + Button::Up => Key(KEY_UP), + Button::PageUp => Key(KEY_PAGE_UP), + Button::PageDown => Key(KEY_PAGE_DOWN), + Button::Home => Key(KEY_HOME), + Button::End => Key(KEY_END), + Button::CapsLock => Key(KEY_CAPS_LOCK), + Button::ScrollLock => Key(KEY_SCROLL_LOCK), + Button::NumLock => Key(KEY_NUM_LOCK), + Button::PrintScreen => Key(KEY_PRINT_SCREEN), + Button::Pause => Key(KEY_PAUSE), + Button::F1 => Key(KEY_F1), + Button::F2 => Key(KEY_F2), + Button::F3 => Key(KEY_F3), + Button::F4 => Key(KEY_F4), + Button::F5 => Key(KEY_F5), + Button::F6 => Key(KEY_F6), + Button::F7 => Key(KEY_F7), + Button::F8 => Key(KEY_F8), + Button::F9 => Key(KEY_F9), + Button::F10 => Key(KEY_F10), + Button::F11 => Key(KEY_F11), + Button::F12 => Key(KEY_F12), + Button::LShift => Key(KEY_LEFT_SHIFT), + Button::LCtrl => Key(KEY_LEFT_CONTROL), + Button::LAlt => Key(KEY_LEFT_ALT), + Button::LeftSuper => Key(KEY_LEFT_SUPER), + Button::RShift => Key(KEY_RIGHT_SHIFT), + Button::RCtrl => Key(KEY_RIGHT_CONTROL), + Button::RAlt => Key(KEY_RIGHT_ALT), + Button::RightSuper => Key(KEY_RIGHT_SUPER), + Button::Menu => Key(KEY_KB_MENU), + Button::Kp0 => Key(KEY_KP_0), + Button::Kp1 => Key(KEY_KP_1), + Button::Kp2 => Key(KEY_KP_2), + Button::Kp3 => Key(KEY_KP_3), + Button::Kp4 => Key(KEY_KP_4), + Button::Kp5 => Key(KEY_KP_5), + Button::Kp6 => Key(KEY_KP_6), + Button::Kp7 => Key(KEY_KP_7), + Button::Kp8 => Key(KEY_KP_8), + Button::Kp9 => Key(KEY_KP_9), + Button::KpDecimal => Key(KEY_KP_DECIMAL), + Button::KpDivide => Key(KEY_KP_DIVIDE), + Button::KpMultiply => Key(KEY_KP_MULTIPLY), + Button::KpSubtract => Key(KEY_KP_SUBTRACT), + Button::KpAdd => Key(KEY_KP_ADD), + Button::KpEnter => Key(KEY_KP_ENTER), + Button::KpEqual => Key(KEY_KP_EQUAL), + Button::Back => Key(KEY_BACK), + Button::VolumeUp => Key(KEY_VOLUME_UP), + Button::VolumeDown => Key(KEY_VOLUME_DOWN), Button::_EnumSize => unreachable!(), } } diff --git a/src/lib.rs b/src/lib.rs index 7b1dec4..fb0cef0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,7 @@ use std::fs; use arboard::Clipboard; use config::Config; use input::ActionId; -use macroquad::prelude::*; +use raylib::{texture::Texture2D, RaylibHandle}; use util::{userdata_dir, MouseInput, Textures}; // use util::MouseInput; @@ -29,11 +29,11 @@ pub struct Globals { } impl Globals { - pub async fn new() -> Self { + pub fn new(rl: &mut RaylibHandle, thread: &raylib::prelude::RaylibThread) -> Self { let mut textures = Textures::default(); - textures.load_dir("assets").await; - textures.load_dir("assets/tiles").await; - textures.load_dir("assets/digits").await; + textures.load_dir("assets", rl, thread); + textures.load_dir("assets/tiles", rl, thread); + textures.load_dir("assets/digits", rl, thread); let config_path = userdata_dir().join(CONFIG_FILE_NAME); let mut config: Config = fs::read_to_string(config_path) @@ -52,9 +52,9 @@ impl Globals { } } - pub fn update(&mut self) { - self.config.input.update(); - self.mouse.update(); + pub fn update(&mut self, rl: &RaylibHandle) { + self.config.input.update(rl); + self.mouse.update(rl); } pub fn is_pressed(&self, action: ActionId) -> bool { diff --git a/src/main.rs b/src/main.rs index 86f973a..6d2b0eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use std::{ io::Write, }; -use macroquad::{color::colors, miniquad::window::set_mouse_cursor, prelude::*}; +use raylib::prelude::*; use marble_machinations::*; @@ -20,7 +20,7 @@ const TITLE_TEXT: &str = concat!("Marble Machinations v", env!("CARGO_PKG_VERSIO struct Game { chapters: Vec, - level_scroll: f32, + level_scroll: i32, solutions: HashMap>, open_editor: Option, selected_level: (usize, usize), @@ -32,43 +32,45 @@ struct Game { edit_settings: Option, } -#[macroquad::main("what does thsi doa")] -async fn main() { - // let (mut rl, thread) = raylib::init().resizable().title(TITLE_TEXT).build(); - // set_target_fps(60); - // set_window_min_size(640, 480); - set_mouse_cursor(miniquad::CursorIcon::Crosshair); +fn main() { + let (mut rl, thread) = raylib::init().resizable().title(TITLE_TEXT).build(); + rl.set_target_fps(60); + rl.set_window_min_size(640, 480); + rl.set_mouse_cursor(MouseCursor::MOUSE_CURSOR_CROSSHAIR); + rl.set_exit_key(None); + rl.set_trace_log(TraceLogLevel::LOG_WARNING); - let mut game = Game::new().await; - game.run().await + let mut game = Game::new(&mut rl, &thread); + game.run(&mut rl, &thread); } impl Game { - async fn new() -> Self { + fn new(rl: &mut RaylibHandle, thread: &RaylibThread) -> Self { let solutions = get_solutions(); let chapters = get_chapters(&solutions); Self { chapters, - level_scroll: 0., + level_scroll: 0, solutions, open_editor: None, selected_level: (0, 0), selected_solution: 0, delete_solution: None, editing_solution_name: false, - level_desc_text: ShapedText::new(20.), - globals: Globals::new().await, + level_desc_text: ShapedText::new(20), + globals: Globals::new(rl, thread), edit_settings: None, } } - async fn run(&mut self) { - loop { - self.globals.update(); + fn run(&mut self, rl: &mut RaylibHandle, thread: &RaylibThread) { + while !rl.window_should_close() { + let mut d = rl.begin_drawing(thread); + self.globals.update(&d); if let Some(editor) = &mut self.open_editor { - editor.update(&mut self.globals); - editor.draw(&mut self.globals); + editor.update(&d, &mut self.globals); + editor.draw(&mut d, &mut self.globals); match editor.get_exit_state() { ExitState::Dont => (), ExitState::ExitAndSave => { @@ -88,8 +90,8 @@ impl Game { } } } else if let Some(config) = &mut self.edit_settings { - clear_background(BG_DARK); - match config.draw_edit(&mut self.globals) { + d.clear_background(BG_DARK); + match config.draw_edit(&mut d, &mut self.globals) { config::MenuReturn::Stay => (), config::MenuReturn::StaySave => { self.globals.config = config.clone(); @@ -103,65 +105,65 @@ impl Game { config::MenuReturn::ReturnCancel => self.edit_settings = None, } } else { - self.draw(); + self.draw(&mut d); } - next_frame().await } } - fn draw(&mut self) { - clear_background(BG_DARK); + fn draw(&mut self, d: &mut RaylibDrawHandle) { + d.clear_background(BG_DARK); let mut tooltip = Tooltip::default(); - tooltip.init_frame(); + tooltip.init_frame(d); - draw_text( + d.draw_text( TITLE_TEXT, - screen_width() - 275., - screen_height() - 20., - 20., - colors::GRAY, + d.get_screen_width() - 275, + d.get_screen_height() - 20, + 20, + Color::GRAY, ); - let level_list_width = (screen_width() / 3.).min(400.); - - draw_rectangle(0., 0., level_list_width, screen_height(), BG_MEDIUM); + let level_list_width = (d.get_screen_width() / 3).min(400); + let screen_height = d.get_screen_height(); + d.draw_rectangle(0, 0, level_list_width, screen_height, BG_MEDIUM); if text_button( + d, &self.globals.mouse, - screen_width() - 100., - screen_height() - 70., - 90., + d.get_screen_width() - 100, + d.get_screen_height() - 70, + 90, "settings", ) { self.edit_settings = Some(self.globals.config.clone()); } - const ENTRY_SPACING: f32 = 65.; - let fit_on_screen = (screen_height() / ENTRY_SPACING) as usize; + const ENTRY_SPACING: i32 = 65; + let fit_on_screen = (d.get_screen_height() / ENTRY_SPACING) as usize; let max_scroll = self .chapters .iter() .map(|c| 1 + if c.visible { c.levels.len() } else { 0 }) .sum::() - .saturating_sub(fit_on_screen) as f32 + .saturating_sub(fit_on_screen) as i32 * ENTRY_SPACING; - if self.globals.mouse.pos().x < level_list_width { + if self.globals.mouse.pos().x < level_list_width as f32 { if self.globals.mouse.scroll() == Some(Scroll::Down) && self.level_scroll < max_scroll { self.level_scroll += ENTRY_SPACING; } - if self.globals.mouse.scroll() == Some(Scroll::Up) && self.level_scroll > 0. { + if self.globals.mouse.scroll() == Some(Scroll::Up) && self.level_scroll > 0 { self.level_scroll -= ENTRY_SPACING; } } - let mut y = 10. - self.level_scroll; + let mut y = 10 - self.level_scroll; for (chapter_i, chapter) in self.chapters.iter_mut().enumerate() { - let bounds = Rect::new(5., y - 5., level_list_width - 10., ENTRY_SPACING - 5.); - draw_rectangle_rec(bounds, BG_DARK); - draw_text(&chapter.title, 10., y, 30., FG_CHAPTER_TITLE); + let bounds = rect(5, y - 5, level_list_width - 10, ENTRY_SPACING - 5); + d.draw_rectangle_rec(bounds, BG_DARK); + d.draw_text(&chapter.title, 10, y, 30, FG_CHAPTER_TITLE); let subtitle = format!("{} levels", chapter.levels.len()); - draw_text(&subtitle, 10., y + 30., 20., colors::WHITE); + d.draw_text(&subtitle, 10, y + 30, 20, Color::WHITE); y += ENTRY_SPACING; let clicked_this = self.globals.mouse.left_click() && self.globals.mouse.is_over(bounds); @@ -175,7 +177,7 @@ impl Game { } for (level_index, level) in chapter.levels.iter().enumerate() { - let bounds = Rect::new(5., y - 5., level_list_width - 10., ENTRY_SPACING - 5.); + let bounds = rect(5, y - 5, level_list_width - 10, ENTRY_SPACING - 5); let clicked_this = self.globals.mouse.left_click() && self.globals.mouse.is_over(bounds); @@ -189,18 +191,18 @@ impl Game { self.selected_solution = solutions.len().saturating_sub(1); } } - draw_rectangle_rec( + d.draw_rectangle_rec( bounds, widget_bg(self.selected_level == (chapter_i, level_index)), ); - let mut title_color = colors::WHITE; + let mut title_color = Color::WHITE; if let Some(solutions) = self.solutions.get(level.id()) { if solutions.iter().any(|s| s.score.is_some()) { - title_color = colors::GREEN; + title_color = Color::LIGHTGREEN; } } - draw_text(level.name(), 10., y, 30., title_color); + d.draw_text(level.name(), 10, y, 30, title_color); let solution_count = self .solutions .get(level.id()) @@ -208,11 +210,11 @@ impl Game { .unwrap_or_default(); let subtext = format!("solutions: {solution_count}"); let subtext_color = if solution_count > 0 { - colors::GOLD + Color::GOLD } else { - colors::LIGHTGRAY + Color::LIGHTGRAY }; - draw_text(&subtext, 10., y + 30., 20., subtext_color); + d.draw_text(&subtext, 10, y + 30, 20, subtext_color); y += ENTRY_SPACING; } } @@ -222,31 +224,25 @@ impl Game { .get(self.selected_level.0) .and_then(|c| c.levels.get(self.selected_level.1)) { - draw_text( - level.name(), - level_list_width + 10., - 10., - 40., - colors::SKYBLUE, - ); - draw_text(level.id(), level_list_width + 10., 50., 10., colors::GRAY); + d.draw_text(level.name(), level_list_width + 10, 10, 40, Color::CYAN); + d.draw_text(level.id(), level_list_width + 10, 50, 10, Color::GRAY); - let mut y = 70.; + let mut y = 70; self.level_desc_text.set_text(level.description()); self.level_desc_text - .update_width(screen_width() - level_list_width - 30.); - self.level_desc_text.draw(level_list_width + 10., y); - y += self.level_desc_text.height() + 10.; + .update_width(d, d.get_render_width() - level_list_width - 30); + self.level_desc_text.draw(d, level_list_width + 10, y); + y += self.level_desc_text.height() + 10; if let Some(solutions) = self.solutions.get_mut(level.id()) { - let solution_entry_height = 40.; - let entry_width = 200.; + let solution_entry_height = 40; + let entry_width = 200; let mut solution_y = y; for (solution_index, solution) in solutions.iter().enumerate() { if simple_option_button( - &self.globals.mouse, - Rect::new( - level_list_width + 10., + (d, &self.globals.mouse), + rect( + level_list_width + 10, solution_y, entry_width, solution_entry_height, @@ -257,39 +253,40 @@ impl Game { self.editing_solution_name = false; } let name_color = if solution.score.is_some() { - colors::LIME + Color::LIME } else { - colors::ORANGE + Color::ORANGE }; - draw_text( + d.draw_text( &solution.name, - level_list_width + 15., - solution_y + 5., - 20., + level_list_width + 15, + solution_y + 5, + 20, name_color, ); - draw_text( + d.draw_text( &solution.score_text(), - level_list_width + 15., - solution_y + 25., - 10., - colors::WHITE, + level_list_width + 15, + solution_y + 25, + 10, + Color::WHITE, ); if tex32_button( - &self.globals.mouse, - (level_list_width + entry_width + 15., solution_y + 4.), + (d, &self.globals.mouse), + (level_list_width + entry_width + 15, solution_y + 4), self.globals.get_tex("cancel"), (&mut tooltip, "delete"), ) { self.delete_solution = Some(solution_index); } - solution_y += solution_entry_height + 10.; + solution_y += solution_entry_height + 10; } let next_id = get_free_id(solutions, Solution::id); if text_button( + d, &self.globals.mouse, - level_list_width + 10., + level_list_width + 10, solution_y, entry_width, "new solution", @@ -300,23 +297,24 @@ impl Game { if let Some(i) = self.delete_solution { let text = format!("really delete solution '{}'?", &solutions[i].name); - let y = (solution_y + 40.).max(240.); - let x = level_list_width + 10.; - draw_text(&text, x, y, 20., colors::ORANGE); - if text_button(&self.globals.mouse, x, y + 30., 100., "yes") { + let y = (solution_y + 40).max(240); + let x = level_list_width + 10; + d.draw_text(&text, x, y, 20, Color::ORANGE); + if text_button(d, &self.globals.mouse, x, y + 30, 100, "yes") { solutions[i].remove_file(); solutions.remove(i); self.delete_solution = None; } - if text_button(&self.globals.mouse, x + 110., y + 30., 100., "no") { + if text_button(d, &self.globals.mouse, x + 110, y + 30, 100, "no") { self.delete_solution = None; } } if let Some(solution) = solutions.get_mut(self.selected_solution) { - let column_x = level_list_width + entry_width + 56.; - let bounds = Rect::new(column_x, y, 220., 30.); + let column_x = level_list_width + entry_width + 56; + let bounds = Rectangle::new(column_x as f32, y as f32, 220., 30.); if text_input( + d, &mut self.globals, bounds, &mut solution.name, @@ -327,18 +325,18 @@ impl Game { solution.save(); } let id_text = format!("{}", solution.id()); - draw_text(&id_text, column_x, y + 35., 10., colors::GRAY); + d.draw_text(&id_text, column_x, y + 35, 10, Color::GRAY); - if text_button(&self.globals.mouse, column_x, y + 50., 220., "clone") { + if text_button(d, &self.globals.mouse, column_x, y + 50, 220, "clone") { let cloned = solution.new_copy(next_id); self.selected_solution = solutions.len(); solutions.push(cloned); return; } - if text_button(&self.globals.mouse, column_x, y + 85., 220., "edit") { + if text_button(d, &self.globals.mouse, column_x, y + 85, 220, "edit") { let mut editor = Editor::new(solution.clone(), level.clone()); - editor.center_view(); + editor.center_view(d); self.open_editor = Some(editor); } } @@ -346,7 +344,7 @@ impl Game { self.solutions.insert(level.id().to_owned(), Vec::new()); } } - tooltip.draw(); + tooltip.draw(d); } fn save_config(&self) { diff --git a/src/marble_engine.rs b/src/marble_engine.rs index 1607317..7bd40a3 100644 --- a/src/marble_engine.rs +++ b/src/marble_engine.rs @@ -1,4 +1,4 @@ -use macroquad::prelude::*; +use raylib::prelude::*; pub mod grid; pub mod pos; @@ -99,23 +99,26 @@ impl Machine { self.input = bytes; } - pub fn draw_marble_values(&self, textures: &Textures, offset: Vec2, scale: f32) { - let tile_size = TILE_TEXTURE_SIZE * scale; + pub fn draw_marble_values( + &self, + d: &mut RaylibDrawHandle, + textures: &Textures, + offset: Vector2, + scale: f32, + ) { + let tile_size = (TILE_TEXTURE_SIZE * scale) as i32; for marble in &self.marbles { let x = marble.x; let y = marble.y; if let Some(tile) = self.grid.get(*marble) { - let px = x as f32 * tile_size + offset.x; - let py = y as f32 * tile_size + offset.y; + let px = x as i32 * tile_size + offset.x as i32; + let py = y as i32 * tile_size + offset.y as i32; if let Tile::Marble { value, dir } = tile { - let tex = textures.get(dir.arrow_texture_name()); - let faded_white = Color::from_rgba(255, 255, 255, 100); - let params = DrawTextureParams { - dest_size: Some(Vec2::new(tex.width() * scale, tex.height() * scale)), - ..Default::default() - }; - draw_texture_ex(tex, px, py, faded_white, params); - draw_usize_small(textures, value as usize, px, py, scale); + let texture = textures.get(dir.arrow_texture_name()); + let pos = Vector2::new(px as f32, py as f32); + let faded_white = Color::new(255, 255, 255, 100); + d.draw_texture_ex(texture, pos, 0., scale, faded_white); + draw_usize_small(d, textures, value as usize, px, py, scale); } } } @@ -541,10 +544,10 @@ impl Machine { let val_b = self.grid.get_or_blank(pos_b).read_value(); let result = match comp { - Comp::LessThan => val_a < val_b, - Comp::GreaterThan => val_a > val_b, - Comp::Equal => val_a == val_b, - Comp::NotEqual => val_a != val_b, + Comparison::LessThan => val_a < val_b, + Comparison::GreaterThan => val_a > val_b, + Comparison::Equal => val_a == val_b, + Comparison::NotEqual => val_a != val_b, }; if result { match self.grid.get_mut(front_pos) { diff --git a/src/marble_engine/grid.rs b/src/marble_engine/grid.rs index 77346dc..75a1475 100644 --- a/src/marble_engine/grid.rs +++ b/src/marble_engine/grid.rs @@ -1,4 +1,4 @@ -use macroquad::prelude::*; +use raylib::prelude::*; use serde::{Deserialize, Serialize}; use super::{tile::*, Pos, PosInt}; @@ -285,43 +285,44 @@ impl Grid { out } - pub fn draw(&self, textures: &Textures, offset: Vec2, scale: f32, power_directions: bool) { + pub fn draw( + &self, + d: &mut RaylibDrawHandle, + textures: &Textures, + offset: Vector2, + scale: f32, + power_directions: bool, + ) { let tile_size = (TILE_TEXTURE_SIZE * scale) as i32; let start_x = (-offset.x as i32) / tile_size - 1; - let tiles_width = screen_width() as i32 / tile_size + 3; + let tiles_width = d.get_screen_width() / tile_size + 3; let start_y = (-offset.y as i32) / tile_size - 1; - let tiles_height = screen_height() as i32 / tile_size + 3; + let tiles_height = d.get_screen_height() / tile_size + 3; for x in start_x..(start_x + tiles_width) { for y in start_y..(start_y + tiles_height) { - let px = (x * tile_size) as f32 + offset.x; - let py = (y * tile_size) as f32 + offset.y; + let px = x * tile_size + offset.x as i32; + let py = y * tile_size + offset.y as i32; if let Some(tile) = self.get((x, y).into()) { let texname = tile.texture(); if texname.is_empty() { continue; } let texture = textures.get(texname); - draw_scaled_texture(texture, px, py, scale); + draw_scaled_texture(d, texture, px, py, scale); if power_directions { if let Tile::Powerable(_, state) = &tile { for dir in Direction::ALL { if state.get_dir(dir) { let texture = textures.get(dir.debug_arrow_texture_name()); - draw_scaled_texture(texture, px, py, scale); + draw_scaled_texture(d, texture, px, py, scale); } } } } } else { - draw_rectangle( - px, - py, - tile_size as _, - tile_size as _, - Color::from_rgba(0, 0, 0, 80), - ); + d.draw_rectangle(px, py, tile_size, tile_size, Color::new(0, 0, 0, 80)); } } } diff --git a/src/marble_engine/pos.rs b/src/marble_engine/pos.rs index 7f2d5af..04cd8da 100644 --- a/src/marble_engine/pos.rs +++ b/src/marble_engine/pos.rs @@ -1,6 +1,6 @@ use std::ops::Add; -use macroquad::prelude::*; +use raylib::prelude::*; use serde::{Deserialize, Serialize}; pub type PosInt = i16; @@ -12,8 +12,8 @@ pub struct Pos { } impl Pos { - pub const fn to_vec(self) -> Vec2 { - Vec2 { + pub const fn to_vec(self) -> Vector2 { + Vector2 { x: self.x as f32, y: self.y as f32, } @@ -52,8 +52,8 @@ impl From<(i32, i32)> for Pos { } } -impl From for Pos { - fn from(vec: Vec2) -> Self { +impl From for Pos { + fn from(vec: Vector2) -> Self { Self { x: vec.x as PosInt, y: vec.y as PosInt, diff --git a/src/marble_engine/tile.rs b/src/marble_engine/tile.rs index da881e5..798c51c 100644 --- a/src/marble_engine/tile.rs +++ b/src/marble_engine/tile.rs @@ -31,7 +31,7 @@ pub enum OpenTile { #[derive(Debug, Clone, Copy, PartialEq)] pub enum PTile { - Comparator(Comp), + Comparator(Comparison), Math(MathOp), Silo, Flipper, @@ -59,7 +59,7 @@ pub enum MathOp { } #[derive(Debug, Clone, Copy, PartialEq)] -pub enum Comp { +pub enum Comparison { LessThan, GreaterThan, Equal, @@ -99,10 +99,10 @@ impl Tile { 'v' => Tile::Arrow(Direction::Down), '<' => Tile::Arrow(Direction::Left), '>' => Tile::Arrow(Direction::Right), - '=' => Tile::Powerable(PTile::Comparator(Comp::Equal), Power::OFF), - '!' => Tile::Powerable(PTile::Comparator(Comp::NotEqual), Power::OFF), - 'L' => Tile::Powerable(PTile::Comparator(Comp::LessThan), Power::OFF), - 'G' => Tile::Powerable(PTile::Comparator(Comp::GreaterThan), Power::OFF), + '=' => Tile::Powerable(PTile::Comparator(Comparison::Equal), Power::OFF), + '!' => Tile::Powerable(PTile::Comparator(Comparison::NotEqual), Power::OFF), + 'L' => Tile::Powerable(PTile::Comparator(Comparison::LessThan), Power::OFF), + 'G' => Tile::Powerable(PTile::Comparator(Comparison::GreaterThan), Power::OFF), 'I' | 'P' => Tile::Powerable(PTile::IO, Power::OFF), 'F' => Tile::Powerable(PTile::Flipper, Power::OFF), 'A' => Tile::Powerable(PTile::Math(MathOp::Add), Power::OFF), @@ -141,10 +141,10 @@ impl Tile { }, Tile::Powerable(tile, _) => match tile { PTile::Comparator(comp) => match comp { - Comp::LessThan => 'L', - Comp::GreaterThan => 'G', - Comp::Equal => '=', - Comp::NotEqual => '!', + Comparison::LessThan => 'L', + Comparison::GreaterThan => 'G', + Comparison::Equal => '=', + Comparison::NotEqual => '!', }, PTile::Math(math) => match math { MathOp::Add => 'A', @@ -453,49 +453,49 @@ impl MathOp { } } -impl Comp { +impl Comparison { pub const fn human_name(self) -> &'static str { match self { - Comp::LessThan => "Comparator: Less than", - Comp::GreaterThan => "Comparator: Greater than", - Comp::Equal => "Comparator: Equal", - Comp::NotEqual => "Comparator: Not Equal", + Comparison::LessThan => "Comparator: Less than", + Comparison::GreaterThan => "Comparator: Greater than", + Comparison::Equal => "Comparator: Equal", + Comparison::NotEqual => "Comparator: Not Equal", } } pub const fn texture_name_on(self) -> &'static str { match self { - Comp::LessThan => "lt_on", - Comp::GreaterThan => "gt_on", - Comp::Equal => "eq_on", - Comp::NotEqual => "neq_on", + Comparison::LessThan => "lt_on", + Comparison::GreaterThan => "gt_on", + Comparison::Equal => "eq_on", + Comparison::NotEqual => "neq_on", } } pub const fn texture_name_off(self) -> &'static str { match self { - Comp::LessThan => "lt_off", - Comp::GreaterThan => "gt_off", - Comp::Equal => "eq_off", - Comp::NotEqual => "neq_off", + Comparison::LessThan => "lt_off", + Comparison::GreaterThan => "gt_off", + Comparison::Equal => "eq_off", + Comparison::NotEqual => "neq_off", } } pub fn next(&mut self) { *self = match self { - Comp::LessThan => Comp::GreaterThan, - Comp::GreaterThan => Comp::Equal, - Comp::Equal => Comp::NotEqual, - Comp::NotEqual => Comp::LessThan, + Comparison::LessThan => Comparison::GreaterThan, + Comparison::GreaterThan => Comparison::Equal, + Comparison::Equal => Comparison::NotEqual, + Comparison::NotEqual => Comparison::LessThan, } } pub fn prev(&mut self) { *self = match self { - Comp::LessThan => Comp::NotEqual, - Comp::GreaterThan => Comp::LessThan, - Comp::Equal => Comp::GreaterThan, - Comp::NotEqual => Comp::Equal, + Comparison::LessThan => Comparison::NotEqual, + Comparison::GreaterThan => Comparison::LessThan, + Comparison::Equal => Comparison::GreaterThan, + Comparison::NotEqual => Comparison::Equal, } } } diff --git a/src/theme.rs b/src/theme.rs index 62ba513..e470639 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -1,4 +1,4 @@ -use macroquad::prelude::*; +use raylib::prelude::*; pub const TILE_TEXTURE_SIZE: f32 = 16.0; @@ -12,8 +12,6 @@ pub const BG_WIDGET: Color = gray(64); pub const BG_WIDGET_ACTIVE: Color = rgb(80, 120, 180); pub const FG_MARBLE_VALUE: Color = rgb(255, 80, 40); pub const FG_CHAPTER_TITLE: Color = rgb(255, 160, 40); -pub const SLIDER_FILL: Color = rgb(255, 160, 40); -pub const LIGHTBLUE: Color = rgb(80, 190, 230); pub const fn widget_bg(highlight: bool) -> Color { if highlight { @@ -24,9 +22,9 @@ pub const fn widget_bg(highlight: bool) -> Color { } pub const fn rgb(r: u8, g: u8, b: u8) -> Color { - Color::from_rgba(r, g, b, 255) + Color::new(r, g, b, 255) } pub const fn gray(value: u8) -> Color { - Color::from_rgba(value, value, value, 255) + Color::new(value, value, value, 255) } diff --git a/src/ui.rs b/src/ui.rs index c5b461c..360e2ee 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -2,25 +2,25 @@ use std::ops::Range; use crate::{ theme::*, - util::{draw_rectangle_rec, draw_scaled_texture, MouseInput, Scroll, Textures}, + util::{draw_scaled_texture, rect, MouseInput, Scroll, Textures}, Globals, }; -use macroquad::{color::colors, prelude::*}; +use raylib::prelude::*; #[derive(Debug)] pub struct ShapedText { text: String, - max_width: f32, - font_size: f32, + max_width: i32, + font_size: i32, lines: Vec>, } impl ShapedText { - pub fn new(font_size: f32) -> Self { + pub fn new(font_size: i32) -> Self { Self { text: String::new(), font_size, - max_width: 500., + max_width: 500, lines: Vec::new(), } } @@ -32,11 +32,11 @@ impl ShapedText { } } - pub fn height(&self) -> f32 { - self.font_size * self.lines.len() as f32 + pub fn height(&self) -> i32 { + self.font_size * self.lines.len() as i32 } - pub fn update_width(&mut self, width: f32) { + pub fn update_width(&mut self, d: &RaylibHandle, width: i32) { if self.max_width == width && !self.lines.is_empty() { return; } @@ -48,7 +48,7 @@ impl ShapedText { for (i, c) in self.text.char_indices() { if c == ' ' { let line = &self.text[line_start..i]; - let new_line_length = measure_text(line, None, self.font_size as _, 1.).width; + let new_line_length = d.measure_text(line, self.font_size); if new_line_length <= self.max_width { line_end = i; } else { @@ -58,7 +58,7 @@ impl ShapedText { } if c == '\n' { let line = &self.text[line_start..i]; - let new_line_length = measure_text(line, None, self.font_size as _, 1.).width; + let new_line_length = d.measure_text(line, self.font_size); if new_line_length <= self.max_width { self.lines.push(line_start..i); line_end = i + 1; @@ -73,7 +73,7 @@ impl ShapedText { } let i = self.text.len(); let line = &self.text[line_start..i]; - let new_line_length = measure_text(line, None, self.font_size as _, 1.).width; + let new_line_length = d.measure_text(line, self.font_size); if new_line_length <= self.max_width { self.lines.push(line_start..i); } else { @@ -82,12 +82,12 @@ impl ShapedText { } } - pub fn draw(&self, x: f32, y: f32) { - // draw_rectangle(x, y, self.max_width, 4, Color::RED); + pub fn draw(&self, d: &mut RaylibDrawHandle, x: i32, y: i32) { + // d.draw_rectangle(x, y, self.max_width, 4, Color::RED); for (i, line) in self.lines.iter().enumerate() { let line = &self.text[line.clone()]; - let line_y = y + self.font_size * i as f32; - draw_text(line, x, line_y, self.font_size, colors::WHITE); + let line_y = y + self.font_size * i as i32; + d.draw_text(line, x, line_y, self.font_size, Color::WHITE); } } } @@ -95,25 +95,25 @@ impl ShapedText { #[derive(Debug, Default)] pub struct Tooltip { text: Option<&'static str>, - mouse_x: f32, - mouse_y: f32, - screen_width: f32, - screen_height: f32, + mouse_x: i32, + mouse_y: i32, + screen_width: i32, + screen_height: i32, } impl Tooltip { - pub fn init_frame(&mut self) { - let (mouse_x, mouse_y) = mouse_position(); + pub fn init_frame(&mut self, d: &RaylibHandle) { + let p = d.get_mouse_position(); *self = Self { text: None, - mouse_x, - mouse_y, - screen_width: screen_width(), - screen_height: screen_height(), + mouse_x: p.x as i32, + mouse_y: p.y as i32, + screen_width: d.get_screen_width(), + screen_height: d.get_screen_height(), }; } - pub fn add(&mut self, x: f32, y: f32, width: f32, height: f32, text: &'static str) { + pub fn add(&mut self, x: i32, y: i32, width: i32, height: i32, text: &'static str) { if self.mouse_x >= x && self.mouse_y >= y && self.mouse_x <= (x + width) @@ -127,91 +127,122 @@ impl Tooltip { self.text = None; } - pub fn add_rec(&mut self, bounds: Rect, text: &'static str) { - self.add(bounds.x, bounds.y, bounds.w, bounds.h, text); + pub fn add_rec(&mut self, bounds: Rectangle, text: &'static str) { + self.add( + bounds.x as i32, + bounds.y as i32, + bounds.width as i32, + bounds.height as i32, + text, + ); } - pub fn draw(&self) { + pub fn draw(&self, d: &mut RaylibDrawHandle) { if let Some(text) = self.text { - let font_size = 20.0; - let margin = 4.0; - let text_width = measure_text(text, None, font_size as _, 1.).width; + let font_size = 20; + let margin = 4; + let text_width = d.measure_text(text, font_size); let x = self .mouse_x - .min(self.screen_width - text_width - margin * 2.); + .min(self.screen_width - text_width - margin * 2); let y = self .mouse_y - .min(self.screen_height - font_size - margin * 2.); - draw_rectangle( + .min(self.screen_height - font_size - margin * 2); + d.draw_rectangle( x, y, - text_width + margin * 2., - font_size + margin * 2., + text_width + margin * 2, + font_size + margin * 2, BG_LIGHT, ); - draw_text(text, x + margin, y + margin, font_size, colors::WHITE); + d.draw_text(text, x + margin, y + margin, font_size, Color::WHITE); } } } -pub fn toggle_button(mouse: &MouseInput, x: f32, y: f32, width: f32, height: f32, val: &mut bool) { - let margin = 5.; +pub fn toggle_button( + (d, mouse): (&mut RaylibDrawHandle, &MouseInput), + x: i32, + y: i32, + width: i32, + height: i32, + val: &mut bool, +) { + let margin = 5; let mouse_pos = mouse.pos(); - let bounds = Rect::new(x, y, width, height); + let bounds = rect(x, y, width, height); - let hover = bounds.contains(mouse_pos); - draw_rectangle(x, y, width, height, widget_bg(hover)); + let hover = bounds.check_collision_point_rec(mouse_pos); + d.draw_rectangle(x, y, width, height, widget_bg(hover)); let pressed = hover && mouse.left_click(); if pressed { *val = !*val; } if *val { - draw_rectangle( + d.draw_rectangle( x + margin, y + margin, - width - margin * 2., - height - margin * 2., - colors::WHITE, + width - margin * 2, + height - margin * 2, + Color::WHITE, ); } } -pub fn simple_button(mouse: &MouseInput, x: f32, y: f32, width: f32, height: f32) -> bool { +pub fn simple_button( + (d, mouse): (&mut RaylibDrawHandle, &MouseInput), + x: i32, + y: i32, + width: i32, + height: i32, +) -> bool { let mouse_pos = mouse.pos(); - let bounds = Rect::new(x, y, width, height); - let hover = bounds.contains(mouse_pos); + let bounds = rect(x, y, width, height); + let hover = bounds.check_collision_point_rec(mouse_pos); let pressed = hover && mouse.left_click(); - draw_rectangle(x, y, width, height, widget_bg(hover)); + d.draw_rectangle(x, y, width, height, widget_bg(hover)); pressed } -pub fn text_button(mouse: &MouseInput, x: f32, y: f32, width: f32, text: &str) -> bool { - let font_size = 20.; - let margin = font_size / 4.; - let height = font_size + margin * 2.; - let clicked = simple_button(mouse, x, y, width, height); - draw_text(text, x + margin, y + margin, font_size, colors::WHITE); +pub fn text_button( + d: &mut RaylibDrawHandle, + mouse: &MouseInput, + x: i32, + y: i32, + width: i32, + text: &str, +) -> bool { + let font_size = 20; + let margin = font_size / 4; + let height = font_size + margin * 2; + let clicked = simple_button((d, mouse), x, y, width, height); + d.draw_text(text, x + margin, y + margin, font_size, Color::WHITE); clicked } pub fn tex32_button( - mouse: &MouseInput, - (x, y): (f32, f32), + (d, mouse): (&mut RaylibDrawHandle, &MouseInput), + (x, y): (i32, i32), texture: &Texture2D, (tooltip, text): (&mut Tooltip, &'static str), ) -> bool { - let size = 32.; - let clicked = simple_button(mouse, x, y, size, size); - draw_scaled_texture(texture, x, y, 2.); + let size = 32; + let clicked = simple_button((d, mouse), x, y, 32, 32); + draw_scaled_texture(d, texture, x, y, 2.); tooltip.add(x, y, size, size, text); clicked } -pub fn simple_option_button(mouse: &MouseInput, bounds: Rect, option: T, current: &mut T) -> bool +pub fn simple_option_button( + (d, mouse): (&mut RaylibDrawHandle, &MouseInput), + bounds: Rectangle, + option: T, + current: &mut T, +) -> bool where T: PartialEq, { - draw_rectangle_rec(bounds, widget_bg(&option == current)); + d.draw_rectangle_rec(bounds, widget_bg(&option == current)); let mut changed = false; if mouse.left_click() && mouse.is_over(bounds) && current != &option { *current = option; @@ -221,33 +252,42 @@ where } pub fn text_input( + d: &mut RaylibDrawHandle, globals: &mut Globals, - bounds: Rect, + bounds: Rectangle, text: &mut String, is_selected: &mut bool, max_len: usize, editable: bool, ) -> bool { let mut changed = false; - let font_size = 20.; - draw_rectangle_rec(bounds, widget_bg(*is_selected)); - draw_rectangle( - bounds.x + 2., - bounds.y + bounds.h - 5., - bounds.w - 4., - 3., + let font_size = 20; + d.draw_rectangle_rec(bounds, widget_bg(*is_selected)); + d.draw_rectangle_rec( + Rectangle::new( + bounds.x + 2., + bounds.y + bounds.height - 5., + bounds.width - 4., + 3., + ), BG_DARK, ); - draw_text(text, bounds.x + 4., bounds.y + 4., font_size, colors::WHITE); + d.draw_text( + text, + bounds.x as i32 + 4, + bounds.y as i32 + 4, + font_size, + Color::WHITE, + ); // blinking cursor - if *is_selected && get_time().fract() < 0.5 { - let width = measure_text(text, None, font_size as _, 1.).width; - draw_rectangle( - bounds.x + 6. + width, - bounds.y + 4., - 2., + if *is_selected && d.get_time().fract() < 0.5 { + let width = d.measure_text(text, font_size); + d.draw_rectangle( + bounds.x as i32 + 6 + width, + bounds.y as i32 + 4, + 2, font_size, - colors::WHITE, + Color::WHITE, ); }; if editable && globals.mouse.left_click() && (globals.mouse.is_over(bounds) || *is_selected) { @@ -256,13 +296,13 @@ pub fn text_input( if *is_selected { globals.config.input.in_text_edit = true; - if is_key_pressed(KeyCode::Escape) || is_key_pressed(KeyCode::Enter) { + if d.is_key_pressed(KeyboardKey::KEY_ESCAPE) || d.is_key_pressed(KeyboardKey::KEY_ENTER) { *is_selected = false; } - if is_key_pressed(KeyCode::Backspace) && !text.is_empty() { + if d.is_key_pressed(KeyboardKey::KEY_BACKSPACE) && !text.is_empty() { changed = true; text.pop(); - if is_key_down(KeyCode::LeftControl) { + if d.is_key_down(KeyboardKey::KEY_LEFT_CONTROL) { while let Some(c) = text.pop() { if c == ' ' { break; @@ -271,7 +311,12 @@ pub fn text_input( } } if text.len() < max_len { - let c = get_char_pressed(); + let char_code = unsafe { ffi::GetCharPressed() }; + let c = if char_code > 0 { + char::from_u32(char_code as u32) + } else { + None + }; if let Some(c) = c { changed = true; text.push(c); @@ -282,8 +327,8 @@ pub fn text_input( } pub fn scrollable_texture_option_button( - mouse: &MouseInput, - pos: Vec2, + (d, mouse): (&mut RaylibDrawHandle, &MouseInput), + pos: Vector2, texture: &Texture2D, option: T, current: &mut T, @@ -293,8 +338,13 @@ pub fn scrollable_texture_option_button( where T: PartialEq, { - let bounds = Rect::new(pos.x, pos.y, 32. + border * 2., 32. + border * 2.); - draw_rectangle_rec( + let bounds = Rectangle { + x: pos.x, + y: pos.y, + width: 32. + border * 2., + height: 32. + border * 2., + }; + d.draw_rectangle_rec( bounds, if &option == current { BG_WIDGET_ACTIVE @@ -302,16 +352,12 @@ where gray(16) }, ); - let params = DrawTextureParams { - dest_size: Some(Vec2::splat(32.)), - ..Default::default() - }; - draw_texture_ex( + d.draw_texture_ex( texture, - pos.x + border, - pos.y + border, - colors::WHITE, - params, + pos + Vector2::new(border, border), + 0., + 32. / texture.width as f32, + Color::WHITE, ); if clicked_override { *current = option; @@ -325,32 +371,34 @@ where } pub fn draw_usize( + d: &mut RaylibDrawHandle, textures: &Textures, mut number: usize, - (x, y): (f32, f32), - digits: u8, - scale: f32, + (x, y): (i32, i32), + digits: i32, + scale: i32, ) { for i in 0..digits { - draw_rectangle( - x + 10. * i as f32 * scale, - y, - 8. * scale, - 16. * scale, - BG_LIGHT, - ); + d.draw_rectangle(x + 10 * i * scale, y, 8 * scale, 16 * scale, BG_LIGHT); } let mut i = 0; while (number != 0 || i == 0) && i < digits { let texture = textures.get(&format!("digit_{}", number % 10)); - let x = x + (digits - i - 1) as f32 * 10. * scale; - draw_scaled_texture(texture, x, y, scale); + let x = x + (digits - i - 1) * 10 * scale; + draw_scaled_texture(d, texture, x, y, scale as f32); number /= 10; i += 1; } } -pub fn draw_usize_small(textures: &Textures, mut num: usize, mut x: f32, y: f32, scale: f32) { +pub fn draw_usize_small( + d: &mut RaylibDrawHandle, + textures: &Textures, + mut num: usize, + mut x: i32, + y: i32, + scale: f32, +) { const MAX_DIGITS: usize = 8; let mut digits = [0; MAX_DIGITS]; let mut i = 0; @@ -361,29 +409,31 @@ pub fn draw_usize_small(textures: &Textures, mut num: usize, mut x: f32, y: f32, } let texture = textures.get("digits_small"); for &digit in &digits[(MAX_DIGITS - i)..] { - let source = Rect::new(4. * digit as f32, 0., 4., 6.); - let params = DrawTextureParams { - dest_size: Some(Vec2::new(4. * scale, 6. * scale)), - source: Some(source), - ..Default::default() - }; - draw_texture_ex(texture, x, y, FG_MARBLE_VALUE, params); - x += 4. * scale; + let source = Rectangle::new(4. * digit as f32, 0., 4., 6.); + let dest = Rectangle::new(x as f32, y as f32, 4. * scale, 6. * scale); + d.draw_texture_pro(texture, source, dest, Vector2::zero(), 0., FG_MARBLE_VALUE); + x += 4 * scale as i32; } } -pub fn slider(mouse: &MouseInput, bounds: Rect, value: &mut u8, min: u8, max: u8) -> bool { +pub fn slider( + (d, mouse): (&mut RaylibDrawHandle, &MouseInput), + bounds: Rectangle, + value: &mut u8, + min: u8, + max: u8, +) -> bool { // draw state // the +1 makes the lowest state look slightly filled and the max state fully filled let percent = (*value - min + 1) as f32 / (max - min + 1) as f32; - draw_rectangle_rec(bounds, BG_WIDGET); + d.draw_rectangle_rec(bounds, BG_WIDGET); let mut filled_bounds = bounds; - filled_bounds.w *= percent; - draw_rectangle_rec(filled_bounds, SLIDER_FILL); + filled_bounds.width *= percent; + d.draw_rectangle_rec(filled_bounds, Color::CYAN); // interaction if mouse.is_over(bounds) { if mouse.left_hold() { - let percent = (mouse.pos().x - bounds.x) / bounds.w; + let percent = (mouse.pos().x - bounds.x) / bounds.width; let new_value = min + (percent * (max - min + 1) as f32) as u8; if *value != new_value { *value = new_value; diff --git a/src/util.rs b/src/util.rs index 243593d..5649306 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, fs::read_dir, path::PathBuf}; -use macroquad::{color::colors, prelude::*}; +use raylib::prelude::*; #[derive(Default)] pub struct Textures { @@ -8,13 +8,14 @@ pub struct Textures { } impl Textures { - pub async fn load_dir(&mut self, folder: &str) { + pub fn load_dir(&mut self, folder: &str, rl: &mut RaylibHandle, thread: &RaylibThread) { for d in read_dir(folder).unwrap().flatten() { let path = d.path(); if path.is_file() { let name = path.file_stem().unwrap().to_string_lossy(); - - let texture = load_texture(&format!("{folder}/{name}.png")).await.unwrap(); + let texture = rl + .load_texture(thread, &format!("{folder}/{name}.png")) + .unwrap(); self.map.insert(name.to_string(), texture); } } @@ -31,24 +32,15 @@ pub fn userdata_dir() -> PathBuf { PathBuf::from("user") } -pub fn draw_rectangle_rec(bounds: Rect, color: Color) { - draw_rectangle(bounds.x, bounds.y, bounds.w, bounds.h, color); -} - -pub fn draw_scaled_texture_c(texture: &Texture2D, x: f32, y: f32, scale: f32, color: Color) { - let params = DrawTextureParams { - dest_size: Some(Vec2::new(texture.width() * scale, texture.height() * scale)), - ..Default::default() - }; - draw_texture_ex(texture, x, y, color, params); -} - -pub fn draw_scaled_texture(texture: &Texture2D, x: f32, y: f32, scale: f32) { - let params = DrawTextureParams { - dest_size: Some(Vec2::new(texture.width() * scale, texture.height() * scale)), - ..Default::default() - }; - draw_texture_ex(texture, x, y, colors::WHITE, params); +pub fn draw_scaled_texture( + d: &mut RaylibDrawHandle, + texture: &Texture2D, + x: i32, + y: i32, + scale: f32, +) { + let pos = Vector2::new(x as f32, y as f32); + d.draw_texture_ex(texture, pos, 0., scale, Color::WHITE); } pub fn get_free_id(items: &[T], id_fn: fn(&T) -> usize) -> usize { @@ -59,21 +51,31 @@ pub fn get_free_id(items: &[T], id_fn: fn(&T) -> usize) -> usize { id } -pub fn screen_centered_rect(width: f32, height: f32) -> Rect { - let w = screen_width(); - let h = screen_height(); - Rect::new(w / 2. - width / 2., h / 2. - height / 2., width, height) +pub fn screen_centered_rect(rl: &RaylibHandle, width: i32, height: i32) -> Rectangle { + let w = rl.get_screen_width(); + let h = rl.get_screen_height(); + Rectangle { + x: (w / 2 - width / 2) as f32, + y: (h / 2 - height / 2) as f32, + width: width as f32, + height: height as f32, + } } -pub fn screen_centered_rect_dyn(margin_x: f32, margin_y: f32) -> Rect { - let w = screen_width(); - let h = screen_height(); - Rect::new(margin_x, margin_y, w - margin_x * 2., h - margin_y * 2.) +pub fn screen_centered_rect_dyn(rl: &RaylibHandle, margin_x: i32, margin_y: i32) -> Rectangle { + let w = rl.get_screen_width(); + let h = rl.get_screen_height(); + Rectangle { + x: margin_x as f32, + y: margin_y as f32, + width: (w - margin_x * 2) as f32, + height: (h - margin_y * 2) as f32, + } } #[derive(Debug, Default)] pub struct MouseInput { - pos: Vec2, + pos: Vector2, left_click: bool, left_hold: bool, left_release: bool, @@ -82,24 +84,24 @@ pub struct MouseInput { } impl MouseInput { - pub fn update(&mut self) { - self.pos = mouse_position().into(); - self.left_click = is_mouse_button_pressed(MouseButton::Left); - self.left_hold = is_mouse_button_down(MouseButton::Left); - self.left_release = is_mouse_button_released(MouseButton::Left); - self.right_hold = is_mouse_button_down(MouseButton::Right); - self.scroll = get_scroll(); + pub fn update(&mut self, rl: &RaylibHandle) { + self.pos = rl.get_mouse_position(); + self.left_click = rl.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT); + self.left_hold = rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT); + self.left_release = rl.is_mouse_button_released(MouseButton::MOUSE_BUTTON_LEFT); + self.right_hold = rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_RIGHT); + self.scroll = get_scroll(rl); } - pub fn is_over(&self, rect: Rect) -> bool { - rect.contains(self.pos) + pub fn is_over(&self, rect: Rectangle) -> bool { + rect.check_collision_point_rec(self.pos) } pub fn clear(&mut self) { *self = Self::default(); } - pub fn pos(&self) -> Vec2 { + pub fn pos(&self) -> Vector2 { self.pos } @@ -130,9 +132,9 @@ pub enum Scroll { Down, } -pub fn get_scroll() -> Option { +pub fn get_scroll(rl: &RaylibHandle) -> Option { const SCROLL_THRESHOLD: f32 = 0.5; - let value = mouse_wheel().0; + let value = rl.get_mouse_wheel_move(); if value > SCROLL_THRESHOLD { Some(Scroll::Up) } else if value < -SCROLL_THRESHOLD { @@ -141,3 +143,7 @@ pub fn get_scroll() -> Option { None } } + +pub fn rect(x: i32, y: i32, width: i32, height: i32) -> Rectangle { + Rectangle::new(x as f32, y as f32, width as f32, height as f32) +}