├── Runtime
├── Unity.ScriptableObjectContainer.Runtime.asmdef
├── Attributes.meta
├── Unity.ScriptableObjectContainer.Runtime.asmdef.meta
├── ScriptableObjectContainer.cs.meta
├── Attributes
│ ├── SubAssetOwnerAttribute.cs.meta
│ ├── CreateSubAssetMenuAttribute.cs.meta
│ ├── SubAssetToggleAttribute.cs.meta
│ ├── DisallowMultipleSubAssetAttribute.cs.meta
│ ├── SubAssetToggleAttribute.cs
│ ├── DisallowMultipleSubAssetAttribute.cs
│ ├── SubAssetOwnerAttribute.cs
│ └── CreateSubAssetMenuAttribute.cs
└── ScriptableObjectContainer.cs
├── Documentation~
└── Images
│ ├── Inspector-FruitExample-1.png
│ ├── Inspector-FruitExample-2.png
│ └── Inspector-FruitExample-3.png
├── CHANGELOG.md.meta
├── LICENSE.md.meta
├── README.md.meta
├── package.json.meta
├── Editor.meta
├── Runtime.meta
├── Tests.meta
├── Tests
├── Editor.meta
└── Editor
│ ├── Editor Resources.meta
│ ├── Unity.ScriptableObjectContainer.Editor.Tests.asmdef.meta
│ ├── Editor Resources
│ ├── Test_001.asset.meta
│ ├── Test_002.asset.meta
│ ├── Test_003.asset.meta
│ ├── Test_004.asset.meta
│ ├── Test_005.asset.meta
│ ├── Test_006.asset.meta
│ ├── Test_007.asset.meta
│ ├── Test_008.asset.meta
│ ├── Test_005.asset
│ ├── Test_004.asset
│ ├── Test_001.asset
│ ├── Test_006.asset
│ ├── Test_007.asset
│ ├── Test_008.asset
│ ├── Test_002.asset
│ └── Test_003.asset
│ ├── Fruit.cs.meta
│ ├── Meat.cs.meta
│ ├── SingleFruit.cs.meta
│ ├── FruitContainer.cs.meta
│ ├── SubAssetWithToggle.cs.meta
│ ├── ScriptableObjectContainerTests.cs.meta
│ ├── Unity.ScriptableObjectContainer.Editor.Tests.asmdef
│ ├── FruitContainer.cs
│ ├── Fruit.cs
│ ├── Meat.cs
│ ├── SingleFruit.cs
│ ├── SubAssetWithToggle.cs
│ └── ScriptableObjectContainerTests.cs
├── Editor
├── Unity.ScriptableObjectContainer.Editor.asmdef.meta
├── ScriptableObjectContainerEditor.cs.meta
├── EditorScriptableObjectContainerUtility.cs.meta
├── ScriptableObjectContainerRenameEditorWindow.cs.meta
├── Unity.ScriptableObjectContainer.Editor.asmdef
├── ScriptableObjectContainerRenameEditorWindow.cs
├── EditorScriptableObjectContainerUtility.cs
└── ScriptableObjectContainerEditor.cs
├── CHANGELOG.md
├── .gitignore
├── package.json
├── LICENSE.md
└── README.md
/Runtime/Unity.ScriptableObjectContainer.Runtime.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Unity.ScriptableObjectContainer.Runtime"
3 | }
4 |
--------------------------------------------------------------------------------
/Documentation~/Images/Inspector-FruitExample-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pschraut/UnityScriptableObjectContainer/HEAD/Documentation~/Images/Inspector-FruitExample-1.png
--------------------------------------------------------------------------------
/Documentation~/Images/Inspector-FruitExample-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pschraut/UnityScriptableObjectContainer/HEAD/Documentation~/Images/Inspector-FruitExample-2.png
--------------------------------------------------------------------------------
/Documentation~/Images/Inspector-FruitExample-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pschraut/UnityScriptableObjectContainer/HEAD/Documentation~/Images/Inspector-FruitExample-3.png
--------------------------------------------------------------------------------
/CHANGELOG.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cd7b06090eb107949a81d6be7506799a
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/LICENSE.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9f43c535946f2b74a9b12398b1c52e0e
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 709827b2b0cd9b04095b39ae99acb1e7
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c50ade3cd1e61b949aca77e39ad0b364
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1dd7a9600a950c9479ad0147d58a3c6f
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Runtime.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dc780965a7037d44d8afb8c5aacc1b78
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b8dd0f57137997b47aab2121d9862d9c
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac029501e15974e4f81a905832c42f6a
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Runtime/Attributes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 29c27a4dc5a407a48ae60c176c8b8169
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f07a2a99328f0c74fa791bb5d36d1960
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Editor/Unity.ScriptableObjectContainer.Editor.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e6711ee95ee562f4499d2c95c4dadef2
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Runtime/Unity.ScriptableObjectContainer.Runtime.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f60f765a85ae24643aff9de06832a458
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Tests/Editor/Unity.ScriptableObjectContainer.Editor.Tests.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d0cfb8bf5ccf62b41aa338806f6c9630
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_001.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dc7a714e8fdc8014393cd8a7641cf954
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_002.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d4de0e16641e83b4490b38c8e190e829
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_003.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 283c4d8dfda39914db6d0a56dec98a98
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_004.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c4f6acf66ba68414b9393d08ea1a819c
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_005.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eaf655f2cebb65a4f9e63dab5a41c36c
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_006.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 139dc730aefebd145bfa5da9335b21d0
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_007.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 17a5657cc184a9144a4f6e0323c65fd8
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_008.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0772d2bfc1456b248bd23d9a7c2da7d3
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 11400000
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Tests/Editor/Fruit.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1360f0b0a64f16b4bb8a81fabdfb3d00
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/Meat.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 02cc9ca69e7435549a7e93d90b79198d
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/SingleFruit.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ec43497dff0d929469b5c456bb1a5bcc
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/FruitContainer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ac9dad67ca91bfb4a956cdf7f6473a2b
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/SubAssetWithToggle.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: de0186abe4dc5ce47a14f83bad33e571
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Runtime/ScriptableObjectContainer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4186eab6ae73578419a08549f3290894
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/ScriptableObjectContainerEditor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 335dc800861814146a8d1a039d7c2506
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Runtime/Attributes/SubAssetOwnerAttribute.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b04b635091a85a94d9d42c0d2f18d718
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/EditorScriptableObjectContainerUtility.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 73560fd2a7c69454ca4facb1d5c8d825
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Runtime/Attributes/CreateSubAssetMenuAttribute.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1fd43ffb69491954f877fe4999e085e7
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Runtime/Attributes/SubAssetToggleAttribute.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d33256029f65d534d9b66b72cb4fcc15
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/ScriptableObjectContainerTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c07897e71c9046b44a3e3cd5c0efabb7
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this package are documented in this file.
3 |
4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6 |
7 |
8 | ## [1.0.0] - 2023-08-26
9 | - First public preview
10 |
--------------------------------------------------------------------------------
/Editor/ScriptableObjectContainerRenameEditorWindow.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5d57d85dc3af6e34db772a1ed86a45da
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Runtime/Attributes/DisallowMultipleSubAssetAttribute.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e0de1f7c7d03ea54fa31c2694838d5ec
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | [Aa]rtifacts/
2 | [Bb]uild/
3 | [Ll]ibrary/
4 | [Oo]bj/
5 | [Tt]emp/
6 | [Ll]og/
7 | [Ll]ogs/
8 | .vs
9 | .vscode
10 | .idea
11 | .DS_Store
12 | *.aspx
13 | *.browser
14 | *.csproj
15 | *.exe
16 | *.ini
17 | *.map
18 | *.mdb
19 | *.npmrc
20 | *.pyc
21 | *.resS
22 | *.sdf
23 | *.sln
24 | *.sublime-project
25 | *.sublime-workspace
26 | *.suo
27 | *.userprefs
28 | .npmrc
29 | *.leu
30 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_005.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: 4186eab6ae73578419a08549f3290894, type: 3}
13 | m_Name: Test_005
14 | m_EditorClassIdentifier:
15 | m_SubObjects: []
16 |
--------------------------------------------------------------------------------
/Editor/Unity.ScriptableObjectContainer.Editor.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Unity.ScriptableObjectContainer.Editor",
3 | "references": [
4 | "GUID:f60f765a85ae24643aff9de06832a458"
5 | ],
6 | "includePlatforms": [
7 | "Editor"
8 | ],
9 | "excludePlatforms": [],
10 | "allowUnsafeCode": false,
11 | "overrideReferences": false,
12 | "precompiledReferences": [],
13 | "autoReferenced": true,
14 | "defineConstraints": [],
15 | "versionDefines": [],
16 | "noEngineReferences": false
17 | }
--------------------------------------------------------------------------------
/Tests/Editor/Unity.ScriptableObjectContainer.Editor.Tests.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Unity.ScriptableObjectContainer.Editor.Tests",
3 | "references": [
4 | "GUID:f60f765a85ae24643aff9de06832a458",
5 | "GUID:e6711ee95ee562f4499d2c95c4dadef2"
6 | ],
7 | "optionalUnityReferences": [
8 | "TestAssemblies"
9 | ],
10 | "includePlatforms": [
11 | "Editor"
12 | ],
13 | "excludePlatforms": [],
14 | "allowUnsafeCode": false,
15 | "overrideReferences": false,
16 | "precompiledReferences": [],
17 | "autoReferenced": true,
18 | "defineConstraints": [],
19 | "versionDefines": [],
20 | "noEngineReferences": false
21 | }
--------------------------------------------------------------------------------
/Runtime/Attributes/SubAssetToggleAttribute.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | #pragma warning disable IDE1006 // Naming Styles
9 | using System;
10 |
11 | namespace Oddworm.Framework
12 | {
13 | [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
14 | public sealed class SubAssetToggleAttribute : Attribute
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Tests/Editor/FruitContainer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | using UnityEngine;
9 | using Oddworm.Framework;
10 |
11 | namespace Oddworm.EditorFramework.Tests.ScriptableObjectContainerTest
12 | {
13 | #if SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS
14 | [CreateAssetMenu(menuName = "ScriptableObjectContainer Tests/Fruit Container")]
15 | #endif
16 | internal class FruitContainer : ScriptableObjectContainer
17 | {
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Tests/Editor/Fruit.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | using UnityEngine;
9 | using Oddworm.Framework;
10 |
11 | namespace Oddworm.EditorFramework.Tests.ScriptableObjectContainerTest
12 | {
13 | #if SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS
14 | [CreateSubAssetMenu(typeof(FruitContainer), menuName = "ScriptableObjectContainer Tests/Fruit")]
15 | #endif
16 | internal class Fruit : ScriptableObject
17 | {
18 | public int number;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Tests/Editor/Meat.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | using UnityEngine;
9 | using Oddworm.Framework;
10 |
11 | namespace Oddworm.EditorFramework.Tests.ScriptableObjectContainerTest
12 | {
13 | #if SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS
14 | [CreateSubAssetMenu(typeof(ScriptableObjectContainer), menuName = "ScriptableObjectContainer Tests/Meat")]
15 | #endif
16 | internal class Meat : ScriptableObject
17 | {
18 | public int number;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Tests/Editor/SingleFruit.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | using UnityEngine;
9 | using Oddworm.Framework;
10 |
11 | namespace Oddworm.EditorFramework.Tests.ScriptableObjectContainerTest
12 | {
13 | #if SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS
14 | [CreateSubAssetMenu(typeof(ScriptableObjectContainer), menuName = "ScriptableObjectContainer Tests/Single Fruit")]
15 | #endif
16 | [DisallowMultipleSubAsset]
17 | internal class SingleFruit : ScriptableObject
18 | {
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Tests/Editor/SubAssetWithToggle.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | using UnityEngine;
9 | using Oddworm.Framework;
10 |
11 | namespace Oddworm.EditorFramework.Tests.ScriptableObjectContainerTest
12 | {
13 | #if SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS
14 | [CreateSubAssetMenu(typeof(ScriptableObjectContainer), menuName = "ScriptableObjectContainer Tests/SubAsset With Toggle")]
15 | #endif
16 | internal class SubAssetWithToggle : ScriptableObject
17 | {
18 | [SubAssetToggle]
19 | [SerializeField] bool m_MyToggle;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Runtime/Attributes/DisallowMultipleSubAssetAttribute.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | #pragma warning disable IDE1006 // Naming Styles
9 | using System;
10 |
11 | namespace Oddworm.Framework
12 | {
13 | ///
14 | /// Prevents ScriptableObjects of same type (or subtype) to be added more than once to a .
15 | ///
16 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
17 | public sealed class DisallowMultipleSubAssetAttribute : Attribute
18 | {
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_004.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &-3186156268429412971
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: ec43497dff0d929469b5c456bb1a5bcc, type: 3}
13 | m_Name: SingleFruit
14 | m_EditorClassIdentifier:
15 | --- !u!114 &11400000
16 | MonoBehaviour:
17 | m_ObjectHideFlags: 0
18 | m_CorrespondingSourceObject: {fileID: 0}
19 | m_PrefabInstance: {fileID: 0}
20 | m_PrefabAsset: {fileID: 0}
21 | m_GameObject: {fileID: 0}
22 | m_Enabled: 1
23 | m_EditorHideFlags: 0
24 | m_Script: {fileID: 11500000, guid: 4186eab6ae73578419a08549f3290894, type: 3}
25 | m_Name: Test_004
26 | m_EditorClassIdentifier:
27 | m_SubObjects:
28 | - {fileID: -3186156268429412971}
29 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_001.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &-2245045354878169941
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: 1360f0b0a64f16b4bb8a81fabdfb3d00, type: 3}
13 | m_Name: Fruit
14 | m_EditorClassIdentifier:
15 | number: 0
16 | --- !u!114 &11400000
17 | MonoBehaviour:
18 | m_ObjectHideFlags: 0
19 | m_CorrespondingSourceObject: {fileID: 0}
20 | m_PrefabInstance: {fileID: 0}
21 | m_PrefabAsset: {fileID: 0}
22 | m_GameObject: {fileID: 0}
23 | m_Enabled: 1
24 | m_EditorHideFlags: 0
25 | m_Script: {fileID: 11500000, guid: ac9dad67ca91bfb4a956cdf7f6473a2b, type: 3}
26 | m_Name: Test_001
27 | m_EditorClassIdentifier:
28 | m_SubObjects:
29 | - {fileID: -2245045354878169941}
30 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_006.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: 4186eab6ae73578419a08549f3290894, type: 3}
13 | m_Name: Test_006
14 | m_EditorClassIdentifier:
15 | m_SubObjects:
16 | - {fileID: 1793690072751849465}
17 | --- !u!114 &1793690072751849465
18 | MonoBehaviour:
19 | m_ObjectHideFlags: 0
20 | m_CorrespondingSourceObject: {fileID: 0}
21 | m_PrefabInstance: {fileID: 0}
22 | m_PrefabAsset: {fileID: 0}
23 | m_GameObject: {fileID: 0}
24 | m_Enabled: 1
25 | m_EditorHideFlags: 0
26 | m_Script: {fileID: 11500000, guid: de0186abe4dc5ce47a14f83bad33e571, type: 3}
27 | m_Name: SubAssetWithToggle
28 | m_EditorClassIdentifier:
29 | m_MyToggle: 1
30 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_007.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: 4186eab6ae73578419a08549f3290894, type: 3}
13 | m_Name: Test_007
14 | m_EditorClassIdentifier:
15 | m_SubObjects:
16 | - {fileID: 1793690072751849465}
17 | --- !u!114 &1793690072751849465
18 | MonoBehaviour:
19 | m_ObjectHideFlags: 0
20 | m_CorrespondingSourceObject: {fileID: 0}
21 | m_PrefabInstance: {fileID: 0}
22 | m_PrefabAsset: {fileID: 0}
23 | m_GameObject: {fileID: 0}
24 | m_Enabled: 1
25 | m_EditorHideFlags: 0
26 | m_Script: {fileID: 11500000, guid: de0186abe4dc5ce47a14f83bad33e571, type: 3}
27 | m_Name: SubAssetWithToggle
28 | m_EditorClassIdentifier:
29 | m_MyToggle: 0
30 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_008.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: 4186eab6ae73578419a08549f3290894, type: 3}
13 | m_Name: Test_008
14 | m_EditorClassIdentifier:
15 | m_SubObjects:
16 | - {fileID: 1793690072751849465}
17 | --- !u!114 &1793690072751849465
18 | MonoBehaviour:
19 | m_ObjectHideFlags: 0
20 | m_CorrespondingSourceObject: {fileID: 0}
21 | m_PrefabInstance: {fileID: 0}
22 | m_PrefabAsset: {fileID: 0}
23 | m_GameObject: {fileID: 0}
24 | m_Enabled: 1
25 | m_EditorHideFlags: 0
26 | m_Script: {fileID: 11500000, guid: de0186abe4dc5ce47a14f83bad33e571, type: 3}
27 | m_Name: SubAssetWithToggle
28 | m_EditorClassIdentifier:
29 | m_MyToggle: 0
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.oddworm.scriptableobjectcontainer",
3 | "version": "1.0.0",
4 | "displayName": "ScriptableObject Container",
5 | "description": "The ScriptableObject Container package provides the ability to nest ScriptableObjects and work with them in a similar manner as Components.\n\nYou can add a ScriptableObject to another ScriptableObject Container just like how you add a Component to a GameObject.\n\nOn the scripting side, you retrieve ScriptableObjects from the Container in a similar way to how you retrieve Components from a GameObject.",
6 | "unity": "2021.3",
7 | "documentationUrl": "https://github.com/pschraut/UnityScriptableObjectContainer",
8 | "dependencies": {
9 | },
10 | "keywords": [
11 | "unity",
12 | "debug"
13 | ],
14 | "author": {
15 | "name": "Peter Schraut",
16 | "url": "http://console-dev.de"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "https://github.com/pschraut/UnityScriptableObjectContainer.git"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020-2023 Peter Schraut (http://www.console-dev.de)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 | of the Software, and to permit persons to whom the Software is furnished to do
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Runtime/Attributes/SubAssetOwnerAttribute.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | #pragma warning disable IDE1006 // Naming Styles
9 | using System;
10 |
11 | namespace Oddworm.Framework
12 | {
13 | ///
14 | /// Use the [] on a field in your sub-asset to let the editor
15 | /// automatically assign a reference to its owner, the .
16 | ///
17 | ///
18 | ///
19 | /// using UnityEngine;
20 | /// using Oddworm.Framework;
21 | ///
22 | /// [CreateSubAssetMenu(menuName = "Example")]
23 | /// public class Example : ScriptableObject
24 | /// {
25 | /// [SubAssetOwner]
26 | /// [SerializeField] ScriptableObjectContainer m_Container;
27 | /// }
28 | ///
29 | ///
30 | [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
31 | public sealed class SubAssetOwnerAttribute : Attribute
32 | {
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_002.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &-5834706919153656172
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: 1360f0b0a64f16b4bb8a81fabdfb3d00, type: 3}
13 | m_Name: Fruit
14 | m_EditorClassIdentifier:
15 | number: 2
16 | --- !u!114 &-2245045354878169941
17 | MonoBehaviour:
18 | m_ObjectHideFlags: 0
19 | m_CorrespondingSourceObject: {fileID: 0}
20 | m_PrefabInstance: {fileID: 0}
21 | m_PrefabAsset: {fileID: 0}
22 | m_GameObject: {fileID: 0}
23 | m_Enabled: 1
24 | m_EditorHideFlags: 0
25 | m_Script: {fileID: 11500000, guid: 1360f0b0a64f16b4bb8a81fabdfb3d00, type: 3}
26 | m_Name: Fruit
27 | m_EditorClassIdentifier:
28 | number: 0
29 | --- !u!114 &11400000
30 | MonoBehaviour:
31 | m_ObjectHideFlags: 0
32 | m_CorrespondingSourceObject: {fileID: 0}
33 | m_PrefabInstance: {fileID: 0}
34 | m_PrefabAsset: {fileID: 0}
35 | m_GameObject: {fileID: 0}
36 | m_Enabled: 1
37 | m_EditorHideFlags: 0
38 | m_Script: {fileID: 11500000, guid: ac9dad67ca91bfb4a956cdf7f6473a2b, type: 3}
39 | m_Name: Test_002
40 | m_EditorClassIdentifier:
41 | m_SubObjects:
42 | - {fileID: -2245045354878169941}
43 | - {fileID: 5518851017741398026}
44 | - {fileID: -5834706919153656172}
45 | --- !u!114 &5518851017741398026
46 | MonoBehaviour:
47 | m_ObjectHideFlags: 0
48 | m_CorrespondingSourceObject: {fileID: 0}
49 | m_PrefabInstance: {fileID: 0}
50 | m_PrefabAsset: {fileID: 0}
51 | m_GameObject: {fileID: 0}
52 | m_Enabled: 1
53 | m_EditorHideFlags: 0
54 | m_Script: {fileID: 11500000, guid: 1360f0b0a64f16b4bb8a81fabdfb3d00, type: 3}
55 | m_Name: Fruit
56 | m_EditorClassIdentifier:
57 | number: 1
58 |
--------------------------------------------------------------------------------
/Runtime/Attributes/CreateSubAssetMenuAttribute.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | #pragma warning disable IDE1006 // Naming Styles
9 | using System;
10 |
11 | namespace Oddworm.Framework
12 | {
13 | ///
14 | /// Mark a -derived type to be automatically listed in the "Add Object" submenu,
15 | /// so that instances of the type can be easily created and added to the particular .
16 | ///
17 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
18 | public sealed class CreateSubAssetMenuAttribute : Attribute
19 | {
20 | ///
21 | /// The type where the menu item is being created at.
22 | ///
23 | public Type type
24 | {
25 | get;
26 | private set;
27 | }
28 |
29 | ///
30 | /// Whether to add the menu item to sub-classes of instances that are of the specified .
31 | ///
32 | public bool allowSubClass
33 | {
34 | get;
35 | set;
36 | }
37 |
38 | ///
39 | /// Whether to create a menu item for the specifically. It's useful when you add
40 | /// the to a base-class where you want all sub-classes to
41 | /// have menu items generated for, except for the base-class.
42 | ///
43 | public bool excludeThisClass
44 | {
45 | get;
46 | set;
47 | }
48 |
49 | ///
50 | /// The display name for this type shown in the "Add Object" menu.
51 | /// If is empty, it uses the type name instead.
52 | ///
53 | ///
54 | /// As with other menu item code, use a forward-slash ("/") to group items into submenus.
55 | /// For example, specifying "Gameplay/Objective" as will cause the menu item
56 | /// 'Objective' to be inside a 'Gameplay' submenu of the "Add Object" menu.
57 | ///
58 | public string menuName
59 | {
60 | get;
61 | set;
62 | }
63 |
64 | public CreateSubAssetMenuAttribute(Type containerType)
65 | : base()
66 | {
67 | this.type = containerType;
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Editor/ScriptableObjectContainerRenameEditorWindow.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | #pragma warning disable IDE1006 // Naming Styles
9 | using UnityEngine;
10 | using UnityEditor;
11 |
12 | namespace Oddworm.EditorFramework
13 | {
14 | internal class ScriptableObjectContainerRenameEditorWindow : EditorWindow
15 | {
16 | string m_NewText;
17 | Object m_ObjectToRename;
18 | bool m_FirstUpdate;
19 |
20 | public void Show(Object objectToRename)
21 | {
22 | m_ObjectToRename = objectToRename;
23 | m_NewText = m_ObjectToRename.name;
24 | m_FirstUpdate = true;
25 |
26 | ShowModalUtility();
27 | }
28 |
29 | void OnEnable()
30 | {
31 | titleContent = new GUIContent("Rename");
32 | minSize = new Vector2(300, 120);
33 | maxSize = new Vector2(300, 120);
34 | }
35 |
36 | void OnGUI()
37 | {
38 | var cancel = false;
39 | var rename = false;
40 |
41 | var e = Event.current;
42 | if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Escape)
43 | cancel = true;
44 |
45 | if (e.type == EventType.KeyDown && e.keyCode == KeyCode.Return)
46 | rename = !string.IsNullOrEmpty(m_NewText);
47 |
48 | EditorGUILayout.Space();
49 | GUI.SetNextControlName("RenameField");
50 | m_NewText = EditorGUILayout.TextField(m_NewText);
51 | if (m_FirstUpdate && e.type == EventType.Layout)
52 | {
53 | m_FirstUpdate = false;
54 | GUI.FocusControl("RenameField");
55 | EditorGUI.FocusTextInControl("RenameField");
56 | }
57 | EditorGUILayout.Space();
58 |
59 | EditorGUILayout.HelpBox("Press Return to rename or Escape to cancel.", MessageType.Info, true);
60 | EditorGUILayout.Space();
61 | GUILayout.FlexibleSpace();
62 |
63 | EditorGUILayout.BeginHorizontal();
64 | GUILayout.FlexibleSpace();
65 |
66 | EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_NewText));
67 | if (GUILayout.Button(new GUIContent("Rename", "Return")) || rename)
68 | {
69 | if (m_ObjectToRename != null && m_ObjectToRename.name != m_NewText)
70 | {
71 | Undo.RecordObject(m_ObjectToRename, "Rename");
72 | m_ObjectToRename.name = m_NewText;
73 | }
74 | Close();
75 | }
76 | EditorGUI.EndDisabledGroup();
77 |
78 | if (GUILayout.Button(new GUIContent("Cancel", "Escape")) || cancel)
79 | Close();
80 |
81 | EditorGUILayout.EndHorizontal();
82 | EditorGUILayout.Space();
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Tests/Editor/Editor Resources/Test_003.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &-5834706919153656172
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: 1360f0b0a64f16b4bb8a81fabdfb3d00, type: 3}
13 | m_Name: Fruit
14 | m_EditorClassIdentifier:
15 | number: 2
16 | --- !u!114 &-2245045354878169941
17 | MonoBehaviour:
18 | m_ObjectHideFlags: 0
19 | m_CorrespondingSourceObject: {fileID: 0}
20 | m_PrefabInstance: {fileID: 0}
21 | m_PrefabAsset: {fileID: 0}
22 | m_GameObject: {fileID: 0}
23 | m_Enabled: 1
24 | m_EditorHideFlags: 0
25 | m_Script: {fileID: 11500000, guid: 1360f0b0a64f16b4bb8a81fabdfb3d00, type: 3}
26 | m_Name: Fruit
27 | m_EditorClassIdentifier:
28 | number: 0
29 | --- !u!114 &11400000
30 | MonoBehaviour:
31 | m_ObjectHideFlags: 0
32 | m_CorrespondingSourceObject: {fileID: 0}
33 | m_PrefabInstance: {fileID: 0}
34 | m_PrefabAsset: {fileID: 0}
35 | m_GameObject: {fileID: 0}
36 | m_Enabled: 1
37 | m_EditorHideFlags: 0
38 | m_Script: {fileID: 11500000, guid: ac9dad67ca91bfb4a956cdf7f6473a2b, type: 3}
39 | m_Name: Test_003
40 | m_EditorClassIdentifier:
41 | m_SubObjects:
42 | - {fileID: -2245045354878169941}
43 | - {fileID: 256508848403889015}
44 | - {fileID: 5518851017741398026}
45 | - {fileID: 2869424647571882560}
46 | - {fileID: -5834706919153656172}
47 | - {fileID: 3674869790121034100}
48 | --- !u!114 &256508848403889015
49 | MonoBehaviour:
50 | m_ObjectHideFlags: 0
51 | m_CorrespondingSourceObject: {fileID: 0}
52 | m_PrefabInstance: {fileID: 0}
53 | m_PrefabAsset: {fileID: 0}
54 | m_GameObject: {fileID: 0}
55 | m_Enabled: 1
56 | m_EditorHideFlags: 0
57 | m_Script: {fileID: 11500000, guid: 02cc9ca69e7435549a7e93d90b79198d, type: 3}
58 | m_Name: Meat
59 | m_EditorClassIdentifier:
60 | number: 0
61 | --- !u!114 &2869424647571882560
62 | MonoBehaviour:
63 | m_ObjectHideFlags: 0
64 | m_CorrespondingSourceObject: {fileID: 0}
65 | m_PrefabInstance: {fileID: 0}
66 | m_PrefabAsset: {fileID: 0}
67 | m_GameObject: {fileID: 0}
68 | m_Enabled: 1
69 | m_EditorHideFlags: 0
70 | m_Script: {fileID: 11500000, guid: 02cc9ca69e7435549a7e93d90b79198d, type: 3}
71 | m_Name: Meat
72 | m_EditorClassIdentifier:
73 | number: 1
74 | --- !u!114 &3674869790121034100
75 | MonoBehaviour:
76 | m_ObjectHideFlags: 0
77 | m_CorrespondingSourceObject: {fileID: 0}
78 | m_PrefabInstance: {fileID: 0}
79 | m_PrefabAsset: {fileID: 0}
80 | m_GameObject: {fileID: 0}
81 | m_Enabled: 1
82 | m_EditorHideFlags: 0
83 | m_Script: {fileID: 11500000, guid: 02cc9ca69e7435549a7e93d90b79198d, type: 3}
84 | m_Name: Meat
85 | m_EditorClassIdentifier:
86 | number: 2
87 | --- !u!114 &5518851017741398026
88 | MonoBehaviour:
89 | m_ObjectHideFlags: 0
90 | m_CorrespondingSourceObject: {fileID: 0}
91 | m_PrefabInstance: {fileID: 0}
92 | m_PrefabAsset: {fileID: 0}
93 | m_GameObject: {fileID: 0}
94 | m_Enabled: 1
95 | m_EditorHideFlags: 0
96 | m_Script: {fileID: 11500000, guid: 1360f0b0a64f16b4bb8a81fabdfb3d00, type: 3}
97 | m_Name: Fruit
98 | m_EditorClassIdentifier:
99 | number: 1
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ScriptableObject Container for Unity
2 |
3 | The [ScriptableObject](https://docs.unity3d.com/Manual/class-ScriptableObject.html) type in Unity is a powerful concept with many different applications.
4 | However, it lacks a feature that would greatly increase its usefulness for me: the ability to add "Components" to it.
5 | While Unity allows you to add "Components" to a ScriptableObject asset through code, it does not provide functionality to do so through the Inspector.
6 |
7 | The ScriptableObject Container package aims to solve this issue.
8 | It allows you to work with ScriptableObjects in a similar manner to how you work with Components and GameObjects.
9 |
10 | To add a ScriptableObject to a ```ScriptableObjectContainer```, you can use the Inspector, just like adding a Component to a GameObject.
11 |
12 | On the scripting side, you can access the ScriptableObject from the ```ScriptableObjectContainer``` in a similar way to how you access a Component from a GameObject.
13 |
14 | | ScriptableObjectContainer | GameObject |
15 | |----------|---------------|
16 | | ```ScriptableObject GetObject(Type type)``` | ```Component GetComponent(Type type)``` |
17 | | ```void GetObjects(Type type, List results)``` | ```void GetComponents(Type type, List results)``` |
18 | | ```T GetObject()``` | ```T GetComponent``` |
19 | | ```void GetObjects(List results)``` | ```void GetComponents(List results)``` |
20 |
21 | You can think of a ScriptableObjectContainer as "GameObject" and its sub-assets (or objects) would be the Components on a GameObject.
22 |
23 | # Installation
24 |
25 | Requires Unity 2021.3 and newer.
26 | From the Unity main menu choose Window > Package Manager.
27 | In the Package Manager window, choose "Add package from git URL" and insert one of the Package URL's you can find below.
28 |
29 | ## Package URL's
30 |
31 | | Version | Link |
32 | |----------|---------------|
33 | | 1.0.0 | https://github.com/pschraut/UnityScriptableObjectContainer.git#1.0.0 |
34 |
35 | # Credits
36 |
37 | If this package is useful to you, please mention my name in your credits screen.
38 | Something like "ScriptableObject Container by Peter Schraut" or "Thanks to Peter Schraut" would be very much appreciated.
39 |
40 | # Contact
41 |
42 | Please post in the Unity forums thread that I created for this package: https://forum.unity.com/threads/scriptableobject-container-package.1484589/
43 |
44 | # Example
45 |
46 | FruitContainer.cs:
47 | ```CSharp
48 | using UnityEngine;
49 | using Oddworm.Framework;
50 |
51 | // Inherit a new container type from ScriptableObjectContainer.
52 | // The CreateAssetMenu attribute lets you create the container from the Assets/Create menu.
53 | [UnityEngine.CreateAssetMenu(menuName = "FruitContainer")]
54 | public class FruitContainer : Oddworm.Framework.ScriptableObjectContainer
55 | {
56 | }
57 | ```
58 |
59 | Fruit.cs:
60 | ```CSharp
61 | using UnityEngine;
62 | using Oddworm.Framework;
63 |
64 | // Create a new type that adds itself to the "FruitContainer" Inspector.
65 | // The CreateSubAssetMenu attribute lets you add objects to the container through in the Inspector.
66 | [Oddworm.Framework.CreateSubAssetMenu(typeof(FruitContainer))]
67 | public class Fruit : UnityEngine.ScriptableObject
68 | {
69 | [SerializeField] int m_HelloWorld = 123;
70 | }
71 | ```
72 |
73 | When you create the ```FruitContainer``` asset via "Assets/Create/FruitContainer" it displays an empty ScriptableObjectContainer in
74 | a similar manner as a GameObject without Components.
75 |
76 | 
77 |
78 | You can then add sub-assets via the "Add Object" button. The menu displays all ScriptableObject that have been added to the
79 | container via the ```CreateSubAssetMenu``` attribute.
80 |
81 | 
82 |
83 | After adding the sub-asset it's shown in the Inspector as demonstrated in the image below.
84 |
85 | 
86 |
87 |
88 | # How it works
89 |
90 | The package introduces the type ```ScriptableObjectContainer``` that inherits from ScriptableObject.
91 |
92 | A custom inspector implements the magic that allows to add a ScriptableObject as sub-asset,
93 | to remove such sub-asset as well as to change properties of such sub-asset through the Inspector.
94 |
95 | The ScriptableObjectContainer Inspector attempts to mimic the look and feel of Unity's built-in
96 | Inspector when working with GameObjects and Components.
97 |
98 | The ScriptableObjectContainer itself is rather light-weight. It contains an array with
99 | references to its sub-assets.
100 | This allows you to retrieve these sub-assets through code, similar to how you work with the
101 | ```GameObject.GetComponent``` and ```GameObject.GetComponents``` methods.
102 |
103 | Beside the sub-assets array and its corresponding getter methods,
104 | the ScriptableObjectContainer does not contain more code that's required in a build.
105 | It implements ```OnValidate``` to update fields in sub-assets that use the
106 | ```SubAssetOwnerAttribute``` attribute, but this code runs in the editor only.
107 |
108 | # Test Runner integration
109 |
110 | The ScriptableObjectContainer package comes with several tests that run in
111 | [Unity's Test Runner](https://docs.unity3d.com/Packages/com.unity.test-framework@latest).
112 |
113 | The tests can be enabled through the
114 | ```SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS``` scripting define symbol.
115 | Add this scripting define symbol to the Player Settings and the tests appear in
116 | Unity's Test Runner.
117 |
118 | Additionally to the tests in the Test Runner window,
119 | it adds various context menu items to create test assets,
120 | which is the reason why it's disabled by default, to avoid cluttering your project with things you most likely don't need.
121 |
122 | # Context Menu integration
123 |
124 | The package adds a "ScriptableObject Container" item to the
125 | assets context menu, which allows to create a new
126 | ScriptableObject Container asset.
127 |
128 | In case you don't want to allow the use of a ScriptableObject Container,
129 | but only allow your specific derived containers, use the
130 | ```SCRIPTABLEOBJECTCONTAINER_DISABLE_MENUITEM```
131 | scripting define symbol to remove the context-menuitem.
132 |
133 |
134 | # More Examples
135 |
136 | ## CreateSubAssetMenuAttribute
137 |
138 | A ScriptableObjectContainer shows an "Add Object" button in the Inspector,
139 | much like a GameObject shows a "Add Component" button. It allows you to add
140 | objects that inherit from ScriptableObject to a specific container.
141 |
142 | In order to add a ScriptableObject to the "Add Object" menu, you need to
143 | add the ```CreateSubAssetMenuAttribute``` to the ScriptableObject type.
144 |
145 | You can add multiple ```CreateSubAssetMenuAttribute``` to add it to different
146 | containers. You can also specify the base-container type to add a menu item
147 | to all types that inherit from the base-container.
148 | ```CSharp
149 | [CreateSubAssetMenu(typeof(FruitContainer), menuName = "Fruit")]
150 | class Fruit : ScriptableObject
151 | {
152 | // ...
153 | }
154 | ```
155 |
156 |
157 | ## DisallowMultipleSubAssetAttribute
158 |
159 | If you want to prevent to add the same ScriptableObject type (or subtype)
160 | more than once to the same container, you can use the ```DisallowMultipleSubAssetAttribute```.
161 |
162 | This works similar to how you use Unity's
163 | [DisallowMultipleComponentAttribute](https://docs.unity3d.com/ScriptReference/DisallowMultipleComponent.html)
164 | to prevent a MonoBehaviour of same type (or subtype) to be added more than once to a GameObject.
165 | ```CSharp
166 | [DisallowMultipleSubAsset]
167 | class Fruit : ScriptableObject
168 | {
169 | // ...
170 | }
171 | ```
172 | [](http://www.youtube.com/watch?v=QnjTcPqM0sg "")
173 |
174 |
175 | ## SubAssetOwnerAttribute
176 |
177 | If you need a reference to the ScriptableObjectContainer inside your ScriptableObject
178 | sub-asset, you can use the ```SubAssetOwnerAttribute``` for the system to automatically
179 | setup the reference for you. The code that sets up references runs in the editor only,
180 | there is no performance penalty in a build.
181 | ```CSharp
182 | class Fruit : ScriptableObject
183 | {
184 | [SubAssetOwner]
185 | [SerializeField] ScriptableObjectContainer m_Container;
186 | }
187 | ```
188 | If you know that a sub-asset lives inside a specific container type only,
189 | you can also use the specific container type.
190 | ```CSharp
191 | class Fruit : ScriptableObject
192 | {
193 | [SubAssetOwner]
194 | [SerializeField] Basket m_Container; // The Basket type must inherit
195 | // from ScriptableObjectContainer
196 | }
197 | ```
198 | [](http://www.youtube.com/watch?v=Ex9FQ3yXhBw "")
199 |
200 |
201 | ## SubAssetToggleAttribute
202 |
203 | Unity does not support the concept of enabling and disabling a ScriptableObject,
204 | but I often found myselfing wanting a simple way to expose an "enabled" toggle
205 | for whatever use-case I have.
206 |
207 | Using the ```SubAssetToggleAttribute``` on a ```bool``` field causes the
208 | ScriptableObjectContainer Inspector to display a toggle (checkbox) like you can find
209 | in Components on a GameObject.
210 | ```CSharp
211 | class Fruit : ScriptableObject
212 | {
213 | [SubAssetToggle]
214 | [SerializeField] bool m_IsEnabled;
215 | }
216 | ```
217 | You can use any field name you like, it doesn't have to be ```m_IsEnabled```.
218 | However, it's worth noting that you can't use ```m_Enabled``` as field name, because
219 | it conflicts with a field that Unity implements too (but seemingly Unity isn't using it).
220 |
221 | [](http://www.youtube.com/watch?v=tMfqDenY1pc "")
222 |
223 |
--------------------------------------------------------------------------------
/Tests/Editor/ScriptableObjectContainerTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0079 // Remove unnecessary suppression
6 | #pragma warning disable IDE0040 // Add accessibility modifiers
7 | #pragma warning disable IDE0051 // Remove unused private members
8 | #pragma warning disable IDE0062 // Make local function 'static'
9 | #pragma warning disable IDE0074 // Use compound assignment
10 | using UnityEngine;
11 | using NUnit.Framework;
12 | using UnityEditor;
13 | using Oddworm.Framework;
14 |
15 | namespace Oddworm.EditorFramework.Tests.ScriptableObjectContainerTest
16 | {
17 | #if SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS
18 | class ScriptableObjectContainerTests
19 | {
20 | const string k_PackageTestsFolderAssetGUID = "f07a2a99328f0c74fa791bb5d36d1960";
21 |
22 | [Test]
23 | public void Test_FindContainerAssets()
24 | {
25 | var folder = AssetDatabase.GUIDToAssetPath(k_PackageTestsFolderAssetGUID);
26 | var assets = FindAllPipelineAssets(new[] { folder });
27 | Assert.IsTrue(assets.Length > 0);
28 | }
29 |
30 | [Test]
31 | public void Test_FindContainerAsset()
32 | {
33 | Assert.IsNotNull(FindContainerAsset("Test_001"));
34 | Assert.IsNotNull(FindContainerAsset("Test_002"));
35 | Assert.IsNotNull(FindContainerAsset("Test_003"));
36 | Assert.IsNotNull(FindContainerAsset("Test_004"));
37 | Assert.IsNotNull(FindContainerAsset("Test_005"));
38 | Assert.IsNotNull(FindContainerAsset("Test_006"));
39 | Assert.IsNotNull(FindContainerAsset("Test_007"));
40 | Assert.IsNotNull(FindContainerAsset("Test_008"));
41 | }
42 |
43 | [Test]
44 | public void Test_001_GetObject()
45 | {
46 | var container = FindContainerAsset("Test_001");
47 | Assert.IsNotNull(container.GetObject(typeof(Fruit)));
48 | Assert.IsNotNull(container.GetObject());
49 |
50 | Assert.IsNotNull(container.GetObject(typeof(ScriptableObject)));
51 | Assert.IsNotNull(container.GetObject());
52 | }
53 |
54 | [Test]
55 | public void Test_001_GetObjects()
56 | {
57 | var container = FindContainerAsset("Test_001");
58 | Assert.IsNotNull(container.GetObjects(typeof(Fruit)));
59 | Assert.IsNotNull(container.GetObjects());
60 |
61 | Assert.AreEqual(1, container.GetObjects(typeof(Fruit)).Length);
62 | Assert.AreEqual(1, container.GetObjects().Length);
63 |
64 |
65 | Assert.IsNotNull(container.GetObjects(typeof(ScriptableObject)));
66 | Assert.IsNotNull(container.GetObjects());
67 |
68 | Assert.AreEqual(1, container.GetObjects(typeof(ScriptableObject)).Length);
69 | Assert.AreEqual(1, container.GetObjects().Length);
70 | }
71 |
72 | [Test]
73 | public void Test_002_GetObject()
74 | {
75 | var container = FindContainerAsset("Test_002");
76 | Assert.IsNotNull(container.GetObject(typeof(Fruit)));
77 | Assert.IsNotNull(container.GetObject());
78 |
79 | Assert.IsNotNull(container.GetObject(typeof(ScriptableObject)));
80 | Assert.IsNotNull(container.GetObject());
81 | }
82 |
83 | [Test]
84 | public void Test_002_GetObjects()
85 | {
86 | var container = FindContainerAsset("Test_002");
87 |
88 | Test(container.GetObjects(typeof(Fruit)));
89 | Test(container.GetObjects());
90 |
91 | Test(container.GetObjects(typeof(ScriptableObject)));
92 | Test(container.GetObjects());
93 |
94 | void Test(System.Collections.Generic.IEnumerable objs)
95 | {
96 | Assert.IsNotNull(objs);
97 | if (objs == null)
98 | return;
99 |
100 | // Tests if "GetObjects" retrieves objects in the expected order
101 | var n = 0;
102 | foreach(var o in objs)
103 | {
104 | var obj = o as Fruit;
105 | Assert.NotNull(obj);
106 | if (obj == null)
107 | return;
108 |
109 | Assert.AreEqual(n, obj.number);
110 | n++;
111 | }
112 |
113 | Assert.AreEqual(3, n);
114 | }
115 | }
116 |
117 | [Test]
118 | public void Test_003_GetObjects()
119 | {
120 | var container = FindContainerAsset("Test_003");
121 |
122 | Test(container.GetObjects(typeof(Fruit)), 3, 0);
123 | Test(container.GetObjects(), 3, 0);
124 |
125 | Test(container.GetObjects(typeof(Meat)), 0, 3);
126 | Test(container.GetObjects(), 0, 3);
127 |
128 | Test(container.GetObjects(typeof(ScriptableObject)), 3, 3);
129 | Test(container.GetObjects(), 3, 3);
130 |
131 | void Test(System.Collections.Generic.IEnumerable objs, int expectedFruitNumber, int expectedMeatNumber)
132 | {
133 | Assert.IsNotNull(objs);
134 | if (objs == null)
135 | return;
136 |
137 | // Tests if "GetObjects" retrieves objects in the expected order
138 | var fruitNumber = 0;
139 | var meatNumber = 0;
140 | foreach (var o in objs)
141 | {
142 | var fruit = o as Fruit;
143 | var meat = o as Meat;
144 | Assert.IsTrue(meat != null || fruit != null);
145 |
146 | if (fruit != null)
147 | {
148 | Assert.AreEqual(fruitNumber, fruit.number);
149 | fruitNumber++;
150 | }
151 |
152 | if (meat != null)
153 | {
154 | Assert.AreEqual(meatNumber, meat.number);
155 | meatNumber++;
156 | }
157 | }
158 |
159 | Assert.AreEqual(expectedFruitNumber, fruitNumber);
160 | Assert.AreEqual(expectedMeatNumber, meatNumber);
161 | }
162 | }
163 |
164 | [Test]
165 | public void Test_004_CanAddObjectOfType()
166 | {
167 | var container = FindContainerAsset("Test_004");
168 |
169 | var canAdd = EditorScriptableObjectContainerUtility.CanAddObjectOfType(container, typeof(SingleFruit), false);
170 | Assert.IsFalse(canAdd);
171 | }
172 |
173 | [Test]
174 | public void Test_005_CanAddObjectOfType()
175 | {
176 | var container = FindContainerAsset("Test_005");
177 |
178 | var canAdd = EditorScriptableObjectContainerUtility.CanAddObjectOfType(container, typeof(SingleFruit), false);
179 | Assert.IsTrue(canAdd);
180 | }
181 |
182 | [Test]
183 | public void Test_006()
184 | {
185 | var container = FindContainerAsset("Test_006");
186 | Assert.NotNull(container);
187 |
188 | var subObj = container.GetObject();
189 | Assert.NotNull(subObj);
190 |
191 | var fields = EditorScriptableObjectContainerUtility.GetObjectToggleFields(subObj);
192 | Assert.NotNull(fields);
193 | Assert.IsTrue(fields.Count == 1);
194 |
195 | var value = EditorScriptableObjectContainerUtility.GetObjectToggleValue(subObj, fields);
196 | Assert.IsTrue(value);
197 | }
198 |
199 | [Test]
200 | public void Test_007()
201 | {
202 | var container = FindContainerAsset("Test_007");
203 | Assert.NotNull(container);
204 |
205 | var subObj = container.GetObject();
206 | Assert.NotNull(subObj);
207 |
208 | var fields = EditorScriptableObjectContainerUtility.GetObjectToggleFields(subObj);
209 | Assert.NotNull(fields);
210 | Assert.IsTrue(fields.Count == 1);
211 |
212 | var value = EditorScriptableObjectContainerUtility.GetObjectToggleValue(subObj, fields);
213 | Assert.IsFalse(value);
214 | }
215 |
216 | [Test]
217 | public void Test_008_SetObjectToggleValue()
218 | {
219 | var container = FindContainerAsset("Test_008");
220 | Assert.NotNull(container);
221 |
222 | var subObj = container.GetObject();
223 | Assert.NotNull(subObj);
224 |
225 | var fields = EditorScriptableObjectContainerUtility.GetObjectToggleFields(subObj);
226 | Assert.NotNull(fields);
227 | Assert.IsTrue(fields.Count == 1);
228 |
229 | Assert.IsFalse(EditorScriptableObjectContainerUtility.GetObjectToggleValue(subObj, fields));
230 | try
231 | {
232 | EditorScriptableObjectContainerUtility.SetObjectToggleValue(subObj, fields, true);
233 | Assert.IsTrue(EditorScriptableObjectContainerUtility.GetObjectToggleValue(subObj, fields));
234 | }
235 | finally
236 | {
237 | EditorScriptableObjectContainerUtility.SetObjectToggleValue(subObj, fields, false);
238 | }
239 | }
240 |
241 | ScriptableObjectContainer FindContainerAsset(string assetName)
242 | {
243 | var folder = AssetDatabase.GUIDToAssetPath(k_PackageTestsFolderAssetGUID);
244 | return FindPipelineAsset(assetName, new[] { folder });
245 | }
246 |
247 | ///
248 | /// Finds the pipeline asset with the specified name.
249 | ///
250 | /// The pipeline asset filename
251 | /// Search for pipeline assets in the specified folders only. Pass null to search entire Assets directory.
252 | /// The asset on success, null otherwise.
253 | /// Thrown when is null.
254 | static ScriptableObjectContainer FindPipelineAsset(string pipelineAssetName, string[] searchInFolders = null)
255 | {
256 | if (string.IsNullOrEmpty(pipelineAssetName))
257 | return null;
258 |
259 | foreach (var asset in FindAllPipelineAssets(searchInFolders))
260 | {
261 | var assetPath = AssetDatabase.GetAssetPath(asset);
262 | var assetName = System.IO.Path.GetFileNameWithoutExtension(assetPath);
263 |
264 | if (string.Equals(assetName, pipelineAssetName, System.StringComparison.OrdinalIgnoreCase))
265 | return AssetDatabase.LoadAssetAtPath(assetPath);
266 | }
267 |
268 | return null;
269 | }
270 |
271 | ///
272 | /// Finds all pipeline asset in the project.
273 | ///
274 | /// Search for pipeline assets in the specified folders only. Pass null to search entire Assets directory.
275 | /// The pipeline assets that were found in the project or an empty array if no pipeline asset was found.
276 | static ScriptableObjectContainer[] FindAllPipelineAssets(string[] searchInFolders = null)
277 | {
278 | if (searchInFolders == null)
279 | searchInFolders = new[] { "Assets" };
280 |
281 | var guids = AssetDatabase.FindAssets($"t: {nameof(ScriptableObjectContainer)}", searchInFolders);
282 | var pipelineAssets = new ScriptableObjectContainer[guids.Length];
283 |
284 | for (var n = 0; n < guids.Length; ++n)
285 | {
286 | var assetPath = AssetDatabase.GUIDToAssetPath(guids[n]);
287 | var pipelineAsset = AssetDatabase.LoadAssetAtPath(assetPath);
288 |
289 | pipelineAssets[n] = pipelineAsset;
290 | }
291 |
292 | return pipelineAssets;
293 | }
294 | }
295 | #endif // SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS
296 | }
297 |
--------------------------------------------------------------------------------
/Runtime/ScriptableObjectContainer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ScriptableObject Container for Unity. Copyright (c) 2020-2023 Peter Schraut (www.console-dev.de). See LICENSE.md
3 | // https://github.com/pschraut/UnityScriptableObjectContainer
4 | //
5 | #pragma warning disable IDE0019 // Use Pattern matching
6 | #pragma warning disable IDE0079 // Remove unnecessary suppression
7 | #pragma warning disable IDE0040 // Add accessibility modifiers
8 | #pragma warning disable IDE0051 // Remove unused private members
9 | #pragma warning disable IDE1006 // Naming Styles
10 | using System;
11 | using System.Collections.Generic;
12 | using UnityEngine;
13 |
14 | #if UNITY_EDITOR
15 | using System.Reflection;
16 | #endif
17 |
18 | namespace Oddworm.Framework
19 | {
20 | #if !SCRIPTABLEOBJECTCONTAINER_DISABLE_MENUITEM
21 | [CreateAssetMenu(menuName = "ScriptableObject Container", order = 310)]
22 | #endif
23 | public class ScriptableObjectContainer : ScriptableObject
24 | {
25 | [Tooltip("The array holds references to the added objects.")]
26 | [HideInInspector]
27 | [SerializeField] ScriptableObject[] m_SubObjects = Array.Empty();
28 |
29 | static readonly List