Skip to content

Commit 126d084

Browse files
committed
Serialize Preset in PropertyModifier directly
GlobalObjectId doesn't work for objects opened in Prefab mode, so this is a more reliable approach
1 parent 95c3de3 commit 126d084

14 files changed

+112
-213
lines changed

Editor/AssetModificationProcessor.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,5 @@ static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions
99
EmbeddedPresetHolder.Instance.HandleAssetDelete(assetPath);
1010
return AssetDeleteResult.DidNotDelete;
1111
}
12-
13-
static string[] OnWillSaveAssets(string[] paths)
14-
{
15-
EmbeddedPresetHolder.Instance.HandleAssetSave(paths);
16-
return paths;
17-
}
1812
}
1913
}

Editor/CustomDependencies/ScriptingDefineSymbolsDependency.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Linq;
21
using UnityEditor;
32
using UnityEditor.Callbacks;
43
#if UNITY_2017_3_OR_NEWER

Editor/CustomInspectors/PropertyModifierEditor.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ public class PropertyModifierEditor : AImportTimeObjectModifierEditor
99
{
1010
private SerializedProperty _gameObjectProperty;
1111
private SerializedProperty _componentIndexProperty;
12-
private GlobalObjectId _serializedObjectId;
13-
private Preset _preset;
12+
private SerializedProperty _presetProperty;
1413
private UnityEditor.Editor _presetEditor;
1514

1615
void OnEnable()
1716
{
1817
_gameObjectProperty = serializedObject.FindProperty($"{nameof(PropertyModifier.Target)}.{nameof(GameObjectOrComponent.GameObject)}");
1918
_componentIndexProperty = serializedObject.FindProperty($"{nameof(PropertyModifier.Target)}.{nameof(GameObjectOrComponent.ComponentIndex)}");
20-
_serializedObjectId = GlobalObjectId.GetGlobalObjectIdSlow(target);
21-
_preset = EmbeddedPresetHolder.Instance.GetOrCreatePreset(_serializedObjectId, GetTarget());
19+
_presetProperty = serializedObject.FindProperty(nameof(PropertyModifier._preset));
2220
}
2321

2422
void OnDisable()
@@ -33,21 +31,32 @@ public override void OnInspectorGUI()
3331
Object previousTarget = GetTarget();
3432
DrawDefaultInspector();
3533
Object newTarget = GetTarget();
36-
if (newTarget != previousTarget)
34+
Preset preset = (Preset) _presetProperty.objectReferenceValue;
35+
if (newTarget != previousTarget || preset == null || !preset.CanBeAppliedTo(newTarget))
3736
{
38-
Undo.RecordObject(EmbeddedPresetHolder.Instance, "");
39-
_preset = EmbeddedPresetHolder.Instance.GetOrCreatePreset(_serializedObjectId, newTarget);
37+
if (newTarget == null)
38+
{
39+
preset = null;
40+
_presetProperty.objectReferenceValue = null;
41+
}
42+
else
43+
{
44+
preset = EmbeddedPresetHolder.Instance.CreatePreset(((Component) target).gameObject, newTarget);
45+
_presetProperty.objectReferenceValue = preset;
46+
}
4047
}
4148

42-
if (_preset != null)
49+
if (preset != null)
4350
{
44-
if (_presetEditor == null || _presetEditor.target != _preset)
51+
if (_presetEditor == null || _presetEditor.target != preset)
4552
{
4653
DestroyImmediate(_presetEditor);
47-
_presetEditor = CreateEditor(_preset);
54+
_presetEditor = CreateEditor(preset);
4855
}
4956
_presetEditor.OnInspectorGUI();
5057
}
58+
59+
serializedObject.ApplyModifiedProperties();
5160
}
5261

5362
private Object GetTarget()

Editor/CustomInspectors/SerializableGlobalObjectIdPropertyDrawer.cs

Lines changed: 0 additions & 55 deletions
This file was deleted.

Editor/PrefabPostprocessor.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#if UNITY_2020_2_OR_NEWER
2+
using System.Collections.Generic;
23
using Gilzoide.ConditionalObjects.Filters;
34
using UnityEditor;
5+
using UnityEditor.Presets;
46
using UnityEngine;
57

68
namespace Gilzoide.ConditionalObjects.Editor
@@ -15,6 +17,8 @@ void OnPostprocessPrefab(GameObject gameObject)
1517
return;
1618
}
1719

