import { Graphics } from '@pixi/graphics' ; import { HANDLE_TO_CURSOR } from './Transformer' ; import { ObjectPoolFactory } from '@pixi-essentials/object-pool' ; import { Matrix , Point } from '@pixi/math' ; import { distanceToLine } from './utils/distanceToLine' ; import type { AxisAlignedBounds , OrientedBounds } from '@pixi-essentials/bounds' ; import type { Handle , Transformer } from './Transformer' ; const pointPool = ObjectPoolFactory . build ( Point ) ; const tempHull = [ new Point ( ) , new Point ( ) , new Point ( ) , new Point ( ) ] ; const tempMatrix = new Matrix ( ) ; const tempPoint = new Point ( ) ; ignore internal const boxRotationRegionTopLeft = [ 0 , 0 , 0 , 1 , - 1 , 1 , - 1 , - 1 , 1 , - 1 , 1 , 0 , ] ; ignore internal const boxRotationRegionTopRight = [ 0 , 0 , - 1 , 0 , - 1 , - 1 , 1 , - 1 , 1 , 1 , 0 , 1 , ] ; ignore internal const boxRotationRegionBottomLeft = [ 0 , 0 , 1 , 0 , 1 , 1 , - 1 , 1 , - 1 , - 1 , 0 , - 1 , ] ; ignore internal const boxRotationRegionBottomRight = [ 0 , 0 , 0 , - 1 , 1 , - 1 , 1 , 1 , - 1 , 1 , - 1 , 0 , ] ; ignore internal const boxRotationTemp = new Array ( 12 ) ; ignore internal const boxRotationRegions = [ boxRotationRegionTopLeft , boxRotationRegionTopRight , boxRotationRegionBottomLeft , boxRotationRegionBottomRight , ] ; ignore public export class TransformerWireframe extends Graphics { protected transformer : Transformer ; /**
     * The four scaling "edges" (or wide handles) for box-scaling.  TransformerWireframe * should draw into these.
      protected boxScalingHandles : [ Graphics , Graphics , Graphics , Graphics ] ; constructor ( transformer ) { super ( ) ; this . transformer = transformer ; this . boxScalingHandles = [ this . addChild ( new Graphics ( ) ) , this . addChild ( new Graphics ( ) ) , this . addChild ( new Graphics ( ) ) , this . addChild ( new Graphics ( ) ) , ] ; this . boxScalingHandles . forEach ( ( scalingHandle ) => { scalingHandle . interactive = true ; } ) ; this . boxScalingHandles [ 0 ] . cursor = HANDLE_TO_CURSOR . topCenter ; this . boxScalingHandles [ 1 ] . cursor = HANDLE_TO_CURSOR . middleRight ; this . boxScalingHandles [ 2 ] . cursor = HANDLE_TO_CURSOR . bottomCenter ; this . boxScalingHandles [ 3 ] . cursor = HANDLE_TO_CURSOR . middleLeft ; } param groupBounds param projectionTransform param pointerPosition public hitHandleType ( groupBounds , projectionTransform , pointerPosition ) { const { boxRotationEnabled , boxRotationTolerance , boxScalingEnabled , boxScalingTolerance , } = this . transformer ; const [ topLeft , topRight , bottomRight , bottomLeft , ] = groupBounds . hull ; const { x , y } = projectionTransform . applyInverse ( pointerPosition , tempPoint ) ; if ( boxScalingEnabled ) { const topProximity = distanceToLine ( x , y , topLeft , topRight ) * projectionTransform . d ; const leftProximity = distanceToLine ( x , y , topLeft , bottomLeft ) * projectionTransform . a ; const rightProximity = distanceToLine ( x , y , topRight , bottomRight ) * projectionTransform . a ; const bottomProximity = distanceToLine ( x , y , bottomLeft , bottomRight ) * projectionTransform . d ; const minProximity = Math . min ( topProximity , leftProximity , rightProximity , bottomProximity ) ; if ( minProximity < boxScalingTolerance ) { switch ( minProximity ) { case topProximity : return 'topCenter' ; case leftProximity : return 'middleLeft' ; case rightProximity : return 'middleRight' ; case bottomProximity : return 'bottomCenter' ; } } } if ( boxRotationEnabled && ! groupBounds . contains ( x , y ) ) { const tlProximity = Math . sqrt ( ( ( topLeft . x - x ) ** 2 ) + ( ( topLeft . y - y ) ** 2 ) ) ; const trProximity = Math . sqrt ( ( ( topRight . x - x ) ** 2 ) + ( ( topRight . y - y ) ** 2 ) ) ; const blProximity = Math . sqrt ( ( ( bottomLeft . x - x ) ** 2 ) + ( ( bottomLeft . y - y ) ** 2 ) ) ; const brProximity = Math . sqrt ( ( ( bottomRight . x - x ) ** 2 ) + ( ( bottomRight . y - y ) ** 2 ) ) ; const minProximity = Math . min ( tlProximity , trProximity , blProximity , brProximity ) ; if ( minProximity < boxRotationTolerance * 1.45 ) { switch ( minProximity ) { case tlProximity : return 'boxRotateTopLeft' ; case trProximity : return 'boxRotateTopRight' ; case blProximity : return 'boxRotateBottomLeft' ; case brProximity : return 'boxRotateBottomRight' ; } } } return null ; } param bounds public drawBounds ( bounds ) { const hull = tempHull ; for ( let i = 0 ; i < 4 ; i ++ ) { this . transformer . projectToLocal ( bounds . hull [ i ] , hull [ i ] ) ; } this . drawPolygon ( hull ) ; } /**
     * Draws around edges of the bounding box to capture pointer events within
     *  Transformer .
     *
     *  param bounds param boxScalingTolerance public drawBoxScalingTolerance ( bounds , boxScalingTolerance = this . transformer . boxScalingTolerance ) { bounds . innerBounds . pad ( - boxScalingTolerance ) ; const innerHull = pointPool . allocateArray ( 4 ) ; innerHull . forEach ( ( innerCorner , i ) => { this . projectToLocal ( bounds . hull [ i ] , innerCorner ) ; } ) ; bounds . innerBounds . pad ( 2.5 * boxScalingTolerance ) ; const outerHull = pointPool . allocateArray ( 4 ) ; outerHull . forEach ( ( outerCorner , i ) => { this . projectToLocal ( bounds . hull [ i ] , outerCorner ) ; } ) ; bounds . innerBounds . pad ( - 1.5 * this . transformer . boxScalingTolerance ) ; for ( let i = 0 ; i < 4 ; i ++ ) { const innerStart = innerHull [ i ] ; const innerEnd = innerHull [ ( i + 1 ) % 4 ] ; const outerStart = outerHull [ i ] ; const outerEnd = outerHull [ ( i + 1 ) % 4 ] ; const boxScalingHandle = this . boxScalingHandles [ i ] ; boxScalingHandle . clear ( ) . beginFill ( 0xffffff , 1e-4 ) . drawPolygon ( innerStart , outerStart , outerEnd , innerEnd ) . endFill ( ) ; } } /**
     * Draws square-shaped tolerance regions for capturing pointer events within  Transformer * of the four corners of the group bounding box. The square are cut in the interior region of the group bounds.
      public drawBoxRotationTolerance ( ) { const { boxRotateTopLeft : tl , boxRotateTopRight : tr , boxRotateBottomLeft : bl , boxRotateBottomRight : br , } = this . transformer . handleAnchors ; const t = this . transformer . boxRotationTolerance * 2 ; const matrix = tempMatrix . identity ( ) . scale ( t , t ) . rotate ( this . transformer . getGroupBounds ( ) . rotation ) ; for ( let i = 0 ; i < 4 ; i ++ ) { const region = boxRotationRegions [ i ] ; let position ; switch ( i ) { case 0 : position = tl ; break ; case 1 : position = tr ; break ; case 2 : position = bl ; break ; case 3 : position = br ; break ; } for ( let j = 0 ; j < region . length ; j += 2 ) { const x = region [ j ] ; const y = region [ j + 1 ] ; tempPoint . set ( x , y ) ; matrix . apply ( tempPoint , tempPoint ) ; boxRotationTemp [ j ] = tempPoint . x + position . x ; boxRotationTemp [ j + 1 ] = tempPoint . y + position . y ; } this . drawPolygon ( boxRotationTemp . slice ( ) ) ; } } /**
     * Alias for  Transformer . The transform of the wireframe should equal that
     * of the transformer itself.
     *
     *  param input param output protected projectToLocal ( input , output ) { return this . transformer . projectToLocal ( input , output ) ; } }