Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ModularButtonComponent.c
Go to the documentation of this file.
1//#define DEBUG_MODULAR_BUTTON
7{
8 STATE_DEFAULT = 1 << 0,
9 STATE_HOVERED = 1 << 1,
10 STATE_ACTIVATED = 1 << 2,
12 STATE_DISABLED = 1 << 4,
14}
15
17enum EModularButtonEventHandler
18{
19 CLICK = 1 << 0,
20 DOUBLE_CLICK = 1 << 1,
21 FOCUS_GAINED = 1 << 2,
22 FOCUS_LOST = 1 << 3,
23 MOUSE_ENTER = 1 << 4,
24 MOUSE_LEAVE = 1 << 5,
25}
26
27//---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
28// Completely separate hierarchy from other buttons and ui components
29
32class SCR_ModularButtonComponent : ScriptedWidgetComponent
33{
34
35//---- REFACTOR NOTE END ----
36
37 // ---- Public and attributes ----
38
39 // Attributes - effects
40
41 [Attribute()]
42 protected ref array<ref SCR_ButtonEffectBase> m_aEffects;
43
44 // Attributes - other properties
45
46 [Attribute("false", UIWidgets.CheckBox, "Can the button be only clicked, or also toggled?")]
47 protected bool m_bCanBeToggled;
48
49 [Attribute("false", UIWidgets.CheckBox, "If the button can be toggled, toggle it automatically on click or only through external API?")]
51
52 [Attribute("false")]
53 protected bool m_bToggledAtStart;
54
55 [Attribute("2147483647", UIWidgets.Flags, "Value which will be returned from event handlers. Useful in button-over-button cases: tiles with buttons inside or similar.", "", ParamEnumArray.FromEnum(EModularButtonEventHandler))]
56 protected EModularButtonEventHandler m_eEventReturnValue;
57
58 [Attribute("false", UIWidgets.CheckBox, "The button will be focused on mouse enter events")]
59 protected bool m_bFocusOnMouseEnter;
60
61 [Attribute("false", UIWidgets.CheckBox, "Mouse over, focus, clicks, etc, will be completely ignored. Useful to create a button driven by SlaveButton effect.")]
63
64//---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
65// Old untyped invokers
66
67 // Script invokers
68
69 ref ScriptInvoker m_OnClicked = new ScriptInvoker(); // (SCR_ModularButtonComponent comp)
70 ref ScriptInvoker m_OnDoubleClicked = new ScriptInvoker(); // (SCR_ModularButtonComponent comp)
71 ref ScriptInvoker m_OnToggled = new ScriptInvoker(); // (SCR_ModularButtonComponent comp, bool newToggled)
72 ref ScriptInvoker m_OnFocus = new ScriptInvoker(); // (SCR_ModularButtonComponent comp)
73 ref ScriptInvoker m_OnFocusLost = new ScriptInvoker(); // (SCR_ModularButtonComponent comp)
74 ref ScriptInvoker m_OnMouseEnter = new ScriptInvoker(); // (SCR_ModularButtonComponent comp, bool mouseInput) - mouseEvent - when true, last input was from a mouse, not keyboard/gamepad.
75 ref ScriptInvoker m_OnMouseLeave = new ScriptInvoker(); // (SCR_ModularButtonComponent comp, bool mouseInput)
76
77//---- REFACTOR NOTE END ----
78
79 // ---- Protected ----
80
81 // Widgets
82 protected Widget m_wRoot;
83
84 // Internal state
85 protected bool m_bFocus;
86 protected bool m_bMouseOver;
87 protected bool m_bToggled;
89
90 // Other
91 protected ref Managed m_UserData; // User data - can be accessed with SetData, GetData
92
93 // ------------------------------- Public -----------------------------------
94
95 //------------------------------------------------------------------------------------------------
99 static SCR_ModularButtonComponent FindComponent(Widget w)
100 {
101 return SCR_ModularButtonComponent.Cast(w.FindHandler(SCR_ModularButtonComponent));
102 }
103
104 //------------------------------------------------------------------------------------------------
106 void SetEnabled(bool enabled)
107 {
108 #ifdef DEBUG_MODULAR_BUTTON
109 _print(string.Format("SetEnabled: %1", enabled));
110 #endif
111
112 m_wRoot.SetEnabled(enabled);
114 }
115
116 //------------------------------------------------------------------------------------------------
119 {
120 return m_wRoot.IsEnabled();
121 }
122
123 //------------------------------------------------------------------------------------------------
126 void SetToggled(bool toggled, bool invokeOnToggled = true, bool instant = false)
127 {
128 #ifdef DEBUG_MODULAR_BUTTON
129 _print(string.Format("SetToggled: %1", toggled));
130 #endif
131
132 if (!m_bCanBeToggled)
133 return;
134
135 Internal_SetToggled(toggled, invokeOnToggled, instant);
136 }
137
138 //------------------------------------------------------------------------------------------------
141 {
142 return m_bToggled;
143 }
144
145 //------------------------------------------------------------------------------------------------
148 {
149 return m_bFocus;
150 }
151
152 //------------------------------------------------------------------------------------------------
155 {
156 return m_bMouseOver;
157 }
158
159 //------------------------------------------------------------------------------------------------
161 void SetToggleable(bool toggleable)
162 {
163 m_bCanBeToggled = toggleable;
164 }
165
166 //------------------------------------------------------------------------------------------------
168 void SetTogglableOnlyThroughApi(bool newValue)
169 {
170 m_bToggledOnlyThroughApi = newValue;
171 }
172
173 //------------------------------------------------------------------------------------------------
175 void SetData(Managed data)
176 {
178 }
179
180 //------------------------------------------------------------------------------------------------
182 Managed GetData()
183 {
184 return m_UserData;
185 }
186
187 //------------------------------------------------------------------------------------------------
190 {
191 return m_wRoot;
192 }
193
194 //------------------------------------------------------------------------------------------------
197 bool SetVisible(bool visible)
198 {
199 if (!m_wRoot)
200 return false;
201
202 m_wRoot.SetVisible(visible);
203
204 return true;
205 }
206
207 //------------------------------------------------------------------------------------------------
211 SCR_ButtonEffectBase FindEffect(string tag)
212 {
213 foreach (SCR_ButtonEffectBase e : m_aEffects)
214 {
215 if (e.m_aTags.Contains(tag))
216 return e;
217 }
218
219 return null;
220 }
221
222 //------------------------------------------------------------------------------------------------
225 array<SCR_ButtonEffectBase> FindAllEffects(string tag)
226 {
227 array<SCR_ButtonEffectBase> effects = {};
228 foreach (SCR_ButtonEffectBase e : m_aEffects)
229 {
230 if (e.m_aTags.Contains(tag))
231 effects.Insert(e);
232 }
233
234 return effects;
235 }
236
237 //------------------------------------------------------------------------------------------------
239 array<SCR_ButtonEffectBase> GetAllEffects()
240 {
241 array<SCR_ButtonEffectBase> effects = {};
242 foreach (SCR_ButtonEffectBase e : m_aEffects)
243 {
244 effects.Insert(e);
245 }
246
247 return effects;
248 }
249
250 //------------------------------------------------------------------------------------------------
254 void SetEffectsEnabled(string tag, bool enable)
255 {
256 #ifdef DEBUG_MODULAR_BUTTON
257 _print(string.Format("SetEffectsEnabled: %1, %2", tag, enable));
258 #endif
259
260 foreach (SCR_ButtonEffectBase e : m_aEffects)
261 {
262 if (e.m_aTags.Contains(tag))
263 e.SetEnabled(enable);
264 }
265 }
266
267 //------------------------------------------------------------------------------------------------
270 void SetEffectsWithAnyTagEnabled(notnull array<string> tags)
271 {
272 foreach (SCR_ButtonEffectBase e : m_aEffects)
273 {
274 bool found = false;
275 foreach (string tag : tags)
276 {
277 if (e.m_aTags.Contains(tag))
278 {
279 found = true;
280 break;
281 }
282 }
283
284 e.SetEnabled(found);
285 }
286 }
287
288 //------------------------------------------------------------------------------------------------
291 void SetAllEffectsEnabled(bool enable)
292 {
293 #ifdef DEBUG_MODULAR_BUTTON
294 _print(string.Format("SetAllEffectsEnabled: %1", enable));
295 #endif
296
297 foreach (SCR_ButtonEffectBase e : m_aEffects)
298 {
299 e.SetEnabled(enable);
300 }
301 }
302
303 //------------------------------------------------------------------------------------------------
308 void InvokeAllEnabledEffects(bool instant)
309 {
311 InvokeEffectsEvent(state, instant);
312
313 if (m_bCanBeToggled)
314 {
315 if (m_bToggled)
316 InvokeEffectsEvent(EModularButtonEventFlag.EVENT_TOGGLED_ON, instant);
317 else
318 InvokeEffectsEvent(EModularButtonEventFlag.EVENT_TOGGLED_OFF, instant);
319 }
320
321 if (m_bFocus)
322 InvokeEffectsEvent(EModularButtonEventFlag.EVENT_FOCUS_GAINED, instant);
323 else
324 InvokeEffectsEvent(EModularButtonEventFlag.EVENT_FOCUS_LOST, instant);
325 }
326
327 // ------------------------ Protected -------------------------------------
328
329 //------------------------------------------------------------------------------------------------
331 protected void UpdateCurrentState()
332 {
334 EModularButtonState oldState = m_eState;
335 m_eState = newState;
336
337 #ifdef DEBUG_MODULAR_BUTTON
338 _print(string.Format("UpdateCurrentState: old: %1, new: %2", typename.EnumToString(EModularButtonState, oldState), typename.EnumToString(EModularButtonState, newState)));
339 #endif
340
341 if (newState != oldState)
342 InvokeEffectsEvent(newState);
343 }
344
345 //------------------------------------------------------------------------------------------------
348 {
349 if (m_wRoot.IsEnabled())
350 {
351 // Enabled
352
353 if (m_bCanBeToggled)
354 {
355 if (m_bToggled)
356 {
357 if (m_bMouseOver)
358 return EModularButtonState.STATE_ACTIVATED_HOVERED;
359 else
360 return EModularButtonState.STATE_ACTIVATED;
361 }
362 else
363 {
364 if (m_bMouseOver)
365 return EModularButtonState.STATE_HOVERED;
366 else
367 return EModularButtonState.STATE_DEFAULT;
368 }
369 }
370 else
371 {
372 // Non toggleable
373 if (m_bMouseOver)
374 return EModularButtonState.STATE_HOVERED;
375 else
376 return EModularButtonState.STATE_DEFAULT;
377 }
378 }
379 else
380 {
381 // Disabled
382
383 if (m_bCanBeToggled)
384 {
385 if (m_bToggled)
386 return EModularButtonState.STATE_DISABLED_ACTIVATED;
387 else
388 return EModularButtonState.STATE_DISABLED;
389 }
390 else
391 return EModularButtonState.STATE_DISABLED;
392 }
393
394 return EModularButtonState.STATE_DEFAULT;
395 }
396
397 //------------------------------------------------------------------------------------------------
401 protected void InvokeEffectsEvent(EModularButtonEventFlag eventFlag, bool instant = false)
402 {
403 EInputDeviceType deviceType = GetGame().GetInputManager().GetLastUsedInputDevice();
404
405 #ifdef DEBUG_MODULAR_BUTTON
406 _print(string.Format("InvokeEffectsEvent: %1, %2", typename.EnumToString(EModularButtonEventFlag, eventFlag), typename.EnumToString(EInputDeviceType, deviceType)));
407 #endif
408
409 foreach (SCR_ButtonEffectBase effect : m_aEffects)
410 {
411 if (effect.GetEnabled())
412 effect.Internal_OnEvent(eventFlag, deviceType, instant);
413 }
414 }
415
416 //------------------------------------------------------------------------------------------------
422 {
423 InvokeEffectsEvent(eventFlag, instant);
424 }
425
426 //------------------------------------------------------------------------------------------------
427 protected void Internal_SetToggled(bool newToggled, bool invokeOnToggled = true, bool instant = false)
428 {
429 bool oldToggled = m_bToggled;
430 m_bToggled = newToggled;
431
432 if (newToggled != oldToggled)
433 {
434 if (newToggled)
435 InvokeEffectsEvent(EModularButtonEventFlag.EVENT_TOGGLED_ON, instant);
436 else
437 InvokeEffectsEvent(EModularButtonEventFlag.EVENT_TOGGLED_OFF, instant);
438 }
439
441
442 if (invokeOnToggled && newToggled != oldToggled)
443 m_OnToggled.Invoke(this, newToggled);
444 }
445
446 //------------------------------------------------------------------------------------------------
449 void Internal_OnEffectEnabled(SCR_ButtonEffectBase effect)
450 {
452 EInputDeviceType deviceType = GetGame().GetInputManager().GetLastUsedInputDevice();
453 effect.Internal_OnEvent(state, deviceType, true);
454
455 if (m_bCanBeToggled)
456 {
457 if (m_bToggled)
458 effect.Internal_OnEvent(EModularButtonEventFlag.EVENT_TOGGLED_ON, deviceType, true);
459 else
460 effect.Internal_OnEvent(EModularButtonEventFlag.EVENT_TOGGLED_OFF, deviceType, true);
461 }
462
463 if (m_bFocus)
464 effect.Internal_OnEvent(EModularButtonEventFlag.EVENT_FOCUS_GAINED, deviceType, true);
465 else
466 effect.Internal_OnEvent(EModularButtonEventFlag.EVENT_FOCUS_LOST, deviceType, true);
467 }
468
469 // --------- Event Handlers ------------
470
471 //------------------------------------------------------------------------------------------------
472 override void HandlerAttached(Widget w)
473 {
474 m_wRoot = w;
475
476 // Initialize effects
477 foreach (SCR_ButtonEffectBase effect : m_aEffects)
478 {
479 effect.Init(this);
480 effect.OnHandlerAttached(w);
481 }
482
484
485 m_bFocus = GetGame().GetWorkspace().GetFocusedWidget() == m_wRoot;
486
487 // Iterate all effects, make sure that there are no effects which are affecting same widget,
488 // have same type and receive same event types
489 array<ref Tuple3<Widget, typename, int>> widgetEffectEventMasks = {};
490 foreach (SCR_ButtonEffectBase effect : m_aEffects)
491 {
492 SCR_ButtonEffectWidgetBase widgetEffect = SCR_ButtonEffectWidgetBase.Cast(effect);
493 if (effect.GetEnabled() && widgetEffect)
494 {
495 // Find entry with this widget, effect type, and event mask which intersects with event mask of this effect
496 bool disabled = false;
497 foreach (Tuple3<Widget, typename, int> i : widgetEffectEventMasks)
498 {
499 if (i.param1 == widgetEffect.GetTargetWidget() &&
500 i.param2 == widgetEffect.Type() &&
501 (i.param3 & widgetEffect.m_eEvents))
502 {
503 disabled = true;
504 widgetEffect.SetEnabled(false);
505 break;
506 }
507 }
508
509 // If this effect is enabled, record what events it listens to.
510 if (!disabled)
511 {
512 // Find entry with this widget and effect type
514 foreach (Tuple3<Widget, typename, int> i : widgetEffectEventMasks)
515 {
516 if (i.param1 == widgetEffect.GetTargetWidget() &&
517 i.param2 == widgetEffect.Type())
518 {
519 entry = i;
520 break;
521 }
522 }
523
524 if (!entry)
525 {
526 entry = new Tuple3<Widget, typename, int>(widgetEffect.GetTargetWidget(), widgetEffect.Type(), 0);
527 widgetEffectEventMasks.Insert(entry);
528 }
529
530 entry.param3 = entry.param3 | widgetEffect.m_eEvents;
531 }
532 }
533 }
534
535 // Invoke effects at start
536 InvokeAllEnabledEffects(instant : true);
537 }
538
539 //------------------------------------------------------------------------------------------------
540 override bool OnClick(Widget w, int x, int y, int button)
541 {
542 #ifdef DEBUG_MODULAR_BUTTON
543 _print("OnClick");
544 #endif
545
546 // Auto focus is focusable
547 if (m_wRoot.IsFocusable())
548 {
549 WorkspaceWidget workspace = GetGame().GetWorkspace();
550 Widget currentFocus = workspace.GetFocusedWidget();
551 if (currentFocus != m_wRoot)
552 workspace.SetFocusedWidget(m_wRoot);
553 }
554
555 bool eventReturnValue = m_eEventReturnValue & EModularButtonEventHandler.CLICK;
556
558 return eventReturnValue;
559
562
564
566 InvokeEffectsEvent(state);
567
568 m_OnClicked.Invoke(this);
569
570 return eventReturnValue;
571 }
572
573 //------------------------------------------------------------------------------------------------
574 override bool OnDoubleClick(Widget w, int x, int y, int button)
575 {
577 return m_eEventReturnValue & EModularButtonEventHandler.DOUBLE_CLICK;
578
579 m_OnDoubleClicked.Invoke(this);
580 return m_eEventReturnValue & EModularButtonEventHandler.DOUBLE_CLICK;
581 }
582
583 //------------------------------------------------------------------------------------------------
584 override bool OnMouseEnter(Widget w, int x, int y)
585 {
586 #ifdef DEBUG_MODULAR_BUTTON
587 _print("OnMouseEnter");
588 #endif
589
591 return m_eEventReturnValue & EModularButtonEventHandler.MOUSE_ENTER;
592
593 m_bMouseOver = true;
594
596
597 EInputDeviceType lastInput = GetGame().GetInputManager().GetLastUsedInputDevice();
598 bool mouseInput = lastInput == EInputDeviceType.MOUSE;
599
601 {
602 if (mouseInput)
603 GetGame().GetWorkspace().SetFocusedWidget(m_wRoot);
604 }
605
607
608 m_OnMouseEnter.Invoke(this, mouseInput);
609
610 return m_eEventReturnValue & EModularButtonEventHandler.MOUSE_ENTER;
611 }
612
613 //------------------------------------------------------------------------------------------------
614 override bool OnMouseLeave(Widget w, Widget enterW, int x, int y)
615 {
616 #ifdef DEBUG_MODULAR_BUTTON
617 _print("OnMouseLeave");
618 #endif
619
621 return m_eEventReturnValue & EModularButtonEventHandler.MOUSE_LEAVE;
622
623 m_bMouseOver = false;
624
626
627 EInputDeviceType lastInput = GetGame().GetInputManager().GetLastUsedInputDevice();
628 bool mouseInput = lastInput == EInputDeviceType.MOUSE;
629
631
632 m_OnMouseLeave.Invoke(this, mouseInput);
633
634 return m_eEventReturnValue & EModularButtonEventHandler.MOUSE_LEAVE;
635 }
636
637 //------------------------------------------------------------------------------------------------
638 override bool OnFocus(Widget w, int x, int y)
639 {
640 #ifdef DEBUG_MODULAR_BUTTON
641 _print("%1 OnFocus");
642 #endif
643
645 return m_eEventReturnValue & EModularButtonEventHandler.FOCUS_GAINED;
646
647 m_bFocus = true;
648
649 m_OnFocus.Invoke(this);
650
652
653 return m_eEventReturnValue & EModularButtonEventHandler.FOCUS_GAINED;
654 }
655
656 //------------------------------------------------------------------------------------------------
657 override bool OnFocusLost(Widget w, int x, int y)
658 {
659 #ifdef DEBUG_MODULAR_BUTTON
660 _print("%1 OnFocusLost");
661 #endif
662
664 return m_eEventReturnValue & EModularButtonEventHandler.FOCUS_LOST;
665
666 m_bFocus = false;
667
668 m_OnFocusLost.Invoke(this);
669
671
672 return m_eEventReturnValue & EModularButtonEventHandler.FOCUS_LOST;
673 }
674
675 //------------------------------------------------------------------------------------------------
678 void _print(string s)
679 {
680 Print(string.Format("[SCR_ModularButtonComponent] %1: %2", GetRootWidget().GetName(), s), LogLevel.NORMAL);
681 }
682
683 //------------------------------------------------------------------------------------------------
686 {
688 }
689
690 //------------------------------------------------------------------------------------------------
692 void SetIsFocusOnMouseEnter(bool focus)
693 {
694 m_bFocusOnMouseEnter = focus;
695 }
696
697 //------------------------------------------------------------------------------------------------
700 {
701 return typename.EnumToString(EModularButtonState, m_eState);
702 }
703
704 //------------------------------------------------------------------------------------------------
705 void IgnoreStandardInputs(bool ignore)
706 {
708 }
709}
ref array< string > tags
ArmaReforgerScripted GetGame()
Definition game.c:1398
EAITargetClusterState m_eState
override string GetData()
EModularButtonEventFlag
override void OnFocusLost(bool instant)
override bool OnMouseLeave(Widget w, Widget enterW, int x, int y)
ref array< ref SCR_BaseEntitiesEditorUIEffect > m_aEffects
override bool OnMouseEnter(Widget w, int x, int y)
override bool OnFocus(Widget w, int x, int y)
Get all prefabs that have the spawner data
Widget m_wRoot
void OnClick()
On click callback.
ref ScriptInvoker m_OnFocusLost
bool GetMouseOver()
ref ScriptInvoker m_OnMouseLeave
STATE_DEFAULT
Default state.
bool m_bFocusOnMouseEnter
STATE_DISABLED
Disabled.
enum EModularButtonState MOUSE_ENTER
bool m_bToggledOnlyThroughApi
void SetEffectsWithAnyTagEnabled(notnull array< string > tags)
void UpdateCurrentState()
Checks current state, invokes state change effects if state has changed.
bool GetToggled()
override bool OnDoubleClick(Widget w, int x, int y, int button)
void _print(string s)
ref Managed m_UserData
STATE_DISABLED_ACTIVATED
Disabled and activated.
bool m_bToggledAtStart
ref ScriptInvoker m_OnDoubleClicked
string GetCurrentStateName()
void SetTogglableOnlyThroughApi(bool newValue)
ref ScriptInvoker m_OnClicked
void InvokeAllEnabledEffects(bool instant)
array< SCR_ButtonEffectBase > GetAllEffects()
STATE_ACTIVATED_HOVERED
Activated and hovered.
STATE_ACTIVATED
Activated.
enum EModularButtonState FOCUS_GAINED
void SetToggled(bool toggled, bool invokeOnToggled=true, bool instant=false)
void SetIsFocusOnMouseEnter(bool focus)
void SetData(Managed data)
STATE_HOVERED
Hovered.
void Internal_SetToggled(bool newToggled, bool invokeOnToggled=true, bool instant=false)
void SetEffectsEnabled(string tag, bool enable)
void SetAllEffectsEnabled(bool enable)
void Internal_OnEffectEnabled(SCR_ButtonEffectBase effect)
enum EModularButtonState DOUBLE_CLICK
enum EModularButtonState FOCUS_LOST
ref ScriptInvoker m_OnFocus
ref ScriptInvoker m_OnToggled
bool GetEnabled()
array< SCR_ButtonEffectBase > FindAllEffects(string tag)
EModularButtonState GetCurrentState()
enum EModularButtonState CLICK
Enum corresponding Enfusion native event types.
void Internal_OnMasterButtonEvent(EModularButtonEventFlag eventFlag, bool instant)
bool m_bIgnoreStandardInputs
bool GetFocused()
EModularButtonEventHandler m_eEventReturnValue
void InvokeEffectsEvent(EModularButtonEventFlag eventFlag, bool instant=false)
Widget GetRootWidget()
ref ScriptInvoker m_OnMouseEnter
void SetToggleable(bool toggleable)
enum EModularButtonState MOUSE_LEAVE
void IgnoreStandardInputs(bool ignore)
bool m_bCanBeToggled
bool GetIsFocusOnMouseEnter()
void SetVisible(int layer)
override void HandlerAttached(Widget w)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
void SetEnabled(bool enabled)
void Tuple3(T1 p1, T2 p2, T3 p3)
Definition tuple.c:95
ScriptInvokerBase< func > ScriptInvoker
Definition tools.c:134