#region Copyright & License Information /* * Copyright (c) The OpenRA Developers and Contributors * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using System.Collections.Generic; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits.Render; using OpenRA.Primitives; using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets.Logic { public class EncyclopediaLogic : ChromeLogic { readonly World world; readonly ModData modData; readonly ScrollPanelWidget descriptionPanel; readonly LabelWidget descriptionLabel; readonly SpriteFont descriptionFont; readonly ScrollPanelWidget actorList; readonly ScrollItemWidget headerTemplate; readonly ScrollItemWidget template; readonly ActorPreviewWidget previewWidget; ActorInfo selectedActor; ScrollItemWidget firstItem; [ObjectCreator.UseCtor] public EncyclopediaLogic(Widget widget, World world, ModData modData, Action onExit) { this.world = world; this.modData = modData; actorList = widget.Get("ACTOR_LIST"); headerTemplate = widget.Get("HEADER"); template = widget.Get("TEMPLATE"); widget.Get("ACTOR_INFO").IsVisible = () => selectedActor != null; previewWidget = widget.Get("ACTOR_PREVIEW"); previewWidget.IsVisible = () => selectedActor != null; descriptionPanel = widget.Get("ACTOR_DESCRIPTION_PANEL"); descriptionLabel = descriptionPanel.Get("ACTOR_DESCRIPTION"); descriptionFont = Game.Renderer.Fonts[descriptionLabel.Font]; actorList.RemoveChildren(); var actorEncyclopediaPair = GetFilteredActorEncyclopediaPairs(); var categories = actorEncyclopediaPair.Select(a => a.Value.Category).Distinct(). OrderBy(string.IsNullOrWhiteSpace).ThenBy(s => s); foreach (var category in categories) { CreateActorGroup(category, actorEncyclopediaPair .Where(a => a.Value.Category == category) .OrderBy(a => a.Value.Order) .Select(a => a.Key)); } widget.Get("BACK_BUTTON").OnClick = () => { Game.Disconnect(); Ui.CloseWindow(); onExit(); }; } IReadOnlyCollection> GetFilteredActorEncyclopediaPairs() { var actors = new List>(); foreach (var actor in modData.DefaultRules.Actors.Values) { if (actor.TraitInfos().Count == 0) continue; var statistics = actor.TraitInfoOrDefault(); if (statistics != null && !string.IsNullOrEmpty(statistics.OverrideActor)) continue; var encyclopedia = actor.TraitInfoOrDefault(); if (encyclopedia == null) continue; actors.Add(new KeyValuePair(actor, encyclopedia)); } return actors; } void CreateActorGroup(string title, IEnumerable actors) { var header = ScrollItemWidget.Setup(headerTemplate, () => false, () => { }); header.Get("LABEL").GetText = () => title; actorList.AddChild(header); foreach (var actor in actors) { var item = ScrollItemWidget.Setup(template, () => selectedActor != null && selectedActor.Name == actor.Name, () => SelectActor(actor)); var label = item.Get("TITLE"); var name = actor.TraitInfos().FirstOrDefault(info => info.EnabledByDefault)?.Name; if (!string.IsNullOrEmpty(name)) WidgetUtils.TruncateLabelToTooltip(label, FluentProvider.GetMessage(name)); if (firstItem == null) { firstItem = item; SelectActor(actor); } actorList.AddChild(item); } } void SelectActor(ActorInfo actor) { selectedActor = actor; var typeDictionary = new TypeDictionary() { new OwnerInit(world.WorldActor.Owner), new FactionInit(world.WorldActor.Owner.PlayerReference.Faction) }; foreach (var actorPreviewInit in actor.TraitInfos()) foreach (var inits in actorPreviewInit.ActorPreviewInits(actor, ActorPreviewType.ColorPicker)) typeDictionary.Add(inits); previewWidget.SetPreview(actor, typeDictionary); var text = ""; var buildable = actor.TraitInfoOrDefault(); if (buildable != null) { var prerequisites = buildable.Prerequisites .Select(a => ActorName(modData.DefaultRules, a)) .Where(s => !s.StartsWith('~') && !s.StartsWith('!')) .ToList(); if (prerequisites.Count != 0) text += $"Requires {prerequisites.JoinWith(", ")}\n\n"; } var info = actor.TraitInfoOrDefault(); if (info != null && !string.IsNullOrEmpty(info.Description)) text += WidgetUtils.WrapText(FluentProvider.GetMessage(info.Description) + "\n\n", descriptionLabel.Bounds.Width, descriptionFont); var height = descriptionFont.Measure(text).Y; descriptionLabel.GetText = () => text; descriptionLabel.Bounds.Height = height; descriptionPanel.Layout.AdjustChildren(); descriptionPanel.ScrollToTop(); } static string ActorName(Ruleset rules, string name) { if (rules.Actors.TryGetValue(name.ToLowerInvariant(), out var actor)) { var actorTooltip = actor.TraitInfos().FirstOrDefault(info => info.EnabledByDefault); if (actorTooltip != null) return FluentProvider.GetMessage(actorTooltip.Name); } return name; } } }