{"version":3,"file":"MeshRope.mjs","sources":["../../../src/scene/mesh-simple/MeshRope.ts"],"sourcesContent":["import { definedProps } from '../container/utils/definedProps';\nimport { Mesh } from '../mesh/shared/Mesh';\nimport { RopeGeometry } from './RopeGeometry';\n\nimport type { PointData } from '../../maths/point/PointData';\nimport type { Texture } from '../../rendering/renderers/shared/texture/Texture';\nimport type { MeshOptions } from '../mesh/shared/Mesh';\n\n/**\n * Constructor options used for `MeshRope` instances. Allows configuration of a rope-like mesh\n * that follows a series of points with a texture applied.\n * @example\n * ```ts\n * // Create a basic rope with two points\n * const rope = new MeshRope({\n *     texture: Texture.from('snake.png'),\n *     points: [\n *         new Point(0, 0),\n *         new Point(100, 0)\n *     ]\n * });\n *\n * // Create a rope with high-quality texture scaling\n * const highQualityRope = new MeshRope({\n *     texture: Texture.from('rope-hd.png'),\n *     points: [\n *         new Point(0, 0),\n *         new Point(50, 25),\n *         new Point(100, 0)\n *     ],\n *     textureScale: 0.5  // Downscale HD texture for better quality\n * });\n * ```\n * @see {@link MeshRope} For the rope implementation\n * @see {@link RopeGeometry} For the underlying geometry\n * @category scene\n * @standard\n * @noInheritDoc\n */\nexport interface MeshRopeOptions extends Omit<MeshOptions, 'geometry'>\n{\n    /** The texture to use on the rope */\n    texture: Texture;\n\n    /** An array of points that determine the rope's shape and path */\n    points: PointData[];\n\n    /**\n     * Controls how the texture is scaled along the rope.\n     * - If 0 (default), the texture stretches to fit between points\n     * - If > 0, texture repeats with preserved aspect ratio\n     * - Larger textures with textureScale < 1 can reduce artifacts\n     * @default 0\n     */\n    textureScale?: number;\n}\n\n/**\n * A specialized mesh that renders a texture along a path defined by points. Perfect for\n * creating snake-like animations, chains, ropes, and other flowing objects.\n * @example\n * ```ts\n * // Create a snake with multiple segments\n * const points = [];\n * for (let i = 0; i < 20; i++) {\n *     points.push(new Point(i * 50, 0));\n * }\n *\n * const snake = new MeshRope({\n *     texture: Texture.from('snake.png'),\n *     points,\n *     textureScale: 0.5\n * });\n *\n * // Animate the snake\n * app.ticker.add((delta) => {\n *     const time = performance.now() / 1000;\n *\n *     // Update points to create wave motion\n *     for (let i = 0; i < points.length; i++) {\n *         points[i].y = Math.sin(i * 0.5 + time) * 30;\n *         points[i].x = (i * 50) + Math.cos(i * 0.3 + time) * 20;\n *     }\n * });\n *\n * // Disable auto updates if manually updating\n * snake.autoUpdate = false;\n * ```\n * @category scene\n * @standard\n */\nexport class MeshRope extends Mesh\n{\n    /**\n     * Default options for creating a MeshRope instance. These values are used when specific\n     * options aren't provided in the constructor.\n     * @example\n     * ```ts\n     * // Use default options globally\n     * MeshRope.defaultOptions = {\n     *     textureScale: 0.5  // Set higher quality texture scaling\n     * };\n     *\n     * // Create rope with modified defaults\n     * const rope = new MeshRope({\n     *     texture: Texture.from('rope.png'),\n     *     points: [\n     *         new Point(0, 0),\n     *         new Point(100, 0)\n     *     ]\n     * }); // Will use textureScale: 0.5\n     * ```\n     * @property {number} textureScale - Controls texture scaling along the rope (0 = stretch)\n     * @see {@link MeshRopeOptions} For all available options\n     */\n    public static defaultOptions: Partial<MeshRopeOptions> = {\n        textureScale: 0,\n    };\n\n    /**\n     * Controls whether the rope's vertices are automatically recalculated each frame based on\n     * its points. When true, the rope will update to follow point movements. When false,\n     * manual updates are required.\n     * @example\n     * ```ts\n     * const points = [];\n     * for (let i = 0; i < 20; i++) {\n     *     points.push(new Point(i * 50, 0));\n     * }\n     *\n     * const rope = new MeshRope({\n     *     texture: Texture.from('rope.png'),\n     *     points\n     * });\n     *\n     * // Auto-update (default)\n     * app.ticker.add(() => {\n     *     // Points will automatically update the rope\n     *     for (let i = 0; i < points.length; i++) {\n     *         points[i].y = Math.sin(i * 0.5 + performance.now() / 1000) * 30;\n     *     }\n     * });\n     *\n     * // Manual update\n     * rope.autoUpdate = false;\n     * app.ticker.add(() => {\n     *     // Update points\n     *     for (let i = 0; i < points.length; i++) {\n     *         points[i].y = Math.sin(i * 0.5 + performance.now() / 1000) * 30;\n     *     }\n     *     // Manually trigger update\n     *     (rope.geometry as RopeGeometry).update();\n     * });\n     * ```\n     * @default true\n     * @see {@link RopeGeometry#update} For manual geometry updates\n     */\n    public autoUpdate: boolean;\n\n    /**\n     * Note: The wrap mode of the texture is set to REPEAT if `textureScale` is positive.\n     * @param options\n     * @param options.texture - The texture to use on the rope.\n     * @param options.points - An array of {@link math.Point} objects to construct this rope.\n     * @param {number} options.textureScale - Optional. Positive values scale rope texture\n     * keeping its aspect ratio. You can reduce alpha channel artifacts by providing a larger texture\n     * and downsampling here. If set to zero, texture will be stretched instead.\n     */\n    constructor(options: MeshRopeOptions)\n    {\n        const { texture, points, textureScale, ...rest } = { ...MeshRope.defaultOptions, ...options };\n        const ropeGeometry = new RopeGeometry(definedProps({ width: texture.height, points, textureScale }));\n\n        if (textureScale > 0)\n        {\n            // attempt to set UV wrapping, will fail on non-power of two textures\n            texture.source.style.addressMode = 'repeat';\n        }\n        super(definedProps({\n            ...rest,\n            texture,\n            geometry: ropeGeometry,\n        }));\n\n        this.autoUpdate = true;\n\n        this.onRender = this._render;\n    }\n\n    private _render(): void\n    {\n        const geometry: RopeGeometry = this.geometry as any;\n\n        if (this.autoUpdate || geometry._width !== this.texture.height)\n        {\n            geometry._width = this.texture.height;\n            geometry.update();\n        }\n    }\n}\n"],"names":[],"mappings":";;;;;AA2FO,MAAM,SAAA,GAAN,MAAM,SAAA,SAAiB,IAAA,CAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4EI,YAAY,OAAA,EACZ;AACI,IAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,YAAA,EAAc,GAAG,IAAA,EAAK,GAAI,EAAE,GAAG,SAAA,CAAS,cAAA,EAAgB,GAAG,OAAA,EAAQ;AAC5F,IAAA,MAAM,YAAA,GAAe,IAAI,YAAA,CAAa,YAAA,CAAa,EAAE,KAAA,EAAO,OAAA,CAAQ,MAAA,EAAQ,MAAA,EAAQ,YAAA,EAAc,CAAC,CAAA;AAEnG,IAAA,IAAI,eAAe,CAAA,EACnB;AAEI,MAAA,OAAA,CAAQ,MAAA,CAAO,MAAM,WAAA,GAAc,QAAA;AAAA,IACvC;AACA,IAAA,KAAA,CAAM,YAAA,CAAa;AAAA,MACf,GAAG,IAAA;AAAA,MACH,OAAA;AAAA,MACA,QAAA,EAAU;AAAA,KACb,CAAC,CAAA;AAEF,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAElB,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,OAAA;AAAA,EACzB;AAAA,EAEQ,OAAA,GACR;AACI,IAAA,MAAM,WAAyB,IAAA,CAAK,QAAA;AAEpC,IAAA,IAAI,KAAK,UAAA,IAAc,QAAA,CAAS,MAAA,KAAW,IAAA,CAAK,QAAQ,MAAA,EACxD;AACI,MAAA,QAAA,CAAS,MAAA,GAAS,KAAK,OAAA,CAAQ,MAAA;AAC/B,MAAA,QAAA,CAAS,MAAA,EAAO;AAAA,IACpB;AAAA,EACJ;AACJ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA5Ga,SAAA,CAwBK,cAAA,GAA2C;AAAA,EACrD,YAAA,EAAc;AAClB,CAAA;AA1BG,IAAM,QAAA,GAAN;;;;"}