20+
var referencedPresets = new HashSet<Preset>();
21+
1822
bool isEditor = EditorDependency.IsEditor;
1923
bool isDevelopment = DevelopmentDependency.IsDevelopment;
2024
string[] scriptingDefineSymbols = ScriptingDefineSymbolsDependency.ScriptingDefineSymbols;
@@ -32,12 +36,18 @@ void OnPostprocessPrefab(GameObject gameObject)
3236
{
3337
context.DependsOnCustomDependency(ScriptingDefineSymbolsDependency.DependencyName);
3438
}
39+
if (objectModifier is PropertyModifier propertyModifier && propertyModifier._preset != null)
40+
{
41+
referencedPresets.Add(propertyModifier._preset);
42+
}
3543
BuildTarget selectedBuildTarget = objectModifier.PlatformFilter.IsEmpty
3644
? BuildTarget.NoTarget
3745
: context.selectedBuildTarget;
3846
objectModifier.Apply(isEditor, isDevelopment, selectedBuildTarget, scriptingDefineSymbols);
3947
Object.DestroyImmediate(objectModifier, true);
4048
}
49+
50+
EmbeddedPresetHolder.Instance.DeleteOrphanPresets(context.assetPath, referencedPresets);
4151
}
4252
}
4353
}

Editor/ScenePostprocessor.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1+
using System.Collections.Generic;
12
using UnityEditor;
2-
using UnityEditor.Callbacks;
3+
using UnityEditor.Build;
4+
using UnityEditor.Build.Reporting;
5+
using UnityEditor.Presets;
36
using UnityEngine;
7+
using UnityEngine.SceneManagement;
48

59
namespace Gilzoide.ConditionalObjects.Editor
610
{
7-
public static class ScenePostprocessor
11+
public class ScenePostprocessor : IProcessSceneWithReport
812
{
9-
[PostProcessScene]
10-
static void OnPostprocessScene()
13+
public int callbackOrder => 0;
14+
15+
public void OnProcessScene(Scene scene, BuildReport report)
1116
{
1217
#if UNITY_2020_1_OR_NEWER
1318
AImportTimeObjectModifier[] foundComponents = Object.FindObjectsOfType<AImportTimeObjectModifier>(true);
@@ -19,15 +24,23 @@ static void OnPostprocessScene()
1924
return;
2025
}
2126

27+
var referencedPresets = new HashSet<Preset>();
28+
2229
bool isEditor = EditorDependency.IsEditor;
2330
bool isDevelopment = DevelopmentDependency.IsDevelopment;
2431
BuildTarget selectedBuildTarget = EditorUserBuildSettings.activeBuildTarget;
2532
string[] scriptingDefineSymbols = ScriptingDefineSymbolsDependency.ScriptingDefineSymbols;
2633
foreach (AImportTimeObjectModifier objectModifier in foundComponents)
2734
{
35+
if (objectModifier is PropertyModifier propertyModifier && propertyModifier._preset != null)
36+
{
37+
referencedPresets.Add(propertyModifier._preset);
38+
}
2839
objectModifier.Apply(isEditor, isDevelopment, selectedBuildTarget, scriptingDefineSymbols);
2940
Object.DestroyImmediate(objectModifier, true);
3041
}
42+
43+
EmbeddedPresetHolder.Instance.DeleteOrphanPresets(scene.path, referencedPresets);
3144
}
3245
}
3346
}

Runtime/Extensions/GameObjectExtensions.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
using System;
2+
using UnityEditor;
3+
#if UNITY_2021_2_OR_NEWER
4+
using UnityEditor.SceneManagement;
5+
#else
6+
using UnityEditor.Experimental.SceneManagement;
7+
#endif
28
using UnityEngine;
39
using Object = UnityEngine.Object;
410

@@ -23,5 +29,27 @@ public static Object ComponentAtIndexOrSelf(this GameObject gameObject, int inde
2329
return gameObject;
2430
}
2531
}
32+
33+
#if UNITY_EDITOR
34+
public static string GetAssetPath(this GameObject gameObject)
35+
{
36+
if (!string.IsNullOrEmpty(gameObject.scene.path))
37+
{
38+
return gameObject.scene.path;
39+
}
40+
else if (PrefabStageUtility.GetCurrentPrefabStage() is PrefabStage prefabStage && prefabStage.IsPartOfPrefabContents(gameObject))
41+
{
42+
#if UNITY_2020_1_OR_NEWER
43+
return prefabStage.assetPath;
44+
#else
45+
return prefabStage.prefabAssetPath;
46+
#endif
47+
}
48+
else
49+
{
50+
return PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(gameObject);
51+
}
52+
}
53+
#endif
2654
}
2755
}

Runtime/Internal/AssemblyInfo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("Gilzoide.ConditionalObjects.Editor")]
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Internal/EmbeddedPresetHolder.cs

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -36,98 +36,60 @@ static EmbeddedPresetHolder GetOrCreateInstance()
3636
[Serializable]
3737
public class EmbeddedPreset
3838
{
39-
public SerializableGlobalObjectId ObjectId;
39+
public GUID AssetGuid;
4040
public Preset Preset;
4141
}
4242

4343
[SerializeField] private List<EmbeddedPreset> _embeddedPresets = new List<EmbeddedPreset>();
4444

