Creating a material and applying to BaseObject within Python Generator
-
Hello, I did a search and couldn't find much to do with materials.
My c4d version is R19
I am creating a bunch of BaseObjects inside a Python Generator and trying to shade them in various ways- which requires me to create a new material for each BaseObject.
I am successfully creating the Material instance (I think) by storing a new c4d.Material() into a new variable. However, when I run MakeTag(c4d.Ttexture) on the BaseObject and set the c4d.TEXTURETAG_MATERIAL parameter to my newly created material, it does not appear to take.
Here is my code. It uses some modata from a linked matrix object to generate a series of discs / rings.
import c4d from c4d.modules import mograph as mo #Welcome to the world of Python def main(): link = op[c4d.ID_USERDATA,1] size = op[c4d.ID_USERDATA,2] roff = op[c4d.ID_USERDATA,3] md = mo.GeGetMoData(link) if md is None: return False null = c4d.BaseObject(c4d.Onull) cnt = md.GetCount() marr = md.GetArray(c4d.MODATA_MATRIX) carr = md.GetArray(c4d.MODATA_COLOR) for i in reversed(xrange(0, cnt)): mat = c4d.Material() mat.SetChannelState(c4d.CHANNEL_COLOR, True) mat[c4d.MATERIAL_COLOR_COLOR] = carr[i] disc1 = c4d.BaseObject(c4d.Odisc) disc1[c4d.PRIM_DISC_ORAD] = carr[i][0] * size disc1[c4d.PRIM_AXIS] = 4 disc1.SetMg(marr[i]) disc1.InsertUnder(null) disc2 = c4d.BaseObject(c4d.Odisc) disc2[c4d.PRIM_DISC_IRAD] = carr[i][0] * size disc2[c4d.PRIM_DISC_ORAD] = carr[i][0] * size * 1.2 disc2[c4d.PRIM_AXIS] = 4 moff = marr[i] moff.off = moff.off + (roff * carr[i][0]) disc2.SetMg(marr[i]) ttag = disc2.MakeTag(c4d.Ttexture) ttag[c4d.TEXTURETAG_MATERIAL] = mat disc2.InsertUnder(null) return null
Any ideas or suggestions are greatly appreciated! Thank you!
-
Hello,
you cannot create a Material in the
main()
function of a Python Generator object.The
main()
function of the Python Generator object defines a cache of "virtual" BaseObjects which will appear in the scene.Materials cannot be created this way. A material must be inserted into the BaseDocument. This must only happen from the main thread, typically in reaction to some user interaction.
One way of doing this would be to add a user data button to your Generator. Then your user could simply press that button to create the needed materials. Pressing the button can be detected by implementing the
message()
function.This could look like this:
def main(): # search for material mat = doc.SearchMaterial("Generator Material") if mat is None: return None # create object cube = c4d.BaseObject(c4d.Ocube) # apply material ttag = cube.MakeTag(c4d.Ttexture) ttag[c4d.TEXTURETAG_MATERIAL] = mat return cube def message(id, data): if id == c4d.MSG_DESCRIPTION_COMMAND: buttonId = data['id'] # check button ID if buttonId[1].id == 1: # create material and insert it into the host document c4d.StopAllThreads() material = c4d.Material() material.SetName("Generator Material") material[c4d.MATERIAL_COLOR_COLOR] = c4d.Vector(1,0,0) doc.InsertMaterial(material, None) c4d.EventAdd()
Also, please use the Q&A system.
best wishes,
Sebastian