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

    Basic plugin creation

    PYTHON Development
    0
    33
    16.9k
    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.
    • H
      Helper
      last edited by

      On 14/02/2013 at 00:21, xxxxxxxx wrote:

      Hi Schnups,

      I'm wondering where you are reading about classes, it obviously is teaching you wrong. In Python,
      you can assign any variable to your own class, not necessarily in the __init__() method which is
      only called when the instance has just been created. But when you assign the instance the
      variable, you also have to read it from it.

      class Foo(object) :
        
          def __init__(self, abc) :
              self.abc = abc
        
          def get_abc(self) :
              return self.abc
        
          def get_other(self) :
              return self.other
        
      f = Foo("hello schnupsi") # creates a new instance and calls __init__() on it
      print f.abc # Prints "hello schnupsi"
      print f.get_abc() # Prints "hello schnupsi"
      print f.get_other() # This will NOT WORK, `f` does not have an attribute `other`
        
      f.other = "other text"
      print f.other # Prints "other text"
      print f.get_other() # Prints "other text"
      

      You should really lay down the book you're currently reading at take a look at the official Python
      tutorial, which is imho the best place to start programming with Python.

      See: http://docs.python.org/2.6/tutorial/index.html

      PS: I still don't understand why you want to use the document that is active at the time
      an instance of your CommandData subclass is created, which is at registration-time. The document
      you obtain might either not be valid at the time Execute() is called (which is when you click on your
      plugin in Cinema's GUI) or simply not be the active document anymore.

      -Niklas

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 14/02/2013 at 01:17, xxxxxxxx wrote:

        "hello schnupsi" 😂

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 14/02/2013 at 01:35, xxxxxxxx wrote:

          Uups, had your name wrong in mind while writing that. 😊

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 14/02/2013 at 01:47, xxxxxxxx wrote:

            Ahh, thanks Niklasi 😉 that helped...

            I didn´t want to get the variables at creation time. I thought before, the class is somehow created while executing...

            So, if I´ve got it right: The class, as everything before and after, is being "executed" while plugin loading up. Putting a function, variable etc. here, you want to execute by using the plugin doesn´t make sense.
            Only the execute triggers its defined code, but I can also use other pre-defined functions in here too, right?

            I guess the jump from little user scripts to the interface plugins I plan is a bit high.
            The Python Tutorial is on my scope now first...

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 14/02/2013 at 04:07, xxxxxxxx wrote:

              Originally posted by xxxxxxxx

              class Starter(c4d.plugins.CommandData) :  
                def __init__ (self) :  
                    self.doc_a  = c4d.documents.GetActiveDocument()  
                      #you refer to the variable of the class, so you have to reference "self."  
                    self.obj    = self.doc_a.GetActiveObject()  
                    self.rnd    = random.random()         
               
               
                def Execute(self, doc) :        
                    if not obj:   
                        print ("Nothing Selected")  
                        return True             
                    obj.SetAbsPos(c4d.Vector((rnd*100), 0, 0))    
                    c4d.EventAdd()  
                    return True   
               
              # NameError: global name 'doc_a' is not defined
              

              What you wrote refers to a variable doc_a which is known for all funtcions, since you haven't declared that it comes from some owner, but such a variable doesn't exist. That's what the error message says "No global variable of that name"

              Greetings
              Nachtmahr

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 16/02/2013 at 02:44, xxxxxxxx wrote:

                Ok, roger that 🙂

                Is it possible give a plugin a background behaviour in a similar way the Script Log works?
                Not in a list, just that it writes the string of the last command called to a variable, (like the entries which also shows up in the Script Log entry)?

                If it´s very complicated don´t worry...

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 16/02/2013 at 03:36, xxxxxxxx wrote:

                  Unfortunately there is not (yet, from Python).

                  -N

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    On 16/02/2013 at 04:04, xxxxxxxx wrote:

                    What a pity, I wanted to do a "Repeat last Command" plugin, like Max and Maya have. Which would check with a list of chosen c4d commands to repeat them easily.

                    Well, another question for future plugins:
                    It is possible to update a plugin-gui spinner, which for instance changes a position, in realtime, without the need of an apply button? Not in an object or tag plugin.
                    Don´t need to know how, just if...

                    Thanks for being such a big helper around here Niklas 🙂

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      On 16/02/2013 at 07:49, xxxxxxxx wrote:

                      what do you mean with   Not in an object or tag plugin ? a dialog or a shader/tool ?
                      for dialogs, use the command/coremessage method to write/read data from/into 
                      your dialog.for descriptions it is allso possible, but actually not the way things are 
                      intended to be done. the message/getdenabling methods could be here a suiteable 
                      place to implement such behaviour. for certain behaviours you would have to write a 
                      message helper plugin to notify your plugins when they have to update themself.

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        On 16/02/2013 at 08:50, xxxxxxxx wrote:

                        A bit confusing written, sorry. I meant the python tag or generator with user data by not in a tag....

                        What Im planning once my skill is good enough, is to do a much improved coordinate manager, which first of all, has an auto update, so you see the changes while adjusting.

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          On 16/02/2013 at 08:57, xxxxxxxx wrote:

                          So, you'll want to make a dialog. This is perfectly possible: once a value is changed by the user, you will be
                          notified about this change and can react on it.

                          -N

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            On 16/02/2013 at 09:03, xxxxxxxx wrote:

                            ps: this feature is already implemented in c4d. the coords tab of an object node works that
                            way.

                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              On 16/02/2013 at 09:12, xxxxxxxx wrote:

                              Thank you, that keeps my motivation up 😉

                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

                                On 16/02/2013 at 09:13, xxxxxxxx wrote:

                                Originally posted by xxxxxxxx

                                ps: this feature is already implemented in c4d. the coords tab of an object node works that
                                way.

                                Yeah, but just working on objects, not all the modes...

                                1 Reply Last reply Reply Quote 0
                                • H
                                  Helper
                                  last edited by

                                  On 21/02/2013 at 02:31, xxxxxxxx wrote:

                                  I´m studying this tutorial:
                                  http://www.smart-page.net/blog/2012/02/22/smart-hn-options-cinema-4d-python-commanddata-plugin-template/
                                  It works with some custom modules and to get a better understanding I rearanged and modified the code to be all in one single pyp file.

                                  I finally got it to work, but there a thing I still don´t understand.
                                  This starts the function  "work" when you press OK in the menu:

                                  .....  
                                          result = work(aEnabledState  = enableState,   
                                                                 aSetEditor     = self.GetBool(MAINDIALOG_CHECK_SETEDITOR),  
                                                                 aSetRender     = self.GetBool(MAINDIALOG_CHECK_SETRENDER),  
                                                                 aEditor        = self.GetLong(MAINDIALOG_SLIDER_EDITOR),  
                                                                 aRender        = self.GetLong(MAINDIALOG_SLIDER_RENDER),  
                                                                 aInc           = self.GetBool(MAINDIALOG_CHECK_INC))  
                                  

                                  which looks like this:

                                  def work(aEnabledState = 0, aSetEditor = False, aSetRender = False, aEditor = 2, aRender = 3, aInc = False)  
                                    
                                    doc = c4d.documents.Get......  
                                    .......  
                                    return result  
                                  

                                  It works like that, but when I put the "work" function in a class (Worker) and update the result to Worker.work:

                                  result = Worker.work(aEnabled....
                                  

                                  I get this message for this line:

                                  "TypeError: unbound method work() must be called with Worker instance as first argument (got nothing instead)"

                                  What does it mean, and what did I do wrong calling the function from the class?
                                  Google couldn´t help me much 😉

                                  1 Reply Last reply Reply Quote 0
                                  • H
                                    Helper
                                    last edited by

                                    On 21/02/2013 at 05:04, xxxxxxxx wrote:

                                    Keep it the way you have it:

                                    Make the method a staticmethod. (google)

                                    Or make it an instance method:

                                    1. Add the self parameter for the Worker.work() function.
                                    2. Create an instance of the Worker class and call work() on it.

                                    1 Reply Last reply Reply Quote 0
                                    • H
                                      Helper
                                      last edited by

                                      On 22/02/2013 at 04:17, xxxxxxxx wrote:

                                      Thanks.

                                      I did a little Gui-Plugin, with a spinner, where the x position is read by CoreMessage and written back by Commmand.  Just  one thing I can´t figure out, the changes get updated in the viewport only after leaving the spinner, although the print command constantly updates:

                                          def Command(self, id, msg) :  
                                                c4d.StopAllThreads()  
                                                if id == IDC_POS:  
                                                    obj = c4d.documents.GetActiveDocument().GetActiveObject()  
                                                    x_value = self.GetReal(IDC_POS)  
                                                    obj_pos_y = obj.GetAbsPos().y  
                                                    obj_pos_z = obj.GetAbsPos().z  
                                                    obj.SetAbsPos(c4d.Vector(x_value, obj_pos_y, obj_pos_z))  
                                                    print x_value  
                                                    c4d.EventAdd()  
                                                return True
                                      
                                      1 Reply Last reply Reply Quote 0
                                      • H
                                        Helper
                                        last edited by

                                        On 22/02/2013 at 04:37, xxxxxxxx wrote:

                                        1. What "spinner"?
                                        2. Make your life easier:
                                        pos = obj.GetAbsPos()  
                                        pos.x = x_value  
                                        obj.SetAbsPos(pos)
                                        

                                        -Nik

                                        1 Reply Last reply Reply Quote 0
                                        • H
                                          Helper
                                          last edited by

                                          On 22/02/2013 at 04:45, xxxxxxxx wrote:

                                          Much easier 😉

                                          Spinner might be 3ds terminology, I refer to the up/down arrows next to my number edit box, which control X Position...

                                          1 Reply Last reply Reply Quote 0
                                          • H
                                            Helper
                                            last edited by

                                            On 22/02/2013 at 06:19, xxxxxxxx wrote:

                                            1. I'm not sure what you're doing in the CoreMessage(), it shouldn't be necessary to override this method.
                                            2. You need to redraw the editor, c4d.EventAdd() just tells Cinema that something happened and a redraw will be necessary the next time Cinema would normally decide whether to redraw or not. To invoke a redraw immediately, use c4d.DrawViews().

                                            See c4dtools.utils.update_editor() for an example call: https://github.com/NiklasRosenstein/c4dtools/blob/master/c4dtools/utils.py#L161-L163

                                            -Nik

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