_import { Constant } from 'points';

/**
 * Class that handles the creation of new {@link Constant}s in Points.
 * @example
 * // js side
 * points.constants.MYCONST = 10;
 *
 * // wgsl side
 * let val = MYCONST; // value is 10 u32 by default
 * @class Constants
 */
export default class Constants {
    #list = [];

    constructor() {
        return new Proxy(this, {
            get(target, prop, receiver) {

                const value = Reflect.get(target, prop, target);

                if (prop === 'list') {
                    return value;
                }

                if (typeof value === 'function') {
                    switch (prop) {
                        case 'find':
                        case 'add':
                        case 'listOfOverrides':
                        case 'stringOfNonOverrides':
                            return value.bind(target);
                    }
                }

                if (prop in target) {
                    return value;
                }
                // If Constant does not exist we create it.
                const constant = new Constant({ name: prop, value: 0 });
                target.list.push(constant);
                Reflect.set(target, prop, constant, target);
                return constant;
            },

            set(target, prop, value, receiver) {
                if (prop === 'list') {
                    return Reflect.set(target, prop, value, target);
                }

                const type = typeof value;
                if (type === 'string') {
                    throw `Constant named '${prop}': No strings allowed or maybe you are adding an array.`;
                }
                if (!type && type === 'object' && !Array.isArray(value)) {
                    throw `Constant named '${prop}': No objects allowed.`;
                }

                if (prop in target) {
                    const constant = Reflect.get(target, prop, target);
                    constant.value = value;
                    return constant;
                }

                // If Constant does not exist we create it.

                const constant = new Constant({ name: prop, value });
                target.list.push(constant);
                return Reflect.set(target, prop, constant, target);
            }
        });
    }

    get list() {
        return this.#list;
    }

    /**
     * List of all {@link Constant}s
     * @param {Array} value
     * @memberof Constants
     */
    set list(value) {
        this.#list = value;
    }

    /**
     * Retrieves a {@link Constant} by its name.
     * @param {String} name
     * @returns {Constant}
     * @memberof Constants
     */
    find(name) {
        return this[name];
    }

    /**
     * Add a new {@link Constant}
     * @param {Constant} constant
     * @memberof Constants
     */
    add(constant) {
        const { name } = constant;
        if (this[name]) {
            throw `Constant named ${name} already exists.`
        }
        this[name] = constant;
        this.#list.push(constant);
    }

    /**
     * Object list with the constants that are overridable.
     * This object will be passed into the pipeline.
     * @param {GPUShaderStage|Number} filter
     * @returns {Object}
     * @memberof Constants
     */
    listOfOverrides(filter) {
        return Object.fromEntries(
            this.#list
                .filter(c => ((filter & c.shaderStage) !== 0))
                .filter(c => c.override)
                .map(c => [c.name, c.value])
        );
    }

    /**
     * List of constants formatted as WGSL string to be interpolated in the
     * shaders.
     * @param {GPUShaderStage|Number} filter
     * @returns {String}
     * @memberof Constants
     */
    stringOfNonOverrides(filter) {
        let consStrings = '';
        this.#list.forEach(c => {
            const hasOneStage = (filter & c.shaderStage) !== 0;
            if (!c.override && hasOneStage) {
                consStrings += /*wgsl*/`const ${c.name}:${c.type} = ${c.value};\n`;
            }
        })
        return consStrings;
    }
}

MIT

Documentation generated by JSDoc 4.0.5 using Docolatte theme on