Polygon Selections with ObjectData Plugin



  • Hi!
    Are there any methods/examples for generating polygon selections with an ObjectData plugin similar to the Selections QuickTab of some Generator Objects?

    7b41588b-ca5c-4c6c-98b2-098ab7631f10-image.png

    Thank you 😃



  • Hi,

    I don't think you can create the new CacheProxy tags in Python yet, at least not in a meaningful manner (haven't tried yet actually). But you can do it for sure the old school way. Just assign some selection tags to your cache. When assigning materials to the generator, Cinema will also look into cache to resolve material restriction selections. The code below can be inserted in a Python Generator and will allow you to assign materials with the selection "a" and "b". The attached file contains such setup.

    Cheers,
    zipit

    mat_selection_generator.c4d

    import c4d
    # Welcome to the world of Python
    
    
    def create_polygon_selection_tag(node, index):
        """Creates a polygon selection and returns it.
        
        Args:
            node (c4d.PolygonObject): The node.
            index (int): The polygon index.
        
        Returns:
            c4d.BaseTag: The selection tag.
        
        Raises:
            RuntimeError: When SMC failed.
        """
        # Select the passed polygon index in the node.
        selection = node.GetPolygonS()
        selection.DeselectAll()
        selection.Select(index)
        # Run SMC
        command = c4d.MCOMMAND_GENERATESELECTION
        mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION
        res = c4d.utils.SendModelingCommand(command=command,
                                            list=[node],
                                            mode=mode,
                                            bc=c4d.BaseContainer(),
                                            doc=c4d.documents.BaseDocument())
        if res is False:
            raise RuntimeError("Whoopsie!")
    
        # Get the last polygon selection tag on the node (which is the new
        # one). You might want to be a bit more careful here than me and
        # properly evaluate which one is the new tag.
        nid = c4d.Tpolygonselection
        tags = [tag for tag in node.GetTags() if tag.CheckType(nid)]
        return tags[-1] if tags else None
    
    
    def main():
        """Entry point.
        """
        node = c4d.PolygonObject(pcnt=6, vcnt=2)
        scale = 200
        u, v = c4d.Vector(1, 0, 0), c4d.Vector(0, 1, 0)
        # Points for first poly
        a = c4d.Vector()
        b = scale * u
        c = scale * (u + v)
        d = scale * v
        # Remaining points
        e = 2 * scale * u
        f = e + scale * v
        #         0  1  2  3  4  5
        points = [a, b, c, d, e, f]
        # Set points and set and create polygons.
        node.SetAllPoints(points)
        node.SetPolygon(0, c4d.CPolygon(0, 1, 2, 3))
        node.SetPolygon(1, c4d.CPolygon(1, 4, 5, 2))
        # We can instiate selection tags in Python, but we cannot set a
        # baseselect for them. So we have to use SMC.
        tag_a = create_polygon_selection_tag(node, 0)
        tag_b = create_polygon_selection_tag(node, 1)
        # Set the reference names of the tags so that we can adress them
        # in materials.
        tag_a[c4d.ID_BASELIST_NAME] = "a"
        tag_b[c4d.ID_BASELIST_NAME] = "b"
        # Farewell little polygon node ;)
        return node
    


  • Hi,

    I don't think you can create the new CacheProxy tags in Python yet, at least not in a meaningful manner (haven't tried yet actually). But you can do it for sure the old school way. Just assign some selection tags to your cache. When assigning materials to the generator, Cinema will also look into cache to resolve material restriction selections. The code below can be inserted in a Python Generator and will allow you to assign materials with the selection "a" and "b". The attached file contains such setup.

    Cheers,
    zipit

    mat_selection_generator.c4d

    import c4d
    # Welcome to the world of Python
    
    
    def create_polygon_selection_tag(node, index):
        """Creates a polygon selection and returns it.
        
        Args:
            node (c4d.PolygonObject): The node.
            index (int): The polygon index.
        
        Returns:
            c4d.BaseTag: The selection tag.
        
        Raises:
            RuntimeError: When SMC failed.
        """
        # Select the passed polygon index in the node.
        selection = node.GetPolygonS()
        selection.DeselectAll()
        selection.Select(index)
        # Run SMC
        command = c4d.MCOMMAND_GENERATESELECTION
        mode = c4d.MODELINGCOMMANDMODE_POLYGONSELECTION
        res = c4d.utils.SendModelingCommand(command=command,
                                            list=[node],
                                            mode=mode,
                                            bc=c4d.BaseContainer(),
                                            doc=c4d.documents.BaseDocument())
        if res is False:
            raise RuntimeError("Whoopsie!")
    
        # Get the last polygon selection tag on the node (which is the new
        # one). You might want to be a bit more careful here than me and
        # properly evaluate which one is the new tag.
        nid = c4d.Tpolygonselection
        tags = [tag for tag in node.GetTags() if tag.CheckType(nid)]
        return tags[-1] if tags else None
    
    
    def main():
        """Entry point.
        """
        node = c4d.PolygonObject(pcnt=6, vcnt=2)
        scale = 200
        u, v = c4d.Vector(1, 0, 0), c4d.Vector(0, 1, 0)
        # Points for first poly
        a = c4d.Vector()
        b = scale * u
        c = scale * (u + v)
        d = scale * v
        # Remaining points
        e = 2 * scale * u
        f = e + scale * v
        #         0  1  2  3  4  5
        points = [a, b, c, d, e, f]
        # Set points and set and create polygons.
        node.SetAllPoints(points)
        node.SetPolygon(0, c4d.CPolygon(0, 1, 2, 3))
        node.SetPolygon(1, c4d.CPolygon(1, 4, 5, 2))
        # We can instiate selection tags in Python, but we cannot set a
        # baseselect for them. So we have to use SMC.
        tag_a = create_polygon_selection_tag(node, 0)
        tag_b = create_polygon_selection_tag(node, 1)
        # Set the reference names of the tags so that we can adress them
        # in materials.
        tag_a[c4d.ID_BASELIST_NAME] = "a"
        tag_b[c4d.ID_BASELIST_NAME] = "b"
        # Farewell little polygon node ;)
        return node
    


  • hi,
    with the proxy tag you would need the function SetRealTag that is not accessible from C++ nor Python.(And i'm going to ask why =))

    You can use a selected tag as ZipIt said, the material will "find" it anyway.

    The voronoi does it in another kind of way. It does create the tags in the generator so you can "drag and drop" them to a field, but you can't drag and drop them in another object.
    For that, you need to set the bits to NBIT_NO_DD.
    The Generator need to track what tag should be active/display (change bits to NBIT_OHIDE and track the tags with an array of BaseLinks.

    And there's some other kind of "hack".

    As @zipit said, doing it "the old way" is maybe enough for users and your health :)

    Cheers,
    Manuel



  • This is very helpful, thank you @zipit and @m_magalhaes! Thank you so much for the example, @zipit !

    So the 'old school way' would require the user to make the object editable? Is there any way to do something similar to the SetRealTag or CacheProxy methods of procedural selection tags? I'd like to somehow control the shading of my object without making it editable. Thanks!



  • Hi,

    @blastframe said in Polygon Selections with ObjectData Plugin:

    So the 'old school way' would require the user to make the object editable?

    that depends on what the user is trying to do. For anything that only references the selection tag by name, e.g. a material tag, no, the user won't have to make the object editable, because Cinema will on its own include the cache of a generator object when looking for selection tags referenced by name. The file above demonstrates that.

    If the user wants to reference the tag anywhere, where an actual BaseLink to a selection tag is required, e.g. the deformer restriction tag thingy, forgot its name, then, yes, the old approach shown above will not work.

    Cheers,
    zipit



  • @zipit

    Sorry, it embarrassingly didn't occur to me that your file example was working because I didn't see the Selection Tags as with the Generators. Thanks again for it! For the best user experience, there would be a proxy tag so the user can link & reference it by name. @m_magalhaes , any updates on the SetRealTag implementation in the SDK? I created a request for the SDK here: SetRealTag Request

    Thank you.


Log in to reply