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(); _elements.PanelRoot = CreatePanelRoot(); InitializePanelContent(); UIRoot.RootVisualElement.Add(_elements.PanelRoot); _signalBus.Subscribe(OnSelectedBuildingChanged); } public void Dispose() { _signalBus.Unsubscribe(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; } } }