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::{
|
||||
coords::{LatLon, WorldTileCoords},
|
||||
error::Error,
|
||||
headless::{HeadlessEnvironment, HeadlessMapWindowConfig},
|
||||
io::apc::SchedulerAsyncProcedureCall,
|
||||
platform::{http_client::ReqwestHttpClient, scheduler::TokioScheduler},
|
||||
render::settings::{RendererSettings, TextureFormat},
|
||||
util::grid::google_mercator,
|
||||
window::WindowSize,
|
||||
MapBuilder,
|
||||
};
|
||||
use maplibre_winit::winit::WinitEnvironment;
|
||||
use tile_grid::{extent_wgs84_to_merc, Extent, GridIterator};
|
||||
|
||||
pub async fn run_headless(tile_size: u32, min: LatLon, max: LatLon) {
|
||||
let client = ReqwestHttpClient::new(None);
|
||||
let mut map =
|
||||
MapBuilder::<HeadlessEnvironment<_, _, _, SchedulerAsyncProcedureCall<_, _>>>::new()
|
||||
.with_map_window_config(HeadlessMapWindowConfig {
|
||||
size: WindowSize::new(tile_size, tile_size).unwrap(),
|
||||
})
|
||||
.with_http_client(client.clone())
|
||||
.with_apc(SchedulerAsyncProcedureCall::new(
|
||||
client,
|
||||
TokioScheduler::new(),
|
||||
)) // FIXME (wasm-executor): avoid passing client and scheduler here
|
||||
.with_scheduler(TokioScheduler::new())
|
||||
.with_renderer_settings(RendererSettings {
|
||||
texture_format: TextureFormat::Rgba8UnormSrgb,
|
||||
..RendererSettings::default()
|
||||
})
|
||||
.build()
|
||||
.initialize_headless()
|
||||
.await;
|
||||
let kernel = KernelBuilder::new()
|
||||
.with_map_window_config(HeadlessMapWindowConfig::new(
|
||||
WindowSize::new(tile_size, tile_size).unwrap(),
|
||||
))
|
||||
.with_http_client(client.clone())
|
||||
.with_apc(SchedulerAsyncProcedureCall::new(
|
||||
client,
|
||||
TokioScheduler::new(),
|
||||
))
|
||||
.with_scheduler(TokioScheduler::new())
|
||||
.build();
|
||||
|
||||
let renderer = RenderBuilder::new()
|
||||
.build()
|
||||
.initialize_headless_with(&kernel)
|
||||
.await
|
||||
.expect("Failed to initialize renderer");
|
||||
|
||||
let mut map = HeadlessMap::new(Style::default(), renderer, kernel).unwrap();
|
||||
|
||||
let tile_limits = google_mercator().tile_limits(
|
||||
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) {
|
||||
let coords = WorldTileCoords::from((x as i32, y as i32, z.into()));
|
||||
println!("Rendering {}", &coords);
|
||||
map.map_schedule
|
||||
.fetch_process(&coords)
|
||||
let tile = map
|
||||
.fetch_tile(coords, &["water"])
|
||||
.await
|
||||
.expect("Failed to fetch and process!");
|
||||
|
||||
match map.map_schedule_mut().update_and_redraw() {
|
||||
Ok(_) => {}
|
||||
Err(Error::Render(e)) => {
|
||||
eprintln!("{}", e);
|
||||
if e.should_exit() {}
|
||||
}
|
||||
e => eprintln!("{:?}", e),
|
||||
};
|
||||
map.render_tile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::Vector2;
|
||||
use maplibre::context::ViewState;
|
||||
use maplibre::world::ViewState;
|
||||
use winit::event::{DeviceEvent, KeyboardInput, TouchPhase, WindowEvent};
|
||||
|
||||
use crate::input::{
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
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 super::UpdateState;
|
||||
@ -45,17 +45,17 @@ impl UpdateState for PanHandler {
|
||||
};
|
||||
|
||||
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 {
|
||||
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),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.reference_camera = Some(state.camera.clone());
|
||||
self.reference_camera = Some(state.camera().clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use maplibre::context::ViewState;
|
||||
use maplibre::world::ViewState;
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::Vector2;
|
||||
use maplibre::context::ViewState;
|
||||
use maplibre::world::ViewState;
|
||||
use winit::event::{ElementState, MouseButton};
|
||||
|
||||
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 _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,
|
||||
&inverted_view_proj,
|
||||
false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{Vector3, Zero};
|
||||
use maplibre::context::ViewState;
|
||||
use maplibre::world::ViewState;
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -17,7 +17,7 @@ impl UpdateState for ShiftHandler {
|
||||
let dt = dt.as_secs_f64() * (1.0 / self.speed);
|
||||
|
||||
let delta = self.camera_translate * dt;
|
||||
state.camera.position += delta;
|
||||
state.camera_mut().move_relative(delta);
|
||||
self.camera_translate -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{Deg, Rad, Zero};
|
||||
use maplibre::context::ViewState;
|
||||
use maplibre::world::ViewState;
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -17,7 +17,7 @@ impl UpdateState for TiltHandler {
|
||||
let dt = dt.as_secs_f64() * (1.0 / self.speed);
|
||||
|
||||
let delta = self.delta_pitch * dt;
|
||||
state.camera.pitch += Rad::from(delta);
|
||||
state.camera_mut().pitch_self(delta);
|
||||
self.delta_pitch -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{Vector2, Vector3};
|
||||
use maplibre::{context::ViewState, coords::Zoom};
|
||||
use maplibre::{coords::Zoom, world::ViewState};
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -24,7 +24,7 @@ impl UpdateState for ZoomHandler {
|
||||
let view_proj = state.view_projection();
|
||||
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,
|
||||
&inverted_view_proj,
|
||||
false,
|
||||
@ -37,7 +37,7 @@ impl UpdateState for ZoomHandler {
|
||||
cursor_position.z,
|
||||
) - 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 maplibre::event_loop::{EventLoop, EventLoopProxy};
|
||||
use maplibre::map::Map;
|
||||
use maplibre::{
|
||||
environment::Environment,
|
||||
error::Error,
|
||||
@ -10,15 +11,17 @@ use maplibre::{
|
||||
source_client::HttpClient,
|
||||
transferables::{DefaultTransferables, Transferables},
|
||||
},
|
||||
map_schedule::InteractiveMapSchedule,
|
||||
window::{EventLoop, HeadedMapWindow, MapWindowConfig},
|
||||
window::{HeadedMapWindow, MapWindowConfig},
|
||||
};
|
||||
use std::{cell::RefCell, marker::PhantomData, ops::Deref, rc::Rc};
|
||||
use winit::{
|
||||
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
||||
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")]
|
||||
mod web;
|
||||
@ -32,14 +35,19 @@ pub use noweb::*;
|
||||
pub use web::*;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub struct WinitMapWindowConfig {
|
||||
pub struct WinitMapWindowConfig<ET> {
|
||||
title: String,
|
||||
|
||||
phantom_et: PhantomData<ET>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl WinitMapWindowConfig {
|
||||
impl<ET> WinitMapWindowConfig<ET> {
|
||||
pub fn new(title: String) -> Self {
|
||||
Self { title }
|
||||
Self {
|
||||
title,
|
||||
phantom_et: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,151 +63,157 @@ impl WinitMapWindowConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WinitMapWindow {
|
||||
window: WinitWindow,
|
||||
event_loop: Option<WinitEventLoop>,
|
||||
pub struct WinitMapWindow<ET: 'static> {
|
||||
window: RawWinitWindow,
|
||||
event_loop: Option<WinitEventLoop<ET>>,
|
||||
}
|
||||
|
||||
impl WinitMapWindow {
|
||||
pub fn take_event_loop(&mut self) -> Option<WinitEventLoop> {
|
||||
impl<ET> WinitMapWindow<ET> {
|
||||
pub fn take_event_loop(&mut self) -> Option<WinitEventLoop<ET>> {
|
||||
self.event_loop.take()
|
||||
}
|
||||
}
|
||||
|
||||
pub type WinitWindow = winit::window::Window;
|
||||
pub type WinitEventLoop = winit::event_loop::EventLoop<()>;
|
||||
|
||||
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>,
|
||||
pub struct WinitEventLoop<ET: 'static> {
|
||||
event_loop: RawWinitEventLoop<ET>,
|
||||
}
|
||||
|
||||
impl<S: Scheduler, HC: HttpClient, T: Transferables, APC: AsyncProcedureCall<T, HC>> Environment
|
||||
for WinitEnvironment<S, HC, T, APC>
|
||||
{
|
||||
type MapWindowConfig = WinitMapWindowConfig;
|
||||
type AsyncProcedureCall = APC;
|
||||
type Scheduler = S;
|
||||
type HttpClient = HC;
|
||||
type Transferables = T;
|
||||
}
|
||||
impl<ET: 'static> EventLoop<ET> for WinitEventLoop<ET> {
|
||||
type EventLoopProxy = WinitEventLoopProxy<ET>;
|
||||
|
||||
///Main (platform-specific) main loop which handles:
|
||||
///* 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(
|
||||
fn run<E>(
|
||||
mut self,
|
||||
map_schedule: Rc<RefCell<InteractiveMapSchedule<E>>>,
|
||||
mut window: <E::MapWindowConfig as MapWindowConfig>::MapWindow,
|
||||
mut map: Map<E>,
|
||||
max_frames: Option<u64>,
|
||||
) {
|
||||
) where
|
||||
E: Environment,
|
||||
<E::MapWindowConfig as MapWindowConfig>::MapWindow: HeadedMapWindow,
|
||||
{
|
||||
let mut last_render_time = Instant::now();
|
||||
let mut current_frame: u64 = 0;
|
||||
|
||||
let mut input_controller = InputController::new(0.2, 100.0, 0.1);
|
||||
|
||||
self.take_event_loop()
|
||||
.unwrap()
|
||||
.run(move |event, _, control_flow| {
|
||||
let mut map_schedule = map_schedule.deref().borrow_mut();
|
||||
|
||||
self.event_loop
|
||||
.run(move |event, window_target, control_flow| {
|
||||
#[cfg(target_os = "android")]
|
||||
if !map_schedule.is_initialized() && event == Event::Resumed {
|
||||
if !map.is_initialized() && event == Event::Resumed {
|
||||
use tokio::{runtime::Handle, task};
|
||||
|
||||
task::block_in_place(|| {
|
||||
Handle::current().block_on(async {
|
||||
map_schedule.late_init().await;
|
||||
map.late_init().await;
|
||||
})
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
match event {
|
||||
Event::DeviceEvent {
|
||||
ref event,
|
||||
.. // We're not using device_id currently
|
||||
} => {
|
||||
input_controller.device_input(event);
|
||||
}
|
||||
Event::DeviceEvent {
|
||||
ref event,
|
||||
.. // We're not using device_id currently
|
||||
} => {
|
||||
input_controller.device_input(event);
|
||||
}
|
||||
|
||||
Event::WindowEvent {
|
||||
ref event,
|
||||
window_id,
|
||||
} if window_id == self.inner().id() => {
|
||||
if !input_controller.window_input(event) {
|
||||
match event {
|
||||
WindowEvent::CloseRequested
|
||||
| WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
state: ElementState::Pressed,
|
||||
virtual_keycode: Some(VirtualKeyCode::Escape),
|
||||
Event::WindowEvent {
|
||||
ref event,
|
||||
window_id,
|
||||
} if window_id == window.id().into() => {
|
||||
if !input_controller.window_input(event) {
|
||||
match event {
|
||||
WindowEvent::CloseRequested
|
||||
| WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
state: ElementState::Pressed,
|
||||
virtual_keycode: Some(VirtualKeyCode::Escape),
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
..
|
||||
} => *control_flow = ControlFlow::Exit,
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
map_schedule.resize(physical_size.width, physical_size.height);
|
||||
} => *control_flow = ControlFlow::Exit,
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
// FIXME map.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(_) => {
|
||||
let now = Instant::now();
|
||||
let dt = now - last_render_time;
|
||||
last_render_time = now;
|
||||
Event::RedrawRequested(_) => {
|
||||
let now = Instant::now();
|
||||
let dt = now - last_render_time;
|
||||
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() {
|
||||
Ok(_) => {}
|
||||
Err(Error::Render(e)) => {
|
||||
eprintln!("{}", e);
|
||||
if e.should_exit() {
|
||||
match map.run_schedule() {
|
||||
Ok(_) => {}
|
||||
Err(Error::Render(e)) => {
|
||||
eprintln!("{}", e);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
current_frame += 1;
|
||||
}
|
||||
|
||||
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
|
||||
//! * 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::{
|
||||
io::apc::SchedulerAsyncProcedureCall,
|
||||
platform::{http_client::ReqwestHttpClient, run_multithreaded, scheduler::TokioScheduler},
|
||||
window::{HeadedMapWindow, MapWindow, MapWindowConfig, WindowSize},
|
||||
MapBuilder,
|
||||
};
|
||||
use winit::window::WindowBuilder;
|
||||
|
||||
use super::{WinitEventLoop, WinitMapWindow, WinitMapWindowConfig, WinitWindow};
|
||||
use crate::winit::WinitEnvironment;
|
||||
use super::{RawWinitEventLoop, RawWinitWindow, WinitMapWindow, WinitMapWindowConfig};
|
||||
use crate::winit::{WinitEnvironment, WinitEventLoop};
|
||||
|
||||
impl MapWindow for WinitMapWindow {
|
||||
impl<T> MapWindow for WinitMapWindow<T> {
|
||||
fn size(&self) -> WindowSize {
|
||||
let size = self.window.inner_size();
|
||||
#[cfg(target_os = "android")]
|
||||
@ -29,27 +34,37 @@ impl MapWindow for WinitMapWindow {
|
||||
window_size
|
||||
}
|
||||
}
|
||||
impl HeadedMapWindow for WinitMapWindow {
|
||||
type RawWindow = WinitWindow;
|
||||
impl<T> HeadedMapWindow for WinitMapWindow<T> {
|
||||
type RawWindow = RawWinitWindow;
|
||||
|
||||
fn inner(&self) -> &Self::RawWindow {
|
||||
fn raw(&self) -> &Self::RawWindow {
|
||||
&self.window
|
||||
}
|
||||
|
||||
fn request_redraw(&self) {
|
||||
self.window.request_redraw()
|
||||
}
|
||||
|
||||
fn id(&self) -> u64 {
|
||||
self.window.id().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl MapWindowConfig for WinitMapWindowConfig {
|
||||
type MapWindow = WinitMapWindow;
|
||||
impl<ET: 'static> MapWindowConfig for WinitMapWindowConfig<ET> {
|
||||
type MapWindow = WinitMapWindow<ET>;
|
||||
|
||||
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()
|
||||
.with_title(&self.title)
|
||||
.build(&event_loop)
|
||||
.build(&raw_event_loop)
|
||||
.unwrap();
|
||||
|
||||
Self::MapWindow {
|
||||
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>) {
|
||||
run_multithreaded(async {
|
||||
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_http_client(client.clone())
|
||||
.with_apc(SchedulerAsyncProcedureCall::new(
|
||||
@ -65,9 +80,21 @@ pub fn run_headed_map(cache_path: Option<String>) {
|
||||
TokioScheduler::new(),
|
||||
))
|
||||
.with_scheduler(TokioScheduler::new())
|
||||
.build();
|
||||
|
||||
let uninitialized = RenderBuilder::new()
|
||||
.build()
|
||||
.initialize()
|
||||
.initialize_with(&kernel)
|
||||
.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 winit::{platform::web::WindowBuilderExtWebSys, window::WindowBuilder};
|
||||
|
||||
use super::{WinitEventLoop, WinitMapWindow, WinitMapWindowConfig, WinitWindow};
|
||||
use super::{RawWinitEventLoop, RawWinitWindow, WinitMapWindow, WinitMapWindowConfig};
|
||||
|
||||
impl MapWindowConfig for WinitMapWindowConfig {
|
||||
type MapWindow = WinitMapWindow;
|
||||
|
||||
fn create(&self) -> Self::MapWindow {
|
||||
let event_loop = WinitEventLoop::new();
|
||||
let event_loop = RawWinitEventLoop::new();
|
||||
|
||||
let window: winit::window::Window = WindowBuilder::new()
|
||||
.with_canvas(Some(get_canvas(&self.canvas_id)))
|
||||
@ -31,9 +31,9 @@ impl MapWindow for WinitMapWindow {
|
||||
}
|
||||
}
|
||||
impl HeadedMapWindow for WinitMapWindow {
|
||||
type RawWindow = WinitWindow;
|
||||
type RawWindow = RawWinitWindow;
|
||||
|
||||
fn inner(&self) -> &Self::RawWindow {
|
||||
fn raw(&self) -> &Self::RawWindow {
|
||||
&self.window
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use crate::event_loop::EventLoopConfig;
|
||||
use crate::kernel::Kernel;
|
||||
use crate::{
|
||||
io::{
|
||||
apc::AsyncProcedureCall,
|
||||
@ -13,63 +15,7 @@ use crate::{
|
||||
pub trait Environment: 'static {
|
||||
type MapWindowConfig: MapWindowConfig;
|
||||
|
||||
type AsyncProcedureCall: AsyncProcedureCall<Self::Transferables, Self::HttpClient>;
|
||||
type AsyncProcedureCall: AsyncProcedureCall<Self::HttpClient>;
|
||||
type Scheduler: Scheduler;
|
||||
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::headless::window::HeadlessMapWindowConfig;
|
||||
use crate::io::apc::SchedulerAsyncProcedureCall;
|
||||
use crate::io::transferables::DefaultTransferables;
|
||||
use crate::platform::http_client::ReqwestHttpClient;
|
||||
use crate::platform::scheduler::TokioScheduler;
|
||||
|
||||
@ -12,5 +11,4 @@ impl Environment for HeadlessEnvironment {
|
||||
type AsyncProcedureCall = SchedulerAsyncProcedureCall<Self::HttpClient, Self::Scheduler>;
|
||||
type Scheduler = TokioScheduler;
|
||||
type HttpClient = ReqwestHttpClient;
|
||||
type Transferables = DefaultTransferables;
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use crate::io::pipeline::Processable;
|
||||
use crate::kernel::Kernel;
|
||||
use crate::render::builder::UninitializedRenderer;
|
||||
use crate::{
|
||||
context::MapContext,
|
||||
coords::{WorldCoords, WorldTileCoords, Zoom, TILE_SIZE},
|
||||
environment::Kernel,
|
||||
error::Error,
|
||||
headless::{
|
||||
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 trait AsyncProcedureCall<T: Transferables, HC: HttpClient>: 'static {
|
||||
type Context: Context<T, HC> + Send;
|
||||
pub trait AsyncProcedureCall<HC: HttpClient>: 'static {
|
||||
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>);
|
||||
}
|
||||
@ -91,12 +92,11 @@ impl<HC: HttpClient, S: Scheduler> SchedulerAsyncProcedureCall<HC, S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<HC: HttpClient, S: Scheduler> AsyncProcedureCall<DefaultTransferables, HC>
|
||||
for SchedulerAsyncProcedureCall<HC, S>
|
||||
{
|
||||
type Context = SchedulerContext<DefaultTransferables, HC>;
|
||||
impl<HC: HttpClient, S: Scheduler> AsyncProcedureCall<HC> for SchedulerAsyncProcedureCall<HC, S> {
|
||||
type Context = SchedulerContext<Self::Transferables, HC>;
|
||||
type Transferables = DefaultTransferables;
|
||||
|
||||
fn receive(&mut self) -> Option<Message<DefaultTransferables>> {
|
||||
fn receive(&self) -> Option<Message<DefaultTransferables>> {
|
||||
let transferred = self.channel.1.try_recv().ok()?;
|
||||
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
|
||||
pub mod benchmarking;
|
||||
|
||||
pub mod event_loop;
|
||||
pub mod kernel;
|
||||
pub mod map;
|
||||
pub mod world;
|
||||
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
use crate::context::MapContext;
|
||||
use crate::coords::{LatLon, WorldCoords, Zoom, TILE_SIZE};
|
||||
use crate::environment::{Environment, Kernel};
|
||||
use crate::environment::Environment;
|
||||
use crate::error::Error;
|
||||
use crate::headless::environment::HeadlessEnvironment;
|
||||
use crate::kernel::Kernel;
|
||||
use crate::render::{create_default_render_graph, register_default_render_stages, Renderer};
|
||||
use crate::schedule::{Schedule, Stage};
|
||||
use crate::stages::register_stages;
|
||||
use crate::style::Style;
|
||||
use crate::world::World;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Map<E: Environment> {
|
||||
kernel: Kernel<E>,
|
||||
kernel: Rc<Kernel<E>>,
|
||||
schedule: Schedule,
|
||||
map_context: MapContext,
|
||||
}
|
||||
@ -31,6 +34,10 @@ impl<E: Environment> Map<E> {
|
||||
let graph = create_default_render_graph().unwrap(); // TODO: Remove unwrap
|
||||
register_default_render_stages(graph, &mut schedule);
|
||||
|
||||
let kernel = Rc::new(kernel);
|
||||
|
||||
register_stages::<E>(&mut schedule, kernel.clone());
|
||||
|
||||
Ok(Self {
|
||||
kernel,
|
||||
map_context: MapContext {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::environment::Kernel;
|
||||
use crate::error::Error;
|
||||
use crate::kernel::Kernel;
|
||||
use crate::{
|
||||
environment::Environment,
|
||||
render::{
|
||||
@ -9,17 +9,20 @@ use crate::{
|
||||
style::Style,
|
||||
window::{HeadedMapWindow, MapWindow, MapWindowConfig},
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct RenderBuilder {
|
||||
pub struct RenderBuilder<MWC: MapWindowConfig> {
|
||||
wgpu_settings: Option<WgpuSettings>,
|
||||
renderer_settings: Option<RendererSettings>,
|
||||
phatom_mwc: PhantomData<MWC>,
|
||||
}
|
||||
|
||||
impl RenderBuilder {
|
||||
impl<MWC: MapWindowConfig> RenderBuilder<MWC> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
wgpu_settings: None,
|
||||
renderer_settings: None,
|
||||
phatom_mwc: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,21 +36,22 @@ impl RenderBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> UninitializedRenderer {
|
||||
pub fn build(self) -> UninitializedRenderer<MWC> {
|
||||
UninitializedRenderer {
|
||||
window: None,
|
||||
wgpu_settings: self.wgpu_settings.unwrap_or_default(),
|
||||
renderer_settings: self.renderer_settings.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum InitializationResult {
|
||||
Initialized(Renderer),
|
||||
Uninizalized(UninitializedRenderer),
|
||||
pub enum InitializationResult<MWC: MapWindowConfig> {
|
||||
Initialized(InitializedRenderer<MWC>),
|
||||
Uninizalized(UninitializedRenderer<MWC>),
|
||||
}
|
||||
|
||||
impl InitializationResult {
|
||||
pub fn unwarp(self) -> Renderer {
|
||||
impl<MWC: MapWindowConfig> InitializationResult<MWC> {
|
||||
pub fn unwarp(self) -> InitializedRenderer<MWC> {
|
||||
match self {
|
||||
InitializationResult::Initialized(renderer) => renderer,
|
||||
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,
|
||||
renderer_settings: RendererSettings,
|
||||
}
|
||||
|
||||
impl UninitializedRenderer {
|
||||
impl<MWC: MapWindowConfig> UninitializedRenderer<MWC>
|
||||
where
|
||||
MWC::MapWindow: MapWindow + HeadedMapWindow,
|
||||
{
|
||||
/// Initializes the whole rendering pipeline for the given configuration.
|
||||
/// Returns the initialized map, ready to be run.
|
||||
async fn initialize<MWC: MapWindowConfig>(
|
||||
self,
|
||||
map_window_config: &MWC,
|
||||
) -> Result<InitializationResult, Error>
|
||||
where
|
||||
MWC::MapWindow: MapWindow + HeadedMapWindow,
|
||||
{
|
||||
async fn initialize(self, map_window_config: &MWC) -> Result<InitializationResult<MWC>, Error> {
|
||||
let window = map_window_config.create();
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
let renderer = Ok(InitializationResult::Uninizalized(self));
|
||||
{
|
||||
Ok(InitializationResult::Uninizalized(self))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let renderer = Ok(InitializationResult::Initialized(
|
||||
Renderer::initialize(
|
||||
{
|
||||
let renderer = Renderer::initialize(
|
||||
&window,
|
||||
self.wgpu_settings.clone(),
|
||||
self.renderer_settings.clone(),
|
||||
)
|
||||
.await?,
|
||||
));
|
||||
|
||||
renderer
|
||||
.await?;
|
||||
Ok(InitializationResult::Initialized(InitializedRenderer {
|
||||
window,
|
||||
renderer,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn initialize_with<E: Environment>(
|
||||
pub async fn initialize_with<E>(
|
||||
self,
|
||||
kernel: &Kernel<E>,
|
||||
) -> Result<InitializationResult, Error>
|
||||
) -> Result<InitializationResult<MWC>, Error>
|
||||
where
|
||||
<E::MapWindowConfig as MapWindowConfig>::MapWindow: MapWindow + HeadedMapWindow,
|
||||
E: Environment<MapWindowConfig = MWC>,
|
||||
{
|
||||
self.initialize(&kernel.map_window_config).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "headless")]
|
||||
impl UninitializedRenderer {
|
||||
async fn initialize_headless<MWC: MapWindowConfig>(
|
||||
self,
|
||||
map_window_config: MWC,
|
||||
) -> Result<Renderer, Error> {
|
||||
impl<MWC: MapWindowConfig> UninitializedRenderer<MWC> {
|
||||
async fn initialize_headless(self, map_window_config: &MWC) -> Result<Renderer, Error> {
|
||||
let window = map_window_config.create();
|
||||
|
||||
Ok(Renderer::initialize_headless(
|
||||
@ -114,13 +118,15 @@ impl UninitializedRenderer {
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn initialize_headless_with<E: Environment>(
|
||||
self,
|
||||
kernel: &Kernel<E>,
|
||||
) -> Result<InitializationResult, Error>
|
||||
pub async fn initialize_headless_with<E>(self, kernel: &Kernel<E>) -> Result<Renderer, Error>
|
||||
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
|
||||
|
||||
use cgmath::{prelude::*, AbsDiffEq, Matrix4, Point2, Point3, Vector2, Vector3, Vector4};
|
||||
use cgmath::{prelude::*, AbsDiffEq, Matrix4, Point2, Point3, Rad, Vector2, Vector3, Vector4};
|
||||
|
||||
use crate::util::{
|
||||
math::{bounds_from_points, Aabb2, Aabb3, Plane},
|
||||
@ -68,12 +68,12 @@ impl ModelViewProjection {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Camera {
|
||||
pub position: Point3<f64>, // The z axis never changes, the zoom is used instead
|
||||
pub yaw: cgmath::Rad<f64>,
|
||||
pub pitch: cgmath::Rad<f64>,
|
||||
position: Point3<f64>, // The z axis never changes, the zoom is used instead
|
||||
yaw: cgmath::Rad<f64>,
|
||||
pitch: cgmath::Rad<f64>,
|
||||
|
||||
pub width: f64,
|
||||
pub height: f64,
|
||||
width: f64,
|
||||
height: f64,
|
||||
}
|
||||
|
||||
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) {
|
||||
self.width = width as f64;
|
||||
self.height = height as f64;
|
||||
@ -347,6 +355,26 @@ impl Camera {
|
||||
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 {
|
||||
|
||||
@ -45,7 +45,8 @@ impl Stage for UploadStage {
|
||||
bytemuck::cast_slice(&[ShaderGlobals::new(ShaderCamera::new(
|
||||
view_proj.downcast().into(),
|
||||
view_state
|
||||
.camera_position()
|
||||
.camera()
|
||||
.position()
|
||||
.to_homogeneous()
|
||||
.cast::<f32>()
|
||||
.unwrap() // TODO: Remove unwrap
|
||||
|
||||
@ -10,6 +10,7 @@ use std::{
|
||||
use geozero::{mvt::tile, GeozeroDatasource};
|
||||
use request_stage::RequestStage;
|
||||
|
||||
use crate::kernel::Kernel;
|
||||
use crate::{
|
||||
coords::{WorldCoords, WorldTileCoords, Zoom, ZoomLevel},
|
||||
environment::Environment,
|
||||
@ -37,16 +38,9 @@ mod populate_tile_store_stage;
|
||||
mod request_stage;
|
||||
|
||||
/// Register stages required for requesting and preparing new tiles.
|
||||
pub fn register_stages<E: Environment>(
|
||||
schedule: &mut Schedule,
|
||||
http_source_client: HttpSourceClient<E::HttpClient>,
|
||||
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 fn register_stages<E: Environment>(schedule: &mut Schedule, kernel: Rc<Kernel<E>>) {
|
||||
schedule.add_stage("request", RequestStage::<E>::new(kernel.clone()));
|
||||
schedule.add_stage("populate_tile_store", PopulateTileStore::<E>::new(kernel));
|
||||
}
|
||||
|
||||
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 crate::kernel::Kernel;
|
||||
use crate::{
|
||||
context::MapContext,
|
||||
environment::Environment,
|
||||
@ -15,12 +16,12 @@ use crate::{
|
||||
};
|
||||
|
||||
pub struct PopulateTileStore<E: Environment> {
|
||||
apc: Rc<RefCell<E::AsyncProcedureCall>>,
|
||||
kernel: Rc<Kernel<E>>,
|
||||
}
|
||||
|
||||
impl<E: Environment> PopulateTileStore<E> {
|
||||
pub fn new(apc: Rc<RefCell<E::AsyncProcedureCall>>) -> Self {
|
||||
Self { apc }
|
||||
pub fn new(kernel: Rc<Kernel<E>>) -> Self {
|
||||
Self { kernel }
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,39 +35,37 @@ impl<E: Environment> Stage for PopulateTileStore<E> {
|
||||
..
|
||||
}: &mut MapContext,
|
||||
) {
|
||||
if let Ok(mut apc) = self.apc.deref().try_borrow_mut() {
|
||||
if let Some(result) = apc.receive() {
|
||||
match result {
|
||||
Message::TileTessellated(tranferred) => {
|
||||
let coords = tranferred.coords();
|
||||
tile_repository.success(coords);
|
||||
tracing::trace!("Tile at {} finished loading", coords);
|
||||
log::warn!("Tile at {} finished loading", coords);
|
||||
}
|
||||
// FIXME: deduplicate
|
||||
Message::UnavailableLayer(tranferred) => {
|
||||
let layer: StoredLayer = tranferred.to_stored_layer();
|
||||
tracing::debug!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
tile_repository.put_tessellated_layer(layer);
|
||||
}
|
||||
Message::TessellatedLayer(data) => {
|
||||
let layer: StoredLayer = data.to_stored_layer();
|
||||
tracing::debug!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
log::warn!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
tile_repository.put_tessellated_layer(layer);
|
||||
}
|
||||
if let Some(result) = self.kernel.apc.receive() {
|
||||
match result {
|
||||
Message::TileTessellated(tranferred) => {
|
||||
let coords = tranferred.coords();
|
||||
tile_repository.success(coords);
|
||||
tracing::trace!("Tile at {} finished loading", coords);
|
||||
log::warn!("Tile at {} finished loading", coords);
|
||||
}
|
||||
// FIXME: deduplicate
|
||||
Message::UnavailableLayer(tranferred) => {
|
||||
let layer: StoredLayer = tranferred.to_stored_layer();
|
||||
tracing::debug!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
tile_repository.put_tessellated_layer(layer);
|
||||
}
|
||||
Message::TessellatedLayer(data) => {
|
||||
let layer: StoredLayer = data.to_stored_layer();
|
||||
tracing::debug!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
log::warn!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
tile_repository.put_tessellated_layer(layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ use std::{
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use crate::kernel::Kernel;
|
||||
use crate::{
|
||||
context::MapContext,
|
||||
coords::{ViewRegion, WorldTileCoords, ZoomLevel},
|
||||
@ -33,19 +34,12 @@ use crate::{
|
||||
};
|
||||
|
||||
pub struct RequestStage<E: Environment> {
|
||||
apc: Rc<RefCell<E::AsyncProcedureCall>>,
|
||||
http_source_client: HttpSourceClient<E::HttpClient>,
|
||||
kernel: Rc<Kernel<E>>,
|
||||
}
|
||||
|
||||
impl<E: Environment> RequestStage<E> {
|
||||
pub fn new(
|
||||
http_source_client: HttpSourceClient<E::HttpClient>,
|
||||
apc: Rc<RefCell<E::AsyncProcedureCall>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
apc,
|
||||
http_source_client,
|
||||
}
|
||||
pub fn new(kernel: Rc<Kernel<E>>) -> Self {
|
||||
Self { kernel }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
context: C,
|
||||
) -> AsyncProcedureFuture {
|
||||
@ -106,12 +106,14 @@ pub fn schedule<E: Environment, C: Context<E::Transferables, E::HttpClient>>(
|
||||
log::error!("{:?}", &e);
|
||||
for to_load in &input.layers {
|
||||
tracing::warn!("layer {} at {} unavailable", to_load, coords);
|
||||
context.send(Message::UnavailableLayer(
|
||||
<E::Transferables as Transferables>::UnavailableLayer::new(
|
||||
context.send(
|
||||
Message::UnavailableLayer(<<E::AsyncProcedureCall as AsyncProcedureCall<
|
||||
E::HttpClient,
|
||||
>>::Transferables as Transferables>::UnavailableLayer::new(
|
||||
input.coords,
|
||||
to_load.to_string(),
|
||||
),
|
||||
));
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,7 +158,7 @@ impl<E: Environment> RequestStage<E> {
|
||||
tile_repository.create_tile(coords);
|
||||
|
||||
tracing::info!("new tile request: {}", &coords);
|
||||
self.apc.deref().borrow().schedule(
|
||||
self.kernel.apc.schedule(
|
||||
Input::TileRequest(TileRequest {
|
||||
coords,
|
||||
layers: layers.clone(),
|
||||
@ -164,7 +166,6 @@ impl<E: Environment> RequestStage<E> {
|
||||
schedule::<
|
||||
E,
|
||||
<E::AsyncProcedureCall as AsyncProcedureCall<
|
||||
E::Transferables,
|
||||
E::HttpClient,
|
||||
>>::Context,
|
||||
>,
|
||||
|
||||
@ -17,6 +17,11 @@ pub trait HeadedMapWindow: MapWindow {
|
||||
type RawWindow: HasRawWindowHandle + HasRawDisplayHandle;
|
||||
|
||||
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
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use cgmath::{Angle, Point3};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::{
|
||||
coords::{LatLon, ViewRegion, WorldCoords, Zoom, ZoomLevel, TILE_SIZE},
|
||||
@ -124,14 +125,23 @@ impl ViewState {
|
||||
*self.zoom
|
||||
}
|
||||
|
||||
pub fn camera_position(&self) -> Point3<f64> {
|
||||
self.camera.position
|
||||
}
|
||||
|
||||
pub fn did_zoom_change(&self) -> bool {
|
||||
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 {
|
||||
self.camera.did_change(0.05)
|
||||
}
|
||||
@ -140,9 +150,4 @@ impl ViewState {
|
||||
self.camera.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