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
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Get shader's parent ID

    Cinema 4D SDK
    python r19
    3
    8
    1.3k
    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.
    • A
      AndreAnjos
      last edited by

      Hi all,

      Is it possible to get the parent ID of a shader?
      For example have a image texture and want to know if is in the diffuse or opacity channel, etc?

      Cheers! ☺

      Andre

      A 1 Reply Last reply Reply Quote 0
      • A
        AndreAnjos @AndreAnjos
        last edited by

        @AndreAnjos

        Here's my answer ☺
        https://developers.maxon.net/forum/topic/9920/13363_solvedhow-to-know-channel/7

        Cheers! 👍

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

          Hey,

          if I do understand your initial question correctly the linked post does not contain your answer. While both BaseShaders and BaseMaterials are GeListNodes only BaseShaders that are attached to each other (a noise shader in a fusion shader for example) are in child - parent relationship. BaseMaterials do not carry their associated BaseShaders as children.

          While it is possible to figure out the hosting material for a shader by walking over all materials in the document, actually implementing that will be probably more work than you expect as you have to accommodate the mess that is Cinemas material system under the hood: reflectance channel, layer shader, multiple material types, and the list goes on.

          Let me clarify this (before an angry maxon employee points out that this all follows a bigger plan :)): I always felt that dealing with the material system is a bit of mess 😉

          Cheers
          zipit

          MAXON SDK Specialist
          developers.maxon.net

          A 1 Reply Last reply Reply Quote 1
          • A
            AndreAnjos @ferdinand
            last edited by

            @zipit said in Get shader's parent ID:

            Hey,

            if I do understand your initial question correctly the linked post does not contain your answer. While both BaseShaders and BaseMaterials are GeListNodes only BaseShaders that are attached to each other (a noise shader in a fusion shader for example) are in child - parent relationship. BaseMaterials do not carry their associated BaseShaders as children.

            While it is possible to figure out the hosting material for a shader by walking over all materials in the document, actually implementing that will be probably more work than you expect as you have to accommodate the mess that is Cinemas material system under the hood: reflectance channel, layer shader, multiple material types, and the list goes on.

            Let me clarify this (before an angry maxon employee points out that this all follows a bigger plan :)): I always felt that dealing with the material system is a bit of mess 😉

            Cheers
            zipit

            Hi Zipit,

            Thanks for your help and reply!
            Yes you are absolutely correct in regards of the relationship between BaseShaders and BaseMaterials (and how the material system works ;)). Perhaps I should have explained it better above, before marking it as solved. So thank you for that! 👍

            The solution I linked seems to be doing the opposite, where it checks the channel first and if enabled and have a shader, returns the channel. (Think this is what is written, but please correct me if i'm wrong! :))

            In my case, I have a specific attribute I want to change with all of the Octane materials. The Image Texture node has a type attribute that need changing to float for specific channels. This is reduce to memory when Octane is loading and rendering textures.

            Have to think of a different solution and come back...

            Thanks for your help again! ☺

            Andre

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

              Hi,

              ah, ok, that was indeed a misunderstanding then. I was just pointing out that you cannot go (easily) from a BaseShader instance to its associated BaseMaterial but you can of course retrieve all shaders associated with a BaseList2D via .GetFirstShader (which includes a BaseMaterial).

              Cheers
              zipit

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 1
              • A
                AndreAnjos
                last edited by AndreAnjos

                @zipit said in Get shader's parent ID:

                Hi,

                ah, ok, that was indeed a misunderstanding then. I was just pointing out that you cannot go (easily) from a BaseShader instance to its associated BaseMaterial but you can of course retrieve all shaders associated with a BaseList2D via .GetFirstShader (which includes a BaseMaterial).

                Cheers
                zipit

                Hi Zipit,

                Absolutely correct! Thank you! 👍

                I've actually end up hardcoding it a bit. To be honest it works for now and if needed to be changed, it's just a matter of changing the channels list. As such:

                import c4d
                
                count = 0
                total_size = 0.00
                
                
                def change_to_float(mat):
                    """
                    If channel contains linked textures, change attribute type to Float.
                    """
                
                    channels = [c4d.OCT_MATERIAL_ROUGHNESS_LINK,
                                c4d.OCT_MATERIAL_SPECULAR_LINK,
                                c4d.OCT_MAT_SPECULAR_MAP_LINK,
                                c4d.OCT_MATERIAL_BUMP_LINK,
                                c4d.OCT_MATERIAL_DISPLACEMENT_LINK,
                                c4d.OCT_MIXMATERIAL_DISPLACEMENT_LINK,
                                c4d.BLENDMAT_DISPLACEMENT_LINK,
                                c4d.OCT_MATERIAL_OPACITY_LINK,
                                c4d.OCT_MAT_REFLECTION_LINK,
                                c4d.MIXMATERIAL_AMOUNT_LNK]
                
                    for channel in channels:
                        if mat[channel]:
                
                            linked = mat[channel]
                
                            if channel == c4d.OCT_MATERIAL_DISPLACEMENT_LINK or \
                                    channel == c4d.BLENDMAT_DISPLACEMENT_LINK or \
                                    channel == c4d.OCT_MIXMATERIAL_DISPLACEMENT_LINK:
                
                                linked = linked[c4d.DISPLACEMENT_INPUT]
                
                            if linked is not None and linked[c4d.IMAGETEXTURE_MODE] == 0:
                
                                linked[c4d.IMAGETEXTURE_MODE] = 1  # Float
                                path = linked[c4d.IMAGETEXTURE_FILE]
                                bmp = c4d.bitmaps.BaseBitmap()
                                bmp.InitWith(path)
                
                                x, y = bmp.GetSize()  # Gets the X and Y dimensions of the image
                
                                size_bmp = (x * y) / 1024
                                global total_size
                                total_size += size_bmp
                
                                global count
                                count += 1
                
                    return count, total_size
                
                
                def main():
                    """
                    Main function for textureTypeFloat().
                    """
                
                    mat = DOC.GetFirstMaterial()
                    c4d.gui.SetMousePointer(c4d.MOUSE_NORMAL)
                
                    if not mat:
                        c4d.gui.MessageDialog("No material(s) in the scene!")
                        c4d.StatusSetText("No material(s) in the scene!")
                        return False
                
                    while mat:
                
                        c4d.gui.SetMousePointer(c4d.MOUSE_BUSY)
                
                        if mat.GetTypeName() == 'Octane Material' or \
                                mat.GetTypeName() == 'Octane Mix Material' or \
                                mat.GetTypeName() == 'Octane Blend Material':
                
                            count, total_size = change_to_float(mat)
                            print("{0} Checked!".format(mat.GetName()))
                
                        mat = mat.GetNext()
                
                    c4d.EventAdd()
                    c4d.gui.SetMousePointer(c4d.MOUSE_NORMAL)
                    c4d.gui.MessageDialog("{0} Shaders Changed! Saving {1:.2f} Mb!".format(count, (total_size / 1024)))
                
                
                if __name__ == '__main__':
                    main()
                
                

                Thank you very much for your help! ☺

                Andre

                1 Reply Last reply Reply Quote 0
                • ManuelM
                  Manuel
                  last edited by Manuel

                  hello,
                  thanks @zipit ^^

                  just one thing, in the context of the script manager, you don't need DOC = c4d.documents.GetActiveDocument() there is already doc.

                  cheers,
                  Manuel.

                  MAXON SDK Specialist

                  MAXON Registered Developer

                  A 1 Reply Last reply Reply Quote 1
                  • A
                    AndreAnjos @Manuel
                    last edited by

                    @m_magalhaes said in Get shader's parent ID:

                    hello,
                    thanks @zipit ^^

                    just one thing, in the context of the script manager, you don't need DOC = c4d.documents.GetActiveDocument() there is already doc.

                    cheers,
                    Manuel.

                    Corrected! ☺

                    Thank you Manuel!

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