import { ProcessDetector } from "@itwin/core-bentley" ; import { CloudStorageContainerUrl , CloudStorageTileCache , RpcConfiguration , TileContentIdentifier } from "@itwin/core-common" ; import { IModelApp , IModelConnection , RenderDiagnostics , RenderSystem , TileAdmin } from "@itwin/core-frontend" ; import { WebGLExtensionName } from "@itwin/webgl-compatibility" ; import { DtaConfiguration , getConfig } from "../common/DtaConfiguration" ; import { DisplayTestApp } from "./App" ; import { openIModel } from "./openIModel" ; import { signIn } from "./signIn" ; import { Surface } from "./Surface" ; import { setTitle } from "./Title" ; import { showStatus } from "./Utils" ; import { Dock } from "./Window" ; const configuration = { } ; const getFrontendConfig = ( ) => { if ( ProcessDetector . isMobileAppFrontend ) { if ( window ) { const urlParams = new URLSearchParams ( window . location . hash ) ; urlParams . forEach ( ( val , key ) => { ( configuration as any ) [ key ] = val ; Object . assign ( configuration , { iModelName : urlParams . get ( "iModelName" ) } ) ; } ) ; } const newConfigurationInfo = JSON . parse ( window . localStorage . getItem ( "imodeljs:env" ) ! ) ; Object . assign ( configuration , newConfigurationInfo ) ; } Object . assign ( configuration , getConfig ( ) ) ; console . log ( "Configuration" , JSON . stringify ( configuration ) ) ; } ; async function openFile ( filename , writable ) { configuration . standalone = true ; const iModelConnection = await openIModel ( filename , writable ) ; configuration . iModelName = iModelConnection . name ; return iModelConnection ; } class FakeTileCache extends CloudStorageTileCache { public constructor ( ) { super ( ) ; } protected override async requestResource ( container , id ) { const init = { headers : container . headers , method : "GET" , } ; const url = `${ container . url }/${ this . formResourceName ( id ) }` ; return fetch ( url , init ) ; } } const dtaFrontendMain = async ( ) => { RpcConfiguration . developmentMode = true ; RpcConfiguration . disableRoutingValidation = true ; getFrontendConfig ( ) ; const renderSystemOptions = { disabledExtensions : configuration . disabledExtensions as WebGLExtensionName [ ] , preserveShaderSourceCode : true === configuration . preserveShaderSourceCode , logarithmicDepthBuffer : false !== configuration . logarithmicZBuffer , filterMapTextures : true === configuration . filterMapTextures , filterMapDrapeTextures : false !== configuration . filterMapDrapeTextures , dpiAwareViewports : false !== configuration . dpiAwareViewports , devicePixelRatioOverride : configuration . devicePixelRatioOverride , dpiAwareLOD : true === configuration . dpiAwareLOD , useWebGL2 : false !== configuration . useWebGL2 , planProjections : true , debugShaders : true === configuration . debugShaders , antialiasSamples : configuration . antialiasSamples , } ; const tileAdminProps = { retryInterval : 50 , enableInstancing : true , enableIndexedEdges : true !== configuration . disableIndexedEdges , } ; if ( configuration . disableInstancing ) tileAdminProps . enableInstancing = false ; if ( false === configuration . enableImprovedElision ) tileAdminProps . enableImprovedElision = false ; if ( configuration . ignoreAreaPatterns ) tileAdminProps . ignoreAreaPatterns = true ; if ( false === configuration . useProjectExtents ) tileAdminProps . useProjectExtents = false ; if ( configuration . cacheTileMetadata ) tileAdminProps . cacheTileMetadata = true ; if ( configuration . disableMagnification ) tileAdminProps . disableMagnification = true ; if ( configuration . disableBRepCache ) tileAdminProps . optimizeBRepProcessing = false ; tileAdminProps . enableExternalTextures = ( configuration . enableExternalTextures !== false ) ; tileAdminProps . tileTreeExpirationTime = configuration . tileTreeExpirationSeconds ; tileAdminProps . tileExpirationTime = configuration . tileExpirationSeconds ; tileAdminProps . maximumLevelsToSkip = configuration . maxTilesToSkip ; tileAdminProps . alwaysRequestEdges = true === configuration . alwaysLoadEdges ; tileAdminProps . minimumSpatialTolerance = configuration . minimumSpatialTolerance ; tileAdminProps . alwaysSubdivideIncompleteTiles = true === configuration . alwaysSubdivideIncompleteTiles ; tileAdminProps . cesiumIonKey = configuration . cesiumIonKey ; if ( configuration . useFakeCloudStorageTileCache ) ( CloudStorageTileCache as any ) . _instance = new FakeTileCache ( ) ; await DisplayTestApp . startup ( configuration , renderSystemOptions , tileAdminProps ) ; if ( false !== configuration . enableDiagnostics ) IModelApp . renderSystem . enableDiagnostics ( RenderDiagnostics . All ) ; if ( ! configuration . standalone && ! configuration . customOrchestratorUri ) { alert ( "Standalone iModel required. Set IMJS_STANDALONE_FILENAME in environment" ) ; return ; } const uiReady = displayUi ( ) ; try { if ( ! configuration . standalone || configuration . signInForStandalone ) { while ( ! await signIn ( ) ) { alert ( "please sign in" ) ; } } let iModel ; const iModelName = configuration . iModelName ; if ( undefined !== iModelName ) { const writable = configuration . openReadWrite ?? false ; iModel = await openFile ( iModelName , writable ) ; setTitle ( iModel ) ; } await uiReady ; await initView ( iModel ) ; if ( configuration . startupMacro ) await IModelApp . tools . parseAndRun ( `dta macro ${ configuration . startupMacro }` ) ; } catch ( reason ) { alert ( reason ) ; return ; } } ; async function documentLoaded ( ) { const readyState = /^complete$/ ; if ( readyState . test ( document . readyState ) ) return ; return new Promise < void > ( ( resolve ) => { const listener = ( ) => { if ( readyState . test ( document . readyState ) ) { document . removeEventListener ( "readystatechange" , listener ) ; resolve ( ) ; } } ; document . addEventListener ( "readystatechange" , listener ) ; listener ( ) ; } ) ; } async function initView ( iModel ) { showStatus ( "opening View" , configuration . viewName ) ; const fileSelector = undefined !== configuration . standalonePath ? { directory : configuration . standalonePath , input : document . getElementById ( "browserFileSelector" ) as HTMLInputElement , } : undefined ; DisplayTestApp . surface = new Surface ( document . getElementById ( "app-surface" ) ! , document . getElementById ( "toolBar" ) ! , fileSelector , configuration . openReadWrite ?? false ) ; await documentLoaded ( ) ; if ( undefined !== iModel ) { const viewer = await DisplayTestApp . surface . createViewer ( { iModel , defaultViewName : configuration . viewName , disableEdges : true === configuration . disableEdges , } ) ; viewer . dock ( Dock . Full ) ; } showStatus ( "View Ready" ) ; hideSpinner ( ) ; } async function displayUi ( ) { return new Promise < void > ( async ( resolve ) => { showSpinner ( ) ; resolve ( ) ; } ) ; } function showSpinner ( ) { const spinner = document . getElementById ( "spinner" ) as HTMLElement ; spinner . style . display = "block" ; } function hideSpinner ( ) { const spinner = document . getElementById ( "spinner" ) ; if ( spinner ) spinner . style . display = "none" ; } dtaFrontendMain ( ) ;