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"];