Files
riversong-code-showcase/Source/Riversong/Game/UI/Panels/DebugPanel/DebugPanelUIControllerSystem.cs
2026-05-21 16:04:49 +02:00

277 lines
10 KiB
C#

using System;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.TextCore.Text;
using UnityEngine.UIElements;
namespace DanieleMarotta.RiversongCodeShowcase
{
[GameSystemGroup(typeof(UISystemGroup))]
[InitializeAfter(typeof(UIInitializationSystem))]
public class DebugPanelUIControllerSystem : UIControllerSystem, IUpdatable, IDisposable
{
[InjectService]
private GameConfig _config;
[InjectService]
private ISignalBus _signalBus;
[InjectService]
private IPointerService _pointerService;
[InjectService]
private ITileSpace _tileSpace;
[InjectService]
private World _world;
private UIElementReferences _elements = new();
private FontAsset _font;
private Building _selectedBuilding;
private bool _isVisible;
public DebugPanelUIControllerSystem(IServiceLocator serviceLocator) : base(serviceLocator)
{
}
public override async UniTask InitializeAsync()
{
await base.InitializeAsync();
_font = await _config.UI.DebugFont.LoadAssetAsync<FontAsset>();
_elements.PanelRoot = CreatePanelRoot();
InitializePanelContent();
UIRoot.RootVisualElement.Add(_elements.PanelRoot);
_signalBus.Subscribe<SelectedBuildingChangedSignal>(OnSelectedBuildingChanged);
}
public void Dispose()
{
_signalBus.Unsubscribe<SelectedBuildingChangedSignal>(OnSelectedBuildingChanged);
}
private void InitializePanelContent()
{
_elements.PanelRoot.Add(CreateHeader("DEBUG PANEL"));
InitializePointerSection();
InitializePopulationSection();
InitializeSelectedBuildingSection();
}
private void InitializePointerSection()
{
_elements.TileCoordsLabel = CreateLabel("Tile: ");
_elements.PanelRoot.Add(_elements.TileCoordsLabel);
}
private void InitializePopulationSection()
{
_elements.PanelRoot.Add(CreateHeader("POPULATION"));
_elements.PopulationCapacityLabel = CreateLabel("Capacity: ");
_elements.PanelRoot.Add(_elements.PopulationCapacityLabel);
_elements.PopulationGrowthAccumulatorLabel = CreateLabel("Growth Accumulator: ");
_elements.PanelRoot.Add(_elements.PopulationGrowthAccumulatorLabel);
}
private void InitializeSelectedBuildingSection()
{
_elements.PanelRoot.Add(CreateHeader("SELECTED BUILDING"));
_elements.SelectedBuildingFallbackLabel = CreateLabel("No building selected");
_elements.PanelRoot.Add(_elements.SelectedBuildingFallbackLabel);
_elements.SelectedBuildingNameLabel = CreateLabel("Building: ");
_elements.PanelRoot.Add(_elements.SelectedBuildingNameLabel);
InitializeSelectedHouseContent();
}
private void InitializeSelectedHouseContent()
{
_elements.SelectedHouseContent = new VisualElement { style = { display = DisplayStyle.None } };
_elements.SelectedBuildingTierLabel = CreateLabel("Tier: ");
_elements.SelectedHouseContent.Add(_elements.SelectedBuildingTierLabel);
_elements.SelectedBuildingHappinessLabel = CreateLabel("Happiness: ");
_elements.SelectedHouseContent.Add(_elements.SelectedBuildingHappinessLabel);
_elements.SelectedBuildingMaxHappinessScoreLabel = CreateLabel("Max Happiness Score: ");
_elements.SelectedHouseContent.Add(_elements.SelectedBuildingMaxHappinessScoreLabel);
_elements.SelectedBuildingOverallWeightLabel = CreateLabel("Overall Weight: ");
_elements.SelectedHouseContent.Add(_elements.SelectedBuildingOverallWeightLabel);
_elements.SelectedBuildingAllNeedsMetLabel = CreateLabel("All Needs Met: ");
_elements.SelectedHouseContent.Add(_elements.SelectedBuildingAllNeedsMetLabel);
_elements.SelectedBuildingNeedsMetForWeeksLabel = CreateLabel("Needs Met For Weeks: ");
_elements.SelectedHouseContent.Add(_elements.SelectedBuildingNeedsMetForWeeksLabel);
_elements.PanelRoot.Add(_elements.SelectedHouseContent);
}
public void Update()
{
if (Keyboard.current.f9Key.wasPressedThisFrame)
{
_isVisible = !_isVisible;
_elements.PanelRoot.style.display = _isVisible ? DisplayStyle.Flex : DisplayStyle.None;
}
if (!_isVisible) return;
UpdatePointerSection();
UpdatePopulationSection();
UpdateSelectedBuildingSection();
}
private void UpdatePointerSection()
{
if (_pointerService.TryGetPositionOnTerrain(out var position))
{
var tile = _tileSpace.WorldToTile(position);
_elements.TileCoordsLabel.text = $"Tile: {tile.x}, {tile.y}";
}
else
{
_elements.TileCoordsLabel.text = "Tile: -";
}
}
private void UpdatePopulationSection()
{
var populationState = _world.PopulationState;
_elements.PopulationCapacityLabel.text = $"Capacity: {populationState.PopulationCapacity}";
_elements.PopulationGrowthAccumulatorLabel.text = $"Growth Accumulator: {populationState.GrowthAccumulator:0.000}";
}
private void UpdateSelectedBuildingSection()
{
var anyBuildingSelected = _selectedBuilding != null;
var houseSelected = anyBuildingSelected && _selectedBuilding.Definition.IsHouse;
_elements.SelectedBuildingFallbackLabel.style.display = anyBuildingSelected ? DisplayStyle.None : DisplayStyle.Flex;
_elements.SelectedBuildingNameLabel.style.display = anyBuildingSelected ? DisplayStyle.Flex : DisplayStyle.None;
_elements.SelectedHouseContent.style.display = houseSelected ? DisplayStyle.Flex : DisplayStyle.None;
if (!anyBuildingSelected) return;
_elements.SelectedBuildingNameLabel.text = $"Building: {_selectedBuilding.Definition.BuildingName} ({_selectedBuilding.Id})";
if (houseSelected) UpdateSelectedHouseInfo();
}
private void UpdateSelectedHouseInfo()
{
ref var needsState = ref _selectedBuilding.GetNeedsStateRW();
_elements.SelectedBuildingTierLabel.text = $"Tier: {_selectedBuilding.TierIndex}";
_elements.SelectedBuildingHappinessLabel.text = $"Happiness: {needsState.Happiness:0.000}";
_elements.SelectedBuildingMaxHappinessScoreLabel.text = $"Max Happiness Score: {Mathf.FloorToInt(needsState.MaxHappinessScore)}";
_elements.SelectedBuildingOverallWeightLabel.text = $"Overall Weight: {needsState.OverallHappinessWeight:0.000}";
_elements.SelectedBuildingAllNeedsMetLabel.text = $"All Needs Met: {needsState.AllNeedsMet}";
_elements.SelectedBuildingNeedsMetForWeeksLabel.text = $"Needs Met For Weeks: {needsState.NeedsMetForWeeks}";
}
private void OnSelectedBuildingChanged(SelectedBuildingChangedSignal signal)
{
_selectedBuilding = signal.NewSelection;
UpdateSelectedBuildingSection();
}
private VisualElement CreatePanelRoot()
{
const int panelWidth = 350;
var panelRoot = new VisualElement
{
name = "debug-panel",
pickingMode = PickingMode.Position,
style =
{
position = Position.Absolute,
top = 16,
left = Screen.width - panelWidth - 16,
width = panelWidth,
paddingTop = 12,
paddingRight = 12,
paddingBottom = 12,
paddingLeft = 12,
backgroundColor = new StyleColor(new Color(0, 0, 0, 0.7f)),
borderTopLeftRadius = 8,
borderTopRightRadius = 8,
borderBottomLeftRadius = 8,
borderBottomRightRadius = 8,
display = DisplayStyle.None
}
};
panelRoot.AddToClassList("drag-target");
UIRoot.MakeDraggable(panelRoot);
return panelRoot;
}
private Label CreateLabel(string text, FontAsset font = null, int fontSize = 14, FontStyle fontStyle = FontStyle.Normal, int marginBottom = 0)
{
var label = new Label(text);
label.pickingMode = PickingMode.Ignore;
label.style.color = Color.white;
label.style.unityFontDefinition = FontDefinition.FromSDFFont(font ?? _font);
label.style.unityFontStyleAndWeight = fontStyle;
label.style.fontSize = fontSize;
label.style.marginBottom = marginBottom;
return label;
}
private Label CreateHeader(string text)
{
var header = CreateLabel(text, fontSize: 16, fontStyle: FontStyle.Bold, marginBottom: 8);
header.pickingMode = PickingMode.Position;
header.AddToClassList("drag-handle");
return header;
}
private class UIElementReferences
{
public VisualElement PanelRoot;
public Label TileCoordsLabel;
public Label PopulationCapacityLabel;
public Label PopulationGrowthAccumulatorLabel;
public Label SelectedBuildingFallbackLabel;
public VisualElement SelectedHouseContent;
public Label SelectedBuildingNameLabel;
public Label SelectedBuildingTierLabel;
public Label SelectedBuildingHappinessLabel;
public Label SelectedBuildingMaxHappinessScoreLabel;
public Label SelectedBuildingOverallWeightLabel;
public Label SelectedBuildingAllNeedsMetLabel;
public Label SelectedBuildingNeedsMetForWeeksLabel;
}
}
}