Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_WorkshopUiCommon.c
Go to the documentation of this file.
1/*
2Common functions and variables related to Workshop UI.
3*/
4
6{
7 static const float IMAGE_SIZE_RATIO = 16.0 / 9.0;
8 static const string PRIMARY_ACTION_MESSAGE_DECORATION = "[%1]";
9 static const int CONTINUOUS_UPDATE_DELAY = 1000;
10 static const int MAX_DEPENDENCIES_SHOWN = 999;
11 static const int MAX_VOTES_SHOWN = 99999;
12
13 // Hacky big number of scenarios
14 static const int PAGE_SCENARIOS = 4096;
15
16 // Map addon tags to icon names
17 static const ResourceName ADDON_TYPE_FILTER_CATEGORY_CONFIG = "{A557E41062372854}Configs/ContentBrowser/Filters/category_type.conf";
18 static const ResourceName ADDON_MANW_FILTER_CATEGORY_CONFIG = "{FB69283C67BD9E67}Configs/ContentBrowser/Filters/category_manw.conf";
19 static ref map<string, string> s_sAddonTagImageMap = new map<string, string>();
20
21 // Map addon tags to default pictures
22 static ref map<string, ResourceName> s_sAddonTagDefaultThumbnailMap = new map<string, ResourceName>();
23
24 // --- THUMBNAILS ---
25 static const ResourceName ADDON_DEFAULT_THUMBNAIL = "{04EB797EBF59CDEF}UI/Textures/Workshop/AddonThumbnails/workshop_defaultFallback_UI.edds";
26 static const ResourceName ADDON_DEFAULT_THUMBNAIL_LOADING = "{75455009AFED376B}UI/Textures/Workshop/AddonThumbnails/workshop_loading_UI.edds";
27 static const ResourceName SCENARIO_SP_DEFAULT_THUMBNAIL = "{17D65C6D78C7722C}UI/Textures/Workshop/AddonThumbnails/workshop_scenarios_UI.edds";
28 static const ResourceName SCENARIO_MP_DEFAULT_THUMBNAIL = "{62A03BAAAED612E8}UI/Textures/Workshop/AddonThumbnails/workshop_mpScenarios_UI.edds";
29
30 // --- MESSAGES ---
31 static const string MESSAGE_DEPENDENCIES_MISSING = "#AR-Workshop_State_MissingDependencies";
32 static const string MESSAGE_DEPENDENCIES_DISABLED = "#AR-Workshop_State_MustEnableDependencies";
33 static const string MESSAGE_DEPENDENCIES_OUTDATED = "#AR-Workshop_State_DependencyUpdateAvailable";
34 static const string MESSAGE_UPDATE_AVAILABLE = "#AR-Workshop_State_UpdateAvailable";
35 static const string MESSAGE_REPORTED = "#AR-Workshop_State_Reported";
36 static const string MESSAGE_BANNED = "#AR-Workshop_State_Banned";
37 static const string MESSAGE_CORRUPTED = "#AR-Workshop_State_Corrupted";
38 static const string MESSAGE_RESTRICTED = "#AR-Workshop_State_Restricted";
39 static const string MESSAGE_RESTRICTED_GENERIC = "#AR-Workshop_Dialog_Error_ModIsBlocked";
40 static const string MESSAGE_FALLBACK = "#AR-CoreMenus_Tooltips_Unavailable";
41
42 // --- LABELS ---
43 static const string LABEL_DOWNLOAD = "#AR-Workshop_ButtonDownload";
44 static const string LABEL_UPDATE = "#AR-Workshop_ButtonUpdate";
45 static const string LABEL_CANCEL = "#AR-Workshop_ButtonCancel";
46 static const string LABEL_ENABLE = "#AR-Workshop_ButtonEnable";
47 static const string LABEL_DISABLE = "#AR-Workshop_ButtonDisable";
48 static const string LABEL_DELETE = "#AR-Workshop_ButtonDelete";
49 static const string LABEL_DEPENDENCIES_DOWNLOAD = "#AR-Workshop_ButtonDownloadDependencies";
50 static const string LABEL_DEPENDENCIES_ENABLE = "#AR-Workshop_ButtonEnableDependencies";
51 static const string LABEL_DEPENDENCIES_UPDATE = "#AR-Workshop_ButtonUpdateDependencies";
52 static const string LABEL_ADDON_DISABLED = "#AR-Workshop_State_Disabled";
53 static const string LABEL_ADDON_MISSING = "#AR-ServerBrowser_JoinMissingModsTittle";
54 static const string LABEL_REPORT = "#AR-Workshop_ButtonReport";
55 static const string LABEL_CANCEL_REPORT = "#AR-Workshop_CancelReportTitle";
56 static const string LABEL_DEPENDENCIES_NUMBER_ONE = "#AR-Workshop_Details_ModDependencies_Short_One_LC";
57 static const string LABEL_DEPENDENCIES_NUMBER = "#AR-Workshop_Details_ModDependencies_Short_LC";
58 static const string LABEL_DEPENDENT_NUMBER_ONE = "#AR-Workshop_Details_DependentMods_Short_One_LC_Downloaded";
59 static const string LABEL_DEPENDENT_NUMBER = "#AR-Workshop_Details_DependentMods_Short_LC_Downloaded";
60 static const string LABEL_IP_ADDRESS = "#AR-ServerBrowser_IP";
61
62 // --- ICONS ---
63 static const string ICON_DOWNLOAD = "download";
64 static const string ICON_UPDATE = "update";
65 static const string ICON_CANCEL_DOWNLOAD = "cancel";
66 static const string ICON_REPAIR = "repairCircle";
67 static const string ICON_DEPENDENCIES = "dependencies";
68 static const string ICON_REPORTED = "reportedByMe";
69 static const string ICON_ENABLED = "okCircle";
70 static const string ICON_DISABLED = "cancelCircle";
71 static const string ICON_LINKED = "linked";
72 static const string ICON_VERSION_MATCH = "version_match";
73 static const string ICON_VERSION_MISMATCH = "version_mismatch";
74
75 // --- REVISION AVAILABILITY ---
76 // Short messages
77 static const string MESSAGE_MOD_NOT_AVAILABLE = "#AR-Workshop_State_NotAvailable"; // Fallback
78 static const string MESSAGE_MOD_NOT_AVAILABLE_REMOVED = "#AR-Workshop_State_Removed";
79 static const string MESSAGE_MOD_NOT_AVAILABLE_INCOMPATIBLE = "#AR-Workshop_State_Incompatible";
80 static const string MESSAGE_MOD_AVAILABLE_WHEN_UPDATED = "#AR-Workshop_State_UpdateRequired";
81 static const string MESSAGE_MOD_DOWNLOAD_NOT_FINISHED = "#AR-Workshop_State_DownloadNotFinished";
82
83 // Verbose messages
84 static const string MESSAGE_VERBOSE_MOD_NOT_AVAILABLE = "#AR-Workshop_State_NotAvailableDesc"; // Fallback
85 static const string MESSAGE_VERBOSE_MOD_NOT_AVAILABLE_REMOVED = "#AR-Workshop_State_RemovedDesc";
86 static const string MESSAGE_VERBOSE_MOD_NOT_AVAILABLE_INCOMPATIBLE = "#AR-Workshop_State_IncompatibleDesc";
87 static const string MESSAGE_VERBOSE_MOD_AVAILABLE_WHEN_UPDATED = "#AR-Workshop_State_UpdateRequiredDesc";
88 static const string MESSAGE_VERBOSE_MOD_DOWNLOAD_NOT_FINISHED = "#AR-Workshop_State_DownloadNotFinishedDesc";
89
90 // Icons
91 static const string ICON_MOD_NOT_AVAILABLE = "not-available"; // Fallback
92 static const string ICON_MOD_NOT_AVAILABLE_REMOVED = "cancelCircle"; // TODO: specific icon?
93 static const string ICON_MOD_NOT_AVAILABLE_INCOMPATIBLE = "incompatible";
94 static const string ICON_MOD_AVAILABLE_WHEN_UPDATED = "available-when-updated";
95 static const string ICON_MOD_DOWNLOAD_NOT_FINISHED = "downloading"; // TODO: specific icon?
96
97 // --- DOWNLOAD STATES ---
98 static const string DOWNLOAD_STATE_DOWNLOADING = "#AR-DownloadManager_State_Downloading";
99 static const string DOWNLOAD_STATE_PROCESSING = "#AR-DownloadManager_State_Processing";
100 static const string DOWNLOAD_STATE_PAUSED = "#AR-Workshop_ButtonPause";
101 static const string DOWNLOAD_STATE_CANCELED = "#AR-Workshop_Canceled";
102 static const string DOWNLOAD_STATE_DOWNLOAD_FAIL = "#AR-Workshop_DownloadFail";
103 static const string DOWNLOAD_STATE_COMPLETED = "#AR-Workshop_Details_Downloaded";
104
105 // State icons
106 static const string DOWNLOAD_STATE_ICON_DOWNLOADING = "downloading";
107 static const string DOWNLOAD_STATE_ICON_PROCESSING = "update";
108 static const string DOWNLOAD_STATE_ICON_PAUSED = "download-pause";
109
110 // --- LINKS ---
111 static const string LINK_NAME_LICENSES = "Link_Bohemia";
112
113 // --- INIT ---
114 //------------------------------------------------------------------------------------------------
116 static void OnGameStart()
117 {
121
122 InitAddonTagMaps(ADDON_TYPE_FILTER_CATEGORY_CONFIG);
123 InitAddonTagMaps(ADDON_MANW_FILTER_CATEGORY_CONFIG);
124 }
125
126 //------------------------------------------------------------------------------------------------
128 static void TryOpenWorkshop()
129 {
131 if (mgr.GetUgcPrivilege())
132 ContentBrowserUI.Create();
133 else
134 {
137 }
138 }
139
140 //------------------------------------------------------------------------------------------------
141 protected static void OnTryOpenWorkshopUgcPrivilegeResult(bool result)
142 {
145 if (result)
146 ContentBrowserUI.Create();
147 else
148 SCR_ConfigurableDialogUi.CreateFromPreset(SCR_CommonDialogs.DIALOGS_CONFIG, "mp_you_dont_have_the_right");
149 }
150
151 // --- ADDON INTERACTIONS ---
152 //------------------------------------------------------------------------------------------------
156 {
157 if (item && (!item.GetOffline() || item.GetRestricted()))
158 return;
159
160 SetAddonEnabled(item, !item.GetEnabled());
161 }
162
163 //------------------------------------------------------------------------------------------------
166 static void OnEnableAddonToggleButton(SCR_WorkshopItem item, SCR_ModularButtonComponent buttonComp)
167 {
168 if (item && (!item.GetOffline() || item.GetRestricted()))
169 return;
170
171 // Button was clicked and it is now toggled or not, and this directly sets addon state
172 SetAddonEnabled(item, buttonComp.GetToggled());
173 }
174
175 //------------------------------------------------------------------------------------------------
178 {
179 // Check if some addons depend on this
180 array<ref SCR_WorkshopItem> offlineAndDependent = GetDownloadedDependentAddons(item);
181
182 if (!offlineAndDependent.IsEmpty())
183 {
184 // Some addons depend on this, show a special confirmation
185 SCR_DeleteAddonDependentAddonsDetected.Create(offlineAndDependent, item);
186 return;
187 }
188
189 // Show a standard confirmation for addon deletion
191 }
192
193 //------------------------------------------------------------------------------------------------
196 static void ExecutePrimaryAction(notnull SCR_WorkshopItem item, out SCR_WorkshopDownloadSequence dlRequest, Revision revision = null)
197 {
198 // --- Cancel current downloads ---
200 {
201 // Aggregate all actions of this item and create a dialog to confirm disabling all current downloads
202 SCR_WorkshopItemActionDownload download = item.GetDownloadAction();
203 SCR_WorkshopItemActionComposite dependenciesDownload = item.GetDependencyCompositeAction();
204
205 array<ref SCR_WorkshopItemActionDownload> downloadsToCancel = {};
206
207 if (download)
208 downloadsToCancel.Insert(download);
209
210 if (dependenciesDownload)
211 {
212 array<ref SCR_WorkshopItemAction> dependencyItemActions = dependenciesDownload.GetActions();
213 foreach (SCR_WorkshopItemAction action : dependencyItemActions)
214 {
216 if (downloadAction)
217 downloadsToCancel.Insert(downloadAction);
218 }
219 }
220
221 // Create a confirmation dialog
222 new SCR_CancelDownloadConfirmationDialog(downloadsToCancel);
223
224 return;
225 }
226
227 // Setup Revision
228 if (!revision)
229 revision = item.GetLatestRevision();
230
231 // --- Download ---
232 if (!item.GetOffline())
233 {
234 dlRequest = SCR_WorkshopDownloadSequence.Create(item, revision, dlRequest);
235 return;
236 }
237
238 // --- Fix issues ---
239 switch (item.GetHighestPriorityProblem())
240 {
241 // Start download/update of whatever is possible to download or update
242 case EWorkshopItemProblem.DEPENDENCY_MISSING:
243 case EWorkshopItemProblem.UPDATE_AVAILABLE:
244 case EWorkshopItemProblem.DEPENDENCY_OUTDATED:
245 {
246 dlRequest = SCR_WorkshopDownloadSequence.Create(item, revision, dlRequest);
247 return;
248 }
249
250 case EWorkshopItemProblem.DEPENDENCY_DISABLED:
251 {
252 item.SetDependenciesEnabled(true);
253 return;
254 }
255
256 //TODO: this does not take dependencies versions into account: what if a player wants a specific addon version to play a scenario he likes?
257 // He has no way of downgrading the dependencies so they match the main addon, if there is a version difference we force him to update everything to latest.
258 // This might cause the scenario he likes to become unavailable, if the author removed it from latest version
259 }
260 }
261
262 //------------------------------------------------------------------------------------------------
263 // NB: Download actions persist on canceled, failed or completed, as we might need to display their history
265 {
266 if (!item)
267 return false;
268
269 return item.GetDownloadAction() || item.GetDependencyCompositeAction();
270
271 //TODO: this might not be correct, as GetDownloadAction() will return true even when the action is completed or failed (for download manager history tab)
272 //Download actions are an entirely scripted solution, so it might be safer to use DownloadableItem.GetDownloadingRevision() instead.
273 }
274
275 //------------------------------------------------------------------------------------------------
276 // Returns if the download is in progress (active or paused) but not finished, canceled or failed
278 {
279 if (!item)
280 return false;
281
282 bool downloading;
284 if (action)
285 downloading = action.IsActive() || action.IsPaused();
286
287 return downloading;
288
289 //TODO:
290 //This method is currently used to disable Delete buttons in workshop menus, as you can't delete data that's not there yet.
291 //This is however hacky, since we have DownloadableItem.GetDownloadingRevision() already
292 //Check if that can be used instead
293 }
294
295 //------------------------------------------------------------------------------------------------
296 static SCR_EAddonPrimaryActionState GetPrimaryActionState(notnull SCR_WorkshopItem item)
297 {
298 // TODO: unify with other Primary Action stuff in SCR_WorkshopUiCommon, as we're performing pretty much the exact same checks
299 // Downloading is true if we are downloading anything for this addon or if we have started a download for any of its dependencies through this item
301 return SCR_EAddonPrimaryActionState.DOWNLOADING;
302
303 EWorkshopItemProblem itemProblem = item.GetHighestPriorityProblem();
304 if (itemProblem != EWorkshopItemProblem.NO_PROBLEM)
305 {
306 switch (itemProblem)
307 {
308 case EWorkshopItemProblem.UPDATE_AVAILABLE: return SCR_EAddonPrimaryActionState.UPDATE;
309 case EWorkshopItemProblem.DEPENDENCY_MISSING: return SCR_EAddonPrimaryActionState.DEPENDENCIES_DOWNLOAD;
310 case EWorkshopItemProblem.DEPENDENCY_OUTDATED: return SCR_EAddonPrimaryActionState.DEPENDENCIES_UPDATE;
311 case EWorkshopItemProblem.DEPENDENCY_DISABLED: return SCR_EAddonPrimaryActionState.DEPENDENCIES_ENABLE;
312 }
313 }
314
315 if (!item.GetOffline())
316 return SCR_EAddonPrimaryActionState.DOWNLOAD;
317
318 return SCR_EAddonPrimaryActionState.DOWNLOADED;
319 }
320
321 // --- ADDON VISUALS ---
322 //------------------------------------------------------------------------------------------------
324 static string GetTagImage(string tag)
325 {
326 tag.ToLower();
327 return s_sAddonTagImageMap.Get(tag);
328 }
329
330 //------------------------------------------------------------------------------------------------
332 {
333 array<WorkshopTag> tagObjs = {};
334
335 WorkshopItem internalItem = item.GetWorkshopItem();
336
337 if (!internalItem || !s_sAddonTagDefaultThumbnailMap)
338 return ADDON_DEFAULT_THUMBNAIL;
339
340 // Iterate all tags, return first found default iamge
341 internalItem.GetTags(tagObjs);
342 foreach (WorkshopTag tagObj : tagObjs)
343 {
344 string tagStr = tagObj.Name();
345 tagStr.ToLower();
346
347 if (s_sAddonTagDefaultThumbnailMap.Contains(tagStr))
348 return s_sAddonTagDefaultThumbnailMap.Get(tagStr);
349 }
350
351 return ADDON_DEFAULT_THUMBNAIL;
352 }
353
354 //------------------------------------------------------------------------------------------------
357 {
358 // Downloading
360 return LABEL_CANCEL;
361
362 // Not downloaded
363 if (!item.GetOffline())
364 return LABEL_DOWNLOAD;
365
366 // Issues to solve
367 switch (item.GetHighestPriorityProblem())
368 {
369 case EWorkshopItemProblem.DEPENDENCY_MISSING: return LABEL_DEPENDENCIES_DOWNLOAD;
370 case EWorkshopItemProblem.DEPENDENCY_DISABLED: return LABEL_DEPENDENCIES_ENABLE;
371 case EWorkshopItemProblem.UPDATE_AVAILABLE: return LABEL_UPDATE;
372 case EWorkshopItemProblem.DEPENDENCY_OUTDATED: return LABEL_DEPENDENCIES_UPDATE;
373 }
374
375 return string.Empty;
376 }
377
378 //------------------------------------------------------------------------------------------------
379 static void GetPrimaryActionLook(SCR_EAddonPrimaryActionState state, SCR_ERevisionAvailability availability, SCR_WorkshopItem item, out string icon, out Color iconColor, out string message, out Color messageColor)
380 {
381 if (!item)
382 return;
383
384 switch (state)
385 {
386 case SCR_EAddonPrimaryActionState.DOWNLOAD:
387 {
388 icon = ICON_DOWNLOAD;
389 iconColor = Color.FromInt(UIColors.IDLE_ACTIVE.PackToInt());
390
391 message = string.Format(PRIMARY_ACTION_MESSAGE_DECORATION, SCR_ByteFormat.GetReadableSize(item.GetSizeBytes())); //TODO: storage size
392 messageColor = Color.FromInt(UIColors.IDLE_ACTIVE.PackToInt());
393 break;
394 }
395
396 case SCR_EAddonPrimaryActionState.DOWNLOADING:
397 {
398 icon = DOWNLOAD_STATE_ICON_DOWNLOADING;
399 iconColor = Color.FromInt(UIColors.CONTRAST_COLOR.PackToInt());
400
402 message = WidgetManager.Translate("%1 %2", DOWNLOAD_STATE_DOWNLOADING, percentage);
403 messageColor = Color.FromInt(UIColors.NEUTRAL_INFORMATION.PackToInt());
404 break;
405 }
406
407 case SCR_EAddonPrimaryActionState.UPDATE:
408 {
409 if (availability != SCR_ERevisionAvailability.ERA_COMPATIBLE_UPDATE_AVAILABLE)
410 {
411 iconColor = Color.FromInt(UIColors.SLIGHT_WARNING.PackToInt());
412 messageColor = Color.FromInt(UIColors.IDLE_ACTIVE.PackToInt());
413 }
414 else
415 {
416 iconColor = Color.FromInt(UIColors.WARNING.PackToInt());
417 messageColor = Color.FromInt(UIColors.WARNING.PackToInt());
418 }
419
420 icon = ICON_UPDATE;
421 //TODO: update size
422 message = string.Format(PRIMARY_ACTION_MESSAGE_DECORATION, GetPrimaryActionName(item));
423 break;
424 }
425
426 case SCR_EAddonPrimaryActionState.DEPENDENCIES_UPDATE:
427 {
428 icon = ICON_UPDATE;
429 iconColor = Color.FromInt(UIColors.SLIGHT_WARNING.PackToInt());
430
431 message = string.Format(PRIMARY_ACTION_MESSAGE_DECORATION, GetPrimaryActionName(item));
432 messageColor = Color.FromInt(UIColors.IDLE_ACTIVE.PackToInt());
433 break;
434 }
435
436 case SCR_EAddonPrimaryActionState.DEPENDENCIES_DOWNLOAD:
437 {
438 icon = ICON_DOWNLOAD;
439 iconColor = Color.FromInt(UIColors.SLIGHT_WARNING.PackToInt());
440
441 message = string.Format(PRIMARY_ACTION_MESSAGE_DECORATION, GetPrimaryActionName(item));
442 messageColor = Color.FromInt(UIColors.IDLE_ACTIVE.PackToInt());
443 break;
444 }
445
446 case SCR_EAddonPrimaryActionState.DEPENDENCIES_ENABLE:
447 {
448 icon = ICON_REPAIR;
449 iconColor = Color.FromInt(UIColors.SLIGHT_WARNING.PackToInt());
450
451 message = string.Format(PRIMARY_ACTION_MESSAGE_DECORATION, GetPrimaryActionName(item));
452 messageColor = Color.FromInt(UIColors.IDLE_ACTIVE.PackToInt());
453 break;
454 }
455 }
456 }
457
458 //------------------------------------------------------------------------------------------------
459 static string GetPrimaryActionTooltipMessage(SCR_EAddonPrimaryActionState state, SCR_WorkshopItem item)
460 {
461 string message = MESSAGE_FALLBACK;
462
463 switch (state)
464 {
465 case SCR_EAddonPrimaryActionState.DOWNLOAD:
466 {
467 message = LABEL_DOWNLOAD;
468 break;
469 }
470
471 case SCR_EAddonPrimaryActionState.DOWNLOADING:
472 {
473 message = LABEL_CANCEL;
474 break;
475 }
476
477 case SCR_EAddonPrimaryActionState.UPDATE:
478 case SCR_EAddonPrimaryActionState.DEPENDENCIES_UPDATE:
479 case SCR_EAddonPrimaryActionState.DEPENDENCIES_DOWNLOAD:
480 case SCR_EAddonPrimaryActionState.DEPENDENCIES_ENABLE:
481 {
482 if (item)
483 message = GetPrimaryActionName(item);
484
485 break;
486 }
487 }
488
489 return message;
490 }
491
492 //------------------------------------------------------------------------------------------------
493 static void GetVersionDisplayLook(SCR_WorkshopItem item, out bool showUpdateText, out string currentVersionIcon, out Color currentVersionIconColor, out string currentVersionText, out Color currentVersionTextColor, out string updateVersionText)
494 {
495 if (!item)
496 return;
497
498 Revision revisionCurrent = item.GetCurrentLocalRevision();
499 Revision revisionLatest = item.GetLatestRevision();
500 bool needsUpdate = revisionCurrent && revisionLatest && !Revision.AreEqual(revisionCurrent, revisionLatest);
501
502 // Show update text
503 showUpdateText = needsUpdate;
504
505 // Version text
506 if (needsUpdate)
507 currentVersionTextColor = UIColors.NEUTRAL_ACTIVE_STANDBY;
508 else
509 currentVersionTextColor = UIColors.NEUTRAL_INFORMATION;
510
511 string revision;
512 if (revisionCurrent && item.GetOffline())
513 revision = revisionCurrent.GetVersion();
514 else if (revisionLatest)
515 revision = revisionLatest.GetVersion();
516
517 currentVersionText = UIConstants.FormatVersion(revision);
518
519 if (revisionLatest)
520 updateVersionText = UIConstants.FormatVersion(revisionLatest.GetVersion());
521
522 // Version Icon
523 if (!item.GetOffline())
524 {
525 currentVersionIconColor = Color.FromInt(UIColors.NEUTRAL_INFORMATION.PackToInt());
526 currentVersionIcon = ICON_DOWNLOAD;
527 }
528 else if (needsUpdate)
529 {
530 currentVersionIconColor = Color.FromInt(UIColors.SLIGHT_WARNING.PackToInt());
531 currentVersionIcon = ICON_UPDATE;
532 }
533 else
534 {
535 currentVersionIconColor = Color.FromInt(UIColors.NEUTRAL_INFORMATION.PackToInt());
536 currentVersionIcon = ICON_VERSION_MATCH;
537 }
538 }
539
540 //------------------------------------------------------------------------------------------------
543 {
544 if (!item.GetRestricted())
545 return string.Empty;
546
547 if (item.GetReportedByMe())
548 return MESSAGE_REPORTED;
549 else if (item.GetBlocked())
550 return MESSAGE_BANNED;
551 else
552 return MESSAGE_RESTRICTED;
553 }
554
555 //------------------------------------------------------------------------------------------------
557 static string GetReportTypeString(EWorkshopReportType eReportType)
558 {
559 switch (eReportType)
560 {
561 case EWorkshopReportType.EWREPORT_INAPPROPRIATE_CONTENT: return "#AR-Workshop_Report_InappropiateContent";
562 case EWorkshopReportType.EWREPORT_OFFENSIVE_LANGUAGE: return "#AR-Workshop_Report_OffensiveLanguage";
563 case EWorkshopReportType.EWREPORT_MISLEADING: return "#AR-Workshop_Report_Missleading_NonFunctional";
564 case EWorkshopReportType.EWREPORT_SPAM: return "#AR-Workshop_Report_Spam";
565 case EWorkshopReportType.EWREPORT_SCAM: return "#AR-Workshop_Report_Scam";
566 case EWorkshopReportType.EWREPORT_MALICIOUS: return "#AR-Workshop_Report_Malicious";
567 case EWorkshopReportType.EWREPORT_INTELLECTUAL_PROPERTY: return "#AR-Workshop_Report_IPInfringement";
568 case EWorkshopReportType.EWREPORT_OTHER: return "#AR-Workshop_Report_Other";
569 }
570
571 return string.Empty;
572 }
573
574 //------------------------------------------------------------------------------------------------
575 static void UpdateEnableAddonToggleButton(SCR_ModularButtonComponent button, SCR_WorkshopItem item, SCR_EAddonPrimaryActionState state, bool alwaysShowWhenDownloaded = true)
576 {
577 if (!item)
578 {
579 button.SetVisible(false);
580 return;
581 }
582
583 bool show = state == SCR_EAddonPrimaryActionState.DOWNLOADED;
584 if (alwaysShowWhenDownloaded)
585 show = item.GetOffline();
586
587 /*WorldSaveItem save = WorldSaveItem.Cast(item.GetWorkshopItem());
588 if (save && show)
589 show = !SCR_SaveWorkshopManager.IsSaveLocalOnly(save);*/
590
591 button.SetVisible(show);
592 button.SetToggled(item.GetEnabled(), false);
593
594 if (!item.GetOffline())
595 return;
596
597 button.SetEnabled(state != SCR_EAddonPrimaryActionState.DOWNLOADING && !(!item.GetEnabled() && state == SCR_EAddonPrimaryActionState.DEPENDENCIES_DOWNLOAD));
598
599 string enableButtonMode = "no_problems";
600 if (state == SCR_EAddonPrimaryActionState.DEPENDENCIES_DOWNLOAD || state == SCR_EAddonPrimaryActionState.DEPENDENCIES_ENABLE)
601 enableButtonMode = "problems";
602
603 button.SetEffectsWithAnyTagEnabled({"all", enableButtonMode});
604 }
605
606 //------------------------------------------------------------------------------------------------
607 static array<ref SCR_WorkshopItem> GetDownloadedDependentAddons(notnull SCR_WorkshopItem item)
608 {
609 return SCR_AddonManager.SelectItemsAnd(item.GetDependentAddons(), EWorkshopItemQuery.OFFLINE);
610 }
611
612 // --- UNIFIED ROUNDING ---
613 //------------------------------------------------------------------------------------------------
614 static int GetDownloadProgressPercentage(float progress)
615 {
616 return Math.Floor(100.0 * progress);
617 }
618
619 //------------------------------------------------------------------------------------------------
620 static int GetRatingPercentage(float rating)
621 {
622 return Math.Ceil(100.0 * rating);
623 }
624
625 //------------------------------------------------------------------------------------------------
626 static int GetUpvotes(notnull SCR_WorkshopItem item)
627 {
628 return Math.Clamp(Math.Ceil(item.GetAverageRating() * item.GetRatingCount()), 0, MAX_VOTES_SHOWN);
629 }
630
631 //------------------------------------------------------------------------------------------------
632 static int GetDownvotes(notnull SCR_WorkshopItem item)
633 {
634 return Math.Clamp(Math.Ceil(item.GetRatingCount() - (item.GetAverageRating() * item.GetRatingCount())), 0, MAX_VOTES_SHOWN);
635 }
636
637 // --- REVISION ERROR MESSAGES ---
638 //------------------------------------------------------------------------------------------------
640 {
641 if (!item)
642 return MESSAGE_MOD_NOT_AVAILABLE;
643
645 }
646
647 //------------------------------------------------------------------------------------------------
648 static string GetRevisionAvailabilityErrorMessage(SCR_ERevisionAvailability state)
649 {
650 switch (state)
651 {
652 case SCR_ERevisionAvailability.ERA_AVAILABLE: return string.Empty;
653 case SCR_ERevisionAvailability.ERA_UNKNOWN_AVAILABILITY: return MESSAGE_MOD_NOT_AVAILABLE;
654 case SCR_ERevisionAvailability.ERA_DELETED: return MESSAGE_MOD_NOT_AVAILABLE_REMOVED;
655 case SCR_ERevisionAvailability.ERA_OBSOLETE: return MESSAGE_MOD_NOT_AVAILABLE_INCOMPATIBLE;
656 case SCR_ERevisionAvailability.ERA_COMPATIBLE_UPDATE_AVAILABLE: return MESSAGE_MOD_AVAILABLE_WHEN_UPDATED;
657 case SCR_ERevisionAvailability.ERA_DOWNLOAD_NOT_FINISHED: return MESSAGE_MOD_DOWNLOAD_NOT_FINISHED;
658 }
659
660 return MESSAGE_MOD_NOT_AVAILABLE;
661 }
662
663 //------------------------------------------------------------------------------------------------
665 {
666 if (!item)
667 return MESSAGE_VERBOSE_MOD_NOT_AVAILABLE;
668
670 }
671
672 //------------------------------------------------------------------------------------------------
673 static string GetRevisionAvailabilityErrorMessageVerbose(SCR_ERevisionAvailability state)
674 {
675 switch (state)
676 {
677 case SCR_ERevisionAvailability.ERA_AVAILABLE: return string.Empty;
678 case SCR_ERevisionAvailability.ERA_UNKNOWN_AVAILABILITY: return MESSAGE_VERBOSE_MOD_NOT_AVAILABLE;
679 case SCR_ERevisionAvailability.ERA_DELETED: return MESSAGE_VERBOSE_MOD_NOT_AVAILABLE_REMOVED;
680 case SCR_ERevisionAvailability.ERA_OBSOLETE: return MESSAGE_VERBOSE_MOD_NOT_AVAILABLE_INCOMPATIBLE;
681 case SCR_ERevisionAvailability.ERA_COMPATIBLE_UPDATE_AVAILABLE: return MESSAGE_VERBOSE_MOD_AVAILABLE_WHEN_UPDATED;
682 case SCR_ERevisionAvailability.ERA_DOWNLOAD_NOT_FINISHED: return MESSAGE_VERBOSE_MOD_DOWNLOAD_NOT_FINISHED;
683 }
684
685 return MESSAGE_VERBOSE_MOD_NOT_AVAILABLE;
686 }
687
688 //------------------------------------------------------------------------------------------------
690 {
691 if (!item)
692 return ICON_MOD_NOT_AVAILABLE;
693
695 }
696
697 //------------------------------------------------------------------------------------------------
698 static string GetRevisionAvailabilityErrorTexture(SCR_ERevisionAvailability state)
699 {
700 switch (state)
701 {
702 case SCR_ERevisionAvailability.ERA_AVAILABLE: return string.Empty;
703 case SCR_ERevisionAvailability.ERA_UNKNOWN_AVAILABILITY: return ICON_MOD_NOT_AVAILABLE;
704 case SCR_ERevisionAvailability.ERA_DELETED: return ICON_MOD_NOT_AVAILABLE_REMOVED;
705 case SCR_ERevisionAvailability.ERA_OBSOLETE: return ICON_MOD_NOT_AVAILABLE_INCOMPATIBLE;
706 case SCR_ERevisionAvailability.ERA_COMPATIBLE_UPDATE_AVAILABLE: return ICON_MOD_AVAILABLE_WHEN_UPDATED;
707 case SCR_ERevisionAvailability.ERA_DOWNLOAD_NOT_FINISHED: return ICON_MOD_DOWNLOAD_NOT_FINISHED;
708 }
709
710 return ICON_MOD_NOT_AVAILABLE;
711 }
712
713 // --- PROTECTED ---
714 //------------------------------------------------------------------------------------------------
716 protected static void Callback_OnAddonsChecked()
717 {
718 array<string> bannedAddons = {};
719 GetGame().GetBackendApi().GetWorkshop().GetBannedItems(bannedAddons);
720
721 if (!bannedAddons.IsEmpty())
722 new SCR_BannedAddonsDetectedDialog(bannedAddons);
723 }
724
725 //------------------------------------------------------------------------------------------------
727 protected static void SetAddonEnabled(SCR_WorkshopItem item, bool newEnabled)
728 {
729 if (!item)
730 return;
731
732 item.SetEnabled(newEnabled);
733
734 if (newEnabled)
735 {
736 // Auto enable dependencies too
737 item.SetDependenciesEnabled(true);
738 return;
739 }
740
741 // Check if some addons depend on this
742 array<ref SCR_WorkshopItem> offlineAndEnabled = SCR_AddonManager.SelectItemsAnd(
743 item.GetDependentAddons(),
744 EWorkshopItemQuery.OFFLINE | EWorkshopItemQuery.ENABLED);
745
746 if (!offlineAndEnabled.IsEmpty())
747 SCR_DisableDependentAddonsDialog.CreateDisableDependentAddons(offlineAndEnabled, item);
748 }
749
750 //------------------------------------------------------------------------------------------------
751 protected static void InitAddonTagMaps(ResourceName configPath)
752 {
753 // Load addon type config
754 SCR_FilterCategory cat = SCR_ConfigHelperT<SCR_FilterCategory>.GetConfigObject(configPath);
755 if (!cat)
756 return;
757
758 foreach (SCR_FilterEntry filter : cat.GetFilters())
759 {
760 string internalName = filter.m_sInternalName;
761 internalName.ToLower();
762 s_sAddonTagImageMap.Insert(internalName, filter.m_sImageName);
763
765 if (filterTag)
766 {
767 if (!filterTag.m_sDefaultThumbnail.IsEmpty())
768 s_sAddonTagDefaultThumbnailMap.Insert(internalName, filterTag.m_sDefaultThumbnail);
769 }
770 }
771 }
772}
773
774enum SCR_EAddonPrimaryActionState
775{
776 DOWNLOAD,
777 UPDATE,
783}
ArmaReforgerScripted GetGame()
Definition game.c:1398
void SCR_DisableDependentAddonsDialog(array< ref SCR_WorkshopItem > items, string preset, SCR_WorkshopItem dependency)
EWorkshopItemQuery
EWorkshopItemProblem
class SCR_WorkshopUiCommon DOWNLOADING
class SCR_WorkshopUiCommon DEPENDENCIES_DOWNLOAD
class SCR_WorkshopUiCommon DOWNLOAD
Job is downloading revision without any other revision of the asset present - fresh download.
class SCR_WorkshopUiCommon DEPENDENCIES_ENABLE
class SCR_WorkshopUiCommon UPDATE
Some revision is already present and job is downloading newer one.
class SCR_WorkshopUiCommon DEPENDENCIES_UPDATE
Definition Color.c:13
Definition Math.c:13
ref ScriptInvoker m_OnUgcPrivilegeResult
void NegotiateUgcPrivilegeAsync()
static SCR_ERevisionAvailability ItemAvailability(notnull WorkshopItem item)
ref ScriptInvoker m_OnAddonsChecked
bool GetUgcPrivilege()
Returns immediate value of UserPrivilege.USER_GEN_CONTENT.
static array< ref SCR_WorkshopItem > SelectItemsAnd(array< ref SCR_WorkshopItem > items, EWorkshopItemQuery query)
static SCR_AddonManager GetInstance()
Dialog which lists names of all banned addons.
static SCR_ConfigurableDialogUi CreateFromPreset(ResourceName presetsResourceName, string tag, SCR_ConfigurableDialogUi customDialogObj=null)
Creates a dialog from preset.
This dialog is shown when we want to delete an addon but some other downloaded addons depend on it.
static SCR_DeleteAddonDependentAddonsDetected Create(array< ref SCR_WorkshopItem > items, SCR_WorkshopItem item)
static SCR_DeleteAddonDialog CreateDeleteAddon(SCR_WorkshopItem item)
static float GetItemDownloadActionsProgress(SCR_WorkshopItem item)
Returns overall download progress for all actions of a workshop item.
array< ref SCR_FilterEntry > GetFilters()
Returns array with filter entries.
static SCR_WorkshopDownloadSequence Create(SCR_WorkshopItem item, Revision itemTargetRevision, SCR_WorkshopDownloadSequence previous)
Tries to create a new request if previous doesn't exist or finished. Otherwise returns the previous r...
Composite action which includes multiple subactions.
Revision GetCurrentLocalRevision()
Returns the revision which we currently have on the local storage.
Revision GetLatestRevision()
bool GetOffline()
True when we have the item on our local storage.
EWorkshopItemProblem GetHighestPriorityProblem()
array< ref SCR_WorkshopItem > GetDependentAddons()
Returns array of dependendent addons.
SCR_WorkshopItemActionComposite GetDependencyCompositeAction()
Returns the current composite action performed for dependencies of this addon.
void SetEnabled(bool enable)
bool GetRestricted()
Returns true when item is restricted for any reason (blocked or reported).
void SetDependenciesEnabled(bool enable)
Enables/disables all downloaded dependencies.
SCR_WorkshopItemActionDownload GetDownloadAction()
Returns current download action.
static void UpdateEnableAddonToggleButton(SCR_ModularButtonComponent button, SCR_WorkshopItem item, SCR_EAddonPrimaryActionState state, bool alwaysShowWhenDownloaded=true)
static int GetRatingPercentage(float rating)
static int GetDownvotes(notnull SCR_WorkshopItem item)
static string GetRevisionAvailabilityErrorMessage(WorkshopItem item)
static string GetRevisionAvailabilityErrorTexture(WorkshopItem item)
static void OnTryOpenWorkshopUgcPrivilegeResult(bool result)
static string GetRevisionAvailabilityErrorMessageVerbose(SCR_ERevisionAvailability state)
static void SetAddonEnabled(SCR_WorkshopItem item, bool newEnabled)
Internal method to handle addon enabling. Might show a dialog or enable some other addons(dependnecie...
static string GetReportTypeString(EWorkshopReportType eReportType)
Converts report type enum to stringtable entry.
static string GetTagImage(string tag)
Returns image associated with given Workshop tag.
static void OnEnableAddonButton(SCR_WorkshopItem item)
static ResourceName GetDefaultAddonThumbnail(notnull SCR_WorkshopItem item)
static string GetPrimaryActionName(SCR_WorkshopItem item)
Returns name of suggested primary action.
static void OnEnableAddonToggleButton(SCR_WorkshopItem item, SCR_ModularButtonComponent buttonComp)
static void ExecutePrimaryAction(notnull SCR_WorkshopItem item, out SCR_WorkshopDownloadSequence dlRequest, Revision revision=null)
static array< ref SCR_WorkshopItem > GetDownloadedDependentAddons(notnull SCR_WorkshopItem item)
static string GetRevisionAvailabilityErrorTexture(SCR_ERevisionAvailability state)
static SCR_EAddonPrimaryActionState GetPrimaryActionState(notnull SCR_WorkshopItem item)
static bool IsDownloadingAddon(SCR_WorkshopItem item)
static string GetRevisionAvailabilityErrorMessage(SCR_ERevisionAvailability state)
static string GetRestrictedAddonStateText(SCR_WorkshopItem item)
Returns string such as "Banned" or "Reported" for a restricted item. Otherwise returns empty string.
static string GetRevisionAvailabilityErrorMessageVerbose(WorkshopItem item)
static void InitAddonTagMaps(ResourceName configPath)
static void Callback_OnAddonsChecked()
Callback from addon manager when addons are checked.
static void GetPrimaryActionLook(SCR_EAddonPrimaryActionState state, SCR_ERevisionAvailability availability, SCR_WorkshopItem item, out string icon, out Color iconColor, out string message, out Color messageColor)
static void OnDeleteAddonButton(SCR_WorkshopItem item)
Shows a confirmation dialog when unsubscribing an addon.
static int GetUpvotes(notnull SCR_WorkshopItem item)
static int GetDownloadProgressPercentage(float progress)
static bool IsDownloadingAddonOrDependencies(SCR_WorkshopItem item)
static void GetVersionDisplayLook(SCR_WorkshopItem item, out bool showUpdateText, out string currentVersionIcon, out Color currentVersionIconColor, out string currentVersionText, out Color currentVersionTextColor, out string updateVersionText)
static string GetPrimaryActionTooltipMessage(SCR_EAddonPrimaryActionState state, SCR_WorkshopItem item)
Workshop Item instance.
Definition Types.c:486
override bool OnGameStart()
Gets called after world is initialized but before first ticks.
Definition game.c:561
EWorkshopReportType