CORE dashboard + a lot of changes
This commit is contained in:
@@ -5,7 +5,7 @@ using RPGCore.ObjectModules.ActionObjectModule;
|
|||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.Actions
|
namespace RPGCore.BackpackEquipment.Actions
|
||||||
{
|
{
|
||||||
public class UseUsableAction : BaseActionParallel
|
public class UseUsableAction : BaseAction
|
||||||
{
|
{
|
||||||
private readonly UsableObject _usable;
|
private readonly UsableObject _usable;
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ namespace RPGCore.BackpackEquipment.ObjectModules.Content.Actions
|
|||||||
|
|
||||||
protected override void OnDoIt()
|
protected override void OnDoIt()
|
||||||
{
|
{
|
||||||
var dropEvent = new DropEvent { unit = unit, item = _item };
|
var dropEvent = new ActionDropEvent { unit = unit, item = _item };
|
||||||
unit.events.InvokeBefore(dropEvent);
|
unit.events.InvokeBefore(dropEvent);
|
||||||
Check(!dropEvent.isPrevented, string.Format(ActionWasPreventedMessage, nameof(DropAction)));
|
Check(!dropEvent.isPrevented, string.Format(ActionWasPreventedMessage, nameof(DropAction)));
|
||||||
unit.events.InvokeAfter(dropEvent);
|
unit.events.InvokeAfter(dropEvent);
|
||||||
|
|
||||||
unit.GetComponent<ContentModule>().Remove(_item);
|
unit.GetComponent<ContentModule>().Drop(_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEndIt()
|
protected override void OnEndIt()
|
||||||
|
|||||||
@@ -19,18 +19,21 @@ namespace RPGCore.BackpackEquipment.ObjectModules.Content.Actions
|
|||||||
|
|
||||||
public override void CanDoIt()
|
public override void CanDoIt()
|
||||||
{
|
{
|
||||||
_contentOwner.CanAdd(_item, _index);
|
Check(
|
||||||
|
_contentOwner.CanAdd(_item, _index),
|
||||||
|
"This unit can't take that"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDoIt()
|
protected override void OnDoIt()
|
||||||
{
|
{
|
||||||
var takeEvent = new TakeEvent { unit = unit, item = _item };
|
var takeEvent = new ActionTakeEvent { unit = unit, item = _item };
|
||||||
unit.events.InvokeBefore(takeEvent);
|
unit.events.InvokeBefore(takeEvent);
|
||||||
Check(!takeEvent.isPrevented, string.Format(ActionWasPreventedMessage, nameof(TakeAction)));
|
Check(!takeEvent.isPrevented, string.Format(ActionWasPreventedMessage, nameof(TakeAction)));
|
||||||
unit.events.InvokeAfter(takeEvent);
|
unit.events.InvokeAfter(takeEvent);
|
||||||
|
|
||||||
var content = unit.GetComponent<ContentModule>();
|
var content = unit.GetComponent<ContentModule>();
|
||||||
content.Add(_item);
|
content.Take(_item);
|
||||||
content.TransferTo(_contentOwner, _item, _index);
|
content.TransferTo(_contentOwner, _item, _index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,26 @@ using UnityEngine;
|
|||||||
namespace RPGCore.BackpackEquipment.ObjectModules.Content
|
namespace RPGCore.BackpackEquipment.ObjectModules.Content
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
[RequireComponent(typeof(BaseObject))]
|
[ObjectModule(
|
||||||
|
name: "[Inventory] Content",
|
||||||
|
description: "Simple content managing attached to any implementation of <b>BaseObject</b>. " +
|
||||||
|
"By itself allows only: taking, dropping and deciding who manages items. " +
|
||||||
|
"Attach implementation of <b>"+nameof(IContentOwner)+"</b> to manage content's items."
|
||||||
|
)]
|
||||||
public sealed class ContentModule : ObjectModule<BaseObject>
|
public sealed class ContentModule : ObjectModule<BaseObject>
|
||||||
{
|
{
|
||||||
// TODO: tutaj jakiś domyślny owner?
|
// RUNTIME
|
||||||
|
private GameObject _contentGameObject;
|
||||||
private Dictionary<ItemObject, IContentOwner> _items = new();
|
private Dictionary<ItemObject, IContentOwner> _items = new();
|
||||||
|
|
||||||
public bool Add(ItemObject item)
|
private void Awake()
|
||||||
|
{
|
||||||
|
_contentGameObject = new GameObject("-- CONTENT --");
|
||||||
|
_contentGameObject.transform.SetParent(transform);
|
||||||
|
_contentGameObject.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Take(ItemObject item)
|
||||||
{
|
{
|
||||||
if (item.data.Get<ItemObjectData>().carriedBy) return false;
|
if (item.data.Get<ItemObjectData>().carriedBy) return false;
|
||||||
if (_items.ContainsKey(item)) return false;
|
if (_items.ContainsKey(item)) return false;
|
||||||
@@ -28,25 +40,32 @@ namespace RPGCore.BackpackEquipment.ObjectModules.Content
|
|||||||
parent.events.Invoke(new ContentAddEvent{obj = parent, item = item});
|
parent.events.Invoke(new ContentAddEvent{obj = parent, item = item});
|
||||||
item.events.Register<RemoveEvent>(OnItemRemove);
|
item.events.Register<RemoveEvent>(OnItemRemove);
|
||||||
|
|
||||||
|
item.gameObject.SetActive(false);
|
||||||
|
item.transform.SetParent(_contentGameObject.transform);
|
||||||
|
item.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove(ItemObject item)
|
public bool Drop(ItemObject item)
|
||||||
{
|
{
|
||||||
if (!_items.ContainsKey(item)) return false;
|
if (!_items.ContainsKey(item)) return false;
|
||||||
|
|
||||||
_items[item]?.Remove_Internal(item);
|
_items[item]?.Remove_Internal(item);
|
||||||
_items.Remove(item);
|
_items.Remove(item);
|
||||||
item.data.Get<ItemObjectData>().carriedBy = null;
|
item.data.Get<ItemObjectData>().carriedBy = null;
|
||||||
parent.events.Invoke(new ContentAddEvent{obj = parent, item = item});
|
parent.events.Invoke(new ContentRemoveEvent { obj = parent, item = item });
|
||||||
item.events.Unregister<RemoveEvent>(OnItemRemove);
|
item.events.Unregister<RemoveEvent>(OnItemRemove);
|
||||||
|
|
||||||
|
item.gameObject.SetActive(true);
|
||||||
|
item.transform.SetParent(null);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TransferTo(IContentOwner newOwner, ItemObject item, int index = -1)
|
public bool TransferTo(IContentOwner newOwner, ItemObject item, int index = -1)
|
||||||
{
|
{
|
||||||
if (parent.data.Get<ItemObjectData>().carriedBy != parent) return false;
|
if (item.data.Get<ItemObjectData>().carriedBy != parent) return false;
|
||||||
|
|
||||||
if (!newOwner.CanAdd(item, index)) return false;
|
if (!newOwner.CanAdd(item, index)) return false;
|
||||||
|
|
||||||
@@ -58,9 +77,14 @@ namespace RPGCore.BackpackEquipment.ObjectModules.Content
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TransferFrom(ItemObject item)
|
||||||
|
{
|
||||||
|
return _items[item]?.Remove_Internal(item) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnItemRemove(RemoveEvent removeEvent)
|
private void OnItemRemove(RemoveEvent removeEvent)
|
||||||
{
|
{
|
||||||
Remove(removeEvent.obj as ItemObject);
|
Drop(removeEvent.obj as ItemObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -4,7 +4,7 @@ using RPGCore.ObjectModules.EventObjectModule;
|
|||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.ObjectModules.Content.Events
|
namespace RPGCore.BackpackEquipment.ObjectModules.Content.Events
|
||||||
{
|
{
|
||||||
public class DropEvent : BasePreventableEvent<UnitObject>
|
public class ActionDropEvent : BasePreventableEvent<UnitObject>
|
||||||
{
|
{
|
||||||
public UnitObject unit;
|
public UnitObject unit;
|
||||||
public ItemObject item;
|
public ItemObject item;
|
||||||
+1
-1
@@ -4,7 +4,7 @@ using RPGCore.ObjectModules.EventObjectModule;
|
|||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.ObjectModules.Content.Events
|
namespace RPGCore.BackpackEquipment.ObjectModules.Content.Events
|
||||||
{
|
{
|
||||||
public class TakeEvent : BasePreventableEvent<UnitObject>
|
public class ActionTakeEvent : BasePreventableEvent<UnitObject>
|
||||||
{
|
{
|
||||||
public UnitObject unit;
|
public UnitObject unit;
|
||||||
public ItemObject item;
|
public ItemObject item;
|
||||||
@@ -5,14 +5,16 @@ using RPGCore.BackpackEquipment.ObjectModules.UnitBackpack.Events;
|
|||||||
using RPGCore.BackpackEquipment.Objects;
|
using RPGCore.BackpackEquipment.Objects;
|
||||||
using RPGCore.Core;
|
using RPGCore.Core;
|
||||||
using RPGCore.Core.Objects;
|
using RPGCore.Core.Objects;
|
||||||
using RPGCoreCommon.Helpers.PropertyAttributeDrawers;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.ObjectModules.UnitBackpack
|
namespace RPGCore.BackpackEquipment.ObjectModules.UnitBackpack
|
||||||
{
|
{
|
||||||
[RequireComponent(typeof(UnitObject))]
|
|
||||||
[RequireComponent(typeof(ContentModule))]
|
[RequireComponent(typeof(ContentModule))]
|
||||||
[DisallowMultipleComponent]
|
[DisallowMultipleComponent]
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Inventory] Backpack",
|
||||||
|
description: "Requires <b>ContentModule</b> to work. Simple backpack that can be attached to <b>UnitObject</b>."
|
||||||
|
)]
|
||||||
public sealed class UnitBackpackModule : ObjectModule<UnitObject>, IContentOwner
|
public sealed class UnitBackpackModule : ObjectModule<UnitObject>, IContentOwner
|
||||||
{
|
{
|
||||||
// TODO: implementacja stackowania tutaj
|
// TODO: implementacja stackowania tutaj
|
||||||
@@ -53,7 +55,7 @@ namespace RPGCore.BackpackEquipment.ObjectModules.UnitBackpack
|
|||||||
|
|
||||||
bool IContentOwner.Add(ItemObject item, int index)
|
bool IContentOwner.Add(ItemObject item, int index)
|
||||||
{
|
{
|
||||||
if (index < 0) index = Array.IndexOf(_items, false);
|
if (index < 0) index = Array.IndexOf(_items, null);
|
||||||
if (index < 0) return false;
|
if (index < 0) return false;
|
||||||
if (isLimited && index >= itemsLimit) return false;
|
if (isLimited && index >= itemsLimit) return false;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using RPGCore.BackpackEquipment.ObjectModules.Content;
|
||||||
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events;
|
||||||
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Objects;
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Objects;
|
||||||
using RPGCore.ObjectModules.ActionObjectModule;
|
using RPGCore.ObjectModules.ActionObjectModule;
|
||||||
|
|
||||||
@@ -16,10 +18,22 @@ namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Actions
|
|||||||
|
|
||||||
public override void CanDoIt()
|
public override void CanDoIt()
|
||||||
{
|
{
|
||||||
|
Check(
|
||||||
|
unit.GetComponent<UnitEquipmentModule>().CanAdd(_wearable, _index),
|
||||||
|
"This unit can't equip that"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDoIt()
|
protected override void OnDoIt()
|
||||||
{
|
{
|
||||||
|
var takeEvent = new ActionEquipEvent { unit = unit, wearable = _wearable };
|
||||||
|
unit.events.InvokeBefore(takeEvent);
|
||||||
|
Check(!takeEvent.isPrevented, string.Format(ActionWasPreventedMessage, nameof(EquipAction)));
|
||||||
|
unit.events.InvokeAfter(takeEvent);
|
||||||
|
|
||||||
|
var content = unit.GetComponent<ContentModule>();
|
||||||
|
var equipment = unit.GetComponent<UnitEquipmentModule>();
|
||||||
|
content.TransferTo(equipment, _wearable, _index);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEndIt() { }
|
protected override void OnEndIt() { }
|
||||||
|
|||||||
+17
-4
@@ -1,27 +1,40 @@
|
|||||||
|
using RPGCore.BackpackEquipment.ObjectModules.Content;
|
||||||
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events;
|
||||||
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Objects;
|
||||||
using RPGCore.ObjectModules.ActionObjectModule;
|
using RPGCore.ObjectModules.ActionObjectModule;
|
||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Actions
|
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Actions
|
||||||
{
|
{
|
||||||
public class UnEquipAction : BaseAction
|
public class UnEquipAction : BaseAction
|
||||||
{
|
{
|
||||||
|
private readonly WearableObject _wearable;
|
||||||
|
private readonly int _index;
|
||||||
|
|
||||||
|
public UnEquipAction(WearableObject wearable)
|
||||||
|
{
|
||||||
|
_wearable = wearable;
|
||||||
|
}
|
||||||
|
|
||||||
public override void CanDoIt()
|
public override void CanDoIt()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDoIt()
|
protected override void OnDoIt()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
var takeEvent = new ActionUnEquipEvent { unit = unit, wearable = _wearable };
|
||||||
|
unit.events.InvokeBefore(takeEvent);
|
||||||
|
Check(!takeEvent.isPrevented, string.Format(ActionWasPreventedMessage, nameof(UnEquipAction)));
|
||||||
|
unit.events.InvokeAfter(takeEvent);
|
||||||
|
|
||||||
|
unit.GetComponent<ContentModule>().TransferFrom(_wearable);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnEndIt()
|
protected override void OnEndIt()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnCancelIt()
|
protected override void OnCancelIt()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Objects;
|
||||||
|
using RPGCore.BackpackEquipment.Objects;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
using RPGCore.ObjectModules.EventObjectModule;
|
||||||
|
|
||||||
|
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events
|
||||||
|
{
|
||||||
|
public class ActionEquipEvent : BasePreventableEvent<UnitObject>
|
||||||
|
{
|
||||||
|
public UnitObject unit;
|
||||||
|
public WearableObject wearable;
|
||||||
|
public int index;
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4de9db105bf64cd98dce43e3ec414e98
|
||||||
|
timeCreated: 1780567832
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Objects;
|
||||||
|
using RPGCore.BackpackEquipment.Objects;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
using RPGCore.ObjectModules.EventObjectModule;
|
||||||
|
|
||||||
|
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events
|
||||||
|
{
|
||||||
|
public class ActionUnEquipEvent : BasePreventableEvent<UnitObject>
|
||||||
|
{
|
||||||
|
public UnitObject unit;
|
||||||
|
public WearableObject wearable;
|
||||||
|
public int index;
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 74199cbcfe30426aa9191ea3f9ab0f9c
|
||||||
|
timeCreated: 1780567872
|
||||||
+1
-1
@@ -5,7 +5,7 @@ using RPGCore.ObjectModules.EventObjectModule;
|
|||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events
|
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events
|
||||||
{
|
{
|
||||||
public class EquipEvent : BaseEvent<UnitObject>
|
public class EquipmentEquipEvent : BaseEvent<UnitObject>
|
||||||
{
|
{
|
||||||
public UnitObject unit;
|
public UnitObject unit;
|
||||||
public WearableObject wearable;
|
public WearableObject wearable;
|
||||||
+1
-1
@@ -5,7 +5,7 @@ using RPGCore.ObjectModules.EventObjectModule;
|
|||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events
|
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events
|
||||||
{
|
{
|
||||||
public class UnEquipEvent : BaseEvent<UnitObject>
|
public class EquipmentUnEquipEvent : BaseEvent<UnitObject>
|
||||||
{
|
{
|
||||||
public UnitObject unit;
|
public UnitObject unit;
|
||||||
public WearableObject wearable;
|
public WearableObject wearable;
|
||||||
+7
-3
@@ -11,9 +11,13 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment
|
namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment
|
||||||
{
|
{
|
||||||
[RequireComponent(typeof(UnitObject))]
|
|
||||||
[RequireComponent(typeof(ContentModule))]
|
[RequireComponent(typeof(ContentModule))]
|
||||||
[DisallowMultipleComponent]
|
[DisallowMultipleComponent]
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Inventory] Equipment",
|
||||||
|
description: "Requires <b>ContentModule</b> to work. Attached to <b>UnitObject</b>. " +
|
||||||
|
"Allows to define equipment schema which further allows to equip those wearable items."
|
||||||
|
)]
|
||||||
public class UnitEquipmentModule : ObjectModule<UnitObject>, IContentOwner
|
public class UnitEquipmentModule : ObjectModule<UnitObject>, IContentOwner
|
||||||
{
|
{
|
||||||
[SerializeField] private EquipmentSchemaSO _schema;
|
[SerializeField] private EquipmentSchemaSO _schema;
|
||||||
@@ -56,7 +60,7 @@ namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment
|
|||||||
{
|
{
|
||||||
var wearable = (WearableObject)item;
|
var wearable = (WearableObject)item;
|
||||||
|
|
||||||
parent.events.Invoke(new EquipEvent { unit = parent, wearable = wearable, index = index });
|
parent.events.Invoke(new EquipmentEquipEvent { unit = parent, wearable = wearable, index = index });
|
||||||
|
|
||||||
_items[index] = wearable;
|
_items[index] = wearable;
|
||||||
return true;
|
return true;
|
||||||
@@ -67,7 +71,7 @@ namespace RPGCore.BackpackEquipment.ObjectModules.UnitEquipment
|
|||||||
var wearable = (WearableObject)item;
|
var wearable = (WearableObject)item;
|
||||||
var index = Array.IndexOf(_items, wearable);
|
var index = Array.IndexOf(_items, wearable);
|
||||||
|
|
||||||
parent.events.Invoke(new UnEquipEvent { unit = parent, wearable = wearable, index = index });
|
parent.events.Invoke(new EquipmentUnEquipEvent { unit = parent, wearable = wearable, index = index });
|
||||||
|
|
||||||
_items[index] = null;
|
_items[index] = null;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
"rootNamespace": "RPGCore.BackpackEquipment",
|
"rootNamespace": "RPGCore.BackpackEquipment",
|
||||||
"references": [
|
"references": [
|
||||||
"RPGCore",
|
"RPGCore",
|
||||||
"RPGCore.StatusEffect",
|
|
||||||
"RPGCoreCommon.Settings",
|
"RPGCoreCommon.Settings",
|
||||||
"RPGCoreCommon.Helpers",
|
"RPGCoreCommon.Helpers",
|
||||||
"RPGCoreCommon.DynamicValues"
|
"RPGCoreCommon.DynamicValues"
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 78e047e9e9834fd1ac2cf2546eb2b8c2
|
||||||
|
timeCreated: 1780247721
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6e793636b88348dd8ba6dfef253056cb
|
||||||
|
timeCreated: 1780247729
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ea5e3fca9792442d90b5aba2ae37e105
|
||||||
|
timeCreated: 1780247773
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "RPGCore.BackpackEquipment.StatusEffect.Editor",
|
||||||
|
"rootNamespace": "RPGCore.BackpackEquipment.StatusEffect.Editor",
|
||||||
|
"references": [
|
||||||
|
"RPGCore",
|
||||||
|
"RPGCore.Editor",
|
||||||
|
"RPGCore.BackpackEquipment",
|
||||||
|
"RPGCore.StatusEffect"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 847b1528d6884dccb4e9eca1e9e0002b
|
||||||
|
timeCreated: 1780247908
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 65d922d179214a61905337e8b7815eae
|
||||||
|
timeCreated: 1780247793
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 658a042ae2aa46a0b66ba1bf4ac209e7
|
||||||
|
timeCreated: 1780344247
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
using RPGCore.BackpackEquipment.Events;
|
||||||
|
using RPGCore.BackpackEquipment.Objects;
|
||||||
|
using RPGCore.Core;
|
||||||
|
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace RPGCore.Inventory2Status.ObjectModules
|
||||||
|
{
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Integration] Usable with effects",
|
||||||
|
description: "<b>UsableObjects</b> with definable effects."
|
||||||
|
)]
|
||||||
|
public class UsableEffectsModule : ObjectModule<UsableObject>
|
||||||
|
{
|
||||||
|
[SerializeField] private BaseEffect[] effectsOnUse;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
parent.events.RegisterAfter<UseUsableEvent>(OnUseUsable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUseUsable(UseUsableEvent ev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 68266e6bff4e407ab40c97af05f6da37
|
||||||
|
timeCreated: 1782059030
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Events;
|
||||||
|
using RPGCore.BackpackEquipment.ObjectModules.UnitEquipment.Objects;
|
||||||
|
using RPGCore.Core;
|
||||||
|
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace RPGCore.Inventory2Status.ObjectModules
|
||||||
|
{
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Integration] Wearable with effects",
|
||||||
|
description: "<b>WearableObjects</b> with definable effects."
|
||||||
|
)]
|
||||||
|
public class WearableEffectsModule : ObjectModule<WearableObject>
|
||||||
|
{
|
||||||
|
[SerializeField] private BaseEffect[] effectsOnEquip;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
parent.events.Register<EquipmentEquipEvent>(OnEquip);
|
||||||
|
parent.events.Register<EquipmentUnEquipEvent>(OnUnEquip);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEquip(EquipmentEquipEvent ev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnEquip(EquipmentUnEquipEvent ev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 054fa1f205b04842a24d93c6316fe929
|
||||||
|
timeCreated: 1782061679
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "RPGCore.BackpackEquipment.StatusEffect",
|
||||||
|
"rootNamespace": "RPGCore.BackpackEquipment.StatusEffect",
|
||||||
|
"references": [
|
||||||
|
"RPGCore",
|
||||||
|
"RPGCore.BackpackEquipment",
|
||||||
|
"RPGCore.StatusEffect"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6b01bf7f791f41d59d0a1dc1e6f164b4
|
||||||
|
timeCreated: 1780247930
|
||||||
@@ -10,8 +10,11 @@ using UnityEngine;
|
|||||||
namespace RPGCore.Movement.ObjectModules.UnitAnimator
|
namespace RPGCore.Movement.ObjectModules.UnitAnimator
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
[RequireComponent(typeof(UnitObject))]
|
|
||||||
[RequireComponent(typeof(UnitMovementModule))]
|
[RequireComponent(typeof(UnitMovementModule))]
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Movement] Animator",
|
||||||
|
description: "Attached to <b>UnitObject</b> and requires <b>UnitMovementModule</b>. Updates animator data."
|
||||||
|
)]
|
||||||
public class UnitAnimatorModule : ObjectModule<UnitObject>
|
public class UnitAnimatorModule : ObjectModule<UnitObject>
|
||||||
{
|
{
|
||||||
// CONSTANT (defined in animator)
|
// CONSTANT (defined in animator)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
||||||
{
|
{
|
||||||
public class DirectionMoveAction : BaseActionParallel
|
public class DirectionMoveAction : BaseAction
|
||||||
{
|
{
|
||||||
private readonly Func<Vector3> _directionGetter;
|
private readonly Func<Vector3> _directionGetter;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using RPGCoreCommon.Helpers;
|
|||||||
|
|
||||||
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
||||||
{
|
{
|
||||||
public class JumpAction : BaseActionParallel
|
public class JumpAction : BaseAction
|
||||||
{
|
{
|
||||||
public override void CanDoIt()
|
public override void CanDoIt()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using UnityEngine.AI;
|
|||||||
|
|
||||||
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
||||||
{
|
{
|
||||||
public class PointMoveAction : BaseActionParallel
|
public class PointMoveAction : BaseAction
|
||||||
{
|
{
|
||||||
private readonly Vector3 _destination;
|
private readonly Vector3 _destination;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
|
||||||
{
|
{
|
||||||
public class RotateAction : BaseActionParallel
|
public class RotateAction : BaseAction
|
||||||
{
|
{
|
||||||
private Coroutine _rotateCoroutine;
|
private Coroutine _rotateCoroutine;
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,11 @@ using UnityEngine.AI;
|
|||||||
namespace RPGCore.Movement.ObjectModules.UnitMovement
|
namespace RPGCore.Movement.ObjectModules.UnitMovement
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
[RequireComponent(typeof(UnitObject))]
|
|
||||||
[RequireComponent(typeof(CapsuleCollider))]
|
[RequireComponent(typeof(CapsuleCollider))]
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Movement] Action Movement",
|
||||||
|
description: "Attached to <b>UnitObject</b>. Simple movement module that allows movement in given direction. Made with action type movement in mind."
|
||||||
|
)]
|
||||||
public class UnitMovementModule : ObjectModule<UnitObject>
|
public class UnitMovementModule : ObjectModule<UnitObject>
|
||||||
{
|
{
|
||||||
// SERIALIZED
|
// SERIALIZED
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace RPGCore.Movement.SceneModules.ActionController
|
|||||||
[SerializeField] private InputActionReference _jumpInput;
|
[SerializeField] private InputActionReference _jumpInput;
|
||||||
|
|
||||||
private Camera _camera;
|
private Camera _camera;
|
||||||
private BaseActionParallel _moveAction;
|
private BaseAction _moveAction;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
|
|||||||
/// Extend this to make custom effect that can be used by <see cref="StatusDefinitionSO"/>.
|
/// Extend this to make custom effect that can be used by <see cref="StatusDefinitionSO"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class Effect
|
public abstract class BaseEffect
|
||||||
{
|
{
|
||||||
public BaseObject obj { get; internal set; }
|
public BaseObject obj { get; internal set; }
|
||||||
public Status status { get; internal set; }
|
public Status status { get; internal set; }
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects
|
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects
|
||||||
{
|
{
|
||||||
public class NotControllableEffect : Effect
|
public class NotControllableEffect : BaseEffect
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -4,7 +4,7 @@ using RPGCore.ObjectModules.EventObjectModule;
|
|||||||
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events
|
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executed when <see cref="Status"/> ends normally - by timer or by <see cref="Effect"/>.
|
/// Executed when <see cref="Status"/> ends normally - by timer or by <see cref="BaseEffect"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StatusEndEvent : BaseEvent<BaseObject>
|
public class StatusEndEvent : BaseEvent<BaseObject>
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ using RPGCore.ObjectModules.EventObjectModule;
|
|||||||
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events
|
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executed when <see cref="Status"/> ends forcefully - by something else than timer or <see cref="Effect"/>.
|
/// Executed when <see cref="Status"/> ends forcefully - by something else than timer or <see cref="BaseEffect"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StatusRemoveEvent : BaseEvent<BaseObject>
|
public class StatusRemoveEvent : BaseEvent<BaseObject>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
|
|||||||
public StatusModule statusModule { get; private set; }
|
public StatusModule statusModule { get; private set; }
|
||||||
|
|
||||||
public float timeRemaining { get; private set; }
|
public float timeRemaining { get; private set; }
|
||||||
public List<Effect> effects { get; private set; }
|
public List<BaseEffect> effects { get; private set; }
|
||||||
|
|
||||||
internal Status(StatusDefinitionSO definition, StatusModule statusModule)
|
internal Status(StatusDefinitionSO definition, StatusModule statusModule)
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,7 @@ namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
|
|||||||
timeRemaining = definition.time;
|
timeRemaining = definition.time;
|
||||||
effects = definition.effects.Select(e =>
|
effects = definition.effects.Select(e =>
|
||||||
{
|
{
|
||||||
var copy = JsonUtility.FromJson<Effect>(JsonUtility.ToJson(e));
|
var copy = JsonUtility.FromJson<BaseEffect>(JsonUtility.ToJson(e));
|
||||||
copy.obj = statusModule.parent;
|
copy.obj = statusModule.parent;
|
||||||
copy.status = this;
|
copy.status = this;
|
||||||
return copy;
|
return copy;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using RPGCore.Core.Objects;
|
using RPGCore.Core.Objects;
|
||||||
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects;
|
|
||||||
using RPGCoreCommon.DynamicValues;
|
using RPGCoreCommon.DynamicValues;
|
||||||
using RPGCoreCommon.Helpers.CustomTypes;
|
using RPGCoreCommon.Helpers.CustomTypes;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -26,7 +25,7 @@ namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
|
|||||||
[Min(0)] public float time;
|
[Min(0)] public float time;
|
||||||
|
|
||||||
[Header("Effects")]
|
[Header("Effects")]
|
||||||
[SerializeReference] public List<Effect> effects = new();
|
[SerializeReference] public List<BaseEffect> effects = new();
|
||||||
|
|
||||||
private void OnValidate()
|
private void OnValidate()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using RPGCore.Core;
|
using RPGCore.Core;
|
||||||
using RPGCore.Core.Objects;
|
using RPGCore.Core.Objects;
|
||||||
using RPGCore.ObjectModules.EventObjectModule;
|
|
||||||
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects;
|
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Effects;
|
||||||
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events;
|
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule.Events;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -11,7 +10,12 @@ using UnityEngine;
|
|||||||
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
|
namespace RPGCore.StatusEffect.ObjectModules.StatusObjectModule
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
[RequireComponent(typeof(BaseObject))]
|
[ObjectModule(
|
||||||
|
name: "[Status] Status",
|
||||||
|
description: "Attached to any implementation of <b>BaseObject</b>. Manages statuses and their effects. " +
|
||||||
|
"Create scriptable object <b>"+nameof(StatusDefinitionSO)+"</b> to make new status. " +
|
||||||
|
"For new effect create new implementation of <b>"+nameof(BaseEffect)+"</b>."
|
||||||
|
)]
|
||||||
public class StatusModule : ObjectModule<BaseObject>
|
public class StatusModule : ObjectModule<BaseObject>
|
||||||
{
|
{
|
||||||
internal List<Status> statuses { get; private set; } = new();
|
internal List<Status> statuses { get; private set; } = new();
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3bc3378d3d4847e3b8a522fce249109b
|
||||||
|
timeCreated: 1780745996
|
||||||
@@ -0,0 +1,364 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using RPGCore.Core;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
using RPGCoreCommon.Helpers;
|
||||||
|
using RPGCoreCommon.Helpers.CustomTypes;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.SceneManagement;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager
|
||||||
|
{
|
||||||
|
internal class DashboardWindow : EditorWindow
|
||||||
|
{
|
||||||
|
[SerializeField] private VisualTreeAsset _visualTreeAsset;
|
||||||
|
|
||||||
|
// CONST
|
||||||
|
private const string IsFirstTimeOpenKey = "TheVVaS.RPGCore.isFirstTimeOpen";
|
||||||
|
private const string PipeStart = "├─";
|
||||||
|
private const string PipeGo = "│\u2007\u2007";
|
||||||
|
private const string PipeEnd = "└─";
|
||||||
|
private const string PipeNone = "\u2007\u2007\u2007";
|
||||||
|
|
||||||
|
// CACHE - check CreateCache()
|
||||||
|
private static Type[] _moduleTypes;
|
||||||
|
private static Type[] _objectTypes;
|
||||||
|
private static Dictionary<Type, List<Type>> _objectTypesMap;
|
||||||
|
private static Dictionary<Type, MonoScript> _moduleMonoScripts;
|
||||||
|
|
||||||
|
// TAB - VERIFY
|
||||||
|
private Button _verifyCheckButton;
|
||||||
|
private Button _verifyFixButton;
|
||||||
|
private Button _verifyClearButton;
|
||||||
|
private MultiColumnListView _verifyListMultiColumnListView;
|
||||||
|
private List<Validation> _validations;
|
||||||
|
|
||||||
|
// TAB - MODULES
|
||||||
|
private ToolbarSearchField _modulesFilterSearchFiled;
|
||||||
|
private ScrollView _modulesListScrollView;
|
||||||
|
|
||||||
|
// TAB - CONFIG
|
||||||
|
private PropertyField _configVerifyPathsProperty;
|
||||||
|
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void OnEditorLoad()
|
||||||
|
{
|
||||||
|
var isFirstTimeOpen = EditorPrefs.GetBool(IsFirstTimeOpenKey, true);
|
||||||
|
|
||||||
|
if (!isFirstTimeOpen) return;
|
||||||
|
|
||||||
|
ShowDashboard();
|
||||||
|
EditorPrefs.SetBool(IsFirstTimeOpenKey, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MenuItem("TheVVaS/RPGCore/Dashboard", priority = -1)]
|
||||||
|
public static void ShowDashboard()
|
||||||
|
{
|
||||||
|
var window = GetWindow<DashboardWindow>();
|
||||||
|
window.titleContent = new GUIContent("RPGCore Dashboard");
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateGUI()
|
||||||
|
{
|
||||||
|
CreateCache();
|
||||||
|
UpdateConfigModules();
|
||||||
|
|
||||||
|
_visualTreeAsset.CloneTree(rootVisualElement);
|
||||||
|
_verifyCheckButton = rootVisualElement.Q<Button>("db-verify-check");
|
||||||
|
_verifyCheckButton.clicked += OnVerifyCheck;
|
||||||
|
_verifyFixButton = rootVisualElement.Q<Button>("db-verify-fix");
|
||||||
|
_verifyFixButton.clicked += OnVerifyFix;
|
||||||
|
_verifyFixButton.SetEnabled(false);
|
||||||
|
_verifyClearButton = rootVisualElement.Q<Button>("db-verify-clear");
|
||||||
|
_verifyClearButton.clicked += OnVerifyClear;
|
||||||
|
_verifyListMultiColumnListView = rootVisualElement.Q<MultiColumnListView>("db-verify-list");
|
||||||
|
CreateVerifyList();
|
||||||
|
|
||||||
|
_modulesFilterSearchFiled = rootVisualElement.Q<ToolbarSearchField>("db-modules-filter");
|
||||||
|
_modulesFilterSearchFiled.RegisterValueChangedCallback(ev => OnModuleFilter(ev.newValue));
|
||||||
|
_modulesListScrollView = rootVisualElement.Q<ScrollView>("db-modules-list");
|
||||||
|
CreateModulesList();
|
||||||
|
|
||||||
|
_configVerifyPathsProperty = rootVisualElement.Q<PropertyField>("db-config-verify-paths");
|
||||||
|
_configVerifyPathsProperty.BindProperty(
|
||||||
|
new SerializedObject(EditorConfigSO.instance).FindProperty(nameof(EditorConfigSO.verifyPaths)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateCache()
|
||||||
|
{
|
||||||
|
_moduleTypes = TypeCache.GetTypesDerivedFrom<ObjectModule>()
|
||||||
|
.OrderBy(t => t.Assembly.GetName().Name)
|
||||||
|
.Where(t => !t.IsAbstract && !t.IsInterface)
|
||||||
|
.ToArray();
|
||||||
|
_objectTypes = TypeCache.GetTypesDerivedFrom<BaseObject>()
|
||||||
|
.Append(typeof(BaseObject))
|
||||||
|
.Sort((t1, t2) => t1.IsAssignableFrom(t2) ? -1 : t2.IsAssignableFrom(t1) ? 1 : 0)
|
||||||
|
.ToArray();
|
||||||
|
_objectTypesMap = _objectTypes
|
||||||
|
.GroupBy(t => t.BaseType)
|
||||||
|
.Where(g => typeof(BaseObject).IsAssignableFrom(g.Key))
|
||||||
|
.ToDictionary(k => k.Key, v => v.ToList());
|
||||||
|
_moduleMonoScripts = MonoImporter.GetAllRuntimeMonoScripts()
|
||||||
|
.Where(m => typeof(ObjectModule).IsAssignableFrom(m.GetClass()))
|
||||||
|
.Where(m => !m.GetClass().IsAbstract && !m.GetClass().IsInterface)
|
||||||
|
.ToDictionary(m => m.GetClass(), m => m);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateConfigModules()
|
||||||
|
{
|
||||||
|
var config = EditorConfigSO.instance;
|
||||||
|
foreach (var moduleType in _moduleTypes)
|
||||||
|
{
|
||||||
|
var isRequired = moduleType.GetCustomAttribute<ObjectModuleAttribute>()?.required ?? false;
|
||||||
|
var baseObjectType = moduleType.FindGenericDefinitionType(typeof(ObjectModule<>)).GetGenericArguments()[0];
|
||||||
|
|
||||||
|
config.modules.TryAdd(moduleType, new List<SerializableType>());
|
||||||
|
|
||||||
|
if (isRequired)
|
||||||
|
{
|
||||||
|
config.modules[moduleType] = new List<SerializableType> { baseObjectType };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.modules[moduleType] = config.modules[moduleType]
|
||||||
|
.Where(t => !config.modules[moduleType].Any(st => t.type.IsSubclassOf(st)))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region VERIFY
|
||||||
|
|
||||||
|
private void CreateVerifyList()
|
||||||
|
{
|
||||||
|
_verifyListMultiColumnListView.columns["validator"].makeCell = () => new Label();
|
||||||
|
_verifyListMultiColumnListView.columns["validator"].bindCell = (element, index) =>
|
||||||
|
{
|
||||||
|
((Label)element).text = element.tooltip = _validations[index].validator.GetType().Name;
|
||||||
|
};
|
||||||
|
_verifyListMultiColumnListView.columns["message"].makeCell = () => new Label();
|
||||||
|
_verifyListMultiColumnListView.columns["message"].bindCell = (element, index) =>
|
||||||
|
{
|
||||||
|
((Label)element).text = element.tooltip = _validations[index].message;
|
||||||
|
};
|
||||||
|
_verifyListMultiColumnListView.columns["context"].makeCell = () => new Label();
|
||||||
|
_verifyListMultiColumnListView.columns["context"].bindCell = (element, index) =>
|
||||||
|
{
|
||||||
|
((Label)element).text = element.tooltip = _validations[index].contextPath;
|
||||||
|
element.RegisterCallback<PointerDownEvent>(ev =>
|
||||||
|
{
|
||||||
|
if (ev.clickCount != 2) return;
|
||||||
|
PingObject(_validations[index].contextPath);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
_verifyListMultiColumnListView.columns["hierarchy"].makeCell = () => new Label();
|
||||||
|
_verifyListMultiColumnListView.columns["hierarchy"].bindCell = (element, index) =>
|
||||||
|
{
|
||||||
|
((Label)element).text = element.tooltip = _validations[index].hierarchyPath;
|
||||||
|
element.RegisterCallback<PointerDownEvent>(ev =>
|
||||||
|
{
|
||||||
|
if (ev.clickCount != 2) return;
|
||||||
|
PingObject(_validations[index].contextPath, _validations[index].hierarchyPath);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
_verifyListMultiColumnListView.columns["result"].makeCell = () => new Label();
|
||||||
|
_verifyListMultiColumnListView.columns["result"].bindCell = (element, index) =>
|
||||||
|
{
|
||||||
|
((Label)element).text = element.tooltip = _validations[index].resultMessage;
|
||||||
|
|
||||||
|
element.EnableInClassList("verify-success", _validations[index].result == true);
|
||||||
|
element.EnableInClassList("verify-error", _validations[index].result == false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PingObject(string contextPath, string hierarchyPath = null)
|
||||||
|
{
|
||||||
|
var contextFile = AssetDatabase.LoadMainAssetAtPath(contextPath);
|
||||||
|
GameObject hierarchyObjectRoot;
|
||||||
|
|
||||||
|
if (hierarchyPath == null)
|
||||||
|
{
|
||||||
|
EditorGUIUtility.PingObject(contextFile.GetInstanceID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hierarchyPathArray = hierarchyPath.Split('/', 2);
|
||||||
|
|
||||||
|
if (contextFile is SceneAsset)
|
||||||
|
{
|
||||||
|
hierarchyObjectRoot = EditorSceneManager.OpenScene(contextPath)
|
||||||
|
.GetRootGameObjects().FirstOrDefault(go => go.name == hierarchyPathArray[0]);
|
||||||
|
}
|
||||||
|
else if (contextFile is GameObject)
|
||||||
|
{
|
||||||
|
hierarchyObjectRoot = PrefabStageUtility.OpenPrefab(contextPath).prefabContentsRoot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"Given file '{contextPath}' is not prefab nor scene!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hierarchyObjectRoot)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Can't find root game object '{hierarchyPathArray[0]}' in '{contextPath}'. Perhaps did you change something?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hierarchyObject = hierarchyPathArray.Length > 1 ?
|
||||||
|
hierarchyObjectRoot.transform.Find(hierarchyPathArray[1])?.gameObject : hierarchyObjectRoot;
|
||||||
|
|
||||||
|
if (!hierarchyObject)
|
||||||
|
{
|
||||||
|
Debug.LogError($"Can't find '{hierarchyPath}' in '{contextPath}'. Perhaps did you change something?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorGUIUtility.PingObject(hierarchyObject.GetInstanceID());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVerifyCheck()
|
||||||
|
{
|
||||||
|
_validations = ValidationSolver.Check(EditorConfigSO.instance.verifyPaths);
|
||||||
|
_verifyListMultiColumnListView.itemsSource = _validations;
|
||||||
|
_verifyListMultiColumnListView.RefreshItems();
|
||||||
|
|
||||||
|
_verifyFixButton.SetEnabled(_validations.Any());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVerifyFix()
|
||||||
|
{
|
||||||
|
ValidationSolver.FixAll(_validations);
|
||||||
|
_verifyListMultiColumnListView.RefreshItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnVerifyClear()
|
||||||
|
{
|
||||||
|
_validations.Clear();
|
||||||
|
_verifyListMultiColumnListView.RefreshItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region MODULES
|
||||||
|
|
||||||
|
private void CreateModulesList()
|
||||||
|
{
|
||||||
|
_modulesListScrollView.Clear();
|
||||||
|
_moduleTypes.Select(CreateModuleRow).ForEach(_modulesListScrollView.Add);
|
||||||
|
}
|
||||||
|
|
||||||
|
private VisualElement CreateModuleRow(Type moduleType)
|
||||||
|
{
|
||||||
|
var objectType = moduleType.FindGenericDefinitionType(typeof(ObjectModule<>)).GetGenericArguments()[0];
|
||||||
|
var moduleAttribute = moduleType.GetCustomAttribute<ObjectModuleAttribute>();
|
||||||
|
var moduleMonoScript = _moduleMonoScripts.GetValueOrDefault(moduleType);
|
||||||
|
|
||||||
|
var foldout = new Foldout();
|
||||||
|
foldout.AddToClassList("module-foldout");
|
||||||
|
foldout.value = false;
|
||||||
|
var moduleName = $"<b>{moduleAttribute?.name ?? moduleType.Name}</b>";
|
||||||
|
var assemblyName = $"<alpha=\"#69\">asm: {moduleType.Assembly.GetName().Name}</alpha>";
|
||||||
|
foldout.text = moduleName + " " + assemblyName;
|
||||||
|
|
||||||
|
var objectField = new ObjectField { objectType = typeof(MonoScript), value = moduleMonoScript, enabledSelf = false };
|
||||||
|
foldout.Add(objectField);
|
||||||
|
|
||||||
|
var descriptionLabel = new Label(moduleAttribute?.description ?? $"// {nameof(ObjectModuleAttribute)} not found on {moduleType.Name} //");
|
||||||
|
descriptionLabel.style.whiteSpace = WhiteSpace.Normal;
|
||||||
|
foldout.Add(descriptionLabel);
|
||||||
|
|
||||||
|
var usageTreeElement = CreateObjectTreeUsageForModule(moduleType, objectType, moduleAttribute?.required ?? false);
|
||||||
|
foldout.Add(usageTreeElement);
|
||||||
|
|
||||||
|
return foldout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VisualElement CreateObjectTreeUsageForModule(Type moduleType, Type objectType, bool isRequired, string prefix = "")
|
||||||
|
{
|
||||||
|
var config = EditorConfigSO.instance;
|
||||||
|
var isEnabled = config.modules?.GetValueOrDefault(moduleType)?.Any(st => st.type == objectType) ?? false;
|
||||||
|
|
||||||
|
var section = new VisualElement();
|
||||||
|
|
||||||
|
if (prefix == "")
|
||||||
|
{
|
||||||
|
var sectionTitle = new Label();
|
||||||
|
sectionTitle.style.marginTop = 8;
|
||||||
|
sectionTitle.text = "<u>Modules enabled by default:</u>";
|
||||||
|
section.Add(sectionTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
var row = new VisualElement();
|
||||||
|
row.style.flexDirection = FlexDirection.Row;
|
||||||
|
section.Add(row);
|
||||||
|
|
||||||
|
var rowPrefixPipe = new Label(prefix);
|
||||||
|
rowPrefixPipe.style.whiteSpace = WhiteSpace.Pre;
|
||||||
|
row.Add(rowPrefixPipe);
|
||||||
|
|
||||||
|
var rowModuleToggle = new Toggle(objectType.Name);
|
||||||
|
rowModuleToggle.name = $"module-{moduleType.Name}-{objectType.Name}";
|
||||||
|
rowModuleToggle.value = isRequired || isEnabled;
|
||||||
|
rowModuleToggle.SetEnabled(!isRequired);
|
||||||
|
rowModuleToggle.RegisterValueChangedCallback(ev => UpdateModuleUsage(moduleType, objectType, ev.newValue));
|
||||||
|
row.Add(rowModuleToggle);
|
||||||
|
|
||||||
|
if (!_objectTypesMap.TryGetValue(objectType, out var subTypes)) return section;
|
||||||
|
|
||||||
|
prefix = prefix.Replace(PipeStart, PipeGo).Replace(PipeEnd, PipeNone);
|
||||||
|
|
||||||
|
for (var i = 0; i < subTypes.Count; i++)
|
||||||
|
{
|
||||||
|
var subPrefix = prefix + (i == subTypes.Count-1 ? PipeEnd : PipeStart);
|
||||||
|
var subType = subTypes[i];
|
||||||
|
var subSection = CreateObjectTreeUsageForModule(moduleType, subType, isRequired || isEnabled, subPrefix);
|
||||||
|
section.Add(subSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateModuleUsage(Type moduleType, Type objectType, bool isRequired)
|
||||||
|
{
|
||||||
|
var toggleName = $"module-{moduleType.Name}-{objectType.Name}";
|
||||||
|
var toggle = _modulesListScrollView.Q<Toggle>(toggleName);
|
||||||
|
toggle.parent.parent
|
||||||
|
.Query<Toggle>()
|
||||||
|
.ToList()
|
||||||
|
.Where(subToggle => subToggle != toggle)
|
||||||
|
.ForEach(subToggle =>
|
||||||
|
{
|
||||||
|
subToggle.SetValueWithoutNotify(false);
|
||||||
|
subToggle.SetEnabled(!isRequired);
|
||||||
|
});
|
||||||
|
|
||||||
|
var config = EditorConfigSO.instance;
|
||||||
|
config.modules[moduleType].RemoveAll(t => objectType.IsAssignableFrom(t));
|
||||||
|
if (isRequired) config.modules[moduleType].Add(objectType);
|
||||||
|
config.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnModuleFilter(string filter)
|
||||||
|
{
|
||||||
|
var foldouts = _modulesListScrollView.Query<Foldout>(className: "module-foldout").ToList();
|
||||||
|
|
||||||
|
foreach (var foldout in foldouts)
|
||||||
|
{
|
||||||
|
var matchFilter = foldout.text.Contains(filter, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
foldout.style.display = matchFilter ? DisplayStyle.Flex : DisplayStyle.None;
|
||||||
|
foldout.value = !string.IsNullOrEmpty(filter) && matchFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 75b5674e6448496f8272962a2786cf84
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences:
|
||||||
|
- m_ViewDataDictionary: {instanceID: 0}
|
||||||
|
- _visualTreeAsset: {fileID: 9197481963319205126, guid: 3407a07e2ddf46b9abc87c2f32b2efb0, type: 3}
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
TabView {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabView #unity-tab-view__header-container {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabView #unity-tab__header {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabView #unity-tab__header-label {
|
||||||
|
flex-grow: 1;
|
||||||
|
-unity-text-align: upper-center;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabView #unity-tab-view__content-container {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabView > Tab {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabView > Tab > #unity-tab__content-container {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toolbar > Label {
|
||||||
|
-unity-text-align: middle-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toolbar > ToolbarSpacer {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toolbar > ToolbarButton {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-hello {
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-hello > #db-hello-title {
|
||||||
|
-unity-text-align: upper-center;
|
||||||
|
-unity-font-style: bold;
|
||||||
|
font-size: 36px;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-hello > #db-hello-description {
|
||||||
|
-unity-text-align: upper-center;
|
||||||
|
-unity-font-style: normal;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-verify {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-verify > #db-verify-list {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-verify > #db-verify-list .unity-multi-column-view__cell > * {
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-left: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-verify > #db-verify-list .verify-success {
|
||||||
|
color: rgb(0, 255, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-verify > #db-verify-list .verify-error {
|
||||||
|
color: rgb(255, 69, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-modules > #db-modules-list > Foldout {
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-right: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-modules > #db-modules-list > Foldout:hover {
|
||||||
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-modules > #db-modules-list > Foldout > Toggle {
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-right: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
padding-left: 2px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
border-bottom-left-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-modules > #db-modules-list > Foldout > Toggle Label {
|
||||||
|
}
|
||||||
|
|
||||||
|
#db-modules > #db-modules-list > Foldout > .unity-foldout__content {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5310fd50f52f49e3aeb54cbd15bc986f
|
||||||
|
timeCreated: 1780746434
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
|
||||||
|
<Style src="project://database/Assets/TheVVaS/RPGCore/Editor/CoreManager/DashboardWindow.uss?fileID=7433441132597879392&guid=5310fd50f52f49e3aeb54cbd15bc986f&type=3#DashboardWindow"/>
|
||||||
|
<ui:TabView name="db-root">
|
||||||
|
<ui:Tab label="Hello" name="db-hello">
|
||||||
|
<ui:Label text="RPGCORE" name="db-hello-title"/>
|
||||||
|
<ui:Label text="RPGCORE" name="db-hello-description"/>
|
||||||
|
</ui:Tab>
|
||||||
|
<ui:Tab label="Verify" name="db-verify">
|
||||||
|
<uie:Toolbar name="">
|
||||||
|
<ui:Label text="Warnings about component usages:"/>
|
||||||
|
<uie:ToolbarSpacer/>
|
||||||
|
<uie:ToolbarButton text="Check" name="db-verify-check"/>
|
||||||
|
<uie:ToolbarButton text="Fix all" name="db-verify-fix"/>
|
||||||
|
<uie:ToolbarButton text="Clear" name="db-verify-clear"/>
|
||||||
|
</uie:Toolbar>
|
||||||
|
<ui:MultiColumnListView columns="" sort-column-descriptions="" name="db-verify-list">
|
||||||
|
<ui:Columns reorderable="false" primary-column-name="validator">
|
||||||
|
<ui:Column name="validator" title="Validator" sortable="false" optional="false" stretchable="true"/>
|
||||||
|
<ui:Column name="message" title="Message" sortable="false" optional="false" stretchable="true"/>
|
||||||
|
<ui:Column name="context" title="File" sortable="false" optional="false" stretchable="true"/>
|
||||||
|
<ui:Column name="hierarchy" title="Hierarchy" sortable="false" optional="false" stretchable="true"/>
|
||||||
|
<ui:Column name="result" title="Result" stretchable="true" sortable="false" optional="false" visible="true"/>
|
||||||
|
</ui:Columns>
|
||||||
|
</ui:MultiColumnListView>
|
||||||
|
</ui:Tab>
|
||||||
|
<ui:Tab label="Modules" name="db-modules">
|
||||||
|
<uie:Toolbar name="">
|
||||||
|
<uie:ToolbarSearchField name="db-modules-filter"/>
|
||||||
|
<uie:ToolbarSpacer/>
|
||||||
|
<uie:ToolbarButton text="Button"/>
|
||||||
|
</uie:Toolbar>
|
||||||
|
<ui:ScrollView name="db-modules-list"/>
|
||||||
|
</ui:Tab>
|
||||||
|
<ui:Tab label="Config" name="db-config">
|
||||||
|
<ui:ScrollView>
|
||||||
|
<uie:PropertyField name="db-config-verify-paths"/>
|
||||||
|
</ui:ScrollView>
|
||||||
|
</ui:Tab>
|
||||||
|
</ui:TabView>
|
||||||
|
</ui:UXML>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3407a07e2ddf46b9abc87c2f32b2efb0
|
||||||
|
timeCreated: 1780746434
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using RPGCoreCommon.Helpers.CustomTypes;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Search;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
[FilePath("Assets/TheVVaS/RPGCore/Editor/CoreManager/EditorConfigSO.asset", FilePathAttribute.Location.ProjectFolder)]
|
||||||
|
internal class EditorConfigSO : ScriptableSingleton<EditorConfigSO>
|
||||||
|
{
|
||||||
|
[SerializeField]
|
||||||
|
internal SerializableDictionary<SerializableType, List<SerializableType>> modules = new();
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
internal string[] verifyPaths;
|
||||||
|
|
||||||
|
internal void Save() => base.Save(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ae589e57361f4f7a8a3c978f5ed6b14e
|
||||||
|
timeCreated: 1781360025
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using RPGCore.Editor.CoreManager.Validators;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager
|
||||||
|
{
|
||||||
|
internal class Validation
|
||||||
|
{
|
||||||
|
internal IValidator validator;
|
||||||
|
internal string message;
|
||||||
|
internal string contextPath;
|
||||||
|
internal string hierarchyPath;
|
||||||
|
internal bool? result;
|
||||||
|
internal string resultMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6cf1ca955da24272b089bf08c86f39f4
|
||||||
|
timeCreated: 1780839857
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using RPGCore.Editor.CoreManager.Validators;
|
||||||
|
using RPGCoreCommon.Helpers;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.SceneManagement;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager
|
||||||
|
{
|
||||||
|
internal static class ValidationSolver
|
||||||
|
{
|
||||||
|
private static readonly List<IValidator> Validators =
|
||||||
|
TypeCache.GetTypesDerivedFrom<IValidator>()
|
||||||
|
.Select(Activator.CreateInstance)
|
||||||
|
.Cast<IValidator>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void AutomaticValidation_Initialize() => ObjectChangeEvents.changesPublished += AutomaticValidation;
|
||||||
|
|
||||||
|
private static void AutomaticValidation(ref ObjectChangeEventStream stream)
|
||||||
|
{
|
||||||
|
var instanceIds = new List<int>();
|
||||||
|
|
||||||
|
for (var i = 0; i < stream.length; i++)
|
||||||
|
{
|
||||||
|
if (stream.GetEventType(i) != ObjectChangeKind.ChangeGameObjectStructure) continue;
|
||||||
|
|
||||||
|
stream.GetChangeGameObjectStructureEvent(0, out var ev);
|
||||||
|
instanceIds.Add(ev.instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceIds.Count == 0) return;
|
||||||
|
|
||||||
|
var validations = Check(instanceIds);
|
||||||
|
FixAll(validations);
|
||||||
|
|
||||||
|
// Can't finish because of exception or error
|
||||||
|
validations
|
||||||
|
.Where(v => v.result == false)
|
||||||
|
.Select(v => "--- ERROR: " + v.resultMessage +
|
||||||
|
"\n> " + v.contextPath +
|
||||||
|
"\n> " + v.hierarchyPath +
|
||||||
|
"\n> " + v.validator.GetType().Name +
|
||||||
|
"\n> " + v.message)
|
||||||
|
.ForEach(Debug.LogError);
|
||||||
|
|
||||||
|
// No fix defined
|
||||||
|
validations
|
||||||
|
.Where(v => v.result == null)
|
||||||
|
.Select(v => "--- WARNING: " + v.resultMessage +
|
||||||
|
"\n> " + v.contextPath +
|
||||||
|
"\n> " + v.hierarchyPath +
|
||||||
|
"\n> " + v.validator.GetType().Name +
|
||||||
|
"\n> " + v.message)
|
||||||
|
.ForEach(Debug.LogWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<Validation> Check(List<int> instanceIds)
|
||||||
|
{
|
||||||
|
var validations = new List<Validation>();
|
||||||
|
|
||||||
|
foreach (var instanceId in instanceIds)
|
||||||
|
{
|
||||||
|
var obj = EditorUtility.EntityIdToObject(instanceId);
|
||||||
|
if (obj is not GameObject go) continue;
|
||||||
|
|
||||||
|
Check(go, validations, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validations;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<Validation> Check(string[] paths)
|
||||||
|
{
|
||||||
|
var validations = new List<Validation>();
|
||||||
|
|
||||||
|
foreach (var guid in AssetDatabase.FindAssetGUIDs("t:Scene", paths))
|
||||||
|
{
|
||||||
|
var scene = EditorSceneManager.OpenPreviewScene(AssetDatabase.GUIDToAssetPath(guid));
|
||||||
|
foreach (var go in scene.GetRootGameObjects())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Check(go, validations, true);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorSceneManager.ClosePreviewScene(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var guid in AssetDatabase.FindAssetGUIDs("t:Prefab", paths))
|
||||||
|
{
|
||||||
|
var prefabPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
|
var prefab = PrefabUtility.LoadPrefabContents(prefabPath);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Check(prefab, validations, true);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefabUtility.UnloadPrefabContents(prefab);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validations;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Check(GameObject go, List<Validation> result, bool recursive)
|
||||||
|
{
|
||||||
|
// On scene and part of other prefab - don't validate that, it will be validated separately anyway
|
||||||
|
if (PrefabUtility.IsPartOfPrefabInstance(go)) return;
|
||||||
|
|
||||||
|
foreach (var validator in Validators)
|
||||||
|
{
|
||||||
|
var message = validator.Check(go);
|
||||||
|
if (string.IsNullOrEmpty(message)) continue;
|
||||||
|
|
||||||
|
result.Add(new Validation
|
||||||
|
{
|
||||||
|
validator = validator,
|
||||||
|
message = message,
|
||||||
|
contextPath = GetContextPath(go),
|
||||||
|
hierarchyPath = GetHierarchyPath(go),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!recursive) return;
|
||||||
|
for (var i = 0; i < go.transform.childCount; i++)
|
||||||
|
Check(go.transform.GetChild(i).gameObject, result, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void FixAll(List<Validation> validations)
|
||||||
|
{
|
||||||
|
foreach (var validation in validations)
|
||||||
|
{
|
||||||
|
var contextType = AssetDatabase.GetMainAssetTypeAtPath(validation.contextPath);
|
||||||
|
|
||||||
|
if (contextType == typeof(SceneAsset)) FixOnScene(validation);
|
||||||
|
else if (contextType == typeof(GameObject)) FixOnPrefab(validation);
|
||||||
|
else throw new Exception($"Given file '{validation.contextPath}' is not prefab nor scene!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FixOnScene(Validation validation)
|
||||||
|
{
|
||||||
|
var scene = Enumerable.Range(0, SceneManager.loadedSceneCount)
|
||||||
|
.Select(SceneManager.GetSceneAt)
|
||||||
|
.FirstOrDefault(scene => scene.path == validation.contextPath);
|
||||||
|
var isActive = scene.IsValid();
|
||||||
|
if (!isActive) scene = EditorSceneManager.OpenPreviewScene(validation.contextPath);
|
||||||
|
var go = FindGameObject(scene.GetRootGameObjects(), validation);
|
||||||
|
FixGameObject(go, validation);
|
||||||
|
if (isActive) EditorUtility.SetDirty(go);
|
||||||
|
if (!isActive) EditorSceneManager.SaveScene(scene);
|
||||||
|
if (!isActive) EditorSceneManager.ClosePreviewScene(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FixOnPrefab(Validation validation)
|
||||||
|
{
|
||||||
|
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
|
||||||
|
var isActive = prefabStage && prefabStage.assetPath == validation.contextPath;
|
||||||
|
var prefabRoot = isActive
|
||||||
|
? prefabStage.prefabContentsRoot
|
||||||
|
: PrefabUtility.LoadPrefabContents(validation.contextPath);
|
||||||
|
var go = FindGameObject(new[] { prefabRoot }, validation);
|
||||||
|
FixGameObject(go, validation);
|
||||||
|
if (isActive) EditorUtility.SetDirty(go);
|
||||||
|
if (!isActive) PrefabUtility.SaveAsPrefabAsset(prefabRoot, validation.contextPath);
|
||||||
|
if (!isActive) PrefabUtility.UnloadPrefabContents(prefabRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GameObject FindGameObject(GameObject[] roots, Validation validation)
|
||||||
|
{
|
||||||
|
var hierarchyPathArray = validation.hierarchyPath.Split('/', 2);
|
||||||
|
var root = roots.FirstOrDefault(go => go.name == hierarchyPathArray[0]);
|
||||||
|
if (!root) throw new Exception($"Root '{hierarchyPathArray[0]}' not found in '{validation.contextPath}'!");
|
||||||
|
var go = hierarchyPathArray.Length > 1 ? root.transform.Find(hierarchyPathArray[1])?.gameObject : root;
|
||||||
|
if (!go) throw new Exception($"GameObject '{validation.hierarchyPath}' not found in '{validation.contextPath}'!");
|
||||||
|
return go;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FixGameObject(GameObject go, Validation validation)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
validation.validator.Fix(go);
|
||||||
|
validation.resultMessage = "Done.";
|
||||||
|
validation.result = true;
|
||||||
|
}
|
||||||
|
catch (NotImplementedException)
|
||||||
|
{
|
||||||
|
validation.resultMessage = "No Auto-fix defined. Do it yourself.";
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
validation.result = false;
|
||||||
|
validation.resultMessage = e.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetContextPath(GameObject go)
|
||||||
|
{
|
||||||
|
// ON PREFAB STAGE - this one will be used only in realtime correcting, never in verify tab
|
||||||
|
if (PrefabStageUtility.GetPrefabStage(go) is {} stage) return stage.assetPath;
|
||||||
|
|
||||||
|
// ON SCENE
|
||||||
|
if (go.scene.IsValid()) return go.scene.path;
|
||||||
|
|
||||||
|
// PREFAB ASSET
|
||||||
|
if (PrefabUtility.IsPartOfPrefabAsset(go)) return go.scene.path;
|
||||||
|
|
||||||
|
throw new Exception("No valid context path found, sad pepe :(");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetHierarchyPath(GameObject go)
|
||||||
|
{
|
||||||
|
var path = new List<string>();
|
||||||
|
|
||||||
|
while (go is not null)
|
||||||
|
{
|
||||||
|
path.Add(go.name);
|
||||||
|
go = go.transform.parent?.gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join("/", path.AsEnumerable().Reverse());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b0debb69c5494d57afaa2f4ae614e28b
|
||||||
|
timeCreated: 1780746179
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 013142cbe59742f3a74785de7737c679
|
||||||
|
timeCreated: 1780836497
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager.Validators
|
||||||
|
{
|
||||||
|
internal interface IValidator
|
||||||
|
{
|
||||||
|
internal string title { get; }
|
||||||
|
internal string Check(GameObject gameObject);
|
||||||
|
internal void Fix(GameObject gameObject) => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bf525989f81247dfb51cd609a3dd659b
|
||||||
|
timeCreated: 1780761759
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using RPGCore.Core;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
using RPGCoreCommon.Helpers;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager.Validators
|
||||||
|
{
|
||||||
|
internal class MissingModuleValidator : IValidator
|
||||||
|
{
|
||||||
|
// ObjectType => List of ModuleType (only required by config)
|
||||||
|
private static readonly Dictionary<Type, List<Type>> RequiredModulesMap =
|
||||||
|
TypeCache.GetTypesDerivedFrom<ObjectModule>()
|
||||||
|
.Where(t => !t.IsAbstract && !t.IsInterface)
|
||||||
|
.GroupBy(t => t.FindGenericDefinitionType(typeof(ObjectModule<>)).GetGenericArguments()[0])
|
||||||
|
.ToDictionary(
|
||||||
|
g => g.Key,
|
||||||
|
g => g.ToList().Where(t => IsModuleRequired(t, g.Key)).ToList()
|
||||||
|
);
|
||||||
|
|
||||||
|
string IValidator.title => "Adding missing modules";
|
||||||
|
|
||||||
|
private static bool IsModuleRequired(Type moduleType, Type objectType)
|
||||||
|
{
|
||||||
|
return EditorConfigSO.instance.modules.GetValueOrDefault(moduleType)?.Contains(objectType) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Type> FindMissingModules(GameObject gameObject)
|
||||||
|
{
|
||||||
|
var objectType = gameObject.GetComponent<BaseObject>()?.GetType();
|
||||||
|
if (objectType == null) return null;
|
||||||
|
|
||||||
|
return RequiredModulesMap
|
||||||
|
.Where(pair => objectType.IsAssignableFrom(pair.Key))
|
||||||
|
.SelectMany(pair => pair.Value)
|
||||||
|
.Where(t => !gameObject.GetComponent(t))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
string IValidator.Check(GameObject gameObject)
|
||||||
|
{
|
||||||
|
var missingModules = FindMissingModules(gameObject);
|
||||||
|
if (missingModules.Count < 1) return null;
|
||||||
|
|
||||||
|
return "Missing modules: " + missingModules.Select(m => m.Name).StringJoin(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IValidator.Fix(GameObject gameObject)
|
||||||
|
{
|
||||||
|
var missingModules = FindMissingModules(gameObject);
|
||||||
|
if (missingModules.Count < 1) return;
|
||||||
|
|
||||||
|
missingModules.ForEach(m => gameObject.AddComponent(m));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 117ff9ca9b964927a0482806c91a75d7
|
||||||
|
timeCreated: 1780846792
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
using RPGCoreCommon.Helpers;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager.Validators
|
||||||
|
{
|
||||||
|
internal class MultipleObjectsValidator : IValidator
|
||||||
|
{
|
||||||
|
string IValidator.title => "Removing duplicated ObjectTypes";
|
||||||
|
|
||||||
|
string IValidator.Check(GameObject gameObject)
|
||||||
|
{
|
||||||
|
var duplicates = gameObject.GetComponents<BaseObject>().Select(c => c.GetType().Name).ToList();
|
||||||
|
if (duplicates.Count <= 1) return null;
|
||||||
|
return "Multiple <b>ObjectTypes</b> on single GameObject: " + duplicates.StringJoin(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9236817ce90b46978bc2ca4b8d042db1
|
||||||
|
timeCreated: 1781469084
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using RPGCore.Core;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
using RPGCoreCommon.Helpers;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
|
namespace RPGCore.Editor.CoreManager.Validators
|
||||||
|
{
|
||||||
|
internal class OrphanModuleValidator : IValidator
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<Type, List<Type>> ModulesMap =
|
||||||
|
TypeCache.GetTypesDerivedFrom<ObjectModule>()
|
||||||
|
.Where(t => !t.IsAbstract && !t.IsInterface)
|
||||||
|
.GroupBy(t => t.FindGenericDefinitionType(typeof(ObjectModule<>)).GetGenericArguments()[0])
|
||||||
|
.ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
|
string IValidator.title => "Removing orphaned modules";
|
||||||
|
|
||||||
|
private static List<ObjectModule> FindOrphanModules(GameObject gameObject)
|
||||||
|
{
|
||||||
|
var objectType = gameObject.GetComponent<BaseObject>()?.GetType();
|
||||||
|
|
||||||
|
var validModuleTypes = ModulesMap
|
||||||
|
.Where(pair => pair.Key.IsAssignableFrom(objectType))
|
||||||
|
.SelectMany(pair => pair.Value)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return gameObject
|
||||||
|
.GetComponents<ObjectModule>()
|
||||||
|
.Where(m => !validModuleTypes.Contains(m.GetType()))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
string IValidator.Check(GameObject gameObject)
|
||||||
|
{
|
||||||
|
var orphanModules = FindOrphanModules(gameObject);
|
||||||
|
if (orphanModules.Count < 1) return null;
|
||||||
|
|
||||||
|
return "Found invalid modules: " + orphanModules.Select(m => m.GetType().Name).StringJoin(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IValidator.Fix(GameObject gameObject)
|
||||||
|
{
|
||||||
|
var orphanModules = FindOrphanModules(gameObject);
|
||||||
|
if (orphanModules.Count < 1) return;
|
||||||
|
|
||||||
|
orphanModules.ForEach(Object.DestroyImmediate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7e12170f343d4538ad98f50ec31325c1
|
||||||
|
timeCreated: 1781464441
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using RPGCore.Core.Objects;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace RPGCore.Core
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This interface allow any <see cref="BaseObject"/> to call <see cref="OnEnter"/> and <see cref="OnExit"/>.<br/>
|
|
||||||
/// Setting <see cref="Collider"/>'s <see cref="Collider.isTrigger"/> to true is required!<br/>
|
|
||||||
/// </summary>
|
|
||||||
public interface ITrigger
|
|
||||||
{
|
|
||||||
public void OnEnter(BaseObject obj);
|
|
||||||
public void OnExit(BaseObject obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace RPGCore.Core
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class ObjectModuleAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public string description;
|
||||||
|
public bool required;
|
||||||
|
|
||||||
|
public ObjectModuleAttribute(string name, string description, bool required = false)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.required = required;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7732c0ab6a6148ddb8c17a80facf5204
|
||||||
|
timeCreated: 1780777138
|
||||||
@@ -13,13 +13,11 @@ namespace RPGCore.Core.Objects
|
|||||||
[DisallowMultipleComponent]
|
[DisallowMultipleComponent]
|
||||||
[RequireComponent(typeof(Rigidbody))]
|
[RequireComponent(typeof(Rigidbody))]
|
||||||
[RequireComponent(typeof(EventModule))]
|
[RequireComponent(typeof(EventModule))]
|
||||||
[RequireComponent(typeof(ActionModule))]
|
|
||||||
[RequireComponent(typeof(DataModule))]
|
[RequireComponent(typeof(DataModule))]
|
||||||
public abstract class BaseObject : MonoBehaviour
|
public abstract class BaseObject : MonoBehaviour
|
||||||
{
|
{
|
||||||
[field: SerializeField, ReadOnly] public new Rigidbody rigidbody { get; private set; }
|
[field: SerializeField, ReadOnly] public new Rigidbody rigidbody { get; private set; }
|
||||||
[field: SerializeField, ReadOnly] public EventModule events { get; private set; }
|
[field: SerializeField, ReadOnly] public EventModule events { get; private set; }
|
||||||
[field: SerializeField, ReadOnly] public ActionModule actions { get; private set; }
|
|
||||||
[field: SerializeField, ReadOnly] public DataModule data { get; private set; }
|
[field: SerializeField, ReadOnly] public DataModule data { get; private set; }
|
||||||
|
|
||||||
[DynamicValueProvider]
|
[DynamicValueProvider]
|
||||||
@@ -34,7 +32,6 @@ namespace RPGCore.Core.Objects
|
|||||||
{
|
{
|
||||||
rigidbody = GetComponent<Rigidbody>();
|
rigidbody = GetComponent<Rigidbody>();
|
||||||
events = GetComponent<EventModule>();
|
events = GetComponent<EventModule>();
|
||||||
actions = GetComponent<ActionModule>();
|
|
||||||
data = GetComponent<DataModule>();
|
data = GetComponent<DataModule>();
|
||||||
GetComponents<ObjectModule>().ForEach(module => module.parent = this);
|
GetComponents<ObjectModule>().ForEach(module => module.parent = this);
|
||||||
}
|
}
|
||||||
@@ -42,25 +39,31 @@ namespace RPGCore.Core.Objects
|
|||||||
/// <summary>Removes this object from game.</summary>
|
/// <summary>Removes this object from game.</summary>
|
||||||
public void Remove()
|
public void Remove()
|
||||||
{
|
{
|
||||||
|
events.Invoke(new TriggerClearEvent { obj = this });
|
||||||
events.Invoke(new RemoveEvent{ obj = this });
|
events.Invoke(new RemoveEvent{ obj = this });
|
||||||
Destroy(gameObject);
|
Destroy(gameObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>It'll execute <see cref="ITrigger"/>.<see cref="ITrigger.OnEnter"/> when this object enter its collider.</summary>
|
public void OnDisable()
|
||||||
|
{
|
||||||
|
events.Invoke(new TriggerClearEvent { obj = this });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>It'll execute <see cref="Trigger"/>.<see cref="Trigger.OnEnter"/> when this object enter its collider.</summary>
|
||||||
private void OnTriggerEnter(Collider other)
|
private void OnTriggerEnter(Collider other)
|
||||||
{
|
{
|
||||||
other.GetComponentsInParent<ITrigger>().ForEach(trigger => {
|
other.GetComponentsInParent<Trigger>().ForEach(trigger => {
|
||||||
trigger.OnEnter(this);
|
trigger.OnEnter(this);
|
||||||
events.Invoke(new TriggerEnterEvent { target = this, trigger = trigger });
|
events.Invoke(new TriggerEnterEvent { obj = this, trigger = trigger });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>It'll execute <see cref="ITrigger"/>.<see cref="ITrigger.OnExit"/> when this object exit its collider.</summary>
|
/// <summary>It'll execute <see cref="Trigger"/>.<see cref="Trigger.OnExit"/> when this object exit its collider.</summary>
|
||||||
private void OnTriggerExit(Collider other)
|
private void OnTriggerExit(Collider other)
|
||||||
{
|
{
|
||||||
other.GetComponentsInParent<ITrigger>().ForEach(trigger => {
|
other.GetComponentsInParent<Trigger>().ForEach(trigger => {
|
||||||
trigger.OnExit(this);
|
trigger.OnExit(this);
|
||||||
events.Invoke(new TriggerExitEvent { target = this, trigger = trigger });
|
events.Invoke(new TriggerExitEvent { obj = this, trigger = trigger });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using RPGCore.ObjectModules.ActionObjectModule;
|
||||||
using RPGCoreCommon.DynamicValues;
|
using RPGCoreCommon.DynamicValues;
|
||||||
using RPGCoreCommon.Helpers.PropertyAttributeDrawers;
|
using RPGCoreCommon.Helpers.PropertyAttributeDrawers;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -6,16 +7,19 @@ using UnityEngine;
|
|||||||
namespace RPGCore.Core.Objects
|
namespace RPGCore.Core.Objects
|
||||||
{
|
{
|
||||||
[RequireComponent(typeof(CapsuleCollider))]
|
[RequireComponent(typeof(CapsuleCollider))]
|
||||||
|
[RequireComponent(typeof(ActionModule))]
|
||||||
public class UnitObject : BaseObject
|
public class UnitObject : BaseObject
|
||||||
{
|
{
|
||||||
[DynamicValueProvider]
|
[DynamicValueProvider]
|
||||||
private ObjectModule<UnitObject> UnitModuleProvider(Type moduleType) => GetComponent(moduleType) as ObjectModule<UnitObject>;
|
private ObjectModule<UnitObject> UnitModuleProvider(Type moduleType) => GetComponent(moduleType) as ObjectModule<UnitObject>;
|
||||||
|
|
||||||
[field: SerializeField, ReadOnly] public CapsuleCollider unitCollider { get; private set; }
|
[field: SerializeField, ReadOnly] public CapsuleCollider unitCollider { get; private set; }
|
||||||
|
[field: SerializeField, ReadOnly] public ActionModule actions { get; private set; }
|
||||||
|
|
||||||
protected new void OnValidate()
|
protected new void OnValidate()
|
||||||
{
|
{
|
||||||
base.OnValidate();
|
base.OnValidate();
|
||||||
|
actions = GetComponent<ActionModule>();
|
||||||
unitCollider = GetComponent<CapsuleCollider>();
|
unitCollider = GetComponent<CapsuleCollider>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
using RPGCore.ObjectModules.EventObjectModule.Events;
|
||||||
|
using RPGCoreCommon.Settings;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace RPGCore.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This MonoBehaviour allow any <see cref="BaseObject"/> to call <see cref="OnEnter"/> and <see cref="OnExit"/>.<br/>
|
||||||
|
/// Setting <see cref="Collider"/>'s <see cref="Collider.isTrigger"/> to true is required!<br/>
|
||||||
|
/// </summary>
|
||||||
|
public class Trigger : MonoBehaviour
|
||||||
|
{
|
||||||
|
private event Action<BaseObject> OnEnterEvent;
|
||||||
|
private event Action<BaseObject> OnExitEvent;
|
||||||
|
|
||||||
|
private readonly Dictionary<BaseObject, int> _collisionCounter = new();
|
||||||
|
|
||||||
|
public static Trigger AddToGameObject(GameObject go, Action<BaseObject> onEnter, Action<BaseObject> onExit)
|
||||||
|
{
|
||||||
|
go.layer = SettingsManager.Get<CoreSettings>().triggerLayer;
|
||||||
|
|
||||||
|
var interactTrigger = go.AddComponent<Trigger>();
|
||||||
|
interactTrigger.OnEnterEvent += onEnter;
|
||||||
|
interactTrigger.OnExitEvent += onExit;
|
||||||
|
|
||||||
|
return interactTrigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnEnter(BaseObject obj)
|
||||||
|
{
|
||||||
|
var alreadyTouching = _collisionCounter.ContainsKey(obj);
|
||||||
|
if (!alreadyTouching) _collisionCounter.Add(obj, 0);
|
||||||
|
_collisionCounter[obj]++;
|
||||||
|
|
||||||
|
if (!alreadyTouching)
|
||||||
|
{
|
||||||
|
obj.events.Register<TriggerClearEvent>(OnClear);
|
||||||
|
OnEnterEvent?.Invoke(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OnExit(BaseObject obj)
|
||||||
|
{
|
||||||
|
if (!_collisionCounter.ContainsKey(obj))
|
||||||
|
{
|
||||||
|
Debug.LogError("Object tried to leave trigger, but never entered it!", obj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_collisionCounter[obj]--;
|
||||||
|
if (_collisionCounter[obj] == 0) Clear(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnClear(TriggerClearEvent ev)
|
||||||
|
{
|
||||||
|
Clear(ev.obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Clear(BaseObject obj)
|
||||||
|
{
|
||||||
|
obj.events.Unregister<TriggerClearEvent>(OnClear);
|
||||||
|
_collisionCounter.Remove(obj);
|
||||||
|
OnExitEvent?.Invoke(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,13 +11,19 @@ using UnityEngine;
|
|||||||
namespace RPGCore.ObjectModules.ActionObjectModule
|
namespace RPGCore.ObjectModules.ActionObjectModule
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Core] Actions",
|
||||||
|
description: "[Built-in module] Module that can be attached to <b>UnitObject</b>. " +
|
||||||
|
"Can execute any implementations of <b>BaseAction</b> with queue and/or instant execution.",
|
||||||
|
required: true
|
||||||
|
)]
|
||||||
public class ActionModule : ObjectModule<UnitObject>
|
public class ActionModule : ObjectModule<UnitObject>
|
||||||
{
|
{
|
||||||
private List<BaseActionParallel> _actionParallels = new();
|
private List<BaseAction> _actionParallels = new();
|
||||||
private readonly List<BaseAction> _actionQueue = new();
|
private readonly List<BaseAction> _actionQueue = new();
|
||||||
private BaseAction _actionCurrent;
|
private BaseAction _actionCurrent;
|
||||||
|
|
||||||
public List<BaseActionParallel> actionParallels => _actionParallels.ToList();
|
public List<BaseAction> actionParallels => _actionParallels.ToList();
|
||||||
public List<BaseAction> actionQueue => _actionQueue.ToList();
|
public List<BaseAction> actionQueue => _actionQueue.ToList();
|
||||||
public BaseAction actionCurrent => _actionCurrent;
|
public BaseAction actionCurrent => _actionCurrent;
|
||||||
|
|
||||||
@@ -30,7 +36,7 @@ namespace RPGCore.ObjectModules.ActionObjectModule
|
|||||||
/// 1. Checks if the action can be executed outside the queue.<br/>
|
/// 1. Checks if the action can be executed outside the queue.<br/>
|
||||||
/// 2. If allowed, executes the action and handles potential errors.
|
/// 2. If allowed, executes the action and handles potential errors.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Execute(BaseActionParallel action)
|
public void Execute(BaseAction action)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace RPGCore.ObjectModules.ActionObjectModule
|
|
||||||
{
|
|
||||||
public abstract class BaseActionParallel : BaseAction
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e46b8a02e3894ecb87b4455602287715
|
|
||||||
timeCreated: 1762624491
|
|
||||||
@@ -8,7 +8,7 @@ namespace RPGCore.ObjectModules.EventObjectModule.Data
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class BaseObjectData : BaseData<BaseObject>
|
public class BaseObjectData : BaseData<BaseObject>
|
||||||
{
|
{
|
||||||
[Header("Uniqueness")]
|
[field: Header("Uniqueness")]
|
||||||
[field: SerializeField, ReadOnly] public string guid { get; private set; } = Guid.NewGuid().ToString();
|
[field: SerializeField, ReadOnly] public string guid { get; private set; } = Guid.NewGuid().ToString();
|
||||||
|
|
||||||
[Header("Display")]
|
[Header("Display")]
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ using UnityEngine;
|
|||||||
namespace RPGCore.ObjectModules.EventObjectModule
|
namespace RPGCore.ObjectModules.EventObjectModule
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
[RequireComponent(typeof(BaseObject))]
|
[ObjectModule(
|
||||||
|
name: "[Core] Data",
|
||||||
|
description: "[Built-in module] Manages all implementations of <b>BaseData</b>. " +
|
||||||
|
"Automatically adds matching data to attached implementation of <b>BaseObject</b>.",
|
||||||
|
required: true
|
||||||
|
)]
|
||||||
public class DataModule : ObjectModule<BaseObject>
|
public class DataModule : ObjectModule<BaseObject>
|
||||||
{
|
{
|
||||||
// SERIALIZED
|
// SERIALIZED
|
||||||
@@ -48,6 +53,9 @@ namespace RPGCore.ObjectModules.EventObjectModule
|
|||||||
|
|
||||||
public T Get<T>() where T : BaseData
|
public T Get<T>() where T : BaseData
|
||||||
{
|
{
|
||||||
|
if (!_dataDict.ContainsKey(typeof(T)))
|
||||||
|
_dataDict.Add(typeof(T), Activator.CreateInstance(typeof(T)) as T);
|
||||||
|
|
||||||
return (T)_dataDict[typeof(T)];
|
return (T)_dataDict[typeof(T)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,28 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using RPGCore.Core;
|
using RPGCore.Core;
|
||||||
using RPGCore.Core.Objects;
|
using RPGCore.Core.Objects;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace RPGCore.ObjectModules.EventObjectModule
|
namespace RPGCore.ObjectModules.EventObjectModule
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
[ObjectModule(
|
||||||
|
name: "[Core] Data",
|
||||||
|
description: "[Built-in module] Manages all implementations of <b>BaseEvent</b> and <b>BasePreventableEvent</b>. " +
|
||||||
|
"Allows for registering and invoking events by its type.",
|
||||||
|
required: true
|
||||||
|
)]
|
||||||
public class EventModule : ObjectModule<BaseObject>
|
public class EventModule : ObjectModule<BaseObject>
|
||||||
{
|
{
|
||||||
// TODO: tutaj dodać serializowane eventy w postaci SerializableDictionary<SerializableType, UnityAction>
|
// TODO: 1. tutaj dodać serializowane eventy w postaci SerializableDictionary<SerializableType, UnityAction>
|
||||||
// TODO: dodatkowo mozna zmienić preventableEvents na dwa osobne słowniki before i after
|
// TODO: w Awake() zrobić bridge to uruchamiania serializowanych eventów jak uruchamia się ten runtimeowy
|
||||||
|
// TODO: 2. dodatkowo mozna zmienić preventableEvents na dwa osobne słowniki before i after
|
||||||
|
|
||||||
internal readonly Dictionary<Type, Delegate> events = new();
|
internal readonly Dictionary<Type, Delegate> events = new();
|
||||||
internal readonly Dictionary<Type, Delegate[]> preventableEvents = new();
|
internal readonly Dictionary<Type, Delegate[]> preventableEvents = new();
|
||||||
|
|
||||||
|
/***** INVOKE *****/
|
||||||
|
|
||||||
public void Invoke<T>(T baseEvent) where T : BaseEvent
|
public void Invoke<T>(T baseEvent) where T : BaseEvent
|
||||||
{
|
{
|
||||||
events.TryAdd(typeof(T), null);
|
events.TryAdd(typeof(T), null);
|
||||||
@@ -23,19 +33,17 @@ namespace RPGCore.ObjectModules.EventObjectModule
|
|||||||
public void Register<T>(Action<T> action) where T : BaseEvent
|
public void Register<T>(Action<T> action) where T : BaseEvent
|
||||||
{
|
{
|
||||||
events.TryAdd(typeof(T), null);
|
events.TryAdd(typeof(T), null);
|
||||||
var temp = (Action<T>)events[typeof(T)];
|
events[typeof(T)] = (Action<T>)events[typeof(T)] + action;
|
||||||
temp += action;
|
|
||||||
events[typeof(T)] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Unregister<T>(Action<T> action) where T : BaseEvent
|
public void Unregister<T>(Action<T> action) where T : BaseEvent
|
||||||
{
|
{
|
||||||
events.TryAdd(typeof(T), null);
|
events.TryAdd(typeof(T), null);
|
||||||
var temp = (Action<T>)events[typeof(T)];
|
events[typeof(T)] = (Action<T>)events[typeof(T)] - action;
|
||||||
temp -= action;
|
|
||||||
events[typeof(T)] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***** INVOKE BEFORE *****/
|
||||||
|
|
||||||
public void InvokeBefore<T>(T basePreventableEvent) where T : BasePreventableEvent
|
public void InvokeBefore<T>(T basePreventableEvent) where T : BasePreventableEvent
|
||||||
{
|
{
|
||||||
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
||||||
@@ -45,22 +53,25 @@ namespace RPGCore.ObjectModules.EventObjectModule
|
|||||||
public void RegisterBefore<T>(Action<T> action) where T : BasePreventableEvent
|
public void RegisterBefore<T>(Action<T> action) where T : BasePreventableEvent
|
||||||
{
|
{
|
||||||
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
||||||
var temp = (Action<T>)preventableEvents[typeof(T)][0];
|
preventableEvents[typeof(T)][0] = (Action<T>)preventableEvents[typeof(T)][0] + action;
|
||||||
temp += action;
|
|
||||||
preventableEvents[typeof(T)][0] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnregisterBefore<T>(Action<T> action) where T : BasePreventableEvent
|
public void UnregisterBefore<T>(Action<T> action) where T : BasePreventableEvent
|
||||||
{
|
{
|
||||||
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
||||||
var temp = (Action<T>)preventableEvents[typeof(T)][0];
|
preventableEvents[typeof(T)][0] = (Action<T>)preventableEvents[typeof(T)][0] - action;
|
||||||
temp -= action;
|
|
||||||
preventableEvents[typeof(T)][0] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***** INVOKE AFTER *****/
|
||||||
|
|
||||||
public void InvokeAfter<T>(T basePreventableEvent) where T : BasePreventableEvent
|
public void InvokeAfter<T>(T basePreventableEvent) where T : BasePreventableEvent
|
||||||
{
|
{
|
||||||
if (basePreventableEvent.isPrevented) throw new EventPreventedException("Event is prevented and can't be invoked!");
|
if (basePreventableEvent.isPrevented)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Event is prevented and can't be invoked!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
||||||
(preventableEvents[typeof(T)][1] as Action<T>)?.Invoke(basePreventableEvent);
|
(preventableEvents[typeof(T)][1] as Action<T>)?.Invoke(basePreventableEvent);
|
||||||
}
|
}
|
||||||
@@ -68,17 +79,13 @@ namespace RPGCore.ObjectModules.EventObjectModule
|
|||||||
public void RegisterAfter<T>(Action<T> action) where T : BasePreventableEvent
|
public void RegisterAfter<T>(Action<T> action) where T : BasePreventableEvent
|
||||||
{
|
{
|
||||||
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
||||||
var temp = (Action<T>)preventableEvents[typeof(T)][1];
|
preventableEvents[typeof(T)][1] = (Action<T>)preventableEvents[typeof(T)][1] + action;
|
||||||
temp += action;
|
|
||||||
preventableEvents[typeof(T)][1] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UnregisterAfter<T>(Action<T> action) where T : BasePreventableEvent
|
public void UnregisterAfter<T>(Action<T> action) where T : BasePreventableEvent
|
||||||
{
|
{
|
||||||
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
preventableEvents.TryAdd(typeof(T), new Delegate[2]);
|
||||||
var temp = (Action<T>)preventableEvents[typeof(T)][1];
|
preventableEvents[typeof(T)][1] = (Action<T>)preventableEvents[typeof(T)][1] - action;
|
||||||
temp -= action;
|
|
||||||
preventableEvents[typeof(T)][1] = temp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace RPGCore.ObjectModules.EventObjectModule
|
|
||||||
{
|
|
||||||
public class EventPreventedException : Exception
|
|
||||||
{
|
|
||||||
public EventPreventedException(string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a647e5d4d4ed44c28fd6961d60943fe4
|
|
||||||
timeCreated: 1761917482
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using RPGCore.Core;
|
||||||
|
using RPGCore.Core.Objects;
|
||||||
|
|
||||||
|
namespace RPGCore.ObjectModules.EventObjectModule.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Executed when <see cref="BaseObject"/> forcefully exits <see cref="Trigger"/> by non-physics means, by default
|
||||||
|
/// it is when object is <b>Disabled</b> or <b>Removed</b>.<br/><br/>
|
||||||
|
/// Execute this if you want to object exit its trigger.
|
||||||
|
/// </summary>
|
||||||
|
public class TriggerClearEvent : BaseEvent<BaseObject>
|
||||||
|
{
|
||||||
|
public BaseObject obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4b02fda53526495c88e8c59795782dec
|
||||||
|
timeCreated: 1779650139
|
||||||
@@ -3,9 +3,12 @@ using RPGCore.Core.Objects;
|
|||||||
|
|
||||||
namespace RPGCore.ObjectModules.EventObjectModule.Events
|
namespace RPGCore.ObjectModules.EventObjectModule.Events
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Executed when <see cref="BaseObject"/> enters <see cref="Trigger"/>'s colliders.
|
||||||
|
/// </summary>
|
||||||
public class TriggerEnterEvent : BaseEvent<BaseObject>
|
public class TriggerEnterEvent : BaseEvent<BaseObject>
|
||||||
{
|
{
|
||||||
public BaseObject target;
|
public BaseObject obj;
|
||||||
public ITrigger trigger;
|
public Trigger trigger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,12 @@ using RPGCore.Core.Objects;
|
|||||||
|
|
||||||
namespace RPGCore.ObjectModules.EventObjectModule.Events
|
namespace RPGCore.ObjectModules.EventObjectModule.Events
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Executed when <see cref="BaseObject"/> exits <see cref="Trigger"/>'s colliders.
|
||||||
|
/// </summary>
|
||||||
public class TriggerExitEvent : BaseEvent<BaseObject>
|
public class TriggerExitEvent : BaseEvent<BaseObject>
|
||||||
{
|
{
|
||||||
public BaseObject target;
|
public BaseObject obj;
|
||||||
public ITrigger trigger;
|
public Trigger trigger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,8 +17,7 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
|
|
||||||
private SerializedProperty _property;
|
private SerializedProperty _property;
|
||||||
private SerializedProperty _tempKeyProperty;
|
private SerializedProperty _tempKeyProperty;
|
||||||
private SerializedProperty _keysProperty;
|
private SerializedProperty _pairsProperty;
|
||||||
private SerializedProperty _valuesProperty;
|
|
||||||
|
|
||||||
private SerializableDictionaryAttribute _sdAttribute;
|
private SerializableDictionaryAttribute _sdAttribute;
|
||||||
private Type _keyType;
|
private Type _keyType;
|
||||||
@@ -29,11 +28,7 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
_property = property;
|
_property = property;
|
||||||
_sdAttribute = fieldInfo.GetCustomAttribute<SerializableDictionaryAttribute>() ?? new SerializableDictionaryAttribute();
|
_sdAttribute = fieldInfo.GetCustomAttribute<SerializableDictionaryAttribute>() ?? new SerializableDictionaryAttribute();
|
||||||
_tempKeyProperty = property.FindPropertyRelative("_tempKey");
|
_tempKeyProperty = property.FindPropertyRelative("_tempKey");
|
||||||
_keysProperty = property.FindPropertyRelative("_keys");
|
_pairsProperty = property.FindPropertyRelative("_pairs");
|
||||||
_valuesProperty = property.FindPropertyRelative("_values");
|
|
||||||
|
|
||||||
if (_keysProperty == null || _valuesProperty == null)
|
|
||||||
return new HelpBox("Keys and Values in SerializableDictionary must be serializable!", HelpBoxMessageType.Error);
|
|
||||||
|
|
||||||
var genericTypes = property.boxedValue.GetType().FindGenericDefinitionType(typeof(SerializableDictionary<,>)).GetGenericArguments();
|
var genericTypes = property.boxedValue.GetType().FindGenericDefinitionType(typeof(SerializableDictionary<,>)).GetGenericArguments();
|
||||||
_keyType = genericTypes[0];
|
_keyType = genericTypes[0];
|
||||||
@@ -52,12 +47,11 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
}
|
}
|
||||||
|
|
||||||
var list = root.Q<ListView>("sd-list");
|
var list = root.Q<ListView>("sd-list");
|
||||||
list.BindProperty(_valuesProperty);
|
list.BindProperty(_pairsProperty);
|
||||||
list.makeItem = CreateRow;
|
list.makeItem = CreateRow;
|
||||||
list.bindItem = BindRow;
|
list.bindItem = BindRow;
|
||||||
list.onAdd = OnAdd;
|
list.onAdd = OnAdd;
|
||||||
list.onRemove = OnRemove;
|
list.onRemove = OnRemove;
|
||||||
list.itemIndexChanged += OnSwap;
|
|
||||||
|
|
||||||
if (_sdAttribute is not null)
|
if (_sdAttribute is not null)
|
||||||
{
|
{
|
||||||
@@ -90,12 +84,6 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSwap(int index1, int index2)
|
|
||||||
{
|
|
||||||
_keysProperty.MoveArrayElement(index1, index2);
|
|
||||||
_property.serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAdd(BaseListView list)
|
private void OnAdd(BaseListView list)
|
||||||
{
|
{
|
||||||
var tempKey = _tempKeyProperty.boxedValue;
|
var tempKey = _tempKeyProperty.boxedValue;
|
||||||
@@ -108,9 +96,10 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyExists = Enumerable.Range(0, _keysProperty.arraySize)
|
var keyExists = Enumerable.Range(0, _pairsProperty.arraySize)
|
||||||
.Select(i => _keysProperty.GetArrayElementAtIndex(i))
|
.Select(i => _pairsProperty.GetArrayElementAtIndex(i))
|
||||||
.Any(prop => prop.boxedValue.Equals(tempKey));
|
.Select(prop => prop.FindPropertyRelative("_key"))
|
||||||
|
.Any(keyProp => keyProp.boxedValue.Equals(tempKey));
|
||||||
|
|
||||||
if (keyExists)
|
if (keyExists)
|
||||||
{
|
{
|
||||||
@@ -124,13 +113,8 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
_tempKeyProperty.boxedValue = _keyType.IsValueType ? Activator.CreateInstance(_keyType) : null;
|
_tempKeyProperty.boxedValue = _keyType.IsValueType ? Activator.CreateInstance(_keyType) : null;
|
||||||
|
|
||||||
// New Key
|
// New Key
|
||||||
_keysProperty.arraySize++;
|
_pairsProperty.arraySize++;
|
||||||
_keysProperty.GetArrayElementAtIndex(_keysProperty.arraySize - 1).boxedValue = tempKey;
|
_pairsProperty.GetArrayElementAtIndex(_pairsProperty.arraySize - 1).FindPropertyRelative("_key").boxedValue = tempKey;
|
||||||
|
|
||||||
// New Value
|
|
||||||
_valuesProperty.arraySize++;
|
|
||||||
_valuesProperty.GetArrayElementAtIndex(_valuesProperty.arraySize - 1).boxedValue =
|
|
||||||
_valueType.IsValueType ? Activator.CreateInstance(_valueType) : null;
|
|
||||||
|
|
||||||
// Update list and property
|
// Update list and property
|
||||||
_property.serializedObject.ApplyModifiedProperties();
|
_property.serializedObject.ApplyModifiedProperties();
|
||||||
@@ -143,11 +127,7 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
var ids = list.selectedIds.SortDescending().ToList();
|
var ids = list.selectedIds.SortDescending().ToList();
|
||||||
if (ids.Count < 0) return;
|
if (ids.Count < 0) return;
|
||||||
|
|
||||||
ids.ForEach(i =>
|
ids.ForEach(i => _pairsProperty.DeleteArrayElementAtIndex(i));
|
||||||
{
|
|
||||||
_keysProperty.DeleteArrayElementAtIndex(i);
|
|
||||||
_valuesProperty.DeleteArrayElementAtIndex(i);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update list and property
|
// Update list and property
|
||||||
_property.serializedObject.ApplyModifiedProperties();
|
_property.serializedObject.ApplyModifiedProperties();
|
||||||
@@ -179,9 +159,9 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
|
|
||||||
private void BindRow(VisualElement row, int i)
|
private void BindRow(VisualElement row, int i)
|
||||||
{
|
{
|
||||||
if (i >= _keysProperty.arraySize) return;
|
if (i >= _pairsProperty.arraySize) return;
|
||||||
row.Q<PropertyField>(className: "row-left").BindProperty(_keysProperty.GetArrayElementAtIndex(i));
|
row.Q<PropertyField>(className: "row-left").BindProperty(_pairsProperty.GetArrayElementAtIndex(i).FindPropertyRelative("_key"));
|
||||||
row.Q<PropertyField>(className: "row-right").BindProperty(_valuesProperty.GetArrayElementAtIndex(i));
|
row.Q<PropertyField>(className: "row-right").BindProperty(_pairsProperty.GetArrayElementAtIndex(i).FindPropertyRelative("_value"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ namespace RPGCoreCommon.Helpers.Editor.Drawers
|
|||||||
|
|
||||||
private void UpdateTypeField(SerializedProperty property, FakeObjectField field)
|
private void UpdateTypeField(SerializedProperty property, FakeObjectField field)
|
||||||
{
|
{
|
||||||
var typeName = ((SerializableType)property.boxedValue).type?.Name ?? NoTypeSelected;
|
var typeName = ((SerializableType)property.boxedValue)?.type?.Name ?? NoTypeSelected;
|
||||||
field.Set(typeName, EditorGUIUtility.FindTexture("cs Script Icon"));
|
field.Set(typeName, EditorGUIUtility.FindTexture("cs Script Icon"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using RPGCoreCommon.Helpers.PropertyAttributeDrawers;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.UIElements;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace RPGCoreCommon.Helpers.Editor.PropertyAttributeDrawers
|
||||||
|
{
|
||||||
|
[CustomPropertyDrawer(typeof(ObjectPickerAttribute))]
|
||||||
|
public class ObjectPickerDrawer : PropertyDrawer
|
||||||
|
{
|
||||||
|
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d82bc4b9420a4ea58ea10c04b9c2307b
|
||||||
|
timeCreated: 1781877687
|
||||||
@@ -53,8 +53,18 @@ namespace RPGCoreCommon.Helpers.Editor.UIElements
|
|||||||
// ENTER - select first visible
|
// ENTER - select first visible
|
||||||
_root.RegisterCallback<KeyDownEvent>(ev =>
|
_root.RegisterCallback<KeyDownEvent>(ev =>
|
||||||
{
|
{
|
||||||
if (ev.keyCode == KeyCode.Escape) Close();
|
switch (ev.keyCode)
|
||||||
if (ev.keyCode == KeyCode.Return) _scrollView.Query<Button>().Visible().First().Click();
|
{
|
||||||
|
case KeyCode.Escape:
|
||||||
|
Close();
|
||||||
|
break;
|
||||||
|
case KeyCode.Return:
|
||||||
|
SelectFirst();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ApplyFilter();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}, TrickleDown.TrickleDown);
|
}, TrickleDown.TrickleDown);
|
||||||
|
|
||||||
return _root;
|
return _root;
|
||||||
@@ -69,5 +79,16 @@ namespace RPGCoreCommon.Helpers.Editor.UIElements
|
|||||||
{
|
{
|
||||||
editorWindow.Close();
|
editorWindow.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SelectFirst()
|
||||||
|
{
|
||||||
|
_scrollView.Query<Button>().Visible().First().Click();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyFilter()
|
||||||
|
{
|
||||||
|
_scrollView.Query<Button>()
|
||||||
|
.ForEach(b => b.style.display = b.text.Contains(_searchField.value) ? DisplayStyle.Flex : DisplayStyle.None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,26 +8,29 @@ namespace RPGCoreCommon.Helpers.CustomTypes
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
|
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
|
||||||
{
|
{
|
||||||
[SerializeField] internal TKey _tempKey;
|
[Serializable]
|
||||||
|
internal class Pair
|
||||||
|
{
|
||||||
|
[SerializeReference] internal TKey _key;
|
||||||
|
[SerializeReference] internal TValue _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeReference] internal TKey _tempKey;
|
||||||
|
[SerializeField] internal List<Pair> _pairs;
|
||||||
|
|
||||||
[SerializeField] internal List<TKey> _keys = new();
|
[SerializeField] internal List<TKey> _keys = new();
|
||||||
[SerializeReference] internal List<TValue> _values = new();
|
[SerializeReference] internal List<TValue> _values = new();
|
||||||
|
|
||||||
public void OnBeforeSerialize()
|
public void OnBeforeSerialize()
|
||||||
{
|
{
|
||||||
_keys = Keys.ToList();
|
_pairs = this.Select(p => new Pair { _key = p.Key, _value = p.Value }).ToList();
|
||||||
_values = Values.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnAfterDeserialize()
|
public void OnAfterDeserialize()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
for (var i = 0; i < _keys.Count; i++)
|
_pairs.ForEach(p => TryAdd(p._key, p._value));
|
||||||
{
|
_pairs.Clear();
|
||||||
if (_keys[i] != null) Add(_keys[i], _values[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_keys.Clear();
|
|
||||||
_values.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,10 @@ using UnityEngine;
|
|||||||
namespace RPGCoreCommon.Helpers.CustomTypes
|
namespace RPGCoreCommon.Helpers.CustomTypes
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class SerializableType : ISerializationCallbackReceiver, ICloneable
|
public class SerializableType : ISerializationCallbackReceiver, ICloneable, IEquatable<SerializableType>
|
||||||
{
|
{
|
||||||
public Type type { get; internal set; }
|
public Type type { get; private set; }
|
||||||
[SerializeField] internal string assemblyQualifiedName;
|
[SerializeField] private string assemblyQualifiedName;
|
||||||
|
|
||||||
public SerializableType(Type type)
|
public SerializableType(Type type)
|
||||||
{
|
{
|
||||||
@@ -32,5 +32,9 @@ namespace RPGCoreCommon.Helpers.CustomTypes
|
|||||||
public static implicit operator Type(SerializableType serializableType) => serializableType.type;
|
public static implicit operator Type(SerializableType serializableType) => serializableType.type;
|
||||||
|
|
||||||
public static implicit operator SerializableType(Type type) => new(type);
|
public static implicit operator SerializableType(Type type) => new(type);
|
||||||
|
|
||||||
|
public override int GetHashCode() => type?.GetHashCode() ?? 0;
|
||||||
|
|
||||||
|
public bool Equals(SerializableType other) => type == other?.type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace RPGCoreCommon.Helpers.PropertyAttributeDrawers
|
||||||
|
{
|
||||||
|
public class ObjectPickerAttribute : PropertyAttribute
|
||||||
|
{
|
||||||
|
// TODO: zrobić to + drawer ObjectPickerDrawer
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 37be47854eb74f7a8558e9ef3de059b3
|
||||||
|
timeCreated: 1781877714
|
||||||
+1
-1
@@ -4,6 +4,6 @@ namespace RPGCoreCommon.Helpers.PropertyAttributeDrawers
|
|||||||
{
|
{
|
||||||
public class SerializeReferenceHelperAttribute : PropertyAttribute
|
public class SerializeReferenceHelperAttribute : PropertyAttribute
|
||||||
{
|
{
|
||||||
|
// TODO: zrobić to + drawer SerializeReferenceHelperDrawer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user