Fix compilation in winit and demo module

This commit is contained in:
Maximilian Ammann 2022-09-25 17:41:59 +02:00
parent c6eadbf2cc
commit c663416d05
27 changed files with 481 additions and 366 deletions

View File

@ -1,37 +1,41 @@
use maplibre::headless::map::HeadlessMap;
use maplibre::headless::window::HeadlessMapWindowConfig;
use maplibre::kernel::KernelBuilder;
use maplibre::render::builder::RenderBuilder;
use maplibre::style::Style;
use maplibre::{ use maplibre::{
coords::{LatLon, WorldTileCoords}, coords::{LatLon, WorldTileCoords},
error::Error, error::Error,
headless::{HeadlessEnvironment, HeadlessMapWindowConfig},
io::apc::SchedulerAsyncProcedureCall, io::apc::SchedulerAsyncProcedureCall,
platform::{http_client::ReqwestHttpClient, scheduler::TokioScheduler}, platform::{http_client::ReqwestHttpClient, scheduler::TokioScheduler},
render::settings::{RendererSettings, TextureFormat}, render::settings::{RendererSettings, TextureFormat},
util::grid::google_mercator, util::grid::google_mercator,
window::WindowSize, window::WindowSize,
MapBuilder,
}; };
use maplibre_winit::winit::WinitEnvironment; use maplibre_winit::winit::WinitEnvironment;
use tile_grid::{extent_wgs84_to_merc, Extent, GridIterator}; use tile_grid::{extent_wgs84_to_merc, Extent, GridIterator};
pub async fn run_headless(tile_size: u32, min: LatLon, max: LatLon) { pub async fn run_headless(tile_size: u32, min: LatLon, max: LatLon) {
let client = ReqwestHttpClient::new(None); let client = ReqwestHttpClient::new(None);
let mut map = let kernel = KernelBuilder::new()
MapBuilder::<HeadlessEnvironment<_, _, _, SchedulerAsyncProcedureCall<_, _>>>::new() .with_map_window_config(HeadlessMapWindowConfig::new(
.with_map_window_config(HeadlessMapWindowConfig { WindowSize::new(tile_size, tile_size).unwrap(),
size: WindowSize::new(tile_size, tile_size).unwrap(), ))
}) .with_http_client(client.clone())
.with_http_client(client.clone()) .with_apc(SchedulerAsyncProcedureCall::new(
.with_apc(SchedulerAsyncProcedureCall::new( client,
client, TokioScheduler::new(),
TokioScheduler::new(), ))
)) // FIXME (wasm-executor): avoid passing client and scheduler here .with_scheduler(TokioScheduler::new())
.with_scheduler(TokioScheduler::new()) .build();
.with_renderer_settings(RendererSettings {
texture_format: TextureFormat::Rgba8UnormSrgb, let renderer = RenderBuilder::new()
..RendererSettings::default() .build()
}) .initialize_headless_with(&kernel)
.build() .await
.initialize_headless() .expect("Failed to initialize renderer");
.await;
let mut map = HeadlessMap::new(Style::default(), renderer, kernel).unwrap();
let tile_limits = google_mercator().tile_limits( let tile_limits = google_mercator().tile_limits(
extent_wgs84_to_merc(&Extent { extent_wgs84_to_merc(&Extent {
@ -46,18 +50,11 @@ pub async fn run_headless(tile_size: u32, min: LatLon, max: LatLon) {
for (z, x, y) in GridIterator::new(10, 10, tile_limits) { for (z, x, y) in GridIterator::new(10, 10, tile_limits) {
let coords = WorldTileCoords::from((x as i32, y as i32, z.into())); let coords = WorldTileCoords::from((x as i32, y as i32, z.into()));
println!("Rendering {}", &coords); println!("Rendering {}", &coords);
map.map_schedule let tile = map
.fetch_process(&coords) .fetch_tile(coords, &["water"])
.await .await
.expect("Failed to fetch and process!"); .expect("Failed to fetch and process!");
match map.map_schedule_mut().update_and_redraw() { map.render_tile(tile);
Ok(_) => {}
Err(Error::Render(e)) => {
eprintln!("{}", e);
if e.should_exit() {}
}
e => eprintln!("{:?}", e),
};
} }
} }

View File

@ -3,7 +3,7 @@
use std::time::Duration; use std::time::Duration;
use cgmath::Vector2; use cgmath::Vector2;
use maplibre::context::ViewState; use maplibre::world::ViewState;
use winit::event::{DeviceEvent, KeyboardInput, TouchPhase, WindowEvent}; use winit::event::{DeviceEvent, KeyboardInput, TouchPhase, WindowEvent};
use crate::input::{ use crate::input::{

View File

@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use cgmath::{EuclideanSpace, Point3, Vector2, Vector3, Zero}; use cgmath::{EuclideanSpace, Point3, Vector2, Vector3, Zero};
use maplibre::{context::ViewState, render::camera::Camera}; use maplibre::{render::camera::Camera, world::ViewState};
use winit::event::{ElementState, MouseButton}; use winit::event::{ElementState, MouseButton};
use super::UpdateState; use super::UpdateState;
@ -45,17 +45,17 @@ impl UpdateState for PanHandler {
}; };
if self.start_camera_position.is_none() { if self.start_camera_position.is_none() {
self.start_camera_position = Some(state.camera.position.to_vec()); self.start_camera_position = Some(state.camera().position().to_vec());
} }
if let Some(start_camera_position) = self.start_camera_position { if let Some(start_camera_position) = self.start_camera_position {
state.camera.position = Point3::from_vec( state.camera_mut().move_to(Point3::from_vec(
start_camera_position + Vector3::new(delta.x, delta.y, 0.0), start_camera_position + Vector3::new(delta.x, delta.y, 0.0),
); ));
} }
} }
} else { } else {
self.reference_camera = Some(state.camera.clone()); self.reference_camera = Some(state.camera().clone());
} }
} }
} }

View File

@ -1,6 +1,6 @@
use std::time::Duration; use std::time::Duration;
use maplibre::context::ViewState; use maplibre::world::ViewState;
use super::UpdateState; use super::UpdateState;

View File

@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use cgmath::Vector2; use cgmath::Vector2;
use maplibre::context::ViewState; use maplibre::world::ViewState;
use winit::event::{ElementState, MouseButton}; use winit::event::{ElementState, MouseButton};
use crate::input::UpdateState; use crate::input::UpdateState;
@ -66,7 +66,7 @@ impl UpdateState for QueryHandler {
let _z = state.visible_level(); // FIXME: can be wrong, if tiles of different z are visible let _z = state.visible_level(); // FIXME: can be wrong, if tiles of different z are visible
let _zoom = state.zoom(); let _zoom = state.zoom();
if let Some(_coordinates) = state.camera.window_to_world_at_ground( if let Some(_coordinates) = state.camera().window_to_world_at_ground(
&window_position, &window_position,
&inverted_view_proj, &inverted_view_proj,
false, false,

View File

@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use cgmath::{Vector3, Zero}; use cgmath::{Vector3, Zero};
use maplibre::context::ViewState; use maplibre::world::ViewState;
use super::UpdateState; use super::UpdateState;
@ -17,7 +17,7 @@ impl UpdateState for ShiftHandler {
let dt = dt.as_secs_f64() * (1.0 / self.speed); let dt = dt.as_secs_f64() * (1.0 / self.speed);
let delta = self.camera_translate * dt; let delta = self.camera_translate * dt;
state.camera.position += delta; state.camera_mut().move_relative(delta);
self.camera_translate -= delta; self.camera_translate -= delta;
} }
} }

