Project_WL/AgentScripts/WL814k_Diag6.cs

179 lines
8.7 KiB
C#
Raw Permalink Normal View History

// WL-814k 진단 ⑥ — 3D 프레임 k 와 스프라이트 프레임 k 가 정말 같은 그림인가(격자 비교)
// run: unity command run_script --file AgentScripts/WL814k_Diag6.cs --entry WL814k_Diag6.Run
using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using WL.Look.SpriteBake;
public static class WL814k_Diag6
{
const string kOut = @"E:\NerdNavis\nn_himminji\Screenshots_WL\WL814k_diag";
const string kTxt = "AgentScripts/WL814k_DIAG6.txt";
const float kOrtho = 3.4f, kPitch = 43.609f;
const int kLowH = 240;
static StringBuilder s_sb;
static void L(string s) { s_sb.AppendLine(s); Debug.Log("[WL814k] " + s); }
public static void Run()
{
s_sb = new StringBuilder();
Directory.CreateDirectory(kOut);
L("WL-814k 진단 ⑥ · " + DateTime.Now.ToString("HH:mm:ss"));
try
{
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
var sun = new GameObject("Sun").AddComponent<Light>();
sun.type = LightType.Directional; sun.shadows = LightShadows.None;
sun.color = new Color(1f, 0.92f, 0.703f, 1f); sun.intensity = 1.2f;
sun.transform.rotation = Quaternion.Euler(26.4f, 238.6f, 0f);
var fill = new GameObject("Fill").AddComponent<Light>();
fill.type = LightType.Directional; fill.shadows = LightShadows.None;
fill.color = new Color(0.596f, 0.703f, 0.839f, 1f); fill.intensity = 0.3f;
fill.transform.rotation = Quaternion.Euler(36.1f, 116.1f, 0f);
RenderSettings.skybox = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Skybox.mat");
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Skybox;
RenderSettings.ambientIntensity = 1f; RenderSettings.fog = false;
DynamicGI.UpdateEnvironment();
var look = WLSpriteLookSettings.Instance;
var actor = Spawn("Assets/Res_Addr/PC/Ai01.prefab", 0.7f);
var set = SpriteBillboard.MatchSet(actor.name, look);
var act = set.FindByKey("attack");
var anim = actor.GetComponent<Animator>();
int cell = 64, cols = act.frameCount, rows = 2, dir = 7;
var rig = MakeCam(cell, cell);
var sheet = new Color32[cols * cell * rows * cell];
// 위 줄 = 3D (매 컷 직전에 포즈를 다시 찍는다)
for (int f = 0; f < cols; f++)
{
actor.transform.rotation = Quaternion.Euler(0f, dir * 45f, 0f);
anim.Play(Animator.StringToHash("attack"), 0, (f + 0.001f) / act.frameCount);
anim.Update(0f);
var st = anim.GetCurrentAnimatorStateInfo(0);
L(string.Format(" 3D f{0} → 상태 해시 {1}(attack={2}) nt {3:0.000}", f, st.shortNameHash, Animator.StringToHash("attack"), st.normalizedTime));
BlitInto(rig.Grab(), cell, cell, sheet, cols * cell, f * cell, 1 * cell);
}
// 아래 줄 = 스프라이트
var e = SpriteBillboard.TryAttach(actor, set);
for (int f = 0; f < cols; f++)
{
actor.transform.rotation = Quaternion.Euler(0f, dir * 45f, 0f);
SpriteBillboard.SetManualFrame(actor, "attack", dir, f);
SpriteBillboard.UpdateAll(rig.cam);
L(string.Format(" 스프라이트 f{0} → 인덱스 {1} (시작 {2} + {3}*{4} + {5})", f,
act.startIndex + dir * act.frameCount + f, act.startIndex, dir, act.frameCount, f));
BlitInto(rig.Grab(), cell, cell, sheet, cols * cell, f * cell, 0 * cell);
}
SpriteBillboard.RestoreNow("diag6");
Save(sheet, cols * cell, rows * cell, kOut + @"\frames_attack_dir7.png", 6);
rig.Dispose();
}
catch (Exception ex) { L("EXCEPTION " + ex); }
finally
{
SpriteBillboard.RestoreNow("diag6-end");
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
}
File.WriteAllText(kTxt, s_sb.ToString(), new UTF8Encoding(false));
}
static GameObject Spawn(string p, float scale)
{
var src = AssetDatabase.LoadAssetAtPath<GameObject>(p);
var go = (GameObject)PrefabUtility.InstantiatePrefab(src);
PrefabUtility.UnpackPrefabInstance(go, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
go.name = Path.GetFileNameWithoutExtension(p) + "(Clone)";
go.transform.position = Vector3.zero;
go.transform.localScale = Vector3.one * scale;
foreach (var c in go.GetComponentsInChildren<Collider>(true)) UnityEngine.Object.DestroyImmediate(c);
foreach (var c in go.GetComponentsInChildren<UnityEngine.AI.NavMeshAgent>(true)) UnityEngine.Object.DestroyImmediate(c);
foreach (var c in go.GetComponentsInChildren<Rigidbody>(true)) UnityEngine.Object.DestroyImmediate(c);
foreach (var c in go.GetComponentsInChildren<ParticleSystem>(true)) UnityEngine.Object.DestroyImmediate(c.gameObject);
foreach (var mb in go.GetComponentsInChildren<MonoBehaviour>(true)) if (mb != null) UnityEngine.Object.DestroyImmediate(mb);
foreach (var sm in go.GetComponentsInChildren<SkinnedMeshRenderer>(true)) sm.updateWhenOffscreen = true;
var an = go.GetComponent<Animator>();
an.applyRootMotion = false; an.cullingMode = AnimatorCullingMode.AlwaysAnimate; an.Rebind();
var bake = WLSpriteBakeSettings.Instance;
foreach (var rend in go.GetComponentsInChildren<Renderer>(true))
{
if (rend == null || rend is ParticleSystemRenderer) continue;
var mats = rend.sharedMaterials; bool any = false;
for (int i = 0; i < mats.Length; i++)
{
if (mats[i] == null) continue;
var t = AssetDatabase.LoadAssetAtPath<Material>(bake.toonMaterialDir + "/" + mats[i].name + bake.toonMaterialSuffix + ".mat");
if (t != null) { mats[i] = t; any = true; }
}
if (any) rend.sharedMaterials = mats;
}
return go;
}
sealed class Rig
{
public Camera cam; public RenderTexture rt; public Texture2D tex; public int w, h;
public Color32[] Grab()
{
cam.targetTexture = rt; cam.Render(); cam.targetTexture = null;
var a = RenderTexture.active; RenderTexture.active = rt;
tex.ReadPixels(new Rect(0, 0, w, h), 0, 0); tex.Apply(false, false);
RenderTexture.active = a;
return tex.GetPixels32();
}
public void Dispose()
{
RenderTexture.active = null;
if (rt != null) { rt.Release(); UnityEngine.Object.DestroyImmediate(rt); }
if (tex != null) UnityEngine.Object.DestroyImmediate(tex);
if (cam != null) UnityEngine.Object.DestroyImmediate(cam.gameObject);
}
}
static Rig MakeCam(int w, int h)
{
var go = new GameObject("Cam");
var c = go.AddComponent<Camera>();
c.orthographic = true;
c.orthographicSize = h * (2f * kOrtho / kLowH) * 0.5f;
c.nearClipPlane = 0.01f; c.farClipPlane = 200f;
c.clearFlags = CameraClearFlags.SolidColor;
c.backgroundColor = new Color(0.34f, 0.40f, 0.25f, 1f);
c.allowHDR = false; c.allowMSAA = false;
go.transform.rotation = Quaternion.Euler(kPitch, 0f, 0f);
go.transform.position = new Vector3(0f, 0.6f, 0f) - go.transform.forward * 40f;
var rt = new RenderTexture(w, h, 24, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB);
rt.filterMode = FilterMode.Point; rt.antiAliasing = 1; rt.Create();
var tex = new Texture2D(w, h, TextureFormat.RGBA32, false, false);
return new Rig { cam = c, rt = rt, tex = tex, w = w, h = h };
}
static void BlitInto(Color32[] src, int sw, int sh, Color32[] dst, int dw, int dx, int dy)
{
for (int y = 0; y < sh; y++)
for (int x = 0; x < sw; x++)
{
int di = (dy + y) * dw + (dx + x);
if (di >= 0 && di < dst.Length) dst[di] = src[y * sw + x];
}
}
static void Save(Color32[] px, int w, int h, string file, int zoom)
{
int ow = w * zoom, oh = h * zoom;
var o = new Color32[ow * oh];
for (int y = 0; y < oh; y++) for (int x = 0; x < ow; x++) o[y * ow + x] = px[(y / zoom) * w + (x / zoom)];
var t = new Texture2D(ow, oh, TextureFormat.RGBA32, false, false);
t.SetPixels32(o); t.Apply(false, false);
File.WriteAllBytes(file, t.EncodeToPNG());
UnityEngine.Object.DestroyImmediate(t);
}
}