Moved GameInput to own module and made use of strum's EnumIter and AsRefStr.

This commit is contained in:
schnippl0r 2021-07-21 13:23:45 +02:00
parent c31d123884
commit 9e3b2a20d0
17 changed files with 198 additions and 242 deletions

3
Cargo.lock generated
View File

@ -5304,6 +5304,9 @@ name = "strum"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"

View File

@ -110,7 +110,7 @@ rayon = "1.5"
rodio = {version = "0.14", default-features = false, features = ["vorbis"]}
ron = {version = "0.6", default-features = false}
serde = {version = "1.0", features = [ "rc", "derive" ]}
strum = "0.21"
strum = { version = "0.21", features = ["derive"] }
strum_macros = "0.21"
treeculler = "0.2"
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }

View File

@ -1,7 +1,7 @@
//! Module containing controller-specific abstractions allowing complex
//! keybindings
use crate::window::{GameInput, MenuInput};
use crate::{game_input::GameInput, window::MenuInput};
use gilrs::{ev::Code as GilCode, Axis as GilAxis, Button as GilButton};
use hashbrown::HashMap;
use serde::{Deserialize, Serialize};

172
voxygen/src/game_input.rs Normal file
View File

@ -0,0 +1,172 @@
use serde::{Deserialize, Serialize};
use std::convert::AsRef;
use strum::{AsRefStr, EnumIter};
/// Represents a key that the game recognises after input mapping.
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Deserialize,
Serialize,
AsRefStr,
EnumIter,
)]
pub enum GameInput {
#[strum(serialize = "gameinput.primary")]
Primary,
#[strum(serialize = "gameinput.secondary")]
Secondary,
#[strum(serialize = "gameinput.block")]
Block,
#[strum(serialize = "gameinput.slot1")]
Slot1,
#[strum(serialize = "gameinput.slot2")]
Slot2,
#[strum(serialize = "gameinput.slot3")]
Slot3,
#[strum(serialize = "gameinput.slot4")]
Slot4,
#[strum(serialize = "gameinput.slot5")]
Slot5,
#[strum(serialize = "gameinput.slot6")]
Slot6,
#[strum(serialize = "gameinput.slot7")]
Slot7,
#[strum(serialize = "gameinput.slot8")]
Slot8,
#[strum(serialize = "gameinput.slot9")]
Slot9,
#[strum(serialize = "gameinput.slot10")]
Slot10,
#[strum(serialize = "gameinput.togglecursor")]
ToggleCursor,
#[strum(serialize = "gameinput.moveforward")]
MoveForward,
#[strum(serialize = "gameinput.moveback")]
MoveBack,
#[strum(serialize = "gameinput.moveleft")]
MoveLeft,
#[strum(serialize = "gameinput.moveright")]
MoveRight,
#[strum(serialize = "gameinput.jump")]
Jump,
#[strum(serialize = "gameinput.sit")]
Sit,
#[strum(serialize = "gameinput.dance")]
Dance,
#[strum(serialize = "gameinput.greet")]
Greet,
#[strum(serialize = "gameinput.glide")]
Glide,
#[strum(serialize = "gameinput.climb")]
Climb,
#[strum(serialize = "gameinput.climbdown")]
ClimbDown,
#[strum(serialize = "gameinput.swimup")]
SwimUp,
#[strum(serialize = "gameinput.swimdown")]
SwimDown,
#[strum(serialize = "gameinput.fly")]
Fly,
#[strum(serialize = "gameinput.sneak")]
Sneak,
#[strum(serialize = "gameinput.togglelantern")]
ToggleLantern,
#[strum(serialize = "gameinput.mount")]
Mount,
#[strum(serialize = "gameinput.chat")]
Chat,
#[strum(serialize = "gameinput.command")]
Command,
#[strum(serialize = "gameinput.escape")]
Escape,
#[strum(serialize = "gameinput.map")]
Map,
#[strum(serialize = "gameinput.bag")]
Bag,
#[strum(serialize = "gameinput.trade")]
Trade,
#[strum(serialize = "gameinput.social")]
Social,
#[strum(serialize = "gameinput.crafting")]
Crafting,
#[strum(serialize = "gameinput.spellbook")]
Spellbook,
#[strum(serialize = "gameinput.settings")]
Settings,
#[strum(serialize = "gameinput.toggleinterface")]
ToggleInterface,
#[strum(serialize = "gameinput.help")]
Help,
#[strum(serialize = "gameinput.toggledebug")]
ToggleDebug,
#[strum(serialize = "gameinput.fullscreen")]
Fullscreen,
#[strum(serialize = "gameinput.screenshot")]
Screenshot,
#[strum(serialize = "gameinput.toggleingameui")]
ToggleIngameUi,
#[strum(serialize = "gameinput.roll")]
Roll,
#[strum(serialize = "gameinput.respawn")]
Respawn,
#[strum(serialize = "gameinput.interact")]
Interact,
#[strum(serialize = "gameinput.togglewield")]
ToggleWield,
#[strum(serialize = "gameinput.swaploadout")]
SwapLoadout,
#[strum(serialize = "gameinput.freelook")]
FreeLook,
#[strum(serialize = "gameinput.autowalk")]
AutoWalk,
#[strum(serialize = "gameinput.cameraclamp")]
CameraClamp,
#[strum(serialize = "gameinput.cyclecamera")]
CycleCamera,
#[strum(serialize = "gameinput.select")]
Select,
#[strum(serialize = "gameinput.acceptgroupinvite")]
AcceptGroupInvite,
#[strum(serialize = "gameinput.declinegroupinvite")]
DeclineGroupInvite,
#[strum(serialize = "gameinput.mapzoomin")]
MapZoomIn,
#[strum(serialize = "gameinput.mapzoomout")]
MapZoomOut,
}
impl GameInput {
pub fn get_localization_key(&self) -> &str { self.as_ref() }
/// Return true if `a` and `b` are able to be bound to the same key at the
/// same time without conflict. For example, the player can't jump and climb
/// at the same time, so these can be bound to the same key.
pub fn can_share_bindings(a: GameInput, b: GameInput) -> bool {
a.get_representative_binding() == b.get_representative_binding()
}
/// If two GameInputs are able to be bound at the same time, then they will
/// return the same value from this function (the representative value for
/// that set). This models the Find operation of a disjoint-set data
/// structure.
fn get_representative_binding(&self) -> GameInput {
match self {
GameInput::Jump => GameInput::Jump,
GameInput::Climb => GameInput::Jump,
GameInput::SwimUp => GameInput::Jump,
GameInput::Respawn => GameInput::Jump,
GameInput::FreeLook => GameInput::FreeLook,
GameInput::AutoWalk => GameInput::FreeLook,
_ => *self,
}
}
}

