Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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

    Creating Custom Callback?

    Scheduled Pinned Locked Moved PYTHON Development
    8 Posts 0 Posters 1.4k Views
    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 Offline
      Helper
      last edited by

      On 15/04/2018 at 15:45, xxxxxxxx wrote:

      For all my experience in Cinema 4D as an artist I am much more familiar with scripting in Nuke and Maya where custom callbacks are relatively straightforward to create.

      Is it possible to create custom callbacks to trigger on specific events?

      I'm specifically interested in modifying Redshift material presets to use the proper colors whether the current document is using an sRGB or Linear input profile.  So far I know that I can use

      doc[c4d.DOCUMENT_COLORPROFILE]
      

      to query the current input profile. And I can use

      c4d.utils.TransformColor()
      

      to convert from Linear to sRGB or vice versa, but how can I attach my custom function to execute when the Redshift material preset dropdown

      c4d.REDSHIFT_SHADER_MATERIAL_PRESET
      

      is modified?

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

        On 16/04/2018 at 03:59, xxxxxxxx wrote:

        Good morning Darby and thanks for writing us.

        With regard to your request on implementing a custom callback triggered on certain events, I invite you to implement a MessageData plugin and implement a CoreMessage method in order to catch the event of your interest.
        I also invite you to give a look at the Core Message Manual which can provide some further explanation about the mechanism behind the message dispatching and handling in Cinema 4D.

        Best, Riccardo

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

          On 16/04/2018 at 23:50, xxxxxxxx wrote:

          Thank you Riccardo for writing back.

          I've looked into writing a MessageData plugin but I'm running into some issues.

          I think I'm able to detect when an attribute is modified, but it seems a bit off as I can't find the right c4d.EVMSG or c4d.MSG constant to use.  Instead I found that the message id 1026901 is sent when most attributes are modified.

          As far as I can tell the base container that comes along with the message may contain up to two additional parameters (c4d.BFM_CORE_PAR1 and c4d.BFM_CORE_PAR2) but these are PyCObjects and I don't know how to use them.

          I can't think of any way to find out which attribute on which material is sending me these messages. Any additional help would be much appreciated!

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

            On 17/04/2018 at 05:24, xxxxxxxx wrote:

            Hi darby, thanks for following up.

            Actually after you catch a value change event it's pretty straightforward to see if linear workflow or color space has changed with something like

              
            class SDKSupport_14183(plugins.MessageData) :
              
            last_cp = 0
            last_lw = 1
            mat_last_cp = 0
              
            def CoreMessage(self, id, bc) :
            # attempt to retrieve the active document
            doc = c4d.documents.GetActiveDocument()
            if doc is None:
            return True
              
            mat = doc.GetActiveMaterial()
            if mat is None:
            return True
              
            if id == c4d.EVMSG_CHANGE:
            matBC = mat.GetDataInstance()
            matTxt = matBC[c4d.MATERIAL_COLOR_SHADER]
            if matTxt.GetType() == c4d.Xbitmap:
            matTxtBC = matTxt.GetDataInstance()
            mat_cp = matTxtBC[c4d.BITMAPSHADER_COLORPROFILE]
            if mat_cp != self.mat_last_cp:
            print "Color profile setting changed [",mat_cp, "] in ", mat.GetName()
            #update the stored value
            self.mat_last_cp = mat_cp
              
            # attempt to retrieve doc settings instance
            docSettings = doc.GetSettingsInstance(c4d.DOCUMENTSETTINGS_DOCUMENT)
            if docSettings is None:
            return True
            # retrieve the color profile and linear workflow values
            cp = docSettings[c4d.DOCUMENT_COLORPROFILE]
            lw = docSettings[c4d.DOCUMENT_LINEARWORKFLOW]
            # check against the last stored value
            if cp != self.last_cp:
            print "Color profile setting changed [", cp, "]"
            #update the stored value
            self.last_cp = cp
              
            # check against the last stored value
            if lw != self.last_lw:
            print "Linear workflow setting changed [", lw, "]"
            #update the stored value
            self.last_lw = lw 
            return True
            

            Hope it helps.
            Riccardo

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

              On 18/04/2018 at 22:06, xxxxxxxx wrote:

              Thanks again Riccardo!

              This has helped me quite a bit but I'm still running into some issues.

              I have a MessageData plugin responding to EVMSG_CHANGE, and I've used the script editor to prototype the action I need to occur on the Redshift material:

              import c4d
              from c4d import documents, utils
                
              def main() :
                  doc = documents.GetActiveDocument() 
                  mat = doc.GetActiveMaterial()
                  
                  if mat:
                      node = mat[c4d.REDSHIFT_GRAPH_NODES]
                      while node:
                          if node[c4d.GV_REDSHIFT_SHADER_META_CLASSNAME] == 'Material':
                              mat_bc = node.GetOperatorContainer()
                              desc = node.GetDescription(c4d.DESCFLAGS_DESC_0)
                              for bc, paramid, groupid in desc:
                                  if paramid[0].dtype == c4d.DTYPE_COLOR and paramid[0].creator == 0:
                                      color = mat_bc[paramid[0].id]
                                      mat_bc[paramid[0].id] = utils.TransformColor(color, c4d.COLORSPACETRANSFORMATION_LINEAR_TO_SRGB)
                                      node.SetOperatorContainer(mat_bc)
                              c4d.EventAdd()
                          node = node.GetNext()
                
              if __name__=='__main__':
                  main()
              

              However, I can't figure out an elegant way to make sure that I only perform the above action to the proper Redshift material graph when a new material preset is selected for that material. Initially the problem was that whenever the EVMSG_CHANGE message was being received it would update the colors on the active material, which obviously happens way too frequently. I changed my MessageData plugin to keep track of the previous material preset but that goes out of sync if you switch from material to material.

              It seems that I need a way to determine whether the EVMSG_CHANGE was triggered by a specific attribute being modified.  Is that possible?  I have to admit that I'm still struggling to understand the details of Descriptions, DescIDs and DescLevels but I'm glad to finally be tackling this stuff 🙂

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

                On 19/04/2018 at 03:00, xxxxxxxx wrote:

                Hello,

                just to drop a short note: you find information on many topics in the C++ SDK documentation. For example:

                • Description Manual
                • DescID Manual

                best wishes,
                Sebastian

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

                  On 28/04/2018 at 16:05, xxxxxxxx wrote:

                  Thanks for the help.

                  I can't find a way around this one.

                  Unless it's possible to find out what sort of message is being sent by the Redshift plugin's Material Preset dropdown menu so that I can act on it as well I think I'm out of luck.  Oh well, on to the next one.

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

                    On 02/05/2018 at 02:44, xxxxxxxx wrote:

                    Good morning, thanks for following up.

                    With regard to your last point, being something out of our purview, I suggest to get in touch with Redshift development and ask them to implement something useful to your purposes.

                    Best, Riccardo

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