From cf3b1fabfc242a07220a24e05bc21edb20b2185c Mon Sep 17 00:00:00 2001 From: Tsuki Date: Wed, 17 Apr 2024 18:35:47 +0800 Subject: [PATCH] sync --- src/actions.rs | 14 +- src/components/app.rs | 189 +++----- src/components/monitor/monitor.rs | 2 +- src/components/monitor/widget/widget.rs | 2 +- src/components/sidebar/sidebar.rs | 17 +- src/map_tile.rs | 2 +- src/pipeline/dispatcher.rs | 15 +- src/pipeline/element.rs | 2 +- src/pipeline/element_imp.rs | 163 +++++-- src/pipeline/mod.rs | 11 +- src/pipeline/new_element.rs | 620 +++++++++++++++++++----- src/pipeline/offscreen_renderer.rs | 17 +- src/pipeline/renders.rs | 3 +- src/pipeline/runner.rs | 95 ++-- src/predefined/widgets.rs | 13 +- src/widgets/render/imp.rs | 2 +- src/widgets/render/interior/layers.rs | 106 +--- src/widgets/render/interior/mod.rs | 2 +- src/widgets/render/mod.rs | 2 +- src/widgets/render/predefined/gis.rs | 2 +- src/widgets/render/renders.rs | 2 +- 21 files changed, 819 insertions(+), 462 deletions(-) diff --git a/src/actions.rs b/src/actions.rs index 2ec2bf6..72175a9 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -7,7 +7,7 @@ use relm4::actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup}; use relm4::{ComponentParts, ComponentSender, RelmApp, RelmWidgetExt, SimpleComponent}; use crate::components::app::{AppModel, AppMsg, LayerMsg}; -use crate::widgets::{AssoElement, Layer}; +use crate::widgets::Layer; relm4::new_action_group!(pub LayerActionGroup, "layer"); relm4::new_stateless_action!(pub AddLayerAction, LayerActionGroup, "add"); @@ -15,24 +15,12 @@ relm4::new_stateless_action!(pub RemoveLayerAction, LayerActionGroup, "remove"); relm4::new_stateless_action!(pub MoveLayerAction, LayerActionGroup, "move"); pub fn register_layer_actions>(widget: W, sender: ComponentSender) { - let add_action: RelmAction = { - let sender = sender.clone(); - RelmAction::new_stateless(move |_| { - sender.input(AppMsg::LayerManager(LayerMsg::Add(Layer::new( - true, - "Test".to_string(), - AssoElement::Test, - )))) - }) - }; - let remove_action: RelmAction = { let sender = sender.clone(); RelmAction::new_stateless(move |_| sender.input(AppMsg::LayerManager(LayerMsg::Remove(0)))) }; let mut group: RelmActionGroup = RelmActionGroup::new(); - group.add_action(add_action); group.add_action(remove_action); group.register_for_widget(widget) } diff --git a/src/components/app.rs b/src/components/app.rs index fc25501..ef24c81 100644 --- a/src/components/app.rs +++ b/src/components/app.rs @@ -8,18 +8,16 @@ use super::{ }; use crate::components::sidebar::{SideBarInputMsg, SideBarModel}; use crate::data_utils::tools; -use crate::pipeline::element::DataTarget; use crate::pipeline::element_imp::{Context, ElementInput, GridImpConfig}; +use crate::pipeline::new_element::Buffer; +use crate::pipeline::new_element::Element; use crate::pipeline::runner::Runner; -use crate::pipeline::OffscreenRenderer; +use crate::pipeline::{DataTarget, Key}; +use crate::pipeline::{KVBuffer, OffscreenRenderer}; use crate::predefined::color_mapper::{BoundaryNorm, ColorMapper, ColorMapperComb, Discrete}; use crate::predefined::widgets::ColorBar; use crate::utils::meshgrid; -use crate::widgets::{AssoElement, DynamicCol}; -use crate::{ - actions::register_layer_actions, - pipeline::element::{Element, InstantElement, InstantElementDrawerType, TimeSeriesElement}, -}; +use crate::widgets::{DynamicCol, ElementType}; use crate::{ coords::{ cms::CMS, @@ -28,7 +26,7 @@ use crate::{ }, data::MetaInfo, errors::RenderError, - pipeline::{Dispatcher, Pipeline, RenderResult}, + pipeline::{Dispatcher, RenderResult}, plugin_system::init_plugin, widgets::render::Layer, CONFIG, PLUGIN_MANAGER, @@ -85,10 +83,9 @@ pub enum AppMsg { OpenDialog, LayerManager(LayerMsg), Layer, - NewElement(Element), + NewElement(Rc), DeleteElement(ElementKey), } -pub type Buffer = Rc, Option>>>>; type RcDispatcher = Rc; #[tracker::track] pub struct AppModel { @@ -109,7 +106,11 @@ pub struct AppModel { #[do_not_track] layers: Rc>>, #[do_not_track] - elements: Vec>>, + buffer: Arc>, + #[do_not_track] + file_pool: Arc>>, + #[do_not_track] + elements: Vec>, #[do_not_track] setting: Controller, } @@ -228,10 +229,7 @@ impl Component for AppModel { root: Self::Root, sender: ComponentSender, ) -> ComponentParts { - let layers = Rc::new(RefCell::new(vec![ - Layer::new(true, "Layer 1".to_string(), AssoElement::Test), - Layer::new(true, "Layer 2".to_string(), AssoElement::Test), - ])); + let layers = Rc::new(RefCell::new(vec![])); let control = ControlPanelModel::builder().launch(layers.clone()).forward( sender.input_sender(), |msg| match msg { @@ -239,6 +237,9 @@ impl Component for AppModel { }, ); + let buffer = Arc::new(Buffer::new(100)); + let file_pool = Arc::new(KVBuffer::new(20)); + let sidebar = SideBarModel::builder() .launch(layers.clone()) @@ -263,117 +264,88 @@ impl Component for AppModel { let mut dispatcher = Rc::new(Dispatcher::new(5, 5, chrono::Duration::minutes(1))); let cms = CMS::new(Mercator::default().into(), (3000.0, 3000.0)); + let dialog_buffer = buffer.clone(); + let dialog_cms = cms.clone(); let dialog = { let dialog_dispatcher = dispatcher.clone(); let dialog_sidebar_sender = sidebar.sender().clone(); let dialog_render_sender = render.sender().clone(); + let dialog_file_pool = file_pool.clone(); OpenDialog::builder() .transient_for_native(&root) .launch(OpenDialogSettings::default()) .forward(sender.input_sender(), move |response| match response { OpenDialogResponse::Accept(path) => { *FILE_PATH_ROOT.lock().unwrap() = path.clone(); - let data = Self::open_file_only(path); + let data = Self::open_file_only(path.clone()); let meta: MetaInfo = (&data.meta).clone().into(); let (lat_start, lat_end) = meta.lat_range.unwrap(); let (lon_start, lon_end) = meta.lon_range.unwrap(); let imp = tools(&data); - // let element_impl = plugin_result_impl(&data); - let mut renderer = OffscreenRenderer::new(3000, 3000).unwrap(); - let mut canvas = renderer.create_canvas(); - let mut dialog_cms = CMS::new(Mercator::default().into(), (3000.0, 3000.0)); - let mut context = Context::new(dialog_cms, canvas); - use femtovg::Color; - - let mut runner = Runner::new( - imp, - Arc::new(GridImpConfig { - color_map: ColorMapperComb::BoundaryNormDiscrete(ColorMapper::new( - Discrete::new(vec![ - Color::rgb(0, 172, 164), - Color::rgb(192, 192, 254), - Color::rgb(122, 114, 238), - Color::rgb(30, 38, 208), - Color::rgb(166, 252, 168), - Color::rgb(0, 234, 0), - Color::rgb(16, 146, 26), - Color::rgb(252, 244, 100), - Color::rgb(200, 200, 2), - Color::rgb(140, 140, 0), - Color::rgb(254, 172, 172), - Color::rgb(254, 100, 92), - Color::rgb(238, 2, 48), - Color::rgb(212, 142, 254), - Color::rgb(170, 36, 250), - ]), - BoundaryNorm::new( - vec![ - 0i8, 5i8, 10i8, 15i8, 20i8, 25i8, 30i8, 35i8, 40i8, - 45i8, 50i8, 55i8, 60i8, 65i8, 70i8, 75i8, - ], - false, - Some(-125), - ), - )), - }), - context, - ); - - let target = runner.run(&data); - let data_target = DataTarget::new(Some(data), target); - - let element = Element::create_instant( - InstantElementDrawerType::Prepared(data_target), + let config = GridImpConfig { + color_map: ColorMapperComb::BoundaryNormDiscrete(ColorMapper::new( + Discrete::new(vec![ + Color::rgb(0, 172, 164), + Color::rgb(192, 192, 254), + Color::rgb(122, 114, 238), + Color::rgb(30, 38, 208), + Color::rgb(166, 252, 168), + Color::rgb(0, 234, 0), + Color::rgb(16, 146, 26), + Color::rgb(252, 244, 100), + Color::rgb(200, 200, 2), + Color::rgb(140, 140, 0), + Color::rgb(254, 172, 172), + Color::rgb(254, 100, 92), + Color::rgb(238, 2, 48), + Color::rgb(212, 142, 254), + Color::rgb(170, 36, 250), + ]), + BoundaryNorm::new( + vec![ + 0i8, 5i8, 10i8, 15i8, 20i8, 25i8, 30i8, 35i8, 40i8, 45i8, + 50i8, 55i8, 60i8, 65i8, 70i8, 75i8, + ], + false, + Some(-125), + ), + )), + }; + let element = Rc::new(Element::new( + "CR", + dialog_cms.clone(), dialog_dispatcher.clone(), - "ET".to_string(), - ) - .get_instance(); - let layer = Layer::new( true, - "New Layer".to_string(), - AssoElement::Instant(element), - ); + Arc::new(config), + path.clone(), + dialog_buffer.clone(), + dialog_file_pool.clone(), + imp, + )); + dialog_sidebar_sender.emit(SideBarInputMsg::AddMetaItems(meta.to_map())); dialog_render_sender.emit(MonitorInputMsg::SetRenderRange( lon_start, lon_end, lat_start, lat_end, )); - // let data_target = element_impl.render(&data, &mut canvas, &mut dialog_cms); - // let data_target = DataTarget::new(Some(data), data_target); - // let element = Element::create_instant( - // InstantElementDrawerType::Prepared((data_target, element_impl)), - // dialog_dispatcher.clone(), - // "ET".to_string(), - // ) - // .get_instance(); - // let layer = Layer::new( - // true, - // "New Layer".to_string(), - // AssoElement::Instant(element), - // ); - // dialog_sidebar_sender.emit(SideBarInputMsg::AddMetaItems(meta.to_map())); - // dialog_render_sender.emit(MonitorInputMsg::SetRenderRange( - // lon_start, lon_end, lat_start, lat_end, - // )); - // let layer = Layer::new(true, "New Layer".to_string(), AssoElement::Test); - - AppMsg::LayerManager(LayerMsg::Add(layer)) + AppMsg::NewElement(element) } _ => AppMsg::Close, }) }; - let buffer: Buffer = Rc::new(RefCell::new(HashMap::new())); let model = AppModel { cms, dispatcher, waiting_for: None, - elements: Vec::with_capacity(20), + buffer, + file_pool, open_dialog: dialog, selected_layer: vec![], sidebar, + elements: vec![], control, render, layers, @@ -386,7 +358,7 @@ impl Component for AppModel { let widgets = view_output!(); let mut group = RelmActionGroup::::new(); relm4::main_application().set_accelerators_for_action::(&["O"]); - register_layer_actions(&widgets.main_window, sender.clone()); + // register_layer_actions(&widgets.main_window, sender.clone()); let action: RelmAction = { RelmAction::new_stateless(move |_| { sender.input(AppMsg::OpenDialog); @@ -411,24 +383,7 @@ impl Component for AppModel { (*self.layers).borrow_mut().push(layer); self.sidebar.sender().send(SideBarInputMsg::RefreshList); } - LayerMsg::SwitchToTime(idx) => { - let mut layer = (*self.layers).borrow_mut(); - let switched_layer = layer.get_mut(idx).unwrap(); - let asso_element = switched_layer.pop_associated_element(); - - if let AssoElement::Instant(e) = asso_element { - let dispatcher = self.dispatcher.clone(); - let cms = self.cms.clone(); - let (mut series, start_time) = e.to_time_series(dispatcher, cms); - switched_layer.set_time(start_time); - series.register(start_time).unwrap(); - let element = Arc::new(Mutex::new(series)); - switched_layer - .set_associated_element(AssoElement::TimeSeries(element.clone())); - self.elements.push(element); - } - self.sidebar.sender().send(SideBarInputMsg::RefreshList); - } + LayerMsg::SwitchToTime(idx) => {} LayerMsg::Select(idx) => { self.set_selected_layer(idx); @@ -446,15 +401,23 @@ impl Component for AppModel { LayerMsg::Remove(idx) => { let mut layers = (*self.layers).borrow_mut(); let mut layer = layers.remove(idx); - if let AssoElement::TimeSeries(e) = layer.pop_associated_element() { - let size = Arc::strong_count(&e); - } self.sidebar.sender().send(SideBarInputMsg::RefreshList); } }, AppMsg::CloseRequest => { relm4::main_application().quit(); } + AppMsg::NewElement(element) => { + let new_layer = Layer::new( + true, + "New Layer".to_string(), + element.clone(), + ElementType::Indenpendent, + ); + _sender.input(AppMsg::LayerManager(LayerMsg::Add(new_layer))); + self.elements.push(element); + self.render.sender().send(MonitorInputMsg::RefreshRender); + } AppMsg::Close => {} AppMsg::OpenDialog => { self.open_dialog.emit(OpenDialogMsg::Open); diff --git a/src/components/monitor/monitor.rs b/src/components/monitor/monitor.rs index 3757670..03de90e 100644 --- a/src/components/monitor/monitor.rs +++ b/src/components/monitor/monitor.rs @@ -22,7 +22,7 @@ use tracing::*; use crate::coords::Range; use crate::map_tile::MapTile; use crate::map_tile_utils::lat_lon_to_zoom; -use crate::pipeline::element::Target; +use crate::pipeline::Target; use crate::utils::estimate_zoom_level; use adw::prelude::*; use femtovg::ImageId; diff --git a/src/components/monitor/widget/widget.rs b/src/components/monitor/widget/widget.rs index 72d10ea..d6dae73 100644 --- a/src/components/monitor/widget/widget.rs +++ b/src/components/monitor/widget/widget.rs @@ -1,5 +1,5 @@ use crate::coords::cms::CMS; -use crate::widgets::{Layer, LayerImpl, Render}; +use crate::widgets::{Layer, Render}; use femtovg::{renderer::OpenGl, Canvas}; use gtk::Align; use std::{fmt::Debug, rc::Rc}; diff --git a/src/components/sidebar/sidebar.rs b/src/components/sidebar/sidebar.rs index 2cbf2e5..202de06 100644 --- a/src/components/sidebar/sidebar.rs +++ b/src/components/sidebar/sidebar.rs @@ -1,5 +1,4 @@ use crate::actions::*; -use crate::widgets::AssoElement; use abi_stable::type_level::trait_marker::Hash; use chrono::{DateTime, Utc}; use glib_macros::clone; @@ -193,11 +192,7 @@ impl SimpleComponent for SideBarModel { v.name.clone(), v.visiable, v.get_thumbnail(), - match v.get_associated_element() { - AssoElement::TimeSeries(_) => LayerStatus::BindToTime(Utc::now()), - AssoElement::Instant(_) => LayerStatus::Instance, - _ => LayerStatus::Instance, - }, + LayerStatus::Instance, ) }) .collect::>(); @@ -221,11 +216,11 @@ impl SimpleComponent for SideBarModel { v.name.clone(), v.visiable, v.get_thumbnail(), - match v.get_associated_element() { - AssoElement::TimeSeries(_) => LayerStatus::BindToTime(Utc::now()), - AssoElement::Instant(_) => LayerStatus::Instance, - _ => LayerStatus::Instance, - }, + LayerStatus::Instance, // match v.get_associated_element() { + // // AssoElement::TimeSeries(_) => LayerStatus::BindToTime(Utc::now()), + // // AssoElement::Instant(_) => LayerStatus::Instance, + // _ => LayerStatus::Instance, + // ) }) .collect::>(); diff --git a/src/map_tile.rs b/src/map_tile.rs index b4ba2eb..8ae4bab 100644 --- a/src/map_tile.rs +++ b/src/map_tile.rs @@ -2,7 +2,7 @@ use crate::components::messages::MonitorInputMsg; use crate::components::{MonitorCommand, MonitorModel}; use crate::coords::Range; use crate::map_tile_utils::lat_lon_to_zoom; -use crate::pipeline::element::{Target, TargetType}; +use crate::pipeline::{Target, TargetType}; use dirs::cache_dir; use femtovg::ImageSource; use futures::future::BoxFuture; diff --git a/src/pipeline/dispatcher.rs b/src/pipeline/dispatcher.rs index 514fdab..1d5e886 100644 --- a/src/pipeline/dispatcher.rs +++ b/src/pipeline/dispatcher.rs @@ -1,15 +1,14 @@ -use super::element::TargetType; use super::offscreen_renderer::{CanvasWrapper, OffscreenRenderer}; -use crate::{ - components::app::{Buffer, FILE_PATH_ROOT}, - CONFIG, -}; +use crate::CONFIG; use chrono::{prelude::*, Duration}; use once_cell::sync::Lazy; use regex::Regex; use std::{cell::Ref, collections::HashMap, path::PathBuf}; use tracing::*; +static DATETIME_FORMAT: Lazy = + Lazy::new(|| Regex::new(r"(?:%[YHMSmd](?:[-/:_]?%[YHMSmd])*)").unwrap()); + static REREMAP: Lazy> = Lazy::new(|| { let mut map = HashMap::new(); map.insert("%Y", r"\d{4}"); @@ -107,8 +106,8 @@ impl Dispatcher { current_time: DateTime, check_existed: bool, mut max_retry_time: usize, + file_path: &PathBuf, ) -> Option)>> { - let datetime_format: regex::Regex = Regex::new(r"%[YHMSmd](?:[-/:_]?%[YHMSmd])*").unwrap(); let config = CONFIG.lock().unwrap(); let path_format = config .plugins @@ -121,7 +120,7 @@ impl Dispatcher { } path_format.unwrap().get(name).map(|s| { let path = s.clone(); - let file_path = { FILE_PATH_ROOT.lock().unwrap().clone() }; + // let file_path = { file_path_root.lock().unwrap().clone() }; let path = if path.starts_with("./") { let file_root = file_root(&file_path, path.replace("./", "")); file_root.map(|root| { @@ -143,7 +142,7 @@ impl Dispatcher { } } - let need_formated = datetime_format.captures_iter(&path_str).collect::>(); + let need_formated = DATETIME_FORMAT.captures_iter(&path_str).collect::>(); let mut fore = self.fore_len; let mut back = 1; diff --git a/src/pipeline/element.rs b/src/pipeline/element.rs index f6d33c5..f5c4524 100644 --- a/src/pipeline/element.rs +++ b/src/pipeline/element.rs @@ -1,4 +1,4 @@ -use super::{offscreen_renderer::CanvasWrapper, Dispatcher, Pipeline}; +use super::{offscreen_renderer::CanvasWrapper, Dispatcher}; use crate::components::Widget; use crate::coords::cms::CMS; use crate::coords::Range; diff --git a/src/pipeline/element_imp.rs b/src/pipeline/element_imp.rs index beb003c..4a4367a 100644 --- a/src/pipeline/element_imp.rs +++ b/src/pipeline/element_imp.rs @@ -4,11 +4,13 @@ use crate::data::Radar2dRef; use crate::pipeline::offscreen_renderer::CanvasWrapper; use crate::predefined::color_mapper::{CMap, ColorMapper, ColorMapperComb, VMap}; use abi_stable::std_types::RVec; -use femtovg::{Paint, Path}; +use femtovg::renderer::OpenGl; +use femtovg::{Canvas, Paint, Path}; use ndarray::{ArrayBase, ArrayView1, ArrayView2, ArrayView3, ArrayViewD, Axis, Ix2, Ix3}; use num_traits::{AsPrimitive, FromPrimitive, Num, NumOps}; use radarg_plugin_interface::{DataShape, PluginResult, VecResult}; use std::any::Any; +use std::borrow::BorrowMut; use std::fmt::Debug; const EARTH_RADIUS: f64 = 6371.0; @@ -16,11 +18,11 @@ const EARTH_RADIUS: f64 = 6371.0; macro_rules! impl_element_imp_dispatch { ($({$Abc: ident, $t:ty},)+) => { impl ElementImpl { - pub fn process<'a, T>(&'a self, + pub fn process<'a,'b:'a, T>(&self, dims: (ArrayView2, ArrayView2), input: ElementInput<'a, T>, config: &dyn Any, - context: &mut Context + context: &mut Context<'b> ) where T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone + 'static, @@ -28,7 +30,7 @@ macro_rules! impl_element_imp_dispatch { match self { $( Self::$Abc(imp) => { - let config = config.downcast_ref::<<$t as ElementImp>::Config>().unwrap(); + let config = config.downcast_ref::<<$t as ElementImp>::Config<'a, T>>().unwrap(); if let ElementInput::$Abc(data) = input { imp.process(dims, data, config, context); } else { @@ -39,6 +41,17 @@ macro_rules! impl_element_imp_dispatch { } } + pub fn output_type(&self,) -> ElementOutput + { + match self { + $( + Self::$Abc(imp) => { + imp.output_type() + } + )+ + } + } + } }; } @@ -110,33 +123,56 @@ macro_rules! result_to_array { }; } -pub struct Context { +pub struct Context<'a> { pub cms: CMS, - pub canvas: CanvasWrapper, + pub canvas: &'a mut Canvas, } -impl Context { - pub fn new(cms: CMS, canvas: CanvasWrapper) -> Self { - Self { cms, canvas } +impl<'a> Context<'a> { + pub fn new(cms: CMS, canvas: &'a mut T) -> Self + where + T: BorrowMut> + 'a, + { + Self { + cms, + canvas: canvas.borrow_mut(), + } } } +#[derive(Debug, Clone, Copy)] +pub enum ElementOutput { + Target, + None, +} + pub trait ElementImp: Debug + TryFrom + Into { - type Config; + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + 'a>: ElementConfig + where + Self: 'a; type Input<'a, T: 'a> where Self: 'a; - fn process<'a, T>( - &'a self, + + fn process<'a, 'b: 'a, T>( + &self, dims: (ArrayView2, ArrayView2), input: Self::Input<'a, T>, - config: &Self::Config, - context: &mut Context, + config: &Self::Config<'a, T>, + context: &mut Context<'b>, ) where T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone; + + fn output_type(&self) -> ElementOutput; } -#[derive(Debug)] +pub trait ElementConfig { + fn upcast_ref<'short, 'long: 'short>(&'long self) -> &'short Self { + self + } +} + +#[derive(Debug, Clone, Copy)] pub struct GridImp(); pub struct GridImpConfig @@ -147,12 +183,12 @@ where } impl GridImp { - fn draw_2d( + fn draw_2d<'a, 'b: 'a, T>( &self, config: &GridImpConfig, - data: ArrayView2, + data: ArrayView2<'a, T>, dims: (ArrayView2, ArrayView2), - context: &mut Context, + context: &mut Context<'b>, ) where T: PartialEq + PartialOrd + Copy + Clone + Send + Sync + Debug, { @@ -195,14 +231,15 @@ impl GridImp { } impl ElementImp for GridImp { - type Config = GridImpConfig; + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq> = GridImpConfig where + T: 'a; type Input<'a, T: 'a> = ArrayViewD<'a, T>; - fn process<'a, T>( - &'a self, + fn process<'a, 'b: 'a, T>( + &self, dims: (ArrayView2, ArrayView2), input: Self::Input<'a, T>, - config: &Self::Config, - context: &mut Context, + config: &Self::Config<'a, T>, + context: &mut Context<'b>, ) where T: Send + Sync + Debug + PartialOrd + PartialEq + Copy + Clone, { @@ -214,11 +251,33 @@ impl ElementImp for GridImp { let data = input.into_dimensionality::().unwrap(); } } + + fn output_type(&self) -> ElementOutput { + ElementOutput::Target + } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct MultiLayerGridImp(); +impl MultiLayerGridImp { + fn draw<'a, 'b: 'a, T>( + &self, + dims: (ArrayView2, ArrayView2), + data: ArrayViewD<'a, T>, + config: &MultiLayerGridImpConfig, + context: &mut Context<'b>, + ) where + T: PartialOrd + PartialEq + Send + Sync + Debug + Copy, + { + let two = config.twod.clone(); + let _layer = data.into_dimensionality::().unwrap(); + let data = _layer.index_axis(Axis(0), config.layer).into_dyn(); + + two.process(dims, data, &config.two_d_config, context); + } +} + pub struct MultiLayerGridImpConfig where T: PartialOrd + PartialEq + Send + Sync + Debug, @@ -229,29 +288,28 @@ where } impl ElementImp for MultiLayerGridImp { - type Config = MultiLayerGridImpConfig; + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq + 'a> = + MultiLayerGridImpConfig; type Input<'a, T: 'a> = ArrayViewD<'a, T>; - fn process<'a, T>( - &'a self, + fn process<'a, 'b: 'a, T>( + &self, dims: (ArrayView2, ArrayView2), input: Self::Input<'a, T>, - config: &Self::Config, - context: &mut Context, + config: &Self::Config<'a, T>, + context: &mut Context<'b>, ) where T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone, { - let data = input.into_dimensionality::().unwrap(); - let layer = config.layer; - let layer_data = data.index_axis(Axis(0), layer); + self.draw(dims, input, config.upcast_ref(), context); + } - config - .twod - .process(dims, layer_data.into_dyn(), &config.two_d_config, context); + fn output_type(&self) -> ElementOutput { + ElementOutput::Target } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct PolarElementImp(); pub struct PolarElementConfig @@ -316,13 +374,13 @@ impl PolarElementImp { Some((final_degree, final_distance)) } - fn draw( + fn draw<'a, T>( &self, dims: (ArrayView2, ArrayView2), center: (f64, f64), data: ArrayView2, - config: &PolarElementConfig, - context: &mut Context, + config: &'a PolarElementConfig, + context: &mut Context<'a>, ) where T: PartialOrd + PartialEq + Send + Sync + Debug + Copy, { @@ -364,28 +422,41 @@ impl PolarElementImp { } impl ElementImp for PolarElementImp { - type Config = PolarElementConfig; + type Config<'a, T: Sync + Send + Debug + PartialOrd + PartialEq> = PolarElementConfig where + T: 'a; type Input<'a, T: 'a> = ArrayViewD<'a, T>; - fn process<'a, T>( - &'a self, + fn process<'a, 'b: 'a, T>( + &self, dims: (ArrayView2, ArrayView2), input: Self::Input<'a, T>, - config: &Self::Config, - context: &mut Context, + config: &Self::Config<'a, T>, + context: &mut Context<'b>, ) where T: Sync + Send + Debug + PartialOrd + PartialEq + Copy + Clone, { let shape = input.shape(); if shape.len() == 2 { let data = input.into_dimensionality::().unwrap(); - self.draw(dims, config.center, data, config, context); + // self.draw(dims, config.center, data, config, context); } else if shape.len() == 3 { let data = input.into_dimensionality::().unwrap(); } } + + fn output_type(&self) -> ElementOutput { + ElementOutput::Target + } } -#[derive(Debug)] +impl ElementConfig for GridImpConfig where T: Sync + Send + Debug + PartialOrd + PartialEq {} +impl ElementConfig for MultiLayerGridImpConfig where + T: Sync + Send + Debug + PartialOrd + PartialEq +{ +} +impl ElementConfig for PolarElementConfig where T: Sync + Send + Debug + PartialOrd + PartialEq +{} + +#[derive(Debug, Clone, Copy)] pub enum ElementImpl { Grid(GridImp), MultiLayerGrid(MultiLayerGridImp), diff --git a/src/pipeline/mod.rs b/src/pipeline/mod.rs index 6aac0a5..6ce9b4e 100644 --- a/src/pipeline/mod.rs +++ b/src/pipeline/mod.rs @@ -1,9 +1,9 @@ pub mod dispatcher; -pub mod element; +// pub mod element; // mod element_impl; -// mod new_element; +pub mod new_element; // mod new_element_impl; -mod new_pipeline; +// mod new_pipeline; pub mod offscreen_renderer; // mod predefined; pub mod element_imp; @@ -12,7 +12,8 @@ pub mod runner; // pub mod utils; pub use dispatcher::Dispatcher; -pub use element::*; +// pub use element::*; // pub use element_impl::*; -pub use new_pipeline::Pipeline; +// pub use new_pipeline::Pipeline; +pub use new_element::*; pub use offscreen_renderer::OffscreenRenderer; diff --git a/src/pipeline/new_element.rs b/src/pipeline/new_element.rs index 13e0b32..3d4aa13 100644 --- a/src/pipeline/new_element.rs +++ b/src/pipeline/new_element.rs @@ -1,14 +1,22 @@ use super::dispatcher; -use super::new_element_impl::ElementConfig; -use super::new_element_impl::ElementImp; +use super::element_imp::Context; +use super::element_imp::ElementImpl; +use super::element_imp::ElementOutput; +use super::offscreen_renderer; use super::offscreen_renderer::CanvasWrapper; +use super::runner::Runner; use super::Dispatcher; -use super::RenderResult; -use super::Target; use crate::coords::cms::CMS; +use crate::coords::Range; +use crate::data::MetaInfo; use crate::pipeline::OffscreenRenderer; +use crate::widgets::Render; use crate::PLUGIN_MANAGER; +use crate::RUNTIME; use chrono::prelude::*; +use femtovg::ImageFlags; +use femtovg::ImageId; +use futures::future::BoxFuture; use num_traits::AsPrimitive; use num_traits::FromPrimitive; use num_traits::Num; @@ -16,9 +24,12 @@ use num_traits::NumOps; use quick_cache::sync::Cache; use radarg_plugin_interface::PluginResult; use std::any::Any; +use std::borrow::BorrowMut; +use std::cell::RefCell; use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hash; +use std::path::PathBuf; use std::rc::Rc; use std::sync::atomic::AtomicI32; use std::sync::Arc; @@ -26,171 +37,546 @@ use std::sync::RwLock; use std::time::Duration; use tokio::sync::oneshot; use tokio::sync::{mpsc, Mutex}; +use tracing::subscriber; static ELEMENT_ID: AtomicI32 = AtomicI32::new(0); pub type ElementID = i32; -pub type Buffer = Cache>>; +pub type KVBuffer = Cache; +pub type Buffer = KVBuffer>>; -pub struct Element -where - V: Num + NumOps + PartialOrd + FromPrimitive + AsPrimitive + Send + Sync + Debug, -{ - pub id: i32, +#[derive(Debug, Hash, Eq, PartialEq, Clone)] +pub struct Key { + pub id: ElementID, pub name: String, - pub description: String, - imp: Arc>, - buffer: Arc>>, - config: Arc>>, - subscribers: Arc>>>>>>>, - cancellers: Arc>>>, - - dispatcher: Rc, - cms: Arc>, + pub root: std::path::PathBuf, + pub datetime: Option>, } -impl Element -where - V: Num + NumOps + PartialOrd + FromPrimitive + AsPrimitive + Send + Sync + Debug, -{ +#[derive(Clone, Debug)] +pub struct Target { + pub target: TargetType, + pub thumbnail: Option, + pub width: f32, + pub height: f32, + pub bounds: (Range, Range), +} + +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)] +pub enum TargetType { + ImageId(ImageId), + Mem(Vec), + NativeBuffer(Vec), +} + +impl Target { pub fn new( - name: String, - description: String, - imp: ElementImp, - config: Box, + target: TargetType, + width: f32, + height: f32, + bounds: (Range, Range), + thumbnail: Option, + // data: Option>, + ) -> Self { + Self { + target, + width, + height, + bounds, + thumbnail, + // data, + } + } + + pub fn size(&self, cms: &Render) -> (f32, f32) { + let (x, y) = self.bounds; + + let p1 = (x.0, y.0); + let p2 = (x.1, y.1); + + let (x1, y1) = cms.map(p1).unwrap(); + let (x2, y2) = cms.map(p2).unwrap(); + + ((x2 - x1).abs(), (y2 - y1).abs()) + } + + pub fn native_buffer_to_native_texture( + &self, + gl: &glow::Context, + flags: ImageFlags, + ) -> glow::NativeTexture { + if let TargetType::NativeBuffer(ref mem) = self.target { + use glow::*; + let texture = unsafe { + let id = gl.create_texture().unwrap(); + gl.bind_texture(glow::TEXTURE_2D, Some(id)); + gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1); + gl.pixel_store_i32(glow::UNPACK_ROW_LENGTH, 3000 as i32); + gl.pixel_store_i32(glow::UNPACK_SKIP_PIXELS, 0); + gl.pixel_store_i32(glow::UNPACK_SKIP_ROWS, 0); + id + }; + let width = 3000; // 纹理宽度 + let height = 3000; // 纹理高度 + unsafe { + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, // level + glow::RGBA as i32, // internal_format + width, + height, + 0, // border + glow::RGBA, // format + glow::UNSIGNED_BYTE, // type + Some(&mem), // pixels + ); + } + + if flags.contains(ImageFlags::GENERATE_MIPMAPS) { + if flags.contains(ImageFlags::NEAREST) { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::NEAREST_MIPMAP_NEAREST as i32, + ); + } + } else { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR_MIPMAP_LINEAR as i32, + ); + } + } + } else if flags.contains(ImageFlags::NEAREST) { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::NEAREST as i32, + ); + } + } else { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + glow::LINEAR as i32, + ); + } + } + + if flags.contains(ImageFlags::NEAREST) { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::NEAREST as i32, + ); + } + } else { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::LINEAR as i32, + ); + } + } + + if flags.contains(ImageFlags::REPEAT_X) { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_S, + glow::REPEAT as i32, + ); + } + } else { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_S, + glow::CLAMP_TO_EDGE as i32, + ); + } + } + + if flags.contains(ImageFlags::REPEAT_Y) { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_T, + glow::REPEAT as i32, + ); + } + } else { + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_T, + glow::CLAMP_TO_EDGE as i32, + ); + } + } + + unsafe { + gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 4); + gl.pixel_store_i32(glow::UNPACK_ROW_LENGTH, 0); + gl.pixel_store_i32(glow::UNPACK_SKIP_PIXELS, 0); + gl.pixel_store_i32(glow::UNPACK_SKIP_ROWS, 0); + } + + if flags.contains(ImageFlags::GENERATE_MIPMAPS) { + unsafe { + gl.generate_mipmap(glow::TEXTURE_2D); + } + } + + unsafe { + gl.bind_texture(glow::TEXTURE_2D, None); + } + + return texture; + } else { + panic!("Target is not mem"); + } + } + + pub fn origin(&self, cms: &Render) -> (f32, f32) { + let (x, y) = self.bounds; + let p1 = (x.0, y.1); + cms.map(p1).unwrap() + } + + pub fn set_target(&mut self, target: TargetType) { + self.target = target; + } +} + +#[derive(Debug, Clone)] +pub struct DataTarget { + data: Option, + target: Target, +} + +impl DataTarget { + pub fn new(data: Option, target: Target) -> Self { + Self { data, target } + } + + pub fn take_data(&mut self) -> Option { + self.data.take() + } + + pub fn data(&self) -> Option<&PluginResult> { + self.data.as_ref() + } + + pub fn mut_data(&mut self) -> Option<&mut PluginResult> { + self.data.as_mut() + } +} + +#[derive(Debug, Clone)] +pub struct RenderResult { + target: DataTarget, + meta_info: MetaInfo, +} + +impl RenderResult { + pub fn new(target: DataTarget, meta_info: MetaInfo) -> Self { + Self { target, meta_info } + } + + pub fn get_meta_info(&self) -> MetaInfo { + self.meta_info.clone() + } + + pub fn get_mut_target(&mut self) -> &mut Target { + &mut self.target.target + } +} + +#[derive(Debug)] +pub struct Element { + pub id: i32, + pub name: String, + pub cache: bool, + root: std::path::PathBuf, + config: Arc, + imp: ElementImpl, + subscribers: Arc>>>>>>, + cancellers: Arc>>>, + current_key: Option, + dispatcher: Rc, + buffer: Arc>, + file_pool: Arc>>, + cms: CMS, +} + +pub enum ElementEvent<'a> { + Init, + DateTime(DateTime), + Key(&'a Key), +} + +impl Element { + pub fn new( + name: impl Into, cms: CMS, dispatcher: Rc, + cache: bool, + config: Arc, + root: std::path::PathBuf, + + buffer: Arc>, + file_pool: Arc>>, + imp: ElementImpl, ) -> Self { let id = ELEMENT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed); Element { id, - name, - description, - imp: Arc::new(imp), - buffer: Arc::new(Mutex::new(Buffer::new(100))), + name: name.into(), + cache, + imp, + config, + root, subscribers: Arc::new(Mutex::new(HashMap::new())), - config: Arc::new(RwLock::new(config)), cancellers: Arc::new(Mutex::new(HashMap::new())), - cms: Arc::new(Mutex::new(cms)), + cms: cms, + current_key: None, + buffer, + file_pool, dispatcher, } } - pub fn new_with_buffer( - name: String, - description: String, - imp: ElementImp, - buffer: Buffer, - config: Box, - cms: CMS, - dispatcher: Rc, - ) -> Self { - let id = ELEMENT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - Element { - id, - name, - description, - imp: Arc::new(imp), - buffer: Arc::new(Mutex::new(buffer)), - subscribers: Arc::new(Mutex::new(HashMap::new())), - config: Arc::new(RwLock::new(config)), - cancellers: Arc::new(Mutex::new(HashMap::new())), - cms: Arc::new(Mutex::new(cms)), - dispatcher, - } - } + pub fn r<'a>(&self, event: ElementEvent<'a>, render: &Render) { + let need_cache = self.cache; + let format = self.imp.output_type(); - pub async fn get(&self, key: T) -> Arc> { - { - let cache = self.buffer.lock().await; - if cache.peek(&key).is_some() { - return cache.get(&key).unwrap(); + match event { + ElementEvent::Init => { + let data = self.file_pool.get(&self.root); + if let Some(data) = data {} + } + + ElementEvent::DateTime(time) => { + let path = self.dispatcher.get_single_path(&self.name, time, true); + path.map(|path| { + let data = self.file_pool.get(&path); + }); + } + + ElementEvent::Key(key) => { + self.buffer.get(key); } } + // match key { + // ElementEvent::Init => { + // let data = self.get_file(&self.root); + // } + // ElementEvent::DateTime(key) => { + // let key = &Key { + // id: self.id, + // name: self.name.clone(), + // root: self.root.clone(), + // datetime: Some(key), + // }; + + // if self.cache { + // if let ElementOutput::Target = self.imp.output_type() { + // let target = self.run(key.to_owned()).await; + // // if let Some(target) = target { + // // let mut target = target.lock().await; + // // let target = target.get_mut_target(); + // // render.draw_img(target); + // // } + // } else { + // let path = (&*self.dispatcher).borrow_mut().get_single_path( + // &self.name, + // key.datetime.to_owned().unwrap(), + // true, + // ); + + // if let Some(path) = path { + // let data = self.get_file(path); + // let mut _canvas = render.get_canvas(); + // let mut canvas = _canvas.as_mut().unwrap(); + // let cms = render.create_cms(); + // let context = Context::new(cms, canvas); + // let mut runner = Runner::new(self.imp, self.config.clone(), context); + // runner.run_without_target(&data); + // } + // } + // } else { + // let path = (&*self.dispatcher).borrow_mut().get_single_path( + // &self.name, + // key.datetime.to_owned().unwrap(), + // true, + // ); + // if let Some(path) = path { + // let data = self.get_file(path); + // let mut _canvas = render.get_canvas(); + // let mut canvas = _canvas.as_mut().unwrap(); + // let cms = render.create_cms(); + // let context = Context::new(cms, canvas); + // let mut runner = Runner::new(self.imp, self.config.clone(), context); + // runner.run_without_target(&data); + // } + // } + // } + + // ElementEvent::Data(data) => { + // let mut _canvas = render.get_canvas(); + // let mut canvas = _canvas.as_mut().unwrap(); + // let cms = render.create_cms(); + // let context = Context::new(cms, canvas); + // let mut runner = Runner::new(self.imp, self.config.clone(), context); + // runner.run_without_target(&data); + // } + // } + } + + fn _rrrr(&self, data: &PluginResult, need_cache: bool, output_type: ElementOutput) { + match output_type { + ElementOutput::Target => {} + + _ => {} + } + } + + fn get_file(&self, path: impl AsRef) -> PluginResult { + let loader = PLUGIN_MANAGER.get_plugin_by_name("etws_loader").unwrap(); + let path = path.as_ref().as_os_str().to_str().unwrap(); + let mut loaded_data = loader.load(path.into()).unwrap(); + + loaded_data + } + + fn current_key(&self) -> Key { + self.current_key.clone().unwrap() + } + + async fn run(&self, key: Key) -> Option>> { { - let mut subscribers = self.subscribers.lock().await; - let (tx, rx) = oneshot::channel(); - if subscribers.contains_key(&key) { - subscribers.get_mut(&key).unwrap().push(tx); + let cache = &self.buffer; + if cache.peek(&key).is_some() { + return Some(cache.get(&key).unwrap()); + } + } + + let datetime = key.datetime.unwrap(); + + let dispatcher = (&*self.dispatcher); + + let current_path = dispatcher.get_single_path(&self.name, datetime, true); + let paths = dispatcher.get_path(&self.name, datetime, true, 3, &self.root); + if let Some(paths) = paths { + paths.iter().for_each(|(p, d)| { + let key = self.generate_key(d.to_owned()); + let f = self._run(p, &key); + let handle = tokio::task::spawn(f); + }); + } + + if let Some(path) = current_path { + let key = self.generate_key(datetime); + let f = self._run(path, &key); + let handle = tokio::task::spawn(f); + let result = handle.await.unwrap(); + Some(result) + } else { + None + } + } + fn generate_key(&self, datetime: DateTime) -> Key { + Key { + id: self.id, + name: self.name.clone(), + root: self.root.clone(), + datetime: Some(datetime), + } + } + + fn _run( + &self, + p: impl AsRef, + key: &Key, + ) -> BoxFuture<'static, Arc>> { + let (tx, rx) = oneshot::channel(); + let buffer = self.buffer.clone(); + let config = self.config.clone(); + let canceller = self.cancellers.clone(); + let subscriber = self.subscribers.clone(); + let mut dialog_cms = self.cms.clone(); + let mut dialog_config = self.config.clone(); + let mut dialog_imp = self.imp.clone(); + + let _key = key.to_owned(); + Box::pin(async move { + let key = &_key; + let mut subscribers = subscriber.lock().await; + if subscribers.contains_key(key) { + subscribers.get_mut(key).unwrap().push(tx); drop(subscribers); } else { let (canceller_tx, canceller_rx) = oneshot::channel(); - subscribers.insert(key, vec![tx]); + subscribers.insert(key.to_owned(), vec![tx]); drop(subscribers); - { - let mut cancellers = self.cancellers.lock().await; - cancellers.insert(key, canceller_tx); - } - - let buffer = self.buffer.clone(); - let config = self.config.clone(); - let imp = self.imp.clone(); - let cancellers = self.cancellers.clone(); - let subscribers = self.subscribers.clone(); + let mut cancellers = canceller.lock().await; + cancellers.insert(key.clone(), canceller_tx); + drop(cancellers); use tokio::task; + + let key = key.to_owned(); tokio::spawn(async move { + let new_key = key.clone(); tokio::select! { _ = async move { - - tokio::time::sleep(Duration::new(5, 0)).await; let handle = task::spawn_blocking(move || { - let config = config.read().unwrap(); - let config: &ElementConfig = &*(*config); + let mut offscreen_renderer = OffscreenRenderer::new(3000, 3000).unwrap(); + let mut canvas = offscreen_renderer.create_canvas(); + let mut context = Context::new(dialog_cms, &mut canvas); + let mut runner = Runner::new(dialog_imp, dialog_config, context); let loader = PLUGIN_MANAGER.get_plugin_by_name("etws_loader").unwrap(); - let mut loaded_data = loader.load(path.as_ref().into()).unwrap(); + let mut loaded_data = loader.load("".into()).unwrap(); let meta = loaded_data.meta.clone().into(); - let mut offscreen_renderer = OffscreenRenderer::new(3000, 3000).unwrap(); - // imp.render() + let target = runner.run(&loaded_data); + + RenderResult::new( + DataTarget::new(Some(loaded_data), target), + meta + ) }); let result = handle.await.unwrap(); - - { - let bf = Arc::new(Mutex::new(result)); - buffer.lock().await.insert(key, bf.clone()); - let mut subscribers = subscribers.lock().await; - for tx in subscribers.remove(&key).unwrap() { - let _ = tx.send(bf.clone()); - } + let bf = Arc::new(Mutex::new(result)); + buffer.insert(key.clone(), bf.clone()); + let mut subscribers = subscriber.lock().await; + for tx in subscribers.remove(&key).unwrap() { + let _ = tx.send(bf.clone()); } } => {} _ = canceller_rx => {} } - let mut cancellers = cancellers.lock().await; - cancellers.remove(&key); + let mut cancellers = canceller.lock().await; + cancellers.remove(&new_key); }); } rx.await.unwrap() - } + }) } - pub async fn cancel_task_for_timestamp(&self, key: T) { - let mut cancellers = self.cancellers.lock().await; - if let Some(canceller) = cancellers.remove(&key) { - let _ = canceller.send(()); // 发送取消信号 - } - } - - pub async fn cancel_all_tasks(&self) { - let mut cancellers = self.cancellers.lock().await; - for (_timestamp, canceller) in cancellers.drain() { - let _ = canceller.send(()); // 发送取消信号 - } + fn key(&self) -> String { + format!("{}-{}", self.id, self.name) } } - -pub trait ElementImpl: Debug + Send + Sync + 'static { - type Config; - fn render( - &self, - data: &PluginResult, - canvas: &mut CanvasWrapper, - cms: &mut CMS, - config: &Self::Config, - ) -> Target; -} diff --git a/src/pipeline/offscreen_renderer.rs b/src/pipeline/offscreen_renderer.rs index 4fabef7..68b0701 100644 --- a/src/pipeline/offscreen_renderer.rs +++ b/src/pipeline/offscreen_renderer.rs @@ -1,4 +1,3 @@ -use crate::pipeline::element::Target; use euclid::Size2D; use femtovg::{renderer::OpenGl, Canvas}; use gl; @@ -15,6 +14,8 @@ use surfman::{ NativeConnection, NativeDevice, }; +use super::Target; + pub struct OffscreenRenderer { context: Arc>, device: Device, @@ -36,7 +37,7 @@ impl OffscreenRenderer { let mut device = connection.create_device(&adapter)?; let descriptor = device.create_context_descriptor(&surfman::ContextAttributes { - version: surfman::GLVersion::new(4, 1), + version: surfman::GLVersion::new(3, 3), flags: ContextAttributeFlags::ALPHA .union(ContextAttributeFlags::DEPTH) .union(ContextAttributeFlags::STENCIL), @@ -196,3 +197,15 @@ impl BorrowMut> for CanvasWrapper { self } } + +impl AsRef> for CanvasWrapper { + fn as_ref(&self) -> &Canvas { + &self + } +} + +impl AsMut> for CanvasWrapper { + fn as_mut(&mut self) -> &mut Canvas { + self + } +} diff --git a/src/pipeline/renders.rs b/src/pipeline/renders.rs index c2e0a8b..bc252e7 100644 --- a/src/pipeline/renders.rs +++ b/src/pipeline/renders.rs @@ -1,7 +1,8 @@ use crate::coords::cms::CMS; -use crate::pipeline::element::Target; use femtovg::{renderer::OpenGl, Canvas}; +use super::Target; + pub trait DataRenderer<'a> { type Data; fn render( diff --git a/src/pipeline/runner.rs b/src/pipeline/runner.rs index f635c4b..98409a5 100644 --- a/src/pipeline/runner.rs +++ b/src/pipeline/runner.rs @@ -1,10 +1,11 @@ use std::{any::Any, sync::Arc}; -use femtovg::RenderTarget; +use femtovg::{renderer::OpenGl, Canvas, RenderTarget}; use gl::types::GLvoid; use image::Rgba; -use ndarray::{ArrayView1, ArrayViewD}; +use ndarray::{Array2, ArrayBase, ArrayView1, ArrayViewD}; use radarg_plugin_interface::{PluginResult, VecResult}; +use smallvec::Array; use crate::{ pipeline::{ @@ -34,14 +35,14 @@ macro_rules! impl_for_runner { }; } -pub struct Runner { +pub struct Runner<'a> { imp: ElementImpl, config: Arc, - context: Context, + context: Context<'a>, } -impl Runner { - pub fn new(imp: ElementImpl, config: Arc, context: Context) -> Self { +impl<'a> Runner<'a> { + pub fn new(imp: ElementImpl, config: Arc, context: Context<'a>) -> Self { Self { imp, config, @@ -50,6 +51,49 @@ impl Runner { } pub fn run(&mut self, data: &PluginResult) -> Target { + use femtovg::{ImageFlags, PixelFormat::Rgba8}; + let canvas = &mut self.context.canvas; + let (w, h) = (canvas.width(), canvas.height()); + + let new_img = canvas + .create_image_empty(w as usize, h as usize, Rgba8, ImageFlags::empty()) + .expect("Can't Create Image"); + canvas.image_size(new_img).unwrap(); + canvas.set_render_target(RenderTarget::Image(new_img)); + + // Drawing + let dims = self.run_without_target(data); + + // Reading Pixels + let mut pixels: Vec = vec![0; w as usize * h as usize * 4]; + unsafe { + gl::ReadPixels( + 0, + 0, + w as i32, + h as i32, + gl::RGBA, + gl::UNSIGNED_BYTE, + pixels.as_mut_ptr() as *mut GLvoid, + ); + debug_assert_eq!(gl::GetError(), gl::NO_ERROR); + } + self.context.canvas.set_render_target(RenderTarget::Screen); + let d1_start = (dims.0.view()).first().unwrap().clone(); + let d1_end = (dims.0.view()).last().unwrap().clone(); + let d2_start = dims.1.view().first().unwrap().clone(); + let d2_end = dims.1.view().last().unwrap().clone(); + + Target::new( + TargetType::NativeBuffer(pixels), + w as f32, + h as f32, + ((d1_start, d1_end).into(), (d2_start, d2_end).into()), + None, + ) + } + + pub fn run_without_target(&mut self, data: &PluginResult) -> (Array2, Array2) { let block = data.blocks.first().unwrap(); let data = &block.data; let dims = &block.dimension_values; @@ -71,17 +115,10 @@ impl Runner { let size = block.size.to_owned().to_vec(); let config = &*self.config; let imp: &ElementImpl = &self.imp; - let context: &mut Context = &mut self.context; + let context = &mut self.context; let cms = &mut context.cms; let canvas = &mut context.canvas; let (w, h) = (canvas.width(), canvas.height()); - use femtovg::{ImageFlags, PixelFormat::Rgba8}; - - let new_img = canvas - .create_image_empty(w as usize, h as usize, Rgba8, ImageFlags::empty()) - .expect("Can't Create Image"); - canvas.image_size(new_img).unwrap(); - canvas.set_render_target(RenderTarget::Image(new_img)); let lat_start = dims.1.view().first().unwrap().clone(); let lat_end = dims.1.view().last().unwrap().clone(); @@ -112,35 +149,7 @@ impl Runner { { U64 }, { U32 }, ); - context.canvas.flush(); - - let mut pixels: Vec = vec![0; w as usize * h as usize * 4]; - unsafe { - gl::ReadPixels( - 0, - 0, - w as i32, - h as i32, - gl::RGBA, - gl::UNSIGNED_BYTE, - pixels.as_mut_ptr() as *mut GLvoid, - ); - debug_assert_eq!(gl::GetError(), gl::NO_ERROR); - } - let d1_start = (dims.0.view()).first().unwrap().clone(); - let d1_end = (dims.0.view()).last().unwrap().clone(); - - let d2_start = dims.1.view().first().unwrap().clone(); - let d2_end = dims.1.view().last().unwrap().clone(); - context.canvas.set_render_target(RenderTarget::Screen); - - Target::new( - TargetType::NativeBuffer(pixels), - w as f32, - h as f32, - ((d1_start, d1_end).into(), (d2_start, d2_end).into()), - None, - ) + dims } } diff --git a/src/predefined/widgets.rs b/src/predefined/widgets.rs index 3d4dd0b..be79cae 100644 --- a/src/predefined/widgets.rs +++ b/src/predefined/widgets.rs @@ -1,6 +1,6 @@ use crate::components::widget::{Widget, WidgetType}; use crate::predefined::color_mapper::ColorMapper; -use crate::widgets::{AssoElement, Layer}; +use crate::widgets::Layer; use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path}; use num_traits::*; use std::any::Any; @@ -39,17 +39,6 @@ impl Widget for ColorBar { let first = layers.first().unwrap(); - match first.get_associated_element() { - AssoElement::Instant(i) => { - let imp = i.imp(); - } - AssoElement::TimeSeries(t) => { - let c = t.lock().unwrap(); - let imp = c.imp(); - } - _ => {} - } - // for ((i, color), label) in self // .color_list // .iter() diff --git a/src/widgets/render/imp.rs b/src/widgets/render/imp.rs index 48c320c..88cc8c9 100644 --- a/src/widgets/render/imp.rs +++ b/src/widgets/render/imp.rs @@ -4,7 +4,7 @@ use super::{Layer, WindowCoord}; use crate::coords::proj::Mercator; use crate::coords::Mapper; use crate::map_tile::MapTile; -use crate::pipeline::element::{Target, TargetType}; +use crate::pipeline::new_element::{Target, TargetType}; use femtovg::{Canvas, Color, FontId, Paint, Renderer}; use gtk::glib::{self, prelude::*, Properties}; use gtk::prelude::*; diff --git a/src/widgets/render/interior/layers.rs b/src/widgets/render/interior/layers.rs index 4a6c630..8f1c337 100644 --- a/src/widgets/render/interior/layers.rs +++ b/src/widgets/render/interior/layers.rs @@ -1,30 +1,19 @@ use super::super::Render; -use crate::coords::cms::CMS; use crate::errors::PipelineError; -use crate::pipeline::element::{self, Target}; -use crate::pipeline::offscreen_renderer::CanvasWrapper; -use chrono::{prelude::*, DateTime}; +use crate::pipeline::new_element::{self, Target}; +use crate::pipeline::new_element::{Element, ElementEvent}; +use crate::RUNTIME; use femtovg::{renderer::OpenGl, Canvas}; +use std::rc::Rc; use std::{ fmt::Debug, sync::{Arc, Mutex}, }; -type PrepareFunc = Arc< - Mutex< - Option< - Box>, CMS) -> Target + Sync + Send>, - >, - >, ->; -type DrawFunc = Arc; -pub type LayerImplSync = Arc>>; - -#[derive(Clone)] -pub enum AssoElement { - TimeSeries(Arc>), - Instant(element::InstantElement), - Test, +#[derive(Clone, Copy, Debug)] +pub enum ElementType { + Asso, + Indenpendent, } #[derive(Clone)] @@ -32,8 +21,8 @@ pub struct Layer { pub visiable: bool, pub alpha: f32, pub name: String, - associated_element: AssoElement, - time: Option>, + element_type: ElementType, + element: Rc, } impl Debug for Layer { @@ -44,64 +33,29 @@ impl Debug for Layer { } } -pub trait LayerImpl: Debug { - fn draw(&self, canvas: &mut Canvas, cms: &CMS) -> Option; -} - impl Layer { - pub fn new(visiable: bool, layer_name: String, element: AssoElement) -> Self { + pub fn new( + visiable: bool, + layer_name: String, + element: Rc, + element_type: ElementType, + ) -> Self { Layer { alpha: 1.0, visiable, name: layer_name, - associated_element: element, - time: None, + element, + element_type, } } - pub fn set_time(&mut self, time: DateTime) { - self.time = Some(time); - } - - pub fn draw(&mut self, render: &Render, window_size: (f32, f32)) -> Result<(), PipelineError> { + pub(super) fn draw( + &mut self, + render: &Render, + window_size: (f32, f32), + ) -> Result<(), PipelineError> { if self.visiable { - match self.associated_element { - AssoElement::Instant(ref mut e) => { - e.render(render); - } - AssoElement::TimeSeries(ref e) => { - let mut e = e.lock().unwrap(); - let mut buffer = e.buffer.lock().unwrap(); - let mut result = buffer.get_mut(&self.time.unwrap()).map(|x| x.as_mut()); - - if result.is_none() { - return Ok(()); - } - - if let Some(result) = result.unwrap() { - let target = result.get_mut_target(); - - // let mut canvas = render.get_canvas(); - // let mut canvas = canvas.as_mut().unwrap(); - // let (ox, oy) = target.origin(render); - // let (x, y) = target.size(render); - - render.draw_img(target); - - // let result_id = match target.target { - // TargetType::ImageId(id) => id, - // TargetType::Mem(ref mem) => { - // let converted = canvas - // .load_image_mem(mem, femtovg::ImageFlags::empty()) - // .unwrap(); - // target.set_target(TargetType::ImageId(converted)); - // converted - // } - // }; - } - } - _ => {} - } + self.element.r(ElementEvent::Init, render); return Ok(()); } @@ -119,16 +73,4 @@ impl Layer { pub fn change_visiable(&mut self, visiable: bool) { self.visiable = visiable; } - - pub fn pop_associated_element(&mut self) -> AssoElement { - std::mem::replace(&mut self.associated_element, AssoElement::Test) - } - - pub fn get_associated_element(&self) -> &AssoElement { - &self.associated_element - } - - pub fn set_associated_element(&mut self, element: AssoElement) { - self.associated_element = element; - } } diff --git a/src/widgets/render/interior/mod.rs b/src/widgets/render/interior/mod.rs index 7507847..2431dcf 100644 --- a/src/widgets/render/interior/mod.rs +++ b/src/widgets/render/interior/mod.rs @@ -9,7 +9,7 @@ use core_extensions::SelfOps; use femtovg::{renderer::OpenGl, Canvas, ImageFlags}; use femtovg::{Paint, Path}; use gtk::glib; -pub use layers::{AssoElement, Layer, LayerImpl, LayerImplSync}; +pub use layers::{ElementType, Layer}; use relm4::channel; use std::cell::Ref; use tokio::task; diff --git a/src/widgets/render/mod.rs b/src/widgets/render/mod.rs index 3e85cc2..ea88d17 100644 --- a/src/widgets/render/mod.rs +++ b/src/widgets/render/mod.rs @@ -10,7 +10,7 @@ use crate::coords::cms::CMS; use crate::coords::{Mapper, Range}; use crate::errors::PipelineError; use crate::map_tile::MapTile; -use crate::pipeline::element::{Target, TargetType}; +use crate::pipeline::{Target, TargetType}; use adw::prelude::{GLAreaExt, GestureDragExt}; use femtovg::ImageFlags; use geo_types::LineString; diff --git a/src/widgets/render/predefined/gis.rs b/src/widgets/render/predefined/gis.rs index 207c620..68b1e37 100644 --- a/src/widgets/render/predefined/gis.rs +++ b/src/widgets/render/predefined/gis.rs @@ -2,7 +2,7 @@ use crate::coords::Range; use std::borrow::BorrowMut; use std::path::Path; -use super::super::{Layer, LayerImpl, Render}; +use super::super::{Layer, Render}; use crate::coords::Mapper; use femtovg::renderer::OpenGl; use femtovg::{Canvas, Paint}; diff --git a/src/widgets/render/renders.rs b/src/widgets/render/renders.rs index 1afab19..187be4e 100644 --- a/src/widgets/render/renders.rs +++ b/src/widgets/render/renders.rs @@ -1,6 +1,6 @@ use super::Render; use crate::coords::cms::CMS; -use crate::pipeline::element::Target; +use crate::pipeline::Target; use femtovg::{renderer::OpenGl, Canvas}; pub trait DataRenderer {