UNPKG

infamous

Version:

A CSS3D/WebGL UI library.

157 lines (127 loc) 5.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _lowclass = _interopRequireDefault(require("lowclass")); var _Mixin = _interopRequireDefault(require("./Mixin")); require("geometry-interfaces"); var _ImperativeBase = _interopRequireWildcard(require("./ImperativeBase")); var _HTMLNode = _interopRequireDefault(require("../html/HTMLNode")); var _Scene = _interopRequireDefault(require("./Scene")); var _three = require("three"); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const radiansPerDegree = 1 / 360 * 2 * Math.PI; (0, _ImperativeBase.initImperativeBase)(); let Node = (0, _Mixin.default)(Base => (0, _lowclass.default)('Node').extends(_ImperativeBase.default.mixin(Base), ({ Super }) => ({ static: { defaultElementName: 'i-node' }, /** * @constructor * * @param {Object} options Initial properties that the node will * have. This can be used when creating a node, alternatively to using the * setters/getters for position, rotation, etc. * * @example * var node = new Node({ * size: {x:100, y:100, z:100}, * rotation: {x:30, y:20, z:25} * }) */ constructor(options = {}) { const self = Super(this).constructor(options); // This was when using my `multiple()` implementation, we could call // specific constructors using specific arguments. But, we're using // class-factory style mixins for now, so we don't have control over the // specific arguments we can pass to the constructors, so we're just // using a single `options` parameter in all the constructors. //self.callSuperConstructor(Transformable, options) //self.callSuperConstructor(TreeNode) //self.callSuperConstructor(ImperativeBase) self._scene = null; // stores a ref to this Node's root Scene. /** * @private * This method is defined here in the consructor as an arrow function * because parent Nodes pass it to Observable#on and Observable#off. If * it were a prototype method, then it would need to be bound when * passed to Observable#on, which would require keeping track of the * bound function reference in order to be able to pass it to * Observable#off later. See ImperativeBase#add and * ImperativeBase#remove. */ self._onParentSizeChange = () => { // We only need to recalculate sizing and matrices if this node has // properties that depend on parent sizing (proportional size, // align, and mountPoint). mountPoint isn't obvious: if this node // is proportionally sized, then the mountPoint will depend on the // size of this element which depends on the size of this element's // parent. Align also depends on parent sizing. if (self._properties.sizeMode.x === "proportional" || self._properties.sizeMode.y === "proportional" || self._properties.sizeMode.z === "proportional" || self._properties.align.x !== 0 || self._properties.align.y !== 0 || self._properties.align.z !== 0) { self._calcSize(); self._needsToBeRendered(); } }; self._calcSize(); self._needsToBeRendered(); return self; }, makeThreeObject3d() { return new _three.Object3D(); }, /** * Get the Scene that this Node is in, null if no Scene. This is recursive * at first, then cached. * * This traverses up the scene graph tree starting at this Node and finds * the root Scene, if any. It caches the value for performance. If this * Node is removed from a parent node with parent.remove(), then the * cache is invalidated so the traversal can happen again when this Node is * eventually added to a new tree. This way, if the scene is cached on a * parent Node that we're adding this Node to then we can get that cached * value instead of traversing the tree. * * @readonly */ get scene() { // NOTE: this._scene is initally null, created in the constructor. // if already cached, return it. Or if no parent, return it (it'll be null). if (this._scene || !this.parent) return this._scene; // if the parent node already has a ref to the scene, use that. if (this.parent._scene) { this._scene = this.parent._scene; } else if (this.parent instanceof _Scene.default) { this._scene = this.parent; } // otherwise call the scene getter on the parent, which triggers // traversal up the scene graph in order to find the root scene (null // if none). else { this._scene = this.parent.scene; } return this._scene; }, /** * @private * This method to be called only when this Node has this.scene. * Resolves the _scenePromise for all children of the tree of this Node. */ _giveSceneRefToChildren() { const children = this.subnodes; for (let i = 0, l = children.length; i < l; i += 1) { const childNode = children[i]; childNode._scene = this._scene; childNode._giveSceneRefToChildren(); } }, _resetSceneRef() { this._scene = null; const children = this.subnodes; for (let i = 0, l = children.length; i < l; i += 1) { children[i]._resetSceneRef(); } } }))); // TODO for now, hard-mixin the HTMLInterface class. We'll do this automatically later. exports.default = Node; exports.default = Node = Node.mixin(_HTMLNode.default);