Restructure project directories (#333)

`/client/web` -> `/frontend`
`/client/cli` -> *delete for now*
`/client/native` -> *delete for now*
`/core/editor` -> `/editor`
`/core/document` -> `/graphene`
`/core/renderer` -> `/charcoal`
`/core/proc-macro` -> `/proc-macros` *(now plural)*
This commit is contained in:
Keavon Chambers
2021-08-07 05:17:18 -07:00
parent 434695d578
commit 53ad105f57
239 changed files with 197 additions and 224 deletions

View File

@@ -0,0 +1,315 @@
use super::{
keyboard::{Key, KeyStates, NUMBER_OF_KEYS},
InputPreprocessor,
};
use crate::consts::{MINUS_KEY_ZOOM_RATE, PLUS_KEY_ZOOM_RATE};
use crate::message_prelude::*;
use crate::tool::ToolType;
use std::fmt::Write;
const NUDGE_AMOUNT: f64 = 1.;
const SHIFT_NUDGE_AMOUNT: f64 = 10.;
#[impl_message(Message, InputMapper)]
#[derive(PartialEq, Clone, Debug, Hash)]
pub enum InputMapperMessage {
PointerMove,
MouseScroll,
KeyUp(Key),
#[child]
KeyDown(Key),
}
#[derive(PartialEq, Clone, Debug)]
struct MappingEntry {
trigger: InputMapperMessage,
modifiers: KeyStates,
action: Message,
}
#[derive(Debug, Clone)]
struct KeyMappingEntries(Vec<MappingEntry>);
impl KeyMappingEntries {
fn match_mapping(&self, keys: &KeyStates, actions: ActionList) -> Option<Message> {
for entry in self.0.iter() {
let all_required_modifiers_pressed = ((*keys & entry.modifiers) ^ entry.modifiers).is_empty();
if all_required_modifiers_pressed && actions.iter().flatten().any(|action| entry.action.to_discriminant() == *action) {
return Some(entry.action.clone());
}
}
None
}
fn push(&mut self, entry: MappingEntry) {
self.0.push(entry)
}
const fn new() -> Self {
Self(Vec::new())
}
fn key_array() -> [Self; NUMBER_OF_KEYS] {
const DEFAULT: KeyMappingEntries = KeyMappingEntries::new();
[DEFAULT; NUMBER_OF_KEYS]
}
}
impl Default for KeyMappingEntries {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
struct Mapping {
key_up: [KeyMappingEntries; NUMBER_OF_KEYS],
key_down: [KeyMappingEntries; NUMBER_OF_KEYS],
pointer_move: KeyMappingEntries,
mouse_scroll: KeyMappingEntries,
}
macro_rules! modifiers {
($($m:ident),*) => {{
#[allow(unused_mut)]
let mut state = KeyStates::new();
$(
state.set(Key::$m as usize);
)*
state
}};
}
macro_rules! entry {
{action=$action:expr, key_down=$key:ident $(, modifiers=[$($m:ident),* $(,)?])?} => {{
entry!{action=$action, message=InputMapperMessage::KeyDown(Key::$key) $(, modifiers=[$($m),*])?}
}};
{action=$action:expr, key_up=$key:ident $(, modifiers=[$($m:ident),* $(,)?])?} => {{
entry!{action=$action, message=InputMapperMessage::KeyUp(Key::$key) $(, modifiers=[$($m),* ])?}
}};
{action=$action:expr, message=$message:expr $(, modifiers=[$($m:ident),* $(,)?])?} => {{
&[MappingEntry {trigger: $message, modifiers: modifiers!($($($m),*)?), action: $action.into()}]
}};
{action=$action:expr, triggers=[$($m:ident),* $(,)?]} => {{
&[
MappingEntry {trigger:InputMapperMessage::PointerMove, action: $action.into(), modifiers: modifiers!()},
$(
MappingEntry {trigger:InputMapperMessage::KeyDown(Key::$m), action: $action.into(), modifiers: modifiers!()},
MappingEntry {trigger:InputMapperMessage::KeyUp(Key::$m), action: $action.into(), modifiers: modifiers!()},
)*
]
}};
}
macro_rules! mapping {
//[$(<action=$action:expr; message=$key:expr; $(modifiers=[$($m:ident),* $(,)?];)?>)*] => {{
[$($entry:expr),* $(,)?] => {{
let mut key_up = KeyMappingEntries::key_array();
let mut key_down = KeyMappingEntries::key_array();
let mut pointer_move: KeyMappingEntries = Default::default();
let mut mouse_scroll: KeyMappingEntries = Default::default();
$(
for entry in $entry {
let arr = match entry.trigger {
InputMapperMessage::KeyDown(key) => &mut key_down[key as usize],
InputMapperMessage::KeyUp(key) => &mut key_up[key as usize],
InputMapperMessage::PointerMove => &mut pointer_move,
InputMapperMessage::MouseScroll => &mut mouse_scroll,
};
arr.push(entry.clone());
}
)*
(key_up, key_down, pointer_move, mouse_scroll)
}};
}
impl Default for Mapping {
fn default() -> Self {
use Key::*;
let mappings = mapping![
entry! {action=DocumentsMessage::PasteLayers{path: vec![], insert_index: -1}, key_down=KeyV, modifiers=[KeyControl]},
entry! {action=MovementMessage::EnableSnapping, key_down=KeyShift},
entry! {action=MovementMessage::DisableSnapping, key_up=KeyShift},
// Select
entry! {action=SelectMessage::MouseMove, message=InputMapperMessage::PointerMove},
entry! {action=SelectMessage::DragStart, key_down=Lmb},
entry! {action=SelectMessage::DragStop, key_up=Lmb},
entry! {action=SelectMessage::Abort, key_down=Rmb},
entry! {action=SelectMessage::Abort, key_down=KeyEscape},
// Eyedropper
entry! {action=EyedropperMessage::LeftMouseDown, key_down=Lmb},
entry! {action=EyedropperMessage::RightMouseDown, key_down=Rmb},
// Rectangle
entry! {action=RectangleMessage::DragStart, key_down=Lmb},
entry! {action=RectangleMessage::DragStop, key_up=Lmb},
entry! {action=RectangleMessage::Abort, key_down=Rmb},
entry! {action=RectangleMessage::Abort, key_down=KeyEscape},
entry! {action=RectangleMessage::Resize{center: KeyAlt, lock_ratio: KeyShift}, triggers=[KeyAlt, KeyShift]},
// Ellipse
entry! {action=EllipseMessage::DragStart, key_down=Lmb},
entry! {action=EllipseMessage::DragStop, key_up=Lmb},
entry! {action=EllipseMessage::Abort, key_down=Rmb},
entry! {action=EllipseMessage::Abort, key_down=KeyEscape},
entry! {action=EllipseMessage::Resize{center: KeyAlt, lock_ratio: KeyShift}, triggers=[KeyAlt, KeyShift]},
// Shape
entry! {action=ShapeMessage::DragStart, key_down=Lmb},
entry! {action=ShapeMessage::DragStop, key_up=Lmb},
entry! {action=ShapeMessage::Abort, key_down=Rmb},
entry! {action=ShapeMessage::Abort, key_down=KeyEscape},
entry! {action=ShapeMessage::Resize{center: KeyAlt, lock_ratio: KeyShift}, triggers=[KeyAlt, KeyShift]},
// Line
entry! {action=LineMessage::DragStart, key_down=Lmb},
entry! {action=LineMessage::DragStop, key_up=Lmb},
entry! {action=LineMessage::Abort, key_down=Rmb},
entry! {action=LineMessage::Abort, key_down=KeyEscape},
entry! {action=LineMessage::Redraw{center: KeyAlt, lock_angle: KeyControl, snap_angle: KeyShift}, triggers=[KeyAlt, KeyShift, KeyControl]},
// Pen
entry! {action=PenMessage::PointerMove, message=InputMapperMessage::PointerMove},
entry! {action=PenMessage::DragStart, key_down=Lmb},
entry! {action=PenMessage::DragStop, key_up=Lmb},
entry! {action=PenMessage::Confirm, key_down=Rmb},
entry! {action=PenMessage::Confirm, key_down=KeyEscape},
entry! {action=PenMessage::Confirm, key_down=KeyEnter},
// Fill
entry! {action=FillMessage::MouseDown, key_down=Lmb},
// Tool Actions
entry! {action=ToolMessage::SelectTool(ToolType::Fill), key_down=KeyF},
entry! {action=ToolMessage::SelectTool(ToolType::Rectangle), key_down=KeyM},
entry! {action=ToolMessage::SelectTool(ToolType::Ellipse), key_down=KeyE},
entry! {action=ToolMessage::SelectTool(ToolType::Select), key_down=KeyV},
entry! {action=ToolMessage::SelectTool(ToolType::Line), key_down=KeyL},
entry! {action=ToolMessage::SelectTool(ToolType::Pen), key_down=KeyP},
entry! {action=ToolMessage::SelectTool(ToolType::Shape), key_down=KeyY},
entry! {action=ToolMessage::SelectTool(ToolType::Eyedropper), key_down=KeyI},
entry! {action=ToolMessage::ResetColors, key_down=KeyX, modifiers=[KeyShift, KeyControl]},
entry! {action=ToolMessage::SwapColors, key_down=KeyX, modifiers=[KeyShift]},
// Document Actions
entry! {action=DocumentMessage::Undo, key_down=KeyZ, modifiers=[KeyControl]},
entry! {action=DocumentMessage::DeselectAllLayers, key_down=KeyA, modifiers=[KeyControl, KeyAlt]},
entry! {action=DocumentMessage::SelectAllLayers, key_down=KeyA, modifiers=[KeyControl]},
entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyDelete},
entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyX},
entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyBackspace},
entry! {action=DocumentMessage::ExportDocument, key_down=KeyE, modifiers=[KeyControl]},
entry! {action=MovementMessage::MouseMove, message=InputMapperMessage::PointerMove},
entry! {action=MovementMessage::RotateCanvasBegin{snap:false}, key_down=Mmb, modifiers=[KeyControl]},
entry! {action=MovementMessage::RotateCanvasBegin{snap:true}, key_down=Mmb, modifiers=[KeyControl, KeyShift]},
entry! {action=MovementMessage::ZoomCanvasBegin, key_down=Mmb, modifiers=[KeyShift]},
entry! {action=MovementMessage::ZoomCanvasToFitAll, key_down=Key0, modifiers=[KeyControl]},
entry! {action=MovementMessage::TranslateCanvasBegin, key_down=Mmb},
entry! {action=MovementMessage::TranslateCanvasEnd, key_up=Mmb},
entry! {action=MovementMessage::MultiplyCanvasZoom(PLUS_KEY_ZOOM_RATE), key_down=KeyPlus, modifiers=[KeyControl]},
entry! {action=MovementMessage::MultiplyCanvasZoom(PLUS_KEY_ZOOM_RATE), key_down=KeyEquals, modifiers=[KeyControl]},
entry! {action=MovementMessage::MultiplyCanvasZoom(MINUS_KEY_ZOOM_RATE), key_down=KeyMinus, modifiers=[KeyControl]},
entry! {action=MovementMessage::SetCanvasZoom(1.), key_down=Key1, modifiers=[KeyControl]},
entry! {action=MovementMessage::SetCanvasZoom(2.), key_down=Key2, modifiers=[KeyControl]},
entry! {action=MovementMessage::WheelCanvasZoom, message=InputMapperMessage::MouseScroll, modifiers=[KeyControl]},
entry! {action=MovementMessage::WheelCanvasTranslate{use_y_as_x: true}, message=InputMapperMessage::MouseScroll, modifiers=[KeyShift]},
entry! {action=MovementMessage::WheelCanvasTranslate{use_y_as_x: false}, message=InputMapperMessage::MouseScroll},
entry! {action=DocumentsMessage::NewDocument, key_down=KeyN, modifiers=[KeyControl]},
entry! {action=DocumentsMessage::NextDocument, key_down=KeyTab, modifiers=[KeyControl]},
entry! {action=DocumentsMessage::PrevDocument, key_down=KeyTab, modifiers=[KeyControl, KeyShift]},
entry! {action=DocumentsMessage::CloseAllDocumentsWithConfirmation, key_down=KeyW, modifiers=[KeyControl, KeyAlt]},
entry! {action=DocumentsMessage::CloseActiveDocumentWithConfirmation, key_down=KeyW, modifiers=[KeyControl]},
entry! {action=DocumentMessage::DuplicateSelectedLayers, key_down=KeyD, modifiers=[KeyControl]},
entry! {action=DocumentsMessage::CopySelectedLayers, key_down=KeyC, modifiers=[KeyControl]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowLeft]},
entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowRight]},
entry! {action=DocumentMessage::NudgeSelectedLayers(0., -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyShift]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyShift, KeyArrowLeft]},
entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyShift, KeyArrowRight]},
entry! {action=DocumentMessage::NudgeSelectedLayers(0., SHIFT_NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyShift]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyShift, KeyArrowUp]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyShift, KeyArrowDown]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, 0.), key_down=KeyArrowLeft, modifiers=[KeyShift]},
entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyShift, KeyArrowUp]},
entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyShift, KeyArrowDown]},
entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, 0.), key_down=KeyArrowRight, modifiers=[KeyShift]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyArrowLeft]},
entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyArrowRight]},
entry! {action=DocumentMessage::NudgeSelectedLayers(0., -NUDGE_AMOUNT), key_down=KeyArrowUp},
entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyArrowLeft]},
entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyArrowRight]},
entry! {action=DocumentMessage::NudgeSelectedLayers(0., NUDGE_AMOUNT), key_down=KeyArrowDown},
entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyArrowUp]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyArrowDown]},
entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, 0.), key_down=KeyArrowLeft},
entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyArrowUp]},
entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyArrowDown]},
entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, 0.), key_down=KeyArrowRight},
entry! {action=DocumentMessage::ReorderSelectedLayers(i32::MAX), key_down=KeyRightCurlyBracket, modifiers=[KeyControl]}, // TODO: Use KeyRightBracket with ctrl+shift modifiers once input system is fixed
entry! {action=DocumentMessage::ReorderSelectedLayers(1), key_down=KeyRightBracket, modifiers=[KeyControl]},
entry! {action=DocumentMessage::ReorderSelectedLayers(-1), key_down=KeyLeftBracket, modifiers=[KeyControl]},
entry! {action=DocumentMessage::ReorderSelectedLayers(i32::MIN), key_down=KeyLeftCurlyBracket, modifiers=[KeyControl]}, // TODO: Use KeyLeftBracket with ctrl+shift modifiers once input system is fixed
// Global Actions
entry! {action=GlobalMessage::LogInfo, key_down=Key1},
entry! {action=GlobalMessage::LogDebug, key_down=Key2},
entry! {action=GlobalMessage::LogTrace, key_down=Key3},
];
let (mut key_up, mut key_down, mut pointer_move, mut mouse_scroll) = mappings;
let sort = |list: &mut KeyMappingEntries| list.0.sort_by(|u, v| v.modifiers.ones().cmp(&u.modifiers.ones()));
for list in [&mut key_up, &mut key_down] {
for sublist in list {
sort(sublist);
}
}
sort(&mut pointer_move);
sort(&mut mouse_scroll);
Self {
key_up,
key_down,
pointer_move,
mouse_scroll,
}
}
}
impl Mapping {
fn match_message(&self, message: InputMapperMessage, keys: &KeyStates, actions: ActionList) -> Option<Message> {
use InputMapperMessage::*;
let list = match message {
KeyDown(key) => &self.key_down[key as usize],
KeyUp(key) => &self.key_up[key as usize],
PointerMove => &self.pointer_move,
MouseScroll => &self.mouse_scroll,
};
list.match_mapping(keys, actions)
}
}
#[derive(Debug, Default)]
pub struct InputMapper {
mapping: Mapping,
}
impl InputMapper {
pub fn hints(&self, actions: ActionList) -> String {
let mut output = String::new();
let mut actions = actions
.into_iter()
.flatten()
.filter(|a| !matches!(*a, MessageDiscriminant::Tool(ToolMessageDiscriminant::SelectTool) | MessageDiscriminant::Global(_)));
self.mapping
.key_down
.iter()
.enumerate()
.filter_map(|(i, m)| {
let ma = m.0.iter().find_map(|m| actions.find_map(|a| (a == m.action.to_discriminant()).then(|| m.action.to_discriminant())));
ma.map(|a| unsafe { (std::mem::transmute_copy::<usize, Key>(&i), a) })
})
.for_each(|(k, a)| {
let _ = write!(output, "{}: {}, ", k.to_discriminant().local_name(), a.local_name().split('.').last().unwrap());
});
output.replace("Key", "")
}
}
impl MessageHandler<InputMapperMessage, (&InputPreprocessor, ActionList)> for InputMapper {
fn process_action(&mut self, message: InputMapperMessage, data: (&InputPreprocessor, ActionList), responses: &mut VecDeque<Message>) {
let (input, actions) = data;
if let Some(message) = self.mapping.match_message(message, &input.keyboard, actions) {
responses.push_back(message);
}
}
advertise_actions!();
}

