How to get a variable from plugin.tag



  • On 15/03/2013 at 15:55, xxxxxxxx wrote:

    Hello everybody,

    i feel a bit stupid, but I have no idea and I do not really know the right keywords for finding solutions.
    I have a plugin.tag, which is doing some stuff and storing that stuff in a list.
    Now Id like to continue to work with the list in a python-tag. How can I get that list from the plugin?

    For example:

    class PlgTAG(plugins.TagData) :  
      
      list_ = ["Hello", 12.3, "Everybody"]  
      
      def Init(self, node) :  
          return True  
      
      def Message(self, node, type, data) :  
          return True  
      
      ...
    

    Thanks and greetings
    rown



  • On 15/03/2013 at 16:05, xxxxxxxx wrote:

    In what context exactly do you want to retrieve the list? Your example is not very meaningful.



  • On 15/03/2013 at 16:38, xxxxxxxx wrote:

    Hello Niklas,

    yes, you are right. The example isnt meaningful. Id like to do something like this:

    class PlgTAG(plugins.TagData) :  
      
      list_ = []  
      
      def Init(self, node) :  
          return True  
      
      def Message(self, node, type, data) :  
          return True  
      
      def AnyFunctionToDefineList(self, ... ) :  
          self.list_ = ["Hello", 12.3, "Everybody"] 
    

    PythonTag

    import c4d  
    #Welcome to the world of Python  
      
    def main() :  
      tag = The plugintag  
      list_ = tag.GetTheListSomehow()  
      Do stuff with list_  
    


  • On 16/03/2013 at 00:50, xxxxxxxx wrote:

    Your plugin tag must be attached to an object in the scene, it can't exist on its own. So in your python tag, you could do something like:

    * look for the first active object in the scene
    * check to see if it has your plugin tag attached to it
    * if it does, get the list

    How you get the list depends on what it is. If it's an InExclude list, you can get the tag's BaseContainer, then get the list from that. If it's an array (as you showed in your code) you'll have to make it available to other objects in some way. Then the python tag can get hold of the list and do whatever with it.

    It's easy in C++ but I'm not sure if the same method works in Python. In C++ you would probably make the array private, then provide getter/setter functions to let another object access it. Or do it the dirty way of just making the array public, then anything can access it but without any checks on the plugin's part as to what they do with it.



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

    Hello spedler,

    thanks for reply. I know how to get my tag in python-tag and checking if its attached and so. The example is just an example.

    Originally posted by xxxxxxxx

    If it's an array (as you showed in your code) you'll have to make it available to other objects in some way.

    But thats what I want. I do not know anything about C++, so Ive to take a look what private means and getter/setter is.
    Is C++ -> public the same as Python -> global? If so, Im still not sure how to call the list/array from python tag.

    Thanks very much
    rown



  • On 16/03/2013 at 02:46, xxxxxxxx wrote:

    It doesn't work with Python unfortunately. We do not have access to the NodeData of a plugin in
    Python, or better say we can not get the NodeData from a BaseList2D object! It would be possible
    with a bit of hacking, but it's not very "beautiful".

    You could exchange information via a Python module or a c4dtools.library.Library class. I do
    not recommend the first one. An example for the c4dtools Library to be put in your Python plugin
    file:

      
    #
    # Python Plugin File
    #
      
    import c4d
    import weakref
    import c4dtools
      
    class PluginTag(c4d.plugins.TagData) :
      
        op = None
        instances = []
      
        def Init(self, op) :
            self.instances.append(weakref.ref(self))
      
            self.list_ = []
            self.op = op
            return True
      
        def Free(self) :
            try:
                self.instances.remove(weakref.ref(self))
            except ValueError:
                pass
      
        # ...
      
    class MyLibrary(c4dtools.library.Library) :
      
        class Meta:
            # Global unique identifier!
            name = 'my-super-duper-cool-library'
      
        def get_plugin_tags(self) :
            return PluginTag.instances[:]
      
    #
    # Python Tag (or just somewhere else than the plugin file)
    #
      
    import c4dtools
    lib = c4dtools.load_library('my-super-duper-cool-library')
    for data in lib.get_plugin_tags() :
        data = data() # dereference the weakref
        if not data:
            continue
      
        print data.list_
    

    Note that this only works when you place the c4dtools module somewhere the Python Interpreter
    can always find it, and not as a local distributed dependency as described in this article.



  • On 16/03/2013 at 03:15, xxxxxxxx wrote:

    Hey Niklas,

    thank you very much. I´ll try your lines.
    But one other question. Is it easier/allowed to exchange information between NodeData(plugin.tag) and BaseData(command.tag)?



  • On 16/03/2013 at 03:24, xxxxxxxx wrote:

    the most common approach would be messages for such a problem. both the sending

    and the recieving class would implement a message method and therefore had to be 
    derived from a c4d class which implements such a method. but i have never tried this
    from a script (python-tag).



  • On 16/03/2013 at 03:24, xxxxxxxx wrote:

    Hi rown,

    yes it is allowed, but limited in Python. You can easily exchange data within C++ between the
    plugin classes.

    @Ferdinand:

    You can not send a Python object via messages (from Python). But actually.. it's a good idea. This
    would be possible to implement I think. Maybe they can add it for R15. 🙂



  • On 16/03/2013 at 04:29, xxxxxxxx wrote:

    i am not talking about sending the instance, but his data, some arrays or whatever.
    and aside from that. the data contains pyobjects, not sure if i do understand pyobjects 
    correctly, but aren't they meant to hold references to methods and such stuff too ?
    never went down very far this rabbit hole, sending some variables always has been 
    enough for me.

    or i musunderstood this thread, i thought he has pluginclass a with member b. now he
    wants to read b from somewhere only knowing the gelistnode instance associated with
    his plugin.



  • On 16/03/2013 at 04:35, xxxxxxxx wrote:

    Hi Ferdiand,

    Holy Sh*t I really didn't know that was possible!

    import c4d
      
    MY_MSG = 5000140436
      
    class Test(c4d.plugins.ObjectData) :
      
        def Message(self, op, msg, data) :
            if msg == MY_MSG:
                data.do_stuff()
            return True
      
    class Foo(object) :
      
        def do_stuff(self) :
            print "Foo.do_stuff()"
      
    def main() :
        op.Message(MY_MSG, Foo())
    

    And you knew that? I always thought that was not possible (didn't try it out since now, though)!
    That's so awesome! 😂



  • On 16/03/2013 at 04:44, xxxxxxxx wrote:

    Seriously, is that in the documentation?! I never read it anywhere! From several reasons and
    thinkings I concluded it would not be possible. I see, I should just have tried it out!

    Anyway, rown, something like this should work then:

    MSG_GIMMELIST = 10000234 # Unique Identifier from the Plugincafe!
      
    class PlgTAG(plugins.TagData) :
      
        list_ = []
      
        def Init(self, node) :
            return True
      
        def Message(self, node, type, data) :
            if type == MSG_GIMMELIST:
                data.value = self.list_
            return True
      
        def AnyFunctionToDefineList(self, ... ) :
            self.list_ =  ["Hello", 12.3, "Everybody"]
    
    MSG_GIMMELIST = 10000234 # Unique Identifier from the Plugincafe!
      
    class ValueBox(object) :
      
        def __init__(self, value=None) :
            super(ValueBox, self).__init__()
            self.value = value
      
    def main() :
        tag = op.GetTag(c4d.Tplg)
        box = ValueBox()
        tag.Message(MSG_GIMMELIST, box)
        print box.value
    

    Best,
    -Niklas



  • On 16/03/2013 at 05:05, xxxxxxxx wrote:

    IT IS UNBELIEVABLE!!!

    Thank you both very much! Thanks Devil for letting Niklas know that and thanks Niklas for letting me know how it works.

    Greetings
    rown




  • On 16/03/2013 at 05:09, xxxxxxxx wrote:

    My thanks go to Ferdinand as well, I never would've known that if he wouldn't have told me. :)



  • On 16/03/2013 at 06:35, xxxxxxxx wrote:

    lol, you are welcome. and no i didn't know it exactly, but i assumed it. yannick showed here 
    once how to unpack pyobject data from a message method, which led me to some reading 
    about the pyobject class.


Log in to reply