45-
public Preset GetPreset(Object owner, Object target)
45+
public Preset CreatePreset(GameObject ownerObject, Object target)
4646
{
47-
GlobalObjectId objectId = GlobalObjectId.GetGlobalObjectIdSlow(owner);
48-
if (objectId.assetGUID.Empty())
49-
{
50-
return null;
51-
}
52-
53-
if (_embeddedPresets.Find(p => objectId.Equals(p.ObjectId)) is EmbeddedPreset embeddedPreset
54-
&& embeddedPreset.Preset != null
55-
&& embeddedPreset.Preset.CanBeAppliedTo(target))
56-
{
57-
return embeddedPreset.Preset;
58-
}
59-
else
60-
{
61-
return null;
62-
}
47+
string assetPath = ownerObject.GetAssetPath();
48+
return CreatePreset(AssetDatabase.AssetPathToGUID(assetPath), target);
6349
}
6450

65-
public Preset GetOrCreatePreset(GlobalObjectId objectId, Object target)
51+
public Preset CreatePreset(string assetGuid, Object target)
6652
{
67-
if (objectId.assetGUID.Empty())
53+
if (string.IsNullOrEmpty(AssetDatabase.GUIDToAssetPath(assetGuid)))
6854
{
69-
return null;
55+
throw new ArgumentOutOfRangeException(nameof(assetGuid), "GUID is not know in AssetDatabase");
7056
}
7157

72-
if (_embeddedPresets.Find(p => objectId.Equals(p.ObjectId)) is EmbeddedPreset embeddedPreset)
58+
var preset = new Preset(target)
7359
{
74-
if (target == null)
75-
{
76-
DestroyImmediate(embeddedPreset.Preset, true);
77-
_embeddedPresets.RemoveAll(p => objectId.Equals(p.ObjectId));
78-
return null;
79-
}
80-
else if (!embeddedPreset.Preset.CanBeAppliedTo(target))
81-
{
82-
DestroyImmediate(embeddedPreset.Preset, true);
83-
}
84-
}
85-
else if (target == null)
86-
{
87-
return null;
88-
}
89-
else
60+
name = $"{assetGuid}-{GlobalObjectId.GetGlobalObjectIdSlow(target).targetObjectId}",
61+
};
62+
preset.ExcludeAllProperties();
63+
_embeddedPresets.Add(new EmbeddedPreset
9064
{
91-
embeddedPreset = new EmbeddedPreset
92-
{
93-
ObjectId = objectId,
94-
};
95-
_embeddedPresets.Add(embeddedPreset);
96-
}
97-
98-
if (embeddedPreset.Preset == null)
99-
{
100-
embeddedPreset.Preset = new Preset(target)
101-
{
102-
name = objectId.ToString(),
103-
};
104-
embeddedPreset.Preset.ExcludeAllProperties();
105-
AssetDatabase.AddObjectToAsset(embeddedPreset.Preset, this);
106-
EditorUtility.SetDirty(this);
107-
}
108-
return embeddedPreset.Preset;
65+
AssetGuid = new GUID(assetGuid),
66+
Preset = preset,
67+
});
68+
AssetDatabase.AddObjectToAsset(preset, this);
69+
AssetDatabase.SaveAssetIfDirty(this);
70+
return preset;
10971
}
11072

11173
public void HandleAssetDelete(string assetPath)
11274
{
113-
DeletePresetsFromAsset(assetPath);
114-
}
115-
116-
public void HandleAssetSave(string[] paths)
117-
{
118-
foreach (string assetPath in paths)
75+
var guid = new GUID(AssetDatabase.AssetPathToGUID(assetPath));
76+
_embeddedPresets.RemoveAll(p =>
11977
{
120-
DeletePresetsFromAsset(assetPath);
121-
}
78+
bool shouldRemove = p.AssetGuid == guid;
79+
if (shouldRemove)
80+
{
81+
DestroyImmediate(p.Preset, true);
82+
}
83+
return shouldRemove;
84+
});
12285
}
12386

124-
private void DeletePresetsFromAsset(string assetPath)
87+
public void DeleteOrphanPresets(string assetPath, HashSet<Preset> referencedPresets)
12588
{
12689
var guid = new GUID(AssetDatabase.AssetPathToGUID(assetPath));
12790
_embeddedPresets.RemoveAll(p =>
12891
{
129-
bool shouldRemove = p.ObjectId.GlobalObjectId.assetGUID == guid
130-
&& GlobalObjectId.GlobalObjectIdentifierToObjectSlow(p.ObjectId) == null;
92+
bool shouldRemove = p.AssetGuid == guid && !referencedPresets.Contains(p.Preset);
13193
if (shouldRemove)
13294
{
13395
DestroyImmediate(p.Preset, true);

0 commit comments

Comments
 (0)