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.
"""
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, {<<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
Logger.debug(fn ->
"Unhandled message #{inspect(msg)}"

View file

@ -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"

View file

@ -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>,
_camera: Hybrid<Camera>,
scripts: HashMap<String, Script>,
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<String>) {
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),
}
}
}
}
}

View file

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

View file

@ -716,18 +716,18 @@ impl From<message::ModifierKey> for ModifierKey {
}
#[derive(NifUnitEnum, Debug, Clone)]
pub enum ViewPortEvent {
pub enum ViewportEvent {
Enter,
Exit,
Reshape,
}
impl From<message::ViewPortEvent> for ViewPortEvent {
fn from(event: message::ViewPortEvent) -> Self {
impl From<message::ViewportEvent> 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<winit::event::MouseButton> for MouseButton {
#[derive(NifTaggedEnum, Debug, Clone)]
pub enum InputEvent {
CodePoint(u32, Vec<ModifierKey>),
Codepoint(u32, Vec<ModifierKey>),
Key(Key, ElementState, Vec<ModifierKey>),
CursorButton(MouseButton, ElementState, Vec<ModifierKey>, 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<message::InputEvent> 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<message::InputEvent> 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),

View file

@ -69,7 +69,7 @@ impl From<winit::dpi::PhysicalSize<u32>> for Point {
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ViewPortEvent {
pub enum ViewportEvent {
Enter,
Exit,
Reshape,
@ -92,7 +92,7 @@ impl From<winit::event::ElementState> for ElementState {
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum InputEvent {
CodePoint {
Codepoint {
codepoint: u32,
modifiers: Vec<ModifierKey>,
},
@ -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<String>),
@ -169,6 +170,7 @@ impl From<elixir_types::DriverConfig> for Message {
resizeable: driver_config.window.resizeable,
title: driver_config.window.title,
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::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<Message> 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<Message> 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<Message> 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<Message> 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<Message> 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);
}