Add Object to Block Python (bypass block edit)

Would it be possible to write a python script that allows the user to INSTANTLY add an object to a block definition without going through block edit?

Hi Guido,

Find attached 2 scripts than can be drag-dropped over Rhino.
They need to remain in the location you dragged them from in order to keep functioning.
I did not test them for some time so see if it is of any use.

AddObjectsToBlock.rvb (1.5 KB)
ExtractObjectsFromBlock.rvb (1.7 KB)
DeleteObjectsFromBlock.rvb (2.1 KB)

Let me know when you have any issues.

@Pascal is there a wish item for this type of functionality already?
If not could it be added the hassle of the block-editor is often inefficient.
I remember having quite a speedup with these scripts for a project with a lot of ‘volatile’ blocks

HTH
_Willem

1 Like

Thanks Willem!

That’s pretty much the functionality I had imagined (and I definitely think this should be standard in Rhino! all the block editing functions and interfaces need an overhaul).

Great work!

-GM

Hi GM,

I was interested in something like this, but the rhinoscripts are no longer available for download.

I’ve tried in Python, but for some reason the block moves position when I add the new Geo.

import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc

def AddToBlock():
    objects = rs.GetObjects("Choose Objects to Add to Block", preselect=True)
    if not objects: return
    
    block = rs.GetObject("Choose Block to Add Object to", rs.filter.instance)
    if not block: return
    
    objref = rs.coercerhinoobject(block)
    idef = objref.InstanceDefinition
    idefIndex = idef.Index
    
    #New Geo
    newGeometry = []
    newAttributes = []
    for object in objects:
        newGeometry.append(rs.coercegeometry(object))
        ref = Rhino.DocObjects.ObjRef(object)
        attr = ref.Object().Attributes
        newAttributes.append(attr)
    
    #Existing Block Geo
    blockCopy = rs.CopyObject(block)
    blockObjects = rs.ExplodeBlockInstance(blockCopy, explode_nested_instances=False)
    for object in blockObjects:
        newGeometry.append(rs.coercegeometry(object))
        ref = Rhino.DocObjects.ObjRef(object)
        attr = ref.Object().Attributes
        newAttributes.append(attr)

    InstanceDefinitionTable = sc.doc.ActiveDoc.InstanceDefinitions
    InstanceDefinitionTable.ModifyGeometry(idefIndex, newGeometry, newAttributes)
    
    rs.DeleteObjects(blockObjects)
    
    sc.doc.Views.Redraw()
    
AddToBlock()
    

Hoping someone might have a solution… or the old rhinoscripts.

Cheers
AM

Hello,
You could try the linked zip file which seems to have survived the current problems with attachments on this site

Cheers
G

1 Like

That works beautifully,

Cheers
AM

1 Like

I translated @Willem’s rhinoscript to python. It seems to be working. Thanks Willem!

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def AddToBlock():
    objects = rs.GetObjects("Choose Objects to Add to Block", preselect=True)
    if not objects: return
    
    block = rs.GetObject("Choose Block to Add Object to", rs.filter.instance)
    if not block: return
    
    rs.EnableRedraw(False)
    
    blockName = rs.BlockInstanceName(block)
    objref = rs.coercerhinoobject(block)
    idef = objref.InstanceDefinition
    idefIndex = idef.Index
    
    
    if rs.IsBlockReference(blockName):
        print "Block is referenced from file; unable to add object(s)"
        return
    
    blnCopy = False
    
    XformBlock = rs.BlockInstanceXform(block)

    rs.TransformObjects(objects, rs.XformInverse(XformBlock), blnCopy)
    
    objects.extend(rs.BlockObjects(blockName))
    
    newGeometry = []
    newAttributes = []
    for object in objects:
        newGeometry.append(rs.coercegeometry(object))
        ref = Rhino.DocObjects.ObjRef(object)
        attr = ref.Object().Attributes
        newAttributes.append(attr)
    
    InstanceDefinitionTable = sc.doc.ActiveDoc.InstanceDefinitions
    InstanceDefinitionTable.ModifyGeometry(idefIndex, newGeometry, newAttributes)
    
    rs.DeleteObjects(objects)
        
    rs.EnableRedraw(True)

AddToBlock()

Edit 1: RemoveFromBlock isn’t working as nicely as Willems so I will see what I can do to fix it
Edit 2: Fixed

And Remove from block:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def RemoveFromBlock():
    block = rs.GetObject("Select Block to extract objects from", rs.filter.instance, preselect=True)
    if not block: return

    blockName = rs.BlockInstanceName(block)
    objref = rs.coercerhinoobject(block)
    idef = objref.InstanceDefinition
    idefIndex = idef.Index
    
    XformBlock = rs.BlockInstanceXform(block)
    blockObjects = rs.BlockObjects(blockName)
    blockInstanceObjects = rs.TransformObjects(blockObjects, XformBlock, True)
    
    objs = rs.GetObjects("Select Objects to extract from Block", objects =blockInstanceObjects)
    if not objs: 
        rs.DeleteObjects(blockInstanceObjects)
        return
    
    keep = [] #List to keep in block
    delete = [] #list to delete from block and add to doc
    
    rs.EnableRedraw(False)
    
    for object in blockInstanceObjects:
        if object in objs: delete.append(object)
        else: keep.append(object)
    
    if rs.IsBlockReference(blockName):
        print "Block is referenced from file; unable to modify block"
        rs.DeleteObjects(keep)
        return
    
    rs.TransformObjects(keep, rs.XformInverse(XformBlock), False)
    
    newGeometry = []
    newAttributes = []
    for object in keep:
        newGeometry.append(rs.coercegeometry(object))
        ref = Rhino.DocObjects.ObjRef(object)
        attr = ref.Object().Attributes
        newAttributes.append(attr)
    
    InstanceDefinitionTable = sc.doc.ActiveDoc.InstanceDefinitions
    InstanceDefinitionTable.ModifyGeometry(idefIndex, newGeometry, newAttributes)
    
    rs.DeleteObjects(keep)  
    rs.EnableRedraw(True)
   
RemoveFromBlock()
7 Likes

A post was split to a new topic: Trying to delete selected layers from blocks s