import {AdvancedShape} from "../../../core/shapes/AdvancedShape.js";
import smoothMinPoly from "../../imports/smoothMinPoly.glsl";
import sdfRegular from "./shaders/sdfRegular.glsl.mustache";
import gradientRegular from "./shaders/gradientRegular.glsl.mustache";
import uv from "./shaders/uv.glsl.mustache";
import sdfPoly from "./shaders/sdfPoly.glsl.mustache";
import struct from "./shaders/struct.glsl";
import gradientPoly from "./shaders/gradientPoly.glsl.mustache";
export const REGULAR_MIN = 0;
export const SMOOTH_MIN_POLY = 1;
export const SMOOTH_MIN_EXP = 2;
export const SMOOTH_MIN_POWER = 3;
/**
* @class
*
* @classdesc
* Union of two shapes
*/
export class UnionShape extends AdvancedShape {
/**
* Constructor.
* The two shapes should be both local or both global.
* @param {Shape} shape1 - the first shape
* @param {Shape} shape2 - the second shape
* @param {Object} params - parameters (basically which kind of min is used)
*/
constructor(shape1, shape2, params = {}) {
if (shape1.isGlobal !== shape2.isGlobal) {
throw new Error('UnionShape: the two shapes should be both local or both global');
}
super();
this.shape1 = shape1;
this.shape2 = shape2;
this.shape1.parent = this;
this.shape2.parent = this;
this.minType = params.minType !== undefined ? params.minType : REGULAR_MIN;
this.minCoeff = 0;
switch (this.minType) {
case SMOOTH_MIN_POLY:
this.addImport(smoothMinPoly);
this.minCoeff = params.minCoeff !== undefined ? params.minCoeff : 0.1;
break;
}
}
updateAbsoluteIsom() {
super.updateAbsoluteIsom();
this.shape1.updateAbsoluteIsom();
this.shape2.updateAbsoluteIsom();
}
updateData() {
super.updateData();
this.shape1.updateData();
this.shape2.updateData();
}
get uniformType() {
return 'UnionShape';
}
static glslClass() {
return struct;
}
get isGlobal() {
return this.shape1.isGlobal;
}
get hasUVMap() {
return this.shape1.hasUVMap && this.shape2.hasUVMap;
}
glslSDF() {
switch (this.minType) {
case SMOOTH_MIN_POLY:
return sdfPoly(this);
default:
return sdfRegular(this);
}
}
glslGradient() {
switch (this.minType) {
case SMOOTH_MIN_POLY:
return gradientPoly(this);
default:
return gradientRegular(this);
}
}
glslUVMap() {
return uv(this);
}
/**
* Set the ID of the shape.
* Propagate the call.
* @param {Scene} scene - the scene to which the object is added.
*/
setId(scene) {
this.shape1.setId(scene);
this.shape2.setId(scene);
super.setId(scene);
}
/**
* Additional actions to perform when the object is added to the scene.
* Propagate the call.
* @param {Scene} scene - the scene to which the object is added.
*/
onAdd(scene) {
this.shape1.onAdd(scene);
this.shape2.onAdd(scene);
super.onAdd(scene);
}
shader(shaderBuilder) {
this.shape1.shader(shaderBuilder);
this.shape2.shader(shaderBuilder);
super.shader(shaderBuilder);
}
}
/**
* The union of an arbitrary number of shapes
* The function takes a bunch of shapes
* The last argument (if not a shape) are the parameters of the union
*/
export function union() {
let res;
let params = {};
const n = arguments.length;
if (n === 0) {
throw new Error('union: the function expect at least one argument');
}
if (!arguments[n - 1].isShape) {
params = arguments[n - 1];
}
res = arguments[0];
for (let i = 1; i < n; i++) {
if (arguments[i].isShape) {
res = new UnionShape(res, arguments[i], params);
}
}
return res;
}