9 Commits

Author SHA1 Message Date
Sebastian Bularca
cfe202da44 Made the popup system a lot more generic 2026-04-06 20:38:58 +02:00
Sebastian Bularca
fa7659d905 added pooling for the gui portraits 2026-04-06 17:41:35 +02:00
Sebastian Bularca
f42885830a added documentation, fixed some bugs 2026-04-06 17:30:09 +02:00
Sebastian Bularca
333539eb0e popup actually working 2026-04-06 15:02:09 +02:00
Sebastian Bularca
9488b98f54 popup sort of works 2026-04-06 14:59:43 +02:00
Sebastian Bularca
b8fa26865d added a disfunctionalk popup system 2026-04-06 12:28:01 +02:00
Sebastian Bularca
cbf9f384d9 popup changes 2026-04-06 10:44:16 +02:00
Sebastian Bularca
61ca3701ae Added a popup system 2026-04-06 10:06:09 +02:00
Sebastian Bularca
a807405585 som qol fixes 2026-04-06 01:35:15 +02:00
124 changed files with 9590 additions and 4974 deletions

View File

@@ -22,7 +22,8 @@
"Bash(xxd Packages/com.jovian.ingame-logging/Runtime/GameLogStore.cs)", "Bash(xxd Packages/com.jovian.ingame-logging/Runtime/GameLogStore.cs)",
"Bash(find D:/repos/trail-into-darkness/Assets -name *.asmdef)", "Bash(find D:/repos/trail-into-darkness/Assets -name *.asmdef)",
"Bash(grep -E \"\\\\.\\(prefab|unity\\)$\")", "Bash(grep -E \"\\\\.\\(prefab|unity\\)$\")",
"Bash(python3:*)" "Bash(python3:*)",
"WebSearch"
] ]
} }
} }

View File

@@ -13,7 +13,6 @@ MonoBehaviour:
m_Name: AddressableAssetGroupSortSettings m_Name: AddressableAssetGroupSortSettings
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.AddressableAssetGroupSortSettings m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.AddressableAssetGroupSortSettings
sortOrder: sortOrder:
- 05b724f967e7d40e69a2f8086a7d78cd
- d7f58d36cc4da874fa45d38c0070c2c2 - d7f58d36cc4da874fa45d38c0070c2c2
- e6a1448ac7179f9469ae917578605c81 - e6a1448ac7179f9469ae917578605c81
- a8838bd8f2db41d4c894d2cf8403f207 - a8838bd8f2db41d4c894d2cf8403f207

View File

@@ -12,7 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 468a46d0ae32c3544b7d98094e6448a9, type: 3} m_Script: {fileID: 11500000, guid: 468a46d0ae32c3544b7d98094e6448a9, type: 3}
m_Name: AddressableAssetSettings m_Name: AddressableAssetSettings
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetSettings m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetSettings
m_DefaultGroup: 05b724f967e7d40e69a2f8086a7d78cd m_DefaultGroup: d7f58d36cc4da874fa45d38c0070c2c2
m_currentHash: m_currentHash:
serializedVersion: 2 serializedVersion: 2
Hash: 00000000000000000000000000000000 Hash: 00000000000000000000000000000000
@@ -60,7 +60,6 @@ MonoBehaviour:
m_BuildAddressablesWithPlayerBuild: 0 m_BuildAddressablesWithPlayerBuild: 0
m_overridePlayerVersion: '[UnityEditor.PlayerSettings.bundleVersion]' m_overridePlayerVersion: '[UnityEditor.PlayerSettings.bundleVersion]'
m_GroupAssets: m_GroupAssets:
- {fileID: 11400000, guid: 6c79f6f00c1f84b1c854543c84d05d0f, type: 2}
- {fileID: 11400000, guid: 8aabd2323ded16346970904048573037, type: 2} - {fileID: 11400000, guid: 8aabd2323ded16346970904048573037, type: 2}
- {fileID: 11400000, guid: 643aef87ff0fa05488c1a0982ec49f26, type: 2} - {fileID: 11400000, guid: 643aef87ff0fa05488c1a0982ec49f26, type: 2}
- {fileID: 11400000, guid: 2ddfa0c67160cbe4f9669d176f0ee01b, type: 2} - {fileID: 11400000, guid: 2ddfa0c67160cbe4f9669d176f0ee01b, type: 2}

View File

@@ -40,11 +40,21 @@ MonoBehaviour:
m_ReadOnly: 0 m_ReadOnly: 0
m_SerializedLabels: [] m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0 FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 15529a69a8231ac43b1108efbaad83b6
m_Address: Assets/Prefabs/UI/CharacterCreationReference.prefab
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 21833c6afc1e0b047a3c49dc9ea35996 - m_GUID: 21833c6afc1e0b047a3c49dc9ea35996
m_Address: Assets/Art/UI/portait_hero_05.png m_Address: Assets/Art/UI/portait_hero_05.png
m_ReadOnly: 0 m_ReadOnly: 0
m_SerializedLabels: [] m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0 FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 2dfcc209b5aff734d863147e5614563c
m_Address: PopupReferencePrefab
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 3225768f79644af4dbda96b8f9d57ed2 - m_GUID: 3225768f79644af4dbda96b8f9d57ed2
m_Address: Assets/Art/UI/menu_supply_bar_full.png m_Address: Assets/Art/UI/menu_supply_bar_full.png
m_ReadOnly: 0 m_ReadOnly: 0
@@ -75,6 +85,11 @@ MonoBehaviour:
m_ReadOnly: 0 m_ReadOnly: 0
m_SerializedLabels: [] m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0 FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 571f2dd77fb442d499cdc9c2afe9f98d
m_Address: PopupSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 60a7c1e10ed7ff94cbe191d9d3e305ed - m_GUID: 60a7c1e10ed7ff94cbe191d9d3e305ed
m_Address: Assets/Art/UI/menu_corner.png m_Address: Assets/Art/UI/menu_corner.png
m_ReadOnly: 0 m_ReadOnly: 0
@@ -206,6 +221,11 @@ MonoBehaviour:
m_ReadOnly: 0 m_ReadOnly: 0
m_SerializedLabels: [] m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0 FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ed9b80145a89c8a4f8d456971d242c3c
m_Address: PortraitsHolder
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: f37df040ec9864f4dbafe3f5e6dfe4d9 - m_GUID: f37df040ec9864f4dbafe3f5e6dfe4d9
m_Address: DefaultPartySettings m_Address: DefaultPartySettings
m_ReadOnly: 0 m_ReadOnly: 0

View File

@@ -1,33 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Default Local Group
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetGroup
m_GroupName: Default Local Group
m_GUID: 05b724f967e7d40e69a2f8086a7d78cd
m_SerializeEntries:
- m_GUID: 15529a69a8231ac43b1108efbaad83b6
m_Address: Assets/Prefabs/UI/CharacterCreationReference.prefab
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: ed9b80145a89c8a4f8d456971d242c3c
m_Address: PortraitsHolder
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: 7e98b357dd76a43e191428299c44eef2, type: 2}
m_SchemaSet:
m_Schemas:
- {fileID: 11400000, guid: 5b53a1ca29cdf45fdb72fa3e94514b82, type: 2}
- {fileID: 11400000, guid: 9148d31c5a1d74102a17c9d6be0baf0e, type: 2}

View File

@@ -1,48 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e5d17a21594effb4e9591490b009e7aa, type: 3}
m_Name: Default Local Group_BundledAssetGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.BundledAssetGroupSchema
m_Group: {fileID: 11400000, guid: 6c79f6f00c1f84b1c854543c84d05d0f, type: 2}
m_InternalBundleIdMode: 1
m_Compression: 1
m_IncludeAddressInCatalog: 1
m_IncludeGUIDInCatalog: 1
m_IncludeLabelsInCatalog: 1
m_InternalIdNamingMode: 0
m_CacheClearBehavior: 0
m_IncludeInBuild: 1
m_BundledAssetProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider
m_StripDownloadOptions: 0
m_ForceUniqueProvider: 0
m_UseAssetBundleCache: 1
m_UseAssetBundleCrc: 1
m_UseAssetBundleCrcForCachedBundles: 1
m_UseUWRForLocalBundles: 0
m_Timeout: 0
m_ChunkedTransfer: 0
m_RedirectLimit: -1
m_RetryCount: 0
m_BuildPath:
m_Id: 8fbce5c7cea8b47209ad27b2e4685031
m_LoadPath:
m_Id: 8e5cf788c2f044c5ba2465efea14a827
m_BundleMode: 0
m_AssetBundleProviderType:
m_AssemblyName: Unity.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
m_ClassName: UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider
m_UseDefaultSchemaSettings: 0
m_SelectedPathPairIndex: 0
m_BundleNaming: 0
m_AssetLoadMode: 0

View File

@@ -1,16 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5834b5087d578d24c926ce20cd31e6d6, type: 3}
m_Name: Default Local Group_ContentUpdateGroupSchema
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.ContentUpdateGroupSchema
m_Group: {fileID: 11400000, guid: 6c79f6f00c1f84b1c854543c84d05d0f, type: 2}
m_StaticContent: 0

View File

@@ -49,7 +49,7 @@ TextureImporter:
alignment: 0 alignment: 0
spritePivot: {x: 0.5, y: 0.5} spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100 spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0} spriteBorder: {x: 0, y: 1, z: 1, w: 0}
spriteGenerateFallbackPhysicsShape: 1 spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1 alphaUsage: 1
alphaIsTransparency: 1 alphaIsTransparency: 1
@@ -93,6 +93,19 @@ TextureImporter:
ignorePlatformSupport: 0 ignorePlatformSupport: 0
androidETC2FallbackOverride: 0 androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0 forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet: spriteSheet:
serializedVersion: 2 serializedVersion: 2
sprites: [] sprites: []
@@ -101,7 +114,7 @@ TextureImporter:
physicsShape: [] physicsShape: []
bones: [] bones: []
spriteID: 5e97eb03825dee720800000000000000 spriteID: 5e97eb03825dee720800000000000000
internalID: 0 internalID: 1537655665
vertices: [] vertices: []
indices: indices:
edges: [] edges: []

View File

@@ -23,14 +23,14 @@ namespace Nox.Game {
} }
var healthModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Health); var healthModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Health);
var staminaModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Mana); var manaModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Mana);
var levelModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Level); var levelModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Level);
var experienceModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Experience); var experienceModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Experience);
return new EntityStats { return new EntityStats {
stats = new[] { stats = new[] {
new Stat(StatType.Health, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Health), healthModifiers, entityDefinition)), new Stat(StatType.Health, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Health), healthModifiers, entityDefinition)),
new Stat(StatType.Mana, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Mana), staminaModifiers, entityDefinition)), new Stat(StatType.Mana, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Mana), manaModifiers, entityDefinition)),
new Stat(StatType.Level, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Level), levelModifiers, entityDefinition)), new Stat(StatType.Level, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Level), levelModifiers, entityDefinition)),
new Stat(StatType.Experience, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Experience), experienceModifiers, entityDefinition)) new Stat(StatType.Experience, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Experience), experienceModifiers, entityDefinition))
} }

View File

