radar-gi/src/_pg.rs
2024-08-14 17:05:06 +08:00

746 lines
24 KiB
Rust

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<T> = Rc<RefCell<T>>;
type ProgramId = &'static str;
// pub struct App<'a> {
// gui: Option<GUI>,
// gl: GL,
// viewport: Viewport,
// programs: Option<Programs<'a>>,
// }
// impl<'a> App<'a> {
// pub fn new(gl: GL) -> Result<Self> {
// let viewport = Viewport::new()?;
// Ok(Self {
// gui: None,
// viewport,
// programs: None,
// gl,
// })
// }
// fn render_for_program<P: Graphics>(
// gl: &'a glow::Context,
// program_with_window: &HashMap<ProgramId, Vec<ImString>>,
// _windows: &mut HashMap<ImString, WindowData<'a>>,
// p: &mut P,
// ) where
// P::Config: From<Config>,
// {
// // 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<ImString, WindowData<'a>>,
// program_with_window: HashMap<ProgramId, Vec<ImString>>,
// }
// 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::<NativeFramebuffer>();
// // let framebuffer = gl.create_framebuffer().unwrap();
// gl.bind_framebuffer(glow::FRAMEBUFFER, Some(framebuffer.native()));
// let texture = self.gl_resource_dispatcher.create_new::<NativeTexture>();
// 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<P: Graphics>(&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<Text<'a>>,
// pub ppi_module: PPI,
// }
impl<'a> Programs<'a> {
fn new(gl: &'a glow::Context, viewport: &Viewport) -> Result<Self> {
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<PPIConfig>) -> 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<P: Graphics>(&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<P::Config>,
// {
// 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<ImString>,
// pub size: [f32; 2],
// gl_fb_resources: Option<RcGlResource<'a, NativeFramebuffer>>,
// gl_tex_resources: Option<RcGlResource<'a, NativeTexture>>,
// need_redraw: bool,
// attach: HashMap<ProgramId, Attach<'a>>,
// confs: HashMap<ProgramId, Config>,
// re_init: bool,
// last_mouse_position: [f32; 2],
// last_mouse_delta: [f32; 2],
// accmulate_mouse_delta: [f32; 2],
// mouse_position: [f32; 2],
// motion: Option<MouseState>,
// modifer: Option<ModiferType>,
// }
// impl<'a> WindowData<'a> {
// fn new(
// gl: &'a glow::Context,
// title: ImString,
// size: [f32; 2],
// modifer: Option<ModiferType>,
// ) -> 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<F>(&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<P: Graphics>(&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<ModiferType>) {
// 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<glow::Context>,
// }
// impl GlResourceDispatcher {
// pub fn new(gl: Rc<glow::Context>) -> 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<T: Resource>(&self) -> RcGlRcResource<T> {
// RcGlRcResource::new(self.gl.clone(), T::create(&self.gl))
// }
// pub fn gl(&self) -> &Rc<glow::Context> {
// &self.gl
// }
// }
// pub struct Manager {
// pub gl_resource_dispatcher: GlResourceDispatcher,
// }
// pub struct GL {
// gl: Rc<glow::Context>,
// }
// impl GL {
// pub fn new(gl: Rc<glow::Context>) -> Self {
// Self { gl }
// }
// fn gl(&self) -> &glow::Context {
// &self.gl
// }
// fn rc_gl(&self) -> Rc<glow::Context> {
// self.gl.clone()
// }
// }