rs.SetUserText(block_definition_id, "key", "value")
gave this error:
Message: 9d0ecdd8-b3ad-4d9d-80bb-020002811910 does not exist in ObjectTable
Some context:
I’m trying to add “Edit in place” functionality to linked blocks - I think that will be useful in case you move your block from original position and need to change it with reference to objects in the active document.
Opening them separately in a new rhino instance loses the context. Worksessions preserve the context, but you can’t move parts of worksessions to new place the way you can transform linked blocks (also I don’t like keeping a separate .rws file)
So I’m trying to change block into an embedded type, make changes and export it again into a linked type (overwriting the previous file).
I wanted to store source archive path on the block definition - saving it on block instance isn’t the safest, because that one instance may be deleted. Saving them in document globally isn’t great neither, because block definition can be renamed/reinsterted. So ideally you could store them on block definitions.
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
block_id = rs.GetObject(filter=4096, preselect=True)
block_definition = rs.coercerhinoobject(block_id).InstanceDefinition
update_type = rs.ComboListBox(["Embedded", "Linked"])
if update_type == "Embedded" and \
block_definition.UpdateType == Rhino.DocObjects.InstanceDefinitionUpdateType.Linked:
if rs.SetUserText(block_id, key="SourceArchive",
value=block_definition.SourceArchive):
sc.doc.InstanceDefinitions.ModifySourceArchive(block_definition.Index,
block_definition.SourceArchive,
Rhino.DocObjects.InstanceDefinitionUpdateType.Static,
quiet=1)
# use Static instead of Embedded
# Rhino will default to Static even if Embedded was set in ModifySourceArchive function
# https://github.com/mcneel/rhinocommon/blob/master/dotnet/rhino/rhinosdkinstance.cs#L23
if update_type == "Linked" and \
block_definition.UpdateType == Rhino.DocObjects.InstanceDefinitionUpdateType.Static:
# you can't store user text on block definition
# and I'd rather not use the description field
# so store it on the first block instance user clicked and
# iterate through all of them (hoping that wasn't deleted)
# don't want to store it in document, because the block may be renamed/reinserted
# https://discourse.mcneel.com/t/can-you-add-user-text-to-block-definition/150530
for block_instance_id in rs.BlockInstances(block_definition.Name):
block_instance_source_archive = rs.GetUserText(block_instance_id, key="SourceArchive")
if block_instance_source_archive:
model_base_point = Rhino.FileIO.File3dm.Read(block_instance_source_archive).Settings.ModelBasepoint
sc.doc.ModelBasepoint = model_base_point
rs.Command("-Cplane World Top")
rs.Command("-Insert File=No " + chr(34) + block_definition.Name + chr(34) + " Block " + str(model_base_point) + " 1 0")
rs.Command("SelLast")
rs.Command("Explode")
rs.Command("-Export " + chr(34) + block_instance_source_archive + chr(34))
rs.Command("Delete")
sc.doc.ModelBasepoint = Rhino.Geometry.Point3d(0,0,0)
sc.doc.InstanceDefinitions.ModifySourceArchive(block_definition.Index,
block_instance_source_archive,
Rhino.DocObjects.InstanceDefinitionUpdateType.Linked,
quiet=1)
# use the first one found - problably should
# add extra checks in case there are multiple paths
break
else:
raise Exception("Couldn't find file path for the Linked Block in any of its instances")