View File

@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use cgmath::{Deg, Rad, Zero}; use cgmath::{Deg, Rad, Zero};
use maplibre::context::ViewState; use maplibre::world::ViewState;
use super::UpdateState; use super::UpdateState;
@ -17,7 +17,7 @@ impl UpdateState for TiltHandler {
let dt = dt.as_secs_f64() * (1.0 / self.speed); let dt = dt.as_secs_f64() * (1.0 / self.speed);
let delta = self.delta_pitch * dt; let delta = self.delta_pitch * dt;
state.camera.pitch += Rad::from(delta); state.camera_mut().pitch_self(delta);
self.delta_pitch -= delta; self.delta_pitch -= delta;
} }
} }

View File

@ -1,7 +1,7 @@
use std::time::Duration; use std::time::Duration;
use cgmath::{Vector2, Vector3}; use cgmath::{Vector2, Vector3};
use maplibre::{context::ViewState, coords::Zoom}; use maplibre::{coords::Zoom, world::ViewState};
use super::UpdateState; use super::UpdateState;
@ -24,7 +24,7 @@ impl UpdateState for ZoomHandler {
let view_proj = state.view_projection(); let view_proj = state.view_projection();
let inverted_view_proj = view_proj.invert(); let inverted_view_proj = view_proj.invert();
if let Some(cursor_position) = state.camera.window_to_world_at_ground( if let Some(cursor_position) = state.camera().window_to_world_at_ground(
&window_position, &window_position,
&inverted_view_proj, &inverted_view_proj,
false, false,
@ -37,7 +37,7 @@ impl UpdateState for ZoomHandler {
cursor_position.z, cursor_position.z,
) - cursor_position; ) - cursor_position;
state.camera.position += delta; state.camera_mut().move_relative(delta);
} }
} }
} }

View File

