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

    Interaction Tag - def message seems to not work

    Cinema 4D SDK
    2
    4
    558
    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
      Smolak
      last edited by

      Hi,

      def message (id,data) in Interaction Tag ( scripting tab ) seems to not work :

      24985db9-2285-4022-a1a0-2fe66b3dcfb9-image.png

      None of the message id's from here doesn't work : https://developers.maxon.net/docs/py/2023_2/manuals/application_development/manual_message_system.html like c4d.MSG_POLYGONS_CHANGED ( id 2 )

      Architectural Visualizations - www.archviz-4d.studio

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

        Hello @Smolak,

        Welcome to the Plugin Café forum and the Cinema 4D development community, it is great to have you with us!

        Getting Started

        Before creating your next postings, we would recommend making yourself accustomed with our Forum and Support Guidelines, as they line out details about the Maxon SDK Group support procedures. Of special importance are:

        • Support Procedures: Scope of Support: Lines out the things we will do and what we will not do.
        • Support Procedures: Confidential Data: Most questions should be accompanied by code but code cannot always be shared publicly. This section explains how to share code confidentially with Maxon.
        • Forum Structure and Features: Lines out how the forum works.
        • Structure of a Question: Lines out how to ask a good technical question. It is not mandatory to follow this exactly, but you follow the idea of keeping things short and mentioning your primary question in a clear manner.

        About your First Question

        Your posting is missing the version you are using, but with 2023.2 I do not have any problems, including retrieving MSG_POLYGONS_CHANGED when the polygons of a PolygonObject hosting the interaction tag have changed.

        import c4d
        
        def message(mid: int, data: any) -> bool:
            """Called by Cinema 4D to convey events to the tag.
            """
            if mid == c4d.MSG_POLYGONS_CHANGED:
                print ("MSG_POLYGONS_CHANGED")
            return True
        

        The major question for me would be what you are trying to do to invoke the message. The purpose of MSG_POLYGONS_CHANGED is as declared in the docs:

        Sent to notify an object its polygons have changed.

        What is meant with that is that you will only receive it when polygons are added or removed. The same goes for MSG_POINTS_CHANGED. When you want to catch point values being changed, e.g., by moving around a polygon in the editor, you usually listen for MSG_UPDATE which has a bit cryptic description:

        Must be sent when the bounding box must be recalculated.

        However, this message is not being propagated to children of a node (probably for performance reasons). We must remember that we are here inside the Python Interaction tag and listening to its node message stream, i.e., we only receive messages sent to the tag. Only when messages are sent deliberately also to all related nodes with C4DAtom.MultiMessage, something like MSG_POLYGONS_CHANGED can bubble up in TagData.Message (which is what is effectively being called here) which has no polygons and therefore is never the direct recipient of such message.

        In the case of manipulating the values of existing points, e.g., moving a polygon, there are two messages being broadcasted to a hosting Python Interaction Tag:

        • MSG_INTERACTIONTAG_INITTWEAKINFO (440000186): The message symbol is internal and neither exposed in C++ nor Python. It is a special message of the interaction tag and is sent every time the user starts dragging in the viewport.
        • c4d.MSG_GETCUSTOMICON (1001090): This message is sent very often and is a common candidate when one wants to catch update events for things one is not explicitly informed about as the message indirectly indicates changes.
        import c4d
        c4d.MSG_INTERACTIONTAG_INITTWEAKINFO: int = 440000186
        
        def message(mid: int, data: any) -> bool:
            """Called by Cinema 4D to convey events to the tag.
            """
            if mid == c4d.MSG_POLYGONS_CHANGED:
                print ("MSG_POLYGONS_CHANGED")
            # Sent when the user clicks into the viewport while the object which hosts this tag is selected.
            # This will then also include point values changes.
            elif mid == c4d.MSG_INTERACTIONTAG_INITTWEAKINFO:
                print ("MSG_INTERACTIONTAG_INITTWEAKINFO")
            # Sent all the time and therefore only useful for piggy backing onto when one does not care
            # about when something does happen.
            elif mid == c4d.MSG_GETCUSTOMICON:
                print ("MSG_GETCUSTOMICON")
            return True
        

        You can make things more precise with BaseObject.IsDirty, but if you really want to narrow down things, you will have to cache things yourself (see end of posting).

        Cheers,
        Ferdionand

        Code:

        import c4d
        
        tag: c4d.BaseTag# The Python interaction tag
        op: c4d.BaseObject # The object owning the tag
        
        # Add the unexposed message ID for an interaction tag preparing for a tweak event.
        c4d.MSG_INTERACTIONTAG_INITTWEAKINFO: int = 440000186
        # A plugin ID to store point cache data under in an interaction tag, you can use that ID if you
        # want to, I registered it just for the example.
        ID_POINTDATA_CACHE: int = 1060897
        
        def IsPointDataDirty(tag: c4d.BaseTag, obj: c4d.PointObject) -> bool:
            """Determines if the point values of the hosting point object #obj of #tag have changed.
        
            This is done by caching the last known point values state in #tag itself. 
            """
            # Get out when #obj is not a point object or not the host of #tag.
            if not isinstance(obj, c4d.PointObject) or tag.GetMain() != obj:
                return False
        
            # The general idea is to simply copy the point values of #obj into #tag as a BaseContainer
            # under the custom parameter ID ID_POINTDATA_CACHE defined above.
            
            # Get the BaseContainer parameter at #ID_POINTDATA_CACHE in #tag or create an empty container
            # when there is None. Also give such container itself the ID #ID_POINTDATA_CACHE to be sure
            # we retrieve the correct data.
            cache: c4d.BaseContainer = (tag.GetParameter(ID_POINTDATA_CACHE, c4d.DESCFLAGS_GET_NONE) or 
                                        c4d.BaseContainer(ID_POINTDATA_CACHE))
            if not cache.GetId() == ID_POINTDATA_CACHE:
                raise RuntimeError(f"Found unexpected data at ID_POINTDATA_CACHE.")
            
            # Now iterate over all point data of #obj and compare/update it with the cache.
            isDirty: bool = False
            for i, liveValue in enumerate(obj.GetAllPoints()):
                cachedValue: c4d.Vector | None = cache.GetVector(i)
                if cache.GetIndexId(i) == c4d.NOTOK or cachedValue != liveValue:
                    cache.SetVector(i, liveValue)
                    isDirty = True
            
            # Write the cache back and report if the cache differed from the current point values of #obj.
            tag.SetParameter(ID_POINTDATA_CACHE, cache, c4d.DESCFLAGS_SET_NONE)
            return isDirty
        
        def message(mid: int, data: any) -> bool:
            """Called by Cinema 4D to convey events to a tag.
            """
            if mid == c4d.MSG_INTERACTIONTAG_INITTWEAKINFO:
                # This will narrow things down to cases where the hosting object is data dirty, which
                # includes but is not limited to point value changes. There is no better dirty flag or 
                # message for this and when we want a more precise event, we must track things ourselves.
                if op.IsDirty(c4d.DIRTYFLAGS_DATA):
                    # print ("Interaction event with the host object being data dirty.")
                    pass
                # Which is done by this function here.
                if IsPointDataDirty(tag, op):
                    print ("The point data of the hosting point object has changed.")
            return True
        
        

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • S
          Smolak
          last edited by Smolak

          Thank you very much for depth explanation. I didn't know that "polygons have changed" means that they need to be deleted. I thought that it will works with polygons modification too.

          But using one of the code I have this error :

          3db1958c-04de-45b5-a257-4f34e2bb091b-image.png

          Regards,
          Sebastian

          Architectural Visualizations - www.archviz-4d.studio

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

            Hey @Smolak,

            You must expose the ID as explained in the posting and shown in the second code listing. Forgot to do it in the second one. I have updated the listing.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

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