MhSystemAnimationExportFunction
now calls the new event symbol sSnapperInsertedAnim
on exported snappers instead of sSnapperInserted
. This engine function is primarily used with inserting row snappers.
/** * Exec. */ public Object exec() { ... for (MhSnapper s in exported) { s.validateBehaviors(sSnapperInsertedAnim); if (s.isRow or s.isAisle) { rows << s; } } ... }
Previously MhSnapperAnimationBehavior.favoriteAnimation()
would return InsertAnimationG2
by default. Now it will return the result of insertAnimation()
instead unless useInsertAnimationG2ForFavorites()
returns true
. By default InsertAnimationG2
will be returned only when the selection contains the behavior's snapper as well as other snappers that are not children of the snapper.
Old: /** * Favorite insert animation. */ public Animation favoriteAnimation(Snapper z, StartInsertAnimationEnv env) { if (Snapper root = eldestAncestorIn(z, env.?selection.snappers)) { if (z != root) { if (SnapperAnimationBehaviour rootAnimBehaviour = root.animationBehaviour) { return rootAnimBehaviour.favoriteAnimation(root, env); } } } return InsertAnimationG2(env); } New: /** * Favorite insert animation. */ public Animation favoriteAnimation(Snapper z, StartInsertAnimationEnv env) { if (Snapper root = eldestAncestorIn(z, env.?selection.snappers)) { if (z != root) { if (SnapperAnimationBehaviour rootAnimBehaviour = root.animationBehaviour) { return rootAnimBehaviour.favoriteAnimation(root, env); } } } if (SpaceSelection sel = env.?selection) { if (useInsertAnimationG2ForFavorites(z.MhSnapper, sel)) return InsertAnimationG2(env); } return insertAnimation(..); } /** * Use InsertAnimationG2 for favorites instead of insertAnimation(z, env). */ extend public bool useInsertAnimationG2ForFavorites(MhSnapper snapper, SpaceSelection selection) { return !sameFamilySelection(..); } /** * Return true if selection only contains this and decendant. */ extend public bool sameFamilySelection(MhSnapper snapper, SpaceSelection selection) { for (s in selection) { if (s == snapper) continue; if (!s.anyChildOf(snapper)) return false; } return true; }
A new animation MhRowChildFavoriteAnimationG2
has been created that can generate row parent snappers when copy-pasting bays/frames. This animation is by default used by bays and frames in the abstract (MhRowChildSnapperAnimationBehavior
). The existing MhBaySnapperAnimationBehavior
is modified to extend from this new parent, and we've added a new MhFrameSnapperAnimationBehavior
for frames in the abstract.
When copy-pasting a bay/frame, pasting it will generate a row and then trigger the events sUserPastedAnim
and sSnapperInserted
. These are to ensure the row is properly updated (e.g. generating default frames for a stand-alone bay, generate empty bays in between the copied snappers).
Snapping also works with the new animation and the pasted snapper will be absorbed into the snapped parent, see MhRowChildFavoriteAnimationG2.tryAdoptChildrenIntoSnapAlt()
.
The method getVoidBaysSample()
in MhRowFillVoidEntriesFunction
previously will only return results if there were any removed bays. If there are no removed bays, it will now return the first group of imported bays with the same x-position, or even generate a bay construction entry if there are no imported bays.
public class MhRowFillVoidEntriesFunction extends MhSystemEngineFunction { /** * Get a sample of bays to be used as reference when filling up void bays. */ extend public MhEngineBoxEntry[] getVoidBaysSample() { MhEngineEntryBlock[] blocks = systemEnvironment.?getImportedBlocks(snapper); MhEngineEntry[] entries = blocks.first.entries; entries = mhXSortedEntries(entries, unmodify=true); MhEngineBoxEntry[] res(4); // Gathers all the bays that have the same x-position appendVoidBaysSample(entries, res, acceptFirst=false); // Did not find any removed bay, fallback to first bays at same x-position. if (!res.any) appendVoidBaysSample(entries, res, acceptFirst=true); // No bay in entries, spawn a single default bay. if (!res.any) res <<? defaultBayConstructionEntry(entries); return res.any ? res : null; } }