// Magica Cloth. // Copyright (c) MagicaSoft, 2020-2022. // https://magicasoft.jp using System.Collections.Generic; using Unity.Mathematics; using UnityEngine; namespace MagicaCloth { /// /// パーティクルゲームオブジェクト基底クラス /// オブジェクトは複数のチームから利用される可能性があり、その場合はチームごとにパーティクルを生成する /// public abstract class ParticleComponent : BaseComponent, IDataHash { /// /// パーティクルID /// チームごと(自身は0) /// protected Dictionary particleDict = new Dictionary(); /// /// 実行状態 /// protected RuntimeStatus status = new RuntimeStatus(); public RuntimeStatus Status { get { return status; } } //========================================================================================= /// /// データを識別するハッシュコードを作成して返す /// /// public abstract int GetDataHash(); //========================================================================================= public int CenterParticleIndex { get { if (particleDict.ContainsKey(0)) return particleDict[0].startIndex; return -1; } } //========================================================================================= protected virtual void Start() { Init(); } public virtual void OnEnable() { status.SetEnable(true); status.UpdateStatus(); } public virtual void OnDisable() { status.SetEnable(false); status.UpdateStatus(); } protected virtual void OnDestroy() { OnDispose(); status.SetDispose(); } // 基本的にVerifyData()は常にtrueなので更新の必要なし //protected virtual void Update() //{ // if (status.IsInitSuccess) // { // var error = !VerifyData(); // status.SetRuntimeError(error); // 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(); } } /// /// 現在のデータが正常(実行できる状態)か返す /// /// public virtual bool VerifyData() { return true; } //========================================================================================= /// /// 初期化 /// protected virtual void OnInit() { } /// /// 破棄 /// protected virtual void OnDispose() { if (MagicaPhysicsManager.IsInstance() == false) return; // パーティクルを破棄する RemoveParticle(); } /// /// 更新 /// protected virtual void OnUpdate() { } /// /// 実行状態に入った場合に呼ばれます /// protected virtual void OnActive() { // パーティクル有効化 EnableParticle(); } /// /// 実行状態から抜けた場合に呼ばれます /// protected virtual void OnInactive() { // パーティクル無効化 DisableParticle(); } //========================================================================================= /// /// パーティクル有効化 /// protected void EnableParticle() { foreach (var teamId in particleDict.Keys) { EnableTeamParticle(teamId); } } /// /// パーティクル無効化 /// protected void DisableParticle() { if (MagicaPhysicsManager.IsInstance()) { foreach (var teamId in particleDict.Keys) { DisableTeamParticle(teamId); } } } /// /// チームパーティクル有効化 /// /// protected void EnableTeamParticle(int teamId) { var c = particleDict[teamId]; MagicaPhysicsManager.Instance.Particle.SetEnable( c, true, UserTransform, UserTransformLocalPosition, UserTransformLocalRotation ); } /// /// チームパーティクル無効化 /// /// protected void DisableTeamParticle(int teamId) { var c = particleDict[teamId]; MagicaPhysicsManager.Instance.Particle.SetEnable( c, false, UserTransform, UserTransformLocalPosition, UserTransformLocalRotation ); } /// /// パーティクルのデータ更新を予約する /// protected void ReserveDataUpdate() { if (MagicaPhysicsManager.IsInstance()) MagicaPhysicsManager.Instance.Component.ReserveDataUpdateParticleComponent(this); } /// /// パーティクルのデータ更新処理 /// internal virtual void DataUpdate() { } /// /// 状態の更新 /// internal void UpdateStatus() { status.UpdateStatus(); } //========================================================================================= /// /// 指定チームのパーティクルを1つ作成 /// /// /// /// /// /// /// /// /// protected ChunkData CreateParticle( uint flag, int teamId, float depth, float3 radius, float3 localPos ) { // すでに登録済みならば無効(v1.9.3) if (particleDict.ContainsKey(teamId)) { return new ChunkData(); } // 自動追加フラグ if (MagicaPhysicsManager.Instance.Team.IsFlag(teamId, PhysicsManagerTeamData.Flag_UpdatePhysics)) flag |= PhysicsManagerParticleData.Flag_Transform_UnityPhysics; var t = transform; var c = MagicaPhysicsManager.Instance.Particle.CreateParticle( flag, teamId, t.position, t.rotation, depth, radius, localPos ); particleDict.Add(teamId, c); // 初期状態はDisable DisableTeamParticle(teamId); return c; } /// /// 指定チームのパーティクルを削除 /// /// protected void RemoveTeamParticle(int teamId) { if (MagicaPhysicsManager.IsInstance()) { // パーティクル無効化 DisableTeamParticle(teamId); // パーティクル削除 var c = particleDict[teamId]; MagicaPhysicsManager.Instance.Particle.RemoveParticle(c); particleDict.Remove(teamId); } } /// /// パーティクル削除 /// protected void RemoveParticle() { if (MagicaPhysicsManager.IsInstance()) { foreach (var teamId in particleDict.Keys) { RemoveTeamParticle(teamId); } } particleDict.Clear(); } /// /// 頂点ごとの連動トランスフォーム設定(不要な場合はnull) /// /// /// protected Transform UserTransform(int vindex) { return transform; } /// /// 頂点ごとの連動トランスフォームのLocalPositionを返す(不要な場合は0) /// /// /// protected float3 UserTransformLocalPosition(int vindex) { return transform.localPosition; } /// /// 頂点ごとの連動トランスフォームのLocalRotationを返す(不要な場合はquaternion.identity) /// /// /// protected quaternion UserTransformLocalRotation(int vindex) { return transform.localRotation; } } }