Merge branch 'master' into fix/spring_limit_specversion

This commit is contained in:
ousttrue
2026-09-25 10:25:51 +09:00
committed by GitHub
4 changed files with 106 additions and 27 deletions

View File

@@ -38,6 +38,8 @@ namespace UniGLTF.SpringBoneJobs.Blittables
public float anglelimit2 => _data.c2.z;
public quaternion anglelimitOffset => _data.c3.xyzw;
// angleLimit1: angle (Cone/Hinge), pitch (Spherical)
// angleLimit2: yaw (Spherical)
public BlittableJointMutable(float stiffnessForce = 0,
float gravityPower = 0,
float3 gravityDir = default,

View File

@@ -63,10 +63,11 @@ namespace UniVRM10
/// spring 情報。readonly。mouse click による hierarchy 参照補助
///
EditorGUI.BeginDisabledGroup(true);
var isLastTail = ShowSpringInfo();
var info = Vrm10InstanceSpringBone.GetEditInfo(m_target, m_root);
ShowSpringInfo(info);
EditorGUI.EndDisabledGroup();
if (isLastTail)
if (info.IsLastTail)
{
EditorGUILayout.HelpBox("末端 joint です。下記の設定は使用されません。", MessageType.Info);
}
@@ -88,7 +89,7 @@ namespace UniVRM10
//
// angle limit
//
var fold = EditorGUILayout.Foldout(m_showAnglelimitSettings, "AngleLimit Settings (experimental)");
var fold = EditorGUILayout.Foldout(m_showAnglelimitSettings, $"AngleLimit Settings (1.0-draft)");
if (m_showAnglelimitSettings != fold)
{
m_showAnglelimitSettings = fold;
@@ -96,8 +97,13 @@ namespace UniVRM10
}
if (m_showAnglelimitSettings)
{
EditorGUILayout.HelpBox("SpringBoneの角度制限はまだdraft仕様です。将来的に仕様が変更される可能性があります。また、VRMファイルへのインポート・エクスポート機能はまだ実装されていません。\nThe angle limit feature for SpringBone is still in draft status. The specifications may change in the future. Also, the import/export of VRM files has not yet been implemented.", MessageType.Warning);
EditorGUILayout.HelpBox("SpringBoneの角度制限はまだdraft仕様です。将来的に仕様が変更される可能性があります。\nThe angle limit feature for SpringBone is still in draft status. The specifications may change in the future.", MessageType.Warning);
if (info.IsLastTail)
{
EditorGUILayout.HelpBox("末端ノードではAngleLimitは無視されます。", MessageType.Info);
}
EditorGUILayout.PropertyField(m_angleLimitType);
switch ((UniGLTF.SpringBoneJobs.AnglelimitTypes)m_angleLimitType.enumValueIndex)
{
@@ -106,12 +112,12 @@ namespace UniVRM10
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Cone:
EditorGUILayout.PropertyField(m_angleLimitRotation);
EditorGUILayout.PropertyField(m_angleLimitPitch);
EditorGUILayout.PropertyField(m_angleLimitPitch, new GUIContent("Angle"));
break;
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Hinge:
EditorGUILayout.PropertyField(m_angleLimitRotation);
EditorGUILayout.PropertyField(m_angleLimitPitch);
EditorGUILayout.PropertyField(m_angleLimitPitch, new GUIContent("Angle"));
break;
case UniGLTF.SpringBoneJobs.AnglelimitTypes.Spherical:
@@ -139,52 +145,51 @@ namespace UniVRM10
/// - Springに関連付けられたColliderの情報を表示する
/// </summary>
/// <returns>末端</returns>
bool ShowSpringInfo()
static void ShowSpringInfo(Vrm10InstanceSpringBone.EditInfo info)
{
if (m_root == null)
if (info.Root == null)
{
EditorGUILayout.HelpBox("no vrm-1.0", MessageType.Warning);
return false;
return;
}
EditorGUILayout.ObjectField("Vrm-1.0", m_root, typeof(Vrm10Instance), true, null);
EditorGUILayout.ObjectField("Vrm-1.0", info.Root, typeof(Vrm10Instance), true, null);
var found = m_root.SpringBone.FindJoint(m_target);
if (!found.HasValue)
if (info.Spring == null)
{
EditorGUILayout.HelpBox("This joint not belongs any spring", MessageType.Warning);
return false;
return;
}
var (spring, i, _) = found.Value;
m_showJoints = EditorGUILayout.Foldout(m_showJoints, $"Springs[{i}]({spring.Name})");
// var (spring, i, _) = found.Value;
m_showJoints = EditorGUILayout.Foldout(m_showJoints, $"Springs[{info.SpringIndex}]({info.Spring.Name})");
int? jointIndex = default;
// joints
for (int j = 0; j < spring.Joints.Count; ++j)
for (int j = 0; j < info.Spring.Joints.Count; ++j)
{
var joint = spring.Joints[j];
var joint = info.Spring.Joints[j];
if (m_showJoints)
{
var label = $"Joints[{j}]";
if (joint == m_target)
if (joint == info.Target)
{
label += "★";
}
EditorGUILayout.ObjectField(label, joint, typeof(VRM10SpringBoneJoint), true, null);
}
if (joint == m_target)
if (joint == info.Target)
{
jointIndex = j;
}
}
m_showColliders = EditorGUILayout.Foldout(m_showColliders, "ColliderGroups");
if (m_showColliders && found.HasValue)
if (m_showColliders)
{
// collider groups
for (int j = 0; j < spring.ColliderGroups.Count; ++j)
for (int j = 0; j < info.Spring.ColliderGroups.Count; ++j)
{
var group = spring.ColliderGroups[j];
var group = info.Spring.ColliderGroups[j];
EditorGUILayout.LabelField($"ColliderGroups[{j}]({group.Name})");
for (int k = 0; k < group.Colliders.Count; ++k)
{
@@ -194,8 +199,6 @@ namespace UniVRM10
}
}
}
return jointIndex == (spring.Joints.Count - 1);
}
/// <summary>

View File

@@ -26,15 +26,27 @@ namespace UniVRM10
[SerializeField]
public float m_jointRadius = 0.02f;
/// <summary>
/// VRMC_springBone_limit
/// </summary>
[SerializeField]
public UniGLTF.SpringBoneJobs.AnglelimitTypes m_anglelimitType;
/// <summary>
/// VRMC_springBone_limit
/// </summary>
[SerializeField]
public Quaternion m_limitSpaceOffset = Quaternion.identity;
/// <summary>
/// VRMC_springBone_limit
/// </summary>
[SerializeField, Range(0, Mathf.PI)]
public float m_pitch = Mathf.PI;
/// <summary>
/// VRMC_springBone_limit
/// </summary>
[SerializeField, Range(0, Mathf.PI / 2)]
public float m_yaw = 0;
@@ -59,7 +71,7 @@ namespace UniVRM10
}
}
void AddJointRecursive(Transform t, VRM10SpringBoneJoint src)
void AddJointRecursive(Transform t, VRM10SpringBoneJoint src, bool copyLimit)
{
var joint = t.gameObject.GetOrAddComponent<VRM10SpringBoneJoint>();
@@ -70,10 +82,19 @@ namespace UniVRM10
joint.m_dragForce = src.m_dragForce;
joint.m_jointRadius = src.m_jointRadius;
if (copyLimit)
{
joint.m_anglelimitType = src.m_anglelimitType;
joint.m_limitSpaceOffset = src.m_limitSpaceOffset;
joint.m_yaw = src.m_yaw;
joint.m_pitch = src.m_pitch;
}
if (t.childCount > 0)
{
// only first child
AddJointRecursive(t.GetChild(0), src);
AddJointRecursive(t.GetChild(0), src, copyLimit);
}
}
@@ -106,7 +127,7 @@ namespace UniVRM10
return;
}
AddJointRecursive(transform.GetChild(0), this);
AddJointRecursive(transform.GetChild(0), this, true);
// updater root
foreach (var spring in root.SpringBone.Springs)

