using System.Collections.Generic; using UnityEngine; using CSharpESP.Drawing; namespace CSharpESP.Renderers { public class BoneRenderer { // Humanoid bone joint pairs private static readonly (HumanBodyBones, HumanBodyBones)[] s_BonePairs = new (HumanBodyBones, HumanBodyBones)[] { // Head and Spine (HumanBodyBones.Head, HumanBodyBones.Neck), (HumanBodyBones.Neck, HumanBodyBones.Chest), (HumanBodyBones.Chest, HumanBodyBones.Spine), (HumanBodyBones.Spine, HumanBodyBones.Hips), // Left Arm (HumanBodyBones.Neck, HumanBodyBones.LeftShoulder), (HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm), (HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm), (HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand), // Right Arm (HumanBodyBones.Neck, HumanBodyBones.RightShoulder), (HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm), (HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm), (HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand), // Left Leg (HumanBodyBones.Hips, HumanBodyBones.LeftUpperLeg), (HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg), (HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot), // Right Leg (HumanBodyBones.Hips, HumanBodyBones.RightUpperLeg), (HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg), (HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot) }; public static void Render(Camera camera, Animator animator, Color color, float thickness = 1.2f) { if (animator == null || !animator.isHuman) return; // Cache bone screen positions to avoid duplicate projections Dictionary boneScreenMap = new Dictionary(); foreach (var pair in s_BonePairs) { if (!TryGetBoneScreenPos(camera, animator, pair.Item1, boneScreenMap, out Vector2 posA)) continue; if (!TryGetBoneScreenPos(camera, animator, pair.Item2, boneScreenMap, out Vector2 posB)) continue; RenderHelper.DrawLine(posA, posB, color, thickness); } // Draw Head marker if (TryGetBoneScreenPos(camera, animator, HumanBodyBones.Head, boneScreenMap, out Vector2 headScreen)) { float headRadius = 4f; Rect headRect = new Rect(headScreen.x - headRadius, headScreen.y - headRadius, headRadius * 2f, headRadius * 2f); RenderHelper.DrawBox(headRect, color, 1f); } } private static bool TryGetBoneScreenPos( Camera camera, Animator animator, HumanBodyBones bone, Dictionary cache, out Vector2 screenPos) { if (cache.TryGetValue(bone, out screenPos)) { return true; } Transform t = animator.GetBoneTransform(bone); if (t == null) { screenPos = Vector2.zero; return false; } if (MathUtils.WorldToScreen(camera, t.position, out screenPos)) { cache[bone] = screenPos; return true; } return false; } } }