forked from Shardstone/trail-into-darkness
added pooling for the gui portraits
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
using Jovian.Logger;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Jovian.PopupSystem;
|
using Jovian.PopupSystem;
|
||||||
using Nox.UI;
|
using Nox.UI;
|
||||||
@@ -7,14 +6,16 @@ using Object = UnityEngine.Object;
|
|||||||
|
|
||||||
namespace Nox.Game.UI {
|
namespace Nox.Game.UI {
|
||||||
public class PartyGuiView {
|
public class PartyGuiView {
|
||||||
|
private const int PoolSize = 4;
|
||||||
|
|
||||||
private readonly Transform portraitsContainer;
|
private readonly Transform portraitsContainer;
|
||||||
private readonly PartyMemberSlot slotPrefab;
|
private readonly PartyMemberSlot slotPrefab;
|
||||||
private readonly PortraitsHolder portraitsHolder;
|
private readonly PortraitsHolder portraitsHolder;
|
||||||
private readonly IPopupSystem popupSystem;
|
private readonly IPopupSystem popupSystem;
|
||||||
private readonly List<PartyMemberSlot> activeSlots = new();
|
private readonly PartyMemberSlot[] slotPool = new PartyMemberSlot[PoolSize];
|
||||||
|
|
||||||
private PartyDefinition trackedParty;
|
private PartyDefinition trackedParty;
|
||||||
private int trackedMemberCount;
|
private int activeCount;
|
||||||
|
|
||||||
public PartyGuiView(Transform portraitsContainer, PartyMemberSlot slotPrefab, PortraitsHolder portraitsHolder, IPopupSystem popupSystem = null) {
|
public PartyGuiView(Transform portraitsContainer, PartyMemberSlot slotPrefab, PortraitsHolder portraitsHolder, IPopupSystem popupSystem = null) {
|
||||||
this.portraitsContainer = portraitsContainer;
|
this.portraitsContainer = portraitsContainer;
|
||||||
@@ -25,8 +26,17 @@ namespace Nox.Game.UI {
|
|||||||
|
|
||||||
public void Initialize(PartyDefinition party) {
|
public void Initialize(PartyDefinition party) {
|
||||||
trackedParty = party;
|
trackedParty = party;
|
||||||
trackedMemberCount = 0;
|
activeCount = 0;
|
||||||
RebuildSlots();
|
|
||||||
|
// 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() {
|
public void Tick() {
|
||||||
@@ -35,58 +45,59 @@ namespace Nox.Game.UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild if member count changed
|
// Rebuild if member count changed
|
||||||
if(trackedParty.members.Count != trackedMemberCount) {
|
if(trackedParty.members.Count != activeCount) {
|
||||||
RebuildSlots();
|
PopulateSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update dynamic values (health, mana)
|
// Update dynamic values
|
||||||
for(int i = 0; i < activeSlots.Count && i < trackedParty.members.Count; i++) {
|
var memberCount = Mathf.Min(activeCount, trackedParty.members.Count);
|
||||||
var member = trackedParty.members[i];
|
for(int i = 0; i < memberCount; i++) {
|
||||||
var slot = activeSlots[i];
|
UpdateSlotStats(slotPool[i], trackedParty.members[i]);
|
||||||
UpdateSlotStats(slot, member);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RebuildSlots() {
|
private void PopulateSlots() {
|
||||||
// Clear existing
|
var memberCount = trackedParty?.members != null
|
||||||
foreach(var slot in activeSlots) {
|
? Mathf.Min(trackedParty.members.Count, PoolSize)
|
||||||
Object.Destroy(slot.gameObject);
|
: 0;
|
||||||
}
|
|
||||||
activeSlots.Clear();
|
|
||||||
|
|
||||||
if(trackedParty?.members == null) {
|
// Activate slots for current members, deactivate the rest
|
||||||
return;
|
for(int i = 0; i < PoolSize; i++) {
|
||||||
|
var slot = slotPool[i];
|
||||||
|
if(i < memberCount) {
|
||||||
|
var member = trackedParty.members[i];
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackedMemberCount = trackedParty.members.Count;
|
activeCount = memberCount;
|
||||||
|
|
||||||
foreach(var member in trackedParty.members) {
|
// Initialize popup triggers
|
||||||
var slot = Object.Instantiate(slotPrefab, portraitsContainer);
|
if(popupSystem != null) {
|
||||||
slot.gameObject.SetActive(true);
|
popupSystem.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
|
||||||
|
var slot = trigger.GetComponentInParent<PartyMemberSlot>();
|
||||||
// Portrait
|
if(slot == null) {
|
||||||
if(portraitsHolder != null && portraitsHolder.portraits.Length > 0) {
|
return;
|
||||||
var idx = Mathf.Clamp(member.PortraitIndex, 0, portraitsHolder.portraits.Length - 1);
|
}
|
||||||
slot.portrait.sprite = portraitsHolder.portraits[idx];
|
var slotIndex = System.Array.IndexOf(slotPool, slot);
|
||||||
}
|
if(slotIndex < 0 || slotIndex >= activeCount) {
|
||||||
|
return;
|
||||||
UpdateSlotStats(slot, member);
|
}
|
||||||
activeSlots.Add(slot);
|
var member = trackedParty.members[slotIndex];
|
||||||
|
view.SetContent(builder => BuildCharacterPopup(builder, member));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize all popup triggers under the container
|
|
||||||
popupSystem?.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
|
|
||||||
var slot = trigger.GetComponentInParent<PartyMemberSlot>();
|
|
||||||
if(slot == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var slotIndex = activeSlots.IndexOf(slot);
|
|
||||||
if(slotIndex < 0 || slotIndex >= trackedParty.members.Count) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var member = trackedParty.members[slotIndex];
|
|
||||||
view.SetContent(builder => BuildCharacterPopup(builder, member));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildCharacterPopup(PopupContentBuilder builder, CharacterDefinition member) {
|
private void BuildCharacterPopup(PopupContentBuilder builder, CharacterDefinition member) {
|
||||||
@@ -99,14 +110,18 @@ namespace Nox.Game.UI {
|
|||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
if(member.Stats?.stats != null) {
|
if(member.Stats?.stats != null) {
|
||||||
foreach(var stat in member.Stats.stats) {
|
var level = member.Stats.GetValue(StatType.Level);
|
||||||
if(stat.stat == StatType.None) {
|
var xp = member.Stats.GetValue(StatType.Experience);
|
||||||
continue;
|
var health = member.Stats.GetValue(StatType.Health);
|
||||||
}
|
var mana = member.Stats.GetValue(StatType.Mana);
|
||||||
builder.AddStat(stat.stat.ToString(), stat.value);
|
builder
|
||||||
}
|
.AddStat("Level", level)
|
||||||
|
.AddStat("XP", xp)
|
||||||
|
.AddSeparator()
|
||||||
|
.AddStat("Health", health)
|
||||||
|
.AddStat("Mana", mana)
|
||||||
|
.AddSeparator();
|
||||||
}
|
}
|
||||||
builder.AddSeparator();
|
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
if(member.Attributes?.attributes != null) {
|
if(member.Attributes?.attributes != null) {
|
||||||
@@ -152,12 +167,13 @@ namespace Nox.Game.UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
foreach(var slot in activeSlots) {
|
for(int i = 0; i < PoolSize; i++) {
|
||||||
if(slot != null) {
|
if(slotPool[i] != null) {
|
||||||
Object.Destroy(slot.gameObject);
|
Object.Destroy(slotPool[i].gameObject);
|
||||||
|
slotPool[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
activeSlots.Clear();
|
activeCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user