Overview

cm.abstract.dataSymbol.materialLegend

In CET 15.5, support for CustomerOwnMaterials has been added to the DsMaterialLegend. Filters have been implemented to also user customization of the legend items. Some fields for COMs are also optionally displayed now.

cm.abstract.dataSymbol.ui.material

In CET 15.5, support for undo operations on CustomerOwnMaterial actions has been added.

cm.core

CoreSchemes and GroupSchemes End of Life

In the CET 15.5 release in November 2024, CoreSchemes and GroupSchemes will reach their End-of-Life (EOL) and be deprecated. All developers are encouraged to upgrade and migrate to PropsSchemes - read more and learn how to migrate to PropsScheme here.

As part of the EOL effort:

  • Some programming interfaces in core will be deprecated and removed, specifically scheme builders, configurators, and user interface builders - see compile-time changes below under "CoreSchemes and GroupSchemes End of Life" section.
  • Specific data structures will be kept in core for ensuring legacy drawings compatibility and some basic functionalities.

cm.core.red3D.distributed

REDRenderJob has been extend with a new parrent class call RenderJob. Where some of the code was move down to the parrent class. Behavior wise it still the same.

Createad a new abstact base class for render jobs.

cm.core.red3D.distributed.redRenderJob

REDRenderJob has been extend with a new parrent class call RenderJob. Where some of the code was move down to the parrent class. Behavior wise it still the same.

cm.core.visibility

ViewMode's and ViewModePanel has received a large clean up. The concept of "temporary" view modes has been completely removed.

Compile Time Changes

Analytics

Analytics/Statisitics

Moved getMainExtensionPackage(symbol pkg) from cm.core to cm.win. And added statsMainExtensionPackage(symbol pkg) that always returns the package.

// cm/win/eventLogG3.cm
Added: public symbol statsMainExtensionPackage(symbol pkg)
Added: public symbol getMainExtensionPackage(symbol pkg) //moved from cm.core

// cm/core/eventLogFunctions.cm
Removed: public symbol getMainExtensionPackage(symbol pkg) //moved to cm.win

