Files
SimUL/Assets/UMA/Core/Scripts/DNAPlugins/BonePoseDNAConverterPlugin.cs
T
2025-01-07 18:54:46 +02:00

362 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UMA.PoseTools;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UMA
{
[System.Serializable]
public class BonePoseDNAConverterPlugin : DynamicDNAPlugin
{
[SerializeField]
private List<BonePoseDNAConverter> _poseDNAConverters = new List<BonePoseDNAConverter>();
public List<BonePoseDNAConverter> poseDNAConverters
{
get { return _poseDNAConverters; }
set { _poseDNAConverters = value; }
}
#region BACKWARDS COMPATIBILITY
//the following are backwards compatible methods for DynamicDNAConverterBehaviour.StartingPose
//TODO can we make this work again?
//backwards compatibility
public UMABonePose StartingPose
{
get {
/*if(_poseDNAConverters.Count > 0)
{
for(int i = 0; i < _poseDNAConverters.Count; i++)
{
if (_poseDNAConverters[i].poseToApply != null && (_poseDNAConverters[i].startingPoseWeight.defaultWeight == 1 > 0f)
return _poseDNAConverters[i].poseToApply;
}
}*/
return null;
}
//this is not bulletproof but it will be obsolete anyway
set {
/*if(_poseDNAConverters.Count > 0)
{
int foundIndex = -1;
for(int i = 0; i < _poseDNAConverters.Count; i++)
{
if (_poseDNAConverters[i].poseToApply == value)
{
foundIndex = i;
break;
}
}
if(foundIndex >= 0 && foundIndex != 0)
{
//move the existing entry to 0
var current = new BonePoseDNAConverter(_poseDNAConverters[foundIndex]);
_poseDNAConverters.RemoveAt(foundIndex);
_poseDNAConverters.Insert(0, current);
return;
}
}
_poseDNAConverters.Insert(0, new BonePoseDNAConverter(value, 1f));*/
}
}
//backwards compatibility
public float StartingPoseWeight
{
get
{
/*if (_poseDNAConverters.Count > 0)
{
for (int i = 0; i < _poseDNAConverters.Count; i++)
{
if (_poseDNAConverters[i].poseToApply != null && _poseDNAConverters[i].defaultPoseWeight > 0f)
return _poseDNAConverters[i].defaultPoseWeight;
}
}*/
return 0f;
}
set {
/*if (_poseDNAConverters.Count > 0)
{
_poseDNAConverters[0].defaultPoseWeight = value;
}*/
}
}
#endregion
#region DYNAMICDNAPLUGIN PROPERTIES
#if UNITY_EDITOR
public override string PluginHelp
{
get { return "Bone Pose DNA Converters convert the set dna names into weight settings for UMA Bone Pose that will be applied to a character. You can use the 'Starting Pose Weight' to force this pose on all characters that use this converter at the start. Or you can hook up to a modifying dna so that the pose is only applied based on a characters dna value."; }
}
#endif
#endregion
#region REQUIRED DYNAMICDNAPLUGIN METHODS
/// <summary>
/// Returns a dictionary of all the dna names in use by the plugin and the entries in its converter list that reference them
/// </summary>
/// <returns></returns>
public override Dictionary<string, List<int>> IndexesForDnaNames
{
get
{
var dict = new Dictionary<string, List<int>>();
for (int i = 0; i < _poseDNAConverters.Count; i++)
{
for (int ci = 0; ci < _poseDNAConverters[i].UsedDNANames.Count; ci++)
{
if (!dict.ContainsKey(_poseDNAConverters[i].UsedDNANames[ci]))
{
dict.Add(_poseDNAConverters[i].UsedDNANames[ci], new List<int>());
}
dict[_poseDNAConverters[i].UsedDNANames[ci]].Add(i);
}
}
return dict;
}
}
/// <summary>
/// Apply the boneposes according to the given dna (determined by the dnaTypeHash)
/// </summary>
/// <param name="umaData"></param>
/// <param name="skeleton"></param>
/// <param name="dnaTypeHash"></param>
public override void ApplyDNA(UMAData umaData, UMASkeleton skeleton, int dnaTypeHash)
{
var umaDna = umaData.GetDna(dnaTypeHash);
var masterWeightCalc = masterWeight.GetWeight(umaDna);
for (int i = 0; i < _poseDNAConverters.Count; i++)
{
_poseDNAConverters[i].ApplyDNA(umaData, skeleton, dnaTypeHash, masterWeightCalc);
}
}
#endregion
#region INSPECTOR GUI OVERRIDES
#if UNITY_EDITOR
public override string[] ImportSettingsMethods
{
get
{
return new string[]
{
"Add",
"Replace"
};
}
}
public override GUIContent GetPluginEntryLabel(SerializedProperty entry, SerializedObject pluginSO, int entryIndex)
{
if (_poseDNAConverters[entryIndex].poseToApply != null)
{
return new GUIContent(_poseDNAConverters[entryIndex].poseToApply.name);
}
return base.GetPluginEntryLabel(entry, pluginSO, entryIndex);
}
public override bool ImportSettings(UnityEngine.Object pluginToImport, int importMethod)
{
//TODO Deal with Morphset?
var importPlug = pluginToImport as BonePoseDNAConverterPlugin;
if (importPlug == null)
{
Debug.LogWarning("The plugin you are trying to import was not a PoseDNAConverterPlugin!");
return false;
}
if (importPlug._poseDNAConverters.Count == 0)
{
Debug.LogWarning("The plugin you are trying to import had no settings!");
return false;
}
//Method Replace
if (importMethod == 1)
{
_poseDNAConverters.Clear();
}
for (int i = 0; i < importPlug._poseDNAConverters.Count; i++)
{
_poseDNAConverters.Add(new BonePoseDNAConverter(importPlug._poseDNAConverters[i]));
}
EditorUtility.SetDirty(this);
AssetDatabase.SaveAssets();
return true;
}
#endif
#endregion
#region SPECIAL TYPES
[System.Serializable]
public class BonePoseDNAConverter
{
#region FIELDS
[Tooltip("The UMABonePose to apply to the character. This will effectively 'morph' the character into a different shape (using bone deformation so clothes will still fit).")]
[SerializeField]
private UMABonePose _poseToApply;
[SerializeField]
[Tooltip("Make the default weight 1 to apply the pose on start to *all* characters that use this converter or set to 0 so the pose is only applied by 'Modifying DNA' below. If you want to affect this 'per character' use 'Modifying DNA' instead")]
[Range(0f, 1f)]
private float _startingPoseWeight = 0f;
[SerializeField]
[Tooltip("Add dna(s) here that will change the amount that this Pose is applied depending on their evaluated value.")]
private DNAEvaluatorList _modifyingDNA = new DNAEvaluatorList();
#endregion
#region PRIVATE VARS
private float _livePoseWeight = 0f;
//private int _dnaIndex = -1;
private DynamicUMADnaBase _activeDNA;
#endregion
#region PUBLIC PROPERTIES
public UMABonePose poseToApply
{
get { return _poseToApply; }
set { _poseToApply = value; }
}
public float startingPoseWeight
{
get { return _startingPoseWeight; }
set { _startingPoseWeight = value; }
}
public DNAEvaluatorList modifyingDNA
{
get { return _modifyingDNA; }
set { _modifyingDNA = new DNAEvaluatorList(value); }
}
//TODO Timeline properties for screwing with the modifying dnas?
public List<string> UsedDNANames
{
get
{
//Do we include masterDNA in this?
//It will make a dna entry where every entry in any plugin that uses the name shows up
//could be more annoying/confusing than useful
return _modifyingDNA.UsedDNANames;
}
}
#endregion
#region CONSTRUCTOR
public BonePoseDNAConverter() { }
public BonePoseDNAConverter(UMABonePose poseToApply, float startingPoseWeight, DNAEvaluatorList modifyingDnas)
{
this._poseToApply = poseToApply;
this._startingPoseWeight = startingPoseWeight;
if (modifyingDnas != null)
{
this._modifyingDNA = new DNAEvaluatorList(modifyingDnas);
}
}
public BonePoseDNAConverter(UMABonePose poseToApply, float startingPoseWeight = 0f, List<DNAEvaluator> modifyingDnas = null)
{
this._poseToApply = poseToApply;
this._startingPoseWeight = startingPoseWeight;
if(modifyingDnas != null)
{
this._modifyingDNA = new DNAEvaluatorList(modifyingDnas);
}
}
public BonePoseDNAConverter(BonePoseDNAConverter other)
{
this._poseToApply = other._poseToApply;
this.startingPoseWeight = other._startingPoseWeight;
this._modifyingDNA = new DNAEvaluatorList(other._modifyingDNA);
}
#endregion
#region METHODS
public void ApplyDNA(UMAData umaData, UMASkeleton skeleton, UMADnaBase activeDNA, float masterWeight = 1f)
{
if (_poseToApply == null)
{
if (Debug.isDebugBuild)
{
Debug.LogWarning(umaData.gameObject.name + " had an invalid or empty pose set in its BonePoseDNAConverters in its DNAConverterController");
}
return;
}
_livePoseWeight = _startingPoseWeight;
//dna weight superceeds startingWeight if it exists
if (_modifyingDNA.UsedDNANames.Count > 0)
{
_livePoseWeight = _modifyingDNA.Evaluate(activeDNA);
}
_livePoseWeight = _livePoseWeight * masterWeight;
_livePoseWeight = Mathf.Clamp(_livePoseWeight, 0f, 1f);
_poseToApply.ApplyPose(skeleton, _livePoseWeight);
}
public void ApplyDNA(UMAData umaData, UMASkeleton skeleton, int dnaTypeHash, float masterWeight = 1f)
{
if (_poseToApply == null)
{
if (Debug.isDebugBuild)
{
Debug.LogWarning(umaData.gameObject.name + " had an invalid or empty pose set in its BonePoseDNAConverters in its DNAConverterController");
}
return;
}
_livePoseWeight = _startingPoseWeight;
//dna weight superceeds startingWeight if it exists
if (_modifyingDNA.UsedDNANames.Count > 0)
{
_activeDNA = (DynamicUMADnaBase)umaData.GetDna(dnaTypeHash);
_livePoseWeight = _modifyingDNA.Evaluate(_activeDNA);
}
_livePoseWeight = _livePoseWeight * masterWeight;
_livePoseWeight = Mathf.Clamp(_livePoseWeight, 0f, 1f);
_poseToApply.ApplyPose(skeleton, _livePoseWeight);
}
#endregion
}
#endregion
}
}