using ChivaXR;
using Sirenix.OdinInspector;
using System;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
public class ToolAni_BanShou : ToolAnimationBase
{
#region 扳手交互参数
[LabelText("相对移动位置")]
public Vector3 localMovePos = new Vector3(0, 0, 0);
[LabelText("相对旋转角度")]
public float rotAngle = 0;
[LabelText("扳手单轮角度")]
public float maxAngle = 40;
[LabelText("运行时长(不包含工具动画)")]
public float duration = 1;
[LabelText("螺丝抬起高度")]
public float moveHigh = 0.02f;
[LabelText("共享锚点")]
public SimpleMoveItem m_SimpleMoveItem;
[InfoBox("开启后,工具会随所有锚点的中心点进行朝向校准,关闭则使用默认朝向")]
[LabelText("是否开启工具校准")]
public bool m_UseCenterReset = true;
//工具锚点旋转角度
private float toolAnchorAngle = 0;
private float timer = 0;
private bool isLuoSiRot = true;
private float toolHighLerp = 0;
[HideInInspector]
public Transform currentModel;
[HideInInspector]
public Transform currentModelAnchor;
public Transform currentToolAnchor;
#endregion
public override void PlayUpdate(ToolAnimationItem toolAnimationItem, bool reverse)
{
if (currentToolAnchor != toolAnimationItem.toolAnchor)
{
PlayBanShouAnimationByFrame(currentModel, currentModelAnchor, currentToolAnchor, () =>
{
toolAnimationItem.isPlaying = false;
if (currentToolAnchor != null)
{
toolAnimationItem.Destroy(currentToolAnchor.gameObject);
}
currentModel.gameObject.SetActive(false);
});
}
else
{
PlayBanShouAnimationByFrame(toolAnimationItem.model.transform, toolAnimationItem.modelAnchor, toolAnimationItem.toolAnchor,
() =>
{
toolAnimationItem.isPlaying = false;
currentToolAnchor.gameObject.SetActive(false);
currentModel.gameObject.SetActive(false);
});
}
}
public void PlayBanShouAnimationByFrame(Transform tmpModel, Transform tmpModelAnchor, Transform tmpToolAnchor, Action finishedCallBack)
{
if (isLuoSiRot)
{
if (toolAnchorAngle < maxAngle)
{
timer += Time.deltaTime;
toolAnchorAngle += Mathf.Abs(rotAngle) * Time.deltaTime / duration;
tmpModel.position = Vector3.Lerp(tmpModelAnchor.position, tmpModelAnchor.position + tmpModelAnchor.TransformDirection(localMovePos), timer / duration);
tmpModel.rotation = tmpModelAnchor.rotation;
tmpModel.RotateAround(tmpModelAnchor.position, tmpModelAnchor.TransformDirection(localMovePos), rotAngle * timer / duration);
tmpToolAnchor.position = tmpModel.position;
tmpToolAnchor.rotation = tmpModelAnchor.rotation;
tmpToolAnchor.RotateAround(tmpModelAnchor.position, tmpModelAnchor.TransformDirection(localMovePos), toolAnchorAngle * (rotAngle > 0 ? 1 : -1));
}
else
{
toolHighLerp += Time.deltaTime * 5;
if (toolHighLerp > 1)
{
toolHighLerp = 1;
isLuoSiRot = false;
}
tmpToolAnchor.position = Vector3.Lerp(tmpModel.position, tmpModel.position + tmpModelAnchor.TransformDirection(localMovePos).normalized * moveHigh, toolHighLerp);
}
}
else //扳手回转
{
if (toolAnchorAngle > 0)
{
toolAnchorAngle -= Mathf.Abs(rotAngle) * Time.deltaTime / duration;
tmpToolAnchor.rotation = tmpModelAnchor.transform.rotation;
tmpToolAnchor.RotateAround(tmpModelAnchor.position, tmpModelAnchor.TransformDirection(localMovePos), toolAnchorAngle * (rotAngle > 0 ? 1 : -1));
}
else
{
toolHighLerp -= Time.deltaTime * 5;
if (toolHighLerp < 0)
{
toolHighLerp = 0;
isLuoSiRot = true;
}
tmpToolAnchor.transform.position = Vector3.Lerp(tmpModel.position, tmpModel.position + tmpModelAnchor.TransformDirection(localMovePos).normalized * moveHigh, toolHighLerp);
}
}
if (timer > duration)
{
timer = 0;
tmpModel.position = tmpModelAnchor.position;
tmpModel.rotation = tmpModelAnchor.rotation;
tmpToolAnchor.position = tmpModelAnchor.position;
tmpToolAnchor.rotation = tmpModelAnchor.rotation;
finishedCallBack?.Invoke();
}
}
public override void FinishedState(ToolAnimationItem toolAnimationItem, bool reverse)
{
toolAnimationItem.toolAnchor.gameObject.SetActive(false);
timer = 0;
StopPlay(toolAnimationItem, reverse);
}
public override void InitState(ToolAnimationItem toolAnimationItem, bool reverse)
{
toolAnimationItem.model.SetActive(true);
if (currentModel != null)
{
currentModel.gameObject.SetActive(true);
}
if (currentToolAnchor != null)
{
if (currentToolAnchor == toolAnimationItem.toolAnchor)
{
currentToolAnchor.gameObject.SetActive(false);
}
else
{
toolAnimationItem.Destroy(currentToolAnchor.gameObject);
}
}
}
public override void PlayTrigger(ToolAnimationItem toolAnimationItem, bool reverse)
{
timer = 0;
isLuoSiRot = true;
toolAnchorAngle = 0;
if (Application.isPlaying)
{
if (AnimationManager.Instance.AnimationActiveObj != null)
{
InitTargetToolAnchor(AnimationManager.Instance.AnimationActiveObj.transform.position, toolAnimationItem);
}
}
else
{
#if UNITY_EDITOR
if (Selection.activeGameObject != null)
{
InitTargetToolAnchor(Selection.activeGameObject.transform.position, toolAnimationItem);
}
else
{
InitTargetToolAnchor(toolAnimationItem.modelAnchor.position, toolAnimationItem);
}
#endif
}
}
public override void StopPlay(ToolAnimationItem toolAnimationItem, bool reverse)
{
timer = 0;
if (currentModel != null)
{
currentModel.position = currentModelAnchor.position;
currentModel.rotation = currentModelAnchor.rotation;
}
if (currentToolAnchor != null)
{
currentToolAnchor.position = currentModelAnchor.position;
currentToolAnchor.rotation = currentModelAnchor.rotation;
}
if (currentToolAnchor != toolAnimationItem.toolAnchor)
{
toolAnimationItem.isPlaying = false;
if (currentToolAnchor != null)
{
toolAnimationItem.Destroy(currentToolAnchor.gameObject);
}
if (Application.isPlaying && currentModel != null)
{
currentModel.gameObject.SetActive(false);
}
}
else
{
toolAnimationItem.isPlaying = false;
currentToolAnchor.gameObject.SetActive(false);
if (Application.isPlaying && currentModel != null)
{
currentModel.gameObject.SetActive(false);
}
}
}
///
/// 根据当前CheckPos选择的物体最近的锚点执行动画
///
///
public void InitTargetToolAnchor(Vector3 CheckPos, ToolAnimationItem toolAnimationItem)
{
currentModel = toolAnimationItem.model.transform;
currentModelAnchor = toolAnimationItem.modelAnchor;
Vector3 centerPoint = Vector3.zero;
if (m_SimpleMoveItem != null)
{
foreach (var item in m_SimpleMoveItem.moveObjs)
{
centerPoint += item.Value.position;
if (Vector3.Distance(item.Key.transform.position, currentModel.position) < 0.001f) continue;
if (Vector3.Distance(CheckPos, currentModelAnchor.position) > Vector3.Distance(CheckPos, item.Value.position))
{
currentModelAnchor = item.Value;
currentModel = item.Key.transform;
}
}
centerPoint = centerPoint / m_SimpleMoveItem.moveObjs.Count;
}
if (currentModelAnchor != toolAnimationItem.modelAnchor)
{
currentToolAnchor = GameObject.Instantiate(toolAnimationItem.toolAnchor);
currentToolAnchor.transform.parent = currentModelAnchor;
currentToolAnchor.transform.localPosition = Vector3.zero;
currentToolAnchor.transform.localRotation = Quaternion.identity;
currentToolAnchor.transform.localScale = Vector3.one;
if (m_UseCenterReset)
{
float angle = Vector3.Angle(toolAnimationItem.modelAnchor.position - centerPoint, currentModelAnchor.position - centerPoint);
Vector3 oldDir = currentModelAnchor.InverseTransformDirection(toolAnimationItem.modelAnchor.position - centerPoint);
Vector3 newDir = currentModelAnchor.InverseTransformDirection(currentModelAnchor.position - centerPoint);
float a = Vector3.Dot(Vector3.Cross(oldDir, newDir), localMovePos);
for (int i = 0; i < currentToolAnchor.childCount; i++)
{
currentToolAnchor.GetChild(i).RotateAround(currentModelAnchor.position, currentModelAnchor.TransformDirection(localMovePos), angle * (a > 0 ? 1 : -1));
}
}
}
else
{
currentToolAnchor = toolAnimationItem.toolAnchor;
toolAnimationItem.toolAnchor.gameObject.SetActive(true);
}
currentToolAnchor.gameObject.SetActive(true);
}
#if UNITY_EDITOR
public override void EditorPlayUpdate(ToolAnimationItem toolAnimationItem, bool reverse)
{
if (currentToolAnchor != toolAnimationItem.toolAnchor)
{
PlayBanShouAnimationByFrame(currentModel, currentModelAnchor, currentToolAnchor, () =>
{
toolAnimationItem.isPlaying = false;
if (currentToolAnchor != null)
{
toolAnimationItem.Destroy(currentToolAnchor.gameObject);
}
});
}
else
{
PlayBanShouAnimationByFrame(toolAnimationItem.model.transform, toolAnimationItem.modelAnchor, toolAnimationItem.toolAnchor,
() => { toolAnimationItem.isPlaying = false; });
}
}
public override void OnDrawGizmos(ToolAnimationItem toolAnimationItem)
{
Gizmos.color = Color.yellow;
Gizmos.DrawLine(toolAnimationItem.modelAnchor.position, toolAnimationItem.modelAnchor.position + toolAnimationItem.modelAnchor.TransformDirection(localMovePos));
}
#endif
}