Branch Execution Code based on Mouse Button

Is it possible to run one of set of commands when a user presses a button with the RMB, and run another set of commands with a LMB click?

Or maybe a CTRL or ALT click, like ZRemesher?

You can do it with Modifier keys. See this (rather old) thread:

Wow Marcus, that thread looks decidedly old school!

I was wondering about the placement of the Sleep command in the source code, does it matter? In your linked example it is obviously required to appear before the IButton that evaluates the mouse click, because that is how zscripts are executed. Variables defined after an IButton may not be in scope when the button is pressed; the ZScript needs to be fully loaded before every top level ZScript command is evaluated and ZScripts are reloaded each time they come into focus.

I think I know the answer but the Sleep command is unique in regards to interaction with the user so I was wondering if there are any special circumstances?

I have to admit TVeyes, your post went slightly over my head, but it’ll start to sink in at some point!

Interesting, I had to modify your code a bit in order to get to it work for me.

On that note… even the ZFileUtils examples in the documentation didn’t work for me out of the box. I find that I usually need to change any or all of the following:

  1. change whitespace (usually omitting)
  2. explicitly call a variable:
  3. [LIST=1]
  4. usually [var, v_name]
  5. sometimes #v_name
  6. almost never v_name (except for dll calls or memory blocks))


Does that sound crazy? I feel like a need to make a styleguide for syntax. It’s been awhile since I’ve been zscripting, and I’m starting to remember all the gotchas I ran into. I tend to get strange, unexpected results when I’m implicit with my variables.

Anyway… Here’s what I got working. I really like this method, because in theory I could have multiple branches (none, alt, ctrl, etc)


Well this keyboard status parameter is interesting. The IDs are different today, even within the same ZBrush session! :confused:

My ALT is no longer 1115, it seems to change (I saw 1024, 1037), and I’m not entirely sure when or why it changes. But it definitely is not consistent.

Marcus, what is this syntax that you used? I couldn’t seem to get it to run on my end:

1024 is the ASCII code for Alt, although as the keyboard status slider combines it with whatever was pressed beforehand you need to do a comparison using bitwise AND - the result of (KeyOnMouseDown)&1024) will be 1024 if keyOnMouseDown contains 1024.

However, I’ve had very mixed results testing the code with 4R7. It’s fine when first loaded but if installed as a plugin it will often fail on reload, needing two presses to register the Alt key. This makes it effectively useless, I’m afraid. There may be a way that I’m missing but if the code as it is is already giving you problems I think you’d save yourself some hair-pulling if you abandoned it. Sleep used to be fine for buttons in the zscript window where they simply disappeared when they were unloaded but it gets decidely tricky for plugins. (Mark, I really don’t have anything more useful to say about it.)

As for your syntax problems, I don’t know offhand what ZBrush thinks of underscores in variable names. I don’t use them (or any special characters/white space) in variables but use them the whole time in memory block names.

I am sorry highbred3d ( and Marcus ), I am not sure my post makes much sense to me either (it was late).

I was certain that assigning a variable a value after an interface item was pressed would not be reflected if the zscript was not in focus. I am at least pretty sure that used to be the case. If you consider the following you may or may not expect myValue to be 22 if you press the button while the ZScript is out of focus:

[ISubPalette, “ZPlugin:ZScript Focus”]

[VarSet, someVariable, 22]

[IButton, “ZPlugin:ZScript Focus:Become the Focus”, “POPUP INFO”,[Note, [StrMerge, "someVariable = ", someVariable]]
, 0, 1, , , .4]

[VarSet, someVariable, 44]

Something might have changed in how ZBrush loads and interprets zscripts. The more likely explanation is I had a gigantic curry brain fart while replying earlier. In any case ZBrush seems to load and parse the entire ZScript each time it comes into focus. Sorry for the confusion :slight_smile:

As for variable naming I have always used the Lower Camel Case naming convention and only in rare instances have I needed to reference the variable using the [Var, …] command. For memory block naming you should obfuscate as much as you feel comfortable with as it will always work and you prevent other ZScript authors from messing with your memory blocks.

oh wow, that is super strange! :confused:

I’m sure it wasn’t your explanation Mark, it was most likely my level of comprehension that caused the mis-understanding :wink:

That is a very interesting example though. I’m trying my best to minimize global variables and use routines with local variables, hopefully I don’t run into this much.

I also just ran into an issue where the _ was indeed causing issues for me. I think it’s time to convert to Camel Case, even though I don’t like it!

In my little example below, I ran into an issue where I was referencing “number_length”, BUT, the value of “number” was being returned. I haven’t tested ALL configurations, but switching to CamelCase DID fix this particular issue and resulted in the intended value being returned.

[RoutineDef, BuildSequenceToken,
[VarSet, number_length, [StrLength, [StrMerge, #number,""]]]
[Note, [StrMerge, "Length: ",#number_length]]

, number

wow. I’ve started switching my convention to camel case, and threw caution to the wind (I removed all my [Var] and #). Everything is SO much more stable. That’s incredible. I wish I knew this along time ago. Although I still like using # with my syntax highlighter so that I can see important variable references.


A variation on your code:

[ISubPalette, “ZPlugin:ZScript Focus”]

[VarSet, someVariable, 22]

[Note, [StrMerge, "someVariable = ", someVariable]]

[IButton, “ZPlugin:ZScript Focus:Become the Focus”, “POPUP INFO”,
[Note, [StrMerge, "someVariable = ", someVariable]]
, 0, 1, , , .4]

[VarSet, someVariable, 44]

Good timing Marcus, I just started re-factoring a lot of my code to follow this format. I actually just started another thread on the broader topic of UI states and variable persistence. I’m starting to create A LOT of memory blocks. It seems to be working, but I’m not sure if there better way.

Your snippet below raises an interesting question.

  1. You are using MVarDef instead of Mem, Create / Write / Read. Are there any advantages / differences other than it being less code?

I think I see. I went back over the docs and played around a bit. MVars are arrays, you still need to assign them to variables to use them, and they are compatible with at least some of the memory block commands.

I like them.

MVarGet, -Set and -Def are simply convenience commands if all you want to store are floats. You get the same functionality when using MemRead, -Write and -Create except you have to calculate the offset when reading/writing and the initial size.

I believe VarSet and VarDef always store numerical values as floats so there is no loss of precision when storing the value using MVarSet.

Yes, if you want numerical variables that persist throughout a ZBrush session then MVarDef etc. make it reasonably easy. As TVeyes says, the values are stored as floats (the memory block size will be 4 bytes multiplied by the number of variables) but access is simply by index, starting at 0.