import { BufferGeometry, Camera, Color, IUniform, Material, MaterialEventMap, MaterialParameters, Object3D, Scene, WebGLProgramParametersWithUniforms, WebGLRenderer } from 'three';
import { IDisposable, IJSONSerializable } from 'ts-browser-helpers';
import { MaterialExtension } from '../materials';
import { ChangeEvent, IUiConfigContainer } from 'uiconfig.js';
import { SerializationMetaType, AnimateTime } from '../utils';
import { IObject3D, ISetDirtyCommonOptions } from './IObject';
import { ITexture } from './ITexture';
import { IImportResultUserData } from '../assetmanager';
export type IMaterialParameters = MaterialParameters & {
    customMaterialExtensions?: MaterialExtension[];
};
export interface IMaterialEventMap extends MaterialEventMap {
    beforeCompile: {
        shader: WebGLProgramParametersWithUniforms;
        renderer: WebGLRenderer;
    };
    beforeRender: {
        renderer: WebGLRenderer;
        scene: Scene;
        camera: Camera;
        geometry: BufferGeometry;
        object: Object3D;
    };
    afterRender: {
        renderer: WebGLRenderer;
        scene: Scene;
        camera: Camera;
        geometry: BufferGeometry;
        object: Object3D;
    };
    /**
     * Fires when the material is set/added to a mesh
     * This is applicable of all types of Object3D, like Line etc, not just Mesh
     */
    addToMesh: {
        object: Object3D;
    };
    /**
     * Fires when the material is changed/removed to a mesh
     * This is applicable of all types of Object3D, like Line etc, not just Mesh
     */
    removeFromMesh: {
        object: Object3D;
    };
    /**
     * For internal use
     */
    beforeDeserialize: {
        data: unknown;
        meta?: SerializationMetaType;
        bubbleToObject: boolean;
        bubbleToParent: boolean;
    };
}
declare module 'three' {
    interface MaterialEventMap {
        materialUpdate: {
            bubbleToObject?: boolean;
            bubbleToParent?: boolean;
            uiChangeEvent?: ChangeEvent;
        } & IMaterialSetDirtyOptions;
        textureUpdate: {
            texture: ITexture;
            bubbleToObject?: boolean;
            bubbleToParent?: boolean;
            uiChangeEvent?: ChangeEvent;
        };
        select: {
            ui?: boolean;
            bubbleToObject?: boolean;
            bubbleToParent?: boolean;
            material: IMaterial;
            value?: /* IObject3D | */ IMaterial | null;
            source?: string;
        };
    }
}
export interface IMaterialSetDirtyOptions extends ISetDirtyCommonOptions {
    /**
     * @default true
     */
    bubbleToObject?: boolean;
    /**
     * @default true
     */
    needsUpdate?: boolean;
    /**
     * Change identifier that triggered the `setDirty` call.
     * This is different from `key` in that it is used to identify the property/key that is changed. In many cases these could be same, but they could also be different eg, key might be x, with change being position.
     */
    change?: string | keyof IMaterial;
    [key: string]: any;
}
export interface IMaterialUserData extends IImportResultUserData {
    uuid?: string;
    /**
     * Automatically dispose material when not used by any object in the scene
     * @default true
     */
    disposeOnIdle?: boolean;
    renderToGBuffer?: boolean;
    /**
     * Same as {@link renderToGBuffer} but for depth only, not normal or flags etc
     */
    renderToDepth?: boolean;
    /**
     * Flag to tell the scene to prefer `material.envMapIntensity` over `scene.envMapIntensity`
     * only for materials that have envMapIntensity
     */
    separateEnvMapIntensity?: boolean;
    /**
     * The environment map to use in the `RootScene`. To use this, object with the material must be in the RootScene, and the key should exist in the `RootScene`'s `textureSlots`.
     *
     * only for materials that have envMap
     */
    envMapSlotKey?: string;
    /**
     * Automatically register this material in the {@link MaterialManager} when added to the scene.
     * This provides hook to other plugins to extend the material, add uiconfig etc.
     * @default true
     */
    autoRegisterInManager?: boolean;
    cloneId?: string;
    cloneCount?: number;
    __envIntensity?: number;
    __isVariation?: boolean;
    inverseAlphaMap?: boolean;
    /**
     * See {@link MaterialManager.dispose} as {@link BaseGroundPlugin._refreshMaterial}
     */
    runtimeMaterial?: boolean;
    /**
     * See {@link GBufferPlugin}
     */
    gBufferData?: {
        materialId?: number;
        /**
         * @default true
         */
        tonemapEnabled?: boolean;
        [key: string]: any;
    };
    /**
     * Force a depth value in GBuffer.
     * This is useful to force center values like 0 to the depth.
     */
    forcedLinearDepth?: number;
    /**
     * General flag to disable multiple plugins on the material at once, like SSAO, SSR, Bloom etc.
     */
    pluginsDisabled?: boolean;
    /**
     * For SSCSPlugin
     */
    sscsDisabled?: boolean;
    /**
     * For SSRPlugin
     */
    ssreflDisabled?: boolean;
    /**
     * For SSRPlugin
     */
    ssreflNonPhysical?: boolean;
    [key: string]: any;
    /**
     * @deprecated
     */
    setDirty?: (options?: IMaterialSetDirtyOptions) => void;
    /**
     * @deprecated Use {@link postTonemap.tonemapEnabled} instead. This is kept because used in old files.
     */
    postTonemap?: boolean;
}
export interface AnimateTimeMaterial extends AnimateTime {
    from?: IMaterial;
}
export interface IMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends Material<TE>, IJSONSerializable, IDisposable, IUiConfigContainer {
    constructor: {
        TYPE: string;
        TypeSlug: string;
        MaterialProperties?: Record<string, any>;
        MapProperties?: string[];
        InterpolateProperties?: string[];
        MaterialTemplate?: IMaterialTemplate;
    };
    assetType: 'material';
    setDirty(options?: IMaterialSetDirtyOptions): void;
    needsUpdate: boolean;
    setValues(parameters: Material | (MaterialParameters & {
        type?: string;
    }), allowInvalidType?: boolean, clearCurrentUserData?: boolean, time?: AnimateTimeMaterial): this;
    toJSON(meta?: SerializationMetaType, _internal?: boolean): any;
    fromJSON(json: any, meta?: SerializationMetaType, _internal?: boolean): this | null;
    extraUniformsToUpload: Record<string, IUniform>;
    materialExtensions: MaterialExtension[];
    registerMaterialExtensions: (customMaterialExtensions: MaterialExtension[]) => void;
    unregisterMaterialExtensions: (customMaterialExtensions: MaterialExtension[]) => void;
    /**
     * Managed internally, do not change manually
     */
    generator?: IMaterialGenerator;
    /**
     * Objects in the scene that are using this material.
     * This is set in the {@link Object3DManager} when the objects are added/removed from the scene. Do not modify this set directly.
     */
    appliedMeshes: Set<IObject3D>;
    lastShader?: WebGLProgramParametersWithUniforms;
    userData: IMaterialUserData;
    /**
     * Disposes the material from the GPU.
     * Set force to false if not sure the material is used by any object in the scene.
     * // todo add check for visible in scene also? or is that overkill
     * @param force - when true, same as three.js dispose. when false, only disposes if disposeOnIdle not false and not used by any object in the scene. default: true
     */
    dispose(force?: boolean): void;
    /**
     * Clones the Material.
     * This is a shallow clone, so the properties are copied by reference.
     *
     * @param track - if true, the clone id and count will be tracked in the userData and a suffix will be appended to the name. default - false
     */
    clone(track?: boolean): this;
    flatShading?: boolean;
    map?: ITexture | null;
    alphaMap?: ITexture | null;
    envMap?: ITexture | null;
    envMapIntensity?: number;
    aoMap?: ITexture | null;
    lightMap?: ITexture | null;
    normalMap?: ITexture | null;
    bumpMap?: ITexture | null;
    displacementMap?: ITexture | null;
    aoMapIntensity?: number;
    lightMapIntensity?: number;
    roughnessMap?: ITexture | null;
    metalnessMap?: ITexture | null;
    roughness?: number;
    metalness?: number;
    transmissionMap?: ITexture | null;
    transmission?: number;
    color?: Color;
    wireframe?: boolean;
    linewidth?: number;
    isRawShaderMaterial?: boolean;
    isPhysicalMaterial?: boolean;
    isLineMaterial?: boolean;
    isUnlitMaterial?: boolean;
    isGBufferMaterial?: boolean;
    isLineMaterial2?: boolean;
    isUnlitLineMaterial?: boolean;
}
export type IMaterialGenerator<T extends IMaterial = IMaterial> = (params: any) => T;
export interface IMaterialTemplate<T extends IMaterial = IMaterial, TP = any> {
    templateUUID?: string;
    name: string;
    typeSlug?: string;
    alias?: string[];
    materialType: string;
    generator?: IMaterialGenerator<T>;
    params?: TP;
}
//# sourceMappingURL=IMaterial.d.ts.map