Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_ChatPanel.c
Go to the documentation of this file.
1 
6 class SCR_ChatPanel : ScriptedWidgetComponent
7 {
8  // Constants
9 
10  protected const string STR_AVAILABLE_CHANNELS = "#AR-Chat_AvailableChannels";
11  protected const string STR_CHANNEL_DISABLED = "#AR-Chat_ChannelDisabled"; // Message to show when channel is disabled.
12  protected const string STR_CHANNEL_UNKNOWN = "#AR-Chat_ChannelUnknown"; // Message to show when entering a non valid chat command.
13  protected const string STR_MESSAGE_LIMIT_REACHED = "#AR-Chat_LimitReached"; // Message to show when max characters for chat input is reached.
14 
15  //Invokers
16  protected ref ScriptInvoker m_OnChatOpen;
17  protected ref ScriptInvoker m_OnChatClosed;
18 
19  // Channel styles
20 
21  [Attribute()]
22  ref SCR_ChatMessageStyle m_SystemChannelStyle;
23 
24  [Attribute()]
25  ref SCR_ChatMessageStyle m_RadioProtocolStyle;
26 
27  [Attribute()]
28  ref SCR_ChatMessageStyle m_GlobalChannelStyle;
29 
30  [Attribute()]
31  ref SCR_ChatMessageStyle m_GroupChannelStyle;
32 
33  [Attribute()]
34  ref SCR_ChatMessageStyle m_FactionChannelStyle;
35 
36  [Attribute()]
37  ref SCR_ChatMessageStyle m_VehicleChannelStyle;
38 
39  [Attribute()]
40  ref SCR_ChatMessageStyle m_LocalChannelStyle;
41 
42  [Attribute()]
43  ref SCR_ChatMessageStyle m_DirectChannelStyle;
44 
45  // Other attributes
46 
47  [Attribute("9", UIWidgets.EditBox, "Max amount of message line widgets")]
48  protected int m_iMessageLineCount;
49 
50  [Attribute("20", UIWidgets.EditBox, "Amount of time till whole chat fades out, seconds")]
51  protected float m_fFadeOutThreshold_s;
52 
53  [Attribute("false", UIWidgets.CheckBox, "When true, chat is always visible. When false, chat will fade out if msg box is hidden for more than m_fFadeOutThreshold_s time")]
54  protected bool m_bAlwaysVisible;
55 
56  [Attribute("{973C90F6B6135A50}UI/layouts/HUD/Chat/ChatMessage.layout", UIWidgets.ResourceNamePicker, params: "layout")]
57  protected ResourceName m_sChatMessageLineLayout;
58 
59  // State of UI
60  protected int m_iHistoryId = 0; // Id of message for history scrolling
61  protected int m_iHistoryIdLowestMessage = 0; // Id of message for history scrolling
62  protected bool m_bHistoryMode = false; // When disabled, we are always looking at new messages.
63  protected ref array<SCR_ChatMessageLineComponent> m_aMessageLines = {}; // Message line components. We reuse same lines for messages.
64  protected bool m_bOpen = false;
65 
66  // Cached components
67  protected ScriptedChatEntity m_ChatEntity;
68  protected BaseChatChannel m_ActiveChannel;
69 
70  // Animations
71  ref SCR_FadeInOutAnimator m_MessageHistoryAnimator;
72 
73  // Widgets and components
74  protected Widget m_wRoot;
75  protected ref SCR_ChatPanelWidgets m_Widgets = new SCR_ChatPanelWidgets();
76  EditBoxFilterComponent m_MessageEditBoxComponent;
77 
78  //------------------------------------------------------------------------------------------------
79  // PUBLIC
80 
81  //------------------------------------------------------------------------------------------------
83  void OnUpdateChat(float timeSlice)
84  {
85  m_MessageHistoryAnimator.ForceVisible(m_bOpen || m_bAlwaysVisible);
86 
87  if (m_bOpen)
88  {
89 
90  GetGame().GetInputManager().ActivateContext("ChatContext", 1);
91 
92  if (m_Widgets.m_MessageEditBox.GetText().Length() >= m_MessageEditBoxComponent.GetNumLimitOfCharacters())
93  {
94  ShowChannelWarning(null, STR_MESSAGE_LIMIT_REACHED);
95  m_Widgets.m_WarningChannelMessage.SetVisible(true);
96  }
97  else
98  {
99  m_Widgets.m_WarningChannelMessage.SetVisible(false);
100  }
101  }
102 
103  m_MessageHistoryAnimator.Update(timeSlice);
104  }
105 
106  //------------------------------------------------------------------------------------------------
108  void OnHUDResize(int newMessageLineCount)
109  {
110  m_iMessageLineCount = newMessageLineCount;
111  int count = m_aMessageLines.Count();
112 
113  if (count == m_iMessageLineCount)
114  return;
115 
116  if (count > m_iMessageLineCount)
117  {
118  for (int i = count - 1; i >= m_iMessageLineCount; i--)
119  {
120  SCR_ChatMessageLineComponent w = m_aMessageLines[i];
121 
122  if (w)
123  {
124  w.GetRootWidget().RemoveFromHierarchy();
125  m_aMessageLines.RemoveItemOrdered(w);
126  }
127 
128  }
129  }
130  else
131  {
132  for (int i = count; i < m_iMessageLineCount; i++)
133  {
134  Widget lineWidget = GetGame().GetWorkspace().CreateWidgets(m_sChatMessageLineLayout, m_Widgets.m_MessageHistory);
136  comp.SetEmptyMessage();
137  m_aMessageLines.Insert(comp);
138  }
139  }
140 
141  UpdateChatMessages();
142  }
143 
144  //------------------------------------------------------------------------------------------------
145  bool IsOpen()
146  {
147  return m_bOpen;
148  }
149 
150  //------------------------------------------------------------------------------------------------
152  bool GetFadeOut()
153  {
154  int state = m_MessageHistoryAnimator.GetState();
155  return state == SCR_FadeInOutAnimator.STATE_FADE_OUT || state == SCR_FadeInOutAnimator.STATE_FADING_DONE;
156  }
157 
158  //------------------------------------------------------------------------------------------------
160  bool GetFadeIn()
161  {
162  int state = m_MessageHistoryAnimator.GetState();
163  return state == SCR_FadeInOutAnimator.STATE_FADE_IN || state == SCR_FadeInOutAnimator.STATE_FADE_OUT_WAIT;
164  }
165 
166 
167  //------------------------------------------------------------------------------------------------
168  // INTERNAL / PROTECTED
169 
170 
171  //------------------------------------------------------------------------------------------------
173  void Internal_Open()
174  {
175  // If m_OnChatOpen is not null we know it's used by the HudManager so we check if the parent (HudManager slot) is enabled (enabled = visible)
176  if (m_bOpen || m_OnChatOpen && !m_wRoot.GetParent().IsEnabled())
177  return;
178 
179  SCR_ChatPanelManager mgr = SCR_ChatPanelManager.GetInstance();
180 
181  // When we open the chat, history mode is disabled unless we start scrolling
182  m_bHistoryMode = false;
183  m_iHistoryId = mgr.GetMessages().Count();
184  m_iHistoryIdLowestMessage = m_iHistoryId;
185 
186  m_bOpen = true;
187  if (m_OnChatOpen)
188  m_OnChatOpen.Invoke();
189 
190  //m_Widgets.m_EditOverlay.SetOpacity(1);
191  AnimateWidget.Opacity(m_Widgets.m_EditOverlay, 1, UIConstants.FADE_RATE_DEFAULT);
192 
193  // Animate the edit background color
194  Color colorStart = Color.FromSRGBA(226, 167, 79, 255); // Orange
195  Color colorEnd = Color.FromSRGBA(0, 0, 0, 140); // Black
196  m_Widgets.m_EditBackgroundImage.SetColor(colorStart);
197  AnimateWidget.Color(m_Widgets.m_EditBackgroundImage, colorEnd, UIConstants.FADE_RATE_SLOW);
198 
199  m_Widgets.m_MessageEditBox.SetEnabled(true);
200 
201  bool bFocus = false;
202  if (GetGame().GetInputManager().IsUsingMouseAndKeyboard())
203  bFocus = true;
204 
205  if (bFocus)
206  {
207  GetGame().GetWorkspace().SetFocusedWidget(m_Widgets.m_MessageEditBox);
208  m_Widgets.m_MessageEditBox.ActivateWriteMode();
209  }
210 
211  if (m_ActiveChannel)
212  {
213  if (!m_ActiveChannel.IsAvailable(GetChatComponent()))
214  CycleChannels(true);
215  }
216 
217 
218  // Instantly show the channel name overlay when we open the chat
219  if (m_Widgets.m_ChannelTagOverlay)
220  {
221  m_Widgets.m_ChannelTagOverlay.SetVisible(true);
222  }
223 
224 
225  m_Widgets.m_WarningChannelMessage.SetVisible(false);
226  UpdateChatMessages();
227  }
228 
229 
230  //------------------------------------------------------------------------------------------------
232  void Internal_Close()
233  {
234  if (!m_bOpen)
235  return;
236 
237  WorkspaceWidget workspace = GetGame().GetWorkspace();
238  if (workspace.GetFocusedWidget() == m_Widgets.m_MessageEditBox)
239  {
240  workspace.SetFocusedWidget(null);
241  }
242 
243  m_bOpen = false;
244  if (m_OnChatClosed)
245  m_OnChatClosed.Invoke();
246 
247  if (m_Widgets.m_MessageEditBox)
248  {
249  m_Widgets.m_MessageEditBox.SetText(string.Empty);
250  m_Widgets.m_MessageEditBox.SetEnabled(false);
251  }
252 
253  AnimateWidget.StopAnimation(m_Widgets.m_EditOverlay, WidgetAnimationOpacity); // Stop the fade in animation in case it's not completed to prevent chat sticking to screen
254  m_Widgets.m_EditOverlay.SetOpacity(0); // Hide it instantly, otherwise it looks weird
255 
256  m_Widgets.m_WarningChannelMessage.SetVisible(false);
257 
258  m_iHistoryId = SCR_ChatPanelManager.GetInstance().GetMessages().Count() - 1; // Force scroll to the end
259  m_iHistoryIdLowestMessage = m_iHistoryId;
260 
261  UpdateChatMessages();
262  }
263 
264 
265  //------------------------------------------------------------------------------------------------
266  void Internal_OnNewMessage(SCR_ChatMessage msg)
267  {
268  // Update history index
269  if (!m_bHistoryMode)
270  {
271  m_iHistoryId = SCR_ChatPanelManager.GetInstance().GetMessages().Count() - 1; // Scroll to the end if we are not scrolling the chat now
272  m_iHistoryIdLowestMessage = m_iHistoryId;
273  }
274 
275  m_MessageHistoryAnimator.FadeIn();
276  this.UpdateChatMessages();
277  }
278 
279  //------------------------------------------------------------------------------------------------
280  notnull Widget GetWidget()
281  {
282  return m_wRoot;
283  }
284 
285  //------------------------------------------------------------------------------------------------
286  override void HandlerAttached(Widget w)
287  {
288  // Bail if we are in workbench editor
289  if (SCR_Global.IsEditMode())
290  return;
291 
292  m_wRoot = w;
293 
294  SCR_ChatPanelManager chatPanelMgr = SCR_ChatPanelManager.GetInstance();
295  m_ChatEntity = ScriptedChatEntity.Cast(GetGame().GetChat());
296 
297  if (!chatPanelMgr)
298  {
299  Print("[Chat] SCR_ChatPanelManager is not found. Chat will not work.", LogLevel.ERROR);
300  return;
301  }
302 
303  m_Widgets.Init(w);
304  m_MessageEditBoxComponent = m_Widgets.m_MessageEditBoxComponent0;
305 
306  VerifyChannelStyles();
307 
308 
309  m_Widgets.m_MessageEditBox.SetEnabled(false);
310 
311  // This callback will hide/show the overlay depending on typed text
312  m_Widgets.m_MessageEditBoxComponent1.GetOnChange().Insert(Callback_OnEditBoxChange);
313 
314  // Init the widgets in the history layout
315  m_MessageHistoryAnimator = new SCR_FadeInOutAnimator(m_Widgets.m_MessageHistory, UIConstants.FADE_RATE_FAST, UIConstants.FADE_RATE_SLOW, m_fFadeOutThreshold_s);
316 
317  for (int i = 0; i < m_iMessageLineCount; i++)
318  {
319  Widget lineWidget = GetGame().GetWorkspace().CreateWidgets(m_sChatMessageLineLayout, m_Widgets.m_MessageHistory);
321  SCR_ChatMessageLineComponent.Cast(lineWidget.FindHandler(SCR_ChatMessageLineComponent));
322  comp.SetEmptyMessage();
323  m_aMessageLines.Insert(comp);
324  }
325 
326  // Init inputs
327  InputManager inputMgr = GetGame().GetInputManager();
328  inputMgr.AddActionListener("ChatSendMessage", EActionTrigger.DOWN, Callback_OnSendMessageAction);
329  inputMgr.AddActionListener("ChatEscape", EActionTrigger.DOWN, Callback_OnCloseAction);
330  inputMgr.AddActionListener("ChatConfirm", EActionTrigger.DOWN, Callback_OnGamepadConfirmAction);
331  inputMgr.AddActionListener("ChatHistoryBrowse", EActionTrigger.VALUE, Callback_OnHistoryAction);
332  inputMgr.AddActionListener("ChatSwitchChannel", EActionTrigger.VALUE, Callback_OnSwitchChannelAction);
333  inputMgr.AddActionListener("ChatSwitchChannelSpace", EActionTrigger.DOWN, Callback_OnPressSpaceAfterCommand);
334 
335  //m_Widgets.m_EditOverlay.SetVisible(false);
336  m_Widgets.m_EditOverlay.SetOpacity(0);
337 
338  //Initialization will depend on avaliable channels for the player
339  if (m_ChatEntity && chatPanelMgr)
340  {
341  chatPanelMgr.Internal_EnableAllChannels();
342  SetActiveChannel(m_ChatEntity.GetDefaultChannel());
343  }
344 
345  // Instantly show previous messages when this UI panel is created.
346  // But only show it if any chat panel is faded in.
347  // We don't want to fade in the panel if previous one was inactive for long time.
348  if (chatPanelMgr.GetAnyPanelFadedIn())
349  {
350  m_iHistoryId = chatPanelMgr.GetMessages().Count() - 1;
351  m_iHistoryIdLowestMessage = m_iHistoryId;
352  m_MessageHistoryAnimator.FadeIn();
353  UpdateChatMessages();
354  }
355 
356  // Register at chat panel mgr
357  if (chatPanelMgr)
358  chatPanelMgr.Register(this);
359  }
360 
361 
362 
363  //------------------------------------------------------------------------------------------------
364  override void HandlerDeattached(Widget w)
365  {
366  // Bail if we are in workbench editor
367  if (SCR_Global.IsEditMode())
368  return;
369 
370  InputManager inputMgr = GetGame().GetInputManager();
371  inputMgr.RemoveActionListener("ChatSendMessage", EActionTrigger.DOWN, Callback_OnSendMessageAction);
372  inputMgr.RemoveActionListener("ChatEscape", EActionTrigger.DOWN, Callback_OnCloseAction);
373  inputMgr.RemoveActionListener("ChatConfirm", EActionTrigger.DOWN, Callback_OnGamepadConfirmAction);
374  inputMgr.RemoveActionListener("ChatHistoryBrowse", EActionTrigger.VALUE, Callback_OnHistoryAction);
375  inputMgr.RemoveActionListener("ChatSwitchChannel", EActionTrigger.VALUE, Callback_OnSwitchChannelAction);
376  inputMgr.RemoveActionListener("ChatSwitchChannelSpace", EActionTrigger.DOWN, Callback_OnPressSpaceAfterCommand);
377 
378  // Unregister at chat panel mgr
379  SCR_ChatPanelManager chatPanelMgr = SCR_ChatPanelManager.GetInstance();
380  if (chatPanelMgr)
381  chatPanelMgr.Unregister(this);
382  }
383 
384 
385 
386  //------------------------------------------------------------------------------------------------
387  // Updates the display with the messages
388  // lastMessageId - id of the last message to be shown in chat
389  protected void UpdateChatMessages()
390  {
391  array<ref SCR_ChatMessage> messages = SCR_ChatPanelManager().GetInstance().GetMessages();
392 
393  int messageCount = messages.Count();
394 
395  if (messageCount > 0)
396  {
397  int lastMessageId = m_iHistoryId;
398  if (!m_bHistoryMode)
399  lastMessageId = m_iHistoryIdLowestMessage;
400 
401  lastMessageId = Math.ClampInt(lastMessageId, 0, messageCount - 1);
402  int currentMessageCount = m_iMessageLineCount;
403 
404  for (int i = 0; i < currentMessageCount; i++)
405  {
406  int messageId = lastMessageId - i; // Message 0 is oldest message
407  int widgetId = i; // Widget 0 is at the bottom
408 
409  if (i > m_aMessageLines.Count() - 1 || i < 0)
410  continue;
411 
412  SCR_ChatMessageLineComponent lineComp = m_aMessageLines[widgetId];
413 
414  if (messageId >= 0 && messageId <= lastMessageId)
415  {
416  SCR_ChatMessage msg = messages[messageId];
417  SCR_ChatMessageStyle style = GetMessageStyle(msg);
418  lineComp.SetVisible(true);
419  lineComp.SetMessage(msg, style);
420 
421  }
422  else
423  {
424  // This line is blank
425  //this.DecorateBlankMessageWidget(messageWidget);
426  lineComp.SetVisible(false);
427  }
428  }
429  }
430  else
431  {
432  for (int i = 0; i < m_iMessageLineCount; i++)
433  {
434  if (i > m_aMessageLines.Count() - 1 || i < 0)
435  continue;
436 
437  SCR_ChatMessageLineComponent lineComp = m_aMessageLines[i];
438 
439  // This line is blank
440  //this.DecorateBlankMessageWidget(messageWidget);
441  lineComp.SetVisible(false);
442  }
443  }
444  }
445 
446 
447  //------------------------------------------------------------------------------------------------
448  protected void SendMessage()
449  {
450  SCR_ChatPanelManager mgr = SCR_ChatPanelManager.GetInstance();
451 
452  SCR_ChatComponent chatComponent = GetChatComponent();
453 
454  if (!chatComponent || !m_ActiveChannel)
455  return;
456 
457  string message;
458  if (m_Widgets.m_MessageEditBox)
459  message = m_Widgets.m_MessageEditBox.GetText();
460  else
461  return;
462 
463  // Check if we want to send some command
464  string cmd = this.GetCommand(message);
465 
466  // If there's a command, we don't want to really send the message
467  // Note: by now the channel tag or player name have been already removed from the message,
468  // so there is no command here any more
469  if (!cmd.IsEmpty())
470  {
471  // Notify the chat panel mgr, pass the message with removed command
472  message = message.Substring(cmd.Length() + 1, message.Length() - cmd.Length() - 1);
473  message.TrimInPlace();
474 
475  mgr.Internal_OnChatCommand(this, cmd, message);
476 
477  return;
478  }
479 
480  if (!m_ActiveChannel.IsAvailable(chatComponent))
481  {
482  SCR_ChatMessageStyle style = this.GetChannelStyle(m_ActiveChannel);
483  SCR_ChatPanelManager.GetInstance().ShowHelpMessage(STR_CHANNEL_DISABLED);
484  }
485  else
486  {
487  if (PrivateMessageChannel.Cast(m_ActiveChannel))
488  {
489  // Get whisper receiver ID
490  int nameLength;
491  int playerId = this.GetPlayerIdByName(cmd);
492 
493  if (playerId != -1)
494  {
495  // Remove player name from the message
496  message = message.Substring(nameLength + 1, message.Length() - nameLength - 1);
497 
498  chatComponent.SendPrivateMessage(message, playerId);
499  }
500  }
501  else
502  {
503  int channelId = GetChannelId(m_ActiveChannel);
504  chatComponent.SendMessage(message, channelId);
505  }
506  }
507  }
508 
509 
510 
511  //------------------------------------------------------------------------------------------------
513  protected void CycleChannels(bool next)
514  {
515  if (!m_ChatEntity)
516  return;
517 
518  SCR_ChatComponent chatComponent = GetChatComponent();
519 
520  if (!chatComponent)
521  return;
522 
523  int id = 0;
524 
525  if (m_ActiveChannel)
526  id = GetChannelId(m_ActiveChannel);
527 
528  int nTries = 0;
529  int channelCount = m_ChatEntity.GetChannelsCount();
530 
531  while (nTries < channelCount)
532  {
533  if (next)
534  {
535  id++;
536  if (id == channelCount)
537  id = 0;
538  }
539  else
540  {
541  id--;
542  if (id == -1)
543  id = channelCount - 1;
544  }
545 
546  BaseChatChannel channel = m_ChatEntity.GetChannel(id);
547 
548  if (channel.IsAvailable(chatComponent))
549  {
550  this.SetActiveChannel(channel);
551  return;
552  }
553 
554  nTries++;
555  }
556  }
557 
558 
559 
560  //------------------------------------------------------------------------------------------------
561  protected void ShowChannelWarning(BaseChatChannel Chatchannel = null, string message = "")
562  {
563  if (Chatchannel && message == string.Empty)
564  m_Widgets.m_WarningText.SetText(STR_CHANNEL_DISABLED);
565  else
566  m_Widgets.m_WarningText.SetText(message);
567 
568  m_Widgets.m_WarningChannelMessage.SetVisible(true);
569  }
570 
571 
572 
573  //------------------------------------------------------------------------------------------------
576  protected string GetCommand(string s)
577  {
578  if (!s.StartsWith(SCR_ChatPanelManager.CHAT_COMMAND_CHARACTER) || s.Length() < 2)
579  return string.Empty;
580 
581  int cmdEnd = s.IndexOf(" ");
582 
583  // No space, everything ot the right of / is command
584  if (cmdEnd == -1)
585  cmdEnd = s.Length();
586 
587  string ret = s.Substring(1, cmdEnd - 1);
588  ret.ToLower();
589 
590  return ret;
591  }
592 
593 
594 
595  //------------------------------------------------------------------------------------------------
597  string Internal_GetChannelListHelpMessage()
598  {
599  SCR_ChatComponent chatComponent = GetChatComponent();
600 
601  if (!m_ChatEntity || !chatComponent)
602  return string.Empty;
603 
604  BaseChatChannel chatChannel;
605  string help_message = STR_AVAILABLE_CHANNELS +": ";
606  for (int j = 0; j < m_ChatEntity.GetChannelsCount(); j++)
607  {
608  if (chatComponent.GetChannelState(j))
609  {
610  chatChannel = m_ChatEntity.GetChannel(j);
611  if (chatChannel.IsAvailable(chatComponent))
612  {
613  SCR_ChatMessageStyle style = GetChannelStyle(chatChannel);
614 
615  // Resolve color of the channel icon
616  Color imageColor = Color.FromInt(Color.WHITE);
617  if (style.m_bColoredIcon)
618  imageColor = style.m_Color;
619 
620  string tagImage = string.Format("<image set=\"%1\" name=\"%2\" scale=\"1\"/>",
621  style.m_IconImageset,
622  style.m_sIconName);
623 
624  string tagImageColored = SCR_RichTextTags.TagColor(tagImage, imageColor);
625 
626  help_message += string.Format("\n /%1 %2 %3",
627  style.m_sPrefix,
628  tagImageColored,
629  style.m_sName);
630  }
631  }
632 
633  }
634 
635  return help_message;
636  }
637 
638 
639 
640  //------------------------------------------------------------------------------------------------
641  protected BaseChatChannel FindChannelByPrefix(string prefix)
642  {
643  if (!m_ChatEntity)
644  return null;
645 
646  bool found = false;
647  int i = 0;
648  int channelCount = m_ChatEntity.GetChannelsCount();
649  while (!found && i < channelCount)
650  {
651  BaseChatChannel channel = m_ChatEntity.GetChannel(i);
652  SCR_ChatMessageStyle style = GetChannelStyle(channel);
653 
654  if (style)
655  {
656  if (style.m_sPrefix == prefix)
657  return channel;
658  }
659 
660  i++;
661  }
662  return null;
663  }
664 
665 
666 
667  //------------------------------------------------------------------------------------------------
668  protected int GetPlayerIdByName(string name)
669  {
670  if (name.IsEmpty())
671  return -1;
672 
673  PlayerManager pm = GetGame().GetPlayerManager();
674  // All players because the message could be from someone who already disconnected
675  array<int> players;
676  pm.GetAllPlayers(players);
677 
678  for (int i = pm.GetAllPlayerCount() - 1; i >= 0; --i)
679  {
680  if (pm.GetPlayerName(i) == name)
681  return i;
682  }
683 
684  return -1;
685  }
686 
687 
688 
689  //------------------------------------------------------------------------------------------------
691  protected void SetActiveChannel(notnull BaseChatChannel channel, string ReceiverName = string.Empty)
692  {
693  SCR_ChatComponent chatComponent = GetChatComponent();
694 
695  if (!chatComponent || !m_ChatEntity)
696  return;
697 
698  int channelId = m_ChatEntity.GetChannelId(channel);
699  m_Widgets.m_WarningChannelMessage.SetVisible(false);
700  m_ActiveChannel = channel;
701 
702  SCR_ChatMessageStyle style = m_SystemChannelStyle;
703 
704  // Set color and image of the channel tag
705 
706  // Resolve style
707  style = GetChannelStyle(m_ActiveChannel);
708 
709  Color color = Color.FromInt(Color.WHITE);
710  if (style.m_bColoredIcon)
711  {
712  color = style.m_Color;
713  }
714  m_Widgets.m_ChannelTypeImage.SetColor(color);
715  m_Widgets.m_ChannelTagEditor.SetColor(color);
716  string chatTypeImageName = style.m_sIconName;
717  if (!chatTypeImageName.IsEmpty())
718  m_Widgets.m_ChannelTypeImage.LoadImageFromSet(0, style.m_IconImageset, chatTypeImageName);
719 
720  string channelName = style.m_sName;
721 
722  if (PrivateMessageChannel.Cast(channel))
723  {
724  if (ReceiverName != string.Empty)
725  {
726  m_Widgets.m_ChannelTagEditor.SetText(channelName + " " + ReceiverName);
727  m_Widgets.m_ChannelTagOverlay.SetText(channelName + " " + ReceiverName);
728  }
729  }
730  else if (chatComponent.GetChannelState(channel))
731  {
732  if (m_ActiveChannel)
733  {
734  if (m_Widgets.m_ChannelTagOverlay)
735  {
736  m_Widgets.m_ChannelTagEditor.SetText(channelName);
737  string tagOverlayText = string.Format(WidgetManager.Translate("#AR-Chat_SendToChannel", WidgetManager.Translate(style.m_sNameLower)));
738  m_Widgets.m_ChannelTagOverlay.SetText(tagOverlayText);
739  }
740  }
741  }
742  }
743 
744 
745 
746  //------------------------------------------------------------------------------------------------
747  protected void VerifyChannelStyles()
748  {
749  int n = 0;
750 
751  // Ensure at least system style is available
752  if (!m_SystemChannelStyle)
753  {
754  m_SystemChannelStyle = new SCR_ChatMessageStyle();
755  n++;
756  }
757 
758 
759  array<Managed> styles = {
760  m_SystemChannelStyle,
761  m_RadioProtocolStyle,
762  m_GlobalChannelStyle,
763  m_FactionChannelStyle,
764  m_VehicleChannelStyle,
765  m_LocalChannelStyle,
766  m_DirectChannelStyle
767  };
768 
769  foreach (Managed style : styles)
770  {
771  if (!style)
772  n++;
773  }
774 
775  if (n > 0)
776  {
777  string s = string.Format("[Chat] %1 chat channel styles are not configured.", n);
778  Print(s, LogLevel.ERROR);
779  }
780  }
781 
782 
783 
784  //------------------------------------------------------------------------------------------------
786  protected SCR_ChatMessageStyle GetChannelStyle(BaseChatChannel channel)
787  {
788  if (channel == null)
789  return m_SystemChannelStyle;
790 
791  SCR_ChatMessageStyle style;
792  switch (channel.Type())
793  {
794  case BaseChatChannel:
795  {
796  if (channel.GetName() == "Global")
797  style = m_GlobalChannelStyle;
798  break;
799  }
800 
801  case GroupChatChannel:
802  style = m_GroupChannelStyle;
803  break;
804  case FactionChatChannel:
805  style = m_FactionChannelStyle;
806  break;
808  style = m_VehicleChannelStyle;
809  break;
810  case LocalChatChannel:
811  style = m_LocalChannelStyle;
812  break;
814  style = m_DirectChannelStyle;
815  break;
816  }
817 
818  if (!style)
819  return m_SystemChannelStyle;
820 
821  return style;
822  }
823 
824 
825 
826  //------------------------------------------------------------------------------------------------
827  protected SCR_ChatMessageStyle GetMessageStyle(notnull SCR_ChatMessage msg)
828  {
829  // Is it a radio protocol msg? Radio protocol is msg is special.
830  if (SCR_ChatMessageRadioProtocol.Cast(msg))
831  return m_RadioProtocolStyle;
832 
833  // Is it a general msg? General msgs have a channel.
834  SCR_ChatMessageGeneral generalMsg = SCR_ChatMessageGeneral.Cast(msg);
835  if (generalMsg)
836  {
837  if (generalMsg.m_Channel)
838  {
839  return GetChannelStyle(generalMsg.m_Channel);
840  }
841  }
842 
843  // Perhaps a system message then or smth similar
844  return m_SystemChannelStyle;
845  }
846 
847 
848 
849  //------------------------------------------------------------------------------------------------
850  protected SCR_ChatComponent GetChatComponent()
851  {
852  PlayerController pc = GetGame().GetPlayerController();
853 
854  if (!pc)
855  return null;
856 
857  return SCR_ChatComponent.Cast(pc.FindComponent(SCR_ChatComponent));
858  }
859 
860 
861  //------------------------------------------------------------------------------------------------
862  protected int GetChannelId(notnull BaseChatChannel channel)
863  {
864  if (!m_ChatEntity)
865  return -1;
866 
867  return m_ChatEntity.GetChannelId(channel);
868  }
869 
870  //------------------------------------------------------------------------------------------------
871  ScriptInvoker GetOnChatOpen()
872  {
873  if (!m_OnChatOpen)
874  m_OnChatOpen = new ScriptInvoker();
875  return m_OnChatOpen;
876  }
877 
878  //------------------------------------------------------------------------------------------------
879  ScriptInvoker GetOnChatClosed()
880  {
881  if (!m_OnChatClosed)
882  m_OnChatClosed = new ScriptInvoker();
883  return m_OnChatClosed;
884  }
885 
886  //------------------------------------------------------------------------------------------------
887  SCR_FadeInOutAnimator GetFadeInOutAnimator()
888  {
889  return m_MessageHistoryAnimator;
890  }
891 
892 
893 
894 
895 
896  //------------------------------------------------------------------------------------------------
897  // CALLBACKS AND ACTIONS
898 
899 
900  //------------------------------------------------------------------------------------------------
902  protected void Callback_OnPressSpaceAfterCommand()
903  {
904  if (!m_bOpen)
905  return;
906 
907  SCR_ChatComponent chatComponent = GetChatComponent();
908 
909  if (!chatComponent)
910  return;
911 
912  string message;
913 
914  message = m_Widgets.m_MessageEditBox.GetText();
915  string cmd = this.GetCommand(message);
916 
917  // Do nothing if there is no command
918  // Or the command doesn't appear to be a channel tag
919  if (cmd.IsEmpty() || cmd.Length() != 1 || !("0123456789".Contains(cmd)))
920  return;
921 
922  BaseChatChannel channel = FindChannelByPrefix(cmd);
923 
924  if (!channel)
925  {
926  ShowChannelWarning(null, STR_CHANNEL_UNKNOWN);
927  return;
928  }
929 
930  // Remove channel prefix
931  message = message.Substring(cmd.Length() + 1, message.Length() - cmd.Length() - 1);
932  message.TrimInPlace();
933 
934  if (channel.IsAvailable(chatComponent))
935  {
936  this.SetActiveChannel(channel);
937  m_Widgets.m_MessageEditBox.SetText(message);
938 
939  // SetText doesn't cause a call to OnChange event handler of the message box
940  // so we call it ourselves
941  Callback_OnEditBoxChange();
942  }
943  else
944  {
945  ShowChannelWarning(channel, STR_CHANNEL_DISABLED);
946  }
947  }
948 
949  //------------------------------------------------------------------------------------------------
951  protected void Callback_OnCloseAction()
952  {
953  Internal_Close();
954  }
955 
956 
957  //------------------------------------------------------------------------------------------------
959  protected void Callback_OnSendMessageAction()
960  {
961  if (!m_bOpen)
962  return;
963 
964  if (!m_Widgets.m_MessageEditBox.GetText().IsEmpty())
965  SendMessage();
966 
967  Internal_Close();
968 
969  // Do nothing if it's closed. It's opened externally.
970  }
971 
972 
973  //------------------------------------------------------------------------------------------------
976  protected void Callback_OnGamepadConfirmAction()
977  {
978  if (!m_bOpen)
979  return;
980 
981  Widget wFocused = GetGame().GetWorkspace().GetFocusedWidget();
982  if (wFocused != m_Widgets.m_MessageEditBox)
983  GetGame().GetWorkspace().SetFocusedWidget(m_Widgets.m_MessageEditBox);
984 
985  if (!m_Widgets.m_MessageEditBox.IsInWriteMode())
986  m_Widgets.m_MessageEditBox.ActivateWriteMode();
987  }
988 
989 
990  //------------------------------------------------------------------------------------------------
992  protected void Callback_OnHistoryAction(float value)
993  {
994  if (!m_bOpen)
995  return;
996 
997  SCR_ChatPanelManager mgr = SCR_ChatPanelManager.GetInstance();
998 
999  // Minimum how many messages we want to show while scrolling
1000  // When too few messages, chat looks weird
1001  // todo we shouldn't use message count but instead real positioning of msg widget
1002  // because messages might be multiline
1003  int minHistoryOffset = m_iMessageLineCount;
1004 
1005  array<ref SCR_ChatMessage> messages = mgr.GetMessages();
1006  int messagesCount = messages.Count();
1007 
1008  if (value != 0)
1009  {
1010  if (messagesCount < minHistoryOffset)
1011  {
1012  // Too few messages to scroll
1013  m_iHistoryId = messagesCount - 1;
1014  m_iHistoryIdLowestMessage = m_iHistoryId;
1015  m_bHistoryMode = false;
1016  }
1017  else
1018  {
1019  m_iHistoryId -= value;
1020  int lastMessageId = messagesCount - 1;
1021  m_iHistoryId = Math.ClampInt(m_iHistoryId, minHistoryOffset - 1, lastMessageId);
1022 
1023  int linesCount = 0;
1024  int offset;
1025  bool increasing = true;
1026  int step = 1;
1027  bool hadToIncrease;
1028 
1029  while (linesCount < m_iMessageLineCount && messagesCount > m_iHistoryId - offset && m_iHistoryId - offset >= -1)
1030  {
1031  linesCount += 1;
1032  if (m_iHistoryId - offset > m_iHistoryId)
1033  m_iHistoryIdLowestMessage = m_iHistoryId - offset;
1034  else
1035  m_iHistoryIdLowestMessage = m_iHistoryId;
1036 
1037  offset += step;
1038 
1039  if (step < 0)
1040  hadToIncrease = true; // This ensures we don't scroll history id unnecesarily too deep (deeper than what's visible)
1041 
1042  if (m_iHistoryId - offset < 0) // No more messges above this one, we have to try the other way
1043  {
1044  step = -1;
1045  offset = -1;
1046 
1047  if (linesCount >= m_iMessageLineCount) // Reached max at the first message -> make sure to show it
1048  m_iHistoryIdLowestMessage = m_iHistoryId;
1049  }
1050  else if (m_iHistoryId - offset >= messagesCount) // Ran out of messages, abort
1051  break;
1052  }
1053 
1054  if (hadToIncrease)
1055  m_iHistoryId += value;
1056 
1057  m_bHistoryMode = m_iHistoryId != lastMessageId;
1058  UpdateChatMessages();
1059  }
1060  }
1061  }
1062 
1063  //------------------------------------------------------------------------------------------------
1065  protected void Callback_OnSwitchChannelAction(float value, EActionTrigger reason)
1066  {
1067  if (!m_bOpen)
1068  return;
1069 
1070  if (value != 0)
1071  {
1072  bool direction = value > 0;
1073  CycleChannels(direction);
1074  }
1075  }
1076 
1077  //------------------------------------------------------------------------------------------------
1079  protected void Callback_OnEditBoxChange()
1080  {
1081  if (!m_bOpen)
1082  return;
1083 
1084  int textLen = m_Widgets.m_MessageEditBox.GetText().Length();
1085  m_Widgets.m_ChannelTagOverlay.SetVisible(textLen == 0); // Visible when there is no text
1086  }
1087 }
SCR_ChatMessageGeneral
Definition: SCR_ChatMessage.c:19
direction
vector direction
Definition: SCR_DestructibleTreeV2.c:31
ScriptedChatEntity
Definition: ScriptedChatEntity.c:9
m_ChatEntity
protected ScriptedChatEntity m_ChatEntity
Definition: game.c:42
SCR_VehicleChatChannel
Definition: SCR_VehicleChatChannel.c:1
m_wRoot
protected Widget m_wRoot
Definition: SCR_ScenarioFrameworkLayerTaskDefend.c:59
UIConstants
Definition: Constants.c:130
PrivateMessageChannel
Definition: PrivateMessageChannel.c:12
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
SCR_ChatMessageLineComponent
Definition: SCR_ChatMessageLineComponent.c:1
SCR_ChatPanelManager
Definition: SCR_ChatPanelManager.c:12
SCR_ChatMessageRadioProtocol
Definition: SCR_ChatMessage.c:46
m_Widgets
ref SCR_VoNOverlay_ElementWidgets m_Widgets
Definition: SCR_VonDisplay.c:3
SCR_ChatPanel
Definition: SCR_ChatPanel.c:6
Attribute
typedef Attribute
Post-process effect of scripted camera.
SCR_ChatMessageStyle
Definition: SCR_ChatMessageStyle.c:6
SCR_ChatPanelWidgets
Definition: SCR_ChatPanelWidgets.c:4
SCR_ChatMessage
Definition: SCR_ChatMessage.c:7
SCR_FadeInOutAnimator
Definition: SCR_FadeInOutAnimator.c:8
SCR_RichTextTags
Definition: SCR_RichTextTags.c:5
SCR_Global
Definition: Functions.c:6
GetInputManager
protected InputManager GetInputManager()
Definition: SCR_BaseManualCameraComponent.c:65
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
PlayerManager
Definition: PlayerManager.c:12
BaseChatChannel
Definition: BaseChatChannel.c:12
EditBoxFilterComponent
Definition: EditBoxFilterComponent.c:5