View File

@@ -0,0 +1,198 @@
use std::usize;
use super::keyboard::{Key, KeyStates};
use super::mouse::{MouseKeys, MouseState, ScrollDelta, ViewportPosition};
use crate::message_prelude::*;
use bitflags::bitflags;
#[doc(inline)]
pub use graphene::DocumentResponse;
#[impl_message(Message, InputPreprocessor)]
#[derive(PartialEq, Clone, Debug)]
pub enum InputPreprocessorMessage {
MouseDown(MouseState, ModifierKeys),
MouseUp(MouseState, ModifierKeys),
MouseMove(ViewportPosition, ModifierKeys),
MouseScroll(ScrollDelta, ModifierKeys),
KeyUp(Key, ModifierKeys),
KeyDown(Key, ModifierKeys),
ViewportResize(ViewportPosition),
}
bitflags! {
#[derive(Default)]
#[repr(transparent)]
pub struct ModifierKeys: u8 {
const CONTROL = 0b0000_0001;
const SHIFT = 0b0000_0010;
const ALT = 0b0000_0100;
}
}
#[derive(Debug, Default, Hash)]
pub struct InputPreprocessor {
pub keyboard: KeyStates,
pub mouse: MouseState,
pub viewport_size: ViewportPosition,
}
enum KeyPosition {
Pressed,
Released,
}
impl MessageHandler<InputPreprocessorMessage, ()> for InputPreprocessor {
fn process_action(&mut self, message: InputPreprocessorMessage, _data: (), responses: &mut VecDeque<Message>) {
match message {
InputPreprocessorMessage::MouseMove(pos, modifier_keys) => {
self.handle_modifier_keys(modifier_keys, responses);
self.mouse.position = pos;
responses.push_back(InputMapperMessage::PointerMove.into());
}
InputPreprocessorMessage::MouseScroll(delta, modifier_keys) => {
self.handle_modifier_keys(modifier_keys, responses);
self.mouse.scroll_delta = delta;
responses.push_back(InputMapperMessage::MouseScroll.into());
}
InputPreprocessorMessage::MouseDown(state, modifier_keys) => {
self.handle_modifier_keys(modifier_keys, responses);
responses.push_back(self.translate_mouse_event(state, KeyPosition::Pressed));
}
InputPreprocessorMessage::MouseUp(state, modifier_keys) => {
self.handle_modifier_keys(modifier_keys, responses);
responses.push_back(self.translate_mouse_event(state, KeyPosition::Released));
}
InputPreprocessorMessage::KeyDown(key, modifier_keys) => {
self.handle_modifier_keys(modifier_keys, responses);
self.keyboard.set(key as usize);
responses.push_back(InputMapperMessage::KeyDown(key).into());
}
InputPreprocessorMessage::KeyUp(key, modifier_keys) => {
self.handle_modifier_keys(modifier_keys, responses);
self.keyboard.unset(key as usize);
responses.push_back(InputMapperMessage::KeyUp(key).into());
}
InputPreprocessorMessage::ViewportResize(size) => {
responses.push_back(
graphene::Operation::TransformLayer {
path: vec![],
transform: glam::DAffine2::from_translation((size.as_f64() - self.viewport_size.as_f64()) / 2.).to_cols_array(),
}
.into(),
);
self.viewport_size = size;
}
};
}
// clean user input and if possible reconstruct it
// store the changes in the keyboard if it is a key event
// transform canvas coordinates to document coordinates
advertise_actions!();
}
impl InputPreprocessor {
fn translate_mouse_event(&mut self, new_state: MouseState, position: KeyPosition) -> Message {
// Calculate the difference between the two key states (binary xor)
let diff = self.mouse.mouse_keys ^ new_state.mouse_keys;
self.mouse = new_state;
let key = match diff {
MouseKeys::LEFT => Key::Lmb,
MouseKeys::RIGHT => Key::Rmb,
MouseKeys::MIDDLE => Key::Mmb,
_ => {
log::warn!("The number of buttons modified at the same time was not equal to 1. Modification: {:#010b}", diff);
Key::UnknownKey
}
};
match position {
KeyPosition::Pressed => InputMapperMessage::KeyDown(key).into(),
KeyPosition::Released => InputMapperMessage::KeyUp(key).into(),
}
}
fn handle_modifier_keys(&mut self, modifier_keys: ModifierKeys, responses: &mut VecDeque<Message>) {
self.handle_modifier_key(Key::KeyControl, modifier_keys.contains(ModifierKeys::CONTROL), responses);
self.handle_modifier_key(Key::KeyShift, modifier_keys.contains(ModifierKeys::SHIFT), responses);
self.handle_modifier_key(Key::KeyAlt, modifier_keys.contains(ModifierKeys::ALT), responses);
}
fn handle_modifier_key(&mut self, key: Key, key_is_down: bool, responses: &mut VecDeque<Message>) {
let key_was_down = self.keyboard.get(key as usize);
if key_was_down && !key_is_down {
self.keyboard.unset(key as usize);
responses.push_back(InputMapperMessage::KeyUp(key).into());
} else if !key_was_down && key_is_down {
self.keyboard.set(key as usize);
responses.push_back(InputMapperMessage::KeyDown(key).into());
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn process_action_mouse_move_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessor::default();
let message = InputPreprocessorMessage::MouseMove((4, 809).into(), ModifierKeys::ALT);
let mut responses = VecDeque::new();
input_preprocessor.process_action(message, (), &mut responses);
assert!(input_preprocessor.keyboard.get(Key::KeyAlt as usize));
assert_eq!(responses.pop_front(), Some(InputMapperMessage::KeyDown(Key::KeyAlt).into()));
}
#[test]
fn process_action_mouse_down_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessor::default();
let message = InputPreprocessorMessage::MouseDown(MouseState::new(), ModifierKeys::CONTROL);
let mut responses = VecDeque::new();
input_preprocessor.process_action(message, (), &mut responses);
assert!(input_preprocessor.keyboard.get(Key::KeyControl as usize));
assert_eq!(responses.pop_front(), Some(InputMapperMessage::KeyDown(Key::KeyControl).into()));
}
#[test]
fn process_action_mouse_up_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessor::default();
let message = InputPreprocessorMessage::MouseUp(MouseState::new(), ModifierKeys::SHIFT);
let mut responses = VecDeque::new();
input_preprocessor.process_action(message, (), &mut responses);
assert!(input_preprocessor.keyboard.get(Key::KeyShift as usize));
assert_eq!(responses.pop_front(), Some(InputMapperMessage::KeyDown(Key::KeyShift).into()));
}
#[test]
fn process_action_key_down_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessor::default();
input_preprocessor.keyboard.set(Key::KeyControl as usize);
let message = InputPreprocessorMessage::KeyDown(Key::KeyA, ModifierKeys::empty());
let mut responses = VecDeque::new();
input_preprocessor.process_action(message, (), &mut responses);
assert!(!input_preprocessor.keyboard.get(Key::KeyControl as usize));
assert_eq!(responses.pop_front(), Some(InputMapperMessage::KeyUp(Key::KeyControl).into()));
}
#[test]
fn process_action_key_up_handle_modifier_keys() {
let mut input_preprocessor = InputPreprocessor::default();
let message = InputPreprocessorMessage::KeyUp(Key::KeyS, ModifierKeys::CONTROL | ModifierKeys::SHIFT);
let mut responses = VecDeque::new();
input_preprocessor.process_action(message, (), &mut responses);
assert!(input_preprocessor.keyboard.get(Key::KeyControl as usize));
assert!(input_preprocessor.keyboard.get(Key::KeyShift as usize));
assert!(responses.contains(&InputMapperMessage::KeyDown(Key::KeyControl).into()));
assert!(responses.contains(&InputMapperMessage::KeyDown(Key::KeyControl).into()));
}
}

