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 ) { 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 ) { 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 ) { if ( this . _rows === value ) { return ; } this . _rows = value ; this . _rowThenColum = false ; Tools . SetImmediate ( ( ) => { this . _arrangeChildren ( ) ; } ) ; } /**
     * Creates new VolumeBasedPanel
     */ public constructor ( name ? ) { super ( name ) ; } 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 ) ) ; for ( var child of this . _children ) { if ( ! child . mesh ) { continue ; } controlCount ++ ; child . mesh . computeWorldMatrix ( true ) ; 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 ; 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 , nodePosition ) ; /** Child classes can implement this function to provide additional processing */ protected _finalProcessing ( ) { } }