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

    Spline User Data Presets

    Cinema 4D SDK
    python r20
    3
    11
    1.7k
    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.
    • G
      gsmetzer
      last edited by Manuel

      Hello forum,

      In my User Data, I have a customized shape as my Spline DataType. I want to keep this custom shape and be able to rebuild as a preset in my plugin. It would function like the 'Save Preset...' and 'Load Preset...' buttons.

      There must be a way to save all the points and tangents in the spline DataType to rebuild the it with python? How would I do this?

      Thank You for any thoughts.

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

        Hi,

        I have recently shown here how to react to user data button clicks in a scripting tag. You could (de-)serialize your c4d.SplineData with the buildin Python module json (link). Also the c4d.SplineData type already does 50% of the work for you as GetKnots() returns a dictionary which you could serialize directly via json.dumps().

        Cheers
        zipit

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • G
          gsmetzer
          last edited by

          Ah, GetKnots() has the data that I need. Thank you for that.
          I also see I SetKnot() is read only. The only way to get around that is sending the GetKey data to json then back again?
          There must be a simpler way of using GetKnots() data and pasting on to a new Spline DataType.

          1 Reply Last reply Reply Quote 0
          • G
            gsmetzer
            last edited by

            or can I place the GetKnots() data into my .res file? That would work for my plugin too.

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

              Hi,

              I am sorry, I did overlook that you were writing a plugin, because I answered a few scripting questions before and you were talking about user data.

              A few assumptions:

              1. I assume you are writing as description resource based plugin data type like or ObjectData or TagData and not a dialog resource based type like CommandData or Tooldata.
              2. I am still not quite clear on what you want to do, but i assume you want to be able to store N amount of spline presets for your plugin, right?

              A few answers:

              1. If you only want to store exactly one preset and do use a description resource, you could actually just let the user use the build in feature "save as default" of the attribute manger.
              2. No, you can not define any storage logic in a res file. They are purely meant to define the interface layer of your plugin. Anything data/logic layer related goes into your code.
              3. You could either store your plugin settings globally in the WorldContainer. Check outc4d.SetWorldContainer() and c4d.GetWorldContainer() for that.
              4. Or you could store the settings locally (per document) via BaseDocument.GetDocumentData() and BaseDocument.SetDocumentData().
              5. In both cases (3. and 4.) you need to register a plugin ID under which you can store your settings.
              6. Serializing the data yourself could still be advantageous depending on what you are trying to do.

              Cheers
              zipit

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • G
                gsmetzer
                last edited by

                Thank You for the thorough reply.

                Yes, I am writing a python tag and running it through Prototype Converter. The goal is to create a plugin tag that adds custom animation curves to the transforms of objects such as cubes and circles etc.
                I haven't looked into it yet but WorldContainer looks like its getting me there. I am assuming there is an easy way to save all of the carefully preset UserData (GUISplines) that I have created and keep it in the plugin for a new animator to use out of the box.

                (Sorry, I'm learning a lot all at once here coming from C# in Unity3D. )

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

                  Hello,
                  thanks again for @zipit and the answer.

                  I would like to add a couple of words.

                  The best way should be to store them in the Content Browser, but it's not available in Python, only C++

                  So that depend if you want your setting to be available only for the document (use Document BaseContainer). For setting that are available independently from the document, you can use the WorldContainer (even if it's to store "preferences" and not librairies)

                  you can also retrieves each knots (SplineData.GetKnots()) and save them to an Hyperfile (@zipit talked about json but hyperfile are also a good way)

                  Of course, If you want just one default "starting" state you can do that in your Init() function

                  Don't forget that with cinema4D, users can also use "Set to default" or save Tags presets. And as you said, they can also use the regular load preset and save preset

                  And you can also share content librairies.

                  also about how to use the forum :

                  For your next threads, please help us keeping things organised and clean. I know it's not your priority but it really simplify our work here.

                  • Q&A New Functionality.
                  • How to Post Questions especially the tagging part.

                  I've added the tags and marked this thread as a question so when you considered it as solved, please change the state :

                  Cheers,
                  Manuel

                  MAXON SDK Specialist

                  MAXON Registered Developer

                  1 Reply Last reply Reply Quote 0
                  • G
                    gsmetzer
                    last edited by

                    Thank You @zipit and @m_magalhaes,

                    You have given me some great leads to solve my problem. It's pretty clear I am in over my head. More code samples in the API would really help a beginner like me. I have done a lot of searching around Hyperfiles and BaseContainers but not finding a solution, mostly due to my lack of familiarity of the sdk.

                    This is the last problem I need to solve in order to use my Tag Plugin.

                    Here is another take:Screen Shot 2019-08-26 at 9.52.55 PM.png
                    I can easily save the splinedata to a file and load it into a blank splineGui like a charm. Can I somehow keep that file in my plugin directory and load it onto the specific user data on initialization of the plugin?

                    Thanks again.

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

                      Hello,
                      About the examples, with the release of R21 there will be a bit more examples. You can still have a look at the c++ examples, you will have some class name and function that can be translate to python.

                      you can't because there's a dialogbox opened by this command. You can't avoid it.

                      About the hyperfile you have an example on the hyperfile documentation page

                      I did write an quick example with splinedata, you can simply use ReadData/WriteData
                      I didn't add comment, you just pick the data and write it. (of course you don't need the LoadDialog)

                      def Read():
                          path = st.LoadDialog(type=c4d.FILESELECTTYPE_ANYTHING, title="Please Select the file")  
                          hf = st.HyperFile()
                          #spdata = op[c4d.ID_USERDATA,1]
                          spdata = None
                          if hf.Open(ident=0, filename=path, mode=c4d.FILEOPEN_READ, error_dialog=c4d.FILEDIALOG_NONE):
                              spdata = hf.ReadData()
                          else:
                              raise ValueError("can't open file")
                          op[c4d.ID_USERDATA,1] = spdata
                          c4d.EventAdd()
                          
                              
                      def Write():
                          path = st.SaveDialog(type=c4d.FILESELECTTYPE_ANYTHING, title="Please Select the file")  
                          hf = st.HyperFile()
                          spdata = op[c4d.ID_USERDATA,1]
                          if hf.Open(ident=0, filename=path, mode=c4d.FILEOPEN_WRITE, error_dialog=c4d.FILEDIALOG_NONE):
                              writeDone = hf.WriteData(spdata)
                          else:
                              raise ValueError("error loading the file")
                      

                      I did try to open directly the file saved with the command but the result is not totally an hyperfile.

                      Cheers,
                      Manuel

                      MAXON SDK Specialist

                      MAXON Registered Developer

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

                        Hello again,

                        After digging a bit you can add a key parameter on your Open function. And write the Version of cinema4D retrieved with GetC4DVersion
                        That way, you can read/write hyperfile to save your SplineData with script and/or using the load/save menu (when right clicking on the parameter)

                        Of course on that example the selected object (op) have a UserData (id 1) that is a spline type.

                        import c4d
                        from c4d import gui
                        from c4d import storage as st, gui
                        # Welcome to the world of Python
                        
                        
                        def Read(path):
                            hf = st.HyperFile()
                            spdata = None
                            if hf.Open(ident=1885434477, filename=path, mode=c4d.FILEOPEN_READ, error_dialog=c4d.FILEDIALOG_NONE):
                                c4dVersion = hf.ReadInt32()
                                spdata = hf.ReadData()
                            else:
                                raise ValueError("can't open file")
                            op[c4d.ID_USERDATA,1] = spdata
                            
                        
                        def Write(path):
                            hf = st.HyperFile()
                            spdata = op[c4d.ID_USERDATA,1]
                            if hf.Open(ident=1885434477, filename=path, mode=c4d.FILEOPEN_WRITE, error_dialog=c4d.FILEDIALOG_NONE):
                                hf.WriteInt32(c4d.GetC4DVersion())
                                writeDone = hf.WriteData(spdata)
                            else:
                                raise ValueError("error openging the file")
                        
                        
                        # Execute main()
                        if __name__=='__main__':
                            path = st.SaveDialog(type=c4d.FILESELECTTYPE_ANYTHING, title="Please Select the file")  
                            Write(path)
                            spdata = op[c4d.ID_USERDATA,1]
                            spdata.DeleteAllPoints()
                            op[c4d.ID_USERDATA,1] = spdata
                            Read(path)
                            c4d.EventAdd()
                        

                        Cheers
                        Manuel

                        MAXON SDK Specialist

                        MAXON Registered Developer

                        1 Reply Last reply Reply Quote 0
                        • G
                          gsmetzer
                          last edited by

                          Thank You @m_magalhaes very helpful! I succeeded. I should have been able to figure this out from the example in the API.
                          I've used the code basically as you have it with my spline datas saved in different hyperfiles. I then load that data from my tag.

                          Thanks again.

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