123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- import { Tools } from "babylonjs/Misc/tools";
- import { Matrix, Vector3, TmpVectors } from "babylonjs/Maths/math.vector";
- import { int } from "babylonjs/types";
- import { Container3D } from "./container3D";
- import { Control3D } from "./control3D";
- /**
- * Abstract class used to create a container panel deployed on the surface of a volume
- */
- export abstract class VolumeBasedPanel extends Container3D {
- private _columns = 10;
- private _rows = 0;
- private _rowThenColum = true;
- private _orientation = Container3D.FACEORIGIN_ORIENTATION;
- protected _cellWidth: number;
- protected _cellHeight: number;
- /**
- * Gets or sets the distance between elements
- */
- public margin = 0;
- /**
- * Gets or sets the orientation to apply to all controls (BABYLON.Container3D.FaceOriginReversedOrientation by default)
- * | Value | Type | Description |
- * | ----- | ----------------------------------- | ----------- |
- * | 0 | UNSET_ORIENTATION | Control rotation will remain unchanged |
- * | 1 | FACEORIGIN_ORIENTATION | Control will rotate to make it look at sphere central axis |
- * | 2 | FACEORIGINREVERSED_ORIENTATION | Control will rotate to make it look back at sphere central axis |
- * | 3 | FACEFORWARD_ORIENTATION | Control will rotate to look at z axis (0, 0, 1) |
- * | 4 | FACEFORWARDREVERSED_ORIENTATION | Control will rotate to look at negative z axis (0, 0, -1) |
- */
- public get orientation(): number {
- return this._orientation;
- }
- public set orientation(value: number) {
- if (this._orientation === value) {
- return;
- }
- this._orientation = value;
- Tools.SetImmediate(() => {
- this._arrangeChildren();
- });
- }
- /**
- * Gets or sets the number of columns requested (10 by default).
- * The panel will automatically compute the number of rows based on number of child controls.
- */
- public get columns(): int {
- return this._columns;
- }
- public set columns(value: int) {
- if (this._columns === value) {
- return;
- }
- this._columns = value;
- this._rowThenColum = true;
- Tools.SetImmediate(() => {
- this._arrangeChildren();
- });
- }
- /**
- * Gets or sets a the number of rows requested.
- * The panel will automatically compute the number of columns based on number of child controls.
- */
- public get rows(): int {
- return this._rows;
- }
- public set rows(value: int) {
- if (this._rows === value) {
- return;
- }
- this._rows = value;
- this._rowThenColum = false;
- Tools.SetImmediate(() => {
- this._arrangeChildren();
- });
- }
- /**
- * Creates new VolumeBasedPanel
- */
- public constructor() {
- super();
- }
- protected _arrangeChildren() {
- this._cellWidth = 0;
- this._cellHeight = 0;
- let rows = 0;
- let columns = 0;
- let controlCount = 0;
- let currentInverseWorld = Matrix.Invert(this.node!.computeWorldMatrix(true));
- // Measure
- for (var child of this._children) {
- if (!child.mesh) {
- continue;
- }
- controlCount++;
- child.mesh.computeWorldMatrix(true);
- // child.mesh.getWorldMatrix().multiplyToRef(currentInverseWorld, Tmp.Matrix[0]);
- let boundingBox = child.mesh.getHierarchyBoundingVectors();
- let extendSize = TmpVectors.Vector3[0];
- let diff = TmpVectors.Vector3[1];
- boundingBox.max.subtractToRef(boundingBox.min, diff);
- diff.scaleInPlace(0.5);
- Vector3.TransformNormalToRef(diff, currentInverseWorld, extendSize);
- this._cellWidth = Math.max(this._cellWidth, extendSize.x * 2);
- this._cellHeight = Math.max(this._cellHeight, extendSize.y * 2);
- }
- this._cellWidth += this.margin * 2;
- this._cellHeight += this.margin * 2;
- // Arrange
- if (this._rowThenColum) {
- columns = this._columns;
- rows = Math.ceil(controlCount / this._columns);
- } else {
- rows = this._rows;
- columns = Math.ceil(controlCount / this._rows);
- }
- let startOffsetX = (columns * 0.5) * this._cellWidth;
- let startOffsetY = (rows * 0.5) * this._cellHeight;
- let nodeGrid = [];
- let cellCounter = 0;
- if (this._rowThenColum) {
- for (var r = 0; r < rows; r++) {
- for (var c = 0; c < columns; c++) {
- nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
- cellCounter++;
- if (cellCounter > controlCount) {
- break;
- }
- }
- }
- } else {
- for (var c = 0; c < columns; c++) {
- for (var r = 0; r < rows; r++) {
- nodeGrid.push(new Vector3((c * this._cellWidth) - startOffsetX + this._cellWidth / 2, (r * this._cellHeight) - startOffsetY + this._cellHeight / 2, 0));
- cellCounter++;
- if (cellCounter > controlCount) {
- break;
- }
- }
- }
- }
- cellCounter = 0;
- for (var child of this._children) {
- if (!child.mesh) {
- continue;
- }
- this._mapGridNode(child, nodeGrid[cellCounter]);
- cellCounter++;
- }
- this._finalProcessing();
- }
- /** Child classes must implement this function to provide correct control positioning */
- protected abstract _mapGridNode(control: Control3D, nodePosition: Vector3): void;
- /** Child classes can implement this function to provide additional processing */
- protected _finalProcessing() {
- }
- }
|