View File

@@ -0,0 +1,189 @@
use crate::message_prelude::*;
pub const NUMBER_OF_KEYS: usize = Key::NumKeys as usize;
// Edit this to specify the storage type used
// TODO: Increase size of type
pub type StorageType = u128;
// base 2 logarithm of the storage type used to represents how many bits you need to fully address every bit in that storage type
const STORAGE_SIZE: u32 = (std::mem::size_of::<StorageType>() * 8).trailing_zeros();
const STORAGE_SIZE_BITS: usize = 1 << STORAGE_SIZE;
const KEY_MASK_STORAGE_LENGTH: usize = (NUMBER_OF_KEYS + STORAGE_SIZE_BITS - 1) >> STORAGE_SIZE;
pub type KeyStates = BitVector<KEY_MASK_STORAGE_LENGTH>;
#[impl_message(Message, InputMapperMessage, KeyDown)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Key {
UnknownKey,
// MouseKeys
Lmb,
Rmb,
Mmb,
// Keyboard keys
KeyA,
KeyB,
KeyC,
KeyD,
KeyE,
KeyF,
KeyG,
KeyH,
KeyI,
KeyJ,
KeyK,
KeyL,
KeyM,
KeyN,
KeyO,
KeyP,
KeyQ,
KeyR,
KeyS,
KeyT,
KeyU,
KeyV,
KeyW,
KeyX,
KeyY,
KeyZ,
Key0,
Key1,
Key2,
Key3,
Key4,
Key5,
Key6,
Key7,
Key8,
Key9,
KeyEnter,
KeyEquals,
KeyMinus,
KeyPlus,
KeyShift,
KeyControl,
KeyDelete,
KeyBackspace,
KeyAlt,
KeyEscape,
KeyTab,
KeyArrowUp,
KeyArrowDown,
KeyArrowLeft,
KeyArrowRight,
KeyLeftBracket,
KeyRightBracket,
KeyLeftCurlyBracket,
KeyRightCurlyBracket,
// This has to be the last element in the enum.
NumKeys,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BitVector<const LENGTH: usize>([StorageType; LENGTH]);
use std::{
fmt::{Display, Formatter},
ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign},
usize,
};
impl<const LENGTH: usize> BitVector<LENGTH> {
#[inline]
fn convert_index(bitvector_index: usize) -> (usize, StorageType) {
let bit = 1 << (bitvector_index & (STORAGE_SIZE_BITS as StorageType - 1) as usize);
let offset = bitvector_index >> STORAGE_SIZE;
(offset, bit)
}
pub const fn new() -> Self {
Self([0; LENGTH])
}
pub fn set(&mut self, bitvector_index: usize) {
let (offset, bit) = Self::convert_index(bitvector_index);
self.0[offset] |= bit;
}
pub fn unset(&mut self, bitvector_index: usize) {
let (offset, bit) = Self::convert_index(bitvector_index);
self.0[offset] &= !bit;
}
pub fn toggle(&mut self, bitvector_index: usize) {
let (offset, bit) = Self::convert_index(bitvector_index);
self.0[offset] ^= bit;
}
pub fn get(&self, bitvector_index: usize) -> bool {
let (offset, bit) = Self::convert_index(bitvector_index);
(self.0[offset] & bit) != 0
}
pub fn is_empty(&self) -> bool {
let mut result = 0;
for storage in self.0.iter() {
result |= storage;
}
result == 0
}
pub fn ones(&self) -> u32 {
let mut result = 0;
for storage in self.0.iter() {
result += storage.count_ones();
}
result
}
}
impl<const LENGTH: usize> Default for BitVector<LENGTH> {
fn default() -> Self {
Self::new()
}
}
impl<const LENGTH: usize> Display for BitVector<LENGTH> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
for storage in self.0.iter().rev() {
write!(f, "{:0width$b}", storage, width = STORAGE_SIZE_BITS)?;
}
Ok(())
}
}
macro_rules! bit_ops {
($(($op:ident, $func:ident)),* $(,)?) => {
$(
impl<const LENGTH: usize> $op for BitVector<LENGTH> {
type Output = Self;
fn $func(self, right: Self) -> Self::Output {
let mut result = Self::new();
for ((left, right), new) in self.0.iter().zip(right.0.iter()).zip(result.0.iter_mut()) {
*new = $op::$func(left, right);
}
result
}
}
impl<const LENGTH: usize> $op for &BitVector<LENGTH> {
type Output = BitVector<LENGTH>;
fn $func(self, right: Self) -> Self::Output {
let mut result = BitVector::<LENGTH>::new();
for ((left, right), new) in self.0.iter().zip(right.0.iter()).zip(result.0.iter_mut()) {
*new = $op::$func(left, right);
}
result
}
}
)*
};
}
macro_rules! bit_ops_assign {
($(($op:ident, $func:ident)),* $(,)?) => {
$(impl<const LENGTH: usize> $op for BitVector<LENGTH> {
fn $func(&mut self, right: Self) {
for (left, right) in self.0.iter_mut().zip(right.0.iter()) {
$op::$func(left, right);
}
}
})*
};
}
bit_ops!((BitAnd, bitand), (BitOr, bitor), (BitXor, bitxor));
bit_ops_assign!((BitAndAssign, bitand_assign), (BitOrAssign, bitor_assign), (BitXorAssign, bitxor_assign));

