Source: scene/mesh/shared/Mesh.ts

import { deprecation, v8_0_0 } from '../../../utils/logging/deprecation';
import { Container } from '../../container/Container';
import { definedProps } from '../../container/utils/definedProps';
import { MeshGeometry } from './MeshGeometry';
import { MeshView } from './MeshView';

import type { Topology } from '../../../rendering/renderers/shared/geometry/const';
import type { State } from '../../../rendering/renderers/shared/state/State';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { ContainerOptions } from '../../container/Container';
import type { MeshViewOptions, TextureShader } from './MeshView';

/**
 * Options for the Mesh constructor.
 * @memberof scene
 */
export type MeshOptions<
    GEOMETRY extends MeshGeometry = MeshGeometry,
    SHADER extends TextureShader = TextureShader
> = Partial<ContainerOptions<MeshView<GEOMETRY, SHADER>>> & MeshViewOptions<GEOMETRY, SHADER>;

/**
 * Base mesh class.
 *
 * This class empowers you to have maximum flexibility to render any kind of WebGL/WebGPU visuals you can think of.
 * This class assumes a certain level of WebGL/WebGPU knowledge.
 * If you know a bit this should abstract enough away to make your life easier!
 *
 * Pretty much ALL WebGL/WebGPU can be broken down into the following:
 * - Geometry - The structure and data for the mesh. This can include anything from positions, uvs, normals, colors etc..
 * - Shader - This is the shader that PixiJS will render the geometry with (attributes in the shader must match the geometry)
 * - State - This is the state of WebGL required to render the mesh.
 *
 * Through a combination of the above elements you can render anything you want, 2D or 3D!
 * @memberof scene
 */
export class Mesh<
    GEOMETRY extends MeshGeometry = MeshGeometry,
    SHADER extends TextureShader = TextureShader
> extends Container<MeshView<GEOMETRY, SHADER>>
{
    constructor(options: MeshOptions<GEOMETRY, SHADER>);
    /** @deprecated since 8.0.0 */
    constructor(geometry: GEOMETRY, shader: SHADER, state?: State, drawMode?: Topology);
    constructor(...args: [MeshOptions<GEOMETRY, SHADER>] | [GEOMETRY, SHADER, State?, Topology?])
    {
        let options = args[0];

        if (options instanceof MeshGeometry)
        {
            deprecation(v8_0_0, 'Mesh: use new Mesh({ geometry, shader }) instead');

            options = {
                geometry: options,
                shader: args[1],
            } as MeshOptions<GEOMETRY, SHADER>;

            if (args[3])
            {
                deprecation(v8_0_0, 'Mesh: drawMode argument has been removed, use geometry.topology instead');
                options.geometry.topology = args[3];
            }
        }

        const { geometry, shader, texture, ...rest } = options;

        super({
            view: new MeshView(definedProps({ geometry, shader, texture })),
            label: 'Mesh',
            ...rest
        });

        this.allowChildren = false;
    }

    /** The texture that the Mesh uses. Null for non-MeshMaterial shaders */
    get texture()
    {
        return this.view.texture;
    }

    set texture(value: Texture)
    {
        this.view.texture = value;
    }

    /**
     * Includes vertex positions, face indices, colors, UVs, and
     * custom attributes within buffers, reducing the cost of passing all
     * this data to the GPU. Can be shared between multiple Mesh objects.
     */
    get geometry()
    {
        return this.view.geometry;
    }

    set geometry(value: GEOMETRY)
    {
        this.view.geometry = value;
    }

    /** Alias for shader. */
    get material()
    {
        deprecation(v8_0_0, 'mesh.material property has been removed, use mesh.shader instead');

        return this.view.shader;
    }

    /**
     * Represents the vertex and fragment shaders that processes the geometry and runs on the GPU.
     * Can be shared between multiple Mesh objects.
     */
    get shader()
    {
        return this.view.shader;
    }

    /** Whether or not to round the x/y position of the mesh. */
    get roundPixels()
    {
        return !!this.view.roundPixels;
    }

    set roundPixels(value: boolean)
    {
        this.view.roundPixels = value ? 1 : 0;
    }
}