Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_PopupNotification.c
Go to the documentation of this file.
1 //------------------------------------------------------------------------------------------------
3 {
4  string m_sText;
5  string m_sSubtitle;
6  float m_fDuration;
7  int m_iPriority;
8  string m_sSound;
9  string m_aTextParams[4] = {"", "", "", ""};
10  string m_aSubtitleParams[4] = {"", "", "", ""};
11  SCR_EPopupMsgFilter m_eFilter;
12  WorldTimestamp m_fProgressStart;
13  WorldTimestamp m_fProgressEnd;
14  WorldTimestamp m_fHideTimestamp;
15 };
16 
17 //------------------------------------------------------------------------------------------------
18 class SCR_PopUpNotificationClass : GenericEntityClass
19 {
20 };
21 
22 //------------------------------------------------------------------------------------------------
25 {
26  protected static const int INVALID_ID = -1;
27  protected static const float FADE_DURATION = 1;
28  protected static const ResourceName LAYOUT_NAME = "{8EF935F196AADE33}UI/layouts/Common/PopupUI.layout";
29  protected static const int POPUP_OFFSET = 35;
30 
31  protected static SCR_PopUpNotification s_Instance = null;
32  protected static SCR_EPopupMsgFilter s_eFilter;
33 
34  static const float DEFAULT_DURATION = 4;
35  static const string TASKS_KEY_IMAGE_FORMAT = "<color rgba='226, 168, 79, 200'><shadow mode='image' color='0, 0, 0' size='1' offset='1, 1' opacity = '0.5'><action name='TasksOpen'/></shadow></color>";
36 
37  protected ref array<ref SCR_PopupMessage> m_aQueue = {};
38 
39  protected RichTextWidget m_wPopupMsg;
40  protected RichTextWidget m_wPopupMsgSmall;
41  protected ProgressBarWidget m_wStatusProgress;
42 
43  protected float m_fDefaultAlpha;
44  protected float m_fDefaultHorizontalOffset = -1;
45 
46  protected bool m_bInventoryOpen;
47  protected bool m_bOffset;
48 
49  protected IEntity m_Player;
50 
51  protected SCR_PopupMessage m_ShownMsg;
52 
53  //------------------------------------------------------------------------------------------------
54  static SCR_PopUpNotification GetInstance()
55  {
56  if (!s_Instance)
57  {
58  BaseWorld world = GetGame().GetWorld();
59 
60  if (world)
62  }
63 
64  return s_Instance;
65  }
66 
67  //------------------------------------------------------------------------------------------------
68  static void SetFilter(SCR_EPopupMsgFilter filter)
69  {
70  s_eFilter = filter;
71  }
72 
73  //------------------------------------------------------------------------------------------------
74  void Offset(bool down)
75  {
76  if (!m_wPopupMsg || !m_wPopupMsgSmall || !m_wStatusProgress)
77  return;
78 
79  if (down == m_bOffset)
80  return;
81 
82  m_bOffset = down;
83 
84  int offset = POPUP_OFFSET;
85 
86  if (!down)
87  offset = offset * -1;
88 
89  FrameSlot.SetPosY(m_wPopupMsg, FrameSlot.GetPosY(m_wPopupMsg) + offset);
90  FrameSlot.SetPosY(m_wPopupMsgSmall, FrameSlot.GetPosY(m_wPopupMsgSmall) + offset);
91  FrameSlot.SetPosY(m_wStatusProgress, FrameSlot.GetPosY(m_wStatusProgress) + offset);
92  }
93 
94  //------------------------------------------------------------------------------------------------
95  protected void ProcessInit()
96  {
97  if (!GetGame().GetHUDManager())
98  return;
99 
100  PlayerController pc = GetGame().GetPlayerController();
101 
102  if (!pc || !pc.GetControlledEntity())
103  return;
104 
105  Widget root = GetGame().GetHUDManager().CreateLayout(LAYOUT_NAME, EHudLayers.MEDIUM, 0);
106 
107  if (!root)
108  return;
109 
110  // Init can be safely processed
111  GetGame().GetCallqueue().Remove(ProcessInit);
112 
113  // Initialize popups UI
114  m_wPopupMsg = RichTextWidget.Cast(root.FindAnyWidget("Popup"));
115  m_wPopupMsgSmall = RichTextWidget.Cast(root.FindAnyWidget("PopupSmall"));
116  m_wStatusProgress = ProgressBarWidget.Cast(root.FindAnyWidget("Progress"));
117  m_fDefaultAlpha = m_wPopupMsg.GetColor().A();
118  m_wPopupMsg.SetVisible(false);
119  m_wPopupMsgSmall.SetVisible(false);
120  m_wStatusProgress.SetVisible(false);
121 
122  GetGame().GetCallqueue().CallLater(SetDefaultHorizontalPosition, 500);
123 
125 
126  if (playerController)
127  playerController.m_OnControlledEntityChanged.Insert(RefreshInventoryInvoker);
128 
129  RefreshQueue();
130 
131  // Popups should not be visible in map
132  SCR_MapEntity mapEntity = SCR_MapEntity.GetMapInstance();
133 
134  if (mapEntity)
135  {
136  MapConfiguration config = mapEntity.GetMapConfig();
137 
138  if (!config)
139  return;
140 
141  Widget mapWidget = config.RootWidgetRef;
142 
143  if (mapWidget)
144  root.SetZOrder(mapWidget.GetZOrder() - 1);
145  }
146  }
147 
148  //------------------------------------------------------------------------------------------------
149  protected void RefreshInventoryInvoker(IEntity previousPlayer, IEntity currentPlayer)
150  {
151  SCR_InventoryStorageManagerComponent inventory;
152 
153  if (previousPlayer)
154  {
155  inventory = SCR_InventoryStorageManagerComponent.Cast(previousPlayer.FindComponent(SCR_InventoryStorageManagerComponent));
156 
157  if (inventory)
158  inventory.m_OnInventoryOpenInvoker.Remove(OnInventoryToggle);
159  }
160 
161  if (!currentPlayer)
162  return;
163 
164  inventory = SCR_InventoryStorageManagerComponent.Cast(currentPlayer.FindComponent(SCR_InventoryStorageManagerComponent));
165 
166  if (!inventory)
167  return;
168 
169  // Make absolutely sure invoker is not used multiple times in the same inventory
170  inventory.m_OnInventoryOpenInvoker.Remove(OnInventoryToggle);
171  inventory.m_OnInventoryOpenInvoker.Insert(OnInventoryToggle);
172  }
173 
174  //------------------------------------------------------------------------------------------------
175  void OnInventoryToggle(bool open)
176  {
177  m_bInventoryOpen = open;
178  }
179 
180  //------------------------------------------------------------------------------------------------
191  void PopupMsg(string text, float duration = DEFAULT_DURATION, string text2 = "", int prio = -1, string param1 = "", string param2 = "", string param3 = "", string param4 = "", string text2param1 = "", string text2param2 = "", string text2param3 = "", string text2param4 = "", string sound = "", SCR_EPopupMsgFilter category = SCR_EPopupMsgFilter.ALL,
192  WorldTimestamp progressStart = null,
193  WorldTimestamp progressEnd = null
194  )
195  {
196  // Don't show UI on headless
197  if (System.IsConsoleApp())
198  return;
199 
200  // Check filter settings, stop if the message is filtered out
201  if (s_eFilter == SCR_EPopupMsgFilter.NONE || (s_eFilter == SCR_EPopupMsgFilter.TUTORIAL && category != SCR_EPopupMsgFilter.TUTORIAL))
202  return;
203 
204  // Invalid params
205  if ((text.IsEmpty() && text2.IsEmpty()) || duration == 0)
206  return;
207 
209 
210  if (!msg)
211  return;
212 
213  msg.m_sText = text;
214  msg.m_sSubtitle = text2;
215  msg.m_fDuration = duration;
216  msg.m_iPriority = prio;
217  msg.m_sSound = sound;
218  msg.m_aTextParams = {param1, param2, param3, param4};
219  msg.m_aSubtitleParams = {text2param1, text2param2, text2param3, text2param4};
220  msg.m_eFilter = category;
221  msg.m_fProgressStart = progressStart;
222  msg.m_fProgressEnd = progressEnd;
223 
224  RefreshQueue(msg);
225  }
226 
227  //------------------------------------------------------------------------------------------------
228  SCR_PopupMessage GetCurrentMsg()
229  {
230  return m_ShownMsg;
231  }
232 
233  //------------------------------------------------------------------------------------------------
234  void HideCurrentMsg()
235  {
236  if (!m_ShownMsg)
237  return;
238 
239  ChimeraWorld world = GetWorld();
240  m_ShownMsg.m_fHideTimestamp = world.GetServerTimestamp();
241  }
242 
243  //------------------------------------------------------------------------------------------------
244  void ChangeProgressBarFinish(WorldTimestamp progressEnd)
245  {
246  if (!m_ShownMsg || m_ShownMsg.m_fProgressEnd == 0)
247  return;
248 
249  ChimeraWorld world = GetWorld();
250  WorldTimestamp curTime = world.GetServerTimestamp();
251 
252  // Save progress bar status so only its filling speed is changed
253  float totalTime = m_ShownMsg.m_fProgressEnd.DiffMilliseconds(m_ShownMsg.m_fProgressStart);
254  float elapsedTime = curTime.DiffMilliseconds(m_ShownMsg.m_fProgressStart);
255  float curProgress = elapsedTime / totalTime;
256 
257  // Avoid possible division by 0 later
258  if (curProgress == 1)
259  return;
260 
261  m_ShownMsg.m_fProgressEnd = progressEnd;
262 
263  // Recalculate start value so the bar keeps its original progress
264  float newRemainingTime = progressEnd.DiffMilliseconds(curTime);
265  float newTotalTime = newRemainingTime / (1 - curProgress);
266  float newElapsedTime = newTotalTime * curProgress;
267  m_ShownMsg.m_fProgressStart = curTime.PlusMilliseconds(-newElapsedTime);
268 
269  // Needed to reset the progress bar limits
270  m_wStatusProgress.SetVisible(false);
271  }
272 
273  //------------------------------------------------------------------------------------------------
274  protected void FadeWidget(notnull Widget widget, bool fadeOut = false)
275  {
276  float alpha, targetAlpha;
277 
278  if (fadeOut)
279  {
280  alpha = m_fDefaultAlpha;
281  targetAlpha = 0;
282  }
283  else
284  {
285  alpha = 0;
286  targetAlpha = m_fDefaultAlpha;
287  }
288 
289  widget.SetOpacity(alpha);
290  AnimateWidget.Opacity(widget, targetAlpha, FADE_DURATION, !fadeOut || widget.IsVisible());
291  }
292 
293  //------------------------------------------------------------------------------------------------
294  protected void RefreshQueue(SCR_PopupMessage msg = null)
295  {
296  if (msg)
297  {
298  int index = m_aQueue.Find(msg);
299 
300  if (index == -1)
301  {
302  // Find the correct array index for the new message (based on priority)
303  SCR_PopupMessage checkedMsg;
304 
305  for (int i = 0, cnt = m_aQueue.Count(); i < cnt; i++)
306  {
307  checkedMsg = m_aQueue[i];
308 
309  // Infinite duration is always considered higher prio
310  if (msg.m_fDuration == -1)
311  {
312  if (checkedMsg.m_fDuration != -1 || checkedMsg.m_iPriority < msg.m_iPriority)
313  index = i;
314  }
315  else if (checkedMsg.m_fDuration != -1 && checkedMsg.m_iPriority < msg.m_iPriority)
316  {
317  index = i;
318  }
319 
320  if (index != -1)
321  break;
322  }
323 
324  if (index == -1)
325  m_aQueue.Insert(msg);
326  else
327  m_aQueue.InsertAt(msg, index);
328  }
329  else
330  {
331  m_aQueue.RemoveOrdered(index);
332  }
333  }
334 
335  if (m_aQueue.IsEmpty())
336  {
337  ClearEventMask(EntityEvent.FRAME);
338  }
339  else if (m_wPopupMsg)
340  {
341  if (m_aQueue[0] != m_ShownMsg)
342  ShowMsg(m_aQueue[0]);
343 
344  SetEventMask(EntityEvent.FRAME);
345  }
346  }
347 
348  //------------------------------------------------------------------------------------------------
349  protected void ShowMsg(notnull SCR_PopupMessage msg)
350  {
351  if (msg == m_ShownMsg)
352  return;
353 
354  if (m_ShownMsg)
355  HideMsg(m_ShownMsg);
356 
357  if (msg.m_fDuration != -1)
358  {
359  ChimeraWorld world = GetWorld();
360  msg.m_fHideTimestamp = world.GetServerTimestamp().PlusSeconds(msg.m_fDuration);
361  }
362 
363  m_wPopupMsg.SetTextFormat(msg.m_sText, msg.m_aTextParams[0], msg.m_aTextParams[1], msg.m_aTextParams[2], msg.m_aTextParams[3]);
364  FadeWidget(m_wPopupMsg);
365 
366  if (!msg.m_sSubtitle.IsEmpty())
367  {
368  m_wPopupMsgSmall.SetTextFormat(msg.m_sSubtitle, msg.m_aSubtitleParams[0], msg.m_aSubtitleParams[1], msg.m_aSubtitleParams[2], msg.m_aSubtitleParams[3]);
369  FadeWidget(m_wPopupMsgSmall);
370  }
371 
372  if (msg.m_fProgressStart != 0 && msg.m_fProgressEnd != 0)
373  {
374  m_wStatusProgress.SetMin(0);
375  m_wStatusProgress.SetMax(msg.m_fProgressEnd.DiffMilliseconds(msg.m_fProgressStart));
376  m_wStatusProgress.SetVisible(false);
377  FadeWidget(m_wStatusProgress);
378  }
379 
380  if (!msg.m_sSound.IsEmpty())
381  SCR_UISoundEntity.SoundEvent(msg.m_sSound);
382 
383  m_ShownMsg = msg;
384  }
385 
386  //------------------------------------------------------------------------------------------------
387  protected void HideMsg(notnull SCR_PopupMessage msg)
388  {
389  if (msg == m_ShownMsg)
390  {
391  m_ShownMsg = null;
392 
393  FadeWidget(m_wPopupMsg, true);
394  FadeWidget(m_wPopupMsgSmall, true);
395  FadeWidget(m_wStatusProgress, true);
396  }
397 
398  RefreshQueue(msg);
399  }
400 
401  //------------------------------------------------------------------------------------------------
402  void SetDefaultHorizontalPosition()
403  {
404  float x, y;
405  m_wPopupMsg.GetScreenPos(x, y);
406  m_fDefaultHorizontalOffset = y;
407  }
408 
409  //------------------------------------------------------------------------------------------------
410  override void EOnFrame(IEntity owner, float timeSlice)
411  {
412  if (!m_ShownMsg)
413  return;
414 
415  if (m_bInventoryOpen)
416  {
417  m_wPopupMsg.SetVisible(false);
418  m_wPopupMsgSmall.SetVisible(false);
419  m_wStatusProgress.SetVisible(false);
420  return;
421  }
422 
423  BaseWorld world = GetGame().GetWorld();
424 
425  if (!world)
426  return;
427 
428  ChimeraWorld chimWorld = world;
429  WorldTimestamp curTime = chimWorld.GetServerTimestamp();
430  if (m_ShownMsg.m_fHideTimestamp != 0 && curTime.GreaterEqual(m_ShownMsg.m_fHideTimestamp))
431  {
432  HideMsg(m_ShownMsg);
433  return;
434  }
435 
436  if (m_ShownMsg.m_sText && !m_wPopupMsg.IsVisible())
437  m_wPopupMsg.SetVisible(true);
438 
439  if (m_ShownMsg.m_sSubtitle && !m_wPopupMsgSmall.IsVisible())
440  m_wPopupMsgSmall.SetVisible(true);
441 
442  if (m_ShownMsg.m_fProgressEnd.Greater(curTime))
443  {
444  if (!m_wStatusProgress.IsVisible())
445  {
446  m_wStatusProgress.SetVisible(true);
447  m_wStatusProgress.SetMin(0);
448  m_wStatusProgress.SetMax(m_ShownMsg.m_fProgressEnd.DiffMilliseconds(m_ShownMsg.m_fProgressStart));
449  }
450 
451  m_wStatusProgress.SetCurrent(curTime.DiffMilliseconds(m_ShownMsg.m_fProgressStart));
452  }
453  else if (m_wStatusProgress.IsVisible())
454  {
455  m_wStatusProgress.SetVisible(false);
456  }
457  }
458 
459  //------------------------------------------------------------------------------------------------
460  void SCR_PopUpNotification(IEntitySource src, IEntity parent)
461  {
462  SetFlags(EntityFlags.NO_TREE | EntityFlags.NO_LINK);
463 
464  // Don't show UI on headless
465  if (System.IsConsoleApp())
466  return;
467 
468  // Make sure init can be processed properly (when HUD Manager is ready, check in ProcessInit())
469  GetGame().GetCallqueue().Remove(ProcessInit);
470  GetGame().GetCallqueue().CallLater(ProcessInit, 1000, true);
471  }
472 
473  //------------------------------------------------------------------------------------------------
474  void ~SCR_PopUpNotification()
475  {
476  if (m_wPopupMsg)
477  m_wPopupMsg.GetParent().RemoveFromHierarchy();
478 
479  s_eFilter = SCR_EPopupMsgFilter.ALL;
480 
481  GetGame().GetCallqueue().Remove(ProcessInit);
482  }
483 };
484 
485 //------------------------------------------------------------------------------------------------
487 {
491 };
ChimeraWorld
Definition: ChimeraWorld.c:12
SpawnEntity
protected IEntity SpawnEntity(ResourceName entityResourceName, notnull IEntity slotOwner)
Definition: SCR_CatalogEntitySpawnerComponent.c:1008
SCR_PlayerController
Definition: SCR_PlayerController.c:31
TUTORIAL
@ TUTORIAL
Definition: SCR_PopupNotification.c:490
SCR_UISoundEntity
Definition: SCR_UISoundEntity.c:7
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
GenericEntity
SCR_GenericBoxEntityClass GenericEntity
SCR_PopUpNotification
Takes care of dynamic and static onscreen popups.
Definition: SCR_PopupNotification.c:24
GetPlayerController
proto external PlayerController GetPlayerController()
Definition: SCR_PlayerDeployMenuHandlerComponent.c:307
SCR_PopupMessage
Definition: SCR_PopupNotification.c:2
SCR_PopUpNotificationClass
Definition: SCR_PopupNotification.c:18
EHudLayers
EHudLayers
Definition: SCR_HUDManagerComponent.c:5
s_Instance
SCR_SpawnerSlotManagerClass s_Instance
Class used for managing changes and removals of slots present in world.
ALL
@ ALL
Definition: SCR_PopupNotification.c:488
NONE
@ NONE
Definition: SCR_PopupNotification.c:489
SCR_MapEntity
Map entity.
Definition: SCR_MapEntity.c:20
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
GetHUDManager
SCR_HUDManagerComponent GetHUDManager()
Definition: game.c:1196
SCR_EPopupMsgFilter
SCR_EPopupMsgFilter
Definition: SCR_PopupNotification.c:486
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180