improvement: Wire up input events to the viewport.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
James Harton 2024-05-17 21:08:46 +12:00
parent e2c9a97a60
commit 9c1b4d917e
Signed by: james
GPG key ID: 90E82DAA13F624F4
8 changed files with 140 additions and 57 deletions

View file

@ -1,3 +1,3 @@
{ {
"cSpell.words": ["centered", "priv", "Renderling"] "cSpell.words": ["centered", "codepoint", "priv", "Renderling"]
} }

View file

@ -3,7 +3,7 @@ defmodule Scenic.Driver.Renderling.Window do
The Scenic for windowed applications. The Scenic for windowed applications.
""" """
alias Scenic.ViewPort alias Scenic.{ViewPort, ViewPort.Input}
alias Scenic.Driver.Renderling.Window.{Config, Nif} alias Scenic.Driver.Renderling.Window.{Config, Nif}
use Scenic.Driver use Scenic.Driver
@ -136,6 +136,51 @@ defmodule Scenic.Driver.Renderling.Window do
end end
end end
def handle_info({:codepoint, codepoint, mods}, driver) do
Input.send(driver.viewport, {:codepoint, {<<codepoint::utf8>>, 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 def handle_info(msg, driver) do
Logger.debug(fn -> Logger.debug(fn ->
"Unhandled message #{inspect(msg)}" "Unhandled message #{inspect(msg)}"

View file

@ -531,9 +531,9 @@ checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53"
[[package]] [[package]]
name = "either" name = "either"
version = "1.11.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
@ -682,9 +682,9 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.15" version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@ -1041,9 +1041,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.154" version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -1084,9 +1084,9 @@ dependencies = [
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.13" version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "lock_api" name = "lock_api"

View file

@ -1,6 +1,6 @@
pub mod script; pub mod script;
use script::{Color, Script}; use script::{Color, Script, ScriptItem};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashMap, f32::consts::PI}; use std::{collections::HashMap, f32::consts::PI};
@ -24,12 +24,18 @@ pub enum Orientation {
pub struct Renderer { pub struct Renderer {
pub stage: Stage, pub stage: Stage,
pub ctx: Context, pub ctx: Context,
camera: Hybrid<Camera>, _camera: Hybrid<Camera>,
scripts: HashMap<String, Script>, scripts: HashMap<String, Script>,
config: Config,
}
pub struct Config {
pub show_cursor: bool,
pub orientation: Orientation,
} }
impl Renderer { impl Renderer {
pub fn new(ctx: Context) -> Self { pub fn new(ctx: Context, config: Config) -> Self {
let mut stage = ctx let mut stage = ctx
.new_stage() .new_stage()
.with_lighting(false) .with_lighting(false)
@ -38,30 +44,22 @@ impl Renderer {
let size = ctx.get_size(); let size = ctx.get_size();
let camera = stage.new_value(Camera::default_ortho2d(size.x as f32, size.y as f32)); 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(); let scripts = HashMap::default();
Self { Self {
stage, stage,
camera, _camera: camera,
ctx, ctx,
scripts, scripts,
} config,
}
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))),
} }
} }
@ -81,19 +79,41 @@ impl Renderer {
pub fn clear_color(&mut self, color: Color) { pub fn clear_color(&mut self, color: Color) {
self.stage.set_background_color(color); self.stage.set_background_color(color);
self.do_update_scene();
} }
pub fn reset_scene(&mut self) { pub fn reset_scene(&mut self) {
self.scripts.clear(); self.scripts.clear();
self.do_update_scene();
} }
pub fn update_scene(&mut self, script_id: String, script: Script) { pub fn update_scene(&mut self, script_id: String, script: Script) {
self.scripts.insert(script_id, script); self.scripts.insert(script_id, script);
self.do_update_scene();
} }
pub fn delete_scripts(&mut self, script_ids: Vec<String>) { pub fn delete_scripts(&mut self, script_ids: Vec<String>) {
for script_id in script_ids { for script_id in script_ids {
self.scripts.remove(&script_id); 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),
}
}
}
} }
} }

View file

@ -325,3 +325,12 @@ impl From<Vec<ScriptItem>> for Script {
Script(vec) 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()
}
}

View file