@@ -1,3 +1,5 @@
using Jovian.PopupSystem;
using Jovian.PopupSystem.UI;
using Jovian.SaveSystem; using Jovian.SaveSystem;
using Jovian.ZoneSystem; using Jovian.ZoneSystem;
using Nox.Core; using Nox.Core;
@@ -39,6 +41,7 @@ namespace Nox.Game {
private TimeHandler timeHandler; private TimeHandler timeHandler;
private PartyInventoryHandler partyInventoryHandler; private PartyInventoryHandler partyInventoryHandler;
private PartyGuiView partyGuiView; private PartyGuiView partyGuiView;
private IPopupSystem popupSystem;
public AdventurePlayMode( public AdventurePlayMode(
PlatformSettings platformSettings, PlatformSettings platformSettings,
@@ -134,7 +137,16 @@ namespace Nox.Game {
if(partyGuiView == null && guiReferences.partyMemberSlotPrefab != null) { if(partyGuiView == null && guiReferences.partyMemberSlotPrefab != null) {
var portraitsHolder = Addressables.LoadAssetAsync<PortraitsHolder>("PortraitsHolder").WaitForCompletion(); var portraitsHolder = Addressables.LoadAssetAsync<PortraitsHolder>("PortraitsHolder").WaitForCompletion();
partyGuiView = new PartyGuiView(guiReferences.portraitsContainer, guiReferences.partyMemberSlotPrefab, portraitsHolder);
if(popupSystem == null) {
var popupSettings = Addressables.LoadAssetAsync<PopupSettings>("PopupSettings").WaitForCompletion();
var popupViewPrefab = Addressables.LoadAssetAsync<GameObject>("PopupReferencePrefab").WaitForCompletion().GetComponent<PopupReference>();
var guiCanvas = guiReferences.GetComponentInParent<Canvas>().transform;
popupSystem = new PopupSystem(popupSettings, popupViewPrefab, guiCanvas);
popupSystem.RegisterCategory(PopupCategory.Character, priority: 10);
}
partyGuiView = new PartyGuiView(guiReferences.portraitsContainer, guiReferences.partyMemberSlotPrefab, portraitsHolder, popupSystem);
partyGuiView.Initialize(partyDefinition); partyGuiView.Initialize(partyDefinition);
} }
@@ -151,6 +163,7 @@ namespace Nox.Game {
partyMovementHandler.Tick(); partyMovementHandler.Tick();
adventureView.Tick(); adventureView.Tick();
partyGuiView?.Tick(); partyGuiView?.Tick();
popupSystem?.Tick(Time.deltaTime);
if(inputActions.UI.PauseMenu.WasPerformedThisFrame()) { if(inputActions.UI.PauseMenu.WasPerformedThisFrame()) {
gameDataState.ChangePlayMode(PlayMode.PauseMenu); gameDataState.ChangePlayMode(PlayMode.PauseMenu);
@@ -178,6 +191,7 @@ namespace Nox.Game {
cameraController?.Dispose(); cameraController?.Dispose();
partyMovementHandler?.Dispose(); partyMovementHandler?.Dispose();
partyGuiView?.Dispose(); partyGuiView?.Dispose();
popupSystem?.Dispose();
} }
} }

View File

@@ -35,7 +35,7 @@ namespace Nox.UI {
private int remainingPoints; private int remainingPoints;
private readonly int[] allocatedPoints = new int[4]; // Might, Reflex, Knowledge, Perception (AttributeType 1-4) private readonly int[] allocatedPoints = new int[4]; // Might, Reflex, Knowledge, Perception (AttributeType 1-4)
private int previousHealth; private int previousHealth;
private int previousStamina; private int previousMana;
// Modifier source tracking // Modifier source tracking
private PerksData racialPerks = new(); private PerksData racialPerks = new();
@@ -87,8 +87,11 @@ namespace Nox.UI {
var canStart = characterCreationRequests is { Count: > 0 }; var canStart = characterCreationRequests is { Count: > 0 };
characterCreationReference.startGameButton.interactable = canStart; characterCreationReference.startGameButton.interactable = canStart;
}; };
characterCreationReference.startGameButton.interactable = false;
characterCreationReference.startGameButton.onClick.AddListener(() => { characterCreationReference.startGameButton.onClick.AddListener(() => {
if(characterCreationRequests == null || characterCreationRequests.Count == 0) {
inGameLogger.Log("You must accept your character before starting the game.", "#FF4444");
return;
}
Hide(); Hide();
menuGameStateData.startGameRequests?.Invoke(PlayMode.Adventure); menuGameStateData.startGameRequests?.Invoke(PlayMode.Adventure);
}); });
@@ -182,7 +185,7 @@ namespace Nox.UI {
// Initialize previous values so first change doesn't log a delta from 0 // Initialize previous values so first change doesn't log a delta from 0
previousHealth = workingStats.GetValue(StatType.Health); previousHealth = workingStats.GetValue(StatType.Health);
previousStamina = workingStats.GetValue(StatType.Mana); previousMana = workingStats.GetValue(StatType.Mana);
} }
private void ApplyRacialBonuses() { private void ApplyRacialBonuses() {
@@ -291,19 +294,19 @@ namespace Nox.UI {
// 10. Log stat deltas // 10. Log stat deltas
var newHealth = workingStats.GetValue(StatType.Health); var newHealth = workingStats.GetValue(StatType.Health);
var newStamina = workingStats.GetValue(StatType.Mana); var newMana = workingStats.GetValue(StatType.Mana);
if(newHealth != previousHealth && previousHealth != 0) { if(newHealth != previousHealth && previousHealth != 0) {
var delta = newHealth - previousHealth; var delta = newHealth - previousHealth;
var sign = delta > 0 ? "+" : ""; var sign = delta > 0 ? "+" : "";
inGameLogger.Log($"Health: {previousHealth} -> {newHealth} ({sign}{delta})", "#87CEEB"); inGameLogger.Log($"Health: {previousHealth} -> {newHealth} ({sign}{delta})", "#87CEEB");
} }
if(newStamina != previousStamina && previousStamina != 0) { if(newMana != previousMana && previousMana != 0) {
var delta = newStamina - previousStamina; var delta = newMana - previousMana;
var sign = delta > 0 ? "+" : ""; var sign = delta > 0 ? "+" : "";
inGameLogger.Log($"Stamina: {previousStamina} -> {newStamina} ({sign}{delta})", "#FFFF99"); inGameLogger.Log($"Mana: {previousMana} -> {newMana} ({sign}{delta})", "#FFFF99");
} }
previousHealth = newHealth; previousHealth = newHealth;
previousStamina = newStamina; previousMana = newMana;
} }
private PerksData BuildCombinedPerks() { private PerksData BuildCombinedPerks() {

View File

@@ -1,28 +1,42 @@
using System.Collections.Generic; using System.Collections.Generic;
using Jovian.PopupSystem;
using Nox.UI; using Nox.UI;
using UnityEngine; using UnityEngine;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace Nox.Game.UI { namespace Nox.Game.UI {
public class PartyGuiView { public class PartyGuiView {
private const int PoolSize = 4;
private readonly Transform portraitsContainer; private readonly Transform portraitsContainer;
private readonly PartyMemberSlot slotPrefab; private readonly PartyMemberSlot slotPrefab;
private readonly PortraitsHolder portraitsHolder; private readonly PortraitsHolder portraitsHolder;
private readonly List<PartyMemberSlot> activeSlots = new(); private readonly IPopupSystem popupSystem;
private readonly PartyMemberSlot[] slotPool = new PartyMemberSlot[PoolSize];
private PartyDefinition trackedParty; private PartyDefinition trackedParty;
private int trackedMemberCount; private int activeCount;
public PartyGuiView(Transform portraitsContainer, PartyMemberSlot slotPrefab, PortraitsHolder portraitsHolder) { public PartyGuiView(Transform portraitsContainer, PartyMemberSlot slotPrefab, PortraitsHolder portraitsHolder, IPopupSystem popupSystem = null) {
this.portraitsContainer = portraitsContainer; this.portraitsContainer = portraitsContainer;
this.slotPrefab = slotPrefab; this.slotPrefab = slotPrefab;
this.portraitsHolder = portraitsHolder; this.portraitsHolder = portraitsHolder;
this.popupSystem = popupSystem;
} }
public void Initialize(PartyDefinition party) { public void Initialize(PartyDefinition party) {
trackedParty = party; trackedParty = party;
trackedMemberCount = 0; activeCount = 0;
RebuildSlots();
// Pre-create all slots (deactivated)
for(int i = 0; i < PoolSize; i++) {
if(slotPool[i] == null) {
slotPool[i] = Object.Instantiate(slotPrefab, portraitsContainer);
}
slotPool[i].gameObject.SetActive(false);
}
PopulateSlots();
} }
public void Tick() { public void Tick() {
@@ -31,33 +45,27 @@ namespace Nox.Game.UI {
} }
// Rebuild if member count changed // Rebuild if member count changed
if(trackedParty.members.Count != trackedMemberCount) { if(trackedParty.members.Count != activeCount) {
RebuildSlots(); PopulateSlots();
} }
// Update dynamic values (health, mana) // Update dynamic values
for(int i = 0; i < activeSlots.Count && i < trackedParty.members.Count; i++) { var memberCount = Mathf.Min(activeCount, trackedParty.members.Count);
for(int i = 0; i < memberCount; i++) {
UpdateSlotStats(slotPool[i], trackedParty.members[i]);
}
}
private void PopulateSlots() {
var memberCount = trackedParty?.members != null
? Mathf.Min(trackedParty.members.Count, PoolSize)
: 0;
// Activate slots for current members, deactivate the rest
for(int i = 0; i < PoolSize; i++) {
var slot = slotPool[i];
if(i < memberCount) {
var member = trackedParty.members[i]; var member = trackedParty.members[i];
var slot = activeSlots[i];
UpdateSlotStats(slot, member);
}
}
private void RebuildSlots() {
// Clear existing
foreach(var slot in activeSlots) {
Object.Destroy(slot.gameObject);
}
activeSlots.Clear();
if(trackedParty?.members == null) {
return;
}
trackedMemberCount = trackedParty.members.Count;
foreach(var member in trackedParty.members) {
var slot = Object.Instantiate(slotPrefab, portraitsContainer);
slot.gameObject.SetActive(true); slot.gameObject.SetActive(true);
// Portrait // Portrait
@@ -66,13 +74,82 @@ namespace Nox.Game.UI {
slot.portrait.sprite = portraitsHolder.portraits[idx]; slot.portrait.sprite = portraitsHolder.portraits[idx];
} }
// Name UpdateSlotStats(slot, member);
if(slot.nameText != null) { }
slot.nameText.text = member.Name; else {
slot.gameObject.SetActive(false);
}
} }
UpdateSlotStats(slot, member); activeCount = memberCount;
activeSlots.Add(slot);
// Initialize popup triggers
if(popupSystem != null) {
popupSystem.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
var slot = trigger.GetComponentInParent<PartyMemberSlot>();
if(slot == null) {
return;
}
var slotIndex = System.Array.IndexOf(slotPool, slot);
if(slotIndex < 0 || slotIndex >= activeCount) {
return;
}
var member = trackedParty.members[slotIndex];
view.SetContent(builder => BuildCharacterPopup(builder, member));
});
}
}
private void BuildCharacterPopup(PopupContentBuilder builder, CharacterDefinition member) {
// Header
builder
.AddText(member.Name, PopupElementType.Header)
.AddText($"{member.Race} {member.Class}", "#CCCCCC", PopupElementType.Text)
.AddText($"Role: {member.Role}", PopupElementType.Text)
.AddSeparator(PopupElementType.Separator);
// Stats
if(member.Stats?.stats != null) {
var level = member.Stats.GetValue(StatType.Level);
var xp = member.Stats.GetValue(StatType.Experience);
var health = member.Stats.GetValue(StatType.Health);
var mana = member.Stats.GetValue(StatType.Mana);
builder
.AddNameValue("Level", level, PopupElementType.LabelValueText)
.AddNameValue("XP", xp, PopupElementType.LabelValueText)
.AddSeparator(PopupElementType.Separator)
.AddNameValue("Health", health, PopupElementType.LabelValueText)
.AddNameValue("Mana", mana, PopupElementType.LabelValueText)
.AddSeparator(PopupElementType.Separator);
}
// Attributes
if(member.Attributes?.attributes != null) {
foreach(var attr in member.Attributes.attributes) {
if(attr.attribute == AttributeType.None) {
continue;
}
builder.AddNameValue(attr.attribute.ToString(), attr.value, PopupElementType.LabelValueText);
}
}
builder.AddSeparator(PopupElementType.Separator);
// Perks
if(member.Perks?.perks is { Count: > 0 }) {
builder.AddText("Perks", "#FFD700", PopupElementType.Text);
foreach(var perk in member.Perks.perks) {
builder.AddText($" {perk.Name}", PopupElementType.Text);
}
builder.AddSeparator(PopupElementType.Separator);
}
// Modifiers
if(member.Modifiers?.modifiers is { Count: > 0 }) {
builder.AddText("Modifiers", "#87CEEB", PopupElementType.Text);
foreach(var mod in member.Modifiers.modifiers) {
var target = mod.Target != null ? mod.Target.ToString() : "";
builder.AddText($" {mod.Name} ({mod.Operation} {mod.Value} {target})", PopupElementType.Text);
}
} }
} }
@@ -83,25 +160,20 @@ namespace Nox.Game.UI {
if(slot.healthBar != null) { if(slot.healthBar != null) {
slot.healthBar.fillAmount = Mathf.Clamp01(health / 100f); slot.healthBar.fillAmount = Mathf.Clamp01(health / 100f);
} }
if(slot.healthText != null) {
slot.healthText.text = health.ToString();
}
if(slot.manaBar != null) { if(slot.manaBar != null) {
slot.manaBar.fillAmount = Mathf.Clamp01(mana / 100f); slot.manaBar.fillAmount = Mathf.Clamp01(mana / 100f);
} }
if(slot.manaText != null) {
slot.manaText.text = mana.ToString();
}
} }
public void Dispose() { public void Dispose() {
foreach(var slot in activeSlots) { for(int i = 0; i < PoolSize; i++) {
if(slot != null) { if(slotPool[i] != null) {
Object.Destroy(slot.gameObject); Object.Destroy(slotPool[i].gameObject);
slotPool[i] = null;
} }
} }
activeSlots.Clear(); activeCount = 0;
} }
} }
} }

View File

@@ -1,4 +1,3 @@
using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@@ -7,8 +6,5 @@ namespace Nox.Game.UI {
public Image portrait; public Image portrait;
public Image healthBar; public Image healthBar;
public Image manaBar; public Image manaBar;
public TextMeshProUGUI nameText;
public TextMeshProUGUI healthText;
public TextMeshProUGUI manaText;
} }
} }

View File

@@ -0,0 +1,44 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e38e313f3665d464b82b22699b2a4634, type: 3}
m_Name: PopupSettings
m_EditorClassIdentifier: Jovian.PopupSystem::Jovian.PopupSystem.PopupSettings
popupDelay: 0.4
fadeDuration: 0.2
defaultAnchorSide: 3
screenEdgePadding: 10
maxPopupWidth: 400
sortingOrder: 100
followMouseOffset: {x: 15, y: -15}
touchHoldDuration: 0.6
gamepadFocusTrigger: 1
elementPrefabs:
- type:
id: header
prefab: {fileID: 7034836061828108288, guid: dfc1bc0bd5b4905409615c3e770a5b77, type: 3}
- type:
id: image
prefab: {fileID: 5887814251614319338, guid: 5e715f4b614d02b4fa0b4d3fcfe3c053, type: 3}
- type:
id: label_value_text
prefab: {fileID: 6246834368258800846, guid: 5882db210c62d8647858933649f64c29, type: 3}
- type:
id: separator
prefab: {fileID: 6770634903822758885, guid: 7ccdfa1a2079db044be4b1684303ec7f, type: 3}
- type:
id: text
prefab: {fileID: 3157287847714375358, guid: bfa97c92d1878cc448ddc7dc456f4b17, type: 3}
categoryPriorities:
- category:
id: Character
priority: 0
categoryDelayOverrides: []

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 9148d31c5a1d74102a17c9d6be0baf0e guid: 571f2dd77fb442d499cdc9c2afe9f98d
NativeFormatImporter: NativeFormatImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 11400000 mainObjectFileID: 11400000

View File

@@ -1,8 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 6c79f6f00c1f84b1c854543c84d05d0f guid: 75a4a222ad797a54aac8ff58761899cf
NativeFormatImporter: folderAsset: yes
DefaultImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 11400000
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:

View File

@@ -1,8 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 5b53a1ca29cdf45fdb72fa3e94514b82 guid: b57e33c3f937ba146a2a13d68b0ce173
NativeFormatImporter: folderAsset: yes
DefaultImporter:
externalObjects: {} externalObjects: {}
mainObjectFileID: 11400000
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:

View File

@@ -59,7 +59,7 @@ MonoBehaviour:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0} m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1} m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1 m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1 m_Maskable: 1
m_OnCullStateChanged: m_OnCullStateChanged:
@@ -92,7 +92,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!224 &7663002820715980796 --- !u!224 &7663002820715980796
RectTransform: RectTransform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -229,7 +229,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!224 &8741529769002405325 --- !u!224 &8741529769002405325
RectTransform: RectTransform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -408,8 +408,8 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0} m_Material: {fileID: 0}
m_Color: {r: 0.6156863, g: 0.6509804, b: 0.63529414, a: 1} m_Color: {r: 0.9818833, g: 1, b: 0, a: 1}
m_RaycastTarget: 1 m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1 m_Maskable: 1
m_OnCullStateChanged: m_OnCullStateChanged:
@@ -442,7 +442,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!224 &32220060764936852 --- !u!224 &32220060764936852
RectTransform: RectTransform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -573,6 +573,7 @@ GameObject:
- component: {fileID: 635472993512454406} - component: {fileID: 635472993512454406}
- component: {fileID: 713960887884573537} - component: {fileID: 713960887884573537}
- component: {fileID: 1445432521138085750} - component: {fileID: 1445432521138085750}
- component: {fileID: 250019032835520348}
m_Layer: 5 m_Layer: 5
m_Name: HeroPortrait m_Name: HeroPortrait
m_TagString: Untagged m_TagString: Untagged
@@ -598,8 +599,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.041302264} m_AnchorMin: {x: 0, y: 0.041302264}
m_AnchorMax: {x: 1, y: 1} m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: -0.19400787, y: -0.000015258789} m_AnchoredPosition: {x: -0.0000076293945, y: -0.000015258789}
m_SizeDelta: {x: -0.38810003, y: 0} m_SizeDelta: {x: 0.000022888, y: 0}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &713960887884573537 --- !u!222 &713960887884573537
CanvasRenderer: CanvasRenderer:
@@ -639,6 +640,22 @@ MonoBehaviour:
m_FillOrigin: 0 m_FillOrigin: 0
m_UseSpriteMesh: 0 m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1 m_PixelsPerUnitMultiplier: 1
--- !u!114 &250019032835520348
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5596812297104419965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4ef9d21a19cd4db4f9d5491202547c05, type: 3}
m_Name:
m_EditorClassIdentifier: Jovian.PopupSystem::Jovian.PopupSystem.UI.PopupTrigger
category:
id: Character
anchorSide: 3
positionMode: 0
--- !u!1 &7521504480723579343 --- !u!1 &7521504480723579343
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -703,9 +720,6 @@ MonoBehaviour:
portrait: {fileID: 1445432521138085750} portrait: {fileID: 1445432521138085750}
healthBar: {fileID: 4550488616099254946} healthBar: {fileID: 4550488616099254946}
manaBar: {fileID: 4614622083837966787} manaBar: {fileID: 4614622083837966787}
nameText: {fileID: 7895725010274726425}
healthText: {fileID: 2204466678496895551}
manaText: {fileID: 1991527881912334546}
--- !u!114 &3828666794624103248 --- !u!114 &3828666794624103248
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -761,8 +775,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.041302264} m_AnchorMin: {x: 0, y: 0.041302264}
m_AnchorMax: {x: 1, y: 0.041302264} m_AnchorMax: {x: 1, y: 0.041302264}
m_AnchoredPosition: {x: -0.19399261, y: -1.4669495} m_AnchoredPosition: {x: -0.19453812, y: -2.3094025}
m_SizeDelta: {x: -0.3880005, y: 2.6903992} m_SizeDelta: {x: -0.38894, y: 4.3752}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2223287144791830491 --- !u!222 &2223287144791830491
CanvasRenderer: CanvasRenderer:
@@ -785,8 +799,8 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0} m_Material: {fileID: 0}
m_Color: {r: 0.48627454, g: 0.06666667, b: 0.08627451, a: 1} m_Color: {r: 0.19131038, g: 0.06666666, b: 0.4862745, a: 1}
m_RaycastTarget: 1 m_RaycastTarget: 0
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1 m_Maskable: 1
m_OnCullStateChanged: m_OnCullStateChanged:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 80b7de964780c3a4d91efbe9df16d961
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b7ddc322bd65e7e46abca4c4c6540bb6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,160 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &7034836061828108288
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1241885294582312999}
- component: {fileID: 1942692710355281447}
- component: {fileID: 6612787789151041457}
- component: {fileID: 743893275569378137}
m_Layer: 5
m_Name: PopupHeader
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1241885294582312999
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7034836061828108288}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 741.369, y: -210.32233}
m_SizeDelta: {x: 214.8432, y: 16}
m_Pivot: {x: 0, y: 1}
--- !u!222 &1942692710355281447
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7034836061828108288}
m_CullTransparentMesh: 1
--- !u!114 &6612787789151041457
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7034836061828108288}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: New Text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 16
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 5
m_fontSizeMax: 16
m_fontStyle: 17
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &743893275569378137
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7034836061828108288}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.LayoutElement
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: 1
m_FlexibleHeight: 1
m_LayoutPriority: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: dfc1bc0bd5b4905409615c3e770a5b77
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &5887814251614319338
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3721371113883694790}
- component: {fileID: 5474191059961008429}
- component: {fileID: 7093821785826926595}
- component: {fileID: 6531872381202374245}
m_Layer: 5
m_Name: PopupIcon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3721371113883694790
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5887814251614319338}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 989.9083, y: -555.6331}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5474191059961008429
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5887814251614319338}
m_CullTransparentMesh: 1
--- !u!114 &7093821785826926595
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5887814251614319338}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: ea02ea44fa86ee445be0f7ca82098b75, type: 3}
m_Type: 0
m_PreserveAspect: 1
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &6531872381202374245
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5887814251614319338}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.LayoutElement
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: -1
m_FlexibleHeight: -1
m_LayoutPriority: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5e715f4b614d02b4fa0b4d3fcfe3c053
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,292 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1599460330468667833
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 623181081371217224}
- component: {fileID: 1835601435911948781}
- component: {fileID: 695849844002832445}
- component: {fileID: 3081303906751693297}
- component: {fileID: -4214546602618600400}
- component: {fileID: 7236468329886607693}
m_Layer: 5
m_Name: PopupReferencePrefab
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &623181081371217224
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1599460330468667833}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8899521584296352500}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 300, y: 0}
m_Pivot: {x: 0, y: 1}
--- !u!225 &1835601435911948781
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1599460330468667833}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0
--- !u!114 &695849844002832445
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1599460330468667833}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bc25da4712d7cc4419eb6f364e032431, type: 3}
m_Name:
m_EditorClassIdentifier: Jovian.PopupSystem::Jovian.PopupSystem.UI.PopupReference
content: {fileID: 176628901263125209}
canvasGroup: {fileID: 1835601435911948781}
background: {fileID: 8899521584296352500}
--- !u!223 &3081303906751693297
Canvas:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1599460330468667833}
m_Enabled: 1
serializedVersion: 3
m_RenderMode: 2
m_Camera: {fileID: 0}
m_PlaneDistance: 100
m_PixelPerfect: 0
m_ReceivesEvents: 1
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 25
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 100
m_TargetDisplay: 0
--- !u!114 &-4214546602618600400
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1599460330468667833}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.CanvasScaler
m_UiScaleMode: 1
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ReferenceResolution: {x: 1920, y: 1080}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0.5
m_PhysicalUnit: 3
m_FallbackScreenDPI: 96
m_DefaultSpriteDPI: 96
m_DynamicPixelsPerUnit: 1
m_PresetInfoIsWorld: 1
--- !u!114 &7236468329886607693
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1599460330468667833}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.ContentSizeFitter
m_HorizontalFit: 0
m_VerticalFit: 2
--- !u!1 &3774543863822571266
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 176628901263125209}
- component: {fileID: 2618782962856630769}
- component: {fileID: 4695064839375127024}
- component: {fileID: 8584485639437491102}
- component: {fileID: 7537071497970891545}
m_Layer: 5
m_Name: Content
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &176628901263125209
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3774543863822571266}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8899521584296352500}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 1}
--- !u!114 &2618782962856630769
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3774543863822571266}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.VerticalLayoutGroup
m_Padding:
m_Left: 8
m_Right: 8
m_Top: 8
m_Bottom: 8
m_ChildAlignment: 0
m_Spacing: 3.82
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 1
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!222 &4695064839375127024
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3774543863822571266}
m_CullTransparentMesh: 1
--- !u!114 &8584485639437491102
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3774543863822571266}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 0.1509434, g: 0.116711326, b: 0.088999644, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 52125a3c3df558448a5af5a04dbf8d2d, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &7537071497970891545
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3774543863822571266}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.ContentSizeFitter
m_HorizontalFit: 0
m_VerticalFit: 2
--- !u!1 &7921791084240859601
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8899521584296352500}
- component: {fileID: 4414385109869753182}
m_Layer: 5
m_Name: Background
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8899521584296352500
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7921791084240859601}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 176628901263125209}
m_Father: {fileID: 623181081371217224}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: -0.000015258789, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0, y: 1}
--- !u!222 &4414385109869753182
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7921791084240859601}
m_CullTransparentMesh: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2dfcc209b5aff734d863147e5614563c
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6770634903822758885
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6952702389074691349}
- component: {fileID: 8646545094697898389}
- component: {fileID: 4190588985333916705}
- component: {fileID: 4150277454754236166}
m_Layer: 5
m_Name: PopupSeparator
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6952702389074691349
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6770634903822758885}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 5.3594}
m_Pivot: {x: 0, y: 1}
--- !u!222 &8646545094697898389
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6770634903822758885}
m_CullTransparentMesh: 1
--- !u!114 &4190588985333916705
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6770634903822758885}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
m_Material: {fileID: 0}
m_Color: {r: 1, g: 0.61809045, b: 0.15566039, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &4150277454754236166
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6770634903822758885}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.LayoutElement
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: 1
m_FlexibleHeight: -1
m_LayoutPriority: 1

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7ccdfa1a2079db044be4b1684303ec7f
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,376 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3992841297615171806
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 292870618973774166}
- component: {fileID: 4060824052845831606}
- component: {fileID: 572642145995679888}
m_Layer: 5
m_Name: label
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &292870618973774166
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3992841297615171806}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1843470073663794312}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 177.619, y: 25.6566}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4060824052845831606
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3992841297615171806}
m_CullTransparentMesh: 1
--- !u!114 &572642145995679888
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3992841297615171806}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: New Text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 16
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 5
m_fontSizeMax: 16
m_fontStyle: 17
m_HorizontalAlignment: 1
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &6246834368258800846
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1843470073663794312}
- component: {fileID: 7829576473989485776}
- component: {fileID: 5426390226938478828}
- component: {fileID: 2356989198378852018}
m_Layer: 0
m_Name: PopupStat
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1843470073663794312
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246834368258800846}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 292870618973774166}
- {fileID: 8849778187297648043}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 835.73267, y: -543.18}
m_SizeDelta: {x: 308.5346, y: 25.640076}
m_Pivot: {x: 0, y: 1}
--- !u!114 &7829576473989485776
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246834368258800846}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.HorizontalLayoutGroup
m_Padding:
m_Left: 18
m_Right: 10
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 0
m_Spacing: 5.4
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 0
m_ChildControlHeight: 0
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!114 &5426390226938478828
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246834368258800846}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.ContentSizeFitter
m_HorizontalFit: 0
m_VerticalFit: 0
--- !u!114 &2356989198378852018
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6246834368258800846}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.LayoutElement
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: 1
m_FlexibleHeight: 1
m_LayoutPriority: 1
--- !u!1 &9078345592336978365
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8849778187297648043}
- component: {fileID: 7828883841352225497}
- component: {fileID: 6763883082192230688}
m_Layer: 5
m_Name: value
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8849778187297648043
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9078345592336978365}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1843470073663794312}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 178.0124, y: 25.64}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7828883841352225497
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9078345592336978365}
m_CullTransparentMesh: 1
--- !u!114 &6763883082192230688
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9078345592336978365}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: New Text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 16
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 1.5
m_fontSizeMax: 16
m_fontStyle: 0
m_HorizontalAlignment: 1
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5882db210c62d8647858933649f64c29
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,184 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3157287847714375358
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3436634297340404643}
- component: {fileID: 386873398398603487}
- component: {fileID: 2506259255305457008}
- component: {fileID: 8858913019524689709}
- component: {fileID: 6923921070612219825}
m_Layer: 5
m_Name: PopupText
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3436634297340404643
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3157287847714375358}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 705.51843, y: -303.7433}
m_SizeDelta: {x: 133.05402, y: 0}
m_Pivot: {x: 0, y: 1}
--- !u!222 &386873398398603487
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3157287847714375358}
m_CullTransparentMesh: 1
--- !u!114 &2506259255305457008
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3157287847714375358}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: New Text New TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew Text New TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew Text New TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew TextNew
TextNew TextNew TextNew Text
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_sharedMaterial: {fileID: 9074173216178389243, guid: a0ee74bf6f853704a8a568d5ef638ee9, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 12
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 1.5
m_fontSizeMax: 12
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_characterHorizontalScale: 1
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_TextWrappingMode: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 0
m_ActiveFontFeatures: 6e72656b
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_EmojiFallbackSupport: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!114 &8858913019524689709
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3157287847714375358}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.LayoutElement
m_IgnoreLayout: 0
m_MinWidth: -1
m_MinHeight: -1
m_PreferredWidth: -1
m_PreferredHeight: -1
m_FlexibleWidth: 1
m_FlexibleHeight: 1
m_LayoutPriority: 1
--- !u!114 &6923921070612219825
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3157287847714375358}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.ContentSizeFitter
m_HorizontalFit: 0
m_VerticalFit: 2

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: bfa97c92d1878cc448ddc7dc456f4b17
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -596,6 +596,10 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: GUI value: GUI
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3496454433051527820, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_Enabled
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5178544305442097730, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3} - target: {fileID: 5178544305442097730, guid: ddc1b5dd628590a4084c1997dd102f62, type: 3}
propertyPath: m_Pivot.x propertyPath: m_Pivot.x
value: 0 value: 0

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 608491ce009b2494c894080b243698b9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "Jovian.PopupSystem.Editor",
"rootNamespace": "Jovian.PopupSystem.Editor",
"references": [
"Jovian.PopupSystem"
],
"includePlatforms": ["Editor"],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e663435ad13b46d40a29802dab7e52f5
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Jovian.PopupSystem.Editor {
[CustomPropertyDrawer(typeof(PopupCategory))]
public sealed class PopupCategoryDrawer : PropertyDrawer {
private static readonly string[] builtInIds = {
"Character",
"Item",
"Skill",
"General"
};
private const string customLabel = "Custom...";
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
var idProp = FindIdProperty(property);
if(idProp == null) {
return EditorGUIUtility.singleLineHeight;
}
var currentValue = idProp.stringValue ?? "";
var isCustom = Array.IndexOf(builtInIds, currentValue) < 0;
// Two lines when in custom mode: dropdown + text field
return isCustom
? EditorGUIUtility.singleLineHeight * 2 + 2
: EditorGUIUtility.singleLineHeight;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
var idProp = FindIdProperty(property);
if(idProp == null) {
EditorGUI.LabelField(position, label.text, "Cannot resolve PopupCategory id field");
EditorGUI.EndProperty();
return;
}
var currentValue = idProp.stringValue ?? "";
var builtInIndex = Array.IndexOf(builtInIds, currentValue);
var isCustom = builtInIndex < 0 && !string.IsNullOrEmpty(currentValue);
// Build display options: built-in entries + "Custom..."
var options = new List<string>(builtInIds);
options.Add(customLabel);
// Determine selected index
int selectedIndex;
if(builtInIndex >= 0) {
selectedIndex = builtInIndex;
}
else {
selectedIndex = options.Count - 1; // "Custom..."
}
// First line: dropdown
var dropdownRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
var newIndex = EditorGUI.Popup(dropdownRect, label.text, selectedIndex, options.ToArray());
if(newIndex != selectedIndex) {
if(newIndex < builtInIds.Length) {
idProp.stringValue = builtInIds[newIndex];
}
else {
// Switched to custom — seed with a placeholder if currently built-in
if(!isCustom) {
idProp.stringValue = "NewCategory";
}
}
}
// Second line: editable text field when custom
var finalIsCustom = newIndex >= builtInIds.Length || (newIndex == selectedIndex && isCustom);
if(finalIsCustom) {
var textRect = new Rect(
position.x + EditorGUIUtility.labelWidth + 2,
position.y + EditorGUIUtility.singleLineHeight + 2,
position.width - EditorGUIUtility.labelWidth - 2,
EditorGUIUtility.singleLineHeight);
var newValue = EditorGUI.TextField(textRect, idProp.stringValue);
if(newValue != idProp.stringValue) {
idProp.stringValue = newValue;
}
}
EditorGUI.EndProperty();
}
private static SerializedProperty FindIdProperty(SerializedProperty property) {
// readonly struct with [SerializeField] readonly string id
// Unity serializes this as "id" directly
var prop = property.FindPropertyRelative("id");
if(prop != null) {
return prop;
}
// Fallback: auto-property backing field pattern
return property.FindPropertyRelative("<id>k__BackingField");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9cc96a089d31fe14cbadf6c59ea0c9aa

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Jovian.PopupSystem.Editor {
/// <summary>
/// Custom PropertyDrawer for <see cref="PopupElementType"/>. Shows a dropdown with
/// built-in element types plus a "Custom..." option for free-text entry.
/// </summary>
[CustomPropertyDrawer(typeof(PopupElementType))]
public sealed class PopupElementTypeDrawer : PropertyDrawer {
private static readonly string[] builtInIds = {
"header",
"text",
"label_value_text",
"image",
"separator"
};
private const string customLabel = "Custom...";
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
var idProp = FindIdProperty(property);
if(idProp == null) {
return EditorGUIUtility.singleLineHeight;
}
var currentValue = idProp.stringValue ?? "";
var isCustom = Array.IndexOf(builtInIds, currentValue) < 0 && !string.IsNullOrEmpty(currentValue);
return isCustom
? EditorGUIUtility.singleLineHeight * 2 + 2
: EditorGUIUtility.singleLineHeight;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
var idProp = FindIdProperty(property);
if(idProp == null) {
EditorGUI.LabelField(position, label.text, "Cannot resolve PopupElementType id field");
EditorGUI.EndProperty();
return;
}
var currentValue = idProp.stringValue ?? "";
var builtInIndex = Array.IndexOf(builtInIds, currentValue);
var isCustom = builtInIndex < 0 && !string.IsNullOrEmpty(currentValue);
var options = new List<string>(builtInIds);
options.Add(customLabel);
int selectedIndex;
if(builtInIndex >= 0) {
selectedIndex = builtInIndex;
}
else {
selectedIndex = options.Count - 1;
}
var dropdownRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
var newIndex = EditorGUI.Popup(dropdownRect, label.text, selectedIndex, options.ToArray());
if(newIndex != selectedIndex) {
if(newIndex < builtInIds.Length) {
idProp.stringValue = builtInIds[newIndex];
}
else {
if(!isCustom) {
idProp.stringValue = "custom_element";
}
}
}
var finalIsCustom = newIndex >= builtInIds.Length || (newIndex == selectedIndex && isCustom);
if(finalIsCustom) {
var textRect = new Rect(
position.x + EditorGUIUtility.labelWidth + 2,
position.y + EditorGUIUtility.singleLineHeight + 2,
position.width - EditorGUIUtility.labelWidth - 2,
EditorGUIUtility.singleLineHeight);
var newValue = EditorGUI.TextField(textRect, idProp.stringValue);
if(newValue != idProp.stringValue) {
idProp.stringValue = newValue;
}
}
EditorGUI.EndProperty();
}
private static SerializedProperty FindIdProperty(SerializedProperty property) {
var prop = property.FindPropertyRelative("id");
if(prop != null) {
return prop;
}
return property.FindPropertyRelative("<id>k__BackingField");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9ea57be8755c60e4bbf156ac2b32c98c

View File

@@ -0,0 +1,80 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Jovian.PopupSystem.Editor {
public sealed class PopupSettingsProvider : SettingsProvider {
private PopupSettings settings;
private PopupSettingsProvider(string path, SettingsScope scope)
: base(path, scope) { }
private SerializedObject serializedSettings;
public override void OnActivate(string searchContext, UnityEngine.UIElements.VisualElement rootElement) {
var guids = AssetDatabase.FindAssets("t:PopupSettings");
if(guids.Length > 0) {
var path = AssetDatabase.GUIDToAssetPath(guids[0]);
settings = AssetDatabase.LoadAssetAtPath<PopupSettings>(path);
}
if(settings != null) {
serializedSettings = new SerializedObject(settings);
}
}
public override void OnGUI(string searchContext) {
if(settings == null) {
EditorGUILayout.HelpBox("No PopupSettings asset found. Create one via Assets > Create > Jovian > Popup System > Popup Settings.", MessageType.Warning);
return;
}
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Popup System Settings", EditorStyles.boldLabel);
EditorGUILayout.Space(5);
serializedSettings.Update();
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(serializedSettings.FindProperty("popupDelay"));
EditorGUILayout.PropertyField(serializedSettings.FindProperty("fadeDuration"));
EditorGUILayout.PropertyField(serializedSettings.FindProperty("defaultAnchorSide"));
EditorGUILayout.PropertyField(serializedSettings.FindProperty("screenEdgePadding"));
EditorGUILayout.PropertyField(serializedSettings.FindProperty("maxPopupWidth"));
EditorGUILayout.PropertyField(serializedSettings.FindProperty("sortingOrder"));
EditorGUILayout.Space(5);
EditorGUILayout.LabelField("Follow Mouse", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(serializedSettings.FindProperty("followMouseOffset"));
EditorGUILayout.Space(5);
EditorGUILayout.LabelField("Input", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(serializedSettings.FindProperty("touchHoldDuration"));
EditorGUILayout.PropertyField(serializedSettings.FindProperty("gamepadFocusTrigger"));
EditorGUILayout.Space(5);
EditorGUILayout.LabelField("Element Prefabs", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(serializedSettings.FindProperty("elementPrefabs"), true);
EditorGUILayout.Space(5);
EditorGUILayout.LabelField("Priority", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(serializedSettings.FindProperty("categoryPriorities"), true);
EditorGUILayout.Space(5);
EditorGUILayout.LabelField("Per-Category Overrides", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(serializedSettings.FindProperty("categoryDelayOverrides"), true);
if(EditorGUI.EndChangeCheck()) {
serializedSettings.ApplyModifiedProperties();
EditorUtility.SetDirty(settings);
}
}
[SettingsProvider]
public static SettingsProvider CreateProvider() {
var provider = new PopupSettingsProvider("Project/Jovian/Popup System", SettingsScope.Project) {
keywords = new HashSet<string>(new[] { "popup", "tooltip", "hover", "delay" })
};
return provider;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 63a03b88ed78a934094ce61f9d127ec9

View File

@@ -0,0 +1,344 @@
# Jovian Popup System
A lightweight, low-allocation popup and tooltip system for Unity with category-based isolation, a generic element cache, type-safe element identifiers, and extensible animations.
## Requirements
- Unity 2022.3 or later
- TextMeshPro 3.0.6+
- Input System 1.18.0+
- Newtonsoft JSON 3.2.1+
Install via the Unity Package Manager by adding the package from its local path or from a git URL.
## Quick Start
### 1. Create a PopupSettings asset
In the Unity Editor, go to **Assets > Create > Jovian > Popup System > Popup Settings**. Configure element prefabs by adding entries to the Element Prefabs list, mapping `PopupElementType` values to your prefabs.
### 2. Build a PopupReference prefab
See the [Prefab Setup](#prefab-setup) section below.
### 3. Create and use PopupSystem
```csharp
using Jovian.PopupSystem;
using Jovian.PopupSystem.UI;
// Create the system. canvasRoot auto-scans all PopupTrigger components.
var popup = new PopupSystem(settings, viewPrefab, canvasRoot);
popup.RegisterCategory(PopupCategory.Item);
popup.RegisterCategory(PopupCategory.Character);
// Set content on auto-scanned triggers by name.
var handler = popup.GetTriggerHandler("ItemSlot");
handler?.SetContent(builder => {
builder
.AddText("Health Potion", PopupElementType.Header)
.AddSeparator(PopupElementType.Separator)
.AddText("Restores health.", PopupElementType.Text)
.AddNameValue("Heal Amount", 50, PopupElementType.LabelValueText);
});
// Or show a popup directly from code.
popup.Show(PopupCategory.Item, builder => {
builder
.AddText("Iron Sword", PopupElementType.Header)
.AddNameValue("Damage", 12, PopupElementType.LabelValueText);
}, anchorRect, AnchorSide.Right);
// Tick each frame.
popup.Tick(Time.deltaTime);
// Clean up when the game state exits.
popup.Dispose();
```
## PopupElementType
`PopupElementType` is a type-safe struct identifying element prefabs in the registry. The Inspector shows a dropdown with built-in types plus a custom text field for game-specific elements.
### Built-in types
| Static Field | ID | Usage |
|---|---|---|
| `PopupElementType.Header` | `"header"` | Bold header text |
| `PopupElementType.Text` | `"text"` | Body text |
| `PopupElementType.LabelValueText` | `"label_value_text"` | Label + value row (two TMP_Text children) |
| `PopupElementType.Image` | `"image"` | Image/icon element |
| `PopupElementType.Separator` | `"separator"` | Horizontal divider line |
### Custom types
Define game-specific element types as static fields:
```csharp
public static class MyPopupElements {
public static readonly PopupElementType Badge = new("badge");
public static readonly PopupElementType ProgressBar = new("progress_bar");
}
```
### Variants
Create variants of built-in types using `Variant()`:
```csharp
// "header_gold" — a gold-styled header
PopupElementType.Header.Variant("gold")
// "separator_thick" — a thicker separator
PopupElementType.Separator.Variant("thick")
```
Register variant prefabs in PopupSettings with the variant ID (e.g. "header_gold").
## PopupCategory
`PopupCategory` is a readonly struct that acts as a channel for isolating popups. Each category gets its own view instance.
### Built-in categories
```csharp
PopupCategory.Character // Character tooltips
PopupCategory.Item // Item tooltips
PopupCategory.Skill // Skill tooltips
PopupCategory.General // General-purpose tooltips
```
### Custom categories
```csharp
var lootCategory = new PopupCategory("Loot");
popup.RegisterCategory(lootCategory, priority: 5);
```
## PopupSettings
ScriptableObject holding all configuration. Create via **Assets > Create > Jovian > Popup System > Popup Settings**.
| Field | Type | Default | Description |
|---|---|---|---|
| `popupDelay` | float | 0.4 | Seconds before popup appears. |
| `fadeDuration` | float | 0.2 | Fade animation duration. |
| `defaultAnchorSide` | AnchorSide | Below | Default anchor side. |
| `screenEdgePadding` | float | 10 | Minimum pixels from screen edge. |
| `maxPopupWidth` | float | 400 | Maximum popup width in pixels. |
| `sortingOrder` | int | 100 | Canvas sorting order. |
| `followMouseOffset` | Vector2 | (15, -15) | Cursor offset in follow mode. |
| `touchHoldDuration` | float | 0.6 | Touch hold duration. |
| `gamepadFocusTrigger` | bool | true | Trigger on gamepad focus. |
| `elementPrefabs` | List | empty | Element prefab registry (PopupElementType -> prefab). |
| `categoryPriorities` | List | empty | Per-category priority overrides. |
| `categoryDelayOverrides` | List | empty | Per-category delay overrides. |
## PopupContentBuilder
Fluent API struct for composing popup content. All methods take a `PopupElementType` to identify which prefab to use.
### Methods
```csharp
// Generic — returns raw GameObject for custom elements
builder.Add(PopupElementType.Header);
builder.Add(new PopupElementType("custom_widget"));
// Text — sets TMP_Text on the element
builder.AddText("Fireball", PopupElementType.Header);
builder.AddText("Body text here.", PopupElementType.Text);
builder.AddText("Colored text", "#FFD700", PopupElementType.Text);
// Name/Value — sets two TMP_Text children (label + value)
builder.AddNameValue("Damage", 120, PopupElementType.LabelValueText);
builder.AddNameValue("Range", "15m", PopupElementType.LabelValueText);
// Image — sets sprite and height
builder.AddImage(iconSprite, PopupElementType.Image, 64f);
// Separator
builder.AddSeparator(PopupElementType.Separator);
```
### Full example
```csharp
popup.Show(PopupCategory.Skill, builder => {
builder
.AddText("Fireball", PopupElementType.Header)
.AddText("Hurls a ball of fire.", PopupElementType.Text)
.AddSeparator(PopupElementType.Separator)
.AddNameValue("Damage", 120, PopupElementType.LabelValueText)
.AddNameValue("Mana Cost", 35, PopupElementType.LabelValueText)
.AddSeparator(PopupElementType.Separator)
.AddText("Requires: Level 5", "FF6666", PopupElementType.Text);
}, targetRect);
```
## PopupTrigger
MonoBehaviour attached to UI elements for hover-based popups. Forwards pointer events to a `PopupTriggerView` behavior handler.
### Inspector fields
| Field | Type | Description |
|---|---|---|
| `category` | PopupCategory | Which category channel to use. |
| `anchorSide` | AnchorSide | Which side to anchor the popup. |
| `positionMode` | PopupPositionMode | `AnchorToElement` or `FollowMouse`. |
### Approach 1: Auto-scanned triggers (recommended for static UI)
```csharp
var popup = new PopupSystem(settings, viewPrefab, canvasRoot);
popup.RegisterCategory(PopupCategory.Character);
// GetTriggerHandler returns PopupTriggerView (the behavior handler)
var handler = popup.GetTriggerHandler("HeroPortrait");
handler?.SetContent(builder => {
builder
.AddText("Kael", PopupElementType.Header)
.AddNameValue("Health", 55, PopupElementType.LabelValueText);
});
// Or all handlers for a category
foreach(var h in popup.GetTriggerHandlers(PopupCategory.Item)) {
h.SetContent(builder => builder.AddText("Item", PopupElementType.Header));
}
```
### Approach 2: Dynamic triggers (for runtime-created UI)
```csharp
popup.InitializeTriggersInChildren(slotsContainer, (trigger, view) => {
var slotData = trigger.GetComponentInParent<SlotComponent>();
view.SetContent(builder => {
builder.AddText(slotData.itemName, PopupElementType.Header);
});
});
```
### Approach 3: Code-only (no PopupTrigger needed)
```csharp
// Anchored
popupSystem.Show(PopupCategory.Item, builder => { ... }, targetRect, AnchorSide.Right);
// Follow mouse
popupSystem.Show(PopupCategory.General, builder => { ... });
// Fixed screen position
popupSystem.ShowAtPosition(PopupCategory.General, builder => { ... }, screenPos);
// Hide
popupSystem.Hide(PopupCategory.Item);
popupSystem.HideAll();
```
## Priority System
Higher priority categories dismiss lower ones when shown:
```csharp
popup.RegisterCategory(PopupCategory.Character, priority: 10);
popup.RegisterCategory(PopupCategory.Item, priority: 5);
```
Settings-based priorities take precedence over registration arguments.
## Lifecycle Integration
Created per game state, not as a singleton:
```csharp
var guiCanvas = guiReferences.GetComponentInParent<Canvas>().transform;
var popupSystem = new PopupSystem(popupSettings, popupViewPrefab, guiCanvas);
popupSystem.RegisterCategory(PopupCategory.Character, priority: 10);
// Tick each frame
popupSystem.Tick(Time.deltaTime);
// Dispose on state exit
popupSystem.Dispose();
```
## IPopupAnimator
Extensible show/hide animation interface. Default: `FadePopupAnimator` (alpha lerp). Pass a factory to the constructor:
```csharp
var popup = new PopupSystem(settings, viewPrefab, canvasRoot, () => new ScalePopupAnimator());
```
## Prefab Setup
```
PopupReferencePrefab Canvas, CanvasGroup, CanvasScaler, PopupReference
Background Image, ContentSizeFitter (V=Preferred)
Content VerticalLayoutGroup (Control Child Width, Force Expand Width)
```
1. **Root**: Canvas (Screen Space Overlay), CanvasScaler (Scale With Screen Size), CanvasGroup, PopupReference. Point anchors, no ContentSizeFitter.
2. **Background**: Image, ContentSizeFitter (Vertical = Preferred).
3. **Content**: Stretched to Background, VerticalLayoutGroup (Control Child Size Width, Child Force Expand Width), no ContentSizeFitter.
4. **Element prefabs**: Create separate prefabs, register in PopupSettings under Element Prefabs with their `PopupElementType`. No ContentSizeFitter on element prefabs.
5. **Wire PopupReference**: Assign Content, CanvasGroup, and Background fields.
## Optimization Notes
- `PopupCategory` and `PopupElementType` are value-type structs — zero heap allocation
- `PopupContentBuilder` is a readonly struct operating directly on cached elements
- Content elements use a **grow-only cache** keyed by `PopupElementType` — activate/deactivate, never destroy after warmup
- Delay timers and animation driven by float fields in `Tick()` — no coroutines
- Screen rect uses static `Vector3[4]` buffer — no per-frame allocation
- Layout rebuilds only on content change (dirty flag)
- Each category gets its own `IPopupAnimator` — no concurrent animation corruption
- MonoBehaviour (`PopupReference`, `PopupTrigger`) holds references only; all behavior in plain C# classes (`PopupView`, `PopupTriggerView`)
## Samples
The `Samples~` folder contains:
- **Prefabs**: PopupReferencePrefab and all element prefabs
- **Settings**: Pre-configured PopupSettings asset
- **Scripts**: Three example scripts (auto-scanned triggers, dynamic triggers, code-only with variants)
Import via Unity Package Manager: select the package, expand Samples, click Import.
## API Reference
### Core Types
| Type | Namespace | Description |
|---|---|---|
| `IPopupSystem` | `Jovian.PopupSystem` | Main interface for showing/hiding popups. |
| `PopupSystem` | `Jovian.PopupSystem` | Implementation. Constructor: `(PopupSettings, PopupReference, Transform, Func<IPopupAnimator>)`. |
| `PopupView` | `Jovian.PopupSystem` | Behavior class: generic element cache, positioning, visibility. |
| `PopupSettings` | `Jovian.PopupSystem` | ScriptableObject configuration + element prefab registry. |
| `PopupCategory` | `Jovian.PopupSystem` | Struct identifying a popup channel. |
| `PopupElementType` | `Jovian.PopupSystem` | Struct identifying an element prefab type. Built-ins + Variant(). |
| `PopupContentBuilder` | `Jovian.PopupSystem` | Fluent readonly struct for building content. |
### UI Types
| Type | Namespace | Description |
|---|---|---|
| `PopupReference` | `Jovian.PopupSystem.UI` | MonoBehaviour reference holder (content, canvasGroup, background). |
| `PopupTrigger` | `Jovian.PopupSystem.UI` | MonoBehaviour reference holder for hover triggers. |
| `PopupTriggerView` | `Jovian.PopupSystem` | Behavior handler for triggers (SetContent, pointer forwarding). |
### Animation Types
| Type | Namespace | Description |
|---|---|---|
| `IPopupAnimator` | `Jovian.PopupSystem` | Interface for custom show/hide animations. |
| `FadePopupAnimator` | `Jovian.PopupSystem` | Default fade animation via CanvasGroup alpha. |
### Enums
| Type | Values |
|---|---|
| `AnchorSide` | `Below`, `Above`, `Left`, `Right` |
| `PopupPositionMode` | `AnchorToElement`, `FollowMouse` |

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d33518dac7899604c9ceeda21897315d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 05f691cbfb7413f4fb735b2ec732ff06
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using System;
using UnityEngine;
namespace Jovian.PopupSystem {
/// <summary>
/// Default popup animator that fades CanvasGroup alpha. Each category gets its own instance
/// so concurrent show/hide animations don't corrupt each other.
/// </summary>
public sealed class FadePopupAnimator : IPopupAnimator {
private CanvasGroup target;
private float timer;
private float elapsed;
private float startAlpha;
private float endAlpha;
private Action onFinish;
public bool IsAnimating => target != null;
public void Show(CanvasGroup canvasGroup, float duration, Action onComplete) {
target = canvasGroup;
timer = Mathf.Max(duration, 0.001f);
elapsed = 0f;
startAlpha = 0f;
endAlpha = 1f;
onFinish = onComplete;
canvasGroup.alpha = 0f;
}
public void Hide(CanvasGroup canvasGroup, float duration, Action onComplete) {
target = canvasGroup;
timer = Mathf.Max(duration, 0.001f);
elapsed = 0f;
startAlpha = canvasGroup.alpha;
endAlpha = 0f;
onFinish = onComplete;
}
public void Tick(float deltaTime) {
if(target == null) {
return;
}
elapsed += deltaTime;
var t = Mathf.Clamp01(elapsed / timer);
target.alpha = Mathf.Lerp(startAlpha, endAlpha, t);
if(!(t >= 1f)) {
return;
}
var callback = onFinish;
target = null;
onFinish = null;
callback?.Invoke();
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 254bb620ce056dd41905258eb0f070d7

View File

@@ -0,0 +1,37 @@
using System;
using UnityEngine;
namespace Jovian.PopupSystem {
/// <summary>
/// Interface for popup show/hide animations. Each registered category gets its own instance
/// to prevent state corruption during concurrent animations. Driven by float timers in
/// <see cref="Tick"/>, not coroutines.
/// </summary>
public interface IPopupAnimator {
/// <summary>
/// Begins a show animation on the given CanvasGroup. Typically fades alpha from 0 to 1.
/// </summary>
/// <param name="canvasGroup">The CanvasGroup to animate.</param>
/// <param name="duration">Animation duration in seconds.</param>
/// <param name="onComplete">Callback invoked when the animation finishes. May be null.</param>
void Show(CanvasGroup canvasGroup, float duration, Action onComplete);
/// <summary>
/// Begins a hide animation on the given CanvasGroup. Typically fades alpha to 0.
/// </summary>
/// <param name="canvasGroup">The CanvasGroup to animate.</param>
/// <param name="duration">Animation duration in seconds.</param>
/// <param name="onComplete">Callback invoked when the animation finishes. May be null.</param>
void Hide(CanvasGroup canvasGroup, float duration, Action onComplete);
/// <summary>
/// Advances the animation by deltaTime. Call every frame from <see cref="IPopupSystem.Tick"/>.
/// </summary>
void Tick(float deltaTime);
/// <summary>
/// True if an animation is currently in progress.
/// </summary>
bool IsAnimating { get; }
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b146d885db3dcef4fa70abd3f43683d3

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using Jovian.PopupSystem.UI;
using UnityEngine;
namespace Jovian.PopupSystem {
/// <summary>
/// Core interface for the popup system. Created per game state, not as a singleton.
/// Manages category registration, trigger discovery, popup display, and lifecycle.
/// </summary>
public interface IPopupSystem {
/// <summary>
/// Scans all <see cref="PopupTrigger"/> components under the given parent and binds them
/// to this system. Each trigger receives a <see cref="PopupTriggerView"/> for behavior.
/// </summary>
void ScanTriggers(Transform parent);
/// <summary>
/// Scans all <see cref="PopupTrigger"/> components under the given parent, binds them,
/// and invokes the configure callback with both the trigger (for hierarchy queries) and
/// its view (for setting content).
/// </summary>
void InitializeTriggersInChildren(Transform parent, Action<PopupTrigger, PopupTriggerView> configureTrigger);
/// <summary>
/// Returns the <see cref="PopupTriggerView"/> for the first registered trigger whose
/// GameObject name matches. Returns null if not found.
/// </summary>
PopupTriggerView GetTriggerHandler(string gameObjectName);
/// <summary>
/// Returns all <see cref="PopupTriggerView"/> instances registered under the given category.
/// </summary>
IReadOnlyList<PopupTriggerView> GetTriggerHandlers(PopupCategory category);
/// <summary>
/// Registers a popup category. Each category gets its own <see cref="PopupReference"/> instance
/// (lazily created on first show) and its own <see cref="IPopupAnimator"/>.
/// </summary>
/// <param name="category">The category to register.</param>
/// <param name="priority">Fallback priority if not defined in <see cref="PopupSettings"/>. Higher dismisses lower.</param>
void RegisterCategory(PopupCategory category, int priority = 0);
/// <summary>
/// Shows a popup for the given category after the configured delay. The build callback
/// populates content via <see cref="PopupContentBuilder"/>. Optionally anchors to a
/// RectTransform or follows the mouse if no anchor is provided.
/// </summary>
void Show(PopupCategory category, Action<PopupContentBuilder> buildContent,
RectTransform anchor = null, AnchorSide? anchorSide = null);
/// <summary>
/// Shows a popup for the given category at a fixed screen position.
/// </summary>
void ShowAtPosition(PopupCategory category, Action<PopupContentBuilder> buildContent,
Vector2 screenPosition);
/// <summary>
/// Hides the popup for the given category with a fade-out animation.
/// </summary>
void Hide(PopupCategory category);
/// <summary>
/// Hides all visible popups across all categories.
/// </summary>
void HideAll();
/// <summary>
/// Drives delay timers, animations, and follow-mouse positioning. Call every frame.
/// </summary>
void Tick(float deltaTime);
/// <summary>
/// Destroys all popup view GameObjects and clears registered categories.
/// Call when the owning game state exits.
/// </summary>
void Dispose();
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 65d563f87bb09de48b8edd12101cdd11

View File

@@ -0,0 +1,19 @@
{
"name": "Jovian.PopupSystem",
"rootNamespace": "Jovian.PopupSystem",
"references": [
"Unity.TextMeshPro",
"Unity.InputSystem"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"Newtonsoft.Json.dll"
],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 31bcaef770c58d94db7f78106f15fd4e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System;
using UnityEngine;
namespace Jovian.PopupSystem {
/// <summary>
/// Value type identifying a popup channel. Each category gets its own popup view instance.
/// Compared by string ID using ordinal comparison. Define custom categories as static fields.
/// </summary>
[Serializable]
public struct PopupCategory : IEquatable<PopupCategory> {
[SerializeField] string id;
public string Id => id;
public PopupCategory(string id) {
this.id = id;
}
public static readonly PopupCategory Character = new("Character");
public static readonly PopupCategory Item = new("Item");
public static readonly PopupCategory Skill = new("Skill");
public static readonly PopupCategory General = new("General");
public bool Equals(PopupCategory other) {
return string.Equals(id, other.id, StringComparison.Ordinal);
}
public override bool Equals(object obj) {
return obj is PopupCategory other && Equals(other);
}
public override int GetHashCode() {
return id != null ? id.GetHashCode() : 0;
}
public override string ToString() {
return id ?? string.Empty;
}
public static bool operator ==(PopupCategory left, PopupCategory right) {
return left.Equals(right);
}
public static bool operator !=(PopupCategory left, PopupCategory right) {
return !left.Equals(right);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bcd1fb0ef93fed0489a43977bc71594b

View File

@@ -0,0 +1,15 @@
using System;
using Newtonsoft.Json;
namespace Jovian.PopupSystem {
public sealed class PopupCategoryJsonConverter : JsonConverter<PopupCategory> {
public override void WriteJson(JsonWriter writer, PopupCategory value, JsonSerializer serializer) {
writer.WriteValue(value.Id);
}
public override PopupCategory ReadJson(JsonReader reader, Type objectType, PopupCategory existingValue, bool hasExistingValue, JsonSerializer serializer) {
var id = reader.Value as string;
return new PopupCategory(id);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 683182ef8e2aa6b4daffc547c481b768

View File

@@ -0,0 +1,115 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace Jovian.PopupSystem {
/// <summary>
/// Fluent API struct for building popup content. Operates on the generic element cache
/// inside a <see cref="PopupView"/>. Received in the build callback passed to
/// <see cref="IPopupSystem.Show"/>. Use <see cref="Add"/> for fully custom elements,
/// or convenience methods for common types.
/// </summary>
public readonly struct PopupContentBuilder {
readonly PopupView view;
/// <summary>
/// Creates a builder targeting the given popup view.
/// </summary>
public PopupContentBuilder(PopupView view) {
this.view = view;
}
/// <summary>
/// Returns a cached or newly instantiated element by its registered type.
/// Use this for fully custom or game-specific element types.
/// </summary>
public GameObject Add(PopupElementType elementType) {
return view.GetElement(elementType);
}
/// <summary>
/// Adds a text element using the given element type and sets its TMP_Text content.
/// </summary>
public PopupContentBuilder AddText(string text, PopupElementType elementType) {
var go = view.GetElement(elementType);
if(go == null) {
return this;
}
var tmp = go.GetComponentInChildren<TMP_Text>();
if(tmp) {
tmp.text = text;
}
return this;
}
/// <summary>
/// Adds a colored text element using the given element type.
/// Hex color can be with or without the # prefix.
/// </summary>
public PopupContentBuilder AddText(string text, string hexColor, PopupElementType elementType) {
var go = view.GetElement(elementType);
if(!go) {
return this;
}
var tmp = go.GetComponentInChildren<TMP_Text>();
if(!tmp) {
return this;
}
var prefix = hexColor.Length > 0 && hexColor[0] == '#' ? "" : "#";
tmp.text = $"<color={prefix}{hexColor}>{text}</color>";
return this;
}
/// <summary>
/// Adds a name/value row using the given element type. The prefab must have
/// exactly two TMP_Text children (label first, value second).
/// </summary>
public PopupContentBuilder AddNameValue(string label, int value, PopupElementType elementType) {
return AddNameValueInternal(elementType, label, value.ToString());
}
/// <summary>
/// Adds a name/value row using the given element type. The prefab must have
/// exactly two TMP_Text children (label first, value second).
/// </summary>
public PopupContentBuilder AddNameValue(string label, string value, PopupElementType elementType) {
return AddNameValueInternal(elementType, label, value);
}
private PopupContentBuilder AddNameValueInternal(PopupElementType elementType, string label, string value) {
var go = view.GetElement(elementType);
if(go != null) {
var children = go.GetComponentsInChildren<TMP_Text>(true);
if(children.Length >= 2) {
children[0].text = label;
children[1].text = value;
}
}
return this;
}
/// <summary>
/// Adds an image element with the given sprite and optional height.
/// </summary>
public PopupContentBuilder AddImage(Sprite sprite, PopupElementType elementType, float height = 64f) {
var go = view.GetElement(elementType);
if(go != null) {
var image = go.GetComponentInChildren<Image>();
if(image != null) {
image.sprite = sprite;
var rt = (RectTransform)image.transform;
rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
}
}
return this;
}
/// <summary>
/// Adds a separator element using the given element type.
/// </summary>
public PopupContentBuilder AddSeparator(PopupElementType elementType) {
view.GetElement(elementType);
return this;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b9f4094c471d0464e95e330331acc813

View File

@@ -0,0 +1,74 @@
using System;
using UnityEngine;
namespace Jovian.PopupSystem {
/// <summary>
/// Value type identifying a popup element prefab. Compared by string ID using ordinal
/// comparison. Built-in types cover common popup elements. Define custom types as static
/// fields or create instances for game-specific elements and variants.
/// </summary>
[Serializable]
public struct PopupElementType : IEquatable<PopupElementType> {
[SerializeField] private string id;
/// <summary>The string identifier for this element type.</summary>
public string Id => id;
public PopupElementType(string id) {
this.id = id;
}
// --- Built-in types ---
/// <summary>Bold header text element.</summary>
public static readonly PopupElementType Header = new("header");
/// <summary>Body text element.</summary>
public static readonly PopupElementType Text = new("text");
/// <summary>Label + value stat row element.</summary>
public static readonly PopupElementType LabelValueText = new("label_value_text");
/// <summary>Image/icon element.</summary>
public static readonly PopupElementType Image = new("image");
/// <summary>Horizontal separator line.</summary>
public static readonly PopupElementType Separator = new("separator");
// --- Variant helper ---
/// <summary>
/// Creates a variant of this element type by appending a suffix.
/// e.g. <c>PopupElementType.Header.Variant("gold")</c> produces <c>"header_gold"</c>.
/// </summary>
public PopupElementType Variant(string variant) {
return new PopupElementType($"{id}_{variant}");
}
// --- Equality ---
public bool Equals(PopupElementType other) {
return string.Equals(id, other.id, StringComparison.Ordinal);
}
public override bool Equals(object obj) {
return obj is PopupElementType other && Equals(other);
}
public override int GetHashCode() {
return id != null ? id.GetHashCode() : 0;
}
public override string ToString() {
return id ?? string.Empty;
}
public static bool operator ==(PopupElementType left, PopupElementType right) {
return left.Equals(right);
}
public static bool operator !=(PopupElementType left, PopupElementType right) {
return !left.Equals(right);
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5ba7e78e3d930334a935a600a8f67ded

View File

@@ -0,0 +1,13 @@
namespace Jovian.PopupSystem {
public enum AnchorSide {
Below,
Above,
Left,
Right
}
public enum PopupPositionMode {
AnchorToElement,
FollowMouse
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 01e69680e496eca4daebbc1874e3a7d9

View File

@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Jovian.PopupSystem {
/// <summary>
/// ScriptableObject holding all popup system configuration. Create via
/// Assets > Create > Jovian > Popup System > Popup Settings.
/// </summary>
[CreateAssetMenu(fileName = "PopupSettings", menuName = "Jovian/Popup System/Popup Settings")]
public class PopupSettings : ScriptableObject {
[Header("General")]
public float popupDelay = 0.4f;
public float fadeDuration = 0.2f;
public AnchorSide defaultAnchorSide = AnchorSide.Below;
public float screenEdgePadding = 10f;
public float maxPopupWidth = 400f;
public int sortingOrder = 100;
[Header("Follow Mouse")]
public Vector2 followMouseOffset = new(15f, -15f);
[Header("Input")]
public float touchHoldDuration = 0.6f;
public bool gamepadFocusTrigger = true;
[Header("Element Prefabs")]
public List<PopupElementEntry> elementPrefabs = new();
[Header("Priority")]
public List<CategoryPriority> categoryPriorities = new();
[Header("Per-Category Overrides")]
public List<CategoryDelay> categoryDelayOverrides = new();
private Dictionary<PopupElementType, GameObject> prefabLookup;
/// <summary>
/// Returns the element prefab registered under the given type, or null if not found.
/// </summary>
public GameObject GetPrefab(PopupElementType elementType) {
if(prefabLookup == null) {
prefabLookup = new Dictionary<PopupElementType, GameObject>();
foreach(var entry in elementPrefabs) {
if(!string.IsNullOrEmpty(entry.type.Id) && entry.prefab != null) {
prefabLookup[entry.type] = entry.prefab;
}
}
}
prefabLookup.TryGetValue(elementType, out var result);
return result;
}
/// <summary>
/// Returns the configured priority for a category, or 0 if not configured.
/// </summary>
public int GetPriority(PopupCategory category) {
foreach(var cp in categoryPriorities) {
if(cp.category == category) {
return cp.priority;
}
}
return 0;
}
/// <summary>
/// Returns the configured delay override for a category, or the default popupDelay.
/// </summary>
public float GetDelay(PopupCategory category) {
foreach(var cd in categoryDelayOverrides) {
if(cd.category == category) {
return cd.delay;
}
}
return popupDelay;
}
}
[Serializable]
public sealed class PopupElementEntry {
public PopupElementType type;
public GameObject prefab;
}
[Serializable]
public sealed class CategoryPriority {
public PopupCategory category;
public int priority;
}
[Serializable]
public sealed class CategoryDelay {
public PopupCategory category;
public float delay;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e38e313f3665d464b82b22699b2a4634

View File

@@ -0,0 +1,282 @@
using System;
using System.Collections.Generic;
using Jovian.PopupSystem.UI;
using UnityEngine;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace Jovian.PopupSystem {
/// <summary>
/// Core implementation of <see cref="IPopupSystem"/>. Created per game state, not as a singleton.
/// Manages category registration, trigger discovery, popup lifecycle, priority dismissal, and
/// tick-driven delay timers and animations. Pass a canvasParent to auto-scan triggers on construction.
/// </summary>
public sealed class PopupSystem : IPopupSystem {
readonly PopupSettings settings;
readonly PopupReference viewPrefab;
readonly Func<IPopupAnimator> animatorFactory;
readonly Transform canvasParent;
readonly Dictionary<PopupCategory, ViewState> categories = new();
readonly List<PopupTrigger> registeredTriggers = new();
/// <summary>
/// Creates a new popup system instance.
/// </summary>
/// <param name="settings">Configuration ScriptableObject with delays, priorities, and display settings.</param>
/// <param name="viewPrefab">The PopupReference prefab to instantiate per category.</param>
/// <param name="canvasParent">Optional parent Canvas transform. When provided, popup views are parented
/// here (inheriting CanvasScaler) and all PopupTrigger components are auto-scanned.</param>
/// <param name="animatorFactory">Optional factory for custom animators. Defaults to FadePopupAnimator.</param>
public PopupSystem(PopupSettings settings, PopupReference viewPrefab, Transform canvasParent = null, Func<IPopupAnimator> animatorFactory = null) {
this.settings = settings;
this.viewPrefab = viewPrefab;
this.canvasParent = canvasParent;
this.animatorFactory = animatorFactory ?? (() => new FadePopupAnimator());
// Auto-scan if a parent was provided
if(canvasParent != null) {
ScanTriggers(canvasParent);
}
}
/// <inheritdoc />
public void RegisterCategory(PopupCategory category, int priority = 0) {
if(categories.ContainsKey(category)) {
return;
}
var effectivePriority = settings.GetPriority(category);
if(effectivePriority == 0) {
effectivePriority = priority;
}
categories[category] = new ViewState {
priority = effectivePriority,
delay = settings.GetDelay(category),
animator = animatorFactory()
};
}
/// <inheritdoc />
public void Show(PopupCategory category, Action<PopupContentBuilder> buildContent,
RectTransform anchor = null, AnchorSide? anchorSide = null) {
if(!categories.TryGetValue(category, out var state)) {
return;
}
DismissLowerPriority(state.priority);
state.pendingBuild = buildContent;
state.pendingAnchor = anchor;
state.pendingAnchorSide = anchorSide ?? settings.defaultAnchorSide;
state.pendingScreenPos = null;
state.delayTimer = state.delay;
state.isPending = true;
}
/// <inheritdoc />
public void ShowAtPosition(PopupCategory category, Action<PopupContentBuilder> buildContent,
Vector2 screenPosition) {
if(!categories.TryGetValue(category, out var state)) {
return;
}
DismissLowerPriority(state.priority);
state.pendingBuild = buildContent;
state.pendingAnchor = null;
state.pendingScreenPos = screenPosition;
state.delayTimer = state.delay;
state.isPending = true;
}
/// <inheritdoc />
public void Hide(PopupCategory category) {
if(!categories.TryGetValue(category, out var state)) {
return;
}
state.isPending = false;
if(state.view != null && state.view.IsVisible) {
state.animator.Hide(state.view.CanvasGroup, settings.fadeDuration, () => {
state.view.SetVisible(false);
});
}
}
/// <inheritdoc />
public void HideAll() {
foreach(var kvp in categories) {
Hide(kvp.Key);
}
}
/// <inheritdoc />
public void Tick(float deltaTime) {
foreach(var kvp in categories) {
kvp.Value.animator.Tick(deltaTime);
}
foreach(var kvp in categories) {
var state = kvp.Value;
if(!state.isPending) {
continue;
}
state.delayTimer -= deltaTime;
if(state.delayTimer > 0f) {
continue;
}
state.isPending = false;
ShowImmediate(state);
}
foreach(var kvp in categories) {
var state = kvp.Value;
if(state.view != null && state.view.IsVisible && state.isFollowMouse) {
state.view.UpdatePosition();
}
}
}
/// <inheritdoc />
public void ScanTriggers(Transform parent) {
var triggers = parent.GetComponentsInChildren<PopupTrigger>(true);
foreach(var trigger in triggers) {
if(!registeredTriggers.Contains(trigger)) {
BindTrigger(trigger);
}
}
}
/// <inheritdoc />
public PopupTriggerView GetTriggerHandler(string gameObjectName) {
foreach(var trigger in registeredTriggers) {
if(trigger != null && trigger.gameObject.name == gameObjectName) {
return trigger.Handler;
}
}
return null;
}
/// <inheritdoc />
public IReadOnlyList<PopupTriggerView> GetTriggerHandlers(PopupCategory category) {
var result = new List<PopupTriggerView>();
foreach(var trigger in registeredTriggers) {
if(trigger != null && trigger.Category == category && trigger.Handler != null) {
result.Add(trigger.Handler);
}
}
return result;
}
/// <inheritdoc />
public void InitializeTriggersInChildren(Transform parent, Action<PopupTrigger, PopupTriggerView> configureTrigger) {
var triggers = parent.GetComponentsInChildren<PopupTrigger>(true);
foreach(var trigger in triggers) {
if(!registeredTriggers.Contains(trigger)) {
BindTrigger(trigger);
}
configureTrigger(trigger, trigger.Handler);
}
}
private void BindTrigger(PopupTrigger trigger) {
var handler = new PopupTriggerView(this);
trigger.Bind(handler);
registeredTriggers.Add(trigger);
}
/// <inheritdoc />
public void Dispose() {
foreach(var kvp in categories) {
if(kvp.Value.view?.Reference != null) {
Object.Destroy(kvp.Value.view.Reference.gameObject);
}
}
categories.Clear();
}
private void ShowImmediate(ViewState state) {
EnsureView(state);
state.view.ClearContent();
var builder = new PopupContentBuilder(state.view);
state.pendingBuild?.Invoke(builder);
// Activate before layout rebuild so Unity has an active hierarchy to calculate
state.view.CanvasGroup.alpha = 0f;
state.view.SetVisible(true);
// Force full layout rebuild so positioning has correct size on first show
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(state.view.Content);
LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)state.view.Transform);
if(state.pendingScreenPos.HasValue) {
state.view.SetFixedPosition(state.pendingScreenPos.Value, settings.screenEdgePadding);
state.isFollowMouse = false;
}
else if(state.pendingAnchor != null) {
state.view.SetAnchorMode(state.pendingAnchor, state.pendingAnchorSide, settings.screenEdgePadding);
state.isFollowMouse = false;
}
else {
state.view.SetFollowMouseMode(settings.followMouseOffset, settings.screenEdgePadding);
state.isFollowMouse = true;
}
state.view.UpdatePosition();
state.animator.Show(state.view.CanvasGroup, settings.fadeDuration, null);
}
private void EnsureView(ViewState state) {
if(state.view != null) {
return;
}
PopupReference popupRef;
if(canvasParent != null) {
popupRef = Object.Instantiate(viewPrefab, canvasParent);
}
else {
popupRef = Object.Instantiate(viewPrefab);
}
var canvas = popupRef.GetComponent<Canvas>();
if(canvas != null) {
canvas.overrideSorting = true;
canvas.sortingOrder = settings.sortingOrder;
}
state.view = new PopupView(popupRef, settings);
state.view.SetVisible(false);
state.view.SetMaxWidth(settings.maxPopupWidth);
}
private void DismissLowerPriority(int showingPriority) {
foreach(var kvp in categories) {
var state = kvp.Value;
if(state.priority < showingPriority && state.view != null && state.view.IsVisible) {
state.isPending = false;
state.animator.Hide(state.view.CanvasGroup, settings.fadeDuration, () => {
state.view.SetVisible(false);
});
}
}
}
private sealed class ViewState {
public PopupView view;
public IPopupAnimator animator;
public int priority;
public float delay;
public float delayTimer;
public bool isPending;
public bool isFollowMouse;
public Action<PopupContentBuilder> pendingBuild;
public RectTransform pendingAnchor;
public AnchorSide pendingAnchorSide;
public Vector2? pendingScreenPos;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 056ed88d12add674798ad4e6300bf222

View File

@@ -0,0 +1,54 @@
using System;
using Jovian.PopupSystem.UI;
using UnityEngine;
namespace Jovian.PopupSystem {
/// <summary>
/// Handles popup behavior for a <see cref="PopupTrigger"/>. Holds the content callback and
/// forwards pointer events to the <see cref="IPopupSystem"/>. This is the behavior layer;
/// the MonoBehaviour trigger is the reference holder that forwards events here.
/// </summary>
public sealed class PopupTriggerView {
readonly IPopupSystem popupSystem;
Action<PopupContentBuilder> contentCallback;
/// <summary>
/// Creates a new trigger view bound to the given popup system.
/// </summary>
public PopupTriggerView(IPopupSystem popupSystem) {
this.popupSystem = popupSystem;
}
/// <summary>
/// Sets the content builder callback that will be invoked when the popup is shown.
/// </summary>
public void SetContent(Action<PopupContentBuilder> callback) {
contentCallback = callback;
}
/// <summary>
/// Called by <see cref="PopupTrigger"/> when the pointer enters. Reads the trigger's
/// category, anchor side, and position mode to show the popup.
/// </summary>
public void OnPointerEnter(PopupTrigger trigger) {
if(popupSystem == null || contentCallback == null) {
return;
}
if(trigger.PositionMode == PopupPositionMode.AnchorToElement) {
popupSystem.Show(trigger.Category, contentCallback, (RectTransform)trigger.transform, trigger.AnchorSide);
}
else {
popupSystem.Show(trigger.Category, contentCallback);
}
}
/// <summary>
/// Called by <see cref="PopupTrigger"/> when the pointer exits. Hides the popup
/// for the trigger's category.
/// </summary>
public void OnPointerExit(PopupTrigger trigger) {
popupSystem?.Hide(trigger.Category);
}
}
}

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