UNPKG

@awayjs/view

Version:
300 lines (271 loc) 8.83 kB
import { Vector3D, AbstractionBase, IAbstractionPool } from '@awayjs/core'; import { IPartitionTraverser } from '../partition/IPartitionTraverser'; import { INode } from '../partition/INode'; import { ITabContainer } from '../base/ITabContainer'; import { ContainerNode } from '../partition/ContainerNode'; /** * Picks a 3d object from a view or scene by 3D raycast calculations. * Performs an initial coarse boundary calculation to return a subset of entities whose bounding volumes intersect with the specified ray, * then triggers an optional picking collider on individual renderable objects to further determine the precise values of the picking ray collision. * * @class away.pick.RaycastPicker */ export class TabPicker extends AbstractionBase implements IPartitionTraverser { /** * * @returns {ContainerNode} */ public get node(): INode { return <INode> this._asset; } private _tabNodes: ContainerNode[] = []; private _customTabNodes: ContainerNode[][] = []; private _customTabNodesSorted: ContainerNode[] = []; /** * Creates a new <code>RaycastPicker</code> object. * * @param findClosestCollision Determines whether the picker searches for the closest bounds collision along the ray, * or simply returns the first collision encountered. Defaults to false. */ public init(node: INode, pool: IAbstractionPool) { super.init(node, pool); } private sortTabEnabledEntities(): void { if (this._customTabNodes.length <= 0 && this._tabNodes.length <= 0) return; const snapGridY: number = 10; let len: number = 0; const orderedOnY: ContainerNode[][] = []; let i: number = 0; let e: number = 0; if (this._customTabNodes.length > 0) { while (i < this._customTabNodes.length) { if (this._customTabNodes[i]) { this._customTabNodes[i] = this._customTabNodes[i].reverse(); } i++; } return; } // first sort into rows based on global y-position, snapping y-positions to a grid // than sort the rows by global x-position len = this._tabNodes.length; for (i = 0; i < len; i++) { const enabledNode = this._tabNodes[i]; const scenePosition: Vector3D = enabledNode.parent.getMatrix3D().position; //console.log("enabledEntity.scenePosition.y", scenePosition.y); const ySnappedToGrid = Math.floor(scenePosition.y / snapGridY); if (orderedOnY.length <= ySnappedToGrid) { orderedOnY.length = ySnappedToGrid + 1; } if (!orderedOnY[ySnappedToGrid]) orderedOnY[ySnappedToGrid] = []; orderedOnY[ySnappedToGrid].push(enabledNode); } this._tabNodes.length = 0; for (i = 0; i < orderedOnY.length; i++) { let entityRow = orderedOnY[i]; if (entityRow) { //console.log("entityRow", entityRow.length); entityRow = entityRow.sort(function(a, b) { return a.parent.getMatrix3D().position.x > b.parent.getMatrix3D().position.x ? 1 : -1; }); for (e = 0; e < entityRow.length; e++) { //console.log("2enabledEntity.scenePosition.y", entityRow[e].transform.concatenatedMatrix3D.position.y); //console.log("2enabledEntity.scenePosition.x", entityRow[e].transform.concatenatedMatrix3D.position.x); this._tabNodes[this._tabNodes.length] = entityRow[e]; } } } } public traverse(): void { this._tabNodes.length = 0; this._customTabNodes.length = 0; this._customTabNodesSorted.length = 0; (<INode> this._asset).acceptTraverser(this); this.sortTabEnabledEntities(); this._invalid = false; } public getTraverser(node: ContainerNode): IPartitionTraverser { return this; } public getNextTabEntity(currentFocus: ContainerNode): ContainerNode { if (this._invalid) this.traverse(); if (this._customTabNodes.length <= 0 && this._tabNodes.length <= 0) return currentFocus; if (this._customTabNodes.length > 0) { var i: number = 0; let i2: number = 0; let t: number = 0; let t2: number = 0; if (currentFocus) { while (i < this._customTabNodes.length) { if (this._customTabNodes[i]) { for (t = 0; t < this._customTabNodes[i].length; t++) { if (this._customTabNodes[i][t] == currentFocus) { t2 = t + 1; while (t2 < this._customTabNodes[i].length) { if (this._customTabNodes[i][t2]) return this._customTabNodes[i][t2]; t2++; } i2 = i + 1; while (i2 < this._customTabNodes.length) { if (this._customTabNodes[i2]) { for (t2 = 0; t2 < this._customTabNodes[i2].length; t2++) { if (this._customTabNodes[i2][t2]) return this._customTabNodes[i2][t2]; } } i2++; } i2 = 0; while (i2 < this._customTabNodes.length) { if (this._customTabNodes[i2]) { for (t2 = 0; t2 < this._customTabNodes[i2].length; t2++) { if (this._customTabNodes[i2][t2]) return this._customTabNodes[i2][t2]; } } i2++; } } } } i++; } } i2 = 0; while (i2 < this._customTabNodes.length) { if (this._customTabNodes[i2]) { for (t2 = 0; t2 < this._customTabNodes[i2].length; t2++) { if (this._customTabNodes[i2][t2]) return this._customTabNodes[i2][t2]; } } i2++; } return currentFocus; } const len: number = this._tabNodes.length; for (var i: number = 0; i < len; i++) { if (this._tabNodes[i] == currentFocus) { if (i == len - 1) { return this._tabNodes[0]; } return this._tabNodes[i + 1]; } } // this point we would already have exit out if tabEntities.length was 0 return this._tabNodes[0]; } public getPrevTabEntity(currentFocus: ContainerNode): ContainerNode { if (this._invalid) this.traverse(); if (this._customTabNodes.length <= 0 && this._tabNodes.length <= 0) return currentFocus; if (this._customTabNodes.length > 0) { var i: number = this._customTabNodes.length; let i2: number = 0; let t: number = 0; let t2: number = 0; if (currentFocus) { while (i > 0) { i--; if (this._customTabNodes[i]) { for (t = this._customTabNodes[i].length - 1; t >= 0; t--) { if (this._customTabNodes[i][t] == currentFocus) { t2 = t - 1; while (t2 > 0) { t2--; if (this._customTabNodes[i][t2]) return this._customTabNodes[i][t2]; } i2 = i - 1; while (i2 > 0) { i2--; if (this._customTabNodes[i2]) { for (t2 = this._customTabNodes[i2].length - 1;t2 >= 0; t2--) { if (this._customTabNodes[i2][t2]) return this._customTabNodes[i2][t2]; } } } i2 = this._customTabNodes.length; while (i2 > 0) { i2--; if (this._customTabNodes[i2]) { for (t2 = this._customTabNodes[i2].length - 1; t2 >= 0; t2--) { if (this._customTabNodes[i2][t2]) return this._customTabNodes[i2][t2]; } } } } } } } } i2 = this._customTabNodes.length - 1; while (i2 > 0) { i2--; if (this._customTabNodes[i2]) { for (t2 = this._customTabNodes[i2].length - 1;t2 >= 0; t2--) { if (this._customTabNodes[i2][t2]) return this._customTabNodes[i2][t2]; } } } return currentFocus; } if (currentFocus) { const len: number = this._tabNodes.length; for (var i: number = len - 1; i >= 0; i--) { if (this._tabNodes[i] == currentFocus) { if (i == 0) { return this._tabNodes[this._tabNodes.length - 1]; } return this._tabNodes[i - 1]; } } } // this point we would already have exit out if tabEntities.length was 0 return this._tabNodes[0]; } /** * Returns true if the current node is at least partly in the frustum. If so, the partition node knows to pass on the traverser to its children. * * @param node The Partition3DNode object to frustum-test. */ public enterNode(node: INode): boolean { if (node.isInvisible()) return false; return true; } public dispose(): void { //TODO } /** * * @param entity */ public applyEntity(node: ContainerNode): void { const tabContainer = <ITabContainer> node.container; if (tabContainer.tabEnabled) { if (tabContainer.assetType != '[asset TextField]' || (<any> tabContainer).type == 'input') { // add the entity to the correct tab list. if (tabContainer.tabIndex >= 0) { if (this._customTabNodes.length < tabContainer.tabIndex) this._customTabNodes.length = tabContainer.tabIndex; if (!this._customTabNodes[tabContainer.tabIndex]) { this._customTabNodes[tabContainer.tabIndex] = []; } this._customTabNodes[tabContainer.tabIndex].push(node); } else { this._tabNodes[this._tabNodes.length] = node; } } } } }