Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_ContentBrowser_AddonsSubMenu.c
Go to the documentation of this file.
1 /*
2 Submenu for local or online addons.
3 
4 !! If you want filters to work, provide filters through the layout prefab or by some other way - into m_FilterCategories variable.
5 */
6 
8 {
9  MODE_OFFLINE, // Gets items from Workshop offline API
10  MODE_ONLINE, // Gets items from Workshop online API
11  MODE_EXTERNAL_ITEM_ARRAY // Operates on fixed array of items supplied externally
12 }
13 
14 class SCR_ContentBrowser_AddonsSubMenu : SCR_SubMenuBase
15 {
16  // This is quite universal and can work in many modes...
17  [Attribute("0", UIWidgets.ComboBox, "This menu is quite universal and can work in many modes - what do you want it to be?", "", ParamEnumArray.FromEnum(EContentBrowserAddonsSubMenuMode))]
19 
20  [Attribute("true", UIWidgets.CheckBox, "Enables the sorting header")]
22 
23  [Attribute("true", UIWidgets.CheckBox, "Enabled the filter panel functionality")]
25 
26  [Attribute("true", UIWidgets.CheckBox, "Enables opening details menu of currently selected tile.")]
27  protected bool m_bEnableOpenDetails;
28 
29  // ---- Constants ----
30 
31  protected const int GRID_N_COLUMNS = 4;
32  protected const int GRID_N_ROWS = 3;
33  protected const int LOAD_PAGE_DELAY = 500;
34 
35  protected const ResourceName LAYOUT_GRID_TILE = "{67B0EFBDF7EAFF27}UI/layouts/Menus/ContentBrowser/Tile/WorkshopTile.layout";
36 
37  // Message tags
38  protected const string MESSAGE_TAG_NOTHING_FOUND = "nothing_found";
39  protected const string MESSAGE_TAG_NOTHING_DOWNLOADED = "nothing_downloaded";
40  protected const string MESSAGE_TAG_NOTHING_DOWNLOADED_2 = "nothing_downloaded2";
41  protected const string MESSAGE_TAG_ERROR_CONNECTION = "error_connection";
42  protected const string MESSAGE_TAG_LOADING = "loading";
43 
44  // ---- Protected / Private ----
45 
47 
48  protected WorkshopApi m_WorkshopApi;
49 
51 
52  protected ref array<SCR_ContentBrowserTileComponent> m_aTileComponents = {};
53 
54  protected bool m_bConnected; // True when we are connected to backend, used to determine when to start sending requests
55  protected bool m_bFailToLoad;
56 
57  protected bool m_bClearCacheAtNextRequest; // Will force workshop to clear page cache. Should be set wherever sorting or filtering changes.
58 
59  protected ref array<ref SCR_WorkshopItem> m_aExternalItems = {}; // Array with externally provided items - used only in MODE_EXTERNAL_ITEM_ARRAY
60 
61  protected SCR_ContentBrowserTileComponent m_LastFocusedTile; // Mainly used to restore focus back to something
62 
65 
66  protected bool m_bFirstPage = true; // True before first page is received.
67 
68  protected bool m_bPanelsModeEmpty; // True when we are showing empty panels
69 
70  protected bool m_bMousePageUsed;
71 
72  protected bool m_bFirstLoad = true;
73 
74  // State of paging
75  protected int m_iCurrentPage;
76  protected int m_iOfflinePageCount; // Amount of pages, used only in MODE_OFFLINE and MODE_EXTERNAL_ITEM_ARRAY
77  protected int m_iOnlinePageCount;
78 
79  // Navigation buttons
85 
86  // Items found message
87  protected int m_iItemsTotal;
88  protected int m_iOnlineFilteredItems;
89  protected ref array<ref SCR_WorkshopApiCallback_RequestPage> m_aSearchCallbacks = {};
90 
91  //------------------------------------------------------------------------------------------------
93  void SetWorkshopItems(array<ref SCR_WorkshopItem> items)
94  {
95  if (m_eMode != EContentBrowserAddonsSubMenuMode.MODE_EXTERNAL_ITEM_ARRAY)
96  return;
97 
98  m_aExternalItems.Clear();
99 
100  foreach (SCR_WorkshopItem i : items)
101  {
102  m_aExternalItems.Insert(i);
103  }
104  }
105 
106  //------------------------------------------------------------------------------------------------
109  {
110  if (m_eMode != EContentBrowserAddonsSubMenuMode.MODE_OFFLINE)
111  return;
112 
113  SCR_FilterPanelComponent fp = m_Widgets.m_FilterPanelComponent;
114  fp.ResetToDefaultValues();
115  SCR_FilterSet filterSet = fp.GetFilter();
116  SCR_FilterEntry filterEntry = filterSet.FindFilterCategory("state").FindFilter("enabled");
117  filterEntry.SetSelected(true);
118  fp.SelectFilter(filterEntry, true, invokeOnChanged: false);
119  RequestPage(0); // Update the page again
120  }
121 
122  //------------------------------------------------------------------------------------------------
123  override void OnTabCreate(Widget menuRoot, ResourceName buttonsLayout, int index)
124  {
125  super.OnTabCreate(menuRoot, buttonsLayout, index);
126 
127  InitWidgets();
128 
129  // Init main parts of the layout
130  GridScreen_Init();
131 
132  // Try to load filters
133  m_Widgets.m_FilterPanelComponent.TryLoad();
134 
135  m_WorkshopApi = GetGame().GetBackendApi().GetWorkshop();
136  InitWorkshopApi();
137 
138  // Init event handlers
140 
141  // In online mode request page only when menu is opened first time
142  if (m_eMode == EContentBrowserAddonsSubMenuMode.MODE_ONLINE)
143  {
144  m_bConnected = SCR_WorkshopUiCommon.GetConnectionState();
145  if (m_bConnected)
146  OnConnected();
147  else
148  SetPanelsMode(true, false, MESSAGE_TAG_ERROR_CONNECTION, false);
149  }
150 
151  else
152  {
153  // Offline modes - request page instantly
154  RequestPage(0);
155  }
156 
157  // Subscribe to addon manager events
158  SCR_AddonManager.GetInstance().m_OnAddonOfflineStateChanged.Insert(Callback_OnAddonOfflineStateChanged);
159 
160  // Subscribe to page refresh request events
161  SCR_AddonManager.GetInstance().m_OnAddonReportedStateChanged.Insert(Callback_OnAddonReportedStateChanged);
162  }
163 
164  //------------------------------------------------------------------------------------------------
165  protected void InitWidgets()
166  {
167  m_Widgets.Init(GetRootWidget());
168 
169  // Hide elements which are disabled through attributes
170  m_Widgets.m_SortingHeader.SetVisible(m_bEnableSorting);
171 
172  // Create nav buttons
173  if (m_bEnableFilter)
174  m_NavFilter = CreateNavigationButton("MenuFilter", "#AR-Editor_ContentBrowser_ButtonOpenFilter", false);
175 
176  m_NavDetails = CreateNavigationButton("MenuSelect", "#AR-Workshop_Details_MenuTitle", true, m_bEnableOpenDetails);
177  m_NavEnable = CreateNavigationButton("MenuEnable", "#AR-Workshop_ButtonEnable", true);
178  m_NavFavourite = CreateNavigationButton("MenuFavourite", UIConstants.FAVORITE_LABEL_ADD, true);
179  m_NavPrimary = CreateNavigationButton("MenuSelectHold", "#AR-Workshop_ButtonDownload", true);
180  }
181 
182  //------------------------------------------------------------------------------------------------
183  protected void InitWidgetEventHandlers()
184  {
185  m_Widgets.m_PrevPageButton_NoScrollComponent.m_OnActivated.Insert(OnPrevPageButton);
186  m_Widgets.m_NextPageButton_NoScrollComponent.m_OnActivated.Insert(OnNextPageButton);
187  GetGame().GetInputManager().AddActionListener("MouseWheel", EActionTrigger.VALUE, OnScrollPage);
188 
189  m_Widgets.m_FilterPanelComponent.GetWidgets().m_FilterSearchComponent.m_OnConfirm.Insert(OnFilterSearchConfirm);
190  m_Widgets.m_SortingHeaderComponent.m_OnChanged.Insert(OnSortingHeaderChange);
191  m_Widgets.m_FilterPanelComponent.GetOnFilterChanged().Insert(OnFilterChange);
192 
193  // Event handlers of nav buttons
194  m_NavEnable.m_OnActivated.Insert(OnEnableButton);
195 
196  if (m_NavFilter)
197  m_NavFilter.m_OnActivated.Insert(OnFilterButton);
198 
199  m_NavPrimary.m_OnActivated.Insert(OnPrimaryButton);
200  m_NavFavourite.m_OnActivated.Insert(OnFavouriteButton);
201  m_NavDetails.m_OnClicked.Insert(OnDetailsButton);
202  }
203 
204  //------------------------------------------------------------------------------------------------
205  override void OnTabShow()
206  {
207  // Check and show backend down
208  super.OnTabShow();
209 
210  // Init workshop API
211  // We do it on tab show becasue this tab and others persists when all other tabs are closed,
212  // But we can switch back to it later, and we must setup the workshop api again
213  InitWorkshopApi();
214 
215  if (m_bFailToLoad)
217  }
218 
219  //------------------------------------------------------------------------------------------------
220  override void OnTabHide()
221  {
222  super.OnTabHide();
223 
224  // Save configuration of filters
225  m_Widgets.m_FilterPanelComponent.Save();
226  }
227 
228  //------------------------------------------------------------------------------------------------
229  override void OnTabRemove()
230  {
231  super.OnTabRemove();
232 
233  // Unsubscribe from addon manager events
234  SCR_AddonManager.GetInstance().m_OnAddonOfflineStateChanged.Remove(Callback_OnAddonOfflineStateChanged);
235 
236  // Unsubscribe from page refresh request events
237  SCR_AddonManager.GetInstance().m_OnAddonReportedStateChanged.Remove(Callback_OnAddonReportedStateChanged);
238 
239  GetGame().GetCallqueue().Remove(RequestOnlinePageUnfiltered);
240  }
241 
242  //------------------------------------------------------------------------------------------------
243  override void OnMenuShow()
244  {
245  super.OnMenuShow();
246 
247  InitWorkshopApi();
248  }
249 
250  //------------------------------------------------------------------------------------------------
252  override void OnMenuUpdate(float tDelta)
253  {
254  // Update connection state, check if we have reconnected
255  bool connectedOld = m_bConnected;
256  bool connectedNew = SCR_WorkshopUiCommon.GetConnectionState();
257  m_bConnected = connectedNew;
258  if (connectedNew != connectedOld)
259  {
260  if (connectedNew)
261  ContentBrowserUI._print("Connected");
262  else
263  ContentBrowserUI._print("Disconnected");
264 
265  if (connectedNew && m_eMode == EContentBrowserAddonsSubMenuMode.MODE_ONLINE) // Only call OnConnected if it's an online tab
266  OnConnected();
267  }
268 
269  // TODO: don't update on tick!
271  UpdateButtons();
272  }
273 
274  //------------------------------------------------------------------------------------------------
275  override void OnMenuFocusGained()
276  {
277  if (m_bShown)
278  SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
279 
280  super.OnMenuFocusGained();
281  }
282 
283  //------------------------------------------------------------------------------------------------
284  override void OnTabChange()
285  {
286  super.OnTabChange();
287 
288  if (GetShown())
289  {
290  if (!m_bConnected && m_eMode == EContentBrowserAddonsSubMenuMode.MODE_ONLINE)
291  SwitchFocus(SCR_EListMenuWidgetFocus.NULL);
292  else
293  SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
294  }
295  }
296 
297  //------------------------------------------------------------------------------------------------
298  // Inits workshop API according to current mode
299  protected void InitWorkshopApi()
300  {
301  // Set grid thumbnail size
302  float imageWidth = SCR_WorkshopUiCommon.GetPreferedTileImageWidth();
303  WorkshopItem.SetThumbnailGridScale(imageWidth);
304 
305  switch (m_eMode)
306  {
307  case EContentBrowserAddonsSubMenuMode.MODE_ONLINE:
309  break;
310 
311  case EContentBrowserAddonsSubMenuMode.MODE_OFFLINE:
312  m_WorkshopApi.ScanOfflineItems();
313  break;
314 
315  case EContentBrowserAddonsSubMenuMode.MODE_EXTERNAL_ITEM_ARRAY:
316  // Don't do anything, we are not using the Workshop API to get items
317  // In this case
318  break;
319  }
320 
321  // Register tags for filters
322  SCR_FilterSet filterSet = m_Widgets.m_FilterPanelComponent.m_FilterSet;
323  if (filterSet)
324  {
325  foreach (SCR_FilterCategory category : filterSet.GetFilterCategories())
326  {
327  foreach (SCR_FilterEntry filterEntry : category.GetFilters())
328  {
329  SCR_ContentBrowserFilterTag filterTag = SCR_ContentBrowserFilterTag.Cast(filterEntry);
330  if (filterTag)
331  filterTag.RegisterInWorkshopApi(m_WorkshopApi);
332  }
333  }
334  }
335  }
336 
337  //------------------------------------------------------------------------------------------------
338  // Requests page from backend or displays items according to current mode
339  protected void RequestPage(int pageId)
340  {
341  // When we request page, we also must clean the grid and side panel
343  m_Widgets.m_AddonDetailsPanelComponent.SetWorkshopItem(null);
344  SetPanelsMode(showEmptyPanel: m_bFirstPage, messagePresetTag: MESSAGE_TAG_LOADING);
345 
346  m_iCurrentPage = pageId;
347  m_bFailToLoad = false;
348 
349  switch (m_eMode)
350  {
351  case EContentBrowserAddonsSubMenuMode.MODE_EXTERNAL_ITEM_ARRAY:
352  DisplayExternalItems(pageId);
353  break;
354  case EContentBrowserAddonsSubMenuMode.MODE_ONLINE:
355  GetGame().GetCallqueue().Remove(RequestOnlinePage);
356  GetGame().GetCallqueue().CallLater(RequestOnlinePage, LOAD_PAGE_DELAY, false, pageId);
357  break;
358  case EContentBrowserAddonsSubMenuMode.MODE_OFFLINE:
359  DisplayOfflineItems(pageId);
360  break;
361  }
362  }
363 
364  // ---- Backend page requests ----
365  //------------------------------------------------------------------------------------------------
368  protected void RequestOnlinePageUnfiltered(int pageId)
369  {
370  GetGame().GetCallqueue().Remove(RequestOnlinePageUnfiltered);
371 
372  m_WorkshopApi.SetPageItems(0);
373 
375  callback.m_OnGetAssets.Insert(Callback_OnRequestPageGetAllAssets);
377  callback.m_OnTimeout.Insert(Callback_OnRequestPageGetAllAssets);
378 
380 
383 
386 
388  }
389 
390  //------------------------------------------------------------------------------------------------
393  protected void RequestOnlinePage(int pageId)
394  {
395  m_WorkshopApi.SetPageItems(GRID_N_COLUMNS * GRID_N_ROWS);
396 
398  callback.m_OnGetAssets.Insert(Callback_OnRequestPageGetAssets);
399  callback.m_OnError.Insert(Callback_OnRequestPageTimeout);
400  callback.m_OnTimeout.Insert(Callback_OnRequestPageTimeout);
401 
403 
406 
408  m_GetAssetListParams.offset = pageId * GRID_N_ROWS * GRID_N_COLUMNS;
409 
410  //m_GetAssetListParams.PackToFile("$profile:GetAssetList.json");
411  #ifdef WORKSHOP_DEBUG
412  ContentBrowserUI._print(string.Format("WorkshopApi.RequestPage() limit: %1, offset: %2", m_GetAssetListParams.limit, m_GetAssetListParams.offset));
413  #endif
414 
416 
418  }
419 
420  //------------------------------------------------------------------------------------------------
422  {
423  callback.m_OnSuccess.Clear();
424  callback.m_OnError.Clear();
425  callback.m_OnTimeout.Clear();
426 
427  m_aSearchCallbacks.RemoveItem(callback);
428  }
429 
430  //------------------------------------------------------------------------------------------------
434  {
435  SCR_FilterSet filterSet = m_Widgets.m_FilterPanelComponent.GetFilter();
436 
437  SCR_FilterCategory otherCategory = filterSet.FindFilterCategory("other");
438 
439  // Pack sorting
440  string orderBy = "name";
441  string currentSortingItem = m_Widgets.m_SortingHeaderComponent.GetSortElementName();
442  bool sortAscending = m_Widgets.m_SortingHeaderComponent.GetSortOrderAscending();
443 
444  const string orderAsc = "asc";
445  const string orderDesc = "desc";
446 
447  switch (currentSortingItem)
448  {
449  case "popularity":
450  orderBy = "popularity";
451  break;
452  case "rating":
453  orderBy = "averageRating";
454  break;
455  case "recently_added":
456  orderBy = "createdAt";
457  sortAscending = !sortAscending; // Invert sorting direction, when ascen
458  break;
459  case "name":
460  orderBy = "name";
461  break;
462  case "subscribers":
463  orderBy = "subscriberCount";
464  break;
465  }
466 
467  string orderDirection = orderAsc;
468  if (!sortAscending)
469  orderDirection = orderDesc;
470 
471  p.StoreString("orderBy", orderBy); // <- "orderBy": "..."
472  p.StoreString("orderDirection", orderDirection); // <- "orderDirection": "..."
473 
474  // Pack search string
475  string searchStr = m_Widgets.m_FilterPanelComponent.GetWidgets().m_FilterSearchComponent.GetValue();
476  if (!searchStr.IsEmpty() && !defaultValues)
477  {
478  p.StoreString("search", searchStr); // <- "search": "..."
479  }
480 
481  // Pack 'quick filters'
482  SCR_FilterCategory quickCategory = filterSet.FindFilterCategory("quick_filters");
483  SCR_FilterEntry filterAll = quickCategory.FindFilter("all");
484  SCR_FilterEntry filterFav = quickCategory.FindFilter("favourite");
485  //SCR_FilterEntry filterSub = quickCategory.FindFilter("subscribed");
486  SCR_FilterEntry filterRated = quickCategory.FindFilter("rated");
487 
488  if (filterFav.GetSelected(defaultValues))
489  p.StoreBoolean("favorited", true); // <- "favorited": true
490  //else if (filterSub.GetSelected())
491  // p.StoreBoolean("subscribed", true); // <- "subscribed": true
492  else if (filterRated.GetSelected(defaultValues))
493  {
494  p.StartObject("averageRating"); // <- "AverageRating" object
495  p.StoreFloat("gt", 0.75); // <- "gt": 1.23
496  p.StoreFloat("lt", 1); // <- "lt": 1.23
497  p.EndObject(); // <- End AverageRating
498  }
499 
500  // -------- Pack tags --------
501 
502  // Make arrays with tags to include or exclude
503  array<ref array<string>> tagArraysInclude = {};
504  array<string> tagsExclude = {};
505 
506  // Tags from type filters
507  SCR_FilterCategory typeCategory = filterSet.FindFilterCategory("type");
508  if (typeCategory.GetAnySelected() && !defaultValues)
509  {
510  array<string> typeTags = {};
511  foreach (SCR_FilterEntry filter : typeCategory.GetFilters())
512  {
513  if (filter.GetSelected(defaultValues))
514  typeTags.Insert(filter.m_sInternalName);
515  }
516  tagArraysInclude.Insert(typeTags);
517  }
518 
519  // Tags from test mods
520  SCR_FilterEntry testFilter = otherCategory.FindFilter("TESTDEV");
521  if (!testFilter.GetSelected(defaultValues))
522  tagsExclude.Insert(testFilter.m_sInternalName);
523 
524  // Pack the tags
525  if (!tagArraysInclude.IsEmpty() || !tagsExclude.IsEmpty())
526  {
527  p.StartObject("tags"); // <- Start "tags" object
528 
529  if (!tagArraysInclude.IsEmpty())
530  {
531  p.StartArray("include"); // <- Start "include" array
532 
533  foreach (array<string> tagArray : tagArraysInclude)
534  {
535  p.ItemArray(); // <- Start tags array
536  foreach (string tag : tagArray)
537  {
538  p.ItemString(tag); // <- Array element
539  }
540  p.EndArray(); // <- End tags array
541  }
542 
543  p.EndArray(); // <- End "include" array
544  }
545 
546  if (!tagsExclude.IsEmpty())
547  {
548  p.StartArray("exclude"); // <- Start "exclude" array
549  foreach (string tag : tagsExclude)
550  {
551  p.ItemString(tag); // <- Array element
552  }
553  p.EndArray(); // <- End "exclude" array
554  }
555 
556  p.EndObject(); // <- End "tags" object
557  }
558 
559  // --------------------------------
560 
561  // Pack reported
562  SCR_FilterEntry reportedFilter = otherCategory.FindFilter("reported");
563  p.StoreBoolean("reported", reportedFilter.GetSelected(defaultValues)); // <- "reported": true
564  p.StoreBoolean("hidden", reportedFilter.GetSelected(defaultValues));
565 
566  // Pack test mods
567  }
568 
569  //------------------------------------------------------------------------------------------------
571  protected void DisplayExternalItems(int pageId)
572  {
573  m_WorkshopApi.SetPageItems(GRID_N_COLUMNS * GRID_N_ROWS);
574 
575  array<ref SCR_WorkshopItem> itemsAtPage = SelectItemsAtPage(m_aExternalItems, pageId);
576 
577  // Filtering is disabled in this mode
578 
579  // Update page count
580  m_iOfflinePageCount = Math.Ceil((float)itemsAtPage.Count() / (float)(GRID_N_ROWS * GRID_N_COLUMNS));
581 
582  SetPanelsMode(false, m_Widgets.m_FilterPanelComponent.AnyFilterButtonsVisible(), string.Empty, m_bFirstPage);
583 
584  GridScreen_DisplayItems(itemsAtPage);
585 
586  m_bFirstPage = false;
587 
589  }
590 
591  //------------------------------------------------------------------------------------------------
592  protected void DisplayOfflineItems(int pageId)
593  {
594  m_WorkshopApi.SetPageItems(GRID_N_COLUMNS * GRID_N_ROWS);
595 
596  // Get offline items from API
597  array<WorkshopItem> rawWorkshopItems = {};
598  m_WorkshopApi.GetOfflineItems(rawWorkshopItems);
599 
600  // Bail if there is no downloaded content
601  if (rawWorkshopItems.IsEmpty())
602  {
603  SetPanelsMode(showEmptyPanel: true, messagePresetTag: MESSAGE_TAG_NOTHING_DOWNLOADED);
605  return;
606  }
607 
608  // Register items in Addon Manager
609  array<ref SCR_WorkshopItem> itemsUnfiltered = {};
610  foreach (WorkshopItem i : rawWorkshopItems)
611  {
612  SCR_WorkshopItem itemRegistered = SCR_AddonManager.GetInstance().Register(i);
613  itemsUnfiltered.Insert(itemRegistered);
614  }
615 
616  // Filter items
617  array<ref SCR_WorkshopItem> itemsFiltered = Filter_OfflineFilterAndSearch(itemsUnfiltered);
618 
619  // Bail if no items after filtering
620  if (itemsFiltered.IsEmpty())
621  {
622  SetPanelsMode(showEmptyPanel: false, forceFiltersList: true, messagePresetTag: MESSAGE_TAG_NOTHING_DOWNLOADED_2);
623  UpdateItemsFoundMessage(0, rawWorkshopItems.Count());
624  return;
625  }
626 
627  // Sort items
628  array<SCR_WorkshopItem> itemsSortedWeakPtrs = {};
629  foreach (SCR_WorkshopItem i : itemsFiltered)
630  {
631  itemsSortedWeakPtrs.Insert(i);
632  }
633 
634  bool sortOrder = !m_Widgets.m_SortingHeaderComponent.GetSortOrderAscending();
635  string currentSortingItem = m_Widgets.m_SortingHeaderComponent.GetSortElementName();
636  if (currentSortingItem.IsEmpty())
637  {
638  currentSortingItem = "name";
639  sortOrder = false;
640  }
641 
642  switch (currentSortingItem)
643  {
644  case "name":
645  SCR_Sorting<SCR_WorkshopItem, SCR_CompareWorkshopItemName>.HeapSort(itemsSortedWeakPtrs, sortOrder);
646  break;
647  case "time_since_played":
648  SCR_Sorting<SCR_WorkshopItem, SCR_CompareWorkshopItemTimeSinceLastPlay>.HeapSort(itemsSortedWeakPtrs, sortOrder);
649  break;
650  case "time_since_downloaded":
651  SCR_Sorting<SCR_WorkshopItem, SCR_CompareWorkshopItemTimeSinceFirstDownload>.HeapSort(itemsSortedWeakPtrs, sortOrder);
652  break;
653  }
654 
655  array<ref SCR_WorkshopItem> itemsSorted = {};
656  foreach (SCR_WorkshopItem i : itemsSortedWeakPtrs)
657  {
658  itemsSorted.Insert(i);
659  }
660 
661  // Update page count
662  m_iOfflinePageCount = Math.Ceil((float)itemsSorted.Count() / (float)(GRID_N_ROWS * GRID_N_COLUMNS));
663 
664  // Display items
665  SetPanelsMode(false, m_Widgets.m_FilterPanelComponent.AnyFilterButtonsVisible(), string.Empty, m_bFirstPage);
666  array<ref SCR_WorkshopItem> itemsAtPage = SelectItemsAtPage(itemsSorted, pageId);
667  GridScreen_DisplayItems(itemsAtPage);
668 
669  m_bFirstPage = false;
670 
671  UpdateItemsFoundMessage(itemsSorted.Count(), rawWorkshopItems.Count());
672  }
673 
674  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
675  // W I D G E T S
676  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
677  //------------------------------------------------------------------------------------------------
681  protected void GridScreen_Init()
682  {
683  for (int i = 0; i < GRID_N_COLUMNS * GRID_N_ROWS; i++)
684  {
685  int colId = i % GRID_N_COLUMNS;
686  int rowId = i / GRID_N_COLUMNS;
687 
688  // Create tile widgets
689  Widget w = GetGame().GetWorkspace().CreateWidgets(LAYOUT_GRID_TILE, m_Widgets.m_Grid);
690 
691  // Set grid positioning
692  GridSlot.SetRow(w, rowId);
693  GridSlot.SetColumn(w, colId);
694 
695  // Init the tile component
697  comp.SetWorkshopItem(null); // Widget will be hidden because of that
698 
699  // Tile event handlers
700  comp.m_OnClick.Insert(OnTileClick);
701  comp.GetOnFocus().Insert(OnTileFocus);
702 
703  m_aTileComponents.Insert(comp);
704  }
705  }
706 
707  //------------------------------------------------------------------------------------------------
709  protected void GridScreen_Clear()
710  {
712  {
713  comp.SetWorkshopItem(null);
714  }
715  }
716 
717  //------------------------------------------------------------------------------------------------
718  protected void GridScreen_DisplayItems(array<ref SCR_WorkshopItem> items)
719  {
720  // Clear old items
722 
723  int nItems = Math.ClampInt(items.Count(), 0, GRID_N_COLUMNS * GRID_N_ROWS);
724 
725  for (int i = 0; i < nItems; i++)
726  {
728  comp.SetWorkshopItem(items[i]);
729  }
730  }
731 
732  //------------------------------------------------------------------------------------------------
733  void SetPanelsMode(bool showEmptyPanel, bool forceFiltersList = false, string messagePresetTag = string.Empty, bool animateFiltersList = false)
734  {
735  m_bPanelsModeEmpty = showEmptyPanel;
736 
737  // Show either main+filter panel or empty panel
738  m_Widgets.m_EmptyPanel.SetVisible(showEmptyPanel);
739  m_Widgets.m_FilterPanel.SetVisible(!showEmptyPanel);
740  m_Widgets.m_LeftPanelArea.SetVisible(!showEmptyPanel);
741 
742  // Show message or hide it
743  m_Widgets.m_EmptyPanelMessage.SetVisible(!messagePresetTag.IsEmpty());
744  m_Widgets.m_MainPanelMessage.SetVisible(!messagePresetTag.IsEmpty());
745 
746  // Set message based on tag
747  if (!messagePresetTag.IsEmpty())
748  {
749  if (showEmptyPanel)
750  m_Widgets.m_EmptyPanelMessageComponent.SetContentFromPreset(messagePresetTag);
751  else
752  m_Widgets.m_MainPanelMessageComponent.SetContentFromPreset(messagePresetTag);
753  }
754 
755  // Force-show filter list
756  if (forceFiltersList)
757  {
758  m_Widgets.m_FilterPanelComponent.ShowFilterListBox(true, animateFiltersList);
759  if (!m_Widgets.m_FilterPanelComponent.GetFocused())
760  SwitchFocus(SCR_EListMenuWidgetFocus.FILTERING);
761  }
762  }
763 
764  //------------------------------------------------------------------------------------------------
765  // F I L T E R A N D S O R T I N G
766  //------------------------------------------------------------------------------------------------
767  //------------------------------------------------------------------------------------------------
768  array<ref SCR_WorkshopItem> SearchItems(array<ref SCR_WorkshopItem> items, string searchStr)
769  {
770  array<ref SCR_WorkshopItem> itemsOut = {};
771 
772  if (searchStr.IsEmpty())
773  {
774  foreach (SCR_WorkshopItem i : items)
775  {
776  itemsOut.Insert(i);
777  }
778 
779  return itemsOut;
780  }
781 
782  string searchStrLower = searchStr;
783  searchStrLower.ToLower();
784 
785  foreach (SCR_WorkshopItem i : items)
786  {
787  // Name
788  string nameLower = i.GetName();
789  nameLower.ToLower();
790  if (nameLower.Contains(searchStrLower))
791  {
792  itemsOut.Insert(i);
793  continue;
794  }
795 
796  // Author name
797  string authorNameLower = i.GetName();
798  authorNameLower.ToLower();
799  if (authorNameLower.Contains(searchStrLower))
800  {
801  itemsOut.Insert(i);
802  continue;
803  }
804 
805  // Description
806  string descriptionLower = i.GetDescription();
807  descriptionLower.ToLower();
808  if (descriptionLower.Contains(searchStrLower))
809  {
810  itemsOut.Insert(i);
811  continue;
812  }
813 
814  // Tags
815  array<WorkshopTag> tags = {};
816  i.GetWorkshopItem().GetTags(tags);
817  bool foundTag = false;
818  foreach (WorkshopTag tag : tags)
819  {
820  string tagNameLower = tag.Name();
821  tagNameLower.ToLower();
822  if (tagNameLower == searchStrLower)
823  {
824  foundTag = true;
825  break;
826  }
827  }
828 
829  if (foundTag)
830  {
831  itemsOut.Insert(i);
832  continue;
833  }
834  }
835 
836  return itemsOut;
837  }
838 
839  //------------------------------------------------------------------------------------------------
842  protected array<ref SCR_WorkshopItem> Filter_OfflineFilterAndSearch(array<ref SCR_WorkshopItem> itemsIn)
843  {
844  SCR_FilterSet filterSet = m_Widgets.m_FilterPanelComponent.GetFilter();
845 
846  string searchStr = m_Widgets.m_FilterPanelComponent.GetEditBoxSearch().GetValue();
847 
848  array<ref SCR_WorkshopItem> items = SearchItems(itemsIn, searchStr);
849 
850  // ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
851  // ! ! Filter categories and filter names are bound by strings, be careful while changing them ! !
852  // ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
853  // Arrays produced by each category. In the end we find intersection of those arrays.
854  array<ref array<ref SCR_WorkshopItem>> arraysFromCategories = {};
855 
856  // Quick filters - only one is selected at a time
857  SCR_FilterCategory catQuick = filterSet.FindFilterCategory("quick_filters");
858  SCR_FilterEntry filterAll = catQuick.FindFilter("all");
859  SCR_FilterEntry filterFav = catQuick.FindFilter("favourite");
860  if (filterAll.GetSelected())
861  arraysFromCategories.Insert(items);
862  else if (filterFav.GetSelected())
863  arraysFromCategories.Insert(SCR_AddonManager.SelectItemsBasic(items, EWorkshopItemQuery.FAVOURITE));
864 
865  // Type tags
866  array<WorkshopTag> selectedWorkshopTags = {};
867  SCR_FilterCategory catType = filterSet.FindFilterCategory("type");
868  foreach (SCR_FilterEntry f : catType.GetFilters())
869  {
871  if (filterEntryTag && filterEntryTag.GetSelected())
872  selectedWorkshopTags.Insert(filterEntryTag.GetWorkshopTag());
873  }
874  // If any tag filter is selected, but not all of them (because it would be same as selecting none)
875  if (!selectedWorkshopTags.IsEmpty() && selectedWorkshopTags.Count() != catType.GetFilters().Count())
876  {
877  array<ref SCR_WorkshopItem> itemsFilteredByTags = {};
878  foreach (SCR_WorkshopItem item : items)
879  {
880  if (item.GetWorkshopItem().HasAnyTag(selectedWorkshopTags))
881  itemsFilteredByTags.Insert(item);
882  }
883  arraysFromCategories.Insert(itemsFilteredByTags);
884  }
885 
886  // State
887  SCR_FilterCategory catState = filterSet.FindFilterCategory("state");
888  if (!catState)
889  return {};
890 
891  if (catState.GetAllSelected() || catState.GetAllDeselected())
892  arraysFromCategories.Insert(items);
893  else
894  {
895  EWorkshopItemQuery query = 0;
896  if (catState.FindFilter("enabled").GetSelected())
897  query = query | EWorkshopItemQuery.ENABLED;
898  if (catState.FindFilter("disabled").GetSelected())
899  query = query | EWorkshopItemQuery.NOT_ENABLED;
900 
901  auto queryResult = SCR_AddonManager.SelectItemsOr(items, query);
902  arraysFromCategories.Insert(queryResult);
903  }
904 
905  // Condition
906  SCR_FilterCategory catCondition = filterSet.FindFilterCategory("condition");
907  if (catCondition.GetAllSelected() || catCondition.GetAllDeselected())
908  arraysFromCategories.Insert(items);
909  else
910  {
911  EWorkshopItemQuery query = 0;
912  if (catCondition.FindFilter("ready").GetSelected())
913  query = query | EWorkshopItemQuery.NO_PROBLEMS;
914  if (catCondition.FindFilter("update_available").GetSelected())
915  query = query | EWorkshopItemQuery.UPDATE_AVAILABLE | EWorkshopItemQuery.DEPENDENCY_UPDATE_AVAILABLE;
916  if (catCondition.FindFilter("repair_required").GetSelected())
917  query = query | EWorkshopItemQuery.DEPENDENCY_MISSING | EWorkshopItemQuery.ENABLED_AND_DEPENDENCY_DISABLED;
918 
919  auto queryResult = SCR_AddonManager.SelectItemsOr(items, query);
920  arraysFromCategories.Insert(queryResult);
921  }
922 
923  // Find intersection of all arrays
924  array<ref SCR_WorkshopItem> intersection = Filter_IntersectArrays(arraysFromCategories);
925 
926  return intersection;
927  }
928 
929  //------------------------------------------------------------------------------------------------
931  protected array<ref SCR_WorkshopItem> Filter_IntersectArrays(array<ref array<ref SCR_WorkshopItem>> arrays)
932  {
933  array<ref SCR_WorkshopItem> result = {};
934 
935  // Trivial cace: no arrays
936  if (arrays.IsEmpty())
937  return result;
938 
939  // Trivial case: one array
940  if (arrays.Count() == 1)
941  {
942  int count = arrays[0].Count();
943  result.Resize(count);
944  for (int i = 0; i < count; i++)
945  {
946  result[i] = arrays[0][i];
947  }
948 
949  return result;
950  }
951 
952  // Non-trivial case: more than one array
953  auto array0 = arrays[0];
954  foreach (auto item : array0)
955  {
956  // This item must be found in all other arrays too
957  bool foundInAll = true;
958  for (int arrayId = 1; arrayId < arrays.Count(); arrayId++)
959  {
960 
961  if (!arrays[arrayId].Contains(item))
962  {
963  foundInAll = false;
964  break;
965  }
966  }
967 
968  if (foundInAll)
969  result.Insert(item);
970  }
971 
972  return result;
973  }
974 
975  //------------------------------------------------------------------------------------------------
976  void UpdateItemsFoundMessage(int current, int total)
977  {
978  if (!m_Widgets || !m_Widgets.m_FilterPanelComponent)
979  return;
980 
981  m_Widgets.m_FilterPanelComponent.SetItemsFoundMessage(current, total, current != total);
982 
983  }
984 
985  //------------------------------------------------------------------------------------------------
987  protected int GetPageCount()
988  {
989  switch (m_eMode)
990  {
991  case EContentBrowserAddonsSubMenuMode.MODE_EXTERNAL_ITEM_ARRAY:
992  return m_iOfflinePageCount;
993  case EContentBrowserAddonsSubMenuMode.MODE_ONLINE:
994  return m_iOnlinePageCount;
995  case EContentBrowserAddonsSubMenuMode.MODE_OFFLINE:
996  return m_iOfflinePageCount;
997  }
998  return 0;
999  }
1000 
1001  //------------------------------------------------------------------------------------------------
1004  {
1005  Widget focusedWidget = GetGame().GetWorkspace().GetFocusedWidget();
1006 
1007  if (!focusedWidget)
1008  return null;
1009 
1011 
1012  if (!comp)
1013  return null;
1014 
1015  return comp.GetWorkshopItem();
1016  }
1017 
1018  //------------------------------------------------------------------------------------------------
1020  protected void UpdatePagingWidgets()
1021  {
1022  int pageCount = GetPageCount();
1023 
1024  m_Widgets.m_PagingButtons.SetVisible(pageCount != 0);
1025 
1026  if (pageCount == 0)
1027  return;
1028 
1029  m_Widgets.m_PageIndicatorText.SetTextFormat("#AR-Editor_ContentBrowser_PageIndex_Text", m_iCurrentPage + 1, pageCount);
1030 
1031  m_Widgets.m_PrevPageButton_NoScrollComponent.SetEnabled(m_iCurrentPage > 0);
1032  m_Widgets.m_NextPageButton_NoScrollComponent.SetEnabled(m_iCurrentPage < pageCount - 1);
1033  }
1034 
1035  //------------------------------------------------------------------------------------------------
1036  protected void UpdateButtons()
1037  {
1038  // Filters button
1039  if (m_NavFilter)
1040  m_NavFilter.SetEnabled(!m_bPanelsModeEmpty);
1041 
1042  // Item buttons
1044 
1045  if (m_NavDetails && m_NavDetails.IsVisible())
1046  m_NavDetails.SetEnabled(item != null);
1047 
1048  if (!item)
1049  {
1050  // Nothing is selected, disable all buttons
1051  m_NavFavourite.SetEnabled(false);
1052  m_NavEnable.SetEnabled(false);
1053  m_NavPrimary.SetEnabled(false);
1054 
1055  return;
1056  }
1057 
1058  if (item.GetRestricted())
1059  {
1060  m_NavFavourite.SetEnabled(false);
1061  m_NavEnable.SetEnabled(false);
1062  m_NavPrimary.SetEnabled(false);
1063 
1064  return;
1065  }
1066 
1067  auto actionThisItem = item.GetDownloadAction();
1068  auto actionDependencies = item.GetDependencyCompositeAction();
1069  bool downloading = actionThisItem || actionDependencies;
1070 
1071  // Favourite button - always enabled
1072  m_NavFavourite.SetEnabled(true);
1073  string favLabel;
1074  if (!item.GetFavourite())
1075  favLabel = UIConstants.FAVORITE_LABEL_ADD;
1076  else
1077  favLabel = UIConstants.FAVORITE_LABEL_REMOVE;
1078  m_NavFavourite.SetLabel(favLabel);
1079 
1080  // Enable button - enabled only for downloaded addons, but not when downloading
1081  m_NavEnable.SetEnabled(item.GetOffline() && !downloading);
1082  if (item.GetOffline())
1083  {
1084  string enableLabel;
1085  if (item.GetEnabled())
1086  enableLabel = "#AR-Workshop_ButtonDisable";
1087  else
1088  enableLabel = "#AR-Workshop_ButtonEnable";
1089  m_NavEnable.SetLabel(enableLabel);
1090  }
1091 
1092  // Primary button
1093  string primaryLabel = SCR_WorkshopUiCommon.GetPrimaryActionName(item);
1094  if (!primaryLabel.IsEmpty())
1095  m_NavPrimary.SetLabel(primaryLabel);
1096  m_NavPrimary.SetEnabled(!primaryLabel.IsEmpty());
1097  }
1098 
1099  //------------------------------------------------------------------------------------------------
1101  protected bool GetShowReportedAddons()
1102  {
1103  SCR_FilterSet filterSet = m_Widgets.m_FilterPanelComponent.GetFilter();
1104 
1105  if (!filterSet)
1106  return false;
1107 
1108  SCR_FilterCategory otherCategory = filterSet.FindFilterCategory("other");
1109 
1110  if (!otherCategory)
1111  return false;
1112 
1113  SCR_FilterEntry reportedFilter = otherCategory.FindFilter("reported");
1114 
1115  if (!reportedFilter)
1116  return false;
1117 
1118  return reportedFilter.GetSelected();
1119  }
1120 
1121  //------------------------------------------------------------------------------------------------
1123  bool IsWidgetUnderCursor(Widget w)
1124  {
1125  Widget wCurrent = WidgetManager.GetWidgetUnderCursor();
1126  while (wCurrent)
1127  {
1128  if (wCurrent == w)
1129  return true;
1130  wCurrent = wCurrent.GetParent();
1131  }
1132  return false;
1133  }
1134 
1135  // ------ Paging -------
1136  //------------------------------------------------------------------------------------------------
1137  protected void OnPrevPageButton()
1138  {
1139  EInputDeviceType inputType = -1;
1140  if (m_bMousePageUsed)
1141  inputType = EInputDeviceType.MOUSE;
1142 
1143  m_bMousePageUsed = false;
1144 
1145  if (!IsWidgetUnderCursor(m_Widgets.m_LeftPanelArea) && inputType == EInputDeviceType.MOUSE)
1146  return;
1147 
1148  m_iCurrentPage--;
1149  m_iCurrentPage = Math.ClampInt(m_iCurrentPage, 0, GetPageCount() - 1);
1150 
1152  }
1153 
1154  //------------------------------------------------------------------------------------------------
1155  protected void OnNextPageButton()
1156  {
1157  EInputDeviceType inputType = -1;
1158  if (m_bMousePageUsed)
1159  inputType = EInputDeviceType.MOUSE;
1160 
1161  m_bMousePageUsed = false;
1162 
1163  if (!IsWidgetUnderCursor(m_Widgets.m_LeftPanelArea) && inputType == EInputDeviceType.MOUSE)
1164  return;
1165 
1166  m_iCurrentPage++;
1167  m_iCurrentPage = Math.ClampInt(m_iCurrentPage, 0, GetPageCount() - 1);
1168 
1170  }
1171 
1172  //------------------------------------------------------------------------------------------------
1173  protected void OnScrollPage()
1174  {
1175  float value = GetGame().GetInputManager().GetActionValue("MouseWheel");
1176 
1177  if (value != 0)
1178  m_bMousePageUsed = true;
1179 
1180  if (value < 0 && m_iCurrentPage < GetPageCount() - 1)
1181  OnNextPageButton();
1182  else if (value > 0 && m_iCurrentPage > 0)
1183  OnPrevPageButton();
1184  }
1185 
1186  //------------------------------------------------------------------------------------------------
1188  protected array<ref SCR_WorkshopItem> SelectItemsAtPage(array<ref SCR_WorkshopItem> items, int pageId)
1189  {
1190  array<ref SCR_WorkshopItem> itemsOut = {};
1191 
1192  float nItemsPerPage = GRID_N_ROWS * GRID_N_COLUMNS;
1193  int nPages = Math.Ceil(items.Count() / nItemsPerPage);
1194 
1195  if (pageId < 0 || pageId >= nPages)
1196  return itemsOut;
1197 
1198  int idStart = nItemsPerPage * pageId; // Select from this
1199  int idEnd = nItemsPerPage * (pageId + 1) - 1; // Up to this (including this)
1200 
1201  if (idEnd >= items.Count())
1202  idEnd = items.Count() - 1;
1203 
1204  for (int i = idStart; i <= idEnd; i++)
1205  {
1206  itemsOut.Insert(items[i]);
1207  }
1208 
1209  return itemsOut;
1210  }
1211 
1212  //------------------------------------------------------------------------------------------------
1214  protected void SwitchFocus(SCR_EListMenuWidgetFocus focus)
1215  {
1216  Widget focusTarget;
1217 
1218  switch (focus)
1219  {
1220  case SCR_EListMenuWidgetFocus.LIST:
1221  {
1222  if (m_LastFocusedTile && m_LastFocusedTile.IsVisible())
1223  focusTarget = m_LastFocusedTile.GetRootWidget();
1224  else if (m_Widgets.m_Grid)
1225  focusTarget = m_Widgets.m_Grid.GetChildren();
1226 
1227  break;
1228  }
1229 
1230  case SCR_EListMenuWidgetFocus.FILTERING:
1231  {
1232  focusTarget = m_Widgets.m_FilterPanelComponent.GetWidgets().m_FilterButton;
1233  break;
1234  }
1235 
1236  case SCR_EListMenuWidgetFocus.SORTING:
1237  {
1238  focusTarget = m_Widgets.m_SortingHeader.GetChildren();
1239  break;
1240  }
1241 
1242  case SCR_EListMenuWidgetFocus.NULL:
1243  {
1244  GetGame().GetWorkspace().SetFocusedWidget(null);
1245  return;
1246  }
1247  }
1248 
1249  if (!focusTarget || !focusTarget.IsVisible())
1250  {
1251  // Fallback
1252  focusTarget = m_Widgets.m_SortingHeader.GetChildren();
1253  }
1254 
1255  GetGame().GetWorkspace().SetFocusedWidget(focusTarget);
1256 
1257  // If we've focused a tile, we need to manually update the details panel (by switching page we focus the same widget, but the tile data is different)
1258  if (!focusTarget)
1259  return;
1260 
1261  SCR_ContentBrowserTileComponent comp = SCR_ContentBrowserTileComponent.FindComponent(focusTarget);
1262  if (comp)
1263  OnTileFocus(comp)
1264  }
1265 
1266  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1267  // C A L L B A C K S A N D E V E N T S
1268  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1269  //------------------------------------------------------------------------------------------------
1273  protected void OnConnected()
1274  {
1275  // Reinit the workshop API
1276  InitWorkshopApi();
1277 
1278  // Ask the same page again
1280  }
1281 
1282  //------------------------------------------------------------------------------------------------
1283  protected void OnTileClick(SCR_ScriptedWidgetComponent baseComp)
1284  {
1286 
1287  if (!comp || !m_bEnableOpenDetails)
1288  return;
1289 
1290  SCR_WorkshopItem selectedItem = comp.GetWorkshopItem();
1291  if (selectedItem)
1292  {
1293  if (! (selectedItem.GetRestricted()) || GetShowReportedAddons())
1294  {
1295  ContentBrowserDetailsMenu.OpenForWorkshopItem(selectedItem);
1296  }
1297  }
1298  }
1299 
1300  //------------------------------------------------------------------------------------------------
1301  protected void OnTileFocus(ScriptedWidgetComponent comp)
1302  {
1304  SCR_WorkshopItem item;
1305  if (tile)
1306  item = tile.GetWorkshopItem();
1307 
1308  if (!item || m_Widgets.m_AddonDetailsPanelComponent.GetItem() == item)
1309  return;
1310 
1311  m_Widgets.m_AddonDetailsPanelComponent.SetWorkshopItem(item);
1312 
1313  m_LastFocusedTile = tile;
1314  }
1315 
1316  //------------------------------------------------------------------------------------------------
1317  protected void OnFilterButton()
1318  {
1319  // Toggle the state of the filter panel
1320  bool show = !m_Widgets.m_FilterPanelComponent.GetFilterListBoxShown();
1321  m_Widgets.m_FilterPanelComponent.ShowFilterListBox(show);
1322 
1323  if (show)
1324  SwitchFocus(SCR_EListMenuWidgetFocus.FILTERING);
1325  else
1326  SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
1327  }
1328 
1329  //------------------------------------------------------------------------------------------------
1330  protected void OnPrimaryButton()
1331  {
1333 
1334  if (!item)
1335  return;
1336 
1337  SCR_WorkshopUiCommon.ExecutePrimaryAction(item, m_DownloadRequest);
1338  }
1339 
1340  //------------------------------------------------------------------------------------------------
1341  protected void OnEnableButton()
1342  {
1343  SCR_WorkshopUiCommon.OnEnableAddonButton(GetSelectedItem());
1344  }
1345 
1346  //------------------------------------------------------------------------------------------------
1347  protected void OnFavouriteButton()
1348  {
1350 
1351  if (!item)
1352  return;
1353 
1354  if (item.GetRestricted())
1355  return;
1356 
1357  bool fav = item.GetFavourite();
1358  item.SetFavourite(!fav);
1359  }
1360 
1361  //------------------------------------------------------------------------------------------------
1363  {
1364  if (GetSelectedItem())
1366  }
1367 
1368  //------------------------------------------------------------------------------------------------
1370  {
1372 
1373  m_iItemsTotal = m_WorkshopApi.GetTotalItemCount();
1375  m_bFirstLoad = false;
1376  }
1377 
1378  //------------------------------------------------------------------------------------------------
1380  {
1382 
1383  // Search Box Message
1384  m_iOnlineFilteredItems = m_WorkshopApi.GetTotalItemCount();
1385 
1386  array<WorkshopItem> items = {};
1387  m_WorkshopApi.GetPageItems(items);
1388 
1389  if (m_iOnlineFilteredItems < items.Count())
1390  m_iOnlineFilteredItems = items.Count();
1391 
1394 
1395  if (!m_bFirstLoad)
1397 
1398  // Update Displayed items
1399  if (callback.m_iPageId != m_iCurrentPage)
1400  return; // ?!
1401 
1402  array<ref SCR_WorkshopItem> itemsRegistered = {};
1403 
1404  foreach (auto i : items)
1405  {
1406  SCR_WorkshopItem iRegistered = SCR_AddonManager.GetInstance().Register(i);
1407  if (iRegistered)
1408  itemsRegistered.Insert(iRegistered);
1409  }
1410 
1411  if (!itemsRegistered.IsEmpty())
1412  {
1413  // There are some items received
1414  SetPanelsMode(false, m_bFirstPage && m_Widgets.m_FilterPanelComponent.AnyFilterButtonsVisible(), string.Empty, m_bFirstPage);
1415  }
1416  else
1417  {
1418  // No items received
1419  SetPanelsMode(false, messagePresetTag: MESSAGE_TAG_NOTHING_FOUND, forceFiltersList: true);
1420  }
1421 
1422  m_iOnlinePageCount = m_WorkshopApi.GetPageCount();
1423  GridScreen_DisplayItems(itemsRegistered);
1424 
1425  m_bFirstPage = false;
1426 
1427  if (!m_Widgets.m_FilterPanelComponent.GetFilterListBoxShown() || !m_Widgets.m_FilterPanelComponent.GetFocused())
1428  SwitchFocus(SCR_EListMenuWidgetFocus.LIST);
1429 
1430  if (m_bFirstLoad)
1431  GetGame().GetCallqueue().CallLater(RequestOnlinePageUnfiltered, LOAD_PAGE_DELAY, false, callback.m_iPageId);
1432  }
1433 
1434  //------------------------------------------------------------------------------------------------
1436  {
1438 
1439  if (GetShown())
1440  {
1441  // This submenu is shown, show the timeout dialog
1442  SCR_ConfigurableDialogUi dlg = SCR_CommonDialogs.CreateTimeoutTryAgainCancelDialog();
1443  dlg.m_OnCancel.Insert(Callback_OnRequestPageTimeout_OnCloseDialog);
1444  dlg.m_OnConfirm.Insert(Callback_OnRequestPageTimeout_OnDialogTryAgain);
1445  }
1446  else
1447  {
1448  // This submenu is not shown (probably we switched to another tab)
1449  // Try to perform the request again
1452  }
1453 
1454  m_bFailToLoad = true;
1455 
1456  m_iOnlinePageCount = 0;
1457  }
1458 
1459  //------------------------------------------------------------------------------------------------
1461  {
1462  // Set message
1464  RequestTabChange(EWorkshopTabId.OFFLINE);
1465  }
1466 
1467  //------------------------------------------------------------------------------------------------
1469  {
1472  }
1473 
1474  //------------------------------------------------------------------------------------------------
1476  protected void Callback_OnAddonOfflineStateChanged(SCR_WorkshopItem item, bool newState)
1477  {
1478  if (m_eMode == EContentBrowserAddonsSubMenuMode.MODE_OFFLINE)
1479  {
1480  // Some addon was installed or uninstalled, we must refresh the page
1482  }
1483  }
1484 
1485  //------------------------------------------------------------------------------------------------
1487  protected void Callback_OnAddonReportedStateChanged(SCR_WorkshopItem item, bool newReported)
1488  {
1489  // Refresh current page if it has this addon
1490  bool found = false;
1492  {
1493  if (comp.GetWorkshopItem() == item)
1494  {
1497  break;
1498  }
1499  }
1500  }
1501 
1502  //------------------------------------------------------------------------------------------------
1504  protected void OnFilterChange(SCR_FilterEntry filter)
1505  {
1507  RequestPage(0);
1508  }
1509 
1510  //------------------------------------------------------------------------------------------------
1512  protected void OnFilterSearchConfirm(SCR_EditBoxComponent comp, string newValue)
1513  {
1515  RequestPage(0);
1516  }
1517 
1518  //------------------------------------------------------------------------------------------------
1521  {
1523  RequestPage(0);
1524  }
1525 
1526  //------------------------------------------------------------------------------------------------
1528  {
1529  return m_Widgets;
1530  }
1531 
1532  //------------------------------------------------------------------------------------------------
1533  array<SCR_ContentBrowserTileComponent> GetTileComponents()
1534  {
1535  array<SCR_ContentBrowserTileComponent> tiles = {};
1536  m_aTileComponents.Copy(tiles);
1537 
1538  return tiles;
1539  }
1540 
1541  //------------------------------------------------------------------------------------------------
1543  {
1544  if (!m_aTileComponents.IsIndexValid(id))
1545  return null;
1546 
1547  return m_aTileComponents[id];
1548  }
1549 
1550  //------------------------------------------------------------------------------------------------
1552  {
1553  return m_aTileComponents.Count();
1554  }
1555 }
1556 
1557 //------------------------------------------------------------------------------------------------
1559 {
1560  // We will call back to submenu to perform packing of the JSON struct
1561  SCR_ContentBrowser_AddonsSubMenu m_AddonsSubMenu;
1562  protected bool m_bUseDefaultValues;
1563 
1564  //------------------------------------------------------------------------------------------------
1565  void SCR_ContentBrowser_GetAssetListParams(SCR_ContentBrowser_AddonsSubMenu subMenu, bool defaultValues = false)
1566  {
1567  m_bUseDefaultValues = defaultValues;
1568  m_AddonsSubMenu = subMenu;
1569  }
1570 
1571  //------------------------------------------------------------------------------------------------
1572  override void OnPack()
1573  {
1574  m_AddonsSubMenu.PackGetAssetListParams(this, m_bUseDefaultValues);
1575  }
1576 }
1577 
1578 //------------------------------------------------------------------------------------------------
1579 class SCR_CompareWorkshopItemName : SCR_SortCompare<SCR_WorkshopItem>
1580 {
1581  override static int Compare(SCR_WorkshopItem left, SCR_WorkshopItem right)
1582  {
1583  string name1 = left.GetName();
1584  string name2 = right.GetName();
1585 
1586  if (name1.Compare(name2) == -1)
1587  return 1;
1588  else
1589  return 0;
1590  }
1591 }
1592 
1593 //------------------------------------------------------------------------------------------------
1594 class SCR_CompareWorkshopItemTimeSinceLastPlay : SCR_SortCompare<SCR_WorkshopItem>
1595 {
1596  override static int Compare(SCR_WorkshopItem left, SCR_WorkshopItem right)
1597  {
1598  int timeLeft = left.GetTimeSinceLastPlay();
1599  if (timeLeft < 0) // Negative value means we have never played this.
1600  timeLeft = 0x7FFFFFFF; // We set it to max positive int for sorting purpuse.
1601  int timeRight = right.GetTimeSinceLastPlay();
1602  if (timeRight < 0)
1603  timeRight = 0x7FFFFFFF;
1604 
1605  return timeLeft < timeRight;
1606  }
1607 }
1608 
1609 //------------------------------------------------------------------------------------------------
1610 class SCR_CompareWorkshopItemTimeSinceFirstDownload : SCR_SortCompare<SCR_WorkshopItem>
1611 {
1612  override static int Compare(SCR_WorkshopItem left, SCR_WorkshopItem right)
1613  {
1614  int timeLeft = left.GetTimeSinceFirstDownload();
1615  if (timeLeft < 0) // Negative value means we never downloaded this
1616  timeLeft = 0x7FFFFFFF; // We set it to max positive int for sorting purpuse.
1617  int timeRight = right.GetTimeSinceFirstDownload();
1618  if (timeRight < 0)
1619  timeRight = 0x7FFFFFFF;
1620 
1621  return timeLeft < timeRight;
1622  }
1623 }
1624 
1625 //------------------------------------------------------------------------------------------------
1626 // Sort by time since last played
1627 class SCR_CompareWorkshopItemTargetSize : SCR_SortCompare<SCR_WorkshopItem>
1628 {
1629  override static int Compare(SCR_WorkshopItem left, SCR_WorkshopItem right)
1630  {
1631  float leftSize = left.GetTargetRevisionPatchSize();
1632  float rightSize = right.GetTargetRevisionPatchSize();
1633 
1634  return leftSize < rightSize;
1635  }
1636 }
m_bShown
protected bool m_bShown
Definition: SCR_InfoDisplay.c:61
SCR_ContentBrowser_GetAssetListParams
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1558
m_NavFilter
protected SCR_InputButtonComponent m_NavFilter
Definition: SCR_ContentBrowser_AddonsSubMenu.c:84
Filter_IntersectArrays
protected array< ref SCR_WorkshopItem > Filter_IntersectArrays(array< ref array< ref SCR_WorkshopItem >> arrays)
Returns intersection of all arrays (array of elements which are contained in all arrays)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:931
SCR_ContentBrowser_GetAssetListParams
void SCR_ContentBrowser_GetAssetListParams(SCR_ContentBrowser_AddonsSubMenu subMenu, bool defaultValues=false)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1557
m_iCurrentPage
protected int m_iCurrentPage
Definition: SCR_ContentBrowser_AddonsSubMenu.c:75
SCR_ContentBrowserTileComponent
Definition: SCR_ContentBrowserTileComponent.c:5
m_LastFocusedTile
protected SCR_ContentBrowserTileComponent m_LastFocusedTile
Definition: SCR_ContentBrowser_AddonsSubMenu.c:61
RequestOnlinePage
protected void RequestOnlinePage(int pageId)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:393
SCR_FilterEntry
Definition: SCR_FilterSet.c:9
MESSAGE_TAG_NOTHING_DOWNLOADED
const protected string MESSAGE_TAG_NOTHING_DOWNLOADED
Definition: SCR_ContentBrowser_AddonsSubMenu.c:39
UpdateItemsFoundMessage
void UpdateItemsFoundMessage(int current, int total)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:976
GetSelectedItem
protected SCR_WorkshopItem GetSelectedItem()
Returns currently selected workshop item.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1003
m_aTileComponents
protected ref array< SCR_ContentBrowserTileComponent > m_aTileComponents
Definition: SCR_ContentBrowser_AddonsSubMenu.c:52
m_iOnlinePageCount
protected int m_iOnlinePageCount
Definition: SCR_ContentBrowser_AddonsSubMenu.c:77
MESSAGE_TAG_NOTHING_FOUND
const protected string MESSAGE_TAG_NOTHING_FOUND
Definition: SCR_ContentBrowser_AddonsSubMenu.c:38
m_WorkshopApi
protected WorkshopApi m_WorkshopApi
Definition: SCR_ContentBrowser_AddonsSubMenu.c:48
Callback_OnRequestPageTimeout_OnCloseDialog
protected void Callback_OnRequestPageTimeout_OnCloseDialog()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1460
m_bEnableFilter
bool m_bEnableFilter
Definition: SCR_ContentBrowser_AddonsSubMenu.c:24
LOAD_PAGE_DELAY
const protected int LOAD_PAGE_DELAY
Definition: SCR_ContentBrowser_AddonsSubMenu.c:33
SCR_WorkshopDownloadSequence
Definition: SCR_WorkshopDownloadSequence.c:9
SCR_WorkshopApiCallback_RequestPage
Definition: SCR_OnlineServiceWorkshop.c:164
OnTileFocus
protected void OnTileFocus(ScriptedWidgetComponent comp)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1301
MESSAGE_TAG_ERROR_CONNECTION
const protected string MESSAGE_TAG_ERROR_CONNECTION
Definition: SCR_ContentBrowser_AddonsSubMenu.c:41
m_bConnected
protected bool m_bConnected
Definition: SCR_ContentBrowser_AddonsSubMenu.c:54
UIConstants
Definition: Constants.c:130
MODE_EXTERNAL_ITEM_ARRAY
MODE_EXTERNAL_ITEM_ARRAY
Definition: SCR_ContentBrowser_AddonsSubMenu.c:5
GridScreen_Init
protected void GridScreen_Init()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:681
m_bMousePageUsed
protected bool m_bMousePageUsed
Definition: SCR_ContentBrowser_AddonsSubMenu.c:70
SetPanelsMode
void SetPanelsMode(bool showEmptyPanel, bool forceFiltersList=false, string messagePresetTag=string.Empty, bool animateFiltersList=false)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:733
Callback_OnAddonReportedStateChanged
protected void Callback_OnAddonReportedStateChanged(SCR_WorkshopItem item, bool newReported)
Called by SCR_AddonManager when some addon is reported or unreported.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1487
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
Callback_OnRequestPageTimeout
protected void Callback_OnRequestPageTimeout(SCR_WorkshopApiCallback_RequestPage callback)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1435
OnTabCreate
override void OnTabCreate(Widget menuRoot, ResourceName buttonsLayout, int index)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:123
GridScreen_DisplayItems
protected void GridScreen_DisplayItems(array< ref SCR_WorkshopItem > items)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:718
SCR_FilterCategory
Definition: SCR_FilterSet.c:65
SCR_CommonDialogs
Definition: CommonDialogs.c:5
Callback_OnRequestPageTimeout_OnDialogTryAgain
protected void Callback_OnRequestPageTimeout_OnDialogTryAgain()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1468
GetTileComponentsCount
int GetTileComponentsCount()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1551
OnPrimaryButton
protected void OnPrimaryButton()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1330
m_iOnlineFilteredItems
protected int m_iOnlineFilteredItems
Definition: SCR_ContentBrowser_AddonsSubMenu.c:88
RequestPage
protected void RequestPage(int pageId)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:339
m_bEnableSorting
bool m_bEnableSorting
Definition: SCR_ContentBrowser_AddonsSubMenu.c:21
SetWorkshopItems
void SetWorkshopItems(array< ref SCR_WorkshopItem > items)
Sets the item array on which this tab operates. Only possible in external item array mode.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:93
Callback_OnAddonOfflineStateChanged
protected void Callback_OnAddonOfflineStateChanged(SCR_WorkshopItem item, bool newState)
Called by SCR_AddonManager when some addon is downloaded or uninstalled.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1476
SCR_SubMenuBase
Definition: SCR_SubMenuBase.c:6
OnTabShow
override void OnTabShow()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:205
Compare
SCR_ContentBrowser_GetAssetListParams PageParams Compare(SCR_WorkshopItem left, SCR_WorkshopItem right)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1581
OnFilterSearchConfirm
protected void OnFilterSearchConfirm(SCR_EditBoxComponent comp, string newValue)
Called when user confirms the value in the seacrh string.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1512
OnScrollPage
protected void OnScrollPage()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1173
SCR_FilterSet
Definition: SCR_FilterSet.c:183
OnTabHide
override void OnTabHide()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:220
SCR_ContentBrowser_AddonsSubMenuBaseWidgets
Definition: SCR_ContentBrowser_AddonsSubMenuBaseWidgets.c:4
LAYOUT_GRID_TILE
const protected ResourceName LAYOUT_GRID_TILE
Definition: SCR_ContentBrowser_AddonsSubMenu.c:35
SCR_WorkshopItem
Definition: SCR_WorkshopItem.c:21
OnDetailsButton
protected void OnDetailsButton(SCR_ButtonBaseComponent comp)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1362
ContentBrowserDetailsMenu
Definition: ContentBrowserDetailsMenu.c:2
OnTileClick
protected void OnTileClick(SCR_ScriptedWidgetComponent baseComp)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1283
OnFilterButton
protected void OnFilterButton()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1317
GetRootWidget
Widget GetRootWidget()
Definition: SCR_UITaskManagerComponent.c:160
SearchItems
array< ref SCR_WorkshopItem > SearchItems(array< ref SCR_WorkshopItem > items, string searchStr)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:768
Callback_OnRequestPageGetAssets
protected void Callback_OnRequestPageGetAssets(SCR_WorkshopApiCallback_RequestPage callback)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1379
m_NavEnable
protected SCR_InputButtonComponent m_NavEnable
Definition: SCR_ContentBrowser_AddonsSubMenu.c:82
SCR_FilterPanelComponent
Definition: SCR_FilterPanelComponent.c:11
OnPrevPageButton
protected void OnPrevPageButton()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1137
OnMenuUpdate
override void OnMenuUpdate(float tDelta)
Called on each frame.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:252
EContentBrowserAddonsSubMenuMode
EContentBrowserAddonsSubMenuMode
Definition: SCR_ContentBrowser_AddonsSubMenu.c:7
InitWidgetEventHandlers
protected void InitWidgetEventHandlers()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:183
EWorkshopTabId
EWorkshopTabId
Definition: ContentBrowserUI.c:1
PageRequestCallbackCleanup
protected void PageRequestCallbackCleanup(SCR_WorkshopApiCallback_RequestPage callback)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:421
SelectItemsAtPage
protected array< ref SCR_WorkshopItem > SelectItemsAtPage(array< ref SCR_WorkshopItem > items, int pageId)
Returns array of items within specified page, page ID starting from 0.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1188
m_NavPrimary
protected SCR_InputButtonComponent m_NavPrimary
Definition: SCR_ContentBrowser_AddonsSubMenu.c:81
UpdatePagingWidgets
protected void UpdatePagingWidgets()
Updates the widgets related to paging: buttons, text.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1020
OnFilterChange
protected void OnFilterChange(SCR_FilterEntry filter)
Called when filter listbox selection changes.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1504
DisplayExternalItems
protected void DisplayExternalItems(int pageId)
Selects items from the externally provided array and shows them on grid, only makes sense in external...
Definition: SCR_ContentBrowser_AddonsSubMenu.c:571
MESSAGE_TAG_NOTHING_DOWNLOADED_2
const protected string MESSAGE_TAG_NOTHING_DOWNLOADED_2
Definition: SCR_ContentBrowser_AddonsSubMenu.c:40
OnNextPageButton
protected void OnNextPageButton()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1155
m_iItemsTotal
protected int m_iItemsTotal
Definition: SCR_ContentBrowser_AddonsSubMenu.c:87
GetWidgets
SCR_ContentBrowser_AddonsSubMenuBaseWidgets GetWidgets()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1527
GRID_N_COLUMNS
const protected int GRID_N_COLUMNS
Definition: SCR_ContentBrowser_AddonsSubMenu.c:31
m_bFailToLoad
protected bool m_bFailToLoad
Definition: SCR_ContentBrowser_AddonsSubMenu.c:55
SCR_ButtonBaseComponent
Base class for any button, regardless its own content.
Definition: SCR_ButtonBaseComponent.c:3
Contains
proto external sealed bool Contains(IEntity item)
GRID_N_ROWS
const protected int GRID_N_ROWS
Definition: SCR_ContentBrowser_AddonsSubMenu.c:32
m_bEnableOpenDetails
protected bool m_bEnableOpenDetails
Definition: SCR_ContentBrowser_AddonsSubMenu.c:27
m_DownloadRequest
protected ref SCR_WorkshopDownloadSequence m_DownloadRequest
Definition: SCR_ContentBrowser_AddonsSubMenu.c:50
DisplayOfflineItems
protected void DisplayOfflineItems(int pageId)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:592
OnSortingHeaderChange
protected void OnSortingHeaderChange(SCR_SortHeaderComponent sortHeader)
Called when sorting header changes.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1520
SCR_CompareWorkshopItemTargetSize
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1627
index
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition: SCR_DestructionSynchronizationComponent.c:17
OnMenuFocusGained
override void OnMenuFocusGained()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:275
SCR_ContentBrowserFilterTag
Definition: ContentBrowserFilters.c:8
m_NavFavourite
protected SCR_InputButtonComponent m_NavFavourite
Definition: SCR_ContentBrowser_AddonsSubMenu.c:83
GetShowReportedAddons
protected bool GetShowReportedAddons()
Returns true when we have selected a filter to show reported mods.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1101
m_Widgets
protected ref SCR_ContentBrowser_AddonsSubMenuBaseWidgets m_Widgets
Definition: SCR_ContentBrowser_AddonsSubMenu.c:46
m_GetAssetListParamsDefault
protected ref SCR_ContentBrowser_GetAssetListParams m_GetAssetListParamsDefault
Definition: SCR_ContentBrowser_AddonsSubMenu.c:64
GridScreen_Clear
protected void GridScreen_Clear()
Tiles are cleared up here. They are not deleted, but hidden.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:709
SCR_CompareWorkshopItemTimeSinceLastPlay
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1594
SCR_ConfigurableDialogUi
Definition: SCR_ConfigurableDialogUI.c:13
m_AddonsSubMenu
SCR_ContentBrowser_AddonsSubMenu m_AddonsSubMenu
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1553
InitWorkshopApi
protected void InitWorkshopApi()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:299
InitWidgets
protected void InitWidgets()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:165
SCR_AddonManager
Definition: SCR_AddonManager.c:72
GetTileComponentById
SCR_ContentBrowserTileComponent GetTileComponentById(int id)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1542
IsWidgetUnderCursor
bool IsWidgetUnderCursor(Widget w)
Returns true if cursor over a given widget.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1123
SCR_EditBoxComponent
Definition: SCR_EditBoxComponent.c:8
m_bUseDefaultValues
protected bool m_bUseDefaultValues
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1554
UpdateButtons
protected void UpdateButtons()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1036
OnConnected
protected void OnConnected()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1273
MODE_OFFLINE
MODE_OFFLINE
Definition: SCR_ContentBrowser_AddonsSubMenu.c:2
OnTabChange
override void OnTabChange()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:284
m_GetAssetListParams
protected ref SCR_ContentBrowser_GetAssetListParams m_GetAssetListParams
Definition: SCR_ContentBrowser_AddonsSubMenu.c:63
OnFavouriteButton
protected void OnFavouriteButton()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1347
SCR_WorkshopUiCommon
Definition: SCR_WorkshopUiCommon.c:5
Callback_OnRequestPageGetAllAssets
protected void Callback_OnRequestPageGetAllAssets(SCR_WorkshopApiCallback_RequestPage callback)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1369
m_bFirstLoad
protected bool m_bFirstLoad
Definition: SCR_ContentBrowser_AddonsSubMenu.c:72
m_NavDetails
protected SCR_InputButtonComponent m_NavDetails
Definition: SCR_ContentBrowser_AddonsSubMenu.c:80
m_iOfflinePageCount
protected int m_iOfflinePageCount
Definition: SCR_ContentBrowser_AddonsSubMenu.c:76
SCR_ScriptedWidgetComponent
Definition: SCR_ScriptedWidgetComponent.c:7
GetTileComponents
array< SCR_ContentBrowserTileComponent > GetTileComponents()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1533
callback
DownloadConfigCallback callback
m_bPanelsModeEmpty
protected bool m_bPanelsModeEmpty
Definition: SCR_ContentBrowser_AddonsSubMenu.c:68
SwitchFocus
protected void SwitchFocus(SCR_EListMenuWidgetFocus focus)
Switch focus.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1214
SCR_SortHeaderComponent
Definition: SCR_SortHeaderComponent.c:7
OnEnableButton
protected void OnEnableButton()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:1341
MODE_ONLINE
MODE_ONLINE
Definition: SCR_ContentBrowser_AddonsSubMenu.c:3
m_aSearchCallbacks
protected ref array< ref SCR_WorkshopApiCallback_RequestPage > m_aSearchCallbacks
Definition: SCR_ContentBrowser_AddonsSubMenu.c:89
Filter_OfflineFilterAndSearch
protected array< ref SCR_WorkshopItem > Filter_OfflineFilterAndSearch(array< ref SCR_WorkshopItem > itemsIn)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:842
MESSAGE_TAG_LOADING
const protected string MESSAGE_TAG_LOADING
Definition: SCR_ContentBrowser_AddonsSubMenu.c:42
m_bClearCacheAtNextRequest
protected bool m_bClearCacheAtNextRequest
Definition: SCR_ContentBrowser_AddonsSubMenu.c:57
Attribute
enum EContentBrowserAddonsSubMenuMode Attribute("0", UIWidgets.ComboBox, "This menu is quite universal and can work in many modes - what do you want it to be?", "", ParamEnumArray.FromEnum(EContentBrowserAddonsSubMenuMode))] EContentBrowserAddonsSubMenuMode m_eMode
PackGetAssetListParams
void PackGetAssetListParams(SCR_ContentBrowser_GetAssetListParams p, bool defaultValues=false)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:433
OnMenuShow
override void OnMenuShow()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:243
EWorkshopItemQuery
EWorkshopItemQuery
Definition: SCR_AddonManager.c:34
OnTabRemove
override void OnTabRemove()
Definition: SCR_ContentBrowser_AddonsSubMenu.c:229
GetPageCount
protected int GetPageCount()
Returns page count, might depend on current mode.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:987
m_aExternalItems
protected ref array< ref SCR_WorkshopItem > m_aExternalItems
Definition: SCR_ContentBrowser_AddonsSubMenu.c:59
m_bFirstPage
protected bool m_bFirstPage
Definition: SCR_ContentBrowser_AddonsSubMenu.c:66
SetFilterConfiguration_EnabledAddons
void SetFilterConfiguration_EnabledAddons()
Sets filters to mode which lists only 'enabled' addons. Only works for offline tab.
Definition: SCR_ContentBrowser_AddonsSubMenu.c:108
SCR_InputButtonComponent
Definition: SCR_InputButtonComponent.c:1
RequestOnlinePageUnfiltered
protected void RequestOnlinePageUnfiltered(int pageId)
Definition: SCR_ContentBrowser_AddonsSubMenu.c:368
category
params category
Definition: SCR_VehicleDamageManagerComponent.c:180