mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Update winit and wgpu (#303)
* Update winit and wgpu which both target rwh 0.6 * Upgrade to winit 0.30 to fix android crash https://github.com/bevyengine/bevy/issues/13331 * Add Carbon framework to desktop builds and improve build script to use nix if available * Fix swift package and compilaiton with Nix * Cleanup nix shell * Avoid setting the size on the canvas, winit resizes now * Handle fetch errors for web
This commit is contained in:
parent
c974e22aa2
commit
de7d18103a
2
.gitignore
vendored
2
.gitignore
vendored
@ -30,3 +30,5 @@ perf.data*
|
||||
frame_*.png
|
||||
|
||||
.direnv/
|
||||
|
||||
xcode/libs/*/**
|
||||
|
||||
3
.idea/maplibre-rs.iml
generated
3
.idea/maplibre-rs.iml
generated
@ -23,8 +23,9 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/web/lib/src/wasm" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/web/lib/dist" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/maplibre-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/apple/xcode/libs" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
||||
6
.idea/runConfigurations/Run_demo__debug_.xml
generated
6
.idea/runConfigurations/Run_demo__debug_.xml
generated
@ -2,6 +2,9 @@
|
||||
<configuration default="false" name="Run demo (debug)" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
|
||||
<option name="command" value="run -p maplibre-demo -- headed" />
|
||||
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
|
||||
<envs>
|
||||
<env name="RUST_LOG" value="maplibre=info" />
|
||||
</envs>
|
||||
<option name="emulateTerminal" value="false" />
|
||||
<option name="channel" value="DEFAULT" />
|
||||
<option name="requiredFeatures" value="true" />
|
||||
@ -9,9 +12,6 @@
|
||||
<option name="withSudo" value="false" />
|
||||
<option name="buildTarget" value="REMOTE" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<envs>
|
||||
<env name="RUST_LOG" value="maplibre=trace" />
|
||||
</envs>
|
||||
<option name="isRedirectInput" value="false" />
|
||||
<option name="redirectInputPath" value="" />
|
||||
<method v="2">
|
||||
|
||||
@ -7,11 +7,9 @@ members = [
|
||||
"maplibre-winit",
|
||||
"maplibre-build-tools",
|
||||
"maplibre-demo",
|
||||
|
||||
"android",
|
||||
"apple",
|
||||
"web",
|
||||
|
||||
"benchmarks",
|
||||
]
|
||||
|
||||
@ -36,7 +34,7 @@ rand = { version = "0.7.3", features = ["wasm-bindgen"] }
|
||||
# FIXME: Untrusted dependency, 0.2.x doesn't compile with cache middleware
|
||||
reqwest-middleware = "0.1.6"
|
||||
|
||||
winit = { version = "0.28.7", default-features = false }
|
||||
winit = { version = "0.30", default-features = false, features = ["rwh_06"] }
|
||||
|
||||
#
|
||||
# These dependencies should be updated to the latest version
|
||||
@ -67,10 +65,8 @@ js-sys = "0.3"
|
||||
log = "0.4.20"
|
||||
lyon = { version = "1.0.1", features = [] }
|
||||
naga = { version = "0.13.0", features = ["wgsl-in"] }
|
||||
android-activity = "0.4.3"
|
||||
android_logger = "0.13.3"
|
||||
png = { version = "0.17.10" }
|
||||
raw-window-handle = "0.5.2"
|
||||
reqwest = { version = "0.11.20", default-features = false, features = ["rustls-tls", "gzip"] } # Use rusttls on android because cross compiling is difficult
|
||||
reqwest-middleware-cache = "0.1.1" # FIXME: Untrusted dependency
|
||||
rstar = "0.11.0"
|
||||
@ -91,7 +87,7 @@ wasm-bindgen = "=0.2.92"
|
||||
wasm-bindgen-futures = "0.4"
|
||||
wasm-bindgen-test = "0.3"
|
||||
web-sys = "0.3" # Individual features are customized in each crate
|
||||
wgpu = "0.18.0"
|
||||
wgpu = "0.19.4"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
@ -13,11 +13,10 @@ authors.workspace = true
|
||||
|
||||
[dependencies]
|
||||
maplibre = { path = "../maplibre", features = ["thread-safe-futures"] }
|
||||
maplibre-winit = { path = "../maplibre-winit", version = "0.1.0" }
|
||||
maplibre-winit = { path = "../maplibre-winit", version = "0.1.0" }
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
android_logger.workspace = true
|
||||
android-activity.workspace = true
|
||||
jni.workspace = true
|
||||
|
||||
[lib]
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
use jni::{objects::JClass, JNIEnv};
|
||||
use log::Level;
|
||||
use maplibre::render::settings::WgpuSettings;
|
||||
use maplibre_winit::{run_headed_map, WinitMapWindowConfig};
|
||||
use maplibre_winit::{android_activity, run_headed_map, WinitMapWindowConfig};
|
||||
|
||||
#[cfg(not(any(no_pendantic_os_check, target_os = "android")))]
|
||||
compile_error!("android works only on android.");
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import maplibre_rs
|
||||
import Metal
|
||||
import AppKit
|
||||
import QuartzCore
|
||||
import SystemConfiguration
|
||||
import Metal // Required by wgpu?
|
||||
import AppKit // Required by ??
|
||||
import QuartzCore // Required by ??
|
||||
import SystemConfiguration // Required by reqwest?
|
||||
import Carbon // Required by winit
|
||||
|
||||
maplibre_rs.MapLibre.start()
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
0B85D599281291A700906D21 /* maplibre_rs.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B85D56B2812903700906D21 /* maplibre_rs.framework */; };
|
||||
0B85D5A42812991100906D21 /* libmaplibre_apple.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B85D5A32812987B00906D21 /* libmaplibre_apple.a */; };
|
||||
5015FE4C2ACCB64600F8E4B6 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5015FE492ACCA78300F8E4B6 /* SystemConfiguration.framework */; };
|
||||
53BD1F062C34FB12008DAA23 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53BD1F052C34FB12008DAA23 /* Carbon.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -32,6 +33,7 @@
|
||||
0BE452D62812EEA8003BD2A5 /* example--iOS--Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "example--iOS--Info.plist"; sourceTree = "<group>"; };
|
||||
5015FE472ACCA77900F8E4B6 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.0.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; };
|
||||
5015FE492ACCA78300F8E4B6 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
53BD1F052C34FB12008DAA23 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -56,6 +58,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5015FE4C2ACCB64600F8E4B6 /* SystemConfiguration.framework in Frameworks */,
|
||||
53BD1F062C34FB12008DAA23 /* Carbon.framework in Frameworks */,
|
||||
0B85D599281291A700906D21 /* maplibre_rs.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -97,6 +100,7 @@
|
||||
0B85D573281290D400906D21 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
53BD1F052C34FB12008DAA23 /* Carbon.framework */,
|
||||
5015FE472ACCA77900F8E4B6 /* SystemConfiguration.framework */,
|
||||
5015FE492ACCA78300F8E4B6 /* SystemConfiguration.framework */,
|
||||
0B85D5A32812987B00906D21 /* libmaplibre_apple.a */,
|
||||
@ -259,6 +263,7 @@
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
0BE452D72812EFC1003BD2A5 /* Cargo Build */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
@ -273,7 +278,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/bash;
|
||||
shellScript = "arch=\"unknown\"\nvendor=\"apple\"\nos_type=\"unknown\"\nenvironment_type=\"\"\n\nmode=\"\"\n\necho \"ARCH: $ARCHS\"\n\nif [[ $CONFIGURATION == \"Release\" ]]\nthen\n mode=\"--release\"\nfi\n\nif [[ $ARCHS == \"x86_64\" ]]\nthen\n arch=\"x86_64\"\nelif [[ $ARCHS == \"arm64\" ]]\nthen\n arch=\"aarch64\"\nfi\n\nif [[ $SDK_NAME == *\"iphoneos\"* ]]\nthen\n os_type=\"ios\"\nelif [[ $SDK_NAME == *\"macos\"* ]]\nthen\n os_type=\"darwin\"\nelif [[ $SDK_NAME == *\"iphonesimulator\"* ]]\nthen\n os_type=\"ios\"\n if [[ $ARCHS == \"arm64\" ]]\n then\n environment_type=\"sim\"\n fi\nfi\n\n\ntriplet=\"$arch-$vendor-$os_type\"\n\nif [ -n \"$environment_type\" ]\nthen\n triplet=\"$triplet-$environment_type\"\nfi\n\necho \"Mode: $mode\"\necho \"Triplet: $triplet\"\necho \"Shell: $SHELL\"\n\ncmd=$(cat << END\n export HOME=$HOME\n . $HOME/.cargo/env\n \n if [ -f \"/opt/homebrew/bin/brew\" ];\n then\n echo \"Homebrew support activated\"\n eval \"\\$(/opt/homebrew/bin/brew shellenv)\"\n fi\n \n cargo build -p apple $mode --target $triplet --lib\nEND\n)\n\necho \"Command: $cmd\"\n\nenv -i /bin/bash -c \"$cmd\"\n";
|
||||
shellScript = "arch=\"unknown\"\nvendor=\"apple\"\nos_type=\"unknown\"\nenvironment_type=\"\"\n\nmode=\"\"\n\necho \"ARCH: $ARCHS\"\n\nif [[ $CONFIGURATION == \"Release\" ]]\nthen\n mode=\"--release\"\nfi\n\nif [[ $ARCHS == \"x86_64\" ]]\nthen\n arch=\"x86_64\"\nelif [[ $ARCHS == \"arm64\" ]]\nthen\n arch=\"aarch64\"\nfi\n\nif [[ $SDK_NAME == *\"iphoneos\"* ]]\nthen\n os_type=\"ios\"\nelif [[ $SDK_NAME == *\"macos\"* ]]\nthen\n os_type=\"darwin\"\nelif [[ $SDK_NAME == *\"iphonesimulator\"* ]]\nthen\n os_type=\"ios\"\n if [[ $ARCHS == \"arm64\" ]]\n then\n environment_type=\"sim\"\n fi\nfi\n\n\ntriplet=\"$arch-$vendor-$os_type\"\n\nif [ -n \"$environment_type\" ]\nthen\n triplet=\"$triplet-$environment_type\"\nfi\n\necho \"Mode: $mode\"\necho \"Triplet: $triplet\"\necho \"Shell: $SHELL\"\n\ncmd=$(cat << END\n export HOME=$HOME # Set home as this env is clean\n export PATH=\"\\$PATH:/usr/bin\" # We have a clean shell, so make /usr/bin available\n . $HOME/.cargo/env\n \n if [ -f \"/opt/homebrew/bin/brew\" ];\n then\n echo \"Homebrew support activated\"\n eval \"\\$(/opt/homebrew/bin/brew shellenv)\"\n fi\n \n cargo build -p apple $mode --target $triplet --lib\nEND\n)\n\necho \"Command: $cmd\"\n\n# Potentially improve this check for other systems\nif test -f /run/current-system/sw/bin/nix-shell; then\n env -i /run/current-system/sw/bin/nix-shell \"$PROJECT_DIR/../../shell.nix\" --run \"$cmd\"\nelse\n env -i /bin/bash -c \"$cmd\"\nfi\n";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
|
||||
@ -13,10 +13,6 @@ authors.workspace = true
|
||||
[target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "linux", target_os = "android", target_os = "windows"))'.dependencies]
|
||||
tokio.workspace = true
|
||||
|
||||
# FIXME: is this section needed? Seems to be identical to the default
|
||||
#[target.'cfg(target_os = "android")'.dependencies]
|
||||
#winit.wokrspace = true
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
winit = { workspace = true, features = ["x11", "wayland"] }
|
||||
|
||||
@ -34,3 +30,4 @@ winit.workspace = true
|
||||
cgmath.workspace = true
|
||||
instant.workspace = true
|
||||
log.workspace = true
|
||||
thiserror.workspace = true
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use maplibre::context::MapContext;
|
||||
use winit::keyboard::Key;
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -35,30 +36,27 @@ impl UpdateState for DebugHandler {
|
||||
}
|
||||
|
||||
impl DebugHandler {
|
||||
pub fn process_key_press(
|
||||
&mut self,
|
||||
key: winit::event::VirtualKeyCode,
|
||||
state: winit::event::ElementState,
|
||||
) -> bool {
|
||||
pub fn process_key_press(&mut self, key: &Key, state: winit::event::ElementState) -> bool {
|
||||
let amount = if state == winit::event::ElementState::Pressed {
|
||||
100.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
match key {
|
||||
winit::event::VirtualKeyCode::V => {
|
||||
|
||||
match key.as_ref() {
|
||||
Key::Character("v") => {
|
||||
self.left_delta += amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::B => {
|
||||
Key::Character("b") => {
|
||||
self.top_delta += amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::N => {
|
||||
Key::Character("n") => {
|
||||
self.bottom_delta += amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::M => {
|
||||
Key::Character("m") => {
|
||||
self.right_delta += amount;
|
||||
true
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ use std::time::Duration;
|
||||
|
||||
use cgmath::Vector2;
|
||||
use maplibre::context::MapContext;
|
||||
use winit::event::{DeviceEvent, KeyboardInput, TouchPhase, WindowEvent};
|
||||
use winit::event::{DeviceEvent, KeyEvent, TouchPhase, WindowEvent};
|
||||
|
||||
use crate::input::{
|
||||
camera_handler::CameraHandler, debug_handler::DebugHandler, pan_handler::PanHandler,
|
||||
@ -72,17 +72,14 @@ impl InputController {
|
||||
true
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
state,
|
||||
virtual_keycode: Some(key),
|
||||
..
|
||||
},
|
||||
event: KeyEvent {
|
||||
state, logical_key, ..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
self.shift_handler.process_key_press(*key, *state)
|
||||
|| self.debug_handler.process_key_press(*key, *state)
|
||||
|| self.zoom_handler.process_key_press(*key, *state)
|
||||
self.shift_handler.process_key_press(logical_key, *state)
|
||||
|| self.debug_handler.process_key_press(logical_key, *state)
|
||||
|| self.zoom_handler.process_key_press(logical_key, *state)
|
||||
}
|
||||
WindowEvent::Touch(touch) => match touch.phase {
|
||||
TouchPhase::Started => {
|
||||
|
||||
@ -2,6 +2,7 @@ use std::time::Duration;
|
||||
|
||||
use cgmath::{Vector2, Zero};
|
||||
use maplibre::context::MapContext;
|
||||
use winit::keyboard::{Key, NamedKey};
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -41,30 +42,26 @@ impl ShiftHandler {
|
||||
} * self.sensitivity;*/
|
||||
}
|
||||
|
||||
pub fn process_key_press(
|
||||
&mut self,
|
||||
key: winit::event::VirtualKeyCode,
|
||||
state: winit::event::ElementState,
|
||||
) -> bool {
|
||||
pub fn process_key_press(&mut self, key: &Key, state: winit::event::ElementState) -> bool {
|
||||
let amount = if state == winit::event::ElementState::Pressed {
|
||||
10.0 * self.sensitivity // left, right is the same as panning 10px
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
match key {
|
||||
winit::event::VirtualKeyCode::W | winit::event::VirtualKeyCode::Up => {
|
||||
match key.as_ref() {
|
||||
Key::Character("w") | Key::Named(NamedKey::ArrowUp) => {
|
||||
self.camera_translate.y -= amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::S | winit::event::VirtualKeyCode::Down => {
|
||||
Key::Character("s") | Key::Named(NamedKey::ArrowDown) => {
|
||||
self.camera_translate.y += amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::A | winit::event::VirtualKeyCode::Left => {
|
||||
Key::Character("a") | Key::Named(NamedKey::ArrowLeft) => {
|
||||
self.camera_translate.x -= amount;
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::D | winit::event::VirtualKeyCode::Right => {
|
||||
Key::Character("d") | Key::Named(NamedKey::ArrowRight) => {
|
||||
self.camera_translate.x += amount;
|
||||
true
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ use std::time::Duration;
|
||||
|
||||
use cgmath::Vector2;
|
||||
use maplibre::{context::MapContext, coords::Zoom};
|
||||
use winit::keyboard::Key;
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -77,23 +78,19 @@ impl ZoomHandler {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn process_key_press(
|
||||
&mut self,
|
||||
key: winit::event::VirtualKeyCode,
|
||||
state: winit::event::ElementState,
|
||||
) -> bool {
|
||||
pub fn process_key_press(&mut self, key: &Key, state: winit::event::ElementState) -> bool {
|
||||
let amount = if state == winit::event::ElementState::Pressed {
|
||||
0.1
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
|
||||
match key {
|
||||
winit::event::VirtualKeyCode::Plus | winit::event::VirtualKeyCode::I => {
|
||||
match key.as_ref() {
|
||||
Key::Character("i") | Key::Character("+") => {
|
||||
self.update_zoom(amount);
|
||||
true
|
||||
}
|
||||
winit::event::VirtualKeyCode::Minus | winit::event::VirtualKeyCode::K => {
|
||||
Key::Character("k") | Key::Character("-") => {
|
||||
self.update_zoom(-amount);
|
||||
true
|
||||
}
|
||||
|
||||
@ -11,14 +11,17 @@ use maplibre::{
|
||||
window::{HeadedMapWindow, MapWindowConfig, PhysicalSize},
|
||||
};
|
||||
use winit::{
|
||||
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
event::{ElementState, Event, KeyEvent, WindowEvent},
|
||||
keyboard::{Key, NamedKey},
|
||||
};
|
||||
|
||||
use crate::input::{InputController, UpdateState};
|
||||
|
||||
pub mod input;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub use winit::platform::android::activity as android_activity;
|
||||
|
||||
pub type RawWinitWindow = winit::window::Window;
|
||||
pub type RawWinitEventLoop<ET> = winit::event_loop::EventLoop<ET>;
|
||||
pub type RawEventLoopProxy<ET> = winit::event_loop::EventLoopProxy<ET>;
|
||||
@ -46,9 +49,9 @@ impl<ET> WinitMapWindow<ET> {
|
||||
}
|
||||
|
||||
impl<ET> HeadedMapWindow for WinitMapWindow<ET> {
|
||||
type RawWindow = RawWinitWindow;
|
||||
type WindowHandle = RawWinitWindow;
|
||||
|
||||
fn raw(&self) -> &Self::RawWindow {
|
||||
fn handle(&self) -> &Self::WindowHandle {
|
||||
&self.window
|
||||
}
|
||||
|
||||
@ -84,7 +87,7 @@ impl<ET: 'static + PartialEq + Debug> EventLoop<ET> for WinitEventLoop<ET> {
|
||||
let mut scale_factor = map.window().scale_factor();
|
||||
|
||||
self.event_loop
|
||||
.run(move |event, _window_target, control_flow| {
|
||||
.run(move |event, window_target| {
|
||||
#[cfg(target_os = "android")]
|
||||
if !map.is_initialized() && event == Event::Resumed {
|
||||
use tokio::{runtime::Handle, task};
|
||||
@ -109,61 +112,67 @@ impl<ET: 'static + PartialEq + Debug> EventLoop<ET> for WinitEventLoop<ET> {
|
||||
ref event,
|
||||
window_id,
|
||||
} if window_id == map.window().id().into() => {
|
||||
match event {
|
||||
WindowEvent::RedrawRequested => {
|
||||
if !map.is_initialized() {
|
||||
return;
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
let dt = now - last_render_time;
|
||||
last_render_time = now;
|
||||
|
||||
if let Ok(map_context) = map.context_mut() {
|
||||
input_controller.update_state(map_context, dt);
|
||||
}
|
||||
|
||||
// TODO: Handle gracefully
|
||||
map.run_schedule().expect("Failed to run schedule!");
|
||||
|
||||
if let Some(max_frames) = max_frames {
|
||||
if current_frame >= max_frames {
|
||||
log::info!("Exiting because maximum frames reached.");
|
||||
window_target.exit()
|
||||
}
|
||||
|
||||
current_frame += 1;
|
||||
}
|
||||
|
||||
map.window().request_redraw();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if !input_controller.window_input(event, scale_factor) {
|
||||
match event {
|
||||
WindowEvent::CloseRequested
|
||||
| WindowEvent::KeyboardInput {
|
||||
input:
|
||||
KeyboardInput {
|
||||
event: KeyEvent {
|
||||
state: ElementState::Pressed,
|
||||
virtual_keycode: Some(VirtualKeyCode::Escape),
|
||||
logical_key: Key::Named(NamedKey::Exit),
|
||||
..
|
||||
},
|
||||
..
|
||||
} => *control_flow = ControlFlow::Exit,
|
||||
} => window_target.exit(),
|
||||
WindowEvent::Resized(winit::dpi::PhysicalSize { width, height}) => {
|
||||
if let Ok(map_context) = map.context_mut() {
|
||||
let size = PhysicalSize::new(*width, *height).expect("window values should not be zero");
|
||||
map_context.resize(size, scale_factor);
|
||||
map.window().request_redraw();
|
||||
}
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { new_inner_size: winit::dpi::PhysicalSize { width, height}, scale_factor: new_scale_factor } => {
|
||||
WindowEvent::ScaleFactorChanged { inner_size_writer, scale_factor: new_scale_factor } => {
|
||||
if let Ok(map_context) = map.context_mut() {
|
||||
log::info!("New scaling factor: {}", new_scale_factor);
|
||||
scale_factor = *new_scale_factor;
|
||||
let size = PhysicalSize::new(*width, *height).expect("window values should not be zero");
|
||||
map_context.resize(size, scale_factor);
|
||||
map_context.resize(map_context.renderer.resources.surface.size(), scale_factor);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
if !map.is_initialized() {
|
||||
return;
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
let dt = now - last_render_time;
|
||||
last_render_time = now;
|
||||
|
||||
if let Ok(map_context) = map.context_mut() {
|
||||
input_controller.update_state(map_context, dt);
|
||||
}
|
||||
|
||||
// TODO: Handle gracefully
|
||||
map.run_schedule().expect("Failed to run schedule!");
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Event::Suspended => {
|
||||
log::info!("Suspending and dropping render state.");
|
||||
map.reset() // TODO: Instead of resetting the whole map (incl. the renderer) only reset the renderer
|
||||
@ -171,11 +180,6 @@ impl<ET: 'static + PartialEq + Debug> EventLoop<ET> for WinitEventLoop<ET> {
|
||||
Event::Resumed => {
|
||||
// FIXME unimplemented!()
|
||||
}
|
||||
Event::MainEventsCleared => {
|
||||
// RedrawRequested will only trigger once, unless we manually
|
||||
// request it.
|
||||
map.window().request_redraw();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
||||
@ -16,9 +16,9 @@ use maplibre::{
|
||||
},
|
||||
render::{builder::RendererBuilder, settings::WgpuSettings, RenderPlugin},
|
||||
style::Style,
|
||||
window::{MapWindow, MapWindowConfig, PhysicalSize},
|
||||
window::{MapWindow, MapWindowConfig, PhysicalSize, WindowCreateError},
|
||||
};
|
||||
use winit::window::WindowBuilder;
|
||||
use winit::window::WindowAttributes;
|
||||
|
||||
use super::WinitMapWindow;
|
||||
use crate::{WinitEnvironment, WinitEventLoop};
|
||||
@ -27,7 +27,7 @@ use crate::{WinitEnvironment, WinitEventLoop};
|
||||
pub struct WinitMapWindowConfig<ET> {
|
||||
title: String,
|
||||
#[cfg(target_os = "android")]
|
||||
android_app: winit::platform::android::activity::AndroidApp,
|
||||
android_app: crate::android_activity::AndroidApp,
|
||||
|
||||
phantom_et: PhantomData<ET>,
|
||||
}
|
||||
@ -72,9 +72,8 @@ impl<ET> MapWindow for WinitMapWindow<ET> {
|
||||
impl<ET: 'static + Clone> MapWindowConfig for WinitMapWindowConfig<ET> {
|
||||
type MapWindow = WinitMapWindow<ET>;
|
||||
|
||||
fn create(&self) -> Self::MapWindow {
|
||||
let mut raw_event_loop_builder =
|
||||
winit::event_loop::EventLoopBuilder::<ET>::with_user_event();
|
||||
fn create(&self) -> Result<Self::MapWindow, WindowCreateError> {
|
||||
let mut raw_event_loop_builder = winit::event_loop::EventLoop::<ET>::with_user_event();
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
use winit::platform::android::EventLoopBuilderExtAndroid;
|
||||
@ -82,19 +81,20 @@ impl<ET: 'static + Clone> MapWindowConfig for WinitMapWindowConfig<ET> {
|
||||
let mut raw_event_loop_builder =
|
||||
raw_event_loop_builder.with_android_app(self.android_app.clone());
|
||||
|
||||
let raw_event_loop = raw_event_loop_builder.build();
|
||||
let raw_event_loop = raw_event_loop_builder
|
||||
.build()
|
||||
.map_err(|_| WindowCreateError::EventLoop)?;
|
||||
|
||||
let window = WindowBuilder::new()
|
||||
.with_title(&self.title)
|
||||
.build(&raw_event_loop)
|
||||
.unwrap();
|
||||
let window = raw_event_loop
|
||||
.create_window(WindowAttributes::new().with_title(&self.title))
|
||||
.map_err(|_| WindowCreateError::Window)?;
|
||||
|
||||
Self::MapWindow {
|
||||
Ok(Self::MapWindow {
|
||||
window,
|
||||
event_loop: Some(WinitEventLoop {
|
||||
event_loop: raw_event_loop,
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use maplibre::window::{MapWindow, MapWindowConfig, PhysicalSize};
|
||||
use winit::{platform::web::WindowBuilderExtWebSys, window::WindowBuilder};
|
||||
use maplibre::window::{MapWindow, MapWindowConfig, PhysicalSize, WindowCreateError};
|
||||
use winit::{platform::web::WindowAttributesExtWebSys, window::WindowAttributes};
|
||||
|
||||
use super::WinitMapWindow;
|
||||
use crate::WinitEventLoop;
|
||||
@ -24,22 +24,23 @@ impl<ET: 'static> WinitMapWindowConfig<ET> {
|
||||
impl<ET: 'static + Clone> MapWindowConfig for WinitMapWindowConfig<ET> {
|
||||
type MapWindow = WinitMapWindow<ET>;
|
||||
|
||||
fn create(&self) -> Self::MapWindow {
|
||||
let raw_event_loop = winit::event_loop::EventLoopBuilder::<ET>::with_user_event().build();
|
||||
fn create(&self) -> Result<Self::MapWindow, WindowCreateError> {
|
||||
let raw_event_loop = winit::event_loop::EventLoop::<ET>::with_user_event()
|
||||
.build()
|
||||
.map_err(|_| WindowCreateError::EventLoop)?;
|
||||
|
||||
let window: winit::window::Window = WindowBuilder::new()
|
||||
.with_canvas(Some(get_canvas(&self.canvas_id)))
|
||||
.build(&raw_event_loop)
|
||||
.unwrap();
|
||||
let window: winit::window::Window = raw_event_loop
|
||||
.create_window(
|
||||
WindowAttributes::default().with_canvas(Some(get_canvas(&self.canvas_id))),
|
||||
)
|
||||
.map_err(|_| WindowCreateError::Window)?;
|
||||
|
||||
let size = get_body_size().unwrap();
|
||||
window.set_inner_size(size);
|
||||
Self::MapWindow {
|
||||
Ok(Self::MapWindow {
|
||||
window,
|
||||
event_loop: Some(WinitEventLoop {
|
||||
event_loop: raw_event_loop,
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,20 +48,10 @@ impl<ET: 'static> MapWindow for WinitMapWindow<ET> {
|
||||
fn size(&self) -> PhysicalSize {
|
||||
let size = self.window.inner_size();
|
||||
|
||||
PhysicalSize::new(size.width, size.height).expect("failed to get window dimensions.")
|
||||
PhysicalSize::new(size.width, size.height).unwrap_or(PhysicalSize::new(1, 1).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_body_size() -> Option<winit::dpi::LogicalSize<i32>> {
|
||||
let web_window: web_sys::Window = web_sys::window().unwrap();
|
||||
let document = web_window.document().unwrap();
|
||||
let body = document.body().unwrap();
|
||||
Some(winit::dpi::LogicalSize {
|
||||
width: body.client_width(),
|
||||
height: body.client_height(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_canvas(element_id: &str) -> web_sys::HtmlCanvasElement {
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
|
||||
@ -58,7 +58,6 @@ tile-grid.workspace = true
|
||||
wgpu.workspace = true
|
||||
#wgpu = { git = "https://github.com/gfx-rs/wgpu.git", rev = "" }
|
||||
lyon.workspace = true
|
||||
raw-window-handle.workspace = true
|
||||
|
||||
# cached = "0.32"
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ pub async fn create_headless_renderer(
|
||||
.build();
|
||||
|
||||
let mwc: &HeadlessMapWindowConfig = kernel.map_window_config();
|
||||
let window: HeadlessMapWindow = mwc.create();
|
||||
let window: HeadlessMapWindow = mwc.create().expect("failed to create headless window");
|
||||
|
||||
let renderer = RendererBuilder::new()
|
||||
.build()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use crate::window::{MapWindow, MapWindowConfig, PhysicalSize};
|
||||
use crate::window::{MapWindow, MapWindowConfig, PhysicalSize, WindowCreateError};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct HeadlessMapWindowConfig {
|
||||
@ -14,8 +14,8 @@ impl HeadlessMapWindowConfig {
|
||||
impl MapWindowConfig for HeadlessMapWindowConfig {
|
||||
type MapWindow = HeadlessMapWindow;
|
||||
|
||||
fn create(&self) -> Self::MapWindow {
|
||||
Self::MapWindow { size: self.size }
|
||||
fn create(&self) -> Result<Self::MapWindow, WindowCreateError> {
|
||||
Ok(Self::MapWindow { size: self.size })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ use crate::{
|
||||
schedule::{Schedule, Stage},
|
||||
style::Style,
|
||||
tcs::world::World,
|
||||
window::{HeadedMapWindow, MapWindow, MapWindowConfig},
|
||||
window::{HeadedMapWindow, MapWindow, MapWindowConfig, WindowCreateError},
|
||||
};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@ -33,6 +33,8 @@ pub enum MapError {
|
||||
RenderGraphInit(RenderGraphError),
|
||||
#[error("initializing device failed")]
|
||||
DeviceInit(RenderError),
|
||||
#[error("creating window failed")]
|
||||
Window(#[from] WindowCreateError),
|
||||
}
|
||||
|
||||
pub enum CurrentMapContext {
|
||||
@ -58,13 +60,13 @@ where
|
||||
{
|
||||
pub fn new(
|
||||
style: Style,
|
||||
mut kernel: Kernel<E>,
|
||||
kernel: Kernel<E>,
|
||||
renderer_builder: RendererBuilder,
|
||||
plugins: Vec<Box<dyn Plugin<E>>>,
|
||||
) -> Result<Self, MapError> {
|
||||
let schedule = Schedule::default();
|
||||
|
||||
let window = kernel.map_window_config().create();
|
||||
let window = kernel.map_window_config().create()?;
|
||||
|
||||
let kernel = Rc::new(kernel);
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ use crate::render::graph::RenderGraphError;
|
||||
pub enum RenderError {
|
||||
#[error("error in surface")]
|
||||
Surface(#[from] wgpu::SurfaceError),
|
||||
#[error("error while getting window handle")]
|
||||
Handle(#[from] wgpu::rwh::HandleError),
|
||||
#[error("error during surface creation")]
|
||||
CreateSurfaceError(#[from] wgpu::CreateSurfaceError),
|
||||
#[error("error in render graph")]
|
||||
|
||||
@ -175,7 +175,10 @@ impl Renderer {
|
||||
gles_minor_version: Default::default(),
|
||||
});
|
||||
|
||||
let surface: wgpu::Surface = unsafe { instance.create_surface(window.raw())? };
|
||||
let surface: wgpu::Surface = unsafe {
|
||||
instance
|
||||
.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(&window.handle())?)?
|
||||
};
|
||||
|
||||
let (adapter, device, queue) = Self::request_device(
|
||||
&instance,
|
||||
@ -255,7 +258,7 @@ impl Renderer {
|
||||
async fn request_device(
|
||||
instance: &wgpu::Instance,
|
||||
settings: &WgpuSettings,
|
||||
request_adapter_options: &wgpu::RequestAdapterOptions<'_>,
|
||||
request_adapter_options: &wgpu::RequestAdapterOptions<'_, '_>,
|
||||
) -> Result<(wgpu::Adapter, wgpu::Device, wgpu::Queue), RenderError> {
|
||||
let adapter = instance
|
||||
.request_adapter(request_adapter_options)
|
||||
@ -400,8 +403,8 @@ impl Renderer {
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: settings.device_label.as_ref().map(|a| a.as_ref()),
|
||||
features,
|
||||
limits,
|
||||
required_features: features,
|
||||
required_limits: limits,
|
||||
},
|
||||
trace_path,
|
||||
)
|
||||
@ -431,7 +434,7 @@ impl Renderer {
|
||||
mod tests {
|
||||
use crate::{
|
||||
tcs::world::World,
|
||||
window::{MapWindow, MapWindowConfig, PhysicalSize},
|
||||
window::{MapWindow, MapWindowConfig, PhysicalSize, WindowCreateError},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -442,8 +445,8 @@ mod tests {
|
||||
impl MapWindowConfig for HeadlessMapWindowConfig {
|
||||
type MapWindow = HeadlessMapWindow;
|
||||
|
||||
fn create(&self) -> Self::MapWindow {
|
||||
Self::MapWindow { size: self.size }
|
||||
fn create(&self) -> Result<Self::MapWindow, WindowCreateError> {
|
||||
Ok(Self::MapWindow { size: self.size })
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,8 +490,8 @@ mod tests {
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
features: wgpu::Features::default(),
|
||||
limits: wgpu::Limits::default(),
|
||||
required_features: wgpu::Features::default(),
|
||||
required_limits: wgpu::Limits::default(),
|
||||
},
|
||||
None,
|
||||
)
|
||||
|
||||
@ -40,7 +40,7 @@ impl BufferDimensions {
|
||||
}
|
||||
|
||||
pub struct WindowHead {
|
||||
surface: wgpu::Surface,
|
||||
surface: wgpu::Surface<'static>,
|
||||
size: PhysicalSize,
|
||||
|
||||
texture_format: wgpu::TextureFormat,
|
||||
@ -63,6 +63,7 @@ impl WindowHead {
|
||||
height: self.size.height(),
|
||||
present_mode: self.present_mode,
|
||||
view_formats: vec![self.texture_format],
|
||||
desired_maximum_frame_latency: 2,
|
||||
};
|
||||
|
||||
self.surface.configure(device, &surface_config);
|
||||
@ -76,7 +77,10 @@ impl WindowHead {
|
||||
where
|
||||
MW: MapWindow + HeadedMapWindow,
|
||||
{
|
||||
self.surface = unsafe { instance.create_surface(window.raw())? };
|
||||
self.surface = unsafe {
|
||||
instance
|
||||
.create_surface_unsafe(wgpu::SurfaceTargetUnsafe::from_window(&window.handle())?)?
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -170,7 +174,7 @@ pub struct Surface {
|
||||
|
||||
impl Surface {
|
||||
pub fn from_surface<MW>(
|
||||
surface: wgpu::Surface,
|
||||
surface: wgpu::Surface<'static>,
|
||||
adapter: &wgpu::Adapter,
|
||||
window: &MW,
|
||||
settings: &RendererSettings,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::{collections::HashSet, marker::PhantomData};
|
||||
use std::{borrow::Cow, collections::HashSet, marker::PhantomData};
|
||||
|
||||
use geozero::{
|
||||
mvt::{tile, Message},
|
||||
@ -24,9 +24,9 @@ pub enum ProcessVectorError {
|
||||
/// Sending of results failed
|
||||
#[error("sending data back through context failed")]
|
||||
SendError(SendError),
|
||||
/// Error during processing of the pipeline
|
||||
#[error("processing data in pipeline failed")]
|
||||
Processing(Box<dyn std::error::Error>),
|
||||
/// Error when decoding e.g. the protobuf file
|
||||
#[error("decoding failed")]
|
||||
Decoding(Cow<'static, str>),
|
||||
}
|
||||
|
||||
/// A request for a tile at the given coordinates and in the given layers.
|
||||
@ -42,7 +42,8 @@ pub fn process_vector_tile<T: VectorTransferables, C: Context>(
|
||||
) -> Result<(), ProcessVectorError> {
|
||||
// Decode
|
||||
|
||||
let mut tile = geozero::mvt::Tile::decode(data).expect("failed to load tile");
|
||||
let mut tile = geozero::mvt::Tile::decode(data)
|
||||
.map_err(|e| ProcessVectorError::Decoding(e.to_string().into()))?;
|
||||
|
||||
// Available
|
||||
|
||||
@ -125,7 +126,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
fn tile_finished(&mut self, coords: &WorldTileCoords) -> Result<(), ProcessVectorError> {
|
||||
self.context
|
||||
.send(T::TileTessellated::build_from(*coords))
|
||||
.map_err(|e| ProcessVectorError::Processing(Box::new(e)))
|
||||
.map_err(|e| ProcessVectorError::SendError(e))
|
||||
}
|
||||
|
||||
fn layer_missing(
|
||||
@ -135,7 +136,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
) -> Result<(), ProcessVectorError> {
|
||||
self.context
|
||||
.send(T::LayerMissing::build_from(*coords, layer_name.to_owned()))
|
||||
.map_err(|e| ProcessVectorError::Processing(Box::new(e)))
|
||||
.map_err(|e| ProcessVectorError::SendError(e))
|
||||
}
|
||||
|
||||
fn layer_tesselation_finished(
|
||||
@ -152,7 +153,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
feature_indices,
|
||||
layer_data,
|
||||
))
|
||||
.map_err(|e| ProcessVectorError::Processing(Box::new(e)))
|
||||
.map_err(|e| ProcessVectorError::SendError(e))
|
||||
}
|
||||
|
||||
fn layer_indexing_finished(
|
||||
@ -165,7 +166,7 @@ impl<T: VectorTransferables, C: Context> ProcessVectorContext<T, C> {
|
||||
*coords,
|
||||
TileIndex::Linear { list: geometries },
|
||||
))
|
||||
.map_err(|e| ProcessVectorError::Processing(Box::new(e)))
|
||||
.map_err(|e| ProcessVectorError::SendError(e))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
use thiserror::Error;
|
||||
use wgpu::rwh::{HasDisplayHandle, HasWindowHandle};
|
||||
|
||||
/// Window of a certain [`PhysicalSize`]. This can either be a proper window or a headless one.
|
||||
pub trait MapWindow {
|
||||
@ -12,9 +13,9 @@ pub trait MapWindow {
|
||||
/// Window which references a physical `RawWindow`. This is only implemented by headed windows and
|
||||
/// not by headless windows.
|
||||
pub trait HeadedMapWindow: MapWindow {
|
||||
type RawWindow: HasRawWindowHandle + HasRawDisplayHandle;
|
||||
type WindowHandle: HasWindowHandle + HasDisplayHandle + Sync;
|
||||
|
||||
fn raw(&self) -> &Self::RawWindow;
|
||||
fn handle(&self) -> &Self::WindowHandle;
|
||||
|
||||
// TODO: Can we avoid this?
|
||||
fn request_redraw(&self);
|
||||
@ -24,12 +25,20 @@ pub trait HeadedMapWindow: MapWindow {
|
||||
fn id(&self) -> u64;
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum WindowCreateError {
|
||||
#[error("unable to create event loop")]
|
||||
EventLoop,
|
||||
#[error("unable to create window")]
|
||||
Window,
|
||||
}
|
||||
|
||||
/// A configuration for a window which determines the corresponding implementation of a
|
||||
/// [`MapWindow`] and is able to create it.
|
||||
pub trait MapWindowConfig: 'static + Clone {
|
||||
type MapWindow: MapWindow;
|
||||
|
||||
fn create(&self) -> Self::MapWindow;
|
||||
fn create(&self) -> Result<Self::MapWindow, WindowCreateError>;
|
||||
}
|
||||
|
||||
/// Window size with a width and an height in pixels.
|
||||
|
||||
19
shell.nix
19
shell.nix
@ -11,20 +11,27 @@ let
|
||||
})
|
||||
{ };
|
||||
in
|
||||
pkgs.mkShell {
|
||||
(pkgs.mkShell.override {
|
||||
# Wew are using the host clang on macOS; the Nix clang adds a clag that breaks cross compilation here:
|
||||
# https://github.com/NixOS/nixpkgs/blob/362cb82b75394680990cbe89f40fe65d35f66617/pkgs/build-support/cc-wrapper/default.nix#L490
|
||||
# It caused this error during the compilation of ring: clang-15: error: invalid argument '-mmacos-version-min=11.0' not allowed with '-miphoneos-version-min=7.0'
|
||||
stdenv = stdenvNoCC;
|
||||
}) {
|
||||
nativeBuildInputs = [
|
||||
# Tools
|
||||
unstable.rustup
|
||||
unstable.just
|
||||
unstable.nodejs
|
||||
unstable.mdbook
|
||||
unstable.wasm-bindgen-cli
|
||||
# unstable.wasm-bindgen-cli # we need wasm-bindgen-cli@0.2.92, so pull it from cargo instead
|
||||
unstable.tracy
|
||||
unstable.nixpkgs-fmt # To format this file: nixpkgs-fmt *.nix
|
||||
# System dependencies
|
||||
unstable.flatbuffers
|
||||
unstable.protobuf
|
||||
|
||||
pkgs.jdk17
|
||||
|
||||
unstable.xorg.libXrandr
|
||||
unstable.xorg.libXi
|
||||
unstable.xorg.libXcursor
|
||||
@ -33,18 +40,12 @@ pkgs.mkShell {
|
||||
unstable.sqlite
|
||||
unstable.wayland
|
||||
unstable.pkg-config
|
||||
]
|
||||
++ lib.optionals stdenv.isDarwin [
|
||||
unstable.libiconv
|
||||
pkgs.darwin.apple_sdk.frameworks.ApplicationServices
|
||||
pkgs.darwin.apple_sdk.frameworks.CoreVideo
|
||||
pkgs.darwin.apple_sdk.frameworks.AppKit
|
||||
];
|
||||
shellHook = ''
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${ pkgs.lib.makeLibraryPath [ unstable.libxkbcommon ] }";
|
||||
# Vulkan
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${ pkgs.lib.makeLibraryPath [ pkgs.vulkan-loader ] }";
|
||||
# EGL
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${ pkgs.lib.makeLibraryPath [ pkgs.libglvnd ] }";
|
||||
'';
|
||||
|
||||
}
|
||||
|
||||
@ -4,6 +4,6 @@
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0; width:100%; height: 100%; max-height: 100%;">
|
||||
<canvas id="maplibre" style="position:absolute;"></canvas>
|
||||
<canvas id="maplibre" style="position:absolute; width:100%; height: 100%;"></canvas>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -20,6 +20,8 @@ pub enum WebError {
|
||||
/// TypeError like it is defined in JS
|
||||
#[error("TypeError from JS")]
|
||||
TypeError(Cow<'static, str>),
|
||||
#[error("fetching data failed")]
|
||||
FetchError(Cow<'static, str>),
|
||||
/// Any other Error
|
||||
#[error("Error from JS")]
|
||||
GenericError(Cow<'static, str>),
|
||||
|
||||
@ -29,6 +29,12 @@ impl WHATWGFetchHttpClient {
|
||||
.dyn_into()
|
||||
.map_err(|_e| WebError::TypeError("Unable to cast to Response".into()))?;
|
||||
|
||||
if !response.ok() {
|
||||
return Err(WebError::GenericError(
|
||||
format!("failed to fetch {}", response.status()).into(),
|
||||
));
|
||||
}
|
||||
|
||||
// Get ArrayBuffer
|
||||
let maybe_array_buffer = JsFuture::from(response.array_buffer()?).await?;
|
||||
Ok(maybe_array_buffer)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user