// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using Unity.Mathematics; using UnityEngine; namespace MagicaCloth { /// /// 風コンポーネントの基底クラス /// public abstract partial class WindComponent : BaseComponent { [SerializeField] [Range(0.0f, Define.Compute.MaxWindMain)] protected float main = 5.0f; [SerializeField] [Range(0.0f, 1.0f)] protected float turbulence = 1.0f; [SerializeField] [Range(0.0f, 1.0f)] protected float frequency = 1.0f; [SerializeField] protected Vector3 areaSize = new Vector3(5.0f, 5.0f, 5.0f); [SerializeField] protected float areaRadius = 5.0f; //[SerializeField] //protected Vector3 anchor; [SerializeField] [Range(-180, 180)] protected float directionAngleX = 0; [SerializeField] [Range(-180, 180)] protected float directionAngleY = 0; [SerializeField] protected PhysicsManagerWindData.DirectionType directionType; [SerializeField] protected BezierParam attenuation = new BezierParam(1f, 1f, false, 0.0f, false); //========================================================================================= /// /// 風データID /// protected int windId = -1; /// /// 実行状態 /// protected RuntimeStatus status = new RuntimeStatus(); internal RuntimeStatus Status { get { return status; } } //========================================================================================= protected virtual void Reset() { ResetParams(); } protected virtual void OnValidate() { //anchor = math.clamp(anchor, -1, 1); areaSize = math.max(areaSize, 0.1f); areaRadius = math.max(areaRadius, 0.1f); if (Application.isPlaying) status.SetDirty(); } // Animator/Animationによるプロパティ変更時コールバック void OnDidApplyAnimationProperties() { if (Application.isPlaying) { status.SetDirty(); } } protected virtual void Start() { Init(); } internal virtual void OnEnable() { status.SetEnable(true); status.UpdateStatus(); } internal virtual void OnDisable() { status.SetEnable(false); status.UpdateStatus(); } protected virtual void OnDestroy() { OnDispose(); status.SetDispose(); } protected virtual void Update() { if (status.IsInitSuccess) { var error = !VerifyData(); status.SetRuntimeError(error); status.UpdateStatus(); if (status.IsActive) OnUpdate(); } } //========================================================================================= /// /// 初期化 /// 通常はStart()で呼ぶ /// /// void Init() { status.UpdateStatusAction = OnUpdateStatus; status.OwnerFunc = () => this; if (status.IsInitComplete || status.IsInitStart) return; status.SetInitStart(); if (VerifyData() == false) { status.SetInitError(); return; } OnInit(); if (status.IsInitError) return; status.SetInitComplete(); status.UpdateStatus(); } // 実行状態の更新 protected void OnUpdateStatus() { if (status.IsActive) { // 実行状態に入った OnActive(); } else { // 実行状態から抜けた OnInactive(); } } /// /// 現在のデータが正常(実行できる状態)か返す /// /// internal virtual bool VerifyData() { return true; } //========================================================================================= /// /// 初期化 /// protected virtual void OnInit() { // 風作成 CreateWind(); // すでにアクティブならば有効化 if (Status.IsActive) EnableWind(); } /// /// 破棄 /// protected virtual void OnDispose() { if (MagicaPhysicsManager.IsInstance() == false) return; // 風を破棄する RemoveWind(); } /// /// 更新 /// protected virtual void OnUpdate() { // 内容変更に伴う再設定 if (status.IsDirty) { status.ClearDirty(); ChangeParameter(); } } /// /// 実行状態に入った場合に呼ばれます /// protected virtual void OnActive() { // 風有効化 EnableWind(); } /// /// 実行状態から抜けた場合に呼ばれます /// protected virtual void OnInactive() { // 風無効化 DisableWind(); } //========================================================================================= /// /// 風有効化 /// protected void EnableWind() { if (windId >= 0) MagicaPhysicsManager.Instance.Wind.SetEnable(windId, true, transform); } /// /// 風無効化 /// protected void DisableWind() { if (MagicaPhysicsManager.IsInstance() == false) return; if (windId >= 0) MagicaPhysicsManager.Instance.Wind.SetEnable(windId, false, transform); } //========================================================================================= /// /// 風削除 /// private void RemoveWind() { if (MagicaPhysicsManager.IsInstance()) { if (windId >= 0) { MagicaPhysicsManager.Instance.Wind.RemoveWind(windId); } } windId = -1; } /// /// 風作成 /// private void CreateWind() { windId = MagicaPhysicsManager.Instance.Wind.CreateWind( GetWindType(), GetShapeType(), GetAreaSize(), IsAddition(), main, turbulence, frequency, GetLocalDirection(), GetDirectionType(), GetAreaVolume(), GetAreaLength(), attenuation ); status.ClearDirty(); } /// /// 現在の風方向(ローカル) /// /// internal Vector3 GetLocalDirection() { var q = Quaternion.Euler(directionAngleX, directionAngleY, 0.0f); return q * Vector3.forward; //var rot = transform.rotation * q; //return rot * Vector3.forward; } /// /// 風パラメータの変更設定 /// private void ChangeParameter() { if (windId >= 0) { MagicaPhysicsManager.Instance.Wind.SetParameter( windId, GetAreaSize(), IsAddition(), main, turbulence, frequency, GetLocalDirection(), GetAreaVolume(), GetAreaLength(), attenuation ); } } //========================================================================================= /// /// 風タイプを返す /// /// public abstract PhysicsManagerWindData.WindType GetWindType(); /// /// 形状タイプを返す /// /// public abstract PhysicsManagerWindData.ShapeType GetShapeType(); /// /// 風向きタイプを返す /// /// public abstract PhysicsManagerWindData.DirectionType GetDirectionType(); /// /// 風が加算モードか返す /// /// public abstract bool IsAddition(); /// /// エリアサイズを返す /// /// public abstract Vector3 GetAreaSize(); /// /// アンカー位置を返す /// /// //public abstract Vector3 GetAnchor(); /// /// 風エリアの体積を返す /// /// public abstract float GetAreaVolume(); /// /// 風エリアの最大距離を返す /// /// public abstract float GetAreaLength(); /// /// パラメータ初期化 /// protected abstract void ResetParams(); } }