@ -1,6 +1,7 @@
use std::{cell::RefCell, marker::PhantomData, ops::Deref, rc::Rc}; use crate::input::{InputController, UpdateState};
use instant::Instant; use instant::Instant;
use maplibre::event_loop::{EventLoop, EventLoopProxy};
use maplibre::map::Map;
use maplibre::{ use maplibre::{
environment::Environment, environment::Environment,
error::Error, error::Error,
@ -10,15 +11,17 @@ use maplibre::{
source_client::HttpClient, source_client::HttpClient,
transferables::{DefaultTransferables, Transferables}, transferables::{DefaultTransferables, Transferables},
}, },
map_schedule::InteractiveMapSchedule, window::{HeadedMapWindow, MapWindowConfig},
window::{EventLoop, HeadedMapWindow, MapWindowConfig},
}; };
use std::{cell::RefCell, marker::PhantomData, ops::Deref, rc::Rc};
use winit::{ use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::ControlFlow, event_loop::ControlFlow,
}; };
use crate::input::{InputController, UpdateState}; pub type RawWinitWindow = winit::window::Window;
pub type RawWinitEventLoop<ET> = winit::event_loop::EventLoop<ET>;
pub type RawEventLoopProxy<ET> = winit::event_loop::EventLoopProxy<ET>;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
mod web; mod web;
@ -32,14 +35,19 @@ pub use noweb::*;
pub use web::*; pub use web::*;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
pub struct WinitMapWindowConfig { pub struct WinitMapWindowConfig<ET> {
title: String, title: String,
phantom_et: PhantomData<ET>,
} }
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
impl WinitMapWindowConfig { impl<ET> WinitMapWindowConfig<ET> {
pub fn new(title: String) -> Self { pub fn new(title: String) -> Self {
Self { title } Self {
title,
phantom_et: Default::default(),
}
} }
} }
@ -55,151 +63,157 @@ impl WinitMapWindowConfig {
} }
} }
pub struct WinitMapWindow { pub struct WinitMapWindow<ET: 'static> {
window: WinitWindow, window: RawWinitWindow,
event_loop: Option<WinitEventLoop>, event_loop: Option<WinitEventLoop<ET>>,
} }
impl WinitMapWindow { impl<ET> WinitMapWindow<ET> {
pub fn take_event_loop(&mut self) -> Option<WinitEventLoop> { pub fn take_event_loop(&mut self) -> Option<WinitEventLoop<ET>> {
self.event_loop.take() self.event_loop.take()
} }
} }
pub type WinitWindow = winit::window::Window; pub struct WinitEventLoop<ET: 'static> {
pub type WinitEventLoop = winit::event_loop::EventLoop<()>; event_loop: RawWinitEventLoop<ET>,
pub struct WinitEnvironment<
S: Scheduler,
HC: HttpClient,
T: Transferables,
APC: AsyncProcedureCall<T, HC>,
> {
phantom_s: PhantomData<S>,
phantom_hc: PhantomData<HC>,
phantom_t: PhantomData<T>,
phantom_apc: PhantomData<APC>,
} }
impl<S: Scheduler, HC: HttpClient, T: Transferables, APC: AsyncProcedureCall<T, HC>> Environment impl<ET: 'static> EventLoop<ET> for WinitEventLoop<ET> {
for WinitEnvironment<S, HC, T, APC> type EventLoopProxy = WinitEventLoopProxy<ET>;
{
type MapWindowConfig = WinitMapWindowConfig;
type AsyncProcedureCall = APC;
type Scheduler = S;
type HttpClient = HC;
type Transferables = T;
}
///Main (platform-specific) main loop which handles: fn run<E>(
///* Input (Mouse/Keyboard)
///* Platform Events like suspend/resume
///* Render a new frame
impl<E: Environment> EventLoop<E> for WinitMapWindow
where
E::MapWindowConfig: MapWindowConfig<MapWindow = WinitMapWindow>,
{
fn run(
mut self, mut self,
map_schedule: Rc<RefCell<InteractiveMapSchedule<E>>>, mut window: <E::MapWindowConfig as MapWindowConfig>::MapWindow,
mut map: Map<E>,
max_frames: Option<u64>, max_frames: Option<u64>,
) { ) where
E: Environment,
<E::MapWindowConfig as MapWindowConfig>::MapWindow: HeadedMapWindow,
{
let mut last_render_time = Instant::now(); let mut last_render_time = Instant::now();
let mut current_frame: u64 = 0; let mut current_frame: u64 = 0;
let mut input_controller = InputController::new(0.2, 100.0, 0.1); let mut input_controller = InputController::new(0.2, 100.0, 0.1);
self.take_event_loop() self.event_loop
.unwrap() .run(move |event, window_target, control_flow| {
.run(move |event, _, control_flow| {
let mut map_schedule = map_schedule.deref().borrow_mut();
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
if !map_schedule.is_initialized() && event == Event::Resumed { if !map.is_initialized() && event == Event::Resumed {
use tokio::{runtime::Handle, task}; use tokio::{runtime::Handle, task};
task::block_in_place(|| { task::block_in_place(|| {
Handle::current().block_on(async { Handle::current().block_on(async {
map_schedule.late_init().await; map.late_init().await;
}) })
}); });
return; return;
} }
match event { match event {
Event::DeviceEvent { Event::DeviceEvent {
ref event, ref event,
.. // We're not using device_id currently .. // We're not using device_id currently
} => { } => {
input_controller.device_input(event); input_controller.device_input(event);
} }
Event::WindowEvent { Event::WindowEvent {
ref event, ref event,
window_id, window_id,
} if window_id == self.inner().id() => { } if window_id == window.id().into() => {
if !input_controller.window_input(event) { if !input_controller.window_input(event) {
match event { match event {
WindowEvent::CloseRequested WindowEvent::CloseRequested
| WindowEvent::KeyboardInput { | WindowEvent::KeyboardInput {
input: input:
KeyboardInput { KeyboardInput {
state: ElementState::Pressed, state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape), virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
.. ..
}, } => *control_flow = ControlFlow::Exit,
.. WindowEvent::Resized(physical_size) => {
} => *control_flow = ControlFlow::Exit, // FIXME map.resize(physical_size.width, physical_size.height);
WindowEvent::Resized(physical_size) => { }
map_schedule.resize(physical_size.width, physical_size.height); WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
// FIXME map.resize(new_inner_size.width, new_inner_size.height);
}
_ => {}
} }
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
map_schedule.resize(new_inner_size.width, new_inner_size.height);
}
_ => {}
} }
} }
} Event::RedrawRequested(_) => {
Event::RedrawRequested(_) => { let now = Instant::now();
let now = Instant::now(); let dt = now - last_render_time;
let dt = now - last_render_time; last_render_time = now;
last_render_time = now;
input_controller.update_state(map_schedule.view_state_mut(), dt); // FIXME input_controller.update_state(map.view_state_mut(), dt);
match map_schedule.update_and_redraw() { match map.run_schedule() {
Ok(_) => {} Ok(_) => {}
Err(Error::Render(e)) => { Err(Error::Render(e)) => {
eprintln!("{}", e); eprintln!("{}", e);
if e.should_exit() { if e.should_exit() {
*control_flow = ControlFlow::Exit;
}
}
e => eprintln!("{:?}", e)
};
if let Some(max_frames) = max_frames {
if current_frame >= max_frames {
log::info!("Exiting because maximum frames reached.");
*control_flow = ControlFlow::Exit; *control_flow = ControlFlow::Exit;
} }
}
e => eprintln!("{:?}", e)
};
if let Some(max_frames) = max_frames { current_frame += 1;
if current_frame >= max_frames {
log::info!("Exiting because maximum frames reached.");
*control_flow = ControlFlow::Exit;
} }
current_frame += 1;
} }
Event::Suspended => {
// FIXME unimplemented!()
}
Event::Resumed => {
// FIXME unimplemented!()
}
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
window.request_redraw();
}
_ => {}
} }
Event::Suspended => {
map_schedule.suspend();
}
Event::Resumed => {
map_schedule.resume(&self);
}
Event::MainEventsCleared => {
// RedrawRequested will only trigger once, unless we manually
// request it.
self.inner().request_redraw();
}
_ => {}
}
}); });
} }
fn create_proxy(&self) -> Self::EventLoopProxy {
WinitEventLoopProxy {
proxy: self.event_loop.create_proxy(),
}
}
}
pub struct WinitEventLoopProxy<ET: 'static> {
proxy: RawEventLoopProxy<ET>,
}
impl<ET: 'static> EventLoopProxy<ET> for WinitEventLoopProxy<ET> {
fn send_event(&self, event: ET) {
self.proxy.send_event(event); // FIXME: Handle unwrap
}
}
pub struct WinitEnvironment<S: Scheduler, HC: HttpClient, APC: AsyncProcedureCall<HC>, ET> {
phantom_s: PhantomData<S>,
phantom_hc: PhantomData<HC>,
phantom_apc: PhantomData<APC>,
phantom_et: PhantomData<ET>,
}
impl<S: Scheduler, HC: HttpClient, APC: AsyncProcedureCall<HC>, ET: 'static> Environment
for WinitEnvironment<S, HC, APC, ET>
{
type MapWindowConfig = WinitMapWindowConfig<ET>;
type AsyncProcedureCall = APC;
type Scheduler = S;
type HttpClient = HC;
} }

View File

