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

    Editable Object Plugin returns Null after scaling

    Cinema 4D SDK
    python
    2
    2
    14
    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

      I'm creating a basic ObjectData plugin that returns a cube with a modified scale. However, when making the object editable (C key), sometimes the result becomes a Null object with the cube inside, especially after changing the scale.

      import c4d
      from c4d import plugins, utils
      
      class MyObjectPlugin(plugins.ObjectData):
      
          def Init(self, op):
              return True
      
          def GetVirtualObjects(self, op, hierarchyhelp):
              dirty = op.CheckCache(hierarchyhelp) or op.IsDirty(c4d.DIRTY_DATA)
              if not dirty:
                  return op.GetCache(hierarchyhelp)
      
              cube = c4d.BaseObject(c4d.Ocube)
              if cube is None:
                  return None
      
              cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_X] = 2.0
              cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_Y] = 1.0
              cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_Z] = 0.5
      
              return cube
      
      

      Am I doing something wrong? My intention is specifically that when making the generator editable, the result is the scaled object, but without the null object that is generated when modifying it, and without modifying the generator scale.

      Thanks in advance for any help!

      PS: I would also like to know if there is a specific way to return several objects or a specific one when making the generator editable, making it more customizable.

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

        Hello @JH23,

        Thank you for reaching out to us. Your code is looks correct, but you should not return None on a critical error (e.g., when you run out of memory to allocate things), but return c4d.BaseObject(c4d.Onull) instead, that is also what Cinema 4D will do, when it cannot make sense out of your method. E.g. it should be:

        if not(cube := c4d.BaseObject(c4d.Ocube)):
            return c4d.BaseObject(c4d.Onull)
        
        cube[c4d.ID_BASEOBJECT_REL_SCALE, c4d.VECTOR_X] = 2.0
        ...
        

        Also, does your object have child inputs it depends on? E.g., like an Extrude object which depends on a child spline? I assume it does not, right? You should then change your manual dirty check to this, because your code also tries to build the children of this node which could lead to issues.

        # Only build the cache of the object when one of its parameters has changed or when there is no cache.
        if not op.IsDirty(c4d.DIRTY_DATA) and op.GetCache():
            return op.GetCache() # you could also pass the hh here, but that is not necessary in this case
        

        Do you see any errors in the console when this happens? Cinema 4D returning a null object for a cache means that building the cache failed. There must be somewhere a bug in your code, I am not sure though that my suggestions will fix it.

        I would also like to know if there is a specific way to return several objects or a specific one when making the generator editable, making it more customizable.

        A cache must always terminate into a singular object because it is just part of an object hierarchy. When you want your cache to contain multiple things, you must parent them to a null and return that null as your cache.

        As to reacting to CTSO, yes that is possible, but not in Python. When an object is being built for CSTO, its HierachyHelp->GetFlags() will be BUILDFLAGS::EXTERNALRENDERER | BUILDFLAGS::ISOPARM but HierachyHelp has not been wrapped for Python. There is MSG_CURRENTSTATE_END emitted, and you can capture this in Python too via NodeData::Message, but that is only the signal that CSTO has finished (and that you might want to revert to a non-CSTO specialized cache).

        But in general, we advise against such trickery where objects switch out their cache in certain contexts. It is valid to do this, but often requires intimate knowledge of the API to be done sucessfully.

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

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