UNPKG

meta-next

Version:

281 lines (235 loc) 5.83 kB
import Engine from "../Engine" import Vector2 from "../math/Vector2" import Vector3 from "../math/Vector3" import Matrix4 from "../math/Matrix4" import AABB from "../math/AABB" class Node { constructor() { this._position = new Vector2(0, 0) this._worldPosition = null this._scale = new Vector2(1, 1) this._pivot = new Vector2(0, 0) this._anchor = null this._size = new Vector2(0, 0) this.color = new Vector3(1, 1, 1) this._volume = new AABB() this._transform = new Matrix4() this._angle = 0.0 this.parent = null this.children = null this.needUpdateTransform = true this.needUpdateVolume = true this.needUpdateOffset = true } updateTransform() { if(this.parent) { const parentSize = this.parent._size const parentPivot = this.parent._pivot this._transform.copy(this.parent.transform) if(this._anchor) { this._transform.translate( this._position.x - (parentSize.x * parentPivot.x) + (parentSize.x * this._anchor.x), this._position.y - (parentSize.y * parentPivot.y) + (parentSize.y * this._anchor.y), 0.0) } else { this._transform.translate( this._position.x - (parentSize.x * parentPivot.x), this._position.y - (parentSize.y * parentPivot.y), 0.0) } } else { this._transform.identity() if(this._anchor) { const engineWindow = Engine.window this._transform.translate( this._position.x + (engineWindow.width * this._anchor.x), this._position.y + (engineWindow.height * this._anchor.y), 0.0) } else { this._transform.translate(this._position.x, this._position.y, 0.0) } } if(this._angle !== 0.0) { this._transform.rotate(this._angle, 0, 0, 1.0) } if(this._scale.x !== 1.0 || this._scale.y !== 1.0) { this._transform.scale(this._scale.x, this._scale.y, 1.0) } if(this.children) { for(let n = 0; n < this.children.length; n++) { this.children[n].needUpdateTransform = true } } this.needUpdateTransform = false this.needUpdateVolume = true } updateVolume() { if(this.parent) { const worldPosition = this.worldPosition this._volume.set( worldPosition.x - (this._pivot.x * this._size.x), worldPosition.y - (this._pivot.y * this._size.y), this._size.x * this._scale.x | 0, this._size.y * this._scale.y | 0) } else { this._volume.set( this._position.x - (this._pivot.x * this._size.x), this._position.y - (this._pivot.y * this._size.y), this._size.x * this._scale.x | 0, this._size.y * this._scale.y | 0) } this.needUpdateVolume = false } get worldPosition() { if(this.parent) { const worldPosition = this.parent.worldPosition if(!this._worldPosition) { this._worldPosition = new Vector2(worldPosition.x + this._position.x, worldPosition.y + this._position.y) } else { this._worldPosition.set(worldPosition.x + this._position.x, worldPosition.y + this._position.y) } return this._worldPosition } return this._position } clampX(increment, min, max) { const volume = this.volume if((volume.minX + increment) < min) { this.x = this._size.x * this._pivot.x return true } else if((volume.maxX + increment) > max) { this.x = max - this._size.x * this._pivot.x return true } this.x += increment return false } clampY(increment, min, max) { const volume = this.volume if((volume.minY + increment) < min) { this.y = this._size.y * this._pivot.y return true } else if((volume.maxY + increment) > max) { this.y = max - this._size.y * this._pivot.y return true } this.y += increment return false } addChild(node) { if(!this.children) { this.children = [ node ] } else { this.children.push(node) } node.parent = this node.needUpdateTransform = true } removeChild(node) { if(!this.children) { return } if(node.parent !== this) { console.warn(`(Node.removeChild) Node has different parent: ${node.parent}`) return } const index = this.children.indexOf(node) if(index === -1) { return } this.children[index] = this.children[this.children.length - 1] this.children.pop() node.parent = null node.needUpdateTransform = true } detach() { if(!this.parent) { return } this.parent.removeChild(this) } get position() { this.needUpdateTransform = true return this._position } set angle(angle) { if(this._angle === angle) { return } this._angle = angle this.needUpdateTransform = true } get angle() { return this._angle } get scale() { this.needUpdateTransform = true return this._scale } get pivot() { this.needUpdateTransform = true this.needUpdateOffset = true return this._pivot } get anchor() { if(!this._anchor) { this._anchor = new Vector2(0, 0) } this.needUpdateTransform = true return this._anchor } get size() { this.needUpdateTransform = true this.needUpdateOffset = true return this._size } get volume() { if(this.needUpdateVolume) { this.updateVolume() } return this._volume } get transform() { if(this.needUpdateTransform) { this.updateTransform() } return this._transform; } set x(value) { this._position.x = value this.needUpdateTransform = true } get x() { return this._position.x } set y(value) { this._position.y = value this.needUpdateTransform = true } get y() { return this._position.y } get width() { return this._size.x } get height() { return this._size.y } } export default Node