4.10.0 Change Notes
Table of contents:
- Revert timeline changes
- Display
- Interactive Tools
- Presentation
- Quantity
- Node 22 support
- Electron 33 support
- API deprecations
Revert timeline changes
At present, the sole method to reverse a defective changeset is to remove it from the iModel hub, which can lead to numerous side effects. A preferable approach would be to reverse the changeset in the timeline and introduce it as a new changeset. Although this method remains intrusive and necessitates a schema lock, it is safer because it allows for the reversal to restore previous changes, ensuring that nothing is permanently lost from the timeline.
BriefcaseDb.revertAndPushChanges Allow to push a single changeset that undo all changeset from tip to specified changeset in history.
Some detail and requirements are as following.
- When invoking the iModel, it must not have any local modifications.
- The operation is atomic; if it fails, the database will revert to its previous state.
- The revert operation necessitates a schema lock (an exclusive lock on the iModel) because it does not lock each individual element affected by the revert.
- If no description is provided after a revert, a default description for the changeset will be created and pushed, which releases the schema lock.
- Schema changes are not reverted during SchemaSync, or they can be optionally skipped when SchemaSync is not utilized.
Display
Instancing
Some scenarios involve displaying the same basic graphic repeatedly. For example, imagine you are writing a Decorator that displays stop signs at many intersections along a road network. You might create one RenderGraphic for each individual stop sign and draw them all, but doing so would waste a lot of memory by duplicating the same geometry many times, and negatively impact your frame rate by invoking many draw calls.
WebGL provides instanced rendering to more efficiently support this kind of use case. You can define a single representation of the stop sign graphic, and then tell the renderer to draw it many times at different locations, orientations, and scales. iTwin.js now provides APIs that make it easy for you to create instanced graphics:
- GraphicTemplate defines what the graphic should look like. You can obtain a template from GraphicBuilder.finishTemplate, RenderSystem.createTemplateFromDescription, or readGltfTemplate.
- RenderInstances defines the set of instances of the template to draw. In addition to a Transform, each instance can also override aspects of the template's appearance like color and line width, along with a unique Feature to permit each instance to behave as a discrete entity. You can create a
RenderInstances
using RenderInstancesParamsBuilder. - RenderSystem.createGraphicFromTemplate produces a RenderGraphic from a graphic template and a set of instances.
GraphicTemplate
and RenderInstances
are both reusable - you can produce multiple sets of instances of a given template, and use the same set of instances with multiple different templates.
For the stop sign example described above, you might have a glTF model representing a stop sign and an array containing the position of each stop sign. You could then use a function like the following to produce a graphic that draws the stop sign at each of those positions.
/** Create a graphic that renders multiple instances of a glTF model. */
export async function instanceGltfModel(gltf: Uint8Array | object, positions: Point3d[], iModel: IModelConnection): Promise<RenderGraphic> {
// Decode the raw glTF as an instanceable template.
const template = (await readGltfTemplate({ gltf, iModel }))?.template;
if (!template) {
throw new Error("Failed to decode glTF model.");
}
// Generate an Id for a "model" to contain the instances.
const modelId = iModel.transientIds.getNext();
// Define multiple instances, one at each of the specified positions.
const instancesBuilder = RenderInstancesParamsBuilder.create({ modelId });
for (const position of positions) {
instancesBuilder.add({
// Translate to the specified position.
transform: Transform.createTranslation(position),
// Assign a unique pickable Id.
feature: iModel.transientIds.getNext(),
});
}
const instancesParams = instancesBuilder.finish();
const instances = IModelApp.renderSystem.createRenderInstances(instancesParams);
// Create a graphic that associates the instances with the template.
return IModelApp.renderSystem.createGraphicFromTemplate({ template, instances });
}
Overriding line color
iTwin.js allows you to dynamically override aspects of the appearance of geometry at display time. However, unlike SubCategoryAppearance and GeometryParams, which can distinguish between "line color" and "fill color", FeatureAppearance only provides a single color override that applies to both types of geometry.
To address this discrepancy, we've added a way to dynamically override the color and transparency of linear geometry independently from the rest of the geometry. Linear geometry includes open curves, line strings, point strings, and the outlines of planar regions. FeatureAppearance.lineRgb controls the color of linear geometry, and FeatureAppearance.lineTransparency controls the transparency. Both of these properties can be undefined
, in which case the existing rgb
or transparency
property affects linear geometry - just as it always has. Or, they can be false
, indicating that no color/transparency override is applied to linear geometry. Or, they can specify a transparency value or RgbColor
that applies only to linear geometry.
Context Reality model visibility
Context reality models that have been attached using DisplayStyleState.attachRealityModel
, can now be hidden by turning ON the ContextRealityModel.invisible
flag. Previous implementation requiered context reality models to be detached in order to hide it from the scene.
Contour Display
A new rendering technique has been added to iTwin.js which allows a user to apply specific contour line renderings to subcategories within a scene.
iTwin.js now provides the following API to use this feature:
- DisplayStyle3dSettings now has a
contours
property which contains all of the subcategories-to-styling association data necessary to enable this feature. That object is of type ContourDisplay. - ContourDisplay defines how contours are displayed in the iModel based on a list of ContourGroup objects in the
groups
property. Whether or not contours will be displayed in the viewport is controlled by this object'sdisplayContours
property, which defaults to false. - ContourGroup describes an association of subcategories to contour styling. It contains a set of subcategory IDs titled
subCategories
. Those subcategories will have the contour styling within the same group's ContourcontourDef
object applied to them. - Contour describes the rendering settings that apply to a specific set of subcategories within a ContourGroup. This actually describes stylings for two sets of contours: major and minor. These stylings are separate from each other. The minor contour occurs at a defined interval in meters. These intervals draw at a fixed height; they are not dependent on the range of the geometry to which they are applied. The major contour is dependent on the minor contour. The interval of its occurence is not measured directly in meters; rather its occurence is determined by the major interval count thusly: every nth contour will be styled as a major contour where n = the major interval count. For example, if you set this number to 1, every contour will be styled as a major contour. When it is 2, every other contour will be styled as a major contour, and so on. The properties describing how major and minor contours are styled are listed here:
majorStyle
is the style that a major contour line will use. Defaults to an instantation of ContourStyle usingpixelWidth
of 2 and default values for the other properties.minorStyle
is the style that a minor contour line will use. Defaults to an instantation of ContourStyle using default values for the properties.minorInterval
is the interval for the minor contour occurrence in meters; these can be specified as fractional. Defaults to 1. If a value <= 0 is specified, this will be treated as 1 meter.majorIntervalCount
is the count of minor contour intervals that define a major interval (integer > 0). A value of 1 means no minor contours will be shown, only major contours. Defaults to 5. If a value < 1 is specified, this will be treated as 1. If a non-integer value is specified, it will be treated as if it were rounded to the nearest integer.showGeometry
, if true, shows underlying geometry along with the associated contours. If false, only shows the contours, not the underlying geometry. Defaults to true.
- ContourStyle describes the style settings used by either a major or minor contour. It contains the following properties:
color
is a color used by the major or minor contour of type RgbColor. Defaults to black.pixelWidth
is the width in pixels of a major or minor contour line, using range 1 to 8.5 in 0.5 increments. Defaults to 1.pattern
is the line pattern applied to a major or minor contour line of type LinePixels. Defaults to LinePixels.Solid.
Consult the following code for an example of enabling and configuring contour display in iTwin.js:
/** Configure and enable contour display on a viewport. */
export function setupContourDisplay(viewport: Viewport): boolean {
const isContourDisplaySupported = (vw: ViewState) => vw.is3d();
const view = viewport.view;
if (!isContourDisplaySupported(view))
return false; // Contour display settings are only valid for 3d views
// Create a ContourDisplay object with the desired contour settings
const contourDisplayProps: ContourDisplayProps = {
displayContours: true, // this flag must be set to true in order to see any contours in the view
groups: [ // the list of style groupings, each associated with a possible list of subcategories
{
contourDef: {
showGeometry: true, // when true, this means the contours AND the underlying geometry will render
majorStyle: {
color: RgbColor.fromColorDef(ColorDef.red),
pixelWidth: 3,
pattern: LinePixels.Solid,
},
minorStyle: {
color: RgbColor.fromColorDef(ColorDef.blue),
pixelWidth: 1,
pattern: LinePixels.Code3,
},
minorInterval: 2,
majorIntervalCount: 8,
},
subCategories: CompressedId64Set.sortAndCompress([ "0x5b", "0x5a" ]),
},
{
contourDef: {
showGeometry: false, // when false, this means only the contours will render (and not the underlying geometry)
majorStyle: {
color: RgbColor.fromColorDef(ColorDef.black),
pixelWidth: 4,
pattern: LinePixels.Code4,
},
minorStyle: {
color: RgbColor.fromColorDef(ColorDef.white),
pixelWidth: 2,
pattern: LinePixels.Solid,
},
minorInterval: 1,
majorIntervalCount: 7,
},
subCategories: CompressedId64Set.sortAndCompress([ "0x5c", "0x6a" ]),
},
],
};
// Create a ContourDisplay object using the props created above
const contourDisplay = ContourDisplay.fromJSON(contourDisplayProps);
// Change the contours object on the 3d display style state to contain the new object
view.getDisplayStyle3d().settings.contours = contourDisplay;
// Sync the viewport with the new view state
viewport.synchWithView();
return true;
}
Here is a sample screenshot of applying some contour display settings to a terrain iModel:
Interactive Tools
Element Locate
After calling ElementLocateManager.doLocate, Reset may now be used to accept some elements that were obscured by another element. Previously Reset would only choose between visible elements within the locate aperture.
Snapping within section drawings
A SectionDrawing view renders the contents of a SpatialViewDefinition in the context of a DrawingViewDefinition. Tools that operate on the drawing view may want to be able to snap to geometry within the "attached" spatial view. For example, you may wish to attach an annotation to a spatial element. AccuSnap now automatically snaps to the geometry based on the current snap settings when mousing over geometry within the section drawing attachment. This works when viewing the drawing directly, or indirectly through a ViewAttachment on a sheet.
You can access the HitPath describing the ViewAttachment and/or SectionDrawing through which a hit was obtained via [[HitDetail.path]].
Presentation
Calculated properties specification enhancements
A new optional extendedData
attribute has been added to calculated properties specification. The attribute allows associating resulting calculated properties field with some extra information, which may be especially useful for dynamically created calculated properties.
Quantity
- Add support for 'Ratio' format type (e.g. "1:2")
- Example: Formatting a Ratio
- Assuming that a
UnitsProvider
has been registered and initialized, here's how to format a ratio:
const ratioFormatProps: FormatProps = {
type: "Ratio",
ratioType: "OneToN", // Formats the ratio in "1:N" form
composite: {
includeZero: true,
units: [
{ name: "Units.HORIZONTAL_PER_VERTICAL" },
],
},
};
const ratioFormat = new Format("Ratio");
ratioFormat.fromJSON(unitsProvider, ratioFormatProps).catch(() => {});
Add support for unit inversion during unit conversion
Change azimuth and bearing logic from working with east-based counterclockwise persisted values to working with north-based clockwise values.
The previous applies to azimuthBase as well, if provided.
Node 22 support
iTwin.js now officially supports Node 22 starting with LTS version of 22.11.0. Node 22 support is in addition to Node 18 and 20, not a replacement.
Electron 33 support
In addition to already supported Electron versions, iTwin.js now supports Electron 33.
API deprecations
@itwin/appui-abstract
LayoutFragmentProps
,ContentLayoutProps
,LayoutSplitPropsBase
,LayoutHorizontalSplitProps
,LayoutVerticalSplitProps
, andStandardContentLayouts
have been deprecated. Use the same APIs from@itwin/appui-react
instead.BackendItemsManager
is internal and should never have been consumed. It has been deprecated and will be removed in 5.0.0. UseUiFramework.backstage
from@itwin/appui-react
instead.
@itwin/core-backend
- IModelHost.snapshotFileNameResolver and FileNameResolver have been deprecated. Make sure to provide resolved file path to SnapshotConnection.openFile.
@itwin/core-frontend
- SnapshotConnection.openRemote has been deprecated. Use CheckpointConnection.openRemote to open a connection to an iModel within web application.
@itwin/core-quantity
Refactored
FormatType
,ScientificType
,ShowSignOption
from int enums to string enums and addedRatioType
as a string enum. Relevant toString functions, including formatTypeToString, scientificTypeToString, and showSignOptionToString, have been deprecated because they don't need serialization methods.Parser.parseToQuantityValue have been deprecated. Use the existing method Parser.parseQuantityString instead.
@itwin/presentation-common
- All public methods of PresentationRpcInterface have been deprecated. Going forward, RPC interfaces should not be called directly. Public wrappers such as PresentationManager should be used instead.
Last Updated: 14 November, 2024