Files
test/Assets/PerfectWorld/Scripts/UI/PortraitCaptureUtils.cs
T

140 lines
6.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
namespace BrewMonster
{
/// <summary>
/// Shared static helpers used by ElsePlayerPortraitCapture and HostPlayerPortraitCapture.
/// </summary>
public static class PortraitCaptureUtils
{
private static readonly string[] HeadBoneNames =
{
"Bip01 Head", "Bip001 Head", "head", "Head", "Bone_Head", "HEAD"
};
// ──────────────────────────────────────────────────────────────────────────────
// Model / bone search
// ──────────────────────────────────────────────────────────────────────────────
/// <summary>
/// Returns the root transform of the visual model inside <paramref name="playerRoot"/>.
/// Tries to find the first child that owns a SkinnedMeshRenderer; falls back to the
/// root itself if a SkinnedMeshRenderer is found anywhere in the hierarchy.
/// </summary>
public static Transform FindVisualModelRoot(Transform playerRoot)
{
if (playerRoot == null) return null;
// Walk immediate children first — model root is usually a direct child
for (int i = 0; i < playerRoot.childCount; i++)
{
var child = playerRoot.GetChild(i);
if (child.GetComponentInChildren<SkinnedMeshRenderer>() != null)
return child;
}
// Fallback: if the root itself contains a SMR, use it
if (playerRoot.GetComponentInChildren<SkinnedMeshRenderer>() != null)
return playerRoot;
return null;
}
/// <summary>
/// Searches <paramref name="modelRoot"/>'s hierarchy for a head bone by common name patterns.
/// </summary>
public static Transform FindHeadBone(Transform modelRoot)
{
if (modelRoot == null) return null;
foreach (var boneName in HeadBoneNames)
{
var bone = FindChildByName(modelRoot, boneName);
if (bone != null) return bone;
}
return null;
}
/// <summary>Recursive depth-first search for a child transform by exact name.</summary>
public static Transform FindChildByName(Transform root, string name)
{
if (root.name == name) return root;
for (int i = 0; i < root.childCount; i++)
{
var result = FindChildByName(root.GetChild(i), name);
if (result != null) return result;
}
return null;
}
// ──────────────────────────────────────────────────────────────────────────────
// Clone setup
// ──────────────────────────────────────────────────────────────────────────────
/// <summary>
/// Strips non-visual components from a cloned GameObject so it becomes a lightweight
/// render-only puppet. Keeps Animator so idle animations continue to play.
/// </summary>
public static void CleanupCloneComponents(GameObject go)
{
foreach (var col in go.GetComponentsInChildren<Collider>(true))
Object.Destroy(col);
foreach (var rb in go.GetComponentsInChildren<Rigidbody>(true))
Object.Destroy(rb);
foreach (var mb in go.GetComponentsInChildren<MonoBehaviour>(true))
{
if (mb is Animator) continue;
Object.Destroy(mb);
}
}
/// <summary>Recursively sets the layer of <paramref name="go"/> and all its children.</summary>
public static void SetLayerRecursive(GameObject go, int layer)
{
go.layer = layer;
foreach (Transform child in go.transform)
SetLayerRecursive(child.gameObject, layer);
}
// ──────────────────────────────────────────────────────────────────────────────
// Camera / RenderTexture factories
// ──────────────────────────────────────────────────────────────────────────────
/// <summary>
/// Creates a Camera child GameObject under <paramref name="parent"/> whose culling mask
/// covers only <paramref name="portraitLayer"/>. Camera starts disabled.
/// </summary>
public static Camera CreatePortraitCamera(Transform parent, string goName, int portraitLayer, float fov)
{
var camGO = new GameObject(goName);
camGO.transform.SetParent(parent, false);
var cam = camGO.AddComponent<Camera>();
cam.cullingMask = 1 << portraitLayer;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = Color.clear;
cam.fieldOfView = fov;
cam.nearClipPlane = 0.1f;
cam.farClipPlane = 200f;
cam.enabled = false;
return cam;
}
/// <summary>
/// Creates a 256×256 ARGB32 RenderTexture and wires it to <paramref name="cam"/> if provided.
/// </summary>
public static RenderTexture CreatePortraitRT(string rtName, Camera cam)
{
var rt = new RenderTexture(256, 256, 16, RenderTextureFormat.ARGB32)
{
name = rtName,
antiAliasing = 1
};
rt.Create();
if (cam != null) cam.targetTexture = rt;
return rt;
}
}
}