156 lines
8.2 KiB
C#
156 lines
8.2 KiB
C#
|
|
using UnityEditor;
|
|||
|
|
using UnityEditor.SceneManagement;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEngine.SceneManagement;
|
|||
|
|
|
|||
|
|
// IB(쿠로네코) 이펙트 → 게임이 읽는 사본 Resources/Fx/TKS_Fx_IB_*(PD 2026-11-10 「IB 이펙트를 그대로 써서 확인 → 나중에 구조에 맞게 새로 그림(화풍 통일)」).
|
|||
|
|
// 원본 = Tools/wl_vfx_import.py copy … --wl E:/NerdNavis/Kuroneko/KuronekoClient --dest Assets/VFX/IB --skip-scripts 로 옮긴 Assets/VFX/IB/AssetResources/FX/*.prefab(무수정).
|
|||
|
|
// 사본 = IB 전용 스크립트 부품(VisualEffectData 등 · 이 게임에 없음) 제거 · 방향 있는 것은 감싸는 루트를 두고 안쪽을 Z −90°
|
|||
|
|
// (IB 정면 = +Y · FollowUnit = FromToRotation(up, 진행 방향) → 이 게임 b_flat 정면 = +X 에 맞춤).
|
|||
|
|
// 실행: unity command --project-path "E:/NerdNavis/ThreeKingdomsSlingshot" script eval --file Tools/make_ib_fx_copies.cs
|
|||
|
|
string src = "Assets/VFX/IB/AssetResources/";
|
|||
|
|
string dst = "Assets/Resources/Fx/";
|
|||
|
|
// { IB 경로(AssetResources 아래), 사본 이름, 1 = 진행 방향으로 돌림(감싸는 루트) }
|
|||
|
|
var jobs = new[]
|
|||
|
|
{
|
|||
|
|
new[] { "FX/ef_booster", "TKS_Fx_IB_Booster", "1" },
|
|||
|
|
new[] { "FX/ef_speed_tail", "TKS_Fx_IB_SpeedTail", "1" },
|
|||
|
|
new[] { "FX/ef_booster_dust", "TKS_Fx_IB_BoosterDust", "1" },
|
|||
|
|
new[] { "FX/ef_normal_hit", "TKS_Fx_IB_NormalHit", "0" },
|
|||
|
|
new[] { "FX/ef_bounce_hit", "TKS_Fx_IB_BounceHit", "0" },
|
|||
|
|
new[] { "FX/ef_dust", "TKS_Fx_IB_Dust", "0" },
|
|||
|
|
// 방향 결정 UI(PD 2026-11-10 「IB 와 같이 슬링샷 조작 시 방향 결정 UI 등을 그대로 이식」) — 동작은 TKS.IbAimArrow(IB GameTouchArrow 이식)
|
|||
|
|
new[] { "Game/GameArrow", "TKS_Fx_IB_GameArrow", "0" },
|
|||
|
|
// 슬링샷 진행 중 캐릭터 연출(PD 2026-11-10 「선택된 캐릭터 주위 연출 누락」) — IB ShowUserTurnMark(발밑 도는 원 · 몸 둘레 빛) · 조준 중 모든 유닛 속성 방울(SetActiveBarrierVisualEffect)
|
|||
|
|
new[] { "FX/ef_target_circle", "TKS_Fx_IB_TargetCircle", "0" },
|
|||
|
|
new[] { "FX/ef_attack_ready_standard", "TKS_Fx_IB_AttackReady", "0" },
|
|||
|
|
new[] { "FX/ef_attribute_water", "TKS_Fx_IB_Attribute_water", "0" },
|
|||
|
|
new[] { "FX/ef_attribute_tree", "TKS_Fx_IB_Attribute_tree", "0" },
|
|||
|
|
new[] { "FX/ef_attribute_fire", "TKS_Fx_IB_Attribute_fire", "0" },
|
|||
|
|
new[] { "FX/ef_attribute_dark", "TKS_Fx_IB_Attribute_dark", "0" },
|
|||
|
|
new[] { "FX/ef_attribute_glow", "TKS_Fx_IB_Attribute_glow", "0" },
|
|||
|
|
};
|
|||
|
|
AssetDatabase.Refresh();
|
|||
|
|
var sb = new System.Text.StringBuilder();
|
|||
|
|
var scene = EditorSceneManager.NewPreviewScene();
|
|||
|
|
foreach (var j in jobs)
|
|||
|
|
{
|
|||
|
|
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(src + j[0] + ".prefab");
|
|||
|
|
if (prefab == null) { sb.AppendLine("없음 " + j[0]); continue; }
|
|||
|
|
var inst = (GameObject)PrefabUtility.InstantiatePrefab(prefab, scene);
|
|||
|
|
PrefabUtility.UnpackPrefabInstance(inst, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
|||
|
|
int removed = 0;
|
|||
|
|
foreach (var t in inst.GetComponentsInChildren<Transform>(true)) removed += GameObjectUtility.RemoveMonoBehavioursWithMissingScript(t.gameObject);
|
|||
|
|
foreach (var r in inst.GetComponentsInChildren<Renderer>(true)) r.sortingLayerID = 0; // IB 정렬 레이어(이 게임에 없음 · <unknown layer>) → Default · 순서는 표 n_order
|
|||
|
|
foreach (var an in inst.GetComponentsInChildren<Animator>(true)) // 클립의 소리 이벤트(FGPlaySoundByString) 받는 곳 — 없으면 재생마다 콘솔 오류
|
|||
|
|
if (an.GetComponent<TKS.IbFxAnimEvents>() == null) an.gameObject.AddComponent<TKS.IbFxAnimEvents>();
|
|||
|
|
GameObject root = inst;
|
|||
|
|
if (j[2] == "1")
|
|||
|
|
{
|
|||
|
|
root = new GameObject(j[1]);
|
|||
|
|
SceneManager.MoveGameObjectToScene(root, scene);
|
|||
|
|
inst.transform.SetParent(root.transform, false);
|
|||
|
|
inst.transform.localPosition = Vector3.zero;
|
|||
|
|
inst.transform.localRotation = Quaternion.Euler(0f, 0f, -90f);
|
|||
|
|
}
|
|||
|
|
else root.name = j[1];
|
|||
|
|
PrefabUtility.SaveAsPrefabAsset(root, dst + j[1] + ".prefab");
|
|||
|
|
Object.DestroyImmediate(root);
|
|||
|
|
var rs = AssetDatabase.LoadAssetAtPath<GameObject>(dst + j[1] + ".prefab").GetComponentsInChildren<Renderer>(true);
|
|||
|
|
var layers = new System.Collections.Generic.HashSet<string>();
|
|||
|
|
foreach (var r in rs) layers.Add(r.sortingLayerName + "/" + r.sortingOrder);
|
|||
|
|
sb.AppendLine(j[1] + " · 스크립트 부품 제거 " + removed + " · 렌더러 " + rs.Length + " · 정렬 " + string.Join(",", layers));
|
|||
|
|
}
|
|||
|
|
EditorSceneManager.ClosePreviewScene(scene);
|
|||
|
|
|
|||
|
|
// ── 진영색 사본(PD 2026-11-10 「진영 색을 입히고」): TKS_Fx_IB_Booster_<진영> · TKS_Fx_IB_SpeedTail_<진영> ──
|
|||
|
|
// 색 = 채도 있는 색만 색상(H)을 진영색으로(채도·밝기 유지 · 흰 심 그대로) · 꼬리 그림 = Tools/make_ib_camp_textures.py 가 만든 Assets/VFX/IB/_TKS/Tail_Basic02_<진영>.png
|
|||
|
|
// 진영색 원본 = Tools/dash2d_camps.csv
|
|||
|
|
Color HueTo(Color c, float hue)
|
|||
|
|
{
|
|||
|
|
float h, s, v;
|
|||
|
|
Color.RGBToHSV(c, out h, out s, out v);
|
|||
|
|
if (s < 0.15f) return c;
|
|||
|
|
var n = Color.HSVToRGB(hue, s, v);
|
|||
|
|
n.a = c.a;
|
|||
|
|
return n;
|
|||
|
|
}
|
|||
|
|
Gradient GradHue(Gradient g, float hue)
|
|||
|
|
{
|
|||
|
|
if (g == null) return null;
|
|||
|
|
var ks = g.colorKeys;
|
|||
|
|
for (int i = 0; i < ks.Length; i++) ks[i].color = HueTo(ks[i].color, hue);
|
|||
|
|
var ng = new Gradient();
|
|||
|
|
ng.SetKeys(ks, g.alphaKeys);
|
|||
|
|
ng.mode = g.mode;
|
|||
|
|
return ng;
|
|||
|
|
}
|
|||
|
|
ParticleSystem.MinMaxGradient MmgHue(ParticleSystem.MinMaxGradient m, float hue)
|
|||
|
|
{
|
|||
|
|
switch (m.mode)
|
|||
|
|
{
|
|||
|
|
case ParticleSystemGradientMode.Color: return new ParticleSystem.MinMaxGradient(HueTo(m.color, hue));
|
|||
|
|
case ParticleSystemGradientMode.TwoColors: return new ParticleSystem.MinMaxGradient(HueTo(m.colorMin, hue), HueTo(m.colorMax, hue));
|
|||
|
|
case ParticleSystemGradientMode.TwoGradients: return new ParticleSystem.MinMaxGradient(GradHue(m.gradientMin, hue), GradHue(m.gradientMax, hue));
|
|||
|
|
default:
|
|||
|
|
var r = new ParticleSystem.MinMaxGradient(GradHue(m.gradient, hue));
|
|||
|
|
r.mode = m.mode;
|
|||
|
|
return r;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
string tks = "Assets/VFX/IB/_TKS/";
|
|||
|
|
var tailMat0 = AssetDatabase.LoadAssetAtPath<Material>("Assets/VFX/IB/FGResources/Effect/Material/Tail_Basic02.mat");
|
|||
|
|
foreach (var line in System.IO.File.ReadAllLines("Tools/dash2d_camps.csv"))
|
|||
|
|
{
|
|||
|
|
var cells = line.Trim('').Split(',');
|
|||
|
|
if (cells.Length < 2 || cells[0] == "s_camp" || cells[0].Length == 0) continue;
|
|||
|
|
string camp = cells[0].Trim();
|
|||
|
|
Color cc;
|
|||
|
|
ColorUtility.TryParseHtmlString(cells[1].Trim(), out cc);
|
|||
|
|
float hue, cs, cv;
|
|||
|
|
Color.RGBToHSV(cc, out hue, out cs, out cv);
|
|||
|
|
|
|||
|
|
var tp = tks + "Tail_Basic02_" + camp + ".png";
|
|||
|
|
var ti = (TextureImporter)AssetImporter.GetAtPath(tp);
|
|||
|
|
ti.wrapMode = TextureWrapMode.Clamp;
|
|||
|
|
ti.mipmapEnabled = false;
|
|||
|
|
ti.alphaIsTransparency = true;
|
|||
|
|
ti.SaveAndReimport();
|
|||
|
|
var mp = tks + "Tail_Basic02_" + camp + ".mat";
|
|||
|
|
var mat = AssetDatabase.LoadAssetAtPath<Material>(mp);
|
|||
|
|
if (mat == null)
|
|||
|
|
{
|
|||
|
|
mat = new Material(tailMat0);
|
|||
|
|
AssetDatabase.CreateAsset(mat, mp);
|
|||
|
|
}
|
|||
|
|
mat.CopyPropertiesFromMaterial(tailMat0);
|
|||
|
|
mat.SetTexture("_MainTex", AssetDatabase.LoadAssetAtPath<Texture2D>(tp));
|
|||
|
|
EditorUtility.SetDirty(mat);
|
|||
|
|
|
|||
|
|
var b = PrefabUtility.LoadPrefabContents(dst + "TKS_Fx_IB_Booster.prefab");
|
|||
|
|
b.name = "TKS_Fx_IB_Booster_" + camp;
|
|||
|
|
foreach (var sr in b.GetComponentsInChildren<SpriteRenderer>(true)) sr.color = HueTo(sr.color, hue);
|
|||
|
|
PrefabUtility.SaveAsPrefabAsset(b, dst + b.name + ".prefab");
|
|||
|
|
PrefabUtility.UnloadPrefabContents(b);
|
|||
|
|
|
|||
|
|
var t = PrefabUtility.LoadPrefabContents(dst + "TKS_Fx_IB_SpeedTail.prefab");
|
|||
|
|
t.name = "TKS_Fx_IB_SpeedTail_" + camp;
|
|||
|
|
foreach (var tr in t.GetComponentsInChildren<TrailRenderer>(true))
|
|||
|
|
{
|
|||
|
|
tr.sharedMaterial = mat;
|
|||
|
|
tr.colorGradient = GradHue(tr.colorGradient, hue);
|
|||
|
|
}
|
|||
|
|
foreach (var ps in t.GetComponentsInChildren<ParticleSystem>(true))
|
|||
|
|
{
|
|||
|
|
var m = ps.main;
|
|||
|
|
m.startColor = MmgHue(m.startColor, hue);
|
|||
|
|
var col = ps.colorOverLifetime;
|
|||
|
|
if (col.enabled) col.color = MmgHue(col.color, hue);
|
|||
|
|
}
|
|||
|
|
PrefabUtility.SaveAsPrefabAsset(t, dst + t.name + ".prefab");
|
|||
|
|
PrefabUtility.UnloadPrefabContents(t);
|
|||
|
|
sb.AppendLine("진영색 " + camp + " " + cells[1].Trim() + " → TKS_Fx_IB_Booster_" + camp + " · TKS_Fx_IB_SpeedTail_" + camp);
|
|||
|
|
}
|
|||
|
|
AssetDatabase.SaveAssets();
|
|||
|
|
return sb.ToString();
|