added configurable key bindings for editor controls

- #366
This commit is contained in:
Dmitry
2023-01-06 22:26:49 +03:00
parent 3ead8a51fd
commit 754c21d16d
5 changed files with 236 additions and 169 deletions
+52 -66
View File
@@ -1,3 +1,4 @@
use crate::settings::keys::KeyBindings;
use crate::{settings::camera::CameraSettings, utils::built_in_skybox, SceneCameraSettings};
use fyrox::{
core::{
@@ -201,80 +202,65 @@ impl CameraController {
}
#[must_use]
pub fn on_key_up(&mut self, key: KeyCode) -> bool {
match key {
KeyCode::W => {
self.move_forward = false;
true
}
KeyCode::S => {
self.move_backward = false;
true
}
KeyCode::A => {
self.move_left = false;
true
}
KeyCode::D => {
self.move_right = false;
true
}
KeyCode::Space | KeyCode::Q => {
self.move_up = false;
true
}
KeyCode::E => {
self.move_down = false;
true
}
KeyCode::LControl | KeyCode::LShift => {
self.speed_factor = 1.0;
true
}
_ => false,
pub fn on_key_up(&mut self, key_bindings: &KeyBindings, key: KeyCode) -> bool {
if key_bindings.move_forward == key {
self.move_forward = false;
true
} else if key_bindings.move_back == key {
self.move_backward = false;
true
} else if key_bindings.move_left == key {
self.move_left = false;
true
} else if key_bindings.move_right == key {
self.move_right = false;
true
} else if key_bindings.move_up == key {
self.move_up = false;
true
} else if key_bindings.move_down == key {
self.move_down = false;
true
} else if key_bindings.slow_down == key || key_bindings.speed_up == key {
self.speed_factor = 1.0;
true
} else {
false
}
}
#[must_use]
pub fn on_key_down(&mut self, key: KeyCode) -> bool {
pub fn on_key_down(&mut self, key_bindings: &KeyBindings, key: KeyCode) -> bool {
if !self.rotate || self.drag {
return false;
}
match key {
KeyCode::W => {
self.move_forward = true;
true
}
KeyCode::S => {
self.move_backward = true;
true
}
KeyCode::A => {
self.move_left = true;
true
}
KeyCode::D => {
self.move_right = true;
true
}
KeyCode::Space | KeyCode::Q => {
self.move_up = true;
true
}
KeyCode::E => {
self.move_down = true;
true
}
KeyCode::LControl => {
self.speed_factor = 2.0;
true
}
KeyCode::LShift => {
self.speed_factor = 0.25;
true
}
_ => false,
if key_bindings.move_forward == key {
self.move_forward = true;
true
} else if key_bindings.move_back == key {
self.move_backward = true;
true
} else if key_bindings.move_left == key {
self.move_left = true;
true
} else if key_bindings.move_right == key {
self.move_right = true;
true
} else if key_bindings.move_up == key {
self.move_up = true;
true
} else if key_bindings.move_down == key {
self.move_down = true;
true
} else if key_bindings.speed_up == key {
self.speed_factor = 2.0;
true
} else if key_bindings.slow_down == key {
self.speed_factor = 0.25;
true
} else {
false
}
}
+82 -92
View File
@@ -97,7 +97,8 @@ use fyrox::{
file_browser::{FileBrowserMode, FileSelectorBuilder, FileSelectorMessage, Filter},
formatted_text::WrapMode,
grid::{Column, GridBuilder, Row},
message::{KeyCode, MessageDirection, UiMessage},
key::HotKey,
message::{MessageDirection, UiMessage},
messagebox::{MessageBoxBuilder, MessageBoxButtons, MessageBoxMessage, MessageBoxResult},
ttf::Font,
widget::{WidgetBuilder, WidgetMessage},
@@ -980,107 +981,96 @@ impl Editor {
let engine = &mut self.engine;
if let Some(WidgetMessage::KeyDown(key)) = message.data() {
match key {
KeyCode::Y if modifiers.control => {
sender.send(Message::RedoSceneCommand).unwrap();
}
KeyCode::Z if modifiers.control => {
sender.send(Message::UndoSceneCommand).unwrap();
}
KeyCode::Key1 => {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Select))
.unwrap();
}
KeyCode::Key2 => {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Move))
.unwrap();
}
KeyCode::Key3 => {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Rotate))
.unwrap();
}
KeyCode::Key4 => {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Scale))
.unwrap();
}
KeyCode::Key5 => {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Navmesh))
.unwrap();
}
KeyCode::Key6 => {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Terrain))
.unwrap();
}
KeyCode::L if modifiers.control => {
sender.send(Message::OpenLoadSceneDialog).unwrap();
}
KeyCode::S if modifiers.control => {
if let Some(scene) = self.scene.as_ref() {
if let Some(path) = scene.path.as_ref() {
self.message_sender
.send(Message::SaveScene(path.clone()))
.unwrap();
} else {
// Scene wasn't saved yet, open Save As dialog.
engine
.user_interface
.send_message(WindowMessage::open_modal(
self.save_file_selector,
MessageDirection::ToWidget,
true,
));
}
let hot_key = HotKey::Some {
code: *key,
modifiers,
};
let key_bindings = &self.settings.key_bindings;
if hot_key == key_bindings.redo {
sender.send(Message::RedoSceneCommand).unwrap();
} else if hot_key == key_bindings.undo {
sender.send(Message::UndoSceneCommand).unwrap();
} else if hot_key == key_bindings.enable_select_mode {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Select))
.unwrap();
} else if hot_key == key_bindings.enable_move_mode {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Move))
.unwrap();
} else if hot_key == key_bindings.enable_rotate_mode {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Rotate))
.unwrap();
} else if hot_key == key_bindings.enable_scale_mode {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Scale))
.unwrap();
} else if hot_key == key_bindings.enable_navmesh_mode {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Navmesh))
.unwrap();
} else if hot_key == key_bindings.enable_terrain_mode {
sender
.send(Message::SetInteractionMode(InteractionModeKind::Terrain))
.unwrap();
} else if hot_key == key_bindings.load_scene {
sender.send(Message::OpenLoadSceneDialog).unwrap();
} else if hot_key == key_bindings.save_scene {
if let Some(scene) = self.scene.as_ref() {
if let Some(path) = scene.path.as_ref() {
self.message_sender
.send(Message::SaveScene(path.clone()))
.unwrap();
} else {
// Scene wasn't saved yet, open Save As dialog.
engine
.user_interface
.send_message(WindowMessage::open_modal(
self.save_file_selector,
MessageDirection::ToWidget,
true,
));
}
}
KeyCode::C if modifiers.control => {
if let Some(editor_scene) = self.scene.as_mut() {
if let Selection::Graph(graph_selection) = &editor_scene.selection {
editor_scene.clipboard.fill_from_selection(
graph_selection,
editor_scene.scene,
engine,
);
}
} else if hot_key == key_bindings.copy_selection {
if let Some(editor_scene) = self.scene.as_mut() {
if let Selection::Graph(graph_selection) = &editor_scene.selection {
editor_scene.clipboard.fill_from_selection(
graph_selection,
editor_scene.scene,
engine,
);
}
}
KeyCode::V if modifiers.control => {
if let Some(editor_scene) = self.scene.as_mut() {
if !editor_scene.clipboard.is_empty() {
} else if hot_key == key_bindings.paste {
if let Some(editor_scene) = self.scene.as_mut() {
if !editor_scene.clipboard.is_empty() {
sender
.send(Message::do_scene_command(PasteCommand::new(
engine.scenes[editor_scene.scene].graph.get_root(),
)))
.unwrap();
}
}
} else if hot_key == key_bindings.new_scene {
sender.send(Message::NewScene).unwrap();
} else if hot_key == key_bindings.close_scene {
sender.send(Message::CloseScene).unwrap();
} else if hot_key == key_bindings.remove_selection {
if let Some(editor_scene) = self.scene.as_mut() {
if !editor_scene.selection.is_empty() {
if let Selection::Graph(_) = editor_scene.selection {
sender
.send(Message::do_scene_command(PasteCommand::new(
engine.scenes[editor_scene.scene].graph.get_root(),
.send(Message::DoSceneCommand(make_delete_selection_command(
editor_scene,
engine,
)))
.unwrap();
}
}
}
KeyCode::N if modifiers.control => {
sender.send(Message::NewScene).unwrap();
}
KeyCode::Q if modifiers.control => {
sender.send(Message::CloseScene).unwrap();
}
KeyCode::Delete => {
if let Some(editor_scene) = self.scene.as_mut() {
if !editor_scene.selection.is_empty() {
if let Selection::Graph(_) = editor_scene.selection {
sender
.send(Message::DoSceneCommand(make_delete_selection_command(
editor_scene,
engine,
)))
.unwrap();
}
}
}
}
_ => (),
}
}
}
+26 -8
View File
@@ -1,9 +1,10 @@
use crate::{
camera::PickingOptions, gui::make_dropdown_list_option,
gui::make_dropdown_list_option_with_height, load_image, utils::enable_widget, AddModelCommand,
AssetItem, AssetKind, BuildProfile, ChangeSelectionCommand, CommandGroup, DropdownListBuilder,
EditorScene, GameEngine, GraphSelection, InteractionMode, InteractionModeKind, Message, Mode,
SceneCommand, Selection, SetMeshTextureCommand, Settings,
gui::make_dropdown_list_option_with_height, load_image, settings::keys::KeyBindings,
utils::enable_widget, AddModelCommand, AssetItem, AssetKind, BuildProfile,
ChangeSelectionCommand, CommandGroup, DropdownListBuilder, EditorScene, GameEngine,
GraphSelection, InteractionMode, InteractionModeKind, Message, Mode, SceneCommand, Selection,
SetMeshTextureCommand, Settings,
};
use fyrox::{
core::{
@@ -555,12 +556,24 @@ impl SceneViewer {
self.on_mouse_move(pos, editor_scene, interaction_mode, engine, settings)
}
WidgetMessage::KeyUp(key) => {
if self.on_key_up(key, editor_scene, interaction_mode, engine) {
if self.on_key_up(
key,
editor_scene,
interaction_mode,
engine,
&settings.key_bindings,
) {
message.set_handled(true);
}
}
WidgetMessage::KeyDown(key) => {
if self.on_key_down(key, editor_scene, interaction_mode, engine) {
if self.on_key_down(
key,
editor_scene,
interaction_mode,
engine,
&settings.key_bindings,
) {
message.set_handled(true);
}
}
@@ -731,8 +744,9 @@ impl SceneViewer {
editor_scene: &mut EditorScene,
active_interaction_mode: Option<&mut Box<dyn InteractionMode>>,
engine: &mut Engine,
key_bindings: &KeyBindings,
) -> bool {
if editor_scene.camera_controller.on_key_up(key) {
if editor_scene.camera_controller.on_key_up(key_bindings, key) {
return true;
}
@@ -752,8 +766,12 @@ impl SceneViewer {
editor_scene: &mut EditorScene,
active_interaction_mode: Option<&mut Box<dyn InteractionMode>>,
engine: &mut Engine,
key_bindings: &KeyBindings,
) -> bool {
if editor_scene.camera_controller.on_key_down(key) {
if editor_scene
.camera_controller
.on_key_down(key_bindings, key)
{
return true;
}
+67
View File
@@ -0,0 +1,67 @@
use fyrox::{
core::reflect::prelude::*,
gui::{
key::{HotKey, KeyBinding},
message::KeyCode,
},
};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, PartialEq, Clone, Debug, Reflect)]
pub struct KeyBindings {
pub move_forward: KeyBinding,
pub move_back: KeyBinding,
pub move_left: KeyBinding,
pub move_right: KeyBinding,
pub move_up: KeyBinding,
pub move_down: KeyBinding,
pub speed_up: KeyBinding,
pub slow_down: KeyBinding,
pub undo: HotKey,
pub redo: HotKey,
pub enable_select_mode: HotKey,
pub enable_move_mode: HotKey,
pub enable_rotate_mode: HotKey,
pub enable_scale_mode: HotKey,
pub enable_navmesh_mode: HotKey,
pub enable_terrain_mode: HotKey,
pub save_scene: HotKey,
pub load_scene: HotKey,
pub copy_selection: HotKey,
pub paste: HotKey,
pub new_scene: HotKey,
pub close_scene: HotKey,
pub remove_selection: HotKey,
}
impl Default for KeyBindings {
fn default() -> Self {
Self {
move_forward: KeyBinding::from_key_code(KeyCode::W),
move_back: KeyBinding::from_key_code(KeyCode::S),
move_left: KeyBinding::from_key_code(KeyCode::A),
move_right: KeyBinding::from_key_code(KeyCode::D),
move_up: KeyBinding::from_key_code(KeyCode::Q),
move_down: KeyBinding::from_key_code(KeyCode::E),
speed_up: KeyBinding::from_key_code(KeyCode::LControl),
slow_down: KeyBinding::from_key_code(KeyCode::LShift),
undo: HotKey::ctrl_key(KeyCode::Z),
redo: HotKey::ctrl_key(KeyCode::Y),
enable_select_mode: HotKey::from_key_code(KeyCode::Key1),
enable_move_mode: HotKey::from_key_code(KeyCode::Key2),
enable_rotate_mode: HotKey::from_key_code(KeyCode::Key3),
enable_scale_mode: HotKey::from_key_code(KeyCode::Key4),
enable_navmesh_mode: HotKey::from_key_code(KeyCode::Key5),
enable_terrain_mode: HotKey::from_key_code(KeyCode::Key6),
save_scene: HotKey::ctrl_key(KeyCode::S),
load_scene: HotKey::ctrl_key(KeyCode::L),
copy_selection: HotKey::ctrl_key(KeyCode::C),
paste: HotKey::ctrl_key(KeyCode::V),
new_scene: HotKey::ctrl_key(KeyCode::N),
close_scene: HotKey::ctrl_key(KeyCode::Q),
remove_selection: HotKey::from_key_code(KeyCode::Delete),
}
}
}
+9 -3
View File
@@ -1,10 +1,10 @@
use crate::{
inspector::editors::make_property_editors_container,
settings::navmesh::NavmeshSettings,
settings::{
camera::CameraSettings, debugging::DebuggingSettings, graphics::GraphicsSettings,
model::ModelSettings, move_mode::MoveInteractionModeSettings, recent::RecentFiles,
rotate_mode::RotateInteractionModeSettings, selection::SelectionSettings,
keys::KeyBindings, model::ModelSettings, move_mode::MoveInteractionModeSettings,
navmesh::NavmeshSettings, recent::RecentFiles, rotate_mode::RotateInteractionModeSettings,
selection::SelectionSettings,
},
GameEngine, Message, MSG_SYNC_FLAG,
};
@@ -17,6 +17,7 @@ use fyrox::{
editors::{
enumeration::EnumPropertyEditorDefinition,
inspectable::InspectablePropertyEditorDefinition,
key::{HotKeyPropertyEditorDefinition, KeyBindingPropertyEditorDefinition},
PropertyEditorDefinitionContainer,
},
InspectorBuilder, InspectorContext, InspectorMessage, PropertyAction, PropertyChanged,
@@ -38,6 +39,7 @@ use std::{fs::File, path::PathBuf, rc::Rc, sync::mpsc::Sender};
pub mod camera;
pub mod debugging;
pub mod graphics;
pub mod keys;
pub mod model;
pub mod move_mode;
pub mod navmesh;
@@ -62,6 +64,7 @@ pub struct Settings {
pub model: ModelSettings,
pub camera: CameraSettings,
pub navmesh: NavmeshSettings,
pub key_bindings: KeyBindings,
#[reflect(hidden)]
pub recent: RecentFiles,
}
@@ -129,6 +132,9 @@ impl Settings {
>::new());
container.insert(InspectablePropertyEditorDefinition::<ModelSettings>::new());
container.insert(InspectablePropertyEditorDefinition::<NavmeshSettings>::new());
container.insert(InspectablePropertyEditorDefinition::<KeyBindings>::new());
container.insert(HotKeyPropertyEditorDefinition);
container.insert(KeyBindingPropertyEditorDefinition);
Rc::new(container)
}