cm.core

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