Calling “Add” button in Multi Shader: doesn’t work!
-
Guys, has anyone tried to call the add button of MoGraph multi shader?
I used c4d.CallButton (oc_multi, C4D.MGMULTISHADER_Add) but it keeps failing
-
Hi can you add a bit more context (when and where do you call this CallButton) and if possible a script and the exact error message you have?
Cheers,
Maxime. -
Hi there, it throws no error. That’s the reason I don’t know what causes that! While I am using what Documentation says.
def oc_floor_material (self): doc = c4d.documents.GetActiveDocument() oc_material = c4d.BaseMaterial(1029501) oc_material.SetName("Magic_Floor") oc_material[c4d.OCT_MATERIAL_TYPE] = 2516 oc_multi_shader = c4d.BaseShader(1019397) oc_material[c4d.OCT_MATERIAL_DIFFUSE_LINK] = oc_multi_shader oc_material.InsertShader(oc_multi_shader) c4d.CallButton(oc_multi_shader, c4d.MGMULTISHADER_ADD) for index, file_path in enumerate(self.get_selected_filess()): _, file_name = os.path.split(file_path) file_name_lower = file_name.lower() oc_base = c4d.BaseShader(1029508) oc_correct = c4d.BaseShader(1029512) oc_multi_shader [1050] = oc_base oc_multi_shader [1051] = oc_base oc_base[c4d.IMAGETEXTURE_FILE] = file_path oc_base [c4d.ID_BASELIST_NAME] = "Color" oc_base[1118] = 1 oc_material[c4d.OCT_MATERIAL_DIFFUSE_FLOAT] = 1 oc_multi_shader.InsertShader(oc_base) c4d.EventAdd() doc.InsertMaterial(oc_material)
edit (@ferdinand): Please use forum markup to embed code. See forum-features for details. Please also follow our support-procedures. Please also consolidate your postings. I have fixed your posting.
@sydney_ko said:
MoGraph Multi Shader belongs to C4D. To increase the number of inputs, I must click on add button. But it doesn’t do anything with my code
-
Hey @sydney_ko,
please follow our posting guidelines I have lined out under your posting. We will also not touch code that uses third party plugins as for example Octane.
The issue with your code is that
CallButton
expects a node that is attached to a document.Cheers,
Ferdinandimport c4d from mxutils import CheckType doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: """Called by Cinema 4D when the script is being executed. """ material: c4d.BaseMaterial = CheckType(c4d.BaseMaterial(c4d.Mmaterial)) shader: c4d.BaseShader = CheckType(c4d.BaseShader(1019397)) # Insert the shader into the material and set the material's color channel to the shader. material.InsertShader(shader) material[c4d.MATERIAL_COLOR_SHADER] = shader # Insert the material into the document and click the "Add" button in the Multishader. doc.InsertMaterial(material) c4d.CallButton(shader, c4d.MGMULTISHADER_ADD) # This won't work because the shader is not yet part of a document. # c4d.CallButton(shader, c4d.MGMULTISHADER_ADD) # doc.InsertMaterial(material) # Update the Cinema 4D UI. c4d.EventAdd() if __name__ == '__main__': main()
-
@ferdinand Thank you
-
Hey,
One more thing, something like this:
for item in collection: DoStuff() c4d.EventAdd() DoStuff() c4d.EventAdd() DoStuff() c4d.EventAdd()
is identical to this:
for item in collection: DoStuff() DoStuff() DoStuff() c4d.EventAdd()
I.e., invoking
EventAdd
multiple times in a script is pointless. There is an event queue in Cinema 4D and once there is already an upcoming event, it is meaningless to try to line up another event. So, it only makes sense once per execution context (a script manager script, Cinema 4D calling a function in a plugin of yours) to invokeEventAdd
and it also does not matter where you do it (at the start, middle, or end), because the event will always only be executed once you give back control to Cinema 4D, i.e., when your code ends.There is a caveat to this, as it can make sense to have multiple
EventAdd
calls when you use the flags passed to the function to possibly add new flags to the upcoming event. But since these flags are only rarely used this is a bit of a fringe case.def foo(doc: c4d.documents.BaseDocument, foreRedraw: bool): """Invokes EventAdd more than once to add EVENT_FORCEREDRAW to an upcoming event. """ # We are always sure that we want to push an event when this functions runs. Normally we would # put this at the end of the function as this makes semantically more sense. But for the sake of # this example we put it at the beginning. c4d.EventAdd() result: bool = DoStuff(doc) # When something happened and #foreRedraw is True we call EventAdd() again. This will not add # another event to the queue but when we pass a new flag it will add this flag to the upcoming # event (the EventAdd() from above did not yet happen). if result and foreRedraw: c4d.EventAdd(c4d.EVENT_FORCEREDRAW)
Cheers,
Ferdinand -
Yes, I know about not using multiple events. I was playing with that, I thought that's the reason the button was not being called
Thank you @ferdinand