using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UniGLTF;
namespace UniVRM10
{
///
/// SpringBone, LookAt の座標を記録しておき、Dispose で復帰する。
///
public class Vrm10GeometryBackup : IDisposable
{
struct Vrm10SpringBoneColliderBackup
{
Vector3 _offsetInWorld;
float _radiusMultLossyScale;
public Vrm10SpringBoneColliderBackup(VRM10SpringBoneCollider collider)
{
_offsetInWorld = collider.transform.TransformPoint(collider.Offset);
_radiusMultLossyScale = collider.transform.UniformedLossyScale() * collider.Radius;
}
public void Restore(VRM10SpringBoneCollider collider)
{
collider.Offset = collider.transform.worldToLocalMatrix.MultiplyPoint(_offsetInWorld);
collider.Radius = _radiusMultLossyScale / collider.transform.UniformedLossyScale();
}
}
struct Vrm10SpringBoneJointBackup
{
Vector3 _gravityDirInWorld;
float _radiusMultLossyScale;
public Vrm10SpringBoneJointBackup(VRM10SpringBoneJoint joint)
{
_gravityDirInWorld = joint.transform.TransformDirection(joint.m_gravityDir);
_radiusMultLossyScale = joint.transform.UniformedLossyScale() * joint.m_jointRadius;
}
public void Restore(VRM10SpringBoneJoint joint)
{
joint.m_gravityDir = joint.transform.worldToLocalMatrix.MultiplyVector(_gravityDirInWorld);
joint.m_jointRadius = _radiusMultLossyScale / joint.transform.UniformedLossyScale();
}
}
Dictionary _springBoneColliders;
Dictionary _springBoneJoints;
Vrm10Instance _vrm;
Vector3 _lookAtOffsetInWorld;
public Vrm10GeometryBackup(GameObject root)
{
_springBoneColliders = root.GetComponentsInChildren().ToDictionary(x => x, x => new Vrm10SpringBoneColliderBackup(x));
_springBoneJoints = root.GetComponentsInChildren().ToDictionary(x => x, x => new Vrm10SpringBoneJointBackup(x));
_vrm = root.GetComponent();
_lookAtOffsetInWorld = _vrm.transform.TransformPoint(_vrm.Vrm.LookAt.OffsetFromHead);
}
public void Dispose()
{
foreach (var (k, v) in _springBoneColliders)
{
v.Restore(k);
}
foreach (var (k, v) in _springBoneJoints)
{
v.Restore(k);
}
_vrm.Vrm.LookAt.OffsetFromHead = _vrm.transform.worldToLocalMatrix.MultiplyPoint(_lookAtOffsetInWorld);
}
}
}