├── .GenericUnityInternals ├── GenericUnityEditorInternals │ ├── EditorGUIHelper.cs │ ├── EditorGUILayoutHelper.cs │ ├── GenericMonoImporterInspector.cs │ ├── GenericTypeHelper.cs │ ├── GenericUnityEditorInternals.csproj │ ├── GenericUnityEventDrawer.cs │ ├── ObjectFieldHelper.cs │ ├── ObjectSelectorExtensions.cs │ ├── ObjectSelectorHelper.cs │ └── Properties │ │ └── AssemblyInfo.cs ├── GenericUnityInternals.sln ├── OdinInternals │ ├── GenericUnityEventDrawer`1.cs │ ├── OdinInternals.csproj │ └── Properties │ │ └── AssemblyInfo.cs └── README.txt ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .images ├── add-component.gif ├── asset-creation.gif ├── creatable-scriptable-object.gif ├── generic-header.png ├── object-field.png └── project-settings.png ├── .releaserc.json ├── CHANGELOG.md ├── CHANGELOG.md.meta ├── Editor.meta ├── Editor ├── AssemblyCreator.meta ├── AssemblyCreator │ ├── AssemblyCreator.cs │ ├── AssemblyCreator.cs.meta │ ├── AssemblyCreatorHelper.cs │ ├── AssemblyCreatorHelper.cs.meta │ ├── BehaviourSelectorCreator.cs │ ├── BehaviourSelectorCreator.cs.meta │ ├── ConcreteClassCreator.cs │ ├── ConcreteClassCreator.cs.meta │ ├── MenuItemsCreator.cs │ └── MenuItemsCreator.cs.meta ├── AssemblyInfo.cs ├── AssemblyInfo.cs.meta ├── Drawers.meta ├── Drawers │ ├── BehaviourSelectorEditor.cs │ ├── BehaviourSelectorEditor.cs.meta │ ├── CreatableObjectDrawer.cs │ ├── CreatableObjectDrawer.cs.meta │ ├── GenericHeaderUtility.cs │ ├── GenericHeaderUtility.cs.meta │ ├── GenericObjectDrawer.cs │ ├── GenericObjectDrawer.cs.meta │ ├── GenericUnityObjectDrawer.cs │ ├── GenericUnityObjectDrawer.cs.meta │ ├── GenericUnityObjectHelper.cs │ ├── GenericUnityObjectHelper.cs.meta │ ├── ScriptableObjectEditor.cs │ ├── ScriptableObjectEditor.cs.meta │ ├── SingletonScriptableObjectEditor.cs │ ├── SingletonScriptableObjectEditor.cs.meta │ ├── TypeReferenceWithBaseTypesDrawer.cs │ ├── TypeReferenceWithBaseTypesDrawer.cs.meta │ ├── UnityObjectEditor.cs │ └── UnityObjectEditor.cs.meta ├── GenerationDatabase.meta ├── GenerationDatabase │ ├── BehavioursGenerationDatabase.Serialization.cs │ ├── BehavioursGenerationDatabase.Serialization.cs.meta │ ├── BehavioursGenerationDatabase.cs │ ├── BehavioursGenerationDatabase.cs.meta │ ├── ConcreteClass.cs │ ├── ConcreteClass.cs.meta │ ├── GenerationDatabase.Serialization.cs │ ├── GenerationDatabase.Serialization.cs.meta │ ├── GenerationDatabase.cs │ ├── GenerationDatabase.cs.meta │ ├── Pool.cs │ ├── Pool.cs.meta │ ├── SOGenerationDatabase.cs │ ├── SOGenerationDatabase.cs.meta │ ├── TypeInfo.meta │ └── TypeInfo │ │ ├── ArgumentInfo.cs │ │ ├── ArgumentInfo.cs.meta │ │ ├── BehaviourInfo.cs │ │ ├── BehaviourInfo.cs.meta │ │ ├── GenericTypeInfo.cs │ │ ├── GenericTypeInfo.cs.meta │ │ ├── TypeInfo.cs │ │ └── TypeInfo.cs.meta ├── GenericTypesAnalyzer.meta ├── GenericTypesAnalyzer │ ├── ArgumentsChecker.cs │ ├── ArgumentsChecker.cs.meta │ ├── AssemblyAssetOperations.cs │ ├── AssemblyAssetOperations.cs.meta │ ├── BehavioursChecker.cs │ ├── BehavioursChecker.cs.meta │ ├── ConcreteClassChecker.cs │ ├── ConcreteClassChecker.cs.meta │ ├── DictInitializer.cs │ ├── DictInitializer.cs.meta │ ├── FailedAssembliesChecker.cs │ ├── FailedAssembliesChecker.cs.meta │ ├── GenericTypesAnalyzer.cs │ ├── GenericTypesAnalyzer.cs.meta │ ├── GenericTypesChecker.cs │ ├── GenericTypesChecker.cs.meta │ ├── MenuItemsChecker.cs │ ├── MenuItemsChecker.cs.meta │ ├── ScriptableObjectsChecker.cs │ └── ScriptableObjectsChecker.cs.meta ├── GenericUnityObjects.Editor.asmdef ├── GenericUnityObjects.Editor.asmdef.meta ├── MissingScriptTypeDisabler.cs ├── MissingScriptTypeDisabler.cs.meta ├── MonoBehaviours.meta ├── MonoBehaviours │ ├── GenericBehaviourCreator.cs │ └── GenericBehaviourCreator.cs.meta ├── OnScriptsReloadActionsRunner.cs ├── OnScriptsReloadActionsRunner.cs.meta ├── PackageUpgrader.cs ├── PackageUpgrader.cs.meta ├── ScriptableObjects.meta ├── ScriptableObjects │ ├── GenericSOCreator.cs │ ├── GenericSOCreator.cs.meta │ ├── SelectionWindow.meta │ ├── SelectionWindow │ │ ├── ITypeSelectionWindow.cs │ │ ├── ITypeSelectionWindow.cs.meta │ │ ├── MultipleTypeSelectionWindow.cs │ │ ├── MultipleTypeSelectionWindow.cs.meta │ │ ├── OneTypeSelectionWindow.cs │ │ └── OneTypeSelectionWindow.cs.meta │ ├── TypeSelectionWindow.cs │ └── TypeSelectionWindow.cs.meta ├── Settings.meta ├── Settings │ ├── ProjectSettings.cs │ ├── ProjectSettings.cs.meta │ ├── ProjectSettingsDrawer.cs │ └── ProjectSettingsDrawer.cs.meta ├── Util.meta └── Util │ ├── Collection`1.cs │ ├── Collection`1.cs.meta │ ├── CompilationChecker.cs │ ├── CompilationChecker.cs.meta │ ├── CompilationHelper.cs │ ├── CompilationHelper.cs.meta │ ├── ConcreteClassCreator.cs │ ├── ConcreteClassCreator.cs.meta │ ├── EditorCoroutineHelper.cs │ ├── EditorCoroutineHelper.cs.meta │ ├── EditorOnlySingletonSO.cs │ ├── EditorOnlySingletonSO.cs.meta │ ├── ExampleInstaller.cs │ ├── ExampleInstaller.cs.meta │ ├── IconFinder.cs │ ├── IconFinder.cs.meta │ ├── IconSetter.cs │ ├── IconSetter.cs.meta │ ├── MenuItemMethod.cs │ ├── MenuItemMethod.cs.meta │ ├── NonGenericAttribute.cs │ ├── NonGenericAttribute.cs.meta │ ├── PersistentStorage.cs │ └── PersistentStorage.cs.meta ├── GenericUnityEditorInternals.dll ├── GenericUnityEditorInternals.dll.meta ├── GenericUnityEditorInternals.pdb ├── GenericUnityEditorInternals.pdb.meta ├── LICENSE ├── LICENSE.meta ├── OdinInternals.dll ├── OdinInternals.dll.meta ├── OdinInternals.pdb ├── OdinInternals.pdb.meta ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── ApplyToChildrenAttribute.cs ├── ApplyToChildrenAttribute.cs.meta ├── AssemblyInfo.cs ├── AssemblyInfo.cs.meta ├── CreatableAttribute.cs ├── CreatableAttribute.cs.meta ├── CreateGenericAssetMenuAttribute.cs ├── CreateGenericAssetMenuAttribute.cs.meta ├── GameObjectExtensions.cs ├── GameObjectExtensions.cs.meta ├── GenericScriptableObject.cs ├── GenericScriptableObject.cs.meta ├── GenericUnityObjects.asmdef ├── GenericUnityObjects.asmdef.meta ├── Util.meta └── Util │ ├── BehaviourSelector.cs │ ├── BehaviourSelector.cs.meta │ ├── Config.cs │ ├── Config.cs.meta │ ├── DebugUtility.cs │ ├── DebugUtility.cs.meta │ ├── GeneratedUnityObjectCache.cs │ ├── GeneratedUnityObjectCache.cs.meta │ ├── GenericTypesDatabase.meta │ ├── GenericTypesDatabase │ ├── BehavioursDatabase.cs │ ├── BehavioursDatabase.cs.meta │ ├── GenericTypesDatabase.cs │ ├── GenericTypesDatabase.cs.meta │ ├── ScriptableObjectsDatabase.cs │ ├── ScriptableObjectsDatabase.cs.meta │ ├── SerializableType.cs │ ├── SerializableType.cs.meta │ ├── SerializableTypeCollection.cs │ ├── SerializableTypeCollection.cs.meta │ ├── SerializableTypeDictionary.cs │ ├── SerializableTypeDictionary.cs.meta │ ├── TypeArrayComparer.cs │ └── TypeArrayComparer.cs.meta │ ├── InstanceGetter.cs │ ├── InstanceGetter.cs.meta │ ├── SingletonScriptableObject.cs │ ├── SingletonScriptableObject.cs.meta │ ├── TypeReferenceCollectionExtensions.cs │ ├── TypeReferenceCollectionExtensions.cs.meta │ ├── TypeReferenceWithBaseTypes.cs │ ├── TypeReferenceWithBaseTypes.cs.meta │ ├── TypeUtility.cs │ └── TypeUtility.cs.meta ├── Samples~ ├── MonoBehaviour Example.meta ├── MonoBehaviour Example │ ├── MonoBehaviour Demo.unity │ ├── MonoBehaviour Demo.unity.meta │ ├── Scripts.meta │ └── Scripts │ │ ├── Archer.cs │ │ ├── Archer.cs.meta │ │ ├── Editor.meta │ │ ├── Editor │ │ ├── Installer.cs │ │ └── Installer.cs.meta │ │ ├── Knight.cs │ │ ├── Knight.cs.meta │ │ ├── Unit`1.cs │ │ ├── Unit`1.cs.meta │ │ ├── Warrior.cs │ │ └── Warrior.cs.meta ├── ScriptableObject Example.meta └── ScriptableObject Example │ ├── Classes.meta │ ├── Classes │ ├── Archer.cs │ ├── Archer.cs.meta │ ├── Berserker.cs │ ├── Berserker.cs.meta │ ├── Knight.cs │ ├── Knight.cs.meta │ ├── WarriorClass.cs │ └── WarriorClass.cs.meta │ ├── GenericScriptableObjects.meta │ ├── GenericScriptableObjects │ ├── WarriorStats`1.cs │ ├── WarriorStats`1.cs.meta │ ├── WarriorsRelationship`2.cs │ └── WarriorsRelationship`2.cs.meta │ ├── README.asset │ ├── README.asset.meta │ ├── Relationships.meta │ ├── Relationships │ ├── Arnet - Geltull.asset │ ├── Arnet - Geltull.asset.meta │ ├── Edun - Fulchard.asset │ ├── Edun - Fulchard.asset.meta │ ├── Geltull - Fulchard.asset │ └── Geltull - Fulchard.asset.meta │ ├── Util.meta │ ├── Util │ ├── Editor.meta │ ├── Editor │ │ ├── Installer.cs │ │ └── Installer.cs.meta │ ├── Readme.cs │ └── Readme.cs.meta │ ├── Warrior Stats.meta │ ├── Warrior Stats │ ├── Default Berserker Stats.asset │ ├── Default Berserker Stats.asset.meta │ ├── Default Knight Stats.asset │ ├── Default Knight Stats.asset.meta │ ├── Heavy Archer.asset │ ├── Heavy Archer.asset.meta │ ├── Light Archer.asset │ └── Light Archer.asset.meta │ ├── Warriors.meta │ └── Warriors │ ├── Arnet.asset │ ├── Arnet.asset.meta │ ├── Edun.asset │ ├── Edun.asset.meta │ ├── Fulchard.asset │ ├── Fulchard.asset.meta │ ├── Geltull.asset │ └── Geltull.asset.meta ├── Tests.meta ├── Tests ├── Editor.meta ├── Editor │ ├── BehaviourInfoTests.cs │ ├── BehaviourInfoTests.cs.meta │ ├── GenerationDatabaseTests.meta │ ├── GenerationDatabaseTests │ │ ├── AddConcreteClass.cs │ │ ├── AddConcreteClass.cs.meta │ │ ├── AddGenericType.cs │ │ ├── AddGenericType.cs.meta │ │ ├── GenerationDatabaseTests.cs │ │ ├── GenerationDatabaseTests.cs.meta │ │ ├── GetConcreteClasses.cs │ │ ├── GetConcreteClasses.cs.meta │ │ ├── GetConcreteClassesByArgument.cs │ │ ├── GetConcreteClassesByArgument.cs.meta │ │ ├── GetReferencedGenericTypes.cs │ │ ├── GetReferencedGenericTypes.cs.meta │ │ ├── OnAfterDeserialize.cs │ │ ├── OnAfterDeserialize.cs.meta │ │ ├── RemoveArgument.cs │ │ ├── RemoveArgument.cs.meta │ │ ├── RemoveGenericType.cs │ │ ├── RemoveGenericType.cs.meta │ │ ├── TypeStub.cs │ │ ├── TypeStub.cs.meta │ │ ├── UpdateArgumentGUID.cs │ │ ├── UpdateArgumentGUID.cs.meta │ │ ├── UpdateArgumentNameAndAssembly.cs │ │ ├── UpdateArgumentNameAndAssembly.cs.meta │ │ ├── UpdateGenericType.cs │ │ ├── UpdateGenericType.cs.meta │ │ ├── UpdateGenericTypeArgs.cs │ │ ├── UpdateGenericTypeArgs.cs.meta │ │ ├── UpdateGenericTypeGUID.cs │ │ └── UpdateGenericTypeGUID.cs.meta │ ├── GenericUnityObjects.EditorTests.asmdef │ ├── GenericUnityObjects.EditorTests.asmdef.meta │ ├── TypeInfoTests.cs │ └── TypeInfoTests.cs.meta ├── Integration.meta └── Integration │ ├── GenericBehaviour_ConcreteClass.cs │ ├── GenericBehaviour_ConcreteClass.cs.meta │ ├── GenericBehaviour_GenericArguments.cs │ ├── GenericBehaviour_GenericArguments.cs.meta │ ├── GenericBehaviour_Selector.cs │ ├── GenericBehaviour_Selector.cs.meta │ ├── GenericScriptableObject_ConcreteClass.cs │ ├── GenericScriptableObject_ConcreteClass.cs.meta │ ├── GenericScriptableObject_GenericArguments.cs │ ├── GenericScriptableObject_GenericArguments.cs.meta │ ├── GenericUnityObjects.IntegrationTests.asmdef │ ├── GenericUnityObjects.IntegrationTests.asmdef.meta │ ├── MenuItems.cs │ ├── MenuItems.cs.meta │ ├── TestHelper.cs │ └── TestHelper.cs.meta ├── package.json └── package.json.meta /.GenericUnityInternals/GenericUnityEditorInternals/EditorGUILayoutHelper.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.UnityEditorInternals 2 | { 3 | using System; 4 | using UnityEditor; 5 | using UnityEngine; 6 | using Object = UnityEngine.Object; 7 | 8 | public static class EditorGUILayoutHelper 9 | { 10 | /// 11 | /// Version of that accepts only a generic type and draws it correctly. 12 | /// 13 | public static Object GenericObjectField(string label, Object oldTarget, Type objType, bool allowSceneObjects) 14 | { 15 | EditorGUILayout.s_LastRect = EditorGUILayout.GetControlRect( 16 | true, 17 | EditorGUI.kSingleLineHeight, 18 | (GUILayoutOption[]) null); 19 | 20 | return EditorGUIHelper.GenericObjectField( 21 | EditorGUILayout.s_LastRect, 22 | EditorGUIUtility.TempContent(label), 23 | oldTarget, 24 | objType, 25 | allowSceneObjects); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /.GenericUnityInternals/GenericUnityEditorInternals/GenericTypeHelper.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.UnityEditorInternals 2 | { 3 | using System; 4 | using UnityEditor; 5 | using UnityEngine; 6 | using Util; 7 | 8 | /// 9 | /// A class that accumulates methods that allow working with a generic type. 10 | /// 11 | internal static class GenericTypeHelper 12 | { 13 | public static Type GetGenericType(SerializedProperty property) 14 | { 15 | ScriptAttributeUtility.GetFieldInfoFromProperty(property, out Type genericType); 16 | return genericType; 17 | } 18 | 19 | public static string GetNiceTypeName(ObjectFieldHelper fieldHelper) 20 | { 21 | Type type = fieldHelper.CurrentTarget is null 22 | ? fieldHelper.ObjType 23 | : fieldHelper.CurrentTarget.GetType().BaseType; 24 | 25 | return TypeUtility.GetNiceNameOfGenericType(type); 26 | } 27 | 28 | public static Type GetConcreteType(Type genericType) 29 | { 30 | if (typeof(MonoBehaviour).IsAssignableFrom(genericType)) 31 | { 32 | return GenericTypesDatabase.TryGetConcreteType(genericType, out Type concreteType) 33 | ? concreteType 34 | : genericType; 35 | } 36 | 37 | if (typeof(ScriptableObject).IsAssignableFrom(genericType)) 38 | { 39 | return GenericTypesDatabase.TryGetConcreteType(genericType, out Type concreteType) 40 | ? concreteType 41 | : genericType; 42 | } 43 | 44 | throw new ArgumentException( 45 | $"Expected a type derived from MonoBehaviour or ScriptableObject. Got {genericType} instead."); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /.GenericUnityInternals/GenericUnityEditorInternals/ObjectSelectorHelper.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.UnityEditorInternals 2 | { 3 | using System; 4 | using UnityEditor; 5 | using Object = UnityEngine.Object; 6 | 7 | public static class ObjectSelectorHelper 8 | { 9 | public static void ShowGenericSelector(Object obj, Object objectBeingEdited, Type requiredType, bool allowSceneObjects, string niceTypeName, Action onObjectSelectedUpdated = null) 10 | { 11 | ObjectSelector.get.ShowGeneric(obj, objectBeingEdited, requiredType, allowSceneObjects, niceTypeName, onObjectSelectedUpdated); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /.GenericUnityInternals/GenericUnityEditorInternals/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("GenericUnityEditorInternals")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("GenericUnityEditorInternals")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("9C80D148-E76D-44E7-87A1-7A59579519E8")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /.GenericUnityInternals/GenericUnityInternals.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenericUnityEditorInternals", "GenericUnityEditorInternals\GenericUnityEditorInternals.csproj", "{9C80D148-E76D-44E7-87A1-7A59579519E8}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OdinInternals", "OdinInternals\OdinInternals.csproj", "{B02F9AC3-C24A-4578-B743-FD8E9287EBD1}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {9C80D148-E76D-44E7-87A1-7A59579519E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {9C80D148-E76D-44E7-87A1-7A59579519E8}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {9C80D148-E76D-44E7-87A1-7A59579519E8}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {9C80D148-E76D-44E7-87A1-7A59579519E8}.Release|Any CPU.Build.0 = Release|Any CPU 17 | {B02F9AC3-C24A-4578-B743-FD8E9287EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 18 | {B02F9AC3-C24A-4578-B743-FD8E9287EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU 19 | {B02F9AC3-C24A-4578-B743-FD8E9287EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU 20 | {B02F9AC3-C24A-4578-B743-FD8E9287EBD1}.Release|Any CPU.Build.0 = Release|Any CPU 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /.GenericUnityInternals/OdinInternals/GenericUnityEventDrawer`1.cs: -------------------------------------------------------------------------------- 1 | namespace OdinInternals 2 | { 3 | // Note that both split and non-split DLLs are held as dependencies. 4 | // Odin dependencies are messed up, and it needs both DLL versions to build this project successfully. 5 | using System.Reflection; 6 | using GenericUnityObjects.UnityEditorInternals; 7 | using JetBrains.Annotations; 8 | using Sirenix.OdinInspector.Editor; 9 | using UnityEngine; 10 | using UnityEngine.Events; 11 | 12 | // A copy of UnityEventDrawer from Odin that creates a GenericUnityEventDrawer instance instead of UnityEventDrawer. 13 | // Unlike UnityEventDrawer it passes 1 as the super parameter which makes it override any other UnityEvent drawer. 14 | [DrawerPriority(1.0, 0.0, 0.45)] 15 | [UsedImplicitly] 16 | public sealed class GenericUnityEventDrawer : UnityPropertyDrawer 17 | where T : UnityEventBase 18 | { 19 | protected override void Initialize() 20 | { 21 | base.Initialize(); 22 | delayApplyValueUntilRepaint = true; 23 | drawer = new GenericUnityEventDrawer(); 24 | 25 | if (UnityPropertyHandlerUtility.IsAvailable) 26 | propertyHandler = UnityPropertyHandlerUtility.CreatePropertyHandler(drawer); 27 | } 28 | 29 | protected override void DrawPropertyLayout(GUIContent label) 30 | { 31 | if (Property.Tree.GetUnityPropertyForPath(Property.Path, out FieldInfo _) == null) 32 | { 33 | CallNextDrawer(label); 34 | return; 35 | } 36 | 37 | base.DrawPropertyLayout(label); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /.GenericUnityInternals/OdinInternals/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("OdinInternals")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("OdinInternals")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("B02F9AC3-C24A-4578-B743-FD8E9287EBD1")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /.GenericUnityInternals/README.txt: -------------------------------------------------------------------------------- 1 | Projects in this solution contain calls to Unity internal methods. They are highlighted as errors but upon building the project, those errors will be ignored. 2 | After building a project, the DLL file will be copied over to the parent folder of GenericUnityInternals~, so you will be able to use the updated DLL in Unity after building it. 3 | Projects a built with help of OpenSesame. Check it out https://github.com/mob-sakai/OpenSesame -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # 3D models 2 | *.3dm filter=lfs diff=lfs merge=lfs -text 3 | *.3ds filter=lfs diff=lfs merge=lfs -text 4 | *.blend filter=lfs diff=lfs merge=lfs -text 5 | *.c4d filter=lfs diff=lfs merge=lfs -text 6 | *.collada filter=lfs diff=lfs merge=lfs -text 7 | *.dae filter=lfs diff=lfs merge=lfs -text 8 | *.dxf filter=lfs diff=lfs merge=lfs -text 9 | *.fbx filter=lfs diff=lfs merge=lfs -text 10 | *.jas filter=lfs diff=lfs merge=lfs -text 11 | *.lws filter=lfs diff=lfs merge=lfs -text 12 | *.lxo filter=lfs diff=lfs merge=lfs -text 13 | *.ma filter=lfs diff=lfs merge=lfs -text 14 | *.max filter=lfs diff=lfs merge=lfs -text 15 | *.mb filter=lfs diff=lfs merge=lfs -text 16 | *.obj filter=lfs diff=lfs merge=lfs -text 17 | *.ply filter=lfs diff=lfs merge=lfs -text 18 | *.skp filter=lfs diff=lfs merge=lfs -text 19 | *.stl filter=lfs diff=lfs merge=lfs -text 20 | *.ztl filter=lfs diff=lfs merge=lfs -text 21 | # Audio 22 | *.aif filter=lfs diff=lfs merge=lfs -text 23 | *.aiff filter=lfs diff=lfs merge=lfs -text 24 | *.it filter=lfs diff=lfs merge=lfs -text 25 | *.mod filter=lfs diff=lfs merge=lfs -text 26 | *.mp3 filter=lfs diff=lfs merge=lfs -text 27 | *.ogg filter=lfs diff=lfs merge=lfs -text 28 | *.s3m filter=lfs diff=lfs merge=lfs -text 29 | *.wav filter=lfs diff=lfs merge=lfs -text 30 | *.xm filter=lfs diff=lfs merge=lfs -text 31 | # Fonts 32 | *.otf filter=lfs diff=lfs merge=lfs -text 33 | *.ttf filter=lfs diff=lfs merge=lfs -text 34 | # Images 35 | *.bmp filter=lfs diff=lfs merge=lfs -text 36 | *.exr filter=lfs diff=lfs merge=lfs -text 37 | *.gif filter=lfs diff=lfs merge=lfs -text 38 | *.hdr filter=lfs diff=lfs merge=lfs -text 39 | *.iff filter=lfs diff=lfs merge=lfs -text 40 | *.jpeg filter=lfs diff=lfs merge=lfs -text 41 | *.jpg filter=lfs diff=lfs merge=lfs -text 42 | *.pict filter=lfs diff=lfs merge=lfs -text 43 | *.psd filter=lfs diff=lfs merge=lfs -text 44 | *.tga filter=lfs diff=lfs merge=lfs -text 45 | *.tif filter=lfs diff=lfs merge=lfs -text 46 | *.tiff filter=lfs diff=lfs merge=lfs -text 47 | 48 | # Collapse Unity-generated files on GitHub 49 | *.asset linguist-generated 50 | *.mat linguist-generated 51 | *.meta linguist-generated 52 | *.prefab linguist-generated 53 | *.unity linguist-generated -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | release: 8 | name: release 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | fetch-depth: 0 14 | - name: Release 15 | uses: cycjimmy/semantic-release-action@v2 16 | with: 17 | extra_plugins: | 18 | @semantic-release/changelog 19 | @semantic-release/git 20 | branch: main 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Derived From: 2 | # http://kleber-swf.com/the-definitive-gitignore-for-unity-projects/ 3 | 4 | # ======= # 5 | # Private # 6 | # ======= # 7 | _private/ 8 | Release/ 9 | /Help/ 10 | *.shfbproj_* 11 | 12 | /Assets/Zenject/Extras 13 | 14 | # =============== # 15 | # Unity generated # 16 | # =============== # 17 | Temp/ 18 | Obj/ 19 | UnityGenerated/ 20 | Library/ 21 | 22 | # ============ # 23 | # OS generated # 24 | # ============ # 25 | .DS_Store 26 | .DS_Store? 27 | ._* 28 | .Spotlight-V100 29 | .Trashes 30 | Icon? 31 | ehthumbs.db 32 | Thumbs.db 33 | 34 | # Common IntelliJ Platform excludes 35 | 36 | # Jetbrain Rider Cache 37 | **/.idea/* 38 | 39 | *.suo 40 | *.user 41 | .vs/ 42 | [Bb]in/ 43 | [Oo]bj/ 44 | _UpgradeReport_Files/ 45 | [Pp]ackages/ 46 | 47 | Thumbs.db 48 | Desktop.ini 49 | .DS_Store 50 | 51 | # The file being generated in root directory instead of obj/debug https://github.com/dotnet/roslyn/issues/48430 52 | *.GeneratedMSBuildEditorConfig.editorconfig -------------------------------------------------------------------------------- /.images/add-component.gif: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:35fa9da36eefc067b26c2e3d70160a41f7c00129a1aa2f57eca87e85c33dc30b 3 | size 154574 4 | -------------------------------------------------------------------------------- /.images/asset-creation.gif: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f6301d05c577cb345a68b09904b7571e8b35fd5da84d8aaec0a736f977c21ee7 3 | size 427817 4 | -------------------------------------------------------------------------------- /.images/creatable-scriptable-object.gif: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a7e7cc409b044e3fa141ffd1ce2048df09540261923a3f9690582846caf39878 3 | size 875740 4 | -------------------------------------------------------------------------------- /.images/generic-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidAlloy/GenericUnityObjects/adc7802151bbcc4a1cc68cfcab6b84c69002fc6e/.images/generic-header.png -------------------------------------------------------------------------------- /.images/object-field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidAlloy/GenericUnityObjects/adc7802151bbcc4a1cc68cfcab6b84c69002fc6e/.images/object-field.png -------------------------------------------------------------------------------- /.images/project-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidAlloy/GenericUnityObjects/adc7802151bbcc4a1cc68cfcab6b84c69002fc6e/.images/project-settings.png -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tagFormat": "${version}", 3 | "plugins": [ 4 | ["@semantic-release/commit-analyzer", { "preset": "angular" }], 5 | "@semantic-release/release-notes-generator", 6 | ["@semantic-release/changelog", { "preset": "angular" }], 7 | ["@semantic-release/npm", { "npmPublish": false }], 8 | ["@semantic-release/git", { 9 | "assets": ["package.json", "CHANGELOG.md"], 10 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 11 | }], 12 | "@semantic-release/github" 13 | ] 14 | } -------------------------------------------------------------------------------- /CHANGELOG.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 098d69d4e7707f04fa882dbfd36cff9a 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2056149d28060a541b2ab5b05caa7b33 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/AssemblyCreator.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: adb21da198164681b647567f81e6fcce 3 | timeCreated: 1609849473 -------------------------------------------------------------------------------- /Editor/AssemblyCreator/AssemblyCreator.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using Util; 5 | using Object = UnityEngine.Object; 6 | 7 | /// 8 | /// A class responsible for emitting and saving assemblies. 9 | /// 10 | internal static class AssemblyCreator 11 | { 12 | // AssemblyGUID is needed to name concrete classes uniquely. This is required to correctly filter types in object fields. 13 | public static string CreateSelectorAssembly(string assemblyName, Type genericBehaviourWithoutArgs, string assemblyGUID) => 14 | BehaviourSelectorCreator.CreateSelectorAssemblyImpl(assemblyName, genericBehaviourWithoutArgs, assemblyGUID); 15 | 16 | public static string CreateConcreteClass(string assemblyName, Type genericBehaviourWithArgs, string assemblyGUID) 17 | where TObject : Object 18 | { 19 | return ConcreteClassCreator.CreateConcreteClass(assemblyName, genericBehaviourWithArgs, assemblyGUID); 20 | } 21 | 22 | public static string CreateMenuItems(string assemblyName, MenuItemMethod[] menuItemMethods) => 23 | MenuItemsCreator.CreateMenuItemsImpl(assemblyName, menuItemMethods); 24 | } 25 | } -------------------------------------------------------------------------------- /Editor/AssemblyCreator/AssemblyCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bad87a219b9d4b13b078eefbf98c3e95 3 | timeCreated: 1608463159 -------------------------------------------------------------------------------- /Editor/AssemblyCreator/AssemblyCreatorHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ce21467facae4d6da275b175ff3bc406 3 | timeCreated: 1610111504 -------------------------------------------------------------------------------- /Editor/AssemblyCreator/BehaviourSelectorCreator.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using GenericUnityObjects.Util; 7 | 8 | /// 9 | /// Emits and saves an assembly of a concrete class that inherits from . 10 | /// 11 | internal static class BehaviourSelectorCreator 12 | { 13 | /// 14 | /// Not supposed to be used directly. Instead, use . 15 | /// 16 | public static string CreateSelectorAssemblyImpl(string assemblyName, Type genericBehaviourWithoutArgs, string assemblyGUID) 17 | { 18 | using var concreteClassAssembly = AssemblyCreatorHelper.CreateConcreteClassAssembly(assemblyName, $"ClassSelector_{assemblyGUID}", typeof(BehaviourSelector)); 19 | CreateBehaviourTypeProperty(concreteClassAssembly.TypeBuilder, genericBehaviourWithoutArgs); 20 | AssemblyCreatorHelper.AddComponentMenuAttribute(concreteClassAssembly.TypeBuilder, genericBehaviourWithoutArgs); 21 | return concreteClassAssembly.Path; 22 | } 23 | 24 | private static void CreateBehaviourTypeProperty(TypeBuilder typeBuilder, Type propertyValue) 25 | { 26 | PropertyBuilder property = typeBuilder.DefineProperty( 27 | "GenericBehaviourType", 28 | PropertyAttributes.None, 29 | typeof(Type), 30 | null); 31 | 32 | MethodBuilder pGet = typeBuilder.DefineMethod( 33 | "get_GenericBehaviourType", 34 | MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, 35 | typeof(Type), 36 | Type.EmptyTypes); 37 | 38 | ILGenerator pILGet = pGet.GetILGenerator(); 39 | 40 | pILGet.Emit(OpCodes.Ldtoken, propertyValue); 41 | pILGet.EmitCall(OpCodes.Call, AssemblyCreatorHelper.GetTypeFromHandle, null); 42 | pILGet.Emit(OpCodes.Ret); 43 | 44 | property.SetGetMethod(pGet); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Editor/AssemblyCreator/BehaviourSelectorCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1c65d050a5e5354d8e5b8a3b80fb86e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/AssemblyCreator/ConcreteClassCreator.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using UnityEngine; 5 | using Object = UnityEngine.Object; 6 | 7 | /// 8 | /// Emits and saves an assembly of a concrete class that inherits from a specific generic UnityEngine.Object 9 | /// 10 | internal static class ConcreteClassCreator 11 | { 12 | /// 13 | /// Not supposed to be used directly. Instead, use . 14 | /// 15 | public static string CreateConcreteClass(string assemblyName, Type genericTypeWithArgs, string assemblyGUID) 16 | where TObject : Object 17 | { 18 | using var concreteClassAssembly = AssemblyCreatorHelper.CreateConcreteClassAssembly(assemblyName, $"ConcreteClass_{assemblyGUID}", genericTypeWithArgs); 19 | 20 | AssemblyCreatorHelper.AddChildrenAttributes(concreteClassAssembly.TypeBuilder, genericTypeWithArgs); 21 | 22 | if (typeof(TObject) == typeof(MonoBehaviour)) 23 | { 24 | AssemblyCreatorHelper.AddComponentMenuAttribute(concreteClassAssembly.TypeBuilder, genericTypeWithArgs); 25 | } 26 | 27 | return concreteClassAssembly.Path; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Editor/AssemblyCreator/ConcreteClassCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b396fdd8267d4c64b5ad343ddef161a2 3 | timeCreated: 1609766612 -------------------------------------------------------------------------------- /Editor/AssemblyCreator/MenuItemsCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 38fc07fac4a64aab8deb73949929ffef 3 | timeCreated: 1609766619 -------------------------------------------------------------------------------- /Editor/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("GenericUnityObjects.EditorTests")] 4 | [assembly: InternalsVisibleTo("GenericUnityObjects.IntegrationTests")] 5 | [assembly: InternalsVisibleTo("OdinInternals")] 6 | [assembly: InternalsVisibleTo("GenericScriptableArchitecture.Editor")] 7 | [assembly: InternalsVisibleTo("GenericScriptableArchitecture.Timeline.Editor")] -------------------------------------------------------------------------------- /Editor/AssemblyInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ae230238c4084f268274480dda977227 3 | timeCreated: 1608122678 -------------------------------------------------------------------------------- /Editor/Drawers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c67840be7e7e4defa156cffb4c876c4a 3 | timeCreated: 1611652107 -------------------------------------------------------------------------------- /Editor/Drawers/BehaviourSelectorEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 357ee24ea65944cf8db88dbf8275b669 3 | timeCreated: 1607506383 -------------------------------------------------------------------------------- /Editor/Drawers/CreatableObjectDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1662109e5e504356a65bbd45b0e47870 3 | timeCreated: 1629529282 -------------------------------------------------------------------------------- /Editor/Drawers/GenericHeaderUtility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 390bf22c0f924c158ee36b23ac8fc14d 3 | timeCreated: 1643109274 -------------------------------------------------------------------------------- /Editor/Drawers/GenericObjectDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a053f0867ae7490d8bde001921af1da5 3 | timeCreated: 1610742764 -------------------------------------------------------------------------------- /Editor/Drawers/GenericUnityObjectDrawer.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | #if ODIN_INSPECTOR 7 | using Sirenix.OdinInspector.Editor; 8 | #endif 9 | 10 | internal abstract class GenericUnityObjectDrawer : PropertyDrawer 11 | { 12 | protected abstract bool AlwaysCreatable { get; } 13 | 14 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 15 | { 16 | if (AlwaysCreatable) 17 | { 18 | CreatableObjectDrawer.Instance.OnGUI(position, property, label); 19 | } 20 | else 21 | { 22 | // ReSharper disable once Unity.PropertyDrawerOnGUIBase 23 | GenericObjectDrawer.ObjectField(position, property, label); 24 | } 25 | } 26 | } 27 | 28 | [CustomPropertyDrawer(typeof(ScriptableObject), true)] 29 | #if ODIN_INSPECTOR 30 | [DrawerPriority(0, 0, 2)] 31 | #endif 32 | internal class GenericSODrawer : GenericUnityObjectDrawer 33 | { 34 | protected override bool AlwaysCreatable => ProjectSettings.AlwaysCreatableScriptableObject; 35 | } 36 | 37 | [CustomPropertyDrawer(typeof(MonoBehaviour), true)] 38 | #if ODIN_INSPECTOR 39 | [DrawerPriority(0, 0, 2)] 40 | #endif 41 | internal class GenericBehaviourDrawer : GenericUnityObjectDrawer 42 | { 43 | protected override bool AlwaysCreatable => ProjectSettings.AlwaysCreatableMonoBehaviour; 44 | } 45 | } -------------------------------------------------------------------------------- /Editor/Drawers/GenericUnityObjectDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5df7623049ac420399fd1f9e05a811b0 3 | timeCreated: 1603985687 -------------------------------------------------------------------------------- /Editor/Drawers/GenericUnityObjectHelper.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using GenericUnityObjects.Util; 5 | using SolidUtilities.Editor; 6 | using UnityEditor; 7 | using UnityEngine; 8 | using Object = UnityEngine.Object; 9 | 10 | /// 11 | /// A class that places the correct script in the MonoScript field of generic UnityEngine.Objects. 12 | /// 13 | public class GenericUnityObjectHelper 14 | { 15 | private readonly bool _drawForGeneric; 16 | private readonly MonoScript _monoScript; 17 | private readonly Type _genericType; 18 | 19 | /// 20 | /// Initializes a new instance of the class. Recommended to use in OnEnable. 21 | /// 22 | /// Target object of custom editor. 23 | public GenericUnityObjectHelper(Object target) 24 | { 25 | var targetType = target.GetType(); 26 | 27 | if (!targetType.FullName.StartsWith(Config.ConcreteClassNamespace)) 28 | return; 29 | 30 | _genericType = targetType.BaseType; 31 | 32 | if (_genericType?.IsGenericType != true) 33 | return; 34 | 35 | _drawForGeneric = true; 36 | _monoScript = AssetHelper.GetMonoScriptFromType(_genericType); 37 | } 38 | 39 | /// 40 | /// Draws MonoScript field and places the correct generic UnityEngine.Object script into it. 41 | /// 42 | /// A MonoScript property. 43 | /// If the passed property path is not m_Script. 44 | public void DrawMonoScript(SerializedProperty monoScriptProperty) 45 | { 46 | if (monoScriptProperty.propertyPath != "m_Script") 47 | { 48 | throw new ArgumentException( 49 | $"Expected a MonoScript property but {monoScriptProperty.propertyPath} was passed as an argument instead."); 50 | } 51 | 52 | using (new EditorGUI.DisabledScope(monoScriptProperty.objectReferenceValue != null)) 53 | { 54 | if (_drawForGeneric && ! (_monoScript is null)) 55 | { 56 | EditorGUILayout.ObjectField("Script", _monoScript, _genericType, false, null); 57 | } 58 | else 59 | { 60 | EditorGUILayout.ObjectField(monoScriptProperty, (GUILayoutOption[]) null); 61 | } 62 | } 63 | 64 | if (_drawForGeneric && _monoScript is null) 65 | { 66 | EditorGUILayout.HelpBox( 67 | "The associated script that contains the generic type could not be found.\n" + 68 | "Please check that its file name matches the class name.", 69 | MessageType.Warning); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Editor/Drawers/GenericUnityObjectHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cae69fd1c5df457890cbae54088c95c4 3 | timeCreated: 1610095337 -------------------------------------------------------------------------------- /Editor/Drawers/ScriptableObjectEditor.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | #if ! DISABLE_GENERIC_OBJECT_EDITOR 7 | [CanEditMultipleObjects] 8 | [CustomEditor(typeof(ScriptableObject), true)] 9 | #endif 10 | public class ScriptableObjectEditor : UnityObjectEditor { } 11 | } -------------------------------------------------------------------------------- /Editor/Drawers/ScriptableObjectEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5cff3e14e15f4460a93a5453c2482b9a 3 | timeCreated: 1643114070 -------------------------------------------------------------------------------- /Editor/Drawers/SingletonScriptableObjectEditor.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using GenericUnityObjects.Util; 4 | using UnityEditor; 5 | 6 | /// 7 | /// Serialized fields of SingletonScriptableObjects are not supposed to be changed from inspector. 8 | /// They are hidden completely from plugin users, and are shown in read-only mode for debugging purposes. 9 | /// 10 | [CustomEditor(typeof(SingletonScriptableObject), true)] 11 | internal class SingletonScriptableObjectEditor : Editor 12 | { 13 | public override void OnInspectorGUI() 14 | { 15 | #if GENERIC_UNITY_OBJECTS_DEBUG 16 | using var disabledScope = new EditorGUI.DisabledScope(true); 17 | DrawDefaultInspector(); 18 | #endif 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Editor/Drawers/SingletonScriptableObjectEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a5eca393f56741bc951300b7a5eedc86 3 | timeCreated: 1610216645 -------------------------------------------------------------------------------- /Editor/Drawers/TypeReferenceWithBaseTypesDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 88229dac4ffd405a8f32ff631376d7b2 3 | timeCreated: 1602943776 -------------------------------------------------------------------------------- /Editor/Drawers/UnityObjectEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ccb024bb3d414c75a6fdf5b3c3775cc3 3 | timeCreated: 1609958498 -------------------------------------------------------------------------------- /Editor/GenerationDatabase.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d94e435f1f8345a5b8a598290fae2aef 3 | timeCreated: 1609850162 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/BehavioursGenerationDatabase.Serialization.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.GeneratedTypesDatabase 2 | { 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using Util; 6 | 7 | internal partial class BehavioursGenerationDatabase 8 | { 9 | [SerializeField] private Collection[] _genericTypeValues; 10 | [SerializeField] private BehaviourInfo[] _genericTypeKeys; 11 | protected override int GenericTypeKeysLength => _genericTypeKeys.Length; 12 | protected override int GenericTypeValuesLength => _genericTypeValues.Length; 13 | protected override GenericTypeInfo[] GetTypeValueAtIndex(int index) => _genericTypeValues[index]; 14 | protected override GenericTypeInfo GetTypeKeyAtIndex(int index) => _genericTypeKeys[index]; 15 | 16 | protected override void SetTypeValueAtIndex(int index, List value) => 17 | _genericTypeValues[index] = value.ConvertAll(typeInfo => (BehaviourInfo) typeInfo); 18 | 19 | protected override void SetTypeKeyAtIndex(int index, GenericTypeInfo value) => 20 | _genericTypeKeys[index] = (BehaviourInfo) value; 21 | 22 | protected override void ResetTypeValuesToLength(int length) => 23 | _genericTypeValues = new Collection[length]; 24 | 25 | protected override void ResetTypeKeysToLength(int length) => _genericTypeKeys = new BehaviourInfo[length]; 26 | } 27 | } -------------------------------------------------------------------------------- /Editor/GenerationDatabase/BehavioursGenerationDatabase.Serialization.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e324614730424ad1938038f2bcab9a97 3 | timeCreated: 1613236486 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/BehavioursGenerationDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.GeneratedTypesDatabase 2 | { 3 | using UnityEngine; 4 | 5 | /// 6 | /// All the work is done in the parent class. This is implemented just to create a ScriptableObject asset. 7 | /// 8 | internal partial class BehavioursGenerationDatabase : GenerationDatabase 9 | { 10 | public static void UpdateComponentName(BehaviourInfo behaviourInfo, string newComponentName) 11 | { 12 | ((BehavioursGenerationDatabase)Instance).UpdateComponentNameImpl(behaviourInfo, newComponentName); 13 | } 14 | 15 | public void UpdateComponentNameImpl(BehaviourInfo behaviourInfo, string newComponentName) 16 | { 17 | TemporarilyRemovingGenericType(behaviourInfo, () => 18 | { 19 | _genericTypesPool.ChangeItem(ref behaviourInfo, genericTypeToChange => 20 | { 21 | genericTypeToChange.UpdateComponentName(newComponentName); 22 | }); 23 | }); 24 | } 25 | 26 | public static void UpdateOrder(BehaviourInfo behaviourInfo, int newOrder) 27 | { 28 | ((BehavioursGenerationDatabase)Instance).UpdateOrderImpl(behaviourInfo, newOrder); 29 | } 30 | 31 | public void UpdateOrderImpl(BehaviourInfo behaviourInfo, int newOrder) 32 | { 33 | TemporarilyRemovingGenericType(behaviourInfo, () => 34 | { 35 | _genericTypesPool.ChangeItem(ref behaviourInfo, genericTypeToChange => 36 | { 37 | genericTypeToChange.UpdateOrder(newOrder); 38 | }); 39 | }); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Editor/GenerationDatabase/BehavioursGenerationDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e34fec35c2bb4f2880a04272d23fbc31 3 | timeCreated: 1609671644 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/ConcreteClass.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.GeneratedTypesDatabase 2 | { 3 | using System; 4 | using SolidUtilities; 5 | using UnityEngine; 6 | 7 | [Serializable] 8 | internal class ConcreteClass : IEquatable 9 | { 10 | private static readonly ArrayEqualityComparer _arrayComparer = new ArrayEqualityComparer(); 11 | 12 | [SerializeField] private ArgumentInfo[] _arguments; 13 | [SerializeField] private string _assemblyGUID; 14 | 15 | public ArgumentInfo[] Arguments => _arguments; 16 | 17 | public string AssemblyGUID => _assemblyGUID; 18 | 19 | public ConcreteClass(ArgumentInfo[] arguments, string assemblyGUID) 20 | { 21 | _arguments = arguments; 22 | _assemblyGUID = assemblyGUID; 23 | } 24 | 25 | public bool Equals(ConcreteClass p) 26 | { 27 | if (ReferenceEquals(p, null)) 28 | { 29 | return false; 30 | } 31 | 32 | if (ReferenceEquals(this, p)) 33 | { 34 | return true; 35 | } 36 | 37 | if (this.GetType() != p.GetType()) 38 | { 39 | return false; 40 | } 41 | 42 | return _arrayComparer.Equals(_arguments, p._arguments) && _assemblyGUID == p._assemblyGUID; 43 | } 44 | 45 | public static bool operator ==(ConcreteClass lhs, ConcreteClass rhs) 46 | { 47 | return lhs?.Equals(rhs) ?? ReferenceEquals(rhs, null); 48 | } 49 | 50 | public static bool operator !=(ConcreteClass lhs, ConcreteClass rhs) 51 | { 52 | return ! (lhs == rhs); 53 | } 54 | 55 | public override bool Equals(object obj) 56 | { 57 | return Equals(obj as ConcreteClass); 58 | } 59 | 60 | // Can't make the fields readonly because Unity will not serialize them. Should be careful with not changing them instead. 61 | public override int GetHashCode() 62 | { 63 | unchecked 64 | { 65 | int hash = 17; 66 | hash = hash * 23 + _arrayComparer.GetHashCode(_arguments); 67 | hash = hash * 23 + _assemblyGUID.GetHashCode(); 68 | return hash; 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Editor/GenerationDatabase/ConcreteClass.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b594c525267044a0ba189807da1215b5 3 | timeCreated: 1608305431 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/GenerationDatabase.Serialization.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ca9687b2f904ecf9c5ecee93cc215d3 3 | timeCreated: 1609853130 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/GenerationDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 62f864a5f756e4849b5976bf2269fd5e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/GenerationDatabase/Pool.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.GeneratedTypesDatabase 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using JetBrains.Annotations; 6 | 7 | internal class Pool 8 | where T : TypeInfo 9 | { 10 | private readonly Dictionary _dict; 11 | private readonly Dictionary _typeNameGUIDDict; 12 | 13 | public Pool(int capacity = 0) 14 | { 15 | _dict = new Dictionary(capacity); 16 | _typeNameGUIDDict = new Dictionary(capacity); 17 | } 18 | 19 | public T GetOrAdd(T item) 20 | { 21 | if (_dict.TryGetValue(item, out T existingItem)) 22 | return existingItem; 23 | 24 | _dict.Add(item, item); 25 | _typeNameGUIDDict.Add(item.TypeNameAndAssembly, item.GUID); 26 | return item; 27 | } 28 | 29 | public void AddRange(T[] items) 30 | { 31 | foreach (T item in items) 32 | { 33 | if (_dict.ContainsKey(item)) 34 | continue; 35 | 36 | _dict.Add(item, item); 37 | _typeNameGUIDDict.Add(item.TypeNameAndAssembly, item.GUID); 38 | } 39 | } 40 | 41 | public void ChangeItem(ref T item, Action changeItem) 42 | { 43 | if (_dict.TryGetValue(item, out T existingItem)) 44 | { 45 | item = existingItem; 46 | _dict.Remove(item); 47 | _typeNameGUIDDict.Remove(item.TypeNameAndAssembly); 48 | } 49 | 50 | changeItem(item); 51 | 52 | _dict.Add(item, item); 53 | _typeNameGUIDDict.Add(item.TypeNameAndAssembly, item.GUID); 54 | } 55 | 56 | public void ChangeItem(ref TChildType item, Action changeItem) 57 | where TChildType : T 58 | { 59 | if (_dict.TryGetValue(item, out T existingItem)) 60 | { 61 | item = (TChildType)existingItem; 62 | _dict.Remove(item); 63 | _typeNameGUIDDict.Remove(item.TypeNameAndAssembly); 64 | } 65 | 66 | changeItem(item); 67 | 68 | _dict.Add(item, item); 69 | _typeNameGUIDDict.Add(item.TypeNameAndAssembly, item.GUID); 70 | } 71 | 72 | [CanBeNull] 73 | public string GetGUID(string typeNameAndAssembly) 74 | { 75 | _typeNameGUIDDict.TryGetValue(typeNameAndAssembly, out string guid); 76 | return guid; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /Editor/GenerationDatabase/Pool.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f160644efbe4d61819ba1c21c6861d8 3 | timeCreated: 1609853004 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/SOGenerationDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.GeneratedTypesDatabase 2 | { 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using Util; 6 | 7 | /// 8 | /// All the work is done in the parent class. This is implemented just to create a ScriptableObject asset. 9 | /// 10 | internal class SOGenerationDatabase : GenerationDatabase 11 | { 12 | [SerializeField] private Collection[] _genericTypeValues; 13 | [SerializeField] private GenericTypeInfo[] _genericTypeKeys; 14 | 15 | protected override int GenericTypeKeysLength => _genericTypeKeys.Length; 16 | 17 | protected override int GenericTypeValuesLength => _genericTypeValues.Length; 18 | 19 | protected override GenericTypeInfo[] GetTypeValueAtIndex(int index) => _genericTypeValues[index]; 20 | 21 | protected override GenericTypeInfo GetTypeKeyAtIndex(int index) => _genericTypeKeys[index]; 22 | 23 | protected override void SetTypeValueAtIndex(int index, List value) => _genericTypeValues[index] = value; 24 | 25 | protected override void SetTypeKeyAtIndex(int index, GenericTypeInfo value) => _genericTypeKeys[index] = value; 26 | 27 | protected override void ResetTypeValuesToLength(int length) => _genericTypeValues = new Collection[length]; 28 | 29 | protected override void ResetTypeKeysToLength(int length) => _genericTypeKeys = new GenericTypeInfo[length]; 30 | } 31 | } -------------------------------------------------------------------------------- /Editor/GenerationDatabase/SOGenerationDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f04e00c890644cc9adb05d0c17f5ee62 3 | timeCreated: 1609670160 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/TypeInfo.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7a43582c3da34a53bbf9465d045420c5 3 | timeCreated: 1608408273 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/TypeInfo/ArgumentInfo.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.GeneratedTypesDatabase 2 | { 3 | using System; 4 | 5 | [Serializable] 6 | internal class ArgumentInfo : TypeInfo 7 | { 8 | public ArgumentInfo(string typeNameAndAssembly, string guid) 9 | : base(typeNameAndAssembly, guid) { } 10 | 11 | public ArgumentInfo(string typeFullName, string assemblyName, string guid) 12 | : base(typeFullName, assemblyName, guid) { } 13 | 14 | public ArgumentInfo(Type type, string typeGUID = null) 15 | : base(type, typeGUID) { } 16 | } 17 | } -------------------------------------------------------------------------------- /Editor/GenerationDatabase/TypeInfo/ArgumentInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 42109e07f3bdb194492f8e7e2eddd09a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/GenerationDatabase/TypeInfo/BehaviourInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cd93b7c48dc641e49186bb8e449cf909 3 | timeCreated: 1612546070 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/TypeInfo/GenericTypeInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1dacf08450734ce2a89078552a23ed5e 3 | timeCreated: 1608407896 -------------------------------------------------------------------------------- /Editor/GenerationDatabase/TypeInfo/TypeInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2f8d4ad5b8ef4971b575f33e044172e1 3 | timeCreated: 1608122735 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ccf7e301932d4bb2872a2c8556efc32c 3 | timeCreated: 1609849497 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/ArgumentsChecker.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using GeneratedTypesDatabase; 5 | using Object = UnityEngine.Object; 6 | 7 | /// 8 | /// Checks if any argument types were changed/updated, updates them in the database and regenerates DLLs if needed. 9 | /// 10 | /// A type derived from . 11 | internal static class ArgumentsChecker 12 | where TObject : Object 13 | { 14 | public static bool Check(GenericTypesChecker genericTypesChecker) 15 | { 16 | bool needsAssetDatabaseRefresh = false; 17 | 18 | foreach (ArgumentInfo argument in GenerationDatabase.ArgumentGenericTypes.Keys) 19 | { 20 | if (argument.RetrieveType(out Type type, out bool retrievedFromGUID)) 21 | { 22 | if (retrievedFromGUID) 23 | { 24 | needsAssetDatabaseRefresh = true; 25 | UpdateArgumentTypeName(argument, type, genericTypesChecker); 26 | } 27 | } 28 | else 29 | { 30 | needsAssetDatabaseRefresh = true; 31 | GenerationDatabase.RemoveArgument(argument, AssemblyAssetOperations.RemoveAssemblyByGUID); 32 | } 33 | } 34 | 35 | return needsAssetDatabaseRefresh; 36 | } 37 | 38 | public static void UpdateArgumentTypeName(ArgumentInfo argument, Type newType, GenericTypesChecker genericTypesChecker) 39 | { 40 | // Retrieve an array of generic arguments where the old argument was listed 41 | var referencedGenericTypes = GenerationDatabase.GetReferencedGenericTypes(argument); 42 | 43 | // Update argument typename in the database before updating assemblies and trying to find behaviour 44 | // because behaviour might also need to be updated, and the argument should already be new. 45 | GenerationDatabase.UpdateArgumentNameAndAssembly(argument, newType); 46 | 47 | genericTypesChecker.UpdateReferencedGenericTypes(argument, referencedGenericTypes); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/ArgumentsChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d0ca89fe36f4a72acd0f36d69c472ab 3 | timeCreated: 1609785833 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/AssemblyAssetOperations.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using System.IO; 5 | using GenericUnityObjects.Util; 6 | using JetBrains.Annotations; 7 | using UnityEditor; 8 | 9 | /// 10 | /// A class that contains methods related to t 11 | /// 12 | internal static class AssemblyAssetOperations 13 | { 14 | public static void RemoveAssemblyByGUID([CanBeNull] string assemblyGUID) 15 | { 16 | if (string.IsNullOrEmpty(assemblyGUID)) 17 | return; 18 | 19 | string assemblyPath = AssetDatabase.GUIDToAssetPath(assemblyGUID); 20 | AssetDatabase.DeleteAsset(assemblyPath); 21 | } 22 | 23 | public static AssemblyReplacer StartAssemblyReplacement(string oldAssemblyPath) 24 | { 25 | return new AssemblyReplacer(oldAssemblyPath); 26 | } 27 | 28 | public readonly struct AssemblyReplacer 29 | { 30 | private readonly string _oldAssemblyPath; 31 | 32 | public AssemblyReplacer(string oldAssemblyPath) 33 | { 34 | _oldAssemblyPath = oldAssemblyPath; 35 | File.Delete(oldAssemblyPath); 36 | } 37 | 38 | public void FinishReplacement(string newAssemblyPath) 39 | { 40 | if (_oldAssemblyPath == newAssemblyPath) 41 | return; 42 | 43 | string oldAssemblyMeta = $"{_oldAssemblyPath}.meta"; 44 | 45 | if (!File.Exists(oldAssemblyMeta)) 46 | return; 47 | 48 | File.Move(oldAssemblyMeta, $"{newAssemblyPath}.meta"); 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/AssemblyAssetOperations.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 19a60c1222f241ffab4a1d4a2092f4fb 3 | timeCreated: 1609785678 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/BehavioursChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 181dd43491774f41a789f2d8434f692c 3 | timeCreated: 1609785819 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/ConcreteClassChecker.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using GeneratedTypesDatabase; 5 | using SolidUtilities.Editor; 6 | using Util; 7 | using Object = UnityEngine.Object; 8 | 9 | /// 10 | /// Methods from this class are called by other checkers to update concrete class assemblies. 11 | /// 12 | /// A type derived from . 13 | internal class ConcreteClassChecker 14 | where TObject : Object 15 | { 16 | private readonly GenericTypesChecker _genericTypesChecker; 17 | 18 | public ConcreteClassChecker(GenericTypesChecker genericTypesChecker) 19 | => _genericTypesChecker = genericTypesChecker; 20 | 21 | public void UpdateConcreteClassesAssemblies(Type behaviourType, ConcreteClass[] concreteClasses, string genericTypeGUID) 22 | { 23 | foreach (ConcreteClass concreteClass in concreteClasses) 24 | { 25 | UpdateConcreteClassAssembly(behaviourType, concreteClass, genericTypeGUID); 26 | } 27 | } 28 | 29 | private void UpdateConcreteClassAssembly(Type genericType, ConcreteClass concreteClass, string genericTypeGUID) 30 | { 31 | if ( ! GetArgumentTypes(concreteClass, out Type[] argumentTypes)) 32 | return; 33 | 34 | ConcreteClassCreator.UpdateConcreteClassAssembly(genericType, argumentTypes, concreteClass, genericTypeGUID); 35 | 36 | // 'ConcreteClass_ade148c5c4a7ea64bb9a635005ef6220' is missing the class attribute 'ExtensionOfNativeClass'! 37 | LogHelper.RemoveLogEntriesByMode(LogModes.EditorErrors); 38 | 39 | // GameObject (named 'New Game Object') references runtime script in scene file. Fixing! 40 | LogHelper.RemoveLogEntriesByMode(LogModes.UserAndEditorWarnings); 41 | } 42 | 43 | private bool GetArgumentTypes(ConcreteClass concreteClass, out Type[] argumentTypes) 44 | { 45 | var arguments = concreteClass.Arguments; 46 | int argumentsLength = arguments.Length; 47 | 48 | argumentTypes = new Type[argumentsLength]; 49 | 50 | for (int i = 0; i < argumentsLength; i++) 51 | { 52 | ArgumentInfo argument = arguments[i]; 53 | 54 | if (argument.RetrieveType(out Type type, out bool retrievedFromGUID)) 55 | { 56 | if (retrievedFromGUID) 57 | { 58 | ArgumentsChecker.UpdateArgumentTypeName(argument, type, _genericTypesChecker); 59 | } 60 | 61 | argumentTypes[i] = type; 62 | } 63 | else 64 | { 65 | GenerationDatabase.RemoveArgument(argument, AssemblyAssetOperations.RemoveAssemblyByGUID); 66 | 67 | // Since one of the arguments was not found, the assembly associated with the concrete class 68 | // already has been removed, and there is no need to try updating it. 69 | return false; 70 | } 71 | } 72 | 73 | return true; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/ConcreteClassChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 20c51099027b44bc8101a750b37607f5 3 | timeCreated: 1609785827 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/DictInitializer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4e30b7b7322a22849be431b6aeb440a7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/FailedAssembliesChecker.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using GeneratedTypesDatabase; 6 | using SolidUtilities.Editor; 7 | using UnityEditor; 8 | using Util; 9 | 10 | internal static class FailedAssembliesChecker 11 | { 12 | private const string FailedAssemblyGuidsKey = "FailedAssemblyGuids"; 13 | 14 | public static readonly List FailedAssemblyPaths = new List(); 15 | 16 | public static readonly List MissingSelectors = new List(); 17 | 18 | public static void ReimportFailedAssemblies() 19 | { 20 | if (FailedAssemblyPaths.Count == 0) 21 | { 22 | return; 23 | } 24 | 25 | using (AssetDatabaseHelper.DisabledScope()) 26 | { 27 | var newFailedAssemblyGuids = new List(); 28 | 29 | var failedAssemblyPathsAndGuids = FailedAssemblyPaths 30 | .Select(path => (path, AssetDatabase.AssetPathToGUID(path))) 31 | .Where(pathAndGuid => !string.IsNullOrEmpty(pathAndGuid.Item2)).ToList(); 32 | 33 | foreach ((string path, string guid) in failedAssemblyPathsAndGuids) 34 | { 35 | AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); 36 | newFailedAssemblyGuids.Add(guid); 37 | } 38 | 39 | if (newFailedAssemblyGuids.Count != 0) 40 | { 41 | PersistentStorage.SaveData(FailedAssemblyGuidsKey, newFailedAssemblyGuids); 42 | PersistentStorage.ExecuteOnScriptsReload(ReimportCreatedAssets); 43 | } 44 | } 45 | 46 | AssetDatabase.Refresh(); 47 | } 48 | 49 | public static void AddMissingSelectors() 50 | { 51 | using var _ = new AssetDatabaseHelper.DisabledAssetDatabase(true); 52 | 53 | foreach (GenericTypeInfo genericTypeInfo in MissingSelectors) 54 | { 55 | BehavioursChecker.AddSelectorAssembly(genericTypeInfo); 56 | } 57 | } 58 | 59 | private static void ReimportCreatedAssets() 60 | { 61 | try 62 | { 63 | var failedAssemblyGuids = PersistentStorage.GetData>(FailedAssemblyGuidsKey); 64 | 65 | if (failedAssemblyGuids == null) 66 | return; 67 | 68 | using(AssetDatabaseHelper.DisabledScope()) 69 | { 70 | var assetPaths = failedAssemblyGuids 71 | .SelectMany(assemblyGuid => AssetDatabase.FindAssets($"t:ConcreteClass_{assemblyGuid}")) 72 | .Select(AssetDatabase.GUIDToAssetPath); 73 | 74 | foreach (string assetPath in assetPaths) 75 | AssetDatabase.ImportAsset(assetPath, ImportAssetOptions.ForceUpdate); 76 | } 77 | } 78 | finally 79 | { 80 | PersistentStorage.DeleteData(FailedAssemblyGuidsKey); 81 | } 82 | 83 | AssetDatabase.Refresh(); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/FailedAssembliesChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48cca1f71de64df6a8a80fecb8b14d1a 3 | timeCreated: 1630848405 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/GenericTypesAnalyzer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84d6f48e195d44944b62c5b590c3950b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/GenericTypesChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 05d2bcac1edc44b78fac98c248bb14aa 3 | timeCreated: 1610206506 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/MenuItemsChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d5992bd2f7fa45ae8336671772801aab 3 | timeCreated: 1609785837 -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/ScriptableObjectsChecker.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using GeneratedTypesDatabase; 5 | using UnityEngine; 6 | 7 | /// 8 | /// Checks if any generic types were changed, removed, or updated, and 9 | /// regenerates DLLs if needed. Most of the work is done in the parent type. This class contains only methods 10 | /// where a task needs to be done differently for ScriptableObject compared to MonoBehaviour. 11 | /// 12 | internal class ScriptableObjectsChecker : GenericTypesChecker 13 | { 14 | protected override bool AddNewGenericTypes(GenericTypeInfo[] genericTypes) 15 | { 16 | base.AddNewGenericTypes(genericTypes); 17 | return false; 18 | } 19 | 20 | protected override bool AdditionalTypeInfoCheck(GenericTypeInfo oldType, GenericTypeInfo newType) 21 | { 22 | return false; 23 | } 24 | 25 | protected override void UpdateGenericTypeNameAndArgs(GenericTypeInfo genericType, Type newType) 26 | { 27 | // Use default implementation 28 | UpdateGenericTypeName(genericType, newType, null); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Editor/GenericTypesAnalyzer/ScriptableObjectsChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e58f2e8be59a493eb09f5809f243405c 3 | timeCreated: 1609863818 -------------------------------------------------------------------------------- /Editor/GenericUnityObjects.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GenericUnityObjects.Editor", 3 | "rootNamespace": "GenericUnityObjects.Editor", 4 | "references": [ 5 | "SolidUtilities.Editor", 6 | "TypeReferences.Editor", 7 | "GenericUnityObjects", 8 | "TypeReferences", 9 | "SolidUtilities", 10 | "EasyButtons.Editor", 11 | "Unity.Settings.Editor", 12 | "UnityDropdown.Editor", 13 | "MissingScriptType.Editor", 14 | "ExtEvents" 15 | ], 16 | "includePlatforms": [ 17 | "Editor" 18 | ], 19 | "excludePlatforms": [], 20 | "allowUnsafeCode": false, 21 | "overrideReferences": true, 22 | "precompiledReferences": [ 23 | "GenericUnityEditorInternals.dll", 24 | "UnityEditorInternals.dll", 25 | "Sirenix.OdinInspector.Editor.dll", 26 | "Sirenix.Utilities.dll", 27 | "Sirenix.OdinInspector.Attributes.dll" 28 | ], 29 | "autoReferenced": true, 30 | "defineConstraints": [], 31 | "versionDefines": [ 32 | { 33 | "name": "com.madsbangh.easybuttons", 34 | "expression": "", 35 | "define": "EASY_BUTTONS" 36 | }, 37 | { 38 | "name": "com.solidalloy.missing-script-type", 39 | "expression": "", 40 | "define": "MISSING_SCRIPT_TYPE" 41 | } 42 | ], 43 | "noEngineReferences": false 44 | } -------------------------------------------------------------------------------- /Editor/GenericUnityObjects.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e5fb71161fa6f74f958f989fbdbb839 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor/MissingScriptTypeDisabler.cs: -------------------------------------------------------------------------------- 1 | #if MISSING_SCRIPT_TYPE 2 | namespace GenericUnityObjects.Editor 3 | { 4 | using UnityEditor; 5 | 6 | [InitializeOnLoad] 7 | internal static class MissingScriptTypeDisabler 8 | { 9 | static MissingScriptTypeDisabler() 10 | { 11 | var symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup); 12 | 13 | if (!symbols.Contains("DISABLE_GENERIC_OBJECT_EDITOR") && !symbols.Contains("DISABLE_MISSING_SCRIPT_EDITOR")) 14 | { 15 | symbols += ";DISABLE_MISSING_SCRIPT_EDITOR"; 16 | PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, symbols); 17 | } 18 | } 19 | } 20 | } 21 | #endif -------------------------------------------------------------------------------- /Editor/MissingScriptTypeDisabler.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a1baeb095043481f8696070bb326a375 3 | timeCreated: 1644609630 -------------------------------------------------------------------------------- /Editor/MonoBehaviours.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5aaa29c34ced4e27b5582edcf6af908c 3 | timeCreated: 1607951839 -------------------------------------------------------------------------------- /Editor/MonoBehaviours/GenericBehaviourCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af9f9bb15f5a4e95adb0b1ce0df226cf 3 | timeCreated: 1607592589 -------------------------------------------------------------------------------- /Editor/OnScriptsReloadActionsRunner.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System; 4 | using GenericUnityObjects.Util; 5 | using UnityEditor.Callbacks; 6 | using Util; 7 | 8 | internal static class OnScriptsReloadActionsRunner 9 | { 10 | [DidReloadScripts] 11 | private static void OnScriptsReload() 12 | { 13 | if (PersistentStorage.DelayActionsOnScriptsReload) 14 | { 15 | PersistentStorage.DelayActionsOnScriptsReload = false; 16 | EditorCoroutineHelper.DelayFrames(OnScriptsReload, 1); 17 | return; 18 | } 19 | 20 | // 1. GenericTypesAnalyzer finds a new generic MonoBehaviour and generates a DLL. 21 | // 2. Scripts are recompiled because of the DLL addition. 22 | // 3. This event is fired before GenericTypesAnalyzer is called again, and sets the custom icon. 23 | // Icons cannot be set immediately after generating a DLL because MonoScript is not generated by Unity yet. 24 | IconSetter.SetIcons(); 25 | 26 | try 27 | { 28 | GenericTypesAnalyzer.AnalyzeGenericTypes(); 29 | } 30 | catch (ApplicationException) 31 | { 32 | DebugUtility.Log("ApplicationException was thrown even though it is not expected here. Running the method again in 1 second."); 33 | EditorCoroutineHelper.Delay(OnScriptsReload, 1f); 34 | return; 35 | } 36 | 37 | PersistentStorage.OnScriptsReload(); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Editor/OnScriptsReloadActionsRunner.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ce898de653875d4ba680c1e33acd72c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/PackageUpgrader.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using System.IO; 4 | using GenericUnityObjects.Util; 5 | using UnityEditor; 6 | using UnityEngine; 7 | 8 | [InitializeOnLoad] 9 | public static class PackageUpgrader 10 | { 11 | private const string PackageUpgradedKey = "GenericUnityObjects_PackageUpgraded"; 12 | 13 | static PackageUpgrader() 14 | { 15 | // Run the upgrade process only once per project. 16 | if (PlayerPrefs.GetInt(PackageUpgradedKey, 0) == 1) 17 | return; 18 | 19 | Directory.CreateDirectory(Config.AssembliesDirPath); 20 | 21 | foreach (string filePath in Directory.EnumerateFiles(Config.AssembliesDirPath)) 22 | { 23 | if (filePath.EndsWith(".mdb")) 24 | { 25 | AssetDatabase.DeleteAsset(filePath); 26 | continue; 27 | } 28 | 29 | if (filePath.EndsWith(".meta") || filePath.Contains("MenuItems")) // skip the GeneratedMenuItems assembly 30 | continue; 31 | 32 | MoveAssemblyToRequiredPath(filePath); 33 | } 34 | 35 | if (FailedAssembliesChecker.FailedAssemblyPaths.Count == 0) 36 | PlayerPrefs.SetInt(PackageUpgradedKey, 1); 37 | } 38 | 39 | private static void MoveAssemblyToRequiredPath(string filePath) 40 | { 41 | var monoScript = AssetDatabase.LoadAssetAtPath(filePath); 42 | 43 | if (monoScript == null) 44 | { 45 | FailedAssembliesChecker.FailedAssemblyPaths.Add(filePath); 46 | return; 47 | } 48 | 49 | var concreteType = monoScript.GetClass(); 50 | 51 | if (concreteType == null) // Shouldn't happen but let's be safe 52 | return; 53 | 54 | string requiredPath = Config.GetAssemblyPathForType(concreteType); 55 | 56 | if (!Directory.Exists(requiredPath)) 57 | Directory.CreateDirectory(requiredPath); 58 | 59 | string assemblyName = Path.GetFileName(filePath); 60 | 61 | File.Move(filePath, $"{requiredPath}/{assemblyName}"); 62 | File.Move($"{filePath}.meta", $"{requiredPath}/{assemblyName}.meta"); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Editor/PackageUpgrader.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d05ac71fc9524c7bbe23b4147ee9d081 3 | timeCreated: 1637511571 -------------------------------------------------------------------------------- /Editor/ScriptableObjects.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 90b0b7b8ea7842abb5f9c4e0b7cd7daa 3 | timeCreated: 1607951881 -------------------------------------------------------------------------------- /Editor/ScriptableObjects/GenericSOCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f1185657666940f1b6d1a93b0802ab55 3 | timeCreated: 1601570147 -------------------------------------------------------------------------------- /Editor/ScriptableObjects/SelectionWindow.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a098b7a2b0f143e894b10e02b43a1f59 3 | timeCreated: 1607952000 -------------------------------------------------------------------------------- /Editor/ScriptableObjects/SelectionWindow/ITypeSelectionWindow.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.ScriptableObjects.SelectionWindow 2 | { 3 | using System; 4 | 5 | internal interface ITypeSelectionWindow 6 | { 7 | void OnCreate(Action onTypesSelected, string[] genericArgNames, Type[][] genericParamConstraints); 8 | } 9 | } -------------------------------------------------------------------------------- /Editor/ScriptableObjects/SelectionWindow/ITypeSelectionWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ed8cd806587448f1a8085960fa861a79 3 | timeCreated: 1616509396 -------------------------------------------------------------------------------- /Editor/ScriptableObjects/SelectionWindow/MultipleTypeSelectionWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3463d3b246ef4b44b09b3f7997406c15 3 | timeCreated: 1602669102 -------------------------------------------------------------------------------- /Editor/ScriptableObjects/SelectionWindow/OneTypeSelectionWindow.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.ScriptableObjects.SelectionWindow 2 | { 3 | using System; 4 | using System.Linq; 5 | using TypeReferences.Editor.Drawers; 6 | using UnityDropdown.Editor; 7 | using Util; 8 | 9 | /// 10 | /// A window that shows the type selection dropdown immediately after the creation, 11 | /// and closes once the type is chosen. 12 | /// 13 | internal class OneTypeSelectionWindow : ITypeSelectionWindow 14 | { 15 | private DropdownWindow _dropdownWindow; 16 | 17 | public void OnCreate(Action onTypeSelected, string[] genericArgNames, Type[][] genericParamConstraints) 18 | { 19 | var typeOptionsAttribute = new NonGenericAttribute(genericParamConstraints[0]); 20 | var dropdownTree = GetDropdownTree(typeOptionsAttribute, onTypeSelected); 21 | _dropdownWindow = dropdownTree.ShowAsContext(typeOptionsAttribute.DropdownHeight); 22 | } 23 | 24 | private DropdownMenu GetDropdownTree(NonGenericAttribute attribute, Action onTypeSelected) 25 | { 26 | var parentDrawer = new TypeDropdownDrawer(null, attribute, null); 27 | var dropdownItems = parentDrawer.GetDropdownItems().ToList(); 28 | 29 | var dropdownMenu = new DropdownMenu(dropdownItems, type => 30 | { 31 | _dropdownWindow.Close(); 32 | onTypeSelected(new[] { type }); 33 | }, 34 | TypeReferences.Editor.ProjectSettings.SearchbarMinItemsCount, true, attribute.ShowNoneElement); 35 | 36 | if (attribute.ExpandAllFolders) 37 | dropdownMenu.ExpandAllFolders(); 38 | 39 | return dropdownMenu; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Editor/ScriptableObjects/SelectionWindow/OneTypeSelectionWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b164937676514a44bf234f9cfc418a82 3 | timeCreated: 1602669091 -------------------------------------------------------------------------------- /Editor/ScriptableObjects/TypeSelectionWindow.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.ScriptableObjects 2 | { 3 | using System; 4 | using System.Linq; 5 | using SelectionWindow; 6 | using SolidUtilities; 7 | using UnityEngine; 8 | 9 | /// 10 | /// A window where you can choose the generic argument types for a asset. 11 | /// 12 | internal static class TypeSelectionWindow 13 | { 14 | /// Creates and shows the . 15 | /// Generic type definition (i.e. without concrete generic arguments). 16 | /// The action to do when all the types are chosen. 17 | public static void Create(Type genericTypeWithoutArgs, Action onTypesSelected) 18 | { 19 | var genericParamConstraints = genericTypeWithoutArgs.GetGenericArguments() 20 | .Select(type => type.GetGenericParameterConstraints()) 21 | .ToArray(); 22 | 23 | var genericArgNames = TypeHelper.GetNiceArgsOfGenericType(genericTypeWithoutArgs); 24 | 25 | ITypeSelectionWindow window; 26 | 27 | if (genericParamConstraints.Length == 1) 28 | { 29 | window = new OneTypeSelectionWindow(); 30 | } 31 | else 32 | { 33 | window = ScriptableObject.CreateInstance(); 34 | } 35 | 36 | window.OnCreate(onTypesSelected, genericArgNames, genericParamConstraints); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Editor/ScriptableObjects/TypeSelectionWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f7600ed5c4304d098e7b61a99c416408 3 | timeCreated: 1601839175 -------------------------------------------------------------------------------- /Editor/Settings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb617c1adc8649b7bff826daa76c3bc1 3 | timeCreated: 1631163804 -------------------------------------------------------------------------------- /Editor/Settings/ProjectSettings.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor 2 | { 3 | using UnityEditor.SettingsManagement; 4 | 5 | public static class ProjectSettings 6 | { 7 | private const string PackageName = "com.solidalloy.generic-unity-objects"; 8 | 9 | private static Settings _instance; 10 | 11 | private static UserSetting _alwaysCreatableScriptableObject; 12 | private static UserSetting _alwaysCreatableMonoBehaviour; 13 | 14 | public static bool AlwaysCreatableScriptableObject 15 | { 16 | get 17 | { 18 | InitializeIfNeeded(); 19 | return _alwaysCreatableScriptableObject.value; 20 | } 21 | 22 | set => _alwaysCreatableScriptableObject.value = value; 23 | } 24 | 25 | public static bool AlwaysCreatableMonoBehaviour 26 | { 27 | get 28 | { 29 | InitializeIfNeeded(); 30 | return _alwaysCreatableMonoBehaviour.value; 31 | } 32 | 33 | set => _alwaysCreatableMonoBehaviour.value = value; 34 | } 35 | 36 | private static void InitializeIfNeeded() 37 | { 38 | if (_instance != null) 39 | return; 40 | 41 | _instance = new Settings(PackageName); 42 | 43 | // Previously, there was only one always-creatable parameter and it was used for scriptable objects. 44 | // For backwards compatibility, it stores the previous name. 45 | const string alwaysCreatableScriptableObjectKey = "_alwaysCreatable"; 46 | _alwaysCreatableScriptableObject = new UserSetting(_instance, alwaysCreatableScriptableObjectKey, false); 47 | 48 | _alwaysCreatableMonoBehaviour = new UserSetting(_instance, nameof(_alwaysCreatableMonoBehaviour), false); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Editor/Settings/ProjectSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2f4a04a9a68b4eb687a79b6820553f97 3 | timeCreated: 1631163813 -------------------------------------------------------------------------------- /Editor/Settings/ProjectSettingsDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b7d0a54fc02642169afc9bc490b282b7 3 | timeCreated: 1631165957 -------------------------------------------------------------------------------- /Editor/Util.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f921555afac4ff3abbdc2459990cfe3 3 | timeCreated: 1607951783 -------------------------------------------------------------------------------- /Editor/Util/Collection`1.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.Util 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | 7 | [Serializable] 8 | internal class Collection 9 | { 10 | [SerializeField] private T[] _array; 11 | 12 | public Collection(List collection) => _array = collection.ToArray(); 13 | 14 | public Collection(T[] collection) => _array = collection; 15 | 16 | public Collection() : this((T[]) null) { } 17 | 18 | public static implicit operator Collection(List list) 19 | { 20 | return new Collection(list); 21 | } 22 | 23 | public static implicit operator Collection(T[] array) 24 | { 25 | return new Collection(array); 26 | } 27 | 28 | public static implicit operator T[] (Collection collection) => 29 | collection._array; 30 | 31 | public static implicit operator List(Collection collection) => new List(collection._array); 32 | 33 | public void ResetToLength(int length) 34 | { 35 | _array = new T[length]; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Editor/Util/Collection`1.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 38966a77f722447bbea651faccf0c832 3 | timeCreated: 1613221896 -------------------------------------------------------------------------------- /Editor/Util/CompilationChecker.cs: -------------------------------------------------------------------------------- 1 | #if GENERIC_UNITY_OBJECTS_DEBUG 2 | namespace GenericUnityObjects.Editor.Util 3 | { 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using UnityEditor; 7 | using Debug = UnityEngine.Debug; 8 | 9 | 10 | using UnityEditor.Compilation; 11 | 12 | 13 | /// 14 | /// Logs how many assemblies were compiled. It may be useful to check that only the assemblies you expect to be 15 | /// affected are compiled and not more. 16 | /// 17 | [InitializeOnLoad] 18 | internal static class CompilationChecker 19 | { 20 | private static readonly List _assemblies; 21 | 22 | static CompilationChecker() 23 | { 24 | CompilationPipeline.compilationStarted += OnCompilationStarted; 25 | CompilationPipeline.compilationFinished += OnCompilationFinished; 26 | #pragma warning disable 618 27 | CompilationPipeline.assemblyCompilationStarted += OnAssemblyCompilationStarted; 28 | #pragma warning restore 618 29 | _assemblies = new List(); 30 | } 31 | 32 | private static void OnCompilationStarted(object context) 33 | { 34 | _assemblies.Clear(); 35 | } 36 | 37 | private static void OnCompilationFinished(object context) 38 | { 39 | string assemblyNames = string.Join(", ", _assemblies 40 | .Select(name => name.Replace("Library/ScriptAssemblies/", string.Empty) 41 | .Replace(".dll", string.Empty))); 42 | 43 | Debug.Log($"{_assemblies.Count} assemblies were compiled: {assemblyNames}"); 44 | } 45 | 46 | private static void OnAssemblyCompilationStarted(string assemblyName) 47 | { 48 | _assemblies.Add(assemblyName); 49 | } 50 | } 51 | } 52 | #endif -------------------------------------------------------------------------------- /Editor/Util/CompilationChecker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 400729803d094715989b3736190fa7b8 3 | timeCreated: 1609239370 -------------------------------------------------------------------------------- /Editor/Util/CompilationHelper.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.Util 2 | { 3 | using UnityEditor; 4 | using UnityEditor.Compilation; 5 | using UnityEngine; 6 | 7 | [InitializeOnLoad] 8 | internal static class CompilationHelper 9 | { 10 | private const string CompiledOnceKey = "CompiledOnce"; 11 | 12 | private static double _recompilationTime; 13 | 14 | public static bool RecompilationRequested { get; private set; } 15 | 16 | static CompilationHelper() 17 | { 18 | EditorApplication.quitting += () => 19 | { 20 | PlayerPrefs.DeleteKey(CompiledOnceKey); 21 | PlayerPrefs.Save(); 22 | }; 23 | 24 | _recompilationTime = EditorApplication.timeSinceStartup; 25 | } 26 | 27 | public static void RecompileOnce() 28 | { 29 | RecompilationRequested = true; 30 | 31 | var timeSinceRecompilation = EditorApplication.timeSinceStartup - _recompilationTime; 32 | 33 | // Recompilation doesn't work when it is requested right after the domain reload, for some reason 34 | if (timeSinceRecompilation < 1) 35 | { 36 | EditorCoroutineHelper.Delay(RecompileOnceImpl, 1 - (float) timeSinceRecompilation); 37 | } 38 | else 39 | { 40 | RecompileOnceImpl(); 41 | } 42 | } 43 | 44 | private static void RecompileOnceImpl() 45 | { 46 | if (PlayerPrefs.GetInt(CompiledOnceKey) == 1) 47 | return; 48 | 49 | PlayerPrefs.SetInt(CompiledOnceKey, 1); 50 | PlayerPrefs.Save(); 51 | CompilationPipeline.RequestScriptCompilation(); 52 | } 53 | 54 | public static void CompilationNotNeeded() 55 | { 56 | PlayerPrefs.SetInt(CompiledOnceKey, 0); 57 | PlayerPrefs.Save(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Editor/Util/CompilationHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 092f07cc1bd3464b80137b497e84747f 3 | timeCreated: 1630846037 -------------------------------------------------------------------------------- /Editor/Util/ConcreteClassCreator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b50896001dc34345a30a0823ddf35172 3 | timeCreated: 1608548825 -------------------------------------------------------------------------------- /Editor/Util/EditorCoroutineHelper.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.Util 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using UnityEditor; 7 | using Debug = UnityEngine.Debug; 8 | 9 | public static class EditorCoroutineHelper 10 | { 11 | private static readonly List<(Action Action, float Time)> _currentTimeActions = new List<(Action Action, float Time)>(); 12 | private static readonly List<(Action Action, int Frames)> _currentFrameActions = new List<(Action Action, int Frames)>(); 13 | 14 | private static readonly Stopwatch _stopwatch; 15 | private static long _elapsedTime; 16 | 17 | static EditorCoroutineHelper() 18 | { 19 | _stopwatch = new Stopwatch(); 20 | _stopwatch.Start(); 21 | EditorApplication.update += Update; 22 | } 23 | 24 | public static void Delay(Action action, float timeInSeconds) 25 | { 26 | if (timeInSeconds <= 0f) 27 | { 28 | action.Invoke(); 29 | return; 30 | } 31 | 32 | _currentTimeActions.Add((action, timeInSeconds)); 33 | } 34 | 35 | public static void DelayFrames(Action action, int frames) 36 | { 37 | if (frames <= 0) 38 | { 39 | action.Invoke(); 40 | return; 41 | } 42 | 43 | _currentFrameActions.Add((action, frames)); 44 | } 45 | 46 | private static void Update() 47 | { 48 | InvokeTimeActions(); 49 | InvokeFrameActions(); 50 | } 51 | 52 | private static void InvokeTimeActions() 53 | { 54 | float timeSinceLastFrameMilliseconds = _stopwatch.ElapsedMilliseconds - _elapsedTime; 55 | _elapsedTime = _stopwatch.ElapsedMilliseconds; 56 | 57 | int i = 0; 58 | 59 | while (i < _currentTimeActions.Count) 60 | { 61 | (Action action, float time) = _currentTimeActions[i]; 62 | time -= timeSinceLastFrameMilliseconds / 1000f; 63 | 64 | if (time > 0f) 65 | { 66 | _currentTimeActions[i] = (action, time); 67 | i++; 68 | continue; 69 | } 70 | 71 | action.Invoke(); 72 | _currentTimeActions.RemoveAt(i); 73 | } 74 | } 75 | 76 | private static void InvokeFrameActions() 77 | { 78 | int i = 0; 79 | 80 | while (i < _currentFrameActions.Count) 81 | { 82 | (Action action, int frames) = _currentFrameActions[i]; 83 | frames--; 84 | 85 | if (frames > 0) 86 | { 87 | _currentFrameActions[i] = (action, frames); 88 | i++; 89 | continue; 90 | } 91 | 92 | action.Invoke(); 93 | _currentFrameActions.RemoveAt(i); 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Editor/Util/EditorCoroutineHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b3cccee0ded6114aa7baff3d5348a5a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Util/EditorOnlySingletonSO.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.Util 2 | { 3 | using GenericUnityObjects.Util; 4 | 5 | /// 6 | /// Completely identical to except that assets are saved to 7 | /// an Editor/Resources folder instead of Resources. 8 | /// 9 | /// Type of singleton ScriptableObject to create. 10 | internal abstract class EditorOnlySingletonSO : SingletonScriptableObject 11 | where T : EditorOnlySingletonSO, ICanBeInitialized 12 | { 13 | private static readonly InstanceGetter _getter = new InstanceGetter(Config.EditorResourcesPath); 14 | 15 | /// Retrieves an instance to the asset. 16 | public static T Instance => _getter.GetInstance(); 17 | } 18 | } -------------------------------------------------------------------------------- /Editor/Util/EditorOnlySingletonSO.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ea08033cb59420386638826e99cdf81 3 | timeCreated: 1609339752 -------------------------------------------------------------------------------- /Editor/Util/ExampleInstaller.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.IntegrationTests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Editor.Util; 6 | using JetBrains.Annotations; 7 | using SolidUtilities.Editor; 8 | using UnityEditor; 9 | using Object = UnityEngine.Object; 10 | 11 | /// 12 | /// A class that helps to install Samples. When a sample is imported to project, its concrete class are not generated 13 | /// yet and need to be generated manually. They call this class to generate a bunch of concrete classes at once. 14 | /// 15 | public static class ExampleInstaller 16 | { 17 | [UsedImplicitly] 18 | public static void AddConcreteClasses(KeyValuePair[] typesToAdd, Action afterAddingTypes) 19 | where TObject : Object 20 | { 21 | using (AssetDatabaseHelper.DisabledScope()) 22 | { 23 | foreach (var pair in typesToAdd) 24 | { 25 | ConcreteClassCreator.CreateConcreteClass(pair.Key, pair.Value); 26 | } 27 | } 28 | 29 | PersistentStorage.ExecuteOnScriptsReload(afterAddingTypes); 30 | AssetDatabase.Refresh(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Editor/Util/ExampleInstaller.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 670019bd5f9748b096730740ebb45c7e 3 | timeCreated: 1611730509 -------------------------------------------------------------------------------- /Editor/Util/IconFinder.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.Util 2 | { 3 | using System; 4 | using System.IO; 5 | using UnityEngine.Assertions; 6 | using UnityEditor; 7 | using UnityEngine; 8 | 9 | internal static class IconFinder 10 | { 11 | public static bool TryGetCustomIcon(string genericTypeGUID, out Texture2D customIcon, bool isScriptableObject) 12 | { 13 | customIcon = null; 14 | 15 | string assetPath = AssetDatabase.GUIDToAssetPath(genericTypeGUID); 16 | 17 | if (string.IsNullOrEmpty(assetPath)) 18 | return false; 19 | 20 | if (TryGetCustomIcon(assetPath, out customIcon)) 21 | return true; 22 | 23 | // If generated type inherits from MonoBehaviour, a default script icon must be set, but for scriptable 24 | // objects, it is not the case. 25 | return ! isScriptableObject && TryGetDefaultIconFromMonoBehaviourScript(assetPath, out customIcon); 26 | } 27 | 28 | private static bool TryGetDefaultIconFromMonoBehaviourScript(string assetPath, out Texture2D customIcon) 29 | { 30 | var monoScript = AssetDatabase.LoadAssetAtPath(assetPath); 31 | 32 | if (monoScript is null) 33 | { 34 | customIcon = null; 35 | return false; 36 | } 37 | 38 | customIcon = AssetPreview.GetMiniThumbnail(monoScript); 39 | return true; 40 | } 41 | 42 | private static bool TryGetCustomIcon(string assetPath, out Texture2D customIcon) 43 | { 44 | // Unity doesn't expose any method to get icon guid or Texture2D from MonoScript, so we have to parse the .meta file manually. 45 | // AssetPreview.GetMiniThumbnail returns the icon, but in 2021 it has the DontSave flag and can't be used to set as a custom icon for an asset. 46 | 47 | string iconLine = GetIconLine(assetPath); 48 | 49 | if (iconLine == null) 50 | { 51 | customIcon = null; 52 | return false; 53 | } 54 | 55 | if (!GetGUIDFromIconLine(iconLine, out string guid)) 56 | { 57 | customIcon = null; 58 | return false; 59 | } 60 | 61 | string texturePath = AssetDatabase.GUIDToAssetPath(guid); 62 | customIcon = AssetDatabase.LoadAssetAtPath(texturePath); 63 | return customIcon != null; 64 | } 65 | 66 | private static bool GetGUIDFromIconLine(string iconLine, out string guid) 67 | { 68 | int guidIndex = iconLine.IndexOf("guid: ", StringComparison.Ordinal); 69 | 70 | // There may be instanceID instead of guid on the icon line. 71 | if (guidIndex == -1 || iconLine.Length < guidIndex + 37) 72 | { 73 | guid = null; 74 | return false; 75 | } 76 | 77 | guid = iconLine.Substring(guidIndex + 6, 32); 78 | return true; 79 | } 80 | 81 | private static string GetIconLine(string assetPath) 82 | { 83 | string[] metaContentLines = File.ReadAllLines($"{assetPath}.meta"); 84 | 85 | foreach (string line in metaContentLines) 86 | { 87 | if (line.StartsWith(" icon: ")) 88 | return line; 89 | } 90 | 91 | return null; 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /Editor/Util/IconFinder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: af218d2005874e0ab15732da87036b65 3 | timeCreated: 1619284383 -------------------------------------------------------------------------------- /Editor/Util/IconSetter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56806844c1434d41ba8220c148a51a4d 3 | timeCreated: 1610535111 -------------------------------------------------------------------------------- /Editor/Util/MenuItemMethod.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.Util 2 | { 3 | using System; 4 | using GenericUnityObjects.Util; 5 | using SolidUtilities; 6 | using UnityEngine; 7 | 8 | /// 9 | /// A struct that holds all variables needed to create a MenuItem method. 10 | /// 11 | [Serializable] 12 | internal class MenuItemMethod : IEquatable 13 | { 14 | public readonly Type Type; 15 | 16 | [SerializeField] private string _typeName; 17 | [SerializeField] private string _fileName; 18 | [SerializeField] private string _menuName; 19 | [SerializeField] private int _order; 20 | 21 | public string TypeName => _typeName; 22 | 23 | public string FileName => _fileName; 24 | 25 | public string MenuName => _menuName; 26 | 27 | public int Order => _order; 28 | 29 | public MenuItemMethod(string fileName, string menuName, int order, Type genericTypeWithoutArgs) 30 | { 31 | Type = genericTypeWithoutArgs; 32 | 33 | _typeName = TypeUtility.GetTypeNameAndAssembly(Type); 34 | _fileName = fileName ?? $"New {Type.Name}"; 35 | _menuName = menuName ?? TypeUtility.GetNiceNameOfGenericType(Type); 36 | _order = order; 37 | } 38 | 39 | public bool Equals(MenuItemMethod p) 40 | { 41 | // If parameter is null, return false. 42 | if (ReferenceEquals(p, null)) 43 | { 44 | return false; 45 | } 46 | 47 | // Optimization for a common success case. 48 | if (ReferenceEquals(this, p)) 49 | { 50 | return true; 51 | } 52 | 53 | // If run-time types are not exactly the same, return false. 54 | if (this.GetType() != p.GetType()) 55 | { 56 | return false; 57 | } 58 | 59 | // Return true if the fields match. 60 | // Note that the base class is not invoked because it is 61 | // System.Object, which defines Equals as reference equality. 62 | return TypeName == p.TypeName 63 | && _fileName == p._fileName 64 | && _menuName == p._menuName 65 | && _order == p._order; 66 | } 67 | 68 | public static bool operator ==(MenuItemMethod lhs, MenuItemMethod rhs) 69 | { 70 | return lhs?.Equals(rhs) ?? ReferenceEquals(rhs, null); 71 | } 72 | 73 | public static bool operator !=(MenuItemMethod lhs, MenuItemMethod rhs) 74 | { 75 | return ! (lhs == rhs); 76 | } 77 | 78 | public override bool Equals(object obj) 79 | { 80 | return this.Equals(obj as MenuItemMethod); 81 | } 82 | 83 | public override int GetHashCode() 84 | { 85 | unchecked 86 | { 87 | int hash = 17; 88 | hash = hash * 23 + _typeName.GetHashCode(); 89 | hash = hash * 23 + _fileName.GetHashCode(); 90 | hash = hash * 23 + _menuName.GetHashCode(); 91 | hash = hash * 23 + _order.GetHashCode(); 92 | return hash; 93 | } 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /Editor/Util/MenuItemMethod.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8311455170f84429b2706146ccce76f5 3 | timeCreated: 1604309645 -------------------------------------------------------------------------------- /Editor/Util/NonGenericAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Editor.Util 2 | { 3 | using System; 4 | using GenericUnityObjects.Util; 5 | using TypeReferences; 6 | 7 | /// 8 | /// This attribute is applied to so that they show only the types that 9 | /// are relevant to user. It filters out generic types, as well as setting a number of properties to preset values. 10 | /// 11 | internal class NonGenericAttribute : InheritsAttribute 12 | { 13 | public NonGenericAttribute(Type[] baseTypes) 14 | : base(baseTypes) 15 | { 16 | ShowNoneElement = true; 17 | ShortName = true; 18 | 19 | // When type has inheritance constraints, there's usually only a few types available, so expanding all 20 | // folders will look nice. 21 | if (baseTypes != null && baseTypes.Length != 0) 22 | ExpandAllFolders = true; 23 | } 24 | 25 | public void ChangeBaseTypes(Type[] baseTypes) 26 | { 27 | BaseTypes = baseTypes; 28 | 29 | if (baseTypes != null && baseTypes.Length != 0) 30 | ExpandAllFolders = true; 31 | } 32 | 33 | internal override bool MatchesRequirements(Type type) 34 | { 35 | return base.MatchesRequirements(type) && ! type.IsGenericTypeDefinition; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Editor/Util/NonGenericAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 09b631879c1a47a4bde7d3203a2c2c41 3 | timeCreated: 1611781395 -------------------------------------------------------------------------------- /Editor/Util/PersistentStorage.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d75b2e71a864ef9b6262b87c89b28d0 3 | timeCreated: 1603364135 -------------------------------------------------------------------------------- /GenericUnityEditorInternals.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidAlloy/GenericUnityObjects/adc7802151bbcc4a1cc68cfcab6b84c69002fc6e/GenericUnityEditorInternals.dll -------------------------------------------------------------------------------- /GenericUnityEditorInternals.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 30e1e47181bed9444a9d9f96b30053a5 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 1 11 | isExplicitlyReferenced: 1 12 | validateReferences: 0 13 | platformData: 14 | - first: 15 | : Any 16 | second: 17 | enabled: 0 18 | settings: 19 | Exclude Android: 1 20 | Exclude Editor: 0 21 | Exclude Linux64: 1 22 | Exclude OSXUniversal: 1 23 | Exclude Win: 1 24 | Exclude Win64: 1 25 | - first: 26 | Android: Android 27 | second: 28 | enabled: 0 29 | settings: 30 | CPU: ARMv7 31 | - first: 32 | Any: 33 | second: 34 | enabled: 0 35 | settings: {} 36 | - first: 37 | Editor: Editor 38 | second: 39 | enabled: 1 40 | settings: 41 | CPU: AnyCPU 42 | DefaultValueInitialized: true 43 | OS: AnyOS 44 | - first: 45 | Standalone: Linux64 46 | second: 47 | enabled: 0 48 | settings: 49 | CPU: None 50 | - first: 51 | Standalone: OSXUniversal 52 | second: 53 | enabled: 0 54 | settings: 55 | CPU: None 56 | - first: 57 | Standalone: Win 58 | second: 59 | enabled: 0 60 | settings: 61 | CPU: None 62 | - first: 63 | Standalone: Win64 64 | second: 65 | enabled: 0 66 | settings: 67 | CPU: None 68 | - first: 69 | Windows Store Apps: WindowsStoreApps 70 | second: 71 | enabled: 0 72 | settings: 73 | CPU: AnyCPU 74 | userData: 75 | assetBundleName: 76 | assetBundleVariant: 77 | -------------------------------------------------------------------------------- /GenericUnityEditorInternals.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidAlloy/GenericUnityObjects/adc7802151bbcc4a1cc68cfcab6b84c69002fc6e/GenericUnityEditorInternals.pdb -------------------------------------------------------------------------------- /GenericUnityEditorInternals.pdb.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c377f37562420bd4fa17712d5ea95c40 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License modified with Commons Clause Restriction 2 | 3 | Copyright (c) 2020 SolidAlloy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | Commons Clause Restriction 24 | 25 | The Software is provided to you by the Licensor under the License, as defined below, subject to 26 | the following condition. 27 | Without limiting other conditions in the License, the grant of rights under the License will not 28 | include, and the License does not grant to you, the right to Sell the Software. 29 | For purposes of the foregoing, “Sell” means practicing any or all of the rights granted to you 30 | under the License to provide to third parties, for a fee or other consideration (including without 31 | limitation fees for hosting or consulting/ support services related to the Software), a product or 32 | service whose value derives, entirely or substantially, from the functionality of the Software. 33 | Any license notice or attribution required by the License must also include this Commons Cause 34 | License Condition notice. 35 | 36 | For purposes of the clause above, the “Licensor” is SolidAlloy, the “License” is the MIT License and the Software is the GenericUnityObjects software provided with this 37 | notice. -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e69416df6b32b3c4aa69c8b7acb4ee83 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /OdinInternals.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidAlloy/GenericUnityObjects/adc7802151bbcc4a1cc68cfcab6b84c69002fc6e/OdinInternals.dll -------------------------------------------------------------------------------- /OdinInternals.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6e7e2f8abfc27b2418c3edf3a40b6fda 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: 9 | - ODIN_INSPECTOR 10 | isPreloaded: 0 11 | isOverridable: 1 12 | isExplicitlyReferenced: 1 13 | validateReferences: 1 14 | platformData: 15 | - first: 16 | : Any 17 | second: 18 | enabled: 0 19 | settings: 20 | Exclude Editor: 0 21 | Exclude Linux64: 1 22 | Exclude OSXUniversal: 1 23 | Exclude Win: 1 24 | Exclude Win64: 1 25 | - first: 26 | Any: 27 | second: 28 | enabled: 0 29 | settings: {} 30 | - first: 31 | Editor: Editor 32 | second: 33 | enabled: 1 34 | settings: 35 | CPU: AnyCPU 36 | DefaultValueInitialized: true 37 | OS: AnyOS 38 | - first: 39 | Standalone: Linux64 40 | second: 41 | enabled: 0 42 | settings: 43 | CPU: None 44 | - first: 45 | Standalone: OSXUniversal 46 | second: 47 | enabled: 0 48 | settings: 49 | CPU: None 50 | - first: 51 | Standalone: Win 52 | second: 53 | enabled: 0 54 | settings: 55 | CPU: None 56 | - first: 57 | Standalone: Win64 58 | second: 59 | enabled: 0 60 | settings: 61 | CPU: None 62 | - first: 63 | Windows Store Apps: WindowsStoreApps 64 | second: 65 | enabled: 0 66 | settings: 67 | CPU: AnyCPU 68 | userData: 69 | assetBundleName: 70 | assetBundleVariant: 71 | -------------------------------------------------------------------------------- /OdinInternals.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SolidAlloy/GenericUnityObjects/adc7802151bbcc4a1cc68cfcab6b84c69002fc6e/OdinInternals.pdb -------------------------------------------------------------------------------- /OdinInternals.pdb.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ba9ce2e7baedea649aa360b71ebdb2f0 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 15402bee27cab124385e6cd78cad93d9 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79daab300d2b8274cbc9714cca755fb3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/ApplyToChildrenAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] 9 | public class ApplyToChildrenAttribute : Attribute 10 | { 11 | public readonly IReadOnlyCollection Attributes; 12 | 13 | public ApplyToChildrenAttribute(params Type[] attributeTypes) 14 | { 15 | Attributes = attributeTypes.Where(attributeType => attributeType.GetCustomAttribute()?.Inherited is false).ToList(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Runtime/ApplyToChildrenAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a2674cb6e3ee4a2cb76a9ef1cdfb2da5 3 | timeCreated: 1629956928 -------------------------------------------------------------------------------- /Runtime/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("GenericUnityObjects.Editor")] 4 | [assembly: InternalsVisibleTo("GenericUnityObjects.EditorTests")] 5 | [assembly: InternalsVisibleTo("GenericUnityObjects.IntegrationTests")] 6 | [assembly: InternalsVisibleTo("GenericUnityEditorInternals")] 7 | [assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.003")] // Debug name of GenericUnityEditorInternals 8 | [assembly: InternalsVisibleTo("GenericScriptableArchitecture.Timeline.Editor")] -------------------------------------------------------------------------------- /Runtime/AssemblyInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ac5fab1e3b0b4b6daa768bd09ef7092f 3 | timeCreated: 1607506206 -------------------------------------------------------------------------------- /Runtime/CreatableAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects 2 | { 3 | using System; 4 | using UnityEngine; 5 | 6 | [AttributeUsage(AttributeTargets.Field)] 7 | public class CreatableAttribute : PropertyAttribute { } 8 | } -------------------------------------------------------------------------------- /Runtime/CreatableAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ab4a050c1aab4982bbfb85503220b06f 3 | timeCreated: 1629529416 -------------------------------------------------------------------------------- /Runtime/CreateGenericAssetMenuAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects 2 | { 3 | using System; 4 | using JetBrains.Annotations; 5 | using UnityEngine; 6 | 7 | /// 8 | /// Marks a ScriptableObject-derived type to be automatically listed in the Assets/Create submenu, so that 9 | /// instances of the type can be easily created and stored in the project as ".asset" files. 10 | /// 11 | [AttributeUsage(AttributeTargets.Class, Inherited = false)] 12 | [BaseTypeRequired(typeof(ScriptableObject))] 13 | public class CreateGenericAssetMenuAttribute : Attribute 14 | { 15 | /// The default file name used by newly created instances of this type. 16 | [PublicAPI] public string FileName; 17 | 18 | /// The display name for this type shown in the Assets/Create menu. 19 | [PublicAPI] public string MenuName; 20 | 21 | /// The position of the menu item within the Assets/Create menu. 22 | [PublicAPI] public int Order = 0; 23 | } 24 | } -------------------------------------------------------------------------------- /Runtime/CreateGenericAssetMenuAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c2a3103ceaf5ab41812b17f695b2504 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/GameObjectExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4d472bc0ffc740f4997c6a198c132149 3 | timeCreated: 1607682862 -------------------------------------------------------------------------------- /Runtime/GenericScriptableObject.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects 2 | { 3 | using System; 4 | using System.Linq; 5 | using JetBrains.Annotations; 6 | using UnityEngine; 7 | using Util; 8 | 9 | /// 10 | /// Inherit from this class to create a generic ScriptableObject. 11 | /// Add a menu to create assets using . 12 | /// 13 | [Serializable] 14 | public class GenericScriptableObject : ScriptableObject 15 | { 16 | /// Creates an instance of . Has support for generic scriptable objects. 17 | /// Type derived from . 18 | /// Instance of . 19 | /// 20 | /// If an asset with such generic arguments was not created through the Assets/Create menu yet, and is 21 | /// instantiated in an IL2CPP build. 22 | /// 23 | [PublicAPI, Pure] 24 | public static new ScriptableObject CreateInstance(Type type) 25 | { 26 | if ( ! type.IsGenericType) 27 | return ScriptableObject.CreateInstance(type); 28 | 29 | if (ScriptableObjectsDatabase.TryGetConcreteType(type, out Type concreteType)) 30 | return ScriptableObject.CreateInstance(concreteType); 31 | 32 | concreteType = GeneratedUnityObjectCache.GetSOClass(type); 33 | 34 | if (concreteType != null) 35 | return ScriptableObject.CreateInstance(concreteType); 36 | 37 | throw new NotSupportedException( 38 | $"There is no {type.GetGenericTypeDefinition()} derivative with type parameters " + 39 | $"{string.Join(", ", type.GetGenericArguments().Select(typeParam => typeParam.Name))} " + 40 | "and a type cannot be created dynamically in an IL2CPP build. " + 41 | "Please create an asset with such type parameters once to be able to create it at runtime."); 42 | } 43 | 44 | /// 45 | /// Creates an instance of . Has support for generic scriptable objects. 46 | /// 47 | /// Type derived from ScriptableObject. 48 | /// Instance of >. 49 | /// 50 | /// If an asset with such generic arguments was not created through the Assets/Create menu yet, and is 51 | /// instantiated in an IL2CPP build. 52 | /// 53 | [PublicAPI, Pure] 54 | public static new T CreateInstance() 55 | where T : ScriptableObject 56 | { 57 | return (T) CreateInstance(typeof(T)); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Runtime/GenericScriptableObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a27715324c3e0304e87e14609ea50189 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/GenericUnityObjects.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GenericUnityObjects", 3 | "rootNamespace": "GenericUnityObjects", 4 | "references": [ 5 | "TypeReferences", 6 | "SolidUtilities", 7 | "SolidUtilities.Editor" 8 | ], 9 | "includePlatforms": [], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [], 17 | "noEngineReferences": false 18 | } -------------------------------------------------------------------------------- /Runtime/GenericUnityObjects.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9168b41b563c2d84b94cfe84212541a9 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Util.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2e12e5eea9984213b49196bfa847f012 3 | timeCreated: 1607951579 -------------------------------------------------------------------------------- /Runtime/Util/BehaviourSelector.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using System.Linq; 5 | using TypeReferences; 6 | using UnityEngine; 7 | using UnityEngine.Assertions; 8 | 9 | /// 10 | /// Parent class to all Generic MonoBehaviour selectors. It is a component that is added to game objects and allows 11 | /// to choose generic arguments to add the actual generic component. 12 | /// 13 | public abstract class BehaviourSelector : MonoBehaviour 14 | { 15 | [SerializeField] internal bool JustBeenAdded; 16 | [SerializeField] internal TypeReferenceWithBaseTypes[] TypeRefs; 17 | 18 | // This field is overriden by individual selectors and represents a generic type definition of a generic MonoBehaviour. 19 | public abstract Type GenericBehaviourType { get; } 20 | 21 | private void Reset() 22 | { 23 | JustBeenAdded = true; 24 | 25 | Assert.IsTrue(GenericBehaviourType.IsGenericTypeDefinition); 26 | 27 | int argsNum = GenericBehaviourType.GetGenericArguments().Length; 28 | TypeRefs = new TypeReferenceWithBaseTypes[argsNum]; 29 | 30 | var constraints = GenericBehaviourType.GetGenericArguments() 31 | .Select(type => type.GetGenericParameterConstraints()) 32 | .ToArray(); 33 | 34 | for (int i = 0; i < argsNum; i++) 35 | { 36 | TypeRefs[i] = new TypeReferenceWithBaseTypes 37 | { 38 | BaseTypeNames = constraints[i] 39 | .Select(TypeReference.GetTypeNameAndAssembly) 40 | .ToArray() 41 | }; 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Runtime/Util/BehaviourSelector.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6cf710599a5749fb9724083c6d026ad4 3 | timeCreated: 1607506085 -------------------------------------------------------------------------------- /Runtime/Util/Config.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using System.IO; 5 | using UnityEngine; 6 | 7 | /// 8 | /// Holder of constant values used by multiple classes in the plugin. 9 | /// 10 | internal static class Config 11 | { 12 | public const string ResourcesPath = MainFolderPath + "/Resources"; 13 | public const string EditorResourcesPath = MainFolderPath + "/EditorResources"; 14 | public const string ScriptableObjectsPath = AssembliesDirPath + "/ScriptableObjects"; 15 | public const string MonoBehavioursPath = AssembliesDirPath + "/MonoBehaviours"; 16 | public const string BehaviourSelectorsPath = AssembliesDirPath + "/BehaviourSelectors"; 17 | public const string AssembliesDirPath = MainFolderPath + "/Assemblies"; 18 | public const string ConcreteClassNamespace = "GenericUnityObjects.ConcreteClasses"; 19 | private const string MainFolderPath = "Assets/Plugins/GenericUnityObjects"; 20 | 21 | public static string GetAssemblyPathForType(Type parentType) 22 | { 23 | if (typeof(ScriptableObject).IsAssignableFrom(parentType)) 24 | { 25 | return ScriptableObjectsPath; 26 | } 27 | 28 | if (typeof(BehaviourSelector).IsAssignableFrom(parentType)) 29 | { 30 | return BehaviourSelectorsPath; 31 | } 32 | 33 | if (typeof(MonoBehaviour).IsAssignableFrom(parentType)) 34 | { 35 | return MonoBehavioursPath; 36 | } 37 | 38 | return AssembliesDirPath; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Runtime/Util/Config.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e67a664e23184cac9dc54ac28881a20c 3 | timeCreated: 1607516281 -------------------------------------------------------------------------------- /Runtime/Util/DebugUtility.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System.Diagnostics; 4 | using Debug = UnityEngine.Debug; 5 | 6 | /// 7 | /// Holder of methods that are fired only if GENERIC_UNITY_OBJECTS_DEBUG is defined. 8 | /// 9 | public static class DebugUtility 10 | { 11 | [Conditional("GENERIC_UNITY_OBJECTS_DEBUG")] 12 | public static void Log(string message) => Debug.Log(message); 13 | } 14 | } -------------------------------------------------------------------------------- /Runtime/Util/DebugUtility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3451285e524e4b34ba40f5dd41de71e4 3 | timeCreated: 1608539729 -------------------------------------------------------------------------------- /Runtime/Util/GeneratedUnityObjectCache.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 40e7809186254f5a817cc9a098d3b8c3 3 | timeCreated: 1609327978 -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8045a44a1f1c428daf25963c25235ef0 3 | timeCreated: 1611849342 -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/BehavioursDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using UnityEngine; 4 | 5 | /// 6 | /// All the work is done in the parent class. This is implemented just to create a ScriptableObject asset. 7 | /// 8 | internal class BehavioursDatabase : GenericTypesDatabase { } 9 | } -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/BehavioursDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 59e0c54c3d494d969fa8a47885b1ba7c 3 | timeCreated: 1609676543 -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/GenericTypesDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a95c703144c84af41b169f28f79438e0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/ScriptableObjectsDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using UnityEngine; 4 | 5 | /// 6 | /// All the work is done in the parent class. This is implemented just to create a ScriptableObject asset. 7 | /// 8 | internal class ScriptableObjectsDatabase : GenericTypesDatabase { } 9 | } -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/ScriptableObjectsDatabase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 402cb5eb17974d24bb00263b59dc709c 3 | timeCreated: 1609676549 -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/SerializableType.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using UnityEngine; 5 | 6 | [Serializable] 7 | internal struct SerializableType : IEquatable 8 | { 9 | [SerializeField] private string _typeNameAndAssembly; 10 | private Type _value; 11 | private bool _triedSettingTypeOnce; 12 | 13 | public Type Value 14 | { 15 | get 16 | { 17 | if (_value != null || _triedSettingTypeOnce) 18 | return _value; 19 | 20 | _value = Type.GetType(_typeNameAndAssembly); 21 | _triedSettingTypeOnce = true; 22 | return _value; 23 | } 24 | } 25 | 26 | public SerializableType(Type type) 27 | { 28 | _value = type; 29 | _typeNameAndAssembly = TypeUtility.GetTypeNameAndAssembly(type); 30 | _triedSettingTypeOnce = false; 31 | } 32 | 33 | public override bool Equals(object obj) 34 | { 35 | return obj is SerializableType type && this.Equals(type); 36 | } 37 | 38 | public bool Equals(SerializableType p) 39 | { 40 | return _typeNameAndAssembly == p._typeNameAndAssembly; 41 | } 42 | 43 | // Serialized field cannot be readonly, so just need to have caution when working with it. 44 | public override int GetHashCode() => _typeNameAndAssembly.GetHashCode(); 45 | 46 | public static bool operator ==(SerializableType lhs, SerializableType rhs) => lhs.Equals(rhs); 47 | 48 | public static bool operator !=(SerializableType lhs, SerializableType rhs) => ! lhs.Equals(rhs); 49 | 50 | public static implicit operator Type(SerializableType typeReference) => typeReference.Value; 51 | 52 | public static implicit operator SerializableType(Type type) => new SerializableType(type); 53 | } 54 | } -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/SerializableType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 29b4198f1fff4d078a4558164085c7a8 3 | timeCreated: 1611849304 -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/SerializableTypeCollection.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using UnityEngine; 5 | 6 | [Serializable] 7 | internal struct SerializableTypeCollection 8 | { 9 | [SerializeField] private SerializableType[] _collection; 10 | 11 | public static implicit operator Type[](SerializableTypeCollection typeCollection) 12 | => Array.ConvertAll(typeCollection._collection, type => type); 13 | 14 | public static implicit operator SerializableTypeCollection(Type[] typeCollection) 15 | => new SerializableTypeCollection(typeCollection); 16 | 17 | public SerializableTypeCollection(Type[] typeCollection) 18 | => _collection = Array.ConvertAll(typeCollection, type => type); 19 | } 20 | } -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/SerializableTypeCollection.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c6b79655a14642948faf6fefcb6af2da 3 | timeCreated: 1611849298 -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/SerializableTypeDictionary.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using UnityEngine; 7 | 8 | [Serializable] 9 | internal struct SerializableTypeDictionary : ISerializationCallbackReceiver 10 | { 11 | private Dictionary _dict; 12 | 13 | [SerializeField] private SerializableTypeCollection[] _keys; 14 | [SerializeField] private SerializableType[] _values; 15 | 16 | public static implicit operator Dictionary(SerializableTypeDictionary serializableDictionary) => serializableDictionary._dict; 17 | 18 | public static implicit operator SerializableTypeDictionary(Dictionary dictionary) => new SerializableTypeDictionary(dictionary); 19 | 20 | public SerializableTypeDictionary(Dictionary dictionary) 21 | { 22 | _dict = dictionary; 23 | _keys = null; 24 | _values = null; 25 | } 26 | 27 | public void OnBeforeSerialize() 28 | { 29 | if (_dict == null) 30 | return; 31 | 32 | int dictLength = _dict.Count; 33 | 34 | _keys = new SerializableTypeCollection[dictLength]; 35 | _values = new SerializableType[dictLength]; 36 | 37 | int index = 0; 38 | 39 | foreach (var kvp in _dict) 40 | { 41 | _keys[index] = kvp.Key; 42 | _values[index] = kvp.Value; 43 | index++; 44 | } 45 | } 46 | 47 | public void OnAfterDeserialize() 48 | { 49 | if (_keys == null) 50 | return; 51 | 52 | int keysLength = _keys.Length; 53 | _dict = new Dictionary(keysLength, default(TypeArrayComparer)); 54 | 55 | for (int i = 0; i < keysLength; i++) 56 | { 57 | Type[] key = _keys[i]; 58 | Type value = _values[i]; 59 | 60 | if (key.Any(type => type == null) || value == null) 61 | continue; 62 | 63 | _dict.Add(key, value); 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/SerializableTypeDictionary.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fce0aa59d56341109c89f2cbe12a0756 3 | timeCreated: 1611849319 -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/TypeArrayComparer.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | internal readonly struct TypeArrayComparer : IEqualityComparer 8 | { 9 | public bool Equals(Type[] firstArray, Type[] secondArray) 10 | { 11 | if (firstArray == null && secondArray == null) 12 | return true; 13 | 14 | if (firstArray == null || secondArray == null) 15 | return false; 16 | 17 | return firstArray.SequenceEqual(secondArray); 18 | } 19 | 20 | public int GetHashCode(Type[] array) 21 | { 22 | int hashCode = 0; 23 | 24 | foreach (Type item in array) 25 | hashCode ^= item.GetHashCode(); 26 | 27 | return hashCode; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Runtime/Util/GenericTypesDatabase/TypeArrayComparer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 64f831aa6f234e39921776cbe0e1f994 3 | timeCreated: 1611849389 -------------------------------------------------------------------------------- /Runtime/Util/InstanceGetter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2ffbafd2cc3e4640bdcacb81a880645f 3 | timeCreated: 1610132430 -------------------------------------------------------------------------------- /Runtime/Util/SingletonScriptableObject.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using UnityEngine; 4 | #if UNITY_EDITOR 5 | using UnityEditor; 6 | #endif 7 | 8 | /// 9 | /// Abstract class for making reload-proof singletons out of ScriptableObjects 10 | /// 11 | /// Singleton type. 12 | internal abstract class SingletonScriptableObject : SingletonScriptableObject 13 | where T : SingletonScriptableObject, ICanBeInitialized 14 | { 15 | private static readonly InstanceGetter _getter = new InstanceGetter(Config.ResourcesPath); 16 | 17 | /// Retrieves an instance to the asset. 18 | public static T Instance => _getter.GetInstance(); 19 | 20 | protected new void SetDirty() 21 | { 22 | #if UNITY_EDITOR 23 | EditorUtility.SetDirty(this); 24 | #endif 25 | } 26 | } 27 | 28 | internal abstract class SingletonScriptableObject : ScriptableObject { } 29 | 30 | internal interface ICanBeInitialized 31 | { 32 | void Initialize(); 33 | } 34 | } -------------------------------------------------------------------------------- /Runtime/Util/SingletonScriptableObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f2935fed72d40a2a0d0531852e75543 3 | timeCreated: 1601467804 -------------------------------------------------------------------------------- /Runtime/Util/TypeReferenceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | 5 | internal static class TypeReferenceCollectionExtensions 6 | { 7 | public static Type[] CastToType(this TypeReferenceWithBaseTypes[] typeReferences) 8 | { 9 | var types = new Type[typeReferences.Length]; 10 | 11 | for (int i = 0; i < typeReferences.Length; i++) 12 | { 13 | types[i] = typeReferences[i].Type; 14 | } 15 | 16 | return types; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Runtime/Util/TypeReferenceCollectionExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fba29a1d8bd149518e3fd6cbf067d626 3 | timeCreated: 1602443801 -------------------------------------------------------------------------------- /Runtime/Util/TypeReferenceWithBaseTypes.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using TypeReferences; 5 | 6 | /// 7 | /// A that holds names of base type names. Base types are needed to constrain generic 8 | /// argument selection only to the types that can be chosen as a generic argument. 9 | /// 10 | [Serializable] 11 | internal class TypeReferenceWithBaseTypes : TypeReference 12 | { 13 | public string[] BaseTypeNames; 14 | public bool TriggerDropdownImmediately; 15 | } 16 | } -------------------------------------------------------------------------------- /Runtime/Util/TypeReferenceWithBaseTypes.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4367a4d5980342e9996ec6a8f6201388 3 | timeCreated: 1607506131 -------------------------------------------------------------------------------- /Runtime/Util/TypeUtility.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.Util 2 | { 3 | using System; 4 | using System.Linq; 5 | using JetBrains.Annotations; 6 | using SolidUtilities; 7 | #if UNITY_EDITOR 8 | using UnityEditor; 9 | #endif 10 | 11 | internal static class TypeUtility 12 | { 13 | public static Type GetEmptyTypeDerivedDirectlyFrom(Type parentType) 14 | { 15 | #if UNITY_EDITOR 16 | return TypeCache.GetTypesDerivedFrom(parentType) 17 | .FirstOrDefault(type => type.IsEmpty() && type.BaseType == parentType); 18 | #else 19 | return parentType.Assembly.GetTypes() 20 | .Where(parentType.IsAssignableFrom) 21 | .FirstOrDefault(type => type.IsEmpty() && type.BaseType == parentType); 22 | #endif 23 | } 24 | 25 | [CanBeNull] 26 | public static Type GetEmptyTypeDerivedFrom(Type parentType) 27 | { 28 | #if UNITY_EDITOR 29 | return TypeCache.GetTypesDerivedFrom(parentType) 30 | .FirstOrDefault(type => type.IsEmpty()); 31 | #else 32 | return parentType.Assembly.GetTypes() 33 | .Where(parentType.IsAssignableFrom) 34 | .FirstOrDefault(type => type.IsEmpty()); 35 | #endif 36 | } 37 | 38 | public static string GetTypeNameAndAssembly(Type type) 39 | { 40 | if (type == null) 41 | return string.Empty; 42 | 43 | if (type.FullName == null) 44 | throw new ArgumentException($"'{type}' does not have full name.", nameof(type)); 45 | 46 | return GetTypeNameAndAssembly(type.FullName, type.Assembly.GetName().Name); 47 | } 48 | 49 | public static string GetTypeNameAndAssembly(string typeFullName, string assemblyName) => 50 | $"{typeFullName}, {assemblyName}"; 51 | 52 | public static string GetNiceNameOfGenericType(Type genericType, bool fullName = false) 53 | { 54 | return TypeHelper.GetNiceNameOfGenericType(genericType, fullName).Replace('.', '/'); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Runtime/Util/TypeUtility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 52b1199f0d534c78afd74c6281cf2238 3 | timeCreated: 1608547578 -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d02e9947557461439e2e4de62b84754 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/MonoBehaviour Demo.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5387a2e8560c6143b55fa97dbd74e77 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18abf26c7624aa746b6ebbf353f85a0c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Archer.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.MonoBehaviour_Example 2 | { 3 | using UnityEngine; 4 | 5 | public class Archer : Warrior 6 | { 7 | [SerializeField] private int _level; 8 | [SerializeField] private int _attackDistance; 9 | 10 | public override int MaxHealth => _level * 100; 11 | 12 | public override void Attack(Warrior enemyWarrior) 13 | { 14 | if (Vector2.Distance(this.transform.position, enemyWarrior.transform.position) <= _attackDistance) 15 | enemyWarrior.CurrentHealth -= _level * 5; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Archer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bb7de12785dc4224906fea0f12f96f09 3 | timeCreated: 1607959344 -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ff3c65c2046f78b4780141174218cfdc 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Editor/Installer.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.MonoBehaviour_Example.Editor 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using IntegrationTests; 7 | using UnityEditor; 8 | using UnityEditor.Callbacks; 9 | using UnityEditor.SceneManagement; 10 | using UnityEngine; 11 | using UnityEngine.Assertions; 12 | using Util; 13 | 14 | public static class Installer 15 | { 16 | private static readonly string _behaviourSampleFolder = FindExampleFolder(); 17 | 18 | [DidReloadScripts((int)DidReloadScriptsOrder.AfterAssemblyGeneration)] 19 | public static void InstallBehaviours() 20 | { 21 | const string key = "InstallBehaviours"; 22 | 23 | if (PlayerPrefs.HasKey(key)) 24 | { 25 | PlayerPrefs.DeleteKey(key); 26 | return; 27 | } 28 | 29 | PlayerPrefs.SetInt(key, 1); 30 | 31 | var typesToAdd = new[] 32 | { 33 | new KeyValuePair(typeof(Unit<>), new[] { typeof(Archer) }), 34 | new KeyValuePair(typeof(Unit<>), new[] { typeof(Knight) }), 35 | }; 36 | 37 | ExampleInstaller.AddConcreteClasses( 38 | typesToAdd, 39 | AddComponentsDelayed); 40 | } 41 | 42 | private static string FindExampleFolder() 43 | { 44 | var guids = AssetDatabase.FindAssets("MonoBehaviour Example", new[] { "Assets/Samples" }); 45 | Assert.IsTrue(guids.Length == 1); 46 | return AssetDatabase.GUIDToAssetPath(guids[0]); 47 | } 48 | 49 | private static void AddComponentsDelayed() => EditorApplication.delayCall += AddComponents; 50 | 51 | private static void AddComponents() 52 | { 53 | var scene = EditorSceneManager.OpenScene($"{_behaviourSampleFolder}/MonoBehaviour Demo.unity", OpenSceneMode.Additive); 54 | var allGameObjects = scene.GetRootGameObjects(); 55 | 56 | var archersSquad = allGameObjects.First(go => go.name == "Archers Squad"); 57 | var archerUnitComponent = archersSquad.AddGenericComponent>(); 58 | Assert.IsNotNull(archerUnitComponent); 59 | archerUnitComponent.Warriors = archersSquad.GetComponentsInChildren(); 60 | 61 | var knightsSquad = allGameObjects.First(go => go.name == "Knights Squad"); 62 | var knightUnitComponent = knightsSquad.AddGenericComponent>(); 63 | Assert.IsNotNull(knightUnitComponent); 64 | knightUnitComponent.Warriors = knightsSquad.GetComponentsInChildren(); 65 | 66 | EditorSceneManager.SaveScene(scene); 67 | EditorSceneManager.CloseScene(scene, true); 68 | 69 | EditorApplication.delayCall -= AddComponents; 70 | DeleteItself(); 71 | } 72 | 73 | private static void DeleteItself() 74 | { 75 | string[] guids = AssetDatabase.FindAssets(nameof(Installer), new[] { _behaviourSampleFolder }); 76 | Assert.IsTrue(guids.Length == 1); 77 | string assetPath = AssetDatabase.GUIDToAssetPath(guids[0]); 78 | AssetDatabase.DeleteAsset(assetPath); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Editor/Installer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 72914374e93f37249952c59466dec8b6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Knight.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.MonoBehaviour_Example 2 | { 3 | using UnityEngine; 4 | 5 | public class Knight : Warrior 6 | { 7 | [SerializeField] private int _level; 8 | [SerializeField] private int _defense; 9 | 10 | public override int MaxHealth => _level * 200; 11 | 12 | public override void Attack(Warrior enemyWarrior) 13 | { 14 | if (Vector2.Distance(this.transform.position, enemyWarrior.transform.position) <= 1f) 15 | enemyWarrior.CurrentHealth -= _level * 10; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Knight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 24c07b3f054a4d7190db7572e101f131 3 | timeCreated: 1607959349 -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Unit`1.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.MonoBehaviour_Example 2 | { 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | public class Unit : MonoBehaviour 7 | where TWarrior : Warrior 8 | { 9 | public TWarrior[] Warriors; 10 | 11 | public int TotalCurrentHealth => Warriors.Sum(warrior => warrior.CurrentHealth); 12 | 13 | public int TotalMaxHealth => Warriors.Sum(warrior => warrior.MaxHealth); 14 | 15 | public void Move(Vector2 position) 16 | { 17 | foreach (TWarrior warrior in Warriors) 18 | warrior.Move(position); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Unit`1.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b7d0e3f1b55cbbf4f8ffd741a18f015b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Warrior.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.MonoBehaviour_Example 2 | { 3 | using UnityEngine; 4 | 5 | public abstract class Warrior : MonoBehaviour 6 | { 7 | private int _currentHealth; 8 | 9 | public abstract int MaxHealth { get; } 10 | 11 | public int CurrentHealth 12 | { 13 | get => _currentHealth; 14 | set => Mathf.Min(value, MaxHealth); 15 | } 16 | 17 | public void Move(Vector2 position) 18 | { 19 | transform.position = position; 20 | } 21 | 22 | public abstract void Attack(Warrior enemyWarrior); 23 | 24 | protected virtual void OnEnable() 25 | { 26 | _currentHealth = MaxHealth; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Samples~/MonoBehaviour Example/Scripts/Warrior.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d66a154367014b5bb1183c7b76c4e9e0 3 | timeCreated: 1607955595 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 47b3d09b9cab31346b95418ce0435b14 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 19a8cc19b3744516b79a167e5f1f4bfd 3 | timeCreated: 1602873799 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/Archer.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.ScriptableObject_Example 2 | { 3 | using UnityEngine; 4 | 5 | [CreateAssetMenu(menuName = "Classes/Archer")] 6 | public class Archer : WarriorClass 7 | { 8 | public WarriorStats Stats; 9 | 10 | public override bool HasMeleeAttack => false; 11 | 12 | public override bool HasRangedAttack => true; 13 | 14 | public override bool HasAOEAttack => false; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/Archer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 000e287a106e415e95a3c215d416486b 3 | timeCreated: 1602872208 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/Berserker.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.ScriptableObject_Example 2 | { 3 | using UnityEngine; 4 | 5 | [CreateAssetMenu(menuName = "Classes/Berserker")] 6 | public class Berserker : WarriorClass 7 | { 8 | public WarriorStats Stats; 9 | 10 | public override bool HasMeleeAttack => true; 11 | 12 | public override bool HasRangedAttack => false; 13 | 14 | public override bool HasAOEAttack => true; 15 | } 16 | } -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/Berserker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e36c3dcbc3241f6a10158e398512d37 3 | timeCreated: 1602872279 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/Knight.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.ScriptableObject_Example 2 | { 3 | using UnityEngine; 4 | 5 | [CreateAssetMenu(menuName = "Classes/Knight")] 6 | public class Knight : WarriorClass 7 | { 8 | public WarriorStats Stats; 9 | 10 | public override bool HasMeleeAttack => true; 11 | 12 | public override bool HasRangedAttack => false; 13 | 14 | public override bool HasAOEAttack => false; 15 | } 16 | } -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/Knight.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c74ad55232f4ce680f3fc54c402e7a3 3 | timeCreated: 1602872298 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/WarriorClass.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.ScriptableObject_Example 2 | { 3 | using SolidUtilities.Attributes; 4 | using UnityEngine; 5 | 6 | public abstract class WarriorClass : ScriptableObject 7 | { 8 | [SerializeField, ReadOnly] private bool _hasMeleeAttack; 9 | [SerializeField, ReadOnly] private bool _hasRangedAttack; 10 | [SerializeField, ReadOnly] private bool _hasAOEAttack; 11 | 12 | public abstract bool HasMeleeAttack { get; } 13 | 14 | public abstract bool HasRangedAttack { get; } 15 | 16 | public abstract bool HasAOEAttack { get; } 17 | 18 | public void TakeDamage() { } 19 | 20 | public void Attack() { } 21 | 22 | private void Reset() 23 | { 24 | _hasMeleeAttack = HasMeleeAttack; 25 | _hasRangedAttack = HasRangedAttack; 26 | _hasAOEAttack = HasAOEAttack; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Classes/WarriorClass.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0698dd5c9b734846af51b0622365ec2f 3 | timeCreated: 1602872098 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/GenericScriptableObjects.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ca580d3b8c4046e42bd379e294787070 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/GenericScriptableObjects/WarriorStats`1.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.ScriptableObject_Example 2 | { 3 | using System; 4 | using GenericUnityObjects; 5 | 6 | [Serializable] 7 | [CreateGenericAssetMenu] 8 | public class WarriorStats : GenericScriptableObject 9 | where TClass : WarriorClass 10 | { 11 | public int Health; 12 | public int Damage; 13 | 14 | public TClass[] FindAllWarriorsWithTheseStats() 15 | { 16 | return FindObjectsOfType(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/GenericScriptableObjects/WarriorStats`1.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f9463e2c87886f84680c6314cba8245b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/GenericScriptableObjects/WarriorsRelationship`2.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.ScriptableObject_Example 2 | { 3 | using System; 4 | using GenericUnityObjects; 5 | 6 | public enum RelationshipType { Friendly, Aggressive, Neutral } 7 | 8 | [Serializable] 9 | [CreateGenericAssetMenu] 10 | public class WarriorsRelationship : GenericScriptableObject 11 | where TFirst : WarriorClass 12 | where TSecond : WarriorClass 13 | { 14 | public TFirst FirstWarrior; 15 | public TSecond SecondWarrior; 16 | public RelationshipType Relationship; 17 | } 18 | } -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/GenericScriptableObjects/WarriorsRelationship`2.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3333b924c4546fc899fb30a013589c4 3 | timeCreated: 1602874000 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/README.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 3732b7fccbe84e4fa096cfbd2b945f24, type: 3} 13 | m_Name: README 14 | m_EditorClassIdentifier: 15 | _description: 'The example contains two classes derived from GenericScriptableObject: 16 | 17 | - 18 | WarriorStats 19 | 20 | - WarriorsRelationship 21 | 22 | 23 | You can 24 | find them in the GenericScriptableObjects folder. 25 | 26 | 27 | You can check the assets 28 | created from those classes in the "Warrior Stats" and "Relationships" folders. 29 | 30 | 31 | To 32 | create a new asset, press RMB in the Project window -> Create -> WarriorStats. 33 | The asset creation looks a bit different for a generic scriptable object with 34 | one generic argument, and with multiple arguments, so be sure to check out both 35 | versions. 36 | 37 | 38 | Inside the scripts, you can see how [CreateGenericAssetMenu] 39 | adds a class to the Assets/Create context menu. 40 | 41 | 42 | You can also notice how 43 | the object picker field has changed in scriptable objects inspector. It contains 44 | a specific generic type (WarriorStats) instead of the short name (WarriorStats`1).' 45 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/README.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c760dc3b08e78747a321f97441e85d4 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Relationships.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 646512073ae7648408fbe5c6eac10897 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Relationships/Arnet - Geltull.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 227358861, guid: 7f7246c110f57fc44a8bebed0f427517, type: 3} 13 | m_Name: Arnet - Geltull 14 | m_EditorClassIdentifier: 15 | FirstWarrior: {fileID: 11400000, guid: 2deee1c3d37688d458a204b3b54a88fc, type: 2} 16 | SecondWarrior: {fileID: 11400000, guid: e0bb2ddddd8cc8547b6cd1f2f27ec69e, type: 2} 17 | Relationship: 2 18 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Relationships/Arnet - Geltull.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36369a9664a5e70469b7cc1389c0b8f7 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Relationships/Edun - Fulchard.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 797222476, guid: 74de9d056beaae04fa0093fbc35479f5, type: 3} 13 | m_Name: Edun - Fulchard 14 | m_EditorClassIdentifier: 15 | FirstWarrior: {fileID: 11400000, guid: e7f8e501e62388e4d876c89fc20f6442, type: 2} 16 | SecondWarrior: {fileID: 11400000, guid: 45a0885acaa5a3d40b8895ac944b8287, type: 2} 17 | Relationship: 0 18 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Relationships/Edun - Fulchard.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0e2450f72e88c904ebc1f10bd14d6d7e 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Relationships/Geltull - Fulchard.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: -599044209, guid: 505d3824df1635d4fafc15fdaa46820e, type: 3} 13 | m_Name: Geltull - Fulchard 14 | m_EditorClassIdentifier: 15 | FirstWarrior: {fileID: 11400000, guid: e0bb2ddddd8cc8547b6cd1f2f27ec69e, type: 2} 16 | SecondWarrior: {fileID: 11400000, guid: 45a0885acaa5a3d40b8895ac944b8287, type: 2} 17 | Relationship: 1 18 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Relationships/Geltull - Fulchard.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd71fc5cac491c9478f06f191cba7e83 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Util.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d0701a61ea2d4c5aaa32f16105e57aee 3 | timeCreated: 1604051374 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Util/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f7cac4b9a694b91bfdf525c9fdbd972 3 | timeCreated: 1604399907 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Util/Editor/Installer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e8fa5ef5ff1946e498fd3226cf277db6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Util/Readme.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.ScriptableObject_Example 2 | { 3 | using JetBrains.Annotations; 4 | using SolidUtilities.Attributes; 5 | using UnityEngine; 6 | 7 | internal class Readme : ScriptableObject 8 | { 9 | #pragma warning disable 414 10 | [SerializeField, ResizableTextArea, UsedImplicitly] 11 | private string _description = null; 12 | #pragma warning restore 414 13 | } 14 | } -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Util/Readme.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3732b7fccbe84e4fa096cfbd2b945f24 3 | timeCreated: 1604048479 -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3a5057ca081da3543b32d1e300308449 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Default Berserker Stats.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 2135577082, guid: 151fbf5b6b40e2c45b15503ca02432dc, type: 3} 13 | m_Name: Default Berserker Stats 14 | m_EditorClassIdentifier: 15 | Health: 1000 16 | Damage: 80 17 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Default Berserker Stats.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 218abc3731531b145bfe775b6f575775 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Default Knight Stats.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: -334746539, guid: 4036c453491f17949ab52305ce9cee51, type: 3} 13 | m_Name: Default Knight Stats 14 | m_EditorClassIdentifier: 15 | Health: 900 16 | Damage: 100 17 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Default Knight Stats.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 86fdcf4314685a54a8d82bfdc0b47977 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Heavy Archer.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 176745257, guid: 7a40321cb45bb4a4abffcc5186d25526, type: 3} 13 | m_Name: Heavy Archer 14 | m_EditorClassIdentifier: 15 | Health: 600 16 | Damage: 65 17 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Heavy Archer.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 256faa2df31684647a9a313711568c1d 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Light Archer.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 176745257, guid: 7a40321cb45bb4a4abffcc5186d25526, type: 3} 13 | m_Name: Light Archer 14 | m_EditorClassIdentifier: 15 | Health: 450 16 | Damage: 85 17 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warrior Stats/Light Archer.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2bf52dc2a1482e54ea3ccecb66c32e51 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a9ad81b2a47661f459f00286f0902676 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Arnet.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 000e287a106e415e95a3c215d416486b, type: 3} 13 | m_Name: Arnet 14 | m_EditorClassIdentifier: 15 | _hasMeleeAttack: 0 16 | _hasRangedAttack: 1 17 | _hasAOEAttack: 0 18 | Stats: {fileID: 11400000, guid: 2bf52dc2a1482e54ea3ccecb66c32e51, type: 2} 19 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Arnet.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2deee1c3d37688d458a204b3b54a88fc 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Edun.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 000e287a106e415e95a3c215d416486b, type: 3} 13 | m_Name: Edun 14 | m_EditorClassIdentifier: 15 | _hasMeleeAttack: 0 16 | _hasRangedAttack: 1 17 | _hasAOEAttack: 0 18 | Stats: {fileID: 11400000, guid: 256faa2df31684647a9a313711568c1d, type: 2} 19 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Edun.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e7f8e501e62388e4d876c89fc20f6442 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Fulchard.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 2c74ad55232f4ce680f3fc54c402e7a3, type: 3} 13 | m_Name: Fulchard 14 | m_EditorClassIdentifier: 15 | _hasMeleeAttack: 1 16 | _hasRangedAttack: 0 17 | _hasAOEAttack: 0 18 | Stats: {fileID: 11400000, guid: 86fdcf4314685a54a8d82bfdc0b47977, type: 2} 19 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Fulchard.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 45a0885acaa5a3d40b8895ac944b8287 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Geltull.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 3e36c3dcbc3241f6a10158e398512d37, type: 3} 13 | m_Name: Geltull 14 | m_EditorClassIdentifier: 15 | _hasMeleeAttack: 1 16 | _hasRangedAttack: 0 17 | _hasAOEAttack: 1 18 | Stats: {fileID: 11400000, guid: 218abc3731531b145bfe775b6f575775, type: 2} 19 | -------------------------------------------------------------------------------- /Samples~/ScriptableObject Example/Warriors/Geltull.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0bb2ddddd8cc8547b6cd1f2f27ec69e 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18dbe5c724358d54f83b43c838b71c58 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: badba526694b7e843a034ff3696a3531 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Editor/BehaviourInfoTests.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using Editor.GeneratedTypesDatabase; 4 | using NUnit.Framework; 5 | 6 | public class BehaviourInfoTests 7 | { 8 | [Test] 9 | public void Instances_with_identical_fields_are_equal() 10 | { 11 | var firstBehaviour = new GenericTypeInfo("firstTypeAndAssembly", "firstGUID", new[] { "firstArg", "secondArg" }); 12 | var secondBehaviour = new GenericTypeInfo("firstTypeAndAssembly", "firstGUID", new[] { "firstArg", "secondArg" }); 13 | 14 | Assert.AreEqual(firstBehaviour, secondBehaviour); 15 | } 16 | 17 | [Test] 18 | public void Instances_with_different_typeNames_are_not_equal() 19 | { 20 | var firstBehaviour = new GenericTypeInfo("firstTypeAndAssembly", "firstGUID", new[] { "firstArg", "secondArg" }); 21 | var secondBehaviour = new GenericTypeInfo("secondTypeAndAssembly", "firstGUID", new[] { "firstArg", "secondArg" }); 22 | 23 | Assert.AreNotEqual(firstBehaviour, secondBehaviour); 24 | } 25 | 26 | [Test] 27 | public void Instances_with_different_guids_are_not_equal() 28 | { 29 | var firstBehaviour = new GenericTypeInfo("firstTypeAndAssembly", "firstGUID", new[] { "firstArg", "secondArg" }); 30 | var secondBehaviour = new GenericTypeInfo("firstTypeAndAssembly", "secondGUID", new[] { "firstArg", "secondArg" }); 31 | 32 | Assert.AreNotEqual(firstBehaviour, secondBehaviour); 33 | } 34 | 35 | [Test] 36 | public void Instances_with_different_args_are_not_equal() 37 | { 38 | var firstBehaviour = new GenericTypeInfo("firstTypeAndAssembly", "firstGUID", new[] { "firstArg", "secondArg" }); 39 | var secondBehaviour = new GenericTypeInfo("firstTypeAndAssembly", "secondGUID", new[] { "firstArg", "thirdArg" }); 40 | 41 | Assert.AreNotEqual(firstBehaviour, secondBehaviour); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Tests/Editor/BehaviourInfoTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1796e15822bd44039e0e97c97e8e2fb9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0cf8a9678714452c9d6e4165c966f0d3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/AddConcreteClass.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f72d28d0ac27e641b6ca2243defa10f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/AddGenericType.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System; 4 | using System.Linq; 5 | using NUnit.Framework; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | public class AddGenericType : GenerationDatabaseTests 10 | { 11 | [Test] 12 | public void Adds_generic_type_to_dict() 13 | { 14 | var expectedGenericTypes = new[] { _genericType }; 15 | 16 | _database.AddGenericTypeImpl(_genericType); 17 | 18 | Assert.IsTrue(_database.InstanceGenericTypeArguments.Keys.SequenceEqual(expectedGenericTypes)); 19 | Assert.IsEmpty(_database.InstanceArgumentGenericTypes.Keys); 20 | } 21 | 22 | [Test] 23 | public void Throws_ArgumentException_if_key_exists() 24 | { 25 | _database.AddGenericTypeImpl(_genericType); 26 | 27 | Assert.Throws(() => 28 | { 29 | _database.AddGenericTypeImpl(_genericType); 30 | }); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/AddGenericType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f47adabb84c271e4195224f5d8876c6c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GenerationDatabaseTests.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using Editor.GeneratedTypesDatabase; 4 | using NUnit.Framework; 5 | using UnityEngine; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | private const string AssemblyGUID = "testAssemblyGUID"; 10 | 11 | private static GenerationDatabase _database; 12 | private static GenericTypeInfo _genericType; 13 | private static ArgumentInfo _firstArg; 14 | private static ArgumentInfo _secondArg; 15 | private static ArgumentInfo[] _firstSecondArgs; 16 | private static GenericTypeInfo[] _expectedGenericTypes; 17 | private static ConcreteClass _expectedConcreteClass; 18 | 19 | [SetUp] 20 | public virtual void BeforeEachTest() 21 | { 22 | _database = ScriptableObject.CreateInstance(); 23 | _database.Initialize(); 24 | 25 | _genericType = new BehaviourInfo("genericTypeName", "genericTypeGUID", new[] { "genericArg" }); 26 | _firstArg = new ArgumentInfo("firstArgumentName", "firstArgumentGUID"); 27 | _secondArg = new ArgumentInfo("secondArgumentName", "secondArgumentGUID"); 28 | _firstSecondArgs = new[] { _firstArg, _secondArg }; 29 | _expectedGenericTypes = new[] { _genericType }; 30 | _expectedConcreteClass = new ConcreteClass(_firstSecondArgs, AssemblyGUID); 31 | } 32 | 33 | private static void AddEntries() 34 | { 35 | _database.AddGenericTypeImpl(_genericType); 36 | _database.AddConcreteClassImpl(_genericType, _firstSecondArgs, AssemblyGUID); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GenerationDatabaseTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3ec2c0dc3db84dce95362a611364b314 3 | timeCreated: 1608283704 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GetConcreteClasses.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Collections.Generic; 4 | using Editor.GeneratedTypesDatabase; 5 | using NUnit.Framework; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | public class GetConcreteClasses : GenerationDatabaseTests 10 | { 11 | private static ConcreteClass[] CallMethod() 12 | { 13 | return _database.GetConcreteClassesImpl(_genericType); 14 | } 15 | 16 | [Test] 17 | public void When_generic_type_does_not_exist_throws_KeyNotFound_exception() 18 | { 19 | Assert.Throws(() => CallMethod()); 20 | } 21 | 22 | [Test] 23 | public void When_generic_type_exists_returns_collection_with_items() 24 | { 25 | AddEntries(); 26 | 27 | ConcreteClass[] concreteClasses = CallMethod(); 28 | 29 | Assert.IsNotNull(concreteClasses); 30 | Assert.IsTrue(concreteClasses.Length == 1); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GetConcreteClasses.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: deb9df297a87420fa15c8edf59cb5224 3 | timeCreated: 1608313823 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GetConcreteClassesByArgument.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Editor.GeneratedTypesDatabase; 6 | using NUnit.Framework; 7 | 8 | internal partial class GenerationDatabaseTests 9 | { 10 | public class GetConcreteClassesByArgument : GenerationDatabaseTests 11 | { 12 | private const string SecondAssemblyGUID = "secondAssemblyGUID"; 13 | 14 | private static ArgumentInfo _thirdArg; 15 | private static ArgumentInfo[] _secondThirdArgs; 16 | 17 | [SetUp] 18 | public override void BeforeEachTest() 19 | { 20 | base.BeforeEachTest(); 21 | 22 | _database.AddGenericTypeImpl(_genericType); 23 | _database.AddConcreteClassImpl(_genericType, _firstSecondArgs, AssemblyGUID); 24 | _thirdArg = new ArgumentInfo("thirdArgumentName", "thirdArgumentGUID"); 25 | _secondThirdArgs = new[] { _secondArg, _thirdArg }; 26 | _database.AddConcreteClassImpl(_genericType, _secondThirdArgs, SecondAssemblyGUID); 27 | } 28 | 29 | private static ConcreteClass[] CallMethod() => 30 | _database.GetConcreteClassesByArgumentImpl(_genericType, _firstArg); 31 | 32 | [Test] 33 | public void Returns_concrete_classes_where_argument_is_listed() 34 | { 35 | var actualClasses = CallMethod(); 36 | 37 | Assert.IsTrue(actualClasses.Any(concreteClass => concreteClass.Arguments.SequenceEqual(_firstSecondArgs))); 38 | } 39 | 40 | [Test] 41 | public void Does_not_return_concrete_classes_where_argument_is_not_listed() 42 | { 43 | var actualClasses = CallMethod(); 44 | 45 | Assert.IsFalse(actualClasses.Any(concreteClass => concreteClass.Arguments.SequenceEqual(_secondThirdArgs))); 46 | } 47 | 48 | [Test] 49 | public void Throws_KeyNotFoundException_when_generic_type_is_not_in_the_database() 50 | { 51 | _database.RemoveGenericTypeImpl(_genericType, null); 52 | 53 | Assert.Throws(() => CallMethod()); 54 | } 55 | 56 | [Test] 57 | public void Returns_empty_collection_when_argument_is_not_present() 58 | { 59 | _database.RemoveArgumentImpl(_firstArg, null); 60 | 61 | var actualClasses = CallMethod(); 62 | 63 | Assert.IsEmpty(actualClasses); 64 | } 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GetConcreteClassesByArgument.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1031cf11276a41b1b2d3f529e0aef7ed 3 | timeCreated: 1610807741 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GetReferencedGenericTypes.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Collections.Generic; 4 | using Editor.GeneratedTypesDatabase; 5 | using NUnit.Framework; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | public class GetReferencedGenericTypes : GenerationDatabaseTests 10 | { 11 | private static GenericTypeInfo[] CallMethod() => _database.GetReferencedGenericTypesImpl(_firstArg); 12 | 13 | [Test] 14 | public void When_argument_does_not_exist_throws_KeyNotFound_exception() 15 | { 16 | Assert.Throws(() => CallMethod()); 17 | } 18 | 19 | [Test] 20 | public void When_argument_exists_returns_collection_with_items() 21 | { 22 | AddEntries(); 23 | 24 | var genericTypes = CallMethod(); 25 | 26 | Assert.IsNotNull(genericTypes); 27 | Assert.IsTrue(genericTypes.Length == 1); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/GetReferencedGenericTypes.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 39ec80be2c3342ef9354e6e79d3a2c28 3 | timeCreated: 1608313815 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/OnAfterDeserialize.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d68d51ab195435eb6c390ec050b12a0 3 | timeCreated: 1608308914 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/RemoveArgument.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using NUnit.Framework; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | public class RemoveArgument : GenerationDatabaseTests 10 | { 11 | [SetUp] 12 | public override void BeforeEachTest() 13 | { 14 | base.BeforeEachTest(); 15 | AddEntries(); 16 | } 17 | 18 | private static void CallRemoveArgument() 19 | { 20 | _database.RemoveArgumentImpl(_firstArg, null); 21 | } 22 | 23 | [Test] 24 | public void Removes_argument_from_arguments_list() 25 | { 26 | CallRemoveArgument(); 27 | Assert.IsFalse(_database.InstanceArgumentGenericTypes.Keys.Contains(_firstArg)); 28 | } 29 | 30 | [Test] 31 | public void Removes_concrete_classes_that_used_the_argument() 32 | { 33 | CallRemoveArgument(); 34 | 35 | var actualClasses = _database.GetConcreteClassesImpl(_genericType); 36 | 37 | Assert.IsFalse(actualClasses.Contains(_expectedConcreteClass)); 38 | } 39 | 40 | [Test] 41 | public void Executes_action_for_assembly_name_of_each_removed_class() 42 | { 43 | bool acceptedAssemblyName = false; 44 | 45 | _database.RemoveArgumentImpl(_firstArg, assemblyName => 46 | { 47 | if (assemblyName == AssemblyGUID) 48 | acceptedAssemblyName = true; 49 | }); 50 | 51 | Assert.IsTrue(acceptedAssemblyName); 52 | } 53 | 54 | [Test] 55 | public void When_argument_is_not_found_throws_KeyNotFound_exception() 56 | { 57 | CallRemoveArgument(); 58 | 59 | Assert.Throws(() => 60 | { 61 | _database.RemoveArgumentImpl(_firstArg, assemblyName => { }); 62 | }); 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/RemoveArgument.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f6d82244b4724444a595ec280ed8d8f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/RemoveGenericType.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Editor.GeneratedTypesDatabase; 6 | using NUnit.Framework; 7 | 8 | internal partial class GenerationDatabaseTests 9 | { 10 | public class RemoveGenericType : GenerationDatabaseTests 11 | { 12 | private static GenericTypeInfo _secondGenericType; 13 | 14 | [SetUp] 15 | public override void BeforeEachTest() 16 | { 17 | base.BeforeEachTest(); 18 | 19 | _secondGenericType = new GenericTypeInfo("secondGenericTypeName", "secondGenericTypeGUID", new[] { "secondArgs" }); 20 | 21 | _database.AddGenericTypeImpl(_genericType); 22 | _database.AddGenericTypeImpl(_secondGenericType); 23 | 24 | _database.AddConcreteClassImpl(_genericType, _firstSecondArgs, AssemblyGUID); 25 | _database.AddConcreteClassImpl(_secondGenericType, _firstSecondArgs, AssemblyGUID); 26 | } 27 | 28 | private void CallRemoveGenericType(GenericTypeInfo behaviour) => _database.RemoveGenericTypeImpl(behaviour, null); 29 | 30 | [Test] 31 | public void Removes_generic_type_from_generic_types_list() 32 | { 33 | CallRemoveGenericType(_genericType); 34 | 35 | Assert.IsFalse(_database.InstanceGenericTypeArguments.Keys.Contains(_genericType)); 36 | } 37 | 38 | [Test] 39 | public void Removes_generic_type_from_referenced_generic_types_of_each_argument() 40 | { 41 | CallRemoveGenericType(_genericType); 42 | 43 | var firstGenericTypes = _database.GetReferencedGenericTypesImpl(_firstArg); 44 | Assert.IsFalse(firstGenericTypes.Contains(_genericType)); 45 | 46 | var secondGenericTypes = _database.GetReferencedGenericTypesImpl(_secondArg); 47 | Assert.IsFalse(secondGenericTypes.Contains(_genericType)); 48 | } 49 | 50 | [Test] 51 | public void When_argument_has_only_this_generic_type_referenced_removes_argument_from_arguments_list() 52 | { 53 | CallRemoveGenericType(_genericType); 54 | CallRemoveGenericType(_secondGenericType); 55 | 56 | Assert.IsEmpty(_database.InstanceArgumentGenericTypes.Keys); 57 | } 58 | 59 | [Test] 60 | public void When_generic_type_is_not_found_throws_KeyNotFound_exception() 61 | { 62 | CallRemoveGenericType(_genericType); 63 | CallRemoveGenericType(_secondGenericType); 64 | 65 | Assert.Throws(() => 66 | { 67 | _database.RemoveGenericTypeImpl(_genericType, null); 68 | }); 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/RemoveGenericType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 71042ddb1bde430cb24c3cc831d88eca 3 | timeCreated: 1608308949 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/TypeStub.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6b87aa31701d4292a4b555c07b9585cb 3 | timeCreated: 1608475727 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateArgumentGUID.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Linq; 4 | using Editor.GeneratedTypesDatabase; 5 | using NUnit.Framework; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | public class UpdateArgumentGUID : GenerationDatabaseTests 10 | { 11 | private const string NewGUID = "newGUID"; 12 | private static ArgumentInfo _expectedArg; 13 | 14 | [SetUp] 15 | public override void BeforeEachTest() 16 | { 17 | base.BeforeEachTest(); 18 | AddEntries(); 19 | _expectedArg = new ArgumentInfo(_firstArg.TypeNameAndAssembly, NewGUID); 20 | } 21 | 22 | [Test] 23 | public void Updates_argument_GUID_in_arguments_list() 24 | { 25 | _database.UpdateArgumentGUIDImpl(_firstArg, NewGUID); 26 | 27 | Assert.IsTrue(_database.InstanceArgumentGenericTypes.Keys.Count == 2); 28 | Assert.Contains(_expectedArg, _database.InstanceArgumentGenericTypes.Keys.ToArray()); 29 | } 30 | 31 | [Test] 32 | public void Updates_argument_GUID_in_concrete_classes() 33 | { 34 | _database.UpdateArgumentGUIDImpl(_firstArg, NewGUID); 35 | 36 | var concreteClasses = _database.GetConcreteClassesImpl(_genericType); 37 | 38 | Assert.IsTrue(concreteClasses.Any(concreteClass => concreteClass.Arguments.Contains(_expectedArg))); 39 | } 40 | 41 | [Test] 42 | public void Referenced_generic_types_can_be_found_by_new_argument() 43 | { 44 | _database.UpdateArgumentGUIDImpl(_firstArg, NewGUID); 45 | 46 | var genericTypes = _database.GetReferencedGenericTypesImpl(_expectedArg); 47 | Assert.IsTrue(genericTypes.Length != 0); 48 | } 49 | 50 | [Test] 51 | public void Updates_passed_argument_GUID() 52 | { 53 | _database.UpdateArgumentGUIDImpl(_firstArg, NewGUID); 54 | Assert.IsTrue(_firstArg.GUID == NewGUID); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateArgumentGUID.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b12dfb8614c475da5095bee8154dda1 3 | timeCreated: 1608312129 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateArgumentNameAndAssembly.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Linq; 4 | using Editor.GeneratedTypesDatabase; 5 | using NUnit.Framework; 6 | using Util; 7 | 8 | internal partial class GenerationDatabaseTests 9 | { 10 | public class UpdateArgumentNameAndAssembly : GenerationDatabaseTests 11 | { 12 | private const string NewName = "newName"; 13 | private const string NewAssembly = "newAssembly"; 14 | private static ArgumentInfo _expectedArg; 15 | private static TypeStub _typeStub; 16 | 17 | private static void CallUpdateArgumentNameAndAssembly() => 18 | _database.UpdateArgumentNameAndAssemblyImpl(_firstArg, _typeStub); 19 | 20 | [OneTimeSetUp] 21 | public void BeforeAllTests() 22 | { 23 | _typeStub = new TypeStub(NewName, NewAssembly); 24 | } 25 | 26 | [SetUp] 27 | public override void BeforeEachTest() 28 | { 29 | base.BeforeEachTest(); 30 | AddEntries(); 31 | 32 | _expectedArg = new ArgumentInfo(NewName, NewAssembly, _firstArg.GUID); 33 | } 34 | 35 | [Test] 36 | public void Updates_argument_name_in_arguments_list() 37 | { 38 | CallUpdateArgumentNameAndAssembly(); 39 | 40 | Assert.IsTrue(_database.InstanceArgumentGenericTypes.Keys.Count == 2); 41 | Assert.Contains(_expectedArg, _database.InstanceArgumentGenericTypes.Keys.ToArray()); 42 | } 43 | 44 | [Test] 45 | public void Updates_argument_name_in_concrete_classes() 46 | { 47 | CallUpdateArgumentNameAndAssembly(); 48 | 49 | var concreteClasses = _database.GetConcreteClassesImpl(_genericType); 50 | 51 | Assert.IsTrue(concreteClasses.Any(concreteClass => concreteClass.Arguments.Contains(_expectedArg))); 52 | } 53 | 54 | [Test] 55 | public void Referenced_generic_types_can_be_found_by_new_argument() 56 | { 57 | CallUpdateArgumentNameAndAssembly(); 58 | 59 | var genericTypes = _database.GetReferencedGenericTypesImpl(_expectedArg); 60 | Assert.IsTrue(genericTypes.Length != 0); 61 | } 62 | 63 | [Test] 64 | public void Updates_passed_argument_TypeNameAndAssembly() 65 | { 66 | CallUpdateArgumentNameAndAssembly(); 67 | Assert.IsTrue(_firstArg.TypeNameAndAssembly == TypeUtility.GetTypeNameAndAssembly(NewName, NewAssembly)); 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateArgumentNameAndAssembly.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4a114185e435439196bf1df7579e1574 3 | timeCreated: 1608312138 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateGenericType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: faf341b70fd35e642b1eb0ebd2a48f50 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateGenericTypeArgs.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Linq; 4 | using Editor.GeneratedTypesDatabase; 5 | using NUnit.Framework; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | public class UpdateGenericTypeArgs : GenerationDatabaseTests 10 | { 11 | private static readonly string[] NewArgs = { "newArgs" }; 12 | private static GenericTypeInfo _expectedGenericType; 13 | 14 | [SetUp] 15 | public override void BeforeEachTest() 16 | { 17 | base.BeforeEachTest(); 18 | AddEntries(); 19 | _expectedGenericType = new GenericTypeInfo(_genericType.TypeNameAndAssembly, _genericType.GUID, NewArgs); 20 | } 21 | 22 | [Test] 23 | public void Updates_generic_type_arguments_in_generic_types_list() 24 | { 25 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateArgNames(NewArgs)); 26 | 27 | Assert.IsTrue(_database.InstanceGenericTypeArguments.Keys.Count == 1); 28 | Assert.Contains(_expectedGenericType, _database.InstanceGenericTypeArguments.Keys.ToArray()); 29 | } 30 | 31 | [Test] 32 | public void Updates_generic_types_arguments_in_referenced_behaviours() 33 | { 34 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateArgNames(NewArgs)); 35 | 36 | var behaviours = _database.GetReferencedGenericTypesImpl(_firstArg); 37 | Assert.IsTrue(behaviours.Any(behaviour => behaviour.ArgNames.SequenceEqual(NewArgs))); 38 | } 39 | 40 | [Test] 41 | public void Concrete_classes_can_be_found_by_new_generic_type() 42 | { 43 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateArgNames(NewArgs)); 44 | 45 | var concreteClasses = _database.GetConcreteClassesImpl(_genericType); 46 | 47 | Assert.IsTrue(concreteClasses.Length != 0); 48 | } 49 | 50 | [Test] 51 | public void Updates_passed_argument_argNames() 52 | { 53 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateArgNames(NewArgs)); 54 | Assert.IsTrue(_genericType.ArgNames == NewArgs); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateGenericTypeArgs.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dce745100ca341cc980fe8b467a5fdbd 3 | timeCreated: 1609621423 -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateGenericTypeGUID.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Linq; 4 | using Editor.GeneratedTypesDatabase; 5 | using NUnit.Framework; 6 | 7 | internal partial class GenerationDatabaseTests 8 | { 9 | public class UpdateGenericTypeGUID : GenerationDatabaseTests 10 | { 11 | private const string NewGUID = "newGUID"; 12 | private static GenericTypeInfo _expectedBehaviour; 13 | 14 | [SetUp] 15 | public override void BeforeEachTest() 16 | { 17 | base.BeforeEachTest(); 18 | AddEntries(); 19 | _expectedBehaviour = new GenericTypeInfo(_genericType.TypeNameAndAssembly, NewGUID, _genericType.ArgNames); 20 | } 21 | 22 | [Test] 23 | public void Updates_behaviour_GUID_in_behaviours_list() 24 | { 25 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateGUID(NewGUID)); 26 | 27 | Assert.IsTrue(_database.InstanceGenericTypeArguments.Keys.Count == 1); 28 | Assert.Contains(_expectedBehaviour, _database.InstanceGenericTypeArguments.Keys.ToArray()); 29 | } 30 | 31 | [Test] 32 | public void Updates_behaviour_GUID_in_referenced_behaviours() 33 | { 34 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateGUID(NewGUID)); 35 | 36 | var behaviours = _database.GetReferencedGenericTypesImpl(_firstArg); 37 | 38 | Assert.IsTrue(behaviours.Any(behaviour => behaviour.GUID == NewGUID)); 39 | } 40 | 41 | [Test] 42 | public void Concrete_classes_can_be_found_by_new_behaviour() 43 | { 44 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateGUID(NewGUID)); 45 | 46 | var concreteClasses = _database.GetConcreteClassesImpl(_genericType); 47 | 48 | Assert.IsTrue(concreteClasses.Length != 0); 49 | } 50 | 51 | [Test] 52 | public void Updates_passed_argument_GUID() 53 | { 54 | _database.UpdateGenericTypeImpl(_genericType, genericTypeInfo => genericTypeInfo.UpdateGUID(NewGUID)); 55 | Assert.IsTrue(_genericType.GUID == NewGUID); 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Tests/Editor/GenerationDatabaseTests/UpdateGenericTypeGUID.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8592174e5328404c9520f06a33368e85 3 | timeCreated: 1608312145 -------------------------------------------------------------------------------- /Tests/Editor/GenericUnityObjects.EditorTests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GenericUnityObjects.EditorTests", 3 | "rootNamespace": "GenericUnityObjects.EditorTests", 4 | "references": [ 5 | "GenericUnityObjects.Editor", 6 | "UnityEngine.TestRunner", 7 | "UnityEditor.TestRunner", 8 | "SolidUtilities", 9 | "GenericUnityObjects" 10 | ], 11 | "includePlatforms": [ 12 | "Editor" 13 | ], 14 | "excludePlatforms": [], 15 | "allowUnsafeCode": false, 16 | "overrideReferences": true, 17 | "precompiledReferences": [ 18 | "nunit.framework.dll" 19 | ], 20 | "autoReferenced": false, 21 | "defineConstraints": [ 22 | "UNITY_INCLUDE_TESTS", 23 | "TEST_FRAMEWORK" 24 | ], 25 | "versionDefines": [ 26 | { 27 | "name": "com.unity.test-framework", 28 | "expression": "", 29 | "define": "TEST_FRAMEWORK" 30 | } 31 | ], 32 | "noEngineReferences": false 33 | } -------------------------------------------------------------------------------- /Tests/Editor/GenericUnityObjects.EditorTests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: afe5aa511db39584ea40ed7d1b054b79 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/Editor/TypeInfoTests.cs: -------------------------------------------------------------------------------- 1 | namespace GenericUnityObjects.EditorTests 2 | { 3 | using System.Collections.Generic; 4 | using Editor.GeneratedTypesDatabase; 5 | using NUnit.Framework; 6 | using SolidUtilities; 7 | 8 | public class TypeInfoTests 9 | { 10 | private TypeInfo _firstInfo; 11 | private TypeInfo _secondInfo; 12 | private TypeInfo _thirdInfo; 13 | private TypeInfo _fourthInfo; 14 | 15 | [OneTimeSetUp] 16 | public void BeforeAllTests() 17 | { 18 | _firstInfo = new ArgumentInfo("firstFullName", "firstGUID"); 19 | _secondInfo = new ArgumentInfo("secondFullName", "secondGUID"); 20 | _thirdInfo = new ArgumentInfo("thirdFullName", "thirdGUID"); 21 | _fourthInfo = new ArgumentInfo("fourthFullName", "fourthGUID"); 22 | } 23 | 24 | [Test] 25 | public void Set_does_not_include_identical_structs() 26 | { 27 | var set = new HashSet { _firstInfo, _secondInfo, _firstInfo }; 28 | 29 | Assert.IsTrue(set.Count == 2); 30 | Assert.IsTrue(set.Contains(_firstInfo)); 31 | Assert.IsTrue(set.Contains(_secondInfo)); 32 | } 33 | 34 | [Test] 35 | public void Sets_with_same_structs_are_identical() 36 | { 37 | var firstSet = new HashSet { _firstInfo, _secondInfo }; 38 | var secondSet = new HashSet { _firstInfo, _secondInfo }; 39 | 40 | Assert.IsTrue(firstSet.SetEquals(secondSet)); 41 | } 42 | 43 | [Test] 44 | public void ExceptWith_correctly_works_with_two_different_sets() 45 | { 46 | var thirdIncludedSet = new HashSet { _firstInfo, _secondInfo, _thirdInfo }; 47 | var fourthIncludedSet = new HashSet { _firstInfo, _secondInfo, _fourthInfo }; 48 | var thirdOnlySet = new HashSet { _thirdInfo }; 49 | 50 | var newSet = thirdIncludedSet.ExceptWithAndCreateNew(fourthIncludedSet); 51 | 52 | Assert.IsTrue(newSet.SetEquals(thirdOnlySet)); 53 | } 54 | 55 | [Test] 56 | public void Sets_with_different_guids_are_different() 57 | { 58 | var firstGUIDInfo = new ArgumentInfo("testType", "firstTestGuid"); 59 | var secondGUIDInfo = new ArgumentInfo("testType", "secondTestGuid"); 60 | 61 | var firstSet = new HashSet { _firstInfo, _secondInfo, firstGUIDInfo }; 62 | var secondSet = new HashSet { _firstInfo, _secondInfo, secondGUIDInfo }; 63 | 64 | Assert.IsFalse(firstSet.SetEquals(secondSet)); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Tests/Editor/TypeInfoTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 25ae250dc3a145a7b7d49356d098a35b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Integration.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 300670a8a7cb2be4f86bb8af881959f6 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/Integration/GenericBehaviour_ConcreteClass.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7175860623b94ceb8b189a457920a137 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Integration/GenericBehaviour_GenericArguments.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6fc4c141d65d4710a48ee70698491b8d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Integration/GenericBehaviour_Selector.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8673240b3e5d441f86bba313d4e1f991 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Integration/GenericScriptableObject_ConcreteClass.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1bfd7470687648a4b9f26c7310489550 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Integration/GenericScriptableObject_GenericArguments.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 54733e2c568247feaa4ccf6dcc47556e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Integration/GenericUnityObjects.IntegrationTests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GenericUnityObjects.IntegrationTests", 3 | "rootNamespace": "GenericUnityObjects.IntegrationTests", 4 | "references": [ 5 | "GenericUnityObjects", 6 | "GenericUnityObjects.Editor", 7 | "SolidUtilities.Editor" 8 | ], 9 | "includePlatforms": [ 10 | "Editor" 11 | ], 12 | "excludePlatforms": [], 13 | "allowUnsafeCode": false, 14 | "overrideReferences": true, 15 | "precompiledReferences": [ 16 | "nunit.framework.dll" 17 | ], 18 | "autoReferenced": false, 19 | "defineConstraints": [ 20 | "UNITY_INCLUDE_TESTS", 21 | "TEST_FRAMEWORK" 22 | ], 23 | "versionDefines": [ 24 | { 25 | "name": "com.unity.test-framework", 26 | "expression": "", 27 | "define": "TEST_FRAMEWORK" 28 | } 29 | ], 30 | "noEngineReferences": false 31 | } -------------------------------------------------------------------------------- /Tests/Integration/GenericUnityObjects.IntegrationTests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4052ed66218bb104ab87e113a60a248d 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/Integration/MenuItems.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5d1fb14235244b4aac73eb8c6e6b9a06 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/Integration/TestHelper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ebd8ad3d429249ce964d0ce0f5a0f538 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.solidalloy.generic-unity-objects", 3 | "version": "2.17.1", 4 | "displayName": "Generic Unity Objects", 5 | "description": "A plugin that allows using of generic scriptable objects and monobehaviours, creating assets and components from them, and instantiating them at runtime.", 6 | "dependencies": { 7 | "com.solidalloy.util": "1.40.0", 8 | "com.solidalloy.type-references": "2.16.0", 9 | "com.unity.settings-manager": "1.0.3", 10 | "com.solidalloy.extevents": "1.7.0" 11 | }, 12 | "keywords": [ 13 | "scriptable", 14 | "object", 15 | "ScriptableObject", 16 | "generic" 17 | ], 18 | "author": { 19 | "name": "SolidAlloy", 20 | "url": "https://github.com/SolidAlloy/" 21 | }, 22 | "samples": [ 23 | { 24 | "displayName": "ScriptableObject Example", 25 | "description": "An example that shows how generic scriptable objects can be implemented and used", 26 | "path": "Samples~/ScriptableObject Example" 27 | }, 28 | { 29 | "displayName": "MonoBehaviour Example", 30 | "description": "An example that shows how generic MonoBehaviours can be implemented and used", 31 | "path": "Samples~/MonoBehaviour Example" 32 | } 33 | ], 34 | "type": "tool", 35 | "unity": "2020.2" 36 | } 37 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b2e25e243489614383d94296908cecc 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------