Files
test/Assets/ModelRenderer/Scripts/A3DModelReader/Common/A3DCombinedAction.cs
T
2026-04-16 15:30:52 +07:00

444 lines
20 KiB
C#
Executable File

using System.Collections.Generic;
using System.IO;
//using ModelViewer.Scene.SceneObject;
namespace ModelViewer.Common
{
public static class A3DCombinedActionConst
{
public static int EVENT_TYPE_NONE = -1;
public static int EVENT_TYPE_BASE = 100;
public static int EVENT_TYPE_GFX = EVENT_TYPE_BASE + 0;
public static int EVENT_TYPE_SFX = EVENT_TYPE_BASE + 1;
public static int EVENT_TYPE_CHLDACT = EVENT_TYPE_BASE + 2;
public static int EVENT_TYPE_MATCHG = EVENT_TYPE_BASE + 3;
public static int EVENT_TYPE_ATT_PT = EVENT_TYPE_BASE + 4;
public static int EVENT_TYPE_SCRIPT = EVENT_TYPE_BASE + 5;
public static int EVENT_TYPE_CAM_PT = EVENT_TYPE_BASE + 6;
public static int EVENT_TYPE_MODELSCLCHG = EVENT_TYPE_BASE + 7;
public static int EVENT_TYPE_MATTRANS = EVENT_TYPE_BASE + 8;
public static int EVENT_TYPE_AUDIOEVENT = EVENT_TYPE_BASE + 9;
// when add new type, change this definition
public static int EVENT_TYPE_END = EVENT_TYPE_AUDIOEVENT;
public static string _format_cact_name = "CombineActName: ";
public static string _format_act_count = "BaseActCount: ";
public static string _format_act_name = "BaseActName: ";
public static string _format_act_start_time = "ActStartTime: ";
public static string _format_act_LoopCount = "LoopCount: ";
public static string _format_act_LoopMinNum = "LoopMinNum: ";
public static string _format_act_LoopMaxNum = "LoopMaxNum: ";
public static string _format_start_time = "StartTime: ";
public static string _format_time_span = "TimeSpan: ";
public static string _format_rank_count = "RankCount: ";
public static string _format_rank = "Channel: "; // "Channel: %d, Rank: %d"
public static string _format_event_channel = "EventChannel: ";
public static string _format_play_speed = "PlaySpeed: ";
public static string _format_stopchildact = "StopChildAct: ";
public static string _format_resetmtlonstop = "ResetMtl: ";
public static string _format_once = "Once: ";
public static string _format_fx_count = "FxCount: ";
public static string _format_fx_type = "FxType: ";
public static string _format_fx_start_time = "FxStartTime: ";
public static string _format_fx_path_num = "FxFileNum: ";
public static string _format_fx_path = "FxFilePath: ";
public static string _format_hook_name = "HookName: ";
public static string _format_hook_offset = "HookOffset: ";
public static string _format_hook_yaw = "HookYaw: ";
public static string _format_hook_pitch = "HookPitch: ";
public static string _format_hook_rot = "HookRot: ";
public static string _format_bind_parent = "BindParent: ";
public static string _format_fadeout = "FadeOut: ";
public static string _format_model_alpha = "UseModelAlpha: ";
public static string _format_custom_path = "CustomPath: ";
public static string _format_atk_path = "AtkPath: ";
public static string _format_divisions = "Divisions: ";
public static string _format_atk_usedelay = "AtkUseDelay: ";
public static string _format_atk_delaycount = "AtkDelayNum: ";
public static string _format_atk_delaytime = "AtkDelayTime: ";
public static string _format_atk_orientation = "AtkOrient: ";
public static string _format_custom_data = "CustomData: ";
public static string _format_gfx_scale = "GfxScale: ";
public static string _format_gfx_alpha = "GfxAlpha: ";
public static string _format_gfx_play_speed = "GfxSpeed: ";
public static string _format_gfx_outer_path = "GfxOuterPath: ";
public static string _format_gfx_rel_ecm = "GfxRelToECM: ";
public static string _format_gfx_param_count = "GfxParamCount: ";
public static string _format_gfx_delay_time = "GfxDelayTime: ";
public static string _format_gfx_rot_with_model = "GfxRotWithModel: ";
public static string _format_param_ele_name = "ParamEleName: ";
public static string _format_param_id = "ParamId: ";
public static string _format_param_type = "ParamDataType: ";
public static string _format_param_is_cmd = "ParamDataIsCmd: ";
public static string _format_param_cmd = "ParamDataCmd: ";
public static string _format_param_pos = "ParamDataPos: ";
public static string _format_param_hook = "ParamDataHook: ";
public static string _format_child_act_count = "ChildActCount: ";
public static string _format_child_act_name = "ChildActName: ";
public static string _format_chld_hhname = "HHName: ";
public static string _format_transtime = "TransTime: ";
public static string _format_chld_istrail = "IsTrail: ";
public static string _format_chld_span = "TrailSpan: ";
public static string _format_chld_segs = "Segs: ";
public static string _format_pos = "Pos: ";
public static string _format_dir = "Dir: ";
public static string _format_matchg = "ColorValue: ";
public static string _format_apply_child = "ApplyChild: ";
public static string _format_mst_orgcol = "OrgColor: ";
public static string _format_mst_destnum = "DestNum: ";
public static string _format_mst_destcol = "Col: ";
public static string _format_mst_desttime = "Time: ";
public static string _format_event_type = "EventType: ";
public static string _format_event_count = "EventCount: ";
public static string _format_script_lines = "ScriptLines: ";
public static string _format_script_cfg_state = "ScriptCfgState: ";
public static string _format_script_usage = "ScriptUsage: ";
public static string _format_cam_dist2host = "Dist2Host: ";
public static string _format_cam_yaw2host = "Yaw2Host: ";
public static string _format_cam_pitch = "Pitch: ";
public static string _format_cam_yawacc = "YawAcc: ";
public static string _format_cam_pitchacc = "PitchAcc: ";
public static string _format_cam_angleacc = "AngleAcc: ";
public static string _format_cam_linearacc = "LinearAcc: ";
public static string _format_cam_isinterp = "IsInterp: ";
public static string _format_cam_beziernum = "BezierNum: ";
public static string _format_cam_beziervert = "";
public static string _format_audioevent = "AudioEvent: ";
public static string _format_audiomindist = "MinDist: ";
public static string _format_audiomaxdist = "MaxDist: ";
public static string _format_audiousecustom = "Custom: ";
public static string _format_audiovolume = "Volume: ";
public static int _trail_delta = 3;
}
[System.Serializable]
public class ACTION_INFO
{
public string m_strName;
public uint m_dwStartTime;
public uint m_dwEndTime;
public uint m_dwSpan;
public int m_nMinLoops;
public int m_nMaxLoops;
public bool Load(FileStream fileStream, StreamReader file, uint dwVersion)
{
bool isBinary = fileStream != null;
if (isBinary)
{
}
else
{
string szLine = string.Empty;
string tagValue;
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_act_name, out tagValue);
m_strName = tagValue;
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_act_start_time, out tagValue);
uint.TryParse(tagValue, out m_dwStartTime);
if (dwVersion < 6)
{
szLine = file.ReadLine();
}
else if (dwVersion >= 9 && dwVersion < 36)
{
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_act_LoopCount, out tagValue);
int nLoops;
int.TryParse(tagValue, out nLoops);
m_nMinLoops = m_nMaxLoops = nLoops;
}
else if (dwVersion >= 36)
{
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_act_LoopMinNum, out tagValue);
int.TryParse(tagValue, out m_nMinLoops);
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_act_LoopMaxNum, out tagValue);
int.TryParse(tagValue, out m_nMaxLoops);
}
}
return true;
}
}
[System.Serializable]
public class EVENT_INFO
{
public int m_nType;
public uint m_dwStartTime;
public uint m_dwTimeSpan;
public bool m_bOnce;
public A3DCombinedAction m_pAct;
public static EVENT_INFO LoadFromFile(A3DCombinedAction pAct, AFile pFile, StreamReader pTextFile, uint dwVersion)
{
string szLine = string.Empty;
string tagValue;
long dwReadLen;
int nType = A3DCombinedActionConst.EVENT_TYPE_NONE;
if (pFile != null)
{
// pFile->Read(&nType, sizeof(nType), &dwReadLen);
}
else
{
// pFile->ReadLine(szLine, AFILE_LINEMAXLEN, &dwReadLen);
// sscanf(szLine, _format_event_type, &nType);
tagValue = pTextFile.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_event_type,out tagValue);
nType = int.TryParse(tagValue, out nType) ? nType : A3DCombinedActionConst.EVENT_TYPE_NONE;
}
EVENT_INFO pEvent = new();
// if (!pEvent) return NULL;
//
// if (dwVersion >= 18 && !pEvent->LoadEventBase(pFile, dwVersion)
// || !pEvent->Load(pFile, dwVersion))
// {
// delete pEvent;
// return NULL;
// }
return pEvent;
}
}
[System.Serializable]
public class FX_BASE_INFO : EVENT_INFO
{
//public RandStringContainer[] m_pFiles;
public string m_strHookName;
//public A3DVECTOR3 m_vOffset;
public float m_fYaw;
public float m_fPitch;
public float m_fRot;
public bool m_bBindParent;
public bool m_bModelAlpha;
public bool m_bCustomFilePath;
public bool m_bUseECMHook;
public A3DMATRIX4 m_matTran;
public uint m_dwFadeOutTime;
public int m_nCustomData;
public static FX_BASE_INFO LoadFromFile(A3DCombinedAction pAct, FileStream fileStream, StreamReader file, uint dwVersion)
{
bool isBinary = fileStream != null;
if (isBinary)
{
}
else
{
string szLine = string.Empty;
string tagValue;
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_fx_type, out tagValue);
int nType = int.TryParse(tagValue, out nType) ? nType : 0;
}
// TODO: There are 3 types: GFX_INFO, SFX_INFO, AUDIOEVENT_INFO
return new FX_BASE_INFO();
}
}
[System.Serializable]
public class A3DCombinedAction
{
public string m_strName;
public int m_nLoops;
public bool IsLooping()
{
if (m_ActLst.Count == 0)
return false;
return m_ActLst[0].m_nMinLoops == -1 || m_ActLst[0].m_nMaxLoops == -1;
}
public List<ACTION_INFO> m_ActLst = new();
public List<EVENT_INFO> m_EventInfoLst = new();
// Original, this property describes the comact's span time, now the span time may change randomly,
// so this property only define the min span time
// And rename it from m_dwComActSpan -> m_dwComActMinSpan
public uint m_dwComActMinSpan;
public bool m_bInfinite;
//public byte[] m_Ranks = new byte[CECModelConst.ACTCHA_MAX];
public int[] m_aEventCounter = new int[A3DCombinedActionConst.EVENT_TYPE_END - A3DCombinedActionConst.EVENT_TYPE_BASE + 1];
public int m_nEventChannel;
public float m_fPlaySpeed;
public bool m_bResetMaterialScale; // Whether to reset color change state when action stops (default is true)
public bool m_bStopChildrenAct; // Whether to stop child model actions when action stops (default is false)
public bool Load(FileStream fileStream, StreamReader file, uint dwVersion)
{
int nActCount = 0;
int nFxCount = 0;
int nChildCount = 0;
int nEventCount = 0;
bool isBinary = fileStream != null;
if (isBinary)
{
}
else
{
string szLine = string.Empty;
string tagValue;
szLine = file.ReadLine();
while(!szLine.Contains(A3DCombinedActionConst._format_cact_name))
{
szLine = file.ReadLine();
}
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_cact_name, out tagValue);
m_strName = tagValue;
if (dwVersion >= 3)
{
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_act_LoopCount, out tagValue);
int.TryParse(tagValue, out m_nLoops);
}
else
m_nLoops = 1;
if (dwVersion >= 30)
{
int rank_count = 0;
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_rank_count, out tagValue);
int.TryParse(tagValue, out rank_count);
for (int i = 0; i < rank_count; i++)
{
int channel = 0;
int rank = 0;
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_rank, out tagValue);
//Output look like this: 2, Rank: 1
string[] values = tagValue.Split(',');
if (values.Length >= 2)
{
int.TryParse(values[0].Trim(), out channel);
int.TryParse(values[1].Substring(values[1].LastIndexOf(' ') + 1).Trim(), out rank);
}
// if (channel >= 0 && channel < CECModelConst.ACTCHA_MAX)
// {
// m_Ranks[channel] = (byte)rank;
// }
}
}
if (dwVersion >= 32)
{
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_event_channel, out tagValue);
int.TryParse(tagValue, out m_nEventChannel);
}
if (dwVersion >= 40)
{
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_play_speed, out tagValue);
float.TryParse(tagValue, out m_fPlaySpeed);
}
if (dwVersion >= 49)
{
int iRead = 0;
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_stopchildact, out tagValue);
int.TryParse(tagValue, out iRead);
m_bStopChildrenAct = (iRead != 0);
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_resetmtlonstop, out tagValue);
int.TryParse(tagValue, out iRead);
m_bResetMaterialScale = (iRead != 0);
}
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_act_count, out tagValue);
int.TryParse(tagValue, out nActCount);
for (int i = 0; i < nActCount; i++)
{
ACTION_INFO pInfo = new ACTION_INFO();
pInfo.Load(fileStream, file, dwVersion);
m_ActLst.Add(pInfo);
}
if (m_nLoops == -1 && nActCount == 1 && m_ActLst.Count > 0)
m_ActLst[0].m_nMinLoops = m_ActLst[0].m_nMaxLoops = -1;
if (dwVersion < 7)
{
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_fx_count, out tagValue);
int.TryParse(tagValue, out nFxCount);
for (int i = 0; i < nFxCount; i++)
{
FX_BASE_INFO pInfo = FX_BASE_INFO.LoadFromFile(this, fileStream, file, dwVersion);
if (pInfo == null) continue;
//TODO: Implement Load function
// pInfo.Load(fileStream, file, dwVersion);
m_EventInfoLst.Add(pInfo);
}
}
else
{
// pFile->ReadLine(szLine, AFILE_LINEMAXLEN, &dwReadLen);
// sscanf(szLine, _format_event_count, &nEventCount);
szLine = file.ReadLine();
AAssit.GetStringAfter(szLine, A3DCombinedActionConst._format_event_count, out tagValue);
int.TryParse(tagValue, out nEventCount);
EVENT_INFO pEvent = null;
for (int i = 0; i < nEventCount; i++)
{
pEvent = EVENT_INFO.LoadFromFile(this, null, file, dwVersion);
if (pEvent == null) continue;
m_EventInfoLst.Add(pEvent);
if (pEvent.m_nType > A3DCombinedActionConst.EVENT_TYPE_END)
continue;
// TODO: Maybe we need to implement this in the future
// m_aEventCounter[pEvent.m_nType - A3DCombinedActionConst.EVENT_TYPE_BASE]++;
}
}
}
/*/ TODO: Maybe we need to implement this in the future
ALISTPOSITION pos = m_EventInfoLst.GetHeadPosition();
while (pos) m_EventInfoLst.GetNext(pos)->Init(pDev);
pos = m_ActLst.GetHeadPosition();
while (pos)
{
if (m_ActLst.GetNext(pos)->IsInfinite()//*GetLoops() == -1)
{
m_bInfinite = true;
break;
}
}
//*/
return true;
}
}
}