123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- namespace UnityEditor.U2D.Animation
- {
- internal enum WeightEditorMode
- {
- AddAndSubtract,
- GrowAndShrink,
- Smooth
- }
- internal class WeightEditor
- {
- public ISpriteMeshData spriteMeshData
- {
- get { return m_SpriteMeshDataController.spriteMeshData; }
- set { m_SpriteMeshDataController.spriteMeshData = value; }
- }
- public ICacheUndo cacheUndo { get; set; }
- public WeightEditorMode mode { get; set; }
- public int boneIndex { get; set; }
- public ISelection<int> selection { get; set; }
- public WeightEditorMode currentMode { get; private set; }
- public bool useRelativeValues { get; private set; }
- public bool emptySelectionEditsAll { get; set; }
- public bool autoNormalize { get; set; }
- private SpriteMeshDataController m_SpriteMeshDataController = new SpriteMeshDataController();
- private const int maxSmoothIterations = 8;
- private float[] m_SmoothValues;
- private readonly List<BoneWeight[]> m_SmoothedBoneWeights = new List<BoneWeight[]>();
- private readonly List<BoneWeight> m_StoredBoneWeights = new List<BoneWeight>();
- private int BoneCount
- {
- get { return spriteMeshData != null ? spriteMeshData.boneCount : 0; }
- }
- public WeightEditor()
- {
- autoNormalize = true;
- }
- public void OnEditStart(bool relative)
- {
- Validate();
-
- RegisterUndo();
- currentMode = mode;
- useRelativeValues = relative;
- if (!useRelativeValues)
- StoreBoneWeights();
- if (mode == WeightEditorMode.Smooth)
- PrepareSmoothingBuffers();
- }
- public void OnEditEnd()
- {
- Validate();
- if (currentMode == WeightEditorMode.AddAndSubtract)
- {
- for (int i = 0; i < spriteMeshData.vertexCount; ++i)
- spriteMeshData.GetWeight(i).Clamp(4);
- }
- if (autoNormalize)
- m_SpriteMeshDataController.NormalizeWeights(null);
- m_SpriteMeshDataController.SortTrianglesByDepth();
- }
- public void DoEdit(float value)
- {
- Validate();
- if (!useRelativeValues)
- RestoreBoneWeights();
- if (currentMode == WeightEditorMode.AddAndSubtract)
- SetWeight(value);
- else if (currentMode == WeightEditorMode.GrowAndShrink)
- SetWeight(value, false);
- else if (currentMode == WeightEditorMode.Smooth)
- SmoothWeights(value);
- }
- private void Validate()
- {
- if (spriteMeshData == null)
- throw (new Exception(TextContent.noSpriteSelected));
- }
- private void RegisterUndo()
- {
- Debug.Assert(cacheUndo != null);
- cacheUndo.BeginUndoOperation(TextContent.editWeights);
- }
- private void SetWeight(float value, bool createNewChannel = true)
- {
- if (boneIndex == -1 || spriteMeshData == null)
- return;
- Debug.Assert(selection != null);
- for (var i = 0; i < spriteMeshData.vertexCount; ++i)
- {
- if (selection.Count == 0 && emptySelectionEditsAll ||
- selection.Count > 0 && selection.Contains(i))
- {
- var editableBoneWeight = spriteMeshData.GetWeight(i);
- int channel = editableBoneWeight.GetChannelFromBoneIndex(boneIndex);
- if (channel == -1)
- {
- if (createNewChannel && value > 0f)
- {
- editableBoneWeight.AddChannel(boneIndex, 0f, true);
- channel = editableBoneWeight.GetChannelFromBoneIndex(boneIndex);
- }
- else
- {
- continue;
- }
- }
- editableBoneWeight[channel].weight += value;
- if (editableBoneWeight.Sum() > 1f)
- editableBoneWeight.CompensateOtherChannels(channel);
- editableBoneWeight.FilterChannels(0f);
- }
- }
- }
- private void SmoothWeights(float value)
- {
- Debug.Assert(selection != null);
- for (int i = 0; i < spriteMeshData.vertexCount; ++i)
- {
- if (selection.Count == 0 && emptySelectionEditsAll ||
- selection.Count > 0 && selection.Contains(i))
- {
- var smoothValue = m_SmoothValues[i];
- if (smoothValue >= maxSmoothIterations)
- continue;
- m_SmoothValues[i] = Mathf.Clamp(smoothValue + value, 0f, maxSmoothIterations);
- float lerpValue = GetLerpValue(m_SmoothValues[i]);
- int lerpIndex = GetLerpIndex(m_SmoothValues[i]);
- BoneWeight[] smoothedBoneWeightsFloor = GetSmoothedBoneWeights(lerpIndex - 1);
- BoneWeight[] smoothedBoneWeightsCeil = GetSmoothedBoneWeights(lerpIndex);
- BoneWeight boneWeight = EditableBoneWeightUtility.Lerp(smoothedBoneWeightsFloor[i], smoothedBoneWeightsCeil[i], lerpValue);
- spriteMeshData.GetWeight(i).SetFromBoneWeight(boneWeight);
- }
- }
- }
- protected void PrepareSmoothingBuffers()
- {
- if (m_SmoothValues == null || m_SmoothValues.Length != spriteMeshData.vertexCount)
- m_SmoothValues = new float[spriteMeshData.vertexCount];
- Array.Clear(m_SmoothValues, 0, m_SmoothValues.Length);
- m_SmoothedBoneWeights.Clear();
- BoneWeight[] boneWeights = new BoneWeight[spriteMeshData.vertexCount];
- for (int i = 0; i < spriteMeshData.vertexCount; i++)
- {
- EditableBoneWeight editableBoneWeight = spriteMeshData.GetWeight(i);
- boneWeights[i] = editableBoneWeight.ToBoneWeight(false);
- }
- m_SmoothedBoneWeights.Add(boneWeights);
- }
- private BoneWeight[] GetSmoothedBoneWeights(int lerpIndex)
- {
- Debug.Assert(lerpIndex >= 0);
- while (lerpIndex >= m_SmoothedBoneWeights.Count && lerpIndex <= maxSmoothIterations)
- {
- BoneWeight[] boneWeights;
- SmoothingUtility.SmoothWeights(m_SmoothedBoneWeights[m_SmoothedBoneWeights.Count - 1], spriteMeshData.indices, BoneCount, out boneWeights);
- m_SmoothedBoneWeights.Add(boneWeights);
- }
- return m_SmoothedBoneWeights[Mathf.Min(lerpIndex, maxSmoothIterations)];
- }
- private float GetLerpValue(float smoothValue)
- {
- Debug.Assert(smoothValue >= 0f);
- return smoothValue - Mathf.Floor(smoothValue);
- }
- private int GetLerpIndex(float smoothValue)
- {
- Debug.Assert(smoothValue >= 0f);
- return Mathf.RoundToInt(Mathf.Floor(smoothValue) + 1);
- }
- private void StoreBoneWeights()
- {
- Debug.Assert(selection != null);
- m_StoredBoneWeights.Clear();
- for (int i = 0; i < spriteMeshData.vertexCount; i++)
- {
- EditableBoneWeight editableBoneWeight = spriteMeshData.GetWeight(i);
- m_StoredBoneWeights.Add(editableBoneWeight.ToBoneWeight(false));
- }
- }
- private void RestoreBoneWeights()
- {
- Debug.Assert(selection != null);
- for (int i = 0; i < spriteMeshData.vertexCount; i++)
- {
- EditableBoneWeight editableBoneWeight = spriteMeshData.GetWeight(i);
- editableBoneWeight.SetFromBoneWeight(m_StoredBoneWeights[i]);
- }
- if (m_SmoothValues != null)
- Array.Clear(m_SmoothValues, 0, m_SmoothValues.Length);
- }
- }
- }
|