This commit is contained in:
2026-07-09 21:33:33 +02:00
commit 84a2a365f3
2364 changed files with 950134 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 327bcefea3eb72f40aeed8b754514774
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 263bb640a3473f747946a6c0890d3372
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,136 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
using VOID.Generic.Player.Input;
using VOID.UserInterface.Game.Interfaces;
using VOID.UserInterface.Game.Util;
using VOID.ScriptableObjects.Abilities;
namespace VOID.UserInterface.Game
{
public class AbilityBookUI : MonoBehaviour, IHasWindow
{
public static AbilityBookUI current { get; private set; }
// WindowUI
public WindowUI windowUI { get; private set; }
// Active Unit and his Backpack
private UnitObject _unit;
private UnitObjectAbilityBook _abilityBook;
// Visual Elements
private VisualElement _rootElement;
private VisualElement _abilityListElement;
private readonly List<SlotUI> _abilitySlots = new();
// References
private ShortcutsInputManager _shortcutsInputManager;
private PlayerController _playerController;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Find all important elements
_rootElement = templateElement.Q("root-ability-book");
_abilityListElement = templateElement.Q("ability-slots");
_abilityListElement.Clear();
windowUI = gameObject.GetComponent<WindowUI>();
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
}
private void Start()
{
_shortcutsInputManager = ShortcutsInputManager.current;
_playerController = PlayerController.current;
// Toggle show/hide when pressing shortcut for ability book
_shortcutsInputManager.abilityBook.performed += _ => windowUI.Toggle();
windowUI.OnOpen += OnOpen;
windowUI.OnClose += OnClose;
windowUI.SetTitle("Ability Book");
// Hidden by default
windowUI.Close();
}
public void Toggle() => windowUI.Toggle();
public void Open() => windowUI.Open();
public void Close() => windowUI.Close();
private void OnOpen()
{
// References to active unit
_unit = PlayerController.current.activeUnit;
_abilityBook = _unit.unitAbilityBook;
// Refresh UI when we change active unit
_playerController.OnActiveUnitChange += OnActiveUnitChange;
// Initialize all VisualElements
_abilityBook.abilities.ForEach(AddSlot);
// Listen to all changes in backpack and update UI
_unit.unitEvents.onAbilityAdded.AddListener(OnAbilityAdded);
_unit.unitEvents.onAbilityRemoved.AddListener(OnAbilityRemoved);
}
private void OnClose()
{
// Stop listening
_playerController.OnActiveUnitChange -= OnActiveUnitChange;
// Backpack closed, no need to listen for backpack changes
if (_unit)
{
_unit.unitEvents.onAbilityAdded.RemoveListener(OnAbilityAdded);
_unit.unitEvents.onAbilityRemoved.RemoveListener(OnAbilityRemoved);
}
// Remove all VisualElement slots
_abilitySlots.ForEach(slot => slot.Destroy());
// Clear variables
_abilitySlots.Clear();
_unit = null;
_abilityBook = null;
}
private void OnActiveUnitChange(UnitObject unitObject)
{
windowUI.Close();
windowUI.Open();
}
private void OnAbilityAdded(AbilityBookAbilityAddedEvent abilityAddedEvent) => AddSlot(abilityAddedEvent.abilityAdded);
private void AddSlot(BasicAbility ability)
{
var newSlot = new SlotUI();
newSlot.InitNew(_abilityListElement, SlotType.AbilityBookSlot, -1);
newSlot.Set(ability);
_abilitySlots.Add(newSlot);
}
private void OnAbilityRemoved(AbilityBookAbilityRemovedEvent abilityRemovedEvent) => RemoveSlot(abilityRemovedEvent.abilityRemoved);
private void RemoveSlot(BasicAbility ability)
{
var oldSlot = _abilitySlots.FirstOrDefault(slot => slot.ability == ability);
oldSlot?.Destroy();
_abilitySlots.Remove(oldSlot);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 639e99804ac245bf9b89cbde747fad4a
timeCreated: 1692803941
@@ -0,0 +1,38 @@
<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="Background" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Window.uxml?fileID=9197481963319205126&amp;guid=04235ec1d1b764e448e2524000a1b87a&amp;type=3#Window" />
<ui:Template name="Slot" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Slot.uxml?fileID=9197481963319205126&amp;guid=5a74e2b56bbc27c4ab7a5d0c1de93f00&amp;type=3#Slot" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/AbilityBookUIStyle.uss?fileID=7433441132597879392&amp;guid=ee302f14a5f44694e870e7a0bb8caaa1&amp;type=3#AbilityBookUIStyle" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/SlotOuter.uss?fileID=7433441132597879392&amp;guid=760aa0b2431a11e46a81be0018d225b1&amp;type=3#SlotOuter" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/WindowOuter.uss?fileID=7433441132597879392&amp;guid=80611877e61dcf346bf43cfc4ebd3394&amp;type=3#WindowOuter" />
<ui:VisualElement name="root-ability-book" picking-mode="Ignore">
<ui:Instance template="Background" name="window" picking-mode="Ignore">
<AttributeOverrides element-name="Title" text="ABILITY BOOK" />
</ui:Instance>
<ui:VisualElement name="wrapper" picking-mode="Ignore">
<ui:VisualElement name="ability-slots" picking-mode="Ignore">
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
</ui:VisualElement>
<ui:VisualElement name="filters" picking-mode="Ignore" class="filters">
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" class="filter" />
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" class="filter" />
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" class="filter" />
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" class="filter" />
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" class="filter" />
<ui:Button parse-escape-sequences="true" display-tooltip-when-elided="true" class="filter" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4f4024165b7734045a81bfa200f3e238
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,52 @@
#root-ability-book {
position: absolute;
width: 475px;
height: 550px;
left: 25px;
top: 25px;
}
#wrapper {
flex-grow: 1;
padding-top: 0;
padding-left: 0;
padding-right: 0;
padding-bottom: 0;
flex-direction: row;
margin-left: 15px;
margin-right: 15px;
margin-top: 50px;
margin-bottom: 15px;
}
#wrapper > #filters {
flex-basis: 50px;
}
#wrapper > #filters > .filter {
width: 40px;
height: 40px;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
padding-bottom: 10px;
margin-left: 5px;
margin-right: 5px;
margin-top: 5px;
margin-bottom: 5px;
}
#wrapper > #ability-slots {
flex-grow: 1;
flex-wrap: wrap;
flex-direction: row;
}
#wrapper > #ability-slots > .slot {
width: 60px;
height: 60px;
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
margin-bottom: 2px;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ee302f14a5f44694e870e7a0bb8caaa1
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,60 @@
using UnityEngine;
using UnityEngine.UIElements;
namespace VOID.UserInterface.Game
{
public class ActionBarMiniMenuUI : MonoBehaviour
{
public static ActionBarMiniMenuUI current {get; private set;}
// Visual Elements - Mini menu
private Button _menuButton;
private Button _backpackButton;
private Button _equipmentButton;
private Button _abilityBookButton;
private Button _mapButton;
private Button _logBookButton;
// References
private BackpackUI _backpackUI;
private EquipmentUI _equipmentUI;
private AbilityBookUI _abilityBookUI;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Find all important elements
_menuButton = templateElement.Q<Button>("menu");
_backpackButton = templateElement.Q<Button>("backpack");
_equipmentButton = templateElement.Q<Button>("equipment");
_abilityBookButton = templateElement.Q<Button>("ability-book");
_mapButton = templateElement.Q<Button>("map");
_logBookButton = templateElement.Q<Button>("log-book");
_menuButton.dataSource = this;
_menuButton.pickingMode = PickingMode.Position;
}
private void Start()
{
_backpackUI = BackpackUI.current;
_equipmentUI = EquipmentUI.current;
_abilityBookUI = AbilityBookUI.current;
// Bind show/hide toggle buttons in mini menu for all UI
_backpackButton.clicked += _backpackUI.Toggle;
_equipmentButton.clicked += _equipmentUI.Toggle;
_abilityBookButton.clicked += _abilityBookUI.Toggle;
_menuButton.clicked += PauseMenuUI.current.Toggle;
// _mapButton.clicked += ???.current.Toggle;
// _logBookButton.clicked += ???.current.Toggle;
_menuButton.clicked += () => Debug.LogWarning("Shortcut for <b>Menu</b> not implemented");
_mapButton.clicked += () => Debug.LogWarning("Shortcut for <b>Map</b> not implemented");
_logBookButton.clicked += () => Debug.LogWarning("Shortcut for <b>Log Book</b> not implemented");
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 34b9ef9a6f4d431282328139bfb791f0
timeCreated: 1698256730
@@ -0,0 +1,147 @@
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
using VOID.Generic.Player.Input;
using VOID.UserInterface.Game.Util;
namespace VOID.UserInterface.Game
{
public class ActionBarSlotsUI : MonoBehaviour
{
public static ActionBarSlotsUI current {get; private set;}
// ActionBar for this unit
private UnitObject _unit;
private UnitObjectActionBar _actionBar;
// Visual Elements - Slots
private VisualElement _slotListElement;
private VisualElement[] _slotElements;
private Button _slotsLockerButton;
private Button _slotsChangerNextButton;
private Button _slotsChangerPreviousButton;
private Label _slotsChangerNumberLabel;
public SlotUI[] slotsUI { get; private set; }
private int _slotsPage = 1;
private int _slotsPageCount = 4;
private int _slotsPerPage;
// References
private ShortcutsInputManager _shortcutsInputManager;
private PlayerController _playerController;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Find all important elements
_slotListElement = templateElement.Q("slots");
_slotsChangerNextButton = templateElement.Q("slots-changer").Q<Button>("next");
_slotsChangerPreviousButton = templateElement.Q("slots-changer").Q<Button>("previous");
_slotsChangerNumberLabel = templateElement.Q("slots-changer").Q<Label>("number");
_slotsLockerButton = templateElement.Q<Button>("slots-locker");
// Get all SlotUI used by ActionBar
_slotElements = _slotListElement.Query(className: "slot").ToList().ToArray();
_slotsPerPage = _slotElements.Length;
slotsUI = new SlotUI[_slotsPerPage];
for (var i = 0; i < _slotsPerPage; i++)
{
var slotUI = new SlotUI();
slotUI.Init(_slotElements[i], SlotType.ActionBarSlot, i);
slotsUI[i] = slotUI;
}
_slotListElement.dataSource = this;
_slotListElement.pickingMode = PickingMode.Position;
}
private void Start()
{
_shortcutsInputManager = ShortcutsInputManager.current;
_playerController = PlayerController.current;
// Bind events to action bar page changers
_slotsChangerNextButton.clicked += OnSlotPageNextButton;
_slotsChangerPreviousButton.clicked += OnSlotPagePreviousButton;
_shortcutsInputManager.actionBarNext.performed += _ => OnSlotPageNextButton();
_shortcutsInputManager.actionBarPrevious.performed += _ => OnSlotPagePreviousButton();
_playerController.OnActiveUnitChange += OnActiveUnitChange;
}
private void OnActiveUnitChange(UnitObject unitObject)
{
// Remove listeners from old unit
if (_unit)
{
_unit.unitEvents.onActionBarSet.RemoveListener(OnSlotSet);
_unit.unitEvents.onActionBarUnSet.RemoveListener(OnSlotUnSet);
}
_slotsPage = 1;
_unit = unitObject;
_actionBar = unitObject.unitActionBar;
_slotsChangerNumberLabel.text = _slotsPage.ToString();
UpdateAllSlots();
// Rebind listeners to new unit
_unit.unitEvents.onActionBarSet.AddListener(OnSlotSet);
_unit.unitEvents.onActionBarUnSet.AddListener(OnSlotUnSet);
}
private void OnSlotPageNextButton()
{
_slotsPage++;
if (_slotsPage > _slotsPageCount) _slotsPage = 1;
_slotsChangerNumberLabel.text = _slotsPage.ToString();
UpdateAllSlots();
}
private void OnSlotPagePreviousButton()
{
_slotsPage--;
if (_slotsPage < 1) _slotsPage = _slotsPageCount;
_slotsChangerNumberLabel.text = _slotsPage.ToString();
UpdateAllSlots();
}
private void OnSlotSet(ActionBarSetEvent actionBarSetEvent)
{
UpdateSlot(actionBarSetEvent.index % _slotsPerPage);
}
private void OnSlotUnSet(ActionBarUnSetEvent actionBarUnSetEvent)
{
UpdateSlot(actionBarUnSetEvent.index % _slotsPerPage);
}
private void UpdateAllSlots()
{
for (var i = 0; i < _slotsPerPage; i++)
UpdateSlot(i);
}
private void UpdateSlot(int index)
{
var sourceIndex = (_slotsPage - 1) * _slotsPerPage + index;
var usable = _actionBar.slots[sourceIndex].usable;
var ability = _actionBar.slots[sourceIndex].ability;
if (usable) slotsUI[index].Set(usable);
else if (ability) slotsUI[index].Set(ability);
else slotsUI[index].Clear();
slotsUI[index].ChangeIndex(sourceIndex);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8900566df7ce4579815b090da229de83
timeCreated: 1698256486
@@ -0,0 +1,257 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
using VOID.Generic.Turn;
namespace VOID.UserInterface.Game
{
/// <summary>
/// Manages ActionBar's Turn elements for current player only:<br/>
/// - Turn resources of <see cref="UnitObject"/><br/>
/// - Button to start new <see cref="TurnManager"/><br/>
/// - Buttons to <see cref="LeaveTurnAction"/> and <see cref="EndTurnAction"/> when in combat
/// </summary>
public class ActionBarTurnInfoUI : MonoBehaviour
{
public static ActionBarTurnInfoUI current { get; private set; }
// ActionBar for this unit
private UnitObject _unit;
private UnitObjectActionBar _actionBar;
// Visual Elements - Turn Info
private VisualElement _turnInfoElement;
private VisualElement _actionPointsElement;
private readonly List<VisualElement> _actionPointsElements = new();
private ProgressBar _moveBar;
private Button _nextTurnButton;
private Button _startTurnButton;
private Button _endTurnButton;
// References
private PlayerController _playerController;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Find all important elements
_turnInfoElement = templateElement.Q("turn-info");
_actionPointsElement = templateElement.Q("action-points");
_moveBar = templateElement.Q<ProgressBar>("move-bar");
_nextTurnButton = templateElement.Q<Button>("next-turn");
_startTurnButton = templateElement.Q<Button>("start-turn");
_endTurnButton = templateElement.Q<Button>("end-turn");
// Remove placeholders from action points
_actionPointsElement.Clear();
_turnInfoElement.dataSource = this;
_turnInfoElement.pickingMode = PickingMode.Position;
}
private void Start()
{
_playerController = PlayerController.current;
_playerController.OnActiveUnitChange += OnActiveUnitChange;
_nextTurnButton.clicked += NextTurn;
_startTurnButton.clicked += StartTurn;
_endTurnButton.clicked += EndTurn;
}
/// <summary>
/// Player order active unit to end its turn.
/// </summary>
private void NextTurn()
{
if (!_unit) return;
_unit.OrderStop();
_unit.Order(new EndTurnAction(_unit));
}
/// <summary>
/// Starts new turn manager - also nearby units will also join
/// </summary>
private void StartTurn()
{
if (!_unit) return;
if (_unit.basicState.turnManager) return;
TurnManager.BuildGameObject(_unit);
}
/// <summary>
/// Player order active unit to try end turn.<br/>
/// - If combat is FORCED then try to escape (if possible)
/// - If combat is NOT FORCED then end whole turn manager
/// </summary>
private void EndTurn()
{
if (!_unit) return;
if (!_unit.basicState.turnManager) return;
// if fight is forced when try leave with current unit
// else end whole turn combat
if (_unit.basicState.turnManager.isForcedFight)
_unit.OrderInstantly(new LeaveTurnAction(_unit));
else
_unit.basicState.turnManager.EndTurnManager();
}
/// <summary>
/// Depending on unit turn state it hide or show player's buttons for turn.
/// </summary>
private void UpdateTurnButtonsVisibility()
{
if (_unit.basicState.turnManager)
{
_nextTurnButton.style.display = DisplayStyle.Flex;
_endTurnButton.style.display = DisplayStyle.Flex;
_startTurnButton.style.display = DisplayStyle.None;
}
else
{
_nextTurnButton.style.display = DisplayStyle.None;
_endTurnButton.style.display = DisplayStyle.None;
_startTurnButton.style.display = DisplayStyle.Flex;
}
}
/// <summary>
/// 1. Stops listening to changes for previous unit
/// 2. Start listening to changes in new active unit
/// 3. Updates whole UI
/// </summary>
private void OnActiveUnitChange(UnitObject unit)
{
if (_unit)
{
_unit.basicEvents.onTurnQueueEnter.RemoveListener(OnTurnEnter);
_unit.basicEvents.onTurnQueueLeave.RemoveListener(OnTurnLeave);
_unit.basicEvents.onTurnSelfStart.RemoveListener(OnTurnSelfStart);
_unit.basicEvents.onTurnSelfEnd.RemoveListener(OnTurnSelfEnd);
_unit.unitEvents.onCurrentResourceChange.RemoveListener(OnResourceChange);
_unit.unitEvents.onMaxResourceChange.RemoveListener(OnResourceChange);
}
_unit = unit;
UpdateActionPoints();
UpdateMovePoints();
UpdateTurnButtonsVisibility();
UpdateWaitingForTurn();
_unit.basicEvents.onTurnQueueEnter.AddListener(OnTurnEnter);
_unit.basicEvents.onTurnQueueLeave.AddListener(OnTurnLeave);
_unit.basicEvents.onTurnSelfStart.AddListener(OnTurnSelfStart);
_unit.basicEvents.onTurnSelfEnd.AddListener(OnTurnSelfEnd);
_unit.unitEvents.onCurrentResourceChange.AddListener(OnResourceChange);
_unit.unitEvents.onMaxResourceChange.AddListener(OnResourceChange);
}
private void OnTurnEnter(TurnEvent turnEvent)
{
UpdateTurnButtonsVisibility();
UpdateWaitingForTurn();
}
private void OnTurnLeave(TurnEvent turnEvent)
{
UpdateTurnButtonsVisibility();
UpdateWaitingForTurn();
}
private void OnTurnSelfStart(TurnEvent turnEvent)
{
UpdateWaitingForTurn();
}
private void OnTurnSelfEnd(TurnEvent turnEvent)
{
UpdateWaitingForTurn();
}
/// <summary>
/// Makes ActionBar's turn elements inactive if currently active unit is waiting for its turn.
/// </summary>
private void UpdateWaitingForTurn()
{
var isWaiting = _unit.basicState.turnManager && _unit.basicState.turnManager.currentUnitTurn != _unit;
_turnInfoElement.EnableInClassList("inactive", isWaiting);
}
private void OnResourceChange(UnitResourceChangeEvent resourceChangeEvent)
{
switch (resourceChangeEvent.type)
{
case UnitResourceType.ActionPoints:
UpdateActionPoints();
break;
case UnitResourceType.MovePoints:
UpdateMovePoints();
break;
default: return;
}
}
/// <summary>
/// Updates current and max action points to correspond these from UnitData.
/// </summary>
private void UpdateActionPoints()
{
var maxActionPoints = (int)_unit.unitData.maxResources.actionPoints;
var currentActionPoints = (int)_unit.unitData.currentResources.actionPoints;
// Add/Remove visual elements if needed
for (var i = 0; i < maxActionPoints - _actionPointsElements.Count;) AddActionPointElement();
for (var i = 0; i < _actionPointsElements.Count - maxActionPoints;) RemoveActionPointElement();
// Activate/Disable action points
for (var i = 0; i < _actionPointsElements.Count; i++)
{
var actionPointElement = _actionPointsElements[i];
actionPointElement.EnableInClassList("active-action-point", i < currentActionPoints);
}
}
/// <summary>
/// Adds new action point element to UI.
/// </summary>
private void AddActionPointElement()
{
var actionPointElement = new VisualElement();
actionPointElement.AddToClassList("action-point");
_actionPointsElement.Add(actionPointElement);
_actionPointsElements.Add(actionPointElement);
}
/// <summary>
/// Removes one action point element from UI.
/// </summary>
private void RemoveActionPointElement()
{
_actionPointsElement.Remove(_actionPointsElements.Last());
_actionPointsElements.Remove(_actionPointsElements.Last());
}
/// <summary>
/// Updates current and max move points to correspond these from UnitData.
/// </summary>
private void UpdateMovePoints()
{
_moveBar.highValue = _unit.unitData.maxResources.movePoints;
_moveBar.value = _unit.unitData.currentResources.movePoints;
_moveBar.title = $"{_moveBar.value:F1} / {_moveBar.highValue:F1}";
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2c8a6007d092484791bc178076b6c722
timeCreated: 1698256942
@@ -0,0 +1,65 @@
<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="Slot" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Slot.uxml?fileID=9197481963319205126&amp;guid=5a74e2b56bbc27c4ab7a5d0c1de93f00&amp;type=3#Slot" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/ActionBarUIStyle.uss?fileID=7433441132597879392&amp;guid=a45ec38a8dc54ab4bb8194d8dd465333&amp;type=3#ActionBarUIStyle" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/SlotOuter.uss?fileID=7433441132597879392&amp;guid=760aa0b2431a11e46a81be0018d225b1&amp;type=3#SlotOuter" />
<ui:VisualElement name="root-action-bar" picking-mode="Ignore">
<ui:VisualElement name="center-background">
<ui:VisualElement name="mini-menu">
<ui:Button text="ESC" name="menu" class="option" />
<ui:Button text="I" name="backpack" class="option" />
<ui:Button text="P" name="equipment" class="option" />
<ui:Button text="O" name="ability-book" class="option" />
<ui:Button text="M" name="map" class="option" />
<ui:Button text="L" name="log-book" class="option" />
<ui:Button text="[o]" name="slots-locker" class="locker option" />
<ui:VisualElement name="slots-changer" picking-mode="Ignore" class="option">
<ui:Button text="v" name="next" />
<ui:Label text="1" name="number" picking-mode="Ignore" />
<ui:Button text="v" name="previous" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="slots">
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
</ui:VisualElement>
<ui:VisualElement name="turn-info">
<ui:VisualElement name="action-points" picking-mode="Ignore" style="flex-grow: 1;">
<ui:VisualElement picking-mode="Ignore" class="action-point active-action-point" style="flex-grow: 1;" />
<ui:VisualElement picking-mode="Ignore" class="action-point active-action-point" style="flex-grow: 1;" />
<ui:VisualElement picking-mode="Ignore" class="action-point" style="flex-grow: 1;" />
</ui:VisualElement>
<ui:ProgressBar value="6.2" title="6.2 / 15.0" name="move-bar" high-value="15" picking-mode="Ignore" />
<ui:VisualElement name="turn-buttons" picking-mode="Ignore">
<ui:Button text="NEXT&lt;br&gt;TURN" name="next-turn" enable-rich-text="true" class="turn-button" />
<ui:Button text="START&lt;br&gt;TURN" name="start-turn" enable-rich-text="true" class="turn-button" />
<ui:Button text="END&lt;br&gt;TURN" name="end-turn" enable-rich-text="true" class="turn-button" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 7c034f1843055df418d83c895798dec3
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,228 @@
#root-action-bar {
width: 100%;
align-items: center;
flex-direction: row;
justify-content: center;
position: absolute;
bottom: 0;
}
#center-background {
flex-direction: row;
align-self: auto;
justify-content: center;
background-color: rgba(0, 0, 0, 0.49);
padding-left: 5px;
padding-right: 5px;
}
#slots {
flex-direction: row;
align-items: center;
flex-shrink: 1;
}
#slots > .slot {
padding-left: 1px;
padding-right: 1px;
padding-top: 1px;
padding-bottom: 1px;
}
#mini-menu {
flex-grow: 0;
flex-direction: row;
flex-shrink: 1;
height: 100%;
}
#mini-menu > .option {
flex-grow: 0;
flex-shrink: 1;
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
margin-bottom: 2px;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
flex-basis: 25px;
}
#mini-menu > #slots-changer {
justify-content: space-between;
align-items: center;
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
margin-bottom: 2px;
padding-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
flex-basis: 15px;
}
#mini-menu > #slots-changer > #next {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 2px;
padding-right: 2px;
padding-top: 0;
padding-bottom: 0;
rotate: 180deg;
}
#mini-menu > #slots-changer > #number {
padding-left: 3px;
padding-right: 3px;
padding-top: 0;
padding-bottom: 0;
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
-unity-text-align: upper-center;
flex-shrink: 1;
flex-grow: 1;
}
#mini-menu > #slots-changer > #previous {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 2px;
padding-right: 2px;
padding-top: 0;
padding-bottom: 0;
}
#turn-info {
position: absolute;
bottom: 100%;
flex-direction: row;
align-items: flex-end;
background-color: rgba(0, 0, 0, 0.39);
padding-left: 3px;
padding-right: 3px;
padding-top: 3px;
padding-bottom: 3px;
margin-bottom: 5px;
}
#turn-info.inactive {
opacity: 0.25;
}
#turn-info > #action-points {
flex-direction: row;
}
#turn-info > #action-points > .action-point {
width: 25px;
height: 25px;
border-left-color: rgb(0, 0, 0);
border-right-color: rgb(0, 0, 0);
border-top-color: rgb(0, 0, 0);
border-bottom-color: rgb(0, 0, 0);
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
border-top-left-radius: 100%;
border-bottom-left-radius: 100%;
border-top-right-radius: 100%;
border-bottom-right-radius: 100%;
margin-left: 3px;
margin-right: 3px;
margin-top: 0;
margin-bottom: 0;
background-color: rgba(132, 132, 132, 0.59);
}
#turn-info > #action-points > .active-action-point {
background-color: rgb(136, 180, 88);
}
#turn-info > #move-bar {
margin-left: 3px;
margin-right: 3px;
margin-top: 0;
margin-bottom: 0;
height: 25px;
width: 200px;
}
#turn-info > #move-bar .unity-progress-bar__container {
max-height: 100%;
max-width: 100%;
min-height: auto;
min-width: auto;
width: 100%;
height: 100%;
}
#turn-info > #move-bar .unity-progress-bar__background {
background-color: rgba(0, 0, 0, 0.39);
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
max-width: 100%;
max-height: 100%;
width: 100%;
height: 100%;
border-left-width: 0;
border-right-width: 0;
border-top-width: 0;
border-bottom-width: 0;
}
#turn-info > #move-bar .unity-progress-bar__progress {
background-color: rgb(188, 124, 68);
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
max-width: 100%;
max-height: 100%;
width: auto;
height: 100%;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
}
#turn-info > #move-bar .unity-progress-bar__title-container {
-unity-font-style: bold;
color: rgb(255, 255, 255);
}
#turn-info > #turn-buttons {
flex-direction: row;
right: auto;
position: absolute;
left: 100%;
margin-left: 10px;
}
#turn-info > #turn-buttons > .turn-button {
flex-direction: row;
margin-top: 0;
margin-right: 3px;
margin-bottom: 0;
margin-left: 3px;
padding-top: 8px;
padding-right: 8px;
padding-bottom: 8px;
padding-left: 8px;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a45ec38a8dc54ab4bb8194d8dd465333
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f8055a465e3fed942be5fc7c99ef6494
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,80 @@
using System.Collections;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
namespace VOID.UserInterface.Game.AlertUI
{
public class AlertUI : MonoBehaviour
{
public static AlertUI current { get; private set; }
[SerializeField, MinValue(0)] private float timeToHideAlert = 3f;
[SerializeField] private string DEATH_MESSAGE = "Died!";
[SerializeField] private string TURN_START = "Turn start";
[SerializeField] private string ACTION_ERROR_MESSAGE = "Action prevented: {0}";
private Label _label;
private VisualElement _root;
private Coroutine _hideAlertCoroutine;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
_root = uiDocument.rootVisualElement;
_label = _root.Q<Label>("alert-label");
HideAlert();
}
private void ShowAlert(string message)
{
if (_hideAlertCoroutine != null)
{
StopCoroutine(_hideAlertCoroutine);
}
_label.text = message;
_label.style.display = DisplayStyle.Flex;
_hideAlertCoroutine = StartCoroutine(HideAlertAfterDelay(timeToHideAlert));
}
private IEnumerator HideAlertAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
HideAlert();
}
private void HideAlert()
{
_label.text = "";
_label.style.display = DisplayStyle.None;
}
public void ListenFor(UnitObject unit)
{
unit.basicEvents.onDeathAfter.AddListener(OnDeathAfter);
unit.basicEvents.onTurnSelfStart.AddListener(OnTurnSelfStart);
unit.unitEvents.onActionError.AddListener(OnActionError);
}
public void StopListenFor(UnitObject unit)
{
unit.basicEvents.onDeathAfter.RemoveListener(OnDeathAfter);
unit.basicEvents.onTurnSelfStart.RemoveListener(OnTurnSelfStart);
unit.unitEvents.onActionError.RemoveListener(OnActionError);
}
/* EVENTS BELOW */
/* for register and unregister */
private void OnDeathAfter(DeathEvent e) => ShowAlert(DEATH_MESSAGE);
private void OnTurnSelfStart(TurnEvent e) => ShowAlert(TURN_START);
private void OnActionError(ActionErrorEvent e) => ShowAlert(string.Format(ACTION_ERROR_MESSAGE, UnitActionErrorMessage.Get(e.cause)));
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1431d504a115b844cbbfb202c996a38e
@@ -0,0 +1,10 @@
#alert-ui {
position: absolute;
top: 20%;
}
#alert-label {
color: red;
font-size: 36px;
font-weight: bold;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8910e204f06c65342b7cec98902b019c
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,6 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/AlertUI/AlertUI.uss?fileID=7433441132597879392&amp;guid=8910e204f06c65342b7cec98902b019c&amp;type=3#AlertUI" />
<ui:VisualElement name="alert-ui" style="flex-direction: column; justify-content: center; align-self: center; align-items: center;">
<ui:Label name="alert-label" text="Alert!" style="color: red; -unity-text-align: upper-left;" />
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: dc08ee0446ff0eb4594fe4fd762b958a
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,198 @@
using System;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
using VOID.Generic.Player.Input;
using VOID.UserInterface.Game.Interfaces;
using VOID.UserInterface.Game.Util;
namespace VOID.UserInterface.Game
{
public class BackpackUI : MonoBehaviour, IHasWindow
{
public static BackpackUI current { get; private set; }
// WindowUI
public WindowUI windowUI { get; private set; }
// Active Unit and his Backpack
private UnitObject _unit;
private UnitObjectBackpack _backpack;
// Visual Elements
private VisualElement _rootElement;
private VisualElement _slotsElement;
private SlotUI[] _slots;
// References
private ShortcutsInputManager _shortcutsInputManager;
private PlayerController _playerController;
// Sort buttons
private Button _sortButton;
private void Awake() {
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Find all important elements
_rootElement = templateElement.Q("root-backpack");
_slotsElement = templateElement.Q("slots");
windowUI = gameObject.GetComponent<WindowUI>();
// Sort buttons
_sortButton = templateElement.Q<Button>("Sort");
// Clear placeholders
_slotsElement.Clear();
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
}
private void Start() {
_shortcutsInputManager = ShortcutsInputManager.current;
_playerController = PlayerController.current;
// Toggle show/hide when pressing shortcut for backpack
_shortcutsInputManager.inventory.performed += _ => windowUI.Toggle();
windowUI.OnOpen += OnOpen;
windowUI.OnClose += OnClose;
// Sort buttons
_sortButton.clicked += () => {
var worldBound = _sortButton.worldBound;
var positionToDisplayDropdown = new Vector2(worldBound.x, worldBound.y + worldBound.height);
DropdownUI.current.Prepare(positionToDisplayDropdown);
DropdownUI.current.AddOption("Name ↑", () => _backpack.Sort(item => item.basicData.finalName, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Name ↓", () => _backpack.Sort(item => item.basicData.finalName, SortDirectionType.Descending));
DropdownUI.current.AddOption("Price ↑", () => _backpack.Sort(item => item.itemData.finalValue, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Price ↓", () => _backpack.Sort(item => item.itemData.finalValue, SortDirectionType.Descending));
DropdownUI.current.AddOption("Weight ↑", () => _backpack.Sort(item => item.itemData.finalWeight, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Weight ↓", () => _backpack.Sort(item => item.itemData.finalWeight, SortDirectionType.Descending));
DropdownUI.current.AddOption("Quality ↑", () => _backpack.Sort(item => item.itemData.quality.index, SortDirectionType.Ascending));
DropdownUI.current.AddOption("Quality ↓", () => _backpack.Sort(item => item.itemData.quality.index, SortDirectionType.Descending));
DropdownUI.current.Open();
};
windowUI.SetTitle("Backpack");
// Hidden by default
windowUI.Close();
}
public void Toggle() => windowUI.Toggle();
public void Open() => windowUI.Open();
public void Close() => windowUI.Close();
private void OnOpen() {
// References to active unit
_unit = PlayerController.current.activeUnit;
_backpack = _unit.unitBackpack;
// Refresh UI when we change active unit
_playerController.OnActiveUnitChange += OnActiveUnitChange;
// Initialize array with same amount of slots as backpack
_slots = new SlotUI[_backpack.items.Length];
// Initialize all VisualElements
for (var i = 0; i < _backpack.items.Length; i++)
UpdateSlotUI(i, _backpack.items[i]);
// Listen to all changes in backpack and update UI
_unit.unitEvents.onBackpackPick.AddListener(OnPick);
_unit.unitEvents.onBackpackDrop.AddListener(OnDrop);
_unit.unitEvents.onBackpackSwap.AddListener(OnSwap);
_unit.unitEvents.onBackpackSort.AddListener(OnSort);
_unit.unitEvents.onBackpackResize.AddListener(OnResize);
}
private void OnClose() {
// Stop listening
_playerController.OnActiveUnitChange -= OnActiveUnitChange;
// Backpack closed, no need to listen for backpack changes
if (_unit) {
_unit.unitEvents.onBackpackPick.RemoveListener(OnPick);
_unit.unitEvents.onBackpackDrop.RemoveListener(OnDrop);
_unit.unitEvents.onBackpackSwap.RemoveListener(OnSwap);
_unit.unitEvents.onBackpackSort.RemoveListener(OnSort);
_unit.unitEvents.onBackpackResize.RemoveListener(OnResize);
}
// Remove all VisualElement slots
if (_slots != null)
for (var i = 0; i < _slots.Length; i++)
RemoveSlotUI(i);
// Clear variables
_slots = null;
_unit = null;
_backpack = null;
}
private void OnActiveUnitChange(UnitObject unitObject) {
windowUI.Close();
windowUI.Open();
}
private void OnPick(BackpackPickEvent backpackPickEvent) {
UpdateSlotUI(backpackPickEvent.slotIndex, backpackPickEvent.item);
}
private void OnDrop(BackpackDropEvent backpackDropEvent) {
UpdateSlotUI(backpackDropEvent.slotIndex, null);
}
private void OnSwap(BackpackSwapEvent backpackSwapEvent) {
UpdateSlotUI(backpackSwapEvent.firstSlotIndex, backpackSwapEvent.firstItem);
UpdateSlotUI(backpackSwapEvent.secondSlotIndex, backpackSwapEvent.secondItem);
}
private void OnSort(BackpackSortEvent backpackSortEvent) {
var backpackItems = backpackSortEvent.unit.unitBackpack.items;
for (var i = 0; i < backpackItems.Length; i++)
UpdateSlotUI(i, backpackItems[i]);
}
private void OnResize(BackpackResizeEvent backpackResizeEvent) {
// Before resizing - remove all unused slots
if (backpackResizeEvent.beforeSlotCount > backpackResizeEvent.afterSlotCount)
for (var i = backpackResizeEvent.afterSlotCount; i < backpackResizeEvent.beforeSlotCount; i++)
RemoveSlotUI(i);
Array.Resize(ref _slots, backpackResizeEvent.afterSlotCount);
// After resizing - insert empty slots
if (backpackResizeEvent.beforeSlotCount < backpackResizeEvent.afterSlotCount)
for (var i = backpackResizeEvent.beforeSlotCount; i < backpackResizeEvent.afterSlotCount; i++)
UpdateSlotUI(i, null);
}
private void UpdateSlotUI(int slotIndex, [CanBeNull] ItemObject item) {
// Create new VisualElement if not exists
if (_slots[slotIndex] is null) {
_slots[slotIndex] = new SlotUI();
_slots[slotIndex].InitNew(_slotsElement, SlotType.BackpackSlot, slotIndex, "Slot-" + slotIndex);
}
// Put item's icon or else remain default
_slots[slotIndex].Set(item);
}
private void RemoveSlotUI(int slotIndex) {
_slots[slotIndex].Destroy();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 507a3046f755426d837f954f4f6c1210
timeCreated: 1670879291
@@ -0,0 +1,46 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.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="Background" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Window.uxml?fileID=9197481963319205126&amp;guid=04235ec1d1b764e448e2524000a1b87a&amp;type=3#Window" />
<ui:Template name="Slot" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Slot.uxml?fileID=9197481963319205126&amp;guid=5a74e2b56bbc27c4ab7a5d0c1de93f00&amp;type=3#Slot" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/BackpackUIStyle.uss?fileID=7433441132597879392&amp;guid=b2a381b6de27c8d44b8421bd60aaf8c7&amp;type=3#BackpackUIStyle" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/WindowOuter.uss?fileID=7433441132597879392&amp;guid=80611877e61dcf346bf43cfc4ebd3394&amp;type=3#WindowOuter" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/SlotOuter.uss?fileID=7433441132597879392&amp;guid=760aa0b2431a11e46a81be0018d225b1&amp;type=3#SlotOuter" />
<ui:VisualElement name="root-backpack">
<ui:Instance template="Background" name="window" style="top: 0; left: 0;">
<AttributeOverrides element-name="Title" text="INVENTORY" />
</ui:Instance>
<ui:VisualElement name="options">
<ui:Button name="Sort" text="▼" />
<ui:Button text="Equipments" name="Button" class="filter" />
<ui:Button text="Materials" display-tooltip-when-elided="true" class="filter" />
<ui:Button text="Usables" display-tooltip-when-elided="true" class="filter" />
<ui:Button text="Scrolls" display-tooltip-when-elided="true" class="filter" />
<ui:Button text="Important" display-tooltip-when-elided="true" class="filter" />
<ui:Button text="Stolen" display-tooltip-when-elided="true" class="filter" />
<ui:Button text="Trash" display-tooltip-when-elided="true" class="filter" />
</ui:VisualElement>
<ui:VisualElement name="slots">
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d6ffd1eb724551a41b9dd092a9ca115c
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,47 @@
#root-backpack {
top: 10px;
right: 10px;
height: 800px;
width: 700px;
position: absolute;
}
#options {
flex-basis: 60px;
flex-direction: row;
align-items: center;
justify-content: center;
margin-left: 15px;
margin-right: 15px;
margin-top: 40px;
margin-bottom: 5px;
border-bottom-width: 1px;
border-left-color: rgb(88, 88, 88);
border-right-color: rgb(88, 88, 88);
border-top-color: rgb(88, 88, 88);
border-bottom-color: rgb(88, 88, 88);
flex-shrink: 0;
}
#slots {
flex-direction: row;
flex-basis: 100%;
margin-left: 15px;
margin-right: 15px;
margin-top: 5px;
margin-bottom: 15px;
flex-wrap: wrap;
align-items: stretch;
justify-content: flex-start;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
}
#slots > .slot {
margin-left: 1px;
margin-right: 1px;
margin-top: 1px;
margin-bottom: 1px;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b2a381b6de27c8d44b8421bd60aaf8c7
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,52 @@
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Container.Events;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Player;
namespace VOID.UserInterface.Game
{
public class ContainerManagerUI : MonoBehaviour
{
public static ContainerManagerUI current { get; private set; }
// References
private PlayerController _playerController;
// Template
[SerializeField, AssetsOnly] private GameObject _containerUIPrefab;
// Unit which we listen for opening container
private UnitObject _unit;
private void Awake()
{
current = this;
}
private void Start()
{
_playerController = PlayerController.current;
_playerController.OnActiveUnitChange += OnActiveUnitChange;
}
private void OnActiveUnitChange(UnitObject unit)
{
if (_unit)
{
_unit.unitEvents.onContainerOpen.RemoveListener(OnContainerOpen);
ContainerUI.currentList.ToList().ForEach(containerUI => containerUI.Close());
}
_unit = unit;
_unit.unitEvents.onContainerOpen.AddListener(OnContainerOpen);
}
private void OnContainerOpen(ContainerOpenEvent containerOpenEvent)
{
Instantiate(_containerUIPrefab, gameObject.transform)
.GetComponent<ContainerUI>()
.Open(containerOpenEvent.container, containerOpenEvent.openedBy);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 55d3913f1a9a4bbebde332293c9f60e7
timeCreated: 1694902221
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Container;
using VOID.Generic.Objects.Container.Events;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions;
using VOID.UserInterface.Game.Interfaces;
using VOID.UserInterface.Game.Util;
namespace VOID.UserInterface.Game
{
public class ContainerUI : MonoBehaviour, IHasWindow
{
public static List<ContainerUI> currentList { get; } = new();
// WindowUI
public WindowUI windowUI { get; private set; }
// ContainerObject, its content to which this UI is connected and also unit who opened it
public ContainerObject container { get; private set; }
private ContainerObjectContent _content;
private UnitObject _unit;
// Visual Elements
private VisualElement _rootElement;
private VisualElement _slotsElement;
private SlotUI[] _slots;
// Sort buttons
private Button _sortButton;
private void Awake() {
currentList.Add(this);
var uiDocument = gameObject.GetComponent<UIDocument>();
var template = uiDocument.rootVisualElement;
// Find all important elements
_rootElement = template.Q("root-container");
_slotsElement = template.Q("slots");
windowUI = gameObject.GetComponent<WindowUI>();
// Sort buttons
_sortButton = template.Q<Button>("Sort");
// Remove place holders
_slotsElement.Clear();
windowUI.OnClose += Close;
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
// Sort buttons
_sortButton.clicked += () => {
var worldBound = _sortButton.worldBound;
var positionToDisplayDropdown = new Vector2(worldBound.x, worldBound.y + worldBound.height);
DropdownUI.current.Prepare(positionToDisplayDropdown);
DropdownUI.current.AddOption("Name ↑", () => _content.Sort(item => item.basicData.finalName, SortDirectionType.Ascending, _unit));
DropdownUI.current.AddOption("Name ↓", () => _content.Sort(item => item.basicData.finalName, SortDirectionType.Descending, _unit));
DropdownUI.current.AddOption("Price ↑", () => _content.Sort(item => item.itemData.finalValue, SortDirectionType.Ascending, _unit));
DropdownUI.current.AddOption("Price ↓", () => _content.Sort(item => item.itemData.finalValue, SortDirectionType.Descending, _unit));
DropdownUI.current.AddOption("Weight ↑", () => _content.Sort(item => item.itemData.finalWeight, SortDirectionType.Ascending, _unit));
DropdownUI.current.AddOption("Weight ↓", () => _content.Sort(item => item.itemData.finalWeight, SortDirectionType.Descending, _unit));
DropdownUI.current.AddOption("Quality ↑", () => _content.Sort(item => item.itemData.quality.index, SortDirectionType.Ascending, _unit));
DropdownUI.current.AddOption("Quality ↓", () => _content.Sort(item => item.itemData.quality.index, SortDirectionType.Descending, _unit));
DropdownUI.current.Open();
};
}
public void Open(ContainerObject container, UnitObject unit) {
this.container = container;
_content = container.containerContent;
_unit = unit;
_slots = new SlotUI[_content.items.Length];
for (var i = 0; i < _content.items.Length; i++)
SetSlot(i, _content.items[i]);
container.containerEvents.onClose.AddListener(OnClose);
container.containerEvents.onResize.AddListener(OnResize);
container.containerEvents.onSwap.AddListener(OnSwap);
container.containerEvents.onMoveIn.AddListener(OnMoveIn);
container.containerEvents.onMoveOut.AddListener(OnMoveOut);
container.containerEvents.onSort.AddListener(OnSort);
windowUI.SetTitle(container.basicData.finalName);
// Make sure it is visible
_rootElement.style.display = DisplayStyle.Flex;
}
public void Close() {
_unit.OrderInstantly(new CloseContainerAction(_unit, container));
}
private void OnClose(ContainerCloseEvent containerCloseEvent) {
container.containerEvents.onClose.RemoveListener(OnClose);
container.containerEvents.onResize.RemoveListener(OnResize);
container.containerEvents.onSwap.RemoveListener(OnSwap);
container.containerEvents.onMoveIn.RemoveListener(OnMoveIn);
container.containerEvents.onMoveOut.RemoveListener(OnMoveOut);
container.containerEvents.onSort.RemoveListener(OnSort);
windowUI.OnClose -= Close;
_rootElement.parent.parent.Remove(_rootElement.parent);
currentList.Remove(this);
Destroy(this);
}
private void OnResize(ContainerResizeEvent containerResizeEvent) {
// Before resizing - remove all unused slots
if (containerResizeEvent.beforeSlotCount > containerResizeEvent.afterSlotCount)
for (var i = containerResizeEvent.afterSlotCount; i < containerResizeEvent.beforeSlotCount; i++)
RemoveSlot(i);
Array.Resize(ref _slots, containerResizeEvent.afterSlotCount);
// After resizing - insert empty slots
if (containerResizeEvent.beforeSlotCount < containerResizeEvent.afterSlotCount)
for (var i = containerResizeEvent.beforeSlotCount; i < containerResizeEvent.afterSlotCount; i++)
SetSlot(i, null);
}
private void OnSwap(ContainerSwapEvent containerSwapEvent) {
SetSlot(containerSwapEvent.firstSlotIndex, containerSwapEvent.firstItem);
SetSlot(containerSwapEvent.secondSlotIndex, containerSwapEvent.secondItem);
}
private void OnMoveIn(ContainerMoveInEvent containerMoveInEvent) {
SetSlot(containerMoveInEvent.slotIndex, containerMoveInEvent.item);
}
private void OnMoveOut(ContainerMoveOutEvent containerMoveOutEvent) {
SetSlot(containerMoveOutEvent.slotIndex, null);
}
private void OnSort(ContainerSortEvent containerSortEvent) {
var containerItems = containerSortEvent.container.containerContent.items;
for (var i = 0; i < containerItems.Length; i++)
SetSlot(i, containerItems[i]);
}
private void SetSlot(int slotIndex, ItemObject item) {
// Create new VisualElement if not exists
if (_slots[slotIndex] is null) {
_slots[slotIndex] = new SlotUI();
_slots[slotIndex].InitNew(_slotsElement, SlotType.ContainerSlot, slotIndex, "Slot-" + slotIndex);
}
// Put item's icon or else remain default
_slots[slotIndex].Set(item);
}
private void RemoveSlot(int slotIndex) {
_slots[slotIndex].Destroy();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8f389f6da8914b1d8fd99551412e1706
timeCreated: 1694902221
@@ -0,0 +1,29 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.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="Window" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Window.uxml?fileID=9197481963319205126&amp;guid=04235ec1d1b764e448e2524000a1b87a&amp;type=3#Window" />
<ui:Template name="Slot" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Slot.uxml?fileID=9197481963319205126&amp;guid=5a74e2b56bbc27c4ab7a5d0c1de93f00&amp;type=3#Slot" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/ContainerUIStyle.uss?fileID=7433441132597879392&amp;guid=964515575a004fc38ed598c57bd6fdc5&amp;type=3#ContainerUIStyle" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/SlotOuter.uss?fileID=7433441132597879392&amp;guid=760aa0b2431a11e46a81be0018d225b1&amp;type=3#SlotOuter" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/WindowOuter.uss?fileID=7433441132597879392&amp;guid=80611877e61dcf346bf43cfc4ebd3394&amp;type=3#WindowOuter" />
<ui:VisualElement name="root-container">
<ui:Instance template="Window" name="window" />
<ui:VisualElement name="sorts">
<ui:VisualElement name="sort_lane" style="flex-grow: 1; flex-direction: row; align-items: center; justify-content: center; align-self: flex-start;">
<ui:Button name="Sort" text="▼" />
</ui:VisualElement>
</ui:VisualElement>
<ui:ScrollView scroll-deceleration-rate="0,135" elasticity="0,1" name="slots-scroller" vertical-scroller-visibility="AlwaysVisible">
<ui:VisualElement name="slots">
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
<ui:Instance template="Slot" class="slot slot-medium" />
</ui:VisualElement>
</ui:ScrollView>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 54bcb053b8c1450489178f11a174ba86
timeCreated: 1694902221
@@ -0,0 +1,58 @@
#root-container {
width: 400px;
height: 400px;
min-width: 400px;
min-height: 400px;
position: absolute;
left: 800px;
top: 400px;
}
#sorts {
flex-basis: 60px;
flex-direction: column;
align-items: center;
justify-content: center;
margin-left: 15px;
margin-right: 15px;
margin-top: 40px;
margin-bottom: 5px;
border-bottom-width: 1px;
border-left-color: rgb(88, 88, 88);
border-right-color: rgb(88, 88, 88);
border-top-color: rgb(88, 88, 88);
border-bottom-color: rgb(88, 88, 88);
flex-shrink: 0;
}
#sort_lane {
flex-direction: row;
align-items: left;
align-self: left;
flex-shrink: 0;
}
#slots-scroller {
margin-left: 15px;
margin-right: 15px;
margin-top: 0px;
margin-bottom: 15px;
height: 100%;
}
#slots-scroller > #slots {
height: 100%;
flex-wrap: wrap;
flex-direction: row;
margin-left: 0;
margin-right: 5px;
margin-top: 0;
margin-bottom: 0;
}
#slots-scroller > #slots > .slot {
margin-left: 1px;
margin-right: 1px;
margin-top: 1px;
margin-bottom: 1px;
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 964515575a004fc38ed598c57bd6fdc5
timeCreated: 1694902221
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
using PlayerInputManager = VOID.Generic.Player.Input.PlayerInputManager;
namespace VOID.UserInterface.Game
{
public class ContextMenuUI : MonoBehaviour
{
public static ContextMenuUI current {get; private set;}
// Visual Elements
private VisualElement _optionsElement;
private readonly List<Button> _options = new();
private event Action BeforeClick;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
_optionsElement = templateElement.Q("options");
_optionsElement.RegisterCallback<MouseLeaveEvent>(_ => PlayerInputManager.current.OnDefaultUse += Close);
_optionsElement.RegisterCallback<MouseEnterEvent>(_ => PlayerInputManager.current.OnDefaultUse -= Close);
}
public void Start()
{
Close();
}
public void Prepare()
{
Close();
PlayerInputManager.current.OnDefaultUse += Close;
PlayerInputManager.current.OnContextUse += Close;
var clickedPosition = RuntimePanelUtils.ScreenToPanel(_optionsElement.panel, Mouse.current.position.ReadValue());
_optionsElement.style.bottom = new StyleLength(clickedPosition.y);
_optionsElement.style.left = new StyleLength(clickedPosition.x);
}
public void AddBeforeClick(Action action)
{
BeforeClick += action;
}
public void AddOption(string text, Action action)
{
var option = new Button();
option.AddToClassList("option");
option.text = text;
option.clicked += () => BeforeClick?.Invoke();
option.clicked += Close;
option.clicked += () => action?.Invoke();
_optionsElement.Add(option);
_options.Add(option);
}
public void Open()
{
if (_options.Count == 0) return;
_optionsElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.Flex);
}
public void Close()
{
BeforeClick = default;
PlayerInputManager.current.OnDefaultUse -= Close;
PlayerInputManager.current.OnContextUse -= Close;
_optionsElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);
_optionsElement.Clear();
_options.Clear();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3c1c37804ab84f24da7108ad463a03a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,13 @@
<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">
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/ContextMenuStyle.uss?fileID=7433441132597879392&amp;guid=74bcb1e0fd0935d4e9843d90c5d5dfc1&amp;type=3#ContextMenuStyle" />
<ui:VisualElement name="options">
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3c4fcd94658687c49a986819a72adf8e
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,19 @@
#options {
width: 200px;
position: absolute;
background-color: rgba(0, 0, 0, 0.48);
padding-left: 2px;
padding-right: 2px;
padding-top: 2px;
padding-bottom: 2px;
}
#options > .option {
font-size: 10px;
height: 0;
width: auto;
margin-left: 1px;
margin-right: 1px;
margin-top: 1px;
margin-bottom: 1px;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74bcb1e0fd0935d4e9843d90c5d5dfc1
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,58 @@
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.UserInterface.Game.Util;
using VOID.ScriptableObjects.Abilities;
namespace VOID.UserInterface.Game
{
public class DraggingUI : MonoBehaviour
{
public static DraggingUI current {get; private set;}
// Private properties
private VisualElement _slotElement;
private SlotUI _slot;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
_slotElement = templateElement.Q("slot");
_slot = new SlotUI();
_slot.Init(_slotElement, SlotType.None, -1);
Hide();
// SAFEGUARD - dragging should never be clickable, if somehow UI was built weird then this should fix it
templateElement.Query<VisualElement>().ForEach(element => element.pickingMode = PickingMode.Ignore);
}
private void Update()
{
var pos = RuntimePanelUtils.ScreenToPanel(_slotElement.panel, Mouse.current.position.ReadValue());
_slotElement.style.bottom = new StyleLength(pos.y);
_slotElement.style.left = new StyleLength(pos.x);
}
public void Set(ItemObject item) => _slot.Set(item);
public void Set(BasicAbility ability) => _slot.Set(ability);
public void Show()
{
_slotElement.style.display = DisplayStyle.Flex;
enabled = true;
}
public void Hide()
{
_slotElement.style.display = DisplayStyle.None;
enabled = false;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 16cd7f1c25d14c419584499d0dcd9498
timeCreated: 1690221347
@@ -0,0 +1,8 @@
<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="Slot" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Slot.uxml?fileID=9197481963319205126&amp;guid=5a74e2b56bbc27c4ab7a5d0c1de93f00&amp;type=3#Slot" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/SlotOuter.uss?fileID=7433441132597879392&amp;guid=760aa0b2431a11e46a81be0018d225b1&amp;type=3#SlotOuter" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/DraggingUIStyle.uss?fileID=7433441132597879392&amp;guid=05a5331e8aada9e45956156967769ef3&amp;type=3#DraggingUIStyle" />
<ui:Instance template="Slot" name="slot" class="slot slot-small" />
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 31f14c42b1ad98a48836a4505066c7a3
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,3 @@
#slot {
position: absolute;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 05a5331e8aada9e45956156967769ef3
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,19 @@
#options {
width: 200px;
position: absolute;
background-color: rgba(0, 0, 0, 0.48);
padding-left: 2px;
padding-right: 2px;
padding-top: 2px;
padding-bottom: 2px;
}
#options > .option {
font-size: 10px;
height: 0;
width: auto;
margin-left: 1px;
margin-right: 1px;
margin-top: 1px;
margin-bottom: 1px;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 860e0bb027d75bb42ba1b617011ab01b
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
using PlayerInputManager = VOID.Generic.Player.Input.PlayerInputManager;
namespace VOID.UserInterface.Game
{
public class DropdownUI : MonoBehaviour
{
public static DropdownUI current {get; private set;}
// Visual Elements
private VisualElement _optionsElement;
private readonly List<Button> _options = new();
private event Action BeforeClick = () => {};
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
_optionsElement = templateElement.Q("options");
_optionsElement.RegisterCallback<MouseLeaveEvent>(_ => PlayerInputManager.current.OnDefaultUse += Close);
_optionsElement.RegisterCallback<MouseEnterEvent>(_ => PlayerInputManager.current.OnDefaultUse -= Close);
}
public void Start()
{
Close();
}
public void Prepare(Vector2 position)
{
Close();
PlayerInputManager.current.OnDefaultUse += Close;
PlayerInputManager.current.OnContextUse += Close;
_optionsElement.style.top = new StyleLength(position.y);
_optionsElement.style.left = new StyleLength(position.x);
}
public void AddBeforeClick(Action action)
{
BeforeClick += action;
}
public void AddOption(string text, Action action)
{
var option = new Button();
option.AddToClassList("option");
option.text = text;
option.clicked += BeforeClick.Invoke;
option.clicked += Close;
option.clicked += action.Invoke;
_optionsElement.Add(option);
_options.Add(option);
}
public void Open()
{
if (_options.Count == 0) return;
_optionsElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.Flex);
}
public void Close()
{
BeforeClick = () => {};
PlayerInputManager.current.OnDefaultUse -= Close;
PlayerInputManager.current.OnContextUse -= Close;
_optionsElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);
_optionsElement.Clear();
_options.Clear();
}
private void OnClickedOutside(InputAction.CallbackContext context)
{
Close();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a2bcfeb76513ee84ea47cc44eb6c424c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,13 @@
<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">
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/ContextMenuStyle.uss?fileID=7433441132597879392&amp;guid=74bcb1e0fd0935d4e9843d90c5d5dfc1&amp;type=3#ContextMenuStyle" />
<ui:VisualElement name="options">
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
<ui:Button text="ExampleButton" class="option" />
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: de05bfffc1bcd1c45923d4fc4c021168
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,361 @@
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
using VOID.Generic.Player.Input;
using VOID.UserInterface.Game.Interfaces;
using VOID.UserInterface.Game.Util;
namespace VOID.UserInterface.Game
{
public class EquipmentUI : MonoBehaviour, IHasWindow
{
public static EquipmentUI current {get; private set;}
// WindowUI
public WindowUI windowUI { get; private set; }
// Visual Elements
private VisualElement _rootElement;
private Button[] _tabElements;
private VisualElement[] _tabContentElements;
// Visual Elements - Attributes values
private Label _strengthLabel;
private Label _dexterityLabel;
private Label _intelligenceLabel;
private Label _constitutionLabel;
private Label _speedLabel;
private Label _perceptionLabel;
private Label _damageLabel;
private Label _accuracyLabel;
private Label _dodgeLabel;
private Label _criticalChanceLabel;
private Label _criticalMultiplierLabel;
private Label _sightLabel;
private Label _hearLabel;
private Label _moveLabel;
private Label _initiativeLabel;
private Label _carryCapacityLabel;
// Visual Elements - Resources values
private Label _healthLabel;
private Label _actionPointsLabel;
private Label _movePointsLabel;
// Visual Elements - Equipment Slots
private readonly SlotUI _mainHandSlot = new();
private readonly SlotUI _offHandSlot = new();
private readonly SlotUI _helmetSlot = new();
private readonly SlotUI _armorSlot = new();
private readonly SlotUI _beltSlot = new();
private readonly SlotUI _pantsSlot = new();
private readonly SlotUI _bootsSlot = new();
private readonly SlotUI _necklaceSlot = new();
private readonly SlotUI _glovesSlot = new();
private readonly SlotUI _ringOneSlot = new();
private readonly SlotUI _ringTwoSlot = new();
// References
private UnitObject _unit;
private UnitObjectEquipment _equipment;
private PlayerController _playerController;
private ShortcutsInputManager _shortcutsInputManager;
// String formattings
private const string F0 = "F0";
private const string F1 = "F1";
private const string F2 = "F2";
private const string P0 = "P0";
private const string P1 = "P1";
private const string P2 = "P2";
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
// Get all VisualElements
_rootElement = templateElement.Q("root-equipment");
windowUI = gameObject.GetComponent<WindowUI>();
// Get all VisualElements - Attributes
_strengthLabel = _rootElement.Q<Label>("strength");
_dexterityLabel = _rootElement.Q<Label>("dexterity");
_intelligenceLabel = _rootElement.Q<Label>("intelligence");
_constitutionLabel = _rootElement.Q<Label>("constitution");
_speedLabel = _rootElement.Q<Label>("speed");
_perceptionLabel = _rootElement.Q<Label>("perception");
_damageLabel = _rootElement.Q<Label>("damage");
_accuracyLabel = _rootElement.Q<Label>("accuracy");
_dodgeLabel = _rootElement.Q<Label>("dodge");
_criticalChanceLabel = _rootElement.Q<Label>("critical-damage-chance");
_criticalMultiplierLabel = _rootElement.Q<Label>("critical-damage-multiplier");
_sightLabel = _rootElement.Q<Label>("sight");
_hearLabel = _rootElement.Q<Label>("hear");
_moveLabel = _rootElement.Q<Label>("move");
_initiativeLabel = _rootElement.Q<Label>("initiative");
// Get all VisualElements - Resources
_healthLabel = _rootElement.Q<Label>("health");
_actionPointsLabel = _rootElement.Q<Label>("action-points");
_movePointsLabel = _rootElement.Q<Label>("move-points");
// Get all VisualElements - Items
_mainHandSlot.Init(_rootElement.Q("item-main-hand"), SlotType.EquipmentSlot, (int)EquipmentSlotType.MainHand);
_offHandSlot.Init(_rootElement.Q("item-off-hand"), SlotType.EquipmentSlot, (int)EquipmentSlotType.OffHand);
_helmetSlot.Init(_rootElement.Q("item-helmet"), SlotType.EquipmentSlot, (int)EquipmentSlotType.Helmet);
_armorSlot.Init(_rootElement.Q("item-armor"), SlotType.EquipmentSlot, (int)EquipmentSlotType.Armor);
_beltSlot.Init(_rootElement.Q("item-belt"), SlotType.EquipmentSlot, (int)EquipmentSlotType.Belt);
_pantsSlot.Init(_rootElement.Q("item-pants"), SlotType.EquipmentSlot, (int)EquipmentSlotType.Pants);
_bootsSlot.Init(_rootElement.Q("item-boots"), SlotType.EquipmentSlot, (int)EquipmentSlotType.Boots);
_necklaceSlot.Init(_rootElement.Q("item-necklace"), SlotType.EquipmentSlot, (int)EquipmentSlotType.Necklace);
_glovesSlot.Init(_rootElement.Q("item-gloves"), SlotType.EquipmentSlot, (int)EquipmentSlotType.Gloves);
_ringOneSlot.Init(_rootElement.Q("item-ring-one"), SlotType.EquipmentSlot, (int)EquipmentSlotType.RingOne);
_ringTwoSlot.Init(_rootElement.Q("item-ring-two"), SlotType.EquipmentSlot, (int)EquipmentSlotType.RingTwo);
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
}
private void Start()
{
_playerController = PlayerController.current;
_shortcutsInputManager = ShortcutsInputManager.current;
// Toggle show/hide when pressing shortcut for backpack
_shortcutsInputManager.equipment.performed += _ => windowUI.Toggle();
windowUI.OnOpen += OnOpen;
windowUI.OnClose += OnClose;
windowUI.SetTitle("Equipment");
// Hidden by default
windowUI.Close();
}
public void Toggle() => windowUI.Toggle();
public void Open() => windowUI.Open();
public void Close() => windowUI.Close();
private void OnOpen()
{
// References to active unit
_unit = PlayerController.current.activeUnit;
_equipment = _unit.unitEquipment;
// Refresh UI when we change active unit
_playerController.OnActiveUnitChange += OnActiveUnitChange;
// Listen to all changes in equipment and update UI
_unit.unitEvents.onEquipmentEquip.AddListener(OnEquip);
_unit.unitEvents.onEquipmentUnEquip.AddListener(OnUnEquip);
_unit.unitEvents.onMainAttributeChange.AddListener(OnMainAttributeChange);
_unit.unitEvents.onSubAttributeChange.AddListener(OnSubAttributeChange);
_unit.unitEvents.onMaxResourceChange.AddListener(OnUnitResourceChange);
_unit.unitEvents.onCurrentResourceChange.AddListener(OnUnitResourceChange);
_unit.basicEvents.onMaxResourceChange.AddListener(OnBasicResourceChange);
_unit.basicEvents.onCurrentResourceChange.AddListener(OnBasicResourceChange);
// Update all values when opening
UpdateAll();
}
private void OnClose()
{
// Stop listening
_playerController.OnActiveUnitChange -= OnActiveUnitChange;
// Backpack closed, no need to listen for backpack changes
if (_unit)
{
_unit.unitEvents.onEquipmentEquip.RemoveListener(OnEquip);
_unit.unitEvents.onEquipmentUnEquip.RemoveListener(OnUnEquip);
_unit.unitEvents.onMainAttributeChange.RemoveListener(OnMainAttributeChange);
_unit.unitEvents.onSubAttributeChange.RemoveListener(OnSubAttributeChange);
_unit.unitEvents.onMaxResourceChange.RemoveListener(OnUnitResourceChange);
_unit.unitEvents.onCurrentResourceChange.RemoveListener(OnUnitResourceChange);
_unit.basicEvents.onMaxResourceChange.RemoveListener(OnBasicResourceChange);
_unit.basicEvents.onCurrentResourceChange.RemoveListener(OnBasicResourceChange);
}
// Clear variables
_unit = null;
_equipment = null;
}
private void OnActiveUnitChange(UnitObject unitObject)
{
windowUI.Close();
windowUI.Open();
}
private void OnMainAttributeChange(MainAttributeChangeEvent mainAttributeChangeEvent)
{
switch (mainAttributeChangeEvent.type)
{
case MainAttributeType.Strength: OnStrengthChange(); break;
case MainAttributeType.Dexterity: OnDexterityChange(); break;
case MainAttributeType.Intelligence: OnIntelligenceChange(); break;
case MainAttributeType.Constitution: OnConstitutionChange(); break;
case MainAttributeType.Speed: OnSpeedChange(); break;
case MainAttributeType.Perception: OnPerceptionChange(); break;
}
}
private void OnSubAttributeChange(SubAttributeChangeEvent subAttributeChangeEvent)
{
switch (subAttributeChangeEvent.type)
{
case SubAttributeType.DamageMin:
case SubAttributeType.DamageMax: OnDamageChange(); break;
case SubAttributeType.CriticalDamageChance: OnCriticalDamageChanceChange(); break;
case SubAttributeType.CriticalDamageMultiplier: OnCriticalDamageMultiplierChange(); break;
case SubAttributeType.Accuracy: OnAccuracyChange(); break;
case SubAttributeType.Dodge: OnDodgeChange(); break;
case SubAttributeType.Sight: OnSightChange(); break;
case SubAttributeType.Hear: OnHearChange(); break;
case SubAttributeType.Move: OnMoveChange(); break;
case SubAttributeType.Initiative: OnInitiativeChange(); break;
}
}
private void OnBasicResourceChange(BasicResourceChangeEvent basicResourceChangeEvent)
{
switch (basicResourceChangeEvent.type)
{
case BasicResourceType.Health: OnHealthChange(); break;
}
}
private void OnUnitResourceChange(UnitResourceChangeEvent unitResourceChangeEvent)
{
switch (unitResourceChangeEvent.type)
{
case UnitResourceType.MovePoints: OnMovePointsChange(); break;
case UnitResourceType.ActionPoints: OnActionPointsChange(); break;
}
}
private void OnEquip(EquipmentEquipEvent equipmentEquipEvent)
{
switch (equipmentEquipEvent.equipmentSlot)
{
case EquipmentSlotType.MainHand: OnMainHandChange(); break;
case EquipmentSlotType.OffHand: OnOffHandChange(); break;
case EquipmentSlotType.Helmet: OnHelmetChange(); break;
case EquipmentSlotType.Armor: OnArmorChange(); break;
case EquipmentSlotType.Pants: OnPantsChange(); break;
case EquipmentSlotType.Belt: OnBeltChange(); break;
case EquipmentSlotType.Boots: OnBootsChange(); break;
case EquipmentSlotType.Gloves: OnGlovesChange(); break;
case EquipmentSlotType.Necklace: OnNecklaceChange(); break;
case EquipmentSlotType.RingOne: OnRingOneChange(); break;
case EquipmentSlotType.RingTwo: OnRingTwoChange(); break;
default: Debug.LogWarning("Unrecognized EquipmentSlot: " + equipmentEquipEvent.equipmentSlot); return;
}
}
private void OnUnEquip(EquipmentUnEquipEvent equipmentUnEquipEvent)
{
switch (equipmentUnEquipEvent.equipmentSlot)
{
case EquipmentSlotType.MainHand: OnMainHandChange(); break;
case EquipmentSlotType.OffHand: OnOffHandChange(); break;
case EquipmentSlotType.Helmet: OnHelmetChange(); break;
case EquipmentSlotType.Armor: OnArmorChange(); break;
case EquipmentSlotType.Pants: OnPantsChange(); break;
case EquipmentSlotType.Belt: OnBeltChange(); break;
case EquipmentSlotType.Boots: OnBootsChange(); break;
case EquipmentSlotType.Gloves: OnGlovesChange(); break;
case EquipmentSlotType.Necklace: OnNecklaceChange(); break;
case EquipmentSlotType.RingOne: OnRingOneChange(); break;
case EquipmentSlotType.RingTwo: OnRingTwoChange(); break;
default: Debug.LogWarning("Unrecognized EquipmentSlot: " + equipmentUnEquipEvent.equipmentSlot); return;
}
}
private void UpdateAll()
{
OnStrengthChange();
OnDexterityChange();
OnIntelligenceChange();
OnConstitutionChange();
OnSpeedChange();
OnPerceptionChange();
OnDamageChange();
OnAccuracyChange();
OnDodgeChange();
OnCriticalDamageChanceChange();
OnCriticalDamageMultiplierChange();
OnSightChange();
OnHearChange();
OnMoveChange();
OnInitiativeChange();
OnHealthChange();
OnActionPointsChange();
OnMovePointsChange();
OnMainHandChange();
OnOffHandChange();
OnHelmetChange();
OnArmorChange();
OnPantsChange();
OnBeltChange();
OnBootsChange();
OnGlovesChange();
OnNecklaceChange();
OnRingOneChange();
OnRingTwoChange();
}
// On Change - MainAttributes
private void OnStrengthChange() => _strengthLabel.text = $"{_unit.unitData.mainAttributes.strength.ToString(F0)}";
private void OnDexterityChange() => _dexterityLabel.text = $"{_unit.unitData.mainAttributes.dexterity.ToString(F0)}";
private void OnIntelligenceChange() => _intelligenceLabel.text = $"{_unit.unitData.mainAttributes.intelligence.ToString(F0)}";
private void OnConstitutionChange() => _constitutionLabel.text = $"{_unit.unitData.mainAttributes.constitution.ToString(F0)}";
private void OnSpeedChange() => _speedLabel.text = $"{_unit.unitData.mainAttributes.speed.ToString(F0)}";
private void OnPerceptionChange() => _perceptionLabel.text = $"{_unit.unitData.mainAttributes.perception.ToString(F0)}";
// On Change - SubAttributes
private void OnDamageChange() => _damageLabel.text = $"{_unit.unitData.subAttributes.damageMin.ToString(F0)} - {_unit.unitData.subAttributes.damageMax.ToString(F0)}";
private void OnAccuracyChange() => _accuracyLabel.text = $"{_unit.unitData.subAttributes.accuracy.ToString(P0)}";
private void OnDodgeChange() => _dodgeLabel.text = $"{_unit.unitData.subAttributes.dodge.ToString(P0)}";
private void OnCriticalDamageChanceChange() => _criticalChanceLabel.text = $"{_unit.unitData.subAttributes.criticalDamageChance.ToString(P0)}";
private void OnCriticalDamageMultiplierChange() => _criticalMultiplierLabel.text = $"{_unit.unitData.subAttributes.criticalDamageMultiplier.ToString(P0)}";
private void OnSightChange() => _sightLabel.text = $"{_unit.unitData.subAttributes.sight.ToString(F0)}";
private void OnHearChange() => _hearLabel.text = $"{_unit.unitData.subAttributes.hear.ToString(F0)}";
private void OnMoveChange() => _moveLabel.text = $"{_unit.unitData.subAttributes.move.ToString(F1)}m";
private void OnInitiativeChange() => _initiativeLabel.text = $"{_unit.unitData.subAttributes.initiative.ToString(F0)}";
// On Change - Resources
private void OnHealthChange() => _healthLabel.text =
$"{_unit.basicData.currentResources.health.ToString(F0)} / {_unit.basicData.maxResources.health.ToString(F0)}";
private void OnActionPointsChange() => _actionPointsLabel.text =
$"{_unit.unitData.currentResources.actionPoints.ToString(F0)} / {_unit.unitData.maxResources.actionPoints.ToString(F0)}";
private void OnMovePointsChange() => _movePointsLabel.text =
$"{_unit.unitData.currentResources.movePoints.ToString(F1)} / {_unit.unitData.maxResources.movePoints.ToString(F1)}";
// On Change - Items
private void OnMainHandChange() => _mainHandSlot.Set(_equipment.GetEquipped(EquipmentSlotType.MainHand));
private void OnOffHandChange() => _offHandSlot.Set(_equipment.GetEquipped(EquipmentSlotType.OffHand));
private void OnHelmetChange() => _helmetSlot.Set(_equipment.GetEquipped(EquipmentSlotType.Helmet));
private void OnArmorChange() => _armorSlot.Set(_equipment.GetEquipped(EquipmentSlotType.Armor));
private void OnPantsChange() => _pantsSlot.Set(_equipment.GetEquipped(EquipmentSlotType.Pants));
private void OnBeltChange() => _beltSlot.Set(_equipment.GetEquipped(EquipmentSlotType.Belt));
private void OnBootsChange() => _bootsSlot.Set(_equipment.GetEquipped(EquipmentSlotType.Boots));
private void OnGlovesChange() => _glovesSlot.Set(_equipment.GetEquipped(EquipmentSlotType.Gloves));
private void OnNecklaceChange() => _necklaceSlot.Set(_equipment.GetEquipped(EquipmentSlotType.Necklace));
private void OnRingOneChange() => _ringOneSlot.Set(_equipment.GetEquipped(EquipmentSlotType.RingOne));
private void OnRingTwoChange() => _ringTwoSlot.Set(_equipment.GetEquipped(EquipmentSlotType.RingTwo));
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: eb29e16065f54ceca671466c31377325
timeCreated: 1672841112
@@ -0,0 +1,133 @@
<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="Background" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Window.uxml?fileID=9197481963319205126&amp;guid=04235ec1d1b764e448e2524000a1b87a&amp;type=3#Window" />
<ui:Template name="Slot" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/Slot.uxml?fileID=9197481963319205126&amp;guid=5a74e2b56bbc27c4ab7a5d0c1de93f00&amp;type=3#Slot" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/WindowOuter.uss?fileID=7433441132597879392&amp;guid=80611877e61dcf346bf43cfc4ebd3394&amp;type=3#WindowOuter" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/Utility/SlotOuter.uss?fileID=7433441132597879392&amp;guid=760aa0b2431a11e46a81be0018d225b1&amp;type=3#SlotOuter" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/EquipmentUIStyle.uss?fileID=7433441132597879392&amp;guid=6a3d633979e13764eb452eb445628b6e&amp;type=3#EquipmentUIStyle" />
<ui:VisualElement name="root-equipment">
<ui:Instance template="Background" name="window" style="position: absolute; width: 100%; height: 100%;">
<AttributeOverrides element-name="Title" text="EQUIPMENT" />
</ui:Instance>
<ui:VisualElement name="left-side">
<ui:Label text="Attributes" display-tooltip-when-elided="true" class="title" style="-unity-text-align: upper-center; background-color: rgba(0, 0, 0, 0.39); color: rgb(187, 187, 187);" />
<ui:VisualElement name="tabs">
<ui:Button class="tab" />
<ui:Button class="tab" />
<ui:Button class="tab" />
<ui:Button class="tab" />
<ui:Button class="tab" />
</ui:VisualElement>
<ui:VisualElement name="contents">
<ui:VisualElement name="attributes" class="content">
<ui:VisualElement class="attribute">
<ui:Label text="Strength" class="attribute-label" />
<ui:Label text="100" name="strength" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Dexterity" class="attribute-label" />
<ui:Label text="100" name="dexterity" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Intelligence" class="attribute-label" />
<ui:Label text="100" name="intelligence" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Constitution" class="attribute-label" />
<ui:Label text="100" name="constitution" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Speed" class="attribute-label" />
<ui:Label text="100" name="speed" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Perception" class="attribute-label" />
<ui:Label text="100" name="perception" class="attribute-value" />
</ui:VisualElement>
<ui:Label class="horizontal-line" />
<ui:VisualElement class="attribute">
<ui:Label text="Damage" class="attribute-label" />
<ui:Label text="50 - 125" name="damage" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Accuracy" class="attribute-label" />
<ui:Label text="60%" name="accuracy" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Dodge" class="attribute-label" />
<ui:Label text="5%" name="dodge" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Critical Damage Chance" class="attribute-label" />
<ui:Label text="75%" name="critical-damage-chance" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Critical Damage Multiplier" class="attribute-label" />
<ui:Label text="225%" name="critical-damage-multiplier" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Sight" class="attribute-label" />
<ui:Label text="5" name="sight" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Hear" class="attribute-label" />
<ui:Label text="5" name="hear" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Move" class="attribute-label" />
<ui:Label text="1 meter" name="move" class="attribute-value" />
</ui:VisualElement>
<ui:VisualElement class="attribute">
<ui:Label text="Initiative" class="attribute-label" />
<ui:Label text="0" name="initiative" class="attribute-value" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement class="content" />
<ui:VisualElement class="content" />
<ui:VisualElement class="content" />
<ui:VisualElement class="content" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="right-side">
<ui:VisualElement name="items">
<ui:Label text="Items" class="title" />
<ui:VisualElement name="items-top">
<ui:Instance template="Slot" name="item-helmet" class="slot-big slot" />
</ui:VisualElement>
<ui:VisualElement name="items-left">
<ui:Instance template="Slot" name="item-armor" class="slot-big slot" />
<ui:Instance template="Slot" name="item-belt" class="slot-big slot" />
<ui:Instance template="Slot" name="item-pants" class="slot-big slot" />
<ui:Instance template="Slot" name="item-boots" class="slot-big slot" />
</ui:VisualElement>
<ui:VisualElement name="items-right">
<ui:Instance template="Slot" name="item-necklace" class="slot-big slot" />
<ui:Instance template="Slot" name="item-gloves" class="slot-big slot" />
<ui:Instance template="Slot" name="item-ring-one" class="slot-big slot" />
<ui:Instance template="Slot" name="item-ring-two" class="slot-big slot" />
</ui:VisualElement>
<ui:VisualElement name="items-bottom">
<ui:Instance template="Slot" name="item-main-hand" class="slot-big slot" />
<ui:Instance template="Slot" name="item-off-hand" class="slot-big slot" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="resources" style="flex-direction: column; padding-bottom: 10px;">
<ui:Label text="Resources" class="title" />
<ui:VisualElement class="resource">
<ui:Label text="Health" class="resource-label" />
<ui:Label text="100 / 100" name="health" class="resource-value" />
</ui:VisualElement>
<ui:Label class="horizontal-line" />
<ui:VisualElement class="resource">
<ui:Label text="Action Points" class="resource-label" />
<ui:Label text="100 / 100" name="action-points" class="resource-value" />
</ui:VisualElement>
<ui:VisualElement class="resource">
<ui:Label text="Move Points" class="resource-label" />
<ui:Label text="100 / 100" name="move-points" class="resource-value" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e90816ace4bcffe4284734fc0279f1a2
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,220 @@
.title {
-unity-text-align: upper-center;
background-color: rgba(0, 0, 0, 0.39);
color: rgb(187, 187, 187);
width: 100%;
}
.horizontal-line {
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
border-left-color: rgb(0, 0, 0);
border-right-color: rgb(0, 0, 0);
border-top-color: rgb(0, 0, 0);
border-bottom-color: rgb(0, 0, 0);
border-bottom-width: 1px;
height: 1px;
margin-top: 3px;
margin-bottom: 3px;
width: 100%;
}
#items .slot {
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
margin-bottom: 2px;
}
#items #item-helmet #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_helm.png?fileID=2800000&guid=c5e900b395fb5c646a19b329d1e32f8a&type=3#icon_bg_helm');
}
#items #item-armor #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_chest.png?fileID=2800000&guid=0997b222910af594bafac8b6e15211f0&type=3#icon_bg_chest');
}
#items #item-belt #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_belt.png?fileID=2800000&guid=af0fe96d0b08e954cbf6fce7efeba021&type=3#icon_bg_belt');
}
#items #item-pants #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_pants.png?fileID=2800000&guid=2f8ed45cd5b08db4db909781fbab764a&type=3#icon_bg_pants');
}
#items #item-boots #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_boots.png?fileID=2800000&guid=30204ce833fe8584ea87ba7d265559b3&type=3#icon_bg_boots');
}
#items #item-necklace #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_neck.png?fileID=2800000&guid=f66f85c68d3e27143975f1e36a5a525b&type=3#icon_bg_neck');
}
#items #item-gloves #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_gloves.png?fileID=2800000&guid=efb38f7b9eec13c4fbade08566e92256&type=3#icon_bg_gloves');
}
#items #item-ring-one #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_ring.png?fileID=2800000&guid=fe777b27404440543b59e3f3d7844913&type=3#icon_bg_ring');
}
#items #item-ring-two #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_ring.png?fileID=2800000&guid=fe777b27404440543b59e3f3d7844913&type=3#icon_bg_ring');
}
#items #item-main-hand #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_dagger.png?fileID=2800000&guid=42a79ae989d4e0748859fb1120db8cca&type=3#icon_bg_dagger');
}
#items #item-off-hand #icon {
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/UI_icons/equipment/icon_bg_dagger.png?fileID=2800000&guid=42a79ae989d4e0748859fb1120db8cca&type=3#icon_bg_dagger');
}
#root-equipment {
position: absolute;
left: 10px;
top: 10px;
width: 700px;
height: 800px;
flex-direction: row;
}
#root-equipment > #left-side {
flex-basis: 50%;
margin-top: 40px;
padding-left: 15px;
padding-right: 5px;
padding-top: 5px;
padding-bottom: 15px;
}
#root-equipment > #right-side {
flex-basis: 50%;
margin-top: 40px;
padding-left: 5px;
padding-right: 15px;
padding-top: 5px;
padding-bottom: 15px;
}
#tabs {
flex-direction: row;
justify-content: center;
margin-top: 5px;
}
#tabs > .tab {
width: 60px;
height: 60px;
margin-left: 2px;
margin-right: 2px;
margin-top: 0;
margin-bottom: 0;
background-color: rgba(188, 188, 188, 0.39);
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
border-left-color: rgb(0, 0, 0);
border-right-color: rgb(0, 0, 0);
border-top-color: rgb(0, 0, 0);
border-bottom-color: rgb(0, 0, 0);
}
#contents {
flex-grow: 1;
margin-top: 0;
}
#contents > .content {
flex-wrap: wrap;
}
#attributes {
}
#attributes > .attribute {
flex-direction: row;
}
#attributes > .attribute > .attribute-label {
flex-grow: 1;
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
color: rgb(187, 187, 187);
}
#attributes > .attribute > .attribute-value {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
color: rgb(187, 187, 187);
}
#items {
flex-direction: row;
flex-grow: 1;
align-items: flex-start;
flex-wrap: wrap;
justify-content: space-between;
}
#items > #items-top {
flex-basis: 100%;
flex-direction: row;
justify-content: center;
}
#items > #items-left {
}
#items > #items-right {
}
#items > #items-bottom {
flex-basis: 100%;
flex-direction: row;
justify-content: center;
}
#resources > .resource {
flex-direction: row;
}
#resources > .resource > .resource-label {
flex-grow: 1;
margin-left: 5px;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
color: rgb(187, 187, 187);
}
#resources > .resource > .resource-value {
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
margin-left: 0;
margin-right: 5px;
margin-top: 0;
margin-bottom: 0;
color: rgb(187, 187, 187);
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a3d633979e13764eb452eb445628b6e
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 731d3c406aa0ac0498a3302b82b1ab92
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
using System;
using UnityEngine.UIElements;
namespace VOID.UserInterface.Game.GameLog
{
[Serializable]
public class GameLogMessageUI
{
private VisualElement _parentElement;
private VisualElement _templateElement;
private Label _timeLabel;
private Label _contentLabel;
public void InitNew(VisualElement parentWrapperElement, string message)
{
_parentElement = parentWrapperElement;
_templateElement = GameLogUI.current.messageTemplate.CloneTree().contentContainer;
_parentElement.Add(_templateElement);
_timeLabel = _templateElement.Q<Label>(className: "time");
_timeLabel.text = "[" + DateTime.Now.ToString("HH:mm:ss") + "]";
_contentLabel = _templateElement.Q<Label>(className: "content");
_contentLabel.text = message;
}
public void Destroy()
{
_parentElement.Remove(_templateElement);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b47d387d194747409fe3eb3e285bfcef
timeCreated: 1698946541
@@ -0,0 +1,7 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" editor-extension-mode="False">
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/GameLog/GameLogMessageUIStyle.uss?fileID=7433441132597879392&amp;guid=6ff0b7b338887ab498883e9cfff6cb62&amp;type=3#GameLogMessageUIStyle" />
<ui:VisualElement name="root-game-log-message" class="message">
<ui:Label tabindex="-1" text="[21:00:37]" enable-rich-text="false" class="time" />
<ui:Label tabindex="-1" text="&lt;u&gt;DUMMY&lt;/u&gt; dealt &lt;u&gt;5 fire&lt;/u&gt; dmg to &lt;u&gt;TARGET&lt;/u&gt; LOREM IPSUMIPSUM 123 LOREM IPSUM 456 LOREM IPSUM 789" parse-escape-sequences="true" display-tooltip-when-elided="true" class="content" />
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 648cfbe70d29b664a946fe7b43eebb89
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,38 @@
#root-game-log-message {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-top: 2px;
padding-bottom: 2px;
flex-direction: row;
align-items: stretch;
flex-wrap: wrap;
align-self: stretch;
}
#root-game-log-message > .time {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
padding-right: 3px;
padding-top: 0;
padding-bottom: 0;
flex-wrap: nowrap;
}
#root-game-log-message > .content {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
padding-right: 3px;
padding-top: 0;
padding-bottom: 0;
flex-grow: 1;
flex-shrink: 1;
white-space: normal;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ff0b7b338887ab498883e9cfff6cb62
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,159 @@
using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Objects.Abstract.Events;
using VOID.Generic.Objects.Item.Events;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions.Exceptions;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Objects.Usable.Events;
using VOID.Generic.Objects.Wearable.Events;
using VOID.Generic.Player;
namespace VOID.UserInterface.Game.GameLog
{
public class GameLogUI : MonoBehaviour
{
public static GameLogUI current { get; private set; }
// Configuration
[SerializeField, MinValue(10)] private int _messageLimit = 100;
[SerializeField] private string SENDER_PREFIX = "<b>{0}:<b> ";
[SerializeField] private string STATUS_START_MESSAGE = "Got status <u>{0}</u> for <u>{1} turns</u>.";
[SerializeField] private string STATUS_END_MESSAGE = "Status <u>{0}</u> ended.";
[SerializeField] private string DEATH_MESSAGE = "Died!";
[SerializeField] private string DAMAGED_MESSAGE = "Received <u>{0} {1}</u> damage from <u>{2}</u>.";
[SerializeField] private string DAMAGE_MESSAGE = "Dealt <u>{0} {1}</u> damage to <u>{2}</u>.";
[SerializeField] private string ABILITY_CAST_MESSAGE = "Casted <u>{0}</u>.";
[SerializeField] private string TAKE_MESSAGE = "Took <u>{0}</u>.";
[SerializeField] private string DROP_MESSAGE = "Dropped <u>{0}</u>.";
[SerializeField] private string EQUIP_MESSAGE = "Equipped <u>{0}</u>.";
[SerializeField] private string UNEQUIP_MESSAGE = "Unequipped <u>{0}</u>.";
[SerializeField] private string USE_MESSAGE = "Used <u>{0}</u>.";
[SerializeField] private string ACTION_ERROR_MESSAGE = "Action prevented: <u>{0}</u>.";
// Message template
public VisualTreeAsset messageTemplate => _messageTemplate;
[SerializeField, Required] private VisualTreeAsset _messageTemplate;
// Visual Elements
private VisualElement _messageWrapper;
private Scroller _scroller;
private readonly List<GameLogMessageUI> _messages = new();
// Units which we listen to
private UnitObject _mainUnit;
private UnitObject _subUnit;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
_messageWrapper = templateElement.Q("message-wrapper");
_messageWrapper.Clear();
}
private void Start()
{
PlayerController.current.OnMainUnitChange += OnMainUnitChange;
PlayerController.current.OnSubUnitChange += OnSubUnitChange;
}
private void OnMainUnitChange(UnitObject unit)
{
if (_mainUnit) StopListenFor(_mainUnit);
_mainUnit = unit;
if (unit) ListenFor(unit);
}
private void OnSubUnitChange(UnitObject unit)
{
if (_subUnit) StopListenFor(_subUnit);
_subUnit = unit;
if (unit) ListenFor(unit);
}
private void ListenFor(UnitObject unit)
{
unit.basicEvents.onStatusStart.AddListener(OnStatusStart);
unit.basicEvents.onStatusEnd.AddListener(OnStatusEnd);
unit.basicEvents.onDeathAfter.AddListener(OnDeathAfter);
unit.basicEvents.onDamagedAfter.AddListener(OnDamagedAfter);
unit.unitEvents.onDamageAfter.AddListener(OnDamageAfter);
unit.unitEvents.onStartAbilityAfter.AddListener(OnAbilityCastAfter);
unit.unitEvents.onTakeAfter.AddListener(OnTakeAfter);
unit.unitEvents.onDropAfter.AddListener(OnDropAfter);
unit.unitEvents.onEquipAfter.AddListener(OnEquipAfter);
unit.unitEvents.onUnEquipAfter.AddListener(OnUnEquipAfter);
unit.unitEvents.onUseAfter.AddListener(OnUseAfter);
unit.unitEvents.onActionError.AddListener(OnActionError);
}
private void StopListenFor(UnitObject unit)
{
unit.basicEvents.onStatusStart.RemoveListener(OnStatusStart);
unit.basicEvents.onStatusEnd.RemoveListener(OnStatusEnd);
unit.basicEvents.onDeathAfter.RemoveListener(OnDeathAfter);
unit.basicEvents.onDamagedAfter.RemoveListener(OnDamagedAfter);
unit.unitEvents.onDamageAfter.RemoveListener(OnDamageAfter);
unit.unitEvents.onStartAbilityAfter.RemoveListener(OnAbilityCastAfter);
unit.unitEvents.onTakeAfter.RemoveListener(OnTakeAfter);
unit.unitEvents.onDropAfter.RemoveListener(OnDropAfter);
unit.unitEvents.onEquipAfter.RemoveListener(OnEquipAfter);
unit.unitEvents.onUnEquipAfter.RemoveListener(OnUnEquipAfter);
unit.unitEvents.onUseAfter.RemoveListener(OnUseAfter);
unit.unitEvents.onActionError.RemoveListener(OnActionError);
}
private void AddError(string richText)
{
AddMessage($"<color=#D33>{richText}</color>");
}
private void AddMessage(string richText)
{
var message = new GameLogMessageUI();
message.InitNew(_messageWrapper, richText);
_messages.Add(message);
if (_messages.Count > _messageLimit) RemoveLastMessage();
}
private void RemoveLastMessage()
{
var lastMessage = _messages.Last();
lastMessage.Destroy();
_messages.RemoveAt(_messages.Count-1);
}
/* EVENTS BELOW */
/* for register and unregister */
private void OnStatusStart(StatusEvent e)
{
if (e.status.hidden) return;
AddMessage(string.Format(SENDER_PREFIX, e.obj.basicData.finalName) + string.Format(STATUS_START_MESSAGE, e.status.displayName, e.status.durationInTurns));
}
private void OnStatusEnd(StatusEvent e)
{
if (e.status.hidden) return;
AddMessage(string.Format(SENDER_PREFIX, e.obj.basicData.finalName) + string.Format(STATUS_END_MESSAGE, e.status.displayName));
}
private void OnDeathAfter(DeathEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.obj.basicData.finalName) + string.Format(DEATH_MESSAGE));
private void OnDamagedAfter(DamageEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.target.basicData.finalName) + string.Format(DAMAGED_MESSAGE, e.amount, e.damageType, e.attacker?.basicData.finalName ?? "unknown"));
private void OnDamageAfter(DamageEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.attacker.basicData.finalName) + string.Format(DAMAGE_MESSAGE, e.amount, e.damageType, e.target.basicData.finalName));
private void OnAbilityCastAfter(AbilityCastEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.caster.basicData.finalName) + string.Format(ABILITY_CAST_MESSAGE, e.ability.displayName));
private void OnTakeAfter(PickEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(TAKE_MESSAGE, e.item.basicData.finalName));
private void OnDropAfter(DropEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(DROP_MESSAGE, e.item.basicData.finalName));
private void OnEquipAfter(EquipEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(EQUIP_MESSAGE, e.wearable.basicData.finalName));
private void OnUnEquipAfter(UnEquipEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(UNEQUIP_MESSAGE, e.wearable.basicData.finalName));
private void OnUseAfter(UseEvent e) => AddMessage(string.Format(SENDER_PREFIX, e.usedBy.basicData.finalName) + string.Format(USE_MESSAGE, e.usedObject.basicData.finalName));
private void OnActionError(ActionErrorEvent e) => AddError(string.Format(SENDER_PREFIX, e.unit.basicData.finalName) + string.Format(ACTION_ERROR_MESSAGE, UnitActionErrorMessage.Get(e.cause)));
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 939ec691a5854e6ba2b35b9a1029c2d9
timeCreated: 1698862707
@@ -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="GameLogMessageUI" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/GameLog/GameLogMessageUI.uxml?fileID=9197481963319205126&amp;guid=648cfbe70d29b664a946fe7b43eebb89&amp;type=3#GameLogMessageUI" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/GameLog/GameLogUIStyle.uss?fileID=7433441132597879392&amp;guid=f8003f5e38dbaa841a5394fb4bfc6aae&amp;type=3#GameLogUIStyle" />
<ui:VisualElement name="root-game-log">
<ui:ScrollView horizontal-scroller-visibility="Hidden" name="message-scroller" vertical-scroller-visibility="AlwaysVisible">
<ui:VisualElement name="message-wrapper" style="flex-grow: 1;">
<ui:Instance template="GameLogMessageUI" />
<ui:Instance template="GameLogMessageUI" />
<ui:Instance template="GameLogMessageUI" />
<ui:Instance template="GameLogMessageUI" />
<ui:Instance template="GameLogMessageUI" />
<ui:Instance template="GameLogMessageUI" />
<ui:Instance template="GameLogMessageUI" />
</ui:VisualElement>
</ui:ScrollView>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3516f8d2aa647d442a6178d9a8379ee6
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,20 @@
#root-game-log {
position: absolute;
bottom: 70px;
right: 5px;
width: 450px;
height: 300px;
padding-left: 3px;
padding-right: 3px;
padding-top: 3px;
padding-bottom: 3px;
background-color: rgba(69, 69, 69, 0.48);
}
#root-game-log > #message-scroller {
flex-grow: 1;
}
#root-game-log > #message-scroller > #message-wrapper {
flex-grow: 1;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f8003f5e38dbaa841a5394fb4bfc6aae
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6fa3f09490cbe654db112c59229193ff
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,39 @@
using System;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.ScriptableObjects.Player;
namespace VOID.UserInterface.Game.LevelUp
{
public class LevelUpOptionUI : MonoBehaviour
{
public event Action OnSelect;
public static LevelUpOptionUI InitNew(GameObject gameObject, VisualElement parentWrapperElement, LevelUpOption option)
{
// New instance to manage this option
var instance = gameObject.AddComponent<LevelUpOptionUI>();
// Get all needed visual elements
var templateElement = GameUI.current.levelUpOptionTemplate.CloneTree().contentContainer;
templateElement.Q<Button>("root-level-up-option").clicked += () => instance.OnSelect?.Invoke();
templateElement.Q<Label>("title").text = option.displayName;
templateElement.Q("image").style.backgroundImage = option.displayIcon;
templateElement.Q<Label>("description").text = new StringBuilder()
.AppendJoin("\n", option.effects.Select(effect => effect.GetSimpleDescription()))
.AppendLine(option.displayDescription)
.ToString();
// Put this option into LevelUpUI
parentWrapperElement.Add(templateElement);
// Bind UI to this script + make it pickable
templateElement.dataSource = instance;
templateElement.pickingMode = PickingMode.Position;
return instance;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8b0abe7e999848df8ab7eeefa2a8b3df
timeCreated: 1729088250
@@ -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">
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/LevelUp/LevelUpOptionUIStyle.uss?fileID=7433441132597879392&amp;guid=f8e50bdc9f94ea34a86065518df01235&amp;type=3#LevelUpOptionUIStyle" />
<ui:Button name="root-level-up-option" style="width: 450px; height: 600px;">
<ui:Label text="{TITLE}" name="title" picking-mode="Ignore" />
<ui:VisualElement name="image" picking-mode="Ignore" />
<ui:Label text="{DESCRIPTION}" name="description" picking-mode="Ignore" />
</ui:Button>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: df731c68208fb8f49b616715fe5fc317
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,40 @@
#root-level-up-option {
width: 100%;
height: 100%;
flex-direction: column;
background-color: rgba(130, 130, 130, 0.98);
border-top-width: 2px;
border-right-width: 2px;
border-bottom-width: 2px;
border-left-width: 2px;
border-left-color: rgb(0, 0, 0);
border-right-color: rgb(0, 0, 0);
border-top-color: rgb(0, 0, 0);
border-bottom-color: rgb(0, 0, 0);
padding-top: 20px;
padding-right: 20px;
padding-bottom: 20px;
padding-left: 20px;
align-items: center;
margin-top: 10px;
margin-right: 10px;
margin-bottom: 10px;
margin-left: 10px;
}
#root-level-up-option > #title {
-unity-text-align: upper-center;
font-size: 50px;
}
#root-level-up-option > #image {
height: 150px;
width: 150px;
background-image: url('project://database/Assets/_ADDONS/MedievalKingdomUI/Artworks/White_gold_Skin/UI_elements_W/icon_frame.png?fileID=2800000&guid=f272753cabc45b9419037998d01412e7&type=3#icon_frame');
}
#root-level-up-option > #description {
-unity-text-align: upper-left;
font-size: 20px;
width: 100%;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f8e50bdc9f94ea34a86065518df01235
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.ScriptableObjects.Player;
namespace VOID.UserInterface.Game.LevelUp
{
public class LevelUpUI : MonoBehaviour
{
public static LevelUpUI current { get; private set; }
// Children - Options
private List<LevelUpOptionUI> _options = new();
// Visual Elements
private VisualElement _rootElement;
private VisualElement _optionListElement;
private Button _closeButton;
private void Awake()
{
current = this;
var uiDocument = gameObject.GetComponent<UIDocument>();
var templateElement = uiDocument.rootVisualElement;
_rootElement = templateElement.Q("root-level-up");
_closeButton = _rootElement.Q<Button>("close");
_optionListElement = _rootElement.Q("options");
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
_closeButton.clicked += Close;
Close();
}
public void Open(List<LevelUpOption> options, Action<LevelUpOption> onOptionSelect)
{
Close();
_rootElement.style.display = DisplayStyle.Flex;
foreach (var option in options)
{
var optionUI = LevelUpOptionUI.InitNew(gameObject, _optionListElement, option);
optionUI.OnSelect += Close;
optionUI.OnSelect += () => onOptionSelect.Invoke(option);
_options.Add(optionUI);
}
}
public void Close()
{
_rootElement.style.display = DisplayStyle.None;
_optionListElement.Clear();
_options.ForEach(Destroy);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 63f40eebe486cd64eb7a5a6bd5da7da4
timeCreated: 1697407029
@@ -0,0 +1,15 @@
<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="LevelUpOptionUI" src="project://database/Assets/92%20-%20UserInterface/Generic/Game/LevelUp/LevelUpOptionUI.uxml?fileID=9197481963319205126&amp;guid=df731c68208fb8f49b616715fe5fc317&amp;type=3#LevelUpOptionUI" />
<Style src="project://database/Assets/92%20-%20UserInterface/Generic/Game/LevelUp/LevelUpUIStyle.uss?fileID=7433441132597879392&amp;guid=1ef38f048e44352458744eb7ba0ef450&amp;type=3#LevelUpUIStyle" />
<ui:VisualElement name="root-level-up">
<ui:Button name="close" text="X" />
<ui:VisualElement name="options">
<ui:Instance template="LevelUpOptionUI" />
<ui:Instance template="LevelUpOptionUI" />
<ui:Instance template="LevelUpOptionUI" />
<ui:Instance template="LevelUpOptionUI" />
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: cea9f1cecad1e6e4fae469eb345a8c2f
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
@@ -0,0 +1,21 @@
#root-level-up {
width: 100%;
height: 100%;
flex-direction: row;
align-items: center;
background-color: rgba(255, 255, 255, 0.08);
}
#root-level-up > #close {
position: absolute;
top: 10px;
right: 10px;
width: 40px;
height: 40px;
}
#root-level-up > #options {
flex-direction: row;
justify-content: center;
width: 100%;
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ef38f048e44352458744eb7ba0ef450
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
@@ -0,0 +1,52 @@
using System.Linq;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Player;
namespace VOID.UserInterface.Game
{
public class OtherUnitBackpackManagerUI : MonoBehaviour
{
public static OtherUnitBackpackManagerUI current { get; private set; }
// References
private PlayerController _playerController;
// Template
[SerializeField, AssetsOnly] private GameObject _containerUIPrefab;
// Unit which we listen for opening container
private UnitObject _unit;
private void Awake()
{
current = this;
}
private void Start()
{
_playerController = PlayerController.current;
_playerController.OnActiveUnitChange += OnActiveUnitChange;
}
private void OnActiveUnitChange(UnitObject unit)
{
if (_unit)
{
_unit.unitEvents.onOpenOtherUnit.RemoveListener(OnContainerOpen);
OtherUnitBackpackUI.CurrentList.ToList().ForEach(containerUI => containerUI.Close());
}
_unit = unit;
_unit.unitEvents.onOpenOtherUnit.AddListener(OnContainerOpen);
}
private void OnContainerOpen(OpenOtherUnitEvent openOtherUnitEvent)
{
Instantiate(_containerUIPrefab, gameObject.transform)
.GetComponent<OtherUnitBackpackUI>()
.Open(openOtherUnitEvent.otherUnit, openOtherUnitEvent.openedBy);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9987a88be69a49778f6609c10be499e3
timeCreated: 1717952380
@@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Item;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Objects.Unit.Actions;
using VOID.Generic.Objects.Unit.Events;
using VOID.UserInterface.Game.Interfaces;
using VOID.UserInterface.Game.Util;
namespace VOID.UserInterface.Game
{
/// <summary>
/// Manages all visuals in one instance of <see cref="OtherUnitBackpackUI"/>.
/// </summary>
public class OtherUnitBackpackUI : MonoBehaviour, IHasWindow
{
public static readonly List<OtherUnitBackpackUI> CurrentList = new();
// WindowUI
public WindowUI windowUI { get; private set; }
// ContainerObject, its content to which this UI is connected and also unit who opened it
public UnitObject unit { get; private set; }
private UnitObjectBackpack _unitBackpack;
private UnitObject _openedBy;
// Visual Elements
private VisualElement _rootElement;
private VisualElement _slotsElement;
private SlotUI[] _slots;
private void Awake()
{
CurrentList.Add(this);
var uiDocument = gameObject.GetComponent<UIDocument>();
var template = uiDocument.rootVisualElement;
// Find all important elements
_rootElement = template.Q("root-container");
_slotsElement = template.Q("slots");
windowUI = gameObject.GetComponent<WindowUI>();
// Remove place holders
_slotsElement.Clear();
windowUI.OnClose += Close;
_rootElement.dataSource = this;
_rootElement.pickingMode = PickingMode.Position;
}
/// <summary>
/// Opens newly initialized <see cref="OtherUnitBackpackUI"/> <see cref="VisualElement"/>.
/// This should be called from <see cref="OtherUnitBackpackManagerUI"/>.
/// </summary>
public void Open(UnitObject unit, UnitObject openedBy)
{
this.unit = unit;
_unitBackpack = unit.unitBackpack;
_openedBy = openedBy;
_slots = new SlotUI[_unitBackpack.items.Length];
for (var i = 0; i < _unitBackpack.items.Length; i++)
SetSlot(i, _unitBackpack.items[i]);
unit.unitEvents.onClosedByOtherUnit.AddListener(OnClose);
unit.unitEvents.onBackpackResize.AddListener(OnResize);
unit.unitEvents.onBackpackSwap.AddListener(OnSwap);
unit.unitEvents.onBackpackPick.AddListener(OnMoveIn);
unit.unitEvents.onBackpackDrop.AddListener(OnMoveOut);
windowUI.SetTitle(unit.basicData.finalName);
// Make sure it is visible
_rootElement.style.display = DisplayStyle.Flex;
}
/// <summary>
/// Orders player's active <see cref="UnitObject"/> to <see cref="CloseOtherUnitAction"/>.
/// This action will close <see cref="WindowUI"/> which execute <see cref="OnClose"/>.
/// </summary>
public void Close()
{
new CloseOtherUnitAction(_openedBy, unit).DoIt();
}
private void OnClose(CloseOtherUnitEvent closeOtherUnitEvent)
{
unit.unitEvents.onClosedByOtherUnit.RemoveListener(OnClose);
unit.unitEvents.onBackpackResize.RemoveListener(OnResize);
unit.unitEvents.onBackpackSwap.RemoveListener(OnSwap);
unit.unitEvents.onBackpackPick.RemoveListener(OnMoveIn);
unit.unitEvents.onBackpackDrop.RemoveListener(OnMoveOut);
windowUI.OnClose -= Close;
_rootElement.parent.parent.Remove(_rootElement.parent);
CurrentList.Remove(this);
Destroy(this);
}
private void OnResize(BackpackResizeEvent backpackResizeEvent)
{
// Before resizing - remove all unused slots
if (backpackResizeEvent.beforeSlotCount > backpackResizeEvent.afterSlotCount)
for (var i = backpackResizeEvent.afterSlotCount; i < backpackResizeEvent.beforeSlotCount; i++)
RemoveSlot(i);
Array.Resize(ref _slots, backpackResizeEvent.afterSlotCount);
// After resizing - insert empty slots
if (backpackResizeEvent.beforeSlotCount < backpackResizeEvent.afterSlotCount)
for (var i = backpackResizeEvent.beforeSlotCount; i < backpackResizeEvent.afterSlotCount; i++)
SetSlot(i, null);
}
private void OnSwap(BackpackSwapEvent backpackSwapEvent)
{
SetSlot(backpackSwapEvent.firstSlotIndex, backpackSwapEvent.firstItem);
SetSlot(backpackSwapEvent.secondSlotIndex, backpackSwapEvent.secondItem);
}
private void OnMoveIn(BackpackPickEvent backpackPickEvent)
{
SetSlot(backpackPickEvent.slotIndex, backpackPickEvent.item);
}
private void OnMoveOut(BackpackDropEvent backpackDropEvent)
{
SetSlot(backpackDropEvent.slotIndex, null);
}
private void SetSlot(int slotIndex, ItemObject item)
{
// Create new VisualElement if not exists
if (_slots[slotIndex] is null)
{
_slots[slotIndex] = new SlotUI();
_slots[slotIndex].InitNew(_slotsElement, SlotType.OtherUnitBackpackSlot, slotIndex, "Slot-" + slotIndex);
}
// Put item's icon or else remain default
_slots[slotIndex].Set(item);
}
private void RemoveSlot(int slotIndex)
{
_slots[slotIndex].Destroy();
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f5cd63e234c4487e86a0074bf7d77b3e
timeCreated: 1717952427
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bf8c0da77ac98cf48986f9343813bb64
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -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

Some files were not shown because too many files have changed in this diff Show More