@urpflanze/js
Version:
A library for developers who want to approach to creative coding, artists who want to approach coding and for those who find it fun to play with math.
1,290 lines (1,267 loc) • 1.33 MB
JavaScript
/*!
* @license UrpflanzeJS v"1.1.5"
* urpflanze.js
*
* Github: https://github.com/urpflanze-org/urpflanze
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* Core: ^0.5.9 | DrawerCanvas: ^0.3.1
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["Urpflanze"] = factory();
else
root["Urpflanze"] = factory();
})(window, function() {
return /******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ([
/* 0 */
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
__exportStar(__webpack_require__(1), exports);
//# sourceMappingURL=index.js.map
/***/ }),
/* 1 */
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SVGImporter = exports.SVGExporter = exports.GCODEExporter = exports.Timeline = exports.Renderer = exports.Color = void 0;
__exportStar(__webpack_require__(2), exports);
exports.Color = __webpack_require__(75);
var cjs_1 = __webpack_require__(80);
Object.defineProperty(exports, "Renderer", ({ enumerable: true, get: function () { return cjs_1.Renderer; } }));
Object.defineProperty(exports, "Timeline", ({ enumerable: true, get: function () { return cjs_1.Timeline; } }));
var cjs_2 = __webpack_require__(97);
Object.defineProperty(exports, "GCODEExporter", ({ enumerable: true, get: function () { return cjs_2.GCODEExporter; } }));
var cjs_3 = __webpack_require__(102);
Object.defineProperty(exports, "SVGExporter", ({ enumerable: true, get: function () { return cjs_3.SVGExporter; } }));
var svg_importer_1 = __webpack_require__(109);
Object.defineProperty(exports, "SVGImporter", ({ enumerable: true, get: function () { return svg_importer_1.SVGImporter; } }));
//# sourceMappingURL=modules.js.map
/***/ }),
/* 2 */
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DrawerCanvas = exports.Animation = void 0;
__exportStar(__webpack_require__(3), exports);
exports.Animation = __webpack_require__(58);
var BrowserDrawerCanvas_1 = __webpack_require__(68);
Object.defineProperty(exports, "DrawerCanvas", ({ enumerable: true, get: function () { return BrowserDrawerCanvas_1.BrowserDrawerCanvas; } }));
//# sourceMappingURL=modules-light.js.map
/***/ }),
/* 3 */
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.mod = exports.log = exports.PI2 = exports.PHI = exports.Vec2 = exports.distributePointsInBuffer = exports.prepareBufferForInterpolation = exports.interpolate = exports.distanceFromRepetition = exports.angle2FromRepetition = exports.angleFromRepetition = exports.random = exports.noise = exports.now = exports.toRadians = exports.toDegrees = exports.relativeClamp = exports.clamp = exports.lerp = void 0;
__exportStar(__webpack_require__(4), exports);
__exportStar(__webpack_require__(5), exports);
__exportStar(__webpack_require__(6), exports);
__exportStar(__webpack_require__(7), exports);
__exportStar(__webpack_require__(36), exports);
__exportStar(__webpack_require__(37), exports);
__exportStar(__webpack_require__(38), exports);
__exportStar(__webpack_require__(35), exports);
__exportStar(__webpack_require__(39), exports);
__exportStar(__webpack_require__(40), exports);
__exportStar(__webpack_require__(41), exports);
__exportStar(__webpack_require__(42), exports);
__exportStar(__webpack_require__(43), exports);
__exportStar(__webpack_require__(44), exports);
__exportStar(__webpack_require__(45), exports);
__exportStar(__webpack_require__(46), exports);
__exportStar(__webpack_require__(47), exports);
__exportStar(__webpack_require__(48), exports);
__exportStar(__webpack_require__(49), exports);
__exportStar(__webpack_require__(50), exports);
__exportStar(__webpack_require__(32), exports);
__exportStar(__webpack_require__(51), exports);
var Utilities_1 = __webpack_require__(33);
Object.defineProperty(exports, "lerp", ({ enumerable: true, get: function () { return Utilities_1.lerp; } }));
Object.defineProperty(exports, "clamp", ({ enumerable: true, get: function () { return Utilities_1.clamp; } }));
Object.defineProperty(exports, "relativeClamp", ({ enumerable: true, get: function () { return Utilities_1.relativeClamp; } }));
Object.defineProperty(exports, "toDegrees", ({ enumerable: true, get: function () { return Utilities_1.toDegrees; } }));
Object.defineProperty(exports, "toRadians", ({ enumerable: true, get: function () { return Utilities_1.toRadians; } }));
Object.defineProperty(exports, "now", ({ enumerable: true, get: function () { return Utilities_1.now; } }));
Object.defineProperty(exports, "noise", ({ enumerable: true, get: function () { return Utilities_1.noise; } }));
Object.defineProperty(exports, "random", ({ enumerable: true, get: function () { return Utilities_1.random; } }));
Object.defineProperty(exports, "angleFromRepetition", ({ enumerable: true, get: function () { return Utilities_1.angleFromRepetition; } }));
Object.defineProperty(exports, "angle2FromRepetition", ({ enumerable: true, get: function () { return Utilities_1.angle2FromRepetition; } }));
Object.defineProperty(exports, "distanceFromRepetition", ({ enumerable: true, get: function () { return Utilities_1.distanceFromRepetition; } }));
Object.defineProperty(exports, "interpolate", ({ enumerable: true, get: function () { return Utilities_1.interpolate; } }));
Object.defineProperty(exports, "prepareBufferForInterpolation", ({ enumerable: true, get: function () { return Utilities_1.prepareBufferForInterpolation; } }));
Object.defineProperty(exports, "distributePointsInBuffer", ({ enumerable: true, get: function () { return Utilities_1.distributePointsInBuffer; } }));
var Vec2_1 = __webpack_require__(29);
Object.defineProperty(exports, "Vec2", ({ enumerable: true, get: function () { return Vec2_1.default; } }));
var math_1 = __webpack_require__(30);
Object.defineProperty(exports, "PHI", ({ enumerable: true, get: function () { return math_1.PHI; } }));
Object.defineProperty(exports, "PI2", ({ enumerable: true, get: function () { return math_1.PI2; } }));
Object.defineProperty(exports, "log", ({ enumerable: true, get: function () { return math_1.log; } }));
Object.defineProperty(exports, "mod", ({ enumerable: true, get: function () { return math_1.mod; } }));
//# sourceMappingURL=core.js.map
/***/ }),
/* 4 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Scene = void 0;
const SceneChild_1 = __webpack_require__(5);
const Group_1 = __webpack_require__(6);
const Shape_1 = __webpack_require__(35);
const Utilities_1 = __webpack_require__(33);
/**
* Container for all SceneChild.
* The main purpose is to manage the drawing order and update the child buffers
*
* @order 1
* @category Scene
* @class Scene
*/
class Scene {
/**
* Creates an instance of Scene.
* You can see the default values in the property definitions
*/
constructor(settings = {}) {
/**
* Logical number, the drawer will take care of defining the unit of measure
*/
this.width = 400;
/**
* Logical number, the drawer will take care of defining the unit of measure
*/
this.height = 400;
/**
* Default background color (black)
*/
this.background = 'hsla(0, 0%, 0%, 1)';
/**
* Default ScenePrimitive stroke color (white)
*/
this.color = 'hsla(0, 0%, 100%, 1)';
/**
* Current time
*/
this.currentTime = 0;
if (typeof settings.width !== 'undefined')
this.width = settings.width;
if (typeof settings.height !== 'undefined')
this.height = settings.height;
if (typeof settings.background !== 'undefined')
this.background = settings.background;
if (typeof settings.color !== 'undefined')
this.color = settings.color;
this.children = [];
this.anchorSettings = settings.anchor;
this.setSize(settings.width || this.width, settings.height || this.height, settings.anchor);
}
/**
* set scene size, center and anchor
*
* @private
* @param {number} width
* @param {number} height
* @param {(['left' | 'right' | 'center' | number, 'top' | 'bottom' | 'center' | number])} [anchor]
*/
setSize(width, height, anchor) {
this.width = width;
this.height = height;
this.center = [this.width / 2, this.height / 2];
this.anchor =
anchor && Array.isArray(anchor)
? [
typeof anchor[0] === 'number'
? (0.5 + Utilities_1.clamp(-1, 1, anchor[0]) * 0.5) * this.width
: anchor[0] === 'left'
? 0
: anchor[0] === 'right'
? this.width
: this.center[0],
typeof anchor[1] === 'number'
? (0.5 + Utilities_1.clamp(-1, 1, anchor[1]) * 0.5) * this.height
: anchor[1] === 'top'
? 0
: anchor[1] === 'bottom'
? this.height
: this.center[1],
]
: [this.center[0], this.center[1]];
}
/**
* Return width percentage
*
* @param {number} [percentage=100]
* @returns {number}
*/
getWidth(percentage = 100) {
return (this.width * percentage) / 100;
}
/**
* Return height percentage
*
* @param {number} [percentage=100]
* @returns {number}
*/
getHeight(percentage = 100) {
return (this.height * percentage) / 100;
}
/**
* Resize the scene size
*
* @param {number} width
* @param {number} [height=width]
* @memberof Scene
*/
resize(width, height = width) {
this.setSize(width, height, this.anchorSettings);
this.children.forEach(sceneChild => sceneChild.clearBuffer(true, false));
}
/**
* Update all children, generate a streamable buffer for drawing
*
* @param {number} [atTime] time in ms
* @memberof Scene
*/
update(atTime = 0) {
this.currentTime = atTime;
for (let i = 0, len = this.children.length; i < len; i++) {
this.children[i].generate(this.currentTime, true);
}
}
/**
* Traverse the child buffer and use it with callback
*
* @param {(streamArguments: IStreamArguments) => void} callback
* @memberof Scene
*/
stream(callback) {
this.children.forEach(sceneChild => sceneChild.stream(callback));
}
/*
|--------------------------------------------------------------------------
| SceneChild
|--------------------------------------------------------------------------
*/
/**
* Return a list of children
*
* @returns {Array<SceneChild>}
* @memberof Scene
*/
getChildren() {
return this.children;
}
/**
* Add SceneChild to Scene, pass `order` as last parameter for drawing priorities
*
* @param {Array<SceneChild>} items
* @param {number} [order]
* @memberof Scene
*/
add(...items /**, order: number */) {
const order = typeof items[items.length - 1] === 'number' ? items[items.length - 1] : undefined;
const len = items.length - (typeof order === 'undefined' ? 0 : 1);
for (let i = 0; i < len; i++) {
const item = items[i];
item.order =
typeof order !== 'undefined'
? order + i
: typeof item.order !== 'undefined'
? item.order
: this.children.length > 0
? Math.max.apply(this, this.children.map(e => e.order || 0)) + 1
: 0;
Scene.propagateToChilden(item, this);
this.children.push(item);
item.clearBuffer(true, false);
item.generate(0, true);
}
this.sortChildren();
}
/**
* Sort children by order
*
* @memberof Scene
*/
sortChildren() {
this.children.sort((a, b) => a.order - b.order);
this.children = this.children.map((child, index) => {
child.order = index;
return child;
});
}
/**
* Find sceneChild from id or name in the whole scene
*
* @param {string | number} idOrName
* @returns {(SceneChild | null)}
* @memberof Scene
*/
find(idOrName) {
const children = this.getChildren();
for (let i = 0, len = children.length; i < len; i++) {
const result = children[i].find(idOrName);
if (result !== null)
return result;
}
return null;
}
/**
* Get shape by index
*
* @param {number} index
* @returns {(SceneChild | null)}
* @memberof Scene
*/
get(index) {
return index >= 0 && index < this.children.length ? this.children[index] : null;
}
/**
* Remove a shape by index
*
* @param {number} index
* @memberof Scene
*/
remove(index) {
index >= 0 && index < this.children.length && this.children.splice(index, 1);
}
/**
* Removes all children
*
* @memberof Scene
*/
removeChildren() {
this.children = [];
}
/**
* Remove sceneChild by id or name
*
* @param {number | number} idOrName
* @memberof Scene
*/
removeFromId(idOrName) {
for (let i = 0, len = this.children.length; i < len; i++)
if (this.children[i].id === idOrName || this.children[i].name === idOrName) {
this.children.splice(i, 1);
return;
}
}
/**
* Return true if sceneChild is direct children
*
* @param {SceneChild} sceneChild
* @returns {boolean}
* @memberof Scene
*/
isFirstLevelChild(sceneChild) {
for (let i = 0, len = this.children.length; i < len; i++)
if (this.children[i].id === sceneChild.id)
return true;
const parents = this.getParentsOfSceneChild(sceneChild);
return parents.length === 1 && parents[0] instanceof Group_1.Group;
}
/**
* Returns the list of sceneChild hierarchy starting from the scene
*
* @param {SceneChild} sceneChild
* @returns {Array<SceneChild>}
* @memberof Scene
*/
getParentsOfSceneChild(sceneChild) {
const result = Scene.getParentsOfSceneChild(this, sceneChild);
if (result) {
result.splice(0, 1);
return result;
}
return [];
}
/**
* Returns the list of sceneChild hierarchy starting from the scene
*
* @static
* @param {(Scene | SceneChild)} current
* @param {SceneChild} sceneChild
* @param {(Array<SceneChild | Scene>)} [parents=[]]
* @returns {(Array<SceneChild | Scene> | null)}
* @memberof Scene
*/
static getParentsOfSceneChild(current, sceneChild, parents = []) {
let result;
if (current instanceof SceneChild_1.SceneChild) {
if (current.id == sceneChild.id)
return parents;
if (current instanceof Shape_1.Shape && current.shape) {
const tmpParents = parents.slice();
tmpParents.push(current);
if ((result = Scene.getParentsOfSceneChild(current.shape, sceneChild, tmpParents)))
return result;
}
}
if (current instanceof Scene || current instanceof Group_1.Group) {
const children = current.getChildren();
parents.push(current);
for (let i = 0, len = children.length; i < len; i++) {
const child = children[i];
if ((result = Scene.getParentsOfSceneChild(child, sceneChild, parents)))
return result;
}
parents.pop();
}
return null;
}
/**
* Walk through the scene
*
* @static
* @param {SceneChild} callbackk
* @param {(Scene | SceneChild)} current
* @memberof Scene
*/
static walk(callback, current) {
if (current instanceof SceneChild_1.SceneChild) {
if (callback(current) === false)
return false;
if (current instanceof Shape_1.Shape && current.shape)
if (Scene.walk(callback, current.shape) === false)
return false;
}
if (current instanceof Scene || current instanceof Group_1.Group) {
const children = current.getChildren();
for (let i = 0, len = children.length; i < len; i++) {
const child = children[i];
if (Scene.walk(callback, child) === false)
return false;
}
}
}
/**
* Propagate scene to sceneChild (and children)
*
* @static
* @param {SceneChild} sceneChild
* @param {Scene} scene
* @memberof Scene
*/
static propagateToChilden(sceneChild, scene) {
sceneChild.scene = scene;
if (sceneChild instanceof Group_1.Group) {
sceneChild.getChildren().forEach((item) => {
Scene.propagateToChilden(item, scene);
});
}
else if (sceneChild instanceof Shape_1.Shape && sceneChild.shape) {
sceneChild.shape.scene = scene;
Scene.propagateToChilden(sceneChild.shape, scene);
}
}
}
exports.Scene = Scene;
//# sourceMappingURL=Scene.js.map
/***/ }),
/* 5 */
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.SceneChild = void 0;
/**
* Autoincrement sceneChild default id
*
* @internal
* @ignore
*/
let __id = 0;
/**
* The element to be added into a scene.
* Preserve props, drawing order, generate and return buffers.
* The only implementations of this class are <a href="[base_url]/Group">Group</a> and <a href="[base_url]/ShapeBase">ShapeBase</a>
*
* @abstract
* @category Scene
* @order 2
* @class SceneChild
*/
class SceneChild {
/**
* Creates an instance of SceneChild.
* Base values will be assigned in case they are not passed
*
* @param {ISceneChildSettings} settings
*/
constructor(settings) {
var _a;
/**
* Shape generation id
* used for prevent buffer calculation
*
* @internal
* @ignore
*/
this.generateId = -1;
this.id = (_a = settings.id) !== null && _a !== void 0 ? _a : ++__id;
this.type = settings.type || 'SceneChild';
this.name = settings.name || this.type + '_' + this.id;
this.data = settings.data || {};
this.props = {};
}
/**
* Find this or form or children.
* Overridden by classes that extend it
*
* @param {string | number} idOrName
* @returns {(SceneChild | null)}
*/
find(idOrName) {
if (this.id === idOrName || this.name === idOrName)
return this;
return null;
}
/**
* Return the sceneChild properties
*
* @returns {Props}
*/
getProps() {
return this.props;
}
/**
* Return a sceneChild prop or default value
*
* @param {keyof Props} key
* @param {PropArguments} [propArguments]
* @param {*} [defaultValue]
* @returns {*}
*/
getProp(key, propArguments, defaultValue) {
var _a;
return ((_a = this.props[key]) !== null && _a !== void 0 ? _a : defaultValue);
}
/**
* Check SceneChild has prop
*
* @param {keyof Props} key
* @returns
*/
hasProp(key) {
return typeof this.props[key] !== 'undefined';
}
/**
* Set a single or multiple props
*
* @param {(keyof ISceneChildProps<PropArguments> | ISceneChildProps<PropArguments>)} key
* @param {*} [value]
*/
setPropUnsafe(key, value) {
if (typeof key == 'string')
this.props[key] = value;
else
Object.keys(key).forEach((k) => (this.props[k] = key[k]));
}
}
exports.SceneChild = SceneChild;
//# sourceMappingURL=SceneChild.js.map
/***/ }),
/* 6 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Group = void 0;
const Scene_1 = __webpack_require__(4);
const SceneChild_1 = __webpack_require__(5);
const ShapeBase_1 = __webpack_require__(7);
const Adapt_1 = __webpack_require__(31);
/**
* A SceneChild container, propagates properties to children
*
* @order 3
* @category Scene.Containers
* @extends {SceneChild}
* @example
* ```javascript
* // Group example
*
* const rect = new Urpflanze.Rect({
* distance: 100 // <- if a property is set the group will not overwrite it
* })
* const group = new Urpflanze.Group({
* repetitions: 3,
* distance: 200
* })
*
* group.add(rect)
* group.add(new Urpflanze.Triangle())
* ```
* @class Group
*/
class Group extends SceneChild_1.SceneChild {
/**
* Creates an instance of Group
*
* @param {ISceneChildSettings} [settings={}]
* @memberof Group
*/
constructor(settings = {}) {
settings.type = 'Group';
super(settings);
this.children = [];
['id', 'name', 'data', 'order', 'type'].forEach((prop) => {
if (prop in settings)
delete settings[prop];
});
this.props = settings;
}
/**
* Check group has static children
*
* @returns {boolean}
* @memberof Group
*/
isStatic() {
const children = this.children;
for (let i = 0, len = children.length; i < len; i++)
if (!children[i].isStatic())
return false;
return true;
}
/**
* Check group has static children indexed
*
* @returns {boolean}
* @memberof Group
*/
isStaticIndexed() {
const children = this.children;
for (let i = 0, len = children.length; i < len; i++)
if (!children[i].isStaticIndexed())
return false;
return true;
}
/**
* Add item to Group
*
* @param {Array<SceneChild>} items
* @memberof Group
*/
add(...items) {
for (let i = 0, len = items.length; i < len; i++) {
const item = items[i];
const rawItemProps = item.getProps();
Object.keys(this.props).forEach((propKey) => {
if (typeof rawItemProps[propKey] === 'undefined')
item.setProp(propKey, this.props[propKey]);
});
item.order =
typeof item.order !== 'undefined'
? item.order
: this.children.length > 0
? Math.max.apply(this, this.children.map(e => e.order || 0)) + 1
: 0;
this.scene && Scene_1.Scene.propagateToChilden(item, this.scene);
this.children.push(item);
}
this.sortChildren();
}
/**
* Sort children
*
* @memberof Group
*/
sortChildren() {
this.children.sort((a, b) => a.order - b.order);
this.children = this.children.map((child, index) => {
child.order = index;
return child;
});
this.clearBuffer(true);
}
/**
* Return shape children
*
* @returns {Array<SceneChild>}
* @memberof Group
*/
getChildren() {
return this.children;
}
/**
* Find scene child from id or name
*
* @param {number | string} idOrName
* @returns {(SceneChild | null)}
* @memberof Group
*/
find(idOrName) {
if (this.id === idOrName || this.name === idOrName)
return this;
const children = this.getChildren();
for (let i = 0, len = children.length; i < len; i++) {
const result = children[i].find(idOrName);
if (result !== null)
return result;
}
return null;
}
/**
* Get item from group
*
* @param {number} index
* @returns {(SceneChild | null)}
* @memberof Group
*/
get(index) {
return index >= 0 && index < this.children.length ? this.children[index] : null;
}
/**
* Remove item from group
*
* @param {number} index
* @returns {(false | Array<SceneChild>)}
* @memberof Group
*/
remove(index) {
if (index >= 0 && index < this.children.length) {
const removed = this.children.splice(index, 1);
this.clearBuffer(true);
return removed;
}
return false;
}
/**
* Remove from id
*
* @param {number} id
* @memberof Scene
*/
removeFromId(id) {
for (let i = 0, len = this.children.length; i < len; i++) {
if (this.children[i].id == id) {
this.children.splice(i, 1);
return this.clearBuffer(true);
}
}
}
/**
* Generate children buffers
*
* @param {number} generateId
* @param {boolean} [bDirectSceneChild=false]
* @param {IPropArguments} [parentPropArguments]
* @memberof Group
*/
generate(generateId, bDirectSceneChild = false, parentPropArguments) {
this.generateId = generateId;
this.children.forEach(item => item.generate(generateId, bDirectSceneChild, parentPropArguments));
}
/**
* Sum the children bounding
*
* @return {IShapeBounding}
*/
getBounding() {
const boundings = [];
const bounding = Adapt_1.Bounding.empty();
if (this.children.length > 0) {
this.children.forEach(item => boundings.push(item.getBounding()));
for (let i = 0, len = this.children.length; i < len; i++) {
bounding.x = bounding.x > boundings[i].x ? boundings[i].x : bounding.x;
bounding.y = bounding.y > boundings[i].y ? boundings[i].y : bounding.y;
bounding.width = bounding.width < boundings[i].width ? boundings[i].width : bounding.width;
bounding.height = bounding.height < boundings[i].height ? boundings[i].height : bounding.height;
}
bounding.cx = bounding.x + bounding.width / 2;
bounding.cy = bounding.y + bounding.height / 2;
}
return bounding;
}
/**
* Chear children buffer
*
* @param {boolean} [bClearIndexed=false]
* @param {boolean} [bPropagateToParents=false]
* @memberof Group
*/
clearBuffer(bClearIndexed = false, bPropagateToParents = true) {
this.children.forEach(item => item.clearBuffer(bClearIndexed, false));
if (this.scene && bPropagateToParents) {
const parents = this.scene.getParentsOfSceneChild(this);
parents.length > 0 && parents[parents.length - 1].clearBuffer(bClearIndexed, bPropagateToParents /* true */);
}
// if (bPropagateToParents && this.scene)
// {
// const parents = this.scene.getParentsOfSceneChild(this)
// parents.length > 0 && parents[parents.length - 1].clearBuffer(bClearIndexed, true, false)
// }
// if (bPropagateToChildren)
// {
// this.children.forEach(sceneChild => sceneChild.clearBuffer(bClearIndexed, false, true))
// }
}
/**
* Set a single or multiple props
*
* @abstract
* @param {(keyof ISceneChildProps | ISceneChildProps)} key
* @param {*} [value]
* @memberof SceneChild
*/
setProp(key, value) {
if (typeof key === 'object')
Object.keys(key).forEach((k) => (this.props[k] = key[k]));
else
this.props[key] = value;
this.children.forEach(item => item.setProp(key, value));
}
/**
* Set a single or multiple props
*
* @param {(keyof ISceneChildProps | ISceneChildProps)} key
* @param {*} [value]
* @memberof ShapeBase
*/
setPropUnsafe(key, value) {
super.setPropUnsafe(key, value);
this.children.forEach(item => item.setPropUnsafe(key, value));
}
/**
* Return length of buffer
*
* @param {IPropArguments} propArguments
* @returns {number}
* @memberof Group
*/
getBufferLength(propArguments) {
return this.children.map(sceneChild => sceneChild.getBufferLength(propArguments)).reduce((p, c) => p + c, 0);
}
/**
* return a single buffer binded from children
*
* @returns {Float32Array}
* @memberof Group
*/
getBuffer() {
const buffers = this.children
.map(item => item.getBuffer())
.filter(b => b !== undefined);
const size = buffers.reduce((currLength, buffer) => currLength + buffer.length, 0);
if (size > 0) {
const result = new Float32Array(size);
result.set(buffers[0], 0);
for (let i = 1, offset = 0, len = buffers.length; i < len; i++) {
offset += buffers[i - 1].length;
result.set(buffers[i], offset);
}
return result;
}
return ShapeBase_1.ShapeBase.EMPTY_BUFFER;
}
/**
* return a single buffer binded from children
*
* @returns {(Array<IBufferIndex> | undefined)}
* @memberof Group
*/
getIndexedBuffer() {
const indexed = this.children.map(item => item.getIndexedBuffer()).filter(b => b !== undefined);
return [].concat.apply([], indexed);
}
/**
* Call strem on children
*
* @param {(streamArguments: IStreamArguments) => void} callback
* @memberof Group
*/
stream(callback) {
this.children.forEach(item => item.stream(callback));
}
}
exports.Group = Group;
//# sourceMappingURL=Group.js.map
/***/ }),
/* 7 */
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ShapeBase = void 0;
const gl_matrix_1 = __webpack_require__(8);
const types_1 = __webpack_require__(19);
const glme = __webpack_require__(28);
const Vec2_1 = __webpack_require__(29);
const math_1 = __webpack_require__(30);
const Adapt_1 = __webpack_require__(31);
const Utilities_1 = __webpack_require__(33);
const SceneChild_1 = __webpack_require__(5);
const tmpMatrix = gl_matrix_1.mat4.create();
const transformMatrix = gl_matrix_1.mat4.create();
const perspectiveMatrix = gl_matrix_1.mat4.create();
const repetitionMatrix = gl_matrix_1.mat4.create();
/**
* Main class for shape generation
*
* @category Scene
* @abstract
* @class ShapeBase
* @order 4
* @extends {SceneChild}
*/
class ShapeBase extends SceneChild_1.SceneChild {
/**
* Creates an instance of ShapeBase
*
* @param {ISceneChildSettings} [settings={}]
*/
constructor(settings = {}) {
super(settings);
/**
* Flag used to determine if indexedBuffer has been generated
*
* @internal
* @ignore
*/
this.bIndexed = false;
/**
* Array used for index a vertex buffer
* only for first level scene children
*
* @internal
* @ignore
*/
this.indexedBuffer = [];
/**
* The bounding inside the scene
*
* @type {IShapeBounding}
*/
this.bounding = {
cx: 0,
cy: 0,
x: -1,
y: -1,
width: 2,
height: 2,
};
this.props = {
distance: settings.distance,
repetitions: settings.repetitions,
rotateX: settings.rotateX,
rotateY: settings.rotateY,
rotateZ: settings.rotateZ,
skewX: settings.skewX,
skewY: settings.skewY,
squeezeX: settings.squeezeX,
squeezeY: settings.squeezeY,
displace: settings.displace,
translate: settings.translate,
scale: settings.scale,
transformOrigin: settings.transformOrigin,
perspective: settings.perspective,
perspectiveOrigin: settings.perspectiveOrigin,
};
this.anchor =
settings.anchor && Array.isArray(settings.anchor)
? [
typeof settings.anchor[0] === 'number'
? Utilities_1.clamp(-1, 1, settings.anchor[0]) * -1
: settings.anchor[0] === 'left'
? 1
: settings.anchor[0] === 'right'
? -1
: 0,
typeof settings.anchor[1] === 'number'
? Utilities_1.clamp(-1, 1, settings.anchor[1]) * -1
: settings.anchor[1] === 'top'
? 1
: settings.anchor[1] === 'bottom'
? -1
: 0,
]
: [0, 0];
this.boundingType =
typeof settings.boundingType === 'string'
? settings.boundingType === 'relative'
? types_1.EBoundingType.Relative
: types_1.EBoundingType.Fixed
: settings.boundingType || types_1.EBoundingType.Fixed;
this.vertexCallback = settings.vertexCallback;
}
/**
* Check if the shape should be generated every time
*
* @returns {boolean}
*/
isStatic() {
const props = this.props;
return (typeof props.repetitions !== 'function' &&
typeof props.distance !== 'function' &&
typeof props.displace !== 'function' &&
typeof props.scale !== 'function' &&
typeof props.translate !== 'function' &&
typeof props.skewX !== 'function' &&
typeof props.skewY !== 'function' &&
typeof props.squeezeX !== 'function' &&
typeof props.squeezeY !== 'function' &&
typeof props.rotateX !== 'function' &&
typeof props.rotateY !== 'function' &&
typeof props.rotateZ !== 'function' &&
typeof props.transformOrigin !== 'function' &&
typeof props.perspective !== 'function' &&
typeof props.perspectiveOrigin !== 'function');
}
/**
* Check if the indexedBuffer array needs to be recreated every time,
* this can happen when a shape generates an array of vertices different in length at each repetition
*
* @returns {boolean}
*/
isStaticIndexed() {
return typeof this.props.repetitions !== 'function';
}
/**
* Return a prop value
*
* @param {keyof ISceneChildProps} key
* @param {PropArguments} [propArguments]
* @param {*} [defaultValue]
* @returns {*}
*/
getProp(key, propArguments, defaultValue) {
let attribute = this.props[key];
if (typeof attribute === 'function') {
attribute = attribute(propArguments);
}
return typeof attribute === 'undefined' || Number.isNaN(attribute) ? defaultValue : attribute;
}
/**
* Set a single or multiple props
*
* @param {(keyof ISceneChildProps<PropArguments> | ISceneChildProps<PropArguments>)} key
* @param {*} [value]
* @param {boolean} [bClearIndexed=false]
*/
setProp(key, value, bClearIndexed = false) {
if (typeof key === 'string') {
bClearIndexed = bClearIndexed || key == 'repetitions';
this.props[key] = value;
}
else {
bClearIndexed = bClearIndexed || 'repetitions' in key;
Object.keys(key).forEach((k) => (this.props[k] = key[k]));
}
this.clearBuffer(bClearIndexed, true);
}
/**
* Unset buffer
*
* @param {boolean} [bClearIndexed=false]
* @param {boolean} [bPropagateToParents=false]
* @param {boolean} [bPropagateToChildren=false]
*/
clearBuffer(bClearIndexed = false, bPropagateToParents = true) {
this.buffer = undefined;
if (bClearIndexed) {
this.bIndexed = false;
this.indexedBuffer = [];
}
this.bStatic = this.isStatic();
this.bStaticIndexed = this.isStaticIndexed();
if (bPropagateToParents && this.scene && !this.scene.isFirstLevelChild(this)) {
const parents = this.scene.getParentsOfSceneChild(this);
parents.length > 0 && parents[parents.length - 1].clearBuffer(bClearIndexed, bPropagateToParents /* true */);
}
}
/**
* Update the vertex array if the shape is not static and update the indexedBuffer if it is also not static
*
* @param {number} generateId generation id
* @param {boolean} [bDirectSceneChild=false] adjust shape of center of scene
* @param {PropArguments} [parentPropArguments]
*/
generate(generateId = 0, bDirectSceneChild = false, parentPropArguments) {
var _a, _b;
if (this.buffer && this.bStatic) {
return;
}
this.generateId = generateId;
if (!this.bStaticIndexed || !this.bIndexed)
this.indexedBuffer = [];
const propArguments = ShapeBase.getEmptyPropArguments(this, parentPropArguments);
const repetition = propArguments.repetition;
const repetitions = this.getProp('repetitions', propArguments, 1);
const repetitionType = Array.isArray(repetitions) ? types_1.ERepetitionType.Matrix : types_1.ERepetitionType.Ring;
const repetitionCount = Array.isArray(repetitions)
? repetitions[0] * ((_a = repetitions[1]) !== null && _a !== void 0 ? _a : repetitions[0])
: repetitions;
const repetitionRowCount = Array.isArray(repetitions) ? repetitions[0] : repetitionCount;
const repetitionColCount = Array.isArray(repetitions) ? (_b = repetitions[1]) !== null && _b !== void 0 ? _b : repetitions[0] : 1;
const rowRepetition = repetition.row;
rowRepetition.count = repetitionRowCount;
const colRepetition = repetition.col;
colRepetition.count = repetitionColCount;
repetition.count = repetitionCount;
repetition.col.count = repetitionColCount;
repetition.row.count = repetitionRowCount;
repetition.type = repetitionType;
let totalBufferLength = 0;
const buffers = [];
let currentIndex = 0;
const centerMatrix = gl_matrix_1.vec2.fromValues((repetitionColCount - 1) / 2, (repetitionRowCount - 1) / 2);
const sceneAnchor = this.scene ? [this.scene.anchor[0], this.scene.anchor[1], 0] : [0, 0, 0];
const tmpTotalShapeBounding = [undefined, undefined, undefined, undefined];
const tmpSingleRepetitionBounding = [undefined, undefined, undefined, undefined];
for (let currentRowRepetition = 0; currentRowRepetition < repetitionRowCount; currentRowRepetition++) {
for (let currentColRepetition = 0; currentColRepetition < repetitionColCount; currentColRepetition++, currentIndex++) {
repetition.index = currentIndex + 1;
repetition.offset = repetitionCount > 1 ? currentIndex / (repetitionCount - 1) : 1;
repetition.angle = repetitionType === types_1.ERepetitionType.Ring ? (math_1.PI2 / repetitionCount) * currentIndex : 0;
colRepetition.index = currentColRepetition + 1;
colRepetition.offset = repetitionColCount > 1 ? currentColRepetition / (repetitionColCount - 1) : 1;
rowRepetition.index = currentRowRepetition + 1;
rowRepetition.offset = repetitionRowCount > 1 ? currentRowRepetition / (repetitionRowCount - 1) : 1;
// Generate primitives buffer recursively
const buffer = this.generateBuffer(generateId, propArguments);
const bufferLength = buffer.length;
const bounding = this.getShapeBounding();
buffers[currentIndex] = new Float32Array(bufferLength);
totalBufferLength += bufferLength;
{
const distance = glme.toVec2(this.getProp('distance', propArguments, glme.VEC2_ZERO));
const displace = this.getProp('displace', propArguments, 0);
const scale = glme.toVec3(this.getProp('scale', propArguments, glme.VEC2_ONE), 1);
const translate = glme.toVec3(this.getProp('translate', propArguments, glme.VEC2_ZERO), 0);
const skewX = this.getProp('skewX', propArguments, 0);
const skewY = this.getProp('skewY', propArguments, 0);
const squeezeX = this.getProp('squeezeX', propArguments, 0);
const squeezeY = this.getProp('squeezeY', propArguments, 0);
const rotateX = this.getProp('rotateX', propArguments, 0);
const rotateY = this.getProp('rotateY', propArguments, 0);
const rotateZ = this.getProp('rotateZ', propArguments, 0);
const perspective = Utilities_1.clamp(0, 1, this.getProp('perspective', propArguments, 0));
const perspectiveOrigin = glme.toVec3(this.getProp('perspectiveOrigin', propArguments, glme.VEC2_ZERO), 0);
const transformOrigin = glme.toVec3(this.getProp('transformOrigin', propArguments, glme.VEC2_ZERO), 0);
let offset;
switch (repetitionType) {
case types_1.ERepetitionType.Ring:
offset = gl_matrix_1.vec3.fromValues(distance[0], 0, 0);
gl_matrix_1.vec3.rotateZ(offset, offset, glme.VEC3_ZERO, repetition.angle + displace);
break;
case types_1.ERepetitionType.Matrix:
offset = gl_matrix_1.vec3.fromValues(distance[1] * (currentColRepetition - centerMatrix[0]), distance[0] * (currentRowRepetition - centerMatrix[1]), 0);
break;
}
const perspectiveSize = perspective > 0 ? Math.max(bounding.width, bounding.height) / 2 : 1;
const perspectiveValue = perspective > 0 ? perspectiveSize + (1 - perspective) * (perspectiveSize * 10) : 0;
const bTransformOrigin = (this.boundingType === types_1.EBoundingType.Relative ? bounding.cx !== 0 || bounding.cy !== 0 : true) ||
perspective !== 0 ||
transformOrigin[0] !== 0 ||
transformOrigin[1] !== 0;
const bPerspectiveOrigin = perspectiveOrigin[0] !== 0 || perspectiveOrigin[1] !== 0;
if (bTransformOrigin) {
if (this.boundingType === types_1.EBoundingType.Relative) {
transformOrigin[0] = transformOrigin[0] * (bounding.width / 2) + bounding.cx;
transformOrigin[1] = transformOrigin[1] * (bounding.height / 2) + bounding.cy;
}
else {
transformOrigin[0] *= bounding.width / 2;
transformOrigin[1] *= bounding.height / 2;
}
transformOrigin[2] = perspectiveValue;
}
/**
* Create Matrices
*/
{
/**
* Create Transformation matrix
*/
gl_matrix_1.mat4.identity(transformMatrix);
bTransformOrigin && gl_matrix_1.mat4.translate(transformMatrix, transformMatrix, transformOrigin);
if (translate[0] !== 0 || translate[1] !== 0)
gl_matrix_1.mat4.translate(transformMatrix, transformMatrix, translate);
if (skewX !== 0 || skewY !== 0) {
glme.fromSkew(tmpMatrix, [skewX, skewY]);
gl_matrix_1.mat4.multiply(transformMatrix, transformMatrix, tmpMatrix);
}
rotateX !== 0 && gl_matrix_1.mat4.rotateX(transformMatrix, transformMatrix, rotateX);
rotateY !== 0 && gl_matrix_1.mat4.rotateY(transformMatrix, transformMatrix, rotateY);
rotateZ !== 0 && gl_matrix_1.mat4.rotateZ(transformMatrix, transformMatrix, rotateZ);
if (scale[0] !== 1 || scale[1] !== 1)
gl_matrix_1.mat4.scale(transformMatrix, transformMatrix, scale);
bTransformOrigin &&
gl_matrix_1.mat4.translate(transformMatrix, transformMatrix, gl_matrix_1.vec3.scale(transformOrigin, transformOrigin, -1));
/**
* Create Perspective matrix
*/
if (perspectiveValue > 0) {
if (bPerspectiveOrigin) {
if (this.boundingType === types_1.EBoundingType.Relative) {
perspectiveOrigin[0] = perspectiveOrigin[0] * (bounding.width / 2) + bounding.cx;
perspectiveOrigin[1] = perspectiveOrigin[1] * (bounding.height / 2) + bounding.cy;
}
else {
perspectiveOrigin[0] *= bounding.width / 2;
perspectiveOrigin[1] *= bounding.height / 2;
}
perspectiveOrigin[2] = 0;
}
gl_matrix_1.mat4.perspective(perspectiveMatrix, -Math.PI / 2, 1, 0, Infinity);
}
/**
* Create Repetition matrix
*/
gl_matrix_1.mat4.identity(repetitionMatrix);
gl_matrix_1.mat4.translate(repetitionMatrix, repetitionMatrix, offset);
if (bDirectSceneChild) {
gl_matrix_1.mat4.translate(repetitionMatrix, repetitionMatrix, sceneAnchor);
}
/**
* Apply anchor
*/
const shapeAnchor = [this.anchor[0] * (bounding.width / 2), this.anchor[1] * (bounding.height / 2), 0];
gl_matrix_1.mat4.translate(repetitionMatrix, repetitionMatrix, shapeAnchor);
if (r