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

    [SOLVED]How to know channel

    PYTHON Development
    0
    7
    888
    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.
    • H
      Helper
      last edited by

      On 27/01/2017 at 02:27, xxxxxxxx wrote:

      In this post https://developers.maxon.net/forum/topic/9910/13352_get-base-object-input-id-for-link-fields&PID=52874#52874 Andreas describe a bit more how link are done in C4D.
      And since I worked on a texture manager like.

      I was wondering how the c4d one acutally know to which channel a bitmap is attached to.

      Here is a quick test but it's only give me the name where the texture is linked not his canal.

      import c4d
        
      def main() :
          mat = doc.GetFirstMaterial()
          desc = mat.GetDescription(c4d.DESCFLAGS_DESC_0)
          for bc, paramid, groupid in desc:
              if bc[c4d.DESC_SHADERLINKFLAG]:
                  if mat[paramid[0].id]:
                      print bc[c4d.DESC_NAME]
       
      main()
      

      Moreover in this exemple this work from material to shader (is it possible to do from shader to material ?) I guess instead of passing a material and checking each link and then comparing with a shader, is it possible to get the parent of a linked shader(I guess no but cost nothing to ask)

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 27/01/2017 at 14:23, xxxxxxxx wrote:

        The shortest way is to test each channel's bool value: print mat[c4d.MATERIAL_USE_COLOR]
        You'll need to do this for each channel. But if you don't want to write each of them by hand. You can scrape them from the c4d descriptions.
        Just limit how many times you do that. Because there's a ton of them, and it could slow down your code if you iterate that huge list of descriptions too often in loops and such.

        This code also works with older versions.
        There might be a way to use GetDescription() in a similar way.
        But since I'm using R13. That is not an option for me.

        #This gets all of the enabled channels in a material  
          
        import c4d  
        def main() :      
          
          mat = doc.GetFirstMaterial()  
          if mat is None: return False  
            
          #Because iterating the descriptions is labor intensive(it's a very long list)  
          #We only want to do it once  
          #So we store the small list of channel description enums in this much smaller list      
          channels = []  
          
          #Iterate through all of the descriptions that are registered in C4D      
          for i, v in c4d.__dict__.iteritems() :  
                
              #If the description ID belongs to one of the channel ID#s  
              #And the channel is enabled  
              #Print the name and ID of the channel  
              if i.startswith("MATERIAL_USE_") :  
                  if mat[v] == 1:  
                      matName = mat.GetName()  
                      ch = "c4d." + i                 
                      channels.append(ch)  
                      print matName, ch, v  
                        
          #From now on...Use the small channels list rather than iterating the huge c4d.__dict__  
            
          c4d.EventAdd()  
          
        if __name__=='__main__':  
          main()
        

        -ScottA

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 28/01/2017 at 04:15, xxxxxxxx wrote:

          Thanks scotta it can be a workaround, but is not exactly what I want. And for exemple with a vray shader it didn't work (he jsut told me use specular) not the channel name.

          So i guess it's not like that c44d work. http://img11.hostingpics.net/pics/262976texturemanager.png As you could see in this screen it put the channel name.

          A workaround could be to do it manually by telling if any bitmap is a child of this linkfield than it's in specular if it's into this linkfield it's in transparency... But it's a bit boring (but it would work for sure.)

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 28/01/2017 at 07:25, xxxxxxxx wrote:

            I was asking a sort of similar question recently about the pop up menu.
            I didn't like having to dig all the way into the shader link just to get the type of shader the user added. It seemed to be not logical to me, and it would be quicker to get that from the item the user clicked on. But Sebastien says that's how we must to do it.

            Regarding your other question about getting the channel from the shader(going backwards).
            I don't think there's any way to do that because those channels are actually just simple checkbox gizmos. The same ones we use when making our plugins. And they are not bound to anything special. They're just simple boolean switches for determining which code blocks to run in the code.
            When I wrote my own custom material plugin I was surprised to learn that those check boxes weren't coded to interact with the rest of the plugin in any special way. They're just plain old check box gizmos. So AFAIK there's no actual code we can use to get the channel from a shader link.

            -ScottA

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 30/01/2017 at 02:02, xxxxxxxx wrote:

              Hi,

              as Scott already pointed out, there's no direct way to get from shader to channel (as Scott said, the channels are more a UI point of view).

              A suggestion, what you could do:
              Build yourself mapping tables per material type (this needs to be done only once), which store the DescID of the "first level" shader slots and the channel ID these are located in. Then, when you want to know, which channel a certain BitmapShader is in, you can use GetMain() (maybe several times) to get to the "first level" shader slot and to the material. And then you can look up in your mapping table, which channel the shader is located in.

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 31/01/2017 at 02:52, xxxxxxxx wrote:

                Make the mapping table it's what i'm afraid of... I'm lazy I prefer do multiple loop than boring stuff (moreover I have to done it with multiple shaders / render engine) but it's ok here is an exemple with c4d material

                import c4d
                  
                  
                def get_channel_from_shader(shader) :
                    mat = shader.GetMain() 
                    parent_shader = shader
                  
                    var=1
                    while var == 1:
                        buffer_sha = parent_shader.GetUp()
                        if buffer_sha:
                            parent_shader = buffer_sha
                        else:
                            break
                    
                    if parent_shader is None:
                        return
                  
                    data = list()
                    text = "Unknown"           
                    if mat.CheckType(c4d.Mmaterial) :
                        text = "c4dMat::"
                        data = [
                            {"link_id": [
                                c4d.MATERIAL_COLOR_SHADER],
                             "value": "Color"},
                  
                            {"link_id": [
                                c4d.MATERIAL_DIFFUSION_SHADER],
                             "value": "Diffusion"},
                  
                            {"link_id": [
                                c4d.MATERIAL_LUMINANCE_SHADER],
                                "value": "Luminance"},
                  
                            {"link_id": [
                                c4d.MATERIAL_TRANSPARENCY_SHADER],
                                "value": "Transparency"},
                  
                            {"link_id": [
                                c4d.REFLECTION_LAYER_COLOR_TEXTURE,
                                c4d.REFLECTION_LAYER_TRANS_TEXTURE],
                                "value": "Reflexion"},
                  
                            {"link_id": [
                                c4d.MATERIAL_ENVIRONMENT_SHADER],
                                "value": "Environment"},
                  
                            {"link_id": [
                                c4d.MATERIAL_BUMP_SHADER],
                                "value": "Bump"},
                  
                            {"link_id": [
                                c4d.MATERIAL_NORMAL_SHADER],
                                "value": "Normal"},
                  
                            {"link_id": [
                                c4d.MATERIAL_ALPHA_SHADER],
                                "value": "Alpha"},
                  
                            {"link_id": [
                                c4d.MATERIAL_DISPLACEMENT_SHADER],
                                "value": "Displace"}
                        ]
                    
                    leave = False
                    for x in data:
                        for link in x["link_id"]:
                            if mat[link] == parent_shader:
                                text += str(x["value"])
                                leave = True
                                break
                        if leave:
                            break
                        
                    return text
                  
                def main() :
                    sha = doc.GetFirstMaterial().GetFirstShader()
                    print get_channel_from_shader(sha)
                  
                if __name__=='__main__':
                    main()
                

                Btw you said GetMain() get the first level but GetMain always return the holder of the shader (so the basematerial).
                You probably want to said GetUp 😉

                Anyway thanks for everything.

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 31/01/2017 at 06:27, xxxxxxxx wrote:

                  Something like you describe as getMain( which return the direct parent will be a nice feature). Since GetUp() is not trustable.
                  Btw here is a workaround using directly linkfield. (Was a bit tricky to code hope it's understable)

                  import c4d
                    
                    
                  def get_linked_shader(shader, all_shader_list=list()) :
                      linkedData = get_linked_data(shader)
                      all_shader_list += linkedData
                    
                      for sha in linkedData:
                          linkedData = get_linked_shader(sha, all_shader_list)
                          for linked_sha in linkedData:
                              if linked_sha not in all_shader_list:
                                  all_shader_list.append(linked_sha)
                    
                      return all_shader_list
                    
                  def get_linked_data(shader) :
                      buffer = list()
                    
                      bc = shader.GetDataInstance()
                      for i in xrange(len(bc)) :
                          index = bc.GetIndexId(i)
                    
                          linked = bc.GetLink(index, doc, c4d.Xbase)
                          if linked:
                              buffer.append(linked)
                    
                      return buffer
                    
                  def get_channel_from_shader(shader) :
                      mat = shader.GetMain() 
                      parent_shader = shader
                    
                      var=1
                      while var == 1:
                          buffer_sha = parent_shader.GetUp()
                          if buffer_sha:
                              parent_shader = buffer_sha
                          else:
                              break
                      
                      if parent_shader is None:
                          return
                    
                      data = list()
                      text = "Unknown"           
                      if mat.CheckType(c4d.Mmaterial) :
                          text = "c4dMat::"
                          data = [
                              {"link_id": [
                                  c4d.MATERIAL_COLOR_SHADER],
                               "value": "Color"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_DIFFUSION_SHADER],
                               "value": "Diffusion"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_LUMINANCE_SHADER],
                                  "value": "Luminance"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_TRANSPARENCY_SHADER],
                                  "value": "Transparency"},
                    
                              {"link_id": [
                                  c4d.REFLECTION_LAYER_COLOR_TEXTURE,
                                  c4d.REFLECTION_LAYER_TRANS_TEXTURE],
                                  "value": "Reflexion"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_ENVIRONMENT_SHADER],
                                  "value": "Environment"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_BUMP_SHADER],
                                  "value": "Bump"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_NORMAL_SHADER],
                                  "value": "Normal"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_ALPHA_SHADER],
                                  "value": "Alpha"},
                    
                              {"link_id": [
                                  c4d.MATERIAL_DISPLACEMENT_SHADER],
                                  "value": "Displace"}
                          ]
                      
                      leave = False
                      for x in data:
                          for link in x["link_id"]:
                              if mat[link]:
                                  list_linked = get_linked_shader(mat[link])
                                  if parent_shader in list_linked or parent_shader == mat[link]:
                                      text += str(x["value"])
                                      leave = True
                                      break
                          if leave:
                              break
                          
                      return text
                    
                    
                  def main() :
                      sha = doc.GetFirstMaterial().GetFirstShader()
                      print get_channel_from_shader(sha)
                    
                  if __name__=='__main__':
                      main()
                  
                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post