Acccessing Inexclude Data



  • On 11/03/2013 at 13:39, xxxxxxxx wrote:

    Hey everyone,

    I'm making a plugin with python. I'ts an objectData Plugin and i'm using .h and .res files for the dialog. I have inexclude lists in the dialog. I have no idea however how to access the objects which i drop into those lists. Also, i couldn't find out where to look in the documentation. I found in the c++ docs how to correctly set up my .h and .res file, but not how to then use that data with python. Neither in the python docs.

    Any help is appreciated!



  • On 11/03/2013 at 14:29, xxxxxxxx wrote:

    c4d.InExcludeData it is all there. There also multiple threads here on PC dealing
    with the InExcludeData class. Nothing really out of the ordinary here. Only  thing 
    worth mentioning is, that you should always construct an instance with an
    existing instance, otherwise funny things tend to happen, despite the fact the
    parameter is flagged optional in the docs.



  • On 12/03/2013 at 01:11, xxxxxxxx wrote:

    Thanks! I am however still unable to get it done. I must mention at this point that i'm  a beginner.

    I have this . res file:

      
    CONTAINER Omlr  
    {  
      NAME Omlr;  
      INCLUDE Obase;  
      
      GROUP ID_OBJECTPROPERTIES  
      {  
          GROUP  
          {  
              BOOL DE_ACTIVATE {}  
              BUTTON VISUAL_REP {}  
          }  
            
          IN_EXCLUDE LAYER_ONE_INEX  {}  
          IN_EXCLUDE LAYER_TWO_INEX   {}  
          IN_EXCLUDE LAYER_THREE_INEX   {}  
      
      }  
    }  
    

    and this .h file:

      
    #ifndef _Oatom_H_  
    #define _Oatom_H_  
      
    enum  
    {  
      
      Omlr                 = 1029977,  
      
      DE_ACTIVATE            = 1000,  
      VISUAL_REP            = 1001,  
      LAYER_ONE_INEX        = 1002,  
      LAYER_TWO_INEX        = 1003,  
      LAYER_THREE_INEX    = 1004  
    };  
      
    #endif  
    

    If yomeone could tell me what code gets me an inexcludedata object with the objects droped in that list i would be really gratefull, because i just can't get it done

    Thanks
    Aurel



  • On 12/03/2013 at 01:21, xxxxxxxx wrote:

    this loops through the list.

    def someMethod(mypluginnode, document) :
    \> inExcludeList = mypluginnode[c4d.LAYER_ONE_INEX]
    \> for i in xrange(inExcludeList.GetObjectCount()) :
    \> > obj = inExcludeList.ObjectFromIndex(document, i)
    


  • On 12/03/2013 at 01:57, xxxxxxxx wrote:

    Thanks! I think i kind of understand how to access things from the .res file. But i still can't get it to work, because i would like to trigger the printing of the inexclude list so to say with a button, in a Message function, which doesn't have op as a parameter (if any of this sounds wrong i'm sorry). Here is the code, hope it isn't too much of a bother:

      
    import c4d  
    from c4d import gui, plugins, documents  
    import os  
      
    PLUGIN_ID = 1029977   
      
    class MultiLayerRender(c4d.plugins.ObjectData) :  
      
      def Execute(self, op, doc, bt, priority, flags) :  
          return True  
      
        def printInEx(op, doc) :  
          inExcludeList = op[c4d.LAYER_ONE_INEX]  
          print inExcludeList  
      
      
      def createTags(self, op, doc) :  
      
            self.printInEx(op, doc)  
      
          doc = c4d.documents.GetActiveDocument()  
          selection = doc.GetSelection()  
          tagID = 5637  
          for hostObject in selection:  
              existing = False  
              tags = hostObject.GetTags()  
              for tag in tags:  
                  if tag.GetType() == tagID:  
                      existing = True  
              if existing == False:  
                  hostObject.InsertTag(c4d.BaseTag(tagID))  
          c4d.EventAdd()  
      
      def VisibilityOn(self) :  
          doc = c4d.documents.GetActiveDocument()  
          selection = doc.GetSelection()  
          tagID = 5637  
          for hostObject in selection:  
              tags = hostObject.GetTags()  
              for tag in tags:  
                  if tag.GetType() == tagID:  
                      tag[c4d.COMPOSITINGTAG_SEENBYCAMERA] = True  
      
      def VisibilityOff(self) :  
          doc = c4d.documents.GetActiveDocument()  
          selection = doc.GetSelection()  
          tagID = 5637  
          for hostObject in selection:  
              tags = hostObject.GetTags()  
              for tag in tags:  
                  if tag.GetType() == tagID:  
                      tag[c4d.COMPOSITINGTAG_SEENBYCAMERA] = False  
      
      def Message(self, node, type, data) :  
          # print "node: " + str(node)  
          if type == c4d.MSG_DESCRIPTION_COMMAND:    
                self.createTags(op, doc) # obviously "op" is not defined  
              # self.VisibilityOn()  
              # self.VisibilityOff()  
              print "type: " + str(type)  
              print "node: " + str(node)  
              print "data: " + str(data)  
          return True  
      
    if __name__=='__main__':  
      bmp = c4d.bitmaps.BaseBitmap()  
      dir, file = os.path.split(__file__)  
      fn = os.path.join(dir, "res", "Icon.tif")  
      bmp.InitWith(fn)  
      result = plugins.RegisterObjectPlugin(  
          id = PLUGIN_ID,  
          str = "MultiLayerRender",  
          g = MultiLayerRender,  
          description ="Omlr",  
          info = c4d.OBJECT_GENERATOR,  
          icon =bmp  
      )  
      
    

    All it gives me, is op is not defined. Including op in the Message parameters howvere doesn't work, i can't just add stuff there apparently.

    I tried figuring out what to do with the help of other threads and the docs but i'm apparently not too good at gathering info yet - couldn't get it solved at all.
    Hope this isn't completly wrong and thanks in advance!

    Aurel



  • On 12/03/2013 at 02:02, xxxxxxxx wrote:

    self is the first parameter to every instance-bound method.

    printInEx(self, op, doc)



  • On 12/03/2013 at 02:05, xxxxxxxx wrote:

    btw. I'm using this op parameter because in another plugin (LiveCaptureNull by Michael Auerswald) he uses op[LAYER_ONE_INEX] or whatever his .res entries are.

      
      def Draw(self, op, drawpass, bd, bh) :  
          if drawpass == c4d.DRAWPASS_OBJECT:  
              if op[LIVECAPTURE_POS] == True or op[LIVECAPTURE_ROT] == True or op[LIVECAPTURE_SCA] == True:  
                  o = op[LIVECAPTURE_LINK]  
                  if o is not None:  
                      self.setKey(op, o.GetAbsPos(), o.GetAbsRot(), o.GetAbsScale())  
          return c4d.DRAWRESULT_OK  
    


  • On 12/03/2013 at 02:19, xxxxxxxx wrote:

    Thanks littledevil and NiklasR for your help so far!

    Forgetting the self there was really stupid of me -.- however, that doesn't do the trick either. printInEx takes3 arguments (self, op, doc) so i need to call it with those three. In createTags however "op" is not defined. So i have to add it to the list of parameters it takes as well, right? -> createTags(self, op, doc) but then i have to call it with those arguments in the Message method, and

    def Message(self, node, type, data, op, doc) :

    gives me an ERROR:

    TypeError: Message() takes exactly 6 arguments (4 given)

    Is there a way to solve that?



  • On 12/03/2013 at 03:13, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    def Message(self, node, type, data, op, doc) :

    gives me an ERROR:

    TypeError: Message() takes exactly 6 arguments (4 given)

    Is there a way to solve that?

    yes and no. you could implement message with op and doc as optional parameters.

    def Message(self, node, type, data, op = None, doc = None) :

    But i guess that is not what you want, because c4d still won't know that you
    expect 6 parameters and call the method with 4 parameters. the only difference
    would be that python won't raise an error and you could call the method from your 
    code with 6 parameters.

    but node and op are basically the same. so you can use node as a substiute.
    and the document can be retrieved from node. with gelistnode.getdocument().



  • On 12/03/2013 at 03:32, xxxxxxxx wrote:

    Thanks littledevil!

    I made the following changes:

      
      def Message(self, node, type, data, ) :  
      
          if type == c4d.MSG_DESCRIPTION_COMMAND:    
              self.printInEx(node)  
          return True  
    

    And

      
      def printInEx(self, node) :  
          myPluginNode = c4d.GeListNode.GetDocument(node)  
          print myPluginNode[c4d.LAYER_ONE_INEX]  
    

    That gives me the error:

    AttributeError: 'module' object has no attribute 'LAYER_ONE_INEX'

    I also tried using the ID which is 1002, no luck with that either. Could it be, that it doesn't find my .res or .h file or something?

    Tahnks in advance!

    Aurel



  • On 12/03/2013 at 03:39, xxxxxxxx wrote:

    and just for the record, when overwriting methods inherited from c4d api classes the naming
    of the parameters does not make any difference, only the order matters, because c4d does not
    call the methods with their keywords. you could overwrite message also this way.

    def Message(self, a, b, c) :

    a(node) would be the the instance derived from gelistdnode of your plugin, a baseobject for
    example. b(type) would be an integer and c(data) would be a basecontainer/pyobject.

    python is pretty unique when it comes to method parameters. you could define message also 
    this way.

    def Message(self, *args) :
    def Message(self, *kwargs) :

    both versions accept any amount of  parameters, the first one is non keyworded, the second 
    one is keyworded.

    myclass.message((a)) # for *args
    myclass.message((a,b)) # for *args
    myclass.message((a,b,c)) # for *args
    ...
    myclass.message({'node': a, 'type': b, 'data':c}) # for *kwargs
    ...



  • On 12/03/2013 at 03:47, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

     
      def printInEx(self, node) :  
          myPluginNode = c4d.GeListNode.GetDocument(node)  
          print myPluginNode[c4d.LAYER_ONE_INEX]  
    

    That gives me the error:
    AttributeError: 'module' object has no attribute 'LAYER_ONE_INEX'

    myPluginNode is a basedocument, the basedocument the instance of the gelistnode
    attached to your pluginclass is attached to. therefore trying to read your inex list does 
    not make much sense, because the inex list is a member of your your plugin instance, 
    not of the document.

    def printInEx(self, node) :
    	if isinstance(node, c4d.GeListNode) :  
          	doc = node.GetDocument()  
          	print node[c4d.LAYER_ONE_INEX]  
    


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

    It works so far, except that it still doesn't find LAYER_ONE_INEX.

    my code ATM:

      
      def printInEx(self, node) :  
          if isinstance(node, c4d.GeListNode) :  
              doc = node.GetDocument()  
          print node[c4d.LAYER_ONE_INEX]   
    

    Error:
    Traceback (most recent call last) :
    File "'MLR.pyp'", line 62, in Message
    File "'MLR.pyp'", line 22, in printInEx
    NameError: global name 'LAYER_ONE_INEX' is not defined

    If i change

      
      
          print node[c4d.LAYER_ONE_INEX]   
    

    to

      
      
          print doc[c4d.LAYER_ONE_INEX]   
    

    i get the error:
    Traceback (most recent call last) :
    File "'MLR.pyp'", line 62, in Message
    File "'MLR.pyp'", line 22, in printInEx
    AttributeError: 'module' object has no attribute 'LAYER_ONE_INEX'

    Do i have to specifically include stuff from Omlr.res / .h? I find it hard to believe that it can be this hard to get that inexclude data - I feel like i'm doing something fundamentaly wrong.

    EDIT:

    I just noticed that

      
      
          print doc[c4d.LAYER_ONE_INEX]   
    

    Doesn't make much sense, because i don't need the document for that, sorry bout that ;/

    Thanks

    Aurel



  • On 12/03/2013 at 05:14, xxxxxxxx wrote:

    have you initialized your attribute ? most customedatatypes have to be initialized, otherwise
    they won't work.



  • On 12/03/2013 at 05:26, xxxxxxxx wrote:

    I GOT IT!!

    It's just that I, being a beginner and all, thought that it's supposed to be

    node[c4d.the name from the .h file]

    but it's actualy

    node[c4d.the ID associated with the name from the .h file]

    so i first had to define LAYER_ONE_INEX = 10002 in the .pyp file XD

    Sorry to bother you with such basic problems and THANK you a lot ;)

    Aurel



  • On 12/03/2013 at 05:30, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    I GOT IT!!

    It's just that I, being a beginner and all, thought that it's supposed to be

    node[c4d.the name from the .h file]

    but it's actualy

    node[c4d.the ID associated with the name from the .h file]

    so i first had to define LAYER_ONE_INEX = 10002 in the .pyp file XD

    Sorry to bother you with such basic problems and THANK you a lot ;)

    Aurel

    you have to init your attribute as i wrote. read c4d.plugins.NodeData.Init()
    and c4d.plugins.NodeData.InitAttr() you do not have to define the ID in your 
    py file again.



  • On 12/03/2013 at 05:45, xxxxxxxx wrote:

    Allright, i will do that! btw. As an obviously pretty expirienced plugin creator, what's in your oppinion the best way of becoming better and understanding the general concept behind cinema? because i would have never thought of looking in those places:

    c4d.plugins.NodeData.Init() and c4d.plugins.NodeData.InitAttr()

    And i most of the time find the plugins more confusing than helping ;(

    Thanks

    Aurel



  • On 12/03/2013 at 07:55, xxxxxxxx wrote:

    i don't think there is any easy way to learn the c4d api, but it is easier than it might look
    on the first glance. simply read the documenation. i started with scripts and added stuff
    as i needed it. you should know and understand the basic principles of oo-programming,
    when you to start writing plugins for c4d (polymorphism and so on).

    those are the most important classes/modules in the python api. >> means read also any 
    class which inherits from this class.

    c4d.Matrix
    c4d.Vector
    c4d.BaseTime
    c4d.BaseContainer
    c4d.C4dAtom (>>)
    c4d.documents.BaseDocument
    c4d.plugins.BaseData (>>)
    c4d.utils

    when you know these you have pretty much the basic tools to write plugins.



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

    Here's some utility functions and examples how I deal with an In/Ex list in an ObjectData plugin and button presses and UI updates.  These are methods in that ObjectData derived class (i.e., my plug-in). Some is pseudo so don't literally try and use this.  More to see how another person approaches it.

    #----------------------------------------------------------------- 
        def __init__(self, node, op) :
            
            node.InitAttr(op, c4d.InExcludeData, [c4d.YOUR_INEX_HERE])

    #-----------------------------------------------------------------

    CALLED WHENEVER A BUTTON IS PRESSED

    def HandleButton(self, id, op) :
            """Make an if statement to do something depending on DescID"""
            #SAMPLE: if id['id'][0].id == 2008: self.__dropdowngrey = False
            #if id['id'][0].id == c4d.NAMELISTBUTTON: self.__NAMEPRINTFUNCTION(op)
            
    #-----------------------------------------------------------------

    CALLED WHENEVER AN ATTRIBUTE CHANGES

    def UpdateChange(self, op) :
            """Any time a user changes an attribute this gets called"""
            print 'someone changed a user doodad'

    #-----------------------------------------------------------------

    RECEIVE MESSAGES FROM C4D

    def Message(self, op, type, data) :

    #Check for button press to call HandleButton function
            if type == c4d.MSG_DESCRIPTION_COMMAND: self.HandleButton(data, op)
         
            #Check for any attribute changes to call UpdateChange function  
            if type == c4d.MSG_DESCRIPTION_CHECKUPDATE: self.UpdateChange(op)
            
            return True

    #-------------------

    def \__NAMEPRINTFUNCTION(self, op) :
    	list = op[c4d.YOUR_INEX_HERE]
    	for i in xrange(list.GetObjectCount()) :
    		#get the object, then get the name and print it
    


  • On 13/03/2013 at 00:27, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    def Message(self, *args) :
    def Message(self, *kwargs) :

    both versions accept any amount of  parameters, the first one is non keyworded, the second 
    one is keyworded.

    myclass.message((a)) # for *args
    myclass.message((a,b)) # for *args
    myclass.message((a,b,c)) # for *args
    ...
    myclass.message({'node': a, 'type': b, 'data':c}) # for *kwargs
    ...

    For the completeness: This is not correct. kwargs is short for "keyword arguments" and using them
    in an "arguments" context is a bit confusing.

    def func(*args, **kwargs) :
        pass
    

    To pass arguments for *args and **kwargs, you can pass them like any other arguments. You
    wouldn't need the *args and **kwargs arguments in the examples you've mentioned.

    def func_1(args, kwargs) :
        print args
        print kwargs
      
    def func_2(*args, **kwargs) :
        print args
        print kwargs
      
    func_1((3, 4, 5), {'node': op, 'data': data})
    func_2(3, 4, 5, node=op, data=data)
      
    args = (3, 4, 5)
    kwargs = {'node': op, 'data': data}
      
    func_1(args, kwargs)
    func_2(*args, **kwargs)
    

    All four function-calls will print the exactly same output here.


Log in to reply