import '../../../material/shader/helper.js';
import { LambertMaterial } from '../../../material/lambert.js';
import { BlinnMaterial } from '../../../material/blinn.js';
import { UnlitMaterial } from '../../../material/unlit.js';
import { ParticleMaterial } from '../../../material/particle.js';
import '@zephyr3d/device';
import '../../../values.js';
import { Vector3, Vector2, Vector4 } from '@zephyr3d/base';
import { MeshMaterial } from '../../../material/meshmaterial.js';
import '../../../material/grassmaterial.js';
import '../../../material/terrain-cm.js';
import { PBRMetallicRoughnessMaterial } from '../../../material/pbrmr.js';
import { PBRSpecularGlossinessMaterial } from '../../../material/pbrsg.js';
import { PBRBluePrintMaterial } from '../../../material/pbrblueprint.js';
import { SpriteMaterial } from '../../../material/sprite.js';
import { StandardSpriteMaterial } from '../../../material/sprite_std.js';
import { SpriteBlueprintMaterial } from '../../../material/spriteblueprint.js';
import { defineProps } from '../types.js';
import { getMeshMaterialInstanceUniformsClass, getTextureProps } from './common.js';

function getPBRCommonProps(manager) {
    return defineProps([
        {
            name: 'IOR',
            description: 'Index of refraction for the material surface',
            type: 'float',
            default: 1.5,
            options: {
                animatable: true
            },
            get (value) {
                value.num[0] = this.ior;
            },
            set (value) {
                this.ior = value.num[0];
            },
            isValid () {
                return !this.$isInstance;
            }
        },
        {
            name: 'OcclusionStrength',
            description: 'Strength multiplier for the occlusion texture effect',
            type: 'float',
            phase: 2,
            default: 1,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1
            },
            get (value) {
                value.num[0] = this.occlusionStrength;
            },
            set (value) {
                this.occlusionStrength = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.occlusionTexture;
            }
        },
        ...getTextureProps(manager, 'occlusionTexture', '2D', false, 0),
        {
            name: 'EmissiveColor',
            description: 'Base self-illumination color emitted by the material',
            type: 'rgb',
            options: {
                animatable: true
            },
            get (value) {
                value.num[0] = this.emissiveColor.x;
                value.num[1] = this.emissiveColor.y;
                value.num[2] = this.emissiveColor.z;
            },
            set (value) {
                this.emissiveColor = new Vector3(value.num[0], value.num[1], value.num[2]);
            },
            getDefaultValue () {
                return this.$isInstance ? this.coreMaterial.emissiveColor : [
                    0,
                    0,
                    0
                ];
            }
        },
        {
            name: 'EmissiveStrength',
            description: 'Intensity multiplier for the emissive color and emissive texture',
            type: 'float',
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1
            },
            get (value) {
                value.num[0] = this.emissiveStrength;
            },
            set (value) {
                this.emissiveStrength = value.num[0];
            },
            getDefaultValue () {
                return this.$isInstance ? this.coreMaterial.emissiveStrength : 1;
            }
        },
        ...getTextureProps(manager, 'emissiveTexture', '2D', true, 0),
        ...getTextureProps(manager, 'specularTexture', '2D', false, 0),
        {
            name: 'Transmission',
            description: 'If true, enables light transmission through the material',
            type: 'bool',
            phase: 0,
            default: false,
            get (value) {
                value.bool[0] = this.transmission;
            },
            set (value) {
                this.transmission = value.bool[0];
            },
            isValid () {
                return !this.$isInstance;
            }
        },
        {
            name: 'TransmissionFactor',
            description: 'Amount of transmitted light, from fully opaque to fully transparent',
            type: 'float',
            phase: 1,
            default: 0,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1
            },
            get (value) {
                value.num[0] = this.transmissionFactor;
            },
            set (value) {
                this.transmissionFactor = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.transmission;
            }
        },
        ...getTextureProps(manager, 'transmissionTexture', '2D', false, 1, function() {
            return this.transmission;
        }),
        {
            name: 'ThicknessFactor',
            description: 'Physical thickness used by transmission and volume attenuation',
            type: 'float',
            phase: 1,
            default: 0,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 99999
            },
            get (value) {
                value.num[0] = this.thicknessFactor;
            },
            set (value) {
                this.thicknessFactor = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.transmission;
            }
        },
        ...getTextureProps(manager, 'thicknessTexture', '2D', false, 1, function() {
            return this.transmission;
        }),
        {
            name: 'AttenuationColor',
            description: 'Color tint applied to transmitted light as it travels through the material',
            type: 'rgb',
            phase: 1,
            default: [
                1,
                1,
                1
            ],
            options: {
                animatable: true
            },
            get (value) {
                value.num[0] = this.attenuationColor.x;
                value.num[1] = this.attenuationColor.y;
                value.num[2] = this.attenuationColor.z;
            },
            set (value) {
                this.attenuationColor = new Vector3(value.num[0], value.num[1], value.num[2]);
            },
            isValid () {
                return !this.$isInstance && !!this.transmission;
            }
        },
        {
            name: 'AttenuationDistance',
            description: 'Distance over which transmitted light is attenuated inside the material',
            type: 'float',
            phase: 1,
            default: 99999,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 99999
            },
            get (value) {
                value.num[0] = this.attenuationDistance;
            },
            set (value) {
                this.attenuationDistance = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.transmission;
            }
        },
        {
            name: 'Iridescence',
            description: 'If true, enables thin-film iridescence on the material surface',
            type: 'bool',
            phase: 0,
            default: false,
            get (value) {
                value.bool[0] = this.iridescence;
            },
            set (value) {
                this.iridescence = value.bool[0];
            },
            isValid () {
                return !this.$isInstance;
            }
        },
        {
            name: 'IridescenceFactor',
            description: 'Strength of the iridescence effect',
            type: 'float',
            phase: 1,
            default: 0,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1
            },
            get (value) {
                value.num[0] = this.iridescenceFactor;
            },
            set (value) {
                this.iridescenceFactor = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.iridescence;
            }
        },
        ...getTextureProps(manager, 'iridescenceTexture', '2D', false, 1, function() {
            return this.iridescence;
        }),
        {
            name: 'IridescenceIOR',
            description: 'Index of refraction used for the iridescence layer',
            type: 'float',
            phase: 1,
            default: 1.3,
            options: {
                animatable: true
            },
            get (value) {
                value.num[0] = this.iridescenceIor;
            },
            set (value) {
                this.iridescenceIor = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.iridescence;
            }
        },
        {
            name: 'IridescenceThicknessMin',
            description: 'Minimum thin-film thickness used for iridescence, typically in nanometers',
            type: 'float',
            phase: 1,
            default: 100,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1000
            },
            get (value) {
                value.num[0] = this.iridescenceThicknessMin;
            },
            set (value) {
                this.iridescenceThicknessMin = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.iridescence;
            }
        },
        {
            name: 'IridescenceThicknessMax',
            description: 'Maximum thin-film thickness used for iridescence, typically in nanometers',
            type: 'float',
            phase: 1,
            default: 400,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1000
            },
            get (value) {
                value.num[0] = this.iridescenceThicknessMax;
            },
            set (value) {
                this.iridescenceThicknessMax = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.iridescence;
            }
        },
        ...getTextureProps(manager, 'iridescenceThicknessTexture', '2D', false, 1, function() {
            return this.iridescence;
        }),
        {
            name: 'ClearCoat',
            description: 'If true, enables a clear coat layer on top of the material',
            type: 'bool',
            phase: 0,
            default: false,
            get (value) {
                value.bool[0] = this.clearcoat;
            },
            set (value) {
                this.clearcoat = value.bool[0];
            },
            isValid () {
                return !this.$isInstance;
            }
        },
        {
            name: 'ClearCoatIntensity',
            description: 'Strength of the clear coat layer',
            type: 'float',
            phase: 1,
            default: 0,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1
            },
            get (value) {
                value.num[0] = this.clearcoatIntensity;
            },
            set (value) {
                this.clearcoatIntensity = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.clearcoat;
            }
        },
        ...getTextureProps(manager, 'clearcoatIntensityTexture', '2D', false, 1, function() {
            return this.clearcoat;
        }),
        {
            name: 'ClearCoatRoughnessFactor',
            description: 'Roughness of the clear coat layer',
            type: 'float',
            phase: 1,
            default: 0,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1
            },
            get (value) {
                value.num[0] = this.clearcoatRoughnessFactor;
            },
            set (value) {
                this.clearcoatRoughnessFactor = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.clearcoat;
            }
        },
        ...getTextureProps(manager, 'clearcoatRoughnessTexture', '2D', false, 1, function() {
            return this.clearcoat;
        }),
        ...getTextureProps(manager, 'clearcoatNormalTexture', '2D', false, 1, function() {
            return this.clearcoat;
        }),
        {
            name: 'Sheen',
            description: 'If true, enables a soft fabric-like sheen layer',
            type: 'bool',
            phase: 0,
            default: false,
            get (value) {
                value.bool[0] = this.sheen;
            },
            set (value) {
                this.sheen = value.bool[0];
            },
            isValid () {
                return !this.$isInstance;
            }
        },
        {
            name: 'SheenColorFactor',
            description: 'Color of the sheen layer',
            type: 'rgb',
            phase: 1,
            default: [
                0,
                0,
                0
            ],
            options: {
                animatable: true
            },
            get (value) {
                value.num[0] = this.sheenColorFactor.x;
                value.num[1] = this.sheenColorFactor.y;
                value.num[2] = this.sheenColorFactor.z;
            },
            set (value) {
                this.sheenColorFactor = new Vector3(value.num[0], value.num[1], value.num[2]);
            },
            isValid () {
                return !this.$isInstance && !!this.sheen;
            }
        },
        ...getTextureProps(manager, 'sheenColorTexture', '2D', true, 1, function() {
            return this.sheen;
        }),
        {
            name: 'SheenRoughnessFactor',
            description: 'Roughness of the sheen layer',
            type: 'float',
            phase: 1,
            default: 0,
            options: {
                animatable: true,
                minValue: 0,
                maxValue: 1
            },
            get (value) {
                value.num[0] = this.sheenRoughnessFactor;
            },
            set (value) {
                this.sheenRoughnessFactor = value.num[0];
            },
            isValid () {
                return !this.$isInstance && !!this.sheen;
            }
        },
        ...getTextureProps(manager, 'sheenRoughnessTexture', '2D', false, 1, function() {
            return this.sheen;
        }),
        ...getLitMaterialProps(manager)
    ]);
}
function getLitMaterialProps(manager) {
    return defineProps([
        ...getUnlitMaterialProps(manager),
        {
            name: 'doubleSidedLighting',
            description: 'If true, lighting is evaluated on both sides of the surface',
            type: 'bool',
            default: false,
            isValid () {
                return !this.$isInstance && this.cullMode !== 'back';
            },
            get (value) {
                value.bool[0] = this.doubleSidedLighting;
            },
            set (value) {
                this.doubleSidedLighting = value.bool[0];
            }
        },
        {
            name: 'vertexNormal',
            description: 'If true, uses vertex normals for lighting and normal mapping',
            type: 'bool',
            default: true,
            get (value) {
                value.bool[0] = this.vertexNormal;
            },
            set (value) {
                this.vertexNormal = value.bool[0];
            },
            isValid () {
                return !this.$isInstance;
            }
        },
        {
            name: 'vertexTangent',
            description: 'If true, uses vertex tangents for tangent-space normal mapping',
            type: 'bool',
            default: false,
            get (value) {
                value.bool[0] = this.vertexTangent;
            },
            set (value) {
                this.vertexTangent = value.bool[0];
            },
            isValid () {
                return !this.$isInstance && !!this.vertexNormal;
            }
        },
        ...getTextureProps(manager, 'normalTexture', '2D', false, 0)
    ]);
}
function getUnlitMaterialProps(manager) {
    return defineProps([
        {
            name: 'vertexColor',
            description: 'If true, multiplies the material color by per-vertex color data',
            type: 'bool',
            default: false,
            get (value) {
                value.bool[0] = this.vertexColor;
            },
            set (value) {
                this.vertexColor = value.bool[0];
            },
            isValid () {
                return !this.$isInstance;
            }
        },
        {
            name: 'AlbedoColor',
            description: 'Base RGBA color of the material before lighting',
            type: 'rgba',
            options: {
                animatable: true
            },
            get (value) {
                const color = this.albedoColor;
                value.num[0] = color.x;
                value.num[1] = color.y;
                value.num[2] = color.z;
                value.num[3] = color.w;
            },
            set (value) {
                this.albedoColor = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
            },
            getDefaultValue () {
                return this.$isInstance ? this.coreMaterial.albedoColor : [
                    1,
                    1,
                    1,
                    1
                ];
            }
        },
        ...getTextureProps(manager, 'albedoTexture', '2D', true, 0)
    ]);
}
/** @internal */ function getMeshMaterialClass() {
    return [
        {
            ctor: MeshMaterial,
            name: 'MeshMaterial',
            getProps () {
                return defineProps([
                    {
                        name: 'AlphaCutoff',
                        description: 'If greater then 0, pixels which have alpha smaller than alpha cutoff will be discarded',
                        type: 'float',
                        default: 0,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 1
                        },
                        get (value) {
                            value.num[0] = this.alphaCutoff;
                        },
                        set (value) {
                            this.alphaCutoff = value.num[0];
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    },
                    {
                        name: 'AlphaToCoverage',
                        description: 'If true, alpha-to-coverage will be enabled',
                        type: 'bool',
                        default: false,
                        get (value) {
                            value.bool[0] = this.alphaToCoverage;
                        },
                        set (value) {
                            this.alphaToCoverage = value.bool[0];
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    },
                    {
                        name: 'AlphaDither',
                        description: 'If true, alpha-dithering will be enabled',
                        type: 'bool',
                        default: false,
                        get (value) {
                            value.bool[0] = this.alphaDither;
                        },
                        set (value) {
                            this.alphaDither = value.bool[0];
                        },
                        isValid () {
                            return !this.$isInstance && this.alphaCutoff > 0;
                        }
                    },
                    {
                        name: 'BlendMode',
                        description: 'Blending mode for this material',
                        type: 'string',
                        options: {
                            enum: {
                                labels: [
                                    'None',
                                    'Blend',
                                    'Additive'
                                ],
                                values: [
                                    'none',
                                    'blend',
                                    'additive'
                                ]
                            }
                        },
                        default: 'none',
                        get (value) {
                            value.str[0] = this.blendMode;
                        },
                        set (value) {
                            this.blendMode = value.str[0];
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    },
                    {
                        name: 'CullMode',
                        description: 'Cull mode for this material',
                        type: 'string',
                        options: {
                            enum: {
                                labels: [
                                    'None',
                                    'Front',
                                    'Back'
                                ],
                                values: [
                                    'none',
                                    'front',
                                    'back'
                                ]
                            }
                        },
                        default: 'back',
                        get (value) {
                            value.str[0] = this.cullMode;
                        },
                        set (value) {
                            this.cullMode = value.str[0];
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    },
                    {
                        name: 'Opacity',
                        description: 'Opacity value for this material, no effect if blendingMode is `none`',
                        type: 'float',
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 1
                        },
                        default: 1,
                        get (value) {
                            value.num[0] = this.opacity;
                        },
                        set (value) {
                            this.opacity = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.opacity : 1;
                        }
                    },
                    {
                        name: 'TAAStrength',
                        description: 'TAA strength for this material',
                        type: 'float',
                        options: {
                            minValue: 0,
                            maxValue: 1
                        },
                        default: 15 / 16,
                        get (value) {
                            value.num[0] = this.TAAStrength;
                        },
                        set (value) {
                            this.TAAStrength = value.num[0];
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    }
                ]);
            }
        },
        getMeshMaterialInstanceUniformsClass(MeshMaterial)
    ];
}
/** @internal */ function getSpriteMaterialClass(_manager) {
    return [
        {
            ctor: SpriteMaterial,
            name: 'SpriteMaterial',
            parent: MeshMaterial,
            getProps () {
                return [];
            }
        },
        getMeshMaterialInstanceUniformsClass(SpriteMaterial)
    ];
}
/** @internal */ function getStandardSpriteMaterialClass(manager) {
    return [
        {
            ctor: StandardSpriteMaterial,
            name: 'StandardSpriteMaterial',
            parent: SpriteMaterial,
            getProps () {
                return defineProps([
                    {
                        name: 'SpriteTexture',
                        description: 'Texture file path for the sprite',
                        type: 'object',
                        default: '',
                        options: {
                            mimeTypes: [
                                'image/jpeg',
                                'image/png',
                                'image/tga',
                                'image/vnd.radiance',
                                'image/x-dds',
                                'image/webp'
                            ]
                        },
                        isNullable () {
                            return true;
                        },
                        get (value) {
                            value.str[0] = manager.getAssetId(this.spriteTexture) ?? '';
                        },
                        async set (value) {
                            if (!value || !value.str[0]) {
                                this.spriteTexture = null;
                            } else {
                                const assetId = value.str[0];
                                let tex;
                                try {
                                    tex = await manager.fetchTexture(assetId, {
                                        linearColorSpace: false
                                    });
                                } catch (err) {
                                    console.error(`Load asset failed: ${value.str[0]}: ${err}`);
                                    tex = null;
                                }
                                if (tex?.isTexture2D()) {
                                    this.spriteTexture = tex;
                                } else {
                                    console.error('Invalid texture type');
                                }
                            }
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    }
                ]);
            }
        },
        getMeshMaterialInstanceUniformsClass(StandardSpriteMaterial)
    ];
}
/** @internal */ function getParticleMaterialClass(manager) {
    return [
        {
            ctor: ParticleMaterial,
            name: 'ParticleMaterial',
            parent: MeshMaterial,
            getProps () {
                return defineProps([
                    {
                        name: 'AlphaMap',
                        description: 'Alpha texture file path',
                        type: 'object',
                        default: '',
                        options: {
                            mimeTypes: [
                                'image/jpeg',
                                'image/png',
                                'image/tga',
                                'image/vnd.radiance',
                                'image/x-dds',
                                'image/webp'
                            ]
                        },
                        isNullable () {
                            return true;
                        },
                        get (value) {
                            value.str[0] = manager.getAssetId(this.alphaMap) ?? '';
                        },
                        async set (value) {
                            if (!value || !value.str[0]) {
                                this.alphaMap = null;
                            } else {
                                const assetId = value.str[0];
                                let tex = null;
                                try {
                                    tex = await manager.fetchTexture(assetId, {
                                        linearColorSpace: true
                                    });
                                } catch (err) {
                                    console.error(`Load asset failed: ${value.str[0]}: ${err}`);
                                }
                                if (tex?.isTexture2D()) {
                                    this.alphaMap = tex;
                                } else {
                                    console.error('Invalid albedo texture');
                                }
                            }
                        }
                    },
                    {
                        name: 'RampMap',
                        description: 'Ramp texture file path',
                        type: 'object',
                        default: '',
                        options: {
                            mimeTypes: [
                                'image/jpeg',
                                'image/png',
                                'image/tga',
                                'image/vnd.radiance',
                                'image/x-dds',
                                'image/webp'
                            ]
                        },
                        isNullable () {
                            return true;
                        },
                        get (value) {
                            value.str[0] = manager.getAssetId(this.rampMap) ?? '';
                        },
                        async set (value) {
                            if (!value || !value.str[0]) {
                                this.rampMap = null;
                            } else {
                                const assetId = value.str[0];
                                let tex = null;
                                try {
                                    tex = await manager.fetchTexture(assetId);
                                } catch (err) {
                                    console.error(`Load asset failed: ${value.str[0]}: ${err}`);
                                }
                                if (tex?.isTexture2D()) {
                                    this.rampMap = tex;
                                } else {
                                    console.error('Invalid albedo texture');
                                }
                            }
                        }
                    }
                ]);
            }
        },
        getMeshMaterialInstanceUniformsClass(ParticleMaterial)
    ];
}
/** @internal */ function getPBRBluePrintMaterialClass() {
    return [
        {
            ctor: PBRBluePrintMaterial,
            parent: MeshMaterial,
            name: 'PBRBluePrintMaterial',
            getProps () {
                return defineProps([
                    {
                        name: 'doubleSidedLighting',
                        description: 'If true, double-sided lighting will be enabled',
                        type: 'bool',
                        default: false,
                        isValid () {
                            return !this.$isInstance && this.cullMode !== 'back';
                        },
                        get (value) {
                            value.bool[0] = this.doubleSidedLighting;
                        },
                        set (value) {
                            this.doubleSidedLighting = value.bool[0];
                        }
                    },
                    {
                        name: 'Reflection',
                        description: 'Reflection mode for the material',
                        type: 'string',
                        default: 'ggx',
                        options: {
                            enum: {
                                labels: [
                                    'None',
                                    'GGX',
                                    'Anisotropic',
                                    'Glint'
                                ],
                                values: [
                                    'none',
                                    'ggx',
                                    'anisotropic',
                                    'glint'
                                ]
                            }
                        },
                        get (value) {
                            value.str[0] = this.reflectionMode;
                        },
                        set (value) {
                            this.reflectionMode = value.str[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.reflectionMode : 'ggx';
                        }
                    },
                    {
                        name: 'SubsurfaceScattering',
                        description: 'If true, subsurface-scattering will be enabled',
                        type: 'bool',
                        phase: 0,
                        default: false,
                        get (value) {
                            value.bool[0] = this.subsurfaceScattering;
                        },
                        set (value) {
                            this.subsurfaceScattering = value.bool[0];
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    },
                    {
                        name: 'SubsurfaceColor',
                        description: 'Subsurface-scattering color',
                        type: 'rgb',
                        phase: 1,
                        default: [
                            1,
                            0.3,
                            0.2
                        ],
                        options: {
                            animatable: true
                        },
                        get (value) {
                            value.num[0] = this.subsurfaceColor.x;
                            value.num[1] = this.subsurfaceColor.y;
                            value.num[2] = this.subsurfaceColor.z;
                        },
                        set (value) {
                            this.subsurfaceColor = new Vector3(value.num[0], value.num[1], value.num[2]);
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfaceColor : [
                                1,
                                0.3,
                                0.2
                            ];
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    {
                        name: 'SubsurfaceScale',
                        description: 'Scale value for subsurface-scattering',
                        type: 'float',
                        phase: 1,
                        default: 0.5,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 8
                        },
                        get (value) {
                            value.num[0] = this.subsurfaceScale;
                        },
                        set (value) {
                            this.subsurfaceScale = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfaceScale : 0.5;
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    {
                        name: 'SubsurfacePower',
                        description: 'Power value for subsurface-scattering',
                        type: 'float',
                        phase: 1,
                        default: 1.5,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 16
                        },
                        get (value) {
                            value.num[0] = this.subsurfacePower;
                        },
                        set (value) {
                            this.subsurfacePower = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfacePower : 1.5;
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    {
                        name: 'SubsurfaceIntensity',
                        description: 'Intensity value for subsurface-scattering',
                        type: 'float',
                        phase: 1,
                        default: 0.5,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 4
                        },
                        get (value) {
                            value.num[0] = this.subsurfaceIntensity;
                        },
                        set (value) {
                            this.subsurfaceIntensity = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfaceIntensity : 0.5;
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    {
                        name: 'Anisotropy',
                        description: 'Anistropy value',
                        type: 'float',
                        default: 0.75,
                        options: {
                            animatable: true,
                            minValue: -0.95,
                            maxValue: 0.95
                        },
                        get (value) {
                            value.num[0] = this.anisotropy;
                        },
                        set (value) {
                            this.anisotropy = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.anisotropy : 0.75;
                        },
                        isValid () {
                            return this.reflectionMode === 'anisotropic';
                        }
                    },
                    {
                        name: 'AnisotropyDirection',
                        description: 'Anisotropy direction',
                        type: 'float',
                        default: 0,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 360
                        },
                        get (value) {
                            value.num[0] = this.anisotropyDirection;
                        },
                        set (value) {
                            this.anisotropyDirection = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.anisotropyDirection : 0;
                        },
                        isValid () {
                            return this.reflectionMode === 'anisotropic';
                        }
                    },
                    {
                        name: 'AnisotropyDirectionScaleBias',
                        description: 'Anisotropy direction scale bias',
                        type: 'vec2',
                        default: [
                            1,
                            0
                        ],
                        options: {
                            animatable: true
                        },
                        get (value) {
                            value.num[0] = this.anisotropyDirectionScaleBias.x;
                            value.num[1] = this.anisotropyDirectionScaleBias.y;
                        },
                        set (value) {
                            this.anisotropyDirectionScaleBias = new Vector2(value.num[0], value.num[1]);
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.anisotropyDirectionScaleBias : [
                                1,
                                0
                            ];
                        },
                        isValid () {
                            return this.reflectionMode === 'anisotropic';
                        }
                    }
                ]);
            }
        },
        getMeshMaterialInstanceUniformsClass(PBRBluePrintMaterial)
    ];
}
/** @internal */ function getSpriteBlueprintMaterialClass() {
    return [
        {
            ctor: SpriteBlueprintMaterial,
            parent: MeshMaterial,
            name: 'SpriteBlueprintMaterial',
            getProps () {
                return [];
            }
        },
        getMeshMaterialInstanceUniformsClass(SpriteBlueprintMaterial)
    ];
}
/** @internal */ function getUnlitMaterialClass(manager) {
    return [
        {
            ctor: UnlitMaterial,
            parent: MeshMaterial,
            name: 'UnlitMaterial',
            getProps () {
                return getUnlitMaterialProps(manager);
            }
        },
        getMeshMaterialInstanceUniformsClass(UnlitMaterial)
    ];
}
/** @internal */ function getLambertMaterialClass(manager) {
    return [
        {
            ctor: LambertMaterial,
            parent: MeshMaterial,
            name: 'LambertMaterial',
            getProps () {
                return getLitMaterialProps(manager);
            }
        },
        getMeshMaterialInstanceUniformsClass(LambertMaterial)
    ];
}
/** @internal */ function getBlinnMaterialClass(manager) {
    return [
        {
            ctor: BlinnMaterial,
            parent: MeshMaterial,
            name: 'BlinnMaterial',
            getProps () {
                return defineProps([
                    {
                        name: 'Shininess',
                        description: 'Shininess value',
                        type: 'float',
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 2048
                        },
                        get (value) {
                            value.num[0] = this.shininess;
                        },
                        set (value) {
                            this.shininess = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.shininess : 32;
                        }
                    },
                    {
                        name: 'ScatterWrap',
                        description: 'Scatter wrap for light warping',
                        type: 'float',
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 1
                        },
                        get (value) {
                            value.num[0] = this.scatterWrap;
                        },
                        set (value) {
                            this.scatterWrap = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.scatterWrap : 0;
                        }
                    },
                    {
                        name: 'ScatterWidth',
                        description: 'Scatter width for light wrapping',
                        type: 'float',
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 1
                        },
                        get (value) {
                            value.num[0] = this.scatterWidth;
                        },
                        set (value) {
                            this.scatterWidth = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.scatterWidth : 0;
                        }
                    },
                    {
                        name: 'ScatterColor',
                        description: 'Scatter color for light warping',
                        type: 'rgb',
                        options: {
                            animatable: true
                        },
                        get (value) {
                            value.num[0] = this.scatterColor.x;
                            value.num[1] = this.scatterColor.y;
                            value.num[2] = this.scatterColor.z;
                        },
                        set (value) {
                            this.scatterColor = new Vector4(value.num[0], value.num[1], value.num[2], 1);
                        },
                        getDefaultValue () {
                            return this.$isInstance ? [
                                this.coreMaterial.scatterColor.x,
                                this.coreMaterial.scatterColor.y,
                                this.coreMaterial.scatterColor.z
                            ] : [
                                0,
                                0,
                                0
                            ];
                        }
                    },
                    ...getLitMaterialProps(manager)
                ]);
            }
        },
        getMeshMaterialInstanceUniformsClass(BlinnMaterial)
    ];
}
/** @internal */ function getPBRMetallicRoughnessMaterialClass(manager) {
    return [
        {
            ctor: PBRMetallicRoughnessMaterial,
            parent: MeshMaterial,
            name: 'PBRMetallicRoughnessMaterial',
            getProps () {
                return defineProps([
                    {
                        name: 'Metallic',
                        description: 'Metallic value',
                        type: 'float',
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 1
                        },
                        get (value) {
                            value.num[0] = this.metallic;
                        },
                        set (value) {
                            this.metallic = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.metallic : 1;
                        }
                    },
                    {
                        name: 'Roughness',
                        description: 'Roughness value',
                        type: 'float',
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 1
                        },
                        get (value) {
                            value.num[0] = this.roughness;
                        },
                        set (value) {
                            this.roughness = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.roughness : 1;
                        }
                    },
                    {
                        name: 'SpecularFactor',
                        description: 'RGBA specular factor used to tint and scale specular reflections',
                        type: 'rgba',
                        options: {
                            animatable: true
                        },
                        get (value) {
                            value.num[0] = this.specularFactor.x;
                            value.num[1] = this.specularFactor.y;
                            value.num[2] = this.specularFactor.z;
                            value.num[3] = this.specularFactor.w;
                        },
                        set (value) {
                            this.specularFactor = new Vector4(value.num[0], value.num[1], value.num[2], value.num[3]);
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.specularFactor : [
                                1,
                                1,
                                1,
                                1
                            ];
                        }
                    },
                    {
                        name: 'Reflection',
                        description: 'Reflection mode',
                        type: 'string',
                        default: 'ggx',
                        options: {
                            enum: {
                                labels: [
                                    'None',
                                    'GGX',
                                    'Anisotropic',
                                    'Glint'
                                ],
                                values: [
                                    'none',
                                    'ggx',
                                    'anisotropic',
                                    'glint'
                                ]
                            }
                        },
                        get (value) {
                            value.str[0] = this.reflectionMode;
                        },
                        set (value) {
                            this.reflectionMode = value.str[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.reflectionMode : 'ggx';
                        }
                    },
                    {
                        name: 'Anisotropy',
                        description: 'Strength of anisotropic reflections; values near 0 behave isotropically',
                        type: 'float',
                        default: 0.75,
                        options: {
                            animatable: true,
                            minValue: -0.95,
                            maxValue: 0.95
                        },
                        get (value) {
                            value.num[0] = this.anisotropy;
                        },
                        set (value) {
                            this.anisotropy = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.anisotropy : 0.75;
                        },
                        isValid () {
                            return this.reflectionMode === 'anisotropic';
                        }
                    },
                    {
                        name: 'AnisotropyDirection',
                        description: 'Rotation angle in degrees for the anisotropic highlight direction',
                        type: 'float',
                        default: 0,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 360
                        },
                        get (value) {
                            value.num[0] = this.anisotropyDirection;
                        },
                        set (value) {
                            this.anisotropyDirection = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.anisotropyDirection : 0;
                        },
                        isValid () {
                            return this.reflectionMode === 'anisotropic';
                        }
                    },
                    ...getTextureProps(manager, 'anisotropyDirectionTexture', '2D', false, 0, function() {
                        return this.reflectionMode === 'anisotropic';
                    }),
                    {
                        name: 'AnisotropyDirectionScaleBias',
                        description: 'Scale and bias applied when decoding anisotropy direction from its texture',
                        type: 'vec2',
                        default: [
                            1,
                            0
                        ],
                        options: {
                            animatable: true
                        },
                        get (value) {
                            value.num[0] = this.anisotropyDirectionScaleBias.x;
                            value.num[1] = this.anisotropyDirectionScaleBias.y;
                        },
                        set (value) {
                            this.anisotropyDirectionScaleBias = new Vector2(value.num[0], value.num[1]);
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.anisotropyDirectionScaleBias : [
                                1,
                                0
                            ];
                        },
                        isValid () {
                            return !this.$isInstance && this.reflectionMode === 'anisotropic' && !!this.anisotropyDirectionTexture;
                        }
                    },
                    {
                        name: 'SubsurfaceScattering',
                        description: 'If true, enables subsurface scattering for translucent materials',
                        type: 'bool',
                        phase: 0,
                        default: false,
                        get (value) {
                            value.bool[0] = this.subsurfaceScattering;
                        },
                        set (value) {
                            this.subsurfaceScattering = value.bool[0];
                        },
                        isValid () {
                            return !this.$isInstance;
                        }
                    },
                    {
                        name: 'SubsurfaceColor',
                        description: 'Color tint of the subsurface scattering effect',
                        type: 'rgb',
                        phase: 1,
                        default: [
                            1,
                            0.3,
                            0.2
                        ],
                        options: {
                            animatable: true
                        },
                        get (value) {
                            value.num[0] = this.subsurfaceColor.x;
                            value.num[1] = this.subsurfaceColor.y;
                            value.num[2] = this.subsurfaceColor.z;
                        },
                        set (value) {
                            this.subsurfaceColor = new Vector3(value.num[0], value.num[1], value.num[2]);
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfaceColor : [
                                1,
                                0.3,
                                0.2
                            ];
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    {
                        name: 'SubsurfaceScale',
                        description: 'Distance scale of the subsurface scattering effect',
                        type: 'float',
                        phase: 1,
                        default: 0.5,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 8
                        },
                        get (value) {
                            value.num[0] = this.subsurfaceScale;
                        },
                        set (value) {
                            this.subsurfaceScale = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfaceScale : 0.5;
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    {
                        name: 'SubsurfacePower',
                        description: 'Falloff power controlling how quickly subsurface scattering fades',
                        type: 'float',
                        phase: 1,
                        default: 1.5,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 16
                        },
                        get (value) {
                            value.num[0] = this.subsurfacePower;
                        },
                        set (value) {
                            this.subsurfacePower = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfacePower : 1.5;
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    {
                        name: 'SubsurfaceIntensity',
                        description: 'Overall intensity of the subsurface scattering effect',
                        type: 'float',
                        phase: 1,
                        default: 0.5,
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 4
                        },
                        get (value) {
                            value.num[0] = this.subsurfaceIntensity;
                        },
                        set (value) {
                            this.subsurfaceIntensity = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.subsurfaceIntensity : 0.5;
                        },
                        isValid () {
                            return this.subsurfaceScattering;
                        }
                    },
                    ...getTextureProps(manager, 'subsurfaceTexture', '2D', false, 1, function() {
                        return this.subsurfaceScattering;
                    }),
                    ...getTextureProps(manager, 'metallicRoughnessTexture', '2D', false, 0),
                    ...getTextureProps(manager, 'specularColorTexture', '2D', true, 0),
                    ...getPBRCommonProps(manager)
                ]);
            }
        },
        getMeshMaterialInstanceUniformsClass(PBRMetallicRoughnessMaterial)
    ];
}
/** @internal */ function getPBRSpecularGlossinessMaterialClass(manager) {
    return [
        {
            ctor: PBRSpecularGlossinessMaterial,
            name: 'PBRSpecularGlossinessMaterial',
            parent: MeshMaterial,
            getProps () {
                return defineProps([
                    {
                        name: 'SpecularFactor',
                        description: 'RGB specular color multiplier for reflected highlights',
                        type: 'rgb',
                        options: {
                            animatable: true
                        },
                        get (value) {
                            value.num[0] = this.specularFactor.x;
                            value.num[1] = this.specularFactor.y;
                            value.num[2] = this.specularFactor.z;
                        },
                        set (value) {
                            this.specularFactor = new Vector3(value.num[0], value.num[1], value.num[2]);
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.specularFactor : [
                                1,
                                1,
                                1
                            ];
                        }
                    },
                    {
                        name: 'GlossnessFactor',
                        description: 'Glossiness of the surface; higher values produce sharper reflections',
                        type: 'float',
                        options: {
                            animatable: true,
                            minValue: 0,
                            maxValue: 1
                        },
                        get (value) {
                            value.num[0] = this.glossinessFactor;
                        },
                        set (value) {
                            this.glossinessFactor = value.num[0];
                        },
                        getDefaultValue () {
                            return this.$isInstance ? this.coreMaterial.glossinessFactor : 1;
                        }
                    },
                    ...getPBRCommonProps(manager)
                ]);
            }
        },
        getMeshMaterialInstanceUniformsClass(PBRSpecularGlossinessMaterial)
    ];
}

export { getBlinnMaterialClass, getLambertMaterialClass, getMeshMaterialClass, getPBRBluePrintMaterialClass, getPBRMetallicRoughnessMaterialClass, getPBRSpecularGlossinessMaterialClass, getParticleMaterialClass, getSpriteBlueprintMaterialClass, getSpriteMaterialClass, getStandardSpriteMaterialClass, getUnlitMaterialClass };
//# sourceMappingURL=material.js.map
