mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-11 21:38:56 -05:00
position/rotation constraint の共通部分を VRM10PostionRotationConstraintEditorBase にまとめた
This commit is contained in:
@@ -3,9 +3,9 @@ using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public static class IVRM10ConstraintSourceDestinationExtensions
|
||||
public static class VRM10PositionRotationConstraintBaseExtensions
|
||||
{
|
||||
public static void DrawSourceCoords(this IVRM10ConstraintSourceDestination self)
|
||||
public static void DrawSourceCoords(this VRM10RotationPositionConstraintBase self)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -16,7 +16,7 @@ namespace UniVRM10
|
||||
|
||||
}
|
||||
}
|
||||
public static void DrawSourceCurrent(this IVRM10ConstraintSourceDestination self)
|
||||
public static void DrawSourceCurrent(this VRM10RotationPositionConstraintBase self)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -30,7 +30,7 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawDstCoords(this IVRM10ConstraintSourceDestination self)
|
||||
public static void DrawDstCoords(this VRM10RotationPositionConstraintBase self)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -42,7 +42,7 @@ namespace UniVRM10
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawDstCurrent(this IVRM10ConstraintSourceDestination self)
|
||||
public static void DrawDstCurrent(this VRM10RotationPositionConstraintBase self)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -5,67 +5,7 @@ using UnityEngine;
|
||||
namespace UniVRM10
|
||||
{
|
||||
[CustomEditor(typeof(VRM10PositionConstraint))]
|
||||
public class VRM10PositionConstraintEditor : Editor
|
||||
public class VRM10PositionConstraintEditor : VRM10PositionRotationConstraintEditorBase
|
||||
{
|
||||
VRM10PositionConstraint m_target;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_target = (VRM10PositionConstraint)target;
|
||||
}
|
||||
|
||||
static GUIStyle s_style;
|
||||
static GUIStyle Style
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_style == null)
|
||||
{
|
||||
s_style = new GUIStyle("box");
|
||||
}
|
||||
return s_style;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSceneGUI()
|
||||
{
|
||||
if (m_target.Source == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this to target line
|
||||
Handles.color = Color.yellow;
|
||||
Handles.DrawLine(m_target.Source.position, m_target.transform.position);
|
||||
|
||||
var delta = m_target.Delta;
|
||||
|
||||
// show source
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"source: {m_target.SourceCoordinate}");
|
||||
sb.AppendLine($"{delta.x:0.00}");
|
||||
sb.AppendLine($"{delta.y:0.00}");
|
||||
sb.Append($"{delta.z:0.00}");
|
||||
Handles.Label(m_target.Source.position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
// show dst
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"constraint: {m_target.DestinationCoordinate}");
|
||||
sb.AppendLine(m_target.FreezeAxes.HasFlag(AxisMask.X) ? $"freeze" : $"{delta.x:0.}");
|
||||
sb.AppendLine(m_target.FreezeAxes.HasFlag(AxisMask.Y) ? $"freeze" : $"{delta.y:0.}");
|
||||
sb.Append(m_target.FreezeAxes.HasFlag(AxisMask.Z) ? $"freeze" : $"{delta.z:0.}");
|
||||
Handles.Label(m_target.transform.position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
m_target.DrawSourceCoords();
|
||||
m_target.DrawSourceCurrent();
|
||||
m_target.DrawDstCoords();
|
||||
m_target.DrawDstCurrent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public abstract class VRM10PositionRotationConstraintEditorBase : Editor
|
||||
{
|
||||
VRM10RotationPositionConstraintBase m_target;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_target = (VRM10RotationPositionConstraintBase)target;
|
||||
}
|
||||
|
||||
static GUIStyle s_style;
|
||||
static GUIStyle Style
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_style == null)
|
||||
{
|
||||
s_style = new GUIStyle("box");
|
||||
}
|
||||
return s_style;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Euler各を +- 180 にクランプする
|
||||
/// </summary>
|
||||
/// <param name="v"></param>
|
||||
/// <returns></returns>
|
||||
static Vector3 Clamp180(Vector3 v)
|
||||
{
|
||||
var x = v.x;
|
||||
while (x < -180) x += 360;
|
||||
while (x > 180) x -= 360;
|
||||
var y = v.y;
|
||||
while (y < -180) y += 360;
|
||||
while (y > 180) y -= 360;
|
||||
var z = v.z;
|
||||
while (z < -180) z += 360;
|
||||
while (z > 180) z -= 360;
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
public void OnSceneGUI()
|
||||
{
|
||||
if (m_target.GetSource() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// source offset
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Quaternion offset = Handles.RotationHandle(m_target.SourceOffset, m_target.GetSource().position);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_target.GetComponent(), "source offset");
|
||||
m_target.SourceOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// dest offset
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Quaternion offset = Handles.RotationHandle(m_target.DestinationOffset, m_target.GetComponent().transform.position);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_target.GetComponent(), "dest offset");
|
||||
m_target.DestinationOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// this to target line
|
||||
Handles.color = Color.yellow;
|
||||
Handles.DrawLine(m_target.GetSource().position, m_target.GetComponent().transform.position);
|
||||
|
||||
var delta = Clamp180(m_target.Delta);
|
||||
|
||||
// show source
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"source: {m_target.SourceCoordinate}");
|
||||
sb.AppendLine($"{delta.x:0.}");
|
||||
sb.AppendLine($"{delta.y:0.}");
|
||||
sb.Append($"{delta.z:0.}");
|
||||
Handles.Label(m_target.GetSource().position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
// show dst
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"constraint: {m_target.DestinationCoordinate}");
|
||||
sb.AppendLine(m_target.FreezeAxes.HasFlag(AxisMask.X) ? $"freeze" : $"{delta.x:0.}");
|
||||
sb.AppendLine(m_target.FreezeAxes.HasFlag(AxisMask.Y) ? $"freeze" : $"{delta.y:0.}");
|
||||
sb.Append(m_target.FreezeAxes.HasFlag(AxisMask.Z) ? $"freeze" : $"{delta.z:0.}");
|
||||
Handles.Label(m_target.GetComponent().transform.position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
m_target.DrawSourceCoords();
|
||||
m_target.DrawSourceCurrent();
|
||||
m_target.DrawDstCoords();
|
||||
m_target.DrawDstCurrent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d1ea0f0f4d95a2499f9aa5a1d7a2235
|
||||
guid: 46c1f13688fee134aa37a39a72433217
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -5,110 +5,7 @@ using UnityEngine;
|
||||
namespace UniVRM10
|
||||
{
|
||||
[CustomEditor(typeof(VRM10RotationConstraint))]
|
||||
public class VRM10RotationConstraintEditor : Editor
|
||||
public class VRM10RotationConstraintEditor : VRM10PositionRotationConstraintEditorBase
|
||||
{
|
||||
VRM10RotationConstraint m_target;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_target = (VRM10RotationConstraint)target;
|
||||
}
|
||||
|
||||
static GUIStyle s_style;
|
||||
static GUIStyle Style
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_style == null)
|
||||
{
|
||||
s_style = new GUIStyle("box");
|
||||
}
|
||||
return s_style;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Euler各を +- 180 にクランプする
|
||||
/// </summary>
|
||||
/// <param name="v"></param>
|
||||
/// <returns></returns>
|
||||
static Vector3 Clamp180(Vector3 v)
|
||||
{
|
||||
var x = v.x;
|
||||
while (x < -180) x += 360;
|
||||
while (x > 180) x -= 360;
|
||||
var y = v.y;
|
||||
while (y < -180) y += 360;
|
||||
while (y > 180) y -= 360;
|
||||
var z = v.z;
|
||||
while (z < -180) z += 360;
|
||||
while (z > 180) z -= 360;
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
public void OnSceneGUI()
|
||||
{
|
||||
if (m_target.Source == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// source offset
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Quaternion offset = Handles.RotationHandle(m_target.SourceOffset.Rotation, m_target.Source.position);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_target, "source offset");
|
||||
m_target.SourceOffset.Rotation = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// dest offset
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Quaternion offset = Handles.RotationHandle(m_target.DestinationOffset.Rotation, m_target.transform.position);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(m_target, "dest offset");
|
||||
m_target.DestinationOffset.Rotation = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// this to target line
|
||||
Handles.color = Color.yellow;
|
||||
Handles.DrawLine(m_target.Source.position, m_target.transform.position);
|
||||
|
||||
var delta = Clamp180(m_target.Delta.eulerAngles);
|
||||
|
||||
// show source
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"source: {m_target.SourceCoordinate}");
|
||||
sb.AppendLine($"{delta.x:0.}");
|
||||
sb.AppendLine($"{delta.y:0.}");
|
||||
sb.Append($"{delta.z:0.}");
|
||||
Handles.Label(m_target.Source.position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
// show dst
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"constraint: {m_target.DestinationCoordinate}");
|
||||
sb.AppendLine(m_target.FreezeAxes.HasFlag(AxisMask.X) ? $"freeze" : $"{delta.x:0.}");
|
||||
sb.AppendLine(m_target.FreezeAxes.HasFlag(AxisMask.Y) ? $"freeze" : $"{delta.y:0.}");
|
||||
sb.Append(m_target.FreezeAxes.HasFlag(AxisMask.Z) ? $"freeze" : $"{delta.z:0.}");
|
||||
Handles.Label(m_target.transform.position, sb.ToString(), Style);
|
||||
}
|
||||
|
||||
m_target.DrawSourceCoords();
|
||||
m_target.DrawSourceCurrent();
|
||||
m_target.DrawDstCoords();
|
||||
m_target.DrawDstCurrent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
class ConstraintDestination
|
||||
public class ConstraintDestination
|
||||
{
|
||||
readonly Transform m_transform;
|
||||
readonly TR m_modelInitial;
|
||||
|
||||
@@ -4,7 +4,7 @@ using UniGLTF.Extensions.VRMC_node_constraint;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
class ConstraintSource
|
||||
public class ConstraintSource
|
||||
{
|
||||
public readonly Transform ModelRoot;
|
||||
readonly Transform m_transform;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace UniVRM10
|
||||
{
|
||||
public interface IVRM10ConstraintSourceDestination
|
||||
{
|
||||
TR GetSourceCoords();
|
||||
TR GetSourceCurrent();
|
||||
|
||||
TR GetDstCoords();
|
||||
TR GetDstCurrent();
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,7 @@ namespace UniVRM10
|
||||
{
|
||||
public abstract class VRM10Constraint : MonoBehaviour
|
||||
{
|
||||
public virtual void Process()
|
||||
{
|
||||
public abstract void Process();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,169 +8,12 @@ namespace UniVRM10
|
||||
/// 対象の初期位置と現在位置の差分(delta)を、自身の初期位置に対してWeightを乗算して加算する。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class VRM10PositionConstraint : VRM10Constraint, IVRM10ConstraintSourceDestination
|
||||
public class VRM10PositionConstraint : VRM10RotationPositionConstraintBase
|
||||
{
|
||||
[SerializeField]
|
||||
public Transform Source = default;
|
||||
Vector3 m_delta;
|
||||
public override Vector3 Delta => m_delta;
|
||||
|
||||
[SerializeField]
|
||||
public ObjectSpace SourceCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
public VRM10RotationOffset SourceOffset = VRM10RotationOffset.Identity;
|
||||
|
||||
[SerializeField]
|
||||
public ObjectSpace DestinationCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
public AxisMask FreezeAxes = default;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
public float Weight = 1.0f;
|
||||
|
||||
[SerializeField]
|
||||
public Transform ModelRoot = default;
|
||||
|
||||
ConstraintSource m_src;
|
||||
|
||||
public TR GetSourceCoords()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoSource);
|
||||
}
|
||||
|
||||
switch (SourceCoordinate)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
{
|
||||
if (ModelRoot == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
|
||||
if (m_src == null)
|
||||
{
|
||||
return new TR(ModelRoot.rotation, Source.position);
|
||||
}
|
||||
|
||||
// runtime
|
||||
return new TR(ModelRoot.rotation, m_src.ModelInitial.Translation);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return TR.FromWorld(Source);
|
||||
}
|
||||
|
||||
// runtime
|
||||
var parent = TR.Identity;
|
||||
if (Source.parent != null)
|
||||
{
|
||||
parent = TR.FromWorld(Source.parent);
|
||||
}
|
||||
return parent * m_src.LocalInitial;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public TR GetSourceCurrent()
|
||||
{
|
||||
var coords = GetSourceCoords();
|
||||
if (m_src == null)
|
||||
{
|
||||
return coords;
|
||||
}
|
||||
|
||||
return new TR(Delta) * coords;
|
||||
}
|
||||
|
||||
public Vector3 Delta
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
ConstraintDestination m_dst;
|
||||
|
||||
public TR GetDstCoords()
|
||||
{
|
||||
switch (DestinationCoordinate)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
{
|
||||
if (ModelRoot == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
return new TR(ModelRoot.rotation, transform.position);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return TR.FromWorld(transform);
|
||||
}
|
||||
|
||||
// runtime
|
||||
var parent = TR.Identity;
|
||||
if (transform.parent != null)
|
||||
{
|
||||
parent = TR.FromWorld(transform.parent);
|
||||
}
|
||||
return parent * m_dst.LocalInitial;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public TR GetDstCurrent()
|
||||
{
|
||||
var coords = GetDstCoords();
|
||||
if (m_src == null)
|
||||
{
|
||||
return coords;
|
||||
}
|
||||
|
||||
return new TR(Delta) * coords;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Editorで設定値の変更を反映するために、クリアする
|
||||
/// </summary>
|
||||
void OnValidate()
|
||||
{
|
||||
// Debug.Log("Validate");
|
||||
if (m_src != null && m_src.ModelRoot != ModelRoot)
|
||||
{
|
||||
m_src = null;
|
||||
}
|
||||
if (m_dst != null && m_dst.ModelRoot != ModelRoot)
|
||||
{
|
||||
m_dst = null;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
var current = transform;
|
||||
while (current.parent != null)
|
||||
{
|
||||
current = current.parent;
|
||||
}
|
||||
ModelRoot = current;
|
||||
}
|
||||
|
||||
public override void Process()
|
||||
protected override void UpdateDelta()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
@@ -187,8 +30,30 @@ namespace UniVRM10
|
||||
m_dst = new ConstraintDestination(transform, ModelRoot);
|
||||
}
|
||||
|
||||
Delta = FreezeAxes.Freeze(m_src.TranslationDelta(SourceCoordinate));
|
||||
m_delta = FreezeAxes.Freeze(m_src.TranslationDelta(SourceCoordinate));
|
||||
m_dst.ApplyTranslation(Delta, Weight, DestinationCoordinate, ModelRoot);
|
||||
}
|
||||
|
||||
public override TR GetSourceCurrent()
|
||||
{
|
||||
var coords = GetSourceCoords();
|
||||
if (m_src == null)
|
||||
{
|
||||
return coords;
|
||||
}
|
||||
|
||||
return new TR(Delta) * coords;
|
||||
}
|
||||
|
||||
public override TR GetDstCurrent()
|
||||
{
|
||||
var coords = GetDstCoords();
|
||||
if (m_src == null)
|
||||
{
|
||||
return coords;
|
||||
}
|
||||
|
||||
return new TR(Delta) * coords;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using UniGLTF.Extensions.VRMC_node_constraint;
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace UniVRM10
|
||||
@@ -9,78 +7,18 @@ namespace UniVRM10
|
||||
/// 対象の初期回転と現在回転の差分(delta)を、自身の初期回転と自身の初期回転にdeltaを乗算したものに対してWeightでSlerpする。
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class VRM10RotationConstraint : VRM10Constraint, IVRM10ConstraintSourceDestination
|
||||
public class VRM10RotationConstraint : VRM10RotationPositionConstraintBase
|
||||
{
|
||||
[SerializeField]
|
||||
[EnumFlags]
|
||||
public AxisMask FreezeAxes = default;
|
||||
Quaternion m_delta;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
public float Weight = 1.0f;
|
||||
public override Vector3 Delta => m_delta.eulerAngles;
|
||||
|
||||
[SerializeField]
|
||||
public Transform ModelRoot = default;
|
||||
|
||||
[Header("Source")]
|
||||
[SerializeField]
|
||||
public Transform Source = default;
|
||||
|
||||
[SerializeField]
|
||||
public ObjectSpace SourceCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
public VRM10RotationOffset SourceOffset = VRM10RotationOffset.Identity;
|
||||
|
||||
[Header("Destination")]
|
||||
[SerializeField]
|
||||
public ObjectSpace DestinationCoordinate = default;
|
||||
|
||||
[SerializeField]
|
||||
public VRM10RotationOffset DestinationOffset = VRM10RotationOffset.Identity;
|
||||
|
||||
ConstraintSource m_src;
|
||||
|
||||
public TR GetSourceCoords()
|
||||
protected override void UpdateDelta()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoSource);
|
||||
}
|
||||
|
||||
switch (SourceCoordinate)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
{
|
||||
if (ModelRoot == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
return new TR(ModelRoot.rotation * SourceOffset.Rotation, Source.position);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return new TR(Source.rotation * SourceOffset.Rotation, Source.position);
|
||||
}
|
||||
|
||||
// runtime
|
||||
var parent = Quaternion.identity;
|
||||
if (Source.parent != null)
|
||||
{
|
||||
parent = Source.parent.rotation;
|
||||
}
|
||||
return new TR(parent * m_src.LocalInitial.Rotation * SourceOffset.Rotation, Source.position);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
m_delta = m_src.RotationDelta(SourceCoordinate, SourceOffset);
|
||||
}
|
||||
|
||||
public TR GetSourceCurrent()
|
||||
public override TR GetSourceCurrent()
|
||||
{
|
||||
var coords = GetSourceCoords();
|
||||
if (m_src == null)
|
||||
@@ -88,51 +26,10 @@ namespace UniVRM10
|
||||
return coords;
|
||||
}
|
||||
|
||||
return coords * new TR(Delta);
|
||||
return coords * new TR(m_delta);
|
||||
}
|
||||
|
||||
public Quaternion Delta
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
ConstraintDestination m_dst;
|
||||
public TR GetDstCoords()
|
||||
{
|
||||
switch (DestinationCoordinate)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
{
|
||||
if (ModelRoot == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
return new TR(ModelRoot.rotation * DestinationOffset.Rotation, transform.position);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return new TR(transform.rotation * DestinationOffset.Rotation, transform.position);
|
||||
}
|
||||
|
||||
// runtime
|
||||
var parent = Quaternion.identity;
|
||||
if (transform.parent != null)
|
||||
{
|
||||
parent = transform.parent.rotation;
|
||||
}
|
||||
return new TR(parent * m_dst.LocalInitial.Rotation * DestinationOffset.Rotation, transform.position);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public TR GetDstCurrent()
|
||||
public override TR GetDstCurrent()
|
||||
{
|
||||
var coords = GetDstCoords();
|
||||
if (m_src == null)
|
||||
@@ -140,62 +37,7 @@ namespace UniVRM10
|
||||
return coords;
|
||||
}
|
||||
|
||||
return coords * new TR(Delta);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Editorで設定値の変更を反映するために、クリアする
|
||||
/// </summary>
|
||||
void OnValidate()
|
||||
{
|
||||
// Debug.Log("Validate");
|
||||
if (m_src != null && m_src.ModelRoot != ModelRoot)
|
||||
{
|
||||
m_src = null;
|
||||
}
|
||||
if (m_dst != null && m_dst.ModelRoot != ModelRoot)
|
||||
{
|
||||
m_dst = null;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
var current = transform;
|
||||
while (current.parent != null)
|
||||
{
|
||||
current = current.parent;
|
||||
}
|
||||
ModelRoot = current;
|
||||
}
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_src == null)
|
||||
{
|
||||
m_src = new ConstraintSource(Source, ModelRoot);
|
||||
}
|
||||
if (m_dst == null)
|
||||
{
|
||||
m_dst = new ConstraintDestination(transform, ModelRoot);
|
||||
}
|
||||
|
||||
// 回転差分
|
||||
Delta = m_src.RotationDelta(SourceCoordinate, SourceOffset.Rotation);
|
||||
|
||||
// 軸制限
|
||||
var fleezed = FreezeAxes.Freeze(Delta.eulerAngles);
|
||||
var rotation = Quaternion.Euler(fleezed);
|
||||
|
||||
// Debug.Log($"{delta} => {rotation}");
|
||||
// オイラー角を再度Quaternionへ。weight を加味してSlerpする
|
||||
m_dst.ApplyRotation(DestinationOffset.Rotation * rotation, Weight, DestinationCoordinate, ModelRoot);
|
||||
return coords * new TR(m_delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
using System;
|
||||
using UniGLTF.Extensions.VRMC_node_constraint;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniVRM10
|
||||
{
|
||||
public abstract class VRM10RotationPositionConstraintBase : VRM10Constraint
|
||||
{
|
||||
[SerializeField]
|
||||
[EnumFlags]
|
||||
AxisMask m_freezeAxes = default;
|
||||
public AxisMask FreezeAxes
|
||||
{
|
||||
get => m_freezeAxes;
|
||||
set => m_freezeAxes = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[Range(0, 10.0f)]
|
||||
public float Weight = 1.0f;
|
||||
|
||||
[SerializeField]
|
||||
public Transform ModelRoot = default;
|
||||
|
||||
#region Source
|
||||
[Header("Source")]
|
||||
[SerializeField]
|
||||
public Transform Source = default;
|
||||
|
||||
public Transform GetSource() => Source;
|
||||
|
||||
[SerializeField]
|
||||
ObjectSpace m_sourceCoordinate = default;
|
||||
public ObjectSpace SourceCoordinate
|
||||
{
|
||||
get => m_sourceCoordinate;
|
||||
set => m_sourceCoordinate = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
VRM10RotationOffset m_sourceOffset = VRM10RotationOffset.Identity;
|
||||
|
||||
public Quaternion SourceOffset
|
||||
{
|
||||
get => m_sourceOffset.Rotation;
|
||||
set => m_sourceOffset.Rotation = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Destination
|
||||
[Header("Destination")]
|
||||
[SerializeField]
|
||||
ObjectSpace m_destinationCoordinate = default;
|
||||
public ObjectSpace DestinationCoordinate
|
||||
{
|
||||
get => m_destinationCoordinate;
|
||||
set => m_destinationCoordinate = value;
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
public VRM10RotationOffset m_destinationOffset = VRM10RotationOffset.Identity;
|
||||
|
||||
public Quaternion DestinationOffset
|
||||
{
|
||||
get => m_destinationOffset.Rotation;
|
||||
set => m_destinationOffset.Rotation = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public abstract Vector3 Delta { get; }
|
||||
|
||||
protected ConstraintSource m_src;
|
||||
|
||||
public TR GetSourceCoords()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoSource);
|
||||
}
|
||||
|
||||
switch (SourceCoordinate)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
{
|
||||
if (ModelRoot == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
return new TR(ModelRoot.rotation * SourceOffset, Source.position);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return new TR(Source.rotation * SourceOffset, Source.position);
|
||||
}
|
||||
|
||||
// runtime
|
||||
var parent = Quaternion.identity;
|
||||
if (Source.parent != null)
|
||||
{
|
||||
parent = Source.parent.rotation;
|
||||
}
|
||||
return new TR(parent * m_src.LocalInitial.Rotation * SourceOffset, Source.position);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract TR GetSourceCurrent();
|
||||
|
||||
protected ConstraintDestination m_dst;
|
||||
|
||||
public TR GetDstCoords()
|
||||
{
|
||||
switch (DestinationCoordinate)
|
||||
{
|
||||
case ObjectSpace.model:
|
||||
{
|
||||
if (ModelRoot == null)
|
||||
{
|
||||
throw new ConstraintException(ConstraintException.ExceptionTypes.NoModelWithModelSpace);
|
||||
}
|
||||
return new TR(ModelRoot.rotation * DestinationOffset, transform.position);
|
||||
}
|
||||
|
||||
case ObjectSpace.local:
|
||||
{
|
||||
if (m_src == null)
|
||||
{
|
||||
return new TR(transform.rotation * DestinationOffset, transform.position);
|
||||
}
|
||||
|
||||
// runtime
|
||||
var parent = Quaternion.identity;
|
||||
if (transform.parent != null)
|
||||
{
|
||||
parent = transform.parent.rotation;
|
||||
}
|
||||
return new TR(parent * m_dst.LocalInitial.Rotation * DestinationOffset, transform.position);
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract TR GetDstCurrent();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Editorで設定値の変更を反映するために、クリアする
|
||||
/// </summary>
|
||||
void OnValidate()
|
||||
{
|
||||
// Debug.Log("Validate");
|
||||
if (m_src != null && m_src.ModelRoot != ModelRoot)
|
||||
{
|
||||
m_src = null;
|
||||
}
|
||||
if (m_dst != null && m_dst.ModelRoot != ModelRoot)
|
||||
{
|
||||
m_dst = null;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
var current = transform;
|
||||
while (current.parent != null)
|
||||
{
|
||||
current = current.parent;
|
||||
}
|
||||
ModelRoot = current;
|
||||
}
|
||||
|
||||
public Component GetComponent()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
protected abstract void UpdateDelta();
|
||||
|
||||
public override void Process()
|
||||
{
|
||||
if (Source == null)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_src == null)
|
||||
{
|
||||
m_src = new ConstraintSource(Source, ModelRoot);
|
||||
}
|
||||
if (m_dst == null)
|
||||
{
|
||||
m_dst = new ConstraintDestination(transform, ModelRoot);
|
||||
}
|
||||
|
||||
// 回転差分
|
||||
UpdateDelta();
|
||||
|
||||
// 軸制限
|
||||
var fleezed = FreezeAxes.Freeze(Delta);
|
||||
var rotation = Quaternion.Euler(fleezed);
|
||||
|
||||
// Debug.Log($"{delta} => {rotation}");
|
||||
// オイラー角を再度Quaternionへ。weight を加味してSlerpする
|
||||
m_dst.ApplyRotation(DestinationOffset * rotation, Weight, DestinationCoordinate, ModelRoot);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07919df684c7a4c47a9492a2de417f66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user