Move materials from Bylayer to Byobject

Is there a way to change globally the materilas of all objects currently ‘bylayer’ to ‘byobject’?

Hi @juancarreras,

below script does this for all selectable surfaces, polysurfaces, meshes, extrusions and subd objects. It changes the material source from “bylayer” to “byobject” and then assigns the rendermaterial (assigned to the layer) to the object, but only if the layer had a rendermaterial.

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def DoSomething():
    obj_ids = rs.ObjectsByType(8 +16 + 32 + 1073741824 + 262144, False, 1)
    if not obj_ids: return
    rh_objs = [rs.coercerhinoobject(obj_id, True, True) for obj_id in obj_ids]
    by_layer = Rhino.DocObjects.ObjectMaterialSource.MaterialFromLayer
    by_object = Rhino.DocObjects.ObjectMaterialSource.MaterialFromObject
    for rh_obj in rh_objs:
        if rh_obj.Attributes.MaterialSource == by_layer:
            layer = scriptcontext.doc.Layers[rh_obj.Attributes.LayerIndex]
            if layer.RenderMaterial is not None:
                rh_obj.Attributes.MaterialSource = by_object
                rh_obj.Attributes.RenderMaterial = layer.RenderMaterial

Note that it does not remove the material assignment from the layers.


Thanks Clement,
It doesn’t seem to do anything …
I get "Message: ‘ObjectAttributes’ object has no attribute ‘RenderMaterial’
I assume that this is a Python script, right?
Attached sample 3dm file.
Test-byobject.3dm (292.1 KB)

BTW can you include blocks to the object type list?

Hi @juancarreras,

i cannot repeat this error. Here is what i get using Rhino 7 SR22 and your example file:

The assigment seems to work. After removing the materials from the layers manually, they are still assigned to the objects (by object). The only thing which does not look right is the material preview, it stays black. Maybe @nathanletwory knows why this happens ?

Yes. Which version of Rhino SR you’re running ?

Probably, but it would require to cycle through the block content and then choose by object type. If blocks are nested this can get complex.


I’m using Rhino 5 SR14
See what happens

Maybe the attribute “rendermaterial” had a different name in version 5?
Regarding the blocks, I’m just interested in changing the material of the block not the contents, I use byblock in the components so it should be easier.

OK, then of course the above script will not work. It is using the ‘newstyle’ RenderMaterial. Where your Rhino 5 materials created in Rhino or are these VRay materials ?

For the sample I just used rhino materials but in general I use vray materials

Hi @juancarreras,

i do not have VRay but below seems to work with your sample file opened in Rhino 5 (no blocks). (1.1 KB)


Excellent, it works also with vray!
Any chance to include block instances (not their contents)?

The material assignments are set for the objects (contents) of the block. So i am not sure this will change anything, please try adding 4096 to rs.ObjectsByType and report what happens, it then should look like below:

obj_ids = rs.ObjectsByType(8 + 16 + 32 + 1073741824 + 4096, False, 0)


It works as intended, so the block instance material changes to byobject and the content objects are not affected.
Thank you so much!

By the way, where can I find the id’s for object types in case I want to add any others and test it?

In the RhinoScript helpfile. Just run _EditPythonScript and from the menu choose Help > Python Help. Then search for the word ‘ObjectType’ in the Index tab. Below are values for objects (Rhino 5):


Note that not all objects can have a material assignment.

Thanks again!