var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var scene_exports = {};
__export(scene_exports, {
  createBoxelNodeScene: () => createBoxelNodeScene,
  createBoxelScene: () => createBoxelScene
});
module.exports = __toCommonJS(scene_exports);
var import_context = require("./context.js");
var import_nodes = require("./nodes.js");
var import_animations = require("./animations.js");
var import_overlays = require("./overlays.js");
function normalizeNodeFilter(nodes) {
  if (!nodes)
    return null;
  if (Array.isArray(nodes)) {
    return new Set(nodes);
  }
  return /* @__PURE__ */ new Set([nodes]);
}
function createBoxelScene(context, options = {}) {
  const { THREE, entity } = context;
  const nodeFilter = normalizeNodeFilter(options.nodes);
  const builderContext = (0, import_context.createBuilderContext)({
    THREE,
    settings: { enableShadows: false }
  });
  (0, import_context.updateBuilderContext)(builderContext, { entity });
  const root = new THREE.Group();
  const nodeObjects = /* @__PURE__ */ new Map();
  const overlayHandles = [];
  const gatherNode = (nodeId) => {
    const node = entity.geometry.root.id === nodeId ? entity.geometry.root : (function find(current) {
      if (current.id === nodeId)
        return current;
      for (const child of current.children) {
        const result = find(child);
        if (result)
          return result;
      }
      return null;
    })(entity.geometry.root);
    if (!node) {
      console.warn("[boxel-three] node not found", nodeId);
      return null;
    }
    const { object, nodes } = (0, import_nodes.buildNodeObject)(builderContext, node);
    nodes.forEach((nodeObject, id) => {
      nodeObjects.set(id, {
        id,
        object: nodeObject,
        primitiveId: nodeObject.userData?.primitiveId,
        connectMode: nodeObject.userData?.connectMode ?? "none"
      });
    });
    return object;
  };
  if (nodeFilter) {
    nodeFilter.forEach((nodeId) => {
      const object = gatherNode(nodeId);
      if (object) {
        root.add(object);
      }
    });
  } else {
    const { object, nodes } = (0, import_nodes.buildNodeObject)(builderContext, entity.geometry.root);
    root.add(object);
    nodes.forEach((nodeObject, id) => {
      nodeObjects.set(id, {
        id,
        object: nodeObject,
        primitiveId: nodeObject.userData?.primitiveId,
        connectMode: nodeObject.userData?.connectMode ?? "none"
      });
    });
  }
  const applyOverlays = (overlayOptions) => {
    if (!overlayOptions)
      return;
    const style = {
      color: overlayOptions.color,
      opacity: overlayOptions.opacity,
      dashed: overlayOptions.dashed
    };
    const rootId = entity.geometry.root.id;
    nodeObjects.forEach((meta) => {
      const request = {
        ...style,
        origin: overlayOptions.origin && meta.id === rootId,
        bounds: overlayOptions.bounds && Boolean(meta.object.userData?.size),
        sockets: overlayOptions.sockets && Boolean(meta.object.userData?.sockets)
      };
      if (!request.origin && !request.bounds && !request.sockets) {
        return;
      }
      const handles = (0, import_overlays.attachBoxelOverlays)({ THREE, target: meta.object }, request);
      overlayHandles.push(handles);
    });
  };
  applyOverlays(options.overlays);
  const animationMeta = (0, import_animations.buildAnimations)(THREE, entity, new Map(Array.from(nodeObjects.entries()).map(([id, meta]) => [id, meta.object])));
  const clips = animationMeta.map((animation) => animation.clip);
  const resources = {
    materials: [],
    textures: [],
    geometries: []
  };
  root.traverse((object) => {
    if (object instanceof THREE.Mesh) {
      const mesh = object;
      const material = mesh.material;
      const collectMaterial = (mat) => {
        resources.materials.push(mat);
        if ("map" in mat && mat.map)
          resources.textures.push(mat.map);
        if ("emissiveMap" in mat && mat.emissiveMap)
          resources.textures.push(mat.emissiveMap);
      };
      if (Array.isArray(material)) {
        material.forEach((mat) => collectMaterial(mat));
      } else if (material) {
        collectMaterial(material);
      }
      if (mesh.geometry) {
        resources.geometries.push(mesh.geometry);
      }
    }
  });
  const dispose = () => {
    overlayHandles.splice(0).forEach((handles) => handles.dispose());
    resources.geometries.forEach((geometry) => geometry.dispose?.());
    resources.materials.forEach((material) => material.dispose?.());
    resources.textures.forEach((texture) => texture.dispose?.());
    nodeObjects.clear();
    root.clear();
  };
  return {
    root,
    nodes: nodeObjects,
    animations: animationMeta,
    clips,
    resources,
    dispose
  };
}
function createBoxelNodeScene(context, nodeId, options = {}) {
  return createBoxelScene(context, { ...options, nodes: nodeId });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  createBoxelNodeScene,
  createBoxelScene
});
