diff --git a/Examples/Assets/InfinityWaves/Enemy/EnemyStateMachine.asset b/Examples/Assets/InfinityWaves/Enemy/EnemyStateMachine.asset
index 43e9b11b..a8406ece 100644
--- a/Examples/Assets/InfinityWaves/Enemy/EnemyStateMachine.asset
+++ b/Examples/Assets/InfinityWaves/Enemy/EnemyStateMachine.asset
@@ -22,70 +22,72 @@ MonoBehaviour:
_transitionStarted: {fileID: 0}
_completeCurrentTransition: {fileID: 0}
_states:
- - _id:
- _usage: 0
- _value: CHASING
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _cooldown:
- _usage: 0
- _value: 0
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _subMachine: {fileID: 0}
- - _id:
- _usage: 0
- _value: ATTACKING
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _cooldown:
- _usage: 0
- _value: 2
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _subMachine: {fileID: 0}
+ _list:
+ - _id:
+ _usage: 0
+ _value: CHASING
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _cooldown:
+ _usage: 0
+ _value: 0
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _subMachine: {fileID: 0}
+ - _id:
+ _usage: 0
+ _value: ATTACKING
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _cooldown:
+ _usage: 0
+ _value: 2
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _subMachine: {fileID: 0}
_transitions:
- - _fromState:
- _usage: 0
- _value: ATTACKING
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _toState:
- _usage: 0
- _value: CHASING
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _command:
- _usage: 0
- _value: CHASE
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _testCondition: {fileID: 0}
- _raiseEventToCompleteTransition: 0
- - _fromState:
- _usage: 0
- _value: CHASING
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _toState:
- _usage: 0
- _value: ATTACKING
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _command:
- _usage: 0
- _value: ATTACK
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _testCondition: {fileID: 0}
- _raiseEventToCompleteTransition: 0
+ _list:
+ - _fromState:
+ _usage: 0
+ _value: CHASING
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _toState:
+ _usage: 0
+ _value: ATTACKING
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _command:
+ _usage: 0
+ _value: ATTACK
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _testCondition: {fileID: 0}
+ _raiseEventToCompleteTransition: 0
+ - _fromState:
+ _usage: 0
+ _value: ATTACKING
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _toState:
+ _usage: 0
+ _value: CHASING
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _command:
+ _usage: 0
+ _value: CHASE
+ _constant: {fileID: 0}
+ _variable: {fileID: 0}
+ _variableInstancer: {fileID: 0}
+ _testCondition: {fileID: 0}
+ _raiseEventToCompleteTransition: 0
diff --git a/Examples/Assets/InfinityWaves/GlobalState/GameStateMachine.asset b/Examples/Assets/InfinityWaves/GlobalState/GameStateMachine.asset
index d33133ad..de63646e 100644
--- a/Examples/Assets/InfinityWaves/GlobalState/GameStateMachine.asset
+++ b/Examples/Assets/InfinityWaves/GlobalState/GameStateMachine.asset
@@ -13,59 +13,15 @@ MonoBehaviour:
m_Name: GameStateMachine
m_EditorClassIdentifier:
_developerDescription:
- _value: InGame
- _initialValue: InGame
- _oldValue: InGame
+ _value:
+ _initialValue:
+ _oldValue:
Changed: {fileID: 11400000, guid: 3979f8535cda044809f98bde2acbadcd, type: 2}
ChangedWithHistory: {fileID: 0}
_preChangeTransformers: []
_transitionStarted: {fileID: 0}
_completeCurrentTransition: {fileID: 0}
_states:
- - _id:
- _usage: 0
- _value: InGame
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _cooldown:
- _usage: 0
- _value: 0
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _subMachine: {fileID: 0}
- - _id:
- _usage: 0
- _value: GameOver
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _cooldown:
- _usage: 0
- _value: 0
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _subMachine: {fileID: 0}
+ _list: []
_transitions:
- - _fromState:
- _usage: 0
- _value: InGame
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _toState:
- _usage: 0
- _value: GameOver
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _command:
- _usage: 0
- _value: SetGameOver
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
- _testCondition: {fileID: 0}
- _raiseEventToCompleteTransition: 0
+ _list: []
diff --git a/Examples/Assets/InfinityWaves/InfinityWaves.unity b/Examples/Assets/InfinityWaves/InfinityWaves.unity
index e25ca5fa..06f08fe1 100644
--- a/Examples/Assets/InfinityWaves/InfinityWaves.unity
+++ b/Examples/Assets/InfinityWaves/InfinityWaves.unity
@@ -1226,88 +1226,6 @@ MonoBehaviour:
_constant: {fileID: 0}
_variable: {fileID: 0}
_variableInstancer: {fileID: 0}
---- !u!1 &1740680898 stripped
-GameObject:
- m_CorrespondingSourceObject: {fileID: 2421445419809145576, guid: 1326bc3a5a491414d936c2cbaaf52c53,
- type: 3}
- m_PrefabInstance: {fileID: 2421445420392131626}
- m_PrefabAsset: {fileID: 0}
---- !u!114 &1740680904 stripped
-MonoBehaviour:
- m_CorrespondingSourceObject: {fileID: 2421445419809145570, guid: 1326bc3a5a491414d936c2cbaaf52c53,
- type: 3}
- m_PrefabInstance: {fileID: 2421445420392131626}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1740680898}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: f4c23750724dd48beb6147120ab31180, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!114 &1740680906 stripped
-MonoBehaviour:
- m_CorrespondingSourceObject: {fileID: -2978108162882953924, guid: 1326bc3a5a491414d936c2cbaaf52c53,
- type: 3}
- m_PrefabInstance: {fileID: 2421445420392131626}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1740680898}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: adacd19b642ba4bd9866612e37971b00, type: 3}
- m_Name:
- m_EditorClassIdentifier:
---- !u!114 &1740680909
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1740680898}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 6a57cc968d2764ec0bc2de2bd308d451, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- _delay:
- _usage: 0
- _value: -1
- _constant: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 0}
---- !u!114 &1740680910
-MonoBehaviour:
- m_ObjectHideFlags: 0
- m_CorrespondingSourceObject: {fileID: 0}
- m_PrefabInstance: {fileID: 0}
- m_PrefabAsset: {fileID: 0}
- m_GameObject: {fileID: 1740680898}
- m_Enabled: 1
- m_EditorHideFlags: 0
- m_Script: {fileID: 11500000, guid: 050ff37b5550f4b7e9bdf8b985aff484, type: 3}
- m_Name:
- m_EditorClassIdentifier:
- _developerDescription:
- _unityEventResponse:
- m_PersistentCalls:
- m_Calls:
- - m_Target: {fileID: 1740680909}
- m_MethodName: DestroyImmediate
- m_Mode: 1
- m_Arguments:
- m_ObjectArgument: {fileID: 0}
- m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
- m_IntArgument: 0
- m_FloatArgument: 0
- m_StringArgument:
- m_BoolArgument: 0
- m_CallState: 2
- _actionResponses: []
- _eventReference:
- _usage: 3
- _event: {fileID: 0}
- _eventInstancer: {fileID: 0}
- _variable: {fileID: 0}
- _variableInstancer: {fileID: 1740680906}
--- !u!1001 &2421445420392131626
PrefabInstance:
m_ObjectHideFlags: 0
@@ -1315,16 +1233,6 @@ PrefabInstance:
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
- - target: {fileID: 2421445419809145569, guid: 1326bc3a5a491414d936c2cbaaf52c53,
- type: 3}
- propertyPath: _enemyState._fsmInstancer
- value:
- objectReference: {fileID: 1740680904}
- - target: {fileID: 2421445419809145569, guid: 1326bc3a5a491414d936c2cbaaf52c53,
- type: 3}
- propertyPath: _enemyState._usage
- value: 1
- objectReference: {fileID: 0}
- target: {fileID: 2421445419809145576, guid: 1326bc3a5a491414d936c2cbaaf52c53,
type: 3}
propertyPath: m_Name
@@ -1385,11 +1293,6 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- - target: {fileID: 2421445419809145581, guid: 1326bc3a5a491414d936c2cbaaf52c53,
- type: 3}
- propertyPath: _enemyState._fsmInstancer
- value:
- objectReference: {fileID: 1740680904}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 1326bc3a5a491414d936c2cbaaf52c53, type: 3}
--- !u!1001 &7203441229205008813
diff --git a/Packages/BaseAtoms/Editor/Drawers/Collections/AtomBaseVariableListDrawer.cs b/Packages/BaseAtoms/Editor/Drawers/Collections/AtomListDrawer.cs
similarity index 83%
rename from Packages/BaseAtoms/Editor/Drawers/Collections/AtomBaseVariableListDrawer.cs
rename to Packages/BaseAtoms/Editor/Drawers/Collections/AtomListDrawer.cs
index 4235aae4..f4cb1ffe 100644
--- a/Packages/BaseAtoms/Editor/Drawers/Collections/AtomBaseVariableListDrawer.cs
+++ b/Packages/BaseAtoms/Editor/Drawers/Collections/AtomListDrawer.cs
@@ -1,5 +1,3 @@
-using System;
-using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityAtoms.Editor;
@@ -9,8 +7,9 @@ namespace UnityAtoms.BaseAtoms.Editor
///
/// A custom property drawer for AtomBaseVariableList.
///
+ [CustomPropertyDrawer(typeof(AtomListAttribute))]
[CustomPropertyDrawer(typeof(AtomBaseVariableList))]
- public class AtomBaseVariableListDrawer : PropertyDrawer
+ public class AtomListDrawer : PropertyDrawer
{
static int INDEX_LABEL_WIDTH = 16;
static int BUTTON_WIDTH = 24;
@@ -24,8 +23,10 @@ namespace UnityAtoms.BaseAtoms.Editor
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
+ AtomListAttribute atomListAttr = attribute as AtomListAttribute;
+
var propertyHeight = EditorGUIUtility.singleLineHeight + LINE_BOTTOM_MARGIN + DRAWER_MARGIN * 2f;
- var listProperty = property.FindPropertyRelative(SERIALIZED_LIST_PROPNAME);
+ var listProperty = property.FindPropertyRelative(atomListAttr != null && !string.IsNullOrWhiteSpace(atomListAttr.ChildPropName) ? atomListAttr.ChildPropName : SERIALIZED_LIST_PROPNAME);
var length = listProperty.arraySize;
for (var i = 0; i < length; ++i)
@@ -40,6 +41,8 @@ namespace UnityAtoms.BaseAtoms.Editor
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
+ AtomListAttribute atomListAttr = attribute as AtomListAttribute;
+
label = EditorGUI.BeginProperty(position, label, property);
var proColor = new Color(83f / 255f, 83f / 255f, 83f / 255f);
var basicColor = new Color(174f / 255f, 174f / 255f, 174f / 255f);
@@ -49,7 +52,7 @@ namespace UnityAtoms.BaseAtoms.Editor
EditorGUI.indentLevel = 0;
EditorGUI.BeginChangeCheck();
- var listArrayProperty = property.FindPropertyRelative(SERIALIZED_LIST_PROPNAME);
+ var listArrayProperty = property.FindPropertyRelative(atomListAttr != null && !string.IsNullOrWhiteSpace(atomListAttr.ChildPropName) ? atomListAttr.ChildPropName : SERIALIZED_LIST_PROPNAME);
var restRect = new Rect();
var initialPosition = new Rect(position);
@@ -59,7 +62,7 @@ namespace UnityAtoms.BaseAtoms.Editor
var labelPosition = IMGUIUtils.SnipRectH(initialPosition, initialPosition.width - BUTTON_WIDTH, out restRect);
labelPosition.height = EditorGUIUtility.singleLineHeight + LINE_BOTTOM_MARGIN;
- EditorGUI.PrefixLabel(initialPosition, new GUIContent(LIST_LABEL_NAME));
+ EditorGUI.PrefixLabel(initialPosition, new GUIContent(atomListAttr != null ? (atomListAttr.Label ?? label.text) : LIST_LABEL_NAME));
var addButtonPosition = IMGUIUtils.SnipRectH(restRect, restRect.width, out restRect);
addButtonPosition.height = EditorGUIUtility.singleLineHeight;
@@ -83,7 +86,7 @@ namespace UnityAtoms.BaseAtoms.Editor
EditorGUI.PrefixLabel(indexLabelPos, new GUIContent(i.ToString()));
var itemPos = IMGUIUtils.SnipRectH(restRect, linePosition.width - BUTTON_WIDTH - INDEX_LABEL_WIDTH - GUTTER * 2, out restRect, GUTTER);
- EditorGUI.PropertyField(itemPos, itemProp, GUIContent.none, false);
+ EditorGUI.PropertyField(itemPos, itemProp, GUIContent.none, atomListAttr != null ? atomListAttr.IncludeChildrenForItems : false);
var removeButtonPosition = new Rect(restRect);
removeButtonPosition.height = EditorGUIUtility.singleLineHeight;
@@ -93,7 +96,7 @@ namespace UnityAtoms.BaseAtoms.Editor
indexToDelete = i;
}
- linePosition.y += EditorGUIUtility.singleLineHeight + LINE_BOTTOM_MARGIN;
+ linePosition.y += EditorGUI.GetPropertyHeight(itemProp) + LINE_BOTTOM_MARGIN;
}
if (insertIndex != -1)
@@ -101,6 +104,8 @@ namespace UnityAtoms.BaseAtoms.Editor
if (listArrayProperty != null)
{
listArrayProperty.InsertArrayElementAtIndex(insertIndex);
+ var newProp = listArrayProperty.GetArrayElementAtIndex(insertIndex);
+ newProp.isExpanded = true;
}
}
diff --git a/Packages/BaseAtoms/Editor/Drawers/Collections/AtomBaseVariableListDrawer.cs.meta b/Packages/BaseAtoms/Editor/Drawers/Collections/AtomListDrawer.cs.meta
similarity index 83%
rename from Packages/BaseAtoms/Editor/Drawers/Collections/AtomBaseVariableListDrawer.cs.meta
rename to Packages/BaseAtoms/Editor/Drawers/Collections/AtomListDrawer.cs.meta
index e83ecafc..6faae403 100644
--- a/Packages/BaseAtoms/Editor/Drawers/Collections/AtomBaseVariableListDrawer.cs.meta
+++ b/Packages/BaseAtoms/Editor/Drawers/Collections/AtomListDrawer.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 01e2d4c866bf1461f99e3ffd89dc8882
+guid: d0d49408cf0e24375a9b017fc4210a94
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Packages/BaseAtoms/Runtime/AtomListWrapper.meta b/Packages/BaseAtoms/Runtime/AtomListWrapper.meta
new file mode 100644
index 00000000..31d26376
--- /dev/null
+++ b/Packages/BaseAtoms/Runtime/AtomListWrapper.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 93604d20e8e8f4a7da3af79e4303a48f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/BaseAtoms/Runtime/AtomListWrapper/AtomListWrapper.cs b/Packages/BaseAtoms/Runtime/AtomListWrapper/AtomListWrapper.cs
new file mode 100644
index 00000000..4ea127a6
--- /dev/null
+++ b/Packages/BaseAtoms/Runtime/AtomListWrapper/AtomListWrapper.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace UnityAtoms.BaseAtoms
+{
+ ///
+ /// Needed in order to create a property drawer for a List / Array. See this for more info: https://answers.unity.com/questions/605875/custompropertydrawer-for-array-types-in-43.html
+ ///
+ /// Type used in list.
+ public abstract class AtomListWrapper
+ {
+ public List List { get => _list; }
+
+ [SerializeField]
+ private List _list;
+ }
+}
\ No newline at end of file
diff --git a/Packages/BaseAtoms/Runtime/AtomListWrapper/AtomListWrapper.cs.meta b/Packages/BaseAtoms/Runtime/AtomListWrapper/AtomListWrapper.cs.meta
new file mode 100644
index 00000000..d96627d0
--- /dev/null
+++ b/Packages/BaseAtoms/Runtime/AtomListWrapper/AtomListWrapper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: cbf386e8976ba4aeebf2c157c511166f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/BaseAtoms/Runtime/Attributes.meta b/Packages/BaseAtoms/Runtime/Attributes.meta
new file mode 100644
index 00000000..2e9bcb96
--- /dev/null
+++ b/Packages/BaseAtoms/Runtime/Attributes.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: ed96ad5d334a847438fd3f164b941c3f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/BaseAtoms/Runtime/Attributes/AtomListAttribute.cs b/Packages/BaseAtoms/Runtime/Attributes/AtomListAttribute.cs
new file mode 100644
index 00000000..3ace5914
--- /dev/null
+++ b/Packages/BaseAtoms/Runtime/Attributes/AtomListAttribute.cs
@@ -0,0 +1,18 @@
+using UnityEngine;
+
+namespace UnityAtoms.BaseAtoms
+{
+ public class AtomListAttribute : PropertyAttribute
+ {
+ public string Label { get; set; }
+ public string ChildPropName { get; set; }
+ public bool IncludeChildrenForItems { get; set; }
+
+ public AtomListAttribute(string label = null, string childPropName = "_list", bool includeChildrenForItems = true)
+ {
+ Label = label;
+ ChildPropName = childPropName;
+ IncludeChildrenForItems = includeChildrenForItems;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Packages/BaseAtoms/Runtime/Attributes/AtomListAttribute.cs.meta b/Packages/BaseAtoms/Runtime/Attributes/AtomListAttribute.cs.meta
new file mode 100644
index 00000000..3549f341
--- /dev/null
+++ b/Packages/BaseAtoms/Runtime/Attributes/AtomListAttribute.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c9cdeac56b0004a4c88add9ed1f3d6a7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/Core/Editor/Editors/Variables/AtomVariableEditor.cs b/Packages/Core/Editor/Editors/Variables/AtomVariableEditor.cs
index b1e0839c..006926d7 100644
--- a/Packages/Core/Editor/Editors/Variables/AtomVariableEditor.cs
+++ b/Packages/Core/Editor/Editors/Variables/AtomVariableEditor.cs
@@ -67,7 +67,7 @@ namespace UnityAtoms.Editor
GUILayout.Space(2);
if (GUILayout.Button("Raise", GUILayout.Width(raiseButtonWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
{
- evt.GetType().GetMethod("Raise", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { atomTarget.BaseValue });
+ evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { atomTarget.BaseValue });
}
}
@@ -85,7 +85,7 @@ namespace UnityAtoms.Editor
{
var oldValueProp = serializedObject.FindProperty("_oldValue");
object oldValue = oldValueProp.GetPropertyValue();
- evt.GetType().GetMethod("Raise", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { (object)(new P() { Item1 = (T)atomTarget.BaseValue, Item2 = (T)oldValue }) });
+ evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { (object)(new P() { Item1 = (T)atomTarget.BaseValue, Item2 = (T)oldValue }) });
}
}
diff --git a/Packages/Core/Runtime/Events/AtomEvent.cs b/Packages/Core/Runtime/Events/AtomEvent.cs
index 1ea9f3e7..b9e21b36 100644
--- a/Packages/Core/Runtime/Events/AtomEvent.cs
+++ b/Packages/Core/Runtime/Events/AtomEvent.cs
@@ -66,6 +66,12 @@ namespace UnityAtoms
AddToReplayBuffer(item);
}
+ ///
+ /// Used in editor scipts since Raise is ambigious when using reflection to get method.
+ ///
+ ///
+ public void RaiseEditor(T item) => Raise(item);
+
///
/// Register handler to be called when the Event triggers.
///
diff --git a/Packages/Core/Runtime/Extensions/IListExtensions.cs b/Packages/Core/Runtime/Extensions/IListExtensions.cs
index 9efe0dd4..51f0e5b0 100644
--- a/Packages/Core/Runtime/Extensions/IListExtensions.cs
+++ b/Packages/Core/Runtime/Extensions/IListExtensions.cs
@@ -16,6 +16,12 @@ namespace UnityAtoms
return default(T);
}
+ public static bool Exists(this IList list, Func func)
+ {
+ var first = list.First(func);
+ return first != null ? true : false;
+ }
+
public static GameObject GetOrInstantiate(this IList list, UnityEngine.Object prefab, Vector3 position, Quaternion quaternion, Func condition)
{
var component = list.First(condition);
diff --git a/Packages/FSM/Editor/Editors/FiniteStateMachineEditor.cs b/Packages/FSM/Editor/Editors/FiniteStateMachineEditor.cs
new file mode 100644
index 00000000..06446fda
--- /dev/null
+++ b/Packages/FSM/Editor/Editors/FiniteStateMachineEditor.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Reflection;
+using UnityEditor;
+using UnityEngine;
+using UnityAtoms.Editor;
+using UnityAtoms.BaseAtoms;
+
+namespace UnityAtoms.FSM.Editor
+{
+ ///
+ /// Custom property drawer for type `FiniteStateMachine`.
+ ///
+ [CustomEditor(typeof(FiniteStateMachine))]
+ public sealed class FiniteStateMachineEditor : UnityEditor.Editor
+ {
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_developerDescription"));
+ EditorGUILayout.Space();
+
+ EditorGUI.BeginDisabledGroup(true);
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_initialValue"), true);
+ EditorGUI.EndDisabledGroup();
+
+ EditorGUI.BeginDisabledGroup(true);
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_value"), true);
+ EditorGUI.EndDisabledGroup();
+
+ EditorGUI.BeginDisabledGroup(true);
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_oldValue"), true);
+ EditorGUI.EndDisabledGroup();
+
+ const int raiseButtonWidth = 52;
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("Changed"));
+ var changed = serializedObject.FindProperty("Changed").objectReferenceValue;
+ if (changed != null && changed is AtomEventBase evt && target is AtomBaseVariable atomTarget)
+ {
+ GUILayout.Space(2);
+ if (GUILayout.Button("Raise", GUILayout.Width(raiseButtonWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
+ {
+ evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { atomTarget.BaseValue });
+ }
+ }
+
+ }
+
+ using (new EditorGUILayout.HorizontalScope())
+ {
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("ChangedWithHistory"));
+ var changedWithHistory = serializedObject.FindProperty("ChangedWithHistory").objectReferenceValue;
+ if (changedWithHistory != null && changedWithHistory is AtomEventBase evt && target is AtomBaseVariable atomTarget)
+ {
+
+ GUILayout.Space(2);
+ if (GUILayout.Button("Raise", GUILayout.Width(raiseButtonWidth), GUILayout.Height(EditorGUIUtility.singleLineHeight)))
+ {
+ var oldValueProp = serializedObject.FindProperty("_oldValue");
+ object oldValue = oldValueProp.GetPropertyValue();
+ evt.GetType().GetMethod("RaiseEditor", BindingFlags.Public | BindingFlags.Instance)?.Invoke(evt, new[] { (object)(new StringPair() { Item1 = (string)atomTarget.BaseValue, Item2 = (string)oldValue }) });
+ }
+ }
+
+ }
+
+ var transitionStartedProp = serializedObject.FindProperty("_transitionStarted");
+ EditorGUILayout.PropertyField(transitionStartedProp, new GUIContent() { tooltip = "Event raised when a transition is started.", text = transitionStartedProp.displayName }, true);
+
+ var completeCurrentTransitionProp = serializedObject.FindProperty("_completeCurrentTransition");
+ EditorGUILayout.PropertyField(completeCurrentTransitionProp, new GUIContent() { tooltip = "A Bool Event that is passed along in the Transition Started event (an event that is required when using this event). The transition needs also to be marked with 'Raise Event To Complete Transition in order to use this event.'", text = completeCurrentTransitionProp.displayName }, true);
+
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_states"), true);
+ EditorGUILayout.PropertyField(serializedObject.FindProperty("_transitions"), true);
+
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+}
diff --git a/Packages/FSM/Editor/Editors/FiniteStateMachineEditor.cs.meta b/Packages/FSM/Editor/Editors/FiniteStateMachineEditor.cs.meta
new file mode 100644
index 00000000..3ab5cdc1
--- /dev/null
+++ b/Packages/FSM/Editor/Editors/FiniteStateMachineEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7c9dfec58f1704690b369ef9580bb07e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/FSM/Runtime/FiniteStateMachine/FSMStateListWrapper.cs b/Packages/FSM/Runtime/FiniteStateMachine/FSMStateListWrapper.cs
new file mode 100644
index 00000000..f7605893
--- /dev/null
+++ b/Packages/FSM/Runtime/FiniteStateMachine/FSMStateListWrapper.cs
@@ -0,0 +1,8 @@
+using System;
+using UnityAtoms.BaseAtoms;
+
+namespace UnityAtoms.FSM
+{
+ [Serializable]
+ public class FSMStateListWrapper : AtomListWrapper { }
+}
\ No newline at end of file
diff --git a/Packages/FSM/Runtime/FiniteStateMachine/FSMStateListWrapper.cs.meta b/Packages/FSM/Runtime/FiniteStateMachine/FSMStateListWrapper.cs.meta
new file mode 100644
index 00000000..32a3703e
--- /dev/null
+++ b/Packages/FSM/Runtime/FiniteStateMachine/FSMStateListWrapper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2aa0cb2bd8023434aab0a911accf16e4
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Packages/FSM/Runtime/FiniteStateMachine/FiniteStateMachine.cs b/Packages/FSM/Runtime/FiniteStateMachine/FiniteStateMachine.cs
index 79f20498..5f9a5215 100644
--- a/Packages/FSM/Runtime/FiniteStateMachine/FiniteStateMachine.cs
+++ b/Packages/FSM/Runtime/FiniteStateMachine/FiniteStateMachine.cs
@@ -1,7 +1,7 @@
using System;
-using System.Collections.Generic;
using UnityEngine;
using UnityAtoms.BaseAtoms;
+using UnityAtoms;
namespace UnityAtoms.FSM
{
@@ -18,20 +18,19 @@ namespace UnityAtoms.FSM
get
{
var state = GetState(_value);
- return state.SubMachine != null ? state.SubMachine.Value : _value;
+ return state != null && state.SubMachine != null ? state.SubMachine.Value : _value;
}
set => Dispatch(value);
}
public FSMTransitionDataEvent TransitionStarted { get => _transitionStarted; set => _transitionStarted = value; }
public BoolEvent CompleteCurrentTransition { get => _completeCurrentTransition; set => _completeCurrentTransition = value; }
- public override string InitialValue { get => _states != null && _states.Count > 0 ? _states[0].Id : ""; }
+ public override string InitialValue { get => _states?.List != null && _states.List.Count > 0 ? _states.List[0].Id : ""; }
///
/// Gets a boolean value indicating if the state machine is currently transitioning.
///
public bool IsTransitioning { get => _currentTransition != null; }
-
[SerializeField]
private FSMTransitionDataEvent _transitionStarted = default(FSMTransitionDataEvent);
@@ -39,10 +38,12 @@ namespace UnityAtoms.FSM
private BoolEvent _completeCurrentTransition = default(BoolEvent);
[SerializeField]
- private List _states;
+ [AtomList]
+ private FSMStateListWrapper _states;
[SerializeField]
- private List _transitions;
+ [AtomList]
+ private TransitionListWrapper _transitions;
private bool _isUpdatingState = false;
private Transition _currentTransition = null;
@@ -165,12 +166,12 @@ namespace UnityAtoms.FSM
public override void Reset(bool shouldTriggerEvents = false)
{
- // TODO: Validate transitions and states
+ Validate();
// Set all timers to the same as the cooldown
- for (var i = 0; i < _states.Count; ++i)
+ for (var i = 0; i < _states.List.Count; ++i)
{
- _states[i].Timer = _states[i].Cooldown;
+ _states.List[i].Timer = _states.List[i].Cooldown;
}
if (!_resetOnNextTransitionCompleted && !IsTransitioning)
@@ -238,6 +239,24 @@ namespace UnityAtoms.FSM
protected override bool ValueEquals(string other) => false; // Always trigger events even if changing to the same state as previous
+
+
+ private void Validate()
+ {
+ for (var i = 0; i < _transitions.List.Count; ++i)
+ {
+ var transition = _transitions.List[i];
+ if (!_states.List.Exists((s) => s.Id == transition.FromState))
+ {
+ Debug.LogError($"Transition with From State {transition.FromState} can't be found in the defined states.");
+ }
+ if (!_states.List.Exists((s) => s.Id == transition.ToState))
+ {
+ Debug.LogError($"Transition with To State {transition.ToState} can't be found in the defined states.");
+ }
+ }
+ }
+
private void EndCurrentTransition()
{
if (_resetOnNextTransitionCompleted)
@@ -268,11 +287,11 @@ namespace UnityAtoms.FSM
private void ResetAllSubMachines()
{
- for (var i = 0; i < _states.Count; ++i)
+ for (var i = 0; i < _states.List.Count; ++i)
{
- if (_states[i].SubMachine != null)
+ if (_states.List[i].SubMachine != null)
{
- _states[i].SubMachine.Reset();
+ _states.List[i].SubMachine.Reset();
}
}
}
@@ -286,9 +305,9 @@ namespace UnityAtoms.FSM
{
// Update timers and call OnStateCooldown handlers if applicable
var currentValue = Value;
- for (var i = 0; i < _states.Count; ++i)
+ for (var i = 0; i < _states.List.Count; ++i)
{
- var state = _states[i];
+ var state = _states.List[i];
if (state.Cooldown > 0f)
{
var isCurrent = state.Id == currentValue;
@@ -336,9 +355,9 @@ namespace UnityAtoms.FSM
{
Transition ret = null;
- for (var i = 0; i < _transitions.Count; ++i)
+ for (var i = 0; i < _transitions.List.Count; ++i)
{
- var transition = _transitions[i];
+ var transition = _transitions.List[i];
if (command == transition.Command && _currentFlatValue == transition.FromState)
{
return transition;
@@ -350,15 +369,15 @@ namespace UnityAtoms.FSM
private FSMState GetState(string id)
{
- for (var i = 0; i < _states.Count; ++i)
+ for (var i = 0; i < _states.List.Count; ++i)
{
- if (_states[i].Id == id)
+ if (_states.List[i].Id == id)
{
- return _states[i];
+ return _states.List[i];
}
}
- throw new System.Exception($"State with id {id} could not be found.");
+ return null;
}
}
}
\ No newline at end of file
diff --git a/Packages/FSM/Runtime/Transition/TransitionListWrapper.cs b/Packages/FSM/Runtime/Transition/TransitionListWrapper.cs
new file mode 100644
index 00000000..9fad5bb3
--- /dev/null
+++ b/Packages/FSM/Runtime/Transition/TransitionListWrapper.cs
@@ -0,0 +1,8 @@
+using System;
+using UnityAtoms.BaseAtoms;
+
+namespace UnityAtoms.FSM
+{
+ [Serializable]
+ public class TransitionListWrapper : AtomListWrapper { }
+}
\ No newline at end of file
diff --git a/Packages/FSM/Runtime/Transition/TransitionListWrapper.cs.meta b/Packages/FSM/Runtime/Transition/TransitionListWrapper.cs.meta
new file mode 100644
index 00000000..477a54e5
--- /dev/null
+++ b/Packages/FSM/Runtime/Transition/TransitionListWrapper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5a7a3f96d68ef4e3d9637bb1f4634554
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: