improvement: Wire up input events to the viewport.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
e2c9a97a60
commit
9c1b4d917e
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"cSpell.words": ["centered", "priv", "Renderling"]
|
||||
"cSpell.words": ["centered", "codepoint", "priv", "Renderling"]
|
||||
}
|
||||
|
|
|
@ -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)}"
|
||||
|
|
16
native/scenic_renderer/Cargo.lock
generated
16
native/scenic_renderer/Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue