forked from Shardstone/trail-into-darkness
Compare commits
9 Commits
character-
...
popup-syst
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfe202da44 | ||
|
|
fa7659d905 | ||
|
|
f42885830a | ||
|
|
333539eb0e | ||
|
|
9488b98f54 | ||
|
|
b8fa26865d | ||
|
|
cbf9f384d9 | ||
|
|
61ca3701ae | ||
|
|
a807405585 |
@@ -22,7 +22,8 @@
|
||||
"Bash(xxd Packages/com.jovian.ingame-logging/Runtime/GameLogStore.cs)",
|
||||
"Bash(find D:/repos/trail-into-darkness/Assets -name *.asmdef)",
|
||||
"Bash(grep -E \"\\\\.\\(prefab|unity\\)$\")",
|
||||
"Bash(python3:*)"
|
||||
"Bash(python3:*)",
|
||||
"WebSearch"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ MonoBehaviour:
|
||||
m_Name: AddressableAssetGroupSortSettings
|
||||
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.GroupSchemas.AddressableAssetGroupSortSettings
|
||||
sortOrder:
|
||||
- 05b724f967e7d40e69a2f8086a7d78cd
|
||||
- d7f58d36cc4da874fa45d38c0070c2c2
|
||||
- e6a1448ac7179f9469ae917578605c81
|
||||
- a8838bd8f2db41d4c894d2cf8403f207
|
||||
|
||||
@@ -12,7 +12,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 468a46d0ae32c3544b7d98094e6448a9, type: 3}
|
||||
m_Name: AddressableAssetSettings
|
||||
m_EditorClassIdentifier: Unity.Addressables.Editor::UnityEditor.AddressableAssets.Settings.AddressableAssetSettings
|
||||
m_DefaultGroup: 05b724f967e7d40e69a2f8086a7d78cd
|
||||
m_DefaultGroup: d7f58d36cc4da874fa45d38c0070c2c2
|
||||
m_currentHash:
|
||||
serializedVersion: 2
|
||||
Hash: 00000000000000000000000000000000
|
||||
@@ -60,7 +60,6 @@ MonoBehaviour:
|
||||
m_BuildAddressablesWithPlayerBuild: 0
|
||||
m_overridePlayerVersion: '[UnityEditor.PlayerSettings.bundleVersion]'
|
||||
m_GroupAssets:
|
||||
- {fileID: 11400000, guid: 6c79f6f00c1f84b1c854543c84d05d0f, type: 2}
|
||||
- {fileID: 11400000, guid: 8aabd2323ded16346970904048573037, type: 2}
|
||||
- {fileID: 11400000, guid: 643aef87ff0fa05488c1a0982ec49f26, type: 2}
|
||||
- {fileID: 11400000, guid: 2ddfa0c67160cbe4f9669d176f0ee01b, type: 2}
|
||||
|
||||
@@ -40,11 +40,21 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 15529a69a8231ac43b1108efbaad83b6
|
||||
m_Address: Assets/Prefabs/UI/CharacterCreationReference.prefab
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 21833c6afc1e0b047a3c49dc9ea35996
|
||||
m_Address: Assets/Art/UI/portait_hero_05.png
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 2dfcc209b5aff734d863147e5614563c
|
||||
m_Address: PopupReferencePrefab
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 3225768f79644af4dbda96b8f9d57ed2
|
||||
m_Address: Assets/Art/UI/menu_supply_bar_full.png
|
||||
m_ReadOnly: 0
|
||||
@@ -75,6 +85,11 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 571f2dd77fb442d499cdc9c2afe9f98d
|
||||
m_Address: PopupSettings
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: 60a7c1e10ed7ff94cbe191d9d3e305ed
|
||||
m_Address: Assets/Art/UI/menu_corner.png
|
||||
m_ReadOnly: 0
|
||||
@@ -206,6 +221,11 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: ed9b80145a89c8a4f8d456971d242c3c
|
||||
m_Address: PortraitsHolder
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: f37df040ec9864f4dbafe3f5e6dfe4d9
|
||||
m_Address: DefaultPartySettings
|
||||
m_ReadOnly: 0
|
||||
|
||||
@@ -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}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -49,7 +49,7 @@ TextureImporter:
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteBorder: {x: 0, y: 1, z: 1, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
@@ -93,6 +93,19 @@ TextureImporter:
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 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:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
@@ -101,7 +114,7 @@ TextureImporter:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
internalID: 1537655665
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
|
||||
@@ -23,14 +23,14 @@ namespace Nox.Game {
|
||||
}
|
||||
|
||||
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 experienceModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Experience);
|
||||
|
||||
return new EntityStats {
|
||||
stats = new[] {
|
||||
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.Experience, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Experience), experienceModifiers, entityDefinition))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Jovian.PopupSystem;
|
||||
using Jovian.PopupSystem.UI;
|
||||
using Jovian.SaveSystem;
|
||||
using Jovian.ZoneSystem;
|
||||
using Nox.Core;
|
||||
@@ -39,6 +41,7 @@ namespace Nox.Game {
|
||||
private TimeHandler timeHandler;
|
||||
private PartyInventoryHandler partyInventoryHandler;
|
||||
private PartyGuiView partyGuiView;
|
||||
private IPopupSystem popupSystem;
|
||||
|
||||
public AdventurePlayMode(
|
||||
PlatformSettings platformSettings,
|
||||
@@ -134,7 +137,16 @@ namespace Nox.Game {
|
||||
|
||||
if(partyGuiView == null && guiReferences.partyMemberSlotPrefab != null) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -151,6 +163,7 @@ namespace Nox.Game {
|
||||
partyMovementHandler.Tick();
|
||||
adventureView.Tick();
|
||||
partyGuiView?.Tick();
|
||||
popupSystem?.Tick(Time.deltaTime);
|
||||
|
||||
if(inputActions.UI.PauseMenu.WasPerformedThisFrame()) {
|
||||
gameDataState.ChangePlayMode(PlayMode.PauseMenu);
|
||||
@@ -178,6 +191,7 @@ namespace Nox.Game {
|
||||
cameraController?.Dispose();
|
||||
partyMovementHandler?.Dispose();
|
||||
partyGuiView?.Dispose();
|
||||
popupSystem?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Nox.UI {
|
||||
private int remainingPoints;
|
||||
private readonly int[] allocatedPoints = new int[4]; // Might, Reflex, Knowledge, Perception (AttributeType 1-4)
|
||||
private int previousHealth;
|
||||
private int previousStamina;
|
||||
private int previousMana;
|
||||
|
||||
// Modifier source tracking
|
||||
private PerksData racialPerks = new();
|
||||
@@ -87,8 +87,11 @@ namespace Nox.UI {
|
||||
var canStart = characterCreationRequests is { Count: > 0 };
|
||||
characterCreationReference.startGameButton.interactable = canStart;
|
||||
};
|
||||
characterCreationReference.startGameButton.interactable = false;
|
||||
characterCreationReference.startGameButton.onClick.AddListener(() => {
|
||||
if(characterCreationRequests == null || characterCreationRequests.Count == 0) {
|
||||
inGameLogger.Log("You must accept your character before starting the game.", "#FF4444");
|
||||
return;
|
||||
}
|
||||
Hide();
|
||||
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
|
||||
previousHealth = workingStats.GetValue(StatType.Health);
|
||||
previousStamina = workingStats.GetValue(StatType.Mana);
|
||||
previousMana = workingStats.GetValue(StatType.Mana);
|
||||
}
|
||||
|
||||
private void ApplyRacialBonuses() {
|
||||
@@ -291,19 +294,19 @@ namespace Nox.UI {
|
||||
|
||||
// 10. Log stat deltas
|
||||
var newHealth = workingStats.GetValue(StatType.Health);
|
||||
var newStamina = workingStats.GetValue(StatType.Mana);
|
||||
var newMana = workingStats.GetValue(StatType.Mana);
|
||||
if(newHealth != previousHealth && previousHealth != 0) {
|
||||
var delta = newHealth - previousHealth;
|
||||
var sign = delta > 0 ? "+" : "";
|
||||
inGameLogger.Log($"Health: {previousHealth} -> {newHealth} ({sign}{delta})", "#87CEEB");
|
||||
}
|
||||
if(newStamina != previousStamina && previousStamina != 0) {
|
||||
var delta = newStamina - previousStamina;
|
||||
if(newMana != previousMana && previousMana != 0) {
|
||||
var delta = newMana - previousMana;
|
||||
var sign = delta > 0 ? "+" : "";
|
||||
inGameLogger.Log($"Stamina: {previousStamina} -> {newStamina} ({sign}{delta})", "#FFFF99");
|
||||
inGameLogger.Log($"Mana: {previousMana} -> {newMana} ({sign}{delta})", "#FFFF99");
|
||||
}
|
||||
previousHealth = newHealth;
|
||||
previousStamina = newStamina;
|
||||
previousMana = newMana;
|
||||
}
|
||||
|
||||
private PerksData BuildCombinedPerks() {
|
||||
|
||||
@@ -1,28 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using Jovian.PopupSystem;
|
||||
using Nox.UI;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Nox.Game.UI {
|
||||
public class PartyGuiView {
|
||||
private const int PoolSize = 4;
|
||||
|
||||
private readonly Transform portraitsContainer;
|
||||
private readonly PartyMemberSlot slotPrefab;
|
||||
private readonly PortraitsHolder portraitsHolder;
|
||||
private readonly List<PartyMemberSlot> activeSlots = new();
|
||||
private readonly IPopupSystem popupSystem;
|
||||
private readonly PartyMemberSlot[] slotPool = new PartyMemberSlot[PoolSize];
|
||||
|
||||
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.slotPrefab = slotPrefab;
|
||||
this.portraitsHolder = portraitsHolder;
|
||||
this.popupSystem = popupSystem;
|
||||
}
|
||||
|
||||
public void Initialize(PartyDefinition party) {
|
||||
trackedParty = party;
|
||||
trackedMemberCount = 0;
|
||||
RebuildSlots();
|
||||
activeCount = 0;
|
||||
|
||||
// Pre-create all slots (deactivated)
|
||||
for(int i = 0; i < PoolSize; i++) {
|
||||
if(slotPool[i] == null) {
|
||||
slotPool[i] = Object.Instantiate(slotPrefab, portraitsContainer);
|
||||
}
|
||||
slotPool[i].gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
PopulateSlots();
|
||||
}
|
||||
|
||||
public void Tick() {
|
||||
@@ -31,33 +45,27 @@ namespace Nox.Game.UI {
|
||||
}
|
||||
|
||||
// Rebuild if member count changed
|
||||
if(trackedParty.members.Count != trackedMemberCount) {
|
||||
RebuildSlots();
|
||||
if(trackedParty.members.Count != activeCount) {
|
||||
PopulateSlots();
|
||||
}
|
||||
|
||||
// Update dynamic values (health, mana)
|
||||
for(int i = 0; i < activeSlots.Count && i < trackedParty.members.Count; i++) {
|
||||
// Update dynamic values
|
||||
var memberCount = Mathf.Min(activeCount, trackedParty.members.Count);
|
||||
for(int i = 0; i < memberCount; i++) {
|
||||
UpdateSlotStats(slotPool[i], trackedParty.members[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateSlots() {
|
||||
var memberCount = trackedParty?.members != null
|
||||
? Mathf.Min(trackedParty.members.Count, PoolSize)
|
||||
: 0;
|
||||
|
||||
// Activate slots for current members, deactivate the rest
|
||||
for(int i = 0; i < PoolSize; i++) {
|
||||
var slot = slotPool[i];
|
||||
if(i < memberCount) {
|
||||
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);
|
||||
|
||||
// Portrait
|
||||
@@ -66,13 +74,82 @@ namespace Nox.Game.UI {
|
||||
slot.portrait.sprite = portraitsHolder.portraits[idx];
|
||||
}
|
||||
|
||||
// Name
|
||||
if(slot.nameText != null) {
|
||||
slot.nameText.text = member.Name;
|
||||
UpdateSlotStats(slot, member);
|
||||
}
|
||||
else {
|
||||
slot.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSlotStats(slot, member);
|
||||
activeSlots.Add(slot);
|
||||
activeCount = memberCount;
|
||||
|
||||
// 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) {
|
||||
slot.healthBar.fillAmount = Mathf.Clamp01(health / 100f);
|
||||
}
|
||||
if(slot.healthText != null) {
|
||||
slot.healthText.text = health.ToString();
|
||||
}
|
||||
|
||||
if(slot.manaBar != null) {
|
||||
slot.manaBar.fillAmount = Mathf.Clamp01(mana / 100f);
|
||||
}
|
||||
if(slot.manaText != null) {
|
||||
slot.manaText.text = mana.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
foreach(var slot in activeSlots) {
|
||||
if(slot != null) {
|
||||
Object.Destroy(slot.gameObject);
|
||||
for(int i = 0; i < PoolSize; i++) {
|
||||
if(slotPool[i] != null) {
|
||||
Object.Destroy(slotPool[i].gameObject);
|
||||
slotPool[i] = null;
|
||||
}
|
||||
}
|
||||
activeSlots.Clear();
|
||||
activeCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
@@ -7,8 +6,5 @@ namespace Nox.Game.UI {
|
||||
public Image portrait;
|
||||
public Image healthBar;
|
||||
public Image manaBar;
|
||||
public TextMeshProUGUI nameText;
|
||||
public TextMeshProUGUI healthText;
|
||||
public TextMeshProUGUI manaText;
|
||||
}
|
||||
}
|
||||
|
||||
44
Assets/Database/UI/PopupSettings.asset
Normal file
44
Assets/Database/UI/PopupSettings.asset
Normal 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: []
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9148d31c5a1d74102a17c9d6be0baf0e
|
||||
guid: 571f2dd77fb442d499cdc9c2afe9f98d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c79f6f00c1f84b1c854543c84d05d0f
|
||||
NativeFormatImporter:
|
||||
guid: 75a4a222ad797a54aac8ff58761899cf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b53a1ca29cdf45fdb72fa3e94514b82
|
||||
NativeFormatImporter:
|
||||
guid: b57e33c3f937ba146a2a13d68b0ce173
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -59,7 +59,7 @@ MonoBehaviour:
|
||||
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_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
@@ -92,7 +92,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &7663002820715980796
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -229,7 +229,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &8741529769002405325
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -408,8 +408,8 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.6156863, g: 0.6509804, b: 0.63529414, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Color: {r: 0.9818833, g: 1, b: 0, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
@@ -442,7 +442,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &32220060764936852
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -573,6 +573,7 @@ GameObject:
|
||||
- component: {fileID: 635472993512454406}
|
||||
- component: {fileID: 713960887884573537}
|
||||
- component: {fileID: 1445432521138085750}
|
||||
- component: {fileID: 250019032835520348}
|
||||
m_Layer: 5
|
||||
m_Name: HeroPortrait
|
||||
m_TagString: Untagged
|
||||
@@ -598,8 +599,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0.041302264}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: -0.19400787, y: -0.000015258789}
|
||||
m_SizeDelta: {x: -0.38810003, y: 0}
|
||||
m_AnchoredPosition: {x: -0.0000076293945, y: -0.000015258789}
|
||||
m_SizeDelta: {x: 0.000022888, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &713960887884573537
|
||||
CanvasRenderer:
|
||||
@@ -639,6 +640,22 @@ MonoBehaviour:
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
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
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -703,9 +720,6 @@ MonoBehaviour:
|
||||
portrait: {fileID: 1445432521138085750}
|
||||
healthBar: {fileID: 4550488616099254946}
|
||||
manaBar: {fileID: 4614622083837966787}
|
||||
nameText: {fileID: 7895725010274726425}
|
||||
healthText: {fileID: 2204466678496895551}
|
||||
manaText: {fileID: 1991527881912334546}
|
||||
--- !u!114 &3828666794624103248
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -761,8 +775,8 @@ RectTransform:
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0.041302264}
|
||||
m_AnchorMax: {x: 1, y: 0.041302264}
|
||||
m_AnchoredPosition: {x: -0.19399261, y: -1.4669495}
|
||||
m_SizeDelta: {x: -0.3880005, y: 2.6903992}
|
||||
m_AnchoredPosition: {x: -0.19453812, y: -2.3094025}
|
||||
m_SizeDelta: {x: -0.38894, y: 4.3752}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &2223287144791830491
|
||||
CanvasRenderer:
|
||||
@@ -785,8 +799,8 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0.48627454, g: 0.06666667, b: 0.08627451, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_Color: {r: 0.19131038, g: 0.06666666, b: 0.4862745, a: 1}
|
||||
m_RaycastTarget: 0
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
8
Assets/Prefabs/UI/IngameLogSystem.meta
Normal file
8
Assets/Prefabs/UI/IngameLogSystem.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80b7de964780c3a4d91efbe9df16d961
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Prefabs/UI/PopupSystem.meta
Normal file
8
Assets/Prefabs/UI/PopupSystem.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7ddc322bd65e7e46abca4c4c6540bb6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
160
Assets/Prefabs/UI/PopupSystem/PopupHeader.prefab
Normal file
160
Assets/Prefabs/UI/PopupSystem/PopupHeader.prefab
Normal 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
|
||||
7
Assets/Prefabs/UI/PopupSystem/PopupHeader.prefab.meta
Normal file
7
Assets/Prefabs/UI/PopupSystem/PopupHeader.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfc1bc0bd5b4905409615c3e770a5b77
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
98
Assets/Prefabs/UI/PopupSystem/PopupIcon.prefab
Normal file
98
Assets/Prefabs/UI/PopupSystem/PopupIcon.prefab
Normal 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
|
||||
7
Assets/Prefabs/UI/PopupSystem/PopupIcon.prefab.meta
Normal file
7
Assets/Prefabs/UI/PopupSystem/PopupIcon.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5e715f4b614d02b4fa0b4d3fcfe3c053
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
292
Assets/Prefabs/UI/PopupSystem/PopupReferencePrefab.prefab
Normal file
292
Assets/Prefabs/UI/PopupSystem/PopupReferencePrefab.prefab
Normal 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
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dfcc209b5aff734d863147e5614563c
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
98
Assets/Prefabs/UI/PopupSystem/PopupSeparator.prefab
Normal file
98
Assets/Prefabs/UI/PopupSystem/PopupSeparator.prefab
Normal 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
|
||||
7
Assets/Prefabs/UI/PopupSystem/PopupSeparator.prefab.meta
Normal file
7
Assets/Prefabs/UI/PopupSystem/PopupSeparator.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ccdfa1a2079db044be4b1684303ec7f
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
376
Assets/Prefabs/UI/PopupSystem/PopupStat.prefab
Normal file
376
Assets/Prefabs/UI/PopupSystem/PopupStat.prefab
Normal 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}
|
||||
7
Assets/Prefabs/UI/PopupSystem/PopupStat.prefab.meta
Normal file
7
Assets/Prefabs/UI/PopupSystem/PopupStat.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5882db210c62d8647858933649f64c29
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
184
Assets/Prefabs/UI/PopupSystem/PopupText.prefab
Normal file
184
Assets/Prefabs/UI/PopupSystem/PopupText.prefab
Normal 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
|
||||
7
Assets/Prefabs/UI/PopupSystem/PopupText.prefab.meta
Normal file
7
Assets/Prefabs/UI/PopupSystem/PopupText.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfa97c92d1878cc448ddc7dc456f4b17
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -596,6 +596,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: GUI
|
||||
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}
|
||||
propertyPath: m_Pivot.x
|
||||
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
File diff suppressed because one or more lines are too long
8
Packages/com.jovian.popup-system/Editor.meta
Normal file
8
Packages/com.jovian.popup-system/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 608491ce009b2494c894080b243698b9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e663435ad13b46d40a29802dab7e52f5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
104
Packages/com.jovian.popup-system/Editor/PopupCategoryDrawer.cs
Normal file
104
Packages/com.jovian.popup-system/Editor/PopupCategoryDrawer.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cc96a089d31fe14cbadf6c59ea0c9aa
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ea57be8755c60e4bbf156ac2b32c98c
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63a03b88ed78a934094ce61f9d127ec9
|
||||
344
Packages/com.jovian.popup-system/README.md
Normal file
344
Packages/com.jovian.popup-system/README.md
Normal 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` |
|
||||
7
Packages/com.jovian.popup-system/README.md.meta
Normal file
7
Packages/com.jovian.popup-system/README.md.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d33518dac7899604c9ceeda21897315d
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.jovian.popup-system/Runtime.meta
Normal file
8
Packages/com.jovian.popup-system/Runtime.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05f691cbfb7413f4fb735b2ec732ff06
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 254bb620ce056dd41905258eb0f070d7
|
||||
37
Packages/com.jovian.popup-system/Runtime/IPopupAnimator.cs
Normal file
37
Packages/com.jovian.popup-system/Runtime/IPopupAnimator.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b146d885db3dcef4fa70abd3f43683d3
|
||||
79
Packages/com.jovian.popup-system/Runtime/IPopupSystem.cs
Normal file
79
Packages/com.jovian.popup-system/Runtime/IPopupSystem.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65d563f87bb09de48b8edd12101cdd11
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31bcaef770c58d94db7f78106f15fd4e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
48
Packages/com.jovian.popup-system/Runtime/PopupCategory.cs
Normal file
48
Packages/com.jovian.popup-system/Runtime/PopupCategory.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcd1fb0ef93fed0489a43977bc71594b
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 683182ef8e2aa6b4daffc547c481b768
|
||||
115
Packages/com.jovian.popup-system/Runtime/PopupContentBuilder.cs
Normal file
115
Packages/com.jovian.popup-system/Runtime/PopupContentBuilder.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9f4094c471d0464e95e330331acc813
|
||||
74
Packages/com.jovian.popup-system/Runtime/PopupElementType.cs
Normal file
74
Packages/com.jovian.popup-system/Runtime/PopupElementType.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ba7e78e3d930334a935a600a8f67ded
|
||||
13
Packages/com.jovian.popup-system/Runtime/PopupEnums.cs
Normal file
13
Packages/com.jovian.popup-system/Runtime/PopupEnums.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Jovian.PopupSystem {
|
||||
public enum AnchorSide {
|
||||
Below,
|
||||
Above,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
public enum PopupPositionMode {
|
||||
AnchorToElement,
|
||||
FollowMouse
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01e69680e496eca4daebbc1874e3a7d9
|
||||
96
Packages/com.jovian.popup-system/Runtime/PopupSettings.cs
Normal file
96
Packages/com.jovian.popup-system/Runtime/PopupSettings.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e38e313f3665d464b82b22699b2a4634
|
||||
282
Packages/com.jovian.popup-system/Runtime/PopupSystem.cs
Normal file
282
Packages/com.jovian.popup-system/Runtime/PopupSystem.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 056ed88d12add674798ad4e6300bf222
|
||||
54
Packages/com.jovian.popup-system/Runtime/PopupTriggerView.cs
Normal file
54
Packages/com.jovian.popup-system/Runtime/PopupTriggerView.cs
Normal 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
Reference in New Issue
Block a user