@@ -14,7 +14,11 @@ namespace cage
1414{
1515 namespace
1616 {
17- std::vector<class KeybindImpl *> global;
17+ std::vector<class KeybindImpl *> &global ()
18+ {
19+ static std::vector<class KeybindImpl *> g;
20+ return g;
21+ }
1822
1923 CAGE_FORCE_INLINE String finishName (String s)
2024 {
@@ -40,7 +44,7 @@ namespace cage
4044
4145 CAGE_FORCE_INLINE KeybindModesFlags matchImpl (input::privat::BaseKey k, KeybindModesFlags activation) const
4246 {
43- if (k.key == key && checkFlags (k.mods ))
47+ if (k.key == key && ( checkFlags (k.mods ) || activation == KeybindModesFlags::Release ))
4448 return activation;
4549 return KeybindModesFlags::None;
4650 }
@@ -64,7 +68,7 @@ namespace cage
6468
6569 CAGE_FORCE_INLINE KeybindModesFlags matchImpl (input::privat::BaseMouse k, KeybindModesFlags activation) const
6670 {
67- if (any (k.buttons & button) && checkFlags (k.mods ))
71+ if (any (k.buttons & button) && ( checkFlags (k.mods ) || activation == KeybindModesFlags::Release ))
6872 return activation;
6973 return KeybindModesFlags::None;
7074 }
@@ -94,7 +98,7 @@ namespace cage
9498 return KeybindModesFlags::None;
9599 }
96100
97- CAGE_FORCE_INLINE String value () const { return finishName (Stringizer () + getModifiersNames (requiredFlags) + " Scroll " ); }
101+ CAGE_FORCE_INLINE String value () const { return finishName (Stringizer () + getModifiersNames (requiredFlags) + " WHEEL " ); }
98102 };
99103
100104 using Matcher = std::variant<std::monostate, KeyboardMatcher, MouseMatcher, WheelMatcher>;
@@ -201,14 +205,14 @@ namespace cage
201205 CAGE_ASSERT (any (config.modes ));
202206 reset (); // make matchers from the defaults
203207 this ->event = event;
204- global.push_back (this );
208+ global () .push_back (this );
205209 }
206210
207211 ~KeybindImpl ()
208212 {
209- auto it = std::find (global.begin (), global.end (), this );
210- if (it != global.end ())
211- global.erase (it);
213+ auto it = std::find (global () .begin (), global () .end (), this );
214+ if (it != global () .end ())
215+ global () .erase (it);
212216 }
213217
214218 bool process (const GenericInput &input) const
@@ -234,7 +238,11 @@ namespace cage
234238 if (any (r & config.modes ))
235239 {
236240 if (event)
237- return event (input);
241+ {
242+ const bool p = event (input);
243+ if (none (r & KeybindModesFlags::Release)) // release always propagates
244+ return p;
245+ }
238246 return false ;
239247 }
240248 }
@@ -285,7 +293,7 @@ namespace cage
285293
286294 void cancel ()
287295 {
288- assignmentListener.clear ();
296+ assignmentListener.unbind ();
289297 assigningIndex = m;
290298 makeGui ();
291299 }
@@ -380,7 +388,7 @@ namespace cage
380388 [](const auto &mt) -> String
381389 {
382390 if constexpr (std::is_same_v<std::decay_t <decltype (mt)>, std::monostate>)
383- return " ----- " ;
391+ return " " ;
384392 else
385393 return mt.value ();
386394 },
@@ -459,7 +467,7 @@ namespace cage
459467
460468 Keybind *findKeybind (const String &id)
461469 {
462- for (KeybindImpl *it : global)
470+ for (KeybindImpl *it : global () )
463471 {
464472 if (it->config .id == id)
465473 return it;
@@ -470,9 +478,9 @@ namespace cage
470478 void keybindsRegisterListeners (EventDispatcher<bool (const GenericInput &)> &dispatcher)
471479 {
472480 assignmentListener.attach (dispatcher, -328655984 );
473- for (KeybindImpl *it : global)
481+ for (KeybindImpl *it : global () )
474482 {
475- it->listener .clear ();
483+ it->listener .unbind ();
476484 it->listener .bind ([it](const GenericInput &in) { return it->process (in); });
477485 it->listener .attach (dispatcher, it->config .eventOrder );
478486 }
@@ -481,7 +489,7 @@ namespace cage
481489 void keybindsDispatchTick ()
482490 {
483491 GenericInput g = input::Tick ();
484- for (KeybindImpl *it : global)
492+ for (KeybindImpl *it : global () )
485493 it->process (g);
486494 }
487495
@@ -495,13 +503,19 @@ namespace cage
495503
496504 void keybindsGuiTable (GuiBuilder *g, const String &filterPrefix)
497505 {
498- std::sort (global.begin (), global.end (), [](const KeybindImpl *a, const KeybindImpl *b) -> bool { return std::pair{ a->config .displayOrder , a->config .id } < std::pair{ b->config .displayOrder , b->config .id }; });
506+ std::vector<KeybindImpl *> tmp;
507+ tmp.reserve (global ().size ());
508+ for (KeybindImpl *k : global ())
509+ {
510+ if (isPattern (k->config .id , filterPrefix, " " , " " ))
511+ tmp.push_back (k);
512+ }
513+ std::sort (tmp.begin (), tmp.end (), [](const KeybindImpl *a, const KeybindImpl *b) -> bool { return std::tuple{ a->config .displayOrder , textsGet (a->textId ), a->config .id } < std::tuple{ b->config .displayOrder , textsGet (b->textId ), b->config .id }; });
514+
499515 auto _ = g->verticalTable (2 );
500- for (KeybindImpl *k : global )
516+ for (KeybindImpl *k : tmp )
501517 {
502- if (!isPattern (k->config .id , filterPrefix, " " , " " ))
503- continue ;
504- g->label ().text (k->textId , k->config .id );
518+ g->label ().update ([k](Entity *e) { e->value <GuiTextFormatComponent>().color = k->active ? Vec3 (0.5 , 0.9 , 1 ) : Vec3::Nan (); }).text (k->textId , k->config .id );
505519 keybindsGuiWidget (g, k);
506520 }
507521 }
0 commit comments