UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

140 lines (139 loc) 4.76 kB
"use strict"; import { TypedCopNode } from "./_Base"; import { DataTexture } from "three"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { SORTED_PALETTE_NAMES, MAX_PALETTE_COLORS_COUNT, visibleIfColorsCountAtLeast } from "../../../core/color/chromotomeWrapper"; import { PaletteController, paletteControllerCallbackOptions } from "../utils/color/PaletteController"; import { Color } from "three"; class PaletteCopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param texture resolution */ this.resolution = ParamConfig.VECTOR2([256, 256], { callback: (node) => { PaletteCopNode.PARAM_CALLBACK_reset(node); } }); /** @param name of the palette */ this.paletteName = ParamConfig.STRING(SORTED_PALETTE_NAMES[0], { menuString: { entries: SORTED_PALETTE_NAMES.map((name, value) => { return { name, value: name }; }) }, ...paletteControllerCallbackOptions(PaletteController.PARAM_CALLBACK_updateColors) }); /** @param click to set the node to the next palette */ this.pickNext = ParamConfig.BUTTON(null, paletteControllerCallbackOptions(PaletteController.PARAM_CALLBACK_pickNext)); /** @param click to set the node to the previous palette */ this.pickPrevious = ParamConfig.BUTTON( null, paletteControllerCallbackOptions(PaletteController.PARAM_CALLBACK_pickPrevious) ); /** @param click to set the node to a random palette */ this.pickRandom = ParamConfig.BUTTON( null, paletteControllerCallbackOptions(PaletteController.PARAM_CALLBACK_pickRandom) ); this.colorsCount = ParamConfig.INTEGER(0, { hidden: true, range: [0, MAX_PALETTE_COLORS_COUNT], separatorAfter: true }); /** @param palette color 1 */ this.color1 = ParamConfig.COLOR([0, 0, 0], { visibleIf: visibleIfColorsCountAtLeast(1) // conversion: ColorConversion.SRGB_TO_LINEAR, }); /** @param palette color 2 */ this.color2 = ParamConfig.COLOR([0, 0, 0], { visibleIf: visibleIfColorsCountAtLeast(2) // conversion: ColorConversion.SRGB_TO_LINEAR, }); /** @param palette color 3 */ this.color3 = ParamConfig.COLOR([0, 0, 0], { visibleIf: visibleIfColorsCountAtLeast(3) // conversion: ColorConversion.SRGB_TO_LINEAR, }); /** @param palette color 4 */ this.color4 = ParamConfig.COLOR([0, 0, 0], { visibleIf: visibleIfColorsCountAtLeast(4) // conversion: ColorConversion.SRGB_TO_LINEAR, }); /** @param palette color 5 */ this.color5 = ParamConfig.COLOR([0, 0, 0], { visibleIf: visibleIfColorsCountAtLeast(5) // conversion: ColorConversion.SRGB_TO_LINEAR, }); } } const ParamsConfig = new PaletteCopParamsConfig(); export class PaletteCopNode extends TypedCopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this.paletteController = new PaletteController( this ); this._colors = [new Color(), new Color(), new Color(), new Color(), new Color()]; } static type() { return "palette"; } initializeNode() { this.params.onParamsCreated("palette_init", () => { PaletteController.PARAM_CALLBACK_updateColors(this); }); } cook() { const w = this.pv.resolution.x; const h = this.pv.resolution.y; this._dataTexture = this._dataTexture || this._createDataTexture(w, h); const alpha = 255; const data = this._dataTexture.image.data; data.fill(alpha); const colorsCount = this.pv.colorsCount; this._colorParams = this._colorParams || [ this.p.color1, this.p.color2, this.p.color3, this.p.color4, this.p.color5 ]; this._colorParams.forEach((p, i) => { this._colors[i].copy(p.value).multiplyScalar(255); }); for (let i = 0; i < w; i++) { const intervalIndex = this._intervalIndex(i / w, colorsCount); const color = this._colors[intervalIndex]; for (let j = 0; j < h; j++) { const offset = i + j * w; color.toArray(data, offset * 4); } } this._dataTexture.needsUpdate = true; this.setTexture(this._dataTexture); } _intervalIndex(ratio, colorsCount) { const interval = 1 / colorsCount; return Math.floor(ratio / interval); } _createDataTexture(width, height) { const pixel_buffer = this._createPixelBuffer(width, height); return new DataTexture(pixel_buffer, width, height); } _createPixelBuffer(width, height) { const size = width * height * 4; return new Uint8Array(size); } static PARAM_CALLBACK_reset(node) { node._reset(); } _reset() { this._dataTexture = void 0; } }