Highlighted Command Text/Icon when it is executed?
-
Hi,
I'm trying to replicate a UI behavior in one of Cineversity's plug-ins where the command text/icon is highlighted when it is toggled for on and off.
You can check the behavior here:
https://www.dropbox.com/s/3ozfoplfyg3yaj9/c4d133_command_highlighting.mp4?dl=0How do I achieve that?
Thank you for looking at the problem
PS. I can't check the code. It's in pypv.
-
Hi, just to be sure you talk about the blueish things on the menu?
If that's the case you simply have to return c4d.CMD_VALUE | CMD_ENABLED c4d. in your GetState method of your CommandData.Cheers,
Maxime. -
Thanks for the solution. Sorry also for the late response.
I tried implementing the following logic of the visibility plug-in: If not visible: Don't enable. If visible: Enable. (i.e. the highlighting.However, it gives me two errors:
'MyMenuPlugin' object has no attribute 'status'
on theself.state = self.status
line. Which is a bit confusing since I already declared status variable above.- Also, I'm not sure if I'm returning properly with the
not c4d.CMD_VALUE | c4d.CMD_ENABLED
statement. LOL
Just to recap, I'm after this behavior
https://www.dropbox.com/s/3ozfoplfyg3yaj9/c4d133_command_highlighting.mp4?dl=0Here is the code so far: import c4d from c4d import gui, plugins, bitmaps, utils, documents PLUGIN_ID = 1010203 class MyMenuPlugin(plugins.CommandData): def toggle_vis_subd(self): self.doc = c4d.documents.GetActiveDocument() bd = self.doc.GetActiveBaseDraw() displayFilter = bd.GetDisplayFilter() if displayFilter & c4d.DISPLAYFILTER_HYPERNURBS: bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = False print "Switched Off Subdivision Surface Display Filter" else: bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = True print "Switched On Subdivision Surface Display Filter" self.status = bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] bd.Message(c4d.MSG_CHANGE) c4d.EventAdd() c4d.StatusClear() def Execute(self, doc): self.toggle_vis_subd() return True def GetState(self, doc): self.state = self.status if self.state == False: return not c4d.CMD_VALUE | c4d.CMD_ENABLED if self.state == True: return c4d.CMD_VALUE | c4d.CMD_ENABLED if __name__ == "__main__": status = plugins.RegisterCommandPlugin(PLUGIN_ID, "bt_Visibility",0, None, "bt_Visibility", MyMenuPlugin()) if (status): print "Visibility plug-in successfully initialized"
Thank you for looking at problem. The visibility code block I think is from a github c4d sample script.
-
Hi @bentraje the issue is that GetState is called way before Execute (it's called at the moment you display the command into the UI, so at the plugin registration).
So either you create a __init__ method en define the default status value either you can do something like that in your get state method
def GetState(self, doc): # Retrieves the status member of self, and if it's not present it will return True status = getattr(self, "status", True) self.state = status # Previously you were almost safe but in case of self.state is something different than True or False you returned nothing if not self.state: return not c4d.CMD_VALUE | c4d.CMD_ENABLED else: return c4d.CMD_VALUE | c4d.CMD_ENABLED
Cheers,
Maxime. -
Thanks again for the response, especially the code.
I no longer have the error but there is a glitch.
Whenever I execute the command, it works okay at first click but not on the second click. It is permanently disabled. (i.e. I can't toggle with the command).I tried using either
not c4d.CMD_VALUE
only ornot c4d.CMD_ENABLED
but I still have the same result?Is there a way around this?
-
@bentraje Yes as you pass not c4d.CMD_ENABLE as its stand it's not enabled.
Besides that, I also reworked a bit your example to make it pythonic by settings state as a property so when you retrieve state its actually the state from the current document.
import c4d from c4d import gui, plugins, bitmaps, utils, documents PLUGIN_ID = 1010203 class MyMenuPlugin(plugins.CommandData): def Execute(self, doc): self.state = not self.state return True def GetState(self, doc): # Previously you were almost safe but in case of self.state is something different than True or False you returned nothing if not self.state: return c4d.CMD_ENABLED else: return c4d.CMD_VALUE | c4d.CMD_ENABLED @property def state(self): doc = c4d.documents.GetActiveDocument() bd = doc.GetActiveBaseDraw() displayFilter = bd.GetDisplayFilter() if displayFilter & c4d.DISPLAYFILTER_HYPERNURBS: return bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] return False @state.setter def state(self, value): # Checks if the value is a boolean if not isinstance(value, bool): raise TypeError("value is not a bool.") doc = c4d.documents.GetActiveDocument() bd = doc.GetActiveBaseDraw() displayFilter = bd.GetDisplayFilter() if displayFilter & c4d.DISPLAYFILTER_HYPERNURBS: bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = False print "Switched Off Subdivision Surface Display Filter" else: bd[c4d.BASEDRAW_DISPLAYFILTER_HYPERNURBS] = True print "Switched On Subdivision Surface Display Filter" bd.Message(c4d.MSG_CHANGE) c4d.EventAdd() c4d.StatusClear() if __name__ == "__main__": status = plugins.RegisterCommandPlugin(PLUGIN_ID, "bt_Visibility",0, None, "bt_Visibility", MyMenuPlugin()) if (status): print "Visibility plug-in successfully initialized"
Cheers,
Maxime. -
Thank you @m_adam. Work as expected!
(I actually just ended up learning about the decorator property since its new to me. haha. Thanks for that).Just want to confirm, am I right to think this is the code flow:
- Register Plug-In
- @property state
- GetState
- Execute(Button Click)
- @state.setter state
- @property state
- GetState
Then back again to #4 for the click.