import { IModelJson as GeomJson , LineString3d , Point3d , Vector3d } from "@itwin/core-geometry" ; import { ColorDef , GeometryStreamProps } from "@itwin/core-common" ; import { AccuDrawHintBuilder , BeButtonEvent , DecorateContext , DynamicsContext , EventHandled , GraphicType , HitDetail , IModelApp , PrimitiveTool , SnapStatus , } from "@itwin/core-frontend" ; export class DrawingAidTestTool extends PrimitiveTool { public static override toolId = "DrawingAidTest.Points" ; public readonly points : Point3d [ ] = [ ] ; protected _snapGeomId ? : string ; public override requireWriteableTarget ( ) { return false ; } public override async onPostInstall ( ) { await super . onPostInstall ( ) ; this . setupAndPromptForNextAction ( ) ; } public setupAndPromptForNextAction ( ) { IModelApp . accuSnap . enableSnap ( true ) ; if ( 0 === this . points . length ) return ; const hints = new AccuDrawHintBuilder ( ) ; hints . enableSmartRotation = true ; if ( this . points . length > 1 && ! ( this . points [ this . points . length - 1 ] . isAlmostEqual ( this . points [ this . points . length - 2 ] ) ) ) hints . setXAxis ( Vector3d . createStartEnd ( this . points [ this . points . length - 2 ] , this . points [ this . points . length - 1 ] ) ) ; hints . setOrigin ( this . points [ this . points . length - 1 ] ) ; hints . sendHints ( ) ; } public override testDecorationHit ( id ) { return id === this . _snapGeomId ; } public override getDecorationGeometry ( _hit ) { if ( this . points . length < 2 ) return undefined ; const geomData = GeomJson . Writer . toIModelJson ( LineString3d . create ( this . points ) ) ; return ( undefined === geomData ? undefined : [ geomData ] ) ; } public override decorate ( context ) { if ( this . points . length < 2 ) return ; if ( undefined === this . _snapGeomId ) this . _snapGeomId = this . iModel . transientIds . next ; const builder = context . createGraphicBuilder ( GraphicType . WorldDecoration , undefined , this . _snapGeomId ) ; builder . setSymbology ( context . viewport . getContrastToBackgroundColor ( ) , ColorDef . black , 1 ) ; builder . addLineString ( this . points ) ; context . addDecorationFromBuilder ( builder ) ; } public override onDynamicFrame ( ev , context ) { if ( this . points . length < 1 ) return ; const builder = context . createSceneGraphicBuilder ( ) ; builder . setSymbology ( context . viewport . getContrastToBackgroundColor ( ) , ColorDef . black , 1 ) ; builder . addLineString ( [ this . points [ this . points . length - 1 ] , ev . point ] ) ; context . addGraphic ( builder . finish ( ) ) ; } public override async onDataButtonDown ( ev ) { this . points . push ( ev . point . clone ( ) ) ; this . setupAndPromptForNextAction ( ) ; if ( ! this . isDynamicsStarted ) this . beginDynamics ( ) ; return EventHandled . No ; } public override async onResetButtonUp ( _ev ) { if ( undefined !== IModelApp . accuSnap . currHit ) { const status = await IModelApp . accuSnap . resetButton ( ) ; if ( SnapStatus . Success === status ) return EventHandled . No ; } await this . onReinitialize ( ) ; return EventHandled . No ; } public override async onUndoPreviousStep ( ) { if ( 0 === this . points . length ) return false ; this . points . pop ( ) ; if ( 0 === this . points . length ) await this . onReinitialize ( ) ; else this . setupAndPromptForNextAction ( ) ; return true ; } public async onRestartTool ( ) { const tool = new DrawingAidTestTool ( ) ; if ( ! await tool . run ( ) ) return this . exitTool ( ) ; } }