// Magica Cloth.
// Copyright (c) MagicaSoft, 2020-2022.
// https://magicasoft.jp
using System.Collections.Generic;
namespace MagicaCloth
{
///
/// コンテンツの実行状態を管理する
///
public class RuntimeStatus
{
// 以下は現在の状態フラグ
///
/// 初期化処理が開始したかどうか
///
bool initStart;
///
/// 初期化が完了するとtrueになる(エラーの有無は問わない)
///
bool init;
///
/// 初期化エラーが発生するとtrueになる
///
bool initError;
///
/// コンテンツの有効状態の切り替え
///
bool enable;
///
/// ユーザー操作によるコンテンツの有効状態の切り替え(v1.2)
///
bool userEnable = true;
///
/// 実行中にエラーが発生した場合にtrueになる
///
bool runtimeError;
///
/// コンテンツが破棄された場合にtrueとなる
///
bool dispose;
///
/// コンテンツの現在の稼働状態
///
bool isActive;
///
/// コンテンツの内容に変更が発生した
///
bool isDirty;
///
/// 連動(親)ステータス
/// 設定されている場合、こららのステータスがすべて停止中ならば自身も停止する
///
internal HashSet parentStatusSet { get; private set; } = new HashSet();
///
/// 連動(子)ステータス
/// 設定されている場合、自身のアクティブ変更時に子のすべてのUpdateStatus()を呼び出す
///
internal HashSet childStatusSet { get; private set; } = new HashSet();
//=========================================================================================
///
/// アクティブ変更時コールバック
///
internal System.Action UpdateStatusAction;
///
/// 連動がすべて切断された時のコールバッグ
///
internal System.Action DisconnectedAction;
///
/// この状態管理のオーナークラス
///
internal System.Func OwnerFunc;
//=========================================================================================
///
/// 現在稼働中か判定する
///
public bool IsActive
{
get
{
return isActive && !dispose;
}
}
///
/// 初期化が開始されたか判定する
///
///
public bool IsInitStart
{
get
{
return initStart;
}
}
///
/// 初期化済みか判定する(エラーの有無は問わない)
///
public bool IsInitComplete
{
get
{
return init;
}
}
///
/// 初期化が成功しているか判定する
///
public bool IsInitSuccess
{
get
{
return init && !initError;
}
}
///
/// 初期化が失敗しているか判定する
///
public bool IsInitError
{
get
{
return init && initError;
}
}
///
/// 破棄済みか判定する
///
public bool IsDispose
{
get
{
return dispose;
}
}
///
/// 内容に変更が発生したか判定する
///
public bool IsDirty => isDirty;
///
/// 初期化の開始フラグを立てる
///
public void SetInitStart()
{
initStart = true;
}
///
/// 初期化済みフラグを立てる
///
public void SetInitComplete()
{
init = true;
}
///
/// 初期化エラーフラグを立てる
///
public void SetInitError()
{
initError = true;
}
///
/// 有効フラグを設定する
///
///
/// フラグに変更があった場合はtrueが返る
public bool SetEnable(bool sw)
{
bool ret = enable != sw;
enable = sw;
return ret;
}
///
/// ユーザー操作による有効フラグを設定する
///
///
/// フラグに変更があった場合はtrueが返る
public bool SetUserEnable(bool sw)
{
bool ret = userEnable != sw;
userEnable = sw;
return ret;
}
///
/// ランタイムエラーフラグを設定する
///
///
/// フラグに変更があった場合はtrueが返る
public bool SetRuntimeError(bool sw)
{
bool ret = runtimeError != sw;
runtimeError = sw;
return ret;
}
///
/// 破棄フラグを立てる
///
///
public void SetDispose()
{
dispose = true;
}
///
/// 変更フラグを立てる
///
public void SetDirty()
{
isDirty = true;
}
///
/// 変更フラグをクリアする
///
public void ClearDirty()
{
isDirty = false;
}
///
/// 現在のアクティブ状態を更新する
///
/// アクティブ状態に変更があった場合はtrueが返る
public bool UpdateStatus()
{
if (dispose)
return false;
// 初期化済み、有効状態、エラー状態、連動(親)ステータス状態、がすべてクリアならばアクティブ状態と判定
var active = init && !initError && enable && userEnable && !runtimeError && IsParentStatusActive();
// およびマネージャのアクティブ状態を判定
if (MagicaPhysicsManager.IsInstance())
active = active && MagicaPhysicsManager.Instance.IsActive;
if (active != isActive)
{
isActive = active;
// コールバック
UpdateStatusAction?.Invoke();
// すべての連動(子)ステータスの更新を呼び出す
foreach (var status in childStatusSet)
{
status?.UpdateStatus();
}
return true;
}
else
return false;
}
//=========================================================================================
///
/// 連動(親)ステータスを追加する
///
///
public void AddParentStatus(RuntimeStatus status)
{
parentStatusSet.Add(status);
}
///
/// 連動(親)ステータスを削除する
///
///
public void RemoveParentStatus(RuntimeStatus status)
{
parentStatusSet.Remove(status);
parentStatusSet.Remove(null);
// 連動切断アクション
if (parentStatusSet.Count == 0 && childStatusSet.Count == 0)
DisconnectedAction?.Invoke();
}
///
/// 連動(子)ステータスを追加する
///
///
public void AddChildStatus(RuntimeStatus status)
{
childStatusSet.Add(status);
}
///
/// 連動(子)ステータスを削除する
///
///
public void RemoveChildStatus(RuntimeStatus status)
{
childStatusSet.Remove(status);
childStatusSet.Remove(null);
// 連動切断アクション
if (parentStatusSet.Count == 0 && childStatusSet.Count == 0)
DisconnectedAction?.Invoke();
}
///
/// 親スタータスと連動する
///
///
public void LinkParentStatus(RuntimeStatus parent)
{
AddParentStatus(parent);
parent.AddChildStatus(this);
}
///
/// 親ステータスとの連動を解除する
///
///
public void UnlinkParentStatus(RuntimeStatus parent)
{
RemoveParentStatus(parent);
parent.RemoveChildStatus(this);
}
///
/// 連動(親)ステータスが1つでも稼働状態か調べる
/// 連動ステータスが無い場合は稼働状態として返す
///
///
bool IsParentStatusActive()
{
if (parentStatusSet.Count == 0)
return true;
foreach (var status in parentStatusSet)
{
if (status != null && status.IsActive)
return true;
}
return false;
}
}
}