New interface to specify Event manufacturer for Window related events (similar interface to Snapper). You may override this to explicitly specify the event manufacturer (if the default isn't applicable).

// cm/win/window.cm  class Window
extend public G3ManufacturerId statsManufacturer() 

For Layout-driven Props Scheme a.k.a PsLayoutPropsScheme (that are not automatically registered by catalogs, instead registered by your extension), the statistics properties can be specified by either overriding the methods from PropsScheme (recommended if you are already using a custom PsLayoutPropsScheme class), or assigning the PsLayoutStatsCB object into the PsLayoutPropsScheme instance (e.g. when registering).

PsLayoutStatsCB object can be supplied either by extending the PsLayoutStatsCB class to provide your implementation of the methods or construct a PsLayoutStoredStatsCB object that can be initialized with static values for the respective statistics related properties

// cm/core/propsScheme/propsSchemeDialog.cm  class PropsScheme
Added: extend public G3ManufacturerId statsManufacturer()

// cm/core/propsScheme/layout/psLayoutPropsScheme.cm class PsLayoutPropsScheme
Added: public PsLayoutStatsCB statsCB

// cm/core/propsScheme/layout/statistics.cm 
Added: public class PsLayoutStatsCB
Added: public class PsLayoutStoredStatsCB extends PsLayoutStatsCB

For Product Analytics (Part statistics), a new interface in "Part" was added to allow a more convenient way to supply option information for part statistics.

// cm/core/part/part.cm  class Part
Added: extend public (PartEntryOption[])[] statsPartEntryOptions()

With the above interface, cm.abstract.part.ProdPart class now implements this new method instead of the whole toStatsPartEntry method.

// cm/abstract/part/prodPart.cm  class ProdPart
Added: public (PartEntryOption[])[] statsPartEntryOptions()
Removed: public void toStatsPartEntry(Space space, PartEntry entry)

As part of PartEntry, the previously deprecated field have been removed.

// cm/statistics/statsPartsDB.cm  class PartEntry
Removed: public str options

Compiler and CM Language

Global Variables

In 15.5, global variables explicitly require to be declared with visibility. Omitted visibility will result in compilation error. In previous versions, global variables declared without visibility would be allowed, but, you would not be able to access them - since each global variable would be scoped in their own run function.

int a; // forbidden in 15.5
private/package/public int a; // ok

{
    ...
}

Any global variables declared as static will cause a compilation error. In previous versions, globals declared as static would only generate a compiler error if declared with public/private/package modifier.

static int a; // forbidden in 15.5
private/package/public static int a; // still forbidden in 15.5

{
    ...
}

cm.abstract.consumer

class ConsumerUXManager

Old: extend public bool checkAndSnoozePHint(str key) {
New: extend public bool checkAndSnooze(str key, timespan duration=timespan(0), bool createIfNecessary=true, int delayToVisitNo=-1) : null=true {
Old: extend public void snoozePHint(str key) {
New: extend public bool snooze(str key) : null=false {
Old: extend public void unsnoozePHint(str key) {
New: extend public bool unsnooze(str key) : null=false {

cm.abstract.consumerG2

class ConsumerUXManager

Old: extend public bool checkAndSnoozePHint(str key) {
New: extend public bool checkAndSnooze(str key, timespan duration=timespan(0), bool createIfNecessary=true, int delayToVisitNo=-1) : null=true {
Old: extend public void snoozePHint(str key) {
New: extend public bool snooze(str key) : null=false {
Old: extend public void unsnoozePHint(str key) {
New: extend public bool unsnooze(str key) : null=false {

cm.abstract.dataSymInterface.communication

The useLsForWs flag, useSslForWs flag, dsUseSSLForCatalogue function, and useLSForWebService method in DsUploadCommunicationForTest class have been removed as they always return true. The logic that execute when useLsForWs=false and useSslForWs=false are all removed.

Removed: public bool useLsForWs = true;
Removed: public bool useSslForWs = true;
Removed: public bool dsUseSSLForCatalogue() {

private class DsUploadCommunicationForTest extends DcUploadCommunication {
- Removed: public bool useLSForWebService() {

Remove DsWsMethod class and move its methods which are stil in use into DsLsWsMethod class. Some unused methods in DsLsWsMethod class are removed too.

package class DsLsWsMethod : abstract {
- Removed: public bool connected(DsCommunication com) {
- Removed: public bool appendProps() {
- Removed: public Task execute() {
- Added: extend public Object output(DsCommunication com, RpcActualArgList resultArgs) {

Remove DsWsAddUser class , DsWsUpdateUser class, DsWsRemoveUser class and DsWsListUsers class as they are not used anymore when useLsForWs is always true. DsLsWsAddUserclass, DsLsWsUpdateUser class, DsLsWsRemoveUser class and DsLsWsListUsers are used when useLsForWs=true.

cm.abstract.dataSymbol

The following functions have been added.

// retrieves a set of all materials applied to a `Snapper` without loading symbol materials
Added: extend public Material{} appliedMaterials(Snapper snapper) {}

// removes COM from applied COM materials and (optionally) cached COM materials
Added: extend public void removeCOM(str comID, bool removeFromCache=false) {}

function buildDsRedirectWarning

The following deprecated method has been removed:

Removed: public void buildDsRedirectWarning(DsPdata data,
                                            LibraryLimb parent,
                                            symbol pkg,
                                            int cid,
                                            str ofdaCode)

The following method has been updated to take in a facelift flag. Setting this to true will construct a facelifted version of data symbol redirect warning.

Old: public void buildDsRedirectWarning(DsPData data,
                                        LibraryLimb parent,
                                        symbol pkg,
                                        int cid,
                                        str ofdaCode,
                                        bool allowClearAllRedirects=true)
New: public void buildDsRedirectWarning(DsPData data,
                                        LibraryLimb parent,
                                        symbol pkg,
                                        int cid,
                                        str ofdaCode,
                                        bool allowClearAllRedirects=true,
                                        bool facelift=false)

class DsUILibraryLimb

The constructor for 'DsUILibraryLimb' has been adjusted to accept a 'facelift' flag, 'preferDesc' flag, 'btnHint' enum, 'src' reference.

Old: public constructor(symbol pkg, str key, DataCatalog cat, Image image=null, bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null, str{} visibleCats=null)
New: public constructor(symbol pkg, str key, DataCatalog cat,
                        LibraryLimbVisibility vs=null, Image image=null,
                        bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null,
                        str{} visibleCats=null, bool facelift=false, bool preferDesc=false,  // bool facelift, bool preferDesc are new
                        dsBtnHint btnHint=dsBtnHint.mediumSquare3D, SrcRef src=#:src)        // dsBtnHint btnHint and SrcRef src are new

Old: public constructor(LibraryLimb parent, symbol pkg, str key, DataCatalog cat, LibraryLimbVisibility vs=null, Image image=null, bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null, str{} visibleCats=null)
New: public constructor(LibraryLimb parent,
                        symbol pkg, str key, DataCatalog cat,
                        LibraryLimbVisibility vs=null, Image image=null,
                        bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null,
                        str{} visibleCats=null, bool facelift=false, bool preferDesc=false,
                        str{} visibleCats=null, bool facelift=false, bool preferDesc=false,  // bool facelift, bool preferDesc are new
                        dsBtnHint btnHint=dsBtnHint.mediumSquare3D, SrcRef src=#:src)        // dsBtnHint btnHint and SrcRef src are new

cm.abstract.dataSymbol.materialLegend

The following function has been removed. build2D() from the parent class (DigitalSwatch) should be utilized.

Removed:  public void build2D() {}

cm.abstract.dataSymbol.ui

class DsLazySnapper3DMemoryBtn

The constructor for 'DsLazySnapper3DMemoryBtn' has been adjusted to accept a 'facelift' flag and 'textSide' alignment.

Old: public constructor(Window parent,
                        DsPData data,
                        // inherited key arguments
                        Font font=smallSystemFont,
                        Brush brush=null,
                        FrameStyle frameStyle=toolboxButtonFrameStyle,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control c) callback=null,
                        function (Control c) leftArrowCB=null,
                        function (Control c) rightArrowCB=null,
                        function (Control c, DsPData data) updateCB=null,
                        function (Control c, str action, DsPData data) rightClickMenuCB=null,
                        function (Window c, pointI p):DsLibAnimation dragAnimationCB=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        symbol snapperPkg=null,
                        str snapperName=null,
                        // extends arguments
                        bool forceRender=false,
                        sizeI outputSize=dsMemBtnSize,
                        double distScale=1,
                        liRenderLevel level=liFull,
                        SnapperSpawner snapperSpawner=null,
                        AnimationSpawner animationSpawner=null,
                        SrcRef src=#:src)
New: public constructor(Window parent,
                        DsPData data,
                        // inherited key arguments
                        Font font=null,                 // default is now null
                        Brush brush=null,            
                        FrameStyle frameStyle=null,     // default is now null
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control c) callback=null,
                        function (Control c) leftArrowCB=null,
                        function (Control c) rightArrowCB=null,
                        function (Control c, DsPData data) updateCB=null,
                        function (Control c, str action, DsPData data) rightClickMenuCB=null,
                        function (Window c, pointI p):DsLibAnimation dragAnimationCB=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        alignment textSide=undefinedAlignment,  // alignment textSide is a new argument
                        symbol snapperPkg=null,
                        str snapperName=null,
                        // extends arguments
                        bool forceRender=false,
                        sizeI outputSize=dsMemBtnSize,
                        double distScale=1,
                        liRenderLevel level=liFull,
                        SnapperSpawner snapperSpawner=null,
                        AnimationSpawner animationSpawner=null,
                        bool facelift=false,                    // bool facelift is a new argument
                        SrcRef src=#:src)

class DsSearchLazySnapper3DMemoryBtn

The constructor for 'DsSearchLazySnapper3DMemoryBtn' has been adjusted to accept a 'facelift' flag and 'src' reference.

Old: public constructor(Window parent,
                        DsPData data,
                            //inherited key arguments
                        Font font=controlFont,
                        Brush brush=null,
                        FrameStyle frameStyle=toolboxButtonFrameStyle,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control control) callback=null,
                        function (Control control) leftArrowCB=null,
                        function (Control control) rightArrowCB=null,
                        function (Control c, DsPData data) updateCB=null,
                        function (Control c, str action, DsPData data) rightClickMenuCB=null,
                        function (Window c, pointI p):DsLibAnimation dragAnimationCB=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        symbol snapperPkg=null,
                        str snapperName=null,
                        // extends arguments
                        bool forceRender=false,
                        sizeI outputSize=(60, 60),
                        double distScale=1,
                        liRenderLevel level=liFull)
New: public constructor(Window parent,
                        DsPData data,
                        //inherited key arguments
                        Font font=controlFont,
                        Brush brush=null,
                        FrameStyle frameStyle=null,    // frameStyle now defaults to null
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control control) callback=null,
                        function (Control control) leftArrowCB=null,
                        function (Control control) rightArrowCB=null,
                        function (Control c, DsPData data) updateCB=null,
                        function (Control c, str action, DsPData data) rightClickMenuCB=null,
                        function (Window c, pointI p):DsLibAnimation dragAnimationCB=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        symbol snapperPkg=null,
                        str snapperName=null,
                        // extends arguments
                        bool forceRender=false,
                        sizeI outputSize=(60, 60),
                        double distScale=1,
                        liRenderLevel level=liFull,
                        bool facelift=false,    // bool facelift is new
                        SrcRef src=#:src)       // SrcRed src is new 

cm.abstract.dataSymbol.ui.material

The following function has been removed as it was previously migrated. The existing function, public bool buildMaterials(TreeViewItem item0, TreeViewItem item, bool open), should be utilized.

Removed: extend public bool buildMaterials(TreeViewItem item0, TreeViewItem item) {}
Existing: extend public bool buildMaterials(TreeViewItem item0, TreeViewItem item, bool open) {}

cm.abstract.draw

A new class was added to reduce duplicated code in the classes DrawLine, DrawDoubleLine, DrawRect, DrawArc, DrawCircle and DrawEllipse. These classes now inherit from DrawOptionalModel3DShape insted of DrawModel3DShape.

Added: public class DrawOptionalModel3DShape extends DrawModel3DShape : abstract

class DrawMeasureFeedbackVessel

Removed: public class DrawMeasureFeedbackVessel extends FeatureSearchFeedbackVessel : deprecated {

class DrawFieldDialog

Removed: extend public void updateDrawField(DRecord info=null, Class type=null): deprecated {

class DrawPathSnapper

Removed: public bool showMarkers = false;
Removed: extend public void changeMarkerProperty(QuickProperties props, Object value, bool testChangeOnly) {

class DrawArc

Removed: extend public void trim2(arc trimArc) {

class ProcessGridSquareEnv

Removed: public point2D graphPoint;

cm.abstract.kitchen

class WallSurfaceAlignPATCH

Removed: final public point rectoskopi(GFacePrimitive owner, point localP, bool turnBitch) {

cm.abstract.material

The following function has been added. It's intended to update the Customer Own Material's card in the material dialog.

Added:  extend public void updateCOMCard(Material mat=null) {

class MaterialLegend

We previously had wrapper methods to access used materials. These have been cleand up as it is faster to directly access mItems instead.

Old: final public Material{} usedMaterials()
Old: final public Material{} used() : deprecated
New: public Material->MaterialLegendItem mItems : copy=shallow;

cm.abstract.materialHandling

Added: private int mhPointXYZPosSort(point a, point b, Object env) {
Added: public int mhSnapperRootXYZPosSort(Snapper a, Snapper b, Object env) {
Added: public int mhSnapperFuncRunOrderSort(Snapper a, Snapper b, Object env) {
Added: public int mhEntryRootXYZPosSort(MhEngineEntry a, MhEngineEntry b, Object env) {
Added: public int mhEntryFuncRunOrderSort(MhEngineEntry a, MhEngineEntry b, Object env) {
Removed: public (Snapper{}) getAllChildrenIntersecting(Snapper snapper, Snapper targetSnapper, Snapper{} exceptTo=null) {
Old: public (Snapper{}) getAllChildrenIntersecting2(Snapper snapper, Snapper targetSnapper, bool trueIntersects=false, Snapper{} exceptTo=null) {
New: public (Snapper{}) getAllChildrenIntersecting(Snapper snapper, Snapper targetSnapper, bool trueIntersects=false, Snapper{} exceptTo=null) {

public class MhConfigManager : unstreamable {
- Old: extend public void removeConfig(MhConfigRef config, MhSnapper z) {
- New: extend public void removeSnapper(MhConfigRef config, MhSnapper z) {
- Removed: extend public void removeSnapper(MhSnapper z, symbol key, bool tempConfig) : deprecated {
- Removed: extend public bool setNewName(MhConfigRef config) : deprecated {
- Removed: extend public bool isConfigNameTaken(str name) {

public class MhSystemConfiguration extends CoreObject {
- Old: extend public void load(RobustFormatter formatter) {
- New: extend public bool load(RobustFormatter formatter) {

public class MhDebugSpaceViewerDialog extends DialogWindow {
- Old: extend public void build(Space space, bool in3D) {
- New: extend public void build(Space space, bool in3D, symbol main) {

public class MhEngineManager extends CoreObject {
- Removed: public void runEngine(MhEngine engine, MhRunEngineEnv runEnv=null)

public class MhSystemEngineEnvironment extends CxEnvironment {
- Old: repairLink(MhEngine engine, MhEngineEntry entry)
- New: shouldRepairLink(MhEngine engine, MhEngineEntry entry)

public class MhConfigBehavior extends MhBehavior : abstract {
- Removed: extend public bool autoAssignConfigName(MhConfigRef config) : deprecated {

public class MhLevelParentEngineBehavior extends MhEngineBehavior {
- Removed: extend public bool addFloorLevel(MhSnapper snapper) {

public class MhSnapperShape extends CorePropObj {
- Added: extend public void buildGeometries(MhSnapperGeometry[] geos) {

Adding more control when calculating shape bound.

- Old: public box shapeBoundWithChildren(MhSnapper owner, symbol[] symbols)
- New: public box shapeBoundWithChildren(MhSnapper owner, symbol[] symbols, SnapperFilter filter=null)  

MhConfigManager changes

The method removeConfig(MhConfigRef config, MhSnapper z) has been renamed to removeSnapper(MhConfigRef config, MhSnapper z) which is a more accurate name representing the logic of the method.

- Old: extend public void removeConfig(MhConfigRef config, MhSnapper z) {
- New: extend public void removeSnapper(MhConfigRef config, MhSnapper z) {

The method removeSnapper(MhSnapper z, symbol key, bool tempConfig) has been removed. Use either removeSnapper(MhConfigRef config, MhSnapper z) or removeSnapper(MhSnapper z, symbol key) instead.

- Removed: extend public void removeSnapper(MhSnapper z, symbol key, bool tempConfig) : deprecated {

The method setNewName(MhConfigRef config) has been removed. Use initialiseConfig(MhConfigRef config) instead.

- Removed: extend public bool setNewName(MhConfigRef config) : deprecated {

The method isConfigNameTaken(str name) has been removed as it was unused.

- Removed: extend public bool isConfigNameTaken(str name) {

MhSystemConfiguration changes

The method load(RobustFormatter formatter) now returns a bool value to allow for returning false when loading fails.

- Old: extend public void load(RobustFormatter formatter) {
- New: extend public bool load(RobustFormatter formatter) {

MhDebugSpaceViewerDialog changes

The build(Space space, bool in3D) method no longer takes in a symbol main argument, instead main is now stored as a field.

- Old: extend public void build(Space space, bool in3D) {
- New: extend public void build(Space space, bool in3D, symbol main) {
- New: public symbol main;

MhSnapper changes

Added filter to childrenShapeBound function so that we can choose what children we want to include.

public class MhSnapper extends Snapper {
- Old: extend public box childrenShapeBound(symbol[] symbols=null) {
- New: extend public box childrenShapeBound(symbol[] symbols=null, SnapperFilter filter=null) {

MhBayEditor and MhStorageConfigurator close dialog methods renamed

Rename function so its more specific to mh.

- Old: public void closeBayConfigurationDialog() {
- New: public void mhCloseBayConfigurationDialog() {
- Old: public void closeConfigurationDialog(symbol pkg=null) {
- New: public void mhCloseConfigurationDialog(symbol pkg=null) {

MhEngineCollisionEntry changes

Move few functions up to MhEngineEntryBase.

- Moved: extend public void ensureCollisionPrimitive() {
- Moved: extend public CollisionPrimitive getPrim() {
- Moved: extend public CollisionPrimitive setPrim(CollisionPrimitive v) {

Sorting of MhSnapper and MhEngineEntry

The sorting functionalities of collections of MhSnapper and MhEngineEntry of varying children and sibling relationships have been consolidated and modularised allowing for a deterministic engine operation (e.g. sorting of engine run functions) using the sorting piorities as follows:

  1. Presence of snapper.
  2. Descending child depth.
  3. Root parent position relative to space.
  4. Local position relative to root parent.
Added: private int mhPointXYZPosSort(point a, point b, Object env) {
Added: public int mhSnapperRootXYZPosSort(Snapper a, Snapper b, Object env) {
Added: public int mhSnapperFuncRunOrderSort(Snapper a, Snapper b, Object env) {
Added: public int mhEntryRootXYZPosSort(MhEngineEntry a, MhEngineEntry b, Object env) {
Added: public int mhEntryFuncRunOrderSort(MhEngineEntry a, MhEngineEntry b, Object env) {

MhConfigBehavior changes

The method autoAssignConfigName(MhConfigRef config) has been removed as it was not in use.

- Removed: extend public bool autoAssignConfigName(MhConfigRef config) : deprecated {

getAllChildrenIntersecting function changes

The function getAllChildrenIntersecting(Snapper snapper, Snapper targetSnapper, Snapper{} exceptTo=null) has been removed as it was redundant. Additionally, getAllChildrenIntersecting2(Snapper snapper, Snapper targetSnapper, bool trueIntersects=false, Snapper{} exceptTo=null) has been renamed to getAllChildrenIntersecting(Snapper snapper, Snapper targetSnapper, bool trueIntersects=false, Snapper{} exceptTo=null).

- Removed: public (Snapper{}) getAllChildrenIntersecting(Snapper snapper, Snapper targetSnapper, Snapper{} exceptTo=null) {
- Old: public (Snapper{}) getAllChildrenIntersecting2(Snapper snapper, Snapper targetSnapper, bool trueIntersects=false, Snapper{} exceptTo=null) {
- New: public (Snapper{}) getAllChildrenIntersecting(Snapper snapper, Snapper targetSnapper, bool trueIntersects=false, Snapper{} exceptTo=null) {

MhLevelParentEngineBehavior changes

The method addFloorLevel(MhSnapper snapper) has been removed.

public class MhLevelParentEngineBehavior extends MhEngineBehavior {
- Removed: extend public bool addFloorLevel(MhSnapper snapper) {

It was only used in the child class MhBayEngineBehavior. This functionality has been replaced to be looked up from the MhSnapperChangedEnv object passed in as an argument to engineFunctionArgs(MhSnapper snapper, MhEngineFunctionRun func, symbol event="", MhPreprocessArgsEnv preprocessArgs=null, Object env=null).

public class MhBayEngineBehavior extends MhLevelParentEngineBehavior {

Old:
    public str->Object engineFunctionArgs(MhSnapper snapper, MhEngineFunctionRun func, symbol event="", MhPreprocessArgsEnv preprocessArgs=null, Object env=null) {
        switch (func.name) {
          case "levelConstruction" : {
              return props { ...
                    addFloorLevel=addFloorLevel(snapper),
                    ...};
          }
    }

New:
    public str->Object engineFunctionArgs(MhSnapper snapper, MhEngineFunctionRun func, symbol event="", MhPreprocessArgsEnv preprocessArgs=null, Object env=null) {
        switch (func.name) {
          case "levelConstruction" : {
              MhSnapperChangedEnv changedEnv = env.MhSnapperChangedEnv;
              ?str->Object v = changedEnv.?value;
              ?Int levelCount = v.?get("noOfLevels");
              ?bool addFloorLevel = v.?get("addFloorLevel");
              
              return props { ...
                    addFloorLevel=addFloorLevel,
                    ...};
          }
    }

This allows the addFloorLevel value to be passed in from outside the engine behavior. One example of how to do this can be seen below.

public class MhBayInsertToolAnimation extends MhSnapperInsertToolAnimation {

    /**
     * Init
     */
    public void init(Snapper snapper) {
        ...
        bool addFloorLevel = false;
        Int levelCount = null;
        if (?MhStorageConfiguration config = main.?configuration) {
            addFloorLevel = config.addFloorLevel();
            if (Number n = config.noOfLevels()) levelCount = n.int;
        }

        MhSnapperChangedEnv changeEnv = main.snapperChangedEnv("bayInsert", v=props{addFloorLevel=addFloorLevel, noOfLevels=levelCount});
        main.validateBehaviors(sInitInsertAnimation, changeEnv);
        mhRunEngines(MhRunEngineEnv(blockImport=true, blockExport=true));
    }
}

cm.abstract.materialHandling.storage

Removed: public void mhFastImportAdjacentAisles(Snapper{} rowsToImport) {
Removed: public symbol getRailLayer(LayerSet classification) {
Old: public Window mhStorageConfigurationDialog() {
New: public Window mhStorageConfigurationDialog(symbol pkg) {
Old: public void mhStorageSetConfigurationDialog(MhStorageConfiguratorDialog dialog) {
New: public void mhStorageSetConfigurationDialog(symbol pkg, MhStorageConfiguratorDialog dialog) { 

Removed: public class MhBayEditorPreviewSpace extends MhBayEditorSpace {

public class MhStorageEditorDialog extends DialogWindow : abstract {
- Old: extend public bool shouldbuildSaveLoad() {
- New: extend public bool shouldBuildSaveLoad() {

public class MhStorageGfxSingleton extends MhStorageSingleton : abstract {
- Old: extend public str cache3DKey(MhSnapper owner, FetchEnv3D env) {
- New: extend public str cache3DKey(MhSnapper owner, FetchEnv3D env, str geomKey=null) {
- Old: extend public void appendCache3DKeyArgs(MhSnapper owner, FetchEnv3D env, Object[] args) {
- New: extend public void appendCache3DKeyArgs(MhSnapper owner, FetchEnv3D env, Object[] args, str geomKey=null) {
- Old: extend public Primitive3D get3D(MhSnapper owner, FetchEnv3D env) {
- New: extend public Primitive3D get3D(MhSnapper owner, FetchEnv3D env, str geomKey=null) {
- Old: extend public Primitive3D cachable3D(MhSnapper owner, FetchEnv3D env) : abstract {
- New: extend public Primitive3D cachable3D(MhSnapper owner, FetchEnv3D env, str geomKey=null) : abstract {

public class MhFrameGfxBehavior extends MhGenericGfxBehavior {
- Old: extend public Primitive3D uprightFoot3D(MhSnapper owner, FetchEnv3D env) {
- New: extend public Primitive3D uprightFoot3D(MhSnapper owner, FetchEnv3D env, str geomKey) {
- Old: extend public Primitive3D uprightCap3D(MhSnapper owner, FetchEnv3D env) {
- New: extend public Primitive3D uprightCap3D(MhSnapper owner, FetchEnv3D env, str geomKey) {
- Old: extend public Primitive3D vertical3D(MhSnapper owner, FetchEnv3D env) {
- New: extend public Primitive3D vertical3D(MhSnapper owner, FetchEnv3D env, str geomKey) {

public class MhStorageEditorConfiguration extends MhSystemConfiguration {
- New: extend public Window buildSpreadButtons(Window w, function(Control) callback) {
- New: extend public Animation spawnConfigSpreadAnimation(symbol s) {
- New: extend public void removeUnqualifiedRowChildren(MhSnapper row, MhSnapper{} newSnappers) {
- New: extend public MhSnapper{} qualifiedRowChildren(MhSnapper row, MhSnapper{} newSnappers) {
- New: extend public void resetTransform(MhSnapper[] rows) {

public class MhBayEditConfiguration extends MhStorageEditorConfiguration {
- Removed: extend public Window buildSpreadButtons(Window w, function(Control) callback) {
- Removed: extend public Animation spawnConfigSpreadAnimation(symbol s) {
- Removed: extend public void removeUnqualifiedRowChildren(MhSnapper row, MhSnapper{} newBays) {
- Removed: extend public MhSnapper{} qualifiedRowChildren(MhSnapper row, MhSnapper{} newBays) {
- Removed: extend public void resetTransform(MhSnapper[] rows) {

public class MhFrameEditConfiguration extends MhStorageEditorConfiguration {
- Removed: extend public Window buildSpreadButtons(Window w, function(Control) callback) {
- Removed: extend public Animation spawnConfigSpreadAnimation(symbol s) {
- Old: extend public void pickupFrames(Snapper{} snappers) {
- New: extend public void appendRefSnappers(Snapper{} snappers) {
- New: extend public void pickupFrames(MhSnapper{} snappers) {
- Old: extend public void removeUnusedFrames(Snapper{} snappers) {
- New: extend public void removeUnusedFrames(Snapper{} snappers, Snapper{} accepted=null) {

public class MhStorageEditorDialog extends DialogWindow : abstract {
- New: extend public function(Control) spreadButtonCallback() {

public class MhDrawRowREDBehavior extends MhBehavior {
- Removed: extend public void polyColorToRED(MhPolylineColor pc, Graph g, REDEnv2D lbEnv, REDDynamicLineEnv lineEnv) : deprecated {

public class MhLevelArrangeFunction extends MhSystemEngineFunction {
- Removed: extend public MhEngineEntry[] getPickAndDropEntries(MhEngine engine) {
- Removed: extend public void movePickAndDropEntry(MhEngineEntry main, double oldZ, MhEngineEntry[] pds) {

public class MhClearanceSpec extends CorePropObj {
- Added: extend public double loadToLoadClearanceZ(double elevation=0) {

Change argument type for isBeam classification checking method.

- Old: public bool isBeam(Snapper snapper) {
- New: public bool isBeam(Object o) { 

Added filter when calculating overhang.

- Old: public <double, double> mhRowUnitLoadOverhang(MhSnapper row) {
- New: public <double, double> mhRowUnitLoadOverhang(MhSnapper row, SnapperFilter filter=null) {

MhUnitLoadSpawner changes

Add unitLoadKey as an argument when creating entry collision primitive. This is so that we have more control of the unit load shape, not just getting the unit load shape from current configuration.

public class MhUnitLoadSpawner extends MhStorageSpawner {
- Old: extend public void appendAdditionalConstructionCollision(MhEngineConstructionEntry entry, LayerSet rootParentClassification) {
- New: extend public void appendAdditionalConstructionCollision(MhEngineConstructionEntry entry, str unitLoadKey, LayerSet rootParentClassification) {
- New: extend public MhEngineConstructionEntry engineConstructionEntry(str unitLoadKey) {

Added MhEntryLayoutEnv class

Introduce MhEntryLayoutEnv to wrap all necessary info for creating entry layout. So now we can just pass MhEntryLayoutEnv on entryLayout creation instead of having different methods with different arguments.

- New: public class MhEntryLayoutEnv {

public class MhSnapperSpawner extends SnapperSpawner {
- Old: extend public MhEntryLayout entryLayout(MhSystemSpawnerSelector ss, LayerSet rootParentClassification) {
- Old: extend public MhEntryLayout entryLayout(MhSystemSpawnerSelector ss) {
- New: extend public MhEntryLayout entryLayout(MhEntryLayoutEnv env) {

MhStorageGfxSingleton additional argument for geometry key

Methods for 3D graphics in MhStorageGfxSingleton have been updated to take in an optional str geomKey argument in an effort to help support building different graphics for specific geometries.

MhFrameGfxBehavior better support for different graphics based on geometries

MhFrameGfxBehavior has been made easier to build separate graphics for the front upright and the back upright.

We have updated existing 3D graphics methods to take in an optional str geomKey argument.

- Old: extend public Primitive3D uprightFoot3D(MhSnapper owner, FetchEnv3D env) {
- New: extend public Primitive3D uprightFoot3D(MhSnapper owner, FetchEnv3D env, str geomKey) {
- Old: extend public Primitive3D uprightCap3D(MhSnapper owner, FetchEnv3D env) {
- New: extend public Primitive3D uprightCap3D(MhSnapper owner, FetchEnv3D env, str geomKey) {
- Old: extend public Primitive3D vertical3D(MhSnapper owner, FetchEnv3D env) {
- New: extend public Primitive3D vertical3D(MhSnapper owner, FetchEnv3D env, str geomKey) {

The logic for building the frame graphics has also been modified. Previously it would build graphics for the front upright, and copy and transform it to represent the back upright. It will now separately build the graphics for the back upright.

Old:
    extend public Primitive3D frame3D(MhSnapper owner, FetchEnv3D env) {
        return cache3D(cacheKey3D(owner, env)) {
            const box b = owner.shapeBound([sUpright]);
            Primitive3D[] uprightPrims();
            Primitive3D vert = vertical3D(owner, env);
            uprightPrims << vert;
            uprightPrims << Instance3D(vert, 180deg, (b.w, b.d, 0));
            ...
            Primitive3D[] footPrims();
            Primitive3D foot = uprightFoot3D(owner, env);
            footPrims << mhInstance3D(foot, symTransform(owner, cUprightFootFront));
            footPrims << mhInstance3D(foot, symTransform(owner, cUprightFootBack));
            ...
            Primitive3D[] capPrims();
            Primitive3D cap = uprightCap3D(owner, env);
            capPrims << mhInstance3D(cap, symTransform(owner, cUprightFootFront));
            capPrims << mhInstance3D(cap, symTransform(owner, cUprightFootBack));
            ...
        };
    }

New:
    extend public Primitive3D frame3D(MhSnapper owner, FetchEnv3D env) {
        return cache3D(cacheKey3D(owner, env)) {
            const box b = owner.shapeBound([sUpright]);
            Primitive3D[] uprightPrims();
            Primitive3D frontVert = vertical3D(owner, env, cUprightFront);
            uprightPrims << frontVert;
            Primitive3D backVert = vertical3D(owner, env, cUprightBack);
            uprightPrims << Instance3D(backVert, 180deg, (b.w, b.d, 0));
            ...
            Primitive3D[] footPrims();
            Primitive3D frontFoot = uprightFoot3D(owner, env, cUprightFootFront);
            footPrims << mhInstance3D(frontFoot, symTransform(owner, cUprightFootFront));
            Primitive3D backFoot = uprightFoot3D(owner, env, cUprightFootBack);
            footPrims << mhInstance3D(backFoot, symTransform(owner, cUprightFootBack));
            ...
            Primitive3D[] capPrims();
            Primitive3D frontCap = uprightCap3D(owner, env, cUprightCapFront);
            Primitive3D backCap = uprightCap3D(owner, env, cUprightCapBack);
            capPrims << mhInstance3D(frontCap, symTransform(owner, cUprightFootFront));
            capPrims << mhInstance3D(backCap, symTransform(owner, cUprightFootBack));
            ...
        };
    }

It is also easier to override the singletons used for building upright graphics.

public class MhFrameGfxBehavior extends MhGenericGfxBehavior {

    /***********************************************************************
     * Singletons
     ***********************************************************************/

    /**
     * Get upright type.
     */
    extend public MhStorageUprightType getUprightType(MhFrameShape shape, str geomKey=null) {
        return shape.getUprightType();
    }


    /**
     * Get upright foot.
     */
    extend public MhStorageUprightFoot getUprightFoot(MhFrameShape shape, str geomKey=null) {
        return shape.getUprightFoot();
    }


    /**
     * Get upright cap.
     */
    extend public MhStorageUprightCap getUprightCap(MhFrameShape shape, str geomKey=null) {
        return shape.getUprightCap();
    }
}

Removed MhBayEditorPreviewSpace class

MhBayEditorPreviewSpace has been removed and its functionality of preventing snapper selections has been moved to the parent class MhBayEditorSpace as an optional feature. Set MhBayEditorSpace.blockEdit = true to block space selections.

public class MhBayEditorSpace extends MhStorageEditorSpace {

    /**
     * Select.
     */
    public void select(SpaceSelection s,
                       bool includeSnapped=false,
                       bool updatePropDlg=true,
                       bool undoable=false,
                       bool updateCameras=false) {
        if (blockEdit) s = null;
        ...
    }

MhStorageEditorConfiguration changes

Some methods have been moved down from MhBayEditConfiguration and MhFrameEditConfiguration.

public class MhStorageEditorConfiguration extends MhSystemConfiguration {
- New: extend public Window buildSpreadButtons(Window w, function(Control) callback) {
- New: extend public Animation spawnConfigSpreadAnimation(symbol s) {
- New: extend public void removeUnqualifiedRowChildren(MhSnapper row, MhSnapper{} newSnappers) {
- New: extend public MhSnapper{} qualifiedRowChildren(MhSnapper row, MhSnapper{} newSnappers) {
- New: extend public void resetTransform(MhSnapper[] rows) {
public class MhBayEditConfiguration extends MhStorageEditorConfiguration {
- Removed: extend public Window buildSpreadButtons(Window w, function(Control) callback) {
- Removed: extend public Animation spawnConfigSpreadAnimation(symbol s) {
- Removed: extend public void removeUnqualifiedRowChildren(MhSnapper row, MhSnapper{} newBays) {
- Removed: extend public MhSnapper{} qualifiedRowChildren(MhSnapper row, MhSnapper{} newBays) {
- Removed: extend public void resetTransform(MhSnapper[] rows) {
public class MhFrameEditConfiguration extends MhStorageEditorConfiguration {
- Removed: extend public Window buildSpreadButtons(Window w, function(Control) callback) {
- Removed: extend public Animation spawnConfigSpreadAnimation(symbol s) {

MhFrameEditConfiguration changes

The existing method pickupFrames(Snapper{} snappers) has been renamed to appendRefSnappers(Snapper{} snappers) which better fits the logic of this method. Replace all overrides and calls to the new method name.

public class MhFrameEditConfiguration extends MhStorageEditorConfiguration {
- Old: extend public void pickupFrames(Snapper{} snappers) {
- New: extend public void appendRefSnappers(Snapper{} snappers) {

A new method pickupFrames(MhSnapper{} snappers) has been introduced to generate copies of a set of snappers and put them into editor space, similarly to the existing MhBayEditConfiguration.pickupBays(MhSnapper{} snappers).

public class MhFrameEditConfiguration extends MhStorageEditorConfiguration {
- New: extend public void pickupFrames(MhSnapper{} snappers) {

Replace all overrides and calls to removeUnusedFrames(Snapper{} snappers) with removeUnusedFrames(Snapper{} snappers, Snapper{} accepted=null).

public class MhFrameEditConfiguration extends MhStorageEditorConfiguration {
- Old: extend public void removeUnusedFrames(Snapper{} snappers) {
- New: extend public void removeUnusedFrames(Snapper{} snappers, Snapper{} accepted=null) {

MhStorageEditorDialog changes

The method spreadButtonCallback() has been moved down from MhBayEditor and MhFrameEditor.

public class MhStorageEditorDialog extends DialogWindow : abstract {
- New: extend public function(Control) spreadButtonCallback() {

MhStorageEditorConfiguration and MhStorageEditorItem changes

When pushing properties to preview snappers, we now add the property that trigger this event as part of the argument.

public class MhStorageEditorConfiguration extends MhSystemConfiguration {
- Old: extend public void pushPropToPreview(Space space, MhStorageEditorItem item) {
- New: extend public void pushPropToPreview(Space space, MhStorageEditorItem item, CoreProperty property=null) {

public class MhStorageEditorItem extends MhSystemConfigurationItem : abstract {
- Old: extend public MhSnapper{} applySnappers(Space space) {
- New: extend public MhSnapper{} applySnappers(Space space, CoreProperty property=null) {

MhRowChildStealConfigFunction changes

Instead of assuming that there will only be 1 child at 1 z position, now this children map stores an array of children per 1 z positon.

public class MhRowChildStealConfigFunction extends MhSystemEngineFunction {
- Old: private double->MhEngineEntry children;
- New: private double->MhEngineEntry[] children;

MhAisleUpdateWidthFunction changes

As we change some calculations for overhang, we rename some functions to better suit their purposes.

public class MhAisleUpdateWidthFunction extends MhSystemEngineFunction {
- Old: extend public box unmodifedBoundIncludingChildren(MhEngineBoxEntry entry, Transform t, MhEngine engine, LayerSet ls=null) {
- New: extend public box unmodifiedOverhangLocalBound(MhEngineBoxEntry entry, Transform t, MhEngine engine, LayerSet ls=null) {
- Old: extend public box localBoundIncludingChildren(MhEngineEntry entry, Transform t, MhEngine engine, LayerSet ls=null) {
- New: extend public bool shouldIncludeChildrenBound(MhEngineEntry entry) {

MhStorageConfigurator changes.

Instead of only having one dialog at a time, now we can have multiple dialogs with package as the key.

- Old: private DialogWindow _dialog : keep;
- New: private symbol->DialogWindow _dialogs : keep;

We have updated the following functions to take in a symbol pkg argument.

Old: public Window mhStorageConfigurationDialog() {
New: public Window mhStorageConfigurationDialog(symbol pkg) {
Old: public void mhStorageSetConfigurationDialog(MhStorageConfiguratorDialog dialog) {
New: public void mhStorageSetConfigurationDialog(symbol pkg, MhStorageConfiguratorDialog dialog) { 

All buttons (add, duplicate, delete, rename, import, export) are moved to a menubar.

public class MhStorageConfiguratorDialog extends DialogWindow {
- Removed: public Button addBtn;
- Removed: public Button duplicateBtn;
- Removed: public Button deleteBtn;
- Removed: public Button renameBtn;
- Removed: public Button importBtn;
- Removed: public Button exportBtn;
- Removed: extend public void buildButtons(Window w) {
- Added: extend public void buildMenuBar(MenuBar menuBar) {

- New: public class MhConfiguratorCoolMenuBar extends FaceliftMenuBar {

MhPrimPopulatorStepper and MhEngineEntryPopulatorStepper

Introduce new field alwaysResolve to control when the populator should be resolving or skip the resolver if it's not colliding.

- Old: public constructor(CollisionPrimitive startPrim, CollisionPrimitive endPrim=null, CollisionPrimitive additionalPrim=null, bool useFixedStep=false) {
- New: public constructor(CollisionPrimitive startPrim, CollisionPrimitive endPrim=null, CollisionPrimitive additionalPrim=null, bool useFixedStep=false, bool alwaysResolve=true) {

Removed public functions

The function mhFastImportAdjacentAisles(Snapper{} rowsToImport) has been removed. Its functionality has been moved into MhAisleFastImportBehavior.fastImportAdjacentAisles(Snapper{} rowsToImport).

Removed: public void mhFastImportAdjacentAisles(Snapper{} rowsToImport) {

public class MhAisleFastImportBehavior extends MhBehavior {

    /**
     * Run fast import on adjacent aisle to get the loadToLoad gap prop.
     */
    extend public void fastImportAdjacentAisles(Snapper{} rowsToImport) {
        if (rowsToImport.empty) return;
        
        MhSnapper{} visited(rowsToImport.count);
        for (MhSnapper row in rowsToImport) {
            if (row in visited or !isRow(row) or isAisle(row)) continue;
            for (r in getConnectedRows(row)) {
                if (r in visited) continue;
                mhFastImportToEngine(r);
                visited << r;
            }
        }
    }
}

The function getRailLayer(LayerSet classification) has been removed as it was not used.

Removed: public symbol getRailLayer(LayerSet classification) {

MhDrawRowREDBehavior changes

The deprecated method polyColorToRED(MhPolylineColor pc, Graph g, REDEnv2D lbEnv, REDDynamicLineEnv lineEnv) has been removed. Use polyColorToRED(MhPolylineColor pc, Graph g, REDLayerBuffer2D lb, REDEnv2D lbEnv, REDDynamicLineEnv lineEnv) instead.

- Removed: extend public void polyColorToRED(MhPolylineColor pc, Graph g, REDEnv2D lbEnv, REDDynamicLineEnv lineEnv) : deprecated {

MhLevelArrangeFunction changes

The following methods getPickAndDropEntries(MhEngine engine) and movePickAndDropEntry(MhEngineEntry main, double oldZ, MhEngineEntry[] pds) have been removed as they are no longer needed.

- Removed: extend public MhEngineEntry[] getPickAndDropEntries(MhEngine engine) {
- Removed: extend public void movePickAndDropEntry(MhEngineEntry main, double oldZ, MhEngineEntry[] pds) {

cm.abstract.materialHandling.storage.racking

public class MhSpacerPopulateFunction extends MhSystemEngineFunction {
- Added: extend public bool allowNewSpacer(double depth) {

cm.abstract.materialHandling.storage.racking.deepstorage

MhDeepstorageUnitLoadConstructionalPopulateFunction changes

The following method noOfUnitLoads() has been removed and replaced with MhUnitLoadConstructionalPopulateFunction.loadCount. We have also added a new field MhDeepstorageUnitLoadConstructionalPopulateFunction.noOfUnitLoadsInDepth. loadCount will populate loads along the x-axis, and noOfUnitLoadsInDepth will populate loads along the y-axis.

Old:
/**
 * Deep storage unit load constructional populate function.
 */
public class MhDeepstorageUnitLoadConstructionalPopulateFunction extends MhUnitLoadConstructionalPopulateFunction {
    /**
     * Number of unit loads.
     */
    extend public int noOfUnitLoads() {
        return configuration.getValue(cMhNoOfUnitLoadsPK).int;
    }
}


New:
/**
 * Unit load constructional populate.
 */
public class MhUnitLoadConstructionalPopulateFunction extends MhSystemEngineFunction {
    /**
     * Unit load depth count.
     * Load row count perpendicular to populate vector.
     */
    public Int loadCount;
}


New:
/**
 * Deep storage unit load constructional populate function.
 */
public class MhDeepstorageUnitLoadConstructionalPopulateFunction extends MhUnitLoadConstructionalPopulateFunction {
    /**
     * No of unit loads in depth.
     */
    public Int noOfUnitLoadsInDepth;
}

Any previous calls to noOfUnitLoads() should be replaced with loadCount.

/**
 * Deep storage unit load constructional populate function.
 */
public class MhDeepstorageUnitLoadConstructionalPopulateFunction extends MhUnitLoadConstructionalPopulateFunction {

Old:
    /**
     * BedWidhts
     */
    extend public double[] bedWidths(MhSystemEngineEnvironment env) {
        double segment = firstBedWidth();
        int unitLoadCount = noOfUnitLoads();

        double[] bedWidths();
        while (unitLoadCount > 0) {
            bedWidths << segment;
            unitLoadCount--;
        }

        return bedWidths;
    }
}


New:
    /**
     * BedWidhts
     */
    extend public double[] bedWidths(MhSystemEngineEnvironment env) {
        double segment = firstBedWidth();
        int unitLoadCount = loadCount.?v;

        double[] bedWidths();
        while (unitLoadCount > 0) {
            bedWidths << segment;
            unitLoadCount--;
        }

        return bedWidths;
    }
}

To maintain your existing workflow, you will need to pass the desired value in as an argument for this function. It is typically executed from a levelConstruction function as shown below.

/**
 * Level Populate engine. Used to populate additional levels from existing ones.
 */
public class MhLevelPopulateFunction extends MhSystemEngineFunction {
    /**
     * levelChildContruction
     */
    extend public void levelChildConstruction(MhEngineConstructionEntry entry) {
        if (?MhStorageConfiguration configuration = configuration) {
            ...
            int loadCount = configuration.unitLoadCountY();
            engine.exec("unitLoadConstruction", config=configuration,
                        ...
                        loadCount=loadCount,
                        directModify=true);
        }
    }
}

The new field noOfUnitLoadsInDepth is now used to control the number of unit loads populated depth-wise. The previous behavior was that it would populate loads until there was no more space to fit unit loads.

/**
 * Deep storage unit load constructional populate function.
 */
public class MhDeepstorageUnitLoadConstructionalPopulateFunction extends MhUnitLoadConstructionalPopulateFunction {

Old:
    /**
     * Add unit loads.
     */
    public void addUnitLoads() {
        ...
            while (populator.step(defaultEntry)) {
                ?MhEngineConstructionEntry entry = copy(defaultEntry);
                entry.move(populator.currentPos, update=update);
                childEntries << entry;
            }
        ...
    }

New:
    /**
     * Add unit loads.
     */
    public void addUnitLoads() {
        ...
            for (i in range(noOfUnitLoadsInDepth.?v)) {
                populator.step(defaultEntry);
                ?MhEngineConstructionEntry entry = copy(defaultEntry);
                entry.move(populator.currentPos, update=update);
                childEntries << entry;
            }
        ...
    }
}

You will now need to pass in a value for this field. Similarly to loadCount, it is also usually passed in from a levelConstruction function.

    /**
     * levelChildConstruction
     */
    public void levelChildConstruction(MhEngineConstructionEntry entry) {
        ...
	    engine.exec("unitLoadConstruction", config=configuration,
			...
			loadCount=loadCount,
			noOfUnitLoadsInDepth=noOfUnitLoadsInDepth,
			directModify=true);
        ...
    }

MhDeepstorageUnitLoadPopulateFunction changes

The following methods have been removed from this class:

/**
 * Unit load Populate engine.
 */
public class MhDeepstorageUnitLoadPopulateFunction extends MhUnitLoadPopulateFunction {
    /**
     * BedWidths
     */
    extend public double[] bedWidths(MhSystemEngineEnvironment env, MhEngineEntry edit) {
        ?double[] bedWidths = env.?getProp(edit.snapper, mhRollerBedWidthKey);
        if (bedWidths.empty) {
            init bedWidths();
            bedWidths << edit.w; //return super(..);
        } else {
            double[] newWidths();
            double div = edit.w/bedWidths.count;
            for (i in 1..bedWidths.count) {
                newWidths << div;
            }
            return newWidths;
        }

        return bedWidths;
    }


    /**
     * Easy populate loads.
     */
    public void easyPopulateLoads(MhEngineEntry edit, MhEngineEntry[] imported,
                                  MhEngineEntry[] children, MhPopulator populator,
                                  MhSystemEngineEnvironment env) {
        double[] bedWidths = bedWidths(env, edit);
        MhBedEngineEntryHolder[] beds = divideImportedInBeds(imported, reverse.?v);
        easyPopulateBeds(edit, imported, children, populator, env, bedWidths, beds);
    }


    /**
     * Easy populate beds.
     */
    extend public void easyPopulateBeds(MhEngineEntry edit, MhEngineEntry[] imported, MhEngineEntry[] children, MhPopulator populator, MhSystemEngineEnvironment env, double[] bedWidths, MhBedEngineEntryHolder[] beds) {
        point startPos = populator.currentPos;

        MhEngineSnapperEntry lastEntry;
        for (bedWidth in bedWidths, index=i) {
            if (!first) {
                populator.currentPos = nextPopulatorPos(edit, startPos, (bedWidths[i-1] + bedWidth)/2, env);
                if (populator as MhStepperPopulator) populator.currentStep = null;
                startPos = populator.currentPos;
            }

            range bedXRange(startPos.x-bedWidth/2, startPos.x+bedWidth/2);

            if (MhBedEngineEntryHolder bed = getValidBedEntryHolder(beds, bedXRange)) {
                beds.exclude(bed);
                for (MhEngineSnapperEntry entry in bed.list, reverse=reverse.?v) {
                    if (populator.step(entry)) {
                        MhEngineConstructionEntry newEntry = entry.toConstructionEntry();
                        if (entry as MhEngineConstructionEntry) newEntry.parent = entry.parent;

                        if (reverse.?v) {
                            point reversedPos =
                              (populator.currentPos.x, edit.d-populator.currentPos.y, populator.currentPos.z);
                            newEntry.move(reversedPos - entry.pos);
                        } else {
                            newEntry.move(populator.currentPos - entry.pos);
                        }

                        children.insert(children.indexOf(entry), newEntry);
                        children.exclude(entry);
                        lastEntry = newEntry;
                    } else {
                        children.exclude(entry);
                        lastEntry = null;
                    }
                }
            }

            if (lastEntry and populateMoreLoads) {
                while (populator.step(lastEntry)) {
                    MhEngineConstructionEntry e = lastEntry.?toConstructionEntry();
                    if (reverse.?v) {
                        point reversedPos =
                          (populator.currentPos.x, edit.d-populator.currentPos.y, populator.currentPos.z);
                        e.move(reversedPos - e.pos);
                    } else {
                        e.move(populator.currentPos - e.pos);
                    }

                    if (reverse.?v) {
                        children.insert(0, e);
                    } else {
                        children << e;
                    }
                }
            }
        }
    }


    /**
     * GetValidBedEntryHolder
     */
    extend public MhBedEngineEntryHolder getValidBedEntryHolder(MhBedEngineEntryHolder[] holders, range xRange) {
        if (holders.any) return holders.first;
        /* CUT THIS OUT  Mon Jan 16 08:19:08 2023 /danan
        for (holder in holders) {
            if (holder.insideBed(xRange)) return holder;
        }
        * CUT THIS OUT /danan */
        return null;
    }


    /**
     * Next populator pos.
     */
    extend public point nextPopulatorPos(MhEngineEntry edit, point startPos, double bedWidth, MhSystemEngineEnvironment env) {
        return startPos + (bedWidth, 0, 0);
    }
}

The above methods and override of easyPopulateLoads() were so that unit loads could be populated depth-wise for multiple "segments" that made up a bay. They are no longer required as we introduced MhUnitLoadArrangement which is able to handle populating unit loads in multiple directions.

If you have overridden this function and added more functionality in it, you could look into now overridding the MhUnitLoadArrangement used by this function and re-implementing your custom functionality there.

Alternatively you can return null for unitLoadArrangement() so that easyPopulateLoads() will be used again, and you can re-introduce the above removed methods into your custom function.

cm.abstract.office

SIF exporters

SIF exporters have been moved to cm.abstract.sif

Old: public str aoSifExportEOL() // in cm.abstract.office
New: public str aSifExportEOL()  // in cm.abstract.sif

Old: public class AOSifExport extends ASifExport : deprecated {} // in cm.abstract.office
New: public class ASifExport extends TextExporter                // in cm.abstract.sif

cm.abstract.unitLoad

Rename getter of unitLoadDialog pos.

- Old: public pointI getLastDialogPos() {
- New: public pointI unitLoadGetLastDialogPos() {

Remove unused method setLinkedDims(str k) of class UnitLoadCarton.

public class UnitLoadCarton extends UnitLoad : abstract {
- Removed: extend public void setLinkedDims(str k) {}

Remove deprecated methods innerBoards3D(Object owner, FetchEnv3D env) and board3D(Object owner, FetchEnv3D env, double w) of class UnitLoadPallet.

Use the methods innerBoards3D(Object owner, FetchEnv3D env, double th) and deckboard3D(Object owner, FetchEnv3D env, double w, double th) instead.

public class UnitLoadPallet extends UnitLoad : abstract {
- Removed: extend public Primitive3D innerBoards3D(Object owner, FetchEnv3D env) : deprecated {
- Removed: extend public Primitive3D board3D(Object owner, FetchEnv3D env, double w) : deprecated {

Removed unused class UnitLoadVessel.

- Removed: public class UnitLoadVessel extends Vessel {

cm.abstract.wardrobe

class WaWallSurfaceAlignPATCH

Removed: final public point rectoskopi(GFacePrimitive owner, point localP, bool turnBitch) {

cm.application

The following deprecated functions have been removed:

public void initSpecMenuDisplay(MenuBar menuBar) {}
public void destroySpecMenuDisplay() {}

cm.core

The following function has been removed. Replace any usage of it with easyLoad(url).?ViewMode.

Removed: public ViewMode loadCustomViewMode(Url url) {

The following function has been removed as it is no longer used in the base repository. If it is still used, consider making a local copy of the function in the affected extension.

Removed: public ViewMode fixPartTagInViewMode(ViewMode vm) {

The functions breakAllConnections(Snapper this, Snapper{} exceptTo=null) and breakConnectionsTo(Snapper this, Snapper b) are now methods in Snapper. This allows them to be overridable.

public class Snapper extends Entity {

    /***********************************************************************
     * Break connections
     ***********************************************************************/

    /**
     * Disconnect all connections in this snapper, except those
     * who are attached to a snapper in 'exceptTo'.
     */
    extend public void breakAllConnections(Snapper{} exceptTo=null) {
        ...
    }


    /**
     * Disconnect the direct connections between this and 'b'.
     */
    extend public void breakConnectionsTo(Snapper b) {
        ...
    }
}

CoreSchemes and GroupSchemes End of Life

As part of the EOL effort, these classes or functions have been moved to cm-unmaintained. They will no longer receive bugfixes or be shipped as part of CET core builds, and you will no longer be able to reference these classes in your packages.

Please note that most of these classes are user interface related classes that were not (and should not) be streamed, specifically the scheme builders, configurators, and user interface builders. However, we retained data structures in Core that are streamed as part of the drawing for old drawing load reasons, however please perform relevant testing to ensure that it works as expected.

For developers unable to move to PropsSchemes in time, you can copy these deprecated classes into your own codebase or packages as a temporary workaround / mitigation. However, we encourage you to plan for a migration to PropsScheme as soon as possible.

# cm.abstract.industry.mobileShelving
- package class MConfigurator extends PropObjConfigurator

# cm.abstract.tools
- public PropObjConfigurator getPropObjConfigurator()
- package class PropObjConfigurator extends DialogWindow
- package class PropObjTreeViewItem extends TreeViewItem
- package class PropObj1TreeViewItem extends PropObjTreeViewItem 
- package class PropObjConfWindow extends CoreSchemeWindow 

# cm.abstract.wardrobe
- package class WardrobeConfigurator extends PropObjConfigurator : abstract 
- public void setWardrobeConfigurator(WardrobeConfigurator configurator) 
- public void setWardrobeConfiguratorScheme(Window parent, bool default, WardrobeScheme scheme, bool lazy=false)
- public void initWardrobeHooks() 

# cm.abstract.dataSymbol
- public class DsSchemeBuilder extends CoreSchemeBuilder 
- public class DsSchemeBuilder extends CoreSchemeBuilder 
- public class DsMatSchemeProp extends DsMaterialSchemeProperty
- public class DsPDataSchemePropDef extends SchemePropDef
- public str stringify(str[] list, str delimiter=";") {

# cm.abstract.material
- public class AbsMatCoreSchemeBuilder extends CoreSchemeBuilder 

cm.core.library

Library

The following field has been removed from Library.

Removed: public int uiVersion;

The following global variables / functions have been removed.

Removed: public bool ui9MasterEnable;
Removed: public void setDynamicUi(bool setDynamic) : deprecated {}
Removed: public bool coolToolboxFrames() { return true; }

Deprecated: public void formatToolboxUI9(Library lib) : deprecated {}

class LibraryLimb

Old: public constructor(symbol pkg, str key, Image image=null, bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null, SectionButton[] buttons=null, UIHint hint=null, SrcRef src=null)
New: public constructor(symbol pkg, str key, LibraryLimbVisibility vs=null, Image image=null,            // LibraryLimbVisibility vs is new
                        bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null,
                        SectionButton[] buttons=null, UIHint hint=null, bool hideSendToButton=false,     // bool hideSendToButton is new
                        SrcRef src=#:src)

Old: public constructor(LibraryLimb parent, symbol pkg, str key, LibraryLimbVisibility vs=null, Image image=null,
                        bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null,
                        SectionButton[] buttons=null, UIHint hint=null, SrcRef src=null)
New: public constructor(LibraryLimb parent,
                        symbol pkg, str key, LibraryLimbVisibility vs=null, Image image=null,
                        bool frame=true, str label=null, str toolTipText=null, Image toolTipImage=null,
                        SectionButton[] buttons=null, UIHint hint=null, bool hideSendToButton=false,     // bool hideSendToButton is new
                        SrcRef src=#:src)

class SubSectionLimb

Old: public constructor(LibraryLimb parent, symbol pkg, str key, LibraryLimbVisibility vs=null, UIHint hint=null, SrcRef src=#:src) 
New: public constructor(LibraryLimb parent,
                        symbol pkg, str key, LibraryLimbVisibility vs=null, str label=null,   // str label is new
                        UIHint hint=null, bool drawLine=false, SrcRef src=#:src)

class SnapperLimb

Old: public constructor(LibraryLimb parent, symbol pkg, str key,
                        UIHint hint=null,
                        LibraryLimbVisibility vs=null,
                        Image image=null,
                        str label=null,
                        str toolTipText=null,
                        Image toolTipImage=null,
                        bool keywordHidden=false,
                        str->Object initProps=null,
                        str->Object applyProps=null,
                        SnapperSpawner spawner=null,
                        SrcRef src=#:src)
New: public constructor(LibraryLimb parent, symbol pkg, str key,
                        UIHint hint=null,
                        LibraryLimbVisibility vs=null,
                        Image image=null,
                        str label=null,
                        str toolTipText=null,
                        Image toolTipImage=null,
                        bool keywordHidden=false,
                        str->Object initProps=null,
                        str->Object applyProps=null,
                        SnapperSpawner spawner=null,
                        bool skipRenderImage=false,  // New argument
                        SrcRef src=#:src)

class AnimationLimb

Old: public constructor(LibraryLimb parent, symbol pkg, str key,
                        UIHint hint=null,
                        LibraryLimbVisibility vs=null,
                        Image image=null,
                        str label=null,
                        str toolTipText=null,
                        Image toolTipImage=null,
                        bool keywordHidden=false,
                        str->Object initProps=null,
                        str->Object applyProps=null,
                        AnimationSpawner spawner=null,
                        SrcRef src=#:src)
New: public constructor(LibraryLimb parent, symbol pkg, str key,
                        UIHint hint=null,
                        LibraryLimbVisibility vs=null,
                        Image image=null,
                        str label=null,
                        str toolTipText=null,
                        Image toolTipImage=null,
                        bool keywordHidden=false,
                        str->Object initProps=null,
                        str->Object applyProps=null,
                        bool skipRenderImage=false,  // New argument
                        AnimationSpawner spawner=null,
                        SrcRef src=#:src)

class HeaderLimb

Old: public constructor(LibraryLimb parent, symbol pkg, str key,
                        LibraryLimbVisibility vs=null,
                        Font font=boldSystemFont,
                        alignment align=middle,
                        bool extendRight=false,
                        Image image=null,
                        bool compact=false,
                        PointI margins=null,
                        color labelColor=color(0),
                        SrcRef src=#:src)
New: public constructor(LibraryLimb parent, symbol pkg, str key,
                        LibraryLimbVisibility vs=null,
                        Font font=boldSystemFont,
                        alignment align=middle,
                        bool extendRight=false,
                        Image image=null,
                        bool compact=false,
                        PointI margins=null,
                        str forceText=null,       // New argument
                        color labelColor=color(0),
                        SrcRef src=#:src)

class VoidCallbackLimb

Old: public constructor(LibraryLimb parent, symbol pkg, str key,
                        UIHint hint=null, LibraryLimbVisibility vs=null,
                        Image image=null,
                        function() callback=null,
                        Image toolTipImage=null,
                        str label=null,
                        SrcRef src=#:src)
New: public constructor(LibraryLimb parent, symbol pkg, str key,
                        UIHint hint=null, LibraryLimbVisibility vs=null,
                        Image image=null,
                        function() callback=null,
                        Image toolTipImage=null,
                        str label=null,
                        str toolTipText=null,
                        SrcRef src=#:src)

class LibraryHeaderBuilder

Old: extend public Window build(Window parent) { return null; }
New: extend public Window build(Window parent, Library library) { return null; }

class BasicLibraryHeaderBuilder

Old: public constructor(Image icon, str title) {}
New: public constructor(Image icon, str title, str schemeKey=null) {}

UI Hints

As part of hint changes made for the new UI Toolbox Guidelines, the largeButtonHint is now removed:

Old: public const UIImageHint largeButtonHint;
New: public const UIImageHint productButtonMediumWithLabel;

As a result of some clean up work, the following global has been made constant:

Old: public UIHelpImageHint uiHelpImageHint();
New: public const UIHelpImageHint uiHelpImageHint();

UIBrushHoverHint has its sized field removed:

Old: public sizeI size;
New: public sizeI preferSize;
New final public sizeI safePreferSize();

cm.core.red3D

old: final public REDRenderJob renderJob()
new: final public RenderJob renderJob()

old: extend public void renderAppend(REDRenderJob job)
new: extend public void renderAppend(RenderJob job)

old: extend public void renderBegin(REDRenderJob job)
new: extend public void renderBegin(RenderJob job)

old: extend public void renderProgress(REDRenderJob job)
new: extend public void renderProgress(RenderJob job)

old: extend public void renderProgressionImage(REDRenderJob job)
new: extend public void renderProgressionImage(RenderJob job)

old: extend public void renderFrame(REDRenderJob job, int frameNumber)
new: extend public void renderFrame(RenderJob job, int frameNumber)

old: extend public void renderEnd(REDRenderJob job)
new: extend public void renderEnd(RenderJob job)

old: final private void cleanupREDTempFile(REDRenderJob job)
new: final private void cleanupREDTempFile(RenderJob job)

cm.core.red3D.distributed

Old: extend public void add(REDRenderJob job, int[] frames) : abstract {}
New: extend public void add(RenderJob job, int[] frames) : abstract {}
old: package REDRenderJob job;
new: public RenderJob job;

old: public constructor(RenderResource resource, REDRenderJob job, int[] frames, str[] specs)
new: public constructor(RenderResource resource, RenderJob job, int[] frames, str[] specs)
old: public void renderBegin(REDRenderJob job)
new: public void renderBegin(RenderJob job)

old: public void renderProgress(REDRenderJob job)
new: public void renderProgress(RenderJob job)

old: public void renderEnd(REDRenderJob job)
new: public void renderEnd(RenderJob job)

the removed code have been move to the parent class RenderJob.

Removed: public str guid;

Removed: private Url snapshotUrl : public readable;

Removed: private ImageWithDepthData progressionImage;

Removed: public Space workingSpace;

Removed: public REDRenderFrame[] frames();

Removed: public bool isPreview;

Removed: public bool isGhost;

Removed: public bool isHLOverlay;

Removed: public bool isPanorama360;
    
Removed: private int->RenderOutputFrame outputFrames() : public readable;

Removed: private jobState jobstate = jobState.rendering : public readable;

Removed: public REDRenderJobEnv env;

Removed: public Photo photo;

Removed: package jobPriority priority = jobPriority.normal : public readable;

Removed: package int order = 0;

Removed: public str name;

Removed: public RenderResource{} resources;

Removed: final package void addResource(RenderResource res) 

Removed: final package void removeResource(RenderResource res)

Removed: final package void kill()

Removed: final private RenderOutputFrame getOutputFrame(REDRenderFrame frame)

Removed: final public bool valid(REDRenderResult renderResult)

New: public str progressbarText(str progressText, int progressTextOffset)

New: public bool isTransferring() { return jobTransferred; }

New: public bool isQueued() { return false; }
New: public str guid;

New: public str name

New: public REDRenderJobEnv env

New: public Photo photo;

New: public jobState jobstate

New: public jobPriority priority

New: public REDRenderFrame[] frames

New: final public void addResource(RenderResource res)

New: final public void removeResource(RenderResource res)

New: public int->RenderOutputFrame outputFrames

New: public bool isPreview;

New: public bool isGhost;

New: public bool isHLOverlay;

New: public bool isPanorama360;

New: public Space workingSpace;

New: public RenderResource{} resources;

New: public float progress() : abstract

New: public void setProgress(float progress)

New: public void process() : abstract

New: public void abortRender()

New: public void kill()

New: public void processPanoramaImages() : abstract 

New: public Url imageUrl(int frameNumber=0) : abstract

New: public Url progressionImageUrl() : abstract

New: public Url snapshotUrl() : abstract

New: public RenderOutputFrame getOutputFrame(REDRenderFrame frame)

New: public RenderOutputFrame getOutputFrame(OutputTile outputTile)

New: public RenderOutputFrame getOutputFrame(int frameIndex)

New: public void renderUpdate(REDRenderResult renderResult) : abstract 

New: public int unscheduledFrameCount(int upto=maxInt)

New: public int[] unscheduledFrames(int upto)

New: public void framesScheduled(int[] scheduled)

New: public void framesDone(int[] done) : abstract

New: public void setJobState(jobState newState)

New: public bool valid(REDRenderResult renderResult)

New: public str progressbarText(str progressText, int progressTextOffset) 

New: public bool isTransferring()

New: public bool isQueued()

New: public bool inProgress() : abstract

New: public bool completed() 

New: public bool aborted() 

New: public bool failed() 

New: public bool visible() : abstract
old: public void add(REDRenderJob job, int[] frames)
new: public void add(RenderJob job, int[] frames) 
old: public REDRenderJob->REDRenderJobItem map()
new: public RenderJob->REDRenderJobItem map()

old: final public void updateJobProgression(REDRenderJob job)
new: final public void updateJobProgression(RenderJob job)

old: final public void add(REDRenderJob job, bool replace=true)
new: final public void add(RenderJob job, bool replace=true)

old: final public void removeJob(REDRenderJob job)
new: final public void removeJob(RenderJob job)

old: final public void fillProgression(REDRenderJob job)
new: final public void fillProgression(RenderJob job)

old: final public void fillProgressionIfSelected(REDRenderJob job)
new: final public void fillProgressionIfSelected(RenderJob job)

old: final public REDRenderJob selectedJob()
new: final public RenderJob selectedJob()

cm.core.red3D.distributed.redRenderJob

the removed code have been move to the parent class RenderJob.

Removed: public str guid;

Removed: private Url snapshotUrl : public readable;

Removed: private ImageWithDepthData progressionImage;

Removed: public Space workingSpace;

Removed: public REDRenderFrame[] frames();

Removed: public bool isPreview;

Removed: public bool isGhost;

Removed: public bool isHLOverlay;

Removed: public bool isPanorama360;
    
Removed: private int->RenderOutputFrame outputFrames() : public readable;

Removed: private jobState jobstate = jobState.rendering : public readable;

Removed: public REDRenderJobEnv env;

Removed: public Photo photo;

Removed: package jobPriority priority = jobPriority.normal : public readable;

Removed: package int order = 0;

Removed: public str name;

Removed: public RenderResource{} resources;

Removed: final package void addResource(RenderResource res) 

Removed: final package void removeResource(RenderResource res)

Removed: final package void kill()

Removed: final private RenderOutputFrame getOutputFrame(REDRenderFrame frame)

Removed: final public bool valid(REDRenderResult renderResult)

New : public str progressbarText(str progressText, int progressTextOffset)

New : public bool isTransferring() { return jobTransferred; }

New : public bool isQueued() { return false; }

cm.core.toolbox

class LazyBasicSnapperButton

Removed: public Margins margins;
Replacement: final public Margins margins()
Replacement: public void setMargins(int left, int upper, int right, int lower)
Replacement: public void setMargins(pointI p)
Replacement: public void setMargins(int x, int y)
Replacement: public void setMargins(int m)

Old: public constructor(Window parent,
                        // inherited key arguments
                        Font font=controlFont,
                        Brush brush=null,
                        FrameStyle frameStyle=selectButtonFrame,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control control) callback=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        // extends arguments
                        alignment textSide=undefinedAlignment,
                        symbol snapperPkg=null,
                        str snapperName=null,
                        Image image=null,
                        str c3CatalogId=null,
                        SnapperSpawner snapperSpawner=null,
                        AnimationSpawner animationSpawner=null,
                        SrcRef src=#:src)
New: public constructor(Window parent,
                        // inherited key arguments
                        Font font=controlFont,
                        Brush brush=null,
                        FrameStyle frameStyle=selectButtonFrame,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control control) callback=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        // extends arguments
                        alignment textSide=undefinedAlignment,
                        symbol snapperPkg=null,
                        str snapperName=null,
                        Image image=null,
                        str c3CatalogId=null,
                        SnapperSpawner snapperSpawner=null,
                        AnimationSpawner animationSpawner=null,
                        bool facelift=false,      // New argument
                        SrcRef src=#:src)

class LazySnapper3DButton

Old: public constructor(Window parent,
                        // inherited key arguments
                        Font font=controlFont,
                        Brush brush=null,
                        FrameStyle frameStyle=selectButtonFrame,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control control) callback=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        alignment textSide=undefinedAlignment,
                        symbol snapperPkg=null,
                        str snapperName=null,
                        str c3CatalogId=null,
                        // extends arguments
                        bool forceRender=false,
                        sizeI outputSize=(60, 60),
                        double distScale=1,
                        liRenderLevel level=liFull,
                        SnapperSpawner snapperSpawner=null,
                        AnimationSpawner animationSpawner=null,
                        SrcRef src=#:src)
New: public constructor(Window parent,
                        // inherited key arguments
                        Font font=controlFont,
                        Brush brush=null,
                        FrameStyle frameStyle=selectButtonFrame,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(-1, -1),
                        pointI margins=(2, 2),
                        alignment align=up,
                        ControlGroup group=null,
                        function (Control control) callback=null,
                        str label=null,
                        color labelColor=color(0, 0, 0),
                        bool threeState=false,
                        alignment textSide=undefinedAlignment,
                        symbol snapperPkg=null,
                        str snapperName=null,
                        str c3CatalogId=null,
                        // extends arguments
                        bool forceRender=false,
                        sizeI outputSize=(60, 60),
                        double distScale=1,
                        liRenderLevel level=liFull,
                        SnapperSpawner snapperSpawner=null,
                        AnimationSpawner animationSpawner=null,
                        bool facelift=false,      // New argument
                        SrcRef src=#:src) {

class Toolbox

Old: public constructor(Window parent,
                            Font font=systemFont(),
                            Brush brush=null,
                            FrameStyle frameStyle=null,
                            frame3DState frameState=frameStateFlat,
                            bool selectable=true,
                            pointI pos=(0, 0),
                            sizeI size=(100, 100),
                            bool passive=false,
                            cardFlapSide flapSide=cardFlapSide.up,
                            int flapSize=useFacelift ? 52 : 24,
                            bool flapsUsesAllSpace=false,
                            function(CardWindow window) callback=null) : deprecated {}

New: public constructor(Window parent,
                        // inherited key arguments
                        Font font=systemFont(),
                        Brush brush=null,
                        // FrameStyle frameStyle=null, // Removed

                        frame3DState frameState=frameStateFlat,
                        bool selectable=true,
                        pointI pos=(0, 0),
                        sizeI clientSize=automaticSize,
                        bool passive=false,
                        cardFlapSide flapSide=cardFlapSide.right,
                        int flapSize=52,
                        bool flapsUsesAllSpace=false,
                        function(CardWindow window) callback=null,
                        SrcRef src=#:src) {

class ToolboxButtonPainter

Old: extend public void truncateToFit(rectI r)
New: public void updateOutText()

Clean up old lazy startup code and keep only V2 stuff

Remove ultraGetPinnedExtensions() to clean up old unnecessary lazy startup code and keep only V2 stuff.

Removed: public str[] ultraGetPinnedExtensions() {

cm.core.undo

Added new argument to collectG3UserEvent in UndoOp.

Old: extend public void collectG3UserEvent(G3UserEventEnv env)
New: extend public void collectG3UserEvent(G3UserEventEnv env, double start)

Added new argument to logG3UserEvents in UndoStep.

Old: extend public void logG3UserEvents()
New: extend public void logG3UserEvents(double start=microTime())

Added new arguments to insertSnapperEvent, groupEntities, and groupInsertEvent in G3UserEventEnv.

Old: extend public void insertSnapperEvent(Snapper snapper)
New: extend public void insertSnapperEvent(Snapper snapper, int quantity=0, double start=microTime())
Old: groupEntities(G3UserEvent event, SnapperStatsEntity snapperEnt, G3StatsEntity[] entities)
New: groupEntities(G3UserEvent event, SnapperStatsEntity snapperEnt, G3StatsEntity[] entities,
				      double start=microTime())
Old: groupInsertEvent(G3UserEvent event, SnapperStatsEntity snapperEntity, G3StatsEntity[] entities)
New: groupInsertEvent(G3UserEvent event, SnapperStatsEntity snapperEntity, G3StatsEntity[] entities,
					 double start=microTime())

cm.core.user

UnitPrecision class has been made public.

Old: package class UnitPrecision {
New: public class UnitPrecision {

cm.core.visibility

Changed the loadCustomViewMode()-function to have a Url argument that points to the view mode file to load. Previously, this function would show a pop-up window where the user had to choose the file location. This interactive functionality has been moved into the load() method of ViewModeTreeViewSpacerItem.

Removed: public void loadNewViewMode() {
Old: public ViewMode loadNewCustomViewMode() {
Old: public ViewMode loadCustomViewMode(Window parent=null) {
New: public ViewMode loadCustomViewMode(Url url) {

The following functions where moved from cm/core/visibility/ to cm/core/

public void loadCustomViewModes() {
public Url[] getAllCustomViewModes() {

The following global variable was removed since the entire "temporary" view mode system is removed.

Removed: public symbol->ViewMode temporaryViewModeMap();

class ViewMode

Removed: extend public void clearUndefinedLabel() {

class ViewModesPanel

Many fields and methods have been removed or had their interface changes. Much of the removed functionality is related to the "temporary" view modes concept, which has been entirely removed.

Removed: public StateControlGroup group;
Removed: public str currentMode;
Removed: private ViewMode tempMode : public readable;
Removed: private bool usingCheckbox = false : public readable;
Removed: public bool inPrint;
Removed: public constructor(Window target, function(Control button) bCB, function(Control button) sCB = null, bool print=false) {
Removed: extend public void addTempModesToTree() {
Removed: extend public void setTempMode(ViewMode vm) {
Removed: extend public void eraseTempMode() {

Old: extend public void update(str currentViewMode, bool useCheckbox = false) {
New: extend public void update(ViewMode select=null) {
Old: extend private void updateViewItems(str currentViewMode, bool useCheckbox = false) {
New: extend private void updateViewItems(ViewMode temp=null) {
Old: public void exportViewMode(ViewMode vm) {
New: public void exportViewMode(ViewMode vm, Window parent=null) {

cm.extension

Clean up old lazy startup code and keep only V2 stuff

Remove ultraLazyV2 to clean up old unnecessary lazy startup code and keep only V2 stuff.

Removed: public bool ultraLazyV2 = true;

cm.extension.ultraLazy

Clean up old lazy startup code and keep only V2 stuff

The following changes were made to clean up old unnecessary lazy startup code and keep only V2 stuff.

Removed functions in trampoline.cm

Removed: public void ultraStartWithinThreshold() {
Removed: public void ultraStartMyFavorites(double deadline) {
Removed: public void ultraStartRandom(double deadline) {
Removed: public void ultraRecordAction(str key) {

Remove useV2 from UltraLazyDebugInfo class in ultraLazyDebugSettings.cm

public class UltraLazyDebugInfo : unstreamable {
- Removed: public bool useV2;

The following functions have been moved from trampoline.cm into UltraLazyStarter class

public class UltraLazyStarter {
- Added: public timespan lazyWakeupTime() {
- Added: public int wokenUpCount() {
- Added: public void showEndSnoozes() {

cm.std.draw3D

Old: public double initialLineLength = 20cm : keep;
New: private const str initialLineLengthCoreSettingsKey = "cm.std.draw3D.twoClickMeasureInitialLineLength";
New: package double getInitialLineLength() {
New: package double setInitialLineLength(double length) {

class TwoClickMeasureInsertAnimationSecond

Old: public double lineLength = getInitialLineLength();
New: private double lineLength = getInitialLineLength();

cm.std.print.template

The following classes have been marked as deprecated. They will be removed in a future versions.

Deprecated: public class DrawTemplate3D2SidedRect
Deprecated: public class DrawTemplate3D3SidedDoubleRect
Deprecated: public class DrawTemplate3D3SidedRect
Deprecated: public class DrawTemplate3DArc
Deprecated: public class DrawTemplate3DBackgroundRect
Deprecated: public class DrawTemplate3Dbox
Deprecated: public class DrawTemplate3DCircle
Deprecated: public class DrawTemplate3DDoubleArc
Deprecated: public class DrawTemplate3DDoubleLine
Deprecated: public class DrawTemplate3DDoubleRect
Deprecated: public class DrawTemplate3Dhelpline
Deprecated: public class DrawTemplate3DLineAnimationG2
Deprecated: public class DrawTemplate3DLineAnimationG2Vessels
Deprecated: public class DrawTemplate3DLine
Deprecated: public class DrawTemplate3DMeasure
Deprecated: public class DrawTemplate3DMixedLine
Deprecated: public class DrawTemplate3DNurb
Deprecated: public class DrawTemplate3DNurbsCPConnector
Deprecated: public class DrawTemplate3DRect
Deprecated: public class DrawTemplate3DReferencePoint
Deprecated: public class DrawTemplate3DRevisionCloud
Deprecated: public class DrawTemplateStretchablePolyLineInsertAnimation

Each one has an equivalent in package cm.std.print that has the same name except for the Template part. These have slightly different behavior, but are very similar. Generally, you should be fine by your deprecated class with the corresponding one below.

public class Draw3D2SidedRect
public class Draw3D3SidedDoubleRect
public class Draw3D3SidedRect
public class Draw3DArc
public class Draw3DBackgroundRect
public class Draw3Dbox
public class Draw3DCircle
public class Draw3DDoubleArc
public class Draw3DDoubleLine
public class Draw3DDoubleRect
public class Draw3Dhelpline
public class Draw3DLineAnimationG2
public class Draw3DLineAnimationG2Vessels
public class Draw3DLine
public class Draw3DMeasure
public class Draw3DMixedLine
public class Draw3DNurb
public class Draw3DNurbsCPConnector
public class Draw3DRect
public class Draw3DReferencePoint
public class Draw3DRevisionCloud
public class DrawStretchablePolyLineInsertAnimation

The following function is also deprecated:

Deprecated: public Library stdPrintFrameLibrary() : deprecated {

cm.std.wall

Old: public void cleanCutBy(DrawSnapper w, DrawSnapper candidate, RemoveSnappersEnv env=null) {
New: private void cleanCutBy(DrawSnapper w, DrawSnapper candidate, RemoveSnappersEnv env=null) {

class SpecialWallFeatureSearch

Old: extend public SimpleWallLine previousWall() { return null; }
New: extend public SimpleWallLine previousWall(SimpleWallLine wallBeingAnimated, point wallBeingAnimatedStart) {
Removed: extend public GraphPrimitive{} otherFeatureTypeFeatures(FeatureLineSearch fs, point fp, SimpleWallLine{} walls) {
Removed: extend public void appendExtendLineCandidates(SimpleWallLine wall, SpecialWallFeaturePrimitive current, SpecialWallFeaturePrimitive other, FeatureLineSearch fs) {

class WallSurfaceAlign

Removed: final public point rectoskopi(GFacePrimitive owner, point localP, bool turnBitch) {

class WallSurfaceAlignG2

Removed: extend public void adjustWallDistance() {
Removed: final public point rectoskopi(GFacePrimitive owner, point localP, bool turnBitch) {

class WallImageSnapper

Old: extend public void verifyMinWidthAndHeight() {
New: extend public void enforceMinDimensions() {
Old: final public void resizeToAspectRatio() : deprecated {
New: final public void resizeWidthToAspectRatio() {

cm.test.cmunit.testInstructions

Removed the PrintWarningInstruction test instruction since it is unused and should not be needed.

Removed: public class PrintWarningInstruction extends TestInstruction {

cm.util.commander

Old: public class CleanupCommand extends Command : deprecated {
New: public class CheckAndCleanUpCommand extends Command {

cm.win

The functions to create visually transparent windows (layered windows in Windows parlance) have been changed to make their purpose clearer: For more information, you can refer to the comments in cm/win/winApi.cm

Old: public void overlayCapture(mwnd hwnd, int alpha)
New: public void setLayeredWindow(mwnd hwnd, int alpha)

Old: public void setOverlayCaptureAlpha(mwnd hwnd, int alpha)
New: public void setLayeredWindow(mwnd hwnd, byte alpha)

Old: public void initOverlayCapture(mwnd hwnd, int alpha) = win_initOverlayCapture;
New: public void setLayeredWindow(mwnd hwnd, byte alpha) = win_setLayeredWindow;

New: public void removeLayeredWindow(mwnd hwnd) {}

The following methods on Window have been removed:

Removed: final public bool isSuspended() {}

The following method has been removed from FrameWindow:

Removed: final public void reportVisibleTime() {}

The Card constructor has been modified to remove the pos and size parameters:

Old: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        pointI pos=(0, 0),
                        sizeI size=sizeI(-1, -1),
                        bool passive=false,
                        str key=null,
                        str label=null,
                        str toolTip=null,
                        Image image=null,
                        Skin overrideSkin=null,
                        bool on=true,
                        SrcRef src=#:src) {}

New: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        pointI origin=(0, 0),
                        bool selectable=true,
                        //pointI pos=(0, 0),           // REMOVED
                        //sizeI size=sizeI(-1, -1),    // REMOVED
                        bool passive=false,
                        str key=null,
                        str label=null,
                        str toolTip=null,
                        Image image=null,
                        Skin overrideSkin=null,
                        bool on=true,
                        SrcRef src=#:src) {}

The FormattedTextArea constructor has been updated to handle links.

Old: public constructor(Window parent,
                        // inherited key arguments
                        Font font=smallSystemFont,
                        Brush brush=null,
                        FrameStyle frameStyle=stdLightFrame,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(0, 0),
                        pointI margins=(2, 1),
                        // extended
                        bool lineBreak=true,
                        function(Control button) posChangedCallback=null,
                        function(Control button) callback=null,
                        function(Control button) escapeKeyCallback=null,
                        function(Control button) lostFocusCallback=null,
                        str key=null,
                        bool absFontH=false,
                        bool spellCheck=false,
                        SrcRef src=#:src) {
New: public constructor(Window parent,
                        // inherited key arguments
                        Font font=smallSystemFont,
                        Brush brush=null,
                        FrameStyle frameStyle=stdLightFrame,
                        frame3DState frameState=frameStateDown,
                        pointI pos=(0, 0),
                        sizeI size=(0, 0),
                        pointI margins=(2, 1),
                        // extended
                        bool lineBreak=true,
                        function(Control button) posChangedCallback=null,
                        function(Control button) callback=null,
                        function(Control button) escapeKeyCallback=null,
                        function(Control button) lostFocusCallback=null,
                        str key=null,
                        bool absFontH=false,
                        bool spellCheck=false,
                        // link support
                        color linkColor=primary600,
                        color linkHoverColor=primary600,
                        function(Control button, str key):bool linkCallback=null,
                        SrcRef src=#:src {
 

The ColorControl class has had the following fields removed:

Removed: public IntField rC;
Removed: public IntField gC;
Removed: public IntField bC;
Removed: public HsvSlider hsvC;

The RoundedPenFrame constructor has ability to show on hover.

Old: public constructor(Pen pen, Pen highlightPen) {
New: public constructor(Pen pen, Pen highlightPen, bool onlyOnHover=false) {

A method was removed from the FaceliftToggle class:

Removed: extend public void drawToggle(PixelDevice device,
                                       pointI p,
                                       int w,
                                       int h,
                                       int progress,
                                       int innerOffset) : deprecated {}

The IconInfo class has been removed. As a result of this change, IconFinder's fields have been changed to remove references to this type:

Removed: public str->IconInfo icons();

The MenuBar class has a couple of its methods changed as follows:

Old: extend public int buildButton(str key,
                                   Image img,
                                   str toolTipText,
                                   function(Control) cb,
                                   int margin=0,
                                   bool right=false,
                                   bool assignIID=false) {}

New: extend public int buildButton(str key,
                                   Image img,
                                   str toolTipText,
                                   function(Control) cb,
                                   str bindingKey=null    // ADDED
                                   int margin=0,
                                   bool right=false,
                                   bool assignIID=false,
                                   SrcRef src=#:src) {}   // ADDED

Old: extend public int buildSeparator(bool right=false) {}

New: extend public int buildSeparator(bool right=false, SrcRef src=#:src)  {}

Old: final public void initIID(str buttonsIID) : deprecated {}

New: final public void initIID(str buttonsIID, VisibilityProfile root)

The constructor for SeparatorLine has been changed to allow spawning it as a popup window:

Old: public constructor(Window parent,
                        FrameStyle frameStyle=thin3DFrame,
                        frame3DState frameState=frameStateDown,
                        int external=0,
                        int internal=0,
                        bool vertical=false,
                        bool light=false,
                        SrcRef src=#:src) {}

New:
Old: public constructor(Window parent,
                        FrameStyle frameStyle=thin3DFrame,
                        frame3DState frameState=frameStateDown,
                        int external=0,
                        int internal=0,
                        bool vertical=false,
                        bool light=false,
                        bool popup=false,    // ADDED
                        SrcRef src=#:src) {}

The following methods on TreeViewItem have been changed:

Old: final public void sortByLabel(bool recursive=true) {}
New: final public void sortByLabel(bool recursive=true, Object{} visited=null) {}

The following methods on TreeViewSubTree have been changed:

Old: extend public void sortByLabel(bool recursive=true) {}
New: extend public void sortByLabel(bool recursive=true, Object{} visited=null) {}

The following functions have been removed from this package:

Removed: public bool removeRegisteredLanguage(str lang, str resKey, str nextLang) {}

GroupBox

Some changes have been made to GroupBox to rationalise it's behaviour regarding origins. The constructor now takes an origin offset instead of an origin directly:

Old: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        FrameStyle frameStyle=noFrame,
                        frame3DState frameState=frameStateDown,
                        pointI origin=(0, 0),    // REMOVED
                        bool selectable=true,
                        pointI pos=(0, 0),
                        sizeI size=(0, 0),
                        bool passive=true,
                        str label=null,
                        color labelColor=color(),
                        str key=null,
                        SrcRef src=#:src) {}

New: public constructor(Window parent,
                        Font font=systemFont(),
                        Brush brush=null,
                        FrameStyle frameStyle=noFrame,
                        frame3DState frameState=frameStateDown,
                        pointI originOffset=(0, 0),    // ADDED
                        bool selectable=true,
                        pointI pos=(0, 0),
                        sizeI size=(0, 0),
                        bool passive=true,
                        str label=null,
                        color labelColor=color(),
                        str key=null,
                        SrcRef src=#:src) {}

The following method was also removed as part of this origin rationalisation:

Removed: final public void updateOrigin() {}

Previously, the API did not respect the origin set by the user, as an overriding origin was required to fit the text into the element. With the new originOffset parameter, a custom offset from the text of the GroupBox can now be specified.

The constructors for SubGroupBox and ShrinkBox have also been modified to match this change.

custom.dataCatalog.builder

Removed deprecated field meshDatas from DcMeshDataValidationEnv.

//custom/dataCatalog/builder/geometry/dcGeometryValidations.cm   class DcMeshDataValidationEnv
Removed: public MeshData[] meshDatas()

Runtime/Behavior Changes

cm.abstract.dataSymbol

The fields I1 (part base price) and O1 (option price) have been added to SIF exports for parts. OL for option price has been removed.

final package str[] generateConfiguraSifRows(DsPart part, Space space) {
	
	...
	
	// I1= base price (without option upcharges)
	addSifRow(env, "I1", part.basePrice().toS());
	
	...
	
	//Options
	for (DsPDataOption pO in sortedSelOptions, index=index) {
		...
		addSifRow(env, "O1", o.price(this).toS);
		...
	}
	
	...
}

The fields I1 (part base price) and O1 (option price) have been added to SIF exports for parts, leading to these additions in DsFreeformPData:

public str[] generateSifRows(DsPart part, Space space) {
	
	...
	
	// I1= base price (without option upcharges)
	addSifRow(env, "I1", part.basePrice().toS());
	
	...
	
	//Options
	for (pO in sortedSelOptions, index=index) if (pO as DsPDataOption) {
		...
		addSifRow(env, "O1", o.price(this).toS);
		...
	}
	
	...
}

cDsFreeformMeasTypeSubSet now excludes enum types unknown, mirrorPointX, mirrorPointY, and insertElevation. This means these columns are no longer available as columns in the freeform picklist.

cm.abstract.dataSymbol.materialLegend

The following functions have been added to support filtering of materials in DsMaterialLegendSnappers.

DsMaterialLegendSnapper

Added: public ObjectLabelSubSet _filterSubSet;
Added: public void initFilters() {}
Added: extend public ObjectSubSet filterSubSet() {}

The following functions have been added to support length units for COMs in the in DsMaterialLegendItems.

DsMaterialLegendItem
Added: extend public Graph graphLengthUnit(UserTextStyle style) {}

DsMaterialLegendItemBuildEnv 
Added: public constructor(bool buildName=true, bool buildDescription=true,
		       bool buildID=true, bool buildEnterprise=true|, bool buildLengthUnit=false) {}

To support filtering of DsMaterialLegends, ObjFilters are utilized to filter materials in the legend. As a result, the optional bool filtered parameter was added when retrieving the sorted item list for legends..

DsMaterialLegend 
Old: public sorted str->MaterialLegendItem sortedList() {}
New: public sorted str->MaterialLegendItem sortedList(bool filtered=true) {}

cm.abstract.draw

On drawing load, instances of DrawEllipse will be replaced by instances of Draw3DEllipse. The only major difference between them is that Draw3DEllipse optionally supports 3D graphics outside of paper space.

cm.abstract.material

The following overidden getter/setter functions have been added. Now, changes to description on COMPartProxy change the description on the referenced CustomerOwnMaterial.

// get/set now reference CustomerOwnMaterial description
Added: public str description() {}
Added: public str description=(str v) {}

The following functions have been added to support updating a specific MaterialTreeViewItem in the tree view of materials and CustomerOwnMaterial undo operations.

// Updates a specific MaterialTreeViewItem in the tree view
Added: extend public void updateMaterial(Material mat) {}

// returns the COMUndoOp for the CustomerOwnMaterial and the operation being performed
Added: extend public COMUndoOp comUndoOp(CustomerOwnMaterial com, comUndoOperation operation) {}

cm.abstract.materialHandling

MhAfterEngineInitialExportBehavior changes

Change sorting of snapper from locally defined snapper child depth sorting to use newly added mhSnapperFuncRunOrderSort(Snapper a, Snapper b, Object env).

MhEngineRun changes

Change sorting of snapper from locally defined snapper child depth sorting to use newly added mhSnapperFuncRunOrderSort(Snapper a, Snapper b, Object env) during export.

MhRemoverExecuteVessel changes

Change sorting of snapper from locally defined snapper child depth sorting to use newly added mhSnapperFuncRunOrderSort(Snapper a, Snapper b, Object env).

MhSnapperShape changes

Implement sorting of snapper children to use newly added mhSnapperRootXYZPosSort(Snapper a, Snapper b, Object env) during property change.

MhEngineManager

Split run functions into multiple functions for clarity. This means that runFunctions will be a stand alone function and no longer call post engine run and finalize engine run.

        int i;
        while (i <= list.lastIndex) {
            if (MhEngineRun r = list[i]) {
                currentRun = r;
                
                r.beforeEngineRun(e, runEnv);
                
                r.mainRunFunctions(e, runEnv);
                r.postRunFunctions(e, runEnv);
                r.finalizeRunFunctions(e, runEnv);
                
                r.afterEngineRun(e, runEnv);
                
                currentRun = null;
            }

            i++;
        }

For function that called runFunctions outside of engine manager, this will have to change as below.

Example: 

Old:  {
    run.runFunctions(runEngine, env);
}

New: { 
    run.mainRunFunctions(runEngine, env);
    run.postRunFunctions(runEngine, env);
}

Temporary MhConfigRef copy changes

The function mhConfigTempCopy(MhConfigRef ref) will now also set the field id = 0 of MhConfigRef objects where their field isCustom = true.

Old:
public MhConfigRef mhConfigTempCopy(MhConfigRef ref) {
    MhConfigRef cRef = copy(ref);
    cRef.gid = guid();
    
    if (ref.isCustom) {
        if (developMode) if (cRef.id != -1) ptrace("Expected ID to be -1 for custom!".eAngry);
    } else {
        cRef.id = 0;
        cRef.name = "";
    }
    return cRef;
}

New:
public MhConfigRef mhConfigTempCopy(MhConfigRef ref) {
    if (!ref) return null;
    MhConfigRef cRef = copy(ref);
    cRef.gid = guid();
    cRef.id = 0;
    if (!ref.isCustom) cRef.name = "";
    return cRef;
}

This is because MhConfigRef objects are only considered temporary if id == 0.

public class MhConfigRef {

    /**
     * Temp.
     */
    final public bool temp() { return id == 0; }
}

Without resetting the id field back to 0, they will not be treated as temporary config refs by MhConfigManager, stopping those instances from being merged with identical config refs in the MhConfigManager.configs container field.

MhLevelConstructionalPopulateFunction changes

A new field public Int noOfLevels has been added to MhLevelConstructionalPopulateFunction. When a noOfLevels value is passed in from your engine behavior, this function will only populate loads up to the noOfLevels value instead of using the parent bound and populating as much as possible up to the bound height.

cm.abstract.materialHandling.storage

Drawing configurations changes for bay and frame editors

Drawing configurations are now directly editable in the bay and frame editors. We have made several updates to the editors and configurations to support this.

You can control which configurations are editable by overriding isConfigEditable(MhStorageEditorConfiguration config). This will disable the various editor tabs, quick properties as well as preview snappers for the given configuration.

public class MhStorageEditorDialog extends DialogWindow : abstract {

    /**
     * Is config editable?
     */
    extend public bool isConfigEditable(MhStorageEditorConfiguration config) {
        if (config.?drawingConfig) {
            for (snapper in mainSpace.snappers) {
                forChildrenRecursive(MhSnapper child in snapper) {
                    if (child.configEq(config)) {
                        if (child.readOnly()) {
                            return false;
                        }
                    }
                }
            }

            return drawingConfigsEditable();
        }
        return true;
    }
}

Additionally if you do not want drawing configurations to be editable like before, then you can override drawingConfigsEditable().

public class MhStorageEditorDialog extends DialogWindow : abstract {

    /**
     * Drawing configs editable?
     */
    extend public bool drawingConfigsEditable() {
        return true;
    }
}

MhStorageEditorDialog now has a default implementation for buildApplyButtons(Window w). It is broken up into 2 sub-windows, spreadSub and saveAndApplyButtonsSub. spreadSub is built by the configuration and should already be present in existing implementations. We have added saveAndApplyButtonsSub as a new sub-window which by default is positioned to the left of spreadSub. saveAndApplyButtonsSub is used by drawing configurations to apply the modifications directly to snappers in the drawing.

If you have overridden how your dialog builds its windows, you may have to look into adding the saveAndApplyButtonsSub to your overridden code to ensure users can apply drawing configuration changes. The methods below were added to support controlling these 2 sub-windows.

public class MhStorageEditorDialog extends DialogWindow : abstract {

    /**
     * Build apply buttons.
     */
    extend public Window buildApplyButtons(Window w) {
        MhStorageEditorConfiguration config = currentConfig();
        if (!config) return null;

        SubWindow sub(w, frameStyle=noFrame);
        spreadSub = config.?buildSpreadButtons(sub, spreadButtonCallback);
        saveAndApplyButtonsSub = buildSaveAndApplyButtons(sub);

        if (saveAndApplyButtonsSub and spreadSub) {
            spreadSub.rightOf(saveAndApplyButtonsSub);
            saveAndApplyButtonsSub.alignCenterY(spreadSub);
        }
        sub.autoSize();
        return sub;
    }


    /**
     * Spread buttons subwindow enabled?
     */
    extend public bool spreadSubEnabled() {
        MhStorageEditorConfiguration config = currentConfig();
        return config and (!config.drawingConfig or !isConfigModified(config));
    }


    /**
     * Show save and apply buttons.
     */
    extend public bool showSaveAndApplyButtons() {
        return currentConfig().?drawingConfig;
    }


    /**
     * Save and apply button enabled?
     */
    extend public bool saveAndApplyButtonEnabled() {
        MhStorageEditorConfiguration config = currentConfig();
        return config and config.drawingConfig and isConfigModified(config);
    }


    /**
     * Save and apply all button enabled?
     */
    extend public bool saveAndApplyAllButtonEnabled() {
        return anyModifiedConfigs();
    }


    /**
     * Build save and apply buttons.
     */
    extend public Window buildSaveAndApplyButtons(Window w) {
        SubWindow sub(w, frameStyle=noFrame);
        saveAndApplyBtn = Button(sub, key="saveAndApply",
                                 label=$saveAndApplyExisting, textSide=alignment.down,
                                 callback=buttonCallback());
        saveAndApplyAllBtn = Button(sub, key="saveAndApplyAll",
                                    label=$saveAndApplyAll,
                                    textSide=alignment.down,
                                    callback=buttonCallback());
        saveAndApplyAllBtn.rightOf(saveAndApplyBtn);
        sub.autoSize();
        return sub;
    }


    /**
     * Toggle spread buttons.
     */
    extend public void toggleSpreadButtons() {
        spreadSub.?enable(spreadSubEnabled(), update=true);
    }


    /**
     * Toggle save and apply buttons.
     */
    extend public void toggleSaveAndApplyButtons() {
        if (showSaveAndApplyButtons()) {
            saveAndApplyButtonsSub.show();
            saveAndApplyBtn.?enable(saveAndApplyButtonEnabled(), update=true);
            saveAndApplyAllBtn.?enable(saveAndApplyAllButtonEnabled(), update=true);
        } else {
            saveAndApplyButtonsSub.hide();
        }
    }
}

As for applying configurations to drawing snappers, a new method in MhStorageEditorConfiguration was added to support this which uses the existing spread animation defined by this class.

public class MhStorageEditorConfiguration extends MhSystemConfiguration {

    /**
     * Apply to space.
     */
    extend public bool applyToSpace(Space space, Snapper{} affected=null, bool validate=false) {
        if (MhSnapperApplyAnimation anim = getApplyToSpaceAnim(space)) {
            animate(anim);
            anim.applyEvent();
            if (affected) affected += anim.affectedSnappers;
            if (validate) space.validateSnapperInvalidations();
            abortAnimation();
            return true;
        }

        return false;
    }
}

When a user attempts to close the bay/frame editor, if there are any unapplied drawing configuration changes, they will by default receive a prompt notifying them. You can override this feature with promptUnappliedChanges().

public class MhStorageEditorDialog extends DialogWindow : abstract {

    /**
     * Close event.
     */
    public void close() {
        if (!promptUnappliedChanges()) return;
        ...
    }


    /**
     * Prompt unapplied changes dialog.
     * Return false when user clicks cancel.
     */
    extend public bool promptUnappliedChanges() {
        if (anyModifiedConfigs()) {
            str label = unappliedChangesLabel();
            if (!label) {
                if (developMode) ptrace("Missing label");
                return true;
            }

            FlexDialog mgBox(label);
            mgBox.setCustomCaption(getLabel());
            mgBox.addButton($saveAndApplyAll, dialogResult.ok, image=icon("apply"), closeOnClick=true);
            mgBox.addButton($close, dialogResult.no, image=icon("no"), closeOnClick=true);
            mgBox.addButton($cancelButtonLabel, dialogResult.cancel, image=icon("cancel"), closeOnClick=true);

            int res = mgBox.showModal();
            if (res.dialogResult.cancel) {
                return false;
            } else if (res.dialogResult.ok) {
                event("saveAndApplyAll");
            }
        }

        return true;
    }
}

Lastly, we now emit different events for selecting a snapper selectionChanged as well as renaming configs configRenamed. Previously both these actions would emit the afterPropertyChanged event.

package class MhStorageEditorWorldEvents extends EventViewer {

Old:
    /**
     * Event.
     */
    public bool event(symbol event, Object z, str->Object args) {
        if (event == #endUndoStep) {
            if (z as UndoStep) {
                mhStorageEditorNotifyEvent("afterPropertyChanged");
            }
        }
        return false;
    }


New:
    /**
     * Event.
     */
    public bool event(symbol event, Object z, str->Object args) {
        if (event == #endUndoStep) {
            if (z as UndoStep) {
                if (z.operations.count == 1) {
                    UndoOp op = z.operations.first;
                    if (op in UndoSelectOp) {
                        mhStorageEditorNotifyEvent("selectionChanged");
                    } else if (op in MhStorageEditorConfigRenameUndoOp) {
                        mhStorageEditorNotifyEvent("configRenamed");
                    }
                } else {
                    mhStorageEditorNotifyEvent("afterPropertyChanged");
                }
            }
        }
        return false;
    }
}

Rows break all soft connections

MhRowShape has extended the breakAllConnections feature to also break all soft connections.

public class MhRowShape extends MhSnapperShape {

    /**
     * Disconnect all connections in this snapper, except those
     * who are attached to a snapper in 'exceptTo'.
     */
    public void breakAllConnections(Snapper{} exceptTo=null) {
        if (owner.isActive and owner.useSoftConnect()) {
            mhBreakAllSoftConnections(owner, exceptTo=exceptTo);
        }
    }
}

MhRowStretchAnimation has also been updated to maintain soft connections so that all soft connections in a system will not be broken whenever the stretch animation is run.

public class MhRowStretchAnimation extends MhPropertyStretchAnimation {

    /**
     * Keep connected.
     */
    public Snapper{} keepConnected() {
        Snapper{} res = super(..);

        Snapper{} snappers();
        snappers += ogSelection.snappers;

        Snapper{} visited();
        for (z in snappers) {
            for (MhRowConnectLine c in z.connectors()) {
                if (c.isSoftConnected()) {
                    bool cr = c.keepConnectedDuringAnimation(ogSelection);
                    Snapper{} connSnappers = mhGetSoftConnectedSnappers(c);
                    for (z2 in connSnappers) {
                        if (z2 in visited) continue;
                        visited << z2;
                        if (z2.keepConnectedDuringAnimation(ogSelection) or cr) {
                            snappers += connSnappers;
                        }
                    }
                }
            }
        }

        return res + snappers;
    }

MhStorageConfiguration changes

When loading configuration, instead of checking the configuration package against class.pkg, check with the package. As well as when getting addtional suffixes in additionalSuffixes, embeding security info in embedPackageInfo, and validating package info in validPackageInfo. This is due to when we save the configuration, we put the package into the formatter.

    /**
     * Pre loading check for configuration file.
     */
    public bool isAllowedLoadConfigurationFile(Url url) {
	bool canLoad = super(..);
	using (File f = url.openForRead()) {
	    RobustFormatter formatter(f, Version(fastRobustVersion));
	    if (formatter.stream.remaining > 0) {
		// label object.
		formatter.getObject();
	    }
	    if (formatter.stream.remaining > 0) {
		// package object.
		?symbol savedPkg = formatter.getObject();
		if (savedPkg != package) canLoad = false;
	    }
	}
	return canLoad;
    }

MhLevelArrangeFunction2, a better and simpler MhLevelArrangeFunction

MhLevelArrangeFunction2 is replacing the old MhLevelArrangeFunction, providing simpler logic and clearer structure. It also separate out levelChildArrange into another engine function.

- New: public class MhUnitLoadStandOnUpdateFunction extends MhSystemEngineFunction {
- New: public class MhLevelArrangeFunction2 extends MhSystemEngineFunction {

MhUnitLoadArrangement, to handle unitload layout on unit load.

New unit load arrangement class to help populating unit loads on level. MhUnitLoadConstructionalPopulateFunction will now be using the arrangement class to handle unit load creation.

- New: public class MhUnitLoadArrangement
- New: public class MhConstructionUnitLoadArrangement extends MhUnitLoadArrangement
- New: public class MhPopulateUnitLoadArrangement extends MhUnitLoadArrangement
- New: public class MhClearanceUnitLoadArrangement extends MhUnitLoadArrangement
- New: public class MhFillSpacesUnitLoadArrangement extends MhUnitLoadArrangement

Introduce MhUnitLoadEnsureClearanceFunction2 to replace MhUnitLoadEnsureClearanceFunction to use the new unit load arrangement. The MhUnitLoadEnsureClearanceFunction will still be available for extensions to opt-out from this changes by overriding the engine function registered in assortment.

MhPopulator

Added new method reset in MhPopulator class to reset the state of populator. Engine now is a copy by reference field to allow for populator copy.

- New: public void reset() {

MhCompartmentConfigurationItem

Added support noOfUnitLoadsY to handle number of unitload in perpendecular direction.

cm.abstract.materialHandling.storage.engine

MhSystemExportFunction changes

Change sorting of entry from locally defined entry snapper child depth sorting to use newly added mhEntryFuncRunOrderSort(MhEngineEntry a, MhEngineEntry b, Object env).

mhStorageChildrenBlocks changes

Change sorting of entry from locally defined entry local position sorting to use newly added mhEntryFuncRunOrderSort(MhEngineEntry a, MhEngineEntry b, Object env).

MhSystemImportFunction changes

Move logic that break linking after export to actual import function MhSystemImportFunction

- New: public void afterImport(MhEngineEntry{} imported, MhEngine engine) {

cm.abstract.materialHandling.storage.racking

Add logic to explicitly allowNewSpacer(..) calculated using aisle depth and implemented as always true by default.

cm.abstract.materialHandling.storage.racking.deepstorage

MhDeepstorageUnitLoadConstructionalPopulateFunction changes

MhDeepstorageUnitLoadConstructionalPopulateFunction is now able to populate based on noOfUnitLoadsInDepth that is passed in as an argument. A new flag is added populateBasedOnNoUlDepth, so that you can decide whether to populate unit load based on the noOfUnitLoadsInDepth given or populate as many as possible.

public class MhDeepstorageUnitLoadConstructionalPopulateFunction extends MhUnitLoadConstructionalPopulateFunction {
- New: public Bool populateBasedOnNoUlDepth;
- New: public Int noOfUnitLoadsInDepth;

cm.abstract.part

The field I1 (part base price) has been added to SIF exports for parts, leading to this addition:

extend public str[] internal_generateConfiguraSifRows(Space space) {
	...
	addSifRow("I1", basePrice().toS(), lines);
	...
}

cm.core

Core Properties bugfix

'cm/core/coreProperties.cm::build(PreCorePropObj z, symbol{} attributes=null, BuildPropertiesEnv env=null, str->Object args=null)`

Resolved a bug during properties rebuild, with existing properties not getting removed correctly if the rebuilt properties has zero item or only one item left. This may impact developers using workarounds to manually remove properties that are incorrectly left behind.

cm.core.red3D.distributed

In runtime REDRenderJOB work the same as it before.

cm.core.red3D.distributed.redRenderJob

In runtime REDRenderJOB work the same as it before.

cm.core.toolbox

Extension Tabs

With the addition of Extension Tabs (not to be confused with Toolbox Component Tabs), the toolbox card can now contain multiple instances of ToolboxSectionedScrollableSubWindow, one for each tab. To differentiate between these instances, the key of the window can be used instead. The format of a key is $cardKey!$tabKey.

Changes to the toolbox configuration have been made as well. It stores information such as what sections should be hidden, what the order of each section should be, and what was collapsed by the user. If the Component Tab uses Extension Tabs, the key of each tab is prepended to the section keys that are stored into the config.

If your tab does not have any tabs, behaviour is unchanged from previous versions.

New libraryFun for Paper Tools toolbox in facelift

Many functions inside cm.core.toolbox/toolbox.cm uses the name of the function that created a library to find it.

In facelift, they key for the paper tools library is instead faceliftPaperToolsLibrary. So when trying to find the paper tools library, make sure to search for that when useFacelift is true.

Affected functions are:

public bool updateToolboxCheckBox(symbol pkg, str libraryFun, str checkBoxKey, bool check, CoreAppWindow appWindow=null, bool invokeCallback=true) {
public bool updateAllTbCheckBoxes(symbol pkg, str libraryFun, str checkBoxKey, bool check, bool invokeCallback=true) {
public bool updateToolboxSubSetDropDown(symbol pkg, str libraryFun, str dropDownLimbKey, str selectItemKey, CoreAppWindow appWindow=null, bool invokeCallback=true) {
public bool rebuildToolboxSubSetDropDown(symbol pkg, str libraryFun, str dropDownLimbKey, Object initial, Object[] seq, CoreAppWindow appWindow=null, bool invokeCallback=true) {
public bool updateAllTbSubSetDropDowns(symbol pkg, str libraryFun, str dropDownLimbKey, str selectItemKey, bool invokeCallback=true) {
public bool updateToolboxMaterialTreeDropDown(symbol pkg, str libraryFun, str dropDownLimbKey, str selectItemKey, CoreAppWindow appWindow=null, bool invokeCallback=false) {
public bool updateAllTbMaterialTreeDropDowns(symbol pkg, str libraryFun, str dropDownLimbKey, str selectItemKey, bool invokeCallback=false) {
public bool updateToolboxEnumDropDown(symbol pkg, str libraryFun, str dropDownLimbKey, str selectItemKey, CoreAppWindow appWindow=null, bool invokeCallback=true) {
public bool updateAllTbEnumDropDowns(symbol pkg, str libraryFun, str dropDownLimbKey, str selectItemKey, bool invokeCallback=true) {
public bool updateToolboxDistanceLimb(symbol pkg, str libraryFun, str distanceLimbKey, Object object, CoreAppWindow appWindow=null, bool invokeCallback=true) {
public bool updateAllTbDistanceDropDowns(symbol pkg, str libraryFun, str distanceLimbKey, Object object, bool invokeCallback=true) {
public bool updateToolboxButton(symbol pkg, str libraryFun, str buttonKey, CoreAppWindow appWindow=null) {
public bool updateAllTbButtons(symbol pkg, str libraryFun, str buttonKey) {
public bool updateToolboxButtonColor(symbol pkg, str libraryFun, str buttonKey, color c, CoreAppWindow appWindow=null) {
public bool updateAllTbButtonColors(symbol pkg, str libraryFun, str buttonKey, color c) {
public bool updateToolboxDoubleTextField(symbol pkg, str libraryFun, str textFieldKey, Object object, CoreAppWindow appWindow=null, bool invokeCallback=true) {
public bool updateToolboxDistanceTextField(symbol pkg, str libraryFun, str textFieldKey, Object object, CoreAppWindow appWindow=null, bool invokeCallback=true) {
public bool updateAllTbDoubleTextFields(symbol pkg, str libraryFun, str textFieldKey, Object object, bool invokeCallback=true) {
public LazyLibraryCard getLibraryCard(symbol pkg, str libraryFun, CoreAppWindow appWindow=null) {
public SubSetLimbDropDown getSubSetDropDown(symbol pkg, str libraryFun, str dropDownLimbKey) {

Possibly other in other packages are also affected. Anything that used stdPaperToolsLibrary as a key and is also supposed to work in facelift, essentially.

cm.import.interop

COM Interop / DotNetInvokerServer potential behavior change

We have fixed an issue with DotNetInvokerServer failing to resolve necessary DLL dependencies. Previously it calls .NET Assembly library's LoadFile which loads the specified assembly, but this method does not resolve dependencies. This means custom COM code that references an external library will not work properly or silently fail.

This has been resolved by calling LoadFrom() instead, which attempts to automatically resolve dependencies, for example it will attempt to search for dependencies in the same folder and load them. However, in rare cases the dependency may resolve to an already loaded version with the same identity but on a different path, which might potentially be an issue in development environments. Please perform a smoke test with your COM interop functionalities to ensure they are working fine.

cm.std.print.template

Through PackageStreamRenamer, the classes below will be replaced as followed when a drawing or favorite is loaded:

DrawTemplate3DCircle     -> Draw3DCircle
DrawTemplate3DRect       -> Draw3DRect
DrawTemplate3DArc        -> Draw3DArc
DrawTemplate3DLine       -> Draw3DLine
DrawTemplate3DHelpLine   -> Draw3DHelpLine
DrawTemplate3D2SidedRect -> Draw3D2SidedRect
DrawTemplate3D3SidedRect -> Draw3D3SidedRect

cm.win

Added new argument to isValid method of G3StatsEntity in cm.win.eventLogG3.cm to allow for different validities for different event actions.

Old: extend public bool isValid()
New: extend public bool isValid(str action)

The following functions have been overritten in Display affecting displays with passive=true.

public void rightClick(pointI p) {
public void rightClick2(pointI p) {
public void rightRelease(pointI p) {
public void rightRelease2(pointI p) {

The setGlobalSkin(Skin) function is now a no-op when CET is in the new UI. This is part of larger plan to remove the Skin concept entirely in a future version of CET.

Miscellaneous

cm.core.collab

Collaboration

Collab G1 has seen some behavior changes to clarify the various caching and unnecessary streaming of data in a collaboration local workspace.

  • CollWorkspace will now remove auxillary data in the chunk before streaming into local workspace DB to reduce performance impact on frequent operations.
  • As a consequence, we also try to clarify the purpose of CollFile instances that you get between CollWorld, CollWorkspace, and CollCollection.
  • We attempt to favor the CollFile entries in CollWorld when performing active drawing operations.
  • We removed CollFile streamed references in CollWorld through CollCollection - this reduces data streaming impact on CollWorld CMDRW and prevents infinite file size growth.

These changes were made to CollWorkspace:

= private DB _db : stream=null, copy=null, public readable; // has been marked as copy=null.
+ public Guid->CollFile _workspaceFiles : copy=null, stream=null;
+ private CollRelease _currentRelease;
+ final package bool defragDB(bool force=false)

These changes were made to CollCollection:

= private symbol->CollFile _repositoryFiles : copy=null, stream=null; 
= private symbol->CollFolder _repositoryFolders : copy=null, stream=null;

cm.std.draw3D

The button in the Drawing (Paper) toolbox that used to insert a DrawEllipse now inserts a Draw3DEllipse. These should behave identically in paperspace.

cm.std.tools

The button in the Tools toolbox that used to insert a DrawEllipse now inserts a Draw3DEllipse. The major difference between these is that the latter optionally supports 3D graphics.