polygonjs-engine
Version:
node-based webgl 3D engine https://polygonjs.com
139 lines (138 loc) • 5.35 kB
JavaScript
import {BaseController as BaseController2} from "./_BaseController";
import {ParamConfig} from "../../utils/params/ParamsConfig";
import {NodeContext as NodeContext2} from "../../../poly/NodeContext";
import {NODE_PATH_DEFAULT} from "../../../../core/Walker";
export function TextureMapParamConfig(Base5) {
return class Mixin extends Base5 {
constructor() {
super(...arguments);
this.useMap = ParamConfig.BOOLEAN(0);
this.map = ParamConfig.OPERATOR_PATH(NODE_PATH_DEFAULT.NODE.UV, {visibleIf: {useMap: 1}});
}
};
}
export function BooleanParamOptions(controller_class) {
return {
cook: false,
callback: (node, param) => {
controller_class.update(node);
}
};
}
export function OperatorPathOptions(controller, use_map_name) {
return {
visibleIf: {[use_map_name]: 1},
nodeSelection: {context: NodeContext2.COP},
cook: false,
callback: (node, param) => {
controller.update(node);
}
};
}
export class BaseTextureMapController extends BaseController2 {
constructor(node, _update_options) {
super(node);
this.node = node;
this._update_options = _update_options;
}
add_hooks(use_map_param, path_param) {
use_map_param.addPostDirtyHook("TextureController", () => {
this.update();
});
path_param.addPostDirtyHook("TextureController", () => {
this.update();
});
}
static update(node) {
}
async _update(material, mat_attrib_name, use_map_param, path_param) {
if (this._update_options.uniforms) {
const shader_material = material;
const attr_name = mat_attrib_name;
await this._update_texture_on_uniforms(shader_material, attr_name, use_map_param, path_param);
}
if (this._update_options.direct_params) {
const mat = material;
const attr_name = mat_attrib_name;
await this._update_texture_on_material(mat, attr_name, use_map_param, path_param);
}
}
async _update_texture_on_uniforms(material, mat_attrib_name, use_map_param, path_param) {
this._update_required_attribute(material, material.uniforms, mat_attrib_name, use_map_param, path_param, this._apply_texture_on_uniforms.bind(this), this._remove_texture_from_uniforms.bind(this));
}
_apply_texture_on_uniforms(material, uniforms, mat_attrib_name, texture) {
const has_texture = uniforms[mat_attrib_name] != null && uniforms[mat_attrib_name].value != null;
let new_texture_is_different = false;
if (has_texture) {
const current_texture = uniforms[mat_attrib_name].value;
if (current_texture.uuid != texture.uuid) {
new_texture_is_different = true;
}
}
if (!has_texture || new_texture_is_different) {
uniforms[mat_attrib_name].value = texture;
this._apply_texture_on_material(material, material, mat_attrib_name, texture);
material.needsUpdate = true;
}
}
_remove_texture_from_uniforms(material, uniforms, mat_attrib_name) {
if (uniforms[mat_attrib_name].value) {
uniforms[mat_attrib_name].value = null;
this._remove_texture_from_material(material, material, mat_attrib_name);
material.needsUpdate = true;
}
}
async _update_texture_on_material(material, mat_attrib_name, use_map_param, path_param) {
this._update_required_attribute(material, material, mat_attrib_name, use_map_param, path_param, this._apply_texture_on_material.bind(this), this._remove_texture_from_material.bind(this));
}
_apply_texture_on_material(material, texture_owner, mat_attrib_name, texture) {
const has_texture = texture_owner[mat_attrib_name] != null;
let new_texture_is_different = false;
if (has_texture) {
const current_texture = texture_owner[mat_attrib_name];
if (current_texture.uuid != texture.uuid) {
new_texture_is_different = true;
}
}
if (!has_texture || new_texture_is_different) {
texture_owner[mat_attrib_name] = texture;
material.needsUpdate = true;
}
}
_remove_texture_from_material(material, texture_owner, mat_attrib_name) {
if (texture_owner[mat_attrib_name]) {
texture_owner[mat_attrib_name] = null;
material.needsUpdate = true;
}
}
async _update_required_attribute(material, texture_owner, mat_attrib_name, use_map_param, path_param, update_callback, remove_callback) {
if (use_map_param.isDirty()) {
await use_map_param.compute();
}
const use_map = use_map_param.value;
if (use_map) {
if (path_param.isDirty()) {
await path_param.compute();
}
const found_node = path_param.found_node();
if (found_node) {
if (found_node.nodeContext() == NodeContext2.COP) {
const texture_node = found_node;
const container = await texture_node.requestContainer();
const texture = container.texture();
if (texture) {
update_callback(material, texture_owner, mat_attrib_name, texture);
return;
} else {
this.node.states.error.set(`found node has no texture`);
}
} else {
this.node.states.error.set(`found map node is not a COP node`);
}
} else {
this.node.states.error.set(`could not find map node ${path_param.name()} with path ${path_param.value}`);
}
}
remove_callback(material, texture_owner, mat_attrib_name);
}
}