I use rs.MatchObjectAttributes() to clone the attributes (e.g. objectlayer, usertexts, etc) from objects, nested inside a block to their copies. (I use this mechanism as a workaround for this related issue)
When I run the script below with runPythonScript "C:/path/scriptname.py", I expect the copies to be in the document, but when I call rs.MatchObjectAttributes(), the objects seem to have become invalid (or at least unselectable). If rs.MatchObjectAttributes() is not called, the copies are valid and selected
#! python 2
import traceback as tb
import rhinoscriptsyntax as rs
class BlockDefinition(object):
def __init__(self, name):
self.name = name
def traverse(self, func, result=None, block_name=None, parent_xform=rs.XformIdentity()):
# initialize variables if not set
if result == None:
result = []
if block_name == None:
block_name = self.name
# traverse block tree
content = rs.BlockObjects(block_name)
for obj in content:
if rs.IsBlockInstance(obj):
instance_xform = rs.BlockInstanceXform(obj)
if parent_xform:
instance_xform = rs.XformMultiply(parent_xform, instance_xform )
self.traverse( func, result, rs.BlockInstanceName(obj), instance_xform )
func(obj, result, parent_xform)
return result
def main():
try:
objs = rs.GetObjects(preselect=True, filter=rs.filter.instance)
for obj in objs:
if rs.IsBlockInstance(obj):
block_name = rs.BlockInstanceName(obj)
# traverse all child blocks, and add breps to the result
definition = BlockDefinition(block_name)
def _get_breps(obj, result, xform):
# when obj is a brep, add it to the result
if rs.IsBrep(obj):
copy = rs.TransformObject(obj, xform, copy=True)
""" ############# ISSUE OCCURS HERE ########### """
""" when I comment out the line below, the described issue does not occur """
rs.MatchObjectAttributes(copy, obj)
result.append(copy)
content_copies = definition.traverse(_get_breps)
print('content_copies', content_copies)
# empty current selection and select copies
rs.UnselectAllObjects()
rs.SelectObjects(content_copies)
print('selection', rs.SelectedObjects())
rs.ZoomSelected()
except Exception as exc:
print(tb.format_exc())
if __name__ == '__main__':
main()
First of all, thanks for your response. I much appreciate your help. However, I don’t think my question did come across correctly.
The issue reported here is that when I call rs.MatchObjectAttributes(obj, copy) the selection is empty when I run rs.SelectObjects(content) later in the script. I don’t think that is intended behavior. If I comment out rs.MatchObjectAttributes, the copies are selected as expected.
Thanks,
Tim
P.S. using rs.MatchObjectAttributes() was a workaround for this issue, that @pascal reported in youtrack, but was never solved
MatchProperties will replace the object with a copy that contains new attributes. Because the object is replaced, you’ll (probably) need to reselect the new reference (if you want or need it to be selected).
I am running into the same issue in other parts of my code.
I interpret this line:
if scriptcontext.doc.Objects.ModifyAttributes(id, source_attr, True):
in the definition of rs.MatchObjectAttributes() in object.py as if the objects’ Attributes should be modified, rather than returning a new reference. Also the documentation doesn’t mention that another reference is created.
I have a workaround now, but I still think rs.MatchObjectAttributes() shows unintended behavior. Could you have another look at it? I have another isolated example that demonstrates the unintended behavior if that helps.
based on your answer on my other topic, I’ve made a modified version of my script. It still puzzles me that copies seem to disappear from the doc when I match the attributes with the orginal.
If I run the script below, I expect the content from all blocks to be in the document. However, the breps from linked blocks have disappeared.
#! python3
import rhinoscriptsyntax as rs
import scriptcontext as sc
def traverse(block_name, my_func, result=None, parent_xform = rs.XformIdentity()):
if result is None:
result=[]
block_objects = rs.BlockObjects(block_name)
for obj in block_objects:
if rs.IsBlockInstance(obj):
child_block_name = rs.BlockInstanceName(obj)
xform = rs.BlockInstanceXform(obj)
traverse(child_block_name, my_func, result, xform * parent_xform)
my_func(obj, result, parent_xform)
return result
def main():
# let user select the input
obj = rs.GetObject("select block with nested linked instances", filter=rs.filter.instance, preselect=True)
if not obj:
return
block_name = rs.BlockInstanceName(obj)
def create_transformed_copy(obj, result, parent_xform):
"""
function to create a copy of objects that are not instances
@param obj: GUID object ref
@param result: list of function result
@param parent_xform: parent transformation matrix
return None
"""
if not rs.IsBlockInstance(obj):
copy = rs.TransformObject(obj, parent_xform, True)
# -----------------------
# match attributes of original to copy
if rs.IsObjectReference(obj):
source = rs.coercerhinoobject(obj)
source_attr = source.Attributes.Duplicate()
target = rs.coerceguid(copy, True)
sc.doc.Objects.ModifyAttributes(target, source_attr, True)
result.append(copy)
# recursively run this function on all objects in tree
result = traverse( block_name, create_transformed_copy)
# "result" contains all breps nested inside the block
print('result', result)
# "selection" unexpectedly does not contain breps from linked blocks
rs.UnselectAllObjects()
rs.SelectObjects(result)
print('selection', rs.SelectedObjects())
rs.ZoomSelected()
if __name__ == '__main__':
main()