You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
7.4 KiB
C#
253 lines
7.4 KiB
C#
using MalbersAnimations.Events;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace MalbersAnimations.Utilities
|
|
{
|
|
/// <summary>Manage the Blend Shapes of a Mesh</summary>
|
|
[AddComponentMenu("Malbers/Utilities/Mesh/Blend Shapes")]
|
|
public class BlendShape : MonoBehaviour
|
|
{
|
|
[CreateScriptableAsset]
|
|
public BlendShapePreset preset;
|
|
public bool LoadPresetOnStart = true;
|
|
[RequiredField]
|
|
public SkinnedMeshRenderer mesh;
|
|
public SkinnedMeshRenderer[] LODs;
|
|
|
|
[Range(0, 100)]
|
|
public float[] blendShapes; //Value of the Blend Shape
|
|
|
|
public bool random;
|
|
public int PinnedShape;
|
|
|
|
/// <summary>Does the mesh has Blend Shapes? </summary>
|
|
internal bool HasBlendShapes => mesh && mesh.sharedMesh.blendShapeCount > 0;
|
|
|
|
|
|
private void Start()
|
|
{
|
|
if (LoadPresetOnStart)
|
|
LoadPreset();
|
|
else if (random)
|
|
Randomize();
|
|
}
|
|
|
|
|
|
private void Reset()
|
|
{
|
|
mesh = GetComponentInChildren<SkinnedMeshRenderer>();
|
|
if (mesh)
|
|
{
|
|
blendShapes = new float[mesh.sharedMesh.blendShapeCount];
|
|
|
|
for (int i = 0; i < blendShapes.Length; i++)
|
|
blendShapes[i] = mesh.GetBlendShapeWeight(i);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>Returns the current Blend Shapes Values</summary>
|
|
public virtual float[] GetBlendShapeValues()
|
|
{
|
|
if (HasBlendShapes)
|
|
{
|
|
float[] BS = new float[mesh.sharedMesh.blendShapeCount];
|
|
|
|
for (int i = 0; i < BS.Length; i++)
|
|
{
|
|
BS[i] = mesh.GetBlendShapeWeight(i);
|
|
}
|
|
return BS;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
public void SmoothBlendShape(BlendShapePreset preset) => LoadSmoothPreset(preset);
|
|
|
|
public void LoadSmoothPreset(BlendShapePreset preset)
|
|
{
|
|
StopAllCoroutines();
|
|
preset.SmoothBlend(mesh);
|
|
}
|
|
|
|
public void SavePreset()
|
|
{
|
|
if (preset)
|
|
{
|
|
preset.blendShapes = new float[blendShapes.Length];
|
|
|
|
for (int i = 0; i < preset.blendShapes.Length; i++)
|
|
{
|
|
preset.blendShapes[i] = blendShapes[i];
|
|
}
|
|
Debug.Log("Preset: " + preset.name + " Saved");
|
|
|
|
MTools.SetDirty(preset);
|
|
}
|
|
}
|
|
|
|
public void LoadPreset() => LoadPreset(preset);
|
|
|
|
public void LoadPreset(BlendShapePreset preset)
|
|
{
|
|
if (preset)
|
|
{
|
|
blendShapes = new float[preset.blendShapes.Length];
|
|
|
|
for (int i = 0; i < preset.blendShapes.Length; i++)
|
|
{
|
|
blendShapes[i] = preset.blendShapes[i];
|
|
}
|
|
|
|
Debug.Log("Preset: " + preset.name + " Loaded");
|
|
UpdateBlendShapes();
|
|
|
|
MTools.SetDirty(preset);
|
|
}
|
|
}
|
|
|
|
public virtual void SetShapesCount()
|
|
{
|
|
if (mesh)
|
|
{
|
|
blendShapes = new float[mesh.sharedMesh.blendShapeCount];
|
|
|
|
for (int i = 0; i < blendShapes.Length; i++)
|
|
{
|
|
blendShapes[i] = mesh.GetBlendShapeWeight(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>Set Random Values to the Mesh Blend Shapes</summary>
|
|
public virtual void Randomize()
|
|
{
|
|
if (HasBlendShapes)
|
|
{
|
|
for (int i = 0; i < blendShapes.Length; i++)
|
|
{
|
|
blendShapes[i] = Random.Range(0, 100);
|
|
mesh.SetBlendShapeWeight(i, blendShapes[i]);
|
|
}
|
|
UpdateLODs();
|
|
}
|
|
}
|
|
|
|
/// <summary>Set a weight of a Blend Shape by its name</summary>
|
|
public virtual void SetWeight(string name, float value)
|
|
{
|
|
if (HasBlendShapes)
|
|
{
|
|
PinnedShape = mesh.sharedMesh.GetBlendShapeIndex(name);
|
|
if (PinnedShape != -1)
|
|
{
|
|
mesh.SetBlendShapeWeight(PinnedShape, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Set a weight of a Blend Shape by its index</summary>
|
|
public virtual void SetWeight(int index, float value)
|
|
{
|
|
if (HasBlendShapes)
|
|
mesh.SetBlendShapeWeight(PinnedShape = index, value);
|
|
}
|
|
|
|
public virtual void _PinShape(string name)
|
|
{
|
|
PinnedShape = mesh.sharedMesh.GetBlendShapeIndex(name);
|
|
}
|
|
|
|
public virtual void _PinShape(int index)
|
|
{
|
|
PinnedShape = index;
|
|
}
|
|
|
|
public virtual void _PinnedShapeSetValue(float value)
|
|
{
|
|
if (PinnedShape != -1)
|
|
{
|
|
value = Mathf.Clamp(value, 0, 100);
|
|
blendShapes[PinnedShape] = value;
|
|
mesh.SetBlendShapeWeight(PinnedShape, value);
|
|
UpdateLODs(PinnedShape);
|
|
}
|
|
}
|
|
|
|
|
|
public virtual void UpdateBlendShapes()
|
|
{
|
|
if (mesh && blendShapes != null)
|
|
{
|
|
int Length = Mathf.Min(mesh.sharedMesh.blendShapeCount, blendShapes.Length);
|
|
|
|
for (int i = 0; i < Length; i++)
|
|
{
|
|
mesh.SetBlendShapeWeight(i, blendShapes[i]);
|
|
}
|
|
|
|
UpdateLODs();
|
|
}
|
|
}
|
|
|
|
/// <summary>Update the LODs Values</summary>
|
|
protected virtual void UpdateLODs()
|
|
{
|
|
for (int i = 0; i < blendShapes.Length; i++)
|
|
{
|
|
UpdateLODs(i);
|
|
}
|
|
}
|
|
|
|
/// <summary>Updates Only a Shape in all LODS
|
|
protected virtual void UpdateLODs(int index)
|
|
{
|
|
if (LODs != null)
|
|
{
|
|
foreach (var lods in LODs)
|
|
{
|
|
if (lods != null && lods.sharedMesh.blendShapeCount > index)
|
|
lods.SetBlendShapeWeight(index, blendShapes[index]);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
[ContextMenu("Create Event Listeners")]
|
|
void CreateListeners()
|
|
{
|
|
|
|
MEventListener listener = this.FindComponent<MEventListener>();
|
|
if (listener == null) listener = transform.root.gameObject.AddComponent<MEventListener>();
|
|
if (listener.Events == null) listener.Events = new List<MEventItemListener>();
|
|
|
|
MEvent BlendS = MTools.GetInstance<MEvent>("Blend Shapes");
|
|
|
|
|
|
if (listener.Events.Find(item => item.Event == BlendS) == null)
|
|
{
|
|
var item = new MEventItemListener()
|
|
{
|
|
Event = BlendS,
|
|
useVoid = false,
|
|
useString = true,
|
|
useInt = true,
|
|
useFloat = true
|
|
};
|
|
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(item.ResponseInt, _PinShape);
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(item.ResponseString, _PinShape);
|
|
UnityEditor.Events.UnityEventTools.AddPersistentListener(item.ResponseFloat, _PinnedShapeSetValue);
|
|
listener.Events.Add(item);
|
|
|
|
Debug.Log("<B>Blend Shapes</B> Added to the Event Listeners");
|
|
|
|
MTools.SetDirty(listener);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
} |