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

289 lines
10 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 UnityEngine;
namespace MagicaCloth2
{
public partial class MagicaCloth
{
/// <summary>
/// シリアライズデータ2の取得
/// SerializeData2クラスはシステムが利用するパラメータクラスです。
/// そのためユーザーによる変更は推奨されていません。
///
/// Acquisition of SerializedData2.
/// The SerializeData2 class is a parameter class used by the system.
/// Therefore, user modification is not recommended.
/// </summary>
/// <returns></returns>
public ClothSerializeData2 GetSerializeData2()
{
return serializeData2;
}
/// <summary>
/// クロスデータ構築完了後イベント
/// Event after completion of cloth data construction.
/// (true = Success, false = Failure)
/// </summary>
public Action<bool> OnBuildComplete;
/// <summary>
/// 初期化を実行します
/// すでに初期化済みの場合は何もしません。
/// perform initialization.
/// If already initialized, do nothing.
/// </summary>
public void Initialize()
{
if (Application.isPlaying == false)
return;
Process.Init();
}
/// <summary>
/// コンポーネントのStart()で実行される自動ビルドを無効にします
/// Disable automatic builds that run on the component's Start().
/// </summary>
public void DisableAutoBuild()
{
if (Application.isPlaying == false)
return;
Process.SetState(ClothProcess.State_DisableAutoBuild, true);
}
/// <summary>
/// コンポーネントを構築し実行します
/// すべてのデータをセットアップしたあとに呼び出す必要があります
/// build and run the component.
/// Must be called after setting up all data.
/// </summary>
/// <returns>true=start build. false=build failed.</returns>
public bool BuildAndRun()
{
bool ret = false;
bool buildComplate = true;
try
{
if (Application.isPlaying == false)
throw new MagicaClothProcessingException();
DisableAutoBuild();
if (Process.IsState(ClothProcess.State_Build))
{
Develop.LogError($"Already built.:{this.name}");
throw new MagicaClothProcessingException();
}
// initialize generated data.
if (Process.GenerateInitialization() == false)
throw new MagicaClothProcessingException();
// check Pre-Build
bool usePreBuildData = serializeData2.preBuildData.UsePreBuild();
if (usePreBuildData == false)
{
// Runtime Build.
// setting by type.
switch (serializeData.clothType)
{
case ClothProcess.ClothType.BoneCloth:
case ClothProcess.ClothType.BoneSpring:
// BoneCloth用のセレクションデータの作成
// ただしセレクションデータが存在し、かつユーザー定義されている場合は作成しない
var nowSelection = serializeData2.selectionData;
if (nowSelection == null || nowSelection.IsValid() == false || nowSelection.IsUserEdit() == false)
{
if (Process.GenerateBoneClothSelection() == false)
throw new MagicaClothProcessingException();
}
break;
}
// build and run.
ret = Process.StartRuntimeBuild();
if (ret)
buildComplate = false; // OnBuildCompleteはランタイム構築後に呼ばれる
}
else
{
// pre-build
ret = Process.PreBuildDataConstruction();
}
}
catch (MagicaClothProcessingException)
{
}
catch (Exception exception)
{
Debug.LogException(exception);
}
finally
{
// ビルド完了イベント
if (buildComplate)
OnBuildComplete?.Invoke(ret);
}
return ret;
}
/// <summary>
/// コンポーネントが保持するトランスフォームを置換します。
/// 置換先のトランスフォーム名をキーとした辞書を渡します。
/// Replaces a component's transform.
/// Passes a dictionary keyed by the name of the transform to be replaced.
/// </summary>
/// <param name="targetTransformDict">Dictionary keyed by the name of the transform to be replaced.</param>
public void ReplaceTransform(Dictionary<string, Transform> targetTransformDict)
{
// コンポーネントが利用しているすべてのTransformを取得します
var useTransformSet = new HashSet<Transform>();
Process.GetUsedTransform(useTransformSet);
// 置換処理用の辞書を作成
// key:置換対象トランスフォームのインスタンスID
// value:入れ替えるトランスフォーム
var replaceDict = new Dictionary<int, Transform>();
foreach (var t in useTransformSet)
{
if (targetTransformDict.ContainsKey(t.name))
{
replaceDict.Add(t.GetInstanceID(), targetTransformDict[t.name]);
}
}
// 置換する
Process.ReplaceTransform(replaceDict);
}
/// <summary>
/// パラメータの変更を通知
/// 実行中にパラメータを変更した場合はこの関数を呼ぶ必要があります
/// You should call this function if you changed parameters during execution.
/// </summary>
public void SetParameterChange()
{
if (IsValid())
{
Process.DataUpdate();
}
}
/// <summary>
/// タイムスケールを変更します
/// Change the time scale.
/// </summary>
/// <param name="timeScale">0.0-1.0</param>
public void SetTimeScale(float timeScale)
{
if (IsValid())
{
ref var tdata = ref MagicaManager.Team.GetTeamDataRef(Process.TeamId);
tdata.timeScale = Mathf.Clamp01(timeScale);
}
}
/// <summary>
/// タイムスケールを取得します
/// Get the time scale.
/// </summary>
/// <returns></returns>
public float GetTimeScale()
{
if (IsValid())
{
ref var tdata = ref MagicaManager.Team.GetTeamDataRef(Process.TeamId);
return tdata.timeScale;
}
else
return 1.0f;
}
/// <summary>
/// シミュレーションを初期状態にリセットします
/// Reset the simulation to its initial state.
/// </summary>
/// <param name="keepPose">If true, resume while maintaining posture.</param>
public void ResetCloth(bool keepPose = false)
{
if (IsValid())
{
ref var tdata = ref MagicaManager.Team.GetTeamDataRef(Process.TeamId);
if (keepPose)
{
// Keep
tdata.flag.SetBits(TeamManager.Flag_KeepTeleport, true);
}
else
{
// Reset
tdata.flag.SetBits(TeamManager.Flag_Reset, true);
tdata.flag.SetBits(TeamManager.Flag_TimeReset, true);
tdata.flag.SetBits(TeamManager.Flag_CullingKeep, false);
Process.SetState(ClothProcess.State_CullingKeep, false);
Process.UpdateRendererUse();
}
}
}
/// <summary>
/// 慣性の中心座標を取得します
/// Get the center of inertia position.
/// </summary>
/// <returns></returns>
public Vector3 GetCenterPosition()
{
if (IsValid())
{
ref var cdata = ref MagicaManager.Team.GetCenterDataRef(Process.TeamId);
return ClothTransform.TransformPoint(cdata.frameLocalPosition);
}
else
return Vector3.zero;
}
/// <summary>
/// 外力を加えます
/// Add external force.
/// </summary>
/// <param name="forceDirection"></param>
/// <param name="forceVelocity">(m/s)</param>
/// <param name="fmode"></param>
public void AddForce(Vector3 forceDirection, float forceVelocity, ClothForceMode fmode = ClothForceMode.VelocityAdd)
{
if (IsValid() && forceDirection.magnitude > 0.0f && forceVelocity > 0.0f && fmode != ClothForceMode.None)
{
ref var tdata = ref MagicaManager.Team.GetTeamDataRef(Process.TeamId);
tdata.forceMode = fmode;
tdata.impactForce = forceDirection.normalized * forceVelocity;
}
}
/// <summary>
/// TransformおよびMeshへの書き込みを禁止または許可します
/// この機能を使うことでストップモーションを実装することが可能です
/// Prevent or allow writing to Transform and Mesh.
/// By using this function, it is possible to implement stop motion.
/// </summary>
/// <param name="sw">true=write disabled, false=write enabled</param>
public void SetSkipWriting(bool sw)
{
if (IsValid())
{
Process.SetSkipWriting(sw);
}
}
}
}