import { Layer , picking , project32 } from '@deck.gl/core' ; import GL from '@luma.gl/constants' ; import { Geometry , Model } from '@luma.gl/core' ; import { RGBA } from '../colors' ; import { AccessorObjectInfo , Flow } from '../types' ; import FragmentShader from './AnimatedFlowLinesLayerFragment.glsl' ; import VertexShader from './AnimatedFlowLinesLayerVertex.glsl' ; import { LayerProps } from '../LayerProps' ; export interface Props extends LayerProps { id : string ; opacity ? : number ; pickable ? : boolean ; updateTriggers ? : { [ key ] : { } ; } ; data : Flow [ ] ; drawOutline : boolean ; outlineColor ? : RGBA ; outlineThickness ? : number ; currentTime ? : number ; thicknessUnit ? : number ; animationTailLength ? : number ; getSourcePosition ? : ( d : Flow ) => [ number , number ] ; getTargetPosition ? : ( d : Flow ) => [ number , number ] ; getStaggering ? : ( d : Flow , info : AccessorObjectInfo ) => number ; getPickable ? : ( d : Flow , { index } : { index : number ; } ) => number ; getColor ? : ( d : Flow ) => RGBA ; getThickness ? : ( d : Flow ) => number ; getEndpointOffsets ? : ( d : Flow ) => [ number , number ] ; } const DEFAULT_COLOR = [ 0 , 132 , 193 , 255 ] ; export default class AnimatedFlowLinesLayer extends Layer { static defaultProps = { currentTime : 0 , animationTailLength : 0.7 , getSourcePosition : { type : 'accessor' , value : ( d ) => d . sourcePosition } , getTargetPosition : { type : 'accessor' , value : ( d ) => d . targetPosition } , getPickable : { type : 'accessor' , value : ( d ) => 1.0 } , getStaggering : { type : 'accessor' , value : ( d , { index } ) => Math . random ( ) } , getColor : { type : 'accessor' , value : DEFAULT_COLOR } , getThickness : { type : 'accessor' , value : 1 } , thicknessUnit : 15 * 2 , parameters : { depthTest : false , } , } ; constructor ( props ) { super ( props ) ; } getShaders ( ) { return super . getShaders ( { vs : VertexShader , fs : FragmentShader , modules : [ project32 , picking ] , shaderCache : this . context . shaderCache , } ) ; } initializeState ( ) { const attributeManager = this . getAttributeManager ( ) ; attributeManager . addInstanced ( { instanceSourcePositions : { size : 3 , transition : true , accessor : 'getSourcePosition' , } , instanceTargetPositions : { size : 3 , transition : true , accessor : 'getTargetPosition' , } , instanceColors : { size : 4 , type : GL . UNSIGNED_BYTE , transition : true , accessor : 'getColor' , defaultValue : [ 0 , 0 , 0 , 255 ] , } , instanceWidths : { size : 1 , transition : true , accessor : 'getThickness' , defaultValue : 1 , } , instanceStaggering : { accessor : 'getStaggering' , size : 1 , transition : false , } , instancePickable : { accessor : 'getPickable' , size : 1 , transition : false , } , } ) ; } updateState ( { props , oldProps , changeFlags } ) { super . updateState ( { props , oldProps , changeFlags } ) ; if ( changeFlags . extensionsChanged ) { const { gl } = this . context ; if ( this . state . model ) { this . state . model . delete ( ) ; } this . setState ( { model : this . _getModel ( gl ) } ) ; this . getAttributeManager ( ) . invalidateAll ( ) ; } } draw ( { uniforms } ) { const { currentTime , thicknessUnit , animationTailLength } = this . props ; this . state . model . setUniforms ( { ... uniforms , thicknessUnit : thicknessUnit ! * 4 , animationTailLength , currentTime , } ) . draw ( ) ; } _getModel ( gl ) { const positions = [ 0 , - 1 , 0 , 0 , 1 , 0 , 1 , - 1 , 0 , 1 , 1 , 0 ] ; return new Model ( gl , Object . assign ( { } , this . getShaders ( ) , { id : this . props . id , geometry : new Geometry ( { drawMode : GL . TRIANGLE_STRIP , attributes : { positions : new Float32Array ( positions ) , } , } ) , isInstanced : true , } ) ) ; } }