First commit
This commit is contained in:
180
Assets/Code/GameState/UI/PartyGuiView.cs
Normal file
180
Assets/Code/GameState/UI/PartyGuiView.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using System.Collections.Generic;
|
||||
using Jovian.PopupSystem;
|
||||
using Nox.UI;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Nox.Game.UI {
|
||||
public class PartyGuiView {
|
||||
private const int PoolSize = 4;
|
||||
|
||||
private readonly Transform portraitsContainer;
|
||||
private readonly PartyMemberSlot slotPrefab;
|
||||
private readonly PortraitsHolder portraitsHolder;
|
||||
private readonly IPopupSystem popupSystem;
|
||||
private readonly PartyMemberSlot[] slotPool = new PartyMemberSlot[PoolSize];
|
||||
|
||||
private PartyDefinition trackedParty;
|
||||
private int activeCount;
|
||||
|
||||
public PartyGuiView(Transform portraitsContainer, PartyMemberSlot slotPrefab, PortraitsHolder portraitsHolder, IPopupSystem popupSystem = null) {
|
||||
this.portraitsContainer = portraitsContainer;
|
||||
this.slotPrefab = slotPrefab;
|
||||
this.portraitsHolder = portraitsHolder;
|
||||
this.popupSystem = popupSystem;
|
||||
}
|
||||
|
||||
public void Initialize(PartyDefinition party) {
|
||||
trackedParty = party;
|
||||
activeCount = 0;
|
||||
|
||||
// Pre-create all slots (deactivated)
|
||||
for(int i = 0; i < PoolSize; i++) {
|
||||
if(slotPool[i] == null) {
|
||||
slotPool[i] = Object.Instantiate(slotPrefab, portraitsContainer);
|
||||
}
|
||||
slotPool[i].gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
PopulateSlots();
|
||||
}
|
||||
|
||||
public void Tick() {
|
||||
if(trackedParty == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Rebuild if member count changed
|
||||
if(trackedParty.members.Count != activeCount) {
|
||||
PopulateSlots();
|
||||
}
|
||||
|
||||
// Update dynamic values
|
||||
var memberCount = Mathf.Min(activeCount, trackedParty.members.Count);
|
||||
for(int i = 0; i < memberCount; i++) {
|
||||
UpdateSlotStats(slotPool[i], trackedParty.members[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateSlots() {
|
||||
var memberCount = trackedParty?.members != null
|
||||
? Mathf.Min(trackedParty.members.Count, PoolSize)
|
||||
: 0;
|
||||
|
||||
// Activate slots for current members, deactivate the rest
|
||||
for(var i = 0; i < PoolSize; i++) {
|
||||
var slot = slotPool[i];
|
||||
if(i < memberCount && trackedParty?.members != null) {
|
||||
var member = trackedParty.members[i];
|
||||
if(member == null) {
|
||||
continue;
|
||||
}
|
||||
slot.gameObject.SetActive(true);
|
||||
|
||||
// Portrait
|
||||
if(portraitsHolder != null && portraitsHolder.portraits.Length > 0) {
|
||||
var idx = Mathf.Clamp(member.PortraitIndex, 0, portraitsHolder.portraits.Length - 1);
|
||||
slot.portrait.sprite = portraitsHolder.portraits[idx];
|
||||
}
|
||||
|
||||
UpdateSlotStats(slot, member);
|
||||
}
|
||||
else {
|
||||
slot.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
activeCount = memberCount;
|
||||
|
||||
// Initialize popup triggers
|
||||
popupSystem?.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
|
||||
var slot = trigger.GetComponentInParent<PartyMemberSlot>();
|
||||
if(!slot) {
|
||||
return;
|
||||
}
|
||||
var slotIndex = System.Array.IndexOf(slotPool, slot);
|
||||
if(slotIndex < 0 || slotIndex >= activeCount) {
|
||||
return;
|
||||
}
|
||||
var member = trackedParty.members[slotIndex];
|
||||
view.SetContent(builder => BuildCharacterPopup(builder, member));
|
||||
});
|
||||
}
|
||||
|
||||
private void BuildCharacterPopup(PopupContentBuilder builder, CharacterDefinition member) {
|
||||
// Header
|
||||
builder
|
||||
.AddText(member.Name, PopupElementType.Header)
|
||||
.AddText($"{member.Race} {member.Class}", "#CCCCCC", PopupElementType.Text)
|
||||
.AddText($"Role: {member.Role}", PopupElementType.Text)
|
||||
.AddSeparator(PopupElementType.Separator);
|
||||
|
||||
// Stats
|
||||
if(member.Stats?.stats != null) {
|
||||
var level = member.Stats.GetValue(StatType.Level);
|
||||
var xp = member.Stats.GetValue(StatType.Experience);
|
||||
var health = member.Stats.GetValue(StatType.Health);
|
||||
var mana = member.Stats.GetValue(StatType.Mana);
|
||||
builder
|
||||
.AddNameValue("Level", level, PopupElementType.LabelValueText)
|
||||
.AddNameValue("XP", xp, PopupElementType.LabelValueText)
|
||||
.AddSeparator(PopupElementType.Separator)
|
||||
.AddNameValue("Health", health, PopupElementType.LabelValueText)
|
||||
.AddNameValue("Mana", mana, PopupElementType.LabelValueText)
|
||||
.AddSeparator(PopupElementType.Separator);
|
||||
}
|
||||
|
||||
// Attributes
|
||||
if(member.Attributes?.attributes != null) {
|
||||
foreach(var attr in member.Attributes.attributes) {
|
||||
if(attr.attribute == AttributeType.None) {
|
||||
continue;
|
||||
}
|
||||
builder.AddNameValue(attr.attribute.ToString(), attr.value, PopupElementType.LabelValueText);
|
||||
}
|
||||
}
|
||||
builder.AddSeparator(PopupElementType.Separator);
|
||||
|
||||
// Perks
|
||||
if(member.Perks?.perks is { Count: > 0 }) {
|
||||
builder.AddText("Perks", "#FFD700", PopupElementType.Text);
|
||||
foreach(var perk in member.Perks.perks) {
|
||||
builder.AddText($" {perk.Name}", PopupElementType.Text);
|
||||
}
|
||||
builder.AddSeparator(PopupElementType.Separator);
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
if(member.Modifiers?.modifiers is { Count: > 0 }) {
|
||||
builder.AddText("Modifiers", "#87CEEB", PopupElementType.Text);
|
||||
foreach(var mod in member.Modifiers.modifiers) {
|
||||
var target = mod.Target != null ? mod.Target.ToString() : "";
|
||||
builder.AddText($" {mod.Name} ({mod.Operation} {mod.Value} {target})", PopupElementType.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateSlotStats(PartyMemberSlot slot, CharacterDefinition member) {
|
||||
var health = member.Stats.GetValue(StatType.Health);
|
||||
var mana = member.Stats.GetValue(StatType.Mana);
|
||||
|
||||
if(slot.healthBar != null) {
|
||||
slot.healthBar.fillAmount = Mathf.Clamp01(health / 100f);
|
||||
}
|
||||
|
||||
if(slot.manaBar != null) {
|
||||
slot.manaBar.fillAmount = Mathf.Clamp01(mana / 100f);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
for(int i = 0; i < PoolSize; i++) {
|
||||
if(slotPool[i] != null) {
|
||||
Object.Destroy(slotPool[i].gameObject);
|
||||
slotPool[i] = null;
|
||||
}
|
||||
}
|
||||
activeCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user