import { QueryRowFormat } from "@itwin/core-common" ; import { FeatureSymbology , IModelConnection , SceneContext , SnapshotConnection , SpatialModelState , TiledGraphicsProvider , TileTreeReference , Viewport , } from "@itwin/core-frontend" ; import { DisplayTestApp } from "./App" ; /** A reference to a TileTree originating from a different IModelConnection than the one the user opened. */ class ExternalTreeRef extends TileTreeReference { private readonly _ref : TileTreeReference ; private readonly _ovrs : FeatureSymbology . Overrides ; public constructor ( ref , ovrs ) { super ( ) ; this . _ref = ref ; this . _ovrs = ovrs ; } public override get castsShadows ( ) { return this . _ref . castsShadows ; } public get treeOwner ( ) { return this . _ref . treeOwner ; } public override addToScene ( context ) { const tree = this . treeOwner . load ( ) ; if ( undefined === tree ) return ; const args = this . createDrawArgs ( context ) ; if ( undefined === args ) return ; tree . draw ( args ) ; args . graphics . symbologyOverrides = this . _ovrs ; const branch = context . createBranch ( args . graphics , args . location ) ; context . outputGraphic ( branch ) ; } } class Provider implements TiledGraphicsProvider { private readonly _refs : TileTreeReference [ ] = [ ] ; public readonly iModel : IModelConnection ; private constructor ( vp , iModel , ovrs ) { this . iModel = iModel ; for ( const model of iModel . models ) { const spatial = model . asSpatialModel ; if ( undefined !== spatial ) { const ref = spatial . createTileTreeReference ( vp . view ) ; this . _refs . push ( new ExternalTreeRef ( ref , ovrs ) ) ; } } } public static async create ( vp , iModel ) { const query = { from : SpatialModelState . classFullName , wantPrivate : false } ; const props = await iModel . models . queryProps ( query ) ; const modelIds = [ ] ; for ( const prop of props ) if ( undefined !== prop . id ) modelIds . push ( prop . id ) ; await iModel . models . load ( modelIds ) ; const ecsql = "SELECT DISTINCT Category.Id as CategoryId from BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId from BisCore.SpatialCategory)" ; const catIds = [ ] ; for await ( const catId of iModel . query ( ecsql , undefined , { rowFormat : QueryRowFormat . UseJsPropertyNames } ) ) catIds . push ( catId . categoryId ) ; const subcatsRequest = iModel . subcategories . load ( catIds ) ; if ( undefined !== subcatsRequest ) await subcatsRequest . promise ; const ovrs = new FeatureSymbology . Overrides ( ) ; for ( const catId of catIds ) { const subcats = iModel . subcategories . getSubCategories ( catId ) ; if ( undefined !== subcats ) for ( const subcat of subcats ) ovrs . setVisibleSubCategory ( subcat ) ; } return new Provider ( vp , iModel , ovrs ) ; } public forEachTileTreeRef ( _vp , func ) { for ( const ref of this . _refs ) func ( ref ) ; } } const providersByViewport = new Map < Viewport , Provider > ( ) ; /** A simple proof-of-concept for drawing tiles from a different IModelConnection into a Viewport. */ export async function toggleExternalTiledGraphicsProvider ( vp ) { const existing = providersByViewport . get ( vp ) ; if ( undefined !== existing ) { vp . dropTiledGraphicsProvider ( existing ) ; providersByViewport . delete ( vp ) ; await existing . iModel . close ( ) ; return ; } const filename = await DisplayTestApp . surface . selectFileName ( ) ; if ( undefined === filename ) return ; let iModel ; try { iModel = await SnapshotConnection . openFile ( filename ) ; const provider = await Provider . create ( vp , iModel ) ; providersByViewport . set ( vp , provider ) ; vp . addTiledGraphicsProvider ( provider ) ; } catch ( err ) { alert ( err . toString ( ) ) ; return ; } }