This commit is contained in:
tsuki 2024-03-13 01:04:03 +08:00
parent de324daada
commit f860aadfa8
6 changed files with 66 additions and 90 deletions

View File

@ -7,6 +7,7 @@ use crate::{
}; };
pub enum MonitorInputMsg { pub enum MonitorInputMsg {
RefreshRender,
AddWidget(Box<dyn Widget>), AddWidget(Box<dyn Widget>),
RemoveWidget, RemoveWidget,
AddMetaItem(HashMap<String, String>), AddMetaItem(HashMap<String, String>),
@ -22,6 +23,7 @@ pub enum MonitorInputMsg {
impl Debug for MonitorInputMsg { impl Debug for MonitorInputMsg {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
MonitorInputMsg::RefreshRender => write!(f, "MonitorInputMsg::RefreshRender"),
MonitorInputMsg::RefreshTiles => write!(f, "MonitorInputMsg::RefreshTiles"), MonitorInputMsg::RefreshTiles => write!(f, "MonitorInputMsg::RefreshTiles"),
MonitorInputMsg::ChangeZoom(_) => write!(f, "MonitorInputMsg::ChangeZoom"), MonitorInputMsg::ChangeZoom(_) => write!(f, "MonitorInputMsg::ChangeZoom"),
MonitorInputMsg::SetRenderRange(_, _, _, _) => write!(f, "MonitorInputMsg::SetRenderRange"), MonitorInputMsg::SetRenderRange(_, _, _, _) => write!(f, "MonitorInputMsg::SetRenderRange"),

View File

@ -1,4 +1,4 @@
pub mod messages; pub mod messages;
pub mod monitor; pub mod monitor;
pub mod sidebar; pub mod sidebar;
pub use monitor::MonitorModel; pub use monitor::*;

View File

@ -26,7 +26,6 @@ use crate::map_tile_utils::lat_lon_to_zoom;
use crate::pipeline::element::Target; use crate::pipeline::element::Target;
use adw::prelude::*; use adw::prelude::*;
use femtovg::ImageId; use femtovg::ImageId;
use quick_cache::unsync::Cache;
use relm4::{component::Component, *}; use relm4::{component::Component, *};
use slippy_map_tiles::Tile; use slippy_map_tiles::Tile;
use tokio::task; use tokio::task;
@ -34,7 +33,7 @@ use tracing::instrument::WithSubscriber;
#[derive(Debug)] #[derive(Debug)]
pub enum MonitorCommand { pub enum MonitorCommand {
LoadTile(Tile, Vec<u8>, (f64, f64), (Range, Range)), LoadedTile(Tile),
None, None,
} }
#[tracker::track] #[tracker::track]
@ -45,11 +44,7 @@ pub struct MonitorModel {
sidebar_width: i32, sidebar_width: i32,
zoom: u8, zoom: u8,
#[do_not_track] #[do_not_track]
tile_cache: Cache<Tile, Target>, map_tile_getter: Rc<MapTile>,
#[do_not_track]
map_tile_getter: Arc<tokio::sync::Mutex<MapTile>>,
#[do_not_track]
tiles: Rc<RefCell<HashMap<Tile, Option<Target>>>>,
new_layer: i8, new_layer: i8,
#[no_eq] #[no_eq]
widgets: Vec<WidgetFrame>, widgets: Vec<WidgetFrame>,
@ -100,10 +95,10 @@ impl Component for MonitorModel {
set_cfg: model.render_cfg, set_cfg: model.render_cfg,
#[track = "model.changed(MonitorModel::render_range())"] #[track = "model.changed(MonitorModel::render_range())"]
set_view: model.render_range, set_view: model.render_range,
set_tiles: model.map_tile_getter.clone(),
connect_render_status_notify[sender] => move |r| { connect_render_status_notify[sender] => move |r| {
sender.output(MonitorOutputMsg::LayerRenderFinished); sender.output(MonitorOutputMsg::LayerRenderFinished);
}, },
set_tiles: model.tiles.clone(),
connect_range_changing_notify[sender] => move |r| { connect_range_changing_notify[sender] => move |r| {
sender.input(MonitorInputMsg::RefreshTiles); sender.input(MonitorInputMsg::RefreshTiles);
}, },
@ -145,9 +140,12 @@ impl Component for MonitorModel {
) { ) {
self.reset(); self.reset();
match message { match message {
MonitorInputMsg::RefreshRender => {
widgets.renderer.queue_render();
}
MonitorInputMsg::RefreshLayerList => { MonitorInputMsg::RefreshLayerList => {
self.sidebar.sender().send(SideBarInputMsg::RefreshList); self.sidebar.sender().send(SideBarInputMsg::RefreshList);
widgets.renderer.queue_render(); sender.input(MonitorInputMsg::RefreshRender);
} }
MonitorInputMsg::AddMetaItem(map) => { MonitorInputMsg::AddMetaItem(map) => {
self.sidebar.emit(SideBarInputMsg::AddMetaItems(map)) self.sidebar.emit(SideBarInputMsg::AddMetaItems(map))
@ -162,7 +160,7 @@ impl Component for MonitorModel {
} }
MonitorInputMsg::RefreshTiles => { MonitorInputMsg::RefreshTiles => {
let ((x1 , x2), (y1,y2)) = widgets.renderer.render_range(); let ((x1 , x2), (y1,y2)) = widgets.renderer.render_range();
// Self::load_cache_tile(&mut self.tile_cache,&sender, &self.map_tile_getter, self.zoom, ((y1 as f32, y2 as f32),(x1 as f32,x2 as f32))); self.load_tile(&sender, ((y1 as f32, y2 as f32), (x1 as f32, x2 as f32)));
} }
MonitorInputMsg::AddWidget(widget) => match widget.widget_type() { MonitorInputMsg::AddWidget(widget) => match widget.widget_type() {
WidgetType::Cairo => { WidgetType::Cairo => {
@ -176,6 +174,7 @@ impl Component for MonitorModel {
MonitorInputMsg::ChangeZoom(zoom) => { MonitorInputMsg::ChangeZoom(zoom) => {
if self.zoom != zoom { if self.zoom != zoom {
self.zoom = zoom; self.zoom = zoom;
self.map_tile_getter.set_zoom(zoom);
sender.input(MonitorInputMsg::RefreshTiles); sender.input(MonitorInputMsg::RefreshTiles);
} }
} }
@ -211,20 +210,16 @@ impl Component for MonitorModel {
render_range: (4.0, 53.3, 73.3, 135.0), render_range: (4.0, 53.3, 73.3, 135.0),
new_layer: 0, new_layer: 0,
widgets: vec![], widgets: vec![],
tiles: Rc::new(RefCell::new(HashMap::new())),
render_cfg, render_cfg,
tile_cache: Cache::new(32),
sidebar_open: true, sidebar_open: true,
sidebar_width: 400, sidebar_width: 400,
layers: init, layers: init,
zoom: 4, zoom: 4,
map_tile_getter: Arc::new(tokio::sync::Mutex::new( MapTile::default())), map_tile_getter: Rc::new(MapTile::default()),
sidebar, sidebar,
tracker: 0, tracker: 0,
}; };
let map_tile_getter = model.map_tile_getter.clone();
let tiles = model.tiles.clone();
let widgets = view_output! {}; let widgets = view_output! {};
ComponentParts { model, widgets } ComponentParts { model, widgets }
} }
@ -238,17 +233,8 @@ impl Component for MonitorModel {
) { ) {
self.reset(); self.reset();
match message { match message {
MonitorCommand::LoadTile(key, ref tile, origin, bounds) => { MonitorCommand::LoadedTile(tile) => {
let target = widgets sender.input(MonitorInputMsg::RefreshRender);
.renderer
.load_img_mem(&tile, origin, (256f32, 256f32), bounds)
.unwrap();
let mut binding = self.tiles.borrow_mut();
if !binding.contains_key(&key) {
return ;
}
binding.entry(key).and_modify(|x| *x = Some(target));
widgets.renderer.queue_draw();
} }
_ => {} _ => {}
} }
@ -258,41 +244,13 @@ impl Component for MonitorModel {
impl MonitorModel { impl MonitorModel {
fn load_tile(tiles: &Rc<RefCell<HashMap<Tile, Option<Target>>>> ,sender: &ComponentSender<Self>, map_tile_getter: &Arc<MapTile>, zoom:u8, range:((f32,f32), (f32,f32))) { fn load_tile(&self, sender: &ComponentSender<Self>, range:((f32,f32), (f32,f32))) {
let map_tile_getter = map_tile_getter.clone(); let task = self.map_tile_getter.load_tiles(range, sender.clone());
let new_tiles = map_tile_getter.new_tiles(zoom ,range.0, range.1); sender.oneshot_command(async move {
let mut tiles = (*tiles).borrow_mut(); task.await;
let new_tiles = new_tiles.filter(|x| !tiles.contains_key(x)).collect::<Vec<_>>(); MonitorCommand::None
tiles.extend(new_tiles.iter().map(|x| (*x, None))); });
if new_tiles.len() > 0 {
let new_sender = sender.clone();
sender.oneshot_command(async move {
for tile in new_tiles {
let map_tile_getter = map_tile_getter.clone();
let sender = new_sender.clone();
task::spawn(async move {
let result = map_tile_getter.get_tile(&tile).await;
if let Ok(result) = result {
let origin = tile.nw_corner();
let rb = tile.se_corner();
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
});
}
}
fn load_tiles(&self, sender: &ComponentSender<Self>,range:((f32,f32), (f32,f32))) {
// sender.oneshot_command(async move {
// MapTile::load_tiles(self.map_tile_getter.clone(), self.zoom, range).await;
// MonitorCommand::None
// });
} }
} }

View File

@ -1,3 +1,4 @@
use std::cell::{Cell, RefCell};
use crate::coords::Range; use crate::coords::Range;
use crate::map_tile_utils::lat_lon_to_zoom; use crate::map_tile_utils::lat_lon_to_zoom;
use crate::pipeline::element::{Target, TargetType}; use crate::pipeline::element::{Target, TargetType};
@ -16,15 +17,16 @@ use tokio::sync::Mutex;
use tokio::task; use tokio::task;
use tracing::{debug, info}; use tracing::{debug, info};
use crate::components::messages::MonitorInputMsg; use crate::components::messages::MonitorInputMsg;
use crate::components::MonitorModel; use crate::components::{MonitorCommand, MonitorModel};
pub struct MapTile { pub struct MapTile {
server: String, server: String,
api_key: String, api_key: String,
style: String, style: String,
client: Client, client: Client,
onloading: HashSet<Tile>, onloading: Arc<std::sync::Mutex<HashSet<Tile>>>,
cache: Arc<std::sync::Mutex<Cache<Tile, Arc<Target>>>>, cache: Arc<std::sync::Mutex<Cache<Tile, Arc<std::sync::Mutex<Target>>>>>,
zoom_level: Cell<u8>,
} }
impl Default for MapTile { impl Default for MapTile {
@ -34,8 +36,9 @@ impl Default for MapTile {
api_key: "06f1aeed-5d91-48e3-9ce5-1e99063f7f73".to_string(), api_key: "06f1aeed-5d91-48e3-9ce5-1e99063f7f73".to_string(),
style: "stamen_terrain/".to_string(), style: "stamen_terrain/".to_string(),
client: Client::new(), client: Client::new(),
onloading: HashSet::new(), onloading: Arc::new(std::sync::Mutex::new( HashSet::new())),
cache: Arc::new(std::sync::Mutex::new(Cache::new(32))), cache: Arc::new(std::sync::Mutex::new(Cache::new(32))),
zoom_level: Cell::new(4),
} }
} }
} }
@ -89,23 +92,31 @@ impl MapTile {
Ok(bytes.to_vec()) Ok(bytes.to_vec())
} }
pub fn set_zoom(&self, zoom: u8) {
self.zoom_level.set(zoom);
}
pub fn load_tiles( pub fn load_tiles(
&self, &self,
zoom: u8,
range: ((f32, f32), (f32, f32)), range: ((f32, f32), (f32, f32)),
sender: ComponentSender<MonitorModel>, sender: ComponentSender<MonitorModel>,
) -> BoxFuture<'static, ()> { ) -> BoxFuture<'static, ()> {
let zoom = self.zoom_level.get();
let new_tiles = self.new_tiles(zoom, range.0, range.1); let new_tiles = self.new_tiles(zoom, range.0, range.1);
let cache = (*self.cache).lock().unwrap(); let cache = (*self.cache).lock().unwrap();
let mut bindings = self.onloading.lock().unwrap();
let new_tiles = new_tiles let new_tiles = new_tiles
.filter(|x| cache.peek(x).is_none() && !self.onloading.contains(x)) .filter(|x| cache.peek(x).is_none() && !bindings.contains(x))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if new_tiles.len() > 0 { if new_tiles.len() > 0 {
bindings.extend(new_tiles.iter().cloned());
info!("Load new tiles");
let tasks = new_tiles.into_iter().map(move |tile| { let tasks = new_tiles.into_iter().map(move |tile| {
let _task = self.get_tile_task(&tile); let _task = self.get_tile_task(&tile);
let sender = sender.clone(); let sender = sender.clone();
let cache = self.cache.clone(); let cache = self.cache.clone();
let onloading = self.onloading.clone();
task::spawn(async move { task::spawn(async move {
let result = _task.await; let result = _task.await;
if let Ok(result) = result { if let Ok(result) = result {
@ -123,24 +134,26 @@ impl MapTile {
None, None,
None None
); );
cache.lock().unwrap().insert(tile, Arc::new(result)); cache.lock().unwrap().insert(tile, Arc::new(std::sync::Mutex::new(result)));
sender.input(MonitorInputMsg::RefreshTiles); onloading.lock().unwrap().remove(&tile);
sender.command_sender().emit(MonitorCommand::LoadedTile(tile));
} }
}) })
}); }).collect::<Vec<_>>();
Box::pin(async move { return Box::pin(async move {
for task in tasks { for task in tasks {
task.await.unwrap(); task.await.unwrap();
} }
}); });
} else { } else {
debug!("No new tiles to load"); info!("No new tiles to load");
} }
Box::pin(async move {}) Box::pin(async move {})
} }
pub fn current_tiles(&self, zoom: u8, range: ((f32, f32), (f32, f32))) -> Vec<Arc<Target>> { pub fn current_tiles(&self, range: ((f32, f32), (f32, f32))) -> Vec<Arc<std::sync::Mutex<Target>>> {
let zoom = self.zoom_level.get();
let current = self.new_tiles(zoom, range.0, range.1); let current = self.new_tiles(zoom, range.0, range.1);
let mut total_len = 0; let mut total_len = 0;
let mut results = Vec::new(); let mut results = Vec::new();
@ -160,16 +173,17 @@ impl MapTile {
center.lat() as f64, center.lat() as f64,
start_zoom, start_zoom,
); );
let tile = Tile::new(start_zoom, x, y).unwrap(); let tile = Tile::new(start_zoom, tile.0, tile.1).unwrap();
if cached.contains(&tile) { if cached.contains(&tile) {
break; break;
} else { } else {
cached.push(tile); if let Some(target) = cache.get(&tile) {
} results.insert(0, target);
if let Some(target) = cache.get(&tile) { cached.push(tile);
results.insert(0, target); break;
break; }
} }
start_zoom -= 1; start_zoom -= 1;
} }
} }

View File

@ -15,6 +15,7 @@ use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use slippy_map_tiles::Tile; use slippy_map_tiles::Tile;
use tracing::info; use tracing::info;
use crate::map_tile::MapTile;
#[derive(Debug, Default, Clone, Copy, PartialEq)] #[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct RenderConfig { pub struct RenderConfig {
@ -61,7 +62,7 @@ pub struct Render {
pub(super) interior: RefCell<InteriorWidget>, pub(super) interior: RefCell<InteriorWidget>,
pub(super) canvas: RefCell<Option<femtovg::Canvas<femtovg::renderer::OpenGl>>>, pub(super) canvas: RefCell<Option<femtovg::Canvas<femtovg::renderer::OpenGl>>>,
pub(super) glow_context: RefCell<Option<glow::Context>>, pub(super) glow_context: RefCell<Option<glow::Context>>,
pub(super) tiles: RefCell<Rc<RefCell<HashMap<Tile, Option<Target>>>>>, pub(super) tiles: RefCell<Option<Rc<MapTile>>>,
pub config: RefCell<RenderConfig>, pub config: RefCell<RenderConfig>,
pub status: RefCell<RenderStatus>, pub status: RefCell<RenderStatus>,
pub mapper: RefCell<Mapper>, pub mapper: RefCell<Mapper>,
@ -80,7 +81,7 @@ impl Default for Render {
interior_layers: RefCell::new(Rc::new(RefCell::new(Vec::new()))), interior_layers: RefCell::new(Rc::new(RefCell::new(Vec::new()))),
config: RefCell::new(RenderConfig::default()), config: RefCell::new(RenderConfig::default()),
status: RefCell::new(RenderStatus::default()), status: RefCell::new(RenderStatus::default()),
tiles: RefCell::new(Rc::new(RefCell::new(HashMap::new()))), tiles: RefCell::new(None),
mapper: RefCell::new(Mercator::default().into()), mapper: RefCell::new(Mercator::default().into()),
canvas: RefCell::new(None), canvas: RefCell::new(None),
} }
@ -165,12 +166,13 @@ impl GLAreaImpl for Render {
(w, h) (w, h)
}; };
let mut binding = self.tiles.borrow(); let binding = self.tiles.borrow();
let mut tiles = binding.borrow_mut(); if let Some(tiles) = binding.as_ref() {
let ((x1 , x2), (y1,y2)) = self.view_range().unwrap();
for tile in tiles.values_mut(){ let mut tiles = tiles.current_tiles( ((y1 as f32, y2 as f32), (x1 as f32, x2 as f32)));
if let Some(tile) = tile.as_mut() { for tile in tiles.iter_mut() {
self.draw_target(tile); let mut binding = (*tile).lock().unwrap();
self.draw_target(&mut *binding);
} }
} }

View File

@ -23,6 +23,7 @@ use std::sync::{Arc, Mutex};
use femtovg::ImageFlags; use femtovg::ImageFlags;
use slippy_map_tiles::Tile; use slippy_map_tiles::Tile;
use crate::errors::PipelineError; use crate::errors::PipelineError;
use crate::map_tile::MapTile;
use crate::pipeline::element::{Target, TargetType}; use crate::pipeline::element::{Target, TargetType};
pub type WindowCoord = (f32, f32); pub type WindowCoord = (f32, f32);
@ -212,12 +213,11 @@ impl Render {
pub fn set_view(&self, range: (f64, f64, f64, f64)) { pub fn set_view(&self, range: (f64, f64, f64, f64)) {
self.imp().set_view(range); self.imp().set_view(range);
self.set_range_changing(range.0 + range.1); self.set_range_changing(range.0 + range.1);
// self.set_range(range);
self.queue_render(); self.queue_render();
} }
pub fn set_tiles(&self, tiles: Rc<RefCell<HashMap<Tile, Option<Target>>>>) { pub fn set_tiles(&self, tiles: Rc<MapTile>) {
self.imp().tiles.replace(tiles); self.imp().tiles.replace(Some(tiles));
self.queue_render(); self.queue_render();
} }