Skip to content

Commit

Permalink
keybinds separate wheel up/down
Browse files Browse the repository at this point in the history
  • Loading branch information
malytomas committed Jan 29, 2025
1 parent 33b9e59 commit 353a741
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 29 deletions.
16 changes: 9 additions & 7 deletions sources/include/cage-engine/keybinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace cage
String name() const;
String value(uint32 index = 0) const;
bool process(const GenericInput &input) const;
void setActive(bool a);
void setActive(bool active, bool autoDeactivate = false);
bool active() const;

uint32 count() const;
Expand All @@ -36,7 +36,8 @@ namespace cage
None = 0,
Keyboard = 1 << 0,
Mouse = 1 << 1,
Wheel = 1 << 2,
WheelRoll = 1 << 2, // tracks wheel up and down as separate events (as if buttons)
WheelScroll = 1 << 3, // tracks wheel uniformly as one event
// todo controller
};
GCHL_ENUM_BITS(KeybindDevicesFlags);
Expand All @@ -50,9 +51,10 @@ namespace cage
MousePress = 1 << 3,
MouseDouble = 1 << 4,
MouseRelease = 1 << 5,
WheelScroll = 1 << 6,
GameTick = 1 << 7,
EngineTick = 1 << 8,
WheelRoll = 1 << 6,
WheelScroll = 1 << 7,
GameTick = 1 << 8,
EngineTick = 1 << 9,
};
GCHL_ENUM_BITS(KeybindModesFlags);
CAGE_ENGINE_API KeybindModesFlags keybindMode(const GenericInput &in);
Expand All @@ -65,8 +67,8 @@ namespace cage
ModifiersFlags requiredFlags = ModifiersFlags::None;
ModifiersFlags forbiddenFlags = ModifiersFlags::Super;
bool exactFlags = true;
KeybindDevicesFlags devices = KeybindDevicesFlags::Keyboard | KeybindDevicesFlags::Mouse; // which devices are allowed to bind
KeybindModesFlags modes = KeybindModesFlags::KeyPress | KeybindModesFlags::MousePress; // which modes trigger the event (contrary: activation is always with press and release)
KeybindDevicesFlags devices = KeybindDevicesFlags::Keyboard | KeybindDevicesFlags::Mouse | KeybindDevicesFlags::WheelRoll; // which devices are allowed to bind
KeybindModesFlags modes = KeybindModesFlags::KeyPress | KeybindModesFlags::MousePress | KeybindModesFlags::WheelRoll; // which modes trigger the event (contrary: activation is always with press and release)
};

CAGE_ENGINE_API Holder<Keybind> newKeybind(const KeybindCreateConfig &config, const GenericInput &defaults = {}, Delegate<bool(const GenericInput &)> event = {});
Expand Down
68 changes: 50 additions & 18 deletions sources/libengine/keybinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,36 @@ namespace cage

struct WheelMatcher : public MatcherBase
{
sint32 direction = 0;

CAGE_FORCE_INLINE KeybindModesFlags match(const GenericInput &input) const
{
if (input.has<input::MouseWheel>())
{
if (checkFlags(input.get<input::MouseWheel>().mods))
const input::MouseWheel w = input.get<input::MouseWheel>();
if (!checkFlags(w.mods))
return KeybindModesFlags::None;
if (direction == 0)
return KeybindModesFlags::WheelScroll;
if (direction > 0 && w.wheel > 0)
return KeybindModesFlags::WheelRoll;
if (direction < 0 && w.wheel < 0)
return KeybindModesFlags::WheelRoll;
}
return KeybindModesFlags::None;
}

CAGE_FORCE_INLINE String value() const { return finishName(Stringizer() + getModifiersNames(requiredFlags) + " WHEEL"); }
CAGE_FORCE_INLINE String value() const
{
String w;
if (direction > 0)
w = "WHUP";
else if (direction < 0)
w = "WHDN";
else
w = "WHEEL";
return finishName(Stringizer() + getModifiersNames(requiredFlags) + " " + w);
}
};

using Matcher = std::variant<std::monostate, KeyboardMatcher, MouseMatcher, WheelMatcher>;
Expand Down Expand Up @@ -153,11 +172,14 @@ namespace cage

