feat(archive): add world stats tracker and terminal UI

This commit is contained in:
Alexa Amundson
2025-11-25 15:07:28 -06:00
parent ffc2842bd0
commit e74b698924
3 changed files with 207 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
using UnityEngine;
using UnityEngine.UI;
namespace BlackRoad.Worldbuilder.Archive
{
/// <summary>
/// Simple on-screen panel that displays world stats from WorldStatsTracker.
/// Can be toggled on/off by ArchiveTerminal or key.
/// </summary>
public class ArchivePanelUI : MonoBehaviour
{
[Header("Text Elements")]
[SerializeField] private Text timeText;
[SerializeField] private Text populationText;
[SerializeField] private Text cosmosText;
[Header("Toggle")]
[SerializeField] private KeyCode toggleKey = KeyCode.Tab;
[SerializeField] private bool startVisible = false;
private CanvasGroup _canvasGroup;
private void Awake()
{
_canvasGroup = GetComponent<CanvasGroup>();
SetVisible(startVisible);
}
private void Update()
{
if (Input.GetKeyDown(toggleKey))
{
Toggle();
}
Refresh();
}
public void Refresh()
{
var stats = WorldStatsTracker.Instance;
if (stats == null) return;
if (timeText != null)
timeText.text = stats.GetTimeSummary();
if (populationText != null)
populationText.text = stats.GetPopulationSummary();
if (cosmosText != null)
cosmosText.text = stats.GetCosmosSummary();
}
public void Toggle()
{
SetVisible(!IsVisible());
}
public void SetVisible(bool visible)
{
if (_canvasGroup == null) return;
_canvasGroup.alpha = visible ? 1f : 0f;
_canvasGroup.interactable = visible;
_canvasGroup.blocksRaycasts = visible;
}
public bool IsVisible()
{
return _canvasGroup != null && _canvasGroup.alpha > 0.9f;
}
}
}

View File

@@ -0,0 +1,36 @@
using UnityEngine;
using BlackRoad.Worldbuilder.Interaction;
namespace BlackRoad.Worldbuilder.Archive
{
/// <summary>
/// In-world terminal that toggles the archive UI panel when interacted with.
/// Attach to a console/monolith object with a collider.
/// </summary>
public class ArchiveTerminal : Interactable
{
[SerializeField] private ArchivePanelUI archivePanel;
private void Awake()
{
// Default labels for Interactable UI
#if UNITY_EDITOR
var so = new UnityEditor.SerializedObject(this);
so.FindProperty("displayName").stringValue = "Archive Terminal";
so.FindProperty("verb").stringValue = "Access";
so.ApplyModifiedPropertiesWithoutUndo();
#endif
}
public override void Interact(GameObject interactor)
{
if (archivePanel == null)
archivePanel = Object.FindObjectOfType<ArchivePanelUI>();
if (archivePanel != null)
{
archivePanel.Toggle();
}
}
}
}

View File

@@ -0,0 +1,98 @@
using UnityEngine;
using BlackRoad.Worldbuilder.Environment;
using BlackRoad.Worldbuilder.Life;
using BlackRoad.Worldbuilder.Villagers;
using BlackRoad.Worldbuilder.Space;
namespace BlackRoad.Worldbuilder.Archive
{
/// <summary>
/// Central registry for world statistics: population, critters, time, solar system.
/// Other systems can query this for UI/Archive purposes.
/// </summary>
public class WorldStatsTracker : MonoBehaviour
{
public static WorldStatsTracker Instance { get; private set; }
[Header("References")]
[SerializeField] private DayNightCycle dayNight;
[SerializeField] private SolarSystemManager solarSystem;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
private void Start()
{
if (dayNight == null)
dayNight = FindObjectOfType<DayNightCycle>();
if (solarSystem == null)
solarSystem = FindObjectOfType<SolarSystemManager>();
}
// --- Population stats ---
public int GetCritterCount()
{
return FindObjectsOfType<CritterAgent>().Length;
}
public int GetVillagerCount()
{
return FindObjectsOfType<VillagerAgent>().Length;
}
// --- Time / Day stats ---
public float GetTimeOfDayNormalized()
{
return dayNight != null ? dayNight.timeOfDay : 0.5f;
}
public float GetTimeOfDayHours()
{
return GetTimeOfDayNormalized() * 24f;
}
// --- Solar stats (very simple) ---
public int GetOrbitingBodyCount()
{
if (solarSystem == null || solarSystem.bodies == null)
return 0;
return solarSystem.bodies.Length;
}
// --- High-level summary strings used by UI ---
public string GetTimeSummary()
{
float hours = GetTimeOfDayHours();
int h = Mathf.FloorToInt(hours);
int m = Mathf.FloorToInt((hours - h) * 60f);
return $"Day time: {h:00}:{m:00}";
}
public string GetPopulationSummary()
{
int critters = GetCritterCount();
int villagers = GetVillagerCount();
return $"Critters: {critters} Villagers: {villagers}";
}
public string GetCosmosSummary()
{
int bodies = GetOrbitingBodyCount();
return $"Orbiting bodies tracked: {bodies}";
}
}
}