it's like minifb but at home
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

124 lignes
3.5 KiB

  1. #![allow(dead_code)]
  2. // modules
  3. pub mod color;
  4. pub mod prelude;
  5. // namespacing
  6. use color::Color;
  7. pub use minifb::{Key, MouseButton};
  8. use minifb::{Window, WindowOptions};
  9. // error type
  10. #[derive(Debug, thiserror::Error)]
  11. pub enum Error {
  12. #[error(transparent)]
  13. MiniFb(#[from] minifb::Error),
  14. }
  15. // result type
  16. pub type Result<T> = std::result::Result<T, Error>;
  17. // pixel buffer for internal use
  18. struct PixelBuffer {
  19. data: Vec<u32>,
  20. width: usize,
  21. height: usize,
  22. }
  23. impl PixelBuffer {
  24. // create a new pixel buffer
  25. fn new(width: usize, height: usize) -> PixelBuffer {
  26. PixelBuffer { width, height, data: vec![0; height * width] }
  27. }
  28. // index pixel buffer !! will panic if given x/y are out of bounds
  29. fn at(&self, x: usize, y: usize) -> &u32 {
  30. assert!(x < self.width);
  31. assert!(y < self.height);
  32. &self.data[y * self.width + x]
  33. }
  34. // index pixel buffer mut !! will panic if given x/y are out of bounds
  35. fn at_mut(&mut self, x: usize, y: usize) -> &mut u32 {
  36. assert!(x < self.width);
  37. assert!(y < self.height);
  38. &mut self.data[y * self.width + x]
  39. }
  40. // returns the buffer as a slice
  41. fn as_ref(&self) -> &[u32] {
  42. &self.data
  43. }
  44. // returns a mutable reference to a slice
  45. fn as_mut_ref(&mut self) -> &mut [u32] {
  46. &mut self.data
  47. }
  48. }
  49. /// context data
  50. pub struct Context {
  51. pixel_buffer: PixelBuffer,
  52. height: usize,
  53. width: usize,
  54. window: Window,
  55. }
  56. impl Context {
  57. /// create a new context
  58. pub fn new(width: usize, height: usize, title: String) -> Result<Context> {
  59. let pixel_buffer = PixelBuffer::new(height, width);
  60. let mut window = Window::new(&title, width, height, WindowOptions::default())?;
  61. window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
  62. Ok(Context { pixel_buffer, window, height, width })
  63. }
  64. /// render the internal buffer to the screen
  65. pub fn present(&mut self) -> Result<()> {
  66. self.window.update_with_buffer(&self.pixel_buffer.as_ref(), self.width, self.height)?;
  67. Ok(())
  68. }
  69. /// clears the pixel buffer
  70. pub fn clear(&mut self, color: Option<color::Color>) {
  71. let color = color.unwrap_or(color::BLACK);
  72. self.pixel_buffer.as_mut_ref().iter_mut().for_each(|pixel| *pixel = color.as_u32());
  73. }
  74. /// checks if window is open
  75. pub fn is_open(&self) -> bool {
  76. self.window.is_open()
  77. }
  78. /// set a pixel
  79. pub fn insert_pixel(&mut self, x: usize, y: usize, color: Color) {
  80. if x < self.pixel_buffer.width && y < self.pixel_buffer.height {
  81. *self.pixel_buffer.at_mut(x, y) = color.as_u32();
  82. }
  83. }
  84. /// insert a slice into the pixel buffer x/y are offsets w/h are the dimensions of the slice
  85. /// !! this method can panic if the given buffer dimensions don't match the buffer length
  86. pub fn insert_slice(&mut self, x: usize, y: usize, w: usize, h: usize, slice: &[Color]) {
  87. assert!(w * h == slice.len());
  88. for i in x..(x + w) {
  89. for j in y..(y + h) {
  90. let color = slice[w * (i - x) + (j - y)];
  91. self.insert_pixel(i, j, color);
  92. }
  93. }
  94. }
  95. /// get mouse position
  96. pub fn get_mouse_pos(&self) -> Option<(f32, f32)> {
  97. self.window.get_mouse_pos(minifb::MouseMode::Discard)
  98. }
  99. /// get mouse down
  100. pub fn get_mouse_down(&self, button: MouseButton) -> bool {
  101. self.window.get_mouse_down(button)
  102. }
  103. }