"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var import_node_test = __toESM(require("node:test"));
var import_strict = __toESM(require("node:assert/strict"));
var THREE = __toESM(require("three"));
var import_promises = require("node:fs/promises");
var import_node_path = __toESM(require("node:path"));
var import_node_url = require("node:url");
var import_boxel_core = require("@playdrop/boxel-core");
var import_skinned_mesh = require("../src/skinned-mesh.js");
const import_meta = {};
const HERE = import_node_path.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
const fixture = (...segments) => import_node_path.default.resolve(HERE, "./fixtures", ...segments);
(0, import_node_test.default)("buildEntitySkinnedMesh exposes atlas and connect stats", async () => {
  const entityRaw = await (0, import_promises.readFile)(fixture("entity-connect.json"), "utf-8");
  const entity = (0, import_boxel_core.parseBoxel)(JSON.parse(entityRaw));
  const result = (0, import_skinned_mesh.buildEntitySkinnedMesh)({ THREE, entity });
  try {
    const { mesh, stats } = result;
    import_strict.default.ok(mesh instanceof THREE.SkinnedMesh, "skinned mesh returned");
    import_strict.default.ok(!Array.isArray(mesh.material), "single material used");
    const material = mesh.material;
    import_strict.default.strictEqual(material.skinning, true);
    import_strict.default.ok(stats.atlas === null || typeof stats.atlas === "object", "atlas info present (or null)");
    const breakdown = stats.connectBreakdown;
    import_strict.default.deepEqual(Object.keys(breakdown).sort(), ["Chest"], "connect breakdown captured child node");
    import_strict.default.ok(breakdown.Chest.childVertices > 0, "child vertices blended");
    import_strict.default.ok(breakdown.Chest.parentVertices > 0, "parent vertices blended");
    const geometry = mesh.geometry;
    const connectStrength = geometry.getAttribute("connectStrength");
    import_strict.default.ok(connectStrength, "connect strength attribute exists");
    let sawHalf = false;
    let sawFull = false;
    for (let i = 0; i < connectStrength.count; i += 1) {
      const value = connectStrength.getX(i);
      if (Math.abs(value - 0.5) < 1e-3)
        sawHalf = true;
      if (Math.abs(value - 1) < 1e-3)
        sawFull = true;
    }
    import_strict.default.ok(sawHalf, "detected vertices blending 50/50");
    import_strict.default.ok(sawFull || !breakdown.Chest.childVertices || sawHalf, "detected vertices fully or partially reassigned when expected");
    const skinWeights = geometry.getAttribute("skinWeight");
    import_strict.default.ok(skinWeights, "skin weights present");
    for (let i = 0; i < skinWeights.count; i += 1) {
      const sum = skinWeights.getX(i) + skinWeights.getY(i) + skinWeights.getZ(i) + skinWeights.getW(i);
      import_strict.default.ok(Math.abs(sum - 1) < 1e-3, "weights normalised per vertex");
    }
  } finally {
    result.dispose();
  }
});
