Navigation

    • Register
    • Login
    • Search
    • Categories
    1. Home
    2. Graeme
    G
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Graeme

    @Graeme

    0
    Reputation
    10
    Posts
    60
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online

    Graeme Follow

    Posts made by Graeme

    • RE: Material Assignments doesn't update when changing TextureTag Material

      Thanks for your reply. You're right I was inserting it afterwards.
      Is it best to insert the material to the document immediately after creation before I start to change anything ?
      It's working correctly now.

      posted in Cinema 4D Development
      G
      Graeme
    • Material Assignments doesn't update when changing TextureTag Material

      Python
      Cinema 4D R23.110
      Windows 10 latest

      I have written a simple back-converter to change Octane Materials back to Cinema 4D materials, for export or for members of our team who don't have Octane.
      It basically works by creating a new Cinema 4D Material, setting it up & then changing the link in the existing Texture Tag from the Octane material to the new Cinema 4D material.
      It all works fine, except that after the script has run, the 'Assign' tab of the new Cinema 4D material doesn't show the objects & texture tags to which it is assigned. This makes me worry that I'm missing some kind of message or initialisation step.
      Here's the bit of code that's relevant:

      def ReAssign(doc, oct_mat, c4d_mat):                                              #Assigns the new Cinema 4D material to the texture tags
          obj_link = oct_mat[c4d.ID_MATERIALASSIGNMENTS]                                #Get the link list for the Octane Material's assignment
          link_count = obj_link.GetObjectCount()                                        #Get how many objects are in the link list
          for i in range(link_count):                                                   #For each of them...
              tex_tag = obj_link.ObjectFromIndex(doc, i)                                #Get the texture tag
              doc.AddUndo(c4d.UNDOTYPE_CHANGE, tex_tag)                                 #Add an undo for the tex tag change
              tex_tag[c4d.TEXTURETAG_MATERIAL] = c4d_mat                                #Replace the Octane Material with the Cinema 4D material
              tex_tag.Message(c4d.MSG_CHANGE)                                           #update the tex tag
              c4d_mat.Message(c4d.MSG_CHANGE)                                           #update the c4d material
      

      Any pointers on what I'm missing/ best practice ?

      posted in Cinema 4D Development
      G
      Graeme
    • RE: Can't work out BaseDocument.StartPickSession

      So trying this out, there are a couple of problems:

      1. Once I have run the script & picked an object, it 'remembers' it & if I run the script again, pickedObjects contains the object I picked in that previous session. I want the selection to be cleared each time
      2. If I revert my scene to saved, run the script & press escape to cancel the pick session, it reliably hangs Cinema 4D - is there some kind of clean-up I need to be performing or msg to send ?

      Thanks for your help.

      posted in Cinema 4D Development
      G
      Graeme
    • RE: Can't work out BaseDocument.StartPickSession

      Thanks Maxime, I'll process this & see if I can work it out.
      Thanks for the example.

      posted in Cinema 4D Development
      G
      Graeme
    • RE: Can't work out BaseDocument.StartPickSession

      Any ideas anyone ?
      I can't find an example anywhere on the internet for how a pick session works, except for one plugin cafe post, which is how I got as far as I have.

      posted in Cinema 4D Development
      G
      Graeme
    • Can't work out BaseDocument.StartPickSession

      I want to do something very simple: Enter into a pick session & return the 1st object picked, ending the session & storing the object reference. I don't need a multi-pick session.
      Here's my code:

      def OnPick(flags, active, multi):
          if flags & c4d.PICKSESSION_FLAG_CANCELED:
              print "User cancel"
              doc.StopPickSession(cancel = True)
          else:
              doc.StopPickSession(cancel = False)
          print "active: ", active
      
      def main():
          doc = documents.GetActiveDocument()
          doc.StartPickSession(OnPick, multi=False)
      

      This seems to work & 'active' contains the picked object.
      But I can't return any reference to the object in 'active'
      as soon as I try to read it into a variable, or return it I get AttributeError: 'function' object has no attribute 'function'.

      I'm afraid I just don't understand how pick sessions are supposed to work.
      Any help would be very appreciated.

      posted in Cinema 4D Development
      G
      Graeme
    • RE: Accessing Octane node editor with python

      Another link to the Otoy forums:
      https://render.otoy.com/forum/viewtopic.php?f=87&t=56039

      posted in General Programming & Plugin Discussions
      G
      Graeme
    • RE: Accessing Octane node editor with python

      Not about the node editor specifically, but there are some example Python Octane scripts in this thread:
      https://render.otoy.com/forum/viewtopic.php?f=30&t=43086&p=208809&hilit=python#p208809
      Also, here is a script I wrote to convert Octane Materials to native Cinema 4D ones, mainly so the textures are picked up by FBX export to Unreal. It shows you examples of some of the Octane nodes etc. It's a little crude, but every line is commented. When it comes to finding out the ID's for different Octane nodes, you can drag them into the console & then add '.GetType()' & hit enter - that will give you the numerical ID for that Octane node.

      """
      OctaneToC4d
      v0.1
      
      Written by Graeme McDougall for Painting Practice
      Copyright: Painting Practice (www.paintingpractice.com)
      Written for Cinema 4d R20.057
      
      Name-US:OctaneToC4d
      Description-US:Converts selected Octane materials to Cinema 4d materials, as best as possible
      """
      
      import c4d
      from c4d import documents
      
      ID_OCTANE_MATERIAL = 1029501                                                      #Here we define more readable IDs for any integer IDs we are using
      ID_OCTANE_IMAGE_TEXTURE = 1029508                                                 #To make our code more readable
      ID_OCTANE_COLORCORRECTION = 1029512
      ID_OCTANE_INVERT_TEXTURE = 1029514
      ID_OCTANE_MULTIPLY_TEXTURE = 1029516
      ID_OCTANE_MIXTEXTURE = 1029505
      mainLayerId = 526336
      
      
      def CheckSelection(doc, mats):                                                    #Checks selection & returns a list of only the Octane materials
          oct_mats = []                                                                 #Create an empty list, to later store any Octane materials
          if mats:                                                                      #If there are any materials selected...
              count  = len(mats)                                                        #...get how many
              for i in range(count):                                                    #for each one...
                  if mats[i].GetType() == ID_OCTANE_MATERIAL:                           #...if it's an Octane material...
                      oct_mats.append(mats[i])                                          #...add it to our list of Octane materials
          return oct_mats                                                               #Return the list of Ocatne mats
      
      def GetTexture(doc, oct_mat, channel):                                            #Gets a filename from a particular channel of an Octane mat
          image_name = None                                                             #Create an empty variable to store the image name
          image_shader = oct_mat[channel]                                               #Check the texture link & load shader in variable image_tex
          if image_shader:                                                              #If one is found...
              shader_type = image_shader.GetType()                                      #...get it's type
      
              if shader_type == ID_OCTANE_MULTIPLY_TEXTURE:                             #If it's a multiply shader...
                  image_shader = image_shader[c4d.MULTIPLY_TEXTURE1]                    #Get the first shader in it
                  if image_shader:                                                      #If we found a shader of some sort
                      shader_type = image_shader.GetType()                              #Load it's type into the tex_type variable
      
              if shader_type == ID_OCTANE_MIXTEXTURE:                                   #If it's a mix shader...
                  image_shader = image_shader[c4d.MIXTEX_TEXTURE1_LNK]                  #Get the first shader in it
                  if image_shader:                                                      #If we found a shader of some sort
                      shader_type = image_shader.GetType()                              #Load it's type into the tex_type variable
      
              if shader_type == ID_OCTANE_COLORCORRECTION:                              #If it's a colour correction shader
                  image_shader = image_shader[c4d.COLORCOR_TEXTURE_LNK]                 #Get the texture in it's texture link & replace the image_tex var
                  if image_shader:                                                      #If we found a shader of some sort
                      shader_type = image_shader.GetType()                              #Load it's type into the tex_type variable
      
              if shader_type == ID_OCTANE_INVERT_TEXTURE:                               #If it's an invert shader
                  image_shader = image_shader[c4d.INVERT_TEXTURE]                       #Get the texture in it's texture link & replace the image_tex var
                  if image_shader:                                                      #If we found a shader of some sort
                      shader_type = image_shader.GetType()                              #Get it's type
      
              if shader_type == ID_OCTANE_IMAGE_TEXTURE:                                #If after checking all this, we have an image texture shader..
                  image_name = image_shader[c4d.IMAGETEXTURE_FILE]                      #Read the filename into the image_link variable
                  print image_name
          return image_name                                                             #Return the filename, if found
      
      def ReAssign(doc, oct_mat, c4d_mat):                                              #Assigns the new Cinema 4D material to the texture tags
          obj_link = oct_mat[c4d.ID_MATERIALASSIGNMENTS]                                #Get the link list for the Octane Material's assignment
          link_count = obj_link.GetObjectCount()                                        #Get how many objects are in the link list
          for i in range(link_count):                                                   #For each of them...
              tex_tag = obj_link.ObjectFromIndex(doc, i)                                #Get the texture tag
              doc.AddUndo(c4d.UNDOTYPE_CHANGE, tex_tag)                                 #Add an undo for the tex tag change
              tex_tag[c4d.TEXTURETAG_MATERIAL] = c4d_mat                                #Replace the Octane Material with the Cinema 4D material
              tex_tag.Message(c4d.MSG_CHANGE)                                           #update the tex tag
      
      def RebuildMats(doc, oct_mats):                                                   #Rebuilds each Octane material as a Cinema 4D material
          c4d_mats = []                                                                 #Create an empty list where we store our new Cinema 4D mats
          count = len(oct_mats)                                                         #Get how many Octane mats we have
          for i in range(count):                                                        #For each one...
              oct_mat = oct_mats[i]                                                     #Read the Octane Material into the variable oct_mat
              c4d_mat = c4d.BaseMaterial(c4d.Mmaterial)                                 #Create a new Cinema 4D material
              name = oct_mat[c4d.ID_BASELIST_NAME]                                      #Read the Material's name from the Octane mat...
              c4d_mat[c4d.ID_BASELIST_NAME] = name                                      #...and name the c4d material the same
      
              diff_file = GetTexture(doc, oct_mat, c4d.OCT_MATERIAL_DIFFUSE_LINK)       #Get the texure filename from the diffuse channel
              if diff_file:                                                             #If we did find a texrure filename...
                  diff_shader = c4d.BaseShader(c4d.Xbitmap)                             #...create a new empty bitmap shader...
                  diff_shader[c4d.BITMAPSHADER_FILENAME] = diff_file                    #...and load the filename in there
                  c4d_mat[c4d.MATERIAL_COLOR_SHADER] = diff_shader                      #Assign the bitmap shader to the material's colour channel...
                  c4d_mat.InsertShader(diff_shader)                                     #...and insert it into the material
      
              opac_file = GetTexture(doc, oct_mat, c4d.OCT_MATERIAL_OPACITY_LINK)       #Get the texture filename from the opacity channel
              if opac_file:                                                             #If we found one...
                  opac_shader = c4d.BaseShader(c4d.Xbitmap)                             #...create a new empty bitmap shader...
                  opac_shader[c4d.BITMAPSHADER_FILENAME] = opac_file                    #...and load the filename in there
                  c4d_mat[c4d.MATERIAL_ALPHA_SHADER] = opac_shader                      #Assign the bitmap shader to the material's alpha channel...
                  c4d_mat.InsertShader(opac_shader)                                     #...and insert it into the material
                  c4d_mat[c4d.MATERIAL_USE_ALPHA] = True                                #Activate the alpha channel
      
              normal_file = GetTexture(doc, oct_mat, c4d.OCT_MATERIAL_NORMAL_LINK)      #Get the texure filename from the normal channel...
              if normal_file:                                                           #If we found one...
                  normal_shader = c4d.BaseShader(c4d.Xbitmap)                           #...create a new empty bitmap shader
                  normal_shader[c4d.BITMAPSHADER_FILENAME] = normal_file                #...and load the filename in there
                  c4d_mat[c4d.MATERIAL_NORMAL_SHADER] = normal_shader                   #Assign the bitmap shader to the material's mormal channel...
                  c4d_mat.InsertShader(normal_shader)                                   #...and insert it into the material
                  c4d_mat[c4d.MATERIAL_USE_NORMAL] = True                               #Activate the normal channel
      
              bump_file = GetTexture(doc, oct_mat, c4d.OCT_MATERIAL_BUMP_LINK)          #Get the texure filename from the normal channel...
              if bump_file:                                                             #If we found one...
                  bump_shader = c4d.BaseShader(c4d.Xbitmap)                             #...create a new empty bitmap shader
                  bump_shader[c4d.BITMAPSHADER_FILENAME] = bump_file                    #...and load the filename in there
                  c4d_mat[c4d.MATERIAL_BUMP_SHADER] = bump_shader                       #Assign the bitmap shader to the material's mormal channel...
                  c4d_mat.InsertShader(bump_shader)                                     #...and insert it into the material
                  c4d_mat[c4d.MATERIAL_USE_BUMP] = True                                 #Activate the normal channel
      
              rough_file = GetTexture(doc, oct_mat, c4d.OCT_MATERIAL_ROUGHNESS_LINK)    #Get the texure filename from the roughness channel...
              if rough_file:                                                            #If we found one...
                  rough_shader = c4d.BaseShader(c4d.Xbitmap)                            #...create a new empty bitmap shader
                  rough_shader[c4d.BITMAPSHADER_FILENAME] = rough_file                  #...and load the filename in there
                  c4d_mat[c4d.MATERIAL_USE_REFLECTION] = True                           #Activate the Reflectance channel
                  c4d_mat[mainLayerId + c4d.REFLECTION_LAYER_MAIN_DISTRIBUTION] = 2     #Change the Default Specular to a Beckmann type
                  c4d_mat[mainLayerId + c4d.REFLECTION_LAYER_MAIN_SHADER_ROUGHNESS] = rough_shader
                  c4d_mat.InsertShader(rough_shader)                                    #...and insert it into the material
      
              ReAssign(doc, oct_mat, c4d_mat)                                           #Assign the new Cinema material inplace of the Octane one
      
              c4d_mats.append(c4d_mat)                                                  #Add the new mat to our list of Cinema 4D materials
              doc.InsertMaterial(c4d_mat)                                               #Insert the Cinema 4D Material in the document
              doc.AddUndo(c4d.UNDOTYPE_NEW, c4d_mat)                                    #Add an undo step for the new material
      
          return
      
      
      def main():
          my_doc = documents.GetActiveDocument()                                        #Get the active document
          my_mats = my_doc.GetActiveMaterials()                                         #Get the selected materials
          my_oct_mats = CheckSelection(my_doc, my_mats)                                 #Checks the selected mats & returns only the octane ones
      
          if my_oct_mats:                                                               #If we did find Octane materials...
              doc.StartUndo()                                                           #Start the undo chain
              RebuildMats(my_doc, my_oct_mats)                                          #...re-create them as Cinema 4D mats
              doc.EndUndo()                                                             #End the undo chain
              c4d.EventAdd()                                                            #Add an event
      
      
      
      if __name__=='__main__':
          main()
      
      posted in General Programming & Plugin Discussions
      G
      Graeme
    • RE: Updating Polygon Selection Tag

      Firstly, thanks for your reply.
      Secondly, for the Q&A, it seems like the way the forum works has updated since I last used it. I will be sure to follow the correct protocol in future.

      Well, I just typed out a big answer & then I saw that you're right - the Polygon Selection Tags are already updated, without me having to do anything more !

      Is there some message I should send to the tags for safety, like a MSG_CHANGE from the c4dAtom ?

      posted in Cinema 4D Development
      G
      Graeme
    • Updating Polygon Selection Tag

      Hi there, I'm writing a script in python & I wanted to ask how I can update a polygon selection tag (Exactly as if you call the 'Select' -> 'Set Selection' command with the polygon selection tag selected).

      Basically, I am Getting the C4d.BaseSelect from the c4d.SelectionTag & altering the C4d.BaseSelect - afterwards, I want to update the c4d.SelectionTag with the changes.

      Here is a very simplified sample code:

      curr_sel = sel_tag.GetBaseSelect()
      comp_sel = comp_tag.GetBaseSelect()
      curr_sel.DeselectFrom(comp_sel)

      Now I would like to write my modified curr_sel back to the sel_tag Polygon Selection Tag, but I don't know how.

      I am prepared to select it in the interface & use CallCommand as a last resort, but it's not very elegant & I won't be able to add undos.

      Thanks in advance for your help.

      posted in Cinema 4D Development
      G
      Graeme