@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
140 lines (139 loc) • 4.76 kB
JavaScript
"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;
}
}