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
    • Register
    • Register
    • Login

    access the layers in the shader layer

    Cinema 4D SDK
    python
    2
    10
    1.9k
    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.
    • JH23J
      JH23
      last edited by

      Hi,
      Today I was trying to link or access the color within a sahder layer only with python, I know I can get it and change its parameter in the same sahder layer, but my question is more about how I can enter one of these and change its data , as in this case the color, or also the direction of a bitmap.

      1 Reply Last reply Reply Quote 0
      • i_mazlovI
        i_mazlov
        last edited by

        Hi @JH23,

        Thanks for reaching out to us. Please consider checking our Forum Guidelines about the question structure. I'm struggling from understanding your problem and would kindly ask you to elaborate on it.

        In addition, Ferdinand shared an awesome example on the topic of shader layers earlier this week: Traversing a layer shader with python. You might be also interested in the How to change bitmap in layered shader? thread as it seems to directly answer your question.

        Cheers,
        Ilia

        MAXON SDK Specialist
        developers.maxon.net

        JH23J 1 Reply Last reply Reply Quote 1
        • JH23J
          JH23 @i_mazlov
          last edited by

          Hi @i_mazlov ,
          Excuse me for the lack of research, if I usually check if there were similar cases but I don't think I was able to understand it well, thank you very much for showing me these examples, they were really helpful.
          the code you wanted:

          import c4d
          
          def ChangeTexturePathOfLayer(layer = c4d.LayerShaderLayer, Vector = c4d.Vector()):
              bmpShader = layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK)
              bmpShader[c4d.COLORSHADER_COLOR] = Vector
          def main():
              mat = doc.GetFirstMaterial()
              if not mat:
                  return
              shd = mat.GetFirstShader()
              if shd.CheckType(c4d.Xlayer):
                  ChangeTexturePathOfLayer(shd.GetFirstLayer(), c4d.Vector(0.458823, 0.278431, 0.164705))
                  c4d.EventAdd()    
          if __name__ == '__main__':
              main()
          

          I still don't know what c4d.LAYER_S_PARAM_SHADER_LINK does specifically
          Well, within the documentation it is only mentioned that int is allowed as a parameter.
          Cheers,
          James H.

          1 Reply Last reply Reply Quote 0
          • i_mazlovI
            i_mazlov
            last edited by

            Hi James,

            Thank you for your follow up message. The information about what you're trying to achieve is still missing or highly implicit in your reply (there is no question).

            Assuming your goal is to adjust shader attributes (color value for color shader and bitmap path for the bitmap shader), the snippet on the thread that I pointed you out to shows up exactly this case (for the bitmap path): How to change bitmap in layered shader?. I've sketched up the corresponding part for the color shader for you (please find below).

            The c4d.LAYER_S_PARAM_SHADER_LINK parameter basically points to the object that contains the shader. Please, refer to the C++ documentation in this regard: LAYER_S_PARAM_SHADER. Some parts of our API are better documented on the C++ side, so it is worth double checking the missing parts there.

            Cheers,
            Ilia

            Cinema_4D_F6zPrm5IbI.gif

            The code snippet:

            import c4d
            
            doc: c4d.documents.BaseDocument  # The active document
            
            def RetrieveShader(layer: c4d.LayerShaderLayer):
                # Check if the layer is really a shader
                if not layer or layer.GetType() != c4d.TypeShader:
                    raise ValueError("Layer is not a shader")
            
                # Retrieve the linked shader of this layer
                return layer.GetParameter(c4d.LAYER_S_PARAM_SHADER_LINK)
            
            def ChangeTexturePathOfLayer(layer: c4d.LayerShaderLayer, texturePath: str) -> None:
                """Change the texture path of an existing Bitmap Layer
                """
                shader: c4d.C4DAtom = RetrieveShader(layer)
            
                # check if this is really a bitmap shader
                if not shader.CheckType(c4d.Xbitmap):
                    raise ValueError("First layer is not a bitmap shader")
            
                # Update the texture path of the shader linked to this layer
                shader[c4d.BITMAPSHADER_FILENAME] = texturePath
            
            def ChangeColorShader(layer: c4d.LayerShaderLayer, color: c4d.Vector) -> None:
                """Change the color of and existing Color Shader
                """
                shader: c4d.C4DAtom = RetrieveShader(layer)
            
                if not shader.CheckType(c4d.Xcolor):
                    raise ValueError("First layer is not a color shader")
            
                shader[c4d.COLORSHADER_COLOR] = color
            
            def main() -> None:
                # Get the color channel shader for the first material in the scene.
                material: c4d.BaseMaterial | None = doc.GetFirstMaterial()
                if not material:
                    raise RuntimeError("Please add at least one material to the document.")
            
                shader: c4d.BaseList2D | None = material.GetFirstShader()
                if not shader or not shader.CheckType(c4d.Xlayer):
                    raise RuntimeError("First shader is not a layer shader")
            
                # Update an existing Bimtap Layer
                ChangeTexturePathOfLayer(shader.GetFirstLayer(), r"D:\temp\tex2.jpg")
            
                # Update an existing Color Layer
                ChangeColorShader(shader.GetFirstLayer().GetNext(), c4d.Vector(0., 1., 0.))
            
                c4d.EventAdd()
            
            
            if __name__ == '__main__':
                main()
            

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 3
            • JH23J
              JH23
              last edited by

              Hi @i_mazlov ,
              I have another question and I want to take advantage of this situation to consult, I really also want to be able to change the float that measures the mixing force, (I also wanted to know how to access the rounding) and I could, but now my problem is that it really takes too long, because not to say that it does not react until I manually move this float.
              Here is an example:

              here the code (python tag)

              import c4d
              def main():
                  doc = c4d.documents.GetActiveDocument()
                  obj = op.GetObject()
                  F = obj[c4d.ID_USERDATA,1]
                  FM = doc.GetFirstMaterial()
                  shd = FM.GetFirstShader()
                  layer = shd.GetFirstLayer()
                  i = 0
                  while True:
                      if layer:
                          if i == F:
                              layer.SetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND,1)
                          else:
                              layer.SetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND,0)
                          layer = layer.GetNext()
                      elif layer == None:
                          break
                      i = i+1
                  c4d.EventAdd()
              
              

              cheers,
              James H.

              JH23J 1 Reply Last reply Reply Quote 0
              • JH23J
                JH23 @JH23
                last edited by

                Currently my problem would only be the issue of the lack of updating, because now I know that I can change the boolean of the layer with LAYER_S_PARAM_ALL_ACTIVE , but the lack of updating persists, I really don't know what could be causing it is causing.
                code example, using the booleans of the layer:

                
                import c4d
                def main():
                    doc = c4d.documents.GetActiveDocument()
                    obj = op.GetObject()
                    F = obj[c4d.ID_USERDATA,1]
                    FM = doc.GetFirstMaterial()
                    shd = FM.GetFirstShader()
                    layer = shd.GetFirstLayer()
                    i = 0
                    while True:
                        if layer:
                            if i == F:
                                #layer.SetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND,True)
                                layer.SetParameter(c4d.LAYER_S_PARAM_ALL_ACTIVE,True)
                            else:
                                #layer.SetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND,False)
                                layer.SetParameter(c4d.LAYER_S_PARAM_ALL_ACTIVE,False)
                            layer = layer.GetNext()
                        elif layer == None:
                            break
                        i = i+1
                    c4d.EventAdd()
                
                1 Reply Last reply Reply Quote 0
                • i_mazlovI
                  i_mazlov
                  last edited by

                  Hi @JH23,

                  Sorry for the delayed reply.

                  The issue you're struggling with is more the UI not being updated with the changed data. Normally, the SetParameter function also takes flags argument as a 3rd parameter, i.e. using
                  DESCFLAGS_SET_USERINTERACTION would do the trick. However, the LayerShader object is special in a way that it doesn't accept any flags argument. I'm not aware of a possible workaround for it.

                  Let me know if you have any further questions.

                  Cheers,
                  Ilia

                  MAXON SDK Specialist
                  developers.maxon.net

                  JH23J 1 Reply Last reply Reply Quote 0
                  • JH23J
                    JH23 @i_mazlov
                    last edited by

                    Hola @i_mazlov ,
                    Yes, it is true, DESCFLAGS_SET_USERINTERACTION does not work with layers, any other contribution to the problem is appreciated, from this I have no other doubt related to this topic, I leave the file here as an example.
                    example.c4d
                    cheers,
                    James H.

                    1 Reply Last reply Reply Quote 0
                    • i_mazlovI
                      i_mazlov
                      last edited by i_mazlov

                      Hi @JH23,

                      We had an internal discussion about this issue. Sending the c4d.MSG_UPDATE message does trigger the necessary update. Please find the code snippet below.

                      Let me know if you have any further questions.

                      Cheers,
                      Ilia

                      explorer_Oogrx5yDAk.gif

                      import c4d
                      doc: c4d.documents.BaseDocument # The active document
                      
                      def main():
                          material: c4d.BaseMaterial = doc.GetFirstMaterial()
                          if not material:
                              return
                      
                          shader: c4d.BaseShader = material[c4d.MATERIAL_COLOR_SHADER]
                          if not shader or not shader.CheckType(c4d.Xlayer):
                              print ("Color channel does not contain layer shader.")
                              return
                      
                          layer: c4d.LayerShaderLayer = shader.GetFirstLayer()
                          if not layer:
                              return
                      
                          layer.SetParameter(c4d.LAYER_S_PARAM_SHADER_BLEND, 0.5)
                          shader.Message(c4d.MSG_UPDATE)
                          
                          c4d.EventAdd()
                      
                      if __name__ == "__main__":
                          main()
                      

                      MAXON SDK Specialist
                      developers.maxon.net

                      1 Reply Last reply Reply Quote 1
                      • JH23J
                        JH23
                        last edited by

                        Hi @i_mazlov ,
                        This solves my problem, for now I don't think I have another question, and I could consider my problem solved, thanks.
                        cheers,
                        James H.

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