diff --git a/Cargo.lock b/Cargo.lock index 12bd831..6aed3f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,6 +282,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block-sys" version = "0.2.1" @@ -452,7 +461,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -550,6 +559,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.4.2" @@ -590,12 +608,32 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "cursor-icon" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dirs" version = "5.0.1" @@ -729,6 +767,12 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + [[package]] name = "fdeflate" version = "0.3.4" @@ -840,6 +884,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "geo" version = "0.28.0" @@ -1353,7 +1407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -1821,7 +1875,7 @@ dependencies = [ "libc", "redox_syscall 0.5.1", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2015,8 +2069,10 @@ dependencies = [ "pathfinder_geometry", "raw-window-handle 0.5.2", "regex", + "rust-embed", "serde", "serde_json", + "tempfile", "thiserror", "tinyfiledialogs", "toml", @@ -2234,6 +2290,40 @@ dependencies = [ "smallvec", ] +[[package]] +name = "rust-embed" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.66", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc_version" version = "0.4.0" @@ -2373,6 +2463,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "simba" version = "0.8.1" @@ -2557,6 +2658,19 @@ version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "thiserror" version = "1.0.61" @@ -3051,7 +3165,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3078,7 +3192,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -3113,18 +3236,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3141,9 +3264,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3159,9 +3282,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3177,15 +3300,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -3201,9 +3324,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3219,9 +3342,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3237,9 +3360,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3255,9 +3378,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" diff --git a/Cargo.toml b/Cargo.toml index dd3a379..14ac301 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,8 @@ glsl = "7.0.0" glsl-quasiquote = "7.0.0" toml = "0.8.19" femtovg = "0.9.2" +rust-embed = "8.5.0" +tempfile = "3.12.0" [features] default = ["sdf_font"] diff --git a/src/font_manager/mod.rs b/src/font_manager/mod.rs index 33a58a0..0c42cb5 100644 --- a/src/font_manager/mod.rs +++ b/src/font_manager/mod.rs @@ -1,4 +1,4 @@ -use crate::errors::*; +use crate::{errors::*, Asset}; use dirs::font_dir; use freetype::face::LoadFlag; use freetype::{Face, GlyphMetrics, Library}; @@ -7,26 +7,46 @@ use image::GrayImage; use image::ImageBuffer; use log::*; use std::collections::HashMap; +use std::io::Write; +use std::path::PathBuf; +use std::{env, fs}; pub struct FontManager { library: Library, fonts: HashMap, } +use tempfile::NamedTempFile; impl FontManager { pub fn new() -> Result { // let source = fk::source::SystemSource::new(); + let library = Library::init().map_err(|e| Error::InitError(e.into()))?; - let root_path = font_dir().map_or_else( - || { - error!("Font dir not found"); - Err(Error::InitError(anyhow::anyhow!("Font dir not found"))) - }, - |font_dir| { - info!("Font dir: {:?}", font_dir); - Ok(font_dir) - }, - )?; + let root_path = font_dir().unwrap_or_else(|| { + let default_font = Asset::get("Roboto-Regular.ttf").unwrap(); + let exe_path = env::current_exe().unwrap(); + let mut folder_path = exe_path.parent().unwrap().to_path_buf(); + folder_path.push("resources"); + + if folder_path.exists() { + info!("Resources Folder exists"); + } else { + fs::create_dir_all(&folder_path).unwrap(); + } + + folder_path + }); + + // let root_path = font_dir().map_or_else( + // || { + // error!("Font dir not found"); + // Err(Error::InitError(anyhow::anyhow!("Font dir not found"))) + // }, + // |font_dir| { + // info!("Font dir: {:?}", font_dir); + // Ok(font_dir) + // }, + // )?; Ok(Self { library, diff --git a/src/graphics/collections/agg_fast_path.rs b/src/graphics/collections/agg_fast_path.rs index 0f8b5d1..7d0ffe2 100644 --- a/src/graphics/collections/agg_fast_path.rs +++ b/src/graphics/collections/agg_fast_path.rs @@ -145,7 +145,6 @@ impl AttaWithBuffer for AggFastPath { sum += num; } - let point_lens = data.iter().map(|d| d.len()).collect::>(); let mut vbo = Vec::with_capacity(points.len() * 10); for p in points { vbo.extend_from_slice(&[ @@ -155,15 +154,9 @@ impl AttaWithBuffer for AggFastPath { } let mut ebo = vec![]; for (idx, e) in data.iter().map(|v| &v.ebo).enumerate() { - if idx > 0 { - let len = lens[idx - 1] as u32; - for e in e.iter() { - ebo.extend_from_slice(&[e[0] + len, e[1] + len, e[2] + len]); - } - } else { - for e in e.iter() { - ebo.extend_from_slice(e); - } + let len = lens[idx] as u32; + for e in e.iter() { + ebo.extend_from_slice(&[e[0] + len, e[1] + len, e[2] + len]); } } diff --git a/src/graphics/mod.rs b/src/graphics/mod.rs index 9d3f337..30a98b3 100644 --- a/src/graphics/mod.rs +++ b/src/graphics/mod.rs @@ -120,7 +120,7 @@ pub enum Config { config_for_everyitem!({PPIConfig => PPI},{FontConfig => Font}, ); -pub trait AttachWithMouse { +pub trait AttachWithIO { type State: CameraOP; fn attach_with_mouse( &mut self, @@ -141,3 +141,9 @@ pub enum MouseState { Wheel(f32), None, } + +#[derive(Debug, Clone)] +pub struct MouseKeyboardState { + pub mouse_state: MouseState, + pub keyboard_state: [bool; 652], +} diff --git a/src/graphics/ppi.rs b/src/graphics/ppi.rs index ff46dac..1c288db 100644 --- a/src/graphics/ppi.rs +++ b/src/graphics/ppi.rs @@ -1,6 +1,6 @@ use super::colormap::ColorMap; use super::transforms::viewport::Viewport; -use super::{transforms, AttaWithBuffer, AttaWithProgram, AttachWithMouse, Config, Graphics}; +use super::{transforms, AttaWithBuffer, AttaWithProgram, AttachWithIO, Config, Graphics}; use crate::components::{CodeType, Program, Shader}; use crate::data_loader::{CoordType, Data, DataType}; use crate::errors::*; diff --git a/src/graphics/threed.rs b/src/graphics/threed.rs index 8995769..a7b4247 100644 --- a/src/graphics/threed.rs +++ b/src/graphics/threed.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use tracker::track; use super::transforms::{position::Position, trackball::TrackballModel}; -use super::{AttaWithProgram, AttachWithMouse}; +use super::{AttaWithProgram, AttachWithIO}; use crate::camera::{self, Camera}; use crate::errors::*; use crate::pg::layout_type::ViewPort; @@ -17,7 +17,7 @@ pub struct Trackball { impl Trackball { pub fn new(aspect: f32, z_near: f32, z_far: f32, fov: f32) -> Result { - let trackball = TrackballModel::new(0.0, 90.0); + let trackball = TrackballModel::new(0.0, 90.0, 20.0); Ok(Self { trackball }) } @@ -40,7 +40,7 @@ impl AttaWithProgram for Trackball { } } -impl AttachWithMouse for Trackball { +impl AttachWithIO for Trackball { type State = super::MouseState; fn attach_with_mouse( &mut self, diff --git a/src/graphics/transforms/plane.rs b/src/graphics/transforms/plane.rs index 91d3f2e..2b6c93f 100644 --- a/src/graphics/transforms/plane.rs +++ b/src/graphics/transforms/plane.rs @@ -1,17 +1,53 @@ use crate::components::{CodeType, Program, Snippet}; use crate::errors::Result; -use crate::graphics::{AttaWithProgram, AttachWithMouse, MouseState}; +use crate::graphics::{AttaWithProgram, AttachWithIO, MouseKeyboardState, MouseState}; use crate::pg::layout_type::ViewPort; +use crate::ui::operation::Projection; use glow::HasContext; use nalgebra::{Matrix4, Quaternion, Translation3, Unit, UnitQuaternion, Vector3}; use nalgebra_glm::vec3; +use serde::de; + +use super::trackball::{self, TrackballModel}; +use super::viewport; #[derive(Debug, Clone)] -pub struct PlaneTrans {} +pub struct PlaneTrans { + trackball: TrackballModel, +} -impl AttachWithMouse for PlaneTrans { - type State = MouseState; +impl PlaneTrans { + fn translate( + &self, + projection: &Projection, + camera: &mut crate::camera::Camera, + delta: &[f32; 2], + viewport_size: &[f32; 2], + ) { + let watch_vec = camera.front(); + let fov = projection.fov().to_radians(); + let aspect = projection.aspect(); + + // Z_near + let z_distance = camera.front().norm().abs(); + + let h = 2.0 * z_distance * (fov / 2.0).tan(); + let w = h * aspect; + + let move_width = (delta[0] * w) / viewport_size[0]; + let move_height = (delta[1] * h) / viewport_size[1]; + + let up = camera.get_upward(); + let right = watch_vec.cross(&up).normalize(); + let _move = move_width * right + move_height * up; + camera.set_position(camera.get_position() - _move); + camera.set_center(camera.get_center() - _move); + } +} + +impl AttachWithIO for PlaneTrans { + type State = MouseKeyboardState; fn attach_with_mouse( &mut self, @@ -20,47 +56,50 @@ impl AttachWithMouse for PlaneTrans { projection: &mut crate::ui::operation::Projection, viewport: &ViewPort, ) -> bool { - let watch_vec = camera.front(); let viewport_size = viewport.size(); - let if_vertical = true; + let shift_key = state.keyboard_state[imgui::Key::LeftShift as usize]; + let ctrl_key = state.keyboard_state[imgui::Key::LeftCtrl as usize]; - match state { + match &state.mouse_state { MouseState::Drag { from, delta } => { - if if_vertical { - // Radian - let fov = projection.fov().to_radians(); - let aspect = projection.aspect(); - - // Z_near - let z_near = projection.z_near(); - - let h = 2.0 * z_near * (fov / 2.0).tan(); - let w = h * aspect; - - let move_width = (delta[0] * w) / viewport_size[0]; - let move_height = (delta[1] * h) / viewport_size[1]; - - let up = camera.get_upward(); - let right = watch_vec.cross(&up).normalize(); - let _move = move_width * right + move_height * up; - - camera.set_position(camera.get_position() + _move); - camera.set_center(camera.get_center() + _move); + if shift_key { + self.trackball.drag_to( + from[0] - viewport_size[0] / 2.0, + from[1] - viewport_size[1] / 2.0, + 0.0, + -delta[1], + ); + } else if ctrl_key { + self.trackball.drag_to( + from[0] - viewport_size[0] / 2.0, + from[1] - viewport_size[1] / 2.0, + -delta[0], + 0.0, + ); + } else if shift_key && ctrl_key { + self.trackball.drag_to( + from[0] - viewport_size[0] / 2.0, + from[1] - viewport_size[1] / 2.0, + -delta[0], + -delta[1], + ) } else { + self.translate(projection, camera, delta, &viewport_size); } + true } MouseState::Wheel(delta) => { projection.set_fov((projection.fov() - delta).clamp(15.0, 120.0)); + true } - _ => {} + _ => false, } - true } fn init_camera(&self) -> crate::camera::Camera { crate::camera::Camera::new( - vec3(0.0, 20.0, 0.0), - vec3(0.0, 0.0, 1.0), + vec3(0.0, 0.0, 20.0), + vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 0.0), ) } @@ -72,10 +111,7 @@ impl AttaWithProgram for PlaneTrans { fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result<()> { unsafe { let loc = program.get_uniform_location(gl, "trackball_model"); - - let trackball = nalgebra_glm::rotate_x(&nalgebra_glm::identity(), 90.0f32.to_radians()); - - gl.uniform_matrix_4_f32_slice(loc.as_ref(), false, trackball.as_slice()); + self.trackball.attach_with_program(gl, program)?; } Ok(()) } @@ -83,6 +119,7 @@ impl AttaWithProgram for PlaneTrans { impl Default for PlaneTrans { fn default() -> Self { - Self {} + let trackball = TrackballModel::new(0.0, 0.0, 200.0); + Self { trackball } } } diff --git a/src/graphics/transforms/trackball.rs b/src/graphics/transforms/trackball.rs index b3b1c29..05616d9 100644 --- a/src/graphics/transforms/trackball.rs +++ b/src/graphics/transforms/trackball.rs @@ -19,13 +19,13 @@ pub struct TrackballModel { } impl TrackballModel { - pub fn new(theta: f32, phi: f32) -> Self { + pub fn new(phi: f32, theta: f32, range: f32) -> Self { let mut trackball = Self { rotation: UnitQuaternion::identity(), count: 0, model: Matrix4::identity(), renorm_count: 97, - trackball_size: 20.0, + trackball_size: range, x: 0.0, y: 0.0, theta, @@ -35,6 +35,17 @@ impl TrackballModel { trackball } + pub fn rotate_z(&mut self, angle: f32) { + let q = UnitQuaternion::from_axis_angle(&Vector3::z_axis(), angle); + self.rotation *= q; + self.count += 1; + if self.count > self.renorm_count { + self.rotation = UnitQuaternion::new_normalize(*self.rotation.clone()); + self.count = 0; + } + self.model = self.rotation.to_homogeneous(); + } + pub fn drag_to(&mut self, x: f32, y: f32, dx: f32, dy: f32) { let q = self.rotate(x, y, dx, dy); self.rotation *= q; @@ -159,7 +170,7 @@ mod test { #[test] fn test_trackball() { - let mut trackball = TrackballModel::new(45.0, 45.0); + let mut trackball = TrackballModel::new(45.0, 45.0, 20.0); println!("{:?}", trackball.model()); trackball.drag_to(0.0, 10.0, 15.0, 30.0); diff --git a/src/main.rs b/src/main.rs index 688aafd..25c6810 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,12 @@ mod utils; use pg::App; use support::supporter::run; +use rust_embed::RustEmbed; + + +#[derive(RustEmbed)] +#[folder = "resources/"] +pub struct Asset; use once_cell::sync::Lazy; static SETTING: Lazy = Lazy::new(|| setting::Setting::new()); diff --git a/src/pg/mod.rs b/src/pg/mod.rs index ed96f14..d93a691 100644 --- a/src/pg/mod.rs +++ b/src/pg/mod.rs @@ -13,7 +13,7 @@ use crate::graphics::ppi::PPI; use crate::graphics::threed::Trackball; use crate::graphics::transforms::plane::PlaneTrans; use crate::graphics::transforms::viewport; -use crate::graphics::{AttaWithProgram, AttachWithMouse}; +use crate::graphics::{AttaWithProgram, AttachWithIO}; use crate::ui::operation::Operation; use crate::ui::typ::LayoutAttach; use crate::utils::cache::CachedData; diff --git a/src/pg/modules/mod.rs b/src/pg/modules/mod.rs index 2767e8f..10cda77 100644 --- a/src/pg/modules/mod.rs +++ b/src/pg/modules/mod.rs @@ -1,5 +1,5 @@ use crate::{ - graphics::AttachWithMouse, + graphics::AttachWithIO, ui::{ operation::{self, Operation}, typ::CameraOP, @@ -59,22 +59,19 @@ impl<'a> Attach<'a> { } } - fn bind_data(&mut self, vbo: &Vec, ebo: Option<&Vec>, len: i32) { + fn bind_data(&mut self, vbo: &Vec, ebo: Option<&Vec>, len: i32, usage: u32) { use bytemuck::cast_slice; self.vbo.bind(glow::ARRAY_BUFFER); unsafe { self.gl - .buffer_data_u8_slice(glow::ARRAY_BUFFER, cast_slice(&vbo), glow::STATIC_DRAW); + .buffer_data_u8_slice(glow::ARRAY_BUFFER, cast_slice(&vbo), usage); if let Some(ebo) = ebo { self.gl.bind_buffer( glow::ELEMENT_ARRAY_BUFFER, Some(self.ebo.as_ref().unwrap().native()), ); - self.gl.buffer_data_u8_slice( - glow::ELEMENT_ARRAY_BUFFER, - cast_slice(&ebo), - glow::STATIC_DRAW, - ); + self.gl + .buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, cast_slice(&ebo), usage); self.gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None); } @@ -91,7 +88,7 @@ impl<'a> Attach<'a> { pub trait Module: Sized { type Cursor: ModuleCursor; type Data; - type Operation: AttachWithMouse; + type Operation: AttachWithIO; fn render( &mut self, diff --git a/src/pg/modules/ppi.rs b/src/pg/modules/ppi.rs index 2522044..4d890eb 100644 --- a/src/pg/modules/ppi.rs +++ b/src/pg/modules/ppi.rs @@ -55,7 +55,7 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { config: &PPIModuleConfig, ) -> Result<()> { let (vbo, ebo, len) = self.ppi_program.bake(data, &config.to_ppi_config())?; - attach.bind_data(&vbo, ebo.as_ref(), len); + attach.bind_data(&vbo, ebo.as_ref(), len, glow::DYNAMIC_DRAW); Ok(()) } @@ -65,19 +65,25 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { data: &Data, config: &PPIModuleConfig, ) -> Result<()> { - let config = config.to_line_config(); + let raw_config = config.to_line_config(); + // Will be changed in the future let outskirt = 10.0; let mut paths = vec![]; - for range in 1..=6 { - let r = outskirt / 5.0 * range as f32; + let range_line_num = config.range_line_num; + let r = outskirt / range_line_num as f32; + let seg_num = 200; + let angle = 2f32 * f32::consts::PI / seg_num as f32; + + for range in 1..=range_line_num { // Create the path let mut path = Path::new(true); + let r = r * range as f32; // Draw the circle - for seg in 0..200 { - let angle = 2f32 * f32::consts::PI / 200.0 * seg as f32; + for seg in 0..seg_num { + let angle = angle * seg as f32; let x = (angle.cos() * r) as f32; let y = (angle.sin() * r) as f32; path.push([x, y, 0.01]); @@ -86,9 +92,10 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { paths.push(path); } - let a = 2.0 * f32::consts::PI / 6.0; + let ath_lin_num = config.ath_line_num; - for _a in 0..7 { + let a = 2.0 * f32::consts::PI / ath_lin_num as f32; + for _a in 0..=ath_lin_num { let mut path = Path::new(false); let x = (a * _a as f32).cos() * outskirt; let y = (a * _a as f32).sin() * outskirt; @@ -98,8 +105,16 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { paths.push(path); } - let (vbo, ebo, len) = self.line_program.bake(&paths, &config)?; - attach.bind_data(&vbo, ebo.as_ref(), len); + if config.vertical_axis { + let mut path = Path::new(false); + path.push([0.0, 0.0, 0.0]); + path.push([0.0, 0.0, outskirt]); + path.finish(); + paths.push(path); + } + + let (vbo, ebo, len) = self.line_program.bake(&paths, &raw_config)?; + attach.bind_data(&vbo, ebo.as_ref(), len, glow::STATIC_DRAW); Ok(()) } @@ -113,7 +128,7 @@ impl<'b, 'a: 'b> PPIModule<'b, 'a> { PositionText::new(new_text, [0.0, 0.0, 0.0], font::Anchor::BottomCenter); let text_pg_config = config.to_font_config(); let (vbo, ebo, len) = self.text_program.bake(&position_text, &text_pg_config)?; - attach.bind_data(&vbo, ebo.as_ref(), len); + attach.bind_data(&vbo, ebo.as_ref(), len, glow::STATIC_DRAW); } } @@ -151,6 +166,13 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { self.bind_ppi_pg(ppi_attach, data, config); } + if config.changed_range_line_num() + || config.changed_ath_line_num() + || config.changed_vertical_axis() + { + self.bind_line_pg(&mut cursor.line_attach, data, config)?; + } + // PPI Draw ppi_attach.bind_self(); self.ppi_program.draw(&self.gl, ppi_attach.len())?; @@ -304,15 +326,27 @@ impl<'gl> ModuleCursor for PPIPackage<'gl> { let mut line_width = self.ppi_config.line_width; let mut line_antialias = self.ppi_config.line_antialias; + let mut range_line_num = self.ppi_config.range_line_num; + let mut ath_line_num = self.ppi_config.ath_line_num; ui.text("PPI Line Config"); ui.slider("line width", 0.1, 10.0, &mut line_width); ui.slider("line ana", 0.1, 10.0, &mut line_antialias); + ui.slider("Range Line Num", 0, 10, &mut range_line_num); + ui.slider("Ath Line Num", 0, 10, &mut ath_line_num); + + ui.separator(); + + let mut value = self.ppi_config.vertical_axis; + ui.checkbox("Axis?", &mut value); self.ppi_config.set_layer(layer); self.ppi_config.set_is_three_d(is_three_d); self.ppi_config.set_line_width(line_width); self.ppi_config.set_line_antialias(line_antialias); + self.ppi_config.set_range_line_num(range_line_num); + self.ppi_config.set_ath_line_num(ath_line_num); + self.ppi_config.set_vertical_axis(value); self.ppi_config.changed_any() } @@ -329,6 +363,9 @@ pub struct PPIModuleConfig { pub line_color: [f32; 4], pub line_width: f32, pub line_antialias: f32, + pub range_line_num: usize, + pub ath_line_num: usize, + pub vertical_axis: bool, pub layer: usize, pub colors: Vec<[u8; 4]>, pub color_range: [f32; 2], @@ -354,6 +391,9 @@ impl Default for PPIModuleConfig { line_width: 1.5, line_antialias: 0.5, layer: 0, + vertical_axis: false, + range_line_num: 5, + ath_line_num: 6, colors: vec![], color_range: [0.0, 0.0], is_three_d: true, diff --git a/src/ui/io.rs b/src/ui/io.rs index 3c62b7e..a09e452 100644 --- a/src/ui/io.rs +++ b/src/ui/io.rs @@ -10,7 +10,7 @@ pub struct MouseIO { } pub struct KeyboardIO { - pub keys: [bool; 512], // 键盘按键状态 + pub keys: [bool; 652], // 键盘按键状态 } pub struct IO { @@ -23,7 +23,8 @@ impl IO { let io = ui.io(); let delta = if ui.is_mouse_dragging(imgui::MouseButton::Left) { - let delta = ui.mouse_drag_delta_with_threshold(imgui::MouseButton::Left, 5.0); + // let delta = ui.mouse_drag_delta_with_threshold(imgui::MouseButton::Left, 5.0); + let delta = ui.mouse_drag_delta_with_button(imgui::MouseButton::Left); ui.reset_mouse_drag_delta(imgui::MouseButton::Left); Some(delta) } else { @@ -31,20 +32,22 @@ impl IO { }; let windows_position = ui.window_pos(); + let inner_pad = ui.window_content_region_min(); + let position = [ + io.mouse_pos[0] - windows_position[0] - inner_pad[0], + io.mouse_pos[1] - windows_position[1] - inner_pad[1], + ]; IO { mouse: MouseIO { - position: [ - io.mouse_pos[0] - windows_position[0], - io.mouse_pos[1] - windows_position[1], - ], + position: position, drag_delta: delta, is_dragging: ui.is_mouse_dragging(imgui::MouseButton::Left), left_button_pressed: io.mouse_down[0], right_button_pressed: io.mouse_down[1], wheel_delta: io.mouse_wheel, }, - keyboard: KeyboardIO { keys: [false; 512] }, + keyboard: KeyboardIO { keys: io.keys_down }, } } } diff --git a/src/ui/operation.rs b/src/ui/operation.rs index 3baa245..ac35a66 100644 --- a/src/ui/operation.rs +++ b/src/ui/operation.rs @@ -2,18 +2,18 @@ use super::typ::CameraOP; use crate::{ camera::Camera, components::Program, - graphics::{AttaWithProgram, AttachWithMouse}, + graphics::{AttaWithProgram, AttachWithIO}, pg::layout_type::ViewPort, }; -pub struct Operation { +pub struct Operation { camera: Camera, projection: Projection, operation: T, need_update: bool, } -impl Operation { +impl Operation { pub fn new(operation: T, aspect: f32, fov: f32, z_near: f32, z_far: f32) -> Self { let projection = Projection::new(aspect, fov, z_near, z_far); Self { @@ -58,11 +58,6 @@ impl Operation { self.operation.attach_with_program(gl, program); } - // pub fn attach_with_mouse(&mut self, camera_op: &T::State) -> bool { - // self.operation - // .attach_with_mouse(camera_op, &mut self.camera, &mut self.projection) - // } - pub fn is_need_update(&self) -> bool { self.need_update } @@ -71,6 +66,10 @@ impl Operation { self.operation.reset(); self.need_update = true; } + + pub fn clean(&mut self) { + self.need_update = false; + } } pub struct Projection { diff --git a/src/ui/typ/main_load.rs b/src/ui/typ/main_load.rs index 34a49ae..435c4f2 100644 --- a/src/ui/typ/main_load.rs +++ b/src/ui/typ/main_load.rs @@ -4,7 +4,7 @@ use super::{CameraOP, Layout, LayoutAttach, LayoutMod, Size}; use crate::camera::Camera; use crate::graphics::threed::Trackball; use crate::graphics::transforms::plane::PlaneTrans; -use crate::graphics::{AttaWithProgram, AttachWithMouse, MouseState}; +use crate::graphics::{AttaWithProgram, AttachWithIO, MouseKeyboardState, MouseState}; use crate::pg::ModulePackage; use crate::pg::{_ModulePackage, layout_type::ViewPort}; use crate::ui::helper::Helper; @@ -182,6 +182,15 @@ impl CameraOP for MouseState { } } +impl CameraOP for MouseKeyboardState { + fn from_context(context: &IO) -> Self { + Self { + mouse_state: MouseState::from_context(context), + keyboard_state: context.keyboard.keys, + } + } +} + impl<'gl> LayoutAttach<'gl> for MainLoadAttach<'gl> { fn append(&mut self, package: ModulePackage<'gl>) { self.packages.push(package); @@ -194,7 +203,10 @@ impl<'gl> LayoutAttach<'gl> for MainLoadAttach<'gl> { helper: &mut Helper, ) -> crate::errors::Result<()> { // helper.draw_modules(gl, &self.packages); - if self.packages.iter().any(|v| v.need_update) || self.operation.is_need_update() { + + let need_launch = + self.packages.iter().any(|v| v.need_update) || self.operation.is_need_update(); + if need_launch { // Helper task self.main_viewport.bind(gl); @@ -205,6 +217,8 @@ impl<'gl> LayoutAttach<'gl> for MainLoadAttach<'gl> { for package in self.packages.iter_mut() { programs.draw_modules(package, &self.operation, &self.main_viewport)?; } + + self.operation.clean(); } if self.packages.is_empty() {