import { applyMeshTransformToActor , updateActorMeshTransform } from '@lib/graphics/meshHelper' ; import { Actor } from 'satisfactory-json' ; import { Mesh , MeshMatcapMaterial , Scene } from 'three' ; import ColorFactory from './ColorFactory' ; import GeometryFactory from './GeometryFactory' ; import InstancedMeshGroup from './InstancedMeshGroup' ; /**
 * Interface for Meshes
 * This can be either a wrapper around a usual THREE.Mesh or points to a node in an InstancedMesh
 */ export interface ModelMesh { getPathName ( ) : string ; getRaycastMesh ( ) : Mesh ; addToScene ( scene ) : void ; removeFromScene ( scene ) : void ; rebuildGeometry ( actor , geometryFactory ) : void ; rebuildColor ( actor , colorFactory ) : void ; dispose ( ) : void ; setSelected ( selected , colorFactory , scene ) : void ; applyTransformToActor ( actor ) : void ; applyTransform ( actor ) : void ; } export class ThreeModelMesh implements ModelMesh { private mesh : Mesh ; private material : MeshMatcapMaterial ; constructor ( mesh ) { this . mesh = mesh ; this . material = ( mesh . material as MeshMatcapMaterial ) . clone ( ) as MeshMatcapMaterial ; this . mesh . material = this . material ; for ( const child of this . mesh . children ) { if ( child instanceof Mesh ) { child . material = this . material ; } } } getPathName ( ) { return this . mesh . userData . pathName ; } getRaycastMesh ( ) { return this . mesh ; } addToScene ( scene ) { scene . add ( this . mesh ) ; } removeFromScene ( scene ) { scene . remove ( this . mesh ) ; } rebuildGeometry ( actor , geometryFactory ) { geometryFactory . createGeometry ( actor ) . then ( result => ( this . mesh . geometry = result . geometry ) ) ; } rebuildColor ( actor , colorFactory ) { this . material . color = colorFactory . getColor ( actor ) ; } dispose ( ) { } setSelected ( selected , colorFactory , scene ) { if ( selected ) { this . mesh . material = colorFactory . getSelectedMaterial ( ) ; for ( const child of this . mesh . children ) { if ( child instanceof Mesh ) { child . material = colorFactory . getSelectedMaterial ( ) ; } } } else { this . mesh . material = this . material ; for ( const child of this . mesh . children ) { if ( child instanceof Mesh ) { child . material = this . material ; } } } } applyTransformToActor ( actor ) { applyMeshTransformToActor ( this . mesh , actor ) ; } applyTransform ( actor ) { updateActorMeshTransform ( this . mesh , actor ) ; } } export class InstancedModelMesh implements ModelMesh { private instancedMeshGroup : InstancedMeshGroup ; private index : number ; private raycastMesh : Mesh ; constructor ( instancedMeshGroup , index , raycastMesh ) { this . instancedMeshGroup = instancedMeshGroup ; this . index = index ; this . raycastMesh = raycastMesh ; } getPathName ( ) { return this . raycastMesh . userData . pathName ; } getRaycastMesh ( ) { return this . raycastMesh ; } addToScene ( scene ) { this . instancedMeshGroup . setVisible ( this . index , true ) ; } removeFromScene ( scene ) { scene . remove ( this . raycastMesh ) ; this . instancedMeshGroup . setVisible ( this . index , false ) ; } rebuildGeometry ( actor , geometryFactory ) { geometryFactory . createGeometry ( actor ) . then ( result => this . instancedMeshGroup . setGeometry ( result . geometry ) ) ; } rebuildColor ( actor , colorFactory ) { this . instancedMeshGroup . setColor ( this . index , colorFactory . getColor ( actor ) ) ; } dispose ( ) { } setSelected ( selected , colorFactory , scene ) { if ( selected ) { this . raycastMesh . material = colorFactory . getSelectedMaterial ( ) ; scene . add ( this . raycastMesh ) ; } else { scene . remove ( this . raycastMesh ) ; } this . instancedMeshGroup . setVisible ( this . index , ! selected ) ; } applyTransformToActor ( actor ) { applyMeshTransformToActor ( this . raycastMesh , actor ) ; } applyTransform ( actor ) { updateActorMeshTransform ( this . raycastMesh , actor ) ; this . instancedMeshGroup . setTransform ( this . index , this . raycastMesh . position , this . raycastMesh . quaternion , this . raycastMesh . scale ) ; } }