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)
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.
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.
Definining a literal Range in reverse order as part of the for syntax will now cause the loop to be skipped entirely. Rewrite the Range literal to correct order. The regular expression for.*\(.*[.][.].*reverse can be used to quickly find all places in your code where you are using the reverse keyword with a literal Range.
The constructors of DsiConstraintSelPath have been changed.
Old: public constructor auto(path, feature, option); public constructor auto(path, feature, option, checkedV); public constructor auto(path, feature, option, numV);
New: public constructor(str path, SFeature feature, Option option, DsiPDataOption dataOption, DsiPDataOption parentDataOption)
The following interfaces will be removed as part of the Component Tab and Component Tab Creator EOL effort:
class ProductCatalog
Removed: extend public void appendToolbox(str url)
The following interfaces will be removed as part of the Component Tab and Component Tab Creator EOL effort:
Functions: Removed: public bool dsCloneToolboxes(DataCatalog catalog, ProductCatalog productCatalog, DsToolboxCreatorToolboxCards toolboxCards) Removed: public str dsToolboxFileStr(DataCatalog catalog, DsToolboxCreatorToolboxCards cards, DsToolboxCreatorToolboxCard card)
Note: cm.abstract.dataSymbol.ui.toolboxCreator package is completely removed. If your extension has dependency to this package, please remove it.
// Constants Removed: public const str dsToolboxCreatorFileType = ".cmtbxc"; // Functions Removed: public Image DsToolboxCreatorLoadToolboxImage(Url file) Removed: public DsToolboxCreatorExtensionToolboxCard dsToolboxCreatorCreateExtensionToolboxCard(Window parent, symbol pkg, DsToolboxCreatorToolboxCard card, str sortKey, str groupId, str libraryFunctionName=null, Image image=null, str label=null) Removed: public str tbCatCardStatsEntityKey(DsCatalogToolboxData cData) Removed: public void dsToolboxCreatorToolboxCardSetSectionLabelAnimationEnv(Window window, DsDragAnimationEnv env) Removed: public void dsToolboxCreatorToolboxCardSetSectionAnimationEnv(Window window, DsDragAnimationEnv env) Removed: public void dsToolboxCreatorToolboxCardSetThumbnailViewAnimationEnv(Window window, DsDragAnimationEnv env) Removed: public void dsToolboxCreatorToolboxCardSetToolboxSectionWindowAnimationEnv(Window window, DsDragAnimationEnv env) Removed: public void dsToolboxCreatorToolboxCardSetHeaderAnimationEnv(Window window, DsDragAnimationEnv env) Removed: public void dsToolboxCreatorToolboxCardSetImageSectionAnimationEnv(Window window, DsDragAnimationEnv env) Removed: public void dsToolboxCreatorToolboxCardSetSchemeButtonAnimationEnv(Window window, DsDragAnimationEnv env) Removed: public Library dsToolboxCreatorLibraryFromCard(Card card, symbol pkg) Removed: public void faceliftPreprocess(Library library) Removed: public str->str dsDefaultSchemeDescriptionMap(str{} languages) // Classes Removed: public class DsToolboxCreatorCardPropertyWindow extends SubWindow Removed: public class DsToolboxCreatorCardWindow extends CardWindow Removed: public class DsToolboxCreatorControlWindow extends SubWindow Removed: public class DsToolboxCreatorDataCatalogHeader extends DsDataCatalogHeader Removed: public class DsToolboxCreatorDataCatalogSectionedLabel extends DsDataCatalogSectionedLabel Removed: public class DsToolboxCreatorDataCatalogSectionedScrollableSubWindow extends DsDataCatalogSectionedScrollableSubWindow Removed: public class DsToolboxCreatorDesignWindow extends SubWindow Removed: public class DsToolboxCreatorDialog extends DialogWindow Removed: public class DsToolboxCreatorDeletionSubWindow extends SubWindow Removed: public class DsToolboxCreatorDragAnimation extends DsDragAnimation Removed: public class DsToolboxCreatorDropDownTreeView extends DropDownTreeView Removed: public class DsToolboxCreatorDynamicCard extends DsDynamicCard Removed: public class DsToolboxCreatorExtensionToolboxCard extends ExtensionToolboxCard Removed: public class DsToolboxCreatorFillerInsertDragAnimation extends DsToolboxCreatorThumbnailViewMoveDragAnimation Removed: public class DsToolboxCreatorFillerMoveDragAnimation extends DsToolboxCreatorThumbnailViewMoveDragAnimation Removed: public class DsToolboxCreatorFillerThumbnail extends DsThumbnail Removed: public class DsToolboxCreatorFocusLines Removed: public class DsToolboxCreatorFocusRect Removed: public class DsToolboxCreatorGroupInsertDragAnimation extends DsToolboxCreatorDragAnimation Removed: public class DsToolboxCreatorGroupMoveDragAnimation extends DsToolboxCreatorGroupInsertDragAnimation Removed: public class DsToolboxCreatorHeaderInsertDragAnimation extends DsToolboxCreatorGroupInsertDragAnimation Removed: public class DsToolboxCreatorHeaderLimb extends DsDynamicHeaderLimb Removed: public class DsToolboxCreatorHeaderMoveDragAnimation extends DsToolboxCreatorGroupMoveDragAnimation Removed: public class DsToolboxCreatorHeaderPropertyWindow extends SubWindow Removed: public class DsToolboxCreatorImageSectionInsertDragAnimation extends DsToolboxCreatorDragAnimation Removed: public class DsToolboxCreatorImageSectionMoveDragAnimation extends DsToolboxCreatorImageSectionInsertDragAnimation Removed: public class DsToolboxCreatorImageSectionPropertyWindow extends ShrinkWindow Removed: public class DsToolboxCreatorLibraryLimb extends DsDynamicLibraryLimb Removed: public class DsToolboxCreatorProductCatalogLimbBuilder extends DsProductCatalogLimbBuilder Removed: public class DsToolboxCreatorProductLevelPropertySubWindow extends ShrinkWindow Removed: public class DsToolboxCreatorProductViewInsertDragAnimation extends DsDragAnimation Removed: public class DsToolboxCreatorPropertyWindow extends SubWindow Removed: public class DsToolboxCreatorSchemeButton extends DsDataCatalogSchemeButton Removed: public class DsToolboxCreatorSchemeButtonInsertDragAnimation extends DsToolboxCreatorDragAnimation Removed: public class DsToolboxCreatorSchemeButtonMoveDragAnimation extends DsToolboxCreatorSchemeButtonInsertDragAnimation Removed: public class DsToolboxCreatorSchemeButtonPropertyWindow extends ShrinkWindow Removed: public class DsToolboxCreatorSectionLabelPropertyWindow extends SubWindow Removed: public class DsToolboxCreatorSideBarPropertiesPropertyWindow extends DsInWindowSideBarProperties Removed: public class DsToolboxCreatorThumbnailsLimb extends DsThumbnailsLimb Removed: public class DsToolboxCreatorThumbnailPropertyWindow extends SubWindow Removed: public class DsToolboxCreatorThumbnailViewMoveDragAnimation extends DsThumbnailViewMoveDragAnimation Removed: public class DsToolboxCreatorToolboxCard Removed: public class DsToolboxCreatorToolboxCards Removed: public class DsToolboxCreatorToolboxSectionedScrollableSubWindow extends ToolboxSectionedScrollableSubWindow Removed: public class DsToolboxCreatorToolboxThumbnail extends DsToolboxThumbnail Removed: public class DsToolboxCreatorToolboxThumbnailView extends DsToolboxThumbnailView Removed: public class DsToolboxCreatorTooltip Removed: public class DsToolboxCreatorTreeViewItem extends TreeViewItem Removed: public class DsToolboxCreatorHeaderTreeViewItem extends DsToolboxCreatorTreeViewItem Removed: public class DsToolboxCreatorGroupTreeViewItem extends DsToolboxCreatorTreeViewItem Removed: public class DsToolboxCreatorProductViewTreeViewItem extends DsToolboxCreatorTreeViewItem Removed: public class DsToolboxCreatorFillerTreeViewItem extends DsToolboxCreatorTreeViewItem Removed: public class DsToolboxCreatorImageSectionTreeViewItem extends DsToolboxCreatorTreeViewItem Removed: public class DsToolboxCreatorSchemeButtonTreeViewItem extends DsToolboxCreatorTreeViewItem Removed: public class DsToolboxCreatorUIBuilder extends DsNewUIBuilder Removed: public class DsToolboxCreatorUIGroupBuilder extends DsUIGroupBuilder
Changed the length setter function from final to extend.
Old: final public double length=(double v) { New: extend public double length=(double v) { Removed: extend public void lengthChanged() {
Renamed two methods to more clearly convey what they do.
Old: extend public void setP0(point p, Angle forcedAngle=null, bool updateD=true) { New: extend public void setSpaceP0(point p, Angle forcedAngle=null, bool updateD=true) { Old: extend public void setP1(point p, Angle forcedAngle=null) { New: extend public void setSpaceP1(point p, Angle forcedAngle=null) {
Removed the following functions:
Removed: final public void drawHelpFrameIfSelected(GInstance gs) { Removed: extend public void drawMarginHelpFrameIfSelected(GInstance gs, rect mr) { Removed: final public void drawHelpFrameIfSelectedOrZoomedOut(GInstance gs, GTextBox gText) {
Instead, use one of these:
Added: final public void drawHelpFrame(GInstance gs) { Added: final public void drawMarginHelpFrame(GInstance gs) {
Old: extend public void addSuperStretchVessel(point p) { New: extend public void addSuperStretchVessel(point p, angle a) {
Changed the constructor to optionally support custom labels for collections.
Old: public constructor(str collectionName, str dbPath, str namespace, str uom, symbol[] tags, int version, Material m) { New: public constructor(str collectionName, str dbPath, str namespace, str uom, symbol[] tags, int version, Material m, str collectionLabel=null) {
Steal was removed and made inaccessible, not meant to be used from the outside.
Old: extend public void steal(AbsExtrCollection f) { New: extend package void registryCopyContent(AbsExtrCollection f) {
Minor name changes:
Old: final public AbsExtrProfile get(str name) { New: final public AbsExtrProfile get(str id) {
Made member not intended to be changed from the outside private but public readable.
Old: public str id; New: private str id : public readable;
Added a optional construction argument to decide whether the profile shape should be closed or not.
Old: public constructor(str coll, str name, AbsExtrShapeDefItem[] shapeDef) { New: public constructor(str coll, str name, AbsExtrShapeDefItem[] shapeDef, bool closeProfile=true) {
AbsMaterial now includes thumbnailType method, subclasses will need to remove extend keyword if they had previously defined this method.
AbsMaterial public class AbsMaterial extends CachedMaterial { extend public gmThumbnailType thumbnailType() {..} } public class FOMaterial extends OfficeMaterial { Old: extend public gmThumbnailType thumbnailType() {..} New: public gmThumbnailType thumbnailType() {..} }
The abstract class MhSystemConfiguration, and the child classes MhStorageConfiguration and MhStorageEditorConfiguration have had similar methods declared in them.
MhStorageConfiguration.configUserPropertyChanged(str key, Object value, Object oldValue, Object propOwner, MhStorageConfigurationItem item) and MhStorageEditorConfiguration.userPropertyChange(MhStorageEditorItem item, CoreProperty property, Object oldValue) were both doing similar logic and so we have now created a new method in the parent class MhSystemConfiguration that calls this similar functionality. If you had previously overridden either of these two methods, you should now override configUserPropertyChanged(MhSystemConfigurationItem item, CoreProperty property, Object oldValue) instead.
public class MhSystemConfiguration extends CoreObject { Added: /** * Config user property changed. */ extend public void configUserPropertyChanged(MhSystemConfigurationItem item, CoreProperty property, Object oldValue) { if (property.owner != item) { item.?additionalPropChanged(property.key, property.value, oldValue, property.owner); } configUserPropertyChanged(property.key, property.value, oldValue, property.owner, item); } } public class MhStorageConfiguration extends MhSystemConfiguration { Removed: /** * configUserPropertyChanged - user changed property. Adjust configuration accordingly. */ extend public void configUserPropertyChanged(str key, Object value, Object oldValue, Object propOwner, MhStorageConfigurationItem item) { for (it in items) { it.configUserPropertyChanged(..); } } } public class MhStorageEditorConfiguration extends MhSystemConfiguration { Removed: /** * User property changed. */ extend public void userPropertyChange(MhStorageEditorItem item, CoreProperty property, Object oldValue) { if (property.owner != item) { item.additionalPropChanged(property.key, property.value, oldValue, property.owner); } if (space and !skipPushToPreview(..-)) { beforePushPropToPreview(..); pushPropToPreview(space, ..-); afterPushPropToPreview(..); } } }
The function Snapper getNextSingleAisle(MhSnapper snapper, bool top=true) has been removed and a function Snapper getNextAisle(MhSnapper snapper, bool top=true) has been added.
Removed: public Snapper getNextSingleAisle(MhSnapper snapper, bool top=true) { for (r in getAllRows(snapper, top=top, reverse=false)) { if (r == snapper) continue; if (r.isSingle and r.isAisle) return r; } return null; } Added: public Snapper getNextAisle(MhSnapper snapper, bool top=true) { for (r in getAllRows(snapper, top=top, reverse=false)) { if (r == snapper) continue; if ((r.isDouble and r.isAisle and !r.isFlueGap) or (r.isSingle and r.isAisle)) return r; } return null; }
Previously MhEngineEntry has a map field str->Object additionalShapeArgs that allows storing key-value data. This has now been changed to a private field str->Object _additionalShapeArgs and new public methods have been introduced with the same name. This is so that the source of this map can be overridden.
For example, MhEngineConstructionEntry overrides the additionalShapeArgs methods to put/retrieve data from the owned constructionInfo() object instead. The class MhEngineConstructionEntryInfo now has a new field str->Object _additionalShapeArgs and method str->Object additionalShapeArgs(). This allows the map of the info class to be set independently and for the data to later be assigned to a MhEngineConstructionEntry at a later time.
// cm/abstract/materialHandling/engine/mhEngineEntry.cm public class MhEngineEntry extends MhEngineEntryBase { Old: public str->Object additionalShapeArgs; New: private str->Object _additionalShapeArgs; New: extend public str->Object additionalShapeArgs() { } New: extend public str->Object additionalShapeArgs=(str->Object args) { } New: extend public Object getAdditionalShapeArg(str key) { } New: extend public void putAdditionalShapeArg(str key, Object val) { } } // cm/abstract/materialHandling/engine/mhEngineConstructionEntry.cm public class MhEngineConstructionEntryInfo { New: private str->Object _additionalShapeArgs; New: extend public str->Object additionalShapeArgs() { } } // cm/abstract/materialHandling/mhSnapperSpawner.cm public class MhSnapperSpawner extends SnapperSpawner { Old: extend public MhEngineConstructionEntry engineConstructionEntry() { } New: extend public MhEngineConstructionEntry engineConstructionEntry(MhEngineConstructionEntryInfo info=null) { } }
The additionalShapeArgs are primarily used to push property values to spawned snappers on constructions. They can also be used to hold distinct entry values to be used during engine functions.
These additionalShapeArgs are applied in three areas during construction, one during instantiation of an MhEngineConstructionEntry, one during spawning of a snapper, and one more time after export of entry.
1. Instantiation of `MhEngineConstructionEntry` public class MhSnapperSpawner extends SnapperSpawner { /** * Engine construction entry (used by entry layout only). */ extend public MhEngineConstructionEntry engineConstructionEntry(MhEngineConstructionEntryInfo info=null) { MhSnapperShape shape = createShape(); for (key, val in info.?additionalShapeArgs) shape.?changeShape(key, val); ... } } 2. Spawning of a snapper public class MhEngineConstructionEntry extends MhEngineSnapperEntry { /** * Spawn snapper. */ extend public MhSnapper spawnSnapper(MhEngine engine, MhSystemSpawnerSelector spawnerSelector=null) { ... if (MhSnapper s = spawnerSelector.?spawnSnapper(classification, shapeArgs=shapeArgs+additionalShapeArgs, env=this)) { return s; } ... } } 3. After export of entry. public class MhSnapperShape extends CorePropObj { /** * Entry exported. */ extend public void entryExported(MhSnapper snapper, MhEngineEntry entry) { ... // Apply additional shape args on exported as they are not included in entry cache key so export function might have spawned snapper without using correct shape args from mhSystemEngineCache. if (entry as MhEngineConstructionEntry) { for (key, val in entry.additionalShapeArgs()) { changeShape(key, val); } } } }
Several changes have been made for handling level clearances in the abstract. First of all, the class MhClearanceSpecLevelClearanceBehavior and the field levelClearanceZ field in MhClearanceSpec have been removed.
How this would be used is the MhClearanceSpecLevelClearanceBehavior class would call spec.?collisionPrimitives(shape, env) which by default would call MhClearanceSpec.levelClearanceCollision(MhSnapperShape shape, MhCollisionFetchEnv env) that returns a CollisionPrimitive built based on spec.levelClearanceZ. This would result in a CollisionPrimitive always being built for the level.
Removed: public mhLazyGlobal MhBehavior mhClearanceSpecLevelClearanceBehavior = MhClearanceSpecLevelClearanceBehavior(); Removed: public class MhClearanceSpecLevelClearanceBehavior extends MhClearanceSpecBehavior public class MhClearanceSpec extends CorePropObj { Removed: public Double levelClearanceZ; Removed: Prop cMhLevelClearanceZPK : attributes={#allowPush, #allowPushNull}; }
Instead of always building a CollisionPrimitive for the level to represent the level clearance, we now only append this primitive during the construction of entries.
public class MhLevelShape extends MhBoxSnapperShape { Old: extend public void appendLevelClearancePrimitives(CollisionPrimitive{} prims, MhCollisionFetchEnv env) { if (?MhClearanceBehavior b = owner.?behavior("levelClearance")) { if (!env) env = MhCollisionFetchEnv(); Transform t = env.transform; double elevation; if (t) elevation = t.pos.z; else elevation = owner.toSpaceTransform().pos.z; MhClearanceCollisionFetchEnv clearanceEnv(env, elevation, owner.rootParent.MhSnapper.?classification); b.appendCollisionPrimitives(this, clearanceEnv, prims); } } New: extend public void appendLevelClearancePrimitives(CollisionPrimitive{} prims, MhCollisionFetchEnv env) { } } public class MhLevelSpawner extends MhStorageSpawner { New: /** * Return construction entry collision primitive. */ public CollisionPrimitive engineConstructionCollision(MhSnapperShape shape, MhEngineConstructionEntry entry) { CollisionPrimitive res = super(..); appendLevelClearancePrimitive(res, shape, entry); return res; } New: /** * Append level clearance primitive. * Simple implementation of level clearance when using MhCompartmentType with no unit loads. For custom logic, override either this or MhClearanceSpec.levelClearanceCollision(). */ extend public void appendLevelClearancePrimitive(CollisionPrimitive prim, MhSnapperShape shape, MhEngineConstructionEntry entry) { if (prim as CollisionPrimitiveSet) { if (?MhClearanceBehavior b = statelessBehavior("Clearance")) { MhCollisionFetchEnv env(reason=#construction, entry=entry); b.appendCollisionPrimitives(shape, env, prim.subPrims); } } } }
Due to the above change in behavior, the ownership of a level clearance value has been changed from the clearance spec to the engine entry, more specifically it is stored in the additionalShapeArgs() of MhEngineEntry.
public class MhClearanceSpec extends CorePropObj { Old: /** * Collision primitives based on `levelClearanceZ`. */ extend public CollisionPrimitive[] levelClearanceCollision(MhSnapperShape shape, MhCollisionFetchEnv env) { CollisionPrimitive[] res(4); if (levelClearanceZ and shape) { box b = shape.localBound(); b.h = levelClearanceZ.v; static Layer layer = Layer(layerSet(sClearance, sLevelClearanceZ), layerSet(sLevel, sLevelFrame)); res << mhGetBoxCollisionPrimitive(b, layer, env.transform); } return res.any ? res : null; } New: /** * Collision primitives for level clearance. */ extend public CollisionPrimitive[] levelClearanceCollision(MhSnapperShape shape, MhCollisionFetchEnv env) { CollisionPrimitive[] res(4); // Append level clearance collision from MhCompartmentType during construction. if (env.?reason == #construction) { MhEngineEntry entry = env.entry; if (?Double levelClearance = entry.?getAdditionalShapeArg("levelClearance")) { box b = shape.?localBound([sLevelFrame]); b.h += levelClearance.v; static Layer layer = Layer(layerSet(sClearance, sLevelClearanceZ), layerSet(sLevel, sLevelFrame)); res << mhGetBoxCollisionPrimitive(b, layer); } } return res.any ? res : null; } } public class MhCollisionFetchEnv { New: public MhEngineEntry entry; Old: public constructor(symbol reason=#none, Transform transform=null, bool includeChildren=false, Object arg=null) New: public constructor(symbol reason=#none, Transform transform=null, bool includeChildren=false, MhEngineEntry entry=null, Object arg=null) }
Changes have been made to support different level entries having different unit load clearances. MhUnitLoadSpawner can pass in different clearance specs for each level entry instead of always using the same clearance spec from the configuration.
public class MhEntryLayoutEnv { New: public MhEngineEntry entry; } public class MhUnitLoadSpawner extends MhStorageSpawner { Old: extend public void appendAdditionalConstructionCollision(MhEngineConstructionEntry entry, str unitLoadKey, LayerSet rootParentClassification, MhEntryLayoutEnv env) { ... for (MhClearanceSpecBehavior behavior in collection.behaviors) { MhStorageClearanceCollisionFetchEnv clearanceEnv(..., clearanceSpec=config.?clearanceSpec); behavior.appendCollisionPrimitives(loadShape, clearanceEnv, set.subPrims); } } New: extend public void appendAdditionalConstructionCollision(MhEngineConstructionEntry entry, str unitLoadKey, LayerSet rootParentClassification, MhEntryLayoutEnv env) { ... MhClearanceSpec spec; if (?MhEngineConstructionEntry parent = env.entry) { if (?MhClearanceSpec cSpec = parent.getAdditionalShapeArg(cMhClearanceSpecPK)) { spec = cSpec; } } if (!spec) spec = config.?clearanceSpec; for (MhClearanceSpecBehavior behavior in collection.behaviors) { MhStorageClearanceCollisionFetchEnv clearanceEnv(..., clearanceSpec=spec); behavior.appendCollisionPrimitives(loadShape, clearanceEnv, set.subPrims); } } }
We have added further control over the number of unit loads populated during construction.
MhUnitLoadConstructionalPopulateFunction class (unitLoadConstructionalPopulate) had the argument loadCount, which was passed to MhConstructionUnitLoadArrangement to populate unit loads perpendicular to the populate vector. It has been renamed to repeatCount. Additionally, a new argument ulCount has been added to represent the number of unit loads to populate in the direction of population. If left as null, the previous behavior will be used which is to populate as many loads as possible. Similarly the MhConstructionUnitLoadArrangement class now holds fields repeatCount and ulCount in place of the previous field count.
Effectively, previous specification of loadCount will now need to specify repeatCount instead. Make sure to search for loadCount in your extension as engine function execute arguments do not throw compile errors for incorrect arguments.
// cm/abstract/materialHandling/storage/engine/mhUnitLoadConstructionalPopulateFunction.cm public class MhUnitLoadConstructionalPopulateFunction extends MhSystemEngineFunction { Old: public Int loadCount; New: public Int repeatCount; //replaces loadCount New: public int ulCount; } // cm/abstract/materialHandling/storage/mhUnitLoadArrangement.cm public class MhConstructionUnitLoadArrangement extends MhUnitLoadArrangement { Old: public int count; New: public int repeatCount; //replaces count New: public int ulCount; Old: public constructor(MhPopulator populator, MhEngineEntry defaultLoadEntry, int count=1, vector direction=(0, 1, 0), bool spreadEvenly=true) { } New: public constructor(MhPopulator populator, MhEngineEntry defaultLoadEntry, int ulCount=0, int repeatCount=1, vector direction=(0, 1, 0), bool spreadEvenly=true) { } }
The repeatCount and ulCount fields for MhUnitLoadConstructionalPopulateFunction are typically passed in from MhLevelConstructionalPopulateFunction.levelChildConstruction(MhEngineConstructionEntry entry) where it passes the values from entry.constructionInfo. Additionally in MhEngineLevelConstructionEntryInfo, the field noOfUnitLoads was renamed to noOfUnitLoadsX and both noOfUnitLoadsX and noOfUnitLoadsY fields are now boxed Int types instead of primitive int.
// cm/abstract/materialHandling/storage/engine/mhLevelConstructionalPopulateFunction.cm public class MhLevelConstructionalPopulateFunction extends MhSystemEngineFunction { /** * levelChildContruction */ extend public void levelChildConstruction(MhEngineConstructionEntry entry) { ... ?MhEngineLevelConstructionEntryInfo info = entry.constructionInfo; Int ulXCount = info.?noOfUnitLoadsX; Int ulYCount = info.?noOfUnitLoadsY; if (!ulYCount) ulYCount = configuration.unitLoadCountY(); engine.exec("unitLoadConstruction", ..., ulCount=ulXCount, repeatCount=ulYCount, ...); ... } } public class MhEngineLevelConstructionEntryInfo extends MhEngineConstructionEntryInfo { Old: public int noOfUnitLoads; New: public Int noOfUnitLoadsX; Old: public int noOfUnitLoadsY; New: public Int noOfUnitLoadsY; }
Undo operation class MhStorageEditorConfigPropModifyUndoOp now stores the Guid to the config instead of the config object itself.
public class MhStorageEditorConfigPropModifyUndoOp extends MhStorageEditorUndoOp { Removed: public MhStorageEditorConfiguration config : copy=reference; New: public Guid configGid; New: public constructor(MhStorageEditorDialog dialog, Guid configGid, str propKey, Object propVal) { }
Removed classes MhStorageEditorDimensionToolbarModelItem and MhBayEditorElevArrowToolbarModelItem. Both functionalities are now implemented in MhStorageEditorConfiguration. Instead of separate toolbar items, they have been combined into one visibility toolbar item.
Removed: public class MhStorageEditorDimensionToolbarModelItem extends ToolbarModelItem { Removed: public class MhBayEditorElevArrowToolbarModelItem extends ToolbarModelItem { Removed: public const str cMhArrowVisibilityStateKey = "arrowVisibilityState"; public class MhStorageEditorConfiguration extends MhSystemConfiguration { New: /** * Allow dimension visibility toggle? */ extend public bool allowDimensionVisibilityToggle(View view) { return false; } New: /** * Allow arrow visibility toggle? */ extend public bool allowArrowVisibilityToggle(View view) { return false; } New: /** * Dimension visibility toggle changed. */ extend public void dimensionVisibilityToggleChanged(bool state, View view) { if (Space space = view.?space) { mhStorageEditorDimensionTogglePutCached(space, value=state); for (s in space.snappers) mhUpdateEditorDimensionVisibility(s); } } New: /** * Arrow visibility toggle changed. */ extend public void arrowVisibilityToggleChanged(bool state, View view) { if (Space space = view.?space) { mhStorageEditorArrowTogglePutCached(space, value=state); insertArrowVessel(space); } } New: /** * Update snappers visibility. */ extend public void updateSnappersVisibility() { for (s in space.snappers) mhUpdateEditorDimensionVisibility(s); insertArrowVessel(space); } }
The dimensions toggle is visible by default for bay editor. The arrow toggle is visible by default for frame editor, and bay editor's 3D view.

Removed field str volumeId and replaced with a private field private symbol volumeId. Replaced methods str volId=(str id) with symbol volId=(symbol id) and str volId() with symbol volId().
public class AbsMezzLevelRectInsertAnimation extends DrawShapeRectAnimation { Old: public str volumeId; New: private symbol volumeId; Old: extend public str volId=(str id) { New: extend public symbol volId=(symbol id) { Old: extend public str volId() { New: extend public symbol volId() { }
Removed function void mezzInsertRails(APolyline2D poly, AbsMezzDecking{} deckings, Space space). Call function void mezzInsertRailGroup(APolyline2D poly, APolyline2D[] holes, AbsMezzDecking{} deckings, Space space) instead.
Removed: public bool dbg_verboseProfilerDump = false; Removed: public void repairBlocks() {
Removed enum that is not used anywhere in the base repository.
Removed: public enum featureDetail : field access {
The visibility of dropDownImage field has been altered, you will need to use setDropDownImage to change the image.
Old: public Image dropDownImage : copy=reference; New: private Image dropDownImage : copy=reference, public readable; New: final public void setDropDownImage(Image i)
This class has been removed. You can replace it with FaceliftToggle
Old: public class InfoTipToggle extends CheckBox { New: public class FaceliftToggle extends CheckBox {
The following interfaces in SelectLasso2DAnimation have been changed:
Old: extend public bool isTarget(Snapper s, APolyline2D pline=null, bool quickElim=true) { New: extend public bool isTarget(Snapper s, APolyline2D pline) {
The following interfaces in SelectLasso2DAnimation have been removed:
Removed: final public void appendTargets(line2D l) { Removed: extend public bool contained(Snapper s, APolyline2D pline=null) { Removed: extend public bool ridiculous(rect sb, APolyline2D pline) { Removed: extend public bool plausible(rect sb, APolyline2D pline) { Removed: extend public GeometricFinder[] getFinders(APolyline2D pline) { Removed: extend public int snapperBoundInPolyline(Snapper s, APolyline2D pline) { Removed: extend public int graphInPolyline(GraphPrimitive gp, APolyline2D pline, line2D e, bool oneUncontained, bool seen) {
Deprecated functions have been removed.
Old: public void removeOldCetQLParamsFromSnapper(Snapper z) : deprecated { New: public void removeCetQLParamsFromSnapper(Snapper z) {
Removed: public class FunkySelectionVisualizer extends SelectionVisualizer {
Made showLibHelpText return the constructed window.
Old: public void showLibHelpText(Window parent, str text="No help available in BETA version.", str title=null, str key=null, int width=300, PointI pos=null, symbol pkg=null) { New: public DialogWindow showLibHelpText(Window parent, str text="No help available in BETA version.", str title=null, str key=null, int width=300, PointI pos=null, symbol pkg=null) { Removed: public DialogWindow showLibHelpText2(str pkg="cm.std.tools", Window parent=null, str text="No help available in BETA version.", str key=null, PointI p=null) {
Added a bool suppressZeroFraction argument to the constructor.
Old: public constructor(symbol pkg, str key, str name, alignment textAlignment, distanceUnit unit, int precision1, distanceUnit unit2, int precision2, bool suppressZeroFraction, double arrowHSize, Class arrowHType, Class arrowHType2, double gap, double extLineExt, bool onlyPaperView=false, bool stackDims=false, Bool showDistanceUnit=null) { New: public constructor(symbol pkg, str key, str name, alignment textAlignment, distanceUnit unit, int precision1, distanceUnit unit2, int precision2, bool suppressZeroFraction, double arrowHSize, Class arrowHType, Class arrowHType2, double gap, double extLineExt, bool suppressZeroFeet=false, bool onlyPaperView=false, bool stackDims=false, Bool showDistanceUnit=null) {
Combined all 5 constructors into 1. The default argument values are the same as before in all cases except for the constructor with the bool real argument. There shouldn't have been any reason to use that constructor since "real" width lines have never been supported. But if you want to ensure the same behavior as before, specify widthStyle=lineWidthStyle.variable for any instance that previously set the bool real argument to any value.
In the majority of cases though, all that needs to be done is to add the argument hint for the width (e.g. LineType(.., .., w=5)).
Old: public constructor() { Old: public constructor(color lineColor) { Old: public constructor(color lineColor, lineStyle style, int width=0) { Old: public constructor(color lineColor, double width, bool real=false) { Old: public constructor(color lineColor, lineStyle style, lineWidthStyle widthStyle, double w) { New: public constructor(color lineColor=black, lineStyle style=lineStyle.solid, lineWidthStyle widthStyle=lineWidthStyle.unit, int w=0) {
Also consider if you should be using the LineType constructor at all. As long as the LineType instance does not need to be modified, it is recommended to get it using the lineType(..)-function instead, which returns a cached copy for improved performance.
Change the width argument from a double to an integer, which is what the value has always been converted to internally. If you have previously passed it a fractional value and is unsure what to replace it with, you can just cast it to an integer (e.g. myVar.int) to maintain the same behaviour as before.
Old: public str lineCacheKey(color c, lineStyle style, lineWidthStyle widthStyle, double width) : inline { New: public str lineCacheKey(color c, lineStyle style, lineWidthStyle widthStyle, int width) : inline { Old: public LineType lineType(color c, lineStyle style=lineStyle.solid, lineWidthStyle widthStyle=lineWidthStyle.unit, double width=0) { New: public LineType lineType(color c, lineStyle style=lineStyle.solid, lineWidthStyle widthStyle=lineWidthStyle.unit, int width=0) {
The interfaces to getStateContaining and getInfoContaining have been changed to allow bypassing the pkgStateCache:
Old: final public ExtensionState getStateContaining(symbol pkg) New: final public ExtensionState getStateContaining(symbol pkg, bool skipCache=false) Old: final public ExtensionInfo getInfoContaining(symbol pkg) New: final public ExtensionInfo getInfoContaining(symbol pkg, bool skipCache=false)
The constructor now requires you to specify the start point and the end point of the line, in world coordinates.
Removed: public constructor(pointF ipWC, int lineIndex) { Added: public constructor(pointF ipWC, pointF p0WC, pointF p1WC, int lineIndex) {
Renamed the atan functions that take 2 arguments to be correctly called atan2.
Old: public angle atan(double y, double x) : nonfglue = ang_atan2; New: public angle atan2(double y, double x) : nonfglue = ang_atan2; Old: public double atand(double y, double x) : nonfglue = ang_atan2d; New: public double atan2Rad(double y, double x) : nonfglue = ang_atan2d; Old: public double atanquick(double y, double x) : nonfglue = ang_qatan2d; New: public double quickAtan2Rad(double y, double x) : nonfglue = ang_qatan2d;
Renamed the atan functions that take 2 arguments to be correctly called atan2.
Old: public angle atan(float y, float x) : nonfglue = angF_atan2; New: public angle atan2(float y, float x) : nonfglue = angF_atan2; Old: public float atand(float y, float x) : nonfglue = angF_atan2f; New: public float atan2Rad(float y, float x) : nonfglue = angF_atan2f; Old: public float atanquick(float y, float x) : nonfglue = angF_qatan2f; New: public float quickAtan2Rad(float y, float x) : nonfglue = angF_qatan2f;
Moved classes AEVEventReciever,AEVButton and AEVDialog from cm.statistics.reporter.test to cm.statistics.reporter. This also moves the methods public void startAnalyticsEventViewer() and public void stopAnalyticsEventViewer().
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library stdArchitecturalLibrary() {
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library stdWallLibrary() {
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library stdPaperToolsLibrary() { Removed: public class ViewportSnapperLimbVisibility extends LibraryLimbVisibility { Removed: public class XCLipLimbVisibility extends LibraryLimbVisibility {
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library stdWallLibrary() {
Replaced the thickness field with a width and depth component.
Old: public double thickness; New: public double width; New: public double depth; Removed: public const DistanceRange pillarThicknessDomain(1cm, 100m);
Removed: extend public void drawGraphsLocal(Snapper snapper, LayerBuffer lb) {
Added caller eval to the testPackage(..) package-argument, which causes the package argument to be set from the call location rather than the function definition location. This means that if the function is called for example from the package "cm.core.dwg.test", it will now run all tests in that same package even if you don't pass any arguments to the function.
Old: public void testPackage(symbol pkg=#:package, bool verbose=false, bool hideErrors=false) { New: public void testPackage(symbol pkg=#:package : caller eval, bool verbose=false, bool hideErrors=false) { Removed: public void testPackage(symbol pkg=#:package : caller eval) {
For example, if you previously called the function like so:
testPackage(#:package, verbose=true);
You can now call it like this and it will still behave the same:
testPackage(verbose=true);
Some classes in getWindowInstruction.cm has been moved to their own files: See getParentWindowInstruction.cm and getChildInstruction.cm.
Two deprecated constructors have been removed:
Removed: public constructor(str windowKey, str outputKey, SrcRef src=#:src) { Removed: public constructor(Class windowClass, str outputKey, SrcRef src=#:src) {
Instead, use one of these constructors:
public constructor(str windowKey, str outputKey, bool ensureFound=true, bool ensureUnique=true, bool ensureValid=true, bool ensureVisible=true, SrcRef src=#:src) { public constructor(Class windowClass, str outputKey, bool ensureFound=true, bool ensureUnique=true, bool ensureValid=true, bool ensureVisible=true, SrcRef src=#:src) {
Two deprecated constructors have been removed:
Removed: public constructor(str windowKey, str parentKey, str outputKey, SrcRef src=#:src) { Removed: public constructor(Class windowClass, str parentKey, str outputKey, SrcRef src=#:src) {
Instead, use one of these constructors:
public constructor(str windowKey, str parentKey|, str outputKey, bool ensureFound=true, bool ensureUnique=true, bool ensureValid=true, bool ensureVisible=true, SrcRef src=#:src) { public constructor(Class windowClass, str parentKey|, str outputKey, bool ensureFound=true, bool ensureUnique=true, bool ensureValid=true, bool ensureVisible=true, SrcRef src=#:src) {
Changes that have been done:
DibImage instead of MemoryImage. For more details, check the run-time/behavior changes section.bool newSvgRenderer now defaults to true for icon loading functions.Old: public Image icon(str name, symbol key=#default, bool debug=false) Old: public Image icon(str name, symbol key=#default, bool newSvgRenderer=false, bool debug=false) New: public Image icon(str name, symbol key=#default, bool newSvgRenderer=true, bool debug=false) Old: public Image icon(str name, bool enabled, symbol key=#default) New: public Image icon(str name, bool enabled, symbol key=#default, bool newSvgRenderer=true) Old: public Image disabledIcon(str name, symbol key=#default) New: public Image disabledIcon(str name, symbol key=#default, bool newSvgRenderer=true) Old: public Image dibIcon(str name, symbol key=#default, bool debug=false) Old: public Image dibIcon(str name, symbol key=#default, bool newSvgRenderer=false, bool debug=false) New: public Image dibIcon(str name, symbol key=#default, bool newSvgRenderer=true, bool debug=false) Old: public Image disabledDibIcon(str name, symbol key=#default) New: public Image disabledDibIcon(str name, symbol key=#default, bool newSvgRenderer=true)
The following fields and methods have been removed:
public str->DibImage dibIconLookup(); final public Image getDib(str name, bool debug=false) final public Image getDib(str name, bool newSvgRenderer=false, bool debug=false) final public Image getDisabledDib(str name, bool debug=false)
The following methods have been updated:
Old: final public Image get(str name, bool debug=false) Old: final public Image get(str name, bool newSvgRenderer=false, bool debug=false) New: final public Image get(str name, bool newSvgRenderer=true, bool debug=false)
The following methods have been updated to remove bool dib=false:
Old: final public Image get(str name, symbol key, bool dib=false, bool debug=false) Old: final public Image get(str name, symbol key, bool dib=false, bool newSvgRenderer=false, bool debug=false) New: final public Image get(str name, symbol key, bool newSvgRenderer=true, bool debug=false) Old: final public Image getDisabled(str name, symbol key, bool dib=false) New: final public Image getDisabled(str name, symbol key)
Old: public constructor(Url imageFile, sizeI size=(-1, -1), SrcRef src=#:src) Old: public constructor(Url imageFile, bool newSvgRenderer, sizeI size=(-1, -1) New: public constructor(Url imageFile, bool newSvgRenderer=true, sizeI size=(-1, -1) Old: public SvgImage vectorImage(Url url, bool use=false, SrcRef src=#:src) Old: public SvgImage vectorImage(Url url, bool newSvgRenderer, bool use=false, SrcRef src=#:src) New: public SvgImage vectorImage(Url url, bool newSvgRenderer=true, bool use=false, SrcRef src=#:src)
The function showForeignWindow no longer restores the window when setting its visibility.
Use restoreForeignWindow if you want the old behavior of restoring the window.
Old: public void showForeignWindow2(mwnd hwnd) = win_showForeignWindow; New: public void showForeignWindow(mwnd hwnd) = win_showForeignWindow; Old: public void showForeignWindow(mwnd hwnd) = win_restoreForeignWindow; New: public void restoreForeignWindow(mwnd hwnd) = win_restoreForeignWindow;
The following functions have been removed.
public bool faceliftDeveloper() : deprecated { return staffan or prismDeveloper; } public bool isAlphaLegacy(char c) { return spellChecker.isAlpha(c); }
AppWindow
Old: final public pointI dropDownShow(pointI p, bool autoSize=true) New: final public pointI dropDownShow(pointI p, bool autoSize=true, bool enforceMinWidth=true)
Window
Old: extend public pointI showDropDownMenu(pointI p, bool pInScreenCoords=false, bool autoSize=true) New: extend public pointI showDropDownMenu(pointI p, bool pInScreenCoords=false, bool autoSize=true, bool enforceMinWidth=true)
We have added a new argument bool establishSocketConnection=false into the constructor.
Old: public constructor(str key, str url, int port=-1, bool launch=false, str label="CET", bool showPageTitle=false, bool showNavigation=true, bool alwaysOnTop=false, bool hideUrl=false, pointI initPos=(-1, -1), sizeI initSize=(-1, -1), bool resizable=false, sizeI minSize=(-1, -1), sizeI maxSize=(-1, -1), bool devMode=false, webViewCB msgCallback=null) New: public constructor(str key, str url, int port=-1, bool launch=false, str label="CET", bool showPageTitle=false, bool showNavigation=true, bool alwaysOnTop=false, bool hideUrl=false, pointI initPos=(-1, -1), sizeI initSize=(-1, -1), bool resizable=false, sizeI minSize=(-1, -1), sizeI maxSize=(-1, -1), bool devMode=false, webViewCB msgCallback=null, bool establishSocketConnection=false)
The sizeI size argument has been changed to int width.
Old: public constructor(Window parent, str message, Image image, str key=null, sizeI size=(0, 0), int internalMargin=7, Brush brush=ultraLightGrayBrush, FrameStyle frameStyle=lightGrayPenFrame, color textColor=black, color linkColor=primary600, color linkHoverColor=primary600, int textSize=12, str fontFace=null, function(Control button, str key):bool linkCallback=null, SrcRef src=#:src) { New: public constructor(Window parent, str message, Image image, str key=null, int width=0, int internalMargin=7, Brush brush=ultraLightGrayBrush, FrameStyle frameStyle=lightGrayPenFrame, color textColor=black, color linkColor=primary600, color linkHoverColor=primary600, int textSize=12, str fontFace=null, function(Control button, str key):bool linkCallback=null, SrcRef src=#:src) {
This MessageWindow constructor now takes in argument int width.
Old: public constructor(Window parent, str message, messageType msgType=messageType.undefined, str key=null, int internalMargin=7, function(Control button, str key):bool linkCallback=null, SrcRef src=#:src) { New: public constructor(Window parent, str message, messageType msgType=messageType.undefined, str key=null, int width=0, int internalMargin=7, function(Control button, str key):bool linkCallback=null, SrcRef src=#:src) {
statsMainExtensionPackage now accepts argument bool allowGuess to try guessing the main extension package via the provided package.
Old: public symbol statsMainExtensionPackage(symbol pkg) New: public symbol statsMainExtensionPackage(symbol pkg, bool allowGuess=false)
getMainExtensionPackage now accepts argument bool skipCache to allow bypassing cached results
Old: public symbol getMainExtensionPackage(symbol pkg) New: public symbol getMainExtensionPackage(symbol pkg, bool skipCache=false)
The following classes have been removed as film strip view functionality has been removed.
Removed: public class FilmStripView extends ThumbNailView { Removed: public class PreviewWindow extends SubWindow {
The following fields and methods have been removed in ExploreDialog
Removed: public PreviewWindow previewWin; Removed: extend public PreviewWindow buildPreviewWin() { Removed: extend public void refreshPreviewWin() { Removed: extend public void setPreviewContent(Image image=null, str label=null) { Removed: extend public void updatePreviewButtons(bool disablePrev, bool disableNext) { Removed: extend public sizeI previewImageSize() { Removed: extend public bool filmStripMode() {
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library genericElectricalLibrary() { Old: public Library faceliftElectricalLibrary() { New: private Library faceliftElectricalLibrary() {
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library classicStdLightsLibrary() { Old: public Library faceliftStdLightsLibrary() { New: private Library faceliftStdLightsLibrary() {
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library medicalLibrary() { Old: public Library faceliftMedicalLibrary() { New: private Library faceliftMedicalLibrary() {
Removed the classic library. Update references to the facelifted library or remove them.
Removed: public Library stdPlantsLibrary() { Old: public Library faceliftPlantsLibrary() { New: private Library faceliftPlantsLibrary() {
The following interfaces will be removed as part of the Component Tab and Component Tab Creator EOL effort:
// Functions Removed: public void dcShowToolboxCreatorVendorChangeWarning(DataCatalog catalog)
// Functions Removed: public DcToolboxCreatorDialog dcToolboxCreatorDialog() Removed: public DcToolboxCreatorDialog dcShowToolboxCreatorDialog() Removed: public DcToolboxCreatorDialog dcShowToolboxCreatorDialog(bool setFocus) Removed: public void dcCloseToolboxCreatorDialog() // Classes Removed: public class DcToolboxCreatorDialog extends DsToolboxCreatorDialog Removed: public class DcAnimationTreeViewAnimationEnv extends DsDragAnimationEnv Removed: public class DcDataCatalogLimbEnv extends DsDataCatalogLimbEnv Removed: public class DcToolboxCreatorToolboxCards extends DsToolboxCreatorToolboxCards
// Classes Removed: public class DcProductCatalogToolboxProductReferencesEnv extends DcProductCatalogReferencesValidationEnv { Removed: public class DcProductCatalogToolboxReferencesEnv extends DcValidationEnv Removed: public class DcProductCatalogToolboxProductOptionsEnv extends DcValidationEnv
class DcProductLevelEditSubWindow
Removed: extend public void updateActivation()
class DcTableOfContentsSubWindow
// Field public NoteWindow noteWindow; // Methods Removed: extend public void openToolboxCreator() Removed: extend public void buildNoteWindow() Removed: extend public void updateNote()
class DcTableOfContentToolboxSubWindow
Removed: public DsButton toolboxCreatorBtn; Removed: extend public void updateActivation()
class DcTableOfContentsTreeView
Removed: public bool keyCode(Window originator, KeyCode keyCode) Removed: public bool acceptTVI(TreeViewItem item)
// Classes: Removed: public class DcTbOptionsValidationUndoOp extends DcUndoOp Removed: public class DcProductCatalogAddToolboxesUndoOp extends DcUndoOp Removed: public class DcProductCatalogRemoveToolboxesUndoOp extends DcProductCatalogAddToolboxesUndoOp
// Classes Removed: public class DcPsLayoutReferencesValidationEnv extends DcValidationEnv
// Classes Removed: public class DcCompTabValidationResult extends DcValidationResult Functions: Removed: public void dcNavigateToToolboxCreator() Removed: public void dcNavigateToToolboxCreatorCard(str code)
Added 2 new parameters to updateProductDD to flag that first/last product is selected.
Old: extend public void updateProductDD(bool updateCard=true) New: extend public void updateProductDD(bool updateCard=true, bool selFirstProd=false, bool selLastProd=false)
Added 2 new parameters to updateSelProd to flag that first/last product is selected.
Old: extend public void updateSelProd(int start) New: extend public void updateSelProd(int start, bool selFirstProd=false, bool selLastProd=false)
Added 1 new parameter to 'dcBuildAddProductTreeViewItem' to keep track of the additional product's parent product.
Old: public DcAddProductTreeViewItem dcBuildAddProductTreeViewItem(DsiAddProductRefType prod, CatalogTreeViewEnv env) New: public DcAddProductTreeViewItem dcBuildAddProductTreeViewItem(DsiAddProductRefType prod, CatalogTreeViewEnv env, DsProductType parentProd)
DsAPIPData which is the data used for snappers imported from stage has been removed. Stage snappers will now use DsPData which is used by regular catalogue symbols to be more consistent with CET catalogue symbols.
As part of the EOL effort, the Component Tab file format (.cmtbxt) will also be retired and no longer be loadable as the streamed Component Tab class packages are removed. Ideally the Component Tab interfaces should only be streamed as part of the cmtbxt file format, and should not (and is not supposed to) be streamed with other cm file format (e.g., drawings, favorites). However, if the classes were somehow streamed as part of other file format, a new PackageStreamRenamer class is introduced to redirect these missing classes to a temporary placeholder class. Do note that this class serves no meaningful purpose, as it merely exists to suppress or bypass any load failure/errors caused by missing Component Tab related packages.
In developMode, the renamer will print extra info and a short stack dump so that it won't go fully unnoticed.
In cm.abstract.dataSymbol.renamer.cm:
/** * Stream renamer for removed toolbox creator package (cm.abstract.dataSymbol.ui.toolboxCreator). * which was permanently removed starting 17.0. * * Handles and redirect the streamed objs to a dummy class so it does not crash CET. */ private class DsToolboxCreatorRenamer extends PackageStreamRenamer { public void type(version v, Symbol pkg, Str name, Str fileName=null) { if (pkg.v == "cm.abstract.dataSymbol.ui.toolboxCreator") { if (developMode) { pln("Attempting to load Component Tab interfaces!".eAngry; #pkg; #name); stackDump(3); } pkg.v = "cm.abstract.dataSymbol"; name.v = "DsDummyTBCreatorStreamPlaceHolder"; } } /** * Deprecate old packages. */ final private void deprecateOldPackages() { // Used to deprecate packages info stored in drawings to avoid load warnings about missing packages if (StreamRenamer r = globalStreamRenamer) { r.deprecatePkg((#"cm.abstract.dataSymbol.ui.toolboxCreator")); } } } /** * Placeholder for streamed classes from 'cm.abstract.dataSymbol.ui.toolboxCreator'. */ public class DsDummyTBCreatorStreamPlaceHolder : unstreamable { /** * Load failure event. */ public loadFailedResult loadFailed(ObjectFormatter formatter, LoadFailure failure) { return loadFailedResult.ignore; } }
IFC export was using a snapper's sym representation to generate the IFC geometry of the IFC symbol. This was because sym supports geometries such as extrusions, which can be exported as solids. However, due to how certain SymNodes were generated, this resulted in compound solids which cause the geometries to go missing when viewed in certain IFC viewer softwares (such as Solibri and Revit) due to the rendering rules of those softwares. Defaulted this now to export using the snapper's mesh instead to improve the consistency of the visibility of IFC symbol geometries in IFC viewer softwares. However, if a manufacturer wishes to still export their snapper using the sym based representation (possibly to export as a solid), they can override extend public bool useSymBasedRepresentations() method in IfcExportCoreObjectFactory to return true.
In 17.0 Major we have fixed an issue involving level snappers inserted without any unit loads. They do not have a MhSnapperBehavior in its stateBehaviorCollection field after insertion. The problem is that after inserting a UnitLoad onto a level, it does not get absorbed as a MhSnapperInfo due to the level missing the MhSnapperBehavior, and this behavior does not get initialized for existing levels.
We have since fixed it to start initializing MhSnapperBehavior when needed, and to ensure old drawings are handled we added this load code. If you have a custom level shape class that does not extend from MhLevelShape, you will need to copy the below code into your class.
public class MhLevelShape extends MhBoxSnapperShape { public void loaded1(ObjectFormatter formatter, LoadFailInfo failInfo) { super(..); mhUnstreamStoredSpec(formatter); // CETC-134365. if (formatter.version(#:package) < version(17, 0, 0)) { if (owner and !owner.snapperInfosBehavior()) { if (MhSystemConfiguration config = owner.configuration()) { forChildren(MhSnapper child in owner) { if (config.exportAsBehavior(child.classification)) { owner.initSnapperInfosBehavior(); break; } } } } } } }
The following spawners have had the mhRowChildSelectionBehavior added to them. This changes their group selection behavior such that the row is no longer included in the selection when the accessory is selected. You may need to exclude this behavior if your custom class already appends a selection behavior.
The drawFeatures(..) method has been changed so that features for the 3D view are now generated from the snappers 3D mesh instead of using the same features as for the 2D view, which were often not accurate in 3D space. The method can be overriden to define a custom behaviour.
drawFeatures → Use the overridedrawFeatures → Take features based on drawGraphs (2D graphics)drawFeatures → Use the overridedrawFeatures → Add features based on 3D meshdrawFeatures → Use the overridedrawFeatures → Take features based on drawGraphs (2D graphics)drawFeatures → Use the overridedrawFeatures → Take features based on drawGraphs (2D graphics)Some core snappers override drawFeature in order to retain the old behavior. The reasons for this vary, but one example is lines where we want it to snap to the mathematical (infinitely small) line rather than to the cylindrical mesh of the line.
The following snappers have overriden the behavior:
drawFeatures to return drawGraphs(..).drawFeatures and define your own more accurate features.drawFeatures or systemDrawFeatures:
In general, it's recommended to test the feature snapping of your extension and ensure it's working as expected. For example, check if the measure tool can be used to accurately measure the dimensions your objects.
Improved UV mapping so that textures get applied uniformly across the mesh at a UV-to-world scale of 1 UV unit = 1m. This change should generally not require any migration effort, unless your extension has taken measure to counteract the previously incorrect UV mapping. Please note that this change does not affect ClosedCylinder3D.
Below are comparisons of how it looked before (left) and how it looks after the change (right).
{ width=400px }
{ width=400px }
Improved UV mapping so that textures get applied uniformly across the mesh at a UV-to-world scale of 1 UV unit = 1m. This change should generally not require any migration effort, unless your extension has taken measure to counteract the previously incorrect UV mapping.
Below are comparisons of how it looked before (left) and how it looks after the change (right).
{ width=400px }
{ width=400px }
{ width=400px }
{ width=400px }
Corrected the UV mapping of Rect3D's constructed with the type rect3DtypeWH. Previously, the width and depth component of the UV coordinates were swapped. This change should generally not require any migration effort, unless your extension has taken measure to counteract the previously incorrect UV mapping.
Below is a comparison of how it looked before (left) and how it looks after the change (right).
{ width=400px }
Previously, the inchesS(double v, bool showUnit, lcid local, int decimals, unitMagnitude magnitude) function would disregard the decimals value. This behavior has been updated to respect that argument.
The location of saved preferences has changed from "
When loading saved UserSettings (such as RtSettings and CoreSettings) CET looks for the file in the folder in "\CET Preferences\
Changed the origin from the bottom-left corner to the bottom-center of the cube.
Improved UV mapping of many snappers in the wall package. In general, all symbols should now apply textures more uniformly across the mesh at a UV-to-world scale of 1 UV unit = 1m. However, smaller inaccuracies may still exist.
This change affect the following symbols (and possibly more):
Below are some sample comparisons of how it looked before (left) and how it looks after the change (right).
{ width=400px }
{ width=400px }
{ width=400px }
{ width=400px }
{ width=400px }
{ width=400px }
{ width=400px }
{ width=400px }
Now also triggers the snapper's click animation to more closely mimic an actual user click. Tests that start failing due to this are recommended be repeated by hand to figure out whether it's a false negative or not.
In 16.5, we introduced dibIcon(..) which loads icon as DibImage instead of MemoryImage. For 17.0, we are replacing the existing icon(..) to behave exactly as dibIcon(..).
Benefits of DibImage:
For existing code that calls icon(..) and expects a MemoryImage, migration will be required.
Common symptoms are:
How to resolve this:
In core, we had 2 common scenarios.
// Previous logic only handles MemoryImage. byte beforeBlend = 255; if (image as MemoryImage) { beforeBlend = image.blend; image.blend = 100; } image.transparentDraw(c.hdc, imgPos); if (image as MemoryImage) image.blend = beforeBlend; // New logic now handles MemoryImage, DibImage and SvgImage. byte beforeBlend = image.blend; image.blend = 100; image.transparentDraw(c.hdc, imgPos); image.blend = beforeBlend;
// Previous logic only handles MemoryImage and Icon if (limb as SnapperLimb) { if (limb.image in MemoryImage or limb.image in Icon) { button = snapperImage(window, label, limb, limb.src); } } else if (limb as AnimationLimb or limb.image in Icon) { if (limb.image in MemoryImage) { button = animationImage(window, label, limb, limb.src); } } // New logic now handles MemoryImage, Icon, DibImage and SvgImage if (limb as SnapperLimb) { if (limb.image in MemoryImage or limb.image in Icon or limb.image in DibImage or limb.image in SvgImage) { button = snapperImage(window, label, limb, limb.src); } } else if (limb as AnimationLimb) { if (limb.image in MemoryImage or limb.image in Icon or limb.image in DibImage or limb.image in SvgImage) { button = animationImage(window, label, limb, limb.src); } }
In 16.5 Minor:
For 17.0 Major:
If you spot issues loading your svg icons, you can pass newSvgRenderer=false when you call icon(..)
// New svg renderer causing issues icon("myIcon", #:pkg) icon("myIcon", false, #:pkg) vectorImage(url); // Fallback to svg renderer used in CET 16.5 icon("myIcon", #:pkg, newSvgRenderer=false) icon("myIcon", false, #:pkg, newSvgRenderer=false) vectorImage(url, newSvgRenderer=false);
As we now have better SVG rendering capabilities in CET, IconFinder will search for SVG first before other suffixes.
Old: public str[] suffixSearchPriority = [".png", ".bmp", ".cmpng", ".cmbmp", ".svg"]; New: public str[] suffixSearchPriority = [".svg", ".png", ".bmp", ".cmpng", ".cmbmp"];
Previously DsPData used G2 properties by default for its base class. This has now been changed so that subclasses of DsPData will also use G2 properties by default as well.
Old: extend public bool usingG2() { if (blockDataProxy == 0 and proxy) return proxy.usingG2(DsPDataProxyEnv(this)); return (this.class.toS in {"DsPData", "DcPData", "DcPRenderData"} and (!proxy or proxy.class.toS == "DsPDataProxy")); }
New: extend public bool usingG2() { if (blockDataProxy == 0 and proxy) return proxy.usingG2(DsPDataProxyEnv(this)); return true; }
To override the default behavior, override the usingG2 method in your DsPData subclass, or register a DsPDataProxy and override the public bool usingG2(DsPDataProxyEnv env) method to return false.
Previously IFC import did not account for the mapping target of an IfcMappedRepresentation (only the mapping source's mapping origin) when calculating the IFC snapper's transform which resulted in multiple snappers being placed in the same location on import. Updated this so now the mapping target transform is applied onto the mapping source's mapping origin's transform on import to determine its position relative to the IFC project.
Improved IFC export to include mezzanines, and user placed floors when the "Include architectural objects on exporting" setting is enabled.