@awayjs/view
Version:
View for AwayJS
628 lines (627 loc) • 27 kB
JavaScript
import { __extends } from "tslib";
import { Vector3D, AbstractionBase, Matrix3D, ColorTransform, Point, Transform, PerspectiveProjection, CoordinateSystem, } from '@awayjs/core';
import { HierarchicalProperty } from '../base/HierarchicalProperty';
import { BlendMode, Settings as StageSettings, isNativeBlend } from '@awayjs/stage';
import { AlignmentMode } from '../base/AlignmentMode';
import { OrientationMode } from '../base/OrientationMode';
import { ContainerNodeEvent } from '../events/ContainerNodeEvent';
import { View } from '../View';
var ContainerNode = /** @class */ (function (_super) {
__extends(ContainerNode, _super);
function ContainerNode() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._renderToImage = false;
_this._position = new Vector3D();
_this._matrix3D = new Matrix3D();
_this._inverseMatrix3DDirty = true;
_this._maskDisabled = false;
_this._colorTransformDisabled = false;
_this._transformDisabled = false;
_this._maskId = -1;
_this._masks = [];
_this._childNodes = new Array();
_this._numChildNodes = 0;
_this._hierarchicalPropsDirty = HierarchicalProperty.ALL;
return _this;
}
Object.defineProperty(ContainerNode.prototype, "parent", {
get: function () {
return this._parent;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "numChildNodes", {
get: function () {
return this._numChildNodes;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "container", {
get: function () {
return this._asset;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "pickObjectNode", {
get: function () {
if (this._pickObject != this._asset.pickObject) {
this._pickObject = this._asset.pickObject;
if (this._pickObject) {
this._pickObjectNode = this._pickObject.getAbstraction(this._pool);
if (this._pickObject.pickObjectFromTimeline)
this._pickObjectNode.setParent(this);
}
else {
this._pickObjectNode.setParent(null);
this._pickObjectNode = null;
}
}
return this._pickObjectNode;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "renderToImage", {
get: function () {
var _a = this._asset, blendMode = _a.blendMode, filters = _a.filters, cacheAsBitmap = _a.cacheAsBitmap;
var renderToImage = this.isRenderable() && (cacheAsBitmap ||
filters && filters.length > 0 ||
(blendMode && blendMode !== BlendMode.LAYER && blendMode !== BlendMode.NORMAL && (StageSettings.USE_NON_NATIVE_BLEND || isNativeBlend(blendMode))));
if (this._renderToImage !== renderToImage) {
this._renderToImage = renderToImage;
if (!this._renderToImage)
this.clearLocalNode();
}
return this._renderToImage;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "boundsVisible", {
get: function () {
return false;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "view", {
get: function () {
return this._pool;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "colorTransformDisabled", {
get: function () {
return this._colorTransformDisabled;
},
/**
* Allow disable/enable colorTransform for this node independent of transform, this required for cache phase
* @param value
*/
set: function (value) {
this._colorTransformDisabled = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "maskDisabled", {
get: function () {
return this._maskDisabled;
},
set: function (value) {
this._maskDisabled = value;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ContainerNode.prototype, "transformDisabled", {
get: function () {
return this._transformDisabled;
},
set: function (value) {
if (this._transformDisabled == value)
return;
this._maskDisabled = value;
this._transformDisabled = value;
this._colorTransformDisabled = value;
if (this._transformDisabled) {
this._activeTransform = ContainerNode._nullTransform;
}
else {
this._activeTransform = this._asset.transform;
}
},
enumerable: false,
configurable: true
});
ContainerNode.prototype.getScale9Container = function () {
var _a;
if (this._hierarchicalPropsDirty & HierarchicalProperty.SCALE9) {
this._scale9Container = this._asset.scale9Grid
? this._asset
: (_a = this._parent) === null || _a === void 0 ? void 0 : _a.getScale9Container();
this._hierarchicalPropsDirty ^= HierarchicalProperty.SCALE9;
}
return this._scale9Container;
};
/**
*
*/
ContainerNode.prototype.getPosition = function () {
if (this._positionDirty) {
if (this._asset._registrationMatrix3D &&
this._asset.alignmentMode === AlignmentMode.REGISTRATION_POINT) {
this._position.x = -this._asset._registrationMatrix3D._rawData[12];
this._position.y = -this._asset._registrationMatrix3D._rawData[13];
this._position.z = -this._asset._registrationMatrix3D._rawData[14];
this._position = this.getMatrix3D().transformVector(this._position, this._position);
/*
this._position.decrementBy(
new Vector3D(
this._registrationPoint.x*this._scaleX,
this._registrationPoint.y*this._scaleY,
this._registrationPoint.z*this._scaleZ));
*/
}
else {
this.getMatrix3D().copyColumnTo(3, this._position);
}
this._positionDirty = false;
}
return this._position;
};
/**
*
*/
ContainerNode.prototype.getInverseMatrix3D = function () {
if (this._inverseMatrix3DDirty) {
if (!this._inverseMatrix3D)
this._inverseMatrix3D = new Matrix3D();
this._inverseMatrix3DDirty = false;
this._inverseMatrix3D.copyFrom(this.getMatrix3D());
this._inverseMatrix3D.invert();
}
return this._inverseMatrix3D || (this._inverseMatrix3D = new Matrix3D());
};
ContainerNode.prototype.getMatrix3D = function () {
if (this._hierarchicalPropsDirty & HierarchicalProperty.SCENE_TRANSFORM) {
this._matrix3D.copyFrom(this._activeTransform.matrix3D);
if (!this._transformDisabled) {
if (this._asset._registrationMatrix3D) {
this._matrix3D.prepend(this._asset._registrationMatrix3D);
if (this._asset.alignmentMode != AlignmentMode.REGISTRATION_POINT) {
this._matrix3D.appendTranslation(-this._asset._registrationMatrix3D._rawData[12] * this._activeTransform.scale.x, -this._asset._registrationMatrix3D._rawData[13] * this._activeTransform.scale.y, -this._asset._registrationMatrix3D._rawData[14] * this._activeTransform.scale.z);
}
}
if (this._parent)
this._matrix3D.append(this._parent.getMatrix3D());
// scrollRect-masks are childs of the object that have the scrollRect applied
// to support scrolling we need to:
// - move objects with scrollRect by negative scrollRect position
// - move scrollRect-masks by positive scrollRect position
if (!this._asset.maskMode && this._asset.scrollRect)
this._matrix3D.prependTranslation(-this._asset.scrollRect.x, -this._asset.scrollRect.y, 0);
else if (this._asset.maskMode && this._asset.scrollRect)
this._matrix3D.prependTranslation(this._asset.scrollRect.x, this._asset.scrollRect.y, 0);
}
this._hierarchicalPropsDirty ^= HierarchicalProperty.SCENE_TRANSFORM;
//TODO: refactor controller API
if (this._asset['_iController'])
this._asset['_iController'].updateController();
}
return this._matrix3D;
};
/**
*
*/
ContainerNode.prototype.getRenderMatrix3D = function (cameraTransform) {
if (this._asset.orientationMode == OrientationMode.CAMERA_PLANE) {
var comps = cameraTransform.decompose();
comps[0].copyFrom(this.getPosition());
comps[3].copyFrom(this._activeTransform.scale);
(this._orientationMatrix || (this._orientationMatrix = new Matrix3D())).recompose(comps);
//add in case of registration point
if (this._asset._registrationMatrix3D) {
this._orientationMatrix.prepend(this._asset._registrationMatrix3D);
if (this._asset.alignmentMode != AlignmentMode.REGISTRATION_POINT)
this._orientationMatrix.appendTranslation(-this._asset._registrationMatrix3D._rawData[12] * this._activeTransform.scale.x, -this._asset._registrationMatrix3D._rawData[13] * this._activeTransform.scale.y, -this._asset._registrationMatrix3D._rawData[14] * this._activeTransform.scale.z);
}
return this._orientationMatrix;
}
return this.getMatrix3D();
};
ContainerNode.prototype.getColorTransform = function () {
if (this._colorTransformDisabled) {
return ContainerNode._nullColorTransform;
}
if (this._hierarchicalPropsDirty & HierarchicalProperty.COLOR_TRANSFORM) {
this._hierarchicalPropsDirty ^= HierarchicalProperty.COLOR_TRANSFORM;
if (this._colorTransformDisabled) {
return ContainerNode._nullColorTransform;
}
if (!this._colorTransform)
this._colorTransform = new ColorTransform();
if (this._parent && this._parent.getColorTransform()) {
this._colorTransform.copyFrom(this._parent.getColorTransform());
// we MUST prepend real transform in cached phase, but reset in cached image render phase
this._colorTransform.prepend(this._asset.transform.colorTransform);
}
else {
this._colorTransform.copyFrom(this._asset.transform.colorTransform);
}
/*
// if we will use getter - it return empty blend in USE_UNSAFE_BLEND = false
if ((<any> (<IContainer> this._asset))._blendMode === BlendMode.OVERLAY) {
// apply 0.5 alpha for object with `overlay` because we not support it now
this._colorTransform.alphaMultiplier *= 0.5;
}*/
}
return this._colorTransform || ContainerNode._nullColorTransform;
};
/**
*
* @returns {number}
*/
ContainerNode.prototype.getMaskId = function () {
if (this._hierarchicalPropsDirty & HierarchicalProperty.MASK_ID) {
this._maskId = (this._asset.maskId != -1)
? this._asset.maskId
: (this._parent)
? this._parent.getMaskId()
: -1;
this._hierarchicalPropsDirty ^= HierarchicalProperty.MASK_ID;
}
return this._maskId;
};
ContainerNode.prototype.getMasks = function (update) {
if (update === void 0) { update = false; }
if (!update) {
return this._masks;
}
if (this._asset.masks) {
var len = this._asset.masks.length;
this._masks.length = len;
for (var i = 0; i < len; i++) {
this._masks[i] = this._pool.getNode(this._asset.masks[i]);
}
}
else {
this._masks.length = 0;
}
return this._masks;
};
ContainerNode.prototype.getMaskOwners = function () {
var _a;
if (this._hierarchicalPropsDirty & HierarchicalProperty.MASKS) {
var masks = this.getMasks(true);
this._maskOwners = this._maskDisabled
? null
: (((_a = this._parent) === null || _a === void 0 ? void 0 : _a.getMaskOwners()) && this.getMaskId() == -1)
? masks.length
? this._parent.getMaskOwners().concat([this])
: this._parent.getMaskOwners().concat()
: masks.length
? [this]
: null;
this._hierarchicalPropsDirty ^= HierarchicalProperty.MASKS;
}
return this._maskOwners;
};
/**
* Converts the `point` object from the Stage(global) coordinates to the
* display object's(local) coordinates.
*
* To use this method, first create an instance of the Point class. The _x_
* and _y_ values that you assign represent global coordinates because they
* relate to the origin(0,0) of the main display area. Then pass the Point
* instance as the parameter to the `globalToLocal()` method. The method
* returns a new Point object with _x_ and _y_ values that relate to the
* origin of the display object instead of the origin of the Stage.
*
*/
ContainerNode.prototype.globalToLocal = function (point, target) {
if (target === void 0) { target = null; }
var tmp = ContainerNode._tempVector3D;
tmp.setTo(point.x, point.y, 0);
var pos = this.getInverseMatrix3D().transformVector(tmp, tmp);
if (!target) {
target = new Point();
}
target.x = pos.x;
target.y = pos.y;
return target;
};
/**
* Converts a two-dimensional point from the Scene(global) coordinates to a
* three-dimensional display object's(local) coordinates.
*
* <p>To use this method, first create an instance of the Vector3D class. The x,
* y and z values that you assign to the Vector3D object represent global
* coordinates because they are relative to the origin(0,0,0) of the scene. Then
* pass the Vector3D object to the <code>globalToLocal3D()</code> method as the
* <code>position</code> parameter.
* The method returns three-dimensional coordinates as a Vector3D object
* containing <code>x</code>, <code>y</code>, and <code>z</code> values that
* are relative to the origin of the three-dimensional display object.</p>
*
*/
ContainerNode.prototype.globalToLocal3D = function (position) {
return this.getInverseMatrix3D().transformVector(position);
};
/**
* Converts the `point` object from the display object's(local) coordinates
* to the Stage(global) coordinates.
*
* This method allows you to convert any given _x_ and _y_ coordinates from
* values that are relative to the origin(0,0) of a specific display
* object(local coordinates) to values that are relative to the origin of
* the Stage(global coordinates).
*
* To use this method, first create an instance of the Point class. The _x_
* and _y_ values that you assign represent local coordinates because they
* relate to the origin of the display object.
*
* You then pass the Point instance that you created as the parameter to the
* `localToGlobal()` method. The method returns a new Point object with _x_
* and _y_ values that relate to the origin of the Stage instead of the
* origin of the display object.
*
* @param point The name or identifier of a point created with the Point
* class, specifying the _x_ and _y_ coordinates as properties.
* @param target Result point
* @return A Point object with coordinates relative to the Stage.
*/
ContainerNode.prototype.localToGlobal = function (point, target) {
if (target === void 0) { target = null; }
var tmp = ContainerNode._tempVector3D;
tmp.setTo(point.x, point.y, 0);
var pos = this.getMatrix3D().transformVector(tmp, tmp);
if (!target) {
target = new Point();
}
target.x = pos.x;
target.y = pos.y;
return target;
};
ContainerNode.prototype.getBoundsPrimitive = function (_pickGroup) {
return null;
};
ContainerNode.prototype.init = function (container, pool) {
_super.prototype.init.call(this, container, pool);
container._initNode(this);
this._hierarchicalPropsDirty = HierarchicalProperty.ALL;
this._activeTransform = this._asset.transform;
};
ContainerNode.prototype.getLocalNode = function () {
if (!this._localNode) {
/**
* projection is not simple object
* not needed spawn it for every cached partition
* it has 3 matrices = 100 bytes + Transform,
* that have 4 matrices + a lot of vectors (16 bytes) = 300 bytes,
* And this is under heavy extending. 1 projection allocate more that 4kb per instance
*/
var projection = new PerspectiveProjection();
projection.coordinateSystem = CoordinateSystem.LEFT_HANDED;
projection.originX = -1;
projection.originY = -1;
projection.transform = new Transform();
projection.transform.moveTo(0, 0, -1000);
projection.transform.lookAt(new Vector3D());
var view = new View(projection, this.view.stage);
view.backgroundAlpha = 0;
this._localNode = view.getNode(this._asset);
this._localNode.transformDisabled = true;
this._localNode.setParent(this);
}
return this._localNode;
};
ContainerNode.prototype.clearLocalNode = function () {
if (this._localNode) {
this._localNode.onClear(null);
this._localNode = null;
}
};
ContainerNode.prototype.onClear = function (event) {
this.clearLocalNode();
if (this._pickObject) {
this._pickObject = null;
this._pickObjectNode.setParent(null);
this._pickObjectNode = null;
}
for (var i = 0; i < this._numChildNodes; i++)
this._childNodes[i].onClear(event);
this._childNodes.length = 0;
this._numChildNodes = 0;
this._scrollRect = null;
this._scrollRectNode = null;
this._renderToImage = false;
this._isDragEntity = false;
this._positionDirty = false;
this._scale9Container = null;
this._inverseMatrix3DDirty = true;
this._maskDisabled = false;
this._colorTransformDisabled = false;
this._transformDisabled = false;
this._maskOwners = null;
this._masks.length = 0;
this._parent = null;
_super.prototype.clear.call(this);
_super.prototype.onClear.call(this, event);
};
ContainerNode.prototype.onInvalidate = function (event) {
this.invalidate();
};
ContainerNode.prototype.clear = function () {
_super.prototype.clear.call(this);
if (this._localNode)
this._localNode.clear();
for (var i = 0; i < this._numChildNodes; i++)
this._childNodes[i].clear();
if (this._pickObject)
this._pickObjectNode.clear();
};
ContainerNode.prototype.isInFrustum = function (_rootEntity, _planes, _numPlanes, _pickGroup) {
return !this.isInvisible();
};
ContainerNode.prototype.invalidate = function () {
if (this._invalid)
return;
this._invalid = true;
_super.prototype.invalidate.call(this);
if (this._parent)
this._parent.invalidate();
};
/**
* @internal
*/
ContainerNode.prototype.isInvisible = function () {
var _a;
if (this._hierarchicalPropsDirty & HierarchicalProperty.VISIBLE) {
this._invisible = this._transformDisabled
? false
: !this._asset.visible || ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isInvisible());
this._hierarchicalPropsDirty ^= HierarchicalProperty.VISIBLE;
}
return this._invisible;
};
ContainerNode.prototype.isIntersectingRay = function (_rootEntity, _rayPosition, _rayDirection, _pickGroup) {
return true;
};
/**
*
* @returns {boolean}
*/
ContainerNode.prototype.isRenderable = function () {
// if container is invisible - all child nodes automatically invisible to
return this.getMaskId() != -1 || !this.isInvisible() && this.getColorTransform()._isRenderable();
};
/**
*
* @returns {boolean}
*/
ContainerNode.prototype.isCastingShadow = function () {
return true;
};
/**
* @param traverser
*/
ContainerNode.prototype.acceptTraverser = function (traverser) {
this._invalid = false;
//get the sub-traverser for the partition, if different, terminate this traversal
if (traverser.node != this && traverser !== traverser.getTraverser(this))
return;
if (!traverser.enterNode(this))
return;
if (!this._asset.maskMode && this._scrollRect !== this._asset.scrollRect) {
this._scrollRect = this._asset.scrollRect;
if (this._scrollRectNode) {
this._scrollRectNode.setParent(null);
this._scrollRectNode = null;
}
if (this._scrollRect) {
this._scrollRectNode = this._asset.getScrollRectPrimitive()
.getAbstraction(this._pool);
this._scrollRectNode.container.scrollRect = this._scrollRect;
this._scrollRectNode.setParent(this);
}
}
traverser.applyEntity(this);
for (var i = 0; i < this._numChildNodes; i++)
this._childNodes[i].acceptTraverser(traverser);
};
ContainerNode.prototype.addChildAt = function (entity, index) {
var node = entity.getAbstraction(this._pool);
node.setParent(this);
if (index == this._numChildNodes)
this._childNodes.push(node);
else
this._childNodes.splice(index, 0, node);
this._numChildNodes++;
this.invalidate();
return node;
};
ContainerNode.prototype.removeChildAt = function (index) {
this._numChildNodes--;
var node = (index === this._numChildNodes)
? this._childNodes.pop()
: this._childNodes.splice(index, 1)[0];
node.setParent(null);
this.invalidate();
return node;
};
ContainerNode.prototype.getChildAt = function (index) {
return this._childNodes.length > index ? this._childNodes[index] : null;
};
ContainerNode.prototype.startDrag = function () {
this._isDragEntity = true;
};
ContainerNode.prototype.stopDrag = function () {
this._isDragEntity = false;
};
ContainerNode.prototype.isDragEntity = function () {
return this._isDragEntity;
};
ContainerNode.prototype.isMouseDisabled = function () {
var _a;
return this.isInvisible() || !this._asset.mouseEnabled || ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isMouseChildrenDisabled());
};
ContainerNode.prototype.isMouseChildrenDisabled = function () {
var _a;
if (this._hierarchicalPropsDirty & HierarchicalProperty.MOUSE_ENABLED) {
this._mouseChildrenDisabled = !this._asset.mouseChildren || ((_a = this.parent) === null || _a === void 0 ? void 0 : _a.isMouseChildrenDisabled());
this._hierarchicalPropsDirty ^= HierarchicalProperty.MOUSE_ENABLED;
}
return this._mouseChildrenDisabled;
};
ContainerNode.prototype.isDescendant = function (node) {
var parent = this;
while (parent.parent) {
parent = parent.parent;
if (parent == node)
return true;
}
return false;
};
ContainerNode.prototype.invalidateHierarchicalProperty = function (property) {
// property dirty check not working for ColorTransform
// will emit every change
// todo Fixme
if (property & HierarchicalProperty.COLOR_TRANSFORM) {
// eslint-disable-next-line max-len
this.dispatchEvent(this._invalidateColorTransformEvent || (this._invalidateColorTransformEvent = new ContainerNodeEvent(ContainerNodeEvent.INVALIDATE_COLOR_TRANSFORM)));
}
var propertyDirty = (this._hierarchicalPropsDirty ^ property) & property;
if (!propertyDirty)
return;
this._hierarchicalPropsDirty |= propertyDirty;
for (var i = 0; i < this._childNodes.length; ++i)
this._childNodes[i].invalidateHierarchicalProperty(property);
if (this._pickObjectNode)
this._pickObjectNode.invalidateHierarchicalProperty(property);
if (this._localNode)
this._localNode.invalidateHierarchicalProperty(property);
if (property & HierarchicalProperty.SCENE_TRANSFORM) {
this._positionDirty = true;
this._inverseMatrix3DDirty = true;
this.dispatchEvent(this._invalidateMatrix3DEvent
|| (this._invalidateMatrix3DEvent = new ContainerNodeEvent(ContainerNodeEvent.INVALIDATE_MATRIX3D)));
this.invalidate();
}
};
ContainerNode.prototype.setParent = function (parent) {
if (this._parent)
this.clear();
this._parent = parent;
this.invalidateHierarchicalProperty(HierarchicalProperty.ALL);
};
ContainerNode._nullTransform = new Transform();
ContainerNode._tempVector3D = new Vector3D();
ContainerNode._nullColorTransform = new ColorTransform();
return ContainerNode;
}(AbstractionBase));
export { ContainerNode };