import { WonderlandEngine } from '../engine.js';
import { Resource, ResourceManager, ResourceType } from './resource.js';
/**
 * Material parameter type.
 */
export declare enum MaterialParamType {
    /** Unsigned integer parameter type. */
    UnsignedInt = 0,
    /** Integer parameter type. */
    Int = 1,
    /** 16-bit float parameter type. */
    HalfFloat = 2,
    /** Float parameter type. */
    Float = 3,
    /** Sampler resource parameter type, i.e., a {@link Texture}. */
    Sampler = 4,
    /**
     * Font resource parameter type.
     *
     * **Note**: Changing font isn't exposed yet and will raise an error.
     */
    Font = 5
}
/**
 * Constructor parameters object for a {@link Material} instance.
 *
 * @deprecated Use {@link MaterialManager#getTemplate} instead:
 *
 * ```js
 * const PhongMaterial = engine.materials.getTemplate('Phong Opaque');
 * const material = new PhongMaterial();
 * material.setDiffuseColor([1, 0, 0]);
 * ```
 */
export interface MaterialParameters {
    /** The name of the pipeline. */
    pipeline: string;
}
/**
 * Material constructor.
 *
 * Material classes are automatically generated by the runtime based on the
 * loaded scene shaders.
 */
export interface MaterialConstructor<T extends Material = Material> {
    /**
     * Set of the dynamic parameters that exist on the definition.
     *
     * For instance, the set would contain elements such as `ambientColor`, `diffuseColor`
     * for a Phong material.
     */
    readonly Parameters: Set<string>;
    /**
     * Create a new Material.
     *
     * The material is created from the pipeline associated to the material class.
     *
     * @note Creating material is expensive. Please use {@link Material#clone} to clone a material.
     * @note Do not use this constructor directly with an index, this is reserved for internal purposes.
     */
    new (index?: number): T;
}
/**
 * Wrapper around a native material.
 *
 * For more information about how to create materials, have a look at the
 * {@link MaterialManager} class.
 *
 * #### Properties
 *
 * The material properties are automatically converted into getters/setters:
 *
 * ```js
 * const material = new PhongMaterial();
 *
 * // Set the `diffuseColor` property
 * material.setDiffuseColor([1.0, 0.0, 0.0, 1.0]);
 * console.log(material.getDiffuseColor());
 * ```
 *
 * Getters for non-scalar types have an optional argument to skip an array
 * allocation:
 *
 * ```js
 * const material = new PhongMaterial();
 * const diffuse = [0, 0, 0, 0];
 * material.getDiffuseColor(diffuse);
 * console.log(diffuse) // Prints '[1.0, 1.0, 1.0, 1.0]'
 * ```
 *
 * @note Materials are **per-engine**, they can thus be shared by multiple scenes.
 *
 * #### TypeScript
 *
 * The Wonderland Editor can automatically generate material definitions (.d.ts)
 * from the project pipelines.
 *
 * To enable the generation, go to the `Project Settings > JavaScript` panel and
 * set `materialDefinitions` to a path, e.g., `materials.d.ts`.
 *
 * It's then possible to cast the material type using:
 *
 * ```ts
 * // Note the `.js` instead of `.d.ts`
 * import {PhongOpaque} from './materials.js';
 *
 * const mesh = object.getComponent('mesh');
 * const material = mesh.material as PhongOpaque;
 * material.setDiffuseColor([1, 0, 0, 1]); // Set a red diffuse
 * ```
 *
 * @since 1.2.0
 */
