Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_FieldManualUI.c
Go to the documentation of this file.
2 {
3  protected TextWidget m_wMenuTitle;
4  protected VerticalLayoutWidget m_wMenuCategoryList;
5  protected SCR_EditBoxSearchComponent m_MenuSearchbar;
6  protected SCR_InputButtonComponent m_MenuBtnBack;
7 
8  protected Widget m_wReadingWidget;
9  protected SCR_BreadCrumbsComponent m_BreadCrumbsComponent;
10  protected TextWidget m_wPageEntryTitle;
11  protected Widget m_wPageFrame;
12  protected ScrollLayoutWidget m_wGridScrollLayoutWidget;
13  protected GridLayoutWidget m_wMenuGridLayout;
14 
15  protected string m_sLastSearch;
16 
17  protected ref SCR_FieldManualConfigRoot m_ConfigRoot;
18  protected ref array<ref SCR_FieldManualConfigEntry> m_aAllEntries;
19  protected ref map<Widget, ref SCR_FieldManualConfigEntry> m_mWidgetEntryMap;
20  protected ref map<Widget, ref SCR_FieldManualConfigCategory> m_mWidgetSubCategoryMap;
21  protected ref SCR_FieldManualSubCategoryScriptedWidgetEventHandler m_SubCategoryButtonEventHandler;
22  protected ref SCR_FieldManualEntryScriptedWidgetEventHandler m_EntryButtonEventHandler;
23  protected Widget m_wLastClickedSubCategory;
24 
25  protected SCR_FieldManualConfigEntry m_CurrentEntry;
26 
27  protected ButtonWidget m_wFirstSubCategoryButton;
28 
29  protected bool m_bIsInEntryViewMode;
30  protected bool m_bIsInSearchMode;
31  protected bool m_bOpenedFromOutside;
32 
33  protected bool m_bArmaWarning;
34 
35  protected static const int TILES_GRID_WIDTH = 5;
36  protected static const string SEARCH_RESULT_KEY = "#AR-FieldManual_SearchResult";
37  protected static const string SEARCH_NO_RESULT_KEY = "#AR-FieldManual_SearchResult_None";
38  protected static const string SCROLL_NAME = "mainScroll";
39  protected static const int ENTRY_INPUT_REFRESH_DELAY = 500; // min time in ms before KBM/pad entry refreshes
40  protected static const int ENTRY_SCROLL_INPUT_REFRESH_DELAY = 1000 / 60; // time in ms between KBM/pad entry scroll refreshes
41 
42  //------------------------------------------------------------------------------------------------
43  protected override void OnMenuOpen()
44  {
45  super.OnMenuOpen();
46 
47  Widget rootWidget = GetRootWidget();
48  SCR_ConfigUIComponent component = SCR_ConfigUIComponent.Cast(rootWidget.FindHandler(SCR_ConfigUIComponent));
49  if (!component)
50  {
51  Print("No config component found | " + __FILE__ + ": " + __LINE__, LogLevel.WARNING);
52  Close();
53  return;
54  }
55 
56  SCR_FieldManualConfigRoot configRoot = SCR_FieldManualConfigLoader.LoadConfigRoot(component.m_ConfigPath);
57  if (!configRoot)
58  {
59  Print("Could not load provided config | " + __FILE__ + ": " + __LINE__, LogLevel.WARNING);
60  Close();
61  return;
62  }
63 
64  m_ConfigRoot = configRoot;
65  SetAllEntriesAndParents();
66 
67  // which background do you want, gents?
68  bool isMainMenu = GetGame().m_bIsMainMenuOpen;
69  Widget blur = GetRootWidget().FindAnyWidget("Blur");
70  Widget backgroundImage = GetRootWidget().FindAnyWidget("MenuBackground");
71  if (blur && isMainMenu)
72  blur.RemoveFromHierarchy();
73 
74  if (backgroundImage && !isMainMenu)
75  backgroundImage.RemoveFromHierarchy();
76 
77  Widget menuFrame = rootWidget.FindAnyWidget("MenuFrame");
78  TextWidget menuTitle = TextWidget.Cast(menuFrame.FindAnyWidget("Title"));
79  VerticalLayoutWidget menuCategoryList = VerticalLayoutWidget.Cast(rootWidget.FindAnyWidget("CategoryList"));
80  GridLayoutWidget menuGridLayout = GridLayoutWidget.Cast(rootWidget.FindAnyWidget("GridLayout"));
81  if (!menuFrame || !menuTitle || !menuCategoryList || !menuGridLayout)
82  {
83  Print("Important elements (menu frame & title, category list, grid layout) are missing | " + __FILE__ + ": " + __LINE__, LogLevel.WARNING);
84  Close();
85  return;
86  }
87 
88  Widget readingWidget = rootWidget.FindAnyWidget("ReadingWidget");
89 
90  TextWidget entryTitle = TextWidget.Cast(readingWidget.FindAnyWidget("EntryTitle"));
91  Widget entryFrame = readingWidget.FindAnyWidget("EntryFrame");
92  if (!readingWidget || !entryTitle || !entryFrame)
93  {
94  Print(string.Format("missing one: reading widget (%1), entryTitle (%2), entryFrame (%3) | " + FilePath.StripPath(__FILE__) + ":" + __LINE__, readingWidget != null, entryTitle != null, entryFrame != null), LogLevel.WARNING);
95  Close();
96  return;
97  }
98 
99  SCR_InputButtonComponent backButtonMenuFrame = SCR_InputButtonComponent.GetInputButtonComponent("Back", menuFrame);
100  if (!backButtonMenuFrame || !backButtonMenuFrame.m_OnClicked)
101  {
102  Print(string.Format("missing menu frame's back button menu (%1) or m_OnClicked (%2) | " + FilePath.StripPath(__FILE__) + ":" + __LINE__, backButtonMenuFrame != null, backButtonMenuFrame.m_OnClicked != null), LogLevel.WARNING);
103  Close();
104  return;
105  }
106 
107  m_MenuBtnBack = backButtonMenuFrame;
108 
109  m_wMenuTitle = menuTitle;
110  m_wMenuCategoryList = menuCategoryList;
111  m_wMenuGridLayout = menuGridLayout;
112 
113  m_wReadingWidget = readingWidget;
114  m_wPageEntryTitle = entryTitle;
115  m_wPageFrame = entryFrame;
116 
117  // breadcrumbs is not mandatory
118  m_BreadCrumbsComponent = SCR_BreadCrumbsComponent.Cast(SCR_BreadCrumbsComponent.GetComponent(SCR_BreadCrumbsComponent, "BreadCrumbs", rootWidget));
119 
120  // scrolling reset is not mandatory
121  m_wGridScrollLayoutWidget = ScrollLayoutWidget.Cast(rootWidget.FindAnyWidget("GridScrollLayout"));
122 
123  // searchbar functionality is not mandatory
124  m_MenuSearchbar = SCR_EditBoxSearchComponent.Cast(SCR_EditBoxSearchComponent.GetEditBoxComponent("Searchbar", rootWidget));
125  if (m_MenuSearchbar && m_MenuSearchbar.m_OnConfirm)
126  m_MenuSearchbar.m_OnConfirm.Insert(ProcessSearch);
127 
128  m_MenuBtnBack.m_OnActivated.Insert(CloseMenuOrReadingPanel);
129 
130 #ifdef WORKBENCH
131  InputManager inputManager = GetGame().GetInputManager();
132  if (inputManager)
133  {
134  inputManager.AddActionListener("MenuOpenWB", EActionTrigger.DOWN, CloseMenuOrReadingPanel);
135  inputManager.AddActionListener("MenuBackWB", EActionTrigger.DOWN, CloseMenuOrReadingPanel);
136  }
137 #endif // WORKBENCH
138 
139  m_SubCategoryButtonEventHandler = new SCR_FieldManualSubCategoryScriptedWidgetEventHandler(this);
140  m_EntryButtonEventHandler = new SCR_FieldManualEntryScriptedWidgetEventHandler(this);
141  }
142 
143  //------------------------------------------------------------------------------------------------
144  protected override void OnMenuShow()
145  {
146  super.OnMenuShow();
147 
148  CreateCategoryMenuWidgets();
149  CloseReadingPanel();
150  OpenFirstSubCategory();
151  }
152 
153 #ifdef WORKBENCH
154  //------------------------------------------------------------------------------------------------
155  protected override void OnMenuClose()
156  {
157  super.OnMenuClose();
158 
159  InputManager inputManager = GetGame().GetInputManager();
160  if (inputManager)
161  {
162  inputManager.RemoveActionListener("MenuOpenWB", EActionTrigger.DOWN, CloseMenuOrReadingPanel);
163  inputManager.RemoveActionListener("MenuBackWB", EActionTrigger.DOWN, CloseMenuOrReadingPanel);
164  }
165  }
166 #endif // WORKBENCH
167 
168  //------------------------------------------------------------------------------------------------
170  void OnSubCategoryClicked(Widget w)
171  {
172  bool resetTiles = m_bIsInSearchMode || m_bIsInEntryViewMode || w != m_wLastClickedSubCategory;
173  m_bIsInSearchMode = false;
174  m_wLastClickedSubCategory = w;
175  CloseReadingPanel();
176  ResetLastSearch();
177  if (resetTiles)
178  SetTilesByWidget(w);
179  }
180 
181  //------------------------------------------------------------------------------------------------
183  void OnTileClicked(Widget w)
184  {
185  m_bIsInSearchMode = false;
186  SetCurrentEntryByWidget(w);
187 
188  if (m_wLastClickedSubCategory)
189  GetGame().GetWorkspace().SetFocusedWidget(m_wLastClickedSubCategory);
190  }
191 
192  //------------------------------------------------------------------------------------------------
194  protected Widget CreateTileWidget(notnull SCR_FieldManualConfigEntry entry, notnull Widget parent)
195  {
196  Widget createdWidget = GetGame().GetWorkspace().CreateWidgets(m_ConfigRoot.m_MenuEntryTileLayout, parent);
197  if (!createdWidget)
198  {
199  Print("could not create tile widget for entry | " + FilePath.StripPath(__FILE__) + ":" + __LINE__, LogLevel.WARNING);
200  return null;
201  }
202 
203  Widget assetImage = createdWidget.FindAnyWidget("AssetImage");
204  if (assetImage)
205  {
206  ImageWidget backgroundImageWidget = ImageWidget.Cast(createdWidget.FindAnyWidget("FullBackground"));
207  if (backgroundImageWidget && m_ConfigRoot.m_aTileBackgrounds && !m_ConfigRoot.m_aTileBackgrounds.IsEmpty())
208  backgroundImageWidget.LoadImageTexture(0, m_ConfigRoot.m_aTileBackgrounds.GetRandomElement());
209 
210  ImageWidget imageWidget = ImageWidget.Cast(assetImage.FindAnyWidget("Image"));
211  if (imageWidget)
212  {
213  if (!entry.m_Image.IsEmpty())
214  imageWidget.LoadImageTexture(0, entry.m_Image);
215  else
216  imageWidget.SetVisible(false);
217  }
218  }
219 
220  Widget assetInfo = createdWidget.FindAnyWidget("AssetInfo");
221  if (assetInfo)
222  {
223  TextWidget textWidget = TextWidget.Cast(assetInfo.FindAnyWidget("EntityName"));
224  if (textWidget)
225  textWidget.SetText(entry.m_sTitle);
226  }
227 
228  return createdWidget;
229  }
230 
231  //------------------------------------------------------------------------------------------------
233  // used in SCR_FieldManualSubCategoryScriptedWidgetEventHandler.OnClick
234  protected void SetTilesByWidget(Widget widget)
235  {
236  SCR_FieldManualConfigCategory subCategory = m_mWidgetSubCategoryMap.Get(widget);
237 
238  if (!subCategory)
239  return;
240 
241  if (m_BreadCrumbsComponent && subCategory.m_Parent)
242  m_BreadCrumbsComponent.Set(subCategory.m_Parent.m_sTitle, subCategory.m_sTitle);
243 
244  SetTiles(subCategory.m_aEntries);
245  }
246 
247  //------------------------------------------------------------------------------------------------
249  protected void SetTiles(array<ref SCR_FieldManualConfigEntry> entries)
250  {
251  if (!m_wMenuGridLayout)
252  return;
253 
254  SCR_WidgetHelper.RemoveAllChildren(m_wMenuGridLayout);
255 
256  if (!entries || entries.IsEmpty())
257  return;
258 
259  m_mWidgetEntryMap.Clear();
260 
261  int column, line;
262  Widget assetCard;
263  ButtonWidget button;
264  foreach (SCR_FieldManualConfigEntry entry : entries)
265  {
266  assetCard = CreateTileWidget(entry, m_wMenuGridLayout);
267  if (!assetCard)
268  continue;
269 
270  GridSlot.SetColumn(assetCard, column);
271  GridSlot.SetRow(assetCard, line);
272 
273  column++;
274  if (column >= TILES_GRID_WIDTH)
275  {
276  column = 0;
277  line++;
278  }
279 
280  button = ButtonWidget.Cast(SCR_WidgetHelper.GetWidgetOrChild(assetCard, "AssetCard0"));
281  if (button)
282  {
283  button.AddHandler(m_EntryButtonEventHandler);
284  m_mWidgetEntryMap.Insert(button, entry);
285  }
286  }
287 
288  if (m_wGridScrollLayoutWidget)
289  m_wGridScrollLayoutWidget.SetSliderPos(0, 0);
290  }
291 
292  //------------------------------------------------------------------------------------------------
294  protected void SetCurrentEntry(SCR_FieldManualConfigEntry entry)
295  {
296  if (!m_wPageFrame || !m_wPageEntryTitle)
297  return;
298 
299  SCR_WidgetHelper.RemoveAllChildren(m_wPageFrame);
300 
301  m_bIsInEntryViewMode = entry != null;
302 
303  m_wGridScrollLayoutWidget.SetVisible(!m_bIsInEntryViewMode);
304  m_wReadingWidget.SetVisible(m_bIsInEntryViewMode);
305 
306  if (!m_bIsInEntryViewMode)
307  {
308  if (m_BreadCrumbsComponent && m_CurrentEntry && m_CurrentEntry.m_Parent && m_CurrentEntry.m_Parent.m_Parent)
309  m_BreadCrumbsComponent.Set(m_CurrentEntry.m_Parent.m_Parent.m_sTitle, m_CurrentEntry.m_Parent.m_sTitle);
310 
311  m_CurrentEntry = null;
312  return;
313  }
314 
315  if (m_BreadCrumbsComponent && entry.m_Parent && entry.m_Parent.m_Parent)
316  m_BreadCrumbsComponent.Set(entry.m_Parent.m_Parent.m_sTitle, entry.m_Parent.m_sTitle, entry.m_sTitle);
317 
318  m_CurrentEntry = entry;
319 
320  m_wPageEntryTitle.SetText(entry.m_sTitle);
321 
322  // entry tab management - disabled for now
323 // if (m_PageTabView)
324 // {
325 // while (m_PageTabView.GetTabCount() > 0)
326 // {
327 // m_PageTabView.RemoveTab(0);
328 // }
329 // m_PageTabView.AddTab("", entry.m_sTitle);
330 // m_PageTabView.ShowTab(0, false, false);
331 // }
332 
333  Widget readingWidget = entry.CreateWidget(m_wPageFrame);
335  if (weaponEntry)
336  FillEntry_Weapon(readingWidget, weaponEntry);
337  }
338 
339  //------------------------------------------------------------------------------------------------
341  protected void QueueRefreshCurrentEntry()
342  {
343  if (!m_CurrentEntry || !m_CurrentEntry.CanRefresh())
344  return;
345 
346  // safety to not saturate the call queue if someone has fun using pad and kbm at the same time
347  GetGame().GetCallqueue().Remove(RefreshCurrentEntry); // in case it was added
348  GetGame().GetCallqueue().CallLater(RefreshCurrentEntry, ENTRY_INPUT_REFRESH_DELAY, false);
349  }
350 
351  //------------------------------------------------------------------------------------------------
353  protected void RefreshCurrentEntry()
354  {
355  if (!m_CurrentEntry.CanRefresh())
356  return;
357 
358  float x, y;
359  ScrollLayoutWidget scroll = ScrollLayoutWidget.Cast(m_wPageFrame.FindWidget(SCROLL_NAME)); // a bit ugly?
360  if (scroll)
361  scroll.GetSliderPos(x, y);
362 
363  SetCurrentEntry(m_CurrentEntry);
364 
365  if (!scroll)
366  return;
367 
368  scroll = ScrollLayoutWidget.Cast(m_wPageFrame.FindWidget(SCROLL_NAME));
369  if (scroll)
370  SetScrollAfterRefresh(scroll, x, y);
371  }
372 
373  //------------------------------------------------------------------------------------------------
374  protected void SetScrollAfterRefresh(notnull ScrollLayoutWidget scroll, float x, float y)
375  {
376  float w, h;
377  scroll.GetScreenSize(w, h);
378  if (h <= 0) // ugly, but no other choice as setting scroll right after Widget creation does nothing
379  {
380  GetGame().GetCallqueue().CallLater(SetScrollAfterRefresh, ENTRY_SCROLL_INPUT_REFRESH_DELAY, false, scroll, x, y);
381  }
382  else
383  {
384  GetGame().GetCallqueue().Remove(SetScrollAfterRefresh); // safety, as spam occured
385  scroll.SetSliderPos(x, y);
386  }
387  }
388 
389  //------------------------------------------------------------------------------------------------
392  void OpenEntry(EFieldManualEntryId entryId)
393  {
394  if (entryId == EFieldManualEntryId.NONE)
395  {
396  SetCurrentEntry(null);
397  return;
398  }
399 
400  foreach (SCR_FieldManualConfigEntry entry : m_aAllEntries)
401  {
402  if (entry.m_eId == entryId)
403  {
404  m_bOpenedFromOutside = true;
405  SetCurrentEntry(entry);
406  return;
407  }
408  }
409 
410  SetCurrentEntry(null);
411  }
412 
413  //------------------------------------------------------------------------------------------------
415  protected void SetCurrentEntryByWidget(Widget widget)
416  {
417  SCR_FieldManualConfigEntry entry = m_mWidgetEntryMap.Get(widget);
418  if (!entry)
419  return;
420 
421  SetCurrentEntry(entry);
422  }
423 
424  //------------------------------------------------------------------------------------------------
425  protected void FillEntry_Weapon(notnull Widget widget, notnull SCR_FieldManualConfigEntry_Weapon entry)
426  {
427  Widget weaponRender = widget.FindAnyWidget("weaponRender");
428  if (true /* remove later */ || !FillEntry_Weapon_Render(RenderTargetWidget.Cast(weaponRender), entry.m_sWeaponEntityPath))
429  if (weaponRender)
430  weaponRender.RemoveFromHierarchy();
431 
432  FillEntry_Weapon_Statistics(widget.FindAnyWidget("statsLayout"), entry);
433  }
434 
435  //------------------------------------------------------------------------------------------------
436  protected bool FillEntry_Weapon_Render(RenderTargetWidget renderTarget, ResourceName weaponResourceName)
437  {
438  if (!renderTarget || !weaponResourceName)
439  return false;
440 
441  Resource resource = Resource.Load(weaponResourceName);
442  IEntity entity = GetGame().SpawnEntityPrefabLocal(resource, null, null);
443  if (!entity)
444  return false;
445 
446  ChimeraWorld world = ChimeraWorld.CastFrom(GetGame().GetWorld());
447  if (!world)
448  return false;
449 
450  ItemPreviewManagerEntity manager = world.GetItemPreviewManager();
451  if (!manager)
452  return false;
453 
454  ItemPreviewWidget renderPreview = ItemPreviewWidget.Cast(renderTarget);
455  if (!renderPreview)
456  return false;
457 
458  manager.SetPreviewItem(renderPreview, entity);
459  return true;
460  }
461 
462  //------------------------------------------------------------------------------------------------
463  protected void FillEntry_Weapon_Statistics(Widget statsLayout, SCR_FieldManualConfigEntry_Weapon entry)
464  {
465  if (!statsLayout)
466  return;
467 
468  SCR_FieldManualUI_WeaponStatsHelper weaponStatsHelper = entry.m_WeaponStatsHelper;
469  if (!weaponStatsHelper)
470  {
471  SCR_WidgetHelper.RemoveAllChildren(statsLayout);
472  return;
473  }
474 
475  FillEntry_Weapon_Statistics_Mass(statsLayout, weaponStatsHelper);
476  FillEntry_Weapon_Statistics_SightAdjustments(statsLayout, weaponStatsHelper);
477  FillEntry_Weapon_Statistics_DefaultSightAdjustment(statsLayout, weaponStatsHelper);
478  FillEntry_Weapon_Statistics_RateOfFire(statsLayout, weaponStatsHelper);
479  FillEntry_Weapon_Statistics_MuzzleVelocity(statsLayout, weaponStatsHelper);
480  FillEntry_Weapon_Statistics_FireModes(statsLayout, weaponStatsHelper);
481  }
482 
483  //------------------------------------------------------------------------------------------------
484  protected void FillEntry_Weapon_Statistics_Mass(notnull Widget statsLayout, notnull SCR_FieldManualUI_WeaponStatsHelper weaponStatsHelper)
485  {
486  SCR_FieldManual_StatisticsLineComponent statsMass = SCR_FieldManual_StatisticsLineComponent.GetComponent(statsLayout, "statsWeight");
487  if (!statsMass)
488  return;
489 
490  float mass = weaponStatsHelper.GetMass();
491  if (mass < 0)
492  statsMass.RemoveWidgetFromHierarchy();
493  else
494  statsMass.SetTranslatedValue("#AR-ValueUnit_Short_Kilograms", mass.ToString(-1, 2));
495  }
496 
497  //------------------------------------------------------------------------------------------------
498  protected void FillEntry_Weapon_Statistics_SightAdjustments(notnull Widget statsLayout, notnull SCR_FieldManualUI_WeaponStatsHelper weaponStatsHelper)
499  {
500  SCR_FieldManual_StatisticsLineComponent statsSightAdjustments = SCR_FieldManual_StatisticsLineComponent.GetComponent(statsLayout, "statsSightAdjustments");
501  if (!statsSightAdjustments)
502  return;
503 
504  array<int> sightDistanceSettings = weaponStatsHelper.GetSightDistanceSettings();
505  if (!sightDistanceSettings || sightDistanceSettings.IsEmpty())
506  {
507  statsSightAdjustments.RemoveWidgetFromHierarchy();
508  return;
509  }
510 
511  array<string> settingsStr = {};
512  foreach (int sightDistanceSetting : sightDistanceSettings)
513  {
514  settingsStr.Insert(WidgetManager.Translate("#AR-ValueUnit_Short_Meters", sightDistanceSetting));
515  }
516 
517  statsSightAdjustments.SetValue(ArrayJoin(settingsStr));
518  }
519 
520  //------------------------------------------------------------------------------------------------
521  protected void FillEntry_Weapon_Statistics_DefaultSightAdjustment(notnull Widget statsLayout, notnull SCR_FieldManualUI_WeaponStatsHelper weaponStatsHelper)
522  {
523  SCR_FieldManual_StatisticsLineComponent statsDefaultSightAdjustment = SCR_FieldManual_StatisticsLineComponent.GetComponent(statsLayout, "statsDefaultSightAdjustment");
524  if (!statsDefaultSightAdjustment)
525  return;
526 
527  int defaultSightDistanceSetting = weaponStatsHelper.GetDefaultSightDistanceSetting();
528  if (defaultSightDistanceSetting < 0)
529  statsDefaultSightAdjustment.RemoveWidgetFromHierarchy();
530  else
531  statsDefaultSightAdjustment.SetTranslatedValue("#AR-ValueUnit_Short_Meters", defaultSightDistanceSetting.ToString());
532  }
533 
534  //------------------------------------------------------------------------------------------------
535  protected void FillEntry_Weapon_Statistics_RateOfFire(notnull Widget statsLayout, notnull SCR_FieldManualUI_WeaponStatsHelper weaponStatsHelper)
536  {
537  SCR_FieldManual_StatisticsLineComponent statsRateOfFire = SCR_FieldManual_StatisticsLineComponent.GetComponent(statsLayout, "statsRateOfFire");
538  if (!statsRateOfFire)
539  return;
540 
541  if (weaponStatsHelper.GetRateOfFire() < 1)
542  statsRateOfFire.RemoveWidgetFromHierarchy();
543  else
544  statsRateOfFire.SetTranslatedValue("#AR-ValueUnit_Short_RoundsPerMinute", weaponStatsHelper.GetRateOfFire().ToString());
545  }
546 
547  //------------------------------------------------------------------------------------------------
548  protected void FillEntry_Weapon_Statistics_MuzzleVelocity(notnull Widget statsLayout, notnull SCR_FieldManualUI_WeaponStatsHelper weaponStatsHelper)
549  {
550  SCR_FieldManual_StatisticsLineComponent statsMuzzleVelocity = SCR_FieldManual_StatisticsLineComponent.GetComponent(statsLayout, "statsMuzzleVelocity");
551  if (!statsMuzzleVelocity)
552  return;
553 
554  if (weaponStatsHelper.m_iMuzzleVelocity < 1)
555  statsMuzzleVelocity.RemoveWidgetFromHierarchy();
556  else
557  statsMuzzleVelocity.SetTranslatedValue("#AR-ValueUnit_Short_MetersPerSeconds", weaponStatsHelper.m_iMuzzleVelocity.ToString());
558  }
559 
560  //------------------------------------------------------------------------------------------------
561  protected void FillEntry_Weapon_Statistics_FireModes(notnull Widget statsLayout, notnull SCR_FieldManualUI_WeaponStatsHelper weaponStatsHelper)
562  {
563  SCR_FieldManual_StatisticsLineComponent statsFireModes = SCR_FieldManual_StatisticsLineComponent.GetComponent(statsLayout, "statsFireModes");
564  if (!statsFireModes)
565  return;
566 
567  array<string> fireModes = weaponStatsHelper.GetFireModes();
568  if (!fireModes || fireModes.IsEmpty())
569  statsFireModes.RemoveWidgetFromHierarchy();
570  else
571  statsFireModes.SetValue(ArrayJoin(fireModes));
572  }
573 
574  //------------------------------------------------------------------------------------------------
576  // TODO: break down in smaller methods?
577  protected void SetAllEntriesAndParents()
578  {
579  m_aAllEntries.Clear();
580  array<SCR_FieldManualConfigCategory> categoriesToRemove = {};
581  array<SCR_FieldManualConfigCategory> subCategoriesToRemove = {};
582  array<SCR_FieldManualConfigEntry> entriesToRemove = {};
583  foreach (SCR_FieldManualConfigCategory category : m_ConfigRoot.m_aCategories)
584  {
585  if (!category.m_bEnabled)
586  {
587  categoriesToRemove.Insert(category);
588  continue;
589  }
590 
591  subCategoriesToRemove.Clear();
592  foreach (SCR_FieldManualConfigCategory subCategory : category.m_aCategories) // only two levels are supported by the UI for now
593  {
594  if (!subCategory.m_bEnabled)
595  {
596  subCategoriesToRemove.Insert(subCategory);
597  continue;
598  }
599 
600  entriesToRemove.Clear();
601  foreach (SCR_FieldManualConfigEntry entry : subCategory.m_aEntries)
602  {
603  if (!entry.m_bEnabled || entry.m_aContent.IsEmpty())
604  {
605  entriesToRemove.Insert(entry);
606  continue;
607  }
608 
609  entry.m_Parent = subCategory;
610  m_aAllEntries.Insert(entry);
611  }
612 
613  foreach (SCR_FieldManualConfigEntry entry : entriesToRemove)
614  {
615  subCategory.m_aEntries.RemoveItemOrdered(entry);
616  }
617 
618  if (subCategory.m_aEntries.IsEmpty() && subCategory.m_aCategories.IsEmpty())
619  {
620  subCategoriesToRemove.Insert(subCategory);
621  continue;
622  }
623 
624  subCategory.m_Parent = category;
625  }
626 
627  foreach (SCR_FieldManualConfigCategory subCategory : subCategoriesToRemove)
628  {
629  category.m_aCategories.RemoveItemOrdered(subCategory);
630  }
631 
632  if (category.m_aEntries.IsEmpty() && category.m_aCategories.IsEmpty())
633  categoriesToRemove.Insert(category);
634  }
635 
636  foreach (SCR_FieldManualConfigCategory category : categoriesToRemove)
637  {
638  m_ConfigRoot.m_aCategories.RemoveItemOrdered(category);
639  }
640  }
641 
642  //------------------------------------------------------------------------------------------------
644  protected void CreateCategoryMenuWidgets()
645  {
646  if (!m_ConfigRoot || !m_ConfigRoot.m_aCategories || !m_wMenuCategoryList)
647  return;
648 
649  m_wFirstSubCategoryButton = null;
650  m_mWidgetSubCategoryMap.Clear();
651  SCR_WidgetHelper.RemoveAllChildren(m_wMenuCategoryList);
652 
653  if (m_wMenuTitle)
654  m_wMenuTitle.SetText(m_ConfigRoot.m_sTitle);
655 
656  Widget subCategoryWidget;
657  ButtonWidget button;
658  foreach (SCR_FieldManualConfigCategory category : m_ConfigRoot.m_aCategories)
659  {
660  category.CreateWidget(m_wMenuCategoryList);
661 
662  foreach (SCR_FieldManualConfigCategory subCategory : category.m_aCategories)
663  {
664  subCategoryWidget = subCategory.CreateWidget(m_wMenuCategoryList);
665  button = ButtonWidget.Cast(subCategoryWidget);
666  if (button)
667  {
668  button.AddHandler(m_SubCategoryButtonEventHandler);
669  m_mWidgetSubCategoryMap.Insert(button, subCategory);
670 
671  if (!m_wFirstSubCategoryButton)
672  m_wFirstSubCategoryButton = button;
673  }
674  }
675  }
676  }
677 
678  //------------------------------------------------------------------------------------------------
680  protected void OpenFirstSubCategory()
681  {
682  OnSubCategoryClicked(m_wFirstSubCategoryButton);
683  GetGame().GetCallqueue().CallLater(GetGame().GetWorkspace().SetFocusedWidget, 0, false, m_wFirstSubCategoryButton, false);
684  }
685 
686  //------------------------------------------------------------------------------------------------
688  // used in SCR_FieldManualSubCategoryScriptedWidgetEventHandler.OnClick
689  protected void ResetLastSearch()
690  {
691  m_sLastSearch = string.Empty;
692  }
693 
694  //------------------------------------------------------------------------------------------------
696  protected void ProcessSearch(SCR_EditBoxSearchComponent searchbox, string search)
697  {
698  search = search.Trim();
699 
700  if (search.IsEmpty())
701  {
702  ResetLastSearch();
703 // if (m_bIsInSearchMode)
704 // OpenFirstSubCategory();
705 
706  return;
707  }
708 
709  CloseReadingPanel();
710 
711  if (!m_bArmaWarning && search.Contains("ArmA"))
712  {
713  m_bArmaWarning = true;
714 
715  if (m_BreadCrumbsComponent)
716  m_BreadCrumbsComponent.Set("#AR-FieldManual_Page_EasterEgg_ArmA_BreadCrumbs");
717 
719  ArmaEntry.m_sTitle = "#AR-FieldManual_Page_EasterEgg_ArmA_Title";
721  ArmaPiece.m_sText = "#AR-FieldManual_Page_EasterEgg_ArmA_Text";
722  ArmaEntry.m_aContent.Insert(ArmaPiece);
723  SetCurrentEntry(ArmaEntry);
724 
725  EditBoxWidget searchEditBox = EditBoxWidget.Cast(GetRootWidget().FindAnyWidget("Searchbar").FindAnyWidget("EditBox"));
726  string searchText = searchEditBox.GetText();
727  searchText.Replace("ArmA", "Arma");
728  searchEditBox.SetText(searchText);
729 
730  ResetLastSearch();
731 
732  return;
733  }
734 
735  m_bIsInSearchMode = true;
736 
737  string originalSearch = search;
738  search.ToLower();
739  if (search == m_sLastSearch)
740  return;
741 
742  m_sLastSearch = search;
743 
744  array<ref SCR_FieldManualConfigEntry> entries = {};
745 
746  if (!m_sLastSearch.IsEmpty())
747  {
748  array<int> indexList = {};
749 
750  array<string> allEntriesKeys = {};
751  foreach (SCR_FieldManualConfigEntry entry : m_aAllEntries)
752  {
753  allEntriesKeys.Insert(entry.m_sTitle);
754  }
755 
756  WidgetManager.SearchLocalized(m_sLastSearch, allEntriesKeys, indexList);
757 
758  foreach (int index : indexList)
759  {
760  entries.Insert(m_aAllEntries.Get(index));
761  }
762  }
763 
764  if (m_BreadCrumbsComponent)
765  {
766  if (entries.IsEmpty())
767  m_BreadCrumbsComponent.SetRichFormat(SEARCH_NO_RESULT_KEY, originalSearch);
768  else
769  m_BreadCrumbsComponent.SetRichFormat(SEARCH_RESULT_KEY, originalSearch, entries.Count().ToString());
770  }
771 
772  SetTiles(entries);
773  }
774 
775  //------------------------------------------------------------------------------------------------
777  protected void CloseReadingPanel()
778  {
779  SetCurrentEntry(null);
780  }
781 
782  //------------------------------------------------------------------------------------------------
786  protected void CloseMenuOrReadingPanel()
787  {
788  if (m_bIsInEntryViewMode && !m_bOpenedFromOutside)
789  CloseReadingPanel();
790  else
791  Close();
792  }
793 
794  //------------------------------------------------------------------------------------------------
795  //----- STATIC METHODS
796  //------------------------------------------------------------------------------------------------
797 
798  //------------------------------------------------------------------------------------------------
800  static SCR_FieldManualUI Open(EFieldManualEntryId entryId)
801  {
802  SCR_FieldManualUI ui = SCR_FieldManualUI.Cast(GetGame().GetMenuManager().OpenMenu(ChimeraMenuPreset.FieldManualDialog));
803  ui.OpenEntry(entryId);
804  return ui;
805  }
806 
807  //------------------------------------------------------------------------------------------------
808  //----- my little helper!
809  //------------------------------------------------------------------------------------------------
811  protected static string ArrayJoin(notnull array<string> entries)
812  {
813  int count = entries.Count();
814  switch (count)
815  {
816  case 0: return "-";
817  case 1: return entries[0];
818  case 2: return WidgetManager.Translate("#AR-General_List_Short_2", entries[0], entries[1]);
819  case 3: return WidgetManager.Translate("#AR-General_List_Short_3", entries[0], entries[1], entries[2]);
820  case 4: return WidgetManager.Translate("#AR-General_List_Short_4", entries[0], entries[1], entries[2], entries[3]);
821  case 5: return WidgetManager.Translate("#AR-General_List_Short_5", entries[0], entries[1], entries[2], entries[3], entries[4]);
822  }
823  Print(string.Format("Too many list entries to join as a string - missing #AR-General_List_Short_%1 translation?", count), LogLevel.WARNING);
824  return WidgetManager.Translate("#AR-General_List_Short_5", entries[0], entries[1], entries[2], entries[3], entries[4]);
825  }
826 
827  //------------------------------------------------------------------------------------------------
828  //----- CONSTRUCTOR / DESTRUCTOR
829  //------------------------------------------------------------------------------------------------
830 
831  //------------------------------------------------------------------------------------------------
832  // constructor
833  void SCR_FieldManualUI()
834  {
835  m_aAllEntries = {};
836  m_mWidgetEntryMap = new map<Widget, ref SCR_FieldManualConfigEntry>();
837  m_mWidgetSubCategoryMap = new map<Widget, ref SCR_FieldManualConfigCategory>();
838 
839  ScriptInvoker inputDeviceIsGamepadInvoker = GetGame().OnInputDeviceIsGamepadInvoker();
840  if (inputDeviceIsGamepadInvoker)
841  inputDeviceIsGamepadInvoker.Insert(QueueRefreshCurrentEntry);
842  }
843 
844  //------------------------------------------------------------------------------------------------
845  // destructor
846  void ~SCR_FieldManualUI()
847  {
848  ScriptInvoker inputDeviceIsGamepadInvoker = GetGame().OnInputDeviceIsGamepadInvoker();
849  if (inputDeviceIsGamepadInvoker)
850  inputDeviceIsGamepadInvoker.Remove(QueueRefreshCurrentEntry);
851  }
852 }
SCR_FieldManualUI
Definition: SCR_FieldManualUI.c:1
ChimeraWorld
Definition: ChimeraWorld.c:12
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
SCR_FieldManualConfigEntry_Weapon
Definition: SCR_FieldManualConfigEntry_Weapon.c:2
GetRootWidget
Widget GetRootWidget()
Definition: SCR_UITaskManagerComponent.c:160
SCR_FieldManual_StatisticsLineComponent
Definition: SCR_FieldManual_StatisticsLineComponent.c:1
SCR_WidgetHelper
Definition: SCR_WidgetHelper.c:1
SCR_ConfigUIComponent
Definition: SCR_ConfigUIComponent.c:1
MenuRootBase
Definition: MenuRootBase.c:6
OnMenuClose
override void OnMenuClose()
Definition: AddonsToolsUI.c:36
SCR_FieldManualConfigEntry_Standard
Definition: SCR_FieldManualConfigEntry_Standard.c:2
SCR_FieldManualSubCategoryScriptedWidgetEventHandler
Definition: SCR_FieldManualSubCategoryScriptedWidgetEventHandler.c:1
SCR_FieldManualConfigCategory
Definition: SCR_FieldManualConfigCategory.c:2
SCR_FieldManualConfigLoader
Definition: SCR_FieldManualConfigLoader.c:1
SCR_FieldManualUI_WeaponStatsHelper
Definition: SCR_FieldManualUI_WeaponStatsHelper.c:1
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
ChimeraMenuPreset
ChimeraMenuPreset
Menu presets.
Definition: ChimeraMenuBase.c:3
SCR_FieldManualConfigRoot
Definition: SCR_FieldManualConfigRoot.c:2
ItemPreviewWidget
Definition: ItemPreviewWidget.c:12
SCR_FieldManualPiece_Text
Definition: SCR_FieldManualPiece_Text.c:2
SCR_FieldManualConfigEntry
Definition: SCR_FieldManualConfigEntry.c:2
EFieldManualEntryId
EFieldManualEntryId
used to grab the first id-matching Field Manual entry
Definition: EFieldManualEntryId.c:2
SCR_EditBoxSearchComponent
Definition: SCR_EditBoxSearchComponent.c:2
SCR_BreadCrumbsComponent
Definition: SCR_BreadCrumbsComponent.c:1
SCR_FieldManualEntryScriptedWidgetEventHandler
Definition: SCR_FieldManualEntryScriptedWidgetEventHandler.c:1
SCR_InputButtonComponent
Definition: SCR_InputButtonComponent.c:1
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180