9
editor/src/input/mod.rs Normal file
View File

@@ -0,0 +1,9 @@
pub mod input_mapper;
pub mod input_preprocessor;
pub mod keyboard;
pub mod mouse;
pub use {
input_mapper::{InputMapper, InputMapperMessage, InputMapperMessageDiscriminant},
input_preprocessor::{InputPreprocessor, InputPreprocessorMessage, InputPreprocessorMessageDiscriminant, ModifierKeys},
};

62
editor/src/input/mouse.rs Normal file
View File

@@ -0,0 +1,62 @@
use bitflags::bitflags;
use glam::DVec2;
// origin is top left
pub type ViewportPosition = glam::UVec2;
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
pub struct ScrollDelta {
pub x: i32,
pub y: i32,
pub z: i32,
}
impl ScrollDelta {
pub fn new(x: i32, y: i32, z: i32) -> ScrollDelta {
ScrollDelta { x, y, z }
}
pub fn as_dvec2(&self) -> DVec2 {
DVec2::new(self.x as f64, self.y as f64)
}
pub fn scroll_delta(&self) -> f64 {
let (dx, dy) = (self.x, self.y);
dy.signum() as f64 * ((dy * dy + i32::min(dy.abs(), dx.abs()).pow(2)) as f64).sqrt()
}
}
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash)]
pub struct MouseState {
pub position: ViewportPosition,
pub mouse_keys: MouseKeys,
pub scroll_delta: ScrollDelta,
}
impl MouseState {
pub fn new() -> MouseState {
Self::default()
}
pub fn from_pos(x: u32, y: u32) -> MouseState {
MouseState {
position: (x, y).into(),
mouse_keys: MouseKeys::default(),
scroll_delta: ScrollDelta::default(),
}
}
pub fn from_u8_pos(keys: u8, position: ViewportPosition) -> Self {
let mouse_keys = MouseKeys::from_bits(keys).expect("invalid modifier keys");
Self {
position,
mouse_keys,
scroll_delta: ScrollDelta::default(),
}
}
}
bitflags! {
#[derive(Default)]
#[repr(transparent)]
pub struct MouseKeys: u8 {
const LEFT = 0b0000_0001;
const RIGHT = 0b0000_0010;
const MIDDLE = 0b0000_0100;
}
}