export declare class Material extends Resource {
    /** @hidden */
    static getResourceType(): ResourceType;
    /**
     * @deprecated Use {@link MaterialManager#getTemplate} via {@link WonderlandEngine.materials}
     * to create a new material with a given pipeline:
     *
     * ```js
     * const PhongMaterial = engine.materials.getTemplate('Phong Opaque');
     * const material = new PhongMaterial();
     * material.setDiffuseColor([1, 0, 0]);
     * ```
     */
    constructor(engine: WonderlandEngine, params: number | MaterialParameters);
    /**
     * Check whether a parameter exists on this material.
     *
     * @param name The name to check.
     * @returns `true` if the parameter with name `name` exists on this material,
     *     `false` otherwise.
     */
    hasParameter(name: string): boolean;
    /** @deprecated Use {@link pipeline} instead. */
    get shader(): string;
    /** Name of the pipeline used by this material. */
    get pipeline(): string;
    /**
     * Create a copy of the underlying native material.
     *
     * @returns Material clone.
     */
    clone(): Material | null;
    toString(): string;
    /**
     * Wrap a native material index.
     *
     * @param engine Engine instance.
     * @param index The index.
     * @returns Material instance or `null` if index <= 0.
     *
     * @deprecated Use the {@link WonderlandEngine.materials} instead.
     */
    static wrap(engine: WonderlandEngine, index: number): Material | null;
}
/**
 * Manage materials.
 *
 * #### Creation
 *
 * To create a material, first retrieve the class associated to
 * the pipeline using {@link MaterialManager.getTemplate}:
 *
 * ```js
 * const PhongMaterial = engine.materials.getTemplate('Phong Opaque');
 * ```
 *
 * Creating a material is then done using the constructor:
 *
 * ```js
 * const material = new PhongMaterial();
 * material.setDiffuseColor([1.0, 0.0, 0.0, 1.0]);
 * ```
 */
export declare class MaterialManager extends ResourceManager<Material> {
    /** Material classes. @hidden. */
    private readonly _materialTemplates;
    /** @hidden */
    constructor(engine: WonderlandEngine);
    /** @override */
    wrap(index: number): Material | null;
    /**
     * Get the material class with the given pipeline name.
     *
     * #### Usage
     *
     * ```js
     * const PhongMaterial = engine.materials.getTemplate('Phong Opaque');
     * const material = new PhongMaterial();
     * material.setDiffuseColor([1.0, 0.0, 0.0, 1.0]);
     * ```
     *
     * #### TypeScript
     *
     * This method provide a simple way to cast the constructor returned by `getTemplate`:
     *
     * ```ts
     * interface Phong {
     *     getAmbientColor(out?: Float32Array): Float32Array;
     *     setAmbientColor(value: NumberArray): void;
     * }
     * const PhongMaterial = engine.materials.getTemplate<Phong>('Phong Opaque');
     * const mat = new PhongMaterial(); // `mat` is of type `Phong`
     * ```
     *
     * However, this means manually writing types for each pipeline.
     *
     * Fortunately, The Wonderland Editor can automatically generate material definitions (.d.ts)
     * from the project pipelines.
     *
     * To enable the generation, go to the `Project Settings > JavaScript` panel and
     * set `materialDefinitions` to a path, e.g., `materials.d.ts`.
     *
     * Material constructors will then be typed automatically when using a string literal pipeline name:
     *
     * ```ts
     * // Note the `.js` instead of `.d.ts`
     * import {PhongOpaque} from './materials.js';
     *
     * const PhongMaterial = engine.materials.getTemplate('Phong Opaque');
     * const mat = new PhongMaterial(); // `mat` is of type `PhongOpaque`
     * ```
     *
     * @param pipeline The pipeline name to search for.
     * @returns The material class.
     *
     * @throws `Error` if the material class doesn't exist.
     */
    getTemplate<T extends Material = Material>(pipeline: string): MaterialConstructor<T>;
    /**
     * Wrap a material instance.
     *
     * @todo: Remove at 2.0.0.
     *
     * @note Wrapping should only be called once per instance.
     *
     * @param instance The material instance.
     * @returns The new material, wrapped in a proxy.
     */
    _wrapInstance(instance: Material): Material;
    /**
     * Cache all pipeline definitions.
     *
     * @hidden
     */
    private _cacheDefinitions;
    /**
     * Create a material class from a definition index.
     *
     * @param wasm The WASM instance.
     * @param definitionIndex The definition index to wrap.
     * @returns The material class.
     */
    private _createMaterialTemplate;
}
