How do I generate Cycles.xml with ghpython?

I understood how to add new material to the document you have to use:

(one forgotten semi-colon in that python code :wink: )

Question is how can I add Cycles.xml in a similar manner from python?

You need RDK functions to add an Cycles XML instance. (please, no cycles.xml, it isn’t a file).

https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Render_RenderContent_Create_1.htm

For this you need the GUID of the Cycles XML material, which you can find here:

https://github.com/mcneel/RhinoCycles/blob/rhino-6.x/Materials/XmlMaterial.cs#L26

Putting this all together you get a simple Python script to create a new material:

import scriptcontext as sc
import Rhino.Render as rr
import System as system

cxml = rr.RenderContent.Create(system.Guid("8B544B3E-D86F-4BCD-8494-FB660CF15E1C"), rr.RenderContent.ShowContentChooserFlags.None, sc.doc)
print(cxml)

When you find out the type GUID for RenderContent you can create them like this easily.

1 Like

Well, maybe not intended but if you add this material to the material panel and right click it you can save it to a file. And opening that with text editor you see that same GUID in there in a XML like structure. :slight_smile:

I’m not an expert (to say the least) but I’m sure you can generate this with python.

I didn’t know how the GUID is used I guess that’s so you don’t allow customized versions of that material.

Thanks for the example I’ll try it out.

I prefer if I use GH to use GH all the way and not switch between GH and RH.

Not sure what you mean with that, but to be able to use a Cycles XML with Raytraced you’ll have to add it to the document. I don’t see how you could do it without having Rhino document in the mix. You can do that in a GH script node, though.

No, no, I meant that currently you have to go and manually add that material to rhino document.

With these scripts you add the materials from the .gh file it will be added to whatever 3dm file is opened.

This is why I mentioned it’s good to have a scene component and a collective output component.

I simply can’t wait for that evolution to happen. This is why I test using ghpython trying to do it all from a .gh file.

Right, I see your point.

You might want to add some code to also check already existing materials from the doc.

This is for when you are shading Rhino objects and you’re done with that process - you then don’t need Grasshopper anymore but you could re-use that particular material in other files.

It makes sense.

Ah, by the way how can I modify your code (above) to remove the material? Is there .Remove() or .Dispose() method?

Actually I (plan to) make my gh scripts such that I can reuse them without leaving anything behind. So I’ll have to clean the materials.

https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Render_RenderMaterialTable_Remove.htm

(that is the RenderMaterials table on the RhinoDoc)

I have to remove the table and not individual materials? :thinking:

No, you call the Remove() method on the RenderMaterials instance.

doc.RenderMaterials.Remove(rc);

I’m confused. How do I identify the material inside that material table?

that rc how do I identify it?

When I look at:
Rhino.RhinoDoc.ActiveDoc.Materials.Count the result is 0

and yet I do have materials there

image

If it helps, this module seems to help handle xml files with Python

https://docs.python.org/2/library/xml.etree.elementtree.html

1 Like

Sorry, I typoed a bit, I meant to write

doc.RenderMaterials.Remove(rc)

You may have gathered by now that a RenderMaterial is a subclass of RenderContent (at least if you read the documentation on the Remove(RenderMaterial) I linked to and clicked through to RenderMaterial). Hence the parameter name rc I had chosen, short for RenderContent).

Anyway, you don’t look at the doc.Materials table, but at doc.RenderMaterials, as I tried to show (but typoed a bit after midnight). In my defence, I did say RenderMaterials instance - that should’ve been deductable already from the initial link to Remove.

So:

import scriptcontext as sc
for rc in sc.doc.RenderMaterials:
  print(rc)

And before you start changing the RenderMaterial table while looping over it:

import scriptcontext as sc

# first get the mats you want to delete
rendmats = [rc for rc in sc.doc.RenderMaterials]
# loop over that list to remove, instead of looping
# over sc.doc.RenderMaterials
for rc in rendmats:
  sc.doc.RenderMaterials.Remove(rc)
1 Like

Yeah, I tried to read it. Unfortunately I can’t understand much without examples. (this is my bad).

I understood that I have to look for RenderContent, and that rc is RenderContent. What I could not get was how to identify this in my particular document.

I tried .Remove(), I tried .Clear(), I tried .Dispose() on RenderMaterials, on .Materials, on RenderContent, but my document’s materials were untouched :smiley:.

Thanks for the example I’ll test it in a few hours.

Thanks @nathanletwory, I was just able to test the removal of the material. :trophy:

Yay :slight_smile: