Skip to content

Commit

Permalink
Merge pull request #622 from anatawa12/auto-freeze-blendshape
Browse files Browse the repository at this point in the history
fix: AutoFreezeBlendshape will freeze with editor value instead of animated constant
  • Loading branch information
anatawa12 authored Oct 19, 2023
2 parents 9f73011 + 5d0bcb0 commit bee255a
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog].
### Removed

### Fixed
- AutoFreezeBlendShape will freeze BlendShapes with editor value instead of animated constant `#622`

### Security

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog].
### Removed

### Fixed
- AutoFreezeBlendShape will freeze BlendShapes with editor value instead of animated constant `#622`

### Security

Expand Down
63 changes: 33 additions & 30 deletions Editor/Processors/TraceAndOptimize/AutoFreezeBlendShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,48 +35,51 @@ void FreezeNonAnimatedBlendShapes()
// first optimization: unused blend shapes
foreach (var skinnedMeshRenderer in _session.GetComponents<SkinnedMeshRenderer>())
{
var mesh = skinnedMeshRenderer.sharedMesh;

// skip SMR without mesh
if (!mesh) continue;
if (_exclusions.Contains(skinnedMeshRenderer.gameObject)) continue; // manual exclusiton

var meshInfo = _session.MeshInfo2Holder.GetMeshInfoFor(skinnedMeshRenderer);

var modifies = _modifications.GetModifiedProperties(skinnedMeshRenderer);
var blendShapeValues = Enumerable.Range(0, mesh.blendShapeCount)
.Select(i => skinnedMeshRenderer.GetBlendShapeWeight(i)).ToArray();
var notChanged = Enumerable.Range(0, mesh.blendShapeCount)
.Select(i => mesh.GetBlendShapeName(i))
.Where((name, i) =>
{
if (!modifies.TryGetValue($"blendShape.{name}", out var prop)) return true;

switch (prop.State)
{
case AnimationProperty.PropertyState.ConstantAlways:
blendShapeValues[i] = prop.ConstValue;
return true;
case AnimationProperty.PropertyState.ConstantPartially:
return prop.ConstValue.CompareTo(blendShapeValues[i]) == 0;
case AnimationProperty.PropertyState.Variable:
return false;
default:
throw new ArgumentOutOfRangeException();
}
})
.ToArray();
var unchanged = new HashSet<string>();

if (notChanged.Length == 0) continue;
for (var i = 0; i < meshInfo.BlendShapes.Count; i++)
{
var (name, weight) = meshInfo.BlendShapes[i];
if (IsUnchangedBlendShape(name, weight, out var newWeight))
{
unchanged.Add(name);
meshInfo.BlendShapes[i] = (name, newWeight);
}
}

bool IsUnchangedBlendShape(string name, float weight, out float newWeight)
{
newWeight = weight;
if (!modifies.TryGetValue($"blendShape.{name}", out var prop)) return true;

switch (prop.State)
{
case AnimationProperty.PropertyState.ConstantAlways:
newWeight = prop.ConstValue;
return true;
case AnimationProperty.PropertyState.ConstantPartially:
return prop.ConstValue.CompareTo(weight) == 0;
case AnimationProperty.PropertyState.Variable:
return false;
default:
throw new ArgumentOutOfRangeException();
}
}

for (var i = 0; i < blendShapeValues.Length; i++)
skinnedMeshRenderer.SetBlendShapeWeight(i, blendShapeValues[i]);
EditorUtility.SetDirty(skinnedMeshRenderer);
if (unchanged.Count == 0) continue;

var freeze = skinnedMeshRenderer.gameObject.GetOrAddComponent<FreezeBlendShape>();
var serialized = new SerializedObject(freeze);
var editorUtil = PrefabSafeSet.EditorUtil<string>.Create(
serialized.FindProperty(nameof(FreezeBlendShape.shapeKeysSet)),
0, p => p.stringValue, (p, v) => p.stringValue = v);
foreach (var shape in notChanged)
foreach (var shape in unchanged)
editorUtil.GetElementOf(shape).EnsureAdded();
serialized.ApplyModifiedPropertiesWithoutUndo();
}
Expand Down

0 comments on commit bee255a

Please sign in to comment.