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

access the layers in the shader layer

Cinema 4D SDK
python
2
10
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.
  • J
    JH23
    last edited by Jun 9, 2023, 12:25 AM

    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
      i_mazlov
      last edited by Jun 9, 2023, 4:19 PM

      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

      J 1 Reply Last reply Jun 10, 2023, 1:48 AM Reply Quote 1
      • J
        JH23 @i_mazlov
        last edited by Jun 10, 2023, 1:48 AM

        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
          i_mazlov
          last edited by Jun 12, 2023, 11:27 AM

          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
          • J
            JH23
            last edited by Jun 14, 2023, 3:45 PM

            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.

            J 1 Reply Last reply Jun 16, 2023, 12:50 AM Reply Quote 0
            • J
              JH23 @JH23
              last edited by Jun 16, 2023, 12:50 AM

              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
                i_mazlov
                last edited by Jun 20, 2023, 8:40 AM

                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

                J 1 Reply Last reply Jun 20, 2023, 6:50 PM Reply Quote 0
                • J
                  JH23 @i_mazlov
                  last edited by Jun 20, 2023, 6:50 PM

                  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
                    i_mazlov
                    last edited by i_mazlov Jul 3, 2023, 2:54 PM Jul 3, 2023, 2:50 PM

                    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
                    • J
                      JH23
                      last edited by Jul 3, 2023, 10:59 PM

                      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