diff --git a/.vscode/settings.json b/.vscode/settings.json index 294e528..4398da6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "cSpell.words": ["centered", "priv", "Renderling"] + "cSpell.words": ["centered", "codepoint", "priv", "Renderling"] } diff --git a/lib/scenic_driver_rendering/window/window.ex b/lib/scenic_driver_rendering/window/window.ex index 48512cf..d1708cc 100644 --- a/lib/scenic_driver_rendering/window/window.ex +++ b/lib/scenic_driver_rendering/window/window.ex @@ -3,7 +3,7 @@ defmodule Scenic.Driver.Renderling.Window do The Scenic for windowed applications. """ - alias Scenic.ViewPort + alias Scenic.{ViewPort, ViewPort.Input} alias Scenic.Driver.Renderling.Window.{Config, Nif} use Scenic.Driver @@ -136,6 +136,51 @@ defmodule Scenic.Driver.Renderling.Window do end end + def handle_info({:codepoint, codepoint, mods}, driver) do + Input.send(driver.viewport, {:codepoint, {<>, mods}}) + {:noreply, driver} + end + + def handle_info({:key, key, :pressed, mods}, driver) do + Input.send(driver.viewport, {:key, {key, 1, mods}}) + {:noreply, driver} + end + + def handle_info({:key, key, :released, mods}, driver) do + Input.send(driver.viewport, {:key, {key, 0, mods}}) + {:noreply, driver} + end + + def handle_info({:cursor_button, btn, :pressed, mods, pos}, driver) do + Input.send(driver.viewport, {:cursor_button, {btn, 1, mods, pos}}) + {:noreply, driver} + end + + def handle_info({:cursor_button, btn, :released, mods, pos}, driver) do + Input.send(driver.viewport, {:cursor_button, {btn, 0, mods, pos}}) + {:noreply, driver} + end + + def handle_info({:cursor_scroll, offset, pos}, driver) do + Input.send(driver.viewport, {:cursor_scroll, offset, pos}) + {:noreply, driver} + end + + def handle_info({:cursor_pos, pos}, driver) do + Input.send(driver.viewport, {:cursor_pos, pos}) + {:noreply, driver} + end + + def handle_info({:viewport, event, pos}, driver) when event in [:enter, :exit, :reshape] do + Input.send(driver.viewport, {:viewport, {event, pos}}) + {:noreply, driver} + end + + def handle_info({:relative, pos}, driver) do + Input.send(driver.viewport, {:relative, pos}) + {:noreply, driver} + end + def handle_info(msg, driver) do Logger.debug(fn -> "Unhandled message #{inspect(msg)}" diff --git a/native/scenic_renderer/Cargo.lock b/native/scenic_renderer/Cargo.lock index a365c80..8b2c8ea 100644 --- a/native/scenic_renderer/Cargo.lock +++ b/native/scenic_renderer/Cargo.lock @@ -531,9 +531,9 @@ checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "equivalent" @@ -682,9 +682,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", @@ -1041,9 +1041,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -1084,9 +1084,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" diff --git a/native/scenic_renderer/src/lib.rs b/native/scenic_renderer/src/lib.rs index af9f190..11ff9ac 100644 --- a/native/scenic_renderer/src/lib.rs +++ b/native/scenic_renderer/src/lib.rs @@ -1,6 +1,6 @@ pub mod script; -use script::{Color, Script}; +use script::{Color, Script, ScriptItem}; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, f32::consts::PI}; @@ -24,12 +24,18 @@ pub enum Orientation { pub struct Renderer { pub stage: Stage, pub ctx: Context, - camera: Hybrid, + _camera: Hybrid, scripts: HashMap, + config: Config, +} + +pub struct Config { + pub show_cursor: bool, + pub orientation: Orientation, } impl Renderer { - pub fn new(ctx: Context) -> Self { + pub fn new(ctx: Context, config: Config) -> Self { let mut stage = ctx .new_stage() .with_lighting(false) @@ -38,30 +44,22 @@ impl Renderer { let size = ctx.get_size(); let camera = stage.new_value(Camera::default_ortho2d(size.x as f32, size.y as f32)); + + match config.orientation { + Orientation::Normal => camera.modify(|c| c.set_view(Mat4::from_rotation_z(0.0))), + Orientation::Left => camera.modify(|c| c.set_view(Mat4::from_rotation_z(PI / -2.0))), + Orientation::Right => camera.modify(|c| c.set_view(Mat4::from_rotation_z(PI / 2.0))), + Orientation::UpsideDown => camera.modify(|c| c.set_view(Mat4::from_rotation_z(PI))), + } + let scripts = HashMap::default(); Self { stage, - camera, + _camera: camera, ctx, scripts, - } - } - - pub fn set_orientation(&mut self, orientation: Orientation) { - match orientation { - Orientation::Normal => self - .camera - .modify(|c| c.set_view(Mat4::from_rotation_z(0.0))), - Orientation::Left => self - .camera - .modify(|c| c.set_view(Mat4::from_rotation_z(PI / -2.0))), - Orientation::Right => self - .camera - .modify(|c| c.set_view(Mat4::from_rotation_z(PI / 2.0))), - Orientation::UpsideDown => self - .camera - .modify(|c| c.set_view(Mat4::from_rotation_z(PI))), + config, } } @@ -81,19 +79,41 @@ impl Renderer { pub fn clear_color(&mut self, color: Color) { self.stage.set_background_color(color); + self.do_update_scene(); } pub fn reset_scene(&mut self) { self.scripts.clear(); + self.do_update_scene(); } pub fn update_scene(&mut self, script_id: String, script: Script) { self.scripts.insert(script_id, script); + self.do_update_scene(); } pub fn delete_scripts(&mut self, script_ids: Vec) { for script_id in script_ids { self.scripts.remove(&script_id); } + self.do_update_scene(); + } + + fn do_update_scene(&mut self) { + self.render_script("_root_"); + if self.config.show_cursor { + self.render_script("_cursor_"); + } + } + + fn render_script(&mut self, script_id: &str) { + if let Some(script) = self.scripts.get(script_id) { + for script_item in script { + match script_item { + ScriptItem::PushState => (), + _ => println!("unhandled script item: {:?}", script_item), + } + } + } } } diff --git a/native/scenic_renderer/src/script.rs b/native/scenic_renderer/src/script.rs index e187f98..6d928bf 100644 --- a/native/scenic_renderer/src/script.rs +++ b/native/scenic_renderer/src/script.rs @@ -325,3 +325,12 @@ impl From> for Script { Script(vec) } } + +impl<'a> IntoIterator for &'a Script { + type Item = &'a ScriptItem; + type IntoIter = std::slice::Iter<'a, ScriptItem>; + + fn into_iter(self) -> Self::IntoIter { + self.0.as_slice().into_iter() + } +} diff --git a/native/scenic_window/src/elixir_types.rs b/native/scenic_window/src/elixir_types.rs index 436a362..93e7ac0 100644 --- a/native/scenic_window/src/elixir_types.rs +++ b/native/scenic_window/src/elixir_types.rs @@ -716,18 +716,18 @@ impl From for ModifierKey { } #[derive(NifUnitEnum, Debug, Clone)] -pub enum ViewPortEvent { +pub enum ViewportEvent { Enter, Exit, Reshape, } -impl From for ViewPortEvent { - fn from(event: message::ViewPortEvent) -> Self { +impl From for ViewportEvent { + fn from(event: message::ViewportEvent) -> Self { match event { - message::ViewPortEvent::Enter => ViewPortEvent::Enter, - message::ViewPortEvent::Exit => ViewPortEvent::Exit, - message::ViewPortEvent::Reshape => ViewPortEvent::Reshape, + message::ViewportEvent::Enter => ViewportEvent::Enter, + message::ViewportEvent::Exit => ViewportEvent::Exit, + message::ViewportEvent::Reshape => ViewportEvent::Reshape, } } } @@ -1064,12 +1064,12 @@ impl From for MouseButton { #[derive(NifTaggedEnum, Debug, Clone)] pub enum InputEvent { - CodePoint(u32, Vec), + Codepoint(u32, Vec), Key(Key, ElementState, Vec), CursorButton(MouseButton, ElementState, Vec, Point), CursorScroll(Point, Point), CursorPos(Point), - ViewPort(ViewPortEvent, Point), + Viewport(ViewportEvent, Point), Relative(Point), Led(String, u32), Switch(String, u32), @@ -1078,10 +1078,10 @@ pub enum InputEvent { impl From for InputEvent { fn from(event: message::InputEvent) -> Self { match event { - message::InputEvent::CodePoint { + message::InputEvent::Codepoint { codepoint, modifiers, - } => InputEvent::CodePoint( + } => InputEvent::Codepoint( codepoint, modifiers.iter().map(|x| x.clone().into()).collect(), ), @@ -1109,8 +1109,8 @@ impl From for InputEvent { InputEvent::CursorScroll(offset.into(), position.into()) } message::InputEvent::CursorPos { position } => InputEvent::CursorPos(position.into()), - message::InputEvent::ViewPort { event, position } => { - InputEvent::ViewPort(event.into(), position.into()) + message::InputEvent::Viewport { event, position } => { + InputEvent::Viewport(event.into(), position.into()) } message::InputEvent::Relative { position } => InputEvent::Relative(position.into()), message::InputEvent::Led { id, value } => InputEvent::Led(id, value), diff --git a/native/scenic_window/src/message.rs b/native/scenic_window/src/message.rs index cfd989e..1c5dcf6 100644 --- a/native/scenic_window/src/message.rs +++ b/native/scenic_window/src/message.rs @@ -69,7 +69,7 @@ impl From> for Point { } #[derive(Debug, Serialize, Deserialize, Clone)] -pub enum ViewPortEvent { +pub enum ViewportEvent { Enter, Exit, Reshape, @@ -92,7 +92,7 @@ impl From for ElementState { #[derive(Debug, Serialize, Deserialize, Clone)] pub enum InputEvent { - CodePoint { + Codepoint { codepoint: u32, modifiers: Vec, }, @@ -114,8 +114,8 @@ pub enum InputEvent { CursorPos { position: Point, }, - ViewPort { - event: ViewPortEvent, + Viewport { + event: ViewportEvent, position: Point, }, Relative { @@ -150,6 +150,7 @@ pub enum Message { resizeable: bool, title: String, width: u32, + cursor: bool, }, ClearColor(Color), DeleteScripts(Vec), @@ -169,6 +170,7 @@ impl From for Message { resizeable: driver_config.window.resizeable, title: driver_config.window.title, width: driver_config.window.width, + cursor: driver_config.cursor, } } } diff --git a/native/scenic_window/src/server.rs b/native/scenic_window/src/server.rs index 10dcf27..ebf184e 100644 --- a/native/scenic_window/src/server.rs +++ b/native/scenic_window/src/server.rs @@ -28,7 +28,7 @@ use winit::event_loop::{ActiveEventLoop, EventLoop}; use winit::keyboard::{Key, NamedKey, PhysicalKey}; use winit::window::{self, Window, WindowAttributes, WindowId}; -use scenic_renderer::{Context, Orientation, Renderer}; +use scenic_renderer::{Config, Context, Orientation, Renderer}; #[cfg(macos_platform)] use winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS}; @@ -92,6 +92,7 @@ struct InitialWindowConfig { resizeable: bool, title: String, width: u32, + cursor: bool, } struct Application { @@ -116,6 +117,7 @@ impl Application { resizeable, title, width, + cursor, } => Application { initial_config: Some(InitialWindowConfig { centered, @@ -126,6 +128,7 @@ impl Application { resizeable, title, width, + cursor, }), window: None, input_classes: [ @@ -274,7 +277,7 @@ impl ApplicationHandler for Application { if let Some(text) = event.text { let codepoint = text.chars().next().unwrap(); self.sender - .send(Message::InputEvent(message::InputEvent::CodePoint { + .send(Message::InputEvent(message::InputEvent::Codepoint { codepoint: codepoint as u32, modifiers: self .current_modifier_keys @@ -365,8 +368,8 @@ impl ApplicationHandler for Application { WindowEvent::CursorEntered { .. } => { if self.input_classes.contains(&InputClass::Viewport) { self.sender - .send(Message::InputEvent(message::InputEvent::ViewPort { - event: message::ViewPortEvent::Enter, + .send(Message::InputEvent(message::InputEvent::Viewport { + event: message::ViewportEvent::Enter, position: self.last_cursor_pos.clone(), })) .unwrap(); @@ -375,8 +378,8 @@ impl ApplicationHandler for Application { WindowEvent::CursorLeft { .. } => { if self.input_classes.contains(&InputClass::Viewport) { self.sender - .send(Message::InputEvent(message::InputEvent::ViewPort { - event: message::ViewPortEvent::Exit, + .send(Message::InputEvent(message::InputEvent::Viewport { + event: message::ViewportEvent::Exit, position: self.last_cursor_pos.clone(), })) .unwrap(); @@ -385,8 +388,8 @@ impl ApplicationHandler for Application { WindowEvent::Resized(size) => { if self.input_classes.contains(&InputClass::Viewport) { self.sender - .send(Message::InputEvent(message::InputEvent::ViewPort { - event: message::ViewPortEvent::Reshape, + .send(Message::InputEvent(message::InputEvent::Viewport { + event: message::ViewportEvent::Reshape, position: size.into(), })) .unwrap(); @@ -435,8 +438,12 @@ impl ApplicationHandler for Application { self.window = Some(window); - let mut renderer = Renderer::new(context); - renderer.set_orientation(config.orientation); + let config = Config { + show_cursor: config.cursor, + orientation: config.orientation, + }; + + let renderer = Renderer::new(context, config); self.renderer = Some(renderer); }