214 lines
6.4 KiB
C#
214 lines
6.4 KiB
C#
// UTF-8 with BOM — required for Chinese character paths
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using BrewMonster;
|
|
using BrewMonster.Scripts.ECModel;
|
|
using ModelViewer.Common;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
public enum CombinedActionGfxPhase
|
|
{
|
|
All,
|
|
Cast,
|
|
Attack,
|
|
Other,
|
|
}
|
|
|
|
public readonly struct CombinedActionGfxEntry
|
|
{
|
|
public CombinedActionGfxEntry(
|
|
A3DCombinedAction action,
|
|
FX_BASE_INFO fxEvent,
|
|
string path,
|
|
string actionName,
|
|
string gfxBasename,
|
|
CombinedActionGfxPhase phase)
|
|
{
|
|
Action = action;
|
|
FxEvent = fxEvent;
|
|
Path = path;
|
|
ActionName = actionName;
|
|
GfxBasename = gfxBasename;
|
|
Phase = phase;
|
|
}
|
|
|
|
public A3DCombinedAction Action { get; }
|
|
public FX_BASE_INFO FxEvent { get; }
|
|
public string Path { get; }
|
|
public string ActionName { get; }
|
|
public string GfxBasename { get; }
|
|
public CombinedActionGfxPhase Phase { get; }
|
|
}
|
|
|
|
public static class CombinedActionGfxQuery
|
|
{
|
|
const string CastToken = "_\u541f\u5531_";
|
|
const string AttackRiseToken = "_\u65bd\u653e\u8d77_";
|
|
const string AttackFallToken = "_\u65bd\u653e\u843d_";
|
|
|
|
public static CombinedActionGfxPhase GetPhase(string actionName)
|
|
{
|
|
if (string.IsNullOrEmpty(actionName))
|
|
return CombinedActionGfxPhase.Other;
|
|
|
|
if (actionName.Contains(CastToken, StringComparison.Ordinal))
|
|
return CombinedActionGfxPhase.Cast;
|
|
|
|
if (actionName.Contains(AttackRiseToken, StringComparison.Ordinal) ||
|
|
actionName.Contains(AttackFallToken, StringComparison.Ordinal))
|
|
return CombinedActionGfxPhase.Attack;
|
|
|
|
return CombinedActionGfxPhase.Other;
|
|
}
|
|
|
|
public static string GetPhaseLabel(CombinedActionGfxPhase phase)
|
|
{
|
|
return phase switch
|
|
{
|
|
CombinedActionGfxPhase.Cast => "Cast",
|
|
CombinedActionGfxPhase.Attack => "Attack",
|
|
CombinedActionGfxPhase.Other => "Other",
|
|
_ => "All",
|
|
};
|
|
}
|
|
|
|
public static IEnumerable<CombinedActionGfxEntry> Scan(CombinedActionSO so)
|
|
{
|
|
if (so?.CombinedActionData == null)
|
|
yield break;
|
|
|
|
foreach (A3DCombinedAction action in so.CombinedActionData)
|
|
{
|
|
if (action?.m_EventInfoLst == null)
|
|
continue;
|
|
|
|
string actionName = action.m_strName ?? string.Empty;
|
|
CombinedActionGfxPhase phase = GetPhase(actionName);
|
|
|
|
foreach (EVENT_INFO eventInfo in action.m_EventInfoLst)
|
|
{
|
|
if (eventInfo is not FX_BASE_INFO fx || fx.m_strFilePaths == null)
|
|
continue;
|
|
|
|
foreach (string path in fx.m_strFilePaths)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(path) || !path.Contains("gfx", StringComparison.OrdinalIgnoreCase))
|
|
continue;
|
|
|
|
string basename = LogPanelAnimeScene.GfxBasename(path);
|
|
if (string.IsNullOrEmpty(basename))
|
|
continue;
|
|
|
|
yield return new CombinedActionGfxEntry(action, fx, path, actionName, basename, phase);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool MatchesFilters(
|
|
CombinedActionGfxEntry entry,
|
|
CombinedActionGfxPhase phaseFilter,
|
|
string actionFilter,
|
|
string basenameFilter)
|
|
{
|
|
if (phaseFilter != CombinedActionGfxPhase.All && entry.Phase != phaseFilter)
|
|
return false;
|
|
|
|
if (!string.IsNullOrWhiteSpace(actionFilter) &&
|
|
entry.ActionName.IndexOf(actionFilter, StringComparison.OrdinalIgnoreCase) < 0)
|
|
return false;
|
|
|
|
if (!string.IsNullOrWhiteSpace(basenameFilter) &&
|
|
entry.GfxBasename.IndexOf(basenameFilter, StringComparison.OrdinalIgnoreCase) < 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool RemoveEntry(CombinedActionSO so, CombinedActionGfxEntry entry)
|
|
{
|
|
return RemovePath(so, entry.Action, entry.FxEvent, entry.Path);
|
|
}
|
|
|
|
public static bool RemovePath(CombinedActionSO so, A3DCombinedAction action, FX_BASE_INFO fxEvent, string path)
|
|
{
|
|
if (so == null || action == null || fxEvent == null || string.IsNullOrWhiteSpace(path))
|
|
return false;
|
|
|
|
Undo.RecordObject(so, "Remove GFX Event");
|
|
|
|
if (!ApplyRemoval(action, fxEvent, path))
|
|
return false;
|
|
|
|
EditorUtility.SetDirty(so);
|
|
AssetDatabase.SaveAssets();
|
|
return true;
|
|
}
|
|
|
|
public static int RemoveMatchingBasenameFromPhase(
|
|
CombinedActionSO so,
|
|
string basename,
|
|
CombinedActionGfxPhase phase)
|
|
{
|
|
if (so == null || string.IsNullOrWhiteSpace(basename) || phase == CombinedActionGfxPhase.All)
|
|
return 0;
|
|
|
|
Undo.RecordObject(so, "Remove GFX Events");
|
|
|
|
int removed = 0;
|
|
var toRemove = new List<(A3DCombinedAction action, FX_BASE_INFO fx, string path)>();
|
|
|
|
foreach (CombinedActionGfxEntry entry in Scan(so))
|
|
{
|
|
if (entry.Phase != phase)
|
|
continue;
|
|
|
|
if (!string.Equals(entry.GfxBasename, basename, StringComparison.OrdinalIgnoreCase))
|
|
continue;
|
|
|
|
toRemove.Add((entry.Action, entry.FxEvent, entry.Path));
|
|
}
|
|
|
|
foreach ((A3DCombinedAction action, FX_BASE_INFO fx, string path) item in toRemove)
|
|
{
|
|
if (ApplyRemoval(item.action, item.fx, item.path))
|
|
removed++;
|
|
}
|
|
|
|
if (removed > 0)
|
|
{
|
|
EditorUtility.SetDirty(so);
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
return removed;
|
|
}
|
|
|
|
static bool ApplyRemoval(A3DCombinedAction action, FX_BASE_INFO fxEvent, string path)
|
|
{
|
|
if (action == null || fxEvent == null || string.IsNullOrWhiteSpace(path))
|
|
return false;
|
|
|
|
if (fxEvent.m_strFilePaths != null && fxEvent.m_strFilePaths.Count > 1)
|
|
{
|
|
if (!fxEvent.m_strFilePaths.Remove(path))
|
|
return false;
|
|
|
|
if (fxEvent.m_strFilePaths.Count == 0 && action.m_EventInfoLst != null)
|
|
action.m_EventInfoLst.Remove(fxEvent);
|
|
}
|
|
else if (action.m_EventInfoLst != null)
|
|
{
|
|
if (!action.m_EventInfoLst.Remove(fxEvent))
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|