From b6537055ba0e3f1732f7379ae719ef1c40d6a928 Mon Sep 17 00:00:00 2001 From: tsuki Date: Tue, 12 Mar 2024 00:16:01 +0800 Subject: [PATCH] sync --- src/components/monitor/messages.rs | 2 + src/components/monitor/monitor.rs | 65 ++++++++++++++++++++++-------- src/map_tile.rs | 2 +- src/widgets/render/imp.rs | 43 +++++++++++++++++--- src/widgets/render/mod.rs | 12 +++++- 5 files changed, 100 insertions(+), 24 deletions(-) diff --git a/src/components/monitor/messages.rs b/src/components/monitor/messages.rs index 61a0e75..52aa099 100644 --- a/src/components/monitor/messages.rs +++ b/src/components/monitor/messages.rs @@ -15,12 +15,14 @@ pub enum MonitorInputMsg { UpdateMetaItem(HashMap), RefreshLayerList, SetRenderRange(f64, f64, f64, f64), + ChangeZoom(u8), None, } impl Debug for MonitorInputMsg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + MonitorInputMsg::ChangeZoom(_) => write!(f, "MonitorInputMsg::ChangeZoom"), MonitorInputMsg::SetRenderRange(_, _, _, _) => write!(f, "MonitorInputMsg::SetRenderRange"), MonitorInputMsg::RefreshLayerList => write!(f, "MonitorInputMsg::RefreshLayerList"), MonitorInputMsg::NewElement(_) => write!(f, "MonitorInputMsg::NewElement"), diff --git a/src/components/monitor/monitor.rs b/src/components/monitor/monitor.rs index 6615340..453cb4b 100644 --- a/src/components/monitor/monitor.rs +++ b/src/components/monitor/monitor.rs @@ -1,3 +1,4 @@ +use tracing::*; use super::messages::{MonitorInputMsg, MonitorOutputMsg}; use crate::coords::cms::CMS; use crate::pipeline::offscreen_renderer::OffscreenRenderer; @@ -18,20 +19,21 @@ use std::collections::HashMap; use std::rc::Rc; use std::sync::{Arc, Mutex}; -use tokio::task; use super::sidebar::{sidebar::SideBarModel, SideBarInputMsg, SideBarOutputMsg}; +use crate::coords::Range; use crate::map_tile::MapTile; +use crate::map_tile_utils::lat_lon_to_zoom; +use crate::pipeline::element::Target; use adw::prelude::*; use femtovg::ImageId; use relm4::{component::Component, *}; use slippy_map_tiles::Tile; +use tokio::task; use tracing::instrument::WithSubscriber; -use crate::coords::Range; -use crate::pipeline::element::Target; #[derive(Debug)] pub enum MonitorCommand { - LoadTile(Tile, Vec, (f64,f64), (Range, Range)), + LoadTile(Tile, Vec, (f64, f64), (Range, Range)), None, } #[tracker::track] @@ -40,10 +42,11 @@ pub struct MonitorModel { render_range: (f64, f64, f64, f64), sidebar_open: bool, sidebar_width: i32, + zoom: u8, #[do_not_track] map_tile_getter: Arc, #[do_not_track] - tiles: Rc>>, + tiles: Rc>>>, new_layer: i8, #[no_eq] widgets: Vec, @@ -99,14 +102,13 @@ impl Component for MonitorModel { }, set_tiles: model.tiles.clone(), connect_range_changing_notify[sender] => move |r| { - let ((x1 , x2), (y1,y2))= r.render_range(); - let w = r.width() as f32; - let h = r.height() as f32; let map_tile_getter = map_tile_getter.clone(); - let new_tiles = map_tile_getter.new_tiles(3 ,(y1 as f32,y2 as f32),(x1 as f32,x2 as f32)); - - let tiles = (*tiles).borrow(); + let ((x1 , x2), (y1,y2))= r.render_range(); + let new_tiles = map_tile_getter.new_tiles(model.zoom ,(y1 as f32, y2 as f32),(x1 as f32,x2 as f32)); + let mut tiles = (*tiles).borrow_mut(); let new_tiles = new_tiles.filter(|x| !tiles.contains_key(x)).collect::>(); + tiles.extend(new_tiles.iter().map(|x| (*x, None))); + if new_tiles.len() > 0 { let new_sender = sender.clone(); @@ -115,6 +117,7 @@ impl Component for MonitorModel { let map_tile_getter = map_tile_getter.clone(); let sender = new_sender.clone(); task::spawn(async move { + info!("Loading tile {:?}", tile); let result = map_tile_getter.get_tile(&tile).await; if let Ok(result) = result { let origin = tile.nw_corner(); @@ -122,12 +125,19 @@ impl Component for MonitorModel { let bounds = ((origin.lon() as f64..rb.lon() as f64).into(), (origin.lat() as f64..rb.lat() as f64).into()); sender.command_sender().emit(MonitorCommand::LoadTile(tile, result,(origin.lon() as f64, origin.lat() as f64), bounds)); } - }); + }).await; } MonitorCommand::None }); } }, + connect_scale_notify[sender] => move |r| { + // let ((x1 , x2), (y1,y2))= r.render_range(); + // let w = r.width() as f32; + // let h = r.height() as f32; + // let zoom = lat_lon_to_zoom((y1,y2), (x1,x2),w, h); + // sender.input(MonitorInputMsg::ChangeZoom(zoom)); + }, set_interior_layers: model.layers.clone(), }, add_overlay=>k::Button{ @@ -158,7 +168,6 @@ impl Component for MonitorModel { ) { self.reset(); match message { - MonitorInputMsg::RefreshLayerList => { self.sidebar.sender().send(SideBarInputMsg::RefreshList); widgets.renderer.queue_render(); @@ -183,6 +192,19 @@ impl Component for MonitorModel { WidgetType::OpenGl => {} _ => {} }, + MonitorInputMsg::ChangeZoom(zoom) => { + if self.zoom != zoom { + self.zoom = zoom; + + let mut ts = self.tiles.borrow_mut(); + + for (k,v) in ts.drain() { + if let Some(v) = v { + widgets.renderer.delete_img(v); + } + } + } + } MonitorInputMsg::RemoveWidget => {} MonitorInputMsg::None => {} _ => {} @@ -211,7 +233,7 @@ impl Component for MonitorModel { padding: [20.0, 40.0, 20.0, 40.0], }; - let model = MonitorModel { + let mut model = MonitorModel { render_range: (4.0, 53.3, 73.3, 135.0), new_layer: 0, widgets: vec![], @@ -220,6 +242,7 @@ impl Component for MonitorModel { sidebar_open: true, sidebar_width: 400, layers: init, + zoom: 4, map_tile_getter: Arc::new(MapTile::default()), sidebar, tracker: 0, @@ -229,6 +252,11 @@ impl Component for MonitorModel { let tiles = model.tiles.clone(); let widgets = view_output! {}; + + // let (h, w) = (widgets.renderer.height(), widgets.renderer.width()); + // let zoom = lat_lon_to_zoom((4.0, 53.3), (73.3, 135.0), w as f32, h as f32); + // model.zoom = zoom; + ComponentParts { model, widgets } } @@ -242,8 +270,13 @@ impl Component for MonitorModel { self.reset(); match message { MonitorCommand::LoadTile(key, ref tile, origin, bounds) => { - let target = widgets.renderer.load_img_mem(&tile,origin,(256f32,256f32), bounds).unwrap(); - self.tiles.borrow_mut().insert(key, target); + let target = widgets + .renderer + .load_img_mem(&tile, origin, (256f32, 256f32), bounds) + .unwrap(); + // self.tiles.borrow_mut().insert(key, target); + // *self.tiles.borrow_mut().get_mut(&key) = Some(target); + self.tiles.borrow_mut().entry(key).and_modify(|x| *x = Some(target)); widgets.render.queue_draw(); } _ => {} diff --git a/src/map_tile.rs b/src/map_tile.rs index 6a46071..493ba68 100644 --- a/src/map_tile.rs +++ b/src/map_tile.rs @@ -16,7 +16,7 @@ impl Default for MapTile{ Self{ server: "https://tiles.stadiamaps.com/tiles/".to_string(), api_key: "06f1aeed-5d91-48e3-9ce5-1e99063f7f73".to_string(), - style: "stamen_toner/".to_string(), + style: "stamen_terrain/".to_string(), client: Client::new(), } } diff --git a/src/widgets/render/imp.rs b/src/widgets/render/imp.rs index e127777..1db6581 100644 --- a/src/widgets/render/imp.rs +++ b/src/widgets/render/imp.rs @@ -3,8 +3,8 @@ use super::interior::InteriorWidget; use super::{Layer, WindowCoord}; use crate::coords::proj::Mercator; use crate::coords::Mapper; -use crate::pipeline::element::Target; -use femtovg::{Canvas, Color, FontId, Renderer}; +use crate::pipeline::element::{Target, TargetType}; +use femtovg::{Canvas, Color, FontId, Paint, Renderer}; use gtk::glib::{self, prelude::*, Properties}; use gtk::subclass::prelude::*; use gtk::traits::{GLAreaExt, WidgetExt}; @@ -53,11 +53,13 @@ pub struct Render { render_status: Cell, #[property(get, set)] range_changing: Cell, + #[property(get, set)] + scale: Cell, pub(super) exterior: RefCell, pub(super) interior: RefCell, pub(super) canvas: RefCell>>, pub(super) glow_context: RefCell>, - pub(super) tiles: RefCell>>>, + pub(super) tiles: RefCell>>>>, pub config: RefCell, pub status: RefCell, pub mapper: RefCell, @@ -67,6 +69,7 @@ pub struct Render { impl Default for Render { fn default() -> Self { Self { + scale: Cell::new(1.0), range_changing: Cell::new(0.0), render_status: Cell::new(0), exterior: RefCell::new(ExteriorWidget::default()), @@ -160,10 +163,13 @@ impl GLAreaImpl for Render { (w, h) }; - let tiles = self.tiles.borrow().borrow(); - - for tile in tiles.values() { + let mut binding = self.tiles.borrow(); + let mut tiles = binding.borrow_mut(); + for tile in tiles.values_mut(){ + if let Some(tile) = tile.as_mut() { + self.draw_target(tile); + } } let render_range = self.status.borrow().view_range.clone(); @@ -207,6 +213,7 @@ impl GLAreaImpl for Render { let scaled = scale_rate + scale_flag * step; status.scale_rate = Some(scaled); + self.obj().set_scale(scaled as f64); let sx = scale_flag * step * px as f64; let sy = scale_flag * step * py as f64; status.translation = Some((tx - sx, ty - sy)); @@ -345,4 +352,28 @@ impl Render { .view_range .replace(((lat1, lat2), (lon1, lon2))); } + + pub(super) fn draw_target(&self, target: &mut Target) { + let mut canvas = self.canvas.borrow_mut(); + let canvas = canvas.as_mut().unwrap(); + + let obj = self.obj(); + + let (ox,oy) = target.origin(&obj); + let (x, y) = target.size(&obj); + + let 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 + } + }; + + let painter = Paint::image(id, ox, oy, x, y, 0.0, 1.0); + let mut path = femtovg::Path::new(); + path.rect(ox, oy, x, y); + canvas.fill_path(&path, &painter); + } } diff --git a/src/widgets/render/mod.rs b/src/widgets/render/mod.rs index 15abc27..f74ef4e 100644 --- a/src/widgets/render/mod.rs +++ b/src/widgets/render/mod.rs @@ -217,7 +217,7 @@ impl Render { self.queue_render(); } - pub fn set_tiles(&self, tiles: Rc>>) { + pub fn set_tiles(&self, tiles: Rc>>>) { self.imp().tiles.replace(tiles); self.queue_render(); } @@ -229,4 +229,14 @@ impl Render { let (width, height) = size; Ok(Target::new(TargetType::ImageId(img_id), width, height, bounds, None, None)) } + + pub fn delete_img(&self, img: Target) { + let mut canvas = self.get_canvas(); + let cvs = canvas.as_mut().unwrap(); + // cvs.delete_image() + + if let TargetType::ImageId(id) = img.target { + cvs.delete_image(id); + } + } }