diff --git a/CHANGELOG-PRERELEASE.md b/CHANGELOG-PRERELEASE.md index 544240da5..05dd1e132 100644 --- a/CHANGELOG-PRERELEASE.md +++ b/CHANGELOG-PRERELEASE.md @@ -18,6 +18,7 @@ The format is based on [Keep a Changelog]. ### Fixed - Error with nested merge skinned mesh `#1340` - Broken synced Layer support `#1341` +- Unpacking prefab might look like some data lost in PrefabSafeUniqueCollection `#1342` ### Security diff --git a/Internal/PrefabSafeSet/Editor/UniqueCollection/BaseEditorUtil.PrefabModificationBase.cs b/Internal/PrefabSafeSet/Editor/UniqueCollection/BaseEditorUtil.PrefabModificationBase.cs index 36e951eb7..c932b59f3 100644 --- a/Internal/PrefabSafeSet/Editor/UniqueCollection/BaseEditorUtil.PrefabModificationBase.cs +++ b/Internal/PrefabSafeSet/Editor/UniqueCollection/BaseEditorUtil.PrefabModificationBase.cs @@ -547,14 +547,14 @@ ElementStatus.Natural or ElementStatus.Removed or ElementStatus.NewElement } private (int indexInModifier, SerializedProperty modifierProp) AddToAdditions(TAdditionValue value) => - AddToModifications(value, ref _currentAdditionsSize, CurrentAdditions, _helper.WriteAdditionValue); + AddToModifications(value, ref _currentAdditionsSize, ref CurrentAdditions, _helper.WriteAdditionValue); private (int indexInModifier, SerializedProperty modifierProp) AddToRemoves(TRemoveKey value) => - AddToModifications(value, ref _currentRemovesSize, CurrentRemoves, _helper.WriteRemoveKey); + AddToModifications(value, ref _currentRemovesSize, ref CurrentRemoves, _helper.WriteRemoveKey); private (int indexInModifier, SerializedProperty modifierProp) AddToModifications(T value, ref int currentModificationSize, - SerializedProperty? currentModifications, + ref SerializedProperty? currentModifications, // ref is needed to ensure InitCurrentLayer effect Action writeValue) { InitCurrentLayer(true); diff --git a/Internal/PrefabSafeSet/Runtime/PrefabSafeSetTestComponent.cs b/Internal/PrefabSafeSet/Runtime/PrefabSafeSetTestComponent.cs index 4a3ee6ab9..615f7003d 100644 --- a/Internal/PrefabSafeSet/Runtime/PrefabSafeSetTestComponent.cs +++ b/Internal/PrefabSafeSet/Runtime/PrefabSafeSetTestComponent.cs @@ -2,7 +2,7 @@ namespace Anatawa12.AvatarOptimizer.PrefabSafeSet { - public class PrefabSafeSetTestComponent : MonoBehaviour + public class PrefabSafeSetTestComponent : MonoBehaviour, ISerializationCallbackReceiver { [SerializeField] internal PrefabSafeSet materials; @@ -11,9 +11,16 @@ public PrefabSafeSetTestComponent() materials = new PrefabSafeSet(this); } - private void OnValidate() + private void ValidatePSUC() { PrefabSafeSet.OnValidate(this, x => x.materials); } + + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } } } diff --git a/Runtime/FreezeBlendShape.cs b/Runtime/FreezeBlendShape.cs index 8b0e7e362..2ecdfb7d5 100644 --- a/Runtime/FreezeBlendShape.cs +++ b/Runtime/FreezeBlendShape.cs @@ -7,7 +7,7 @@ namespace Anatawa12.AvatarOptimizer [AddComponentMenu("Avatar Optimizer/AAO Freeze BlendShapes")] [DisallowMultipleComponent] [HelpURL("https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/freeze-blendshape/")] - internal class FreezeBlendShape : EditSkinnedMeshComponent + internal class FreezeBlendShape : EditSkinnedMeshComponent, ISerializationCallbackReceiver { public PrefabSafeSet.PrefabSafeSet shapeKeysSet; @@ -18,9 +18,16 @@ public FreezeBlendShape() public HashSet FreezingShapeKeys => shapeKeysSet.GetAsSet(); - private void OnValidate() + private void ValidatePSUC() { PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.shapeKeysSet); } + + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } } } diff --git a/Runtime/MakeChildren.cs b/Runtime/MakeChildren.cs index 8131eed65..f691a66ca 100644 --- a/Runtime/MakeChildren.cs +++ b/Runtime/MakeChildren.cs @@ -6,7 +6,7 @@ namespace Anatawa12.AvatarOptimizer [AddComponentMenu("Avatar Optimizer/AAO Make Children")] [DisallowMultipleComponent] [HelpURL("https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/make-children/")] - internal class MakeChildren : AvatarTagComponent + internal class MakeChildren : AvatarTagComponent, ISerializationCallbackReceiver { [NotKeyable, AAOLocalized("MakeChildren:prop:executeEarly", "MakeChildren:tooltip:executeEarly")] public bool executeEarly; @@ -18,9 +18,16 @@ internal MakeChildren() children = new PrefabSafeSet.PrefabSafeSet(this); } - private void OnValidate() + private void ValidatePSUC() { PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.children); } + + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } } } diff --git a/Runtime/MergePhysBone.cs b/Runtime/MergePhysBone.cs index c30dceb0b..a06d70141 100644 --- a/Runtime/MergePhysBone.cs +++ b/Runtime/MergePhysBone.cs @@ -15,7 +15,7 @@ namespace Anatawa12.AvatarOptimizer [HelpURL("https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/merge-physbone/")] // INetworkID is implemented to make it possible to assign networkID to this components GameObject // Note: when MergePhysBone become a public API, we should consider removing INetworkID implementation - internal class MergePhysBone : AvatarTagComponent, VRC.SDKBase.INetworkID + internal class MergePhysBone : AvatarTagComponent, VRC.SDKBase.INetworkID, ISerializationCallbackReceiver { [NotKeyable] [AAOLocalized("MergePhysBone:prop:makeParent", "MergePhysBone:tooltip:makeParent")] @@ -254,10 +254,17 @@ public MergePhysBone() componentsSet = new PrefabSafeSet.PrefabSafeSet(this); } - private void OnValidate() + private void ValidatePSUC() { PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.componentsSet); } + + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } } internal enum CollidersSettings diff --git a/Runtime/MergeSkinnedMesh.cs b/Runtime/MergeSkinnedMesh.cs index f81a57cfe..5e5bf94dd 100644 --- a/Runtime/MergeSkinnedMesh.cs +++ b/Runtime/MergeSkinnedMesh.cs @@ -13,7 +13,7 @@ namespace Anatawa12.AvatarOptimizer [DisallowMultipleComponent] [HelpURL("https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/merge-skinned-mesh/")] [PublicAPI] - public sealed class MergeSkinnedMesh : EditSkinnedMeshComponent, ISourceSkinnedMeshComponent + public sealed class MergeSkinnedMesh : EditSkinnedMeshComponent, ISourceSkinnedMeshComponent, ISerializationCallbackReceiver { [AAOLocalized("MergeSkinnedMesh:prop:renderers")] [SerializeField] @@ -83,13 +83,20 @@ internal MergeSkinnedMesh() doNotMergeMaterials = new PrefabSafeSet.PrefabSafeSet(this); } - private void OnValidate() + private void ValidatePSUC() { PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.renderersSet); PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.staticRenderersSet); PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.doNotMergeMaterials); } + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } + /// /// Initializes the MergeSkinnedMesh with the specified default behavior version. /// diff --git a/Runtime/RemoveMeshByBlendShape.cs b/Runtime/RemoveMeshByBlendShape.cs index 1c2d77cf6..60d44b66f 100644 --- a/Runtime/RemoveMeshByBlendShape.cs +++ b/Runtime/RemoveMeshByBlendShape.cs @@ -12,7 +12,7 @@ namespace Anatawa12.AvatarOptimizer [AllowMultipleComponent] [HelpURL("https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/remove-mesh-by-blendshape/")] [PublicAPI] - public sealed class RemoveMeshByBlendShape : EditSkinnedMeshComponent + public sealed class RemoveMeshByBlendShape : EditSkinnedMeshComponent, ISerializationCallbackReceiver { [SerializeField] internal PrefabSafeSet.PrefabSafeSet shapeKeysSet; @@ -27,11 +27,18 @@ internal RemoveMeshByBlendShape() internal HashSet RemovingShapeKeys => shapeKeysSet.GetAsSet(); - private void OnValidate() + private void ValidatePSUC() { PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.shapeKeysSet); } + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } + APIChecker _checker; /// diff --git a/Runtime/RenameBlendShape.cs b/Runtime/RenameBlendShape.cs index ef7f628f2..9a0d1c920 100644 --- a/Runtime/RenameBlendShape.cs +++ b/Runtime/RenameBlendShape.cs @@ -1,3 +1,4 @@ +using System; using UnityEngine; namespace Anatawa12.AvatarOptimizer @@ -5,7 +6,7 @@ namespace Anatawa12.AvatarOptimizer [AddComponentMenu("Avatar Optimizer/AAO Rename BlendShape")] [DisallowMultipleComponent] [HelpURL("https://vpm.anatawa12.com/avatar-optimizer/ja/docs/reference/rename-blend-shape/")] - internal class RenameBlendShape : EditSkinnedMeshComponent + internal class RenameBlendShape : EditSkinnedMeshComponent, ISerializationCallbackReceiver { [SerializeField] internal PrefabSafeMap.PrefabSafeMap nameMap; @@ -13,5 +14,17 @@ public RenameBlendShape() { nameMap = new PrefabSafeMap.PrefabSafeMap(this); } + + private void ValidatePSUC() + { + PrefabSafeMap.PrefabSafeMap.OnValidate(this, x => x.nameMap); + } + + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } } } diff --git a/Test~/PrefabSafeSet/PSSTestUtil.cs b/Test~/PrefabSafeSet/PSSTestUtil.cs index bfacb6314..f0fd6c09c 100644 --- a/Test~/PrefabSafeSet/PSSTestUtil.cs +++ b/Test~/PrefabSafeSet/PSSTestUtil.cs @@ -18,7 +18,7 @@ private static GameObject CreateBasePrefab() component.stringSet.mainSet = new[] { "mainSet", "addedTwiceInVariant", "removedInVariant", "addedTwiceInInstance", "removedInInstance" }; newObject = PrefabUtility.SaveAsPrefabAsset(newObject, $"Assets/test-{Guid.NewGuid()}.prefab"); - Assert.True(newObject); + newObject.GetComponent().stringSet.IsNew = false; return newObject; } @@ -31,6 +31,7 @@ private static GameObject CreateBaseVariantPrefab(GameObject basePrefab) new[] { "addedTwiceInVariant", "addedInVariant", "addedInVariantRemovedInInstance" }; component.stringSet.prefabLayers[0].removes = new[] { "removedInVariant", "fakeRemovedInVariant" }; newObject = PrefabUtility.SaveAsPrefabAsset(newObject, $"Assets/test-{Guid.NewGuid()}.prefab"); + newObject.GetComponent().stringSet.IsNew = false; Assert.True(newObject); return newObject; } @@ -43,6 +44,7 @@ private static GameObject CreateInstance(GameObject baseObject) component.stringSet.prefabLayers[1].additions = new[] { "addedTwiceInInstance", "addedInInstance" }; component.stringSet.prefabLayers[1].removes = new[] { "removedInInstance", "addedInVariantRemovedInInstance", "fakeRemovedInInstance" }; + component.stringSet.IsNew = false; return newObject; } diff --git a/Test~/Runtime/PrefabSafeSetComponent.cs b/Test~/Runtime/PrefabSafeSetComponent.cs index 9f1d3cafe..02d68dfdf 100644 --- a/Test~/Runtime/PrefabSafeSetComponent.cs +++ b/Test~/Runtime/PrefabSafeSetComponent.cs @@ -2,7 +2,7 @@ namespace Anatawa12.AvatarOptimizer.Test.Runtime { - public class PrefabSafeSetComponent : MonoBehaviour + public class PrefabSafeSetComponent : MonoBehaviour, ISerializationCallbackReceiver { public PrefabSafeSet.PrefabSafeSet stringSet; @@ -11,9 +11,16 @@ public PrefabSafeSetComponent() stringSet = new PrefabSafeSet.PrefabSafeSet(this); } - private void OnValidate() + private void ValidatePSUC() { PrefabSafeSet.PrefabSafeSet.OnValidate(this, x => x.stringSet); } + + private void OnValidate() => ValidatePSUC(); + void ISerializationCallbackReceiver.OnBeforeSerialize() => ValidatePSUC(); + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + } } }