feat(identity): add entity identity registry and archive listing
This commit is contained in:
83
Assets/Scripts/Archive/IdentityListUI.cs
Normal file
83
Assets/Scripts/Archive/IdentityListUI.cs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
using BlackRoad.Worldbuilder.Identity;
|
||||||
|
|
||||||
|
namespace BlackRoad.Worldbuilder.Archive
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Displays a simple list of all registered identities in the world.
|
||||||
|
/// Intended to sit under the Archive panel.
|
||||||
|
/// </summary>
|
||||||
|
public class IdentityListUI : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Text listText;
|
||||||
|
[SerializeField] private bool groupByType = true;
|
||||||
|
|
||||||
|
[Header("Refresh")]
|
||||||
|
[SerializeField] private float refreshInterval = 2f;
|
||||||
|
|
||||||
|
private float _timer;
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
_timer += Time.deltaTime;
|
||||||
|
if (_timer >= refreshInterval)
|
||||||
|
{
|
||||||
|
_timer = 0f;
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Refresh()
|
||||||
|
{
|
||||||
|
if (listText == null) return;
|
||||||
|
var registry = WorldIdentityRegistry.Instance;
|
||||||
|
if (registry == null)
|
||||||
|
{
|
||||||
|
listText.text = "No registry found.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids = registry.Identities;
|
||||||
|
if (ids == null || ids.Count == 0)
|
||||||
|
{
|
||||||
|
listText.text = "No entities registered.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (groupByType)
|
||||||
|
{
|
||||||
|
foreach (WorldIdentity.EntityType type in System.Enum.GetValues(typeof(WorldIdentity.EntityType)))
|
||||||
|
{
|
||||||
|
bool any = false;
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
if (id == null || id.Type != type) continue;
|
||||||
|
if (!any)
|
||||||
|
{
|
||||||
|
any = true;
|
||||||
|
sb.AppendLine($"== {type} ==");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine($"- {id.DisplayName} ({id.UniqueId.Substring(0, 6)}...)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (any) sb.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var id in ids)
|
||||||
|
{
|
||||||
|
if (id == null) continue;
|
||||||
|
sb.AppendLine($"{id.Type}: {id.DisplayName} ({id.UniqueId.Substring(0, 6)}...)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listText.text = sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Assets/Scripts/Identity/WorldIdentity.cs
Normal file
46
Assets/Scripts/Identity/WorldIdentity.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BlackRoad.Worldbuilder.Identity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Assigns a stable identity to an entity in the world.
|
||||||
|
/// Used by the registry and archive to track critters, villagers, etc.
|
||||||
|
/// </summary>
|
||||||
|
public class WorldIdentity : MonoBehaviour
|
||||||
|
{
|
||||||
|
public enum EntityType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Critter,
|
||||||
|
Villager,
|
||||||
|
Structure,
|
||||||
|
Landmark,
|
||||||
|
Player
|
||||||
|
}
|
||||||
|
|
||||||
|
[Header("Identity")]
|
||||||
|
[SerializeField] private string uniqueId;
|
||||||
|
[SerializeField] private string displayName = "Entity";
|
||||||
|
[SerializeField] private EntityType type = EntityType.Unknown;
|
||||||
|
|
||||||
|
public string UniqueId => uniqueId;
|
||||||
|
public string DisplayName => displayName;
|
||||||
|
public EntityType Type => type;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
// If no ID assigned, generate a pseudo GUID once in editor
|
||||||
|
if (string.IsNullOrEmpty(uniqueId))
|
||||||
|
{
|
||||||
|
uniqueId = System.Guid.NewGuid().ToString("N");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(displayName))
|
||||||
|
{
|
||||||
|
displayName = gameObject.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
28
Assets/Scripts/Identity/WorldIdentityAutoRegister.cs
Normal file
28
Assets/Scripts/Identity/WorldIdentityAutoRegister.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BlackRoad.Worldbuilder.Identity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper that automatically registers a WorldIdentity with the registry.
|
||||||
|
/// </summary>
|
||||||
|
[RequireComponent(typeof(WorldIdentity))]
|
||||||
|
public class WorldIdentityAutoRegister : MonoBehaviour
|
||||||
|
{
|
||||||
|
private WorldIdentity _identity;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
_identity = GetComponent<WorldIdentity>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
WorldIdentityRegistry.Instance?.Register(_identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
WorldIdentityRegistry.Instance?.Unregister(_identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
Assets/Scripts/Identity/WorldIdentityRegistry.cs
Normal file
55
Assets/Scripts/Identity/WorldIdentityRegistry.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BlackRoad.Worldbuilder.Identity
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Keeps track of all WorldIdentity components currently active in the scene.
|
||||||
|
/// Provides lookup and lists for Archive/UI.
|
||||||
|
/// </summary>
|
||||||
|
public class WorldIdentityRegistry : MonoBehaviour
|
||||||
|
{
|
||||||
|
public static WorldIdentityRegistry Instance { get; private set; }
|
||||||
|
|
||||||
|
private readonly List<WorldIdentity> _identities = new List<WorldIdentity>();
|
||||||
|
|
||||||
|
public IReadOnlyList<WorldIdentity> Identities => _identities;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (Instance != null && Instance != this)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
DontDestroyOnLoad(gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register(WorldIdentity identity)
|
||||||
|
{
|
||||||
|
if (identity != null && !_identities.Contains(identity))
|
||||||
|
{
|
||||||
|
_identities.Add(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unregister(WorldIdentity identity)
|
||||||
|
{
|
||||||
|
if (identity != null)
|
||||||
|
{
|
||||||
|
_identities.Remove(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<WorldIdentity> GetByType(WorldIdentity.EntityType type)
|
||||||
|
{
|
||||||
|
foreach (var id in _identities)
|
||||||
|
{
|
||||||
|
if (id != null && id.Type == type)
|
||||||
|
yield return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user