use crate::components::Program; use crate::font_manager::FontManager; use crate::graphics::colormap::linear::LinearColormap; use crate::graphics::font::Text; use crate::graphics::ppi::PPIConfig; use crate::graphics::threed::ThreeD; use crate::graphics::transforms::viewport::Viewport; use crate::graphics::{ppi::PPI, Graphics}; use crate::graphics::{AttaWithProgram, AttachWithMouse, Config, MouseState}; use crate::utils::resources::{ RcGlFramebuffer, RcGlRcResource, RcGlResource, RcGlTexture, Resource, }; // use crate::{ // errors::*, // ui::{State, GUI}, // }; use glow::{HasContext, NativeBuffer, NativeFramebuffer, NativeTexture, NativeVertexArray}; use imgui::{ImString, Ui}; use log::info; use std::marker::PhantomPinned; use std::pin::Pin; use std::ptr::NonNull; use std::{cell::RefCell, collections::HashMap, rc::Rc}; type RcGraphic = Rc>; type ProgramId = &'static str; // pub struct App<'a> { // gui: Option, // gl: GL, // viewport: Viewport, // programs: Option>, // } // impl<'a> App<'a> { // pub fn new(gl: GL) -> Result { // let viewport = Viewport::new()?; // Ok(Self { // gui: None, // viewport, // programs: None, // gl, // }) // } // fn render_for_program( // gl: &'a glow::Context, // program_with_window: &HashMap>, // _windows: &mut HashMap>, // p: &mut P, // ) where // P::Config: From, // { // // let mut p = program.borrow_mut(); // if program_with_window.len() == 0 { // return; // } // p.mount(&gl).unwrap(); // program_with_window.get(&P::id).map(|windows| { // for window in windows.iter() { // let window_info = &mut *(_windows.get_mut(window).unwrap()); // // Skip the window if it doesn't need to be redrawn // if !window_info.need_redraw { // continue; // } // // window_info.re_init = false; // // If the window needs to be reinitialized, set the config // for conf in window_info.confs.iter() { // p.set_config(&gl, &(conf.1.clone()).into()).unwrap(); // } // // Attach the modifer to the program // if let Some(motion) = window_info.modifer.as_ref() { // motion.attach_with_program(&gl, p.program_ref()).unwrap(); // } // // Attach the data to the program // unsafe { // if window_info.gl_fb_resources.is_none() { // continue; // } // let framebuffer = window_info.gl_fb_resources.as_ref().unwrap().native(); // gl.bind_framebuffer(glow::FRAMEBUFFER, Some(framebuffer)); // let attach = window_info.attach.get(P::id); // if attach.is_some() { // let vao = attach.unwrap().vao.native(); // gl.bind_vertex_array(Some(vao)); // } // if attach.is_some() { // let window_size = window_info.size; // gl.viewport(0, 0, window_size[0] as i32, window_size[1] as i32); // p.draw(&gl, attach.as_ref().unwrap().len).unwrap(); // } // if attach.is_some() { // gl.bind_vertex_array(None); // } // gl.bind_framebuffer(glow::FRAMEBUFFER, None); // window_info.need_redraw = false; // } // } // }); // // Unmount the program // p.unmount(&gl).unwrap(); // } // pub fn render(&mut self) { // // Self::render_for_program( // // &self.gl, // // &self.windows_manager.program_with_window, // // &mut self.windows_manager.windows, // // &mut self.programs.ppi_module, // // ); // // Self::render_for_program( // // &self.gl, // // &self.windows_manager.program_with_window, // // &mut self.windows_manager.windows, // // &mut self.programs.text_module, // // ); // } // // pub fn render_ui(&mut self, ui: &Ui, window: &winit::window::Window, run: &mut bool) { // // self.gui.render(ui); // // self.windows_manager.show_window(ui); // // // self.windows_manager.destroy_window(); // // } // pub fn programs(&mut self) -> &mut Programs<'a> { // self.programs.as_mut().unwrap() // } // pub fn prepare(&mut self) { // self.programs = Some(Programs::new(self.gl.gl(), &self.viewport).unwrap()); // self.programs().prepare(); // unsafe { // // self.gl.enable(glow::DEPTH_TEST); // } // } // pub fn destroy(&mut self) { // self.programs().destroy(); // } // } // pub struct WindowsManager<'a> { // gl: &'a glow::Context, // gl_resource_dispatcher: GlResourceDispatcher, // windows: HashMap>, // program_with_window: HashMap>, // } // impl<'a> WindowsManager<'a> { // fn new(gl: &'a glow::Context, gl_resource_dispatcher: GlResourceDispatcher) -> Self { // Self { // gl, // gl_resource_dispatcher, // windows: HashMap::with_capacity(30), // program_with_window: HashMap::with_capacity(30), // } // } // fn destroy_window(&mut self) { // for (id, window) in self.windows.iter() { // if !window.open { // self.program_with_window.iter_mut().for_each(|(_, v)| { // v.retain(|v| v != id); // }); // } // } // self.windows.retain(|_, v| v.open == true); // } // pub fn create_framebuffer( // &mut self, // id: &str, // size: [i32; 2], // ) -> Result<(RcGlFramebuffer<'a>, RcGlTexture<'a>)> { // let id = &ImString::new(id); // if self.windows.contains_key(id) { // let info = self.windows.get(id).unwrap(); // if info.gl_fb_resources.is_some() && info.gl_tex_resources.is_some() { // return Ok(( // info.gl_fb_resources.as_ref().unwrap().clone(), // info.gl_tex_resources.as_ref().unwrap().clone(), // )); // } // } // let gl = self.gl; // let tex = unsafe { // let framebuffer = self // .gl_resource_dispatcher // .create_new::(); // // let framebuffer = gl.create_framebuffer().unwrap(); // gl.bind_framebuffer(glow::FRAMEBUFFER, Some(framebuffer.native())); // let texture = self.gl_resource_dispatcher.create_new::(); // gl.bind_texture(glow::TEXTURE_2D, Some(texture.native())); // gl.tex_image_2d( // glow::TEXTURE_2D, // 0, // glow::RGB8 as i32, // size[0], // size[1], // 0, // glow::RGB, // glow::UNSIGNED_BYTE, // None, // ); // gl.tex_parameter_i32( // glow::TEXTURE_2D, // glow::TEXTURE_MIN_FILTER, // glow::LINEAR as i32, // ); // gl.tex_parameter_i32( // glow::TEXTURE_2D, // glow::TEXTURE_MAG_FILTER, // glow::LINEAR as i32, // ); // gl.framebuffer_texture_2d( // glow::FRAMEBUFFER, // glow::COLOR_ATTACHMENT0, // glow::TEXTURE_2D, // Some(texture.native()), // 0, // ); // assert_eq!( // gl.check_framebuffer_status(glow::FRAMEBUFFER), // glow::FRAMEBUFFER_COMPLETE // ); // gl.bind_framebuffer(glow::FRAMEBUFFER, None); // gl.bind_texture(glow::TEXTURE_2D, None); // (framebuffer, texture) // }; // Ok(tex) // } // pub fn create_render_window( // &mut self, // title: &str, // size: [f32; 2], // ) -> Result<&mut WindowData<'a>> { // // Insert the window data into the windows hashmap // let id = ImString::new(title); // let mut data = WindowData::new(&self.gl, id.clone(), size, None); // let (fb, tex) = // self.create_framebuffer(title, [size[0].floor() as i32, size[1].floor() as i32])?; // data.gl_fb_resources = Some(fb); // data.gl_tex_resources = Some(tex); // self.windows.insert(id.clone(), data); // let window = self.windows.get_mut(&id).unwrap(); // Ok(window) // } // fn show_window(&mut self, ui: &Ui) { // let mut need_resize = vec![]; // for (id, window) in self.windows.iter_mut() { // let mut window = window; // ui.window(&window.title) // .size(window.size, imgui::Condition::FirstUseEver) // .opened(&mut window.open) // .flags(imgui::WindowFlags::NO_SCROLLBAR) // .build(|| { // if ui.is_mouse_clicked(imgui::MouseButton::Left) { // let io = ui.io(); // let pos = io.mouse_pos; // let window_pos = ui.window_pos(); // window.last_mouse_position = // [pos[0] - window_pos[0], pos[1] - window_pos[1]]; // } // if ui.is_mouse_dragging(imgui::MouseButton::Left) { // if ui.is_window_hovered() { // let delta = ui.mouse_drag_delta(); // window.last_mouse_delta = delta; // window.accmulate_mouse_delta = [ // window.accmulate_mouse_delta[0] + delta[0], // window.accmulate_mouse_delta[1] + delta[1], // ]; // window.motion = Some(MouseState::Drag { // from: window.last_mouse_position, // delta: delta, // }); // println!( // "Dragging: {:?} {:?}", // window.last_mouse_position, window.accmulate_mouse_delta // ); // window.modifer.as_mut().map(|v| { // v.exec(window.motion.as_ref().unwrap()); // }); // window.need_redraw = true; // } // } // if ui.is_mouse_released(imgui::MouseButton::Left) { // if window.size != ui.window_size() { // window.size = ui.window_size(); // info!("resized: {:?}", window.size); // need_resize.push((window.title.clone(), ui.window_size())); // } // } // if let Some(texture) = window.gl_tex_resources.as_ref() { // let cursor = ui.cursor_pos(); // imgui::Image::new(texture.native2imguiid(), ui.window_size()).build(ui); // ui.set_cursor_pos(cursor); // if ui.invisible_button(&window.title, ui.window_size()) { // let io = ui.io(); // let pos = io.mouse_pos; // let window_pos = ui.window_pos(); // let related_pos = [pos[0] - window_pos[0], pos[1] - window_pos[1]]; // } // } // }); // } // for (id, size) in need_resize.iter() { // self.reset_window_size(id, *size); // } // } // fn reset_window_size(&mut self, id: &ImString, size: [f32; 2]) { // let window_info = self.windows.get_mut(id).unwrap(); // window_info.need_redraw = true; // info!("resize: {:?}", size); // let tex = unsafe { // self.gl.bind_framebuffer( // glow::FRAMEBUFFER, // window_info.gl_fb_resources.as_ref().map(|v| v.native()), // ); // let texture = self.gl.create_texture().unwrap(); // self.gl.bind_texture(glow::TEXTURE_2D, Some(texture)); // self.gl.tex_image_2d( // glow::TEXTURE_2D, // 0, // glow::RGB8 as i32, // size[0].floor() as i32, // size[1].floor() as i32, // 0, // glow::RGB, // glow::UNSIGNED_BYTE, // None, // ); // self.gl.tex_parameter_i32( // glow::TEXTURE_2D, // glow::TEXTURE_MIN_FILTER, // glow::LINEAR as i32, // ); // self.gl.tex_parameter_i32( // glow::TEXTURE_2D, // glow::TEXTURE_MAG_FILTER, // glow::LINEAR as i32, // ); // self.gl.framebuffer_texture_2d( // glow::FRAMEBUFFER, // glow::COLOR_ATTACHMENT0, // glow::TEXTURE_2D, // Some(texture), // 0, // ); // assert_eq!( // self.gl.check_framebuffer_status(glow::FRAMEBUFFER), // glow::FRAMEBUFFER_COMPLETE // ); // self.gl.bind_framebuffer(glow::FRAMEBUFFER, None); // self.gl.bind_texture(glow::TEXTURE_2D, None); // texture // }; // window_info.gl_tex_resources = Some(RcGlResource::new(self.gl, tex)); // } // pub fn set_window_program(&mut self, window: ImString) { // self.program_with_window // .entry(P::id) // .and_modify(|v| v.push(window.clone())) // .or_insert(vec![window]); // } // } // pub struct Programs<'a> { // gl: &'a glow::Context, // pub text_module: NonNull>, // pub ppi_module: PPI, // } impl<'a> Programs<'a> { fn new(gl: &'a glow::Context, viewport: &Viewport) -> Result { let font_manager = FontManager::new()?; let mut cmap = LinearColormap::new()?; cmap.set_colors(vec![ [170, 170, 170, 255], [0, 34, 255, 255], [1, 160, 246, 255], [0, 236, 236, 255], [0, 216, 0, 255], [1, 144, 0, 255], [255, 255, 0, 255], [231, 192, 0, 255], [255, 144, 0, 255], [255, 0, 0, 255], [214, 0, 0, 255], [192, 0, 0, 255], [255, 0, 240, 255], [150, 0, 180, 255], ]); cmap.set_range(0.0, 70.0); let cmap = Box::new(cmap); let mut ppi = PPI::new()?; ppi.set_viewport(&viewport); ppi.set_colormap(cmap); let mut text_module = Text::new(gl, font_manager)?; text_module.set_viewport(&viewport); Ok(Self { gl, ppi_module: ppi, text_module, }) } fn prepare(&mut self) { self.ppi_module.compile(&self.gl).unwrap(); self.text_module.compile(&self.gl).unwrap(); } fn destroy(&mut self) { self.ppi_module.destroy(&self.gl).unwrap(); self.text_module.destroy(&self.gl).unwrap(); } pub fn create_ppi_render(&self, config: Option) -> Attach<'a> { self.create_render(&self.ppi_module) } pub fn create_text_render(&self) -> Attach<'a> { self.create_render(&self.text_module) } fn create_render(&self, p: &P) -> Attach<'a> { let (vao, vbo, ebo) = p.init(&self.gl); Attach { vao: RcGlResource::new(&self.gl, vao), vbo: RcGlResource::new(&self.gl, vbo), ebo: ebo.map(|ebo| RcGlResource::new(&self.gl, ebo)), len: 0, } } } // pub struct WindowProgram<'a, 'sl, 'pro, P: Graphics> { // window: &'sl mut WindowData<'a>, // program: &'pro P, // } // impl<'a, 's, 'b, P: Graphics> WindowProgram<'a, 's, 'b, P> { // pub fn bind_data(&mut self, data: &P::Data) -> Result { // use bytemuck::cast_slice; // let data = self.program.bake(data)?; // let attach = self.window.attach.get_mut(P::id).unwrap(); // attach.len = data.2; // let gl = self.window.gl; // unsafe { // gl.bind_vertex_array(Some(attach.vao.native())); // // gl.bind_buffer(glow::VERTEX_ARRAY, Some(attach.vbo.native())); // gl.buffer_data_u8_slice( // glow::ARRAY_BUFFER, // cast_slice(data.0.as_slice()), // glow::STATIC_DRAW, // ); // if let Some(_) = attach.ebo.as_ref() { // // gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ebo.native())); // gl.buffer_data_u8_slice( // glow::ELEMENT_ARRAY_BUFFER, // cast_slice(&data.1.as_ref().unwrap()), // glow::STATIC_DRAW, // ); // // gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None); // } // // gl.bind_buffer(glow::VERTEX_ARRAY, None); // gl.bind_vertex_array(None); // } // Ok(()) // } // pub fn set_config(&mut self, config: P::Config) // where // Config: From, // { // let config = Config::from(config); // self.window // .confs // .entry(P::id) // .and_modify(|v| *v = config.clone()) // .or_insert(config); // } // } // pub struct WindowData<'a> { // gl: &'a glow::Context, // pub title: ImString, // pub open: bool, // pub copy_from: Option, // pub size: [f32; 2], // gl_fb_resources: Option>, // gl_tex_resources: Option>, // need_redraw: bool, // attach: HashMap>, // confs: HashMap, // re_init: bool, // last_mouse_position: [f32; 2], // last_mouse_delta: [f32; 2], // accmulate_mouse_delta: [f32; 2], // mouse_position: [f32; 2], // motion: Option, // modifer: Option, // } // impl<'a> WindowData<'a> { // fn new( // gl: &'a glow::Context, // title: ImString, // size: [f32; 2], // modifer: Option, // ) -> Self { // Self { // gl, // title, // open: true, // copy_from: None, // size, // last_mouse_position: [0.0, 0.0], // last_mouse_delta: [0.0, 0.0], // accmulate_mouse_delta: [0.0, 0.0], // mouse_position: [0.0, 0.0], // motion: None, // gl_fb_resources: None, // gl_tex_resources: None, // need_redraw: true, // attach: HashMap::with_capacity(10), // re_init: true, // confs: HashMap::with_capacity(5), // modifer, // } // } // fn set(&mut self, f: F) // where // F: FnOnce(&mut Self), // { // f(self); // self.need_redraw = true; // // let v = self.program_with_window.entry(PPI::id).or_insert(vec![]); // // v.push(id.clone()); // } // pub fn set_attach(&mut self, attach: Attach<'a>) { // self.set(move |w| { // w.attach.insert(P::id, attach); // }); // } // pub fn with_program<'b, 's, P: Graphics>( // &'b mut self, // program: &'s P, // ) -> WindowProgram<'a, 'b, 's, P> // where // 's: 'b, // 'a: 's, // { // WindowProgram { // program, // window: self, // } // } // pub fn set_window_modifer(&mut self, modifier: Option) { // self.set(|w| w.modifer = modifier); // } // pub fn id(&self) -> &ImString { // &self.title // } // fn set_current_mouse_delta(&mut self, delta: [f32; 2]) { // self.last_mouse_delta = delta; // self.accmulate_mouse_delta = [ // self.accmulate_mouse_delta[0] + delta[0], // self.accmulate_mouse_delta[1] + delta[1], // ]; // } // fn set_mouse_postion(&mut self, pos: [f32; 2]) { // self.mouse_position = pos; // } // fn set_motion(&mut self, motion: MouseState) { // self.motion = Some(motion); // } // fn set_need_redraw(&mut self) { // self.need_redraw = true; // } // fn set_re_init(&mut self) { // self.re_init = true; // } // fn on_mouse_drag(&mut self) { // let state = MouseState::Drag { // from: self.last_mouse_position, // delta: self.last_mouse_delta, // }; // self.set_motion(state.clone()); // self.modifer.as_mut().map(|m| {}); // self.set_need_redraw(); // } // } // macro_rules! modifer_exec { // ($(($t:ty => $b:tt),)+) => { // impl ModiferType { // pub fn exec(&mut self, motion: &MouseState) { // match self { // $( // ModiferType::$b(b) => { // b.attach_with_mouse(motion); // } // )+ // _ => {} // } // } // } // impl AttaWithProgram for ModiferType { // fn attach_with_program(&self, gl: &glow::Context, program: &Program) -> Result { // match self { // $( // ModiferType::$b(b) => { // b.attach_with_program(gl, program)?; // } // )+ // _ => { // } // } // Ok(()) // } // } // $( // impl From<$t> for ModiferType { // fn from(t: $t) -> Self { // ModiferType::$b(t) // } // } // )+ // } // } // pub enum ModiferType { // ThreeD(ThreeD), // TwoD, // } // modifer_exec!((ThreeD => ThreeD),); // #[derive(Debug, Clone)] // pub struct GlResourceDispatcher { // gl: Rc, // } // impl GlResourceDispatcher { // pub fn new(gl: Rc) -> Self { // Self { gl } // } // pub fn create_new<'a, T: Resource>(&'a self) -> RcGlResource<'a, T> { // RcGlResource::new(&self.gl, T::create(&self.gl)) // } // pub fn create_new_rc(&self) -> RcGlRcResource { // RcGlRcResource::new(self.gl.clone(), T::create(&self.gl)) // } // pub fn gl(&self) -> &Rc { // &self.gl // } // } // pub struct Manager { // pub gl_resource_dispatcher: GlResourceDispatcher, // } // pub struct GL { // gl: Rc, // } // impl GL { // pub fn new(gl: Rc) -> Self { // Self { gl } // } // fn gl(&self) -> &glow::Context { // &self.gl // } // fn rc_gl(&self) -> Rc { // self.gl.clone() // } // }