diff --git a/Cargo.toml b/Cargo.toml index f6d25fc..e9e66a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,8 +31,8 @@ crossbeam = "0.8.0" toml = "0.5.8" cgmath = "0.18.0" -rapier3d = { version = "0.5.0", features = ["simd-nightly", "parallel"] } -nalgebra = "0.24.1" +rapier3d = { version = "0.11.1", features = ["simd-nightly", "parallel"] } +nalgebra = "0.29.0" legion = "0.3.1" wgpu = "0.7.0" imgui = "0.7.0" diff --git a/exportToHTML/camera.rs.html b/exportToHTML/camera.rs.html new file mode 100644 index 0000000..29827fe --- /dev/null +++ b/exportToHTML/camera.rs.html @@ -0,0 +1,213 @@ + + +camera.rs + + + + + +
+ +camera.rs +
+
1    use std::f32::consts::{FRAC_PI_2, PI};
+2    use std::time::{Duration, Instant};
+3    
+4    use cgmath::{Decomposed, InnerSpace, Matrix4, Point3, Rad, Vector3};
+5    use winit_24::dpi::{LogicalPosition, PhysicalPosition};
+6    use winit_24::event::{ElementState, MouseScrollDelta, VirtualKeyCode};
+7    use crate::render::OPENGL_TO_WGPU_MATRIX;
+8    use imgui::Condition;
+9    use imgui::*;
+10   
+11   #[derive(Clone, Copy, Debug, PartialEq)]
+12   pub struct Camera {
+13       pub position: Point3<f32>,
+14       pub yaw: Rad<f32>,
+15       pub pitch: Rad<f32>,
+16   }
+17   
+18   impl Camera {
+19       pub fn new<V: Into<Point3<f32>>, Y: Into<Rad<f32>>, P: Into<Rad<f32>>>(
+20           position: V,
+21           yaw: Y,
+22           pitch: P,
+23       ) -> Self {
+24           Self {
+25               position: position.into(),
+26               yaw: yaw.into(),
+27               pitch: pitch.into(),
+28           }
+29       }
+30   
+31       pub fn calc_matrix(&self, projection: cgmath::Matrix4<f32>) -> Matrix4<f32> {
+32   
+33           let view_vector = Point3::new(
+34               (1.0 * self.pitch.0.sin() * self.yaw.0.sin()),
+35               (1.0 * self.pitch.0.cos()),
+36               (1.0 * self.pitch.0.sin() * self.yaw.0.cos()),
+37           );
+38   
+39           let mx_view = Matrix4::look_at(
+40               self.position,
+41               Point3::new(
+42                   view_vector.x + self.position.x,
+43                   view_vector.y + self.position.y,
+44                   view_vector.z + self.position.z,
+45               ),
+46               Vector3::unit_y(),
+47           );
+48           // I don't know how this works, but it limits pitching to like
+49           // 70 degrees. Lame
+50           // let mx_view = Matrix4::look_at_dir(
+51           //     self.position,
+52           //     Vector3::new(
+53           //         self.yaw.0.cos(),
+54           //         self.pitch.0.sin(),
+55           //         self.yaw.0.sin(),
+56           //     ).normalize(),
+57           //     Vector3::unit_y(),
+58           // );
+59           let mx_correction = OPENGL_TO_WGPU_MATRIX;
+60           mx_correction * projection * mx_view
+61       }
+62   }
+63   
+64   #[derive(Debug)]
+65   pub struct CameraController {
+66       amount_left: f32,
+67       amount_right: f32,
+68       amount_forward: f32,
+69       amount_backward: f32,
+70       amount_up: f32,
+71       amount_down: f32,
+72       rotate_horizontal: f32,
+73       rotate_vertical: f32,
+74       scroll: f32,
+75       speed: f32,
+76       sensitivity: f32,
+77       active: bool,
+78   }
+79   
+80   impl CameraController {
+81       pub fn new(speed: f32, sensitivity: f32) -> Self {
+82           Self {
+83               amount_left: 0.0,
+84               amount_right: 0.0,
+85               amount_forward: 0.0,
+86               amount_backward: 0.0,
+87               amount_up: 0.0,
+88               amount_down: 0.0,
+89               rotate_horizontal: 0.0,
+90               rotate_vertical: 0.0,
+91               scroll: 0.0,
+92               speed,
+93               sensitivity,
+94               active: true
+95           }
+96       }
+97   
+98       pub fn process_keyboard(&mut self, key: VirtualKeyCode, state: ElementState) -> bool {
+99           let amount = if state == ElementState::Pressed {
+100              1.0
+101          } else {
+102              0.0
+103          };
+104          let active = match key {
+105              VirtualKeyCode::P => {
+106                  if state == ElementState::Pressed {
+107                      self.active = !self.active;
+108                  }
+109                  self.active
+110              },
+111              _ => {self.active}
+112          };
+113          if active {
+114              match key {
+115                  VirtualKeyCode::W | VirtualKeyCode::Up => {
+116                      self.amount_forward = amount;
+117                      true
+118                  }
+119                  VirtualKeyCode::S | VirtualKeyCode::Down => {
+120                      self.amount_backward = amount;
+121                      true
+122                  }
+123                  VirtualKeyCode::A | VirtualKeyCode::Left => {
+124                      self.amount_left = amount;
+125                      true
+126                  }
+127                  VirtualKeyCode::D | VirtualKeyCode::Right => {
+128                      self.amount_right = amount;
+129                      true
+130                  }
+131                  VirtualKeyCode::Space => {
+132                      self.amount_up = amount;
+133                      true
+134                  }
+135                  VirtualKeyCode::LShift => {
+136                      self.amount_down = amount;
+137                      true
+138                  }
+139                  _ => false,
+140              }
+141          } else {
+142              false
+143          }
+144      }
+145  
+146      pub fn process_mouse(&mut self, mouse_dx: f64, mouse_dy: f64) {
+147          if self.active {
+148              self.rotate_horizontal = -mouse_dx as f32;
+149              self.rotate_vertical = mouse_dy as f32;
+150          }
+151      }
+152  
+153      pub fn update_camera(&mut self, camera: &mut Camera, dt: f32) {
+154  
+155          // Move forward/backward and left/right
+156          let view_vector = Vector3::new(
+157              (1.0 * camera.pitch.0.sin() * camera.yaw.0.sin()),
+158              (1.0 * camera.pitch.0.cos()),
+159              (1.0 * camera.pitch.0.sin() * camera.yaw.0.cos()),
+160          );
+161  
+162          // Offset the yaw 90 degrees and set the pitch to level for our
+163          // right / left hand translation vectors
+164          let offset = camera.yaw.0 + PI/2.0;
+165          let pitch = PI/2.0;
+166          let left_vector = Vector3::new(
+167              (1.0 * pitch.sin() * offset.sin()),
+168              (1.0 * pitch.cos()),
+169              (1.0 * pitch.sin() * offset.cos()),
+170          );
+171  
+172          camera.position += view_vector * (self.amount_forward - self.amount_backward) * self.speed * dt;
+173          camera.position += left_vector * (self.amount_left - self.amount_right) * self.speed * dt;
+174          camera.position.y += (self.amount_up - self.amount_down) * self.speed * dt;
+175  
+176          // Rotate
+177          camera.yaw += Rad(self.rotate_horizontal) * self.sensitivity * dt;
+178          camera.pitch += Rad(self.rotate_vertical) * self.sensitivity * dt;
+179  
+180          self.rotate_horizontal = 0.0;
+181          self.rotate_vertical = 0.0;
+182  
+183          // Keep the camera's angle from going too high/low.
+184          if camera.pitch < -Rad(0.001) {
+185              camera.pitch = -Rad(0.001);
+186          } else if camera.pitch > Rad(PI - 0.001) {
+187              camera.pitch = Rad(PI - 0.001);
+188          }
+189      }
+190  }
+191  
+ + \ No newline at end of file diff --git a/exportToHTML/components.rs.html b/exportToHTML/components.rs.html new file mode 100644 index 0000000..040cf40 --- /dev/null +++ b/exportToHTML/components.rs.html @@ -0,0 +1,142 @@ + + +components.rs + + + + + +
+ +components.rs +
+
1    use std::sync::Arc;
+2    use std::time::{Duration, Instant};
+3    
+4    use cgmath::{Deg, Euler};
+5    use rapier3d::dynamics::{RigidBody, RigidBodyHandle};
+6    use rapier3d::geometry::Collider as r3dCollider;
+7    use rapier3d::geometry::ColliderHandle;
+8    use wgpu::{BindGroup, Buffer, TextureView};
+9    
+10   use crate::runtime::state::{TomlPositionDescription, TomlRotationDescription};
+11   use imgui::Ui;
+12   
+13   // a component is any type that is 'static, sized, send and sync
+14   
+15   pub struct ImguiWindow<'a, T> {
+16       pub window: fn() -> imgui::Window<'a>,
+17       pub func: fn(&Ui, Vec<&T>),
+18   }
+19   
+20   #[derive(Clone, Copy, Debug, PartialEq)]
+21   pub struct LoopState {
+22       pub delta_time: Duration,
+23       pub start_time: Instant,
+24       pub step_size: f32,
+25   }
+26   
+27   #[derive(Clone, Copy, Debug, PartialEq)]
+28   pub struct Position {
+29       pub x: f32,
+30       pub y: f32,
+31       pub z: f32,
+32       pub rot: cgmath::Euler<Deg<f32>>,
+33   }
+34   
+35   impl Default for Position {
+36       fn default() -> Self {
+37           Position {
+38               x: 0.0,
+39               y: 0.0,
+40               z: 0.0,
+41               rot: Euler {
+42                   x: Deg(0.0),
+43                   y: Deg(0.0),
+44                   z: Deg(0.0),
+45               },
+46           }
+47       }
+48   }
+49   
+50   impl From<TomlPositionDescription> for Position {
+51       fn from(pos: TomlPositionDescription) -> Self {
+52           let euler = match pos.rot {
+53               None => Euler {
+54                   x: Deg(0.0),
+55                   y: Deg(0.0),
+56                   z: Deg(0.0),
+57               },
+58               Some(v) => Euler {
+59                   x: Deg(v.x),
+60                   y: Deg(v.y),
+61                   z: Deg(v.z),
+62               },
+63           };
+64           Position {
+65               x: pos.x,
+66               y: pos.y,
+67               z: pos.z,
+68               rot: euler,
+69           }
+70       }
+71   }
+72   
+73   impl From<Option<TomlPositionDescription>> for Position {
+74       fn from(pos: Option<TomlPositionDescription>) -> Self {
+75           match pos {
+76               None => Position {
+77                   x: 0.0,
+78                   y: 0.0,
+79                   z: 0.0,
+80                   rot: Euler {
+81                       x: Deg(0.0),
+82                       y: Deg(0.0),
+83                       z: Deg(0.0),
+84                   },
+85               },
+86               Some(v) => Position::from(v),
+87           }
+88       }
+89   }
+90   
+91   #[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)]
+92   pub struct RangeCopy<Idx> {
+93       pub start: Idx,
+94       pub end: Idx,
+95   }
+96   
+97   #[derive(Clone, Debug)]
+98   pub struct Mesh {
+99       pub index_buffer: Arc<Buffer>,
+100      pub index_count: usize,
+101      pub index_format: wgpu::IndexFormat,
+102      pub vertex_buffer: Arc<Buffer>,
+103      pub uniform_buffer: Arc<Buffer>,
+104      pub bind_group: Arc<BindGroup>,
+105      pub color: wgpu::Color,
+106  }
+107  
+108  #[derive(Clone, Debug)]
+109  pub struct Physics {
+110      pub rigid_body: RigidBody,
+111      pub rigid_body_handle: Option<RigidBodyHandle>,
+112  }
+113  
+114  #[derive(Clone)]
+115  pub struct Collider {
+116      pub collider: r3dCollider,
+117      pub collider_handle: Option<ColliderHandle>,
+118  }
+119  
+ + \ No newline at end of file diff --git a/exportToHTML/extended_winit_imgui_support.rs.html b/exportToHTML/extended_winit_imgui_support.rs.html new file mode 100644 index 0000000..d5618d2 --- /dev/null +++ b/exportToHTML/extended_winit_imgui_support.rs.html @@ -0,0 +1,1192 @@ + + +extended_winit_imgui_support.rs + + + + + +
+ +extended_winit_imgui_support.rs +
+
1    //! This crate provides a winit-based backend platform for imgui_supp-rs.
+2    //!
+3    //! A backend platform handles window/input device events and manages their
+4    //! state.
+5    //!
+6    //! # Using the library
+7    //!
+8    //! There are five things you need to do to use this library correctly:
+9    //!
+10   //! 1. Initialize a `WinitPlatform` instance
+11   //! 2. Attach it to a winit `Window`
+12   //! 3. Pass events to the platform (every frame)
+13   //! 4. Call frame preparation callback (every frame)
+14   //! 5. Call render preparation callback (every frame)
+15   //!
+16   //! ## Complete example for winit 0.20+ (without a renderer)
+17   //!
+18   //! ```rust,no_run,ignore
+19   //! # // TODO: Remove ignore when only one winit version is used
+20   //! use imgui_supp::Context;
+21   //! use imgui_winit_support::{HiDpiMode, WinitPlatform};
+22   //! use std::time::Instant;
+23   //! use winit::event::{Event, WindowEvent};
+24   //! use winit::event_loop::{ControlFlow, EventLoop};
+25   //! use winit::window::{Window};
+26   //!
+27   //! let mut event_loop = EventLoop::new();
+28   //! let mut window = Window::new(&event_loop).unwrap();
+29   //!
+30   //! let mut imgui_supp = Context::create();
+31   //! // configure imgui_supp-rs Context if necessary
+32   //!
+33   //! let mut platform = WinitPlatform::init(&mut imgui_supp); // step 1
+34   //! platform.attach_window(imgui_supp.io_mut(), &window, HiDpiMode::Default); // step 2
+35   //!
+36   //! let mut last_frame = Instant::now();
+37   //! let mut run = true;
+38   //! event_loop.run(move |event, _, control_flow| {
+39   //!     match event {
+40   //!         Event::NewEvents(_) => {
+41   //!             // other application-specific logic
+42   //!             last_frame = imgui_supp.io_mut().update_delta_time(last_frame);
+43   //!         },
+44   //!         Event::MainEventsCleared => {
+45   //!             // other application-specific logic
+46   //!             platform.prepare_frame(imgui_supp.io_mut(), &window) // step 4
+47   //!                 .expect("Failed to prepare frame");
+48   //!             window.request_redraw();
+49   //!         }
+50   //!         Event::RedrawRequested(_) => {
+51   //!             let ui = imgui_supp.frame();
+52   //!             // application-specific rendering *under the UI*
+53   //!
+54   //!             // construct the UI
+55   //!
+56   //!             platform.prepare_render(&ui, &window); // step 5
+57   //!             // render the UI with a renderer
+58   //!             let draw_data = ui.render();
+59   //!             // renderer.render(..., draw_data).expect("UI rendering failed");
+60   //!
+61   //!             // application-specific rendering *over the UI*
+62   //!         },
+63   //!         Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
+64   //!             *control_flow = ControlFlow::Exit;
+65   //!         }
+66   //!         // other application-specific event handling
+67   //!         event => {
+68   //!             platform.handle_event(imgui_supp.io_mut(), &window, &event); // step 3
+69   //!             // other application-specific event handling
+70   //!         }
+71   //!     }
+72   //! })
+73   //! ```
+74   //!
+75   //! ## `winit` versions and features.
+76   //!
+77   //! This crate has several features which control the version of winit which is
+78   //! used.
+79   //!
+80   //! The following versions are supported, controlled by the listed feature.
+81   //!
+82   //! - The `winit-24` feature supports winit versions `0.24`. This is
+83   //!   on by default, so to use any other version you need to disable this crates
+84   //!   default features.
+85   //! - The `winit-23` feature uses winit versions compatible with `0.23`.
+86   //! - The `winit-22` feature uses winit versions compatible with `0.22`.
+87   //! - The `winit-20` feature should support winit either `0.20` or winit `0.21`.
+88   //! - The `winit-19` feature should support winits older than `0.19` (possibly
+89   //!   back to winit 0.16.*, but this isn't regularly tested and may not work).
+90   //!
+91   //! If multiple `winit-*` features are enabled, and it is a debug build (as
+92   //! determined by `debug_assertions`), we will log a warning to stderr during
+93   //! init. This can be disabled by either turning on the `no-warn-on-multiple`
+94   //! feature, fixing the configuration, or disabling `debug_assertions`.
+95   //!
+96   //! Conversely, if no `winit-*` features are enabled, we will fail to compile.
+97   //! This is not an issue generally, as by default we turn on `winit-24`.
+98   //!
+99   //! All of this is in attempt to preserve the additive nature of features (while
+100  //! still helping users notice project configuration issues), however it's done
+101  //! fairly weakly as our this crate's API isn't 100% identical across winit
+102  //! versions.
+103  //!
+104  //! ### Using an older `winit` version
+105  //!
+106  //! To use an older version, you must configure `default-features = false` in
+107  //! your `Cargo.toml`:
+108  //!
+109  //! ```toml
+110  //! [dependencies.imgui_supp-winit-support]
+111  //! version = "0.6"
+112  //! features = ["winit-$YOUR_VERSION_HERE"]
+113  //! default-features = false
+114  //! ```
+115  //!
+116  //! ### Old `winit` compatibility
+117  //!
+118  //! No guarantee is made on how long this crate will support legacy versions of
+119  //! `winit`, but we'll try to follow these rules:
+120  //!
+121  //! - Versions which are still in widespread use in the ecosystem will be
+122  //!   supported while that is true (for example, 0.19 at the time of writing is
+123  //!   quite old, but used by the most recent version of several popular crates).
+124  //!
+125  //! - Versions which are not a significant maintenance burden will be supported
+126  //!   (for example, supporting versions older than winit 0.19 given that we
+127  //!   support 0.19).
+128  //!
+129  //! - Explicitly removing support for a feature-indicated version will be
+130  //!   considered a breaking change.
+131  //!
+132  //! - Changing the default feature to the new latest `winit` version is *not* a
+133  //!   breaking change.
+134  
+135  #[cfg(feature = "winit-24")]
+136  use winit_24 as winit;
+137  
+138  #[cfg(all(not(feature = "winit-24"), feature = "winit-23"))]
+139  use winit_23 as winit;
+140  
+141  #[cfg(all(
+142  not(any(feature = "winit-24", feature = "winit-23")),
+143  feature = "winit-22",
+144  ))]
+145  use winit_22 as winit;
+146  
+147  #[cfg(all(
+148  not(any(feature = "winit-24", feature = "winit-23", feature = "winit-22")),
+149  feature = "winit-20",
+150  ))]
+151  use winit_20 as winit;
+152  
+153  #[cfg(all(
+154  not(any(
+155  feature = "winit-24",
+156  feature = "winit-23",
+157  feature = "winit-22",
+158  feature = "winit-20"
+159  )),
+160  feature = "winit-19",
+161  ))]
+162  use winit_19 as winit;
+163  
+164  use imgui::{self, BackendFlags, ConfigFlags, Context, ImString, Io, Key, Ui};
+165  use std::cell::Cell;
+166  use std::cmp::Ordering;
+167  use winit::dpi::{LogicalPosition, LogicalSize};
+168  
+169  #[cfg(all(
+170  not(any(
+171  feature = "winit-24",
+172  feature = "winit-23",
+173  feature = "winit-22",
+174  feature = "winit-20"
+175  )),
+176  feature = "winit-19",
+177  ))]
+178  use winit::{
+179      DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseCursor, MouseScrollDelta,
+180      TouchPhase, VirtualKeyCode, Window, WindowEvent,
+181  };
+182  
+183  #[cfg(any(
+184  feature = "winit-20",
+185  feature = "winit-22",
+186  feature = "winit-23",
+187  feature = "winit-24"
+188  ))]
+189  use winit::{
+190      error::ExternalError,
+191      event::{
+192          DeviceEvent, ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, TouchPhase,
+193          VirtualKeyCode, WindowEvent,
+194      },
+195      window::{CursorIcon as MouseCursor, Window},
+196  };
+197  use crate::owned_event::{OwnedEvent, OwnedWindowEvent};
+198  
+199  // Ensure at least one is enabled
+200  #[cfg(not(any(
+201  feature = "winit-19",
+202  feature = "winit-20",
+203  feature = "winit-22",
+204  feature = "winit-23",
+205  feature = "winit-24",
+206  )))]
+207  compile_error!("Please enable at least one version of `winit` (see documentation for details).");
+208  
+209  // FIXME(thom): make updading winit and adding a new feature less of a hassle here.
+210  fn check_multiple_winits() {
+211      use std::io::Write as _;
+212      use std::sync::atomic::{AtomicBool, Ordering};
+213      // bail out for release builds or if we've been explicitly disabled.
+214      if cfg!(any(not(debug_assertions), feature = "no-warn-on-multiple")) {
+215          return;
+216      }
+217      let winits_enabled = cfg!(feature = "winit-24") as usize
+218          + cfg!(feature = "winit-23") as usize
+219          + cfg!(feature = "winit-22") as usize
+220          + cfg!(feature = "winit-20") as usize
+221          + cfg!(feature = "winit-19") as usize;
+222  
+223      // Only complain once even if we're called multiple times.
+224      static COMPLAINED: AtomicBool = AtomicBool::new(false);
+225      // Note that the `Ordering` basically doesn't matter here, but even if it
+226      // did, `Relaxed` is still correct because we're only interested in the
+227      // effects on a single atomic variable.
+228      if winits_enabled <= 1
+229          || COMPLAINED
+230          .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
+231          .is_err()
+232      {
+233          return;
+234      }
+235      let mut err = Vec::with_capacity(512);
+236  
+237      // Log the complaint into a buffer first — in practice this is enough to
+238      // ensure atomicity.
+239      let _ = writeln!(
+240          err,
+241          "Warning (imgui_supp-winit-support): More than one `winit-*` version feature is enabled \ 
+242          (this likely indicates misconfiguration, see documentation for details)."
+243      );
+244      let feats = [
+245          ("winit-24", cfg!(feature = "winit-24"), " (default)"),
+246          ("winit-23", cfg!(feature = "winit-23"), ""),
+247          ("winit-22", cfg!(feature = "winit-22"), ""),
+248          ("winit-20", cfg!(feature = "winit-20"), ""),
+249          ("winit-19", cfg!(feature = "winit-19"), ""),
+250      ];
+251      for &(name, enabled, extra) in &feats {
+252          if enabled {
+253              let _ = writeln!(err, "    `feature = {:?}` is enabled{}", name, extra);
+254          }
+255      }
+256      if cfg!(feature = "winit-24") && winits_enabled == 2 {
+257          let _ = writeln!(
+258              err,
+259              "    Perhaps you are missing a `default-features = false`?",
+260          );
+261      }
+262      let _ = writeln!(
+263          err,
+264          "    (Note: This warning is only present in debug builds, and \ 
+265          can be disabled using the \"no-warn-on-multiple\" feature)"
+266      );
+267      let _ = std::io::stderr().write_all(&err);
+268  }
+269  
+270  /// State of a single mouse button. Used so that we can detect cases where mouse
+271  /// press and release occur on the same frame (seems surprisingly frequent on
+272  /// macOS now...)
+273  #[derive(Debug, Clone, Default)]
+274  struct Button {
+275      pressed_this_frame: Cell<bool>,
+276      state: Cell<bool>,
+277  }
+278  
+279  impl Button {
+280      // we can use this in an array initializer, unlike `Default::default()` or a
+281      // `const fn new()`.
+282      #[allow(clippy::declare_interior_mutable_const)]
+283      const INIT: Button = Self {
+284          pressed_this_frame: Cell::new(false),
+285          state: Cell::new(false),
+286      };
+287      fn set(&self, pressed: bool) {
+288          self.state.set(pressed);
+289          if pressed {
+290              self.pressed_this_frame.set(true);
+291          }
+292      }
+293      fn get(&self) -> bool {
+294          // If we got a press this frame, record it even if we got a release
+295          // too — this way we don't drop mouse clicks where the release comes
+296          // in on the same frame as the press. (This mirrors what Dear ImGUI
+297          // seems to do in the `imgui_impl_*`)
+298          self.pressed_this_frame.replace(false) || self.state.get()
+299      }
+300  }
+301  
+302  /// winit backend platform state
+303  #[derive(Debug)]
+304  pub struct WinitPlatform {
+305      hidpi_mode: ActiveHiDpiMode,
+306      hidpi_factor: f64,
+307      cursor_cache: Option<CursorSettings>,
+308      mouse_buttons: [Button; 5],
+309  }
+310  
+311  #[derive(Debug, Copy, Clone, Eq, PartialEq)]
+312  struct CursorSettings {
+313      cursor: Option<imgui::MouseCursor>,
+314      draw_cursor: bool,
+315  }
+316  
+317  fn to_winit_cursor(cursor: imgui::MouseCursor) -> MouseCursor {
+318      match cursor {
+319          imgui::MouseCursor::Arrow => MouseCursor::Default,
+320          imgui::MouseCursor::TextInput => MouseCursor::Text,
+321          imgui::MouseCursor::ResizeAll => MouseCursor::Move,
+322          imgui::MouseCursor::ResizeNS => MouseCursor::NsResize,
+323          imgui::MouseCursor::ResizeEW => MouseCursor::EwResize,
+324          imgui::MouseCursor::ResizeNESW => MouseCursor::NeswResize,
+325          imgui::MouseCursor::ResizeNWSE => MouseCursor::NwseResize,
+326          imgui::MouseCursor::Hand => MouseCursor::Hand,
+327          imgui::MouseCursor::NotAllowed => MouseCursor::NotAllowed,
+328      }
+329  }
+330  
+331  impl CursorSettings {
+332      #[cfg(all(
+333      not(any(
+334      feature = "winit-24",
+335      feature = "winit-23",
+336      feature = "winit-22",
+337      feature = "winit-20"
+338      )),
+339      feature = "winit-19",
+340      ))]
+341      fn apply(&self, window: &Window) {
+342          match self.cursor {
+343              Some(mouse_cursor) if !self.draw_cursor => {
+344                  window.hide_cursor(false);
+345                  window.set_cursor(to_winit_cursor(mouse_cursor));
+346              }
+347              _ => window.hide_cursor(true),
+348          }
+349      }
+350      #[cfg(any(
+351      feature = "winit-20",
+352      feature = "winit-22",
+353      feature = "winit-23",
+354      feature = "winit-24"
+355      ))]
+356      fn apply(&self, window: &Window) {
+357          match self.cursor {
+358              Some(mouse_cursor) if !self.draw_cursor => {
+359                  window.set_cursor_visible(true);
+360                  window.set_cursor_icon(to_winit_cursor(mouse_cursor));
+361              }
+362              _ => window.set_cursor_visible(false),
+363          }
+364      }
+365  }
+366  
+367  #[derive(Copy, Clone, Debug, PartialEq)]
+368  enum ActiveHiDpiMode {
+369      Default,
+370      Rounded,
+371      Locked,
+372  }
+373  
+374  /// DPI factor handling mode.
+375  ///
+376  /// Applications that use imgui_supp-rs might want to customize the used DPI factor and not use
+377  /// directly the value coming from winit.
+378  ///
+379  /// **Note: if you use a mode other than default and the DPI factor is adjusted, winit and imgui_supp-rs
+380  /// will use different logical coordinates, so be careful if you pass around logical size or
+381  /// position values.**
+382  #[derive(Copy, Clone, Debug, PartialEq)]
+383  pub enum HiDpiMode {
+384      /// The DPI factor from winit is used directly without adjustment
+385      Default,
+386      /// The DPI factor from winit is rounded to an integer value.
+387      ///
+388      /// This prevents the user interface from becoming blurry with non-integer scaling.
+389      Rounded,
+390      /// The DPI factor from winit is ignored, and the included value is used instead.
+391      ///
+392      /// This is useful if you want to force some DPI factor (e.g. 1.0) and not care about the value
+393      /// coming from winit.
+394      Locked(f64),
+395  }
+396  
+397  impl HiDpiMode {
+398      fn apply(&self, hidpi_factor: f64) -> (ActiveHiDpiMode, f64) {
+399          match *self {
+400              HiDpiMode::Default => (ActiveHiDpiMode::Default, hidpi_factor),
+401              HiDpiMode::Rounded => (ActiveHiDpiMode::Rounded, hidpi_factor.round()),
+402              HiDpiMode::Locked(value) => (ActiveHiDpiMode::Locked, value),
+403          }
+404      }
+405  }
+406  
+407  impl WinitPlatform {
+408      /// Initializes a winit platform instance and configures imgui_supp.
+409      ///
+410      /// This function configures imgui_supp-rs in the following ways:
+411      ///
+412      /// * backend flags are updated
+413      /// * keys are configured
+414      /// * platform name is set
+415      pub fn init(imgui: &mut Context) -> WinitPlatform {
+416          // noop in non-debug builds, if disabled, or if called a second time.
+417          check_multiple_winits();
+418          let io = imgui.io_mut();
+419          io.backend_flags.insert(BackendFlags::HAS_MOUSE_CURSORS);
+420          io.backend_flags.insert(BackendFlags::HAS_SET_MOUSE_POS);
+421          io[Key::Tab] = VirtualKeyCode::Tab as _;
+422          io[Key::LeftArrow] = VirtualKeyCode::Left as _;
+423          io[Key::RightArrow] = VirtualKeyCode::Right as _;
+424          io[Key::UpArrow] = VirtualKeyCode::Up as _;
+425          io[Key::DownArrow] = VirtualKeyCode::Down as _;
+426          io[Key::PageUp] = VirtualKeyCode::PageUp as _;
+427          io[Key::PageDown] = VirtualKeyCode::PageDown as _;
+428          io[Key::Home] = VirtualKeyCode::Home as _;
+429          io[Key::End] = VirtualKeyCode::End as _;
+430          io[Key::Insert] = VirtualKeyCode::Insert as _;
+431          io[Key::Delete] = VirtualKeyCode::Delete as _;
+432          io[Key::Backspace] = VirtualKeyCode::Back as _;
+433          io[Key::Space] = VirtualKeyCode::Space as _;
+434          io[Key::Enter] = VirtualKeyCode::Return as _;
+435          io[Key::Escape] = VirtualKeyCode::Escape as _;
+436          io[Key::KeyPadEnter] = VirtualKeyCode::NumpadEnter as _;
+437          io[Key::A] = VirtualKeyCode::A as _;
+438          io[Key::C] = VirtualKeyCode::C as _;
+439          io[Key::V] = VirtualKeyCode::V as _;
+440          io[Key::X] = VirtualKeyCode::X as _;
+441          io[Key::Y] = VirtualKeyCode::Y as _;
+442          io[Key::Z] = VirtualKeyCode::Z as _;
+443          imgui.set_platform_name(Some(ImString::from(format!(
+444              "imgui_supp-winit-support {}",
+445              env!("CARGO_PKG_VERSION")
+446          ))));
+447          WinitPlatform {
+448              hidpi_mode: ActiveHiDpiMode::Default,
+449              hidpi_factor: 1.0,
+450              cursor_cache: None,
+451              mouse_buttons: [Button::INIT; 5],
+452          }
+453      }
+454      /// Attaches the platform instance to a winit window.
+455      ///
+456      /// This function configures imgui_supp-rs in the following ways:
+457      ///
+458      /// * framebuffer scale (= DPI factor) is set
+459      /// * display size is set
+460      #[cfg(all(
+461      not(any(
+462      feature = "winit-24",
+463      feature = "winit-23",
+464      feature = "winit-22",
+465      feature = "winit-20"
+466      )),
+467      feature = "winit-19",
+468      ))]
+469      pub fn attach_window(&mut self, io: &mut Io, window: &Window, hidpi_mode: HiDpiMode) {
+470          let (hidpi_mode, hidpi_factor) = hidpi_mode.apply(window.get_hidpi_factor());
+471          self.hidpi_mode = hidpi_mode;
+472          self.hidpi_factor = hidpi_factor;
+473          io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
+474          if let Some(logical_size) = window.get_inner_size() {
+475              let logical_size = self.scale_size_from_winit(window, logical_size);
+476              io.display_size = [logical_size.width as f32, logical_size.height as f32];
+477          }
+478      }
+479      /// Attaches the platform instance to a winit window.
+480      ///
+481      /// This function configures imgui_supp-rs in the following ways:
+482      ///
+483      /// * framebuffer scale (= DPI factor) is set
+484      /// * display size is set
+485      #[cfg(any(
+486      feature = "winit-20",
+487      feature = "winit-22",
+488      feature = "winit-23",
+489      feature = "winit-24"
+490      ))]
+491      pub fn attach_window(&mut self, io: &mut Io, window: &Window, hidpi_mode: HiDpiMode) {
+492          let (hidpi_mode, hidpi_factor) = hidpi_mode.apply(window.scale_factor());
+493          self.hidpi_mode = hidpi_mode;
+494          self.hidpi_factor = hidpi_factor;
+495          io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
+496          let logical_size = window.inner_size().to_logical(hidpi_factor);
+497          let logical_size = self.scale_size_from_winit(window, logical_size);
+498          io.display_size = [logical_size.width as f32, logical_size.height as f32];
+499      }
+500      /// Returns the current DPI factor.
+501      ///
+502      /// The value might not be the same as the winit DPI factor (depends on the used DPI mode)
+503      pub fn hidpi_factor(&self) -> f64 {
+504          self.hidpi_factor
+505      }
+506      /// Scales a logical size coming from winit using the current DPI mode.
+507      ///
+508      /// This utility function is useful if you are using a DPI mode other than default, and want
+509      /// your application to use the same logical coordinates as imgui_supp-rs.
+510      #[cfg(all(
+511      not(any(
+512      feature = "winit-24",
+513      feature = "winit-23",
+514      feature = "winit-22",
+515      feature = "winit-20"
+516      )),
+517      feature = "winit-19",
+518      ))]
+519      pub fn scale_size_from_winit(&self, window: &Window, logical_size: LogicalSize) -> LogicalSize {
+520          match self.hidpi_mode {
+521              ActiveHiDpiMode::Default => logical_size,
+522              _ => logical_size
+523                  .to_physical(window.get_hidpi_factor())
+524                  .to_logical(self.hidpi_factor),
+525          }
+526      }
+527      /// Scales a logical size coming from winit using the current DPI mode.
+528      ///
+529      /// This utility function is useful if you are using a DPI mode other than default, and want
+530      /// your application to use the same logical coordinates as imgui_supp-rs.
+531      #[cfg(any(
+532      feature = "winit-20",
+533      feature = "winit-22",
+534      feature = "winit-23",
+535      feature = "winit-24"
+536      ))]
+537      pub fn scale_size_from_winit(
+538          &self,
+539          window: &Window,
+540          logical_size: LogicalSize<f64>,
+541      ) -> LogicalSize<f64> {
+542          match self.hidpi_mode {
+543              ActiveHiDpiMode::Default => logical_size,
+544              _ => logical_size
+545                  .to_physical::<f64>(window.scale_factor())
+546                  .to_logical(self.hidpi_factor),
+547          }
+548      }
+549      /// Scales a logical position coming from winit using the current DPI mode.
+550      ///
+551      /// This utility function is useful if you are using a DPI mode other than default, and want
+552      /// your application to use the same logical coordinates as imgui_supp-rs.
+553      #[cfg(all(
+554      not(any(
+555      feature = "winit-24",
+556      feature = "winit-23",
+557      feature = "winit-22",
+558      feature = "winit-20"
+559      )),
+560      feature = "winit-19",
+561      ))]
+562      pub fn scale_pos_from_winit(
+563          &self,
+564          window: &Window,
+565          logical_pos: LogicalPosition,
+566      ) -> LogicalPosition {
+567          match self.hidpi_mode {
+568              ActiveHiDpiMode::Default => logical_pos,
+569              _ => logical_pos
+570                  .to_physical(window.get_hidpi_factor())
+571                  .to_logical(self.hidpi_factor),
+572          }
+573      }
+574      /// Scales a logical position coming from winit using the current DPI mode.
+575      ///
+576      /// This utility function is useful if you are using a DPI mode other than default, and want
+577      /// your application to use the same logical coordinates as imgui_supp-rs.
+578      #[cfg(any(
+579      feature = "winit-20",
+580      feature = "winit-22",
+581      feature = "winit-23",
+582      feature = "winit-24"
+583      ))]
+584      pub fn scale_pos_from_winit(
+585          &self,
+586          window: &Window,
+587          logical_pos: LogicalPosition<f64>,
+588      ) -> LogicalPosition<f64> {
+589          match self.hidpi_mode {
+590              ActiveHiDpiMode::Default => logical_pos,
+591              _ => logical_pos
+592                  .to_physical::<f64>(window.scale_factor())
+593                  .to_logical(self.hidpi_factor),
+594          }
+595      }
+596      /// Scales a logical position for winit using the current DPI mode.
+597      ///
+598      /// This utility function is useful if you are using a DPI mode other than default, and want
+599      /// your application to use the same logical coordinates as imgui_supp-rs.
+600      #[cfg(all(
+601      not(any(
+602      feature = "winit-24",
+603      feature = "winit-23",
+604      feature = "winit-22",
+605      feature = "winit-20"
+606      )),
+607      feature = "winit-19",
+608      ))]
+609      pub fn scale_pos_for_winit(
+610          &self,
+611          window: &Window,
+612          logical_pos: LogicalPosition,
+613      ) -> LogicalPosition {
+614          match self.hidpi_mode {
+615              ActiveHiDpiMode::Default => logical_pos,
+616              _ => logical_pos
+617                  .to_physical(self.hidpi_factor)
+618                  .to_logical(window.get_hidpi_factor()),
+619          }
+620      }
+621      /// Scales a logical position for winit using the current DPI mode.
+622      ///
+623      /// This utility function is useful if you are using a DPI mode other than default, and want
+624      /// your application to use the same logical coordinates as imgui_supp-rs.
+625      #[cfg(any(
+626      feature = "winit-20",
+627      feature = "winit-22",
+628      feature = "winit-23",
+629      feature = "winit-24"
+630      ))]
+631      pub fn scale_pos_for_winit(
+632          &self,
+633          window: &Window,
+634          logical_pos: LogicalPosition<f64>,
+635      ) -> LogicalPosition<f64> {
+636          match self.hidpi_mode {
+637              ActiveHiDpiMode::Default => logical_pos,
+638              _ => logical_pos
+639                  .to_physical::<f64>(self.hidpi_factor)
+640                  .to_logical(window.scale_factor()),
+641          }
+642      }
+643      /// Handles a winit event.
+644      ///
+645      /// This function performs the following actions (depends on the event):
+646      ///
+647      /// * window size / dpi factor changes are applied
+648      /// * keyboard state is updated
+649      /// * mouse state is updated
+650      #[cfg(all(
+651      not(any(
+652      feature = "winit-24",
+653      feature = "winit-23",
+654      feature = "winit-22",
+655      feature = "winit-20"
+656      )),
+657      feature = "winit-19",
+658      ))]
+659      pub fn handle_event(&mut self, io: &mut Io, window: &Window, event: &Event) {
+660          match *event {
+661              Event::WindowEvent {
+662                  window_id,
+663                  ref event,
+664              } if window_id == window.id() => {
+665                  self.handle_window_event(io, window, event);
+666              }
+667              // Track key release events outside our window. If we don't do this,
+668              // we might never see the release event if some other window gets focus.
+669              Event::DeviceEvent {
+670                  event:
+671                  DeviceEvent::Key(KeyboardInput {
+672                                       state: ElementState::Released,
+673                                       virtual_keycode: Some(key),
+674                                       ..
+675                                   }),
+676                  ..
+677              } => {
+678                  io.keys_down[key as usize] = false;
+679                  match key {
+680                      VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = false,
+681                      VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = false,
+682                      VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = false,
+683                      VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = false,
+684                      _ => (),
+685                  }
+686              }
+687              _ => (),
+688          }
+689      }
+690      /// Handles a winit event.
+691      ///
+692      /// This function performs the following actions (depends on the event):
+693      ///
+694      /// * window size / dpi factor changes are applied
+695      /// * keyboard state is updated
+696      /// * mouse state is updated
+697      #[cfg(all(
+698      not(any(feature = "winit-24", feature = "winit-23", feature = "winit-22")),
+699      feature = "winit-20",
+700      ))]
+701      pub fn handle_event<T>(&mut self, io: &mut Io, window: &Window, event: &Event<T>) {
+702          match *event {
+703              Event::WindowEvent {
+704                  window_id,
+705                  ref event,
+706              } if window_id == window.id() => {
+707                  self.handle_window_event(io, window, event);
+708              }
+709              // Track key release events outside our window. If we don't do this,
+710              // we might never see the release event if some other window gets focus.
+711              Event::DeviceEvent {
+712                  event:
+713                  DeviceEvent::Key(KeyboardInput {
+714                                       state: ElementState::Released,
+715                                       virtual_keycode: Some(key),
+716                                       ..
+717                                   }),
+718                  ..
+719              } => {
+720                  io.keys_down[key as usize] = false;
+721              }
+722  
+723              // We need to track modifiers separately because some system like macOS, will
+724              // not reliably send modifier states during certain events like ScreenCapture.
+725              // Gotta let the people show off their pretty imgui_supp widgets!
+726              Event::DeviceEvent {
+727                  event: DeviceEvent::ModifiersChanged(modifiers),
+728                  ..
+729              } => {
+730                  io.key_shift = modifiers.shift();
+731                  io.key_ctrl = modifiers.ctrl();
+732                  io.key_alt = modifiers.alt();
+733                  io.key_super = modifiers.logo();
+734              }
+735              _ => (),
+736          }
+737      }
+738      /// Handles a winit event.
+739      ///
+740      /// This function performs the following actions (depends on the event):
+741      ///
+742      /// * window size / dpi factor changes are applied
+743      /// * keyboard state is updated
+744      /// * mouse state is updated
+745      #[cfg(any(feature = "winit-22", feature = "winit-23", feature = "winit-24"))]
+746      pub fn handle_event<T>(&mut self, io: &mut Io, window: &Window, event: &OwnedEvent<T>) {
+747          match *event {
+748              OwnedEvent::WindowEvent {
+749                  window_id,
+750                  ref event,
+751              } if window_id == window.id() => {
+752                  // We need to track modifiers separately because some system like macOS, will
+753                  // not reliably send modifier states during certain events like ScreenCapture.
+754                  // Gotta let the people show off their pretty imgui_supp widgets!
+755                  if let OwnedWindowEvent::ModifiersChanged(modifiers) = event {
+756                      io.key_shift = modifiers.shift();
+757                      io.key_ctrl = modifiers.ctrl();
+758                      io.key_alt = modifiers.alt();
+759                      io.key_super = modifiers.logo();
+760                  }
+761  
+762                  self.handle_window_event(io, window, event);
+763              }
+764              // Track key release events outside our window. If we don't do this,
+765              // we might never see the release event if some other window gets focus.
+766              OwnedEvent::DeviceEvent {
+767                  event:
+768                  DeviceEvent::Key(KeyboardInput {
+769                                       state: ElementState::Released,
+770                                       virtual_keycode: Some(key),
+771                                       ..
+772                                   }),
+773                  ..
+774              } => {
+775                  io.keys_down[key as usize] = false;
+776              }
+777              _ => (),
+778          }
+779      }
+780      #[cfg(all(
+781      not(any(
+782      feature = "winit-24",
+783      feature = "winit-23",
+784      feature = "winit-22",
+785      feature = "winit-20"
+786      )),
+787      feature = "winit-19",
+788      ))]
+789      fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
+790          match *event {
+791              WindowEvent::Resized(logical_size) => {
+792                  let logical_size = self.scale_size_from_winit(window, logical_size);
+793                  io.display_size = [logical_size.width as f32, logical_size.height as f32];
+794              }
+795              WindowEvent::HiDpiFactorChanged(scale) => {
+796                  let hidpi_factor = match self.hidpi_mode {
+797                      ActiveHiDpiMode::Default => scale,
+798                      ActiveHiDpiMode::Rounded => scale.round(),
+799                      _ => return,
+800                  };
+801                  // Mouse position needs to be changed while we still have both the old and the new
+802                  // values
+803                  if io.mouse_pos[0].is_finite() && io.mouse_pos[1].is_finite() {
+804                      io.mouse_pos = [
+805                          io.mouse_pos[0] * (hidpi_factor / self.hidpi_factor) as f32,
+806                          io.mouse_pos[1] * (hidpi_factor / self.hidpi_factor) as f32,
+807                      ];
+808                  }
+809                  self.hidpi_factor = hidpi_factor;
+810                  io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
+811                  // Window size might change too if we are using DPI rounding
+812                  if let Some(logical_size) = window.get_inner_size() {
+813                      let logical_size = self.scale_size_from_winit(window, logical_size);
+814                      io.display_size = [logical_size.width as f32, logical_size.height as f32];
+815                  }
+816              }
+817              WindowEvent::KeyboardInput {
+818                  input:
+819                  KeyboardInput {
+820                      virtual_keycode: Some(key),
+821                      state,
+822                      ..
+823                  },
+824                  ..
+825              } => {
+826                  io.keys_down[key as usize] = state == ElementState::Pressed;
+827              }
+828              WindowEvent::ReceivedCharacter(ch) => {
+829                  // Exclude the backspace key ('\u{7f}'). Otherwise we will insert this char and then
+830                  // delete it.
+831                  if ch != '\u{7f}' {
+832                      io.add_input_character(ch)
+833                  }
+834              }
+835              WindowEvent::CursorMoved { position, .. } => {
+836                  let position = self.scale_pos_from_winit(window, position);
+837                  io.mouse_pos = [position.x as f32, position.y as f32];
+838              }
+839              WindowEvent::MouseWheel {
+840                  delta,
+841                  phase: TouchPhase::Moved,
+842                  ..
+843              } => match delta {
+844                  MouseScrollDelta::LineDelta(h, v) => {
+845                      io.mouse_wheel_h = h;
+846                      io.mouse_wheel = v;
+847                  }
+848                  MouseScrollDelta::PixelDelta(pos) => {
+849                      match pos.x.partial_cmp(&0.0) {
+850                          Some(Ordering::Greater) => io.mouse_wheel_h += 1.0,
+851                          Some(Ordering::Less) => io.mouse_wheel_h -= 1.0,
+852                          _ => (),
+853                      }
+854                      match pos.y.partial_cmp(&0.0) {
+855                          Some(Ordering::Greater) => io.mouse_wheel += 1.0,
+856                          Some(Ordering::Less) => io.mouse_wheel -= 1.0,
+857                          _ => (),
+858                      }
+859                  }
+860              },
+861              WindowEvent::MouseInput { state, button, .. } => {
+862                  let pressed = state == ElementState::Pressed;
+863                  match button {
+864                      MouseButton::Left => self.mouse_buttons[0].set(pressed),
+865                      MouseButton::Right => self.mouse_buttons[1].set(pressed),
+866                      MouseButton::Middle => self.mouse_buttons[2].set(pressed),
+867                      MouseButton::Other(idx @ 0..=4) => {
+868                          self.mouse_buttons[idx as usize].set(pressed)
+869                      }
+870                      _ => (),
+871                  }
+872              }
+873              _ => (),
+874          }
+875      }
+876      #[cfg(all(
+877      not(any(feature = "winit-23", feature = "winit-24")),
+878      any(feature = "winit-20", feature = "winit-22")
+879      ))]
+880      fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
+881          match *event {
+882              WindowEvent::Resized(physical_size) => {
+883                  let logical_size = physical_size.to_logical(window.scale_factor());
+884                  let logical_size = self.scale_size_from_winit(window, logical_size);
+885                  io.display_size = [logical_size.width as f32, logical_size.height as f32];
+886              }
+887              WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
+888                  let hidpi_factor = match self.hidpi_mode {
+889                      ActiveHiDpiMode::Default => scale_factor,
+890                      ActiveHiDpiMode::Rounded => scale_factor.round(),
+891                      _ => return,
+892                  };
+893                  // Mouse position needs to be changed while we still have both the old and the new
+894                  // values
+895                  if io.mouse_pos[0].is_finite() && io.mouse_pos[1].is_finite() {
+896                      io.mouse_pos = [
+897                          io.mouse_pos[0] * (hidpi_factor / self.hidpi_factor) as f32,
+898                          io.mouse_pos[1] * (hidpi_factor / self.hidpi_factor) as f32,
+899                      ];
+900                  }
+901                  self.hidpi_factor = hidpi_factor;
+902                  io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
+903                  // Window size might change too if we are using DPI rounding
+904                  let logical_size = window.inner_size().to_logical(scale_factor);
+905                  let logical_size = self.scale_size_from_winit(window, logical_size);
+906                  io.display_size = [logical_size.width as f32, logical_size.height as f32];
+907              }
+908              WindowEvent::KeyboardInput {
+909                  input:
+910                  KeyboardInput {
+911                      virtual_keycode: Some(key),
+912                      state,
+913                      ..
+914                  },
+915                  ..
+916              } => {
+917                  let pressed = state == ElementState::Pressed;
+918                  io.keys_down[key as usize] = pressed;
+919  
+920                  // This is a bit redundant here, but we'll leave it in. The OS occasionally
+921                  // fails to send modifiers keys, but it doesn't seem to send false-positives,
+922                  // so double checking isn't terrible in case some system *doesn't* send
+923                  // device events sometimes.
+924                  match key {
+925                      VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = pressed,
+926                      VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = pressed,
+927                      VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = pressed,
+928                      VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = pressed,
+929                      _ => (),
+930                  }
+931              }
+932              WindowEvent::ReceivedCharacter(ch) => {
+933                  // Exclude the backspace key ('\u{7f}'). Otherwise we will insert this char and then
+934                  // delete it.
+935                  if ch != '\u{7f}' {
+936                      io.add_input_character(ch)
+937                  }
+938              }
+939              WindowEvent::CursorMoved { position, .. } => {
+940                  let position = position.to_logical(window.scale_factor());
+941                  let position = self.scale_pos_from_winit(window, position);
+942                  io.mouse_pos = [position.x as f32, position.y as f32];
+943              }
+944              WindowEvent::MouseWheel {
+945                  delta,
+946                  phase: TouchPhase::Moved,
+947                  ..
+948              } => match delta {
+949                  MouseScrollDelta::LineDelta(h, v) => {
+950                      io.mouse_wheel_h = h;
+951                      io.mouse_wheel = v;
+952                  }
+953                  MouseScrollDelta::PixelDelta(pos) => {
+954                      match pos.x.partial_cmp(&0.0) {
+955                          Some(Ordering::Greater) => io.mouse_wheel_h += 1.0,
+956                          Some(Ordering::Less) => io.mouse_wheel_h -= 1.0,
+957                          _ => (),
+958                      }
+959                      match pos.y.partial_cmp(&0.0) {
+960                          Some(Ordering::Greater) => io.mouse_wheel += 1.0,
+961                          Some(Ordering::Less) => io.mouse_wheel -= 1.0,
+962                          _ => (),
+963                      }
+964                  }
+965              },
+966              WindowEvent::MouseInput { state, button, .. } => {
+967                  let pressed = state == ElementState::Pressed;
+968                  match button {
+969                      MouseButton::Left => self.mouse_buttons[0].set(pressed),
+970                      MouseButton::Right => self.mouse_buttons[1].set(pressed),
+971                      MouseButton::Middle => self.mouse_buttons[2].set(pressed),
+972                      MouseButton::Other(idx @ 0..=4) => {
+973                          self.mouse_buttons[idx as usize].set(pressed)
+974                      }
+975                      _ => (),
+976                  }
+977              }
+978              _ => (),
+979          }
+980      }
+981  
+982      #[cfg(any(feature = "winit-23", feature = "winit-24"))]
+983      fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &OwnedWindowEvent) {
+984          match *event {
+985              OwnedWindowEvent::Resized(physical_size) => {
+986                  let logical_size = physical_size.to_logical(window.scale_factor());
+987                  let logical_size = self.scale_size_from_winit(window, logical_size);
+988                  io.display_size = [logical_size.width as f32, logical_size.height as f32];
+989              }
+990              OwnedWindowEvent::ScaleFactorChanged { scale_factor, .. } => {
+991                  let hidpi_factor = match self.hidpi_mode {
+992                      ActiveHiDpiMode::Default => scale_factor,
+993                      ActiveHiDpiMode::Rounded => scale_factor.round(),
+994                      _ => return,
+995                  };
+996                  // Mouse position needs to be changed while we still have both the old and the new
+997                  // values
+998                  if io.mouse_pos[0].is_finite() && io.mouse_pos[1].is_finite() {
+999                      io.mouse_pos = [
+1000                         io.mouse_pos[0] * (hidpi_factor / self.hidpi_factor) as f32,
+1001                         io.mouse_pos[1] * (hidpi_factor / self.hidpi_factor) as f32,
+1002                     ];
+1003                 }
+1004                 self.hidpi_factor = hidpi_factor;
+1005                 io.display_framebuffer_scale = [hidpi_factor as f32, hidpi_factor as f32];
+1006                 // Window size might change too if we are using DPI rounding
+1007                 let logical_size = window.inner_size().to_logical(scale_factor);
+1008                 let logical_size = self.scale_size_from_winit(window, logical_size);
+1009                 io.display_size = [logical_size.width as f32, logical_size.height as f32];
+1010             }
+1011             OwnedWindowEvent::KeyboardInput {
+1012                 input:
+1013                 KeyboardInput {
+1014                     virtual_keycode: Some(key),
+1015                     state,
+1016                     ..
+1017                 },
+1018                 ..
+1019             } => {
+1020                 let pressed = state == ElementState::Pressed;
+1021                 io.keys_down[key as usize] = pressed;
+1022 
+1023                 // This is a bit redundant here, but we'll leave it in. The OS occasionally
+1024                 // fails to send modifiers keys, but it doesn't seem to send false-positives,
+1025                 // so double checking isn't terrible in case some system *doesn't* send
+1026                 // device events sometimes.
+1027                 match key {
+1028                     VirtualKeyCode::LShift | VirtualKeyCode::RShift => io.key_shift = pressed,
+1029                     VirtualKeyCode::LControl | VirtualKeyCode::RControl => io.key_ctrl = pressed,
+1030                     VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => io.key_alt = pressed,
+1031                     VirtualKeyCode::LWin | VirtualKeyCode::RWin => io.key_super = pressed,
+1032                     _ => (),
+1033                 }
+1034             }
+1035             OwnedWindowEvent::ReceivedCharacter(ch) => {
+1036                 // Exclude the backspace key ('\u{7f}'). Otherwise we will insert this char and then
+1037                 // delete it.
+1038                 if ch != '\u{7f}' {
+1039                     io.add_input_character(ch)
+1040                 }
+1041             }
+1042             OwnedWindowEvent::CursorMoved { position, .. } => {
+1043                 let position = position.to_logical(window.scale_factor());
+1044                 let position = self.scale_pos_from_winit(window, position);
+1045                 io.mouse_pos = [position.x as f32, position.y as f32];
+1046             }
+1047             OwnedWindowEvent::MouseWheel {
+1048                 delta,
+1049                 phase: TouchPhase::Moved,
+1050                 ..
+1051             } => match delta {
+1052                 MouseScrollDelta::LineDelta(h, v) => {
+1053                     io.mouse_wheel_h = h;
+1054                     io.mouse_wheel = v;
+1055                 }
+1056                 MouseScrollDelta::PixelDelta(pos) => {
+1057                     let pos = pos.to_logical::<f64>(self.hidpi_factor);
+1058                     match pos.x.partial_cmp(&0.0) {
+1059                         Some(Ordering::Greater) => io.mouse_wheel_h += 1.0,
+1060                         Some(Ordering::Less) => io.mouse_wheel_h -= 1.0,
+1061                         _ => (),
+1062                     }
+1063                     match pos.y.partial_cmp(&0.0) {
+1064                         Some(Ordering::Greater) => io.mouse_wheel += 1.0,
+1065                         Some(Ordering::Less) => io.mouse_wheel -= 1.0,
+1066                         _ => (),
+1067                     }
+1068                 }
+1069             },
+1070             OwnedWindowEvent::MouseInput { state, button, .. } => {
+1071                 let pressed = state == ElementState::Pressed;
+1072                 match button {
+1073                     MouseButton::Left => self.mouse_buttons[0].set(pressed),
+1074                     MouseButton::Right => self.mouse_buttons[1].set(pressed),
+1075                     MouseButton::Middle => self.mouse_buttons[2].set(pressed),
+1076                     MouseButton::Other(idx @ 0..=4) => {
+1077                         self.mouse_buttons[idx as usize].set(pressed)
+1078                     }
+1079                     _ => (),
+1080                 }
+1081             }
+1082             _ => (),
+1083         }
+1084     }
+1085     /// Frame preparation callback.
+1086     ///
+1087     /// Call this before calling the imgui_supp-rs context `frame` function.
+1088     /// This function performs the following actions:
+1089     ///
+1090     /// * mouse cursor is repositioned (if requested by imgui_supp-rs)
+1091     #[cfg(all(
+1092     not(any(
+1093     feature = "winit-24",
+1094     feature = "winit-23",
+1095     feature = "winit-22",
+1096     feature = "winit-20"
+1097     )),
+1098     feature = "winit-19",
+1099     ))]
+1100     pub fn prepare_frame(&self, io: &mut Io, window: &Window) -> Result<(), String> {
+1101         self.copy_mouse_to_io(&mut io.mouse_down);
+1102         if io.want_set_mouse_pos {
+1103             let logical_pos = self.scale_pos_for_winit(
+1104                 window,
+1105                 LogicalPosition::new(f64::from(io.mouse_pos[0]), f64::from(io.mouse_pos[1])),
+1106             );
+1107             window.set_cursor_position(logical_pos)
+1108         } else {
+1109             Ok(())
+1110         }
+1111     }
+1112     /// Frame preparation callback.
+1113     ///
+1114     /// Call this before calling the imgui_supp-rs context `frame` function.
+1115     /// This function performs the following actions:
+1116     ///
+1117     /// * mouse cursor is repositioned (if requested by imgui_supp-rs)
+1118     #[cfg(any(
+1119     feature = "winit-20",
+1120     feature = "winit-22",
+1121     feature = "winit-23",
+1122     feature = "winit-24"
+1123     ))]
+1124     pub fn prepare_frame(&self, io: &mut Io, window: &Window) -> Result<(), ExternalError> {
+1125         self.copy_mouse_to_io(&mut io.mouse_down);
+1126         if io.want_set_mouse_pos {
+1127             let logical_pos = self.scale_pos_for_winit(
+1128                 window,
+1129                 LogicalPosition::new(f64::from(io.mouse_pos[0]), f64::from(io.mouse_pos[1])),
+1130             );
+1131             window.set_cursor_position(logical_pos)
+1132         } else {
+1133             Ok(())
+1134         }
+1135     }
+1136 
+1137     fn copy_mouse_to_io(&self, io_mouse_down: &mut [bool]) {
+1138         for (io_down, button) in io_mouse_down.iter_mut().zip(&self.mouse_buttons) {
+1139             *io_down = button.get();
+1140         }
+1141     }
+1142 
+1143     /// Render preparation callback.
+1144     ///
+1145     /// Call this before calling the imgui_supp-rs UI `render_with`/`render` function.
+1146     /// This function performs the following actions:
+1147     ///
+1148     /// * mouse cursor is changed and/or hidden (if requested by imgui_supp-rs)
+1149     pub fn prepare_render(&mut self, ui: &Ui, window: &Window) {
+1150         let io = ui.io();
+1151         if !io
+1152             .config_flags
+1153             .contains(ConfigFlags::NO_MOUSE_CURSOR_CHANGE)
+1154         {
+1155             let cursor = CursorSettings {
+1156                 cursor: ui.mouse_cursor(),
+1157                 draw_cursor: io.mouse_draw_cursor,
+1158             };
+1159             if self.cursor_cache != Some(cursor) {
+1160                 cursor.apply(window);
+1161                 self.cursor_cache = Some(cursor);
+1162             }
+1163         }
+1164     }
+1165 }
+1166 
+ + \ No newline at end of file diff --git a/exportToHTML/geometry.rs.html b/exportToHTML/geometry.rs.html new file mode 100644 index 0000000..612b920 --- /dev/null +++ b/exportToHTML/geometry.rs.html @@ -0,0 +1,164 @@ + + +geometry.rs + + + + + +
+ +geometry.rs +
+
1    use bytemuck::{Pod, Zeroable};
+2    use nalgebra::Vector4;
+3    use rapier3d::parry::math::Point;
+4    use tobj::{LoadError, Model, Material};
+5    
+6    
+7    #[repr(C)]
+8    #[derive(Clone, Copy, Debug)]
+9    pub struct Vertex {
+10       pos: [f32; 4],
+11       normal: [f32; 4],
+12       uv: [f32; 2],
+13   }
+14   
+15   impl Vertex {
+16       pub fn position(&self) -> Point<f32> {
+17           Point::<f32>::new(self.pos[0], self.pos[1], self.pos[2])
+18       }
+19       pub fn from(pos: [f32; 3], nor: [f32; 3], uv: [f32; 2]) -> Vertex {
+20           Vertex {
+21               pos: [pos[0], pos[1], pos[2], 1.0],
+22               normal: [nor[0], nor[1], nor[2], 0.0],
+23               uv: [uv[0], uv[1]],
+24           }
+25       }
+26   }
+27   
+28   unsafe impl Pod for Vertex {}
+29   unsafe impl Zeroable for Vertex {}
+30   
+31   #[derive(Clone, Debug)]
+32   pub struct RawMesh {
+33       pub vertices: Vec<Vertex>,
+34       pub indices: Vec<[u32; 3]>,
+35   }
+36   
+37   
+38   /// We use meshes in a few different places. To keep things simple, we return
+39   /// the most basic, direct-to-memory version. If something fancy needs to be done
+40   /// with it, the fancy stays there
+41   pub fn load_obj(obj_path: &str) -> Result<RawMesh, String> {
+42   
+43       log::info!("Loading object {}", obj_path);
+44   
+45       // Is there no better way to translate error messages?
+46       let (models, materials) = match tobj::load_obj(obj_path, true) {
+47           Ok((a, b)) => {Ok((a, b))}
+48           Err(load_error) => {Err(load_error.to_string())}
+49       }?;
+50   
+51       // println!("# of models: {}", models.len());
+52       // println!("# of materials: {}", materials.len());
+53       // println!("{:?}", materials);
+54   
+55       let mut index_data: Vec<[u32; 3]> = Vec::new();
+56       let mut vertex_data = Vec::new();
+57   
+58       for model in models {
+59           let mesh = &model.mesh;
+60   
+61           // Cycle through the faces and chunk out the indices
+62           let mut next_face = 0;
+63           for f in 0..mesh.num_face_indices.len() {
+64               // calculate the next chunk
+65               let end = next_face + mesh.num_face_indices[f] as usize;
+66               let face_indices: Vec<_> = mesh.indices[next_face..end].iter().collect();
+67   
+68               if face_indices.len() != 3 {
+69                   return Err("we only handle triangulated faces".to_string());
+70               }
+71               index_data.push([*face_indices[0], *face_indices[1], *face_indices[2]]);
+72               next_face = end;
+73           }
+74   
+75           if mesh.positions.len() % 3 != 0 {
+76               return Err(format!("position array not % 3 : {}", mesh.positions.len()))
+77           }
+78           if mesh.texcoords.len() % 2 != 0 {
+79               return Err(format!("position array not % 3 : {}", mesh.positions.len()))
+80           }
+81           if mesh.normals.is_empty() {
+82               return Err(format!("It would be best if this had normals"))
+83           }
+84           if mesh.texcoords.is_empty() {
+85               log::info!("\tMesh texture coordinates empty")
+86           }
+87   
+88           for v in 0..mesh.positions.len() / 3 {
+89               let texcoords = if mesh.texcoords.len() == 0 {
+90                   [0.0, 0.0]
+91               } else {
+92                   [mesh.texcoords[2 * v], mesh.texcoords[2 * v + 1]]
+93               };
+94   
+95               vertex_data.push(Vertex::from(
+96                   [
+97                       mesh.positions[3 * v],
+98                       mesh.positions[3 * v + 1],
+99                       mesh.positions[3 * v + 2],
+100                  ],
+101                  [
+102                      mesh.normals[3 * v],
+103                      mesh.normals[3 * v + 1],
+104                      mesh.normals[3 * v + 2],
+105                  ],
+106                  texcoords,
+107              ));
+108          }
+109      }
+110      Ok(RawMesh {
+111          vertices: vertex_data.to_vec(),
+112          indices: index_data.to_vec(),
+113      })
+114  }
+115  
+116  // pub fn create_quad_mesh() -> RawMesh {
+117  //
+118  //     let mut index_data: Vec<[u32; 3]> = Vec::new();
+119  //     let mut vertex_data = Vec::new();
+120  //
+121  //     vertex_data.push(Vertex::from(
+122  //         [
+123  //             mesh.positions[3 * v],
+124  //             mesh.positions[3 * v + 1],
+125  //             mesh.positions[3 * v + 2],
+126  //         ],
+127  //         [
+128  //             mesh.normals[3 * v],
+129  //             mesh.normals[3 * v + 1],
+130  //             mesh.normals[3 * v + 2],
+131  //         ],
+132  //         [mesh.texcoords[2 * v], mesh.texcoords[2 * v + 1]],
+133  //     ));
+134  //
+135  //     RawMesh {
+136  //         vertices: vertex_data.to_vec(),
+137  //         indices: index_data.to_vec(),
+138  //     }
+139  // }
+140  
+ + \ No newline at end of file diff --git a/exportToHTML/imgui_support.rs.html b/exportToHTML/imgui_support.rs.html new file mode 100644 index 0000000..3304650 --- /dev/null +++ b/exportToHTML/imgui_support.rs.html @@ -0,0 +1,32 @@ + + +imgui_support.rs + + + + + +
+ +imgui_support.rs +
+
1    use crate::imgui_supp::extended_winit_imgui_support::WinitPlatform;
+2    
+3    
+4    pub struct ImguiContext {
+5        pub context: imgui::Context,
+6    }
+7    unsafe impl Send for ImguiContext {}
+8    
+9    pub struct ImguiPlatform {
+10       pub platform: WinitPlatform,
+11   }
+12   unsafe impl Send for ImguiPlatform {}
+ + \ No newline at end of file diff --git a/exportToHTML/index.html b/exportToHTML/index.html new file mode 100644 index 0000000..741b6ad --- /dev/null +++ b/exportToHTML/index.html @@ -0,0 +1 @@ +~/source/3d-min-viable-eng/src/imgui_suppmod.rs
imgui_support.rs
extended_winit_imgui_support.rs
\ No newline at end of file diff --git a/exportToHTML/light.rs.html b/exportToHTML/light.rs.html new file mode 100644 index 0000000..08c7e0d --- /dev/null +++ b/exportToHTML/light.rs.html @@ -0,0 +1,79 @@ + + +light.rs + + + + + +
+ +light.rs +
+
1    use bytemuck::__core::ops::Range;
+2    use bytemuck::{Zeroable, Pod};
+3    use cgmath::Point3;
+4    use std::sync::Arc;
+5    use wgpu::TextureView;
+6    use crate::components::{RangeCopy, Position};
+7    use crate::render::OPENGL_TO_WGPU_MATRIX;
+8    
+9    
+10   #[repr(C)]
+11   #[derive(Clone, Copy)]
+12   pub struct LightRaw {
+13       proj: [[f32; 4]; 4],
+14       pos: [f32; 4],
+15       color: [f32; 4],
+16   }
+17   
+18   unsafe impl Pod for LightRaw {}
+19   
+20   unsafe impl Zeroable for LightRaw {}
+21   
+22   #[derive(Clone, Debug)]
+23   pub struct DirectionalLight {
+24       pub color: wgpu::Color,
+25       pub fov: f32,
+26       pub depth: RangeCopy<f32>,
+27       pub target_view: Arc<TextureView>,
+28   }
+29   
+30   impl DirectionalLight {
+31       pub fn to_raw(&self, pos: &Position) -> LightRaw {
+32           use cgmath::{Deg, EuclideanSpace, Matrix4, PerspectiveFov, Point3, Vector3};
+33   
+34           let point3d = Point3::new(pos.x, pos.y, pos.z);
+35           let point3d_2 = Point3::new(pos.x, pos.y - 1.0, pos.z);
+36           let mx_view = Matrix4::look_at(point3d, point3d_2, Vector3::unit_z());
+37   
+38           let projection = PerspectiveFov {
+39               fovy: Deg(self.fov).into(),
+40               aspect: 1.0,
+41               near: self.depth.start,
+42               far: self.depth.end,
+43           };
+44           let mx_correction = OPENGL_TO_WGPU_MATRIX;
+45           let mx_view_proj =
+46               mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view;
+47           LightRaw {
+48               proj: *mx_view_proj.as_ref(),
+49               pos: [pos.x, pos.y, pos.z, 1.0],
+50               color: [
+51                   self.color.r as f32,
+52                   self.color.g as f32,
+53                   self.color.b as f32,
+54                   1.0,
+55               ],
+56           }
+57       }
+58   }
+ + \ No newline at end of file diff --git a/exportToHTML/main.rs.html b/exportToHTML/main.rs.html new file mode 100644 index 0000000..bc83a63 --- /dev/null +++ b/exportToHTML/main.rs.html @@ -0,0 +1,409 @@ + + +main.rs + + + + + +
+ +main.rs +
+
1    extern crate env_logger;
+2    extern crate imgui;
+3    extern crate imgui_wgpu;
+4    #[macro_use]
+5    extern crate lazy_static;
+6    #[macro_use]
+7    extern crate serde_derive;
+8    extern crate tobj;
+9    extern crate toml;
+10   extern crate winit_24;
+11   
+12   use std::collections::HashMap;
+13   use std::f32::consts::PI;
+14   use std::fs;
+15   use std::sync::{Arc, Mutex};
+16   #[cfg(not(target_arch = "wasm32"))]
+17   use std::time::{Duration, Instant};
+18   
+19   use cgmath::{
+20       Decomposed, Deg, Euler, InnerSpace, Point3, Quaternion, Rad, Rotation3, SquareMatrix,
+21   };
+22   use futures::executor::block_on;
+23   use futures::task::LocalSpawn;
+24   use futures::FutureExt;
+25   use gilrs::Event as GilEvent;
+26   use gilrs::{Gamepad, Gilrs};
+27   use imgui::FontSource;
+28   use imgui::__core::convert::TryInto;
+29   use imgui::*;
+30   use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig};
+31   use legion::systems::{SyncResources, UnsafeResources};
+32   use legion::*;
+33   use log::LevelFilter;
+34   use rapier3d::counters::Timer;
+35   use rapier3d::dynamics::{
+36       IntegrationParameters, JointSet, RigidBody, RigidBodyBuilder, RigidBodyHandle, RigidBodySet,
+37   };
+38   use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderHandle, ColliderSet, NarrowPhase};
+39   use rapier3d::math;
+40   use rapier3d::math::Point;
+41   use rapier3d::na::{Isometry, Isometry3, Vector, Vector3};
+42   use rapier3d::pipeline::PhysicsPipeline;
+43   use wgpu::{BindGroup, Buffer, TextureView};
+44   use wgpu_subscriber;
+45   use winit_24::event::DeviceEvent::MouseMotion;
+46   use winit_24::event::{ElementState, VirtualKeyCode};
+47   use winit_24::event_loop::EventLoopProxy;
+48   use winit_24::platform::unix::x11::ffi::Time;
+49   use winit_24::window::Window;
+50   use winit_24::{
+51       event::{self, WindowEvent},
+52       event_loop::{ControlFlow, EventLoop},
+53   };
+54   
+55   use crate::camera::{Camera, CameraController};
+56   use crate::components::{Collider, ImguiWindow, LoopState, Physics, Position};
+57   use crate::geometry::{load_obj, RawMesh};
+58   use crate::imgui_supp::extended_winit_imgui_support;
+59   use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
+60   use crate::owned_event::{OwnedEvent, OwnedEventExtension};
+61   use crate::physics::state::PhysicsState;
+62   use crate::render::system::ImguiPerformanceProfilerLine;
+63   use crate::runtime::state::RuntimeState;
+64   use winit_24::dpi::PhysicalSize;
+65   
+66   mod camera;
+67   mod components;
+68   mod geometry;
+69   mod imgui_supp;
+70   mod light;
+71   mod owned_event;
+72   mod physics;
+73   mod render;
+74   mod runtime;
+75   
+76   /* 
+77    
+78   Collision detection 
+79   https://nphysics.org/rigid_body_simulations_with_contacts/ 
+80    
+81   Obj file format 
+82   http://paulbourke.net/dataformats/obj/ 
+83    
+84   tobj obj loader 
+85   https://docs.rs/tobj/2.0.3/tobj/index.html 
+86    
+87   mesh generator lib, might be useful 
+88   https://docs.rs/genmesh/0.6.2/genmesh/ 
+89    
+90   legion ECS 
+91   https://github.com/amethyst/legion 
+92    
+93    
+94   ECS 
+95       animation 
+96       config / save loading (sorta!) 
+97       render 3d (good!) 
+98       input/io (yep!) 
+99       collision / physics (yep!) 
+100      entities & behaviours (got the entities!) 
+101      scripting! 
+102   
+103   
+104  Todo: 
+105      Load scene imgui interface w/ toml files 
+106      FPS graph port from voxel raycaster 
+107      better imgui interface with components & systems 
+108      Figure out eventing, GameInput, passing all events, etc. 
+109      + texturing 
+110   
+111  I need to figure out the way that I want to do 2d graphics in a 3d engine... 
+112  I suppose I will need sprites. And those are just 2 polygons which are textured 
+113   
+114   
+115   
+116   */
+117  
+118  //log::info!("");
+119  
+120  // ImGUI works on more or less an unsafe global state. which is MegaLame
+121  static mut CURRENT_UI: Option<imgui::Ui<'static>> = None;
+122  pub unsafe fn current_ui<'a>() -> Option<&'a imgui::Ui<'a>> {
+123      CURRENT_UI.as_ref()
+124  }
+125  
+126  
+127  
+128  fn main() {
+129      let logger = env_logger::builder()
+130          .filter(Some("minimal_viable_game_engine"), LevelFilter::Info)
+131          .init();
+132  
+133      let mut world = World::default();
+134  
+135      let mut imgui_prepare_schedule = Schedule::builder()
+136          .add_system(render::system::imgui_prepare_system())
+137          .build();
+138  
+139      let mut load_schedule = Schedule::builder()
+140          .add_system(runtime::system::runtime_load_system())
+141          .add_system(runtime::system::runtime_spawn_system())
+142          .flush()
+143          .build();
+144  
+145      let mut render_schedule = Schedule::builder()
+146          .add_system(render::system::render_imgui_system())
+147          .add_system(render::system::render_test_system())
+148          .add_system(render::system::render_performance_flag_system())
+149          .build();
+150  
+151      let mut update_schedule = Schedule::builder()
+152          .add_system(physics::system::update_camera_system())
+153          .add_system(physics::system::run_physics_system())
+154          .add_system(physics::system::update_models_system())
+155          // next system here, gamelogic update system?
+156          .build();
+157  
+158      let mut event_schedule = Schedule::builder()
+159          .add_system(owned_event::event_dispatch_system())
+160          .build();
+161  
+162      let event_loop = EventLoop::<OwnedEventExtension>::with_user_event();
+163      let mut builder = winit_24::window::WindowBuilder::new();
+164      builder = builder.with_title("MVGE");
+165      builder = builder.with_inner_size(PhysicalSize::new(1200,900));
+166  
+167      let window = builder.build(&event_loop).unwrap();
+168  
+169      let mut resources = Resources::default();
+170  
+171  
+172  
+173      // Load up all the resources
+174      {
+175          let mut imgui_context = imgui::Context::create();
+176          let mut platform = extended_winit_imgui_support::WinitPlatform::init(&mut imgui_context);
+177          platform.attach_window(
+178              imgui_context.io_mut(),
+179              &window,
+180              extended_winit_imgui_support::HiDpiMode::Default,
+181          );
+182  
+183          // imgui_supp rendering context
+184          let mut imgui_context = ImguiContext {
+185              context: imgui_context,
+186          };
+187          let mut imgui_platform = ImguiPlatform { platform: platform };
+188          let font_size = 20.0 as f32;
+189          imgui_context.context.io_mut().font_global_scale = 1.0 as f32;
+190          imgui_context
+191              .context
+192              .fonts()
+193              .add_font(&[FontSource::DefaultFontData {
+194                  config: Some(imgui::FontConfig {
+195                      oversample_h: 1,
+196                      pixel_snap_h: true,
+197                      size_pixels: font_size,
+198                      ..Default::default()
+199                  }),
+200              }]);
+201          imgui_context.context.set_ini_filename(None);
+202  
+203          // The renderer
+204          let mut renderer = render::state::RenderState::init(&window, &mut imgui_context);
+205  
+206          resources.insert(renderer);
+207          resources.insert(Arc::new(Mutex::new(imgui_context)));
+208          resources.insert(Arc::new(Mutex::new(imgui_platform)));
+209          resources.insert(window);
+210  
+211          // Physics
+212          let (physics_state, physics_pipeline) =
+213              PhysicsState::build(rapier3d::math::Vector::new(0.0, -9.81, 0.0));
+214          resources.insert(physics_state);
+215          resources.insert(physics_pipeline);
+216  
+217          // Loop data
+218          resources.insert(LoopState {
+219              delta_time: Default::default(),
+220              start_time: Instant::now(),
+221              step_size: 0.01666, // 60hz
+222          });
+223  
+224          // And our event stack
+225          resources.insert(Vec::<OwnedEvent<OwnedEventExtension>>::new());
+226  
+227          // Our init and runtime data
+228          resources.insert(RuntimeState::new())
+229      };
+230  
+231      setup_gamepad(&event_loop);
+232  
+233      let mut elapsed_time: f32 = {
+234          // deltatime since last frame
+235          let loop_state = resources.get::<LoopState>().unwrap();
+236          loop_state.start_time.elapsed()
+237      }
+238      .as_secs_f32();
+239  
+240      let mut delta_time: f32 = 0.0;
+241      let mut accumulator_time: f32 = 0.0;
+242      let mut current_time: f32 = elapsed_time;
+243  
+244      event_loop.run(move |event, _, control_flow| {
+245          *control_flow = ControlFlow::Poll;
+246          match event {
+247              event::Event::NewEvents(cause) => {
+248                  if cause == winit_24::event::StartCause::Init {
+249                      load_schedule.execute(&mut world, &mut resources);
+250                  }
+251              }
+252  
+253              // This is the big boy section of the event loop
+254              // We : dispatch events and clear the queue, query the loops
+255              //      time data and prep the dt data. Loop the dt locked
+256              //      conditionally, and run the fps locked renderer
+257              event::Event::MainEventsCleared => {
+258                  event_schedule.execute(&mut world, &mut resources);
+259                  resources
+260                      .get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>()
+261                      .unwrap()
+262                      .clear();
+263  
+264                  imgui_prepare_schedule.execute(&mut world, &mut resources);
+265  
+266                  let (step_size, elapsed_time) = {
+267                      let mut loop_state = resources.get_mut::<LoopState>().unwrap();
+268                      (
+269                          loop_state.step_size,
+270                          loop_state.start_time.elapsed().as_secs_f32(),
+271                      )
+272                  };
+273                  delta_time = elapsed_time - current_time;
+274  
+275                  {
+276                      let mut loop_state = resources.get_mut::<LoopState>().unwrap();
+277                      loop_state.delta_time = Duration::from_secs_f32(delta_time);
+278                  }
+279                  current_time = elapsed_time;
+280                  if delta_time > 0.02 {
+281                      delta_time = 0.02;
+282                  }
+283                  accumulator_time += delta_time;
+284  
+285                  while accumulator_time - step_size >= step_size {
+286                      accumulator_time -= step_size;
+287  
+288                      // ==== DELTA TIME LOCKED ====
+289                      update_schedule.execute(&mut world, &mut resources);
+290                  }
+291                  // ==== FPS LOCKED ====
+292                  render_schedule.execute(&mut world, &mut resources);
+293              }
+294              // Resizing will queue a request_redraw
+295              event::Event::WindowEvent {
+296                  event: WindowEvent::Resized(size),
+297                  ..
+298              } => {
+299                  let width = size.width;
+300                  let height = size.height;
+301  
+302                  resources
+303                      .get_mut::<render::state::RenderState>()
+304                      .unwrap()
+305                      .resize(width, height);
+306              }
+307              event::Event::DeviceEvent {
+308                  event: winit_24::event::DeviceEvent::Key(keyboard_input),
+309                  ..
+310              } => {
+311                  if keyboard_input.virtual_keycode.is_some() {
+312                      match keyboard_input.virtual_keycode.unwrap() {
+313                          VirtualKeyCode::Escape => {
+314                              if keyboard_input.state == ElementState::Pressed {
+315                                  *control_flow = ControlFlow::Exit;
+316                              } else {
+317                                  //d
+318                              }
+319                          }
+320                          _ => (),
+321                      }
+322                  }
+323              }
+324              event::Event::WindowEvent {
+325                  event: WindowEvent::CloseRequested,
+326                  ..
+327              } => *control_flow = ControlFlow::Exit,
+328              event::Event::RedrawRequested(_) => {
+329                  // Call the render system
+330                  //                imgui_prepare_schedule.execute(&mut world, &mut resources);
+331                  //                render_schedule.execute(&mut world, &mut resources);
+332              }
+333              _ => {}
+334          }
+335  
+336          resources
+337              .get_mut::<Vec<OwnedEvent<OwnedEventExtension>>>()
+338              .unwrap()
+339              .push(event.into());
+340      });
+341  }
+342  
+343  pub fn setup_gamepad(event_loop: &EventLoop<OwnedEventExtension>) {
+344      let event_loop_proxy = event_loop.create_proxy();
+345  
+346      std::thread::spawn(move || {
+347          let mut gilrs = Gilrs::new().unwrap();
+348          // Iterate over all connected gamepads
+349          let mut gamepad: Option<Gamepad> = None;
+350          for (_id, gamepad_) in gilrs.gamepads() {
+351              if gamepad_.name() == "PS4" {
+352                  gamepad = Some(gamepad_);
+353              }
+354              // println!(
+355              //     "{} is {:?} {:?}",
+356              //     gamepad_.name(),
+357              //     gamepad_.power_info(),
+358              //     gamepad_.id()
+359              // );
+360          }
+361          let mut active_gamepad = None;
+362  
+363          loop {
+364              while let Some(GilEvent { id, event, time }) = gilrs.next_event() {
+365                  //println!("{:?} New event from {}: {:?}", time, id, event);
+366                  active_gamepad = Some(id);
+367                  event_loop_proxy
+368                      .send_event(OwnedEventExtension::GamepadEvent {
+369                          gil_event: GilEvent { id, event, time },
+370                      })
+371                      .ok();
+372              }
+373  
+374              // // You can also use cached gamepad state
+375              // if let Some(gamepad) = active_gamepad.map(|id| gilrs.gamepad(id)) {
+376              //     if gamepad.is_pressed(Button::South) {
+377              //         println!("Button South is pressed (XBox - A, PS - X)");
+378              //     }
+379              // }
+380  
+381              std::thread::sleep(std::time::Duration::from_millis(50));
+382          }
+383      });
+384  }
+385  
+ + \ No newline at end of file diff --git a/exportToHTML/mod.rs.html b/exportToHTML/mod.rs.html new file mode 100644 index 0000000..f2bfced --- /dev/null +++ b/exportToHTML/mod.rs.html @@ -0,0 +1,22 @@ + + +mod.rs + + + + + +
+ +mod.rs +
+
1    pub mod extended_winit_imgui_support;
+2    pub mod imgui_support;
+ + \ No newline at end of file diff --git a/exportToHTML/owned_event.rs.html b/exportToHTML/owned_event.rs.html new file mode 100644 index 0000000..f1f8ed5 --- /dev/null +++ b/exportToHTML/owned_event.rs.html @@ -0,0 +1,330 @@ + + +owned_event.rs + + + + + +
+ +owned_event.rs +
+
1    use std::path::PathBuf;
+2    
+3    use gilrs::Event as GilEvent;
+4    use legion::world::SubWorld;
+5    use legion::*;
+6    use winit_24::dpi::{PhysicalPosition, PhysicalSize, LogicalPosition};
+7    use winit_24::event::DeviceEvent::MouseMotion;
+8    use winit_24::event::{AxisId, DeviceEvent, DeviceId, ElementState, Event, KeyboardInput, ModifiersState, MouseButton, MouseScrollDelta, StartCause, Touch, TouchPhase, WindowEvent, VirtualKeyCode};
+9    use winit_24::window::{Theme, WindowId, Window};
+10   
+11   use crate::camera::{Camera, CameraController};
+12   use crate::owned_event::OwnedWindowEvent::MouseWheel;
+13   use std::sync::{Mutex, Arc};
+14   use std::cmp::Ordering;
+15   use imgui::Io;
+16   use crate::imgui_supp::imgui_support::{ImguiContext, ImguiPlatform};
+17   
+18   #[derive(Clone)]
+19   pub enum OwnedUIEvent<T> {
+20       UIEvent(T),
+21   }
+22   
+23   #[derive(Clone)]
+24   pub enum OwnedEventExtension {
+25       /// Custom events here
+26       MouseHeldEvent {},
+27       KeyHeldEvent {},
+28       GamepadEvent {
+29           gil_event: GilEvent,
+30       },
+31   }
+32   
+33   #[derive(Clone, Debug)]
+34   pub enum OwnedEvent<T> {
+35       /// Custom events here
+36       MouseHeldEvent {},
+37       KeyHeldEvent {},
+38       GamepadEvent {
+39           gil_event: GilEvent,
+40       },
+41   
+42       /// Winit events here
+43       NewEvents(StartCause),
+44       WindowEvent {
+45           window_id: WindowId,
+46           event: OwnedWindowEvent,
+47       },
+48       DeviceEvent {
+49           device_id: DeviceId,
+50           event: DeviceEvent,
+51       },
+52       UserEvent(T),
+53       Suspended,
+54       Resumed,
+55       MainEventsCleared,
+56       RedrawRequested(WindowId),
+57       RedrawEventsCleared,
+58       LoopDestroyed,
+59   }
+60   
+61   impl<T> From<Event<'_, T>> for OwnedEvent<T> {
+62       fn from(event: Event<T>) -> Self {
+63           match event {
+64               Event::NewEvents(cause) => OwnedEvent::NewEvents(cause),
+65               Event::WindowEvent {
+66                   window_id: window_id,
+67                   event: event,
+68               } => OwnedEvent::WindowEvent {
+69                   window_id: window_id,
+70                   event: match event {
+71                       WindowEvent::AxisMotion {
+72                           device_id,
+73                           axis,
+74                           value,
+75                       } => OwnedWindowEvent::AxisMotion {
+76                           device_id,
+77                           axis,
+78                           value,
+79                       },
+80                       WindowEvent::Resized(physical_size) => OwnedWindowEvent::Resized(physical_size),
+81                       WindowEvent::Moved(physical_position) => {
+82                           OwnedWindowEvent::Moved(physical_position)
+83                       }
+84                       WindowEvent::CloseRequested => OwnedWindowEvent::CloseRequested,
+85                       WindowEvent::Destroyed => OwnedWindowEvent::Destroyed,
+86                       WindowEvent::DroppedFile(path_buf) => OwnedWindowEvent::DroppedFile(path_buf),
+87                       WindowEvent::HoveredFile(path_buf) => OwnedWindowEvent::HoveredFile(path_buf),
+88                       WindowEvent::HoveredFileCancelled => OwnedWindowEvent::HoveredFileCancelled,
+89                       WindowEvent::ReceivedCharacter(char) => {
+90                           OwnedWindowEvent::ReceivedCharacter(char)
+91                       }
+92                       WindowEvent::Focused(bool) => OwnedWindowEvent::Focused(bool),
+93                       WindowEvent::KeyboardInput {
+94                           device_id: device_id,
+95                           input: input,
+96                           is_synthetic: is_synthetic,
+97                       } => OwnedWindowEvent::KeyboardInput {
+98                           device_id,
+99                           input,
+100                          is_synthetic,
+101                      },
+102                      WindowEvent::ModifiersChanged(modifiers_state) => {
+103                          OwnedWindowEvent::ModifiersChanged(modifiers_state)
+104                      }
+105                      WindowEvent::CursorMoved {
+106                          device_id: device_id,
+107                          position: position,
+108                          modifiers: modifiers,
+109                      } => OwnedWindowEvent::CursorMoved {
+110                          device_id,
+111                          position,
+112                          modifiers,
+113                      },
+114                      WindowEvent::CursorEntered {
+115                          device_id: device_id,
+116                      } => OwnedWindowEvent::CursorEntered { device_id },
+117                      WindowEvent::CursorLeft {
+118                          device_id: device_id,
+119                      } => OwnedWindowEvent::CursorLeft { device_id },
+120                      WindowEvent::MouseWheel {
+121                          device_id: device_id,
+122                          delta: delta,
+123                          phase: phase,
+124                          modifiers: modifiers,
+125                      } => OwnedWindowEvent::MouseWheel {
+126                          device_id,
+127                          delta,
+128                          phase,
+129                          modifiers,
+130                      },
+131                      WindowEvent::MouseInput {
+132                          device_id: device_id,
+133                          state: state,
+134                          button: button,
+135                          modifiers: modifiers,
+136                      } => OwnedWindowEvent::MouseInput {
+137                          device_id,
+138                          state,
+139                          button,
+140                          modifiers,
+141                      },
+142                      WindowEvent::TouchpadPressure {
+143                          device_id: device_id,
+144                          pressure: pressure,
+145                          stage: stage,
+146                      } => OwnedWindowEvent::TouchpadPressure {
+147                          device_id,
+148                          pressure,
+149                          stage,
+150                      },
+151                      WindowEvent::Touch(touch) => OwnedWindowEvent::Touch(touch),
+152                      WindowEvent::ScaleFactorChanged {
+153                          scale_factor: scale_factor,
+154                          new_inner_size: new_inner_size,
+155                      } => OwnedWindowEvent::ScaleFactorChanged {
+156                          scale_factor,
+157                          new_inner_size: PhysicalSize {
+158                              width: new_inner_size.width,
+159                              height: new_inner_size.height,
+160                          },
+161                      },
+162                      WindowEvent::ThemeChanged(theme) => OwnedWindowEvent::ThemeChanged(theme),
+163                  },
+164              },
+165              Event::DeviceEvent {
+166                  device_id: device_id,
+167                  event: event,
+168              } => OwnedEvent::DeviceEvent { device_id, event },
+169              Event::UserEvent(user_event) => OwnedEvent::UserEvent(user_event),
+170              Event::Suspended => OwnedEvent::Suspended,
+171              Event::Resumed => OwnedEvent::Resumed,
+172              Event::MainEventsCleared => OwnedEvent::MainEventsCleared,
+173              Event::RedrawRequested(window_id) => OwnedEvent::RedrawRequested(window_id),
+174              Event::RedrawEventsCleared => OwnedEvent::RedrawEventsCleared,
+175              Event::LoopDestroyed => OwnedEvent::LoopDestroyed,
+176          }
+177      }
+178  }
+179  
+180  #[derive(Debug, PartialEq, Clone)]
+181  pub enum OwnedWindowEvent {
+182      Resized(PhysicalSize<u32>),
+183      Moved(PhysicalPosition<i32>),
+184      CloseRequested,
+185      Destroyed,
+186      DroppedFile(PathBuf),
+187      HoveredFile(PathBuf),
+188      HoveredFileCancelled,
+189      ReceivedCharacter(char),
+190      Focused(bool),
+191      KeyboardInput {
+192          device_id: DeviceId,
+193          input: KeyboardInput,
+194          is_synthetic: bool,
+195      },
+196      ModifiersChanged(ModifiersState),
+197      CursorMoved {
+198          device_id: DeviceId,
+199          position: PhysicalPosition<f64>,
+200          #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
+201          modifiers: ModifiersState,
+202      },
+203      CursorEntered {
+204          device_id: DeviceId,
+205      },
+206      CursorLeft {
+207          device_id: DeviceId,
+208      },
+209      MouseWheel {
+210          device_id: DeviceId,
+211          delta: MouseScrollDelta,
+212          phase: TouchPhase,
+213          #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
+214          modifiers: ModifiersState,
+215      },
+216      MouseInput {
+217          device_id: DeviceId,
+218          state: ElementState,
+219          button: MouseButton,
+220          #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
+221          modifiers: ModifiersState,
+222      },
+223      TouchpadPressure {
+224          device_id: DeviceId,
+225          pressure: f32,
+226          stage: i64,
+227      },
+228      AxisMotion {
+229          device_id: DeviceId,
+230          axis: AxisId,
+231          value: f64,
+232      },
+233      Touch(Touch),
+234      ScaleFactorChanged {
+235          scale_factor: f64,
+236          new_inner_size: PhysicalSize<u32>,
+237      },
+238      ThemeChanged(Theme),
+239  }
+240  
+241  
+242  /// Because I am a glutton for punishment I am going to just do a mono-event-dispatch-magoooo
+243  #[system]
+244  #[write_component(Camera)]
+245  #[write_component(CameraController)]
+246  pub fn event_dispatch(
+247      world: &mut SubWorld,
+248      #[resource] event_stack: &mut Vec<OwnedEvent<OwnedEventExtension>>,
+249      #[resource] imgui_context: &mut Arc<Mutex<ImguiContext>>,
+250      #[resource] imgui_platform: &mut Arc<Mutex<ImguiPlatform>>,
+251      #[resource] winit_window: &mut Window,
+252  ) {
+253      use winit_24::event::Event::DeviceEvent;
+254  
+255      for event in event_stack {
+256  
+257          match event {
+258              OwnedEvent::DeviceEvent {
+259                  event: winit_24::event::DeviceEvent::MouseMotion { delta },
+260                  ..
+261              } => {
+262                  let mut query = <(&mut CameraController)>::query();
+263                  for (camera_controller) in query.iter_mut(world) {
+264                      camera_controller.process_mouse(delta.0, delta.1);
+265                  }
+266  
+267              },
+268              OwnedEvent::DeviceEvent {
+269                  event: winit_24::event::DeviceEvent::Key(keyboard_input),
+270                  ..
+271              } => {
+272                  let mut query = <(&mut CameraController)>::query();
+273                  for (camera_controller) in query.iter_mut(world) {
+274                      camera_controller.process_keyboard(
+275                          keyboard_input.virtual_keycode.unwrap(),
+276                          keyboard_input.state,
+277                      );
+278                  }
+279  
+280                  match keyboard_input.virtual_keycode.unwrap() {
+281                      VirtualKeyCode::R => {
+282                          if keyboard_input.state == ElementState::Pressed {
+283  
+284  
+285                              //winit_window.set_cursor_grab(true);
+286                          }
+287                      }
+288                      VirtualKeyCode::Escape => {
+289                          if keyboard_input.state == ElementState::Pressed {
+290                              //winit_window.set_cursor_grab(false);
+291                          }
+292                      }
+293                      _ => ()
+294                  }
+295              }
+296              _ => {}
+297          }
+298  
+299          let mut imgui_context = &mut imgui_context.lock().unwrap().context;
+300          let mut imgui_platform = &mut imgui_platform.lock().unwrap().platform;
+301  
+302          imgui_platform.handle_event(imgui_context.io_mut(), &winit_window, &event);
+303      }
+304  }
+305  
+ + \ No newline at end of file diff --git a/exportToHTML/state.rs.html b/exportToHTML/state.rs.html new file mode 100644 index 0000000..a34726b --- /dev/null +++ b/exportToHTML/state.rs.html @@ -0,0 +1,138 @@ + + +state.rs + + + + + +
+ +state.rs +
+
1    use std::collections::HashMap;
+2    use std::fs;
+3    use std::path::PathBuf;
+4    use std::time::Instant;
+5    use serde_derive::Deserialize;
+6    
+7    use cgmath::{Euler, Quaternion, Deg};
+8    use legion::world::SubWorld;
+9    use legion::IntoQuery;
+10   use legion::*;
+11   use nalgebra::Quaternion as naQuaternion;
+12   use rapier3d::dynamics::{IntegrationParameters, JointSet, RigidBodySet};
+13   use rapier3d::geometry::{BroadPhase, ColliderSet, NarrowPhase};
+14   use rapier3d::pipeline::PhysicsPipeline;
+15   use crate::camera::{Camera, CameraController};
+16   use crate::components::{Collider, LoopState, Mesh, Physics, Position};
+17   use crate::geometry::{load_obj, RawMesh};
+18   use std::io::Read;
+19   
+20   
+21   
+22   #[derive(Deserialize, Clone)]
+23   pub struct TomlBallPhysicsBodyDescription {
+24       pub radius: String
+25   }
+26   
+27   #[derive(Deserialize, Clone)]
+28   pub struct TomlCuboidPhysicsBodyDescription {
+29       pub x: f32,
+30       pub y: f32,
+31       pub z: f32,
+32   }
+33   
+34   #[derive(Deserialize, Clone)]
+35   pub struct TomlPhysicsDescription {
+36       pub body_status: String,
+37       pub ball: Option<TomlBallPhysicsBodyDescription>,
+38       pub cuboid: Option<TomlCuboidPhysicsBodyDescription>,
+39   }
+40   
+41   #[derive(Deserialize, Clone)]
+42   pub struct TomlRotationDescription {
+43       pub x: f32,
+44       pub y: f32,
+45       pub z: f32,
+46   }
+47   
+48   #[derive(Deserialize, Clone)]
+49   pub struct TomlPositionDescription {
+50       pub x: f32,
+51       pub y: f32,
+52       pub z: f32,
+53       pub rot: Option<TomlRotationDescription>,
+54   }
+55   
+56   #[derive(Deserialize, Clone)]
+57   pub struct TomlEntityDescription {
+58       pub name: String,
+59       #[serde(rename = "type")]
+60       pub type_name: String,
+61       pub mesh: Option<String>,
+62       pub position: Option<TomlPositionDescription>,
+63       pub physics: Option<TomlPhysicsDescription>,
+64   }
+65   
+66   #[derive(Deserialize, Clone)]
+67   pub struct TomlEntityContainer {
+68       pub entities: Vec<TomlEntityDescription>,
+69   }
+70   
+71   pub struct RuntimeState {
+72       config_db: TomlEntityContainer,
+73       mesh_cache: HashMap<String, RawMesh>,
+74   }
+75   
+76   impl RuntimeState {
+77       pub fn new() -> RuntimeState {
+78           // TODO: Hook this file to the gui
+79           let mut file = fs::File::open("./conf/entity_spawns.toml").unwrap();
+80           let mut content = String::new();
+81           file.read_to_string(&mut content).unwrap();
+82   
+83           // TODO: gracefully fail
+84           let mut settings : TomlEntityContainer = toml::from_str(content.as_str()).unwrap();
+85   
+86           RuntimeState {
+87               config_db: settings,
+88               mesh_cache: Default::default(),
+89           }
+90       }
+91   
+92       pub fn get_mesh(&mut self, mesh: &str) -> Option<&RawMesh> {
+93           self.mesh_cache.get(mesh)
+94       }
+95   
+96       pub fn get_entities(&mut self) -> Vec<TomlEntityDescription> {
+97           self.config_db.entities.clone()
+98       }
+99   
+100      pub fn preload_meshes(&mut self, resources_path: PathBuf) {
+101          log::info!("Preloading meshes...");
+102  
+103          let paths = fs::read_dir(resources_path).unwrap();
+104          for file in paths {
+105              let file = file.unwrap();
+106              let filepath = file.path().clone();
+107              let filename = String::from(file.file_name().to_str().unwrap());
+108  
+109              if filename.ends_with(".obj") {
+110                  let mesh = load_obj(filepath.to_str().unwrap()).unwrap();
+111                  self.mesh_cache.insert(filename, mesh);
+112              }
+113          }
+114      }
+115  }
+116  
+ + \ No newline at end of file diff --git a/exportToHTML/system.rs.html b/exportToHTML/system.rs.html new file mode 100644 index 0000000..3a08027 --- /dev/null +++ b/exportToHTML/system.rs.html @@ -0,0 +1,356 @@ + + +system.rs + + + + + +
+ +system.rs +
+
1    use std::f32::consts::PI;
+2    use std::path::PathBuf;
+3    use std::time::Instant;
+4    
+5    use cgmath::{Deg, Euler, Point3, Quaternion, Rad};
+6    use imgui::*;
+7    use imgui::{Condition, FontSource, Ui};
+8    use legion::systems::CommandBuffer;
+9    use legion::world::SubWorld;
+10   use legion::IntoQuery;
+11   use legion::*;
+12   use nalgebra::Quaternion as naQuaternion;
+13   use rapier3d::dynamics::{
+14       IntegrationParameters, JointSet, MassProperties, RigidBodyBuilder, RigidBodySet,
+15   };
+16   use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase};
+17   use rapier3d::na::{Isometry3, Vector, Vector3};
+18   use rapier3d::pipeline::{ChannelEventCollector, PhysicsPipeline};
+19   
+20   use crate::camera::{Camera, CameraController};
+21   use crate::components::{Collider, ImguiWindow, LoopState, Mesh, Physics, Position};
+22   use crate::geometry;
+23   use crate::physics::state::PhysicsState;
+24   use crate::render::state::RenderState;
+25   use crate::render::system::{ImguiGenericOutputLine, ImguiPerformanceProfilerLine};
+26   use crate::runtime::state::RuntimeState;
+27   use crate::geometry::RawMesh;
+28   
+29   pub fn quad_color(color: [f32; 4]) -> [[f32; 4]; 4] {
+30       [color, color, color, color]
+31   }
+32   
+33   #[system]
+34   #[write_component(Mesh)]
+35   pub fn runtime_load(
+36       cmd: &mut CommandBuffer,
+37       world: &mut SubWorld,
+38       #[resource] runtime_state: &mut RuntimeState,
+39   ) {
+40       runtime_state.preload_meshes(PathBuf::from("./resources"));
+41   
+42       let entity: Entity = cmd.push((ImguiWindow {
+43           // a window that does everything for the performance profiler
+44           window: || {
+45               imgui::Window::new(im_str!("Performance Profiler"))
+46                   .size([400.0, 200.0], Condition::FirstUseEver)
+47                   .position([10.0, 10.0], Condition::FirstUseEver)
+48           },
+49           func: |ui: &Ui, a: Vec<&ImguiPerformanceProfilerLine>| {
+50               // ui.text(im_str!("Performance Graph"));
+51   
+52               let draw_list = ui.get_window_draw_list();
+53               let top_left = ui.cursor_screen_pos();
+54               let region_size = ui.content_region_avail();
+55   
+56               let region_size = [region_size[0] * 0.80, region_size[1]];
+57   
+58               // Fill rect
+59               let qcolor = quad_color([0.5, 0.5, 1.0, 0.1]);
+60               draw_list.add_rect_filled_multicolor(
+61                   top_left,
+62                   [top_left[0] + (region_size[0]), top_left[1] + region_size[1]],
+63                   qcolor[0],
+64                   qcolor[1],
+65                   qcolor[2],
+66                   qcolor[3],
+67               );
+68   
+69               for profiler_line in a {
+70                   let x_scale = (region_size[0]) / 400.0;
+71                   let y_scale = region_size[1] / profiler_line.scale_max;
+72                   profiler_line
+73                       .iter_data_from_head()
+74                       .fold((0, 0.0f32), |accum, &fps_val| {
+75                           let x1 = accum.0 as f32 * x_scale + top_left[0];
+76                           let y1 = top_left[1] + region_size[1] - accum.1 * y_scale;
+77                           let x2 = (accum.0 as f32 + 1.0) * x_scale + top_left[0];
+78                           let y2 = top_left[1] + region_size[1] - fps_val * y_scale;
+79                           let p1 = [x1, y1];
+80                           let p2 = [x2, y2];
+81                           draw_list
+82                               .add_line(p1, p2, [1.0, 1.0, 0.0, 0.8])
+83                               .thickness(1.0)
+84                               .build();
+85                           (accum.0 + 1, fps_val)
+86                       });
+87   
+88                   let text_x = (region_size[0] + top_left[0]);
+89                   let text_y = top_left[1] + region_size[1]
+90                       - profiler_line.current_average_label().0 * y_scale;
+91                   draw_list.add_text(
+92                       [text_x, text_y],
+93                       [1.0, 1.0, 0.0, 1.0],
+94                       format!(
+95                           "{} {:.0}",
+96                           profiler_line.current_average_label().1,
+97                           1.0 / profiler_line.current_average_label().0
+98                       ),
+99                   );
+100              }
+101          },
+102      },));
+103      let entity: Entity = cmd.push((ImguiPerformanceProfilerLine::new("RenderFPS".to_string()),));
+104  
+105      let entity: Entity = cmd.push((ImguiWindow {
+106          // a window that does everything for the performance profiler
+107          window: || {
+108              imgui::Window::new(im_str!("Generic Output"))
+109                  .size([400.0, 500.0], Condition::FirstUseEver)
+110                  .position([50.0, 250.0], Condition::FirstUseEver)
+111          },
+112          func: |ui: &Ui, a: Vec<&ImguiGenericOutputLine>| {
+113              for label in a {
+114                  ui.text(im_str!("{}", label.label));
+115              }
+116          },
+117      },));
+118  }
+119  
+120  #[system]
+121  #[write_component(Mesh)]
+122  pub fn runtime_spawn(
+123      cmd: &mut CommandBuffer,
+124      world: &mut SubWorld,
+125      #[resource] runtime_state: &mut RuntimeState,
+126      #[resource] renderer: &mut RenderState,
+127  ) {
+128      for entity in &runtime_state.get_entities() {
+129          match entity.type_name.as_ref() {
+130              "Sprite" => {
+131  
+132  
+133  
+134                  let mesh_name = entity.mesh.clone().unwrap();
+135                  let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
+136                      None => {
+137                          log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
+138                          continue;
+139                      }
+140                      Some(mesh) => mesh,
+141                  };
+142  
+143                  let position = Position::from(entity.position.clone());
+144  
+145                  let mut static_body = RigidBodyBuilder::new_static()
+146                      .position(Isometry3::new(
+147                          Vector3::new(position.x, position.y, position.z),
+148                          Vector::y(),
+149                      ))
+150                      .build();
+151  
+152                  let mesh_collider = ColliderBuilder::trimesh(
+153                      raw_mesh.vertices.iter().map(|v| v.position()).collect(),
+154                      raw_mesh.indices.clone(),
+155                  )
+156                      .build();
+157  
+158                  let gpu_mesh_buffer = renderer
+159                      .upload_mesh_to_buffer(
+160                          raw_mesh,
+161                          Some(wgpu::Color {
+162                              r: 1.0,
+163                              g: 0.7,
+164                              b: 0.3,
+165                              a: 1.0,
+166                          }),
+167                      )
+168                      .unwrap();
+169  
+170                  let entity: Entity = cmd.push((
+171                      position,
+172                      gpu_mesh_buffer,
+173                      Physics {
+174                          rigid_body: static_body,
+175                          rigid_body_handle: None,
+176                      },
+177                      Collider {
+178                          collider: mesh_collider,
+179                          collider_handle: None,
+180                      },
+181                  ));
+182              }
+183              "PhysicsEntity" => {
+184                  let mesh_name = entity.mesh.as_ref().unwrap();
+185                  let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
+186                      None => {
+187                          log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
+188                          continue;
+189                      }
+190                      Some(mesh) => mesh,
+191                  };
+192  
+193                  let collider = ColliderBuilder::trimesh(
+194                      raw_mesh.vertices.iter().map(|v| v.position()).collect(),
+195                      raw_mesh.indices.clone(),
+196                  )
+197                  .build();
+198  
+199                  let collider = ColliderBuilder::capsule_y(2.0, 1.0).build();
+200  
+201                  let gpu_mesh_buffer = renderer
+202                      .upload_mesh_to_buffer(
+203                          raw_mesh,
+204                          Some(wgpu::Color {
+205                              r: 1.0,
+206                              g: 0.7,
+207                              b: 0.3,
+208                              a: 1.0,
+209                          }),
+210                      )
+211                      .unwrap();
+212  
+213                  let position = Position::from(entity.position.clone());
+214  
+215                  let mut dynamic_body = RigidBodyBuilder::new_dynamic()
+216                      .can_sleep(false)
+217                      .mass(100.0)
+218                      .translation(position.x, position.y, position.z)
+219                      .build();
+220  
+221                  let entity: Entity = cmd.push((
+222                      position,
+223                      gpu_mesh_buffer,
+224                      Physics {
+225                          rigid_body: dynamic_body,
+226                          rigid_body_handle: None,
+227                      },
+228                      Collider {
+229                          collider: collider,
+230                          collider_handle: None,
+231                      },
+232                      ImguiGenericOutputLine::new("wahoo! from a physics entity".to_string()),
+233                  ));
+234              }
+235              "StaticMesh" => {
+236                  let mesh_name = entity.mesh.clone().unwrap();
+237                  let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
+238                      None => {
+239                          log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
+240                          continue;
+241                      }
+242                      Some(mesh) => mesh,
+243                  };
+244  
+245                  let position = Position::from(entity.position.clone());
+246  
+247                  let mut static_body = RigidBodyBuilder::new_static()
+248                      .position(Isometry3::new(
+249                          Vector3::new(position.x, position.y, position.z),
+250                          Vector::y(),
+251                      ))
+252                      .build();
+253  
+254                  let mesh_collider = ColliderBuilder::trimesh(
+255                      raw_mesh.vertices.iter().map(|v| v.position()).collect(),
+256                      raw_mesh.indices.clone(),
+257                  )
+258                  .build();
+259  
+260                  let gpu_mesh_buffer = renderer
+261                      .upload_mesh_to_buffer(
+262                          raw_mesh,
+263                          Some(wgpu::Color {
+264                              r: 1.0,
+265                              g: 0.7,
+266                              b: 0.3,
+267                              a: 1.0,
+268                          }),
+269                      )
+270                      .unwrap();
+271  
+272                  let entity: Entity = cmd.push((
+273                      position,
+274                      gpu_mesh_buffer,
+275                      Physics {
+276                          rigid_body: static_body,
+277                          rigid_body_handle: None,
+278                      },
+279                      Collider {
+280                          collider: mesh_collider,
+281                          collider_handle: None,
+282                      },
+283                  ));
+284              }
+285              "Camera" => {
+286                  let position = Position::from(entity.position.clone());
+287                  let entity: Entity = cmd.push((
+288                      Camera {
+289                          position: cgmath::Point3 {
+290                              x: position.x,
+291                              y: position.y,
+292                              z: position.z,
+293                          },
+294                          yaw: Rad(PI / 2.0),
+295                          pitch: Rad(PI / 2.0 + 25.0),
+296                      },
+297                      CameraController::new(5.0, 1.0),
+298                      ImguiGenericOutputLine::new("wahoo! from a camera".to_string()),
+299                  ));
+300              }
+301              "Light" => {
+302                  let mesh_name = entity.mesh.clone().unwrap();
+303                  let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
+304                      None => {
+305                          log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
+306                          continue;
+307                      }
+308                      Some(mesh) => mesh,
+309                  };
+310  
+311                  let position = Position::from(entity.position.clone());
+312  
+313                  let gpu_mesh_buffer = renderer
+314                      .upload_mesh_to_buffer(
+315                          raw_mesh,
+316                          Some(wgpu::Color {
+317                              r: 1.0,
+318                              g: 0.7,
+319                              b: 0.3,
+320                              a: 1.0,
+321                          }),
+322                      )
+323                      .unwrap();
+324  
+325                  let light_entity: Entity =
+326                      cmd.push((position, gpu_mesh_buffer, renderer.create_light()));
+327              }
+328  
+329              _ => {}
+330          }
+331      }
+332  }
+333  
+ + \ No newline at end of file diff --git a/src/components.rs b/src/components.rs index 233982c..97ed73d 100644 --- a/src/components.rs +++ b/src/components.rs @@ -10,8 +10,9 @@ use wgpu::{BindGroup, Buffer, TextureView}; use crate::runtime::state::{TomlPositionDescription, TomlRotationDescription}; use imgui::Ui; -// a component is any type that is 'static, sized, send and sync - +/// a component is any type that is 'static, sized, send and sync +/// ImguiWindow contains a single handle and lifetime to an Imgui window, along with +/// a function which takes a UI, as well as a vector of a user defined type T pub struct ImguiWindow<'a, T> { pub window: fn() -> imgui::Window<'a>, pub func: fn(&Ui, Vec<&T>), diff --git a/src/geometry.rs b/src/geometry.rs index 8af1efa..29cb71a 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -35,6 +35,8 @@ pub struct RawMesh { } + + /// We use meshes in a few different places. To keep things simple, we return /// the most basic, direct-to-memory version. If something fancy needs to be done /// with it, the fancy stays there diff --git a/src/main.rs b/src/main.rs index 1cbb64a..2c46a6d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -110,13 +110,28 @@ Todo: I need to figure out the way that I want to do 2d graphics in a 3d engine... I suppose I will need sprites. And those are just 2 polygons which are textured + */ - */ + +/** + +Notes: + +(Im)GUI, +* I have to hold onto an ImGUI window and it's lifetime +* I have to execute a bunch of function calls to build + the immediate mode UI each and every frame + +It looks like my solution was to have an entity describing +the window + + +*/ //log::info!(""); -// ImGUI works on more or less an unsafe global state. which is MegaLame +/// ImGUI works on more or less an unsafe global state. which is MegaLame static mut CURRENT_UI: Option> = None; pub unsafe fn current_ui<'a>() -> Option<&'a imgui::Ui<'a>> { CURRENT_UI.as_ref() @@ -143,7 +158,7 @@ fn main() { let mut render_schedule = Schedule::builder() .add_system(render::system::render_imgui_system()) - .add_system(render::system::render_test_system()) + //.add_system(render::system::render_test_system()) .add_system(render::system::render_performance_flag_system()) .build(); diff --git a/src/physics/state.rs b/src/physics/state.rs index a41cf44..f90b483 100644 --- a/src/physics/state.rs +++ b/src/physics/state.rs @@ -12,15 +12,18 @@ use rapier3d::pipeline::PhysicsPipeline; use crate::camera::{Camera, CameraController}; use crate::components::{Collider, LoopState, Mesh, Physics, Position}; use imgui::FontSource; +use rapier3d::prelude::{IslandManager, CCDSolver}; pub struct PhysicsState { pub(in crate::physics) gravity: rapier3d::math::Vector, pub(in crate::physics) integration_parameters: IntegrationParameters, + pub(in crate::physics) island_manager: IslandManager, pub(in crate::physics) broad_phase: BroadPhase, pub(in crate::physics) narrow_phase: NarrowPhase, pub(in crate::physics) bodies: RigidBodySet, pub(in crate::physics) colliders: ColliderSet, pub(in crate::physics) joints: JointSet, + pub(in crate::physics) ccd_solver: CCDSolver, } impl PhysicsState { @@ -30,11 +33,13 @@ impl PhysicsState { PhysicsState { gravity, integration_parameters: IntegrationParameters::default(), + island_manager: IslandManager::new(), broad_phase: BroadPhase::new(), narrow_phase: NarrowPhase::new(), bodies: RigidBodySet::new(), colliders: ColliderSet::new(), joints: JointSet::new(), + ccd_solver: CCDSolver::new(), }, ) } diff --git a/src/physics/system.rs b/src/physics/system.rs index 6a86818..babf2c1 100644 --- a/src/physics/system.rs +++ b/src/physics/system.rs @@ -40,8 +40,8 @@ pub fn run_physics( if collider.collider_handle == None { let handle = physics_state.colliders.insert( collider.collider.clone(), - rigid_body_handle, - &mut physics_state.bodies, + //rigid_body_handle, + //&mut physics_state.bodies, ); collider.collider_handle = Some(handle); } @@ -56,13 +56,14 @@ pub fn run_physics( physics_pipeline.step( &physics_state.gravity, &physics_state.integration_parameters, + &mut physics_state.island_manager, &mut physics_state.broad_phase, &mut physics_state.narrow_phase, &mut physics_state.bodies, &mut physics_state.colliders, &mut physics_state.joints, - None, - None, + &mut physics_state.ccd_solver, + &(), &event_handler, ); diff --git a/src/render/state.rs b/src/render/state.rs index 73db5ec..916893a 100644 --- a/src/render/state.rs +++ b/src/render/state.rs @@ -16,7 +16,6 @@ use imgui::*; use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; use legion::world::SubWorld; use legion::*; -use rapier3d::parry::motion::RigidMotionComposition; use wgpu::util::DeviceExt; use wgpu::{BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, Device, FragmentState, Instance, Queue, Surface, SwapChain, SwapChainDescriptor, SwapChainFrame, TextureView, VertexState, CommandEncoder}; use winit_24::dpi::PhysicalSize; diff --git a/src/render/system.rs b/src/render/system.rs index 3abc569..438803d 100644 --- a/src/render/system.rs +++ b/src/render/system.rs @@ -18,7 +18,6 @@ use imgui::*; use imgui_wgpu::{Renderer as ImguiRenderer, RendererConfig as ImguiRendererConfig}; use legion::world::SubWorld; use legion::*; -use rapier3d::parry::motion::RigidMotionComposition; use wgpu::util::DeviceExt; use wgpu::{ BackendBit, BindGroup, BindGroupLayout, Buffer, BufferBindingType, CommandEncoder, Device, @@ -39,6 +38,7 @@ use crate::render::{ insert_debug_marker_checked, pop_debug_group_checked, push_debug_group_checked, EntityUniforms, }; + #[system] #[write_component(Camera)] pub fn imgui_prepare( @@ -80,6 +80,7 @@ fn run_imgui_render_step(world: &mut SubWorld, .build(&ui, || (window_func.unwrap())(ui, v)); } } + /// Go through each "global" window-data component and render it's data #[system] #[write_component(ImguiWindow)] @@ -87,13 +88,33 @@ fn run_imgui_render_step(world: &mut SubWorld, #[write_component(ImguiWindow)] #[write_component(ImguiGenericOutputLine)] pub fn render_imgui(world: &mut SubWorld, #[resource] loop_state: &mut LoopState) { + + // This is a global that we have to grab for imgui let ui = unsafe { crate::current_ui().unwrap() }; - // Pull out the window associated with this type, and render each of the components in the sytem + // Pull out the window associated with this type, and render each of the components in the system run_imgui_render_step::(world, &ui); run_imgui_render_step::(world, &ui); } + +/** + +Oh boy, now I need to remember this interface that I wrote... + +The (Im)GUI System +* Each window is a static type, like ImguiGenericOutputLine, and ImguiPerformanceProfilerLine. +* Each window is also an entity that we do a query on + + + + +*/ + + + + + // This would be the shared state for all imgui generic output things pub struct ImguiGenericOutputLine { pub label: String, @@ -114,6 +135,7 @@ pub struct ImguiPerformanceProfilerLine { pub scale_max: f32, } +/// Adding samples, iterating, and calculating profiler lines impl ImguiPerformanceProfilerLine { fn add_sample(&mut self, sample: f32) { self.list_of_fps[self.index] = sample; @@ -160,6 +182,7 @@ impl ImguiPerformanceProfilerLine { } } +/// Take the current delta time from the loop state and add it to the profile line #[system] #[write_component(ImguiPerformanceProfilerLine)] pub fn render_performance_flag(world: &mut SubWorld, #[resource] loop_state: &mut LoopState) { @@ -178,7 +201,7 @@ pub fn render_performance_flag(world: &mut SubWorld, #[resource] loop_state: &mu #[write_component(Point3)] #[write_component(Mesh)] #[write_component(DirectionalLight)] -pub fn render_test( +pub fn render_function( world: &mut SubWorld, #[resource] loop_state: &mut LoopState, #[resource] renderer: &mut RenderState, @@ -334,6 +357,7 @@ pub fn render_test( pass.draw_indexed(0..mesh.index_count as u32, 0, 0..1); } } + pop_debug_group_checked(&mut encoder); pop_debug_group_checked(&mut encoder); diff --git a/src/runtime/state.rs b/src/runtime/state.rs index c5c3adb..7e95acb 100644 --- a/src/runtime/state.rs +++ b/src/runtime/state.rs @@ -16,7 +16,7 @@ use crate::camera::{Camera, CameraController}; use crate::components::{Collider, LoopState, Mesh, Physics, Position}; use crate::geometry::{load_obj, RawMesh}; use std::io::Read; - +use imgui_wgpu::Texture; #[derive(Deserialize, Clone)] @@ -71,8 +71,28 @@ pub struct TomlEntityContainer { pub struct RuntimeState { config_db: TomlEntityContainer, mesh_cache: HashMap, + texture_cache: HashMap, +} + +pub struct Model { + pub meshes: Vec, + pub materials: Vec, +} + +pub struct Material { + pub name: String, + pub diffuse_texture: Texture, } +// pub struct Mesh { +// pub name: String, +// pub vertex_buffer: wgpu::Buffer, +// pub index_buffer: wgpu::Buffer, +// pub num_elements: u32, +// pub material: usize, +// } + + impl RuntimeState { pub fn new() -> RuntimeState { // TODO: Hook this file to the gui @@ -86,6 +106,7 @@ impl RuntimeState { RuntimeState { config_db: settings, mesh_cache: Default::default(), + texture_cache: Default::default(), } } @@ -112,6 +133,6 @@ impl RuntimeState { } } - panic!("nah"); + //panic!("nah"); } } diff --git a/src/runtime/system.rs b/src/runtime/system.rs index c34e766..4486cb1 100644 --- a/src/runtime/system.rs +++ b/src/runtime/system.rs @@ -219,7 +219,7 @@ pub fn runtime_spawn( let mut dynamic_body = RigidBodyBuilder::new_dynamic() .can_sleep(false) .mass(100.0) - .translation(position.x, position.y, position.z) + .translation(Vector3::new(position.x, position.y, position.z)) .build(); let entity: Entity = cmd.push((