Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Calling “Add” button in Multi Shader: doesn’t work!

    Cinema 4D SDK
    r25 python 2024
    3
    7
    874
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      sydney_ko
      last edited by

      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

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        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.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • S
          sydney_ko
          last edited by ferdinand

          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

          1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand
            last edited by ferdinand

            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,
            Ferdinand

            import 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()
            

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 0
            • S
              sydney_ko
              last edited by

              @ferdinand Thank you

              ferdinandF 1 Reply Last reply Reply Quote 0
              • ferdinandF
                ferdinand @sydney_ko
                last edited by ferdinand

                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 invoke EventAdd 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

                MAXON SDK Specialist
                developers.maxon.net

                1 Reply Last reply Reply Quote 0
                • S
                  sydney_ko
                  last edited by

                  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

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post