CAGE_FORCE_INLINE void makeImpl(input::MouseWheel k)
{
if (none(config.devices & KeybindDevicesFlags::Wheel))
return;
if (any(k.mods & config.forbiddenFlags))
return;
result = WheelMatcher{ base(k.mods) };
if (any(config.devices & KeybindDevicesFlags::WheelScroll))
result = WheelMatcher{ base(k.mods), 0 };
if (any(config.devices & KeybindDevicesFlags::WheelRoll) && k.wheel > 0)
result = WheelMatcher{ base(k.mods), 1 };
if (any(config.devices & KeybindDevicesFlags::WheelRoll) && k.wheel < 0)
result = WheelMatcher{ base(k.mods), -1 };
}

template<class T>
Expand Down Expand Up @@ -205,6 +227,7 @@ namespace cage
CAGE_ASSERT(!findKeybind(config.id)); // must be unique
CAGE_ASSERT(none(config.requiredFlags & config.forbiddenFlags));
CAGE_ASSERT(any(config.devices));
CAGE_ASSERT(none(config.devices & KeybindDevicesFlags::WheelRoll) || none(config.devices & KeybindDevicesFlags::WheelScroll)); // these two flags are mutually exclusive
CAGE_ASSERT(any(config.modes));
reset(); // make matchers from the defaults
this->event = event;
Expand All @@ -225,26 +248,33 @@ namespace cage
active = false;
return false;
}
if (active)
if (input.has<input::GameTick>())
{
if (input.has<input::GameTick>() && any(config.modes & KeybindModesFlags::GameTick))
{
if (event)
event(input);
return false; // ticks always propagate
}
if (input.has<input::EngineTick>() && any(config.modes & KeybindModesFlags::EngineTick))
if (active && any(config.modes & KeybindModesFlags::GameTick) && event)
event(input);
return false; // ticks always propagate
}
if (input.has<input::EngineTick>())
{
if (active && any(config.modes & KeybindModesFlags::EngineTick) && event)
event(input);
if (autoDeactivate)
{
if (event)
event(input);
return false; // ticks always propagate
active = false;
autoDeactivate = false;
}
return false; // ticks always propagate
}
for (const auto &it : matchers)
{
const KeybindModesFlags r = matches(input, it);
if (any(r & (KeybindModesFlags::KeyPress | KeybindModesFlags::MousePress)))
active = true;
if (any(r & (KeybindModesFlags::WheelRoll | KeybindModesFlags::WheelScroll)))
{
active = true;
autoDeactivate = true;
}
if (any(r & (KeybindModesFlags::KeyRelease | KeybindModesFlags::MouseRelease)))
active = false;
if (any(r & config.modes))
Expand All @@ -267,6 +297,7 @@ namespace cage
std::vector<Matcher> matchers;
const uint32 textId = 0;
mutable bool active = false; // allows tick events
mutable bool autoDeactivate = false; // automatically deactivates after first engine tick

Entity *guiEnt = nullptr;
uint32 assigningIndex = m;
Expand Down Expand Up @@ -418,10 +449,11 @@ namespace cage
return impl->process(input);
}

void Keybind::setActive(bool a)
void Keybind::setActive(bool active, bool autoDeactivate)
{
KeybindImpl *impl = (KeybindImpl *)this;
impl->active = a;
impl->active = active;
impl->autoDeactivate = autoDeactivate;
}

bool Keybind::active() const
Expand Down
8 changes: 4 additions & 4 deletions sources/libsimple/gameloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,14 +353,14 @@ namespace cage
virtualReality->processEvents();
virtualRealitySceneUpdate(+entities);
}
{
ProfilingScope profiling("keybinds engine tick");
engineEvents().dispatch(input::EngineTick());
}
{
ProfilingScope profiling("control callback");
controlThread().update.dispatch();
}
{
ProfilingScope profiling("keybinds engine tick");
engineEvents().dispatch(input::EngineTick());
}
{
ProfilingScope profiling("sound emit");
soundEmit(controlTime);
Expand Down

0 comments on commit 353a741

Please sign in to comment.