This commit is contained in:
2026-07-09 21:33:33 +02:00
commit 84a2a365f3
2364 changed files with 950134 additions and 0 deletions
@@ -0,0 +1,65 @@
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Player;
namespace VOID.UserInterface.Game.Party
{
public class PartyUI : MonoBehaviour
{
public static PartyUI current { get; private set; }
// Visual Elements
private VisualElement _rootElement;
private PartyUnitUI _partyMainUnit;
private PartyUnitUI _partySubUnit;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
_rootElement = templateElement.Q("root-party");
// Find all important elements + initialize MainUnit element
_partyMainUnit = gameObject.AddComponent<PartyUnitUI>();
_partyMainUnit.Init(templateElement.Q("main-unit"));
// Find all important elements + initialize SubUnit element
_partySubUnit = gameObject.AddComponent<PartyUnitUI>();
_partySubUnit.Init(templateElement.Q("sub-unit"));
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
}
private void Start()
{
// This will set portrait active (highlight border) if it belong to currently active unit
PlayerController.current.OnActiveUnitChange += OnActiveUnitChange;
// Updating portraits of party unit when they change
PlayerController.current.OnMainUnitChange += OnMainUnitChange;
PlayerController.current.OnSubUnitChange += OnSubUnitChange;
}
private void OnActiveUnitChange(UnitObject unitObject)
{
_partyMainUnit.SetActive(_partyMainUnit.unit == unitObject);
_partySubUnit.SetActive(_partySubUnit.unit == unitObject);
}
private void OnMainUnitChange(UnitObject unitObject)
{
_partyMainUnit.SetUnit(unitObject);
}
private void OnSubUnitChange(UnitObject unitObject)
{
_partySubUnit.SetUnit(unitObject);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5a3ce2a335409fe4f81fbfcb36c77c25
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,10 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance"
engine="UnityEngine.UIElements" editor="UnityEditor.UIElements"
noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:Template name="UnitPortraitUI" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Party/PartyUnitUI.uxml?fileID=9197481963319205126&amp;guid=937bc4cc745714749bf0809a2816bd10&amp;type=3#PartyUnitUI" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Party/PartyUIStyle.uss?fileID=7433441132597879392&amp;guid=27ecc27feecea444fabee3e6849d925f&amp;type=3#PartyUIStyle" />
<ui:VisualElement name="root-party">
<ui:Instance template="UnitPortraitUI" name="main-unit" />
<ui:Instance template="UnitPortraitUI" name="sub-unit" />
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e1a21811e8e82eb409db19940ccd18ba
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,16 @@
#root-party {
flex-direction: row;
align-self: flex-start;
}
#main-unit {
transform-origin: left top;
}
#sub-unit {
transform-origin: left top;
scale: 0.75 0.75;
left: 145px;
position: absolute;
top: 52px;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27ecc27feecea444fabee3e6849d925f
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,114 @@
using System.Collections.Generic;
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
using VOID.UserInterface.Game.Util;
using VOID.ScriptableObjects;
namespace VOID.UserInterface.Game.Party
{
/// <summary>
/// Manages all visual elements for one <see cref="UnitObject"/> in <see cref="PartyUI"/>, including: portrait and statuses
/// </summary>
public class PartyUnitUI : MonoBehaviour
{
[ShowInInspector, ReadOnly] public UnitObject unit { get; private set; }
// Visual Elements
private VisualElement _templateElement;
private VisualElement _statusRow;
private UnitPortraitUI _unitPortraitUI;
private Dictionary<BasicStatus, StatusUI> _statuses = new();
/// <summary>
/// Initializes whole <see cref="PartyUnitUI"/>, should be executed from <see cref="PartyUI"/>.
/// </summary>
/// <param name="partyUnitTemplate">visual element which already exists and will be used.</param>
public void Init(VisualElement partyUnitTemplate)
{
// Find all important elements
_templateElement = partyUnitTemplate;
_statusRow = _templateElement.Q("status-row");
_unitPortraitUI = new UnitPortraitUI();
_unitPortraitUI.Init(_templateElement.Q("unit-portrait"));
_templateElement.style.display = DisplayStyle.None;
// Clear all placeholder statuses
_statusRow.Clear();
}
/// <summary>
/// Given <see cref="UnitObject"/> will be used in this visual element.
/// Which means its portrait, statuses and health will be displayed.
/// </summary>
public void SetUnit(UnitObject unit)
{
// Remove everything about previous Unit
UnsetUnit();
// New Unit assigned - start listeners and wait
this.unit = unit;
this.unit.basicEvents.onStatusStart.AddListener(OnUnitStatusStart);
this.unit.basicEvents.onStatusEnd.AddListener(OnUnitStatusEnd);
// Make UI visible and set Unit's portrait
_templateElement.style.display = DisplayStyle.Flex;
// For all statuses that already exists we need to initialize them manually
this.unit.statusManager.GetStatuses().ForEach(status => OnUnitStatusStart(new StatusEvent { obj = unit, status = status }));
_unitPortraitUI.SetUnit(unit);
}
/// <summary>
/// Clears and hides this element.
/// </summary>
public void UnsetUnit()
{
// There is no unit currently
if (!unit) return;
// Remove all listeners, then remove assigned Unit
unit.basicEvents.onStatusStart.RemoveListener(OnUnitStatusStart);
unit.basicEvents.onStatusEnd.RemoveListener(OnUnitStatusEnd);
unit = null;
// Make UI invisible and unset portrait
_templateElement.style.display = DisplayStyle.None;
// Remove mapping
_statuses = null;
// Clear all statuses
_statusRow.Clear();
_unitPortraitUI.UnsetUnit();
}
/// <summary>
/// Adds class "active" which usually will be used, by portret of player's currently active <see cref="UnitObject"/>
/// </summary>
public void SetActive(bool active = true)
{
_templateElement.EnableInClassList("active", active);
}
private void OnUnitStatusStart(StatusEvent statusEvent)
{
if (statusEvent.status.hidden) return;
var statusUI = new StatusUI();
statusUI.InitNew(_statusRow, statusEvent.status);
_statuses.Add(statusEvent.status, statusUI);
}
private void OnUnitStatusEnd(StatusEvent statusEvent)
{
if (statusEvent.status.hidden) return;
_statuses.GetValueOrDefault(statusEvent.status)?.Destroy();
_statuses.Remove(statusEvent.status);
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b935b7ac7b0341f88c6551daeb4efddf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- statusElementTemplate: {fileID: 9197481963319205126, guid: 9c95cff4b708f194db8bb1259ba03d85,
type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,19 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance"
engine="UnityEngine.UIElements" editor="UnityEditor.UIElements"
noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:Template name="UnitPortrait" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/UnitPortrait.uxml?fileID=9197481963319205126&amp;guid=2b588e131b790bd408086718bd2f82cd&amp;type=3#UnitPortrait" />
<ui:Template name="Status" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Status.uxml?fileID=9197481963319205126&amp;guid=9c95cff4b708f194db8bb1259ba03d85&amp;type=3#Status" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Party/PartyUnitUIStyle.uss?fileID=7433441132597879392&amp;guid=a6ef3ae902cf35a4082c12dbc37c0999&amp;type=3#PartyUnitUIStyle" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/StatusOuter.uss?fileID=7433441132597879392&amp;guid=6eb1ae18d8fd2c541be09b7ecad6e722&amp;type=3#StatusOuter" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/UnitPortraitOuter.uss?fileID=7433441132597879392&amp;guid=a9fd7af89854ed243b3383ce693bc254&amp;type=3#UnitPortraitOuter" />
<ui:VisualElement name="root-party-unit">
<ui:Instance template="UnitPortrait" name="unit-portrait" class="unit-portrait unit-portrait-big" />
<ui:VisualElement name="status-row">
<ui:Instance template="Status" class="status status-medium" />
<ui:Instance template="Status" class="status status-medium" />
<ui:Instance template="Status" class="status status-medium" />
<ui:Instance template="Status" class="status status-medium" />
<ui:Instance template="Status" class="status status-medium" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 937bc4cc745714749bf0809a2816bd10
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,22 @@
#root-party-unit {
flex-direction: row;
flex-grow: 0;
align-items: flex-start;
flex-shrink: 0;
align-self: flex-start;
}
#status-row {
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
margin-bottom: 2px;
flex-direction: row;
}
#status-row > .status {
margin-left: 1px;
margin-right: 1px;
margin-top: 1px;
margin-bottom: 1px;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6ef3ae902cf35a4082c12dbc37c0999
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0