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

    Unusual "NoneType" Error for GetDeformCache()

    Cinema 4D SDK
    r21 python
    3
    12
    1.8k
    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.
    • B
      bentraje
      last edited by

      Hi,

      I'm having an unusual "NoneType" Error for GetDeformCache().
      For the most part, it works. But there are times where it throws an error.
      I can't replicate the other methods but it always happens when I hit undo.

      You can see the problem here:
      https://www.dropbox.com/s/ybwoy0p403qxprr/c4d306_python_getdeformcache_nonetype_error.mp4?dl=0

      You can check the file here:
      https://www.dropbox.com/s/obngch2rx6dseqn/c4d306_python_getdeformcache_nonetype_error.c4d?dl=0

      Regards,
      Ben

      1 Reply Last reply Reply Quote 0
      • ManuelM
        Manuel
        last edited by

        hi,

        sounds pretty logical to me.
        Your deformer is below the object where your tag is. Your tag is at priority expression +0. So it is executed before the deformer.
        If you retrieve the cache you should retrieve the cache build on the previous execute pass.

        That's why you got the message when you load the document and when you press the a key to force the recalculation of the scene.
        If you set the tag's priority to generator +1 you will not have the message anymore.

        the a key is your best friend when you want to deal with priorities.

        Cheers,
        Manuel

        MAXON SDK Specialist

        MAXON Registered Developer

        1 Reply Last reply Reply Quote 1
        • ferdinandF
          ferdinand
          last edited by ferdinand

          Hi,

          I do not want to be rude, but please put up your code next time and a console dump. You always making these little videos is very nice of you and helps, but cannot replace the mentioned. In this case I could take a glimpse at the code in the video.

          To your problem is is actually not GetDeformCache which is None, but the module attribute op. Invoking an undo seems to clear the selection as you can see in your video. Which in turn means that op, the current primary object selection, is going to be None.

          However, GetDeformCache can be None, as there is no guarantee that the deformation cache is populated at any time (assuming there is some kind of deformer). Invoking undo might produce such scenario (haven't tested it, I am on my iPad). When retrieving caches, it is good practice to so something like this.

          cache = node.GetDeformCache() or node.GetCache()
          node = cache or node
          

          This will replace the reference of the symbol node with the a reference to the deformed cache, the cache or the node itself in decreasing order. After that you can evaluate the type of node to determine how to proceed.

          if not isinstance(node, c4d.PointObject):
              msg = "Could not access point data in {}."
              raise TypeError(msg.format(node))
          

          Edit: It is also worth mentioning that caches can contain caches. So you are not guaranteed to have directly some point data at the top level of the cache. My mentioned snippet therefore only "works" in cases of such "flat" caches.

          Cheers,
          zipit

          MAXON SDK Specialist
          developers.maxon.net

          1 Reply Last reply Reply Quote 1
          • B
            bentraje
            last edited by

            Thanks for the response:

            @m_magalhaes

            RE: Your tag is at priority expression +0. So it is executed before the deformer.
            It seems like you're talking as if the Shrink Wrap Deformer has a "priority", but its basic tab doesn't show anything.
            Interestingly, when I set the tag to generator +1 as suggested, it seems to fix the problem.

            So, indeed, there is an inherent priority for the deformers.
            How do I change them?

            I tried the following deformer[c4d.EXPRESSION_PRIORITY] or even the deformer[c4d.ID_CA_SKIN_OBJECT_PRIORITY] but it gives me None type.

            @zipit

            RE: but please put up your code next time and a console dump
            Gotcha. Noted.

            RE: Code
            The code works as expected.

            RE: caches can contain caches.
            Just want to clarify.
            Cache (GetCache()) can contain Caches and Deform Caches (GetDeformCache)
            But Deform Cache can't contain Caches or othe Deform Caches.

            Is this assessment correct? I'm basing this on a sample image in this documentation.

            RE: "flat" caches.
            Just to clarify, by flat caches, I guess you meant objects with no stacking parent/child hierarchies?

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

              @bentraje said in [Unusual "NoneType" Error for GetDeformCache()]

              RE: caches can contain caches.
              Just want to clarify.
              Cache (GetCache()) can contain Caches and Deform Caches (GetDeformCache)
              But Deform Cache can't contain Caches or othe Deform Caches.

              Is this assessment correct? I'm basing this on a sample image in this documentation.

              Yeah, deform caches are sort of flat. But they are often (when the deformer does not directly act on a PointObject) imbedded within a cache. It will look something like the tree below which represents the example of the docs, but with only one cloned cube. The problem is that this is not a monohierarchical structure which cannot be described very well with a (monohierarchical) taxonomy (i.e. the image in the docs or what I have done below). You can test this yourself with [1].

              # The actual array node.
              Array/Array
                  Array/Array returns for GetCache:
                      # The null object holding all parametric cubes in the cache
                      Null/Array
                          # A null object has no cache
                          Null/Array returns 'None' for GetCache.
                          # And also no deform cache
                          Null/Array returns 'None' for GetDeformCache.
                          # But some children
                          children of Null/Array:
                              # A parametric cube as child of the cache.
                              Cube/Cube.1
                                  # The cache of that part of the cache of the node :o
                                  Cube/Cube.1 returns for GetCache:
                                      # The actual polygonal data created by the GVO of the
                                      # parametric cube object.
                                      Polygon/Cube.1
                                          Polygon/Cube.1 returns 'None' for GetCache.
                                          Polygon/Cube.1 returns for GetDeformCache:
                                              # The deformed polygonal data generated by
                                              # the deformer reaching deep into the cache
                                              # of the array object.
                                              Polygon/Cube.1
                                                  Polygon/Cube.1 returns 'None' for GetCache.
                                                  Polygon/Cube.1 returns 'None' for GetDeformCache.
                                                  Polygon/Cube.1 has no children.
                                          Polygon/Cube.1 has no children.
                                  # No deform cache here, since this is the paramteric cube
                                  # not its polygonal cache.
                                  Cube/Cube.1 returns 'None' for GetDeformCache.
                                  Cube/Cube.1 has no children.
                  # Has no deformed cache since its cache is a null object (which has
                  # stuff attached to it.)
                  Array/Array returns 'None' for GetDeformCache.
              
                  # The actual children of the actual array object.
                  children of Array/Array:
                      Cube/Cube
                          # This one is quite surprising I didn't know either, it seems
                          # like that at least the array object *mutes* its input objects
                          # to avoid overhead. 
                          Cube/Cube returns 'None' for GetCache.
                          Cube/Cube returns 'None' for GetDeformCache.
                          Cube/Cube has no children.
                      Bend/Bend
                          Bend/Bend returns 'None' for GetCache.
                          Bend/Bend returns 'None' for GetDeformCache.
                          Bend/Bend has no children.
              

              RE: "flat" caches.
              Just to clarify, by flat caches, I guess you meant objects with no stacking parent/child hierarchies?

              I meant caches that do not contain caches. A cache that is a null to which multiple other nulls are parented would be flat in this sense, as the nulls will have no further caches. If it were parametric cubes parented instead, it would not be no longer flat, since each cube had its own cache.

              Cheers,
              zipit

              [1]

              """Prints the cache hierarchy of a selected object.
              """
              import c4d
              
              
              def walk_cache(node, indent=0):
                  """
                  """
                  if node is None:
                      return
              
                  node_name = node.GetTypeName() + "/" + node.GetName()
                  is_controlobject = node.GetBit(c4d.BIT_CONTROLOBJECT)
                  print("{}{} (BIT_CONTROLOBJECT: {})".format("\t" * indent,
                                                              node_name,
                                                              is_controlobject))
                  for f in [node.GetCache, node.GetDeformCache]:
                      cache = f()
                      msg = ("{}{} returns for {}:" if cache else
                             "{}{} returns 'None' for {}.")
                      print(msg.format("\t" * (indent + 1), node_name, f.__name__))
                      if cache:
                          walk_cache(cache, indent + 2)
              
                  children = node.GetChildren()
                  no_children = len(children) == 0
                  msg = "{}{} has no children." if no_children else "{}children of {}:"
                  print(msg.format("\t" * (indent + 1), node_name))
                  for child in children:
                      walk_cache(child, indent + 2)
              
              
              def main():
                  """
                  """
                  if op is None:
                      raise ValueError("Please select an object.")
                  walk_cache(op)
              
              
              if __name__ == "__main__":
                  main()
              
              

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 2
              • B
                bentraje
                last edited by

                @zipit

                Thanks for the detailed answer! The walk_cache code really clarifies a lot of what I've been having trouble understanding. Although, I still have to remain the thread open as I'm waiting for @m_magalhaes on my priorities on deformers.

                Thanks again! Have a great day ahead! 🙂

                1 Reply Last reply Reply Quote 0
                • ManuelM
                  Manuel
                  last edited by

                  hi,

                  A deformer is a generator. So it's priority is Generator.

                  You can see in our documentation the sequence of calculation
                  Of course there are some exceptions
                  alt text

                  Cheers,
                  Manuel

                  MAXON SDK Specialist

                  MAXON Registered Developer

                  1 Reply Last reply Reply Quote 0
                  • B
                    bentraje
                    last edited by

                    @m_magalhaes

                    Ah gotcha. I totally missed this one out:
                    A deformer is a generator. So it's priority is Generator.

                    That said, since it has a priority, can I change it's order. I believe its in Generator -1.
                    I want to change it say to Generator -100 or Generator +100
                    This is so I can stack them properly.

                    As mentioned, I tried the following deformer[c4d.EXPRESSION_PRIORITY] or even the deformer[c4d.ID_CA_SKIN_OBJECT_PRIORITY] but it gives me None type.

                    1 Reply Last reply Reply Quote 0
                    • ManuelM
                      Manuel
                      last edited by

                      hi,

                      the skin deformer is a really particular case. The priority only change the moment where Execute will be called. (like any other Generator where you can use AddToExecution and Execute).
                      But in all case it will still use ModifyObject (the GVO for deformer). The priority of this call can't be changed.

                      Cheers,
                      Manuel

                      MAXON SDK Specialist

                      MAXON Registered Developer

                      1 Reply Last reply Reply Quote 0
                      • B
                        bentraje
                        last edited by

                        @m_magalhaes
                        Ah gotcha. Thanks for the clarification.
                        But I'm asking for "Deformer" in general in changing their priority since it's not available in the interface.

                        1 Reply Last reply Reply Quote 0
                        • ManuelM
                          Manuel
                          last edited by

                          Not all modifier use the Execution function.
                          Even on those that use it, not all allow to change the priority.

                          Cheers,
                          Manuel

                          MAXON SDK Specialist

                          MAXON Registered Developer

                          1 Reply Last reply Reply Quote 1
                          • B
                            bentraje
                            last edited by

                            Hi @m_magalhaes

                            Ah gotcha. I guess I can't change the deformer's priority.
                            Anyhow. Thanks for the confirmation.

                            1 Reply Last reply Reply Quote 0
                            • ferdinandF ferdinand referenced this topic on
                            • ferdinandF ferdinand referenced this topic on
                            • First post
                              Last post