@ -716,18 +716,18 @@ impl From<message::ModifierKey> for ModifierKey {
} }
#[derive(NifUnitEnum, Debug, Clone)] #[derive(NifUnitEnum, Debug, Clone)]
pub enum ViewPortEvent { pub enum ViewportEvent {
Enter, Enter,
Exit, Exit,
Reshape, Reshape,
} }
impl From<message::ViewPortEvent> for ViewPortEvent { impl From<message::ViewportEvent> for ViewportEvent {
fn from(event: message::ViewPortEvent) -> Self { fn from(event: message::ViewportEvent) -> Self {
match event { match event {
message::ViewPortEvent::Enter => ViewPortEvent::Enter, message::ViewportEvent::Enter => ViewportEvent::Enter,
message::ViewPortEvent::Exit => ViewPortEvent::Exit, message::ViewportEvent::Exit => ViewportEvent::Exit,
message::ViewPortEvent::Reshape => ViewPortEvent::Reshape, message::ViewportEvent::Reshape => ViewportEvent::Reshape,
} }
} }
} }
@ -1064,12 +1064,12 @@ impl From<winit::event::MouseButton> for MouseButton {
#[derive(NifTaggedEnum, Debug, Clone)] #[derive(NifTaggedEnum, Debug, Clone)]
pub enum InputEvent { pub enum InputEvent {
CodePoint(u32, Vec<ModifierKey>), Codepoint(u32, Vec<ModifierKey>),
Key(Key, ElementState, Vec<ModifierKey>), Key(Key, ElementState, Vec<ModifierKey>),
CursorButton(MouseButton, ElementState, Vec<ModifierKey>, Point), CursorButton(MouseButton, ElementState, Vec<ModifierKey>, Point),
CursorScroll(Point, Point), CursorScroll(Point, Point),
CursorPos(Point), CursorPos(Point),
ViewPort(ViewPortEvent, Point), Viewport(ViewportEvent, Point),
Relative(Point), Relative(Point),
Led(String, u32), Led(String, u32),
Switch(String, u32), Switch(String, u32),
@ -1078,10 +1078,10 @@ pub enum InputEvent {
impl From<message::InputEvent> for InputEvent { impl From<message::InputEvent> for InputEvent {
fn from(event: message::InputEvent) -> Self { fn from(event: message::InputEvent) -> Self {
match event { match event {
message::InputEvent::CodePoint { message::InputEvent::Codepoint {
codepoint, codepoint,
modifiers, modifiers,
} => InputEvent::CodePoint( } => InputEvent::Codepoint(
codepoint, codepoint,
modifiers.iter().map(|x| x.clone().into()).collect(), modifiers.iter().map(|x| x.clone().into()).collect(),
), ),
@ -1109,8 +1109,8 @@ impl From<message::InputEvent> for InputEvent {
InputEvent::CursorScroll(offset.into(), position.into()) InputEvent::CursorScroll(offset.into(), position.into())
} }
message::InputEvent::CursorPos { position } => InputEvent::CursorPos(position.into()), message::InputEvent::CursorPos { position } => InputEvent::CursorPos(position.into()),
message::InputEvent::ViewPort { event, position } => { message::InputEvent::Viewport { event, position } => {
InputEvent::ViewPort(event.into(), position.into()) InputEvent::Viewport(event.into(), position.into())
} }
message::InputEvent::Relative { position } => InputEvent::Relative(position.into()), message::InputEvent::Relative { position } => InputEvent::Relative(position.into()),
message::InputEvent::Led { id, value } => InputEvent::Led(id, value), message::InputEvent::Led { id, value } => InputEvent::Led(id, value),

View file

@ -69,7 +69,7 @@ impl From<winit::dpi::PhysicalSize<u32>> for Point {
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ViewPortEvent { pub enum ViewportEvent {
Enter, Enter,
Exit, Exit,
Reshape, Reshape,
@ -92,7 +92,7 @@ impl From<winit::event::ElementState> for ElementState {
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub enum InputEvent { pub enum InputEvent {
CodePoint { Codepoint {
codepoint: u32, codepoint: u32,
modifiers: Vec<ModifierKey>, modifiers: Vec<ModifierKey>,
}, },
@ -114,8 +114,8 @@ pub enum InputEvent {
CursorPos { CursorPos {
position: Point, position: Point,
}, },
ViewPort { Viewport {
event: ViewPortEvent, event: ViewportEvent,
position: Point, position: Point,
}, },
Relative { Relative {
@ -150,6 +150,7 @@ pub enum Message {
resizeable: bool, resizeable: bool,
title: String, title: String,
width: u32, width: u32,
cursor: bool,
}, },
ClearColor(Color), ClearColor(Color),
DeleteScripts(Vec<String>), DeleteScripts(Vec<String>),
@ -169,6 +170,7 @@ impl From<elixir_types::DriverConfig> for Message {
resizeable: driver_config.window.resizeable, resizeable: driver_config.window.resizeable,
title: driver_config.window.title, title: driver_config.window.title,
width: driver_config.window.width, width: driver_config.window.width,
cursor: driver_config.cursor,
} }
} }
} }

View file

@ -28,7 +28,7 @@ use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::keyboard::{Key, NamedKey, PhysicalKey}; use winit::keyboard::{Key, NamedKey, PhysicalKey};
use winit::window::{self, Window, WindowAttributes, WindowId}; use winit::window::{self, Window, WindowAttributes, WindowId};
use scenic_renderer::{Context, Orientation, Renderer}; use scenic_renderer::{Config, Context, Orientation, Renderer};
#[cfg(macos_platform)] #[cfg(macos_platform)]
use winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS}; use winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS};
@ -92,6 +92,7 @@ struct InitialWindowConfig {
resizeable: bool, resizeable: bool,
title: String, title: String,
width: u32, width: u32,
cursor: bool,
} }
struct Application { struct Application {
@ -116,6 +117,7 @@ impl Application {
resizeable, resizeable,
title, title,
width, width,
cursor,
} => Application { } => Application {
initial_config: Some(InitialWindowConfig { initial_config: Some(InitialWindowConfig {
centered, centered,
@ -126,6 +128,7 @@ impl Application {
resizeable, resizeable,
title, title,
width, width,
cursor,
}), }),
window: None, window: None,
input_classes: [ input_classes: [
@ -274,7 +277,7 @@ impl ApplicationHandler<Message> for Application {
if let Some(text) = event.text { if let Some(text) = event.text {
let codepoint = text.chars().next().unwrap(); let codepoint = text.chars().next().unwrap();
self.sender self.sender
.send(Message::InputEvent(message::InputEvent::CodePoint { .send(Message::InputEvent(message::InputEvent::Codepoint {
codepoint: codepoint as u32, codepoint: codepoint as u32,
modifiers: self modifiers: self
.current_modifier_keys .current_modifier_keys
@ -365,8 +368,8 @@ impl ApplicationHandler<Message> for Application {
WindowEvent::CursorEntered { .. } => { WindowEvent::CursorEntered { .. } => {
if self.input_classes.contains(&InputClass::Viewport) { if self.input_classes.contains(&InputClass::Viewport) {
self.sender self.sender
.send(Message::InputEvent(message::InputEvent::ViewPort { .send(Message::InputEvent(message::InputEvent::Viewport {
event: message::ViewPortEvent::Enter, event: message::ViewportEvent::Enter,
position: self.last_cursor_pos.clone(), position: self.last_cursor_pos.clone(),
})) }))
.unwrap(); .unwrap();
@ -375,8 +378,8 @@ impl ApplicationHandler<Message> for Application {
WindowEvent::CursorLeft { .. } => { WindowEvent::CursorLeft { .. } => {
if self.input_classes.contains(&InputClass::Viewport) { if self.input_classes.contains(&InputClass::Viewport) {
self.sender self.sender
.send(Message::InputEvent(message::InputEvent::ViewPort { .send(Message::InputEvent(message::InputEvent::Viewport {
event: message::ViewPortEvent::Exit, event: message::ViewportEvent::Exit,
position: self.last_cursor_pos.clone(), position: self.last_cursor_pos.clone(),
})) }))
.unwrap(); .unwrap();
@ -385,8 +388,8 @@ impl ApplicationHandler<Message> for Application {
WindowEvent::Resized(size) => { WindowEvent::Resized(size) => {
if self.input_classes.contains(&InputClass::Viewport) { if self.input_classes.contains(&InputClass::Viewport) {
self.sender self.sender
.send(Message::InputEvent(message::InputEvent::ViewPort { .send(Message::InputEvent(message::InputEvent::Viewport {
event: message::ViewPortEvent::Reshape, event: message::ViewportEvent::Reshape,
position: size.into(), position: size.into(),
})) }))
.unwrap(); .unwrap();
@ -435,8 +438,12 @@ impl ApplicationHandler<Message> for Application {
self.window = Some(window); self.window = Some(window);
let mut renderer = Renderer::new(context); let config = Config {
renderer.set_orientation(config.orientation); show_cursor: config.cursor,
orientation: config.orientation,
};
let renderer = Renderer::new(context, config);
self.renderer = Some(renderer); self.renderer = Some(renderer);
} }