import type { Nullable } from "@thi.ng/api" ; import { assert } from "@thi.ng/errors/assert" ; import type { Mat } from "@thi.ng/matrices" ; import type { ReadonlyVec , Vec } from "@thi.ng/vectors" ; import type { ISceneNode , NodeInfo } from "./api.js" ; export abstract class ANode < T extends ISceneNode < any > > { id : string ; parent : Nullable < T > ; children : T [ ] ; body : any ; mat ! : Mat ; invMat ! : Mat ; enabled : boolean ; display : boolean ; constructor ( id , parent ? , body ? ) { this . id = id ; this . parent = parent ; this . children = [ ] ; if ( parent ) { parent . children . push ( < any > this ) ; } this . body = body ; this . mat = [ ] ; this . invMat = [ ] ; this . enabled = true ; this . display = true ; } appendChild ( node ) { this . children . push ( node ) ; return this ; } insertChild ( i , node ) { const children = this . children ; i < 0 && ( i += children . length ) ; assert ( i >= 0 && i <= children . length , "index out of bounds" ) ; children . splice ( i , 0 , node ) ; node . parent = < any > this ; node . update ( ) ; return this ; } abstract deleteChild ( node ) ; abstract update ( ) ; draw < T > ( ctx ) { if ( this . display ) { for ( let c of this . children ) { c . draw ( ctx ) ; } } } param p childForPoint ( p ) { if ( this . enabled ) { const children = this . children ; for ( let i = children . length ; i -- > 0 ; ) { const n = children [ i ] . childForPoint ( p ) ; if ( n ) { return n ; } } const q = this . mapGlobalPoint ( p ) ; if ( q && this . containsLocalPoint ( q ) ) { return { node : < any > this , p : q } ; } } } param p abstract mapGlobalPoint ( p ) ; param dest param p abstract mapLocalPointToNode ( dest , p ) ; param p containsLocalPoint ( _ ) { return false ; } protected _deleteChild ( node , clazz ) { const i = node instanceof clazz ? this . children . indexOf ( < any > node ) : < number > node ; if ( i !== - 1 ) { this . children . splice ( i , 1 ) ; return true ; } return false ; } }