Overview

CM Language

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) {

cm.core3D

Improved the texture mapping of the basic 3D shapes for rectangles, cylinders and pyramids.

cm.std.wall

Improved the texture mapping of many wall symbols such as arced walls, windows and curtains.

Compile Time Changes

CM Language

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.

cm.abstract.material

AbsMaterial thumbnailType

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() {..}
}

cm.core

featureFilter.cm

Removed enum that is not used anywhere in the base repository.

Removed: public enum featureDetail : field access {

ContextualViewDropDownItem

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)

InfoTipToggle

This class has been removed. You can replace it with FaceliftToggle

Old: public class InfoTipToggle extends CheckBox {
New: public class FaceliftToggle extends CheckBox {

selectLasso2DAnimation.cm

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) {

Query language

Deprecated functions have been removed.

Old: public void removeOldCetQLParamsFromSnapper(Snapper z) : deprecated {
New: public void removeCetQLParamsFromSnapper(Snapper z) {

cm.geometry

class PickLineInfo

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) {

cm.std.architectural

library.cm

Removed the classic library. Update references to the facelifted library or remove them.

Removed: public Library stdArchitecturalLibrary() {

cm.std.tools

library.cm

Removed the classic library. Update references to the facelifted library or remove them.

Removed: public Library stdWallLibrary() {

paperLibrary.cm

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 {

cm.std.wall

library.cm

Removed the classic library. Update references to the facelifted library or remove them.

Removed: public Library stdWallLibrary() {

cm.test.cmunit.testInstructions

class GetWindowInstruction

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) {

class GetChildWindowInstruction

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) {

cm.win

Icons

Changes that have been done:

  1. We now return a DibImage instead of MemoryImage. For more details, check the run-time/behavior changes section.
  2. The argument 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)

IconFinder

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)

IconDB

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)

SvgImage

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)

Foreign windows

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;

Removed deprecated functionality

The following functions have been removed.

public bool faceliftDeveloper() : deprecated { return staffan or prismDeveloper; }
public bool isAlphaLegacy(char c) { return spellChecker.isAlpha(c); }

Drop down functionality

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)

WebViewConfig

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)

MessageWindow

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) {

cm.win.advanced

FilmStripView

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() {

custom.accessories.genericElectrical

library.cm

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() {

custom.accessories.lights

library.cm

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() {

custom.accessories.medical

library.cm

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() {

custom.accessories.plants

catalogues/library.cm

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() {

Runtime/Behavior Changes

cm.core3D

class Cylinder3D

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).

Vertical cylinder{ width=400px } Horizontal cylinder{ width=400px }

class Pyramid3D

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).

Pyramid 1{ width=400px } Pyramid 2{ width=400px } Pyramid 3{ width=400px } Pyramid 4{ width=400px }

class Rect3D

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).

Rect3D{ width=400px }

cm.geometry2D

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.

cm.startup

class UserSettings

The location of saved preferences has changed from "\Documents\CET Documents\Preferences\" to "\AppData\Local\CET Preferences\". If CET can't find any saved preferences in the new location, it falls back to the old location.

When loading saved UserSettings (such as RtSettings and CoreSettings) CET looks for the file in the folder in "\CET Preferences\", where versionID is replaced with the versionID of the currently running CET ("64-bit" for the release, "Beta-64-bit" for the beta or the name of the workspace in develop mode for example). Previously, if the file was not found there, CET would search for older versions first by looking in the same folder with the same version ID, and secondly by recursively traversing all folders in "\CET Preferences" and use the first one found. This has now been changed so that CET will now only look for previous versions in the folder with the same version ID.

cm.std.accessories

class TestCubeSnapper

Changed the origin from the bottom-left corner to the bottom-center of the cube.

cm.std.wall

UV Improvements

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):

  • WallDoor
    • Frameless glass
    • Two panel
    • Two panel, top curved
    • Three panel
    • Panel with glass
    • Four panel
    • Five panel
  • WallWindow
    • Straight, Frameless glass
    • Straight, Glass with vault
    • Curved, None
    • Curved, Solid
    • Curved, Glass
    • Curved, Frameless glass
    • Curved, Circular
    • Curved, On edge vault
    • Curved, Glass with vault
  • WallSectionalDoor
  • Curtain
  • VenetiansBlinds
  • WindowSill
  • WallRadiator
  • WallImageSnapper
  • SimpleDrain
  • WallArc

Below are some sample comparisons of how it looked before (left) and how it looks after the change (right).

Door, 3 panel{ width=400px } Window, top curved{ width=400px } Curved windows{ width=400px } Curved 'On edge square' window{ width=400px } Curtain{ width=400px } Arced wall{ width=400px } Image on wall{ width=400px } Radiator{ width=400px }

cm.test.cmunit.testInstructions

class ClickInstruction

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.

cm.win

Icon now returns DibImage

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:

  • Can be resized with less artifacts as DibImage do not premultiply alpha values
  • Does not consume a windows GDI object, making it ideal for loading icons

For existing code that calls icon(..) and expects a MemoryImage, migration will be required. Common symptoms are:

  • Images not loading
  • Toolbox icons get rendered instead of loading an icon
  • Disabled images are not grayed out (blend is not applied)

How to resolve this:

  • Perform a Find in Files, search for "as MemoryImage" and "in MemoryImage"
  • Review the code if it can be generalized or change its logic accordingly
  • Perform the necessary changes to make it work with DibImage

In core, we had 2 common scenarios.

  1. Blend not being applied:
// 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;
  1. UIBuilder not handling DibImage:
// 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);
	}
}

New SVG renderer

In 16.5 Minor:

  • We have introduced a new SVG renderer that better supports the SVG spec.
  • It is only used for CET Icon Library, not affecting SVG loaded anywhere else.
  • The default SVG renderer a number of limitations, more information can be found here

For 17.0 Major:

  • We are defaulting to use the new SVG Renderer everywhere in CET.
  • You can choose to opt-out for cases the new renderer is incorrectly displaying the icons.
  • The new default SVG renderer aims to support the whole SVG spec, more information can be found here

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);

IconFinder

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