[Add] Debugger Inventory & small ui fixes
This commit is contained in:
@@ -516,7 +516,7 @@ GameObject:
|
|||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 0
|
||||||
--- !u!224 &2533462241018374848
|
--- !u!224 &2533462241018374848
|
||||||
RectTransform:
|
RectTransform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -740,7 +740,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 122.6
|
value: 75
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
@@ -776,7 +776,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_AnchoredPosition.x
|
propertyPath: m_AnchoredPosition.x
|
||||||
value: 61.302
|
value: 37.158817
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
@@ -1019,7 +1019,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 77.396
|
value: 125
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
@@ -1055,7 +1055,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_AnchoredPosition.x
|
propertyPath: m_AnchoredPosition.x
|
||||||
value: -38.698
|
value: -62.671
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 703621256034232799, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_AnchoredPosition.y
|
propertyPath: m_AnchoredPosition.y
|
||||||
|
|||||||
@@ -465,7 +465,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 0.5188679, g: 0.5188679, b: 0.5188679, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
@@ -655,7 +655,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 0.2830189, g: 0.2830189, b: 0.2830189, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
@@ -1450,15 +1450,15 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontColor.b
|
propertyPath: m_fontColor.b
|
||||||
value: 0
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontColor.g
|
propertyPath: m_fontColor.g
|
||||||
value: 0
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontColor.r
|
propertyPath: m_fontColor.r
|
||||||
value: 0
|
value: 1
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontSizeBase
|
propertyPath: m_fontSizeBase
|
||||||
@@ -1466,7 +1466,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontColor32.rgba
|
propertyPath: m_fontColor32.rgba
|
||||||
value: 4278190080
|
value: 4294967295
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_VerticalAlignment
|
propertyPath: m_VerticalAlignment
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 0.7924528, g: 0.7924528, b: 0.7924528, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 0.4433962, g: 0.4433962, b: 0.4433962, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
@@ -323,7 +323,7 @@ MonoBehaviour:
|
|||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 0.2924528, g: 0.2924528, b: 0.2924528, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ GameObject:
|
|||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 0
|
||||||
--- !u!224 &133637959725470091
|
--- !u!224 &133637959725470091
|
||||||
RectTransform:
|
RectTransform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@@ -38,7 +38,7 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
m_AnchoredPosition: {x: 39.7049, y: -46.6634}
|
m_AnchoredPosition: {x: 512.5834, y: 300.2}
|
||||||
m_SizeDelta: {x: 150, y: 150}
|
m_SizeDelta: {x: 150, y: 150}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &7291137291065553443
|
--- !u!114 &7291137291065553443
|
||||||
@@ -186,7 +186,8 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_text
|
propertyPath: m_text
|
||||||
value: Name
|
value: "\u0427\u0438\u0441\u0442\u044B\u0439 \u043C\u043D\u043E\u0436\u0438\u0442\u0435\u043B\u044C
|
||||||
|
x1.5"
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontSize
|
propertyPath: m_fontSize
|
||||||
@@ -327,7 +328,9 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_text
|
propertyPath: m_text
|
||||||
value: Description Text
|
value: "\u0423\u043C\u043D\u043E\u0436\u0430\u0435\u0442 \u0438\u0442\u043E\u0433\u043E\u0432\u044B\u0439
|
||||||
|
\u0441\u0447\u0435\u0442 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0438
|
||||||
|
\u043D\u0430 1.5."
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontSize
|
propertyPath: m_fontSize
|
||||||
@@ -476,7 +479,7 @@ PrefabInstance:
|
|||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_text
|
propertyPath: m_text
|
||||||
value: 123
|
value: 'Price: 260'
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
- target: {fileID: 3472307258458128773, guid: 0829148555ff32841afde9f6193a0b72, type: 3}
|
||||||
propertyPath: m_fontSize
|
propertyPath: m_fontSize
|
||||||
|
|||||||
@@ -2041,10 +2041,6 @@ PrefabInstance:
|
|||||||
propertyPath: m_Name
|
propertyPath: m_Name
|
||||||
value: Game Info View
|
value: Game Info View
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 5167299410648281090, guid: 010ebb8b9becf6b45930c5fb7a5c95e0, type: 3}
|
|
||||||
propertyPath: m_IsActive
|
|
||||||
value: 0
|
|
||||||
objectReference: {fileID: 0}
|
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|||||||
@@ -1,224 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using YachtDice.Modifiers.Definition;
|
|
||||||
|
|
||||||
namespace YachtDice.Modifiers.Editor
|
|
||||||
{
|
|
||||||
public static class ModifierDefinitionValidator
|
|
||||||
{
|
|
||||||
[MenuItem("YachtDice/Validate All Modifier Definitions")]
|
|
||||||
public static void ValidateAll()
|
|
||||||
{
|
|
||||||
string[] guids = AssetDatabase.FindAssets("t:ModifierDefinitionSO");
|
|
||||||
|
|
||||||
if (guids.Length == 0)
|
|
||||||
{
|
|
||||||
Debug.Log("[ModifierValidator] No ModifierDefinitionSO assets found.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var errorCount = 0;
|
|
||||||
var warnCount = 0;
|
|
||||||
var usedIds = new Dictionary<string, string>(); // id -> asset path
|
|
||||||
|
|
||||||
foreach (var t in guids)
|
|
||||||
{
|
|
||||||
var path = AssetDatabase.GUIDToAssetPath(t);
|
|
||||||
var def = AssetDatabase.LoadAssetAtPath<ModifierDefinition>(path);
|
|
||||||
|
|
||||||
if (def == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] Failed to load asset at {path}");
|
|
||||||
errorCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Id checks ────────────────────────────────────────
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(def.Id))
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: Id is empty.", def);
|
|
||||||
errorCount++;
|
|
||||||
}
|
|
||||||
else if (usedIds.TryGetValue(def.Id, out string existingPath))
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: Duplicate Id '{def.Id}' (also used by {existingPath}).", def);
|
|
||||||
errorCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
usedIds[def.Id] = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Economy checks ───────────────────────────────────
|
|
||||||
|
|
||||||
if (def.ShopPrice < 0)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: ShopPrice is negative ({def.ShopPrice}).", def);
|
|
||||||
errorCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (def.SellPrice < 0)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: SellPrice is negative ({def.SellPrice}).", def);
|
|
||||||
errorCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (def.SellPrice > def.ShopPrice && def.ShopPrice > 0)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] {path}: SellPrice ({def.SellPrice}) > ShopPrice ({def.ShopPrice}). Infinite money exploit?", def);
|
|
||||||
warnCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Durability checks ────────────────────────────────
|
|
||||||
|
|
||||||
if (def.HasLimitedUses && def.MaxUses <= 0)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: HasLimitedUses is true but MaxUses is {def.MaxUses}.", def);
|
|
||||||
errorCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!def.HasLimitedUses && def.MaxUses > 0)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] {path}: HasLimitedUses is false but MaxUses is {def.MaxUses}. Ignored at runtime.", def);
|
|
||||||
warnCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (def.MaxStacks < 1)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: MaxStacks must be >= 1 (is {def.MaxStacks}).", def);
|
|
||||||
errorCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Behavior checks ──────────────────────────────────
|
|
||||||
|
|
||||||
if (def.Behaviors == null || def.Behaviors.Count == 0)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] {path}: No behaviors assigned. Modifier will do nothing.", def);
|
|
||||||
warnCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int b = 0; b < def.Behaviors.Count; b++)
|
|
||||||
{
|
|
||||||
var behavior = def.Behaviors[b];
|
|
||||||
|
|
||||||
if (behavior == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: Behavior slot [{b}] is null.", def);
|
|
||||||
errorCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for null conditions
|
|
||||||
if (behavior.Conditions != null)
|
|
||||||
{
|
|
||||||
for (int c = 0; c < behavior.Conditions.Count; c++)
|
|
||||||
{
|
|
||||||
if (behavior.Conditions[c] == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] {path}: Behavior '{behavior.name}' has null condition at slot [{c}].", behavior);
|
|
||||||
warnCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for null or empty effects
|
|
||||||
if (behavior.Effects == null || behavior.Effects.Count == 0)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] {path}: Behavior '{behavior.name}' has no effects.", behavior);
|
|
||||||
warnCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int e = 0; e < behavior.Effects.Count; e++)
|
|
||||||
{
|
|
||||||
if (behavior.Effects[e] == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] {path}: Behavior '{behavior.name}' has null effect at slot [{e}].", behavior);
|
|
||||||
errorCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Display checks ───────────────────────────────────
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(def.DisplayName))
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] {path}: DisplayName is empty.", def);
|
|
||||||
warnCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(def.Description))
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] {path}: Description is empty.", def);
|
|
||||||
warnCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string summary = $"[ModifierValidator] Validated {guids.Length} modifier(s): {errorCount} error(s), {warnCount} warning(s).";
|
|
||||||
|
|
||||||
if (errorCount > 0)
|
|
||||||
Debug.LogError(summary);
|
|
||||||
else if (warnCount > 0)
|
|
||||||
Debug.LogWarning(summary);
|
|
||||||
else
|
|
||||||
Debug.Log(summary);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("YachtDice/Validate Modifier Catalog")]
|
|
||||||
public static void ValidateCatalog()
|
|
||||||
{
|
|
||||||
string[] guids = AssetDatabase.FindAssets("t:ModifierCatalogSO");
|
|
||||||
|
|
||||||
if (guids.Length == 0)
|
|
||||||
{
|
|
||||||
Debug.LogWarning("[ModifierValidator] No ModifierCatalogSO asset found. Create one via Create > YachtDice/Modifiers/Catalog.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < guids.Length; i++)
|
|
||||||
{
|
|
||||||
string path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
|
||||||
var catalog = AssetDatabase.LoadAssetAtPath<ModifierCatalog>(path);
|
|
||||||
|
|
||||||
if (catalog == null)
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] Failed to load catalog at {path}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (catalog.All == null || catalog.All.Count == 0)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"[ModifierValidator] Catalog at {path} is empty.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nullCount = 0;
|
|
||||||
var catalogIds = new HashSet<string>();
|
|
||||||
|
|
||||||
for (int j = 0; j < catalog.All.Count; j++)
|
|
||||||
{
|
|
||||||
if (catalog.All[j] == null)
|
|
||||||
{
|
|
||||||
nullCount++;
|
|
||||||
Debug.LogError($"[ModifierValidator] Catalog {path}: Null entry at index [{j}].", catalog);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
string id = catalog.All[j].Id;
|
|
||||||
if (!catalogIds.Add(id))
|
|
||||||
{
|
|
||||||
Debug.LogError($"[ModifierValidator] Catalog {path}: Duplicate modifier Id '{id}' in catalog.", catalog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.Log($"[ModifierValidator] Catalog {path}: {catalog.All.Count} entries, {nullCount} null.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2f07f633fcb085e49890cec1280b4129
|
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using YachtDice.Inventory;
|
||||||
|
using YachtDice.Modifiers.Definition;
|
||||||
|
using YachtDice.Modifiers.Runtime;
|
||||||
|
|
||||||
|
namespace YachtDice.Modifiers.Editor
|
||||||
|
{
|
||||||
|
public class ModifierInventoryDebugWindow : EditorWindow
|
||||||
|
{
|
||||||
|
private const double RepaintIntervalSeconds = 0.5d;
|
||||||
|
|
||||||
|
private readonly List<ModifierDefinition> _allDefinitions = new();
|
||||||
|
|
||||||
|
private Vector2 _catalogScroll;
|
||||||
|
private Vector2 _inventoryScroll;
|
||||||
|
private string _search = string.Empty;
|
||||||
|
private InventoryController _inventoryController;
|
||||||
|
private double _nextRepaintTime;
|
||||||
|
|
||||||
|
[MenuItem("YachtDice/Debug/Modifier Inventory")]
|
||||||
|
public static void Open()
|
||||||
|
{
|
||||||
|
var window = GetWindow<ModifierInventoryDebugWindow>("Modifier Debug");
|
||||||
|
window.minSize = new Vector2(700f, 400f);
|
||||||
|
window.RefreshDefinitions();
|
||||||
|
window.ResolveInventoryController();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
RefreshDefinitions();
|
||||||
|
ResolveInventoryController();
|
||||||
|
EditorApplication.playModeStateChanged += HandlePlayModeStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
EditorApplication.playModeStateChanged -= HandlePlayModeStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFocus()
|
||||||
|
{
|
||||||
|
RefreshDefinitions();
|
||||||
|
ResolveInventoryController();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnHierarchyChange()
|
||||||
|
{
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ResolveInventoryController();
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if (EditorApplication.timeSinceStartup < _nextRepaintTime)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_nextRepaintTime = EditorApplication.timeSinceStartup + RepaintIntervalSeconds;
|
||||||
|
|
||||||
|
if (Application.isPlaying && (_inventoryController == null || _inventoryController.Model == null))
|
||||||
|
ResolveInventoryController();
|
||||||
|
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
DrawToolbar();
|
||||||
|
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Enter Play Mode to edit runtime inventory state.", MessageType.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
var model = GetInventoryModel();
|
||||||
|
if (Application.isPlaying && model == null)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("InventoryController was not found in the scene.", MessageType.Warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawOwnedModifiers(model);
|
||||||
|
EditorGUILayout.Space(8f);
|
||||||
|
DrawDefinitionCatalog(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawToolbar()
|
||||||
|
{
|
||||||
|
using (new EditorGUILayout.HorizontalScope(EditorStyles.toolbar))
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Refresh Catalog", EditorStyles.toolbarButton))
|
||||||
|
RefreshDefinitions();
|
||||||
|
|
||||||
|
if (GUILayout.Button("Find Inventory", EditorStyles.toolbarButton))
|
||||||
|
ResolveInventoryController();
|
||||||
|
|
||||||
|
GUILayout.FlexibleSpace();
|
||||||
|
EditorGUILayout.LabelField("Search", GUILayout.Width(45f));
|
||||||
|
_search = EditorGUILayout.TextField(_search, GUILayout.Width(220f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawOwnedModifiers(InventoryModel model)
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField("Owned Modifiers", EditorStyles.boldLabel);
|
||||||
|
|
||||||
|
if (model == null)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Inventory is unavailable.", MessageType.None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.LabelField($"Active slots: {model.ActiveCount}/{model.MaxActiveSlots}");
|
||||||
|
|
||||||
|
var snapshot = new List<ModifierInstance>(model.OwnedModifiers);
|
||||||
|
if (snapshot.Count == 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Inventory is empty.", MessageType.None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_inventoryScroll = EditorGUILayout.BeginScrollView(_inventoryScroll, GUILayout.MinHeight(140f));
|
||||||
|
|
||||||
|
foreach (var instance in snapshot)
|
||||||
|
{
|
||||||
|
DrawOwnedModifierRow(model, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawOwnedModifierRow(InventoryModel model, ModifierInstance instance)
|
||||||
|
{
|
||||||
|
var definition = instance.Definition;
|
||||||
|
if (definition == null)
|
||||||
|
{
|
||||||
|
using (new EditorGUILayout.VerticalScope("box"))
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField("<missing definition>", EditorStyles.boldLabel);
|
||||||
|
if (GUILayout.Button("Remove", GUILayout.Width(90f)))
|
||||||
|
model.RemoveModifier(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = instance.IsActive ? "Active" : "Inactive";
|
||||||
|
var uses = definition.HasLimitedUses
|
||||||
|
? $"Uses: {instance.RemainingUses}/{definition.MaxUses}"
|
||||||
|
: "Uses: infinite";
|
||||||
|
|
||||||
|
using (new EditorGUILayout.VerticalScope("box"))
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField(BuildDefinitionLabel(definition), EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.LabelField($"State: {state} | {uses}");
|
||||||
|
|
||||||
|
using (new EditorGUILayout.HorizontalScope())
|
||||||
|
{
|
||||||
|
using (new EditorGUI.DisabledScope(instance.IsActive))
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Activate", GUILayout.Width(90f)))
|
||||||
|
{
|
||||||
|
if (!model.TryActivate(instance))
|
||||||
|
Debug.LogWarning($"[ModifierDebug] Failed to activate '{definition.Id}'. Check slot limits.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (new EditorGUI.DisabledScope(!instance.IsActive))
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Deactivate", GUILayout.Width(90f)))
|
||||||
|
model.Deactivate(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUILayout.Button("Remove", GUILayout.Width(90f)))
|
||||||
|
model.RemoveModifier(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawDefinitionCatalog(InventoryModel model)
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField("All Modifier Definitions", EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.LabelField($"Loaded assets: {_allDefinitions.Count}");
|
||||||
|
|
||||||
|
if (_allDefinitions.Count == 0)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("No ModifierDefinition assets found.", MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_catalogScroll = EditorGUILayout.BeginScrollView(_catalogScroll);
|
||||||
|
|
||||||
|
var loweredSearch = string.IsNullOrWhiteSpace(_search)
|
||||||
|
? string.Empty
|
||||||
|
: _search.Trim().ToLowerInvariant();
|
||||||
|
|
||||||
|
for (var i = 0; i < _allDefinitions.Count; i++)
|
||||||
|
{
|
||||||
|
var definition = _allDefinitions[i];
|
||||||
|
if (definition == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!MatchesSearch(definition, loweredSearch))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DrawDefinitionRow(model, definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUILayout.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawDefinitionRow(InventoryModel model, ModifierDefinition definition)
|
||||||
|
{
|
||||||
|
var uses = definition.HasLimitedUses ? $"limited ({definition.MaxUses})" : "permanent";
|
||||||
|
|
||||||
|
using (new EditorGUILayout.HorizontalScope("box"))
|
||||||
|
{
|
||||||
|
EditorGUILayout.LabelField($"{BuildDefinitionLabel(definition)} | {uses}");
|
||||||
|
|
||||||
|
using (new EditorGUI.DisabledScope(model == null))
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Add", GUILayout.Width(90f)))
|
||||||
|
model.AddModifier(definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool MatchesSearch(ModifierDefinition definition, string loweredSearch)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(loweredSearch))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var id = definition.Id ?? string.Empty;
|
||||||
|
var displayName = definition.DisplayName ?? string.Empty;
|
||||||
|
return id.IndexOf(loweredSearch, StringComparison.OrdinalIgnoreCase) >= 0
|
||||||
|
|| displayName.IndexOf(loweredSearch, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildDefinitionLabel(ModifierDefinition definition)
|
||||||
|
{
|
||||||
|
var displayName = string.IsNullOrWhiteSpace(definition.DisplayName)
|
||||||
|
? "<unnamed>"
|
||||||
|
: definition.DisplayName;
|
||||||
|
var id = string.IsNullOrWhiteSpace(definition.Id)
|
||||||
|
? "<no-id>"
|
||||||
|
: definition.Id;
|
||||||
|
return $"{displayName} [{id}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
private InventoryModel GetInventoryModel()
|
||||||
|
{
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (_inventoryController == null)
|
||||||
|
ResolveInventoryController();
|
||||||
|
|
||||||
|
return _inventoryController != null ? _inventoryController.Model : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResolveInventoryController()
|
||||||
|
{
|
||||||
|
if (!Application.isPlaying)
|
||||||
|
{
|
||||||
|
_inventoryController = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_inventoryController = FindObjectOfType<InventoryController>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshDefinitions()
|
||||||
|
{
|
||||||
|
_allDefinitions.Clear();
|
||||||
|
|
||||||
|
var guids = AssetDatabase.FindAssets("t:ModifierDefinition");
|
||||||
|
for (var i = 0; i < guids.Length; i++)
|
||||||
|
{
|
||||||
|
var path = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||||
|
var definition = AssetDatabase.LoadAssetAtPath<ModifierDefinition>(path);
|
||||||
|
if (definition != null)
|
||||||
|
_allDefinitions.Add(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
_allDefinitions.Sort((a, b) =>
|
||||||
|
{
|
||||||
|
var nameComparison = string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase);
|
||||||
|
if (nameComparison != 0)
|
||||||
|
return nameComparison;
|
||||||
|
return string.Compare(a.Id, b.Id, StringComparison.OrdinalIgnoreCase);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandlePlayModeStateChanged(PlayModeStateChange change)
|
||||||
|
{
|
||||||
|
if (change == PlayModeStateChange.EnteredPlayMode)
|
||||||
|
ResolveInventoryController();
|
||||||
|
|
||||||
|
if (change == PlayModeStateChange.ExitingPlayMode || change == PlayModeStateChange.EnteredEditMode)
|
||||||
|
_inventoryController = null;
|
||||||
|
|
||||||
|
Repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4a8b096304878c94e83fb2a8c711a969
|
||||||
Reference in New Issue
Block a user