BITFALL/Assets/MagicaCloth2/Scripts/Core/Cloth/ClothProcessData.cs

400 lines
13 KiB
C#
Raw Normal View History

2024-03-18 18:20:23 +08:00
// Magica Cloth 2.
// Copyright (c) 2023 MagicaSoft.
// https://magicasoft.jp
using System;
using System.Collections.Generic;
using System.Threading;
using Unity.Collections;
using UnityEngine;
namespace MagicaCloth2
{
/// <summary>
/// MagicaClothコンポーネント処理のデータ部分
/// </summary>
public partial class ClothProcess : IDisposable, IValid, ITransform
{
public MagicaCloth cloth { get; internal set; }
/// <summary>
/// 状態フラグ(0 ~ 31)
/// </summary>
public const int State_Valid = 0;
public const int State_Enable = 1;
public const int State_ParameterDirty = 2;
public const int State_InitSuccess = 3;
public const int State_InitComplete = 4;
public const int State_Build = 5;
public const int State_Running = 6;
public const int State_DisableAutoBuild = 7;
public const int State_CullingInvisible = 8; // チームデータの同フラグのコピー
public const int State_CullingKeep = 9; // チームデータの同フラグのコピー
public const int State_SkipWriting = 10; // 書き込み停止(ストップモーション用)
public const int State_SkipWritingDirty = 11; // 書き込み停止フラグ更新サイン
public const int State_UsePreBuild = 12; // PreBuildを利用
/// <summary>
/// 現在の状態
/// </summary>
internal BitField32 stateFlag;
/// <summary>
/// 初期クロスコンポーネントトランスフォーム状態
/// </summary>
internal TransformRecord clothTransformRecord { get; private set; } = null;
/// <summary>
/// レンダー情報へのハンドル
/// (レンダラーのセットアップデータ)
/// </summary>
List<int> renderHandleList = new List<int>();
/// <summary>
/// BoneClothのセットアップデータ
/// </summary>
internal RenderSetupData boneClothSetupData;
/// <summary>
/// レンダーメッシュの管理
/// </summary>
public class RenderMeshInfo
{
public int renderHandle;
public VirtualMeshContainer renderMeshContainer;
public DataChunk mappingChunk;
}
internal List<RenderMeshInfo> renderMeshInfoList = new List<RenderMeshInfo>();
/// <summary>
/// カスタムスキニングのボーン情報
/// </summary>
internal List<TransformRecord> customSkinningBoneRecords = new List<TransformRecord>();
/// <summary>
/// 法線調整用のトランスフォーム状態
/// </summary>
internal TransformRecord normalAdjustmentTransformRecord { get; private set; } = null;
//=========================================================================================
/// <summary>
/// ペイントマップ情報
/// </summary>
public class PaintMapData
{
public const byte ReadFlag_Fixed = 0x01;
public const byte ReadFlag_Move = 0x02;
public const byte ReadFlag_Limit = 0x04;
public Color32[] paintData;
public int paintMapWidth;
public int paintMapHeight;
public ExBitFlag8 paintReadFlag;
}
//=========================================================================================
/// <summary>
/// 処理結果
/// </summary>
internal ResultCode result;
public ResultCode Result => result;
/// <summary>
/// Cloth Type
/// </summary>
public enum ClothType
{
MeshCloth = 0,
BoneCloth = 1,
BoneSpring = 10,
}
internal ClothType clothType { get; private set; }
/// <summary>
/// リダクション設定(外部から設定する)
/// </summary>
ReductionSettings reductionSettings;
/// <summary>
/// シミュレーションパラメータ
/// </summary>
public ClothParameters parameters { get; private set; }
/// <summary>
/// プロキシメッシュ
/// </summary>
public VirtualMeshContainer ProxyMeshContainer { get; private set; } = null;
/// <summary>
/// コライダーリスト
/// コライダーが格納されるインデックスは他のデータのインデックスと一致している
/// </summary>
internal List<ColliderComponent> colliderList = new List<ColliderComponent>();
/// <summary>
/// コライダー配列数
/// </summary>
internal int ColliderCapacity => colliderList.Count;
//=========================================================================================
/// <summary>
/// チームID
/// </summary>
public int TeamId { get; private set; } = 0;
/// <summary>
/// 慣性制約データ
/// </summary>
internal InertiaConstraint.ConstraintData inertiaConstraintData;
/// <summary>
/// 距離制約データ
/// </summary>
internal DistanceConstraint.ConstraintData distanceConstraintData;
/// <summary>
/// 曲げ制約データ
/// </summary>
internal TriangleBendingConstraint.ConstraintData bendingConstraintData;
//=========================================================================================
/// <summary>
/// カリング用対象アニメーター
/// </summary>
internal Animator cullingAnimator = null;
/// <summary>
/// カリング用アニメーター配下のレンダラーリスト
/// </summary>
internal List<Renderer> cullingAnimatorRenderers = new List<Renderer>();
//=========================================================================================
/// <summary>
/// キャンセルトークン
/// </summary>
CancellationTokenSource cts = new CancellationTokenSource();
volatile object lockObject = new object();
volatile object lockState = new object();
/// <summary>
/// 初期化待機カウンター
/// </summary>
volatile int suspendCounter = 0;
/// <summary>
/// 破棄フラグ
/// </summary>
volatile bool isDestory = false;
/// <summary>
/// 内部データまで完全に破棄されたかどうか
/// </summary>
volatile bool isDestoryInternal = false;
/// <summary>
/// 構築中フラグ
/// </summary>
volatile bool isBuild = false;
public BitField32 GetStateFlag()
{
lock (lockState)
{
// copy
var state = stateFlag;
return state;
}
}
public bool IsState(int state)
{
lock (lockState)
{
return stateFlag.IsSet(state);
}
}
public void SetState(int state, bool sw)
{
lock (lockState)
{
stateFlag.SetBits(state, sw);
}
}
public bool IsValid() => IsState(State_Valid);
public bool IsCullingInvisible() => IsState(State_CullingInvisible);
public bool IsCullingKeep() => IsState(State_CullingKeep);
public bool IsSkipWriting() => IsState(State_SkipWriting);
public bool IsEnable
{
get
{
if (IsValid() == false || TeamId == 0)
return false;
return MagicaManager.Team.IsEnable(TeamId);
}
}
public bool HasProxyMesh
{
get
{
if (IsValid() == false || TeamId == 0)
return false;
return ProxyMeshContainer?.shareVirtualMesh?.IsSuccess ?? false;
}
}
public string Name => cloth != null ? cloth.name : "(none)";
//=========================================================================================
public ClothProcess()
{
// 初期状態
result = ResultCode.Empty;
}
public void Dispose()
{
lock (lockObject)
{
isDestory = true;
SetState(State_Valid, false);
result.Clear();
cts.Cancel();
}
DisposeInternal();
//Debug.Log($"ClothProcessData.Dispose()!");
}
void DisposeInternal()
{
lock (lockObject)
{
// すでに破棄完了ならば不要
if (isDestoryInternal)
return;
// ビルド中は破棄を保留する
if (isBuild)
return;
// マネージャから削除
MagicaManager.Simulation?.ExitProxyMesh(this);
MagicaManager.VMesh?.ExitProxyMesh(TeamId); // マッピングメッシュも解放される
MagicaManager.Collider?.Exit(this);
MagicaManager.Cloth?.RemoveCloth(this);
// レンダーメッシュの破棄
foreach (var info in renderMeshInfoList)
{
if (info == null)
continue;
// 仮想メッシュ破棄
info.renderMeshContainer?.Dispose();
}
renderMeshInfoList.Clear();
renderMeshInfoList = null;
// レンダーデータの利用終了
foreach (int renderHandle in renderHandleList)
{
MagicaManager.Render?.RemoveRenderer(renderHandle);
}
renderHandleList.Clear();
renderHandleList = null;
// BoneClothセットアップデータ
boneClothSetupData?.Dispose();
boneClothSetupData = null;
// プロキシメッシュ破棄
ProxyMeshContainer?.Dispose();
ProxyMeshContainer = null;
colliderList.Clear();
cullingAnimator = null;
cullingAnimatorRenderers.Clear();
// PreBuildデータ解除
MagicaManager.PreBuild?.UnregisterPreBuildData(cloth?.GetSerializeData2()?.preBuildData.GetSharePreBuildData());
// 完全破棄フラグ
isDestoryInternal = true;
}
Develop.DebugLog($"Cloth dispose internal.");
// 破棄監視リストから削除する
MagicaManager.Team.RemoveMonitoringProcess(this);
}
internal void IncrementSuspendCounter()
{
lock (lockObject)
{
suspendCounter++;
}
}
internal void DecrementSuspendCounter()
{
lock (lockObject)
{
suspendCounter--;
}
}
internal int GetSuspendCounter()
{
return suspendCounter;
}
public RenderMeshInfo GetRenderMeshInfo(int index)
{
if (index >= 0 && index < renderMeshInfoList.Count)
return renderMeshInfoList[index];
else
return null;
}
internal void SyncParameters()
{
parameters = cloth.SerializeData.GetClothParameters();
}
public void GetUsedTransform(HashSet<Transform> transformSet)
{
cloth.SerializeData.GetUsedTransform(transformSet);
cloth.serializeData2.GetUsedTransform(transformSet);
clothTransformRecord?.GetUsedTransform(transformSet);
boneClothSetupData?.GetUsedTransform(transformSet);
renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).GetUsedTransform(transformSet));
customSkinningBoneRecords.ForEach(rd => rd.GetUsedTransform(transformSet));
normalAdjustmentTransformRecord?.GetUsedTransform(transformSet);
}
public void ReplaceTransform(Dictionary<int, Transform> replaceDict)
{
cloth.SerializeData.ReplaceTransform(replaceDict);
cloth.serializeData2.ReplaceTransform(replaceDict);
clothTransformRecord?.ReplaceTransform(replaceDict);
boneClothSetupData?.ReplaceTransform(replaceDict);
renderHandleList.ForEach(handle => MagicaManager.Render.GetRendererData(handle).ReplaceTransform(replaceDict));
customSkinningBoneRecords.ForEach(rd => rd.ReplaceTransform(replaceDict));
normalAdjustmentTransformRecord?.ReplaceTransform(replaceDict);
}
internal void SetSkipWriting(bool sw)
{
// ここではフラグのみ更新する
// 実際の更新はチームのAlwaysTeamUpdate()で行われる
SetState(State_SkipWriting, sw);
SetState(State_SkipWritingDirty, true);
}
}
}