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