View File

@@ -89,5 +89,58 @@ namespace UniVRM10
}
return default;
}
public struct EditInfo
{
public VRM10SpringBoneJoint Target;
public Vrm10Instance Root;
public Spring Spring;
public int SpringIndex;
public int JointIndex;
public bool IsLastTail;
}
/// <summary>
/// Return SpringBone EditInfo.
/// Do not call on runtime play for performance.
/// </summary>
/// <param name="target">On Editor may null.</param>
/// <param name="root">GetComponentInParent cache.</param>
/// <returns></returns>
public static EditInfo GetEditInfo(VRM10SpringBoneJoint target, Vrm10Instance root)
{
EditInfo info = default;
if (target == null)
{
return info;
}
info.Target = target;
if (root == null)
{
root = target.GetComponentInParent<Vrm10Instance>();
}
if (root == null)
{
return info;
}
info.Root = root;
var found = root.SpringBone.FindJoint(target);
if (!found.HasValue)
{
return info;
}
(info.Spring, info.SpringIndex, info.JointIndex) = found.Value;
// ヒエラルキーの末端ではなく、Springの末端である
if (info.Spring.Joints.Count > 0 && info.Spring.Joints[info.Spring.Joints.Count - 1] == target)
{
info.IsLastTail = true;
}
return info;
}
}
}