import { AfterViewInit , Directive , Input , OnDestroy } from '@angular/core' ; import { AbstractObject3D } from '../object/abstract-object-3d' ; import * as THREE from 'three' ; import { AnimationService } from '../animation/animation.service' ; import { Subscription } from 'rxjs' ; @ Directive ( { selector : '[atft-dashed-draw]' } ) export class DashedDrawDirective implements AfterViewInit , OnDestroy { @ Input ( ) dashColor : string | number = '#FF0000' ; @ Input ( ) dashIncrement = 10 ; @ Input ( ) initialOpacity ; @ Input ( ) targetOpacity ; @ Input ( ) hideDash = false ; private edges : any ; private material : THREE . Material ; private stop = false ; protected animation : Subscription ; constructor ( private host , private animationService ) { } ngAfterViewInit ( ) { this . tryToFindGeometry ( ) ; this . animate = this . animate . bind ( this ) ; this . animation = this . animationService . animate . subscribe ( this . animate ) ; this . animationService . start ( ) ; } private tryToFindGeometry ( ) { const object = this . host . getObject ( ) as THREE . Object3D ; object . traverse ( child => { const findMesh = ( child instanceof THREE . Mesh ? child : child . children [ 0 ] ) ; if ( findMesh && findMesh instanceof THREE . Mesh && ! this . edges ) { const edgesGeom = new THREE . EdgesGeometry ( findMesh . geometry , 8 ) ; this . edges = new THREE . LineSegments ( edgesGeom , new THREE . LineDashedMaterial ( { color : this . dashColor } ) ) ; this . edges . computeLineDistances ( ) ; this . edges . material . dashSize = 0 ; this . edges . material . gapSize = this . edges . geometry . attributes . lineDistance . array [ this . edges . geometry . attributes . lineDistance . count - 1 ] ; this . material = findMesh . material as THREE . Material ; if ( this . initialOpacity >= 0.0 ) { if ( ! this . material . transparent ) { this . material . transparent = true ; } this . material . opacity = this . initialOpacity ; } findMesh . add ( this . edges ) ; } else { } } ) ; } private animate ( ) { if ( ! this . stop ) { if ( this . edges ) { this . edges . material . dashSize += this . dashIncrement ; if ( this . edges . material . dashSize >= this . edges . material . gapSize ) { if ( this . hideDash ) { this . edges . parent . children = [ ] ; } if ( this . targetOpacity >= 0.0 ) { this . material . opacity = this . targetOpacity ; if ( this . targetOpacity === 1 ) { this . material . transparent = false ; } } this . stop = true ; } } else { this . tryToFindGeometry ( ) ; } } } ngOnDestroy ( ) { this . animation ?. unsubscribe ( ) ; } }