From 013391c5dc4e75e1ed62fc6c12be1a3d10c9dd0a Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Fri, 5 Dec 2025 15:46:38 +0100 Subject: [PATCH 01/13] reload --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f95b85b..b1db6f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -288,7 +288,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chinchilib" -version = "0.2.1" +version = "0.3.0" dependencies = [ "array2d", "env_logger", From 1bc9f81b87e929758562a62056269f4e8649b63e Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Fri, 5 Dec 2025 15:47:33 +0100 Subject: [PATCH 02/13] update on tick function --- examples/moving_pixel.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/moving_pixel.rs b/examples/moving_pixel.rs index 5367c4a..9ff97b6 100644 --- a/examples/moving_pixel.rs +++ b/examples/moving_pixel.rs @@ -39,7 +39,11 @@ const RED: rgb::RGBA8 = rgb::RGBA8 { }; impl GfxApp for MovingPixel { - fn on_tick(&mut self, pressed_keys: &std::collections::HashSet) -> bool { + fn on_tick( + &mut self, + pressed_keys: &std::collections::HashSet, + window_size: (usize, usize), + ) -> bool { let mut needs_redraw = true; for key in pressed_keys { match key { From a58c504282a3f705328a7000bf008902ec462924 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Fri, 5 Dec 2025 15:49:12 +0100 Subject: [PATCH 03/13] public width and height for app and on_tick function give window_size --- src/lib.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e8f5d81..3a26ce6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,8 +55,8 @@ impl std::convert::TryFrom<&winit::keyboard::Key> for Key { /// are constructed on "resume" and cannot be construted earlier pub struct WinitHandler { winfbx: Option, - width: usize, - height: usize, + pub width: usize, + pub height: usize, last_frame: std::time::Instant, tick: std::time::Duration, /// Set to true if your app has something special to do at every tick even if there are no user @@ -278,7 +278,9 @@ impl WinFbx { fn on_tick(&mut self) { if self.app.done() == DoneStatus::NotDone { - self.needs_render = self.app.on_tick(&self.pressed_keys); + self.needs_render = self + .app + .on_tick(&self.pressed_keys, (self.width, self.height)); } self.pressed_keys .retain(|candidate| !self.released_keys.contains(candidate)); @@ -333,7 +335,11 @@ pub enum DoneStatus { pub trait GfxApp { /// Every tick, this method gets called with currently pressed keys. Released keys during the tick are considered still pressed. But will be removed after this call. - fn on_tick(&mut self, pressed_keys: &std::collections::HashSet) -> bool; + fn on_tick( + &mut self, + pressed_keys: &std::collections::HashSet, + window_size: (usize, usize), + ) -> bool; /// You get the pixel array, so you can draw on it before the render. fn draw(&mut self, pixels: &mut Pixels, width: usize); From d199bb127f1dc7d4513daa11b011a90298677bb3 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Sat, 6 Dec 2025 13:46:48 +0100 Subject: [PATCH 04/13] change version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1db6f0..17002c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -288,7 +288,7 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chinchilib" -version = "0.3.0" +version = "0.3.1" dependencies = [ "array2d", "env_logger", diff --git a/Cargo.toml b/Cargo.toml index 5fdce71..caf56e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chinchilib" -version = "0.3.0" +version = "0.3.1" edition = "2021" license-file = "LICENSE.txt" description = "A graphical prototyping library for my students" From 477b778343b103b59ee4d59e0e2834067591a98b Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Sat, 6 Dec 2025 13:47:00 +0100 Subject: [PATCH 05/13] init --- examples/moving_pixel_limited_by_window.rs | 103 +++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 examples/moving_pixel_limited_by_window.rs diff --git a/examples/moving_pixel_limited_by_window.rs b/examples/moving_pixel_limited_by_window.rs new file mode 100644 index 0000000..fae459e --- /dev/null +++ b/examples/moving_pixel_limited_by_window.rs @@ -0,0 +1,103 @@ +use chinchilib::pixels::Pixels; +use chinchilib::rgb; +use chinchilib::{put_pixel, GfxApp, Key, WinitHandler}; + +fn main() { + env_logger::init(); + + log::info!("Hello, world!"); + + let moving_pixel = Box::new(MovingPixel::new(50, 100)); + let mut app = WinitHandler::new(moving_pixel, (500, 500), 60); + // We don't have any physics or animations, false helps to preserve performance. + app.set_always_tick(false); + app.run().unwrap(); +} + +/// Example app that only feature a pixel that moves. +struct MovingPixel { + pos: (usize, usize), +} + +impl Default for MovingPixel { + fn default() -> Self { + Self { pos: (0, 0) } + } +} + +impl MovingPixel { + fn new(x: usize, y: usize) -> Self { + Self { pos: (x, y) } + } +} + +const RED: rgb::RGBA8 = rgb::RGBA8 { + r: u8::MAX, + g: 0, + b: 0, + a: u8::MAX, +}; + +impl GfxApp for MovingPixel { + fn on_tick( + &mut self, + pressed_keys: &std::collections::HashSet, + window_size: (usize, usize), + ) -> bool { + let mut needs_redraw = true; + for key in pressed_keys { + match key { + Key::Left => { + if self.pos.0 == 0 { + self.pos.0 = window_size.0 - 1; + } else { + self.pos.0 -= 1; + } + } + Key::Right => { + self.pos.0 += 1; + if self.pos.0 >= window_size.0 { + self.pos.0 = 0 + } + } + Key::Up => { + if self.pos.1 == 0 { + self.pos.1 = window_size.1 - 1; + } else { + self.pos.1 -= 1; + } + } + Key::Down => { + self.pos.1 += 1; + if self.pos.1 >= window_size.1 { + self.pos.1 = 0; + } + } + _ => { + needs_redraw = false; + } + } + } + needs_redraw + } + + fn draw(&mut self, pixels: &mut Pixels, width: usize) { + if self.pos.0 * self.pos.1 < pixels.frame().len() { + put_pixel(pixels.frame_mut(), width, self.pos.0, self.pos.1, RED); + } + } + + /// For the sake of the example, when x goes under 50, we inidcate that we are done and that + /// the windows should remain open, when y goes under 50 we indicate that the window should + /// close, otherwise we are not done. + fn done(&self) -> chinchilib::DoneStatus { + // if self.pos.0 < 50 { + // chinchilib::DoneStatus::Remain + // } else if self.pos.1 < 50 { + // chinchilib::DoneStatus::Exit + // } else { + // chinchilib::DoneStatus::NotDone + // } + chinchilib::DoneStatus::NotDone + } +} From db1cd8c6e7e06e4823380d3b92542eded9c9de61 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Tue, 9 Dec 2025 13:18:05 +0100 Subject: [PATCH 06/13] add temp folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ea8c4bf..2a7f9d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/temp \ No newline at end of file From c1becc520bbf8c69c5fab4139516b9956c5acb95 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Tue, 9 Dec 2025 13:18:23 +0100 Subject: [PATCH 07/13] add get_pixel and put_pixel documentation --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index a4684d1..44892fb 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,24 @@ It's mostly a wrapper arround pixels and winit that takes care of refresh rate, # Usage +`chinchilib` two functions are public in the library, one getter and one to compute on the window: + +- `get_pixel` + _Return the color `RGBA8` of a pixel at coordinates (x, y)_. + Parameters: + - `frame: &[u8]` - image buffer encoded in `RGBA8` + - `width: usize` - image width in pixels + - `x, y: usize` - pixel coordinates + **The caller must ensure the coordinates are within bounds** +- `put_pixel` + _Set the color of a pixel at coordinates (x, y)_. + Parameters: + - `frame: &mut [u8]` - mutable image buffer encoded in `RGBA8` + - `width: usize` - image width in pixels + - `x, y: usize` - pixel coordinates + - `color: rgb::RGBA8` - new pixel color + **The caller must ensure the coordinates are within bounds** + `WinitHandler` creates a window for you and manages events and timing. You can package your code into a `chinchilib::GfxApp` implementing struct such as `MovingPixel` in the example bellow. `WinitHandler` will make calls to: From 99c824ce02e880885739e903aadbda6873688813 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Tue, 9 Dec 2025 13:18:48 +0100 Subject: [PATCH 08/13] add get_pixel function --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 3a26ce6..a1349f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,6 +205,12 @@ impl winit::application::ApplicationHandler for WinitHandler { } } +pub fn get_pixel(frame: &[u8], width: usize, x: usize, y: usize) -> rgb::RGBA8 { + use rgb::*; + let idx = y * width + x; + frame.as_rgba()[idx] +} + pub fn put_pixel(frame: &mut [u8], width: usize, x: usize, y: usize, color: rgb::RGBA8) { use rgb::*; let idx = width * y + x; From 0909225eda48df25508bd406c9b92669b7e40122 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Tue, 9 Dec 2025 13:18:54 +0100 Subject: [PATCH 09/13] deleted --- examples/moving_pixel_limited_by_window.rs | 103 --------------------- 1 file changed, 103 deletions(-) delete mode 100644 examples/moving_pixel_limited_by_window.rs diff --git a/examples/moving_pixel_limited_by_window.rs b/examples/moving_pixel_limited_by_window.rs deleted file mode 100644 index fae459e..0000000 --- a/examples/moving_pixel_limited_by_window.rs +++ /dev/null @@ -1,103 +0,0 @@ -use chinchilib::pixels::Pixels; -use chinchilib::rgb; -use chinchilib::{put_pixel, GfxApp, Key, WinitHandler}; - -fn main() { - env_logger::init(); - - log::info!("Hello, world!"); - - let moving_pixel = Box::new(MovingPixel::new(50, 100)); - let mut app = WinitHandler::new(moving_pixel, (500, 500), 60); - // We don't have any physics or animations, false helps to preserve performance. - app.set_always_tick(false); - app.run().unwrap(); -} - -/// Example app that only feature a pixel that moves. -struct MovingPixel { - pos: (usize, usize), -} - -impl Default for MovingPixel { - fn default() -> Self { - Self { pos: (0, 0) } - } -} - -impl MovingPixel { - fn new(x: usize, y: usize) -> Self { - Self { pos: (x, y) } - } -} - -const RED: rgb::RGBA8 = rgb::RGBA8 { - r: u8::MAX, - g: 0, - b: 0, - a: u8::MAX, -}; - -impl GfxApp for MovingPixel { - fn on_tick( - &mut self, - pressed_keys: &std::collections::HashSet, - window_size: (usize, usize), - ) -> bool { - let mut needs_redraw = true; - for key in pressed_keys { - match key { - Key::Left => { - if self.pos.0 == 0 { - self.pos.0 = window_size.0 - 1; - } else { - self.pos.0 -= 1; - } - } - Key::Right => { - self.pos.0 += 1; - if self.pos.0 >= window_size.0 { - self.pos.0 = 0 - } - } - Key::Up => { - if self.pos.1 == 0 { - self.pos.1 = window_size.1 - 1; - } else { - self.pos.1 -= 1; - } - } - Key::Down => { - self.pos.1 += 1; - if self.pos.1 >= window_size.1 { - self.pos.1 = 0; - } - } - _ => { - needs_redraw = false; - } - } - } - needs_redraw - } - - fn draw(&mut self, pixels: &mut Pixels, width: usize) { - if self.pos.0 * self.pos.1 < pixels.frame().len() { - put_pixel(pixels.frame_mut(), width, self.pos.0, self.pos.1, RED); - } - } - - /// For the sake of the example, when x goes under 50, we inidcate that we are done and that - /// the windows should remain open, when y goes under 50 we indicate that the window should - /// close, otherwise we are not done. - fn done(&self) -> chinchilib::DoneStatus { - // if self.pos.0 < 50 { - // chinchilib::DoneStatus::Remain - // } else if self.pos.1 < 50 { - // chinchilib::DoneStatus::Exit - // } else { - // chinchilib::DoneStatus::NotDone - // } - chinchilib::DoneStatus::NotDone - } -} From 6d0776ec6227c5d808795a7d71d78ddb77385956 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Tue, 9 Dec 2025 13:23:30 +0100 Subject: [PATCH 10/13] fix documentation bad display --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 44892fb..247dbbd 100644 --- a/README.md +++ b/README.md @@ -8,21 +8,21 @@ It's mostly a wrapper arround pixels and winit that takes care of refresh rate, `chinchilib` two functions are public in the library, one getter and one to compute on the window: -- `get_pixel` - _Return the color `RGBA8` of a pixel at coordinates (x, y)_. +- `get_pixel`\ + _Return the color `RGBA8` of a pixel at coordinates (x, y)_.\ + **The caller must ensure the coordinates are within bounds**\ Parameters: - `frame: &[u8]` - image buffer encoded in `RGBA8` - `width: usize` - image width in pixels - `x, y: usize` - pixel coordinates - **The caller must ensure the coordinates are within bounds** -- `put_pixel` - _Set the color of a pixel at coordinates (x, y)_. +- `put_pixel`\ + _Set the color of a pixel at coordinates (x, y)_.\ + **The caller must ensure the coordinates are within bounds**\ Parameters: - `frame: &mut [u8]` - mutable image buffer encoded in `RGBA8` - `width: usize` - image width in pixels - `x, y: usize` - pixel coordinates - `color: rgb::RGBA8` - new pixel color - **The caller must ensure the coordinates are within bounds** `WinitHandler` creates a window for you and manages events and timing. You can package your code into a `chinchilib::GfxApp` implementing struct such as `MovingPixel` in the example bellow. From a63f8879938331160cee452810ae704ce7ec0f4b Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Tue, 9 Dec 2025 13:25:18 +0100 Subject: [PATCH 11/13] simplify chinchilib section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 247dbbd..f302072 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ It's mostly a wrapper arround pixels and winit that takes care of refresh rate, # Usage -`chinchilib` two functions are public in the library, one getter and one to compute on the window: +`chinchilib` exposes two public functions for pixel access: - `get_pixel`\ _Return the color `RGBA8` of a pixel at coordinates (x, y)_.\ From 57675fe391c6d4d2454e93a130831521c61b2c09 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Tue, 9 Dec 2025 13:32:46 +0100 Subject: [PATCH 12/13] remove public width and height in WinitHandler --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a1349f6..83ac1d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,8 +55,8 @@ impl std::convert::TryFrom<&winit::keyboard::Key> for Key { /// are constructed on "resume" and cannot be construted earlier pub struct WinitHandler { winfbx: Option, - pub width: usize, - pub height: usize, + width: usize, + height: usize, last_frame: std::time::Instant, tick: std::time::Duration, /// Set to true if your app has something special to do at every tick even if there are no user From cc7c7ac7e8c3133d13d9cd4c0ab9bc685e4651d2 Mon Sep 17 00:00:00 2001 From: Owen Neuillyr Date: Fri, 12 Dec 2025 15:30:57 +0100 Subject: [PATCH 13/13] bump to good version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index caf56e4..9377e61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chinchilib" -version = "0.3.1" +version = "0.4.0" edition = "2021" license-file = "LICENSE.txt" description = "A graphical prototyping library for my students"