@ -3,18 +3,23 @@
//! * Platform Events like suspend/resume //! * Platform Events like suspend/resume
//! * Render a new frame //! * Render a new frame
use maplibre::event_loop::EventLoop;
use maplibre::headless::map::HeadlessMap;
use maplibre::kernel::{Kernel, KernelBuilder};
use maplibre::map::Map;
use maplibre::render::builder::RenderBuilder;
use maplibre::style::Style;
use maplibre::{ use maplibre::{
io::apc::SchedulerAsyncProcedureCall, io::apc::SchedulerAsyncProcedureCall,
platform::{http_client::ReqwestHttpClient, run_multithreaded, scheduler::TokioScheduler}, platform::{http_client::ReqwestHttpClient, run_multithreaded, scheduler::TokioScheduler},
window::{HeadedMapWindow, MapWindow, MapWindowConfig, WindowSize}, window::{HeadedMapWindow, MapWindow, MapWindowConfig, WindowSize},
MapBuilder,
}; };
use winit::window::WindowBuilder; use winit::window::WindowBuilder;
use super::{WinitEventLoop, WinitMapWindow, WinitMapWindowConfig, WinitWindow}; use super::{RawWinitEventLoop, RawWinitWindow, WinitMapWindow, WinitMapWindowConfig};
use crate::winit::WinitEnvironment; use crate::winit::{WinitEnvironment, WinitEventLoop};
impl MapWindow for WinitMapWindow { impl<T> MapWindow for WinitMapWindow<T> {
fn size(&self) -> WindowSize { fn size(&self) -> WindowSize {
let size = self.window.inner_size(); let size = self.window.inner_size();
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
@ -29,27 +34,37 @@ impl MapWindow for WinitMapWindow {
window_size window_size
} }
} }
impl HeadedMapWindow for WinitMapWindow { impl<T> HeadedMapWindow for WinitMapWindow<T> {
type RawWindow = WinitWindow; type RawWindow = RawWinitWindow;
fn inner(&self) -> &Self::RawWindow { fn raw(&self) -> &Self::RawWindow {
&self.window &self.window
} }
fn request_redraw(&self) {
self.window.request_redraw()
}
fn id(&self) -> u64 {
self.window.id().into()
}
} }
impl MapWindowConfig for WinitMapWindowConfig { impl<ET: 'static> MapWindowConfig for WinitMapWindowConfig<ET> {
type MapWindow = WinitMapWindow; type MapWindow = WinitMapWindow<ET>;
fn create(&self) -> Self::MapWindow { fn create(&self) -> Self::MapWindow {
let event_loop = WinitEventLoop::new(); let raw_event_loop = winit::event_loop::EventLoopBuilder::<ET>::with_user_event().build();
let window = WindowBuilder::new() let window = WindowBuilder::new()
.with_title(&self.title) .with_title(&self.title)
.build(&event_loop) .build(&raw_event_loop)
.unwrap(); .unwrap();
Self::MapWindow { Self::MapWindow {
window, window,
event_loop: Some(event_loop), event_loop: Some(WinitEventLoop {
event_loop: raw_event_loop,
}),
} }
} }
} }
@ -57,7 +72,7 @@ impl MapWindowConfig for WinitMapWindowConfig {
pub fn run_headed_map(cache_path: Option<String>) { pub fn run_headed_map(cache_path: Option<String>) {
run_multithreaded(async { run_multithreaded(async {
let client = ReqwestHttpClient::new(cache_path); let client = ReqwestHttpClient::new(cache_path);
MapBuilder::<WinitEnvironment<_, _, _, SchedulerAsyncProcedureCall<_, _>>>::new() let kernel: Kernel<WinitEnvironment<_, _, _, ()>> = KernelBuilder::new()
.with_map_window_config(WinitMapWindowConfig::new("maplibre".to_string())) .with_map_window_config(WinitMapWindowConfig::new("maplibre".to_string()))
.with_http_client(client.clone()) .with_http_client(client.clone())
.with_apc(SchedulerAsyncProcedureCall::new( .with_apc(SchedulerAsyncProcedureCall::new(
@ -65,9 +80,21 @@ pub fn run_headed_map(cache_path: Option<String>) {
TokioScheduler::new(), TokioScheduler::new(),
)) ))
.with_scheduler(TokioScheduler::new()) .with_scheduler(TokioScheduler::new())
.build();
let uninitialized = RenderBuilder::new()
.build() .build()
.initialize() .initialize_with(&kernel)
.await .await
.run() .expect("Failed to initialize renderer");
let result = uninitialized.unwarp();
let mut window = result.window;
let renderer = result.renderer;
window.event_loop.take().unwrap().run(
window,
Map::new(Style::default(), kernel, renderer).unwrap(),
None,
)
}) })
} }

View File

@ -1,13 +1,13 @@
use maplibre::window::{HeadedMapWindow, MapWindow, MapWindowConfig, WindowSize}; use maplibre::window::{HeadedMapWindow, MapWindow, MapWindowConfig, WindowSize};
use winit::{platform::web::WindowBuilderExtWebSys, window::WindowBuilder}; use winit::{platform::web::WindowBuilderExtWebSys, window::WindowBuilder};
use super::{WinitEventLoop, WinitMapWindow, WinitMapWindowConfig, WinitWindow}; use super::{RawWinitEventLoop, RawWinitWindow, WinitMapWindow, WinitMapWindowConfig};
impl MapWindowConfig for WinitMapWindowConfig { impl MapWindowConfig for WinitMapWindowConfig {
type MapWindow = WinitMapWindow; type MapWindow = WinitMapWindow;
fn create(&self) -> Self::MapWindow { fn create(&self) -> Self::MapWindow {
let event_loop = WinitEventLoop::new(); let event_loop = RawWinitEventLoop::new();
let window: winit::window::Window = WindowBuilder::new() let window: winit::window::Window = WindowBuilder::new()
.with_canvas(Some(get_canvas(&self.canvas_id))) .with_canvas(Some(get_canvas(&self.canvas_id)))
@ -31,9 +31,9 @@ impl MapWindow for WinitMapWindow {
} }
} }
impl HeadedMapWindow for WinitMapWindow { impl HeadedMapWindow for WinitMapWindow {
type RawWindow = WinitWindow; type RawWindow = RawWinitWindow;
fn inner(&self) -> &Self::RawWindow { fn raw(&self) -> &Self::RawWindow {
&self.window &self.window
} }
} }

View File

@ -1,3 +1,5 @@
use crate::event_loop::EventLoopConfig;
use crate::kernel::Kernel;
use crate::{ use crate::{
io::{ io::{
apc::AsyncProcedureCall, apc::AsyncProcedureCall,
@ -13,63 +15,7 @@ use crate::{
pub trait Environment: 'static { pub trait Environment: 'static {
type MapWindowConfig: MapWindowConfig; type MapWindowConfig: MapWindowConfig;
type AsyncProcedureCall: AsyncProcedureCall<Self::Transferables, Self::HttpClient>; type AsyncProcedureCall: AsyncProcedureCall<Self::HttpClient>;
type Scheduler: Scheduler; type Scheduler: Scheduler;
type HttpClient: HttpClient; type HttpClient: HttpClient;
type Transferables: Transferables;
}
pub struct Kernel<E: Environment> {
pub map_window_config: E::MapWindowConfig,
pub apc: E::AsyncProcedureCall,
pub scheduler: E::Scheduler,
pub source_client: SourceClient<E::HttpClient>,
}
pub struct KernelBuilder<E: Environment> {
map_window_config: Option<E::MapWindowConfig>,
apc: Option<E::AsyncProcedureCall>,
scheduler: Option<E::Scheduler>,
http_client: Option<E::HttpClient>,
}
impl<E: Environment> KernelBuilder<E> {
pub fn new() -> Self {
Self {
scheduler: None,
apc: None,
http_client: None,
map_window_config: None,
}
}
pub fn with_map_window_config(mut self, map_window_config: E::MapWindowConfig) -> Self {
self.map_window_config = Some(map_window_config);
self
}
pub fn with_scheduler(mut self, scheduler: E::Scheduler) -> Self {
self.scheduler = Some(scheduler);
self
}
pub fn with_apc(mut self, apc: E::AsyncProcedureCall) -> Self {
self.apc = Some(apc);
self
}
pub fn with_http_client(mut self, http_client: E::HttpClient) -> Self {
self.http_client = Some(http_client);
self
}
pub fn build(self) -> Kernel<E> {
Kernel {
scheduler: self.scheduler.unwrap(), // TODO: Remove unwrap
apc: self.apc.unwrap(), // TODO: Remove unwrap
source_client: SourceClient::new(HttpSourceClient::new(self.http_client.unwrap())), // TODO: Remove unwrap
map_window_config: self.map_window_config.unwrap(), // TODO: Remove unwrap
}
}
} }

View File

@ -0,0 +1,29 @@
use crate::environment::Environment;
use crate::map::Map;
use crate::window::{HeadedMapWindow, MapWindowConfig};
pub trait EventLoopConfig {
type EventType: 'static;
type EventLoopProxy: EventLoopProxy<Self::EventType>;
fn create_proxy() -> Self::EventLoopProxy;
}
pub trait EventLoopProxy<T: 'static> {
fn send_event(&self, event: T);
}
pub trait EventLoop<T: 'static> {
type EventLoopProxy: EventLoopProxy<T>;
fn run<E>(
self,
window: <E::MapWindowConfig as MapWindowConfig>::MapWindow,
map: Map<E>,
max_frames: Option<u64>,
) where
E: Environment,
<E::MapWindowConfig as MapWindowConfig>::MapWindow: HeadedMapWindow;
fn create_proxy(&self) -> Self::EventLoopProxy;
}

View File

@ -1,7 +1,6 @@
use crate::environment::Environment; use crate::environment::Environment;
use crate::headless::window::HeadlessMapWindowConfig; use crate::headless::window::HeadlessMapWindowConfig;
use crate::io::apc::SchedulerAsyncProcedureCall; use crate::io::apc::SchedulerAsyncProcedureCall;
use crate::io::transferables::DefaultTransferables;
use crate::platform::http_client::ReqwestHttpClient; use crate::platform::http_client::ReqwestHttpClient;
use crate::platform::scheduler::TokioScheduler; use crate::platform::scheduler::TokioScheduler;
@ -12,5 +11,4 @@ impl Environment for HeadlessEnvironment {
type AsyncProcedureCall = SchedulerAsyncProcedureCall<Self::HttpClient, Self::Scheduler>; type AsyncProcedureCall = SchedulerAsyncProcedureCall<Self::HttpClient, Self::Scheduler>;
type Scheduler = TokioScheduler; type Scheduler = TokioScheduler;
type HttpClient = ReqwestHttpClient; type HttpClient = ReqwestHttpClient;
type Transferables = DefaultTransferables;
} }

View File

@ -1,9 +1,9 @@
use crate::io::pipeline::Processable; use crate::io::pipeline::Processable;
use crate::kernel::Kernel;
use crate::render::builder::UninitializedRenderer; use crate::render::builder::UninitializedRenderer;
use crate::{ use crate::{
context::MapContext, context::MapContext,
coords::{WorldCoords, WorldTileCoords, Zoom, TILE_SIZE}, coords::{WorldCoords, WorldTileCoords, Zoom, TILE_SIZE},
environment::Kernel,
error::Error, error::Error,
headless::{ headless::{
environment::HeadlessEnvironment, graph_node::CopySurfaceBufferNode, environment::HeadlessEnvironment, graph_node::CopySurfaceBufferNode,

View File

@ -48,10 +48,11 @@ pub type AsyncProcedureFuture = Pin<Box<(dyn Future<Output = ()> + 'static)>>;
pub type AsyncProcedure<C> = fn(input: Input, context: C) -> AsyncProcedureFuture; pub type AsyncProcedure<C> = fn(input: Input, context: C) -> AsyncProcedureFuture;
pub trait AsyncProcedureCall<T: Transferables, HC: HttpClient>: 'static { pub trait AsyncProcedureCall<HC: HttpClient>: 'static {
type Context: Context<T, HC> + Send; type Context: Context<Self::Transferables, HC> + Send;
type Transferables: Transferables;
fn receive(&mut self) -> Option<Message<T>>; fn receive(&self) -> Option<Message<Self::Transferables>>;
fn schedule(&self, input: Input, procedure: AsyncProcedure<Self::Context>); fn schedule(&self, input: Input, procedure: AsyncProcedure<Self::Context>);
} }
@ -91,12 +92,11 @@ impl<HC: HttpClient, S: Scheduler> SchedulerAsyncProcedureCall<HC, S> {
} }
} }
impl<HC: HttpClient, S: Scheduler> AsyncProcedureCall<DefaultTransferables, HC> impl<HC: HttpClient, S: Scheduler> AsyncProcedureCall<HC> for SchedulerAsyncProcedureCall<HC, S> {
for SchedulerAsyncProcedureCall<HC, S> type Context = SchedulerContext<Self::Transferables, HC>;
{ type Transferables = DefaultTransferables;
type Context = SchedulerContext<DefaultTransferables, HC>;
fn receive(&mut self) -> Option<Message<DefaultTransferables>> { fn receive(&self) -> Option<Message<DefaultTransferables>> {
let transferred = self.channel.1.try_recv().ok()?; let transferred = self.channel.1.try_recv().ok()?;
Some(transferred) Some(transferred)
} }

56
maplibre/src/kernel.rs Normal file
View File

@ -0,0 +1,56 @@
use crate::environment::Environment;
use crate::io::source_client::{HttpSourceClient, SourceClient};
pub struct Kernel<E: Environment> {
pub map_window_config: E::MapWindowConfig,
pub apc: E::AsyncProcedureCall,
pub scheduler: E::Scheduler,
pub source_client: SourceClient<E::HttpClient>,
}
pub struct KernelBuilder<E: Environment> {
map_window_config: Option<E::MapWindowConfig>,
apc: Option<E::AsyncProcedureCall>,
scheduler: Option<E::Scheduler>,
http_client: Option<E::HttpClient>,
}
impl<E: Environment> KernelBuilder<E> {
pub fn new() -> Self {
Self {
scheduler: None,
apc: None,
http_client: None,
map_window_config: None,
}
}
pub fn with_map_window_config(mut self, map_window_config: E::MapWindowConfig) -> Self {
self.map_window_config = Some(map_window_config);
self
}
pub fn with_scheduler(mut self, scheduler: E::Scheduler) -> Self {
self.scheduler = Some(scheduler);
self
}
pub fn with_apc(mut self, apc: E::AsyncProcedureCall) -> Self {
self.apc = Some(apc);
self
}
pub fn with_http_client(mut self, http_client: E::HttpClient) -> Self {
self.http_client = Some(http_client);
self
}
pub fn build(self) -> Kernel<E> {
Kernel {
scheduler: self.scheduler.unwrap(), // TODO: Remove unwrap
apc: self.apc.unwrap(), // TODO: Remove unwrap
source_client: SourceClient::new(HttpSourceClient::new(self.http_client.unwrap())), // TODO: Remove unwrap
map_window_config: self.map_window_config.unwrap(), // TODO: Remove unwrap
}
}
}

View File

@ -42,6 +42,8 @@ pub mod environment;
// Used for benchmarking // Used for benchmarking
pub mod benchmarking; pub mod benchmarking;
pub mod event_loop;
pub mod kernel;
pub mod map; pub mod map;
pub mod world; pub mod world;

View File

@ -1,15 +1,18 @@
use crate::context::MapContext; use crate::context::MapContext;
use crate::coords::{LatLon, WorldCoords, Zoom, TILE_SIZE}; use crate::coords::{LatLon, WorldCoords, Zoom, TILE_SIZE};
use crate::environment::{Environment, Kernel}; use crate::environment::Environment;
use crate::error::Error; use crate::error::Error;
use crate::headless::environment::HeadlessEnvironment; use crate::headless::environment::HeadlessEnvironment;
use crate::kernel::Kernel;
use crate::render::{create_default_render_graph, register_default_render_stages, Renderer}; use crate::render::{create_default_render_graph, register_default_render_stages, Renderer};
use crate::schedule::{Schedule, Stage}; use crate::schedule::{Schedule, Stage};
use crate::stages::register_stages;
use crate::style::Style; use crate::style::Style;
use crate::world::World; use crate::world::World;
use std::rc::Rc;
pub struct Map<E: Environment> { pub struct Map<E: Environment> {
kernel: Kernel<E>, kernel: Rc<Kernel<E>>,
schedule: Schedule, schedule: Schedule,
map_context: MapContext, map_context: MapContext,
} }
@ -31,6 +34,10 @@ impl<E: Environment> Map<E> {
let graph = create_default_render_graph().unwrap(); // TODO: Remove unwrap let graph = create_default_render_graph().unwrap(); // TODO: Remove unwrap
register_default_render_stages(graph, &mut schedule); register_default_render_stages(graph, &mut schedule);
let kernel = Rc::new(kernel);
register_stages::<E>(&mut schedule, kernel.clone());
Ok(Self { Ok(Self {
kernel, kernel,
map_context: MapContext { map_context: MapContext {

View File

@ -1,5 +1,5 @@
use crate::environment::Kernel;
use crate::error::Error; use crate::error::Error;
use crate::kernel::Kernel;
use crate::{ use crate::{
environment::Environment, environment::Environment,
render::{ render::{
@ -9,17 +9,20 @@ use crate::{
style::Style, style::Style,
window::{HeadedMapWindow, MapWindow, MapWindowConfig}, window::{HeadedMapWindow, MapWindow, MapWindowConfig},
}; };
use std::marker::PhantomData;
pub struct RenderBuilder { pub struct RenderBuilder<MWC: MapWindowConfig> {
wgpu_settings: Option<WgpuSettings>, wgpu_settings: Option<WgpuSettings>,
renderer_settings: Option<RendererSettings>, renderer_settings: Option<RendererSettings>,
phatom_mwc: PhantomData<MWC>,
} }
impl RenderBuilder { impl<MWC: MapWindowConfig> RenderBuilder<MWC> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
wgpu_settings: None, wgpu_settings: None,
renderer_settings: None, renderer_settings: None,
phatom_mwc: Default::default(),
} }
} }
@ -33,21 +36,22 @@ impl RenderBuilder {
self self
} }
pub fn build(self) -> UninitializedRenderer { pub fn build(self) -> UninitializedRenderer<MWC> {
UninitializedRenderer { UninitializedRenderer {
window: None,
wgpu_settings: self.wgpu_settings.unwrap_or_default(), wgpu_settings: self.wgpu_settings.unwrap_or_default(),
renderer_settings: self.renderer_settings.unwrap_or_default(), renderer_settings: self.renderer_settings.unwrap_or_default(),
} }
} }
} }
pub enum InitializationResult { pub enum InitializationResult<MWC: MapWindowConfig> {
Initialized(Renderer), Initialized(InitializedRenderer<MWC>),
Uninizalized(UninitializedRenderer), Uninizalized(UninitializedRenderer<MWC>),
} }
impl InitializationResult { impl<MWC: MapWindowConfig> InitializationResult<MWC> {
pub fn unwarp(self) -> Renderer { pub fn unwarp(self) -> InitializedRenderer<MWC> {
match self { match self {
InitializationResult::Initialized(renderer) => renderer, InitializationResult::Initialized(renderer) => renderer,
InitializationResult::Uninizalized(_) => panic!("Renderer is not initialized"), InitializationResult::Uninizalized(_) => panic!("Renderer is not initialized"),
@ -55,55 +59,55 @@ impl InitializationResult {
} }
} }
pub struct UninitializedRenderer { pub struct UninitializedRenderer<MWC: MapWindowConfig> {
window: Option<MWC::MapWindow>,
wgpu_settings: WgpuSettings, wgpu_settings: WgpuSettings,
renderer_settings: RendererSettings, renderer_settings: RendererSettings,
} }
impl UninitializedRenderer { impl<MWC: MapWindowConfig> UninitializedRenderer<MWC>
where
MWC::MapWindow: MapWindow + HeadedMapWindow,
{
/// Initializes the whole rendering pipeline for the given configuration. /// Initializes the whole rendering pipeline for the given configuration.
/// Returns the initialized map, ready to be run. /// Returns the initialized map, ready to be run.
async fn initialize<MWC: MapWindowConfig>( async fn initialize(self, map_window_config: &MWC) -> Result<InitializationResult<MWC>, Error> {
self,
map_window_config: &MWC,
) -> Result<InitializationResult, Error>
where
MWC::MapWindow: MapWindow + HeadedMapWindow,
{
let window = map_window_config.create(); let window = map_window_config.create();
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
let renderer = Ok(InitializationResult::Uninizalized(self)); {
Ok(InitializationResult::Uninizalized(self))
}
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
let renderer = Ok(InitializationResult::Initialized( {
Renderer::initialize( let renderer = Renderer::initialize(
&window, &window,
self.wgpu_settings.clone(), self.wgpu_settings.clone(),
self.renderer_settings.clone(), self.renderer_settings.clone(),
) )
.await?, .await?;
)); Ok(InitializationResult::Initialized(InitializedRenderer {
window,
renderer renderer,
}))
}
} }
pub async fn initialize_with<E: Environment>( pub async fn initialize_with<E>(
self, self,
kernel: &Kernel<E>, kernel: &Kernel<E>,
) -> Result<InitializationResult, Error> ) -> Result<InitializationResult<MWC>, Error>
where where
<E::MapWindowConfig as MapWindowConfig>::MapWindow: MapWindow + HeadedMapWindow, E: Environment<MapWindowConfig = MWC>,
{ {
self.initialize(&kernel.map_window_config).await self.initialize(&kernel.map_window_config).await
} }
} }
#[cfg(feature = "headless")] #[cfg(feature = "headless")]
impl UninitializedRenderer { impl<MWC: MapWindowConfig> UninitializedRenderer<MWC> {
async fn initialize_headless<MWC: MapWindowConfig>( async fn initialize_headless(self, map_window_config: &MWC) -> Result<Renderer, Error> {
self,
map_window_config: MWC,
) -> Result<Renderer, Error> {
let window = map_window_config.create(); let window = map_window_config.create();
Ok(Renderer::initialize_headless( Ok(Renderer::initialize_headless(
@ -114,13 +118,15 @@ impl UninitializedRenderer {
.await?) .await?)
} }
pub async fn initialize_headless_with<E: Environment>( pub async fn initialize_headless_with<E>(self, kernel: &Kernel<E>) -> Result<Renderer, Error>
self,
kernel: &Kernel<E>,
) -> Result<InitializationResult, Error>
where where
<E::MapWindowConfig as MapWindowConfig>::MapWindow: MapWindow + HeadedMapWindow, E: Environment<MapWindowConfig = MWC>,
{ {
self.initialize(&kernel.map_window_config).await self.initialize_headless(&kernel.map_window_config).await
} }
} }
pub struct InitializedRenderer<MWC: MapWindowConfig> {
pub window: MWC::MapWindow,
pub renderer: Renderer,
}

View File

@ -1,6 +1,6 @@
//! Main camera //! Main camera
use cgmath::{prelude::*, AbsDiffEq, Matrix4, Point2, Point3, Vector2, Vector3, Vector4}; use cgmath::{prelude::*, AbsDiffEq, Matrix4, Point2, Point3, Rad, Vector2, Vector3, Vector4};
use crate::util::{ use crate::util::{
math::{bounds_from_points, Aabb2, Aabb3, Plane}, math::{bounds_from_points, Aabb2, Aabb3, Plane},
@ -68,12 +68,12 @@ impl ModelViewProjection {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Camera { pub struct Camera {
pub position: Point3<f64>, // The z axis never changes, the zoom is used instead position: Point3<f64>, // The z axis never changes, the zoom is used instead
pub yaw: cgmath::Rad<f64>, yaw: cgmath::Rad<f64>,
pub pitch: cgmath::Rad<f64>, pitch: cgmath::Rad<f64>,
pub width: f64, width: f64,
pub height: f64, height: f64,
} }
impl SignificantlyDifferent for Camera { impl SignificantlyDifferent for Camera {
@ -103,6 +103,14 @@ impl Camera {
} }
} }
pub fn move_to(&mut self, point: Point3<f64>) {
self.position = point;
}
pub fn move_relative(&mut self, delta: Vector3<f64>) {
self.position += delta;
}
pub fn resize(&mut self, width: u32, height: u32) { pub fn resize(&mut self, width: u32, height: u32) {
self.width = width as f64; self.width = width as f64;
self.height = height as f64; self.height = height as f64;
@ -347,6 +355,26 @@ impl Camera {
Point2::new(max_x, max_y), Point2::new(max_x, max_y),
)) ))
} }
pub fn position(&self) -> Point3<f64> {
self.position
}
pub fn yaw(&self) -> cgmath::Rad<f64> {
self.yaw
}
pub fn yaw_self<P: Into<Rad<f64>>>(&mut self, delta: P) {
self.yaw += delta.into();
}
pub fn pitch(&self) -> cgmath::Rad<f64> {
self.pitch
}
pub fn pitch_self<P: Into<Rad<f64>>>(&mut self, delta: P) {
self.pitch += delta.into();
}
} }
pub struct Perspective { pub struct Perspective {

View File

@ -45,7 +45,8 @@ impl Stage for UploadStage {
bytemuck::cast_slice(&[ShaderGlobals::new(ShaderCamera::new( bytemuck::cast_slice(&[ShaderGlobals::new(ShaderCamera::new(
view_proj.downcast().into(), view_proj.downcast().into(),
view_state view_state
.camera_position() .camera()
.position()
.to_homogeneous() .to_homogeneous()
.cast::<f32>() .cast::<f32>()
.unwrap() // TODO: Remove unwrap .unwrap() // TODO: Remove unwrap

View File

@ -10,6 +10,7 @@ use std::{
use geozero::{mvt::tile, GeozeroDatasource}; use geozero::{mvt::tile, GeozeroDatasource};
use request_stage::RequestStage; use request_stage::RequestStage;
use crate::kernel::Kernel;
use crate::{ use crate::{
coords::{WorldCoords, WorldTileCoords, Zoom, ZoomLevel}, coords::{WorldCoords, WorldTileCoords, Zoom, ZoomLevel},
environment::Environment, environment::Environment,
@ -37,16 +38,9 @@ mod populate_tile_store_stage;
mod request_stage; mod request_stage;
/// Register stages required for requesting and preparing new tiles. /// Register stages required for requesting and preparing new tiles.
pub fn register_stages<E: Environment>( pub fn register_stages<E: Environment>(schedule: &mut Schedule, kernel: Rc<Kernel<E>>) {
schedule: &mut Schedule, schedule.add_stage("request", RequestStage::<E>::new(kernel.clone()));
http_source_client: HttpSourceClient<E::HttpClient>, schedule.add_stage("populate_tile_store", PopulateTileStore::<E>::new(kernel));
apc: Rc<RefCell<E::AsyncProcedureCall>>,
) {
schedule.add_stage(
"request",
RequestStage::<E>::new(http_source_client, apc.clone()),
);
schedule.add_stage("populate_tile_store", PopulateTileStore::<E>::new(apc));
} }
pub struct HeadedPipelineProcessor<T: Transferables, HC: HttpClient, C: Context<T, HC>> { pub struct HeadedPipelineProcessor<T: Transferables, HC: HttpClient, C: Context<T, HC>> {

View File

@ -2,6 +2,7 @@
use std::{borrow::BorrowMut, cell::RefCell, ops::Deref, rc::Rc}; use std::{borrow::BorrowMut, cell::RefCell, ops::Deref, rc::Rc};
use crate::kernel::Kernel;
use crate::{ use crate::{
context::MapContext, context::MapContext,
environment::Environment, environment::Environment,
@ -15,12 +16,12 @@ use crate::{
}; };
pub struct PopulateTileStore<E: Environment> { pub struct PopulateTileStore<E: Environment> {
apc: Rc<RefCell<E::AsyncProcedureCall>>, kernel: Rc<Kernel<E>>,
} }
impl<E: Environment> PopulateTileStore<E> { impl<E: Environment> PopulateTileStore<E> {
pub fn new(apc: Rc<RefCell<E::AsyncProcedureCall>>) -> Self { pub fn new(kernel: Rc<Kernel<E>>) -> Self {
Self { apc } Self { kernel }
} }
} }
@ -34,39 +35,37 @@ impl<E: Environment> Stage for PopulateTileStore<E> {
.. ..
}: &mut MapContext, }: &mut MapContext,
) { ) {
if let Ok(mut apc) = self.apc.deref().try_borrow_mut() { if let Some(result) = self.kernel.apc.receive() {
if let Some(result) = apc.receive() { match result {
match result { Message::TileTessellated(tranferred) => {
Message::TileTessellated(tranferred) => { let coords = tranferred.coords();
let coords = tranferred.coords(); tile_repository.success(coords);
tile_repository.success(coords); tracing::trace!("Tile at {} finished loading", coords);
tracing::trace!("Tile at {} finished loading", coords); log::warn!("Tile at {} finished loading", coords);
log::warn!("Tile at {} finished loading", coords); }
} // FIXME: deduplicate
// FIXME: deduplicate Message::UnavailableLayer(tranferred) => {
Message::UnavailableLayer(tranferred) => { let layer: StoredLayer = tranferred.to_stored_layer();
let layer: StoredLayer = tranferred.to_stored_layer(); tracing::debug!(
tracing::debug!( "Layer {} at {} reached main thread",
"Layer {} at {} reached main thread", layer.layer_name(),
layer.layer_name(), layer.get_coords()
layer.get_coords() );
); tile_repository.put_tessellated_layer(layer);
tile_repository.put_tessellated_layer(layer); }
} Message::TessellatedLayer(data) => {
Message::TessellatedLayer(data) => { let layer: StoredLayer = data.to_stored_layer();
let layer: StoredLayer = data.to_stored_layer(); tracing::debug!(
tracing::debug!( "Layer {} at {} reached main thread",
"Layer {} at {} reached main thread", layer.layer_name(),
layer.layer_name(), layer.get_coords()
layer.get_coords() );
); log::warn!(
log::warn!( "Layer {} at {} reached main thread",
"Layer {} at {} reached main thread", layer.layer_name(),
layer.layer_name(), layer.get_coords()
layer.get_coords() );
); tile_repository.put_tessellated_layer(layer);
tile_repository.put_tessellated_layer(layer);
}
} }
} }
} }

View File

@ -12,6 +12,7 @@ use std::{
str::FromStr, str::FromStr,
}; };
use crate::kernel::Kernel;
use crate::{ use crate::{
context::MapContext, context::MapContext,
coords::{ViewRegion, WorldTileCoords, ZoomLevel}, coords::{ViewRegion, WorldTileCoords, ZoomLevel},
@ -33,19 +34,12 @@ use crate::{
}; };
pub struct RequestStage<E: Environment> { pub struct RequestStage<E: Environment> {
apc: Rc<RefCell<E::AsyncProcedureCall>>, kernel: Rc<Kernel<E>>,
http_source_client: HttpSourceClient<E::HttpClient>,
} }
impl<E: Environment> RequestStage<E> { impl<E: Environment> RequestStage<E> {
pub fn new( pub fn new(kernel: Rc<Kernel<E>>) -> Self {
http_source_client: HttpSourceClient<E::HttpClient>, Self { kernel }
apc: Rc<RefCell<E::AsyncProcedureCall>>,
) -> Self {
Self {
apc,
http_source_client,
}
} }
} }
@ -75,7 +69,13 @@ impl<E: Environment> Stage for RequestStage<E> {
} }
} }
pub fn schedule<E: Environment, C: Context<E::Transferables, E::HttpClient>>( pub fn schedule<
E: Environment,
C: Context<
<E::AsyncProcedureCall as AsyncProcedureCall<E::HttpClient>>::Transferables,
E::HttpClient,
>,
>(
input: Input, input: Input,
context: C, context: C,
) -> AsyncProcedureFuture { ) -> AsyncProcedureFuture {
@ -106,12 +106,14 @@ pub fn schedule<E: Environment, C: Context<E::Transferables, E::HttpClient>>(
log::error!("{:?}", &e); log::error!("{:?}", &e);
for to_load in &input.layers { for to_load in &input.layers {
tracing::warn!("layer {} at {} unavailable", to_load, coords); tracing::warn!("layer {} at {} unavailable", to_load, coords);
context.send(Message::UnavailableLayer( context.send(
<E::Transferables as Transferables>::UnavailableLayer::new( Message::UnavailableLayer(<<E::AsyncProcedureCall as AsyncProcedureCall<
E::HttpClient,
>>::Transferables as Transferables>::UnavailableLayer::new(
input.coords, input.coords,
to_load.to_string(), to_load.to_string(),
), )),
)); );
} }
} }
} }
@ -156,7 +158,7 @@ impl<E: Environment> RequestStage<E> {
tile_repository.create_tile(coords); tile_repository.create_tile(coords);
tracing::info!("new tile request: {}", &coords); tracing::info!("new tile request: {}", &coords);
self.apc.deref().borrow().schedule( self.kernel.apc.schedule(
Input::TileRequest(TileRequest { Input::TileRequest(TileRequest {
coords, coords,
layers: layers.clone(), layers: layers.clone(),
@ -164,7 +166,6 @@ impl<E: Environment> RequestStage<E> {
schedule::< schedule::<
E, E,
<E::AsyncProcedureCall as AsyncProcedureCall< <E::AsyncProcedureCall as AsyncProcedureCall<
E::Transferables,
E::HttpClient, E::HttpClient,
>>::Context, >>::Context,
>, >,

View File

@ -17,6 +17,11 @@ pub trait HeadedMapWindow: MapWindow {
type RawWindow: HasRawWindowHandle + HasRawDisplayHandle; type RawWindow: HasRawWindowHandle + HasRawDisplayHandle;
fn raw(&self) -> &Self::RawWindow; fn raw(&self) -> &Self::RawWindow;
// TODO: Can we avoid this?
fn request_redraw(&self);
fn id(&self) -> u64;
} }
/// A configuration for a window which determines the corresponding implementation of a /// A configuration for a window which determines the corresponding implementation of a

View File

@ -1,4 +1,5 @@
use cgmath::{Angle, Point3}; use cgmath::{Angle, Point3};
use std::ops::{Deref, DerefMut};
use crate::{ use crate::{
coords::{LatLon, ViewRegion, WorldCoords, Zoom, ZoomLevel, TILE_SIZE}, coords::{LatLon, ViewRegion, WorldCoords, Zoom, ZoomLevel, TILE_SIZE},
@ -124,14 +125,23 @@ impl ViewState {
*self.zoom *self.zoom
} }
pub fn camera_position(&self) -> Point3<f64> {
self.camera.position
}
pub fn did_zoom_change(&self) -> bool { pub fn did_zoom_change(&self) -> bool {
self.zoom.did_change(0.05) self.zoom.did_change(0.05)
} }
pub fn update_zoom(&mut self, new_zoom: Zoom) {
*self.zoom = new_zoom;
log::info!("zoom: {}", new_zoom);
}
pub fn camera(&self) -> &Camera {
self.camera.deref()
}
pub fn camera_mut(&mut self) -> &mut Camera {
self.camera.deref_mut()
}
pub fn did_camera_change(&self) -> bool { pub fn did_camera_change(&self) -> bool {
self.camera.did_change(0.05) self.camera.did_change(0.05)
} }
@ -140,9 +150,4 @@ impl ViewState {
self.camera.update_reference(); self.camera.update_reference();
self.zoom.update_reference(); self.zoom.update_reference();
} }
pub fn update_zoom(&mut self, new_zoom: Zoom) {
*self.zoom = new_zoom;
log::info!("zoom: {}", new_zoom);
}
} }