import { Scene } from "../../scene/index.js";
export class A3DScene extends Scene {
    geometryLibrary = new Map();
    materialLibrary = new Map();
    morphTargetLibrary = new Map();
    generatedGeometryId = 0;
    generatedMaterialId = 0;
    addGeometry(id, geometry) {
        if (!id.trim())
            throw new Error("A3DScene geometry id is required.");
        this.geometryLibrary.set(id, geometry);
        return this;
    }
    addMaterial(id, material) {
        if (!id.trim())
            throw new Error("A3DScene material id is required.");
        this.materialLibrary.set(id, material);
        return this;
    }
    addMorphTargets(id, morphTargets) {
        if (!id.trim())
            throw new Error("A3DScene morph target id is required.");
        this.morphTargetLibrary.set(id, morphTargets);
        return this;
    }
    createRenderableMesh(options) {
        const geometry = this.resolveGeometryHandle(options.geometry, options.geometryId);
        const material = this.resolveMaterialHandle(options.material, options.materialId);
        const mesh = this.createMesh({
            ...options,
            renderable: { geometry, material }
        });
        this.root.addChild(mesh);
        return mesh;
    }
    toRenderSource(options = {}) {
        return {
            cameraPolicy: "auto-frame",
            frustumCulling: true,
            ...options,
            scene: this,
            geometryLibrary: options.geometryLibrary ?? this.geometryLibrary,
            materialLibrary: options.materialLibrary ?? this.materialLibrary,
            morphTargetLibrary: options.morphTargetLibrary ?? this.morphTargetLibrary
        };
    }
    dispose() {
        super.dispose();
        for (const geometry of this.geometryLibrary.values())
            geometry.dispose();
        for (const material of this.materialLibrary.values()) {
            if (isDisposableResource(material))
                material.dispose();
        }
        this.geometryLibrary.clear();
        this.materialLibrary.clear();
        this.morphTargetLibrary.clear();
    }
    resolveGeometryHandle(geometry, preferredId) {
        if (typeof geometry === "string") {
            if (!this.geometryLibrary.has(geometry))
                throw new Error(`A3DScene missing geometry resource: ${geometry}`);
            return geometry;
        }
        const id = preferredId ?? `geometry:${++this.generatedGeometryId}`;
        this.addGeometry(id, geometry);
        return id;
    }
    resolveMaterialHandle(material, preferredId) {
        if (typeof material === "string") {
            if (!this.materialLibrary.has(material))
                throw new Error(`A3DScene missing material resource: ${material}`);
            return material;
        }
        const id = preferredId ?? `material:${++this.generatedMaterialId}`;
        this.addMaterial(id, material);
        return id;
    }
}
function isDisposableResource(value) {
    return typeof value === "object" && value !== null && "dispose" in value && typeof value.dispose === "function";
}
//# sourceMappingURL=A3DScene.js.map