Some informational CET windows have been removed and consolidated into a new About CET window.
Using GDI or integer-based method on the PdfCanvas
is causing a lot of precision problems for PDFs and printing.
To make PDF and printing more robust, the Canvas
class will now be separated into two subclasses, ToPixelCanvas
and VectorCanvas
.
In the future, PdfVectorCanvas
will be used instead, and it subclasses from VectorCanvas
where the methods will be floating-point based.
The PixelDevice
dc
field on Canvas
will be moved to ToPixelCanvas
.
Since VectorCanvas
will not use GDI, it's device context or dc
field will not be the PixelDevice
type, but VectorDevice
instead.
The VectorDevice
will support floating-point based methods instead.
The DRecord
class now supports indexing into StrArray
.
The dsiConstraintsApplyStyle
enumeration is not used anymore because we are limiting the constraint apply style options to only Top Down. As a result, all relevant interfaces in OFDAHeaderData
will be deprecated and the ConstraintsApplyStyle
tag will not be used.
A bug would be triggered if an imageSnapper was placed in paperSpace and then stretched or scaled followed by an undo/redo operation. The same problem occured with all classes derived from drawRect if the layer was set to bottom. In order to remedy this issue the previously named photoSnapperUndoHook has been moved into the drawRect super class and renamed drawRectUndoHook.
COMaterials have been changed to always use GMaterial3D. Previously WrappedImageMaterial3D was used for texture materials and ColorMaterial3D for color materials.
A few interfaces in the Material Handling Abstract related to the Animation Tool Spreading functionality has been reworked to be easier to use and customize.
MhSpreadPatternBehavior
has been extended to allow for easier customization of snapper spreading cache keys. As a result, MhSpreadPatternBehavior
and MhSpreadCacheKeyBehavior
functionalities has been merged, with MhSpreadCacheKeyBehavior
removed.SpreadPattern
classes in the abstract has been removed, e.g. MhUnitLoadLevelSpreadPattern
, MhUnitLoadNoSpreadPattern
; along with the behaviors that existed solely to enable usage of these customized spread patterns.MhSnapperSpreadVessel
, MhSnapperRemoverVessel
, MhSnapperSpreadToolAnimation
, and MhSnapperInsertToolAnimation
refactoring to consolidate spreading-related functionalities and various caching, with the introduction of a MhSpreadToolEnv
structure.When copying papers within within a group, the copied paper would be assigned a new group instance, resulting in the paper ordering being incorrect. To solve this we now make sure the copied paper belongs to the same group as the original. We then rebuild the panel to update and get the correct paper ordering.
Additionally, when multiple papers within a group where copied one of the papers would have an additional copy made. This has been fixed by making sure the specific paper is only copied once.
Previously when changing any of the pageSetup settings in paperSpace (such as paper resolution, margins or paper dimensions) and creating a new drawing, the settings were reset to their default values. Changes have now been made to reflect the most recent change made to a paper. A new drawing will thus have the same settings as the last paper created.
When moving the 2D view rectangle in paperspace users would experience significant lag due to a costly rebuild2D invalidation call each frame. This lag is mitigated by instead running the rebuild in the snappers' updateContent method.
PhotoSnapper now shows unrendered photos in the photo series. Double clicking a PhotoSnapper now opens a SelectPhotoDialog.
Rewrite of probes.
Public classes: Probe - Single probe. Probes - Collection of all probes. ProbeTest - Single probe test. ProbeTests - All probe tests for a single probe. ProbeTestResult - Calculates median, avg, min, max etc for a ProbeTests.
Contains functionallity to:
The following classes and functions have been removed:
cm.core.technologyPartners
:
Removed: public void showTechnologyPartners(Window parent, str key=null);
cm.core.legacy.oldAboutDialog
:
Removed: public class OldAboutDialog; Removed: public OldAboutDialog showOldAboutDialog(Window parent);
cm.core.ui.aboutDialog
:
Removed: public class AboutDialog; Removed: public void showAboutDialog(Window parent, str key=null);
cm.core.ui.cetAboutDialog
:
Removed: public class CetAboutDialog; Removed: public CetAboutDialog showCetAboutDialog(Window parent);
cm.win.technologyPartnersDialog
:
Removed: public class TechnologyPartnersDialog; Removed: public TechnologyPartnersDialog showTechnologyPartnersDialog(Window parent);
The following classes have their parent class changed:
cm.abstract.consumer.ConsumerAboutDialog: AboutDialog -> DialogWindow cm.abstract.consumerG2.ConsumerAboutDialog: AboutDialog -> DialogWindow
To show the new About CET dialog, call cm.core.ui.showAboutCet(Window parent)
// cm/core/graph/gAdvImage.cm, Class: GAdvImage Old: final public mrgn combinedClipRgn(Canvas gd, mrgn oldRgn) New: final public mrgn combinedClipRgn(ToPixelCanvas gd, mrgn oldRgn) // cm/core/windowView.cm, Class: WindowView Old: public Canvas canvas New: public ToPixelCanvas canvas // cm/draw/canvas.cm, Class Canvas Old: public constructor(PixelDevice c) New: public constructor() Removed: public PixelDevice dc // cm/draw/canvas.cm, new global function to make things compile easily rather than casting the Canvas to ToPixelCanvas New: public PixelDevice getCanvasDC(Canvas c) // cm/draw/gdiCanvas.cm Old: public class GdiCanvas extends Canvas New: public class GdiCanvas extends ToPixelCanvas // cm/std/print/photoLayoutSnapshot.cm, Class PhotoLayoutSnapshot Old: extend public void draw(Canvas canvas, rectI targetRect) : abstract New: extend public void draw(ToPixelCanvas canvas, rectI targetRect) : abstract // cm/std/print/photoLayoutSnapshot.cm, Class PhotoLayoutREDSnapshot Old: public void draw(Canvas canvas, rectI targetRect) New: public void draw(ToPixelCanvas canvas, rectI targetRect)
CollAccountType
and all related classes are undeprecated to be used for holding subscription tier information.
# collAccountTypes.cm Old: public class CollAccountTypes : deprecated New: public class CollAccountTypes Old: public class CollAccountType : deprecated, abstract New: public class CollAccountType : abstract Old: public class CollAccountTypeFree extends CollAccountType : deprecated New: public class CollAccountTypeFree extends CollAccountType Old: public class CollAccountTypeCorporate extends CollAccountType : deprecated New: public class CollAccountTypeCorporate extends CollAccountType Old: public class CollAccountTypeAdvanced extends CollAccountType : deprecated New: public class CollAccountTypeAdvanced extends CollAccountType # collProjectController.cm Old: public str accountTypeKey : deprecated New: public str accountTypeKey
The following accessors/mutators related to CollFileG3
are removed in favour of using a static type key to access files.
# collCollection.cm Removed: extend public CollFileG3{} serverFiles(CollFileType type) Removed: extend public symbol{} serverFileIds(CollFileType type) Removed: extend public CollFileG3{} editFiles(CollFileType type) Removed: extend public symbol{} loadedFileIds(CollFileType type) Removed: extend public CollFileG3{} loadedFiles(CollFileType type) # collFile.cm Removed: extend public CollFileG3{} files(CollFileType t) Removed: extend public symbol{} ids(CollFileType t) Removed: extend public void changeType(CollFileType t) # collFileSubModel.cm Old: extend public CollFileG3{} loadedFiles(CollFileType type) New: extend public CollFileG3{} loadedFiles(str typeKey) # collFileType.cm Old: final public str packageName() New: final public symbol packageName() Old: final public str packageVersion() New: final public version packageVersion()
CollFileG3
and CollUFOFileType
constructors are modified to take in a CollFileTypeId
parameter.
# collFile.cm Old: public constructor(CollFileType type, str name, int v, symbol id) New: package constructor(CollFileTypeId typeId, str name, int v, symbol id) # collUFOFileType.cm Removed: public constructor() Old: public constructor(str id, str description) New: public constructor(CollFileTypeId srcTypeId)
The following file type classes are removed.
Removed: public class CollPdfFileType extends CollDocFileType Removed: public class CollDwgFileType extends CollDocFileType
The signatures of the following utility functions are modified:
# collFileNamer.cm Old: public str getUniqueCopiedName(CollCollectionG3 this, str fileName, CollFileType fileType, collCopyMode mode=collCopyMode.normal) New: public str getUniqueCopiedName(CollCollectionG3 this, str fileName, str fileTypeKey=null, collCopyMode mode=collCopyMode.normal) Old: public str getUniqueNewName(CollCollectionG3 this, str rootName, CollFileType fileType) New: public str getUniqueNewName(CollCollectionG3 this, str rootName, str fileTypeKey) Old: public bool isUniqueFileName(CollCollectionG3 this, str name, CollFileType fileType=null) New: public bool isUniqueFileName(CollCollectionG3 this, str name, str fileTypeKey=null) Old: public bool isUniqueServerFileName(CollCollectionG3 this, str name, CollFileType fileType=null) New: public bool isUniqueServerFileName(CollCollectionG3 this, str name, str fileTypeKey=null) Old: public bool isUniqueLocalFileName(CollCollectionG3 this, str name, CollFileType fileType=null) New: public bool isUniqueLocalFileName(CollCollectionG3 this, str name, str fileTypeKey=null) # collFileType.cm Old: public void unregister(CollFileType type) New: public void unregisterCollFileType(str key) Old: public CollFileType collFileType(str id) New: public CollFileType resolveCollFileType(CollFileTypeId typeId, collReleaseStage stage) # collUFOFileType.cm Old: public CollFileType collUFOFileType() New: public CollFileType collUFOFileType(CollFileTypeId typeId)
In 13.5, the if-as statement and if-as expression were quite "magical", able to apply a wide variety of conversions including function calls and constructors. This can create confusing and error-prone situations.
In 14.0, the if-as statement is limited to membership testing and unboxing conversions (see below). The if-as expression is now exactly equivalent in behaviour to the if-as statement.
public void foo(Object o) { // These two are equivalent if (o as Str) {pln(o.v);} if (o as str) {pln(o);} // These two are equivalent if (o as Int) {pln(o.v);} if (o as int) {pln(o);} // new in 14.0 // These two are equivalent in 14.0 if (o as int) {pln(o);} else {pln("not an int");} pln(o as int ? o : "not an int"); }
public class A { public constructor() {pln(this, " is created");} } public class B { public constructor(A a) {pln(this, " is created from A");} } public class C extends A { public constructor() {} public constructor(A a) {pln(this, " is created from A");} } public void foo(A a) { pln("a=", a); if (a as B) {pln("a as B=", a);} // forbidden in 14.0 if (a as C) {pln("a as C=", a);} } { foo(A()); pln(); foo(C()); }
Since B
does not inherit from A
, if (a as B)
is not valid in 14.0. It only works in 13.5 because there is a constructor which "converts" A
into a new instance of B
.
This happened in practice with DialogWindow
and Button
, respectively, since Button
has a constructor with one required argument of type Window
(and DialogWindow
is a Window
).
Output in 13.5
A(175) is created
a=A(175)
B(165) is created from A
a as B=B(165)
C(171) is created
a=C(171)
B(161) is created from A
a as B=B(161)
a as C=C(171)
Output in 14.0
A(36) is created
a=A(36)
C(79) is created
a=C(79)
a as C=C(79)
The compileFun
CM function has been replaced with a native
implementation, which is faster and cleaner. The remove
optional
argument has been removed as the new version avoids writing the code
to disk in any case.
Old: public Function compileFun(str def, bool output=false, bool remove=true) New: public Function compileFun(str def, bool output=false) Old: public Function compileFun(StrBuf def, bool output=false, bool remove=true) New: public Function compileFun(StrBuf def, bool output=false)
A similar function which returns all compiled functions in the file, rather than just the first one, has been added.
Added: public Function[] compileFuns(str def, bool output=false) Added: public Function[] compileFuns(StrBuf def, bool output=false)
The internal code responsible for finding the appropriate conversion path between types (if any) has been significantly improved. There is a small risk of surprising behaviour since the new algorithm performs an exhaustive search and selects the "best" path, rather than using flawed pruning heuristics.
In some circumstances, the type conversion search may recurse forever; the old version would treat this as a failure to find an appropriate conversion, the new version will treat this as an error.
Old: public bool cm.io.easySave(Object obj, Url url, bool pkgVersions=true, bool fast=false); New: public bool cm.io.easySave(Object obj, Url url, bool pkgVersions=true, bool fast=false, bool verifyCRC=false); Old: public bool cm.io.object.safeReplaceUrl(Url this, Url target, bool xtrace=false) New: public bool cm.io.object.safeReplaceUrl(Url this, Url target, bool verifyCRC=false, bool xtrace=false)
public void foo(FooClass this) { pln(field); // equivalent to this.field } public void foo(fooValue& this) { pln(field); // equivalent to this.field } public void foo(fooValue this) { pln(field); // equivalent to this.field in 14.0 }
The garbage collector (GC) has two different pause-states; "frozen"
and "parked". The former prevents almost all GC activity, the latter
forces the GC to finish any pending work and prevents all GC
activity. The GC interface now exposes gcUnPark
so that CM code can
enter and leave the "parked" state.
Added: gcUnPark();
14.0 makes many changes to the CM-DLL interface, you must rebuild all DLLs.
The CM-DLL interface now uses a secondary version check, allowing breaking API changes without necessarily changing the size of the DllStartInfo struct.
Due to internal refactoring, funFunLinkOffset
has been removed; use
getFunLink(Fun*)
instead.
Removed: int funFunLinkOffset;
We have enabled MSVC errors for comparisons between signed and unsigned values. If you encounter code which you cannot migrate for this (e.g. third-party libraries), add the following lines to your DLL's Makefile to disable the errors.
CFLAGS := $(filter-out /w34287,$(CFLAGS))
CFLAGS := $(filter-out /w34388,$(CFLAGS))
Deprecated: cm.core.ui.HighlightSnapper
The HighlightSnapper
class used for InvalidListDialog
have been deprecated and replaced with the more modern implementation of HighlightVessels
, to resolve some issues with using Snapper for temporary graphics. Consider replacing any relevant usage with highlightInvalidObject()
, or related methods in cm/core/highlightVessel.cm
.
As a consequence, these fields and references to them have also been removed:
Removed: InvalidListDialog::HighlightSnapper{} hlSnappers Removed: DsIncompleteOptionDialog::HighlightSnapper{} hlSnappers Removed: DsCatalogVersionDialog::HighlightSnapper{} hlSnappers
Removed the entire Constraints Toolbox for the following reasons:
Top Down
and All
is now deprecated.Removed: public DcDBBuilderShrinkWindow toolboxWindow; Removed: public Display appleStyleDisplay; Removed: public DsRadioButton applyStyleAllRadioButton; Removed: public DsRadioButton applyStyleTopDownRadioButton; Removed: public StateControlGroup applyStyleControlGroup; Removed: public Display constraintTypeDisplay; Removed: public DsRadioButton validConstraintTypeRadioButton; Removed: public DsRadioButton invalidConstraintTypeRadioButton; Removed: public StateControlGroup constraintTypeControlGroup;
New argument to determine the constraint's expression type.
Old: extend public bool validExpression(str exp, StrBuf error) New: extend public bool validExpression(dsiConstraintExpressionType constraintExpType, str exp, StrBuf error)
Column label does not need to be updated dynamically anymore.
Removed: public str labelText()
dcConstraintsUndoOp.cm
is removed as dsiConstraintsApplyStyle
and dsiConstraintType
enumerations are not used anymore.
Removed: public class DcConstraintTypeUndoOp extends DcUndoOp
The following method signatures are changed to accommodate the addition of the constraint expression type.
// DsiExprValidationEnv (dsiExprValidationEnv.cm) Old: public constructor(VxRuntime rt, str expr, DataCatalog cat) New: public constructor(VxRuntime rt, dsiConstraintExpressionType exprType, str expr, DataCatalog cat) Old: extend public void doesNothign(VxExpr e, StrBuf error) New: extend public void doesNothing(VxExpr e, StrBuf error) // dsiVariants.cm Old: public VConstraint dsiCreateConstraint(DataCatalog catalog, str expression) New: public VConstraint dsiCreateConstraint(dsiConstraintExpressionType expressionType, str expression) Old: public bool dsiValidateConstraintExpr(DataCatalog cat, str exp, StrBuf error=null) New: public bool dsiValidateConstraintExpr(DataCatalog cat, dsiConstraintExpressionType exprType, str expr, StrBuf error=null) Old: public str->SFeature dsiVariantsFeatures(DsiPData data, str featureCode) New: public str->SFeature dsiVariantsFeatures(DsiPData data, str featurePath) Old: public str->Object dsiVariantsTableSelectedValues(DsiPData data, str featCode) New: public str->Object dsiVariantsTableSelectedValues(DsiPData data, str featurePath) Removed: public void dsiClearVariantsTableCache()
All interfaces of constraintsApplyStyle
and constraintType
in OFDAHeaderData
are now deprecated.
// OFDAHeaderData Deprecated: private dsiConstraintsApplyStyle _constraintsApplyStyle : deprecated; Deprecated: extend public dsiConstraintsApplyStyle constraintsApplyStyle() : deprecated Deprecated: extend public dsiConstraintsApplyStyle constraintsApplyStyle=(dsiConstraintsApplyStyle constraintsApplyStyle) : deprecated Deprecated: extend public dsiConstraintType constraintType() : deprecated Deprecated: extend public dsiConstraintType constraintType=(dsiConstraintType constraintType) : deprecated
Commit ae48deba Removed the acceptAccessory() method in favor of the acceptLocation() method on AccessoryEnv.
The visibility of DsControlPanelPage is no longer affected by whether the Catalog Browser is turned on or not. It will be always visible in control panel. The "Package required" and "Extensions" under Portfolio Info in "Catalogue Details" dialog will now show the target extensions of the portfolio if any.
A few methods that responsible to check for "Catalog Details" visibility has been removed in 14.0.
// class DsControlPanelPage Removed: final public bool isCtlgBrowserTurnedOn() Removed: extend public void setCatDetailsVisibility(bool visible) Removed: public void dsEnableCatDetails(bool enable)
Embedded extension's 'getCatEmbeddedExtensions' method has been renamed to license for clarity.
// class DsCatInfoView Old: extend public str getCatEmbeddedExtensions(str[] embedded) New: extend public str getCatRequiredLicenses(DsCatCatalogue cat) // class DsCatInfoView Old: extend public str getCatEmbeddedExtensionNames(str[] pkgs) New: extend public str getCatEmbeddedExtensionNames(DsCatCatalogue cat)
Introduced a new class DsToolboxCreatorDragAnimation
that responsible dragged item removal. With this new added class, all item's drag animation inheritance has been updated accordingly.
New: public class DsToolboxCreatorDragAnimation extends DsDragAnimation New: public class DsToolboxCreatorThumbnailViewMoveDragAnimation extends DsThumbnailViewMoveDragAnimation Old: public class DsToolboxCreatorFillerInsertDragAnimation extends DsThumbnailViewMoveDragAnimation New: public class DsToolboxCreatorFillerInsertDragAnimation extends DsToolboxCreatorThumbnailViewMoveDragAnimation Old: public class DsToolboxCreatorSchemeButtonInsertDragAnimation extends DsDragAnimation New: public class DsToolboxCreatorSchemeButtonInsertDragAnimation extends DsToolboxCreatorDragAnimation Old: public class DsToolboxCreatorGroupInsertDragAnimation extends DsDragAnimation New: public class DsToolboxCreatorGroupInsertDragAnimation extends DsToolboxCreatorDragAnimation Old: public class DsToolboxCreatorImageSectionInsertDragAnimation extends DsDragAnimation New: public class DsToolboxCreatorImageSectionInsertDragAnimation extends DsToolboxCreatorDragAnimation
The following Excel-related classes in cm.abstact.interop.excelObj.cm are now deprecated, as there are identical classes in cm.core.msOffice.excel with more functionalities.
// cm.abstract.interop.excelObj.cm Deprecated: public class ExcelObj extends NetObj : deprecated Deprecated: public class ExcelWorkbook extends NetObj : deprecated Deprecated: public class ExcelSheet extends NetObj : deprecated Deprecated: public class ExcelRange extends NetObj : deprecated
Data catalogue behaviors (K2XpToDataControllerBehavior) will now use the 'Code' field from Smart Objects (XpSnapperSpawner) as part no. The Part No field on XpDataBehavior is no longer used, but remains to make the transition easier.
Removed: K2Assortment::public K2StyleStore styleStore
Old: extend public K2PropDef propDef(XpPropDef def) { New: extend public K2PropDef propDef(XpPropDef def, XpShape shape) {
Old: public constructor(XpPropDef xpPropDef) { New: public constructor(XpPropDef xpPropDef, XpShape shape) {
Removed: public class K2StyleStore
Old: public Class{} allNonAbstractSubclasses(Class definition) { New: private Class{} allNonAbstractSubclasses(Class definition) { Removed: public Class[] runtimeGetAllXpDefinitions() { Removed: public void checkXpDefinitions() { }
Old: public class K2SnapperSpawner extends SnapperSpawner : inherit constructors { New: public class K2SnapperSpawner extends SnapperSpawner : abstract, inherit constructors {
Removed: public K2PropDef toK2PropDef(XpPropDef xpPropDef, K2Assortment assortment=null) { Old: public PropDef toK2(XpPropDef xpPropDef, K2Assortment assortment=null) { New: public PropDef toK2(XpPropDef xpPropDef, XpShape shape, K2Assortment assortment=null) { Old: public PropInputSetting toK2(XpPropInputSetting xpPropInputSetting, XpPropDef xpPropDef, str label=null) { New: public PropInputSetting toK2(XpPropInputSetting xpPropInputSetting, XpPropDef xpPropDef, XpShape shape, str label=null) { Removed: public Object k2Default(XpPropDef xpPropDef) {
Old: extend public K2Behavior process(K2Behavior unstreamed, K2Assortment assortment) { New: extend public K2Behavior[] process(K2Behavior unstreamed, K2Assortment assortment) {
Old: public class K2ShapeInvalidationEnv extends K2InvalidationEnv { New: package class K2ShapeInvalidationEnv extends K2InvalidationEnv {
Old: public K2PropDef propDef(XpPropDef def) { New: public K2PropDef propDef(XpPropDef def, XpShape shape) {
Old: public XpShape[] findAlternatives(K2AlternativeEngine this, Line mouseLine=null, Point2D p=null, Space space=null) { New: public XpShape[] findAlternatives(K2AlternativeEngine this, Snapper existing, Line mouseLine=null, Point2D p=null, Space space=null) {
Removed: XpFaceIntersectFilter::public bool excludeEdges
Old: K2ExcludeNotInCornerToCornerFaceOp::public LayerExpr corner0 New: K2ExcludeNotInCornerToCornerFaceOp::public LayerExpr corner0LayerExpr Old: K2ExcludeNotInCornerToCornerFaceOp::public LayerExpr corner1 New: K2ExcludeNotInCornerToCornerFaceOp::public LayerExpr corner1LayerExpr Old: K2ExcludeNotInCornerToCornerFaceOp::constructor(LayerExpr corner0=null, LayerExpr corner1=null) New: K2ExcludeNotInCornerToCornerFaceOp::constructor(LayerExpr corner0LayerExpr, LayerExpr corner1LayerExpr)
Removed: K2Library::extend public str splitStr(str s, int length) { Old: public constructor(LayerExpr expr=null, str sortKey=null, function() viewModeHook=function k2SetDefaultViewModes) { New: public constructor(LayerExpr expr=null, str sortKey=null, function() viewModeHook=function k2SetDefaultViewModes, int maxVisibleSpawners=20) {
Removed: K2GeneralLibrary::extend public void addProjectInfoLimb(LibraryLimb parent) {
Removed: K2InsertNodeChooser::public K2InsertNodeFinder finder
Removed: public class K2InsertNodeFinder
Old: public XpFace[] worktopCandidateFacesToShapeAlternativeFaces(XpFace[] candidates, LayerExpr faceFilter, WindowView view) { New: public XpFace[] buildWorktopCandidateFaces(XpFace[] faces, LayerExpr candidateTag, WindowView view) { Old: public void bridgeWorktopCandidateFaces(XpFace[] candidates) { New: private void bridgeWorktopFaces(XpFace[] candidates) { Old: public void adaptAdaptableWorktopFaces(XpFace[] faces) { New: private void adaptAdaptableWorktopFaces(XpFace[] faces) {
Old: public XpFace[] soffitCandidateFacesToShapeAlternativeFaces(XpFace[] candidates, LayerExpr faceFilter, WindowView view) { New: package XpFace[] buildSoffitCandidateFaces(XpFace[] faces, LayerExpr faceFilter, WindowView view) {
Old: public XpWorktopShape k2DefaultWorktopShapeAlternative(XpFace[] candidateFaces, XpFace[] joints, Line mouseLine=null, Point2D p=null, double z=0, LayerExpr layer=null) { New: package XpWorktopShape defaultWorktopAlternative(WorktopAlternativeEnv env) { Old: public XpWorktopShape k2ExtendBackWorktopShapeAlternative(XpFace[] candidateFaces, XpFace[] joints, Line mouseLine=null, Point2D p=null, double z=0, LayerExpr layer=null) { New: package XpWorktopShape extendBackWorktopAlternative(WorktopAlternativeEnv env) { Old: public XpWorktopShape k2ExtendOverlappingBackWorktopShapeAlternative(XpFace[] candidateFaces, XpFace[] joints, Line mouseLine=null, Point2D p=null, double z=0, LayerExpr layer=null) { New: package XpWorktopShape extendOverlappingBackWorktopAlternative(WorktopAlternativeEnv env) { Old: public XpWorktopShape k2MergedAndJoinedWorktopShapeAlternative(XpFace[] candidateFaces, XpFace[] joints, Line mouseLine=null, Point2D p=null, double z=0, LayerExpr layer=null) { New: package XpWorktopShape mergedAndJoinedWorktopAlternative(WorktopAlternativeEnv env) { Old: public XpWorktopShape k2ExtendSideWorktopShapeAlternative(XpFace[] candidateFaces, XpFace[] joints, Line mouseLine=null, Point2D p=null, double z=0, LayerExpr layer=null) { New: package XpWorktopShape extendSideWorktopAlternative(WorktopAlternativeEnv env) { Old: public XpWorktopShape createWorktopShapeAlternativeWithJoints(XpFace[] faces, Line mouseLine=null, Point2D p=null, double z=0, XpFace[] joints=null) { New: public XpWorktopShape createWorktopShapeAlternativeWithJoints(WorktopAlternativeEnv env, XpFace[] faces) {
Removed: extend public double frontOverhang() { Removed: extend public double sideOverhang() { Replaced with K2WorktopOverhangModifier (behavior).
Old: extend public void modifyFaces(K2Snapper owner, XpFace[] faces) { New: extend public void modifyFaces(K2Snapper owner, XpFace[] faces, WindowView view) {
Old: public XpFace[] k2GenericSnapperShapeWorktopFaces(K2Snapper snapper, symbol engineTag, double z, double h, double overhang) { New: package XpFace[] k2GenericSnapperShapeWorktopFaces(K2Snapper snapper, symbol engineTag, double z, double h) { Old: public XpFace[] k2AdaptableFrontGapWorktopFaces(K2Snapper snapper, symbol engineTag, double z, double h, double overhang) { New: package XpFace[] k2AdaptableFrontGapWorktopFaces(K2Snapper snapper, symbol engineTag, double z, double h) { Old: public XpFace[] k2AdaptableFrontAndSideWorktopFaces(K2Snapper snapper, symbol engineTag, double z, double h, double overhang) { New: package XpFace[] k2AdaptableFrontAndSideWorktopFaces(K2Snapper snapper, symbol engineTag, double z, double h) {
Old: public class K2GenericInvalidateFun extends K2EngineInvalidateFun { New: private class K2GenericInvalidateFun extends K2EngineInvalidateFun { Old: public class K2AppendArchitecturalCutoutsFun extends K2EngineFun { New: private class K2AppendArchitecturalCutoutsFun extends K2EngineFun {
Old: public Object default() { New: public Object default(XpShape shape) { Old: public XpDomain domain() { New: public XpDomain domain(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) { Old: public XpDomain domain() { New: public XpDomain domain(XpShape shape) {
Old: extend public SubSet subset() { New: extend public SubSet subset(XpShape shape) { Old: public SubSet subset() { New: public SubSet subset(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) { Old: public XpDomain domain() { New: public XpDomain domain(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) {
XpFace now now supports bent faces, i.e a face is described by an arc rather than a line. The bend of the face is controlled by the relativeBendTangentAngle member.
Most things should work the same way for straight faces (whether a face is straight can be checked with isStraight()), but you must be mindful that a face now describes an arc when you use it. For example, a point between p0 and p1 might not be on the face, if it isn't straight.
Because of this, some of its methods has changed name and/or behavior.
Old: final public point center() // midPoint describes the center between p0 and p1, i.e the old center() if you ignore the bend of the face. // The midPoint isn't necessarily located on the face. New: final public point midPoint() // bendZenith describes the center of the arc of the face. // For straight faces, this is the same as midPoint(). New: final public point2D bendZenith()
Old: final public double length() // The actual length of the worktop, considering the bend. // Always greater than or equal to the old length(). // Equals the old length() for straight faces. New: final public double length() // The length of the straight line from p0 to p1 // Same as the old implementation of length(). // Equals the new length() as well as the old for straight faces. New: final public double backLength()
Old: final public bool contains(point2D& p, double precision=1e-6) // The new implementation ignores the bend of the line. It works exactly the same as before. // Might not be what you want. New: final public bool straightContains(point2D& p, double precision=1e-6) // Returns the distance between a point and the face, including bend. New: final public double distance(point2D p)
Old: final public rect bound() New: final public box bound(double thickness=0) New: final public rect bound2D(double thickness=0)
Old: public constructor(XpFace face) { New: public constructor(XpFace face, XpMeasureBasePropDef def) {
Old: public Object inputAttributes() { New: public Object inputAttributes(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) { Old: public XpDomain domain() { New: public XpDomain domain(XpShape shape) {
Old: public Object inputAttributes() { New: public Object inputAttributes(XpShape shape) { Old: public Object default() { New: public Object default(XpShape shape) { Old: public XpDomain domain() { New: public XpDomain domain(XpShape shape) {
Old: extend public Object default() { New: extend public Object default(XpShape shape) { Old: extend public SubSet subset() { New: extend public SubSet subset(XpShape shape) { Old: public Object default() { New: public Object default(XpShape shape) { Old: public SubSet subset() { New: public SubSet subset(XpShape shape) { Old: public constructor() { New: public constructor(XpMeasureBasePropDef def) {
Old: public str->Object inputArgs() { New: public str->Object inputArgs(XpShape shape) { Old: public Object default() { New: public Object default(XpShape shape) { Old: public SubSet domain() { New: public SubSet domain(XpShape shape) { Old: public class XpMeasurePropDef extends XpPropDef { New: public class XpMeasurePropDef extends XpMeasureBasePropDef {
Old: public XpPropInputSetting propInputSetting(str key) { New: public XpPropInputSetting propInputSetting(str key, XpShape shape) {
Old: extend public Object inputAttributes() { New: extendpublic Object inputAttributes(XpShape shape) { Old: extend public str->Object inputArgs() { New: extend public str->Object inputArgs(XpShape shape) { Old: extend public Object default() { New: extend public Object default(XpShape shape) { Old: extend public XpDomain domain() { New: extend public XpDomain domain(XpShape shape) { Old: extend public SubSet subset() { New: extend public SubSet subset(XpShape shape) {
Old: extend public str->Object args(XpPropDef def) : abstract { } New: extend public str->Object args(XpPropDef def, XpShape shape) : abstract { } Old: public str->Object args(XpPropDef def) { New: public str->Object args(XpPropDef def, XpShape shape) {
Removed: public class XpParentRsStr
Old: extend public XpPropInputSetting propInputSetting(str key) { New: extend public XpPropInputSetting propInputSetting(str key, XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) { Old: public SubSet domain() { New: public SubSet domain(XpShape shape) {
Old: public XpPropInputSetting propInputSetting(str key) { New: public XpPropInputSetting propInputSetting(str key, XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) { Old: public SubSet domain() { New: public SubSet domain(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) {
Old: public Object default() { New: public Object default(XpShape shape) { Old: public SubSet domain() { New: public SubSet domain(XpShape shape) {
Removed: XpWorktopLayout::public double frontOverhang Removed: XpWorktopLayout::public double sideOverhang
MhAfterEngineInitialExportBehavior
interface changes:
Old : extend public void afterInitialExport(MhSnapper parent, MhSnapper owner) {} New : extend public void afterInitialExport(MhSystemCollection system, MhSnapper parent, MhSnapper owner) {}
MhAfterEngineInitialExportBehavior::void afterInitialExport(MhSystemCollection system)
now has a default implementation, moved from MhRowAfterEngineInitialExportBehavior
.
extend public void afterInitialExport(MhSystemCollection system) { Snapper[] sortedSnappers = sortedSystemSnappers(system); for (MhSnapper snapper in sortedSnappers) { if (!system.exportedFromEngine(snapper)) continue; ?MhSnapper parent = snapper.parent; forAllBehaviors (b in snapper) { if (b as MhAfterEngineInitialExportBehavior) { b.afterInitialExport(system, parent, snapper); } } snapper.validateBehaviors(sAfterInitialExport); } }
MhCheckValidFrameChildBehavior
now extends from MhAfterEngineInitialExportBehavior
.
Old : public class MhCheckValidFrameChildBehavior extends MhBehavior New : public class MhCheckValidFrameChildBehavior extends MhAfterEngineInitialExportBehavior
MhCheckValidFrameChildBehavior
interface changes:
Old : extend public bool isInvalidFrameChild(MhSnapper parent, MhSnapper child) { New : extend public bool isInvalidFrameChild(MhSnapper parent, MhSnapper child, MhEngine engine=null) { Old : extend public void removeInvalidChild(MhSnapper parent, MhSnapper child) { New : extend public void removeInvalidChild(MhSnapper parent, MhSnapper child, MhEngine engine=null) {
MhCheckValidFrameChildBehavior
's execution logic has been moved:
Old : public void validate(Object owner, symbol k, MhSnapperChangedEnv env=null) { New : public void afterInitialExport(MhSystemCollection system, MhSnapper parent, MhSnapper owner) {
MhRunEngineEnv
interface changes:
Old : public constructor(bool cleanup=true, bool blockImport=false, bool blockExport=false, bool blockFinalize=true, bool showProgressBar=false) { set*(this: cleanup, blockImport, blockExport, blockFinalize, showProgressBar); } New : public constructor(bool cleanup=true, bool blockImport=false, bool blockExport=false, bool blockFinalize=true, bool removeFailedEntry=true, bool showProgressBar=false) { set*(this: cleanup, blockImport, blockExport, blockFinalize, removeFailedEntry, showProgressBar); }
MhEngineRun
interface changes:
Old : extend public Snapper{} export(MhEngine engine, MhSystemEngineEnvironment env, MhEngineEntry[] entries, Space space=null) { New : extend public Snapper{} export(MhEngine engine, MhSystemEngineEnvironment env, MhEngineEntry[] entries, Space space=null, MhRunEngineEnv runEnv=null) {
The MhRowPopulator
and MhStorageRowPopulator
classes have swapped positions in the parent-child class hierarchy. For classes that extend from MhRowPopulator
, they now need to extend from MhStorageRowPopulator
.
Old : public class MhStorageRowPopulator extends MhPopulator New : public class MhRowPopulator extends MhPopulator Old : public class MhRowPopulator extends MhStorageRowPopulator New : public class MhStorageRowPopulator extends MhRowPopulator
Interface changes in MhRowLayout
:
Old : public MhRowLayout::MhStorageRowPopulator populator; New : public MhRowLayout::MhRowPopulator populator; Old : extend public MhRowLayout::MhStorageRowPopulator rowPopulator(MhStorageConfiguration config, rect systemRect, bool isAisle, bool first, bool lastRow) { New : extend public MhRowLayout::MhRowPopulator rowPopulator(MhStorageConfiguration config, rect systemRect, bool isAisle, bool first, bool lastRow) {
MhClearanceBehavior
constructor interface change. Now able to set a different purposeKey for clearance behaviors.
Old : public constructor() { super("Clearance"); } New : public constructor(str key="Clearance") { super(key); }
Introduced a new engine function MhAnimRowConstructionalFunction
. In 13.5, MhSystemAnimationExportFunction
also handled constructing row entries but in 14.0, we have now moved out that functionality into the new class MhAnimRowConstructionalFunction
.
The class MhSystemAnimationLevelPopulateExportFunction
has also been replaced by MhAnimRowLevelConstructionalFunction
.
Old : res << MhSystemAnimationLevelPopulateExportFunction("animationExport"); New : res << MhAnimRowLevelConstructionalFunction("animRowConstruction"); New : res << MhSystemAnimationExportFunction("animationExport"); Old : public class MhSystemAnimationLevelPopulateExportFunction extends MhSystemAnimationExportFunction { New : public class MhAnimRowLevelConstructionalFunction extends MhAnimRowConstructionalFunction {
Important to note is that "animRowConstruction" is executed before "animationExport".
public class MhRowAnimationEngineBehavior extends MhEngineBehavior { public void putEngineRunFunctions(MhSnapper snapper, symbol event="", Object env=null) { ... if (event == sSnapperInserted) { bool addFloorLevel = mhStorageConfiguration(snapper).?addFloorLevel(); mhPutEngineRunFunction(engine, "animRowConstruction", snapper=snapper, info=info, holeZDomain=holeZDomain, addFloorLevel=addFloorLevel, additionalPrim=additionalPrim); mhPutEngineRunFunction(engine, "animationExport", snapper=snapper, space=space, tryConnectToOtherRow=info.tryConnectToOtherRow, populateOffset=info.unitLoadPopulateOffset(snapper)); } ... }
Check any classes that extend from MhSystemAnimationExportFunction
to see if they should be executed before "animationExport". If this is the case, then they should instead extend from MhAnimRowConstructionalFunction
.
One example of this is MhAnimCantileverConstructionalFunction
which used to extend from MhSystemAnimationExportFunction
but now extends from MhAnimRowConstructionalFunction
.
With these changes, several fields have also been removed from MhSystemAnimationExportFunction
.
The fields below have been moved from MhSystemAnimationExportFunction
to MhAnimRowConstructionalFunction
.
public SubSet holeZDomain; public Bool addFloorLevel; public CollisionPrimitive additionalPrim; public MhRowAnimationInfo info;
The fields below have been removed from MhSystemAnimationExportFunction
without replacement. MhAnimRowConstructionalFunction
now retrieves these values directly from the MhRowAnimationInfo
field.
// removed public Point pos; public Angle rot; // MhRowAnimationInfo extend public MhEngineConstructionEntry createRowEntry(MhEngineEntryBlock block, MhEngineConstructionEntry e) { ... point pos = info.p0; orientation rot = info.a; ... }
New functions mhUnrollCollisionPrim()
which are used to remove roll angles from collision primitives.
/** * Unroll primitive transform. * Collision resolver does not support rolled primitive. */ public CollisionPrimitive mhUnrollCollisionPrim(CollisionPrimitive prim) { CollisionPrimitiveSet set(null, null); CollisionPrimitive[] prims(); mhUnrollCollisionPrim(prim, prims); for (p in prims) set.subPrims << p; return set; } /** * Unroll collision primitive. * @list : result will be appended to the list. */ public void mhUnrollCollisionPrim(CollisionPrimitive prim, CollisionPrimitive[] list) : inline { if (!list) init list(); prim.?explode(list); for (p in list) if (p.t.rot.roll != 0deg) p.t -= Transform(orientation(0deg, 0deg, p.t.rot.roll)); }
Deprecated MhEngineSnapperEntry::zeroTransformSnapperEntry()
method, calls to this method should be replaced with mhUnrollCollisionPrim()
.
Removed MhLevelPopulateFunction::orientedCollisionEntry()
method, calls to this method should be replaced with mhUnrollCollisionPrim()
.
Two additional parameters have been added to this function.
loadWithinLimit
: Set this parameter to true
to ensure that the calculated bay height includes all unit loads within the bay bound.filter
: You can now pass in a SnapperFilter
different from mhBayChildrenFilter
.Old : public <double, int, double> mhCalculatedBayHeight(MhSystemConfigurationItem this, MhSnapper bay, int stepCount, double maxBayHeight=maxDouble, bool xtrace=false) { New : public <double, int, double> mhCalculatedBayHeight(MhSystemConfigurationItem this, MhSnapper bay, int stepCount, bool loadWithinLimit=false, SnapperFilter filter=mhBayChildrenFilter, double maxBayHeight=maxDouble, bool xtrace=false) {
This function has been updated to support top levels (top level will be processed last by populator). It also better supports non-selective racks (e.g. levels with a roll angle).
There has been various changes to rename "row width" to "row cross aisle" and "row length" to "row down aisle".
The following classes have been renamed:
Old : MhRowWidthInsertAnimation New : MhRowCrossAisleInsertAnimation Old : MhRowLengthInsertAnimation New : MhRowDownAisleInsertAnimation
MhRowAnimationInfo
interface changes:
// Fields Old : /** * Length. X-axis. */ public double length = 1m; New : /** * Down aisle dimension. X-axis. */ public double downAisleDist = 1m; Old : /** * Width. Y-axis. */ public double width = 1.5m; New : /** * Cross aisle dimension. Y-axis. */ public double crossAisleDist = 1.5m; Old : public props : cached=false { ... "length"; "width"; ... } New : public props : cached=false { ... "downAisleDist"; "crossAisleDist"; ... } // Methods Old : extend public double minRowLength() { New : extend public double minRowDownAisleDist() { Old : extend public double minRowWidth() { New : extend public double minRowCrossAisleDist() {
MhRowInsertAnimation
interface changes:
Old : extend public MhRowLengthInsertAnimation lengthAnimation() { New : extend public MhRowDownAisleInsertAnimation lengthAnimation() {
MhRowDownAisleInsertAnimation
interface changes:
Old : extend public MhRowWidthInsertAnimation widthAnimation() { New : extend public MhRowCrossAisleInsertAnimation widthAnimation() {
MhRowLayout
interface changes:
Old : public double aisleW; New : public double aisleWidth : stream=null;
// public class MhSnapperRemoverVessel // Consolidated into MhSpreadToolEnv Removed field: public MhSnapperSpreadPattern spreadPattern; New: extend public MhSnapperSpreadPattern spreadPattern() New: extend public MhSnapperSpreadPattern spreadPattern=(MhSnapperSpreadPattern p) Removed field: public SpreadPatternGroup currentSpreadGroup; New: extend public SpreadPatternGroup currentSpreadGroup() New: extend public SpreadPatternGroup currentSpreadGroup=(SpreadPatternGroup g) // public class MhSnapperSpreadVessel // Consolidated to MhSpreadToolEnv Removed field: public MhSnapperSpreadPattern spreadPattern; Removed field: public SpreadPatternGroup currentSpreadGroup; Old: extend public CoreObject[] getCandidates() New: extend public CoreObject{} getCandidates() // cachedSpreadSnappers globals and public functions - moved into MhSnapperSpreadVessel Removed function: public void clearCachedSpread() Removed function: public (CoreObject{}) cachedSpreadSnappers(str key) Removed function: public void putToCachedSpreadSnappers(str key, CoreObject{} ss) Removed function: public void updateCachedSpreadAfterExplode(Snapper parent, box[] markedInfoBounds, MhSnapper[] explodedChildren, str cacheKey) New: extend public void updateSpreadGroupAfterExplode(Snapper parent, box[] markedInfoBounds, MhSnapper[] explodedChildren, str cacheKey) // cached spreadgroups globals and public functions - consolidated into MhSpreadToolEnv Removed function: public void clearSpreadGroups() Removed function: public SpreadPatternGroup spreadGroup(CoreObject[] snappers) Removed function: public SpreadPatternGroup addSpreadGroup(str cacheKey, CoreObject[] snappers) // public class SpreadPatternGroup Removed: public str cacheKey; Old: public constructor(str cacheKey, CoreObject[] snappers) New: public constructor(str key, CoreObject{} candidates) Old: public CoreObject[] snappers(); New: public CoreObject{} candidates(); Old: extend public bool sameGroup(CoreObject[] incomings) New: xtend public bool sameGroup(CoreObject{} incomings) // public class MhSnapperSpreadPattern Old: extend public str cacheKey(MhTrySnapAlternative mainAlt, CoreObject{} candidates) New: extend public void appendCacheKey(StrBuf buf, SnapAlternative mainAlt, CoreObject{} candidates) Removed: extend public MhSnapperInsertEntry[] getCachedEntries(MhTrySnapAlternative mainAlt, CoreObject{} candidates) Removed: extend public void cacheEntries(MhTrySnapAlternative mainAlt, CoreObject{} candidates, MhSnapperInsertEntry[] entries)
// globals Removed: public mhLazyGlobal MhBehavior mhStdSpreadCacheKeyBehavior = MhSpreadCacheKeyBehavior(); // public class MhSpreadPatternBehavior extends MhBehavior New: extend public MhSnapperSpreadPattern spreadPattern(MhSnapperSpreadPattern current, MhSnapper candidate) New: extend public void appendCacheKey(StrBuf buf, MhSnapper main, SnapAlternative alternative, MhSnapperSpreadPattern pattern)
// public class MhStorageSystemSpreadPattern Removed field: public str->MhSnapperInsertEntry[] cache(); // Moved to SpreadPatternGroup // Various SpreadPattern subclasses that existed solely to customize cacheKey Removed: public class MhUnitLoadNoSpreadPattern extends MhNoSpreadPattern Removed: public class MhUnitLoadBaySpreadPattern extends MhStorageBaySpreadPattern Removed: public class MhUnitLoadLevelSpreadPattern extends MhStorageLevelSpreadPattern Removed: public class MhUnitLoadRowLevelSpreadPattern extends MhStorageRowLevelSpreadPattern Removed: public class MhUnitLoadRowSpreadPattern extends MhStorageRowSpreadPattern Removed: public class MhUnitLoadDoubleDeepColumnLevelSpreadPattern extends MhDoubleDeepColumnLevelSpreadPattern Removed: public class MhUnitLoadColumnLevelSpreadPattern extends MhStorageColumnLevelSpreadPattern Removed: public class MhUnitLoadColumnSpreadPattern extends MhStorageColumnSpreadPattern Removed: public class MhUnitLoadSystemSpreadPattern extends MhStorageSystemSpreadPattern
Removed: public class MhNamePlateColumnSpreadPattern
Removed: public class MhFlankProtectorSpreadCacheKeyBehavior // globals Removed: public mhLazyGlobal MhBehavior mhFlankProtectorSpreadCacheKeyBehavior
In UnitLoad
, the public field name
has been replaced by a private field _name
together with public getter and setter methods.
Old : public str name; New : private str _name; New : extend public str name() { New : extend public str name=(str newName) {
By default, the setter method for _name
will trigger mtbhCache()
to be rehashed if the unit load is in the cache. This is because unit load name is used in the hash function of mtbhCache()
and therefore the hash needs to be updated when name is changed.
extend public str name=(str newName) { bool rehashCache = this in mtbhCache(); str res = _name = newName; if (rehashCache) mhRehashUnitLoadCache(); return res; }
The class NetObj2DArray in cm.core.msOffice.excel is now deprecated as there is already an identical class in cm.abstract.interop with the exact same functionality.
// cm.core.msOffice.excel.excelObj.cm Deprecated: public class NetObj2DArray extends NetObj {
Interface classes for creating render jobs have changed, using int64
instead of int
where needed to support large render specs.
// cm.core.red3d.redRenderJobEnv.cm, Class: REDRenderEnv Old: extend public void packageAdded(int total) New: extend public void packageAdded(int64 total) Old: extend public void packageProgress(int current) New: extend public void packageProgress(int64 current) Old: extend public void packageFinished(int total) New: extend public void packageFinished(int64 total)
Interface classes for creating render jobs have changed, using Stream64
instead of Stream
to support larger files.
And also using int64
instead of int
where needed for sizes of large streams/files.
// redRenderFrame.cm, Class: REDRenderFrame Old: final public void serialize(Stream stream) New: final public void serialize(Stream64 stream) // redRenderJob.cm, Class: REDRenderJob Old: final public void packageProgress(bool first, bool last, int incrProgress, int totalProgress) New: final public void packageProgress(bool first, bool last, int incrProgress, int64 totalProgress) // redRenderPackageFactory.cm, Class: REDRenderPackageFactory Old: public int bytesPacked = 0; New: public int64 bytesPacked = 0; Old: final public int totalSize(); New: final public int64 totalSize(); // redRenderSpec.cm, Class: REDRenderSpec Old: final public bool serialize(Stream stream) New: final public bool serialize(Stream64 stream) // renderChore.cm, Class: RenderChore Old: final public void serialize(Stream stream) New: final public void serialize(Stream64 stream) // tile.cm, Class: Tile Old: extend public void serialize(Stream stream) Mew: extend public void serialize(Stream64 stream) // tile.cm, Class: InputTile Old: extend public void serialize(Stream stream) New: extend public void serialize(Stream64 stream)
In cm/std/photo/photoSnapper.cm
an argument has been added to the createNewPhoto
method.
Old: final public void createNewPhoto() New: final public void createNewPhoto(bool loadPhoto=true)
Old: public function initAllProbes() New: public function initProbes() Old: public function destroyAllProbes() New: public function destroyProbes() old: public function probeManager() new: public function probes()
There are two parameters that are affecting this search function in constructor of DropDownTreeView
which are searchable
and searchThreshold
.
searchable
, the search function will only be enabled if true
is passed in, won't be enabled otherwise.searchThreshold
, the search function will only be enabled if the count of TreeViewItem
in this drop down is larger than the threshold, won't be enabled otherwise.public class DropDownTreeView extends BasicTreeView { public constructor(Window parent, ... bool searchable=false, // Added flag to control the search. int searchThreshold=10, // Threshold when to start the search. ...
Added method enableSearch()
in 14.0 to DropDownTreeViewPopup
, which can be used to toggle search window.
/** * Enable search field. */ extend public void enableSearch(bool searchable=true, int searchThreshold=10) { this.searchable = searchable; if (searchable) { this.searchThreshold = searchThreshold; searchField = defaultSearchField(); } }
MemoryStream
.There was previously no way to load DIB images from a stream, which forced the developer to first write the image to file and then loading with the URL. Now that shouldn't be a problem anymore with this new function.
/** * Load the stream of a jpg or png image to DibImage. * * stream - The sequence of bytes that holds the image, it * should be formatted as a jpg or png file. * inlineStream - Write the URL to the image object? * props - The properties on how to read the image. * The stream can be formatted in many ways, this * object tells the reader how to interpret the data. * use - Is the image going to be used after the current thread * has run its course? Then you should set this to true. */ public DibImage dibImage(Stream stream, bool inlineStream=false, ReadImageProps props=dibImageProps, bool use=false) { if (!stream) return null; if (!props.dibPadding) props = props + ReadImageProps(dibPadding=true); ReadImageResult readResult; try { lastLoadImageErrorCode = 0; readResult = imageMagick.read(stream.array, byteCount=stream.count(), pixels=true, blob=false, props=props); } catch (OutOfMemory e) { lastLoadImageErrorCode = 3; return null; } catch (Exception e) { lastLoadImageErrorCode = 4; return null; } if (!readResult) return null; // Not including this test as we still need to read the stream to know the pixel count, // so we've already paid the price to performance if we have a gigantic image //if (imageAreaLimit > 0 and fileReadable and url.imageSize.area() > imageAreaLimit) throw ImageTooBigException(); Dib dib(); if (createDibImageFromDibBytes(readResult.pixels.array, readResult.size.w, readResult.size.h, readResult.channels, dib)) { DibImage image(alpha=props.alpha); image.dib = dib; if (!inlineStream) image.file = stream.path; image.setSize(image.dib.size); image.bitDepth = image.dib.bitDepth(); if (use) image.use(); return image; } return null; }
Some of the files are moved to abstract package to remove dependency to the catalog browser. This means downloaded catalog toolboxed will be visible without having to turned on "Catalog Browser"'s extension.
custom/catalogBrowser/schemes.cm
file has been moved to abstract package cm/abstract/dataSymbol/scheme/layout/
.custom/catalogBrowser/toolboxes.cm
file has been moved to abstract package cm/abstract/dataSymbol/toolbox/
.In custom/dataCatalog/builder/publish/dcPortfolioDetailsSub.cm
, embedDD
field has been rename to license for clarity.
Old : public DsDropDownTreeView embedDD; New : public DsDropDownTreeView licenseDD;
custom.dataCatalog.builder.publish
packageRemoved dependency from custom.dataCatalog.builder.geometry
in custom.dataCatalog.builder.publish
In custom/dataCatalog/builder/publish/dcDeleteConfirmationDialog.cm
, added new class DcConfirmationDialog
and made DcPublishConfirmationDialog
as a subclass of the new class. Also changed the modifier from public
to package
.
We've changed almost everything of the flooring extension by refactoring. Flooring was never intended to be inherited. But we have opened it up a bit to allow reading of flooring information.
// REDRenderGIEnv Old: public void packageAdded(int total) New: public void packageAdded(int64 total) Old: public void packageFinished(int total) New: public void packageFinished(int64 total) // REDRenderJobEnv Old: public void packageAdded(int total) New: public void packageAdded(int64 total) Old: public void packageProgress(int current) New: public void packageProgress(int64 current)
Canvas
implementations that subclass Canvas
directly, instead of a more specific implementation like GdiCanvas
will find many things not working, since many methods have been moved to ToPixelCanvas
. Try subclassing GdiCanvas
or ToPixelCanvas
instead.
Although a local file containing CollUFOFileType
is never created, bug()
will now be triggered as an additional enforcement in the event it is mistakenly created.
Time conversion functions throughout various parts of the system were incorrectly handling daylight-savings transitions. This has been fixed.
The setField
method used to permit almost any value type so long as
the type of the destination field was assignable to Object
. This is
a severe violation of the type system's rules and thus in the new
version, setField
ensures that the type of the instance passed in is
assignable to the type of the destination field.
Basically, the same rules that apply to normal field assignment
(instance.field = value
) now apply to setField
(instance.setField("field", value)
). There is an exception for
unboxing -- for example, you can use setField
to set an int
field,
even though you're passing in an Int
, since setField
takes an Object
.
public class Foo { public constructor() {} public str->str map_field; } { Foo f(); f.setField("map_field", new str->str()); // ok f.setField("map_field", new str->Object()); // forbidden in 14.0 }
When CM has a severe internal error, it will perform a "bail out". In some circumstances, the bail out may itself cause further errors. In 14.0, many of those situations are now handled by "fast fail" instead. If minidump generation or JIT debugging are configured, they will be invoked, otherwise the application will terminate ungracefully.
Some extremely severe errors (e.g. garbage collector state corruption) may go directly to "fast fail" without a "bail out" attempt, leaving no trace in log files.
When calling a DRecord
method that takes the path to a StrArray variable, an additional indexing operator ";;" can now be specified, followed with an integer, to access the value stored at that index.
DRecord root(); root.assign("test.var", StrArray(["one", "two"])); pln(root.lookupStr("test.var;;1")); // output: two
As a result of this change, the substring ";;" can no longer appear in any part of the path to the variable, and can only appear when accessing a StrArray.
DRecord root(); root.assign("test.var;;1", null); // not allowed root.assign("test.v;;ar", 3); // not allowed
This is not something introduced in 14.0. This is something introduced in Windows 10 version 2004 (build 19041) which was released May 2020. This is now covered here because it directly affects how floating-point numbers are rounded and has not been mentioned in any migration guide yet.
This update changes the way the fprint-family formats floating-point numbers. Before the mentioned build, floating-point numbers ending in '5' always rounded up. This was changed in May 2020 to always round to the closest even digit (known as Banker's rounding). This to be more in line with IEEE 754.
This affects all methods which in converts a floating-point number into a string.
Before May 2020:
formatted(1.45, precision=1)=1.5
formatted(1.35, precision=1)=1.4
After May 2020 (currently):
formatted(1.45, precision=1)=1.4
formatted(1.35, precision=1)=1.4
For more information, read Microsoft's Documentation
Certain tags stored in XML will be removed/added in ofdaImport()
and ofdaExport()
. db3 import and export behaviours will also be affected similarly. Hence, forward compatibility would not be supported i.e., importing a newer XML/db3 file into an older version of CET may not have the correct apply style applied to the catalog.
The following classes are affected:
Tags removed:
ConstraintsApplyStyle
ConstraintType
Tags added:
ConstraintExpressionType
The global private bool _blockedUndoHookCB has been removed from photoSnapper and instead added as a public field in the drawRect parent class. This was done since this value needs to be checked during the drawRectUndoHook. Although it is only used by photoSnapper, it was moved to the parent class to avoid drawRect from needing a dependecy on photoSnapper. In order for the photoSnapper subclass to be able to read and modify its value, it was changed to a public variable.
old: cm/std/photo/photoSnapper.cm
private bool _blockUndoHookCB = false;
new: cm/abstract/draw/drawRect.cm
/** * Block undo hook. */ public bool blockUndoHookCB = false;
As a result we now instead modify this public field in cm/std/photo/photoSnapper.cm quickPropertyChanged():
old:
_blockUndoHookCB = true; ... _blockUndoHookCB = false;
new:
blockUndoHookCB = true; ... blockUndoHookCB = false;
As mentioned, the previously named photoSnapperUndoHook has been moved from PhotoSnapper to its parent class DrawRect and renamed drawRectUndoHook. As a result the hook registration has also been moved to the parent class:
cm/std/photo/photoSnapper.cm removed:
/** * Photo snapper undo hook. */ private void photoSnapperUndoHook(World w, UndoStep step) { if (_blockUndoHookCB) return; //double start = microTime(); if (step and step.contains(UndoModifyOp)) { if (!w.isUndoRecording and !isUndoRestoreInProgress) { Space{} affected(4); for (PhotoSnapper s in step.modified) { if (s.space !in affected and s.space.isPaperSpace() and step.affects(s.space)) { affected << s.space; } } if (affected.any) { View{} visited(4); for (space in affected) { for (REDPaperView view in space.views, index=i) { if (view !in visited) { view.invalidatePaperShape(); visited << view; } } } } } } //pln("Invalidate paper shape took: ", us(microTime - start)); }
old:
init { putAlternativesChangedHook("cm.std.photo.photoSnapper", function changedAlternativeHook); registerUndoHook("photoSnapperUndoHook", function photoSnapperUndoHook); }
new:
init { putAlternativesChangedHook("cm.std.photo.photoSnapper", function changedAlternativeHook); }
cm/abstract/draw/drawRect.cm added:
use cm.application;
added:
/** * Draw rect undo hook. */ private void drawRectUndoHook(World w, UndoStep step) { if (step and step.contains(UndoModifyOp)) { if (!w.isUndoRecording and !isUndoRestoreInProgress) { Space{} affected(4); for (DrawRect s in step.modified) { if (s.space !in affected and s.space.isPaperSpace() and step.affects(s.space) and s.drawLayer == bottomLayer and !s.blockUndoHookCB) { affected << s.space; } } if (affected.any) { View{} visited(4); for (space in affected) { for (REDPaperView view in space.views, index=i) { if (view !in visited) { view.invalidatePaperShape(); visited << view; } } } } } } }
added:
init { registerUndoHook("drawRectUndoHook", function drawRectUndoHook); }
Commit ae48deba In createAccessory() now checks to see if the AccessoryEnv accepts the location instead making a new accessory and asking the location if it accepts the accessory.
Old : extend public bool createAccessory(AccGenBehavior behavior, AccLoc loc, CoreObject{} existing) { CoreObject acc = generateAccessory(behavior, loc); if (loc.acceptAccessory(acc)) { behavior.updateAccessory(acc, loc); ... } New : extend public bool createAccessory(AccGenBehavior behavior, AccLoc loc, CoreObject{} existing) { if (acceptLocation(loc)) { CoreObject acc = generateAccessory(behavior, loc); behavior.updateAccessory(acc, loc); ... }
Creating a COMaterial will always create a GMaterial3D. It will use a PBRMatSpec as its spec. Selecting a texture from the COMaterial dialog will set the baseTextureUrl of the spec, while selecting a color from the dialog will set the baseColorFactor of the spec.
cm/abstract/material/comMaterialDialog.cm and cm/abstract/industry/comMaterialDialog.cm:
Constructor:
old: if (!tempMat) tempMat = CustomerOwnMaterial("COMTEMP", "", colorMaterial3D( 125, 125, 125 )); new: if (!tempMat) tempMat = CustomerOwnMaterial("COMTEMP", "", GMaterial3D());
cm/abstract/material/comMaterialDialog.cm
old: extend public void chooseBtnColorCB() { color c = chooseColorDialog(parent, tempMat.color2D); if (c.isColor) { Material3D m = colorMaterial3D(c); tempMat.updateMaterial3D(m); setControlsEnable(); updateImage(); } new: extend public void chooseBtnColorCB() { color c = chooseColorDialog(parent, tempMat.color2D); if (c.isColor) { PBRMatSpec spec(); spec.baseColorFactor = colorToColorF(c); GMaterial3D m = GMaterial3D(spec); tempMat.updateGMaterial3D(m); setControlsEnable(); updateImage(); } old: extend public void browseUrl() { Url url = coreSettings.get("COMaterialDialog.wrappedImageFile").Url; int imageFileFilterIdx = coreSettings.safeGetInt("COMaterialDialog.fileFilterIdx"); Int fileFilterIdx(imageFileFilterIdx); url = getOpenFileName(this, url, imageImportFilter, filterIndex=fileFilterIdx); if (url and url.isReadable) { setLastUrlAndIndex(url, fileFilterIdx.v); Material3D m = wrappedImageMaterial3D(url); tempMat.updateMaterial3D(m); updateImage(); } new: extend public void browseUrl() { Url url = coreSettings.get("COMaterialDialog.wrappedImageFile").Url; int imageFileFilterIdx = coreSettings.safeGetInt("COMaterialDialog.fileFilterIdx"); Int fileFilterIdx(imageFileFilterIdx); url = getOpenFileName(this, url, imageImportFilter, filterIndex=fileFilterIdx); if (url and url.isReadable) { setLastUrlAndIndex(url, fileFilterIdx.v); PBRMatSpec spec(); spec.baseTextureUrl = url; Material3D m = GMaterial3D(spec); tempMat.updateGMaterial3D(m); updateImage(); }
cm/abstract/industry/comMaterialDialog.cm
old: extend public void chooseBtnColorCB() { color c = chooseColorDialog(parent, tempMat.color2D); if (c.isColor) { tempMat.invalidate(); Material3D m = colorMaterial3D(c); tempMat.updateMaterial3D(m); tempMat._color2D = c; updateImage(); } new: extend public void chooseBtnColorCB() { color c = chooseColorDialog(parent, tempMat.color2D); if (c.isColor) { tempMat.invalidate(); PBRMatSpec spec(); spec.baseColorFactor = colorToColorF(c); GMaterial3D m = GMaterial3D(spec); tempMat.updateGMaterial3D(m); updateImage(); } old: extend public void browseUrl() { Url url = coreSettings.get("IndCOMaterialDialog.wrappedImageFile").Url; int imageFileFilterIdx = coreSettings.safeGetInt("IndCOMaterialDialog.fileFilterIdx"); Int fileFilterIdx(imageFileFilterIdx); url = getOpenFileName(this, url, imageImportFilter, filterIndex=fileFilterIdx); if (url and url.isReadable) { setLastUrlAndIndex(url, fileFilterIdx.v); Material3D m = wrappedImageMaterial3D(url); tempMat.updateMaterial3D(m); updateImage(); } } new: extend public void browseUrl() { Url url = coreSettings.get("IndCOMaterialDialog.wrappedImageFile").Url; int imageFileFilterIdx = coreSettings.safeGetInt("IndCOMaterialDialog.fileFilterIdx"); Int fileFilterIdx(imageFileFilterIdx); url = getOpenFileName(this, url, imageImportFilter, filterIndex=fileFilterIdx); if (url and url.isReadable) { setLastUrlAndIndex(url, fileFilterIdx.v); PBRMatSpec spec(); spec.baseTextureUrl = url; Material3D m = GMaterial3D(spec); tempMat.updateGMaterial3D(m); updateImage(); } } added: private str[] gMatImportFilter() { return [$fileFilterGMatStr, $fileFilterGMatFilter, $allFilesFilter, "*.*"]; }
cm/abstract/industry/customerOwnMaterials.cm
added: extend public void updateGMaterial3D(Material3D mat) { material3D = mat; _color2D = nocolor; }
cm/std/assetTools/material/lab/mlGMaterial3D.cm
old: final public str{} textureLinksToBase() { if (?(str{}) links = misc.get("textureLinksToBase")) { return links; } return null; } new: final public str{} textureLinksToBase() { if (?(str{}) links = misc.?get("textureLinksToBase")) { return links; } return null; }
Introduced a additional field targetExtensions
to store information regarding content pack's extension that being provided by the webservice. This target extension is currently used to check for the extension dependencies and will automatically enabled when user toogle the catalog's state.
New : public str[] targetExtensions();
Additional enum
value for dsUILevel
is added in 14.0.
public enum dsUILevel : field access { ... card = 4; // Added for 14.0 }
DsPicklistSubWindow now sends all item creation and freeform data creation to the item manager. Previously the item manager would handle some item management and the sub window would handle others.
The following methods/functions were modified.
public void endDrag(pointI p) public void addFreeformItem(DsFreeformItem freeform) public void copyItem() private void dragAnimationDropCB(DsDragAnimation animation, Window window, pointI p)
A DrawSurfaceSnapper will now not display path snap points if the member count is 500 or over. This was done to prevent a bug where only some of the snap points would appear if the count was very great.
XpWorktopTypeBehavior has been deprecated* Instead, the thickness property should be defined on the worktop shape, and the material should be defined on the worktop graphics behavior.
K2Worktop2DBehavior, k2Worktop3DBehavior and K2Backsplash2DBehavior have all been deprecated*. Instead a new behavior called K2WorktopGfxBehavior will replace all of them.
*Deprecated behaviors will remain in 14.0 and should keep functioning. But they are planned to be entirely removed in 14.5.
There is now a devmode warning during system export that is printed when an entry is deemed to have failed a consistency check.
/** * Check for consistency. Return true if exported is consistent with entry. */ extend public bool exportFailed(MhEngineEntry entry, box exportedBound) { box eb = exportedBound; return eb.w != entry.w or eb.d != entry.d or eb.h != entry.h; }
extend public void exportEntry(Space space, MhEngineConstructionEntry entry, MhSnapper parent=null, Snapper{} visited=null) { ... box eb = info ? info.shape.?engineEntryBound() : s.?engineEntryBound(); if (exportFailed(entry, eb)) { if (developMode) pln("Export failed for ".eRed; entry; entry.classification); if (removeFailedEntry.?v) return; } ... }
When loading MhLevelShape
and unstreaming the saved MhClearanceSpec
, we check existing clearance specs in the MhClearanceSpecContainer
of a world. Previously this always checked mainWorld
's clearance specs, but this has now been changed to check against the shape owner's world.
This change addresses checking against incorrect clearance specs when loading a drawing.
extend public void unstreamStoredSpec(ObjectFormatter formatter) { ... Old : if (MhClearanceSpecContainer container = clearanceSpecContainer()) { New : if (MhClearanceSpecContainer container = clearanceSpecContainer(owner.?space.world)) {
Usage of the limitZ
field in MhLevelPopulateFunction
has been updated. In 13.5 the accepts()
method would immediately check against the limitZ
value if it exists, ignoring the maxZ()
method. In 14.0 the accepts()
method will always call maxZ()
, and maxZ()
now returns limitZ
if it exists.
extend public bool accepts(MhEngineEntry parent, MhEngineEntry newLevel) { ... double maxZ = maxZ(parent, prim); ... } extend public double maxZ(MhEngineEntry levelParentEntry, CollisionPrimitive prim) { if (limitZ) return limitZ.safeDouble(); }
Updated the behavior of the accepts()
method. It now returns highestZ <= maxZ
instead of highestZ < maxZ
. Additionally the highestZ
calculation when loadWithinLimit=true
has been updated.
Old : if (loadWithinLimit.?v) { double max = 0; if (CollisionPrimitive prim = newLevel.collisionPrim(engine.MhEngine)) { max = prim.bound.h; } else { for (c in newLevel.children(engine.MhEngine)) { double h = c.localBound.h; max = max(max, h); } } highestZ += max; } New : if (loadWithinLimit.?v) { double max = 0; for (c in newLevel.children(engine.MhEngine)) { if (!c.isUnitLoad) continue; double h = c.localBound.h; max = max(max, h); } highestZ += max; }
MhMobileFloorUpdateBehavior
now has the following key "updateMobileFloorAfterInitialExport".
MhMobilePlatformUpdateBehavior
now has the following key "updateMobilePlatformAfterInitialExport".
The following spawners have had the sFrameAccessory
layer added to their classifications.
MhCornerProtectorSpawner
MhFlankProtectorSpawner
MhUprightProtectorSpawner
applyToCandidateGroup()
no longer always selects the first snapper in the given MhSnapperGroup
. It now also checks for and returns the first snapper in the MhSnapperGroup
that matches the classification of the selection's main snapper.
Old: extend public void applyToCandidateGroup(MhSnapperGroup grp) { if (MhSnapper grpMain = grp.?snappers.get) { } new: extend public void applyToCandidateGroup(MhSnapperGroup grp) { if (MhSnapper grpMain = getGrpMain(grp)) { } /** * Get SnapperGroup main. */ extend public MhSnapper getGrpMain(MhSnapperGroup grp) { if (!grp) return null; for (s in grp.snappers) if (s.classification.eval(selection.?main.MhSnapper.classification)) return s; return grp.?snappers.get; }
The bottomStorageLevel
field in MhBayShape
is now only used when the bay has a floor level.
public class MhBayShape extends MhBoxSnapperShape { /** * HoleZDomain */ extend public SubSet holeZDomain() { ... if (!hasFloorLevel()) res.minV = res.closestSucceeding(bottomStorageLevel).safeDouble; return res; } /** * Append Bottom Storage Primitives */ extend public void appendBottomStoragePrimitives(CollisionPrimitive{} prims, Transform t=null) { double floorZ = -1mm; // Under the floor to ensure collition with first level Bool actualHasFloorLevel = get("configLoadOnFloor").?Bool; if (!actualHasFloorLevel) actualHasFloorLevel = hasFloorLevel(); double bottomZ = (!actualHasFloorLevel.v ? bottomStorageLevel : 0); ... } } public class MhStorageConfiguration extends MhSystemConfiguration { /** * HoleZDomain */ extend public SubSet holeZDomain() { ... double bottomZ = !addFloorLevel() ? bottomStorageLevel.safeDouble : 0; res.minV = res.closestSucceeding(bottomZ).safeDouble; return res; }
Additionally, MhBaySpawner
now also returns a loadOnFloor
value in shapeCreationProps()
from the current configuration.
/** * ShapeCreationProps */ public str->Object shapeCreationProps() { if (currentConfig) { str->Object res = props { ... loadOnFloor=currentConfig.addFloorLevel() ... }
MhCollisionResolver
now always unrolls collision primitives when they are appended to the resolver. This change was made as collision primitives currently do not support resolving collisions with a roll or pitch angle.
/** * Append fixed. */ public void appendFixed(CollisionPrimitive z) { CollisionPrimitive[] list(); mhUnrollCollisionPrim(z, list); for (p in list) fixed << p; } /** * Append. */ public void append(CollisionPrimitive z) { CollisionPrimitive[] list(); mhUnrollCollisionPrim(z, list); for (p in list) prims << p; }
All previous abstract code that initialized CollisionResolver
have been replaced with MhCollisionResolver
.
public class MhCollisionAlternative extends MhTrySnapAlternative { extend public CollisionResolver collisionResolver(Snapper z) { if (!_resolver) _resolver = MhCollisionResolver(); return _resolver; } } public class MhSnapperSpreadPattern : abstract { extend public SnapAlternative[] snapAlternatives(Snapper candidate, MhTrySnapAlternative mainAlt, MhSnapBehavior[] behaviors) { ... MhCollisionResolver cr(); ... } } // cm/abstract/materialHandling/mhResolverFunctions.cm public Point resolveNextTo(CollisionPrimitive prim, CollisionPrimitive fixedPrim, CollisionPrimitive additionalPrim, CollisionVectorOption option) { ... MhCollisionResolver resolver(); resolver.append(option); ... } public bool primConflicts(CollisionPrimitive prim, CollisionPrimitive fixedPrim) { MhCollisionResolver resolver(); ... }
The logic in the load()
method (to load a configuration from a file) has been modified. It now calls setItemProps()
instead of initItems()
.
With this change, it will no longer set owner of items, create MhConfigurationItemGroup
for items, and it will no longer call item.afterInit()
.
Additionally there is a new call to afterLoad()
, which calls afterConfigLoad()
in all items.
/** * After load. */ extend public void afterLoad(RobustFormatter formatter) { for (item in _items) { item.afterConfigLoad(formatter); } }
If there is some logic for classes extending from MhSystemConfigurationItem
that needs to be done after loading a configuration from a file, you may have previously added that code to afterInit()
. You should now override the new method afterConfigLoad()
instead.
/** * After configuration load. */ extend public void afterConfigLoad(RobustFormatter formatter) { }
MhDeepstorageLevelEngineBehavior
now responds different to the sUnitLoadChanged
and sChildShapeChanged
events. It will now run "unitLoadPopulate" regardless of what spread pattern is used, so it will no longer run "unitLoadEnsureClearance" instead.
MhRowSelectionBehavior
has been updated to use the MhRowBackToBackFilter
for flue gap rows (excluding double-deep flue gaps). With this change, selecting flue gap rows will now also select the directly connected top and bottom rows.
MhSnapperShape
now has a new method rotatable()
.
/** * Return true if s is a 'rotation snap'. */ extend public bool rotatable(MhSnapper snapper, Connector s) { return true; }
This is called from MhSnapper.rotatable()
.
/** * Return true if s is a 'rotation snap'. */ public bool rotatable(Connector s) { if (parent) return false; return super(..) and shape.?rotatable(this, s); }
public class SpreadPatternGroup
is now unstreamable
.MhSnapper.spreadFilter()
now returns null
if no MhSpreadSnapperFilterBehavior
has been defined. Consider defining the behavior if required.MhTrySnapAlternative
now sets lastAlternativeSelected
before candidateChanged
and candidateChosen
to ensure the animation acts on the current information.MhUnitLoadSpreadPatternBehavior.spreadPatternDomain()
now returns a ClassSubSet
domain of MhStorageXXXXXXXSpreadPattern
(old: MhUnitLoadXXXXXXXXSpreadPattern
).Added code to modifyCopy(CopyEnv cEnv) and to restored(Snapper s) to address an issue where the ModifyEnv system wasn't updating tiles.
Changes to cm/application/paperSelectionPanel.cm
old:
final public bool loadPaper(Url path=null) { ... if (selectedSpace) { // Assign the same group to the new space in order to ensure that the paper ordering is correct. if (world.isCollWorldG2()) newSpace.group = selectedSpace.group; if (!world.isCollWorld()) newSpace.setOrderNr(selectedSpace.orderNr); } createSmallPagePreviewControl(newSpace); ... }
new:
final public bool loadPaper(Url path=null) { ... if (selectedSpace) { // Assign the same group to the new space in order to ensure that the paper ordering is correct. newSpace.group = selectedSpace.group; newSpace.setOrderNr(selectedSpace.orderNr); } clearAndRebuild(); ... }
The following change makes sure the selected papers are only cloned once:
old:
private void clonePaperCB(Control c) { if (PaperSelectionPanel selector = c.container(PaperSelectionPanel).PaperSelectionPanel) { logEvent("clonePaper", "paperview"); PaperSpace[] toClone(); for (z in selector.inMultiSelect) { toClone << z; } selector.clonePaper(); for (z in toClone) { selector.select(z); selector.clonePaper(); } } }
new:
private void clonePaperCB(Control c) { if (PaperSelectionPanel selector = c.container(PaperSelectionPanel).PaperSelectionPanel) { logEvent("clonePaper", "paperview"); PaperSpace[] toClone(); for (z in selector.inMultiSelect) { toClone << z; } if (toClone.empty()) selector.clonePaper(); for (z in toClone) { selector.select(z); selector.clonePaper(); } } }
Finally, the below line in cm/application/paperUI.cm was changed in order to make tesing easier:
old:
final private SubWindow buildActionPanel(Window parent) { ... groupButton.hide(); ... }
new:
final private SubWindow buildActionPanel(Window parent) { ... if (!developMode) groupButton.hide(); //Show only for testing. ... }
In order to keep the changes of the last paperspace, we need to access the most recent world. In multi-drawing mode, this is straightforward and can be done by accessing the previous world:
cm/std/print/paperspace/paperSpaces.cm
old: public PaperSpace[] allPaperSpaces(World world, bool createIfNone=true) { PaperSpace[] spaces(); if (!world or !world.spaces) return spaces; if (world.isCollWorldG3) createIfNone=false; for (space in world.spaces) if (space as PaperSpace) spaces << space; if (createIfNone and spaces.count() == 0) { spaces << PaperSpace(world, $paperDefaultName, group=null); if (DocumentCreator z = currentDocumentCreatorIfAny()) z.visibilityChanged(); } spaces.sort(function paperSpaceDifference, null); return spaces; } new: public PaperSpace[] allPaperSpaces(World world, bool createIfNone=true) { PaperSpace[] spaces(); if (!world or !world.spaces) return spaces; if (world.isCollWorldG3) createIfNone=false; for (space in world.spaces) if (space as PaperSpace) spaces << space; if (createIfNone and spaces.count() == 0) { PaperSpace newPaperSpace(world, $paperDefaultName, group=null); World prevWorld = session.prevWorld(); if (prevWorld and (PaperSpace prevPaper = prevWorld.getLastPaperSpace())) { newPaperSpace.pageSetup.?assimilate(prevPaper.pageSetup); } spaces << newPaperSpace; if (DocumentCreator z = currentDocumentCreatorIfAny()) z.visibilityChanged(); } spaces.sort(function paperSpaceDifference, null); return spaces; }
In single drawing mode some changes were required in order to be able to access the previous world, which would have otherwise been destroyed before the new paperspace had been created: cm/core/multiWorldManager.cm >>>>>>> b892a94b2ab38fe1f04775d1f9eee139bfae2fd8
old: extend public World create(str id=null) { // old-tech from before LARGEADDRESSAWARE and 64-bits //if (virtualSize() > 1.5GB) { pln(eLtRed, "large virtualSize, ", virtualSize.byteFormat, ", run full gc..."); gc(); pln("done", ePop); } if (dbg_undoRestoreInProgress) { ptrace("force reset undo state for interaction"); dbg_undoRestoreInProgress = false; } bool anyWorld = session.anySelectableWorld; if (singleDrawingMode and anyWorld) close(); World world = lowLevelCreateWorld(id=id); initialize(world); return world; } new: extend public World create(str id=null) { // old-tech from before LARGEADDRESSAWARE and 64-bits //if (virtualSize() > 1.5GB) { pln(eLtRed, "large virtualSize, ", virtualSize.byteFormat, ", run full gc..."); gc(); pln("done", ePop); } if (dbg_undoRestoreInProgress) { ptrace("force reset undo state for interaction"); dbg_undoRestoreInProgress = false; } World worldToClose; bool anyWorld = session.anySelectableWorld; if (singleDrawingMode and anyWorld) { worldToClose = session.mainWorld; worldToClose.?setViewMode(normalViewMode, alert=false); for (v in session.views) { v.unlock(); v.removeClipping(); } } World world = lowLevelCreateWorld(id=id); initialize(world); if (worldToClose) close(worldToClose); return world; }
Before 14.0, item tag info map was streamed with world.auxillary under the key "LITINFO". The map has been moved to world.cachedData which is not streamed with the drawing. The itemTags have a reference to their info hence the infos are already streamed with the drawing. The cache is rebuilt on load. Reason for this change is to avoid infos getting stuck in the drawing causing dependencies to extensions.
The #1 issue from users at CETX last year was the ability to filter individual items in blocks (for example hiding all objects without the #panel category).
To accomplish this a new category was added cCoreBlockCat
that is currently set to #block
. This category resides on BlockSnappers
. All view modes needs to add the cCoreBlockCat
to its categories. Most uses are covered by a change to categoryViewMode(..)
and other standard ViewModes
were modified to always add the cCoreBlockCat
, to ensure as few changes to be done as possible on the manufacturer side. However, do keep these changes in mind as you are migrating and testing for 14.0.
While the category 'cCoreBlockCat` is still available, a last-minute change to 14.0 disabled the category to no longer serve a purpose. This may be revisited.
=======
Added check of active when calling profilerStop()
which prevents a crash if you are stopping before starting.
We introduce a flag which will be set each frame to indicate if the content should be rebuild or not:
cm/core/xclip/xclipWormholeSnapper2D.cm
added: /** * Invalidate clipped snappers. */ public bool inv_clippedGraphicSnappers : copy=null, stream=null, ignore modify notice; added: /** * Update 'scene' to show 'objs'. */ public void updateContent(XClipScene scene, Object{} objs) { if (inv_clippedGraphicSnappers) { content2D.?invalidateClippedGraphicsSnappers(); inv_clippedGraphicSnappers = false; } super(..); }
We also changed the invalidation to simply set this flag instead of running a costly method each frame:
old: public void invalidate_clipContent() { inv_clipContent = true; content2D.?invalidateClippedGraphicsSnappers(); inv_beforeMaster = true; } new: public void invalidate_clipContent() { inv_clipContent = true; inv_clippedGraphicSnappers = true; inv_beforeMaster = true;}
The closest(Object o) method has been updated to return 'v' instead of 'o' if 'o' was a Number.
Old: /** * Return the closest member to 'o' in this subset. */ public Object closest(Object o) { ... if (o as Number) { distance v = o.double.distance; if (v < minV) return minV; if (v > maxV) return maxV; return o; } ... } New: /** * Return the closest member to 'o' in this subset. */ public Object closest(Object o) { ... if (o as Number) { distance v = o.double.distance; if (v < minV) return minV; if (v > maxV) return maxV; return v; } ... }
Nullcheck in PaneTreeNode.toS()
preventing access violation.
If the directory path used to access icons from file didn't have '/' at the end they would appear to work in developMode, but fail in releaseMode. They now fail in developMode as well, to prevent surprises at build.
/** * Put icon database finder extension directory if necessary. * * k - Key differentiating icons of different systems. * Typically this is the package of the extension * that is registering a directory. * dir - Path where icons are located. * Typically this looks something like * "custom/extension-name/res/images/". * * NOTE: The directory must end with "/" or it isn't * going to work in releaseMode. */ public void putIconDbExtensionDir(symbol k, str dir) { if (k !in iconDB) { // This will make the behavior like releaseMode. if (developMode and !dir.endsWith('/')) return; Url[] locations = cmInstalledAll(dir); if (locations.any) { for (l in locations) { } else { iconDB.finder(k, cmNative(dir)); } //Url completeDir = iconDbExtensionDir(dir); //iconDB.finder(k, completeDir); } }
Added: private str getTruncatedPortDesc(str portfolioDesc);
Before 14.0, when a drawing's parts were loaded into the Reconfiguration tool, their owners were removed. In 14.0 this has changed to keeping the original owner. Because the Reconfiguration Tool is creating a drawing in the background and extracting the parts to the ReconfigSpace, the owner's dead space have also been replaced with the current ReconfigSpace.
This change was made because of the parts' need of providing a space, which they do by returning their owner's space. Without a space, the user might experience loss of information while doing things like exporting. Without a correct space, things like sorting the article view on adjusted values stop to work.
While working with parts in the Reconfiguration Tool, all parts can be relied on to have the current ReconfigSpace set as their space.
The following code was/is called after a list of parts are imported into the Reconfiguration Tool:
New: /** * Post processing part list. */ extend private void postProcessList(PartList list) { if (!list) return; for (p in list.parts) { if (list) for (p in list.parts) { if (p.owner) { // Replace the temporary space the parts got when created to the current ReconfigSpace. // The parts need to have their space set to the current ReconfigSpace // for the user to for example be able to sort on adjusted columns. p.owner.space = reconfigCalcSpace(); } } } return list; } Removed: /*********************************************************************** * Post processing ***********************************************************************/ /** * Post process result parts. */ extend public void postProcessResultParts() { //ptrace(#newParts.count); for (p in newParts.parts) { postProcessOrderPart(p, null); } //ptrace(#reused.count); for (k, list in reused) for (row in list.rows) for (p in row.parts) { postProcessReusePart(p, null); } //ptrace(#excess.count); for (k, list in excess) for (row in list.rows) for (p in row.parts) { postProcessExcessPart(p, null); } } /** * Post process order part, with recursion. */ extend public void postProcessOrderPart(Part part, Space orderPartSpace) { //ptrace(#part); removeOwners(part); } /** * Post process reuse part, with recursion. */ extend public void postProcessReusePart(Part part, Space reusePartSpace) { //ptrace(#part); removeOwners(part); } /** * Post process excess part, with recursion. */ extend public void postProcessExcessPart(Part part, Space excessPartSpace) { //ptrace(#part); removeOwners(part); } /** * Remove owners. */ final public void removeOwners(Part part) { if (part) { // Remove owners in children for (c in part.children) if (c) removeOwners(c); // Remove in part part.data.setOwner(null); if ((Snapper{}) set = part.data.owners) set.clear(); } }
See https://git.configura.com/cet/external/base/-/merge_requests/29409
This function is no longer prone to infinite loops and properly generates a string of characters, not their ASCII codes.
The internal printf wrapper function, which is also used for pln
and
pnn
, should now handle invalid characters by replacing them rather
than silently aborting output (and skipping the logfile).
The MemUsage tool has been refactored for better performance and significantly lower memory usage.
Executing code using C-M-SPC
(cm-compilation-interact-line
) in a
file with top-level run blocks used to cause problems due to using the
same namespace. This is fixed in 14.0.
See https://git.configura.com/cet/external/base/-/merge_requests/29350
The Material Handling extension (extensions/custom/materialHandling) has been moved to the base repository (base/custom/materialHandling).
The Essential Guarding extension (extensions/custom/guarding) has been moved to the base repoitory (base/custom/guarding).