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

    Python - InExcludeData initialization problem

    General Talk
    3
    5
    1.0k
    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.
    • S
      SolarPH
      last edited by

      I had a problem (again) with InExcludeData. this time with initializing the thing

      Also, it seems like there is no way to merge two different InExcludeData fields to make a single InExcludeData list with no object duplicates on it.

      Can any of you can explain to me how can I really do this using Python?
      8333ccd7-1f71-49e9-aa85-e7296b4a2eee-image.png
      It basically was unclear for me as of now...

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

        Hi,

        the docs are trying to tell you that the argument v is an optional argument. For the rest, see the attached example.

        Cheers,
        zipit

        """ Run this in the Script Manager.
        
        You will need to select an object in your scene, which has InExcludeData 
        fields as its first and second user data element. The fields should be
        ideally populated with overlapping sets of objects (e.g. [a, b, c] and [b, 
        c, d]). The script will write the union of those two object sets to the first
        InExcludeData field.
        """
        
        import c4d
        
        def get_objects(doc, op):
            """Returns the objects referenced by an InExcludeData as a list.
            
            Args:
                doc (c4d.documents.BaseDocument): The document the referenced 
                 objects are attached to.
                op (c4d.InExcludeData): The InExcludeData to get the objects from.
            
            Returns:
                list[c4d.BaseObject]: The referenced objects.
            """
            return [op.ObjectFromIndex(doc, i) 
                    for i in range(op.GetObjectCount())]
        
        def main():
            """
            """
            if op is None:
                return
        
            # The two InExcludeData
            inex_a = op[c4d.ID_USERDATA, 1]
            inex_b = op[c4d.ID_USERDATA, 2]
        
            # Get the objects 
            nodes_a = get_objects(doc, inex_a)
            nodes_b = get_objects(doc, inex_b)
            print "nodes in inex_a:", nodes_a
            print "nodes in inex_b:", nodes_b
        
            # Create a new InExcludeData, using the default constructor.
            inex_c = c4d.InExcludeData()
            # Unsurprisingly there is nothing in there.
            print "nodes in inex_c:", get_objects(doc, inex_c)
        
            # Create a new InExcludeData, using the copy constructor.  
            inex_d = c4d.InExcludeData(inex_a)
            # Since we copied from inex_a, it references the same objects.
            print "nodes in inex_d:", get_objects(doc, inex_d)
        
            # Adding the union of the object sets a and b to a new InExcludeData is
            # a little bit convoluted, because the type InExcludeData is not a set
            # by nature and nodes not being hashable prevents us from using Python's
            # sets.
            nodes_union = nodes_a + [n for n in nodes_b if n not in nodes_a]
            inex_union = c4d.InExcludeData()
            for node in nodes_union:
                inex_union.InsertObject(node, 0)
        
            # Write the union back to the first InExcludeData. 
            op[c4d.ID_USERDATA, 1] = inex_union
            c4d.EventAdd()
        
        
        if __name__=='__main__':
            main()```

        MAXON SDK Specialist
        developers.maxon.net

        S 1 Reply Last reply Reply Quote 0
        • r_giganteR
          r_gigante
          last edited by

          Hi @SolarPH, thanks for reaching out us.

          With regard to your question, actually initializing the InExcludeData has nothing to do with having the list not including duplicates.
          The v parameter pointed out in the documentation is used to fill the to-be-created InExcludeData with the values found in the passed InExcludeData as @zipit has shown in line 48.
          To avoid duplication instead you've to manually browse the items in the lists and pickup from the second only those not found in the first. Again @zippit code perfectly shows this.

          Cheers, R

          1 Reply Last reply Reply Quote 0
          • S
            SolarPH @ferdinand
            last edited by

            @zipit Thanks for sharing the code. Now I know that initializing the InExcludeData is not InExcludeData.__init__ and the correct way was c4d.InExcludeData(), which I really did not think of when initializing specialized data containers.

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

              Hi,

              @SolarPH said in Python - InExcludeData initialization problem:

              Now I know that initializing the InExcludeData is not InExcludeData.__init__ and the correct way was c4d.InExcludeData(), ...

              I am not quite sure how you did mean this, but InExcludeData.__init__ is one of the methods called when you invoke c4d.InExcludeData(). Like all double underscore methods __init__ implements an operator, in that case the construction operator. Invoking SomeClass() will first call the constructor SomeClass.__new__ and after that the initialisator SomeClass.__init__. Due to the fact that __new__ only rarely has to be implemented explicitly and because people are accustomed to talking about constructor functions, __init__ is also often called a constructor, while technically it is just the initialisator. A prime example would be both the InExcludeData documentation and my example code, which both talk about a copy constructor, but are actually referring to __init__ and not __new__.

              Cheers,
              zipit

              MAXON SDK Specialist
              developers.maxon.net

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