using Content.Shared._NF.Research; using Content.Shared.Research.Prototypes; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; namespace Content.Client._NF.Research.UI; [GenerateTypedNameReferences] public sealed partial class FancyResearchConsoleItem : LayoutContainer { [Dependency] private readonly IPrototypeManager _prototype = default!; // Public fields public TechnologyPrototype Prototype; public Action? SelectAction; public ResearchAvailability Availability; // Some visuals - now using centralized color scheme public static readonly Color DefaultColor = ResearchColorScheme.UIColors.DefaultTechBackground; public static readonly Color DefaultBorderColor = ResearchColorScheme.UIColors.DefaultTechBorder; public static readonly Color DefaultHoveredColor = ResearchColorScheme.UIColors.DefaultTechHover; public Color BackgroundColor = DefaultColor; public Color SecondaryBackgroundColor = DefaultColor; public Color BorderColor = DefaultBorderColor; public Color HoveredColor = DefaultHoveredColor; public Color SecondaryHoveredColor = DefaultHoveredColor; public Color SelectedColor = DefaultHoveredColor; public Color SecondarySelectedColor = DefaultHoveredColor; // Selection state private bool _isSelected = false; public bool IsSelected { get => _isSelected; set { if (_isSelected == value) return; _isSelected = value; UpdateColor(); } } public FancyResearchConsoleItem(TechnologyPrototype proto, SpriteSystem sprite, ResearchAvailability availability) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); Availability = availability; Prototype = proto; // Get the primary discipline for background color var primaryDiscipline = _prototype.Index(proto.Discipline); var primaryColor = primaryDiscipline.Color; // Check if there's a secondary discipline TechDisciplinePrototype? secondaryDiscipline = null; Color? secondaryColor = null; if (proto.SecondaryDiscipline.HasValue) { secondaryDiscipline = _prototype.Index(proto.SecondaryDiscipline.Value); secondaryColor = secondaryDiscipline.Color; } // Handle technology icon - prioritize EntityIcon for full sprite layers if (proto.EntityIcon.HasValue) { // Use EntityPrototypeView to show all sprite layers ResearchDisplay.SetPrototype(proto.EntityIcon.Value); } else if (proto.Icon != null) { // For legacy Icon support, we need to handle this differently since EntityPrototypeView // expects entity prototypes. For now, we'll need a fallback approach. // TODO: Consider deprecating the Icon field in favor of EntityIcon // We cannot directly set a SpriteSpecifier on EntityPrototypeView // This is a limitation of the new approach - EntityIcon should be preferred // For now, this will show no icon for legacy Icon-only technologies ResearchDisplay.SetPrototype(null); } else { // No icon specified ResearchDisplay.SetPrototype(null); } Button.OnPressed += Selected; Button.OnDrawModeChanged += UpdateColor; // Set colors - border & background color varies by availability state BorderColor = ResearchColorScheme.GetTechBorderColor(availability); // Calculate background colors based on availability using centralized factors var darkenFactor = ResearchColorScheme.GetBackgroundInterpolationFactor(availability); BackgroundColor = Color.InterpolateBetween(primaryColor, Color.Black, darkenFactor); if (secondaryColor.HasValue) SecondaryBackgroundColor = Color.InterpolateBetween(secondaryColor.Value, Color.Black, darkenFactor); // Create brighter versions of the discipline colors for hover by interpolating with white var hoverFactor = ResearchColorScheme.GetHoverMixingFactor(); HoveredColor = Color.InterpolateBetween(primaryColor, Color.White, hoverFactor); if (secondaryColor.HasValue) SecondaryHoveredColor = Color.InterpolateBetween(secondaryColor.Value, Color.White, hoverFactor); // Create even brighter versions for selection (persistent bright highlight) var selectionFactor = ResearchColorScheme.GetSelectionMixingFactor(); SelectedColor = Color.InterpolateBetween(primaryColor, Color.White, selectionFactor); if (secondaryColor.HasValue) SecondarySelectedColor = Color.InterpolateBetween(secondaryColor.Value, Color.White, selectionFactor); // Create appropriate style box based on whether we have dual disciplines if (secondaryDiscipline != null) { // Create dual-color rounded style box with diagonal split var dualColorStyle = new RoundedDualColorStyleBoxFlat { PrimaryColor = BackgroundColor, SecondaryColor = SecondaryBackgroundColor, BorderColor = BorderColor, BorderThickness = new Thickness(2.5f), CornerRadius = 8f }; Panel.PanelOverride = dualColorStyle; } else { // Create regular single-color rounded style box var roundedStyle = new RoundedStyleBoxFlat { BackgroundColor = BackgroundColor, BorderColor = BorderColor, BorderThickness = new Thickness(2.5f), CornerRadius = 8f }; Panel.PanelOverride = roundedStyle; } UpdateColor(); } private void UpdateColor() { if (Panel.PanelOverride is RoundedDualColorStyleBoxFlat dualColorPanel) { // Priority: Selected > Hovered > Normal if (IsSelected) { dualColorPanel.PrimaryColor = SelectedColor; dualColorPanel.SecondaryColor = SecondarySelectedColor; } else if (Button.IsHovered) { dualColorPanel.PrimaryColor = HoveredColor; dualColorPanel.SecondaryColor = SecondaryHoveredColor; } else { dualColorPanel.PrimaryColor = BackgroundColor; dualColorPanel.SecondaryColor = SecondaryBackgroundColor; } dualColorPanel.BorderColor = BorderColor; } else if (Panel.PanelOverride is RoundedStyleBoxFlat singleColorPanel) { // Priority: Selected > Hovered > Normal if (IsSelected) singleColorPanel.BackgroundColor = SelectedColor; else if (Button.IsHovered) singleColorPanel.BackgroundColor = HoveredColor; else singleColorPanel.BackgroundColor = BackgroundColor; singleColorPanel.BorderColor = BorderColor; } } protected override void ExitedTree() { base.ExitedTree(); Button.OnPressed -= Selected; } private void Selected(BaseButton.ButtonEventArgs args) { SelectAction?.Invoke(Prototype, Availability); } } public sealed class DrawButton : Button { public event Action? OnDrawModeChanged; public DrawButton() { } protected override void DrawModeChanged() { OnDrawModeChanged?.Invoke(); } }