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
    • Register
    • Register
    • Login

    Dynamically changing custom icon of TagData Plugin

    Cinema 4D SDK
    python s26 windows
    2
    6
    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.
    • H
      HerrMay
      last edited by

      Hi guys,

      I have a tag plugin which makes use of c4d.MSG_GETCUSTOMICON stole the code from here to dynamically change its icon based on a parameter of the tag.

      While this is all fine and dandy, I encountered the problem that this only works if I add the tag to a single object. The minute I have multiple objects selected and add my tag plugin to them, the first (or last, depending how you want to see it) always loads the wrong icon while the other objects get the correct one. See pictures below.

      Wrong behaviour:
      Not_Working.jpg

      Expected behaviour:
      Working.jpg

      My feeling is, that c4d.MSG_MENUPREPARE is the culprit here and only gets called for a single instance of the tag. Not sure though.

      To circumvent this I implemented a c4d.plugins.MessageData plugin which reacts to a c4d.SpecialEventAdd() call I send every time c4d.MSG_MENUPREPARE is called received in the tag plugin. So in essence I delegate the work to the MessageData plugin which is now responsible to set the parameter on the tag plugin instances.

      Long story short - it works. 😄
      But I wonder if this is "the right" way to do it. As it feels a little bit clunky and also somehow overkill for such a small feature. Imagine having a couple of plugins which all implement some similar feature. All of these plugins would then need a MessageData plugin which communicates with them.

      So, to finish this of. Could someone tell me if this is the intended approach or if I#m missing something here and doing things unnecessarily complicated?

      I attached the project so that its easier to follow.

      TagTest.zip

      Cheers,
      Sebastian

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

        Hello @HerrMay.

        Thank you for reaching out to us. While I sort of understand what you are talking about, I struggle quite a bit with this:

        While this is all fine and dandy, I encountered the problem that this only works if I add the tag to a single object. The minute I have multiple objects selected and add my tag plugin to them, the first (or last, depending how you want to see it) always loads the wrong icon while the other objects get the correct one. See pictures below.

        When I run your plugin on 2023.2.1, and try to roughly mimic what you are talking about, I end up with this:

        First, I thought something is broken with tri states (i.e., being able to select multiple nodes and edit parameters with overlapping IDs in all selected nodes at once), because the tri states seemingly break as soon as you select "off". But in the video above I realized then that also a singular parameter is being grayed out when you select "off", meaning that you must have implemented GetDEnabling.

        And sure enough, you do this:

        def GetDEnabling(self, node, id, t_data, flags, itemdesc):
            """
            """
            if node[IDC_ACTIVE] == IDC_ACTIVE_OFF:
                return False
        
            return True
        

        Which is a bit odd to say the least, because toggling IDC_ACTIVE to "off" will effectively brick your tag, since it will disable all parameters, including IDC_ACTIVE itself.

        Other than that, and as shown in the video, I was not able to reproduce your problem. You should share a step-by-step reproduction in a form as such:

        Reproduce
        ---------
        
        1. With the Create/Mesh/Cube entry add a cube object to a scene.
        2. For that new cube object, in the Attribute Manager:
          I. Set the Segments.X parameter to 42.
          II. Check the Separate Surfaces parameter.
        
        Result
        ------
        
        1. The cube object is shown as a sphere in the viewport.
        2. All parameter changes made to the Attribute Manager for such malformed cube object are being ignored, the object is permanently broken.
        

        Cheers,
        Ferdinand

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • H
          HerrMay
          last edited by

          Hi @ferdinand,

          ah stupid me. I forgot to remove the GetDEnabling part. Didn't mean to bring that along.

          My problem is not so much about enabling or disabling the node(s) but more the fact that some nodes are simply getting the "wrong" icon status when the tag is apllied from the menu.

          Try to comment def CoreMessage(self, id, bc) in the TagTestMessageHandler class and then reload the plugin and apply the tag to your object selection again. You should see that the topmost object gets the red icon while the others get the expected green one.

          Cheers,
          Sebastian

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

            Hello @HerrMay,

            I unfortunately do not have the time to go bug hunting on my own. Debugging of user projects is out of scope of support in general as stated in our guidelines. I doubt there is a bug in our icon handling, so there is more likely a problem in your logic.

            Please provide code and clear instructions on how to reproduce the problem, preferably in the (1, 2, 3, ...) manner as shown above. Otherwise, I will not be able to make here an exception and help you debugging this.

            Cheers,
            Ferdiand

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 0
            • H
              HerrMay
              last edited by

              Hi @ferdinand,

              alrighty, understood. I know you don't have either the time nor the permission to go on deep bug hunting tours. So no worries there. 🙂

              I stripped down the code to the bare minimum. That way it should be easier.

              Please find below the new project.

              DoNothingTag.zip

              To mimic what I've down please follow these steps. Tested in 2023.2.1

              1. Install the "Do Nothing Tag" Plugin from the ZIP-Archive.

              2. Create some objects. Doesn't matter what kind.

              3. Select all of these objects and apply the "Do Nothing Tag" from the extensions submenu inside the tag menu.

              4. You see the topmost object of the selection gets the red icon while the others get the green one.

              I hope I could be more helpful with these informations. If not, don't hesitate to tell me what I could provide additionally.

              Thank you,
              Sebastian

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

                Hello @HerrMay,

                Thank you for the updated information. I had a look at your problem, and I could reproduce it, but it is primarily a problem of your code as suspected.

                I document below how I analyzed this problem not as a passive aggressive expression of "look how easy that is!". But to give an insight on how to approach such debugging task. The core rule is here to question one's own assumptions and assure that things are indeed how we think they are.

                Debugging

                So, when one follows your steps, one indeed ends up with something like this:

                8fdef1aa-1a5e-43d8-8cdb-42b480fd4f0d-image.png

                Your assumption here was that the icon handling is bugged on our side. For that to be true, the tag on Null.2 would have to be IDC_ACTIVE_ON but with the icon handling failing and Cinemas 4D rendering it as disabled.

                So, I checked the value with this code:

                        # Set custom icon for node.
                        if id == c4d.MSG_GETCUSTOMICON:
                            host: c4d.BaseObject = tag.GetObject()
                            isFirst: bool = host.GetUp() == None and host.GetPred() == None
                            if isFirst:
                                print(f"TOP: {host.GetName() = }, {tag[IDC_ACTIVE] = }")
                            else:
                                print(f"OTHER: {host.GetName() = }, {tag[IDC_ACTIVE] = }")
                
                            icon = self.PLUGIN_ICON_INACTIVE if tag[IDC_ACTIVE] == IDC_ACTIVE_OFF else self.PLUGIN_ICON_ACTIVE
                
                            data["bmp"] = icon
                            data["w"] = icon.GetBw()
                            data["h"] = icon.GetBh()
                            data["filled"] = True
                

                Which will print this when you add the tags:

                baebed6a-fdc0-4d53-8214-1d6b2011cad8-image.png

                So, the topmost tag is indeed inactive and the icon rendering is correct. The question is now: 'Why is that tag inactive because we initialize all tags as node[IDC_ACTIVE] = IDC_ACTIVE_ON ?' The likely culprit is just a few lines above, as we toggle there the active state of our tag.

                        # Handle double click on tag.
                        if id == c4d.MSG_EDIT:
                            if tag[IDC_ACTIVE] == IDC_ACTIVE_OFF:
                                tag[IDC_ACTIVE] = IDC_ACTIVE_ON
                            else:
                                tag[IDC_ACTIVE] = IDC_ACTIVE_OFF
                

                And indeed, when we comment out these lines, we end up with this when creating multiple new tags.

                ebddd8e2-ff78-47f3-a4ca-40cbd26ac047-image.png

                Moreover, when we revert our change of commenting out that code and test our assumption 'only happens for multi-object selections', we can see that this does not hold true:

                e5f2a8dd-2ebd-4555-8188-d769b84895e3-image.png

                We can now check our own comment:

                # Handle double click on tag.
                if id == c4d.MSG_EDIT:
                    ...
                

                and check MSG_EDIT:

                de39ee11-81d9-4e68-a2a6-a4c4dd182b84-image.png

                The documentation says, "for example". So, the event does not capture a double click, but double clicking a BaseObject to edit its name is one example of an edit event. Adding a tag to an object apparently also emits MSG_EDIT to the tag, and when you have a multi-selection, MSG_EDIT is only emitted to the first element in the selection.

                Conclusion

                That behavior of MSG_EDIT in regard to tags and multi-selections is of course quite odd, but I would not consider it to be a bug, as an edit event is not really defined for tags in the first place. And while I understand what you want to do here, I would also say that what you do in MSG_EDIT is a violation of the UX principles of Cinema 4D. Double clicking a tag should not edit a random parameter in it. We strive for Cinema 4D having a seamless UX-experience for users including plugins. So, we rather not support it when plugin authors are trying to break these UX rules.

                But I will nevertheless talk with my colleagues about the subject and if we want to consider this behavior of MSG_EDIT to be a bug.

                Cheers,
                Ferdinand

                MAXON SDK Specialist
                developers.maxon.net

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