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

    Generator plugin and loading preset objects from file (cache issue?)

    Cinema 4D SDK
    python
    3
    11
    1.3k
    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.
    • fuchsundvogelF
      fuchsundvogel
      last edited by

      Hello everyone,

      I'm writing a python generator plugin that should load an preset object from a file and return a modified version of that in GetVirtualObjects().
      Right now the preset scene is just a simple cube without anything else.

      The code I'm using:

      def __init__(self):
      	self.loadedObject = None
      	self.SetOptimizeCache(True)
      
      def Init(self, op):
      	#loading preset file and save first object internally
      	if not self.loadedObject:
      		dir, file = os.path.split(__file__)
      		path = os.path.join(dir, "presets", "test.c4d")
      
      		presetDoc = c4d.documents.LoadDocument(path, c4d.SCENEFILTER_OBJECTS, None)
      		self.loadedObject = presetDoc.GetFirstObject()
      
      	return True
      
      def GetVirtualObjects(self, op, hh):
      	#return clone of loaded object
      	return self.loadedObject.GetClone()
      

      Basically loading and extracting the object from the file is fine. The problem is that the object is not loaded/executed before it is added to the current doc and a refresh was forced.
      When I add or reload the generator the object looks like this until i move the mouse and trigger a refresh:

      Anmerkung 2020-08-10 150850_02.png

      I can of course force a refresh via code, but I still can't convert the generator with "Make editable" or "Current State to object". Then only an empty object is returned.
      It looks like the conversion uses the state before the refresh and returns nothing.

      I tried a lot of things like ExecutePasses() on the loaded document or setting the cube to dirty and sending update messages but nothing helped so far.
      Adding the cube into the current document under the generator and hiding it is some kind of workaround but that leads to other problems - like being added multiple times because op.GetDown() not always returns the child on undo or scene changes or not being able to use "Make editable" and stuff like that.

      Maybe there is something I missed?

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

        Hi,

        as I have ran into funky call orderingd in ObjectData myself, my suspicion would be that you get an error something like this when you add your generator: AttributeError: <some object handle> has no attribute 'loadedObject'. The reason being the execution order and as a result your GVO will have terminated irregularly.

        You could simply determine inside your GVO if your generator has to be initialised to circumvent these problems.

        Cheers,
        zipit

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • fuchsundvogelF
          fuchsundvogel
          last edited by

          Hey zipit,

          thank you very much for your answer!

          No errors in the console at all (unfortunately? 😁). Also no change if i add a check for self.loadedObject. Or even load the object in the GVO itself. So it looks like the order is not the problem here. The loaded object seems to be present.

          Jens

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

            hi,

            you probably have some generator (hypernurbs, SweepNurbs ?

            Cheers,
            Manuel

            MAXON SDK Specialist

            MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • fuchsundvogelF
              fuchsundvogel
              last edited by fuchsundvogel

              Hey Manuel,

              no, the scene I load is just a simple cube object.
              Initially I started with SweepNurbs and also suspected them to be the problem but then noticed it already happens with simple objects.

              This old post I found seems to be a similar problem or even the same.
              https://developers.maxon.net/forum/topic/11787/make-editable-an-object-generated-by-getvirtualobjects
              Unfortunately the issue was not solved. The original poster gave up on loading presets and created them in code which is not sensible for me because the presets will be quite complex.

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

                Hi,

                total shot in the dark, but have you tried building the caches on the document you retrieve the object from? Technically Cinema should build caches recursively, but maybe there is something going wrong with the dirty state of the loaded object, which prevents Cinema to properly evaluate its cache the first time GVO is being invoked? Alternatively you could probably also increment the cache dirty counter of that object (via BaseObject.SetDirty).

                Cheers,
                zipit

                MAXON SDK Specialist
                developers.maxon.net

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

                  hi,

                  This is working. But the cache of the generators will not be cloned. It's working with simple object.
                  Also, if you want to import Material or change the scene in any way, you can't do it in GVO (as said in the other thread)

                  I'm still looking to find a solution.

                     def Init(self, op):
                          self.InitAttr(op, float, [c4d.ONEFLOAT])
                  
                          op[c4d.ONEFLOAT] = 10.0
                          #loading preset file and save first object internally
                          if self.loadedObject is None:
                              location = "C:\\Users\\Manuel Magalhaes\\Desktop\\temp\\sweep.c4d"
                              presetDoc = c4d.documents.LoadDocument(location, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_SAVECACHES | c4d.SCENEFILTER_MATERIALS, None)
                              if presetDoc is None:
                                  print ("can't load the file")
                                  return False
                              firstObject = presetDoc.GetFirstObject()
                              
                              presetDoc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_NONE)
                              presetDoc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_NONE)
                              
                  
                              self.loadedObject = firstObject.GetClone()
                              if self.loadedObject is None:
                                  return False
                  
                          return True
                      
                      def GetVirtualObjects(self, op, hierarchyhelp):
                          
                         
                  
                  
                          if self.loadedObject is None:
                              return c4d.BaseObject(c4d.Onull)
                        
                          return self.loadedObject.GetClone()
                  
                  

                  Cheers,
                  Manuel

                  MAXON SDK Specialist

                  MAXON Registered Developer

                  1 Reply Last reply Reply Quote 0
                  • fuchsundvogelF
                    fuchsundvogel
                    last edited by fuchsundvogel

                    Hey Manuel,

                    thanks for your code and for investing time into that!

                    I tried it and found some problems:

                    • Probably what you meant by 'cache will not be cloned': object is still invisible in the beginning until you refresh. But converting the generator works fine (that is because you omitted the .GetClone() in GVO I think).
                    • Because you don't return a clone in GVO you get ReferenceError: the object 'c4d.BaseObject' is not alive when switching documents. But if you do so you can't use 'Make editable'.

                    I think your code behaves the same as mine from the first post if you omit the .GetClone() in GVO there. I am not sure if the c4d.SCENEFILTER_SAVECACHES loading flag and ExecutePasses change anything. I have to add I only tested with a cube as preset. I could be the case that some of that is needed for Sweeps or the like.

                    Jens

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

                      @fuchsundvogel said in Generator plugin and loading preset objects from file (cache issue?):

                      Because you don't return a clone in GVO you get ReferenceError: the object 'c4d.BaseObject' is not alive when switching documents. But if you do so you can't use 'Make editable'.

                      good point on that one.

                      A simple cube is a generator. That's what the GVO is doing, create that geometry and create the cache.
                      In our case, if you clone the generator, the cache will not be cloned. That's the problem here.
                      None of the generator will be displayed because their cache isn't created.

                      If you are using edited geometry it's working pretty fine.

                      I need to search a bit more if it's even possible to do it. (we are not in a real ordinary case)

                      Cheers,
                      Manuel

                      MAXON SDK Specialist

                      MAXON Registered Developer

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

                        hi,

                        pretty interesting that if you add your object inside a null, it kind of work but if you edit the object, the content will be edited as well.
                        But that may be enough for your need

                           def GetVirtualObjects(self, op, hierarchyhelp):
                        
                                location = "C:\\Users\\Manuel Magalhaes\\Desktop\\temp\\blender.c4d"
                                presetDoc = c4d.documents.LoadDocument(location, c4d.SCENEFILTER_OBJECTS | c4d.SCENEFILTER_SAVECACHES | c4d.SCENEFILTER_MATERIALS, None)
                                if presetDoc is None:
                                    print ("can't load the file")
                                    return None
                                
                                presetDoc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_NONE)
                                presetDoc.ExecutePasses(None, True, True, True, c4d.BUILDFLAGS_NONE)
                                
                                firstObject = presetDoc.GetFirstObject()
                                parent = c4d.BaseObject(c4d.Onull)
                                firstObject.InsertUnder(parent)
                        
                                return parent
                        
                        

                        Of course, GVO isn't the right place to load files. But if you do it in the Init function, it will not work.

                        Cheers,
                        Manuel

                        MAXON SDK Specialist

                        MAXON Registered Developer

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

                          hi

                          can we considered this thread as solved ? (even if there's no real right answer)

                          Cheers,
                          Manuel

                          MAXON SDK Specialist

                          MAXON Registered Developer

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