GH - New MakeBlock & MakeLayer components

( EDIT : Rev 1.1.2 | 2017-03-13 - Now optional Block Instantiation + MaterialSource = “By Parent” etc.)

For Grasshopper Windows users,
If you need discrete GH components (VBScript implementations) of MakeBlock and MakeLayer (or the two combined into a MakeBlockOnLayer component) then you may have use for these components which I just made (using VBScript and thus Windows only?).

Layer Structure
The MakeLayer component is capable of creating deep LayerPaths (like “ASM:PART::MORE_PARTS::Aso”) and, if used with the Block Definition component, thus capable of dropping a Block definition onto that very specified layer (e.g. the layer “Aso” in the example string). And more. See the GH file attached far below.

Feedback & Bugs
I would appreciate any feedback on useful enhancements or bugs. The following component description is from the combined component, where relevant parts apply for the separate components.

'// MAIN METHOD
'// -----------------------------------------------------------------------------
'// Rev 1.0.0 (2017-03-12) //Rolf Lampa (RIL)
'// Rev 1.0.1 (2017-03-12) RIL - Cmd line messages. Testing for IsDeleted & IsReference. Added ctrl switch DoCreateBlock.
'// Rev 1.1.2 (2017-03-13) RIL - Added Instantiate, InstanceName & Material (By Parent as default).
'// -----------------------------------------------------------------------------
'// SUMMARY -   Creates, or recreates, a Block Definition on specified LayerName.
'//             If the LayerName (entire path) doesn't exist, it will be created.
'//             Optionally one instance can be created (on the same layer).
'// ..............................................................................
'//
'// Run       - Trigs the component code to execute.
'//
'// BlockName - Required. Block Definition name. Any existing Block Definitions
'//             with the same name (and its instances, if any) will be replaced on Run.
'//
'// Instantiate-Optional. Default=False. Trye = creates one (1) Block Instance based
'//             on the Block Defintion. Note: Block Instances are placed on the same
'//             layer path as Block Definitions.
'//
'// InstanceName - Optional. If Instantiate = True, the new Block Instance will be
'//             given the name specified here. No unique ckeck of the names are performed.
'//
'// LayerName - Optional. If no name is specified, the CurrentLayer is used.
'//             Any new LayerName will be created strictly with full path,
'//             with double colon as separator between LayerNames in the
'//             Structure. Strict means also that a LayerNames without a path
'//             will end up as a "root" layer (first level).
'//             Example 1: LayerName with path;    "ASM::PART"
'//             Example 2: LayerName without path; "PART"
'//
'// Description-Optional. Extra field shown in the Block Manager.
'//
'// BasePoint - Required. Defines the instertion point for future Block Instances.
'//
'// Objects   - Required. Valid Objects may be one or more Rhino objects (via Brep
'//             component) or Grasshopper generated geometry. Multiple objects/geometry
'//             will be baked into one Block Definition under the specified BlockName.
'//
'// MaterialSrc-Optional. Default = By Parent (good for Block defintiions).
'//             Values: 1 = By Object, 2 = By Layer, 3 By Parent.
'//
'// ChangeLayer-Optional. Default is; stay on current layer. During execution the layer
'//             will change if LayerName is different from CurrentLayer, but will be
'//             restored after execution if ChangeLayer = False. If set to True, the
'//             specified LayerName will be set as the CurrrentLayer
'//
'// LogDebug  - If set to true, log messages are sent to the out parameter. To be
'//             be used with a Panel. Press a button to activate Run and HOLD the
'//             button while reading the output written to the Panel.
'//
'// Trig      - Sends a "True" signal useful for trigging subsequent components.
'//
'// LastLayer - Outputs the actual Layer object at the end of any LayerName path.
'//
'// LayerPath - The same path as the LayerName input.
'//
'// LayerIndex- The Index for the LastLayer in the global LayerTable.
'//
'// -----------------------------------------------------------------------------

Notice that the MakeLayer feature can handle any depth of Layer Paths on the following format:

PARENT::child::CHILD_OF_CHILD::Aso

or:

ASM::COMPONENT::PART::Aso

etc.

Single Layer or Path
Also “single” Layer names are valid, but then they will be inserted as “root level” layers. If no LayerName is specified (empty string) then Rhino’s CurrentLayer will be used.

ChangeLayer
Note that an option exist for allowing the component to change the Rhino CurrentLayer to the LayerName specified (the component often needs to change the layer during execution in any case - for example for dropping a Block Definition at the specified LayerName, but the initial CurrentLayer will be restored if not asked to change (option ChangeLayer ).

LogDebug
The components has a LogDebug feature which, if activated, displays some execution info via out parameter to a Panel component. The LogDebug info can be read if you press Run and hold the button.

The components [EDIT: Rev 1.1.2]:
Rev 1.0.1 with IsReference check etc :
Rev 1.1.2 (2017-03-13) - Added Instantiate, InstanceName & Material (By Parent as default).
AddBlockDefinition_VB - Rev1.1.2.gh (28.0 KB)

Fig 1. [EDIT: Updated picture] Example output when the LogDebug info is activated (the combined component doing it all, is now included). The LayerName (a long path in this case) is automatically created as shown in the Rhino Layer manager to the far left, and a block definition (without any instance) is placed on the layer “BDef” :

The text output to the /Panel is sent from the two components, and the row numbers helps spotting the code section where the message came from.

// Rolf

3 Likes

BUG?
@DavidRutten or @dale ,
I discovered that a child layer - newly coupled to a parent layer - doesn’t return the full path when calling the method Layer.FullPath. Hence the error indication message “<-(Bug in Layer.FullPath?)” in the picture above (run the MakeLayer component on an empty layer manager as to make new layers, and look up the message number in the code to find the call that fails).

Strangely enough, the parent layer in the same structure returns the correct (full) path.

Either this is a bug or some kind of update or “refresh” needs to be done. The need for that is not documented though so I assume it’s a bug that shows in that specific situation in that specific code (?)

I’m puzzled and was stuck on this for hours, but @DavidRutten or @dale may know better about this.

// Rolf

@RIL, this is a lot of code and complexity to take in. Can you possibly reduce the problem to the simplest form?

Note that changes to objects from the Rhino document typically do not take affect until you call the type.CommitChanges() method. This is because these objects are basically readonly and trying to update them on every change the programmer makes would result in a huge amount of steps in the undo buffer, not to mention a severe performance degradation.

Hi,
The erroneous code was marked with a comment pointing out the error:

Row 341:

Log(“08 ACTUAL CHILD PATH : " + childlayer.FullPath + " <–(Bug in ‘Layer.FullPath’?)”) '<- #?

I remember trying to call CommitChanges(), but to no avail. Calling FullPath on the parent object works fine immediately after assignment. (after assigning parent to the child).

Strange.

Edit: Ah sorry, I now realize that the initial picture in the illustrated post above, was replaced after my post about the bug. The original picture had this very error message clearly marked (which I then assumed would help spotting the error location in the code), but the picture was later updated together with a newer version of the code.

// Rolf