2.5.0 Change Notes

Restart Query (ECSQL)

Added method that let you cancel last query with same token. This cause last query to throw a exception that was cancelled.

// A async task running following query
for await (const row of db.restartQuery("my-tag", "SELECT * FROM ts.Foo")) {
    // ...
}

// Now submit another query with same tag 'my-tag'.
// If above query still running it would be cancelled and exception would be thrown
for await (const row of db.restartQuery("my-tag", "SELECT * FROM ts.Goo")) {
    ...
}

// In order to see what error was thrown use
try {
    for await (const row of db.restartQuery("my-tag", "SELECT * FROM ts.Foo")) {
        // ...
    }
} catch(err) {
    if (err.errorNumber === DbResult.BE_SQLITE_INTERRUPT){
        // query cancelled
    }
}

This method is available on all following classes

  • ECDb (backend)
  • IModelDb (backend)
  • IModelConnection (frontend)

Cached decorations

A Decorator's decorate method is invoked to create new Decorations whenever a viewport's decorations are invalidated. Decorations are invalidated quite frequently - for example, every time the view frustum or scene changes, and even on every mouse motion. Most decorators' decorations only actually change when the scene changes. Having to regenerate them every time the mouse moves is quite wasteful and - for all but the most trivial decorations - can negatively impact framerate. Here's an example of a decorator that draws some complicated shape in a specified color:

class FancyDecorator {
  private _color: ColorDef; // the color of our shape decoration

  public set color(color: ColorDef): void {
    this._color = color;

    // Make sure our decorate method is called so we draw using the new color.
    // This also invalidates every other decorator's decorations!
    IModelApp.viewManager.invalidateDecorationsAllViews();
  }

  public decorate(context: DecorateContext): void {
    // ...draw a fancy shape using this._color
    // This gets called every single time the mouse moves,
    // and any other time the viewport's decorations become invalidated!
  }
}

We can avoid unnecessarily recreating decorations by defining the useCachedDecorations property. If this is true, then whenever the viewport's decorations are invalidated, the viewport will first check to see if it already has cached decorations for this decorator. If so, it will simply reuse them; if not, it will invoke decorate and cache the result. When the scene changes, our cached decorations will automatically be discarded. Here's the decorator from above, updated to use cached decorations:

class FancyDecorator {
  private _color: ColorDef; // the color of our shape decoration

  // Tell the viewport to cache our decorations.
  // We'll tell it when to regenerate them.
  public readonly useCachedDecorations = true;

  public set color(color: ColorDef): void {
    this._color = color;

    // Invalidate *only* this decorator's decorations.
    IModelApp.viewManager.invalidateCachedDecorationsAllViews(this);
  }

  public decorate(context: DecorateContext): void {
    // ...draw a fancy shape using this._color
    // This *only* gets called if the scene changed,
    // or if explicitly asked for our decorations to be regenerated.
  }
}

ViewManager.invalidateCachedDecorationsAllViews (and ScreenViewport.invalidateCachedDecorations) give the decorator much tighter control over when its decorations are regenerated, potentially resulting in significantly improved performance.

FeatureSymbology namespace

Types related to overriding feature symbology - previously defined in imodeljs-frontend's FeatureSymbology namespace - are now also available in the imodeljs-common package.

Locatable flag for background map

Previously, TerrainSettings.locatable and TerrainProps.nonLocatable could be used to control whether or not tools could locate and interact with the background map while terrain was enabled - but there was no way to similarly control locatability of the map when terrain was disabled. Now, these two properties are deprecated in favor of BackgroundMapSettings.locatable and BackgroundMapProps.nonLocatable. The new properties control locatability of the map regardless of whether or not terrain is enabled. To retain backwards compatibility with the deprecated properties:

  • If TerrainProps.nonLocatable is true, then the terrain will be non-locatable.
  • Otherwise, the terrain will be locatable if and only if the background map is locatable.

ui-components

Breaking change to the beta interface ColorPickerProps. The activeColor property has been renamed to initialColor. The modified props are used by the ColorPickerButton React component.

Model Appearance Overrides

Appearance overrides can be applied to models in a similar manner to subcategory overrides with [DisplayStyleState.overrideModelAppearance] or [Viewport.overrideModelAppearance]. Overrides can be applied to the "contextual" reality models included within display styles with [DisplayStyleState.overrideRealityModelAppearance] or [Viewport.overrideRealityModelAppearance]. For reality models only transparency, color, emphasized and nonLocatable overrides are applicable.

CSRF Security Option

IModelApp now supports passing FrontendSecurityOptions at startup. In particular, one can now enable CSRF (Cross Site Request Forgery) protection. To enable CSRF protection, set csrfProtection: enabled in the new security section of IModelAppOptions. The header and cookie names for CSRF are configurable as needed and default to X-XSRF-TOKEN and XSRF-TOKEN.

ESLint Support and Configuration Available

The @itwin/build-tools package now supports ESLint ^6.8.0 and a configuration file to match, the now deprecated, TSLint configuration. The TSLint configuration and custom rules will still exist for the rest of iModel.js 2.x and will be removed in iModel.js 3.0.

To start using the new configuration add the following to the package.json to extend the build-tools package and run the eslint rules against all ts and tsx files:

"scripts": {
  "lint": "eslint ./src/**/*.{ts,tsx} 1>&2",
},
"devDependencies": {
  "eslint": "^6.8.0",
  ...
},
"eslintConfig": {
  "extends": "./node_modules/@itwin/build-tools/.eslintrc.js"
}

Last Updated: 02 February, 2022