Multiple developers have discovered that the reverse keyword, used as part of the for syntax, will not always behave as intended. It is the intention of the syntax to cause the loop to reverse iterate over the members of the collection with no other changes/syntaxes/keywords necessary. However, in the current state, Ranges require the developer to also define the collection in reverse order, which shouldn't be necessary.
With this release, this behavior has been fixed and the reverse keyword now functions as intended for Ranges. As a consequnce of the fix, however, existing workarounds will no longer function. If you have used the "define the range in reverse" trick to workaround the problem, you will need un-reverse the range. Failure to make this change will cause the loop to be skipped entirely.
For example, if you have code that is currently written as:
for (i in 3..1, reverse) {
you will need to re-write it as:
for (i in 1..3, reverse) {
In the CET 17.0 release in May 2026, Catalogue Component Tab and Component Tab Creator will reach their End-of-Life (EOL) and be retired completely.
As part of the EOL effort,
All developers are strongly encouraged to migrate to the new Table of Content (ToC) Toolbox introduced in 15.5 Major as the replacement for the Component Tab - (read more and learn how to migrate or build toolbox with ToC here) [https://dev-docs.configura.com/design-system/cet-developer-guides/catalogue-table-of-contents-with-the-new-ui]
Main MR: [https://git.configura.com/cet/external/base/-/merge_requests/42378]
Data symbol parts and picklists now follow the new 17.0 core Ind. Tag model. Stable Ind. Tag identity is based on sourceId(), user-modified tag text is stored through the shared UserTagInfoHolder, and legacy picklist tag data is migrated during load so existing user overrides can be preserved across reset-behavior changes and older drawings.
MR: Ind. Tag migration and restoration changes
Data-symbol product parts also participate in the 17.0 option-special storage split. Before 17.0, DsPart option specials were read from the shared owner-level PartSpecialHolder using data-symbol-specific combined keys. In 17.0, those option specials belong in the per-part OptionSpecialHolder introduced in cm.abstract.part, and DsPartSpecialMigrator exists to translate older DsSpecOption keys into the new holder layout.
If your catalogue package has older drawings that must preserve DsPart option specials or additional options, you need to opt in to that migration flow during load.
cm.abstract.office no longer provides the older panel-frame electrical object framework from electrical.cm.
Instead, the package now depends on cm.abstract.pathing and exposes AOElecNode as a small office-level building block for packages that want to implement a routed electrical system.
The new 17.0 custom.fika electrical system is the reference example for that new routed architecture. Rather than asking PanelFrame and PanelJunctionSnapper for EOPosition or EORange data and applying ElectricalObjects directly, Fika defines electrical snappers, routing nodes, and A-star path finding on top of AOElecNode and cm.abstract.pathing.
For most manufacturers, the lower-effort migration path is not to fully adopt the new Fika routing model. If your package already relies on the old office electrical interfaces, the practical migration path is to copy the removed interfaces and supporting logic into your own package-owned classes and continue using that model there.
The abstract part layer now follows the new core Ind. Tag model. The calculation Ind. Tag column can split rows by actual user-entered tag text, only treats true user overrides as adjusted values, and applies row-level Ind. Tag adjustments to each underlying part. A post-merge hook also repairs pre-17.0 adjustment keys when older drawings are loaded.
MR: Ind. Tag migration and restoration changes
ProdPart has also been expanded with first-class support for option additions, option import, and option-level customization state.
Those changes provide the part foundation for the new query import workflow in cm.abstract.part.query, where imported option items can be dragged into the query dialog and applied as additions or special overrides.
CET 17.0 also changes where option specials live at runtime. Before 17.0, both PartSpecial and OptionSpecial data were stored together in the snapper-level PartSpecialHolder under cSpecialHolderKey, and option-special lookup depended on a combined part-and-option key. In 17.0, option specials move into a separate per-part OptionSpecialHolder, stored on the owner under a key built from optionSpecialHolderPropKey(part) and the part's sourceId(). That split is what makes stable option identity, inserted-option ordering, and per-part option-special migration possible.
Because older drawings still load old option specials from PartSpecialHolder, packages that need backward compatibility must opt in to the new migration helpers such as ProdPartSpecialMigrator and DsPartSpecialMigrator during their load/migration flow.
CET 17.0 adds a new product-part import layer in cm.abstract.part.import. These classes specialize the new core importer framework so SIF, PMX, and OFDA XML imports can create ProdPart instances instead of plain Part instances.
The most important new behavior is in SIF and OFDA XML import. ProdPartSIFImporterEnv can now build SpecOption data during import, and OFDA XML import can now route option tags into ProdPart through new shared option-import hooks.
This package is also the bridge used by the query import UI. cm.abstract.part.query now returns these environments from ProdPartQueryDialogBehavior.getImporterEnv(str suffix), so imported product parts and product options flow through the same importer framework as the core query import path.
cm.abstract.part.query adds the product-part and option-specific part of the new 17.0 query import workflow.
Together with the base dialog changes in cm.core.part.query and the underlying option/customization changes in cm.abstract.part.ProdPart, product-part query dialogs can now import product parts and option items, drag option items into the query grid, and create option additions or overrides in addition to the existing option-special workflow.
CET 17.0 splits the PMX code that used to live entirely in cm.abstract.pmx into two layers.
cm.abstract.pmx is now the abstract/export-facing package: it keeps the PMX order exporter, package initialization, test hooks, and local file-move/debug helpers.
The reusable PMX database wrapper types, PMX data-definition objects, constants, and .NET bridge code have been moved into the new shared package cm.core.pmx.
That means most compile-time migration work is import and type rerouting. If your code previously referenced PMX model/database types through cm.abstract.pmx, update those references to cm.core.pmx instead. If your code used PMX import helpers such as PMXFilePartSource or ItemDataConverter, those APIs were not moved into cm.core.pmx; they now live in cm.core.part.import.
The ItemData option payload also changed shape during that extraction. The old abstract-only optionsSeq storage is gone in 17.0; the shared cm.core.pmx.ItemData uses a single canonical options array for option generation, appending through operator<<, exporter insertion, and part initialization from PMX data.
cm.abstract.projectInfo now stores and restores project-information drop-down selections in a way that preserves the selected item's label as well as its key.
This fixes a visible behavior issue in paper view and other text-driven outputs where fields such as terms of delivery, delivery method, terms of payment, and delivery time could show only the stored numeric/key value instead of the human-readable label.
cm.core.Snapper is also part of the 17.0 migration story for query-related part customization.
During load, Snapper.loaded1(...) now initializes the optional PartSpecialMigrator, and later Snapper.fetchParts(...) invokes migratePartSpecials(localParts) before applying 17.0 additions and overrides.
That makes cm.core.Snapper the package where migrator discovery and execution actually happen. The migrator types themselves are documented under cm.core.part and cm.abstract.part.
We've identified that feature snapping in 3D works poorly for most snappers, and that many extensions do not provide their own snap features. To fix this with minimal migration effort, 3D features are now generated from each snapper's mesh by default.
Core validation now exposes Check Drawing from the Tools menu, normal extension snapper appended in appendInvalidation will be still register here.
Navisworks NWD Export will be removed as an extension from the Marketplace and moved into core.
As part of this the package has changed from cm.core.nwd to cm.core.sceneExport.nwd.
The export will be automatically activated only when using a Material Handling edition
CET 17.0 refactors Ind. Tag identity and storage in cm.core.part. User-entered Ind. Tag text is now stored separately from the default ItemTagInfo key, part identity for Ind. Tags and part annotations is driven by sourceId(), and drawings from 16.5 and earlier are migrated on load so existing user-modified tags, AN/AD annotations, and single-part adjustments continue to work.
MR: Ind. Tag migration and restoration changes
The same stable-identity work also introduces broader Part support for additions, overrides, and customization state. Those APIs are important context for the new import/customization workflows in cm.core.part.query and cm.abstract.part.query, where imported parts are applied as additions or overrides and need to map back to a stable logical part identity.
CET 17.0 also separates part-special storage from option-special storage. PartSpecialHolder remains the shared owner-level container for part specials, overrides, and additional parts, while cm.abstract.part introduces a separate per-part OptionSpecialHolder for option specials and added options. Older drawings may therefore need holder migration in addition to key migration.
CET 17.0 adds a new core import layer for Part data. cm.core.part.import provides the importer classes, the shared importer-environment model, and the default SIF, PMX, and OFDA XML implementations that now back file-based part import workflows.
The main migration impact is compile-time. Packages that want to import custom part types should now plug into this framework by subclassing PartImporterEnv, returning the correct Part subclass from createPart(...), and,
for OFDA XML, overriding the new OFDA import hooks on Part.
PMX import continues to rely on initializePartFromItemData(...), which was already part of the older PMX import path. The truly new Part interfaces in this area are the OFDA import hooks described below.
The query dialog was expanded in 17.0 with a resizable window, a right-side import pane, and drag-and-drop support for imported parts.
Together with the underlying cm.core.part and cm.abstract.part changes, the query workflow now supports importing both parts and
product-part options, and applying them as additions or overrides in addition to the existing special-part workflow.
CET 17.0 extracts the reusable PMX runtime surface from cm.abstract.pmx into the new shared package cm.core.pmx.
This is now the package that owns the PMX data model (ItemData, OptionData, PartDetails, and related records), the PMX database wrapper (Database), the PMX file constants, and the PMXNetObj/DataDefinition bridge layer.
The move makes PMX functionality available to both exporter code and generic part-import code without forcing those consumers to depend on the abstract exporter package. It also broadens the PMX database/export payload to include project-level metadata such as notes, order info, and sold-to/ship-to records.
Because the package is new, migration work is mostly straightforward namespace replacement: code that previously instantiated PMX data/database types from cm.abstract.pmx should now import cm.core.pmx and use the same type names there.
Improved the texture mapping of the basic 3D shapes for rectangles, cylinders and pyramids.
Improved the texture mapping of many wall symbols such as arced walls, windows and curtains.
DcSIFExportEnv no longer has ambiguous constructor overloadscustom.dataCatalog.builder removes the ambiguous DcSIFExportEnv constructor overload pair that previously accepted the same overall argument set with catalogCodeOverride and useInFile in conflicting positions.
This fixes a compile-time problem for downstream subclasses calling super(...), where CET could report an ambiguous function error unless the caller forced the overload with a positional null.
custom.fika is not where the shared migrator framework is defined, but it is an important example package for the 17.0 migration story. It shows how a catalogue package with older custom Part key history can opt in to the new PartSpecialMigrator load flow by exposing a snapper-level partSpecialMigrator prop and returning a package-specific migrator.
In Fika's case, FikaDsPartSpecialMigrator extends DsPartSpecialMigrator and overrides oldPartSpecialsKey(Part part) so older Fika drawings can still find part and option specials that were stored under pre-17.0 key formats.