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

    Object Plugin : Sweep with 2 Splines - After MakeEditable just 1 spline

    Cinema 4D SDK
    2023 windows python r23
    2
    4
    873
    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.
    • ThomasBT
      ThomasB
      last edited by ThomasB

      Hi have a simple Object-Plugin:

      • It creates first a Sweep Nurb

      • then it creates the path spline related to the description parameters

      • it puts this spline under the sweep

      • then it loads a profile spline from an Hyperfile / printing works profile is loaded

      • then it puts this profile under the sweep

      • then the sweep is returned in the GVO

      • everthing is happening in the GVO

      Returning in the GVO works, everthing is visible.
      When I press MakeEditable in the active document of the node, just the sweep and the path-spline are present but not the profile

      It also doesent work when I create a virtual document with the spline-profile and extract it from there

      But when I press a button then I can add it to the active document....
      I do not understand, because the path spline works , maybe since it is mathmetically created?
      If I use just a Osplinerectangel as profile then it works

          def GetVirtualObjects(self, op, hh):       
              dirty = op.CheckCache(hh) or op.IsDirty(c4d.DIRTYFLAGS_DESCRIPTION)
              if not dirty:
                  return op.GetCache(hh)       
      
      
              self.spline = BowSpline(op[c4d.PY_WINDOW_WIDTH], op[c4d.PY_WINDOW_HEIGHT], op[c4d.PY_ARCH_HEIGHT], op[c4d.PY_ARCH_SUBD]).spline.GetClone()
              self.frame = c4d.BaseObject(c4d.Osweep)
              self.spline.InsertUnder(self.frame)
              profile = self.load_profile().GetClone()
              profile.InsertUnder(self.frame)      
      
      
              if op[10105]:
                  self.frame.SetRelPos(c4d.Vector(0, 0,  op[10105]))
      
              return self.frame
          
      
          def load_profile(self):
              #c4d.documents.MergeDocument(self.new_doc, f"{path}/res/profile.c4d", c4d.SCENEFILTER_OBJECTS)
              patho = os.path.join(path, "res", "profile")
              profile = c4d.BaseObject(c4d.Ospline)
              c4d.storage.ReadHyperFile(None, profile, patho, 100)
              return profile
      

      What I am also not understanding is, when I change the description parameter while dragging it, the sweep gets invisible and just the spline is shown which is changing
      For this realtime refresh I just catched the global MSG_DESCRIPTION_POSTSETPARAMETER.
      is there another way to refesh it instead of callcommand and the id for redraw, maybe DrawViews()?

      def Message(self, node, type, data):     
              
              
                      if type == c4d.MSG_DESCRIPTION_POSTSETPARAMETER:
              
                          #if data['descid'][0].id == c4d.PY_WINDOW_WIDTH:   
              
                          c4d.CallCommand(12147)
      

      Thanks,
      T.S.B

      1 Reply Last reply Reply Quote 0
      • ThomasBT
        ThomasB
        last edited by

        My solution so far is to create a virtual document insert the object from the GVO and call ModelingCommand CURRENTSTATETOOBEJCT and return this object now it works. I got the finished object. But anyways I ask myself why it not works in the other way

        Thanks,
        T.S.B

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

          Hello @thomasb,

          Thank you for reaching out to us. Just as in your other thread, it is probably best to share the plugin with us, as I otherwise will be mostly guessing here too. Again, here are some things which stand out to me.

          • Doing things like self.frame and self.spline, i.e., binding a reference of the cache of the object instance op to the instance of the hook is at least very odd. What you return in GVO IS the cache of the node. By also tying the reference to the plugin hook instance, you might throw a wrench into the memory management of the C++ layer (Cinema 'owns', i.e., manages the lifetime of, the object returned by GVO). It also implies that you later want to access or even modify the cache with these plugin hook instance attributes. Accessing is technically fine, but the references might be dead by then, and modifying the caches is off limits.
          • def load_profile
            1. Using c4d.storage.ReadHyperFile in this manner seems dangerous since you clone the exact same node over and over. It might work in this context, I did not try. I would be a bit more defensive and only save the data I need. You could for example clone the data container of the node and just read/write that using c4d.storage.HyperFile. You could of course also be even more conservative and just read/write the parameters of the profile you really want to copy.
            2. load_profile is executed asynchronously because GVO is. File IO is a dangerous thing to do here, even for read operations. You should defer reading to the (non-drawing) main thread. Theoretically, the Asset API would be an alternative and you could use AssetCreationInterface.SaveDefaultPresetFromObject to create an object preset asset. But this will always invoke the object preset GUI dialog and gives you no control over the asset ID. You could wiggle yourself around this but nothing will be really won in the end [1].

          Cheers,
          Ferdinand

          [1] SaveDefaultPresetFromObject only thinly wraps AssetCreationInterface.SaveBrowserPreset and most of it can be emulated, but two crucial bits - a message for filtering/gathering the parameters to store and the special preset types handling this form of presets - are not public, even in C++. As a way out, you could either implement your own preset type (only possible in C++) or simply use something like AssetCreationInterface.CreateObjectAsset to save the whole object as an asset. The idea is then to load that asset and simply copy its data container to get the preset you are after. You would have to manually load the asset back, as shown in the C++ docs, because maxon.AssetManagerInterface.LoadAssets will load into the active document which is not what you want. Since this will effectively cause you to use c4d.documents.LoadFile to load the raw asset file, you are then again subject to the same threading restrictions as before and would have to preload your data.

          MAXON SDK Specialist
          developers.maxon.net

          ThomasBT 1 Reply Last reply Reply Quote 0
          • ThomasBT
            ThomasB @ferdinand
            last edited by

            @ferdinand
            Yes you are right, in relation to this the self.spline etc is unnecessary that could also be a normal local variable. Is correct.
            But basically if I load a profile spline in my init method, for example, I can already save it in such a variable. I need to be able to access it from anywhere in the class.
            But here it is totally superfluous....sorry

            Thanks,
            T.S.B

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