View File

@ -6,6 +6,7 @@ use super::{
Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
};
use crate::{
game_input::GameInput,
i18n::Localization,
ui::{
fonts::Fonts,
@ -13,7 +14,6 @@ use crate::{
ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, TooltipManager,
Tooltipable,
},
window::GameInput,
GlobalState,
};
use client::Client;

View File

@ -3,9 +3,10 @@ use super::{
BLACK, CRITICAL_HP_COLOR, LOW_HP_COLOR, QUALITY_LEGENDARY, TEXT_COLOR,
};
use crate::{
game_input::GameInput,
i18n::Localization,
ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
window::{GameInput, KeyMouse},
window::KeyMouse,
GlobalState,
};
use client::Client;

View File

@ -7,11 +7,11 @@ use super::{
};
use crate::{
game_input::GameInput,
hud,
i18n::Localization,
settings::Settings,
ui::{fonts::Fonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
window::GameInput,
GlobalState,
};
use client::{self, Client};

View File

@ -53,6 +53,7 @@ use trade::Trade;
use crate::{
ecs::{comp as vcomp, comp::HpFloaterList},
game_input::GameInput,
hud::{img_ids::ImgsRot, prompt_dialog::DialogOutcomeEvent},
i18n::Localization,
render::UiDrawer,
@ -66,7 +67,7 @@ use crate::{
self, fonts::Fonts, img_ids::Rotations, slot, slot::SlotKey, Graphic, Ingameable,
ScaleMode, Ui,
},
window::{Event as WinEvent, GameInput},
window::Event as WinEvent,
GlobalState,
};
use client::Client;

View File

@ -1,8 +1,8 @@
use crate::{
game_input::GameInput,
i18n::Localization,
settings::ControlSettings,
ui::{fonts::Fonts, Ingameable},
window::GameInput,
};
use conrod_core::{
color,

View File

@ -1,10 +1,10 @@
use super::{img_ids::Imgs, TEXT_COLOR, UI_HIGHLIGHT_0};
use crate::{
game_input::GameInput,
hud::{Event, PromptDialogSettings},
i18n::LocalizationHandle,
settings::Settings,
ui::fonts::Fonts,
window::GameInput,
};
use conrod_core::{
widget::{self, Button, Image, Text},

View File

@ -1,11 +1,11 @@
use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH};
use crate::{
game_input::GameInput,
hud::{img_ids::Imgs, ERROR_COLOR, TEXT_BIND_CONFLICT_COLOR, TEXT_COLOR},
i18n::Localization,
session::settings_change::{Control as ControlChange, Control::*},
ui::fonts::Fonts,
window::GameInput,
GlobalState,
};
use conrod_core::{
@ -14,6 +14,7 @@ use conrod_core::{
widget::{self, Button, Rectangle, Scrollbar, Text},
widget_ids, Borderable, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
};
use strum::IntoEnumIterator;
widget_ids! {
struct Ids {
@ -94,7 +95,7 @@ impl<'a> Widget for Controls<'a> {
// Used for sequential placement in a flow-down pattern
let mut previous_element_id = None;
let mut keybindings_vec: Vec<GameInput> = GameInput::iterator().collect();
let mut keybindings_vec: Vec<GameInput> = GameInput::iter().collect();
keybindings_vec.sort();
let controls = &self.global_state.settings.controls;

View File

@ -6,6 +6,7 @@ use super::{
QUALITY_EPIC, STAMINA_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0,
};
use crate::{
game_input::GameInput,
hud::ComboFloater,
i18n::Localization,
ui::{
@ -14,7 +15,6 @@ use crate::{
ImageFrame, ItemTooltip, ItemTooltipManager, ItemTooltipable, Tooltip, TooltipManager,
Tooltipable,
},
window::GameInput,
GlobalState,
};

View File

@ -18,6 +18,7 @@ pub mod audio;
pub mod controller;
mod ecs;
pub mod error;
pub mod game_input;
pub mod hud;
pub mod key_state;
pub mod menu;

View File

@ -35,13 +35,14 @@ use common_net::{
use crate::{
audio::sfx::SfxEvent,
game_input::GameInput,
hud::{DebugInfo, Event as HudEvent, Hud, HudInfo, LootMessage, PromptDialogSettings},
key_state::KeyState,
menu::char_selection::CharSelectionState,
render::{Drawer, GlobalsBindGroup},
scene::{camera, terrain::Interaction, CameraMode, DebugShapeId, Scene, SceneData},
settings::Settings,
window::{AnalogGameInput, Event, GameInput},
window::{AnalogGameInput, Event},
Direction, Error, GlobalState, PlayState, PlayStateResult,
};
use hashbrown::HashMap;

View File

@ -1,6 +1,7 @@
use super::SessionState;
use crate::{
controller::ControllerSettings,
game_input::GameInput,
hud::{
BarNumbers, BuffPosition, ChatTab, CrosshairType, Intro, PressBehavior, ScaleChange,
ShortcutNumbers, XpBar,
@ -11,7 +12,7 @@ use crate::{
AudioSettings, ChatSettings, ControlSettings, Fps, GamepadSettings, GameplaySettings,
GraphicsSettings, InterfaceSettings,
},
window::{FullScreenSettings, GameInput},
window::FullScreenSettings,
GlobalState,
};
use vek::*;

View File

@ -1,6 +1,7 @@
use crate::window::{GameInput, KeyMouse};
use crate::{game_input::GameInput, window::KeyMouse};
use hashbrown::{HashMap, HashSet};
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
use winit::event::{MouseButton, VirtualKeyCode};
// ControlSetting-like struct used by Serde, to handle not serializing/building
@ -181,7 +182,7 @@ impl Default for ControlSettings {
inverse_keybindings: HashMap::new(),
};
// Sets the initial keybindings for those GameInputs.
for game_input in GameInput::iterator() {
for game_input in GameInput::iter() {
new_settings.insert_binding(game_input, ControlSettings::default_binding(game_input));
}
new_settings

View File

@ -1,5 +1,6 @@
use crate::{
controller::*,
game_input::GameInput,
render::Renderer,
settings::{ControlSettings, Settings},
ui, Error,
@ -15,233 +16,6 @@ use tracing::{error, warn};
use vek::*;
use winit::monitor::VideoMode;
/// Represents a key that the game recognises after input mapping.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub enum GameInput {
Primary,
Secondary,
Block,
Slot1,
Slot2,
Slot3,
Slot4,
Slot5,
Slot6,
Slot7,
Slot8,
Slot9,
Slot10,
ToggleCursor,
MoveForward,
MoveBack,
MoveLeft,
MoveRight,
Jump,
Sit,
Dance,
Greet,
Glide,
Climb,
ClimbDown,
SwimUp,
SwimDown,
Fly,
Sneak,
ToggleLantern,
Mount,
Chat,
Command,
Escape,
Map,
Bag,
Trade,
Social,
Crafting,
Spellbook,
Settings,
ToggleInterface,
Help,
ToggleDebug,
Fullscreen,
Screenshot,
ToggleIngameUi,
Roll,
Respawn,
Interact,
ToggleWield,
SwapLoadout,
FreeLook,
AutoWalk,
CameraClamp,
CycleCamera,
Select,
AcceptGroupInvite,
DeclineGroupInvite,
MapZoomIn,
MapZoomOut,
}
impl GameInput {
pub fn get_localization_key(&self) -> &str {
match *self {
GameInput::Primary => "gameinput.primary",
GameInput::Secondary => "gameinput.secondary",
GameInput::Block => "gameinput.block",
GameInput::ToggleCursor => "gameinput.togglecursor",
GameInput::MoveForward => "gameinput.moveforward",
GameInput::MoveLeft => "gameinput.moveleft",
GameInput::MoveRight => "gameinput.moveright",
GameInput::MoveBack => "gameinput.moveback",
GameInput::Jump => "gameinput.jump",
GameInput::Sit => "gameinput.sit",
GameInput::Dance => "gameinput.dance",
GameInput::Greet => "gameinput.greet",
GameInput::Glide => "gameinput.glide",
GameInput::Climb => "gameinput.climb",
GameInput::ClimbDown => "gameinput.climbdown",
GameInput::SwimUp => "gameinput.swimup",
GameInput::SwimDown => "gameinput.swimdown",
GameInput::Fly => "gameinput.fly",
GameInput::Sneak => "gameinput.sneak",
GameInput::ToggleLantern => "gameinput.togglelantern",
GameInput::Mount => "gameinput.mount",
GameInput::Chat => "gameinput.chat",
GameInput::Command => "gameinput.command",
GameInput::CycleCamera => "gameinput.cyclecamera",
GameInput::Escape => "gameinput.escape",
GameInput::Map => "gameinput.map",
GameInput::Bag => "gameinput.bag",
GameInput::Trade => "gameinput.trade",
GameInput::Social => "gameinput.social",
GameInput::Crafting => "gameinput.crafting",
GameInput::Spellbook => "gameinput.spellbook",
GameInput::Settings => "gameinput.settings",
GameInput::ToggleInterface => "gameinput.toggleinterface",
GameInput::Help => "gameinput.help",
GameInput::ToggleDebug => "gameinput.toggledebug",
GameInput::Fullscreen => "gameinput.fullscreen",
GameInput::Screenshot => "gameinput.screenshot",
GameInput::ToggleIngameUi => "gameinput.toggleingameui",
GameInput::Roll => "gameinput.roll",
GameInput::Respawn => "gameinput.respawn",
GameInput::Interact => "gameinput.interact",
GameInput::ToggleWield => "gameinput.togglewield",
GameInput::FreeLook => "gameinput.freelook",
GameInput::AutoWalk => "gameinput.autowalk",
GameInput::CameraClamp => "gameinput.cameraclamp",
GameInput::Slot1 => "gameinput.slot1",
GameInput::Slot2 => "gameinput.slot2",
GameInput::Slot3 => "gameinput.slot3",
GameInput::Slot4 => "gameinput.slot4",
GameInput::Slot5 => "gameinput.slot5",
GameInput::Slot6 => "gameinput.slot6",
GameInput::Slot7 => "gameinput.slot7",
GameInput::Slot8 => "gameinput.slot8",
GameInput::Slot9 => "gameinput.slot9",
GameInput::Slot10 => "gameinput.slot10",
GameInput::SwapLoadout => "gameinput.swaploadout",
GameInput::Select => "gameinput.select",
GameInput::AcceptGroupInvite => "gameinput.acceptgroupinvite",
GameInput::DeclineGroupInvite => "gameinput.declinegroupinvite",
GameInput::MapZoomIn => "gameinput.mapzoomin",
GameInput::MapZoomOut => "gameinput.mapzoomout",
}
}
pub fn iterator() -> impl Iterator<Item = GameInput> {
[
GameInput::Primary,
GameInput::Secondary,
GameInput::Block,
GameInput::ToggleCursor,
GameInput::MoveForward,
GameInput::MoveLeft,
GameInput::MoveRight,
GameInput::MoveBack,
GameInput::Jump,
GameInput::Sit,
GameInput::Dance,
GameInput::Greet,
GameInput::Glide,
GameInput::Climb,
GameInput::ClimbDown,
GameInput::SwimUp,
GameInput::SwimDown,
GameInput::Fly,
GameInput::Sneak,
GameInput::ToggleLantern,
GameInput::Mount,
GameInput::Chat,
GameInput::Command,
GameInput::Escape,
GameInput::Map,
GameInput::Bag,
GameInput::Trade,
GameInput::Social,
GameInput::Crafting,
GameInput::Spellbook,
GameInput::Settings,
GameInput::ToggleInterface,
GameInput::Help,
GameInput::ToggleDebug,
GameInput::Fullscreen,
GameInput::Screenshot,
GameInput::ToggleIngameUi,
GameInput::Roll,
GameInput::Respawn,
GameInput::Interact,
GameInput::ToggleWield,
GameInput::FreeLook,
GameInput::AutoWalk,
GameInput::CameraClamp,
GameInput::Slot1,
GameInput::Slot2,
GameInput::Slot3,
GameInput::Slot4,
GameInput::Slot5,
GameInput::Slot6,
GameInput::Slot7,
GameInput::Slot8,
GameInput::Slot9,
GameInput::Slot10,
GameInput::SwapLoadout,
GameInput::CycleCamera,
GameInput::Select,
GameInput::AcceptGroupInvite,
GameInput::DeclineGroupInvite,
GameInput::MapZoomIn,
GameInput::MapZoomOut,
]
.iter()
.copied()
}
/// Return true if `a` and `b` are able to be bound to the same key at the
/// same time without conflict. For example, the player can't jump and climb
/// at the same time, so these can be bound to the same key.
pub fn can_share_bindings(a: GameInput, b: GameInput) -> bool {
a.get_representative_binding() == b.get_representative_binding()
}
/// If two GameInputs are able to be bound at the same time, then they will
/// return the same value from this function (the representative value for
/// that set). This models the Find operation of a disjoint-set data
/// structure.
fn get_representative_binding(&self) -> GameInput {
match self {
GameInput::Jump => GameInput::Jump,
GameInput::Climb => GameInput::Jump,
GameInput::SwimUp => GameInput::Jump,
GameInput::Respawn => GameInput::Jump,
GameInput::FreeLook => GameInput::FreeLook,
GameInput::AutoWalk => GameInput::FreeLook,
_ => *self,
}
}
}
/// Represents a key that the game menus recognise after input mapping
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub enum MenuInput {