diff --git a/Code/Editor/Drawers/AiSimulation.meta b/Code/Editor/Drawers/AiSimulation.meta new file mode 100644 index 00000000..ec3dba84 --- /dev/null +++ b/Code/Editor/Drawers/AiSimulation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9e1f4154ea1bef04db091ca4bd96685e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Editor/Drawers/AiSimulation/BehaviorStateDrawer.cs b/Code/Editor/Drawers/AiSimulation/BehaviorStateDrawer.cs new file mode 100644 index 00000000..52b9a757 --- /dev/null +++ b/Code/Editor/Drawers/AiSimulation/BehaviorStateDrawer.cs @@ -0,0 +1,18 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityUtility.AiSimulation.Simple; +using UnityUtilityEditor.Drawers.Attributes; + +namespace UnityUtilityEditor.Drawers.AiSimulation +{ + [CustomPropertyDrawer(typeof(BehaviorState), true)] + internal class BehaviorStateDrawer : ReferenceSelectionDrawer + { + protected override void DrawExtendedContent(in Rect position, SerializedProperty property) + { + Type conditionType = (property.serializedObject.targetObject as AiStateSet).GetStateRootType(); + DrawContent(position, property, conditionType); + } + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/Common.cs.meta b/Code/Editor/Drawers/AiSimulation/BehaviorStateDrawer.cs.meta similarity index 83% rename from Code/Runtime/UnityUtility/AiSimulation/Common.cs.meta rename to Code/Editor/Drawers/AiSimulation/BehaviorStateDrawer.cs.meta index f32c3508..4a503710 100644 --- a/Code/Runtime/UnityUtility/AiSimulation/Common.cs.meta +++ b/Code/Editor/Drawers/AiSimulation/BehaviorStateDrawer.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 802ffff7de3225945b014108cf9b2a8a +guid: 7dc0403882aaabd4ea501743c21abdb8 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Code/Editor/Drawers/AiSimulation/CompleteHandlerDrawer.cs b/Code/Editor/Drawers/AiSimulation/CompleteHandlerDrawer.cs new file mode 100644 index 00000000..8e10e43a --- /dev/null +++ b/Code/Editor/Drawers/AiSimulation/CompleteHandlerDrawer.cs @@ -0,0 +1,28 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityUtility.AiSimulation; +using UnityUtility.AiSimulation.NodeBased; +using UnityUtility.AiSimulation.Simple; +using UnityUtilityEditor.Drawers.Attributes; + +namespace UnityUtilityEditor.Drawers.AiSimulation +{ + [CustomPropertyDrawer(typeof(CompleteHandler), true)] + internal class CompleteHandlerDrawer : ReferenceSelectionDrawer + { + protected override void DrawExtendedContent(in Rect position, SerializedProperty property) + { + Type rootType = GetRootType(property); + DrawContent(position, property, rootType); + } + + private Type GetRootType(SerializedProperty property) + { + if (property.serializedObject.targetObject is AiStateSet set) + return set.GetCompleteHandlerRootType(); + + return (property.serializedObject.targetObject as AiStateGraph).GetCompleteHandlerRootType(); + } + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/CommonCondition.cs.meta b/Code/Editor/Drawers/AiSimulation/CompleteHandlerDrawer.cs.meta similarity index 83% rename from Code/Runtime/UnityUtility/AiSimulation/CommonCondition.cs.meta rename to Code/Editor/Drawers/AiSimulation/CompleteHandlerDrawer.cs.meta index a11aba52..7eb4a4c6 100644 --- a/Code/Runtime/UnityUtility/AiSimulation/CommonCondition.cs.meta +++ b/Code/Editor/Drawers/AiSimulation/CompleteHandlerDrawer.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2260e9de8947f2544b1344f682ff2d02 +guid: e19f2e51c5e01954583b2f168c154559 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Code/Editor/Drawers/StateConditionDrawer.cs b/Code/Editor/Drawers/AiSimulation/StateConditionDrawer.cs similarity index 50% rename from Code/Editor/Drawers/StateConditionDrawer.cs rename to Code/Editor/Drawers/AiSimulation/StateConditionDrawer.cs index a31dadf7..78ad16da 100644 --- a/Code/Editor/Drawers/StateConditionDrawer.cs +++ b/Code/Editor/Drawers/AiSimulation/StateConditionDrawer.cs @@ -1,18 +1,20 @@ -using UnityEditor; +using System; +using UnityEditor; using UnityEngine; -using UnityUtility.AiSimulation; +using UnityUtility.AiSimulation.Simple; +using UnityUtilityEditor.Drawers.Attributes; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.AiSimulation { - [CustomPropertyDrawer(typeof(StateCondition))] + [CustomPropertyDrawer(typeof(StateCondition), true)] internal class StateConditionDrawer : ReferenceSelectionDrawer { protected override void DrawExtendedContent(in Rect position, SerializedProperty property) { if (!property.HasManagedReferenceValue()) { - base.DrawExtendedContent(position, property); + Draw(position, property); return; } @@ -20,7 +22,7 @@ protected override void DrawExtendedContent(in Rect position, SerializedProperty Rect rect = position; rect.width *= weight; - base.DrawExtendedContent(rect, property); + Draw(position, property); SerializedProperty notProp = property.FindPropertyRelative(StateCondition.NotFieldName); @@ -28,5 +30,14 @@ protected override void DrawExtendedContent(in Rect position, SerializedProperty rect.width = position.width * (1f - weight); notProp.boolValue = EditorGui.ToggleButton(rect, "Not", notProp.boolValue); } + + private void Draw(in Rect position, SerializedProperty property) + { + Type conditionType = (property.serializedObject.targetObject as AiStateSet).GetConditionRootType(); + if (conditionType == typeof(StateCondition)) + DrawContent(position, property, conditionType); + else + DrawContent(position, property, conditionType, typeof(Any), typeof(All)); + } } } diff --git a/Code/Editor/Drawers/StateConditionDrawer.cs.meta b/Code/Editor/Drawers/AiSimulation/StateConditionDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/StateConditionDrawer.cs.meta rename to Code/Editor/Drawers/AiSimulation/StateConditionDrawer.cs.meta diff --git a/Code/Editor/Drawers/Attributes.meta b/Code/Editor/Drawers/Attributes.meta new file mode 100644 index 00000000..612c2ef6 --- /dev/null +++ b/Code/Editor/Drawers/Attributes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 529081fe011f3594abb6d49783cb88b6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Editor/Drawers/Attributes/CertainTypesDrawer.cs b/Code/Editor/Drawers/Attributes/CertainTypesDrawer.cs new file mode 100644 index 00000000..68e71b37 --- /dev/null +++ b/Code/Editor/Drawers/Attributes/CertainTypesDrawer.cs @@ -0,0 +1,48 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityUtility.CSharp; +using UnityUtility.Inspector; +using UnityUtilityEditor.Engine; +using UnityObject = UnityEngine.Object; + +namespace UnityUtilityEditor.Drawers.Attributes +{ + [CustomPropertyDrawer(typeof(CertainTypesAttribute))] + public class CertainTypesDrawer : AttributeDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + Type type = EditorUtilityExt.GetFieldType(this); + if (!type.IsAssignableTo(typeof(UnityObject))) + { + EditorGui.ErrorLabel(position, label, $"Use {nameof(CertainTypesAttribute)} with {nameof(UnityEngine)}.{nameof(UnityEngine.Object)}."); + return; + } + + UnityObject prevValue = property.objectReferenceValue; + property.Draw(position, label); + + if (property.objectReferenceValue == null) + return; + + Type tryType = property.objectReferenceValue.GetType(); + if (!Inherited(tryType)) + { + property.objectReferenceValue = prevValue == null || Inherited(prevValue.GetType()) ? prevValue : null; + Debug.LogWarning($"Cannot assign {tryType}. It is not specified by {nameof(CertainTypesAttribute)}."); + } + } + + private bool Inherited(Type assignedType) + { + for (int i = 0; i < attribute.Types.Length; i++) + { + if (assignedType.IsAssignableTo(attribute.Types[i])) + return true; + } + + return false; + } + } +} diff --git a/Code/Editor/Drawers/RngParamOptionDrawer.cs.meta b/Code/Editor/Drawers/Attributes/CertainTypesDrawer.cs.meta similarity index 83% rename from Code/Editor/Drawers/RngParamOptionDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/CertainTypesDrawer.cs.meta index 00febcef..00dfc3c0 100644 --- a/Code/Editor/Drawers/RngParamOptionDrawer.cs.meta +++ b/Code/Editor/Drawers/Attributes/CertainTypesDrawer.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7ace47522d389f949880ff1ac3ed20ba +guid: 9756eb77ce7601e47baffaf31ccfc29b MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Code/Editor/Drawers/ClampDiapasonDrawer.cs b/Code/Editor/Drawers/Attributes/ClampDiapasonDrawer.cs similarity index 97% rename from Code/Editor/Drawers/ClampDiapasonDrawer.cs rename to Code/Editor/Drawers/Attributes/ClampDiapasonDrawer.cs index 390f4ff4..340f4690 100644 --- a/Code/Editor/Drawers/ClampDiapasonDrawer.cs +++ b/Code/Editor/Drawers/Attributes/ClampDiapasonDrawer.cs @@ -6,7 +6,7 @@ using UnityUtility.NumericEntities; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(ClampDiapasonAttribute))] internal class ClampDiapasonDrawer : AttributeDrawer diff --git a/Code/Editor/Drawers/ClampDiapasonDrawer.cs.meta b/Code/Editor/Drawers/Attributes/ClampDiapasonDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/ClampDiapasonDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/ClampDiapasonDrawer.cs.meta diff --git a/Code/Editor/Drawers/DisableEditingDrawer.cs b/Code/Editor/Drawers/Attributes/DisableEditingDrawer.cs similarity index 92% rename from Code/Editor/Drawers/DisableEditingDrawer.cs rename to Code/Editor/Drawers/Attributes/DisableEditingDrawer.cs index 15e5bfee..53bc2631 100644 --- a/Code/Editor/Drawers/DisableEditingDrawer.cs +++ b/Code/Editor/Drawers/Attributes/DisableEditingDrawer.cs @@ -2,7 +2,7 @@ using UnityEngine; using UnityUtility.Inspector; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(DisableEditingAttribute))] internal class DisableEditingDrawer : PropertyDrawer diff --git a/Code/Editor/Drawers/DisableEditingDrawer.cs.meta b/Code/Editor/Drawers/Attributes/DisableEditingDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/DisableEditingDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/DisableEditingDrawer.cs.meta diff --git a/Code/Editor/Drawers/DrawFlagsDrawer.cs b/Code/Editor/Drawers/Attributes/DrawFlagsDrawer.cs similarity index 99% rename from Code/Editor/Drawers/DrawFlagsDrawer.cs rename to Code/Editor/Drawers/Attributes/DrawFlagsDrawer.cs index 5cdea6ba..4a67b954 100644 --- a/Code/Editor/Drawers/DrawFlagsDrawer.cs +++ b/Code/Editor/Drawers/Attributes/DrawFlagsDrawer.cs @@ -8,7 +8,7 @@ using UnityUtilityEditor.Engine; using UnityUtilityEditor.Window; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(DrawFlagsAttribute))] internal class DrawFlagsDrawer : AttributeDrawer diff --git a/Code/Editor/Drawers/DrawFlagsDrawer.cs.meta b/Code/Editor/Drawers/Attributes/DrawFlagsDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/DrawFlagsDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/DrawFlagsDrawer.cs.meta diff --git a/Code/Editor/Drawers/DrawObjectFieldsDrawer.cs b/Code/Editor/Drawers/Attributes/DrawObjectFieldsDrawer.cs similarity index 95% rename from Code/Editor/Drawers/DrawObjectFieldsDrawer.cs rename to Code/Editor/Drawers/Attributes/DrawObjectFieldsDrawer.cs index aaf49d23..121feb84 100644 --- a/Code/Editor/Drawers/DrawObjectFieldsDrawer.cs +++ b/Code/Editor/Drawers/Attributes/DrawObjectFieldsDrawer.cs @@ -5,7 +5,7 @@ using UnityUtility.Tools; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(DrawObjectFieldsAttribute))] internal class DrawObjectFieldsDrawer : AttributeDrawer @@ -14,7 +14,7 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten { if (!EditorUtilityExt.GetFieldType(this).IsAssignableTo(typeof(ScriptableObject))) { - EditorGui.ErrorLabel(position, label, $"Use {nameof(DrawObjectFieldsAttribute)} only with ScriptableObject."); + EditorGui.ErrorLabel(position, label, $"Use {nameof(DrawObjectFieldsAttribute)} only with {nameof(ScriptableObject)}."); return; } diff --git a/Code/Editor/Drawers/DrawObjectFieldsDrawer.cs.meta b/Code/Editor/Drawers/Attributes/DrawObjectFieldsDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/DrawObjectFieldsDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/DrawObjectFieldsDrawer.cs.meta diff --git a/Code/Editor/Drawers/DrawTypenameDrawer.cs b/Code/Editor/Drawers/Attributes/DrawTypenameDrawer.cs similarity index 94% rename from Code/Editor/Drawers/DrawTypenameDrawer.cs rename to Code/Editor/Drawers/Attributes/DrawTypenameDrawer.cs index c3dcfb48..c2308f96 100644 --- a/Code/Editor/Drawers/DrawTypenameDrawer.cs +++ b/Code/Editor/Drawers/Attributes/DrawTypenameDrawer.cs @@ -5,7 +5,7 @@ using UnityUtility.Inspector; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(DrawTypenameAttribute))] internal class DrawTypenameDrawer : SerializeReferenceDrawer diff --git a/Code/Editor/Drawers/DrawTypenameDrawer.cs.meta b/Code/Editor/Drawers/Attributes/DrawTypenameDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/DrawTypenameDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/DrawTypenameDrawer.cs.meta diff --git a/Code/Editor/Drawers/EnumMenuDrawer.cs b/Code/Editor/Drawers/Attributes/EnumMenuDrawer.cs similarity index 95% rename from Code/Editor/Drawers/EnumMenuDrawer.cs rename to Code/Editor/Drawers/Attributes/EnumMenuDrawer.cs index 88934ad7..a199c3e2 100644 --- a/Code/Editor/Drawers/EnumMenuDrawer.cs +++ b/Code/Editor/Drawers/Attributes/EnumMenuDrawer.cs @@ -4,7 +4,7 @@ using UnityUtility.Inspector; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(EnumMenuAttribute), true)] internal sealed class EnumMenuDrawer : PropertyDrawer diff --git a/Code/Editor/Drawers/EnumMenuDrawer.cs.meta b/Code/Editor/Drawers/Attributes/EnumMenuDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/EnumMenuDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/EnumMenuDrawer.cs.meta diff --git a/Code/Editor/Drawers/FolderRequiredDrawer.cs b/Code/Editor/Drawers/Attributes/FolderRequiredDrawer.cs similarity index 93% rename from Code/Editor/Drawers/FolderRequiredDrawer.cs rename to Code/Editor/Drawers/Attributes/FolderRequiredDrawer.cs index 57e5866d..1453ccef 100644 --- a/Code/Editor/Drawers/FolderRequiredDrawer.cs +++ b/Code/Editor/Drawers/Attributes/FolderRequiredDrawer.cs @@ -3,7 +3,7 @@ using UnityUtility.Inspector; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(FolderRequiredAttribute))] internal class FolderRequiredDrawer : PropertyDrawer diff --git a/Code/Editor/Drawers/FolderRequiredDrawer.cs.meta b/Code/Editor/Drawers/Attributes/FolderRequiredDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/FolderRequiredDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/FolderRequiredDrawer.cs.meta diff --git a/Code/Editor/Drawers/IdentifierDrawer.cs b/Code/Editor/Drawers/Attributes/IdentifierDrawer.cs similarity index 96% rename from Code/Editor/Drawers/IdentifierDrawer.cs rename to Code/Editor/Drawers/Attributes/IdentifierDrawer.cs index ced37b5e..7ed0117a 100644 --- a/Code/Editor/Drawers/IdentifierDrawer.cs +++ b/Code/Editor/Drawers/Attributes/IdentifierDrawer.cs @@ -5,7 +5,7 @@ using UnityUtility.Inspector; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(IdentifierAttribute))] internal class IdentifierDrawer : AttributeDrawer diff --git a/Code/Editor/Drawers/IdentifierDrawer.cs.meta b/Code/Editor/Drawers/Attributes/IdentifierDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/IdentifierDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/IdentifierDrawer.cs.meta diff --git a/Code/Editor/Drawers/InitListDrawer.cs b/Code/Editor/Drawers/Attributes/InitListDrawer.cs similarity index 98% rename from Code/Editor/Drawers/InitListDrawer.cs rename to Code/Editor/Drawers/Attributes/InitListDrawer.cs index 118b6683..14a4a4fc 100644 --- a/Code/Editor/Drawers/InitListDrawer.cs +++ b/Code/Editor/Drawers/Attributes/InitListDrawer.cs @@ -7,7 +7,7 @@ using UnityUtility.Inspector; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(InitListAttribute))] internal class InitListDrawer : SerializeReferenceDrawer diff --git a/Code/Editor/Drawers/InitListDrawer.cs.meta b/Code/Editor/Drawers/Attributes/InitListDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/InitListDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/InitListDrawer.cs.meta diff --git a/Code/Editor/Drawers/InitToggleDrawer.cs b/Code/Editor/Drawers/Attributes/InitToggleDrawer.cs similarity index 96% rename from Code/Editor/Drawers/InitToggleDrawer.cs rename to Code/Editor/Drawers/Attributes/InitToggleDrawer.cs index 66a0bcf6..cb5c10ff 100644 --- a/Code/Editor/Drawers/InitToggleDrawer.cs +++ b/Code/Editor/Drawers/Attributes/InitToggleDrawer.cs @@ -4,7 +4,7 @@ using UnityUtility.Inspector; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(InitToggleAttribute))] internal class InitToggleDrawer : SerializeReferenceDrawer diff --git a/Code/Editor/Drawers/InitToggleDrawer.cs.meta b/Code/Editor/Drawers/Attributes/InitToggleDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/InitToggleDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/InitToggleDrawer.cs.meta diff --git a/Code/Editor/Drawers/LayerFieldDrawer.cs b/Code/Editor/Drawers/Attributes/LayerFieldDrawer.cs similarity index 93% rename from Code/Editor/Drawers/LayerFieldDrawer.cs rename to Code/Editor/Drawers/Attributes/LayerFieldDrawer.cs index 6d2c599d..62ef9da2 100644 --- a/Code/Editor/Drawers/LayerFieldDrawer.cs +++ b/Code/Editor/Drawers/Attributes/LayerFieldDrawer.cs @@ -5,7 +5,7 @@ using UnityUtility.Inspector; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(LayerFieldAttribute))] internal class LayerFieldDrawer : AttributeDrawer diff --git a/Code/Editor/Drawers/LayerFieldDrawer.cs.meta b/Code/Editor/Drawers/Attributes/LayerFieldDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/LayerFieldDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/LayerFieldDrawer.cs.meta diff --git a/Code/Editor/Drawers/ReferenceSelectionDrawer.cs b/Code/Editor/Drawers/Attributes/ReferenceSelectionDrawer.cs similarity index 67% rename from Code/Editor/Drawers/ReferenceSelectionDrawer.cs rename to Code/Editor/Drawers/Attributes/ReferenceSelectionDrawer.cs index f57cc909..0e33bd75 100644 --- a/Code/Editor/Drawers/ReferenceSelectionDrawer.cs +++ b/Code/Editor/Drawers/Attributes/ReferenceSelectionDrawer.cs @@ -2,17 +2,24 @@ using UnityEditor; using UnityEngine; using UnityUtility; +using UnityUtility.CSharp; +using UnityUtility.CSharp.Collections; using UnityUtility.Inspector; using UnityUtilityEditor.Engine; using UnityUtilityEditor.Window; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { //Based on https://forum.unity.com/threads/serializereference-genericserializedreferenceinspectorui.813366/ [CustomPropertyDrawer(typeof(ReferenceSelectionAttribute))] internal class ReferenceSelectionDrawer : SerializeReferenceDrawer { protected override void DrawExtendedContent(in Rect position, SerializedProperty property) + { + DrawContent(position, property); + } + + public static void DrawContent(in Rect position, SerializedProperty property, params Type[] rootTypes) { Type assignedType = EditorUtilityExt.GetTypeFromSerializedPropertyTypename(property.managedReferenceFullTypename); bool nullRef = assignedType == null; @@ -22,12 +29,12 @@ protected override void DrawExtendedContent(in Rect position, SerializedProperty GUI.color = Colours.Orange; if (EditorGUI.DropdownButton(position, EditorGuiUtility.TempContent(label), FocusType.Keyboard)) - ShowContextMenu(position, property); + ShowContextMenu(position, property, rootTypes); GUI.color = Colours.White; } - private static void ShowContextMenu(in Rect buttonPosition, SerializedProperty property) + private static void ShowContextMenu(in Rect buttonPosition, SerializedProperty property, params Type[] rootTypes) { Type fieldType = EditorUtilityExt.GetTypeFromSerializedPropertyTypename(property.managedReferenceFieldTypename); @@ -37,35 +44,46 @@ private static void ShowContextMenu(in Rect buttonPosition, SerializedProperty p return; } - Type assignedType = EditorUtilityExt.GetTypeFromSerializedPropertyTypename(property.managedReferenceFullTypename); - var types = TypeCache.GetTypesDerivedFrom(fieldType); - DropDownWindow menu = ScriptableObject.CreateInstance(); + Type assignedType = EditorUtilityExt.GetTypeFromSerializedPropertyTypename(property.managedReferenceFullTypename); menu.AddItem("Null", assignedType == null, () => assignField(property, null)); - addMenuItem(fieldType); - foreach (Type type in types) + if (rootTypes.IsNullOrEmpty()) + { + addMenuItem(fieldType); + + TypeCache.GetTypesDerivedFrom(fieldType) + .ForEach(type => addMenuItem(type)); + } + else { - addMenuItem(type); + foreach (Type rootType in rootTypes) + { + if (!rootType.IsAssignableTo(fieldType)) + { + Debug.LogWarning($"{rootType.Name} is not subclass of {fieldType.Name}"); + continue; + } + + addMenuItem(rootType); + + TypeCache.GetTypesDerivedFrom(rootType) + .ForEach(type => addMenuItem(type)); + } } menu.ShowMenu(buttonPosition); void addMenuItem(Type type) { - if (isValidType(type)) + if (!type.IsAbstract && !type.IsInterface) { string entryName = $"{type.Name} ({type.Namespace})"; menu.AddItem(entryName, type == assignedType, () => assignField(property, Activator.CreateInstance(type))); } } - bool isValidType(Type type) - { - return !type.IsAbstract && !type.IsInterface; - } - void assignField(SerializedProperty prop, object newValue) { prop.serializedObject.Update(); diff --git a/Code/Editor/Drawers/ReferenceSelectionDrawer.cs.meta b/Code/Editor/Drawers/Attributes/ReferenceSelectionDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/ReferenceSelectionDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/ReferenceSelectionDrawer.cs.meta diff --git a/Code/Editor/Drawers/SortingLayerIDDrawer.cs b/Code/Editor/Drawers/Attributes/SortingLayerIDDrawer.cs similarity index 98% rename from Code/Editor/Drawers/SortingLayerIDDrawer.cs rename to Code/Editor/Drawers/Attributes/SortingLayerIDDrawer.cs index 184e6309..a10898c1 100644 --- a/Code/Editor/Drawers/SortingLayerIDDrawer.cs +++ b/Code/Editor/Drawers/Attributes/SortingLayerIDDrawer.cs @@ -6,7 +6,7 @@ using UnityUtility.Mathematics; using UnityUtilityEditor.Engine; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(SortingLayerIDAttribute))] internal class SortingLayerIDDrawer : PropertyDrawer diff --git a/Code/Editor/Drawers/SortingLayerIDDrawer.cs.meta b/Code/Editor/Drawers/Attributes/SortingLayerIDDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/SortingLayerIDDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/SortingLayerIDDrawer.cs.meta diff --git a/Code/Editor/Drawers/TypeNameDrawer.cs b/Code/Editor/Drawers/Attributes/TypeNameDrawer.cs similarity index 98% rename from Code/Editor/Drawers/TypeNameDrawer.cs rename to Code/Editor/Drawers/Attributes/TypeNameDrawer.cs index 1cf98263..60b3be62 100644 --- a/Code/Editor/Drawers/TypeNameDrawer.cs +++ b/Code/Editor/Drawers/Attributes/TypeNameDrawer.cs @@ -7,7 +7,7 @@ using UnityUtilityEditor.Engine; using UnityUtilityEditor.Window; -namespace UnityUtilityEditor.Drawers +namespace UnityUtilityEditor.Drawers.Attributes { [CustomPropertyDrawer(typeof(TypeNameAttribute))] internal class TypeNameDrawer : AttributeDrawer diff --git a/Code/Editor/Drawers/TypeNameDrawer.cs.meta b/Code/Editor/Drawers/Attributes/TypeNameDrawer.cs.meta similarity index 100% rename from Code/Editor/Drawers/TypeNameDrawer.cs.meta rename to Code/Editor/Drawers/Attributes/TypeNameDrawer.cs.meta diff --git a/Code/Editor/Drawers/NodeBased.meta b/Code/Editor/Drawers/NodeBased.meta new file mode 100644 index 00000000..572fc2d7 --- /dev/null +++ b/Code/Editor/Drawers/NodeBased.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6e46fa57346dd9e4495e6760fb79aff3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Editor/Drawers/NodeBased/ConditionDrawer.cs b/Code/Editor/Drawers/NodeBased/ConditionDrawer.cs new file mode 100644 index 00000000..f00431d8 --- /dev/null +++ b/Code/Editor/Drawers/NodeBased/ConditionDrawer.cs @@ -0,0 +1,63 @@ +using System; +using UnityEditor; +using UnityEngine; +using UnityUtility.NodeBased; +using UnityUtility.NodeBased.Service; +using UnityUtilityEditor.Drawers.Attributes; +using UnityUtilityEditor.Engine; + +namespace UnityUtilityEditor.Drawers.NodeBased +{ + [CustomPropertyDrawer(typeof(Condition), true)] + internal class ConditionDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + Rect rect = position; + rect.height = EditorGUIUtility.singleLineHeight; + rect.xMin += 13f; + rect = EditorGUI.PrefixLabel(rect, label); + DrawExtendedContent(rect, property); + + EditorGUI.PropertyField(position, property, GUIContent.none, true); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + if (property.isExpanded) + return EditorGUI.GetPropertyHeight(property, label, true); + + return EditorGUIUtility.singleLineHeight; + } + + private void DrawExtendedContent(in Rect position, SerializedProperty property) + { + if (!property.HasManagedReferenceValue()) + { + DrawContent(position, property); + return; + } + + const float weight = 0.75f; + + Rect rect = position; + rect.width *= weight; + DrawContent(position, property); + + SerializedProperty notProp = property.FindPropertyRelative(Condition.NotFieldName); + + rect.x += rect.width; + rect.width = position.width * (1f - weight); + notProp.boolValue = EditorGui.ToggleButton(rect, "Not", notProp.boolValue); + } + + private void DrawContent(in Rect position, SerializedProperty property) + { + Type conditionType = (property.serializedObject.targetObject as RawGraph).GetConditionRootType(); + if (conditionType == typeof(Condition)) + ReferenceSelectionDrawer.DrawContent(position, property, conditionType); + else + ReferenceSelectionDrawer.DrawContent(position, property, conditionType, typeof(Any), typeof(All)); + } + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/ConditionUtility.cs.meta b/Code/Editor/Drawers/NodeBased/ConditionDrawer.cs.meta similarity index 83% rename from Code/Runtime/UnityUtility/AiSimulation/ConditionUtility.cs.meta rename to Code/Editor/Drawers/NodeBased/ConditionDrawer.cs.meta index 0f2b7f74..f1a19def 100644 --- a/Code/Runtime/UnityUtility/AiSimulation/ConditionUtility.cs.meta +++ b/Code/Editor/Drawers/NodeBased/ConditionDrawer.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4955267ed0fbe5647b83cc065b151046 +guid: be4fe183fe4050e4d98490d6f4e7616c MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Code/Editor/Drawers/RngParamDrawer.cs b/Code/Editor/Drawers/RngParamDrawer.cs index 3f67b667..45e3ce36 100644 --- a/Code/Editor/Drawers/RngParamDrawer.cs +++ b/Code/Editor/Drawers/RngParamDrawer.cs @@ -3,6 +3,7 @@ using UnityUtility.NumericEntities; using UnityUtility.Tools; using UnityUtilityEditor.Engine; +using static UnityUtility.NumericEntities.RngParam; namespace UnityUtilityEditor.Drawers { @@ -24,7 +25,8 @@ public static void Draw(in Rect position, SerializedProperty property, GUIConten string name = label.text; Rect lineRect = EditorGuiUtility.GetLinePosition(position, 0); - property.FindPropertyRelative(RngParam.RangeFieldName).Draw(lineRect, EditorGuiUtility.TempContent(Helper.SPACE)); + property.FindPropertyRelative(RngParam.RangeFieldName) + .Draw(lineRect, EditorGuiUtility.TempContent(Helper.SPACE)); EditorGUI.PrefixLabel(lineRect, EditorGuiUtility.TempContent(name)); property.isExpanded = EditorGUI.Foldout(lineRect, property.isExpanded, GUIContent.none, true); @@ -46,4 +48,34 @@ public static float GetHeight(SerializedProperty property, GUIContent label) return EditorGUIUtility.singleLineHeight; } } + + [CustomPropertyDrawer(typeof(Option))] + internal class RngParamOptionDrawer : PropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + SerializedProperty modeProp = property.FindPropertyRelative(Option.ModeFieldName); + + Rect lineRect = EditorGuiUtility.GetLinePosition(position, 0); + EditorGUI.PropertyField(lineRect, modeProp); + + if (modeProp.enumValueIndex == 0) + return; + + SerializedProperty intProp = property.FindPropertyRelative(Option.IntensityFieldName); + lineRect = EditorGuiUtility.GetLinePosition(position, 1); + EditorGUI.PropertyField(lineRect, intProp); + } + + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + using (SerializedProperty modeProp = property.FindPropertyRelative(Option.ModeFieldName)) + { + if (modeProp.enumValueIndex == 0) + return EditorGUIUtility.singleLineHeight; + } + + return EditorGUIUtility.singleLineHeight * 2f + EditorGUIUtility.standardVerticalSpacing; + } + } } diff --git a/Code/Editor/Drawers/RngParamOptionDrawer.cs b/Code/Editor/Drawers/RngParamOptionDrawer.cs deleted file mode 100644 index fdd3dc93..00000000 --- a/Code/Editor/Drawers/RngParamOptionDrawer.cs +++ /dev/null @@ -1,37 +0,0 @@ -using UnityEditor; -using UnityEngine; -using UnityUtilityEditor.Engine; -using static UnityUtility.NumericEntities.RngParam; - -namespace UnityUtilityEditor.Drawers -{ - [CustomPropertyDrawer(typeof(Option))] - internal class RngParamOptionDrawer : PropertyDrawer - { - public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) - { - SerializedProperty modeProp = property.FindPropertyRelative(Option.ModeFieldName); - - Rect lineRect = EditorGuiUtility.GetLinePosition(position, 0); - EditorGUI.PropertyField(lineRect, modeProp); - - if (modeProp.enumValueIndex == 0) - return; - - SerializedProperty intProp = property.FindPropertyRelative(Option.IntensityFieldName); - lineRect = EditorGuiUtility.GetLinePosition(position, 1); - EditorGUI.PropertyField(lineRect, intProp); - } - - public override float GetPropertyHeight(SerializedProperty property, GUIContent label) - { - using (SerializedProperty modeProp = property.FindPropertyRelative(Option.ModeFieldName)) - { - if (modeProp.enumValueIndex == 0) - return EditorGUIUtility.singleLineHeight; - } - - return EditorGUIUtility.singleLineHeight * 2f + EditorGUIUtility.standardVerticalSpacing; - } - } -} diff --git a/Code/Editor/Engine/EditorGuiUtility.cs b/Code/Editor/Engine/EditorGuiUtility.cs index f1657081..c8ed776a 100644 --- a/Code/Editor/Engine/EditorGuiUtility.cs +++ b/Code/Editor/Engine/EditorGuiUtility.cs @@ -16,6 +16,7 @@ public static class EditorGuiUtility public static float SmallButtonWidth => EditorGUIUtility.singleLineHeight + 2f; public static float StandardHorizontalSpacing => EditorGUIUtility.standardVerticalSpacing + 1f; + public static float IndentLevelOffset => 15f; public static GUIContent TempContent(string label, string tooltip = null) { diff --git a/Code/Editor/Inspectors/AiBehaviorEditor.cs b/Code/Editor/Inspectors/AiBehaviorEditor.cs index d8b17aa0..c52e6491 100644 --- a/Code/Editor/Inspectors/AiBehaviorEditor.cs +++ b/Code/Editor/Inspectors/AiBehaviorEditor.cs @@ -23,16 +23,24 @@ public override void OnInspectorGUI() EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUI.color = Colours.Lime; - EditorGUILayout.LabelField("Current:", GetStateName(target.CurrentState)); + EditorGUILayout.LabelField("Current:", GetCurrentStateInfo()); GUI.color = Colours.White; EditorGUILayout.LabelField(Helper.SPACE, "↑"); - EditorGUILayout.LabelField("Previous:", GetStateName(target.PrevState)); + EditorGUILayout.LabelField("Previous:", GetPrevStateInfo()); EditorGUILayout.EndVertical(); } - private string GetStateName(BehaviorState state) + private string GetCurrentStateInfo() { - return state == null ? NONE_WORD : state.GetType().Name; + if (target.CurrentState == null) + return NONE_WORD; + + return $"{target.CurrentState.GetType().Name} ({target.Status})" ; + } + + private string GetPrevStateInfo() + { + return target.PrevState == null ? NONE_WORD : target.PrevState.GetType().Name; } } } diff --git a/Code/Editor/Inspectors/RenderSorterEditor.cs b/Code/Editor/Inspectors/RenderSorterEditor.cs index fcad1522..91e8316b 100644 --- a/Code/Editor/Inspectors/RenderSorterEditor.cs +++ b/Code/Editor/Inspectors/RenderSorterEditor.cs @@ -2,7 +2,7 @@ using UnityEngine; using UnityUtility; using UnityUtilityEditor.Engine; -using static UnityUtilityEditor.Drawers.SortingLayerIDDrawer; +using static UnityUtilityEditor.Drawers.Attributes.SortingLayerIDDrawer; namespace UnityUtilityEditor.Inspectors { diff --git a/Code/Editor/Window/NodeBased/GraphMap.cs b/Code/Editor/Window/NodeBased/GraphMap.cs index 7c0e9055..74865aa3 100644 --- a/Code/Editor/Window/NodeBased/GraphMap.cs +++ b/Code/Editor/Window/NodeBased/GraphMap.cs @@ -5,6 +5,7 @@ using UnityEditor; using UnityEngine; using UnityUtility; +using UnityUtility.CSharp; using UnityUtility.CSharp.Collections; using UnityUtility.Engine; using UnityUtility.NodeBased; @@ -336,9 +337,17 @@ private void ProcessContextMenu(Vector2 mousePosition) menu.AddSeparator(string.Empty); - addNodeMenuItem(serializedGraph.GraphAsset.GetNodeType()); + Type nodeType = serializedGraph.GraphAsset.GetNodeRootType(); - foreach (Type type in TypeCache.GetTypesDerivedFrom(serializedGraph.GraphAsset.GetNodeType())) + if (!nodeType.IsAssignableTo(serializedGraph.GraphAsset.RootNodeType)) + { + Debug.LogError($"{nodeType} is not assignable to {serializedGraph.GraphAsset.RootNodeType}."); + return; + } + + addNodeMenuItem(nodeType); + + foreach (Type type in TypeCache.GetTypesDerivedFrom(nodeType)) { addNodeMenuItem(type); } diff --git a/Code/Editor/Window/NodeBased/TransitionInfoPopup.cs b/Code/Editor/Window/NodeBased/TransitionInfoPopup.cs index 787a312f..83c7e475 100644 --- a/Code/Editor/Window/NodeBased/TransitionInfoPopup.cs +++ b/Code/Editor/Window/NodeBased/TransitionInfoPopup.cs @@ -1,6 +1,5 @@ using UnityEditor; using UnityEngine; -using UnityUtility.NodeBased; using UnityUtility.NodeBased.Service; using UnityUtilityEditor.Engine; using UnityUtilityEditor.Window.NodeBased.NodeDrawing; @@ -85,7 +84,6 @@ private void OnGUI() GUILayout.FlexibleSpace(); - using (new EditorGUILayout.HorizontalScope()) { GUILayout.FlexibleSpace(); diff --git a/Code/Runtime/UnityUtility/AiSimulation/AiBehavior.cs b/Code/Runtime/UnityUtility/AiSimulation/AiBehavior.cs index 296b1f0e..8deb63b3 100644 --- a/Code/Runtime/UnityUtility/AiSimulation/AiBehavior.cs +++ b/Code/Runtime/UnityUtility/AiSimulation/AiBehavior.cs @@ -1,17 +1,46 @@ using UnityEngine; using UnityUtility.Engine; +using UnityUtility.Inspector; namespace UnityUtility.AiSimulation { + internal interface IStateSet + { + PermanentState PermanentState { get; } + +#if UNITY_EDITOR + StateStatus Status { get; } + object CurrentState { get; } + object PrevState { get; } +#endif + + void SetUp(GameObject gameObject); + void Destroy(); + void Refresh(float deltaTime); + void Play(); + void Stop(); + } + + public enum StateStatus : byte + { + Running, + Complete, + } + [DisallowMultipleComponent] [AddComponentMenu(nameof(UnityUtility) + "/Ai Behavior")] public class AiBehavior : MonoBehaviour { + [SerializeField, CertainTypes(typeof(IStateSet))] + private ScriptableObject _behaviorSet; [SerializeField] - private AiBehaviorSet _behaviorSet; + private bool _playAutomatically = true; private bool _initialized; - private AiBehaviorSet _behaviorSetInstance; + private IStateSet _behaviorSetInstance; + private bool _active; + + public bool Active => _active; public PermanentState PermanentState { @@ -24,20 +53,50 @@ public PermanentState PermanentState #if UNITY_EDITOR internal bool Initialized => _initialized; - internal BehaviorState CurrentState => _behaviorSetInstance.CurrentState; - internal BehaviorState PrevState => _behaviorSetInstance.PrevState; + internal StateStatus Status => _behaviorSetInstance.Status; + internal object CurrentState => _behaviorSetInstance.CurrentState; + internal object PrevState => _behaviorSetInstance.PrevState; #endif + private void Start() + { + if (_playAutomatically) + Play(); + } + private void OnDestroy() { if (_initialized) _behaviorSetInstance.Destroy(); } - private void Update() + private void LateUpdate() { + if (_active) + { + UpdateBehaviorSet(); + _behaviorSetInstance.Refresh(Time.deltaTime); + } + } + + public void Play() + { + if (_active) + return; + + _active = true; UpdateBehaviorSet(); - _behaviorSetInstance.Refresh(Time.deltaTime); + _behaviorSetInstance.Play(); + } + + public void Stop() + { + if (_active) + { + _active = false; + UpdateBehaviorSet(); + _behaviorSetInstance.Stop(); + } } private void UpdateBehaviorSet() @@ -46,7 +105,7 @@ private void UpdateBehaviorSet() return; _initialized = true; - _behaviorSetInstance = _behaviorSet.Install(); + _behaviorSetInstance = (IStateSet)_behaviorSet.Install(); _behaviorSetInstance.SetUp(gameObject); } } diff --git a/Code/Runtime/UnityUtility/AiSimulation/AiBehaviorSet.cs b/Code/Runtime/UnityUtility/AiSimulation/AiBehaviorSet.cs deleted file mode 100644 index 12e10906..00000000 --- a/Code/Runtime/UnityUtility/AiSimulation/AiBehaviorSet.cs +++ /dev/null @@ -1,81 +0,0 @@ -using UnityEngine; -using UnityUtility.CSharp; -using UnityUtility.Inspector; - -namespace UnityUtility.AiSimulation -{ - [CreateAssetMenu(menuName = nameof(UnityUtility) + "/Ai/Behavior Set")] - internal class AiBehaviorSet : ScriptableObject - { - [SerializeReference, ReferenceSelection] - private PermanentState _permanentState; - - [Space] - [SerializeReference, ReferenceSelection] - private BehaviorState[] _states; - - private BehaviorState _currentState; -#if UNITY_EDITOR - private BehaviorState _prevState; -#endif - - public PermanentState PermanentState => _permanentState; - -#if UNITY_EDITOR - public BehaviorState CurrentState => _currentState; - public BehaviorState PrevState => _prevState; -#endif - - public void SetUp(GameObject gameObject) - { - _permanentState?.SetUp(gameObject); - - if (_states.Length == 0) - return; - - for (int i = 0; i < _states.Length; i++) - { - _states[i].SetUp(_permanentState, gameObject); - } - - _currentState = _states.FromEnd(0); - _currentState.OnBegin(); - } - - private void OnDestroy() - { - _permanentState?.OnDestroy(); - _currentState?.OnEnd(); - - for (int i = 0; i < _states.Length; i++) - { - _states[i].OnDestroy(); - } - } - - public void Refresh(float deltaTime) - { - _permanentState?.Refresh(deltaTime); - - for (int i = 0; i < _states.Length; i++) - { - if (_states[i].Available()) - { - if (_states[i] != _currentState) - { -#if UNITY_EDITOR - _prevState = _currentState; -#endif - _currentState.OnEnd(); - _currentState = _states[i]; - _currentState.OnBegin(); - } - - break; - } - } - - _currentState?.Refresh(deltaTime); - } - } -} diff --git a/Code/Runtime/UnityUtility/AiSimulation/Common.cs b/Code/Runtime/UnityUtility/AiSimulation/Common.cs deleted file mode 100644 index cb94d72f..00000000 --- a/Code/Runtime/UnityUtility/AiSimulation/Common.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using UnityEngine; - -namespace UnityUtility.AiSimulation -{ - [Serializable] - internal class Common : StateCondition - { - [SerializeField] - private CommonCondition _common; - - protected override bool Satisfied(PermanentState permanentState) - { - return _common.Satisfied(permanentState); - } - } -} diff --git a/Code/Runtime/UnityUtility/AiSimulation/CommonCondition.cs b/Code/Runtime/UnityUtility/AiSimulation/CommonCondition.cs deleted file mode 100644 index 8351dea6..00000000 --- a/Code/Runtime/UnityUtility/AiSimulation/CommonCondition.cs +++ /dev/null @@ -1,16 +0,0 @@ -using UnityEngine; - -namespace UnityUtility.AiSimulation -{ - [CreateAssetMenu(menuName = nameof(UnityUtility) + "/Ai/Common Condition")] - internal class CommonCondition : ScriptableObject - { - [SerializeReference] - private StateCondition[] _conditions; - - public bool Satisfied(PermanentState permanentState) - { - return ConditionUtility.All(_conditions, permanentState); - } - } -} diff --git a/Code/Runtime/UnityUtility/AiSimulation/StateFinalizer.cs b/Code/Runtime/UnityUtility/AiSimulation/CompleteHandler.cs similarity index 74% rename from Code/Runtime/UnityUtility/AiSimulation/StateFinalizer.cs rename to Code/Runtime/UnityUtility/AiSimulation/CompleteHandler.cs index 25a01b68..d27405c0 100644 --- a/Code/Runtime/UnityUtility/AiSimulation/StateFinalizer.cs +++ b/Code/Runtime/UnityUtility/AiSimulation/CompleteHandler.cs @@ -3,12 +3,12 @@ namespace UnityUtility.AiSimulation { [Serializable] - public abstract class StateFinalizer + public abstract class CompleteHandler { public abstract void OnComlete(PermanentState permanentState); } - public abstract class StateFinalizer : StateFinalizer where T : PermanentState + public abstract class CompleteHandler : CompleteHandler where T : PermanentState { public sealed override void OnComlete(PermanentState permanentState) { diff --git a/Code/Runtime/UnityUtility/AiSimulation/StateFinalizer.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/CompleteHandler.cs.meta similarity index 100% rename from Code/Runtime/UnityUtility/AiSimulation/StateFinalizer.cs.meta rename to Code/Runtime/UnityUtility/AiSimulation/CompleteHandler.cs.meta diff --git a/Code/Runtime/UnityUtility/AiSimulation/ConditionUtility.cs b/Code/Runtime/UnityUtility/AiSimulation/ConditionUtility.cs deleted file mode 100644 index 1353d553..00000000 --- a/Code/Runtime/UnityUtility/AiSimulation/ConditionUtility.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace UnityUtility.AiSimulation -{ - internal static class ConditionUtility - { - public static bool All(StateCondition[] conditions, PermanentState permanentState) - { - for (int i = 0; i < conditions.Length; i++) - { - if (!conditions[i].Check(permanentState)) - return false; - } - - return true; - } - - public static bool Any(StateCondition[] conditions, PermanentState permanentState) - { - for (int i = 0; i < conditions.Length; i++) - { - if (conditions[i].Check(permanentState)) - return true; - } - - return false; - } - } -} diff --git a/Code/Runtime/UnityUtility/AiSimulation/NodeBased.meta b/Code/Runtime/UnityUtility/AiSimulation/NodeBased.meta new file mode 100644 index 00000000..c8a7b2f8 --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/NodeBased.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b08eb75c04d89534eb9bc0ebce2e890c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/AiSimulation/NodeBased/AiStateGraph.cs b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/AiStateGraph.cs new file mode 100644 index 00000000..6a8104c2 --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/AiStateGraph.cs @@ -0,0 +1,127 @@ +using System; +using UnityEngine; +using UnityUtility.Inspector; +using UnityUtility.NodeBased; + +namespace UnityUtility.AiSimulation.NodeBased +{ + [CreateAssetMenu(menuName = nameof(UnityUtility) + "/Ai/State Graph")] + public class AiStateGraph : Graph, IStateSet + { + [SerializeReference, ReferenceSelection] + private PermanentState _permanentState; + + private StateStatus _status; + private BehaviorState _currentState; + +#if UNITY_EDITOR + private BehaviorState _prevState; +#endif + + public PermanentState PermanentState => _permanentState; + +#if UNITY_EDITOR + StateStatus IStateSet.Status => _status; + object IStateSet.CurrentState => _currentState; + object IStateSet.PrevState => _prevState; +#endif + + private void OnDestroy() + { + _permanentState?.OnDestroy(); + _currentState?.OnEnd(); + + for (int i = 0; i < Nodes.Count; i++) + { + Nodes[i].OnDestroy(); + } + } + + public override Type GetConditionRootType() + { + return typeof(StateCondition); + } + + public virtual Type GetCompleteHandlerRootType() + { + return typeof(CompleteHandler); + } + + void IStateSet.SetUp(GameObject gameObject) + { + _permanentState?.SetUp(gameObject); + + for (int i = 0; i < Nodes.Count; i++) + { + Nodes[i].SetUp(_permanentState, gameObject); + } + } + + void IStateSet.Refresh(float deltaTime) + { + _permanentState?.Refresh(deltaTime); + + if (_currentState == null) + return; + + if (_currentState.Interruptible || _status == StateStatus.Complete) + { + if (!UpdateState(_currentState)) + UpdateState(EnumerateFromAny()); + } + + if (_status == StateStatus.Running) + { + _status = _currentState.Refresh(deltaTime); + + if (_status == StateStatus.Complete) + { + for (int i = 0; i < _currentState.CompleteHandlers.Length; i++) + { + _currentState.CompleteHandlers[i].OnComlete(_permanentState); + } + } + } + } + + void IStateSet.Play() + { + if (Nodes.Count > 0) + { + _currentState = RootNode; + _currentState.OnBegin(); + } + } + + void IStateSet.Stop() + { + _currentState?.OnEnd(); + } + + void IStateSet.Destroy() + { + Destroy(this); + } + + private bool UpdateState(IEnumerableNode next) + { + foreach (TransitionInfo item in next) + { + if (item.Available(_permanentState)) + { +#if UNITY_EDITOR + _prevState = _currentState; +#endif + _currentState.OnEnd(); + _currentState = item.NextNode; + _status = StateStatus.Running; + _currentState.OnBegin(); + + return true; + } + } + + return false; + } + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/NodeBased/AiStateGraph.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/AiStateGraph.cs.meta new file mode 100644 index 00000000..2fd59340 --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/AiStateGraph.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 31f356cb485d94d4c95b079c7a9d2faa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/AiSimulation/NodeBased/BehaviorState.cs b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/BehaviorState.cs new file mode 100644 index 00000000..c1e90c58 --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/BehaviorState.cs @@ -0,0 +1,53 @@ +using System; +using UnityEngine; +using UnityUtility.NodeBased; + +namespace UnityUtility.AiSimulation.NodeBased +{ + [Serializable] + public abstract class BehaviorState : Node + { + [SerializeField] + private bool _interruptible = true; + [SerializeReference] + private CompleteHandler[] _onComlete; + + private GameObject _gameObject; + private Transform _transform; + private PermanentState _permanentState; + +#pragma warning disable IDE1006 + protected GameObject gameObject => _gameObject; + protected Transform transform => _transform; +#pragma warning restore IDE1006 + + protected PermanentState PermanentState => _permanentState; + internal CompleteHandler[] CompleteHandlers => _onComlete; + public bool Interruptible => _interruptible; + + internal void SetUp(PermanentState permanentState, GameObject gameObject) + { + _gameObject = gameObject; + _transform = gameObject.transform; + _permanentState = permanentState; + OnSetUp(); + } + + protected virtual void OnSetUp() { } + public virtual void OnDestroy() { } + public virtual void OnBegin() { } + public virtual void OnEnd() { } + public abstract StateStatus Refresh(float deltaTime); + + protected T GetComponent() + { + return _permanentState.GetComponent(); + } + } + + [Serializable] + public abstract class BehaviorState : BehaviorState where T : PermanentState + { + protected new T PermanentState => (T)base.PermanentState; + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/NodeBased/BehaviorState.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/BehaviorState.cs.meta new file mode 100644 index 00000000..10cd0ded --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/BehaviorState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89f0ca29271023c4eabb6cc5a87358b1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/AiSimulation/NodeBased/StateCondition.cs b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/StateCondition.cs new file mode 100644 index 00000000..7a609b0c --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/StateCondition.cs @@ -0,0 +1,30 @@ +using System; +using UnityUtility.NodeBased; +using UnityUtility.NodeBased.Service; + +namespace UnityUtility.AiSimulation.NodeBased +{ + [Serializable] + public abstract class StateCondition : Condition + { + protected sealed override bool Satisfied(RawNode _, object data) + { + return Satisfied((PermanentState)data); + } + + protected abstract bool Satisfied(PermanentState permanentState); + } + + + [Serializable] + public abstract class StateCondition : StateCondition + where TPermanent : PermanentState + { + protected sealed override bool Satisfied(PermanentState permanentState) + { + return Satisfied((TPermanent)permanentState); + } + + protected abstract bool Satisfied(TPermanent permanentState); + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/NodeBased/StateCondition.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/StateCondition.cs.meta new file mode 100644 index 00000000..4b87b9c3 --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/NodeBased/StateCondition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64a3efb650989064c9c920b427db7af2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/AiSimulation/Selection.cs b/Code/Runtime/UnityUtility/AiSimulation/Selection.cs deleted file mode 100644 index 535e0d3b..00000000 --- a/Code/Runtime/UnityUtility/AiSimulation/Selection.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using UnityEngine; - -namespace UnityUtility.AiSimulation -{ - [Serializable] - internal class Selection : StateCondition - { - [SerializeReference] - private StateCondition[] _conditions; - - protected override bool Satisfied(PermanentState permanentState) - { - return ConditionUtility.Any(_conditions, permanentState); - } - } -} diff --git a/Code/Runtime/UnityUtility/AiSimulation/Selection.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/Selection.cs.meta deleted file mode 100644 index bf9bcef9..00000000 --- a/Code/Runtime/UnityUtility/AiSimulation/Selection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fed4fef085a09d54eb09629985e09219 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/AiSimulation/Simple.meta b/Code/Runtime/UnityUtility/AiSimulation/Simple.meta new file mode 100644 index 00000000..204d1079 --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/Simple.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a108dd129522b9340a1e2c5f88544a0f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/AiSimulation/Simple/AiStateSet.cs b/Code/Runtime/UnityUtility/AiSimulation/Simple/AiStateSet.cs new file mode 100644 index 00000000..3cdc295b --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/Simple/AiStateSet.cs @@ -0,0 +1,131 @@ +using System; +using UnityEngine; +using UnityUtility.CSharp; +using UnityUtility.Inspector; + +namespace UnityUtility.AiSimulation.Simple +{ + [CreateAssetMenu(menuName = nameof(UnityUtility) + "/Ai/State Set")] + public class AiStateSet : ScriptableObject, IStateSet + { + [SerializeReference, ReferenceSelection] + private PermanentState _permanentState; + + [Space] + [SerializeReference] + private BehaviorState[] _states; + + private StateStatus _status; + private BehaviorState _currentState; + +#if UNITY_EDITOR + private BehaviorState _prevState; +#endif + + public PermanentState PermanentState => _permanentState; + +#if UNITY_EDITOR + StateStatus IStateSet.Status => _status; + object IStateSet.CurrentState => _currentState; + object IStateSet.PrevState => _prevState; +#endif + + private void OnDestroy() + { + _permanentState?.OnDestroy(); + _currentState?.OnEnd(); + + for (int i = 0; i < _states.Length; i++) + { + _states[i].OnDestroy(); + } + } + + public virtual Type GetStateRootType() + { + return typeof(BehaviorState); + } + + public virtual Type GetConditionRootType() + { + return typeof(StateCondition); + } + + public virtual Type GetCompleteHandlerRootType() + { + return typeof(CompleteHandler); + } + + void IStateSet.SetUp(GameObject gameObject) + { + _permanentState?.SetUp(gameObject); + + for (int i = 0; i < _states.Length; i++) + { + _states[i].SetUp(_permanentState, gameObject); + } + } + + void IStateSet.Refresh(float deltaTime) + { + _permanentState?.Refresh(deltaTime); + + if (_currentState == null) + return; + + if (_currentState.Interruptible || _status == StateStatus.Complete) + { + for (int i = 0; i < _states.Length; i++) + { + if (_states[i].Available()) + { + if (_states[i] != _currentState) + { +#if UNITY_EDITOR + _prevState = _currentState; +#endif + _currentState.OnEnd(); + _currentState = _states[i]; + _status = StateStatus.Running; + _currentState.OnBegin(); + } + + break; + } + } + } + + if (_status == StateStatus.Running) + { + _status = _currentState.Refresh(deltaTime); + + if (_status == StateStatus.Complete) + { + for (int i = 0; i < _currentState.CompleteHandlers.Length; i++) + { + _currentState.CompleteHandlers[i].OnComlete(_permanentState); + } + } + } + } + + void IStateSet.Play() + { + if (_states.Length > 0) + { + _currentState = _states.FromEnd(0); + _currentState.OnBegin(); + } + } + + void IStateSet.Stop() + { + _currentState?.OnEnd(); + } + + void IStateSet.Destroy() + { + Destroy(this); + } + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/AiBehaviorSet.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/Simple/AiStateSet.cs.meta similarity index 100% rename from Code/Runtime/UnityUtility/AiSimulation/AiBehaviorSet.cs.meta rename to Code/Runtime/UnityUtility/AiSimulation/Simple/AiStateSet.cs.meta diff --git a/Code/Runtime/UnityUtility/AiSimulation/BehaviorState.cs b/Code/Runtime/UnityUtility/AiSimulation/Simple/BehaviorState.cs similarity index 59% rename from Code/Runtime/UnityUtility/AiSimulation/BehaviorState.cs rename to Code/Runtime/UnityUtility/AiSimulation/Simple/BehaviorState.cs index cc83cc05..f94fc0d7 100644 --- a/Code/Runtime/UnityUtility/AiSimulation/BehaviorState.cs +++ b/Code/Runtime/UnityUtility/AiSimulation/Simple/BehaviorState.cs @@ -1,16 +1,17 @@ using System; using UnityEngine; -using UnityUtility.Inspector; -namespace UnityUtility.AiSimulation +namespace UnityUtility.AiSimulation.Simple { [Serializable] public abstract class BehaviorState { + [SerializeField] + private bool _interruptible = true; [SerializeReference] private StateCondition[] _conditions; - [SerializeReference, ReferenceSelection] - private StateFinalizer[] _finalizers; + [SerializeReference] + private CompleteHandler[] _onComlete; private GameObject _gameObject; private Transform _transform; @@ -22,6 +23,8 @@ public abstract class BehaviorState #pragma warning restore IDE1006 protected PermanentState PermanentState => _permanentState; + internal CompleteHandler[] CompleteHandlers => _onComlete; + public bool Interruptible => _interruptible; internal void SetUp(PermanentState permanentState, GameObject gameObject) { @@ -33,38 +36,24 @@ internal void SetUp(PermanentState permanentState, GameObject gameObject) public bool Available() { - return ConditionUtility.All(_conditions, _permanentState); + return StateCondition.All(_conditions, _permanentState); } protected virtual void OnSetUp() { } public virtual void OnDestroy() { } public virtual void OnBegin() { } public virtual void OnEnd() { } - - internal void Refresh(float deltaTime) - { - if (OnRefresh(deltaTime) == Status.Complete) - { - OnComplete(); - for (int i = 0; i < _finalizers.Length; i++) - { - _finalizers[i].OnComlete(PermanentState); - } - } - } - - protected abstract Status OnRefresh(float deltaTime); - protected virtual void OnComplete() { } + public abstract StateStatus Refresh(float deltaTime); protected T GetComponent() { return _permanentState.GetComponent(); } + } - protected enum Status : byte - { - Running, - Complete, - } + [Serializable] + public abstract class BehaviorState : BehaviorState where T : PermanentState + { + protected new T PermanentState => (T)base.PermanentState; } } diff --git a/Code/Runtime/UnityUtility/AiSimulation/BehaviorState.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/Simple/BehaviorState.cs.meta similarity index 100% rename from Code/Runtime/UnityUtility/AiSimulation/BehaviorState.cs.meta rename to Code/Runtime/UnityUtility/AiSimulation/Simple/BehaviorState.cs.meta diff --git a/Code/Runtime/UnityUtility/AiSimulation/Simple/Conditions.cs b/Code/Runtime/UnityUtility/AiSimulation/Simple/Conditions.cs new file mode 100644 index 00000000..b5449e08 --- /dev/null +++ b/Code/Runtime/UnityUtility/AiSimulation/Simple/Conditions.cs @@ -0,0 +1,80 @@ +using System; +using UnityEngine; + +namespace UnityUtility.AiSimulation.Simple +{ + [Serializable] + public abstract class StateCondition + { + [SerializeField, HideInInspector] + private bool _not; + +#if UNITY_EDITOR + internal static string NotFieldName => nameof(_not); +#endif + + internal bool Check(PermanentState permanentState) + { + return Satisfied(permanentState) != _not; + } + + protected abstract bool Satisfied(PermanentState permanentState); + + internal static bool All(StateCondition[] conditions, PermanentState permanentState) + { + for (int i = 0; i < conditions.Length; i++) + { + if (!conditions[i].Check(permanentState)) + return false; + } + + return true; + } + + internal static bool Any(StateCondition[] conditions, PermanentState permanentState) + { + for (int i = 0; i < conditions.Length; i++) + { + if (conditions[i].Check(permanentState)) + return true; + } + + return false; + } + } + + [Serializable] + public abstract class StateCondition : StateCondition where T : PermanentState + { + protected sealed override bool Satisfied(PermanentState permanentState) + { + return Satisfied((T)permanentState); + } + + protected abstract bool Satisfied(T permanentState); + } + + [Serializable] + internal class Any : StateCondition + { + [SerializeReference] + private StateCondition[] _conditions; + + protected override bool Satisfied(PermanentState permanentState) + { + return Any(_conditions, permanentState); + } + } + + [Serializable] + internal class All : StateCondition + { + [SerializeReference] + private StateCondition[] _conditions; + + protected override bool Satisfied(PermanentState permanentState) + { + return All(_conditions, permanentState); + } + } +} diff --git a/Code/Runtime/UnityUtility/AiSimulation/StateCondition.cs.meta b/Code/Runtime/UnityUtility/AiSimulation/Simple/Conditions.cs.meta similarity index 100% rename from Code/Runtime/UnityUtility/AiSimulation/StateCondition.cs.meta rename to Code/Runtime/UnityUtility/AiSimulation/Simple/Conditions.cs.meta diff --git a/Code/Runtime/UnityUtility/AiSimulation/StateCondition.cs b/Code/Runtime/UnityUtility/AiSimulation/StateCondition.cs deleted file mode 100644 index f3a27760..00000000 --- a/Code/Runtime/UnityUtility/AiSimulation/StateCondition.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using UnityEngine; - -namespace UnityUtility.AiSimulation -{ - [Serializable] - public abstract class StateCondition - { - [SerializeField, HideInInspector] - private bool _not; - -#if UNITY_EDITOR - internal static string NotFieldName => nameof(_not); -#endif - - internal bool Check(PermanentState permanentState) - { - return Satisfied(permanentState) != _not; - } - - protected abstract bool Satisfied(PermanentState permanentState); - } - - [Serializable] - public abstract class StateCondition : StateCondition where T : PermanentState - { - protected sealed override bool Satisfied(PermanentState permanentState) - { - return Satisfied((T)permanentState); - } - - protected abstract bool Satisfied(T permanentState); - } -} diff --git a/Code/Runtime/UnityUtility/CSharp/Collections/CollectionExtensions.cs b/Code/Runtime/UnityUtility/CSharp/Collections/CollectionExtensions.cs index 7062e483..83b56a70 100644 --- a/Code/Runtime/UnityUtility/CSharp/Collections/CollectionExtensions.cs +++ b/Code/Runtime/UnityUtility/CSharp/Collections/CollectionExtensions.cs @@ -493,24 +493,6 @@ public static T Push(this IList self, int index, T newItem) return newItem; } - /// - /// Inserts an element into the list at the specified index. Expands the list if the index is out of bounds. - /// - public static void ForceInsert(this IList self, int index, T newItem) - { - while (index > self.Count) { self.Add(default); } - self.Insert(index, newItem); - } - - /// - /// Inserts an element into the list at the specified index and returns that element. Expands the list if the index is out of bounds. - /// - public static T ForcePush(this IList self, int index, T newItem) - { - self.ForceInsert(index, newItem); - return newItem; - } - /// /// Adds an element to the dictionary and returns that element. /// diff --git a/Code/Runtime/UnityUtility/Collections/StateMachine.cs b/Code/Runtime/UnityUtility/Collections/StateMachine.cs index 742559c0..433b7a07 100644 --- a/Code/Runtime/UnityUtility/Collections/StateMachine.cs +++ b/Code/Runtime/UnityUtility/Collections/StateMachine.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using UnityUtility.NodeBased.Service; namespace UnityUtility.Collections { @@ -26,10 +25,10 @@ public class StateMachine where TState : class, IState public StateMachine() { } - public StateMachine(RawGraph graph) - { - graph.InitializeMachine(this); - } + //public StateMachine(RawGraph graph) + //{ + // graph.InitializeMachine(this); + //} public void Start() { diff --git a/Code/Runtime/UnityUtility/Engine/UnityObjectExtensions.cs b/Code/Runtime/UnityUtility/Engine/UnityObjectExtensions.cs index 45bb073e..56655fdf 100644 --- a/Code/Runtime/UnityUtility/Engine/UnityObjectExtensions.cs +++ b/Code/Runtime/UnityUtility/Engine/UnityObjectExtensions.cs @@ -1,13 +1,10 @@ -using System.Runtime.CompilerServices; -using UnityEngine; +using UnityEngine; using UnityObject = UnityEngine.Object; namespace UnityUtility.Engine { public static class UnityObjectExtensions { - private static ConditionalWeakTable _meshRendererData; - /// /// Destroys the unity object. /// @@ -67,20 +64,19 @@ public static Mesh GetSharedMesh(this MeshRenderer self) return GetMeshFilter(self)?.sharedMesh; } - private static MeshFilter GetMeshFilter(MeshRenderer renderer) + public static void SetMesh(this MeshRenderer self, Mesh mesh) { - if (_meshRendererData == null) - _meshRendererData = new ConditionalWeakTable(); - - if (!_meshRendererData.TryGetValue(renderer, out MeshFilter filter)) - { - if (!renderer.TryGetComponent(out filter)) - return null; + self.GetOrAddComponent().mesh = mesh; + } - _meshRendererData.Add(renderer, filter); - } + public static void SetSharedMesh(this MeshRenderer self, Mesh mesh) + { + self.GetOrAddComponent().sharedMesh = mesh; + } - return filter; + private static MeshFilter GetMeshFilter(MeshRenderer renderer) + { + return renderer.TryGetComponent(out MeshFilter filter) ? filter : null; } /// diff --git a/Code/Runtime/UnityUtility/Inspector/CertainTypesAttribute.cs b/Code/Runtime/UnityUtility/Inspector/CertainTypesAttribute.cs new file mode 100644 index 00000000..803f3ef8 --- /dev/null +++ b/Code/Runtime/UnityUtility/Inspector/CertainTypesAttribute.cs @@ -0,0 +1,16 @@ +using System; +using UnityEngine; + +namespace UnityUtility.Inspector +{ + [AttributeUsage(AttributeTargets.Field)] + public sealed class CertainTypesAttribute : PropertyAttribute + { + internal Type[] Types; + + public CertainTypesAttribute(params Type[] types) + { + Types = types; + } + } +} diff --git a/Code/Runtime/UnityUtility/Inspector/CertainTypesAttribute.cs.meta b/Code/Runtime/UnityUtility/Inspector/CertainTypesAttribute.cs.meta new file mode 100644 index 00000000..9e9a4120 --- /dev/null +++ b/Code/Runtime/UnityUtility/Inspector/CertainTypesAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 512e1660a8018d64f8c4bce222156314 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/Inspector/ClampDiapasonAttribute.cs b/Code/Runtime/UnityUtility/Inspector/ClampDiapasonAttribute.cs index 287a711e..33bcddde 100644 --- a/Code/Runtime/UnityUtility/Inspector/ClampDiapasonAttribute.cs +++ b/Code/Runtime/UnityUtility/Inspector/ClampDiapasonAttribute.cs @@ -5,7 +5,7 @@ namespace UnityUtility.Inspector { [AttributeUsage(AttributeTargets.Field)] - public class ClampDiapasonAttribute : PropertyAttribute + public sealed class ClampDiapasonAttribute : PropertyAttribute { internal float Min { get; } internal float Max { get; } diff --git a/Code/Runtime/UnityUtility/Inspector/FolderRequiredAttribute.cs b/Code/Runtime/UnityUtility/Inspector/FolderRequiredAttribute.cs index a5a43bbb..0c614c8b 100644 --- a/Code/Runtime/UnityUtility/Inspector/FolderRequiredAttribute.cs +++ b/Code/Runtime/UnityUtility/Inspector/FolderRequiredAttribute.cs @@ -4,5 +4,5 @@ namespace UnityUtility.Inspector { [AttributeUsage(AttributeTargets.Field)] - public class FolderRequiredAttribute : PropertyAttribute { } + public sealed class FolderRequiredAttribute : PropertyAttribute { } } diff --git a/Code/Runtime/UnityUtility/Inspector/InitListAttribute.cs b/Code/Runtime/UnityUtility/Inspector/InitListAttribute.cs index 341356cc..ec2e272e 100644 --- a/Code/Runtime/UnityUtility/Inspector/InitListAttribute.cs +++ b/Code/Runtime/UnityUtility/Inspector/InitListAttribute.cs @@ -4,7 +4,7 @@ namespace UnityUtility.Inspector { [AttributeUsage(AttributeTargets.Field)] - public class InitListAttribute : PropertyAttribute + public sealed class InitListAttribute : PropertyAttribute { internal readonly Type EnumType; @@ -15,7 +15,7 @@ public InitListAttribute(Type enumType) } [AttributeUsage(AttributeTargets.Field)] - public class BindSubclassAttribute : Attribute + public sealed class BindSubclassAttribute : Attribute { internal Type ClassType { get; } diff --git a/Code/Runtime/UnityUtility/NodeBased/Condition.cs b/Code/Runtime/UnityUtility/NodeBased/Condition.cs new file mode 100644 index 00000000..29e7a82d --- /dev/null +++ b/Code/Runtime/UnityUtility/NodeBased/Condition.cs @@ -0,0 +1,60 @@ +using System; +using UnityEngine; +using UnityUtility.NodeBased.Service; + +namespace UnityUtility.NodeBased +{ + [Serializable] + public abstract class Condition + { + [SerializeField, HideInInspector] + private bool _not; + +#if UNITY_EDITOR + internal static string NotFieldName => nameof(_not); +#endif + + internal bool Check(RawNode from, object data) + { + return Satisfied(from, data) != _not; + } + + protected abstract bool Satisfied(RawNode from, object data); + } + + [Serializable] + internal class Any : Condition + { + [SerializeReference] + private Condition[] _conditions; + + protected override bool Satisfied(RawNode from, object data) + { + for (int i = 0; i < _conditions.Length; i++) + { + if (_conditions[i].Check(from, data)) + return true; + } + + return false; + } + } + + [Serializable] + internal class All : Condition + { + [SerializeReference] + private Condition[] _conditions; + + protected override bool Satisfied(RawNode from, object data) + { + for (int i = 0; i < _conditions.Length; i++) + { + if (!_conditions[i].Check(from, data)) + return false; + } + + return true; + } + } +} diff --git a/Code/Runtime/UnityUtility/NodeBased/Condition.cs.meta b/Code/Runtime/UnityUtility/NodeBased/Condition.cs.meta new file mode 100644 index 00000000..85fe8ce3 --- /dev/null +++ b/Code/Runtime/UnityUtility/NodeBased/Condition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b99d8ea0259d19d4691cac9c813676ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/NodeBased/Graph.cs b/Code/Runtime/UnityUtility/NodeBased/Graph.cs index f1b36c6f..2d6b7452 100644 --- a/Code/Runtime/UnityUtility/NodeBased/Graph.cs +++ b/Code/Runtime/UnityUtility/NodeBased/Graph.cs @@ -1,31 +1,29 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; -using UnityUtility.Collections; -using UnityUtility.CSharp.Collections; using UnityUtility.NodeBased.Service; namespace UnityUtility.NodeBased { public abstract class Graph : RawGraph where TNode : Node { - private ReadOnlyCollection _nodeList; - private CommonNodeWrapper _commonNodeWrapper; + private TNode[] _nodeList; + private NodeWrapper _commonNodeWrapper; public new TNode RootNode => (TNode)base.RootNode; + internal sealed override Type RootNodeType => typeof(TNode); - public ReadOnlyCollection Nodes + public IReadOnlyList Nodes { get { if (_nodeList == null) { - TNode[] nodes = Dict.Values.Where(item => item.RealNode()) - .Select(item => (TNode)item) - .ToArray(); - _nodeList = new ReadOnlyCollection(nodes); + _nodeList = Dict.Values + .Where(item => item.RealNode()) + .Select(item => (TNode)item) + .ToArray(); } return _nodeList; @@ -39,76 +37,77 @@ public ReadOnlyCollection Nodes public IEnumerableNode EnumerateFromAny() { - return _commonNodeWrapper ?? (_commonNodeWrapper = new CommonNodeWrapper(CommonNode)); + return _commonNodeWrapper ?? (_commonNodeWrapper = new NodeWrapper(CommonNode)); } - internal override void InitializeMachine(StateMachine stateMachine) - { - Dictionary states = new Dictionary(Dict.Count); + //internal override void InitializeMachine(StateMachine stateMachine) + //{ + // Dictionary states = new Dictionary(Dict.Count); - RawNode rootNode = RootNode; + // RawNode rootNode = RootNode; - foreach (RawNode node in Dict.Values) - { - if (node is HubNode) - continue; + // foreach (RawNode node in Dict.Values) + // { + // if (node is HubNode) + // continue; - TState state = states.Place(node, node.CreateState()); + // TState state = states.Place(node, node.CreateState()); - if (state != null) - stateMachine.AddState(state, node == rootNode); - } + // if (state != null) + // stateMachine.AddState(state, node == rootNode); + // } - foreach (RawNode node in Dict.Values) - { - if (node.ServiceNode()) - continue; + // foreach (RawNode node in Dict.Values) + // { + // if (node.ServiceNode()) + // continue; - foreach (Transition transition in node as TNode) - { - addTransition(node, transition); - } + // foreach (TransitionInfo transition in node as TNode) + // { + // addTransition(node, transition); + // } - foreach (Transition transition in EnumerateFromAny()) - { - addTransition(node, transition); - } - } + // foreach (TransitionInfo transition in EnumerateFromAny()) + // { + // addTransition(node, transition); + // } + // } - void addTransition(RawNode node, in Transition transition) - { - stateMachine.AddTransition(states[node], - transition.CreateCondition(), - states[transition.NextNode]); - } - } + // void addTransition(RawNode node, in TransitionInfo transition) + // { + // stateMachine.AddTransition(states[node], + // transition.Condition.CreateCondition(), + // states[transition.NextNode]); + // } + //} -#if UNITY_EDITOR - internal sealed override Type GetNodeType() => typeof(TNode); -#endif + public override Type GetNodeRootType() + { + return typeof(TNode); + } - private class CommonNodeWrapper : IEnumerableNode + private class NodeWrapper : IEnumerableNode { - private RawNode _commonNode; + private RawNode _rawNode; - public CommonNodeWrapper(RawNode commonNode) + public NodeWrapper(RawNode rawNode) { - _commonNode = commonNode; + _rawNode = rawNode; } public NodeEnumerator GetEnumerator() { - return new NodeEnumerator(_commonNode); + return new NodeEnumerator(_rawNode); } - IEnumerator> IEnumerable>.GetEnumerator() + IEnumerator> IEnumerable>.GetEnumerator() { - return new NodeEnumerator(_commonNode); + return new NodeEnumerator(_rawNode); } IEnumerator IEnumerable.GetEnumerator() { - return new NodeEnumerator(_commonNode); + return new NodeEnumerator(_rawNode); } } } diff --git a/Code/Runtime/UnityUtility/NodeBased/IEnumerableNode.cs b/Code/Runtime/UnityUtility/NodeBased/IEnumerableNode.cs index b789d4a1..fcec7381 100644 --- a/Code/Runtime/UnityUtility/NodeBased/IEnumerableNode.cs +++ b/Code/Runtime/UnityUtility/NodeBased/IEnumerableNode.cs @@ -1,8 +1,9 @@ using System.Collections.Generic; +using UnityUtility.NodeBased.Service; namespace UnityUtility.NodeBased { - public interface IEnumerableNode : IEnumerable> where TNode : Node + public interface IEnumerableNode : IEnumerable> where TNode : Node { new NodeEnumerator GetEnumerator(); } diff --git a/Code/Runtime/UnityUtility/NodeBased/Node.cs b/Code/Runtime/UnityUtility/NodeBased/Node.cs index 1b83e095..6a54904e 100644 --- a/Code/Runtime/UnityUtility/NodeBased/Node.cs +++ b/Code/Runtime/UnityUtility/NodeBased/Node.cs @@ -9,6 +9,7 @@ namespace UnityUtility.NodeBased public abstract class Node : RawNode, IEnumerableNode where TNode : Node { public Graph Graph => Owner as Graph; + public bool IsRoot => Owner.RootNode == this; public NodeEnumerator GetEnumerator() { @@ -20,7 +21,7 @@ IEnumerator IEnumerable.GetEnumerator() return new NodeEnumerator(this as TNode); } - IEnumerator> IEnumerable>.GetEnumerator() + IEnumerator> IEnumerable>.GetEnumerator() { return new NodeEnumerator(this as TNode); } diff --git a/Code/Runtime/UnityUtility/NodeBased/NodeEnumerator.cs b/Code/Runtime/UnityUtility/NodeBased/Service/NodeEnumerator.cs similarity index 79% rename from Code/Runtime/UnityUtility/NodeBased/NodeEnumerator.cs rename to Code/Runtime/UnityUtility/NodeBased/Service/NodeEnumerator.cs index 667d2384..a11fa480 100644 --- a/Code/Runtime/UnityUtility/NodeBased/NodeEnumerator.cs +++ b/Code/Runtime/UnityUtility/NodeBased/Service/NodeEnumerator.cs @@ -1,31 +1,32 @@ using System.Collections; using System.Collections.Generic; -using UnityUtility.NodeBased.Service; -namespace UnityUtility.NodeBased +namespace UnityUtility.NodeBased.Service { - public struct NodeEnumerator : IEnumerator> where TNode : Node + public struct NodeEnumerator : IEnumerator> where TNode : Node { private RawNode _node; private HubNode _hub; private int _index; private int _subIndex; - public Transition Current + public TransitionInfo Current { get { if (_node == null) return default; - int index = (_hub != null ? _subIndex : _index) - 1; - Transition[] array = (_hub ?? _node).Next; + bool isHub = _hub != null; + Transition[] array = (isHub ? _hub : _node).Next; + int index = (isHub ? _subIndex : _index) - 1; if ((uint)index >= (uint)array.Length) return default; - RawNode nextNode = _node.Owner.Dict[array[index].NextNodeId]; - return new Transition(array[index].Condition, _node, nextNode); + Transition transition = array[index]; + RawNode nextNode = _node.Owner.Dict[transition.NextNodeId]; + return new TransitionInfo(transition.Condition, _node, nextNode); } } diff --git a/Code/Runtime/UnityUtility/NodeBased/NodeEnumerator.cs.meta b/Code/Runtime/UnityUtility/NodeBased/Service/NodeEnumerator.cs.meta similarity index 100% rename from Code/Runtime/UnityUtility/NodeBased/NodeEnumerator.cs.meta rename to Code/Runtime/UnityUtility/NodeBased/Service/NodeEnumerator.cs.meta diff --git a/Code/Runtime/UnityUtility/NodeBased/Service/RawGraph.cs b/Code/Runtime/UnityUtility/NodeBased/Service/RawGraph.cs index dca05872..69a2bb52 100644 --- a/Code/Runtime/UnityUtility/NodeBased/Service/RawGraph.cs +++ b/Code/Runtime/UnityUtility/NodeBased/Service/RawGraph.cs @@ -1,8 +1,7 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using UnityEngine; -using UnityUtility.Collections; namespace UnityUtility.NodeBased.Service { @@ -23,6 +22,7 @@ public abstract class RawGraph : ScriptableObject internal RawNode RootNode => GetNodeById(_rootNodeId); internal RawNode CommonNode => _commonNode; + internal abstract Type RootNodeType { get; } internal Dictionary Dict => _dict ?? (_dict = _nodes.ToDictionary(key => key.Id, value => value)); @@ -34,10 +34,16 @@ internal RawNode GetNodeById(int id) return null; } - internal abstract void InitializeMachine(StateMachine stateMachine) where TState : class, IState; + //internal abstract void InitializeMachine(StateMachine stateMachine) where TState : class, IState; + + public virtual Type GetConditionRootType() + { + return typeof(Condition); + } + + public abstract Type GetNodeRootType(); #if UNITY_EDITOR - internal abstract Type GetNodeType(); internal static string IdGeneratorFieldName => nameof(LastId); internal static string WidthFieldName => nameof(_nodeWidth); internal static string NodesFieldName => nameof(_nodes); diff --git a/Code/Runtime/UnityUtility/NodeBased/Service/RawNode.cs b/Code/Runtime/UnityUtility/NodeBased/Service/RawNode.cs index fe13db52..b82da694 100644 --- a/Code/Runtime/UnityUtility/NodeBased/Service/RawNode.cs +++ b/Code/Runtime/UnityUtility/NodeBased/Service/RawNode.cs @@ -1,6 +1,5 @@ -using System; +using System; using UnityEngine; -using UnityUtility.Collections; namespace UnityUtility.NodeBased.Service { @@ -30,11 +29,6 @@ public abstract class RawNode public string Name => NodeName; internal virtual NodeType NodeType => NodeType.Real; - public virtual TState CreateState() where TState : class, IState - { - throw new NotImplementedException(); - } - #if UNITY_EDITOR internal static string PositionFieldName => nameof(Position); internal static string IdFieldName => nameof(Id); diff --git a/Code/Runtime/UnityUtility/NodeBased/Service/Transition.cs b/Code/Runtime/UnityUtility/NodeBased/Service/Transition.cs new file mode 100644 index 00000000..6db3a727 --- /dev/null +++ b/Code/Runtime/UnityUtility/NodeBased/Service/Transition.cs @@ -0,0 +1,27 @@ +using System; +using UnityEngine; +using UnityUtility.Inspector; + +namespace UnityUtility.NodeBased.Service +{ + [Serializable] + internal struct Transition + { + [SerializeField] + private int _nextNodeId; + [SerializeReference] + private Condition _condition; + + public int NextNodeId => _nextNodeId; + public Condition Condition => _condition; + +#if UNITY_EDITOR + [SerializeField] + private Vector2[] _points; + + internal static string NodeIdFieldName => nameof(_nextNodeId); + internal static string ConditionFieldName => nameof(_condition); + internal static string PointsFieldName => nameof(_points); +#endif + } +} diff --git a/Code/Runtime/UnityUtility/NodeBased/Transition.cs.meta b/Code/Runtime/UnityUtility/NodeBased/Service/Transition.cs.meta similarity index 83% rename from Code/Runtime/UnityUtility/NodeBased/Transition.cs.meta rename to Code/Runtime/UnityUtility/NodeBased/Service/Transition.cs.meta index b6b9b8c8..9b748f7a 100644 --- a/Code/Runtime/UnityUtility/NodeBased/Transition.cs.meta +++ b/Code/Runtime/UnityUtility/NodeBased/Service/Transition.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 52e5b520f41a2034eb35e7d66f2c1463 +guid: 8b0ab45d93f7080478ac255882c5821a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Code/Runtime/UnityUtility/NodeBased/ServiceNodes.cs b/Code/Runtime/UnityUtility/NodeBased/ServiceNodes.cs index 9edd00c5..24f15914 100644 --- a/Code/Runtime/UnityUtility/NodeBased/ServiceNodes.cs +++ b/Code/Runtime/UnityUtility/NodeBased/ServiceNodes.cs @@ -14,10 +14,10 @@ internal sealed class ExitNode : RawNode { internal override NodeType NodeType => NodeType.Exit; - public override TState CreateState() - { - return null; - } + //public override TState CreateState() + //{ + // return null; + //} } [Serializable] diff --git a/Code/Runtime/UnityUtility/NodeBased/Transition.cs b/Code/Runtime/UnityUtility/NodeBased/Transition.cs deleted file mode 100644 index 38a1085d..00000000 --- a/Code/Runtime/UnityUtility/NodeBased/Transition.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using UnityEngine; -using UnityUtility.Collections; -using UnityUtility.Inspector; -using UnityUtility.NodeBased.Service; - -namespace UnityUtility.NodeBased -{ - [Serializable] - internal struct Transition - { - [SerializeField] - private int _nextNodeId; - [SerializeReference, ReferenceSelection] - private Condition _condition; - - public int NextNodeId => _nextNodeId; - public Condition Condition => _condition; - -#if UNITY_EDITOR - [SerializeField] - private Vector2[] _points; - - internal static string NodeIdFieldName => nameof(_nextNodeId); - internal static string ConditionFieldName => nameof(_condition); - internal static string PointsFieldName => nameof(_points); -#endif - } - - public struct Transition where TNode : Node - { - private Condition _condition; - private RawNode _owner; - private RawNode _nextNode; - - public TNode NextNode => _nextNode as TNode; - public bool IsExit => _nextNode is ExitNode; - - internal Transition(Condition condition, RawNode from, RawNode to) - { - _condition = condition; - _owner = from; - _nextNode = to; - } - - public bool Available(object data = null) - { - return _condition == null || _condition.Satisfied(_owner, data); - } - - public Func CreateCondition() where TState : class, IState - { - return _condition.CreateCondition(); - } - } - - [Serializable] - public abstract class Condition - { - public abstract bool Satisfied(RawNode from, object data); - - public virtual Func CreateCondition() where TState : class, IState - { - throw new NotImplementedException(); - } - } -} diff --git a/Code/Runtime/UnityUtility/NodeBased/TransitionInfo.cs b/Code/Runtime/UnityUtility/NodeBased/TransitionInfo.cs new file mode 100644 index 00000000..fbb51129 --- /dev/null +++ b/Code/Runtime/UnityUtility/NodeBased/TransitionInfo.cs @@ -0,0 +1,27 @@ +using UnityUtility.NodeBased.Service; + +namespace UnityUtility.NodeBased +{ + public struct TransitionInfo where TNode : Node + { + private Condition _condition; + private RawNode _from; + private RawNode _to; + + internal Condition Condition => _condition; + public TNode NextNode => _to as TNode; + public bool IsExit => _to is ExitNode; + + internal TransitionInfo(Condition condition, RawNode from, RawNode to) + { + _condition = condition; + _from = from; + _to = to; + } + + public bool Available(object data = null) + { + return _condition == null || _condition.Check(_from, data); + } + } +} diff --git a/Code/Runtime/UnityUtility/NodeBased/TransitionInfo.cs.meta b/Code/Runtime/UnityUtility/NodeBased/TransitionInfo.cs.meta new file mode 100644 index 00000000..6fdd0a90 --- /dev/null +++ b/Code/Runtime/UnityUtility/NodeBased/TransitionInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 753ace5284256114a89b57dfceed88fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Code/Runtime/UnityUtility/Pool/ObjectPool.cs b/Code/Runtime/UnityUtility/Pool/ObjectPool.cs index f224b32f..8566d2f6 100644 --- a/Code/Runtime/UnityUtility/Pool/ObjectPool.cs +++ b/Code/Runtime/UnityUtility/Pool/ObjectPool.cs @@ -26,25 +26,19 @@ public ObjectPool(IPoolStorage storage, IObjectFactory factory) _factory = factory; } - public ObjectPool(IPoolStorage storage, IObjectFactory factory, int preCount) : this(storage, factory) - { - for (int i = 0; i < preCount; i++) - { - Release(factory.Create()); - } - } - public ObjectPool(IPoolStorage storage, Func creator) : this(storage, new DefaultFactory(creator)) { } public ObjectPool(IObjectFactory factory) : this(new QueueStorage(16), factory) { } public ObjectPool(Func creator) : this(new DefaultFactory(creator)) { } - public ObjectPool(IPoolStorage storage, Func creator, int preCount) : this(storage, new DefaultFactory(creator), preCount) { } - - public ObjectPool(IObjectFactory factory, int preCount) : this(new QueueStorage(preCount * 2), factory, preCount) { } - - public ObjectPool(Func creator, int preCount) : this(new DefaultFactory(creator), preCount) { } + public void Fill(int count) + { + for (int i = 0; i < count; i++) + { + Release(_factory.Create()); + } + } /// /// Returns an existing element or creates a new one if pool is empty. diff --git a/package.json b/package.json index c1fd1def..1c66178b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "name": "Oleg Pulkin", "email": "oleghcp@gmail.com" }, - "version": "1.2.10", + "version": "1.3.0", "unity": "2019.4", "description": "A set of helpful code stuff for Unity.", "keywords": [ "Unity", "Utility" ],