mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Fix compilation in winit and demo module
This commit is contained in:
parent
c6eadbf2cc
commit
c663416d05
@ -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),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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::{
|
||||||
|
|||||||
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
29
maplibre/src/event_loop.rs
Normal file
29
maplibre/src/event_loop.rs
Normal 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;
|
||||||
|
}
|
||||||
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
56
maplibre/src/kernel.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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,
|
||||||
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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>> {
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
>,
|
>,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user