Compile Time Changes

Abstract DataSymbol

Modified

public double cm.abstract.dataSymbol.ui.lerp(double from, double to, double lerpTo) : inline
public int cm.abstract.dataSymbol.ui.lerp(int from, int to, double lerpTo) : inline

extend public double DsFreeformPicklistItem::actualQuantity();
private DsFreeformItem DsFreeformPicklistPart._item : copy=reference;

extend public void DsFreeformGridWindow::forceSelect(pointI p);

Old: public void addPropagateProperties(PropDefs defs) {
New: public void dsAddPropagateProperties(PropDefs defs) {

Old: public void addElevationProperty(PropDefs defs) {
New: public void dsAddElevationProperty(PropDefs defs) {

Notes:

  • Use core lerps

Abstract Industry

Removed

public class AisleManager
public class PHNode
final public bool ShelvingGraphicVessel::isDoublePalletRackBody()
public void PHBodyDragAnimationG2::moveMultiSelect(bool refreshMouseInfo=false)

Modified

Due to the removal of the AisleManager class all methods of the AisleManager has been moved to the NoAislePHBody class. During this move some methods also got renamed to clarify the purpose of the methods.

Old: extend public PHBody ShelvingGraphicVessel::palletRactBody()
New: extend public PHBody ShelvingGraphicVessel::phBody()

Old: public double getPotentialAisleWidth(PHBody main, PHBody otherPHBody)
New: public double edgeToEdgeDistance(PHBody main, PHBody other)

Old: public point getMainPositionGivenAisleWidth(NoAislePHBody other, NoAislePHBody main, double aisleWidth)
New: public point adjustPositionToAisleWidth(PHBody main, PHBody other, double aisleWidth)

Old: public ShelvingBody{} getAllGroupShelving(ShelvingBody body)
New: public ShelvingBody{} getSystemShelving(ShelvingBody body)

Old: public ShelvingBody{} getAllGroupShelving(NoAislePHBody phBody)
New: public ShelvingBody{} getSystemShelving(NoAislePHBody phBody)

Old: public bool isAboveOtherBody(NoAislePHBody main, NoAislePHBody other)
New: public bool isAboveOtherBody(PHBody main, PHBody other)

Old: public NoAislePHBody getClosestPHBodyInSpace(Space space, point onFloorPos)
New: public PHBody getClosestPHBodyInSpace(Space space, point onFloorPos, double searchR=3m, SnapperFilter filter=PHBodyFilter())

Old: final public bool LOPositionEnv::isConflicts(box b1, box b2)
New: extend public bool LOPositionEnv::conflicts(box b1, box b2)

Old: extend public void PHBodyInsertAnimationG2::tryUpdateAisle(NoAislePHBody oldClosest)
New: extend public void PHBodyInsertAnimationG2::updateAisleWidth(NoAislePHBody oldClosest)

Old: extend public void PHBodyInsertAnimationG2::tryUpdateMainBody()
New: extend public void PHBodyInsertAnimationG2::updateMainBody()

Old: extend public double PHBodyInsertAnimationG2::getClosestAisle()
New: extend public double PHBodyInsertAnimationG2::getClosestAisleWidth()

Old: public double AisleManager::bottomAisle
New: extend public double NoAislePHBody::getAisleWidth()
New: extend public void NoAislePHBody::setAisleWidth(double newAisleWidth)

Old: extend public double AisleManager::initialAisleWidth()
New: extend public double NoAislePHBody::initialAisleWidth()

Old: extend public NoAislePHBody AisleManager::getTopMost()
New: extend public NoAislePHBody NoAislePHBody::getTopMost()

Old: extend public NoAislePHBody AisleManager::isTopMost()
New: extend public NoAislePHBody NoAislePHBody::isTopMost()

Old: extend public NoAislePHBody AisleManager::getBotMost()
New: extend public NoAislePHBody NoAislePHBody::getBottomMost()

Old: extend public NoAislePHBody AisleManager::isBotMost()
New: extend public NoAislePHBody NoAislePHBody::isBottomMost()

Old: extend public NoAislePHBody AisleManager::getClosestPHBody(bool top=true)
New: extend public NoAislePHBody NoAislePHBody::getClosestPHBody(bool top=true)

Old: extend public NoAislePHBody[] AisleManager::getAllPHBody()
New: extend public NoAislePHBody[] NoAislePHBody::phSystemGroup()

Old: extend public NoAislePHBody[] AisleManager::getAllPHBodyAccordingToDirection(bool top)
New: extend public NoAislePHBody[] NoAislePHBody::phDirectionGroup(bool top)

Old: extend public Snapper{} AisleManager::getAllRelatedSnappers()
New: extend public Snapper{} NoAislePHBody::allConnectedSnappers()

Old: extend public void NoAislePHBody::resetNodeAndRebuild2D()
New: extend public void NoAislePHBody::unlinkAndRebuild2D()

Old: extend public box ShelvingSystemOutlineVessel::getSystemBound(PHNode node)
New: extend public box ShelvingSystemOutlineVessel::getSystemBound(NoAislePHBody ph)

Old: extend public ShelvingSystemOutlineVessel::PHNode getClosestSystemRootNode()
New: extend public ShelvingSystemOutlineVessel::NoAislePHBody getClosestPHBody()

Abstract Kitchen

_scheme field changes

_scheme field have been added to cm.abstract.kitchen.KitchenSnapper and removed from cm.abstract.kitchen.Rack

ChangedScheme() added to KitchenSnapper.

Abstract Labs

LabsScheme

_scheme field has been removed from subclasses in Abstract Labs, since it´s been added to cm.abstract.kitchen.KitchenSnapper.

LabsElevationAutoInsertEnv

LabsElevationAutoInsertEnv needs class types passed in as argument rather than an instantiated LabsElevationArrow object.

Constructor modified on LabsElevationAutoInsertEnv:

    /**
     * Creation.
     */
    public constructor(LabsElevationArrow frontElev, LabsElevationArrow sideElev, LabsElevationArrow worktopElev, LabsElevationArrow rightSideElev=null, LabsElevationArrow backElev=null) {
	elevationAutoInsert(frontElev, sideElev, worktopElev, rightSideElev, backElev);
    }

New constructor cm.abstract.labs.LabsElevationAutoInsertEnv:

    /**
     * Creation.
     */
    public constructor(Class frontElev, Class leftElev, Class worktopElev, Class rightElev=null, Class backElev=null) {

	if (frontElev.extends() in ElevArrow) this.frontElev = frontElev;
	if (leftElev.extends() in ElevArrow) this.leftElev = leftElev;
	if (worktopElev.extends() in ElevArrow) this.worktopElev = worktopElev;
	if (rightElev.extends() in ElevArrow) this.rightElev = rightElev;
	if (backElev.extends() in ElevArrow) this.backElev = backElev;

	elevationAutoInsert();
    }

Abstract Office

  • WorksurfaceSearch and WsPanelSearch have been cleaned up and some methods have been renamed to be more clear. WsPanelSearch was moved to it's own file.

  • Added updateConnectors() to PanelJunctionSnapper.

  • OfficeSpecOption now has a field exportable that can be used for exports (specifically custom SIF) to prevent the option from exporting.

  • Added a method on PanelFrame for getting panels that are tmounted on a specific side.

extend public PanelFrame{} getTMountedPanels(bool up)
  • Added a method for worksurface bottom height
extend public double worksurfaceBottom()
  • Office Material dialog can now be given a label to use.
public OfficeMaterialDialog showOfficeMaterialDialog(Window window, MaterialDomain domain,
						     Material selected,
						     OfficeMaterialLimb limb=null,
						     MaterialSchemeProperty schemeProp=null,
						     str label=null)
  • OfficeMaterialLimb supports the label that can be passed into the Office Material Dialog with a change to the showMaterialDialog() method.
/**
 * Show material dialog.
 */
extend public void showMaterialDialog(Material m, str label=null) {
    showOfficeMaterialDialog(session.mainWindow, domain, m, this, label=label);
}
  • The CustomerOwnMaterials object is stored as an AuxillaryObject now. There is now a global key for getting them, cAOCustomerOwnMatsKey.

  • Renamed function getNewH() to getNewHeight().

  • Added parameter str->Object args to methods on Worksurface for creating/updating WorksurfaceConnectLines and WorksurfaceConnectArc. This was to allow prop data to be passed from the path members to all parts of the connector generation process.

public void createUpdateConnectLine(str id, worksurfaceConnectType ct,
					WorksurfacePathLineTo m,
					point2D last,
					str->WorksurfaceConnectLine currLines,
					str->Object args=null)

public WorksurfaceConnectLine createWksfConnectLine(line2D ln,
							str edgeId,
							worksurfaceConnectType ct,
							ConnectRule rule=null,
							str->Object args=null)

public void updateWksfConnectLine(WorksurfaceConnectLine wcl,
				   line2D ln, worksurfaceConnectType ct,
				   ConnectRule rule=null, str->Object args=null)
  • Worksurface cutouts now use XAPI instead of PropDefs.
Old:  public props {
	(AShape2D[]) "holes" : {
	    Object get(..) {
		return that.getCutouts();
	    }
	}
    }

 New: public xapi {
	public (AShape2D[]) getCutouts(WorksurfacePath p);
    }
  • WorksurfacePathLineTo and WorksurfacePathArcTo have had the id field changed to edgeId to be more consistent with the edgeId field on the connectors that get generated.
Old: public str id;
New: public str edgeId;

Case-insensitive sort (isort) for string types

seq<str, str8, cstr ..: isort() and isorted() previously did regular sort(), this issue has been rectified.

Changes for parttag visibility

In 11.0 part tags no longer add a user category on snappers for visibility. Instead the snappers now iterate over explicit tags and applied tags to add to the layerSet from visibility2D() and visibility3D().

This also means that the part tag categories will no longer be added to the category registry.

rebuildPartTaggingCategories() is now removed since there are no longer any user categories to rebuild.

    /**
     * Visibility 2D.
     * This is a visibility summary over graphs currently produced by the snapper. This is used for visibility filtering on snapper level.
     *
     * If the snapper produces graphs G1, G2, ... GN, with corresponding layer expressions Exp1, Exp2,... ExpN.
     * The returned expression should be equivalent to "or(Exp1, Exp2,... ExpN)".
     */
    extend public LayerExpr visibility2D() {
	if (!layer) {
	    layer = categoryVisibility();

	    if (explicitTags or appliedPartTags.any) layer = or (layer, partTagVisibility());
	    if (chunkId or sectionIdG2) layer = or (layer, collaborationVisibility());
	}

	return layer;
    }

    /**
     * Visibility 3D (similar to visibility 2D)
     */
    extend public LayerExpr visibility3D() {
	if (!layer) {
	    layer = categoryVisibility();

	    if (explicitTags or appliedPartTags.any) layer = or (layer, partTagVisibility());
	    if (chunkId or sectionIdG2) layer = or (layer, collaborationVisibility());
	}

	return layer;
    }

CmSym performance changes

There's been numerous performance optimizations made to CmSym, which has caused a number of API-changes.

Sym stores components in a seq instead of a map

Because components on a sym node are limited, sequences are more efficient than maps both speed wise and storage wise. A number of breaking changes have been made so now we instead store components as a sequence field in SymNode.

Sym features now use an enum

Instead of asking for:

featureProvider("mesh");

You use:

featureProvider(symFeature.mesh);

In this case it's simply better to use:

public SymComponent meshProvider(SymNode this) : inline {

This change is also made for performance reasons.

reps, reps2D and reps3D have been removed

It's been very common for developers to simply add reps() or reps3D() to all their nodes. But it's undesirable to do so because it will implicitly create a LOD for all details, which have negative performance impacts.

Therefore you now have to explicitly ask for the exact details you want:

reps2D(#super)
reps3D(#medium, #high)

This what the previous settings would produce:

reps2D() -> reps2D(#low, #medium, #high, #super)
reps3D() -> reps3D(#low, #medium, #high, #super)
reps()   -> reps(#low, #medium, #high, #super)

(This also excludes the "base" detail level, but it should only exist in Model Lab so you should be able to ignore it).

Note that there's no support for any other 2D detail level than super.

Deprecated sym functions have been removed

A number of sym functions that were deprecated in 10.5 have been removed. This predominantly affects SymHandle methods, such as:

myHandle.setMesh(newMesh);

Which can be replaced with:

symEdit(myHandle) {
    myHandle.xsetMesh(newMesh);
}

or

SymHandle h = sym.beginEditHandle("path.to.handle");
h.xsetMaterial(greenGM);
h.endEdit();

or

SymOwnerNode sym = sym();
sym.beginEdit("path.to.handle");
sym.handle("path.to.handle").xsetMesh(newMesh);
sym.endEdit();

See the 10.0 to 10.5 migration guide for more information.

Do note that previously, handle.setMaterial() used to be able to set the material for the entire model when loaded, but now each node on the model has its own material that blocks xsetMaterial() from being able to set the material. Now it’s required to use xsetGroupMaterial() to set the material for a handle of an imported sym file.

Sym components are now identified by enums

Instead of referring to components with string keys:

node.hasComponent("symReps");
node.getComponent("symReps");
node.removeComponent("symReps");

We now use identifiers:

node.hasComponent(symReps);
node.getComponent(symReps);
node.removeComponent(symReps);

All SymComponent classes have their own entry in the symComponentId:

public enum symComponentId {
    /**
     * An invalid component id, used for deprecated components.
     */
    invalidSymComponent = 0;

    /**
     * All valid components.
     */
    symGMaterial = 1;
    symGfx = 2;
    symMesh = 3;
    symProps = 4;
    symReps = 5;
    ...

Sometimes you'll get a name clash where symReps can either refer to the enum or a method:

public void doStuff(SymNode this) {
    hasComponent(symReps);
}
c:\CetDev\10.5git\base\cm\format\cmsym\component\test\test_components.cm(144, 26):
no function hasComponent(SymReps (symReps(this, false)))

In which case you can explicitly refer to the enum entry like this:

public void doStuff(SymNode this) {
    hasComponent(symComponentId.symReps);
}

This change was introduced for performance reasons.

If you were previously using:

prepareForEdit(h);
h.doStuff();

to update components of a handle, it won't work now and you should use a symEdit block instead.

SymValidationInfo executed programs

Due to changes in sym validation we no longer construct a PathTrie which points out the executed programs. Instead the executed programs are returned directly:

/**
 * Sym validation info.
 */
public class SymValidationInfo {
    /**
     * Rep.
     */
    private SymRep rep : public readable;

    /**
     * Executed programs.
     */
    private SymProgLazyExecEnv[] executedProgs : public readable;
public class SymProgLazyExecEnv {
    public SymExecEnv env;
    public SymProg prog;
    public SymProgs progs;
    public int depth;
    public int order;
    public constructor auto();

This was also made to minimize performance overhead.

Custom DataCatalog

Modified

Old: public void dcCollectExtRefKeys(DsProductType prd, DataCatalog catalog, str->str{} used, str{} visited);
New: public void dcCollectExtRefKeys(DsProductType prd, DataCatalog catalog, str->str{} used);

Old: public DcMaterialToolBoxSubWindow::constructor(Window parent, str key, str label=null,
						    bool showHelp=true, str helpText=null, bool noButtonMode=false,
						    int rightCaptionIndent=0, pointI pos=(0, 0),
						    function(SubWindow c) callback=null, SrcRef src=#:src);
New: public DcMaterialToolBoxSubWindow::constructor(Window parent, str key, DcDBBuilderSpreadsheet spreadsheet,
						    str label=null, bool showHelp=true, bool noButtonMode=false,
						    int rightCaptionIndent=0, pointI pos=(0, 0),
						    function(SubWindow) callback=null,
						    FrameStyle  frameStyle=
						    dsRoundedFrame(dsDialogLightBackgroundBrush),
						    Brush brush=dsDialogDarkBackgroundBrush,
						    DsGridLayoutHelper parentLayoutHelper=null,
						    str helpText=null,
						    str onlineLink=dcOnlineHelpLink("general-commoncomponents",
						    "FindReplace"),
						    SrcRef src=#:src);

Removed

private void custom.dataCatalog.builder._internalUndoCB(Control con);
private void custom.dataCatalog.builder._internalRedoCB(Control con);

public DsGradientButton DcMenuSubWindow::undoBtn;
public DsGradientButton DcMenuSubWindow::redoBtn;

public class custom.dataCatalog.builder.publish.DcCheckBoxCellStyle
public const int custom.dataCatalog.builder.publish.dcCheckBoxSize = 13;

extend public void DcDBBuilderGeometryCard::editExtRefKey();

public class DcEditExtRefKeyWindow;
public class DcEditOptionWindow;
public class DcEditPrdExternalRefKeys;

public DsButton DcExternRefWindow::editExtRefKeyBtn;

extend public void DcModularCard::buildInfoSection(str helpText);
extend public void DcModularCard::buildExtraButton(str buttonKey);

public REDShape DcPreviewSnapperREDView3D::ambientLight;
public REDShape DcPreviewSnapperREDView3D::cameraLight;
public REDShape DcPreviewSnapperREDView3D::distantLight;
extend public REDShape[] DcPreviewSnapperREDView3D::allLights();
extend public void DcPreviewSnapperREDView3D::initLights();
extend public void DcPreviewSnapperREDView3D::updateLights();
extend public void DcProductListSubWindow::selectProduct(str productCode);

public DcFindReplaceSubWindow DcDBBuilderEditMaterialsCard::findReplaceSub;
public DsButtonDropDownTreeView DcDBBuilderEditMaterialsCard::visibleColumnsBtn;
public DsGridLayoutHelper DcDBBuilderEditMaterialsCard::layoutHelper;
extend public DcDBBuilderEditMaterialsCard DcDBBuilderEditMaterialsCard::card();
extend public DataCatalog DcDBBuilderEditMaterialsCard::catalog();
extend public void DcDBBuilderEditMaterialsCard::populateVisibleColumnsDropDown();
public void DcDBBuilderEditMaterialsCard::setSize(sizeI s);
private void removeInvalidProductReferencesFromProductLevel(ProductLevel cur, ProductLevel owner,
							   (str{}) levelsUpdate, int[] currentPath, str prdCat);

public class DcProductListTreeViewCopyDragAnimation;
public class DcTableOfContentsCopyDragAnimation;

extend public void DcDBBuilderEditProductsCard::setProductCatalogFilter(str prodCatCode);
public str DcDBBuilderProductsSS::prodCatCode;
public DsButtonDropDownTreeView DcProductsToolboxSubWindow::showHideDD;
extend public DcDBBuilderEditProductsCard DcProductsToolboxSubWindow::card();
extend public DataCatalog DcProductsToolboxSubWindow::catalog();
extend public void DcProductsToolboxSubWindow::populateShowHideDD()

public str PrdIndTagCategoryCell::getData(int x, int y);
extend private void PrdCategoryCell::getSubData(DsClassificationRefType ref, str{} res, str key);

public DsButton DcTableOfContentsSubWindow::expandAllBtn
public DsButton DcTableOfContentsSubWindowcloseAllBtn;
public DsButton DcTableOfContentsSubWindow::addLevelBtn;
public DsButton DcTableOfContentsSubWindow::addSubLevelBtn;
public DsButton DcTableOfContentsSubWindow::toolboxCreatorBtn;
public DsButton DcTableOfContentsSubWindow::refreshBtn;
public DcTableOfContentsSubWindow::DsGridLayoutHelper layoutHelper;

extend public void DcTableOfContentsSubWindow::updateActivation();

public DsButton DcTableOfContentToolboxSubWindow::expandAllBtn;
public DsButton DcTableOfContentToolboxSubWindow::closeAllBtn;
public DsButton DcTableOfContentToolboxSubWindow::addLevelBtn;
public DsButton DcTableOfContentToolboxSubWindow::addSubLevelBtn;
public DsButton DcTableOfContentToolboxSubWindow::refreshBtn;
public DsGridLayoutHelper DcTableOfContentToolboxSubWindow::layoutHelper;

Notes:

  • DsCheckBoxCellStyle can be used instead of DcCheckBoxCellStyle.

Renamed

Old: public class DcMaterialReferenceValidationEnv1;
New: public class DcMaterialReferenceValidationEnv;

DWG changes

The nurb field in DwgSpline now refers to cm.geometry.brep.BrepBSplineCurve instead of ANurbsCurve. The export methods in Snapper has changed arguments.

DWG import dialog

The dwg import dialog has been overhauled, in that process changes has been made to both functionality of the dialog and it's interface. Settings have generally changed from using last applied from/to coresettings to storing the DwgSettingsEnv in each DwgSnapper and using those settings on all modifications from the import dialog. Presets have been introduced and you can register presets via this function:

 /*
 * Register predefined dwg setting.
 */
public void regPredefinedDwgSetting(DwgSettingsEnv env, bool replace=false) {

Snapper interface

The ExportPaperDwgDialog class has been removed entirely since papers now can be exported from the ExportDwgDialog. When exporting to dwg the user now has the possibility to export 2D-view, 3D-view and/or Papers from paper view (current or all). Due to these changes, some methods have been removed and some have been changed.

These two methods in Snapper now have one single argument. This is to facilitate the need for more arguments now and in the future. The export() method is the method to override in case you want non-default dwg-export behaviour.

    /**
     * Export snapper.
     */
    extend public ExportData export(SnapperExportEnv env) {
	return stdSnapperExport(env);
    }


    /**
     * Export graphical snapper.
     */
    extend public ExportData systemExport(SnapperExportEnv env) {
	if (hasGraphicalSpecial)
	  return stdSnapperExport(env);
	else
	  return export(env);
    }

All the old arguments are contained within the SnapperExportEnv. New is the LayerSet which is used when using ViewMode filtered dwg export. If possible filter your snapper graphics using this filter to avoid returning unnecessary data. The SnapperExportEnv extends CorePropObj to facilitate the need for more arguments in the future.

/**
 * Snapper export env.
 */
public class SnapperExportEnv extends CorePropObj {
    /**
     * Export 2D graphics.
     */
    public bool twoDim;

    /**
     * Export 3D graphics.
     */
    public bool threeDim;

    /**
     * Export item tags.
     */
    public bool itemTags;

    /**
     * The wanted detail of the exported graphics.
     */
    public detailLevel detail;

    /**
     * The wanted layer of the export.
     */
    public LayerSet layer : copy=reference;

    /**
     * Create a new Snapper export env.
     */
    public constructor(bool twoDim=true, bool threeDim=true,
		       bool itemTags=true, detailLevel detail=detailLevel.super,
		       LayerSet layer=normalLayerSet) {
	this.twoDim = twoDim;
	this.threeDim = threeDim;
	this.itemTags = itemTags;
	this.detail = detail;
	this.layer = layer;
    }
}

Public dwg functions

The following public functions have been removed entirely

public void userDwgPaperExport(Window app, Space space, bool initVisible=true, bool applyAndClose=false)

public void userPaperDwgExportToTarget(Window app, Space space, bool initVisible=true, bool applyAndClose=false, Url url=null)

Both could be replaced by the functions

public void userDwgExport(Window app, Space space, bool initVisible=true, bool applyAndClose=false)

public void userDwgExportToTarget(Window app, Space space, bool initVisible=true, bool applyAndClose=false, Url url=null)

DwgExporter class

The constructor() has changed

    public constructor(Space mainSpace, PaperSpace[] paperSpaces=null, bool export2D=true, bool export3D=true, ExportFilterBar exportFilter=null)

Previously it only took a Space as an argument and now a Space and a seq of PaperSpace(s). Any of them can be null. If you only want to export papers then only pass in PaperSpace objects. 2D and 3D only applies to 'Space'.

Also due to this change, the following methods in DwgExporter now takes a Space as an argument.

    extend public void collectSnappers(Space s, SnapperFilter filter=null)

    extend public rect getViewBound(Space s)

DwgSnapper

/**
 * Set env settings.
 */
extend public void setEnvSettings() {

Has been replaced with:

/**
 * Apply settings from env.
 */
extend public void applySettings(DwgSettingsEnv env) {

Insensitive sort (isort) for non-string types

The case insensitive sort methods, isort() and isorted() have been removed for non-string types.

New colored tag view mode

A new colored tag view mode has been added to core and the code can be found in cm.core.partTag.coloredTagViewMode.cm. The colored tag view mode is essentially another way to visualize the tag color of tagged snappers, where the 2D fills of tagged snappers are overridden with the corresponding tag colors.

For customization teams that have similar view modes and plan to migrate to the new colored tag view mode, just replace existing view modes with the new colored tag view mode. Please also remember to replace any references to the old view mode keys with the new colored tag view mode key.

Print API and multiple drawings

We have changed a few functions in the print API (cm.std.print) so that you need to explicitly provide the "correct" world. "Correct" world, in this case, means the world that the function in question wants to operate on. In many cases, we used to rely on session.mainWorld(..). Usually, this works fine but it is more robust to provide the correct world if we have data that refers to it. For instance, you may use methods found in Session, such as worldFromWindow(..) or worldFromAppWindow(..).

PropObj pushProp

The method signature of PropObj::pushProp() has changed.

Old: extend public bool pushProp(str key, PropObj z, Object env=null, StrBuf error=null) {
New: extend public bool pushProp(str key, PropObj z, Object env=null, StrBuf error=null, PushPropsEnv receiverEnv=null, PushPropsEnv pusherEnv=null) {

Singularity Candidates in ToolAnimationG2

Support for Singularity candidates has been added to ToolAnimationG2. This means a variety of new methods in ToolAnimationG2 and Singularity to mirror those related to Snapper and Vessel candidate picking. To turn on Singularity candidate picking in a ToolAnimationG2-derived animation, override singularityCandidateSearch(). If your animation is not meant to handle singularity candidates, the animation itself does not require a migration. Support for picking candidates through XClipWormhole has also been added (using ThruWormholeAnimationCandidatePicker will do this by default). These changes resulted in the following interface changes in FuzzyAnimationHeapCandidatePicker.

extend public void pick(SnapperFilter snapperFilter=null, VesselFilter vesselFilter=null) {

Has been changed to

extend public void pick(SnapperFilter snapperFilter=null, VesselFilter vesselFilter=null,
			    SingularityFilter singularityFilter=null) {

And

extend public void addPicksToHeap(Object[] picks, SnapperFilter snapperFilter, VesselFilter vesselFilter, bool loose) {

Has been changed to

extend public void addPicksToHeap(Object[] picks, SnapperFilter snapperFilter, VesselFilter vesselFilter,
				      SingularityFilter singularityFilter, bool loose, Transform t=null) {

Runtime/Behavior Changes

Abstract Elevations

Elevation Space

Elevation Arrows now works with Favorites, Copy/Paste and Collaboration. Prior to the update, the Space was reset and any added Snapper(s) to the ElevSpace was not coming with the Favorite/Paste/Collaboration load.

To ensure proper behavior any Customization code that uses Elevation Arrow and ElevSpace should consider removing special code that circumvents the previous limitations and that may make the update not work as intended.

Abstract Industry

Animation changes

  • Added animation properties 'Number of racks' and 'Number of rows'.
    • PHBodyInsertAnimationG2
    • PHBodyWidthAdjustingAnimationG2
    • PlacingMultiplePHBodyAnimationG2
  • Added animation properties 'Total length' and 'Total rack count'.
    • ShelvingPropertyStretchAnimation (superStretch)

Shelving insert changes

  • ShelvingSystemInfo.positionShelving() wrongfully offset the first upright by its own width.
  • PHBody.afterShelvingInsert() is called for every PHBody after the shelving has been inserted. This allows for any adjustments needed to be done after the insert. The calls to PHBody.afterShelvingInsert() is done in the same Undo step as the insertion.

Automatic soul key changes

  • Fields marked ignore modify notice and/or stream=null are automatically discarded to prevent them from being part of the soul key.
  • Props with the attribute #stream_null are automatically discarded to prevent them from being part of the soul key.

Compare functions for LOPosition and Layouts

  • Improved the compare functions to take the LOPosition flags front, inner and back into account.
  • Replaced all str->tuple maps with sorted maps that sort on LOPosition according to compareLOPosition() function. The str->tuple maps only sorted on point.toS.

Abstract Labs

Categories

Added symbol and text categories for all labs categories.

Warp space domain registration

Added warp space domain registration for LabsElevationSpace on abstract.labs init to give new viewports visibility to those views.

acceptScheme() overridden

acceptScheme() has been overridden on the following classes:

  • LabsWorktop
  • LabsRackContent
  • LabsRackFront
  • LabsSideSplash

Other classes that were previously overridden:

  • LabsSink
  • LabsTap
  • All Rack types

LabsElevationAutoInsertEnv

LabsElevationAutoInsertEnv needs class types passed in as argument rather than an instantiated LabsElevationArrow object.

Previous constructor cm.abstract.labs.LabsElevationAutoInsertEnv :

    /**
     * Creation.
     */
    public constructor(LabsElevationArrow frontElev, LabsElevationArrow sideElev, LabsElevationArrow worktopElev, LabsElevationArrow rightSideElev=null, LabsElevationArrow backElev=null) {
	elevationAutoInsert(frontElev, sideElev, worktopElev, rightSideElev, backElev);
    }

New constructor cm.abstract.labs.LabsElevationAutoInsertEnv :

    /**
     * Creation.
     */
    public constructor(Class frontElev, Class leftElev, Class worktopElev, Class rightElev=null, Class backElev=null) {

	if (frontElev.extends() in ElevArrow) this.frontElev = frontElev;
	if (leftElev.extends() in ElevArrow) this.leftElev = leftElev;
	if (worktopElev.extends() in ElevArrow) this.worktopElev = worktopElev;
	if (rightElev.extends() in ElevArrow) this.rightElev = rightElev;
	if (backElev.extends() in ElevArrow) this.backElev = backElev;

	elevationAutoInsert();
    }

ElevArrow args

In addition to this, you can leverage the arrowArgs() on LabsRectRack to set fields post-construction as needed. (Don't forget your PropDef).

    /**
     * Arrow Args for auto generated arrows.
     */
    extend public str->Object arrowArgs(str dir=null) { return null; }

Abstract Office

Abstract Office Runtime Changes

  • Fixed an issue where typicals were inconsistently updating their 2D (FO-392)
  • Office material dialog cleanup and adding a method to enable the selection callback to be ran when the dialog tries to select a material.
  • Fix OfficeMaterialSelection to actually use the default size if none is provided.
  • Minor cleanup of tmount methods on PanelFrame.
  • Make animationTrySnap() on worksurface actually return whether it was successful or not, previously it would always return false.
  • Remove arbitrary 1inch inset of left/right snap.
    • Up until now, the left and right snap on PanelFrame were inset by one inch on each side. This was to visually offset the connector graphics since there was code in place to have them functionally behave as if they weren't inset at all.
    • As a result, when subclassing PanelFrame, one would have to either program around this offset by including the one inch in the connectsX() locations for any PanelJunctions, or override the initialLeftSnap(), initialRightSnap(), updateLRSnaps(), and the connectOffset() methods.
    • If you were relying on that offset, you can update your junction's connectsX() method accordingly to no longer use the one inch offset. There is load code on PanelFrame to adjust old drawings to make sure no connections are lost/broken on load.
    • If you want to keep relying on the old offset, you can implement the four methods mentioned in the second bullet point above and add the one inch offsets back in.
  • Move data inititialization for data surfaces to initializeWorksurface()
  • OfficeCabinet now uses visiblePosition() instead of visible3DPosition() for adjusting connector graphics. The visible3DPosition() and visible2DPosition() methods call visiblePosition() by default.
  • PickSkinAnimation now shows the discard property after a skin has been selected.
  • WorksurfaceDragAnimation has been updated to reflect updates to DragAnimation.
  • WorksurfaceInsertAnimationG2:update() has been updated to reflect past updates to InsertAnimationG2:update().
  • Worksurface cutouts have 2D graphics drawn for the holes automatically.

Category Changes/Migration

Coming with 11.0, Categories registered at the Abstract Office level have been drastically changed. This was done with feedback from the F5 and past feedback about categories in general. As such, code updates will be required as part of these changes.

To properly migrate/update to the new categories, a few things need to be done.

First, any place where category symbols were explicitly called out need to be updated. This includes view modes, layers, addSystemCategoriesTo() method on Snapper, systemCategories() method on ItemTag, etc.

Second, consider updating/removing extension specific categories in your custom packages. The new categories cover most of the common office product types so chances are there will be overlap with your current categories.

Because users can manually apply categories to snappers and item tags and can make custom view modes with them, to migrate these over, a migration map must be registered. This has already been done for Abstract Office, but if you are going to map your own categories over to new ones or ones in Abstract Office, you will also need to do this. An example of this is shown below and is taken from Abstract Office.

putCategoryMigratoryMap(cAOPkg, cF5CatUpdateVer, aoCategoryMigrateMap());
/**
 * Since some of the old categories are very generalized and the new
 * sub categories are very specific, we can't accurately map user
 * applied categories, view modes, or view ports.
 *
 * In those cases, we will map the the most general category we can and let
 * the user adjust to a more specific category.
 */
public symbol->symbol aoCategoryMigrateMap() {
    static symbol->symbol cats();

    if (!cats.any) {
	cats.put(#walls, cAOArchWallsCat);
	cats.put(#panels, cAOPanelsPanelCat);
	cats.put(#electric, cAOElectricalCat);
	cats.put(#storage, cAOStorageCat);
	cats.put(#desking, cAOCasegoodsCat);
	cats.put(#seating, cAOSeatingCat);
	cats.put(#worksurfaces, cAOWksfWorksurfaceCat);
	cats.put(#tables, cAOTablesTableCat);
	cats.put(#lighting, cAOLightAccessoryCat);
	cats.put(#legend, cAOLegendsCat);
	cats.put(#isoviews, cAOElevationCat);

	// old sub categories
	cats.put(#panelAnnotation, cAOPanelsPanelTxt);
	cats.put(#panelSym, cAOPanelsPanelSym);

	cats.put(#tableText, cAOTablesTableTxt);

	cats.put(#wsText, cAOWksfWorksurfaceTxt);
	cats.put(#wsSym, cAOWksfWorksurfaceSym);

	cats.put(#ohStorage, cAOStorageUpperCat);
	cats.put(#ohStorageTxt, cAOStorageUpperTxt);
	cats.put(#ohStorageSym, cAOStorageUpperSym);

	cats.put(#storageSym, cAOStorageLowerSym);
	cats.put(#storageText, cAOStorageLowerTxt);
    }

    return cats;
}

The map is defined as old category to new category (symbol->symbol). With this map, you then register it to a global migrator by using the function putCategoryMigratoryMap(). This function takes in symbol that represents the package the categories were registered with (for example cm.abstract.office), a version when the migration is happening (so in this case 11.0.0), and then the map of old to new categories.

/**
 * Package symbol to map of old category and new category.
 */
private CategoryMigrator _catMigrator : keep;

public CategoryMigrator categoryMigrator() {
    if (!_catMigrator) init _catMigrator();

    return _catMigrator;
}


/**
 * Put a migratory map (old category, new category) for a specific package.
 */
public void putCategoryMigratoryMap(symbol pkg, version v, symbol->symbol pairs) {
    categoryMigrator().putMigrator(pkg, v, pairs);
}


/**
 * Put a migratory map (old category, new category) for a specific package.
 */
extend public void putMigrator(symbol pkg, version v, symbol->symbol pairs) {

    version->symbol->symbol verMap = versionMigrateMap.get(pkg);
    if (verMap) {
	  verMap.put(v, pairs);
    } else {
	  version->symbol->symbol temp();
	  temp.put(v, pairs);
	  versionMigrateMap.put(pkg, temp);
    }
}

This registered map will be used when snappers, item tags, view ports, elevations, and custom view modes load to 11.0 to migrate their user applied categories correctly. This happens during loaded1() of these objects. The migrator and its code can be found in cm/core/category/categoryMigrator.cm.

    public void loaded1(ObjectFormatter formatter, LoadFailInfo failInfo) {
	super(formatter, failInfo);

	if (dbg_traceSnapperEvents) ptrace();
	if (dbg_traceSnapperEvWPln) pln("EV: ", this, ".loaded");

	#if (trackSnapperHistory) history(", ld1");
	initVessels();

	if (pkgVersion(#"core", formatter) < version(11, 0, 0)) {
	    migrateCategories(formatter);
	}
    }

    /**
     * Manually migrate any category failures after the migrator has mad an initial pass.
     */
    extend public void migrateCategoryFailures(symbol{} failures) {
	// Subclass responsiblity!
    }

How this works is that when the first object tries to migrate, all registered migration maps will be consolidated down based on their versions. For example, if the current version of Fika is 11.5 and a 10.5 drawing is loaded, migration for 11.0 and 11.5 will be checked and consolidated down for each package. If in 11.0, category A changed to category B, and in 11.5 category B changed to category C, the migrator will have a migrate A to C for all objects whose class is under custom.fika. Categories from core/abstracts will always be migrated after ones for a custom. This can also be handled at the snapper and item tag levels through the migrateCategories() method. This is the method that passes the object to the migrator to be processed. There is also the migrateCategoryFailures() method that gets called after the first pass of migration where extension specific categories should have been migrated. Here you can change how categories from core/abstracts get migrated.

Alt-i consistency improved

Alt-i was specifically inconsistent in 10.5 if a file was saved as UTF-8 instead of UTF-16 because CmScanner skipped the byte-order-mark (BOM). This is corrected in 11.0 and some other adjustments to alt-i should make it more consistent and correct.

In 10.5 alt-i sometimes does not move to the target even though a next-error-list was output. This has been fixed as well in 11.0.

Change to PropDef.adjusted()

Motivation:

  • Cleanup of messy conditional code
  • Speedup for common cases
  • Allow widening conversions (for instance double = int) in assign to make PropObj behave more as the cm language in general.

PropDef.adjusted() is extremely central to all customization code and we need to keep a thorough lookout for any trouble. If any trouble arises, the following debug-tools have been prepared:

  • The original adjusted() remains in PropDef as deprecated_adjusted().
  • cm.props propDef.cm has a tracing constant: private const bool dbg_trace_put = true;
  • PropObj has a deprecated_put()
  • PropObj has a compare_put() which runs both new and old versions to pinpoint what potentially differs
use cm.props, cm.subset, cm.basic;
private class T1 extends PropObj {
    public props {
	double "w" v=0.2 : domain=DoubleEnum(0.2, 0.4);
	distance "d" v=0.3 : domain=DistanceEnum(0.3, 0.5);
	distance "e" v=distance(0.3) : domain=DistanceEnum(0.3, 0.5);
    }
}

{
    T1 z();
    pln(#z."w");
    z."w" = 1; // uses the new PropDef adjusted which allows us to widen Int(1) -> double PropDef field
    pln(#z."w");
    pln(#z."w".class);
}
output:
  z."w"=0.2
  z."w"=1
  z."w".class=Double

{
    T1 z();
    pln(#z."w");
    z.deprecated_put("w", 1); // same behavior as in 10.5
    pln(#z."w");
    pln(#z."w".class);
}
output:
  z."w"=0.2
    PropDef(double w [ reg boxClass=Double]).depr_adj() null value or wrong boxClass double=1.Int, pType.boxClass=Double
  z."w"=0.2
  z."w".class=Double

Upgraded error reporting

{
    T1 z();
    pln(#z."w");
    z."w" = "ddd"; // "w" is a double field
}
output:
  z."w"=0.2
    PropDef(double w [ reg boxClass=Double]).adjusted() value type mismatch: double=ddd.Str

Extended tracing and compare put

cm.props propDef.cm
private const bool dbg_trace_put = true;
{
    T1 z();
    pln(#z."w");
    z."w" = 1;
    pln(z.compare_put("w", "dd"));
}
output:
  z."w"=0.2
  compare_put:
    new
      PropDef(double w [ reg boxClass=Double]).adjusted() value type mismatch: double=dd.Str
    old
      PropDef(double w [ reg boxClass=Double]).depr_adj() null value or wrong boxClass double=dd.Str, pType.boxClass=Double
    new=dd
    OLD=dd
  <dd, dd>
{
    T1 z();
    pln(#z."w");
    z."w" = 1;
    pln(z.compare_put("w", Byte(2)));
}
output:
  z."w"=0.2
  compare_put:
    new
    old
      PropDef(double w [ reg boxClass=Double]).depr_adj() null value or wrong boxClass double=2.Byte, pType.boxClass=Double
    new=2
    OLD=2
  <2, 2>

If you wish to add your own widening conversions to PropDef.put(), please contact dev support.

Supported widening conversions

private Object angleF_sangleF_widener(Object z)
private Object angleF_sangleF_widener(Object z)
private Object angle_orientation_widener(Object z)
private Object angle_orientation_widener(Object z)
private Object angle_sangle_widener(Object z)
private Object angle_sangle_widener(Object z)
private Object byte_double_widener(Object z)
private Object byte_double_widener(Object z)
private Object byte_float_widener(Object z)
private Object byte_float_widener(Object z)
private Object byte_int16_widener(Object z)
private Object byte_int16_widener(Object z)
private Object byte_int64_widener(Object z)
private Object byte_int64_widener(Object z)
private Object byte_int_widener(Object z)
private Object byte_int_widener(Object z)
private Object byte_nat64_widener(Object z)
private Object byte_nat64_widener(Object z)
private Object byte_nat_widener(Object z)
private Object byte_nat_widener(Object z)
private Object byte_word_widener(Object z)
private Object byte_word_widener(Object z)
private Object color_colorF_widener(Object z)
private Object color_colorF_widener(Object z)
private Object distance_double_widener(Object z)
private Object distance_double_widener(Object z)
private Object float_double_widener(Object z)
private Object float_double_widener(Object z)
private Object int16_double_widener(Object z)
private Object int16_double_widener(Object z)
private Object int16_float_widener(Object z)
private Object int16_float_widener(Object z)
private Object int16_int64_widener(Object z)
private Object int16_int64_widener(Object z)
private Object int16_int_widener(Object z)
private Object int16_int_widener(Object z)
private Object int16_nat64_widener(Object z)
private Object int16_nat64_widener(Object z)
private Object int64_double_widener(Object z)
private Object int64_double_widener(Object z)
private Object int8_double_widener(Object z)
private Object int8_double_widener(Object z)
private Object int8_float_widener(Object z)
private Object int8_float_widener(Object z)
private Object int8_int16_widener(Object z)
private Object int8_int16_widener(Object z)
private Object int8_int64_widener(Object z)
private Object int8_int64_widener(Object z)
private Object int8_int_widener(Object z)
private Object int8_int_widener(Object z)
private Object int8_nat64_widener(Object z)
private Object int8_nat64_widener(Object z)
private Object int_double_widener(Object z)
private Object int_double_widener(Object z)
private Object int_float_widener(Object z)
private Object int_float_widener(Object z)
private Object int_int64_widener(Object z)
private Object int_int64_widener(Object z)
private Object int_nat64_widener(Object z)
private Object int_nat64_widener(Object z)
private Object nat_double_widener(Object z)
private Object nat_double_widener(Object z)
private Object nat_float_widener(Object z)
private Object nat_float_widener(Object z)
private Object nat_int64_widener(Object z)
private Object nat_int64_widener(Object z)
private Object nat_nat64_widener(Object z)
private Object nat_nat64_widener(Object z)
private Object point2D_rect_widener(Object z)
private Object point2D_rect_widener(Object z)
private Object point2D_size2D_widener(Object z)
private Object point2D_size2D_widener(Object z)
private Object pointI_point2D_widener(Object z)
private Object pointI_point2D_widener(Object z)
private Object pointI_rect_widener(Object z)
private Object pointI_rect_widener(Object z)
private Object pointI_size2D_widener(Object z)
private Object pointI_size2D_widener(Object z)
private Object point_colorF_widener(Object z)
private Object point_colorF_widener(Object z)
private Object point_color_widener(Object z)
private Object point_color_widener(Object z)
private Object point_version_widener(Object z)
private Object point_version_widener(Object z)
private Object rangeI_range_widener(Object z)
private Object rangeI_range_widener(Object z)
private Object size2D_rect_widener(Object z)
private Object size2D_rect_widener(Object z)
private Object word_double_widener(Object z)
private Object word_double_widener(Object z)
private Object word_float_widener(Object z)
private Object word_float_widener(Object z)
private Object word_int64_widener(Object z)
private Object word_int64_widener(Object z)
private Object word_int_widener(Object z)
private Object word_int_widener(Object z)
private Object word_nat64_widener(Object z)
private Object word_nat64_widener(Object z)
private Object word_nat_widener(Object z)
private Object word_nat_widener(Object z)

Changes for background reports

In 11.0 its a lot easier to get started using background reports. Now there is a single interface in cet/runtime/errorlogger.cm. To send an background report simply call this function with the data you want to include in the report.

New for 11.0 is that files now can be added to the report using the files field.

/**
 * Log error.
 *
 * Origin is an optional reference to issue origin.
 */
public void logError(str message=null,
		     Exception exception=null,
		     CallStack stack=null,
		     StrBuf logOutput=null,
		     SrcRef origin=null,
		     SrcRef loggedAt=#:src,
		     Url[] files=null) {
    errorLogger.logError(..);
}

Changes in Locale Independence for String Comparisons

In 11.0, all built in string type (str) comparison methods have been changed to be locale-independent to ensure deterministic behavior. This includes compare(), icompare(), gt(), lt(), ge(), le(), sort(), isort(), >, >=, <, <=, and sorted maps with str key types.

In previous versions, certain low level drivers were overriding the global locale which resulted in unpredictable behaviors with CET, usually manifesting in issues with displaying the correct $RS value or crashes in worst cases. This change means that the C locale environment variable (LC_ALL) will now be ignored.

What are the effects?

In practical scenarios, this should not affect general behavior such as sorting or localization, as CM has been using the default LC_ALL=C locale, and most UI in CET should be handled transparently with our localization wrappers. However, testing should still be done to ensure there are no undesirable side effects.

How to check if I have any code that is affected?

We have provided a detector for any such methods that may be affected by the changes above. Simply run the code below, and evaluate if each warning need to be fixed (see next sections).

{
  enableLocaleStrCompareWarnings(enable=true, warnings=true);
  cm.runtime.util.qmegaCAB("custom.extensionName");
}

How do I fix the warnings or revert to the old behavior?

We have also provided versions of the methods above, prefixed with lc_, which will behave the same as older versions of CM, including lc_compare(), lc_icompare(), lc_gt(), lc_lt(), lc_ge(), lc_le(), lc_sort(), lc_isort(). These methods would respect the C Locale, however we would recommend to only use them if you are sure you need to.

For sorted maps, you can fix by setting a custom compare function:

{
    sorted str->int test = ["dd"->3, "ee"->4];
    test.setCompare(function lc_compare3);

    public int lc_compare3(str a, str b, Object env) { return lc_compare(a, b); }
}

How to silence (ignore) the warnings?

Simply add // !lc to the end of the line of code.

Changes to Line Styles and Thickness for 2D View and PaperSpace

We have made some changes to Line Styles in 11.0 This affects how they look in:

  • Standard 2D views and paper space (RED/GDI)
  • Print preview and physical print (GDI)
  • Print to PDF

Both line thickness and the look of stippled lines (dot, dash, dash-dot etc) are affected. The default thickness of solid lines should look the same as before.

Note that this will affect any PDF DIFF Tests with references made before 11.0. If you have any references with lines for PDF Diff Tests made before 11.0, the different line styles will cause the diff test to fail if run in 11.0. You will need to make new references in 11.0 for those tests.

You may find more information and some comparison images on this page.

Component

  • selected() now has a CoreObject owner passed through as needed.
    /**
     * Selected.
     * From componentVessel in space OR from pickSurface in view.
     * Return true if taken care of.
     */
    extend public bool selected(View view, WindowViewMouseInfo mi, PickSurface3D surface, CoreObject owner=null) {
	/** Subclass */
	return false;
    }
  • updating methods have been added:
    /**
     * Update Components.
     */
    public void updateComponents() {
	update();
	super(..);
    }


    /**
     * Update
     */
    extend public void update() { /** Subclass */ }
  • CoreObject now has:
    /**
     * Update Components.
     */
    extend public void updateComponents() {
	for (c in components()) c.updateComponents();
    }
     /**
      * Rotate component on insert.
      */
     extend public Orientation componentInsertRotation(Component component, Animation insertAnimation) {
	return null;
     }

Note: Nothing inherently calling this. You still need to manually invoke this as needed.

  • 2D selection has been fixed.

Default Calculation Columns

For a more complete guide/explanation, please refer to this page We have shrunk the default calculations that are visible to these 7:

  • Complete
  • Description
  • Quantity
  • List
  • Manual Sort
  • Options
  • Part Number Every other default core calculation column set to be initially not visible.

Visibility of Abstract DataSymbol Columns

We have made abstract dataSymbol columns not visible by default so you do not get 15 visible columns for turning on an extension with dataSymbol.

  • Area - DsPRdAreaColumn
  • Depth - DsPrdMeasurementColumn
  • Feature Description - DsFeatureDescPartColumn
  • Height - DsPrdMeasurementColumn
  • Length - DsPrdMeasurementColumn
  • Package Count - DsPackageCountColumn
  • Preview - DsPreviewColumn
  • Pricelist - DsPricelistColumn
  • SKU - DsPrdSKUColumn
  • Vendor - DsVendorNameColumn
  • Volume - DsPrdVolumeColumn
  • Weight - DsPrdWeightColumn
  • Width - DsPrdMeasurementColumn

Default Visible Columns in Main Article View

Instead of showing every registered column set to initially visible, we now set a limit of 10 columns to show in the calculation view. These will be determined by votes cast by each extension. The 10 columns with the most votes will show.

These votes should be placed in the extension start. They will be cast once the extension is turned on (for lazy extensions, this means when it is selected in toolbox).

Voting for columns is done like this:

upvotePartColumnVisibility(absUpchargePartColumn.key);
upvotePartColumnVisibility(absSourcePartColumn.key);

For tag columns, there are no public PartColumn classes so you have to specify the key like this:

upvotePartColumnVisibility("#cm.core;TAG1")

You can find core/abstract part columns in the following places:

  • cm/core/init/corePartColumns.cm
  • cm/abstract/dataSymbol/init.cm
  • cm/abstract/part/partColumns.cm

Empty Feature Description

If the feature descriptions are empty in the calculation dialog, do check your overridden DsPart class's infoTrees() method. When constructing a DsOptionInfoTree, pass in the groupDescription argument. As that is what will be shown in the calculation dialog.

ItemTag Change

Version 11.0 introduces a new inspection tool for users to view categories, tags, level, collaboration section, and other information associated with Snapper(s) and ItemTag(s). In order to generically obtain the tag text of an ItemTag (for identification purposes in the dialog), the following method has been added to ItemTag:

    /**
     * Tag Text.
     */
    extend public str tagText() {
	if (info and !info.tagText.emptyOrOnlyWhiteSpace) return info.tagText;
	return $noTagTextFoundFor # " " # toS;
    }

If you implement an ItemTag that does not store its text in its ItemTagInfo, it is imperative that you override tagText() to point towards either the actual displayed text or some other text that identifies the ItemTag.

JsonInt now supports 64-bit integers

cm.format.json.JsonInt now stores the numeric value as int64 instead of int. Be careful when calling JsonInt.int() as the returned value will be incorrect if the real value is not between minInt and maxInt.

// Max int value.
public const int maxInt = 2147483647;


// Min int value.
public const int minInt = (-2147483647 - 1);

Nested soulModify and quickSoulModify

The syntax soulModify and quickSoulModify now supports nesting. The temporarliy spawned soul copy gets replaced by a pure soul at the end of the outermost soulModify/quickSoulModify block.

Optimizations for searching and iterating in a sym

SymNode(s) now hold a mask of all components both on the node and everything below. This means we can now iterate efficiently over the structure if we're searching for something specific.

For example this code would in 10.5 always visit the whole graph, but in 11.0 it will instantly abort if there's no mesh below a node:

for (node in root, filter=SymNodeMeshFilter()) {
    ...
}

Most filters (with the exception of searching for specific node ids or leafs) are now efficient. For example if you would like to visit nodes that contain geometry, with a specific rep and that is tagged you can do this:

SymNodeFilter f = and(SymNodeRepFilter(rep),
		      SymNodeGeometryFilter(),
		      SymNodeComponentFilter(symTags));
for (node in root, filter=f) {
    ...
}

Internally this is used in many places to speed up the handling of syms, and should be used if possible.

Orientation basis vectors

We have corrected the perpendicular() function for orientation and orientationF. Previously it did not return a vector that was orthogonal against the direction/normal vector.

PropScheme and Selection Tool

We have upgraded props scheme with a new look together with the new selection tool dialog(Tools > Advanced Selection ...). Most of the changes for props scheme are related to UI elements.

All related files to PropsScheme has been moved into cm.core.propsScheme directory.

More information can be found in PropsScheme Migration

Sym stretching

The parameters used to control stretching behavior for CmSym models have been changed. Previously the stretch operation took two parameters as input:

  • stretchingEP (bool)
  • wantedLength (double)

This works well for most scenarios but if you change the stretchingEP parameter between different stretch operations you were forced to keep track of how much you stretched in each direction by yourself. To overcome this we have replaced the stretchingEP param with a new param called spOffset. This means that we now use the following two parameters to control the stretch operation:

  • spOffset (double)
  • wantedLength (double)

This means that we from now on always "right stretch" first (stretch the end point of the measure) and then adjust everything stretched by applying an offset - spOffset. If spOffset if positive "everything" will move in the sp -> ep direction. If spOffset is negative "everything" will move in the ep -> sp direction. This gives us two benefits:

  • It means that we always can reproduce the same stretch result by applying these parameters.
  • We can stretch both the starting point and the end point of the measure in a single operation (for instance center stretch).

Note A: Old CmSym files with stretching behavior will continue to function and you may still change the stretchingEP param for these old CmSym files.

Note B: If you import an old CmSym file, with stretching already defined, to Model Lab the old stretch programs will be translated to the new spOffset approach. So if you for some reason want to change an old CmSym model with stretch beavior already defined you must adapt the new way of controlling the stretch operation.

SymProps allowed keys

Keys prefixed with "_" are now reserved for internal use in SymProps only. Any internal key, like localBound, will now use _localBound instead. If you use the props API make sure you don't use the "_" prefix.

SymProps geometry flag has been removed

The hasGeometry flag in SymProps has been removed (corresponding to the symGeometryKey id). It has been replaced with matching against the component mask. The call SymNode.hasGeometry(descend=true) is still fast, and the prop can simply be ignored.

Toolbox cards

In CET 10.5 and older versions, we used to call rebuildAllToolboxCards() when the main app window got resize and resizeEnd. These calls (of course) produce a lot of slow response and flickering, so they have been removed. This means that your custom toolbox cards will no longer get rebuilt on app window resize, and there is no reason they should have to. However, if you really need this, please contact developer support!

Viewport2D deprecated

In order to convert the legacy viewports to XClip view clips, four new methods has been added to the Viewport2D class:

public XClipWormholeSnapper2D createXClipFromViewport() { ... }
public XClipWormholeSnapper2D createXClipFromWormholeCollapsed(Space space = null) { ... }
public void copyConfiguration(XClipWormholeSnapper2D wh) { ... }
public void createCompanionsFromViewport(XClipWormholeSnapper2D wh, XClipWormholeCompanionSnapper[] companions) { ... }

The first two methods generates a XClipWormholeSnapper2D object from the current ViewportSnapper2D instance and can be overridden in case your extended Viewport2D requires some intricate conversion logic.

Copying the Configuration

If your viewport has some additional configuration, this can be converted by simply overriding the copyConfiguration() method, which is called in both viewport conversion methods. Let's look at the base method:

/**
 * Copy configuration.
 */
extend public void copyConfiguration(XClipWormholeSnapper wh) {
    if (!wh.settings) return;
    if (blackAndWhite) wh."whBlackWhite" = true;

    if (ViewMode vm = getRegisteredViewMode(this.?viewModeKey.str)) {
	wh.setViewMode(vm);
    } else {
	wh.setViewMode(ViewMode("cm.core.visibility","newViewModeName", viewModeLayers));
    }

    if (ViewContentFilter filter = viewContentFilter) {
	wh.setViewContentFilter(copyContentFilter(filter));
    }
}

The ViewportSnapper2D class has a member called blackAndWhite, indicating whether the viewport should be without colors. This corresponds to the whBlackAndWhite property of the XClip view clip. The conversion transfers this configuration option to the new view clip in line 3.

Attaching Companions

In some cases, some of your extended viewport functionality can be abstracted into a companion. If this is the case, the method createCompanionsFromViewport() can be extended to automatically create and attach companions to the new XClip view clip based on the current ViewportSnapper2D. Let's look at the implementation of the base method:

/**
 * Create companions from the give viewport.
 * XClipWormholeSnapper wh currently unused, still kept since subclass might need it.
 * XClipWormholeCompanionSnapper[] companions is the list which should be populated with new companions by this method.
 */
extend public void createCompanionsFromViewport(XClipWormholeSnapper wh, XClipWormholeCompanionSnapper[] companions) {
    if (!frameType.none) {
	XClipWormholeFrameCompanionSnapper frame();
	frame."frameType" = frameType;
	frame."lStyle" = usedLineStyle;
	frame."lineWidth" = lineWidth;
	frame."lineColor" = lineColor;

	companions << frame;
    }

    if (showScale) {
	XClipWormholeScaleCompanionSnapper scale();
	scale."frame" = !frameType.none;

	companions << scale;
    }
}

The ViewportSnapper2D object uses the frametype member to indicate its frame. In XClip view clips, however, the frame functionality exists in a companion object which is attached to the viewport. So, in the conversion, if the ViewportSnapper2D instance has a frame, an XClipWormholeFrameCompanion instance is created, the frame type is set, and the companion gets appended to the companions list. That list will later be used to attach all companions to the new XClip view clip. The creation of the frame companion is implemented on lines 7-15.

Show content from other spaces

The XClip view clip supports showing contents from other spaces then the main 2D space. If multiple spaces exists in the drawing (e.g. alternatives, elevation views, etc.), the user will see a dropdown option for selecting other spaces than the main 2D space when inserting a new view clip. In order to add your own custom spaces to the list of available spaces you need to add an XClipWarpSpaceDomainEnv for your type of space.

The code below illustrates how the XClipWarpSpaceDomainEnv looks for elevation spaces.

public class ElevWarpSpaceDomainEnv extends XClipWarpSpaceDomainEnv  {
    public constructor() {
	spaceClass = ElevSpace;
    }


    /**
     * Return the name of the space.
     * if the return string is null the space will not be added.
     */
    public Str spaceName(Space space) {
	if (space as ElevSpace) {
	    if (space.arrow) {
	    return space.arrow.label();
	    }
	}
	return null;
    }
}

Once your XClipWarpSpaceDomain subclass has been implemented, it has to be registered in the xclip system. This is done using the global method xclipAddWarpSpaceDomain(XClipWarpSpaceDomain env).

xclipAddWarpSpaceDomain(ElevWarpSpaceDomainEnv());

Your specific space might also want a specific XClipSpaceManager that has some special logic for handling XClip-related events in your space. Refer to XClipSpaceManager and ElevXClipSpaceManager for further details on the class implementation. Once your space manager is implemented, connect it to your space by overriding the initXClips() method in your space.

public class ElevSpace extends Space {
    ...


    /**
     * init Elevation xclip space manager.
     */
    public void initXClips() {
	    if (!xclips) xclips = ElevXClipSpaceManager(this);
    }


    ...
}

Companions

There are currently 2 types of Companions for XClip view clips:

1.Graph additions - Changes the graphic of the view clip snapper, but does not alter the content (e.g. add a frame around the view clip, draw out the used scale of the view clip, etc.).

  1. Editors - Alters the content of the view clip (e.g. draw snappers inside view clip with part tagging colors, draw snappers in black and white, etc).

The Companion connects to the XClip Wormhole using normal connectors. They connect at (0, 0, 0) and shares rotation. This means the XClip Wormhole and the Companions connected have the same local coordinate systems (I.e. 5mm x-axis into the XClip Wormhole is 5mm x-axis into the Companion.

All Companions must inherit from XClipWormholeCompanionSnapper and the class must be registered using the registerXClipWormholeCompanionClass() function. When registered the Companion will show up in the same box in the Paperspace Toolbox under the XClipWormhole icon.

To create a Graphical Companion implement as a normal GraphSnapper usingG2() = true subclassing the base class directly XClipWormholeCompanionSnapper.

To create an Editor Companion inherit from the XClipWormholeEditor2DCompanionSnapper class and override the createEditor() method. Standard CET Wormhole Companions:

  • XClipWormholeScaleCompanionSnapper - Shows the scale of the XClip Wormhole.
  • XClipWormholeFrameCompanionSnapper - Creates a border around the clipped area in the XClip Wormhole.
  • XClipColumnBalloonCompanion - Shows and dimensions Column balloons outside edge of XClip Wormhole.
  • XClipWormholeTagCompanionSnapper - Colors content of XClip Wormhole with tagged Part Tags from chosen Part Tag Category.

Black and White changes from 10.5 to 11.0:

Starting from version 11.0, it is possible to give graphs a black fill color when using the BlackAndWhite companion. To do this, add a property called blackAndWhiteAllowFill to your snapper and set it to true. This will fill all graphs in that snapper where the line color is the same as the fill color.

Column Balloons

Column balloons are reference balloons for Columns in the drawing. They can be named and are interfacing with the XClip Column Balloon Companion.

If your Extension has Column Balloons it is strongly recommended to subclass the CET standard Column Balloon for future compatibility.

Auto Papers

If you have auto papers that previously generated viewports, these will now be automatically converted to view clips. All configuration and functionality of the AbsAPViewport2D will be transferred to the view clip through a companion called AbsXClipApWormholeSettingsCompanionSnapper. However, since the conversion is performed by the makePapers() method, you need to manually add the code line below in your subclass if this method has been overridden. The code below shows how and where the conversion is made in the BasicAPPaperMaker class.

    /**
     * Create paper(s) from the env.
     */
    public PaperSpace[] makePapers(AbsAPGroupEnv env) {
	StreamPaper stream(templateUrl);
	PaperSpace newSpace = stream.load(env.world);
	if (!newSpace) return null;
	if (paperGroup) newSpace.group = paperGroup;
	for (z in newSpace.snappers) {
	    if (developMode) {
		// Not needed in release.
		// FIXME: Will be unneeded when StreamPaper is fixed.
		z.initEntityId(newSpace);
	    }
	    if (z as ImageSnapper) {
		str fileName = z.originalFilename;

		Url imUrl;

		for (im in filesIn(templateUrl, fileName # ".*")) {
		    imUrl = im;
		    break;
		}

		z.file = imUrl;
		z.createGImage();
	    }
	    z.propDefs;
	    if (PropDef def = z.propDef(cAbsAPPushEnvProp)) {
		def.put(z, this, env);
		z.invalidate(dirty2D.rebuild);
	    }

	    if (z as AbsAPViewport2D) z.replaceWithXClip(); // <================ This line converts the viewport
	}
	return [newSpace];
    }

Custom View Clip Buttons

If you want to create a button for inserting a view clip that automatically modifies the view clip in some fashion (e.g. attaching companions, changing some configuration etc.) you can use the method xclipWormholeSnapperLimb(). This method has one parameter called configureCallback which will be invoked once the view clip has been created, providing a straight-forward method of editing your newly created view clip. For instance, the function createCustomXClipLimb below creates a button which starts the animation for inserting a view clip and automatically attaches an AbsXClipAPWormholeSettingsCompanionSnapper to each.

use cm.core.xclip;

package const symbol pkgXClip = #"cm.core.xclip";


/**
 * Configure the wormhole however you like
 */
package void configureWormhole(XClipWormholeSnapper wh) {
    AbsXClipAPWormholeSettingsCompanionSnapper c();
    c.z2m = apViewportZoomMode.group;
    wh.connectCompanion(c);
}


/**
 * Create our own button which lets us configure the wormhole snapper using the method above.
 */
package ComponentLimb createCustomXClipLimb(LibraryLimb parent, symbol pkg, str key, UIHint hint=null) {
   return xclipWormholeSnapperLimb(parent, pkg, key, hint, function configureWormhole);
}

checkfile in loadSym now defaults to true

checkFile was previously true, but it's now false because of the possibly severe performance penalty of including modification date for a cached request, if it's just going to use the cache anyway.

public SymNode loadSym(Url url, bool lazy=true, bool cache=true, bool checkFile=false) {

eqBox(Object, Object) method has been deprecated

In 10.5 eqBox(Str, Str) and other cases produces incorrect results. eqBox() now uses the eqBoxedValue() function which always has produced correct results for all boxed values including strings.

use cm.runtime;
{
    str a = "dd";
    str b = "dd";
    str c = "d" # "d";
    str d = b.copy;
    pln(#a.eqBox(b));
    pln(#a.eqBox(c));
    pln(#a.eqBox(d));
    pln(#a.eqBoxedValue(b));
    pln(#a.eqBoxedValue(c));
    pln(#a.eqBoxedValue(d));
}

10.5:
a.eqBox(b)=true
a.eqBox(c)=false
a.eqBox(d)=false
a.eqBoxedValue(b)=true
a.eqBoxedValue(c)=true
a.eqBoxedValue(d)=true

11.0:
a.eqBox(b)=true
a.eqBox(c)=true
a.eqBox(d)=true
a.eqBoxedValue(b)=true
a.eqBoxedValue(c)=true
a.eqBoxedValue(d)=true

putAuxillaryObject() and getAuxillaryObject() for calcArticleView

All functions in cm.core.calc.articleViewsInSpace.cm now use putAuxillaryObject()/getAuxillaryObject() instead of putAuxillary()/getAuxillary() for the key "calcArticleViews". The motivation for this change is to reduce dependencies. If you are getting or putting "calcArticleView" in your extensions you will have to do the same change.