iTwin / itwinjs-core

Monorepo for iTwin.js Library
https://www.itwinjs.org
MIT License
600 stars 210 forks source link

Feature overrides on imodel load not applied #3265

Closed deanmarcussen closed 2 years ago

deanmarcussen commented 2 years ago

Describe the bug

We are trying to apply FeatureOverrides via the EmphasizeElements api when the iModel is loaded.

However the overrides aren't applied.

If I delay the call to the EmphasizeElements api by approx 2 seconds, after model load they are correctly set.

I can see the call to addFeatureOverrides being made early in the sequence, but calling it later doesn't redraw. We set them overrides in a sequence, so many calls with different elements are made to this._emphasizedElements.overrideElements(elData.elements, vp, elData.color, FeatureOverrideType.ColorAndAlpha, false); but I can see only one call to addFeatureOverrides is actually made, and subsequent overrides are not being applied.

I suspect I need some way to invalidate the view, or delay the calls, but haven't found the approriate api.

This appeared for us after moving to v3, but I cannot be certain it wasn't occuring on the previous version.

To Reproduce Steps to reproduce the behavior:

When iModel is initially loaded, i.e. viewport.areAllTileTreesLoaded returns true call this._emphasizedElements.overrideElements(elData.elements, vp, elData.color, FeatureOverrideType.ColorAndAlpha, false);

Expected behavior overrides are applied.

Desktop (please complete the applicable information):

pmconne commented 2 years ago

Please show your code and specify what app template you used. @kckst8 @aruniverse wasn't there an issue with one of the react app templates recreating the viewport after initial load?

deanmarcussen commented 2 years ago

I rebuilt the app from the v3 webviewer template when we migrated up, approx two weeks ago. I've included the package.json if that's helpful.

The app initialization code looks like this...

  useEffect(() => {
    let providers = Object.entries(availableFactories)
      .filter(([k, _]) => Object.values(options.widgets).some(x => x.widgetProvider === k))
      .map(([_, v]) => v());;

    // Currently we always enable this.
    providers = providers.concat([new ViewAttributesStatusBarProvider()]);

    setUIProviders(providers);
  }, [options])

  const viewConfiguration = useCallback((viewPort: ScreenViewport) => {
    const viewStyle: DisplayStyleSettingsProps = {
      // Transformed iModels are black by default, so we need to set the background color to white.
      backgroundColor: ColorDef.create("#FFFFFF").toJSON(),
      viewflags: {
        visEdges: false,
        shadows: true
      }
    }
    viewPort.overrideDisplayStyle(viewStyle);

    // default execute the fitview tool and use the iso standard view after tile trees are loaded
    const tileTreesLoaded = () => {
      return new Promise((resolve, reject) => {
        const start = new Date();
        const intvl = setInterval(() => {
          if (viewPort.areAllTileTreesLoaded) {
            clearInterval(intvl);
            resolve(true);
          }
          const now = new Date();
          // after 20 seconds, stop waiting and fit the view
          if (now.getTime() - start.getTime() > 20000) {
            reject();
          }
        }, 100);
      });
    };

    tileTreesLoaded()
      .finally(() => {
        void IModelApp.tools.run(FitViewTool.toolId, viewPort, true, false);
        viewPort.view.setStandardRotation(StandardViewId.Iso);
        setIsLoaded(true);
      });
  }, []);

  const viewCreatorOptions = useMemo(
    () => ({ viewportConfigurer: viewConfiguration }),
    [viewConfiguration]
  );

  const viewportOptions: ViewerViewportControlOptions = {
    featureOptions: {
      defaultViewOverlay: {
        // this is now false by default, so must be supplied
        enableScheduleAnimationViewOverlay: true,
        enableAnalysisTimelineViewOverlay: false,
        enableSolarTimelineViewOverlay: false,
      },
    }
  }

  const handleOnIModelAppInit = async () => {
    // V3 does not seem to initialize the store like the old one used to.
    await UiFramework.initialize(undefined);
  };

  return (
    <div className={styles['itwin__dcw-viewer']}>
      {contextId && iModelId &&
        <Viewer
          onIModelAppInit={handleOnIModelAppInit}
          enablePerformanceMonitors={false}
          authClient={new DcwViewerAuthorizationClient(options.authOptions)}
          iTwinId={contextId}
          iModelId={iModelId}
          productId={productId}
          viewCreatorOptions={viewCreatorOptions}
          viewportOptions={viewportOptions}
          uiProviders={uiProviders}

        />
      }
      {!isLoaded &&
        <div className="dcw-viewer__spinner">
          <Spinner animation="border" variant="primary" />
        </div>
      }
    </div>
  );
}

I use a UiItemsProvider to load this particular widget, and after it makes a graphql call to our api to discover what elements it should be overriding, and then after making an iModel.query to get the element ids based on the results of the graphql query it calls this.

this._emphasizedElements.overrideElements(elData.elements, vp, elData.color, FeatureOverrideType.ColorAndAlpha, false);

package.json (abbreviated) is this

    "@bentley/icons-generic": "^1.0.34",
    "@bentley/react-scripts": "^4.0.5",
    "@itwin/appui-abstract": "^3.0.0",
    "@itwin/appui-layout-react": "^3.0.0",
    "@itwin/appui-react": "^3.0.0",
    "@itwin/browser-authorization": "^0.5.1",
    "@itwin/components-react": "^3.0.0",
    "@itwin/core-bentley": "^3.0.0",
    "@itwin/core-common": "^3.0.0",
    "@itwin/core-frontend": "^3.0.0",
    "@itwin/core-geometry": "^3.0.0",
    "@itwin/core-i18n": "^3.0.0",
    "@itwin/core-markup": "^3.0.0",
    "@itwin/core-orbitgt": "^3.0.0",
    "@itwin/core-quantity": "^3.0.0",
    "@itwin/core-react": "^3.0.0",
    "@itwin/core-telemetry": "^3.0.0",
    "@itwin/imodel-components-react": "^3.0.0",
    "@itwin/imodels-access-frontend": "^1.0.1",
    "@itwin/imodels-client-management": "^1.0.1",
    "@itwin/itwinui-react": "^1.29.3",
    "@itwin/presentation-common": "^3.0.0",
    "@itwin/presentation-frontend": "^3.0.0",
    "@itwin/reality-data-client": "^0.7.0",
    "@itwin/web-viewer-react": "^2.0.4",
    "@itwin/measure-tools-react": "^0.3.0",
    "@itwin/webgl-compatibility": "^3.0.0",
kckst8 commented 2 years ago

@deanmarcussen can you try upgrading @itwin/web-viewer-react to the latest version (2.0.7)? There were some fixes related to viewport rendering that may help here.

deanmarcussen commented 2 years ago

Looks like a package update resolved the issue thanks all.