ZBrushCentral

How to distinguish keydown from keyup in same Sleep command!!!????

Hi there

Am having much trouble here

Trying to distuinguish key down from key up from user of particular key (so that I execute some commands when keydown as loop and others as soon as key up) but it aint working!

I have this format in Sleep command

[Sleep, 0.001,
blah blah

if sleepresult=16 , blah blah

if sleepresult = 32, blah

[SleepAgain]

, 16 + 32 (codes for key up and keydown), SleepResult]

I wanna apply this for particular keyboard key. Problem is , sleep result is ALWAYS 16! (keydown) I tried a new sleep command for separating but doesnt work, ZScript doesnt allow 2 sleep commands in a row

Would appreciate advice
Cheers!

And one more thing

Is it just me or is the timer event not working in Sleep for repetitive timed actions!? Sleep can only ever be woken with the other discrete events it seems, why is this so, and how do I approach time based events / loops?

Cheers!

I don’t think that this will work. The problem is that the keydown will always occur first, so that that is always the wake up event. Holding down a key is read as a series of keypresses.

You can get it to work if you use two different keys, and one is a modifier key:


[Sleep, 0.001,
[If,(SleepResult&16 == 16),[Note,keydown,,1]]
[If,(SleepResult&128 == 128),[Note,Modkeyup,,1]]
[SleepAgain]
,16+ 128, SleepResult]

I don’t remember the default ‘timer’ event ever working. (It may have done with version 1.5 but that was before my time.) :slight_smile:

You can use [ZBrushInfo,2] to get the runtime and create a timer that way. I used the idea in a script I wrote ages ago here:
http://www.zbrushcentral.com/showthread.php?t=23620

HTH,

Well there is a way you can get the keyup to register but is still doesn’t do you any good because of the repeating keypresses effect. Also the script has to be reloaded to force ZBrush to recognize the new sleep event:


[MVarDef,timer_mem,1,16]
[Sleep, 0.001,
[If,(SleepResult&16 == 16),[Note,keyDown,,1][MVarSet,timer_mem,0,32][IPress,zscript:reload]]
[If,(SleepResult&32 == 32),[Note,keyUp,,1][MVarSet,timer_mem,0,16][IPress,zscript:reload]]
[SleepAgain]
,[MVarGet,timer_mem,0], SleepResult]

I think I have lost more hair through the Sleep command than any other zscript command. :wink:

Lol this can’t be more true!! Same for me!

Thank you Marcus, much appreciated, you’re always there for us! =)

Finally, one more small question,

is there a way in which to make a Loop based on a counter rather than a fixed number. Im trying to simulate a while loop where the counter doesn’t always go up, like while counter

for instance normally we have [Loop, n, whereas I want something like [while n < m do blah blah] etc, where n doesnt always increase by 1 in each iteration, or for instance it depends on time etc.

My work around for now was to do, [Loop, 100000, …] a hug number, and then exit loop at the right time, but isn’t a goodlooking solution

Shame about timer, so basically u can’t simulate events over time, e.g. every 0.1 seconds till an overall timer is complete, without events such as mouseclick etc in betrween

Cheers!

The only way to simulate a while loop is to do as you’ve done:


[Loop,10000,
//do stuff
  [If,(exit condition is met),
    [LoopExit]
  ]
]

This might not be quite as tidy as an actual while loop but it works fine - I use it all the time in multi-selection dialog boxes.

thanks for the clarification

Finally I was wondering why the IModSet doesn’t work through ZScript for Layers, i.e. I want to set through ZScript a layer onto Record mode when it isn’t but it aint working. Is there a way?

Yeah, I’ve not got the IModSet to work either. Layers are problematic, more so in ZB 4 because there’s no certain way of selecting the right layer (at least, not that I’ve found - have you??).

This code will work if the layers have different names, or there is only one, but will select the top layer when there are several layers with the same name:


[IButton,TurnOnRecord,,
	[VarSet,layerPath,[StrMerge,"Tool:Layers:",[IGetTitle,"Tool:Layers:Layer Intensity"]]]
	//set Intensity to 1 for recording
	[ISet,Tool:Layers:Layer Intensity,1]
	//turn on Layer recording if necessary
	[VarSet,wid,[IWidth,layerPath]]	
	[If,([IModGet,layerPath]&1) != 1,				
		[IClick,layerPath,wid-28,12]//turn on recording
	]
]

Hey thanks for that.

I struggled with this point for a short while but indeed there is a way to select the desired layer, and I use this method, otherwise ZAnimator keyframed claymation part would be impossible.

You see I ID each layer based it’s location on the scrollbar when it’s oon the top of the layer list. To select that layer, I move the scrollbar to a position (always unique for each layer) where the layer in question is at the top (if they all have same name coz they are generated through zscript etc) then it automatically selects top one, or u select it and it takes top by default.


  [VarSet, LayerNumbers, [Igetsecondary, Tool:Layers:Layers ScrollBar]+1]] //number of layers, based on scrollbar value
  
  // blah blah code to select top, through ISet or IPress etc given all layers have same name
  
 //then to scroll down to next layer
  
 [ISet, Tool:Layers:Layers ScrollBar, 0, [Igetsecondary, Tool:Layers:Layers ScrollBar]-1]
  
 //this scrolls layer scrollbar down 1 notch so that you get second 
 layer at top to select that. You can keep scrolling down to 0 etc based on layer you want to select.
  

:wink:

Cheers!

Also, how can you distinguish between clicking on the canvas empty space and between clicking on a 3d model in edit mode on the canvas, is there a way?

Cheers

Sorry for asking too many questions =) it’s just faster than losing countless hours figuring things out :stuck_out_tongue: I would have taken ages to think of the recird mode thing for instance, thx for that

And I hope this should be last question but how do you simulate button presses with modifier key down through ZScript

For instance simulate press ‘Preview’ button press of Adaptive Skin but with Shift key down ? It doesnt work as simply [IPress…]

Thx in advance

Layers:
I didn’t put it well. What I meant was how to identify the Layer in ZScript so you can do things to it, rather than selecting the layer. Selecting the layer is not difficult, as you have shown. The problems start when you want to refer to the selected layer. The only way I have found is by using the title of the Intensity slider but this doesn’t distinguish between layers of the same name. So if you want to set record on for the second layer but the first layer has the same name my code will turn on record for that.

In earlier versions of ZBrush the Layer had a label ‘3D Layer 0’ or whatever that was independent of the name. But that doesn’t appear to be the case with ZBrush 4. :frowning:

Clicking on a Model:
This is not simple. There’s no absolutely fail-safe way that I know of. I’ve attached a script which gives a fairly good method but you need to be aware of a few things. It uses PixolPick to sample the Z depth at various points on the canvas. If the depth is different from the background then there’s something there. Problem is it could be a different subtool or some 2.5D painting. See the zscript comments for suggestions.

Using a keypress:
You can use [IKeyPress,SHIFT,[IPress,Tool:Adaptive Skin:Preview]]. For the other modifier keys you can put in CTRL or ALT. You can also use the ASCII codes, 256 , 512 & 1024. Other keys can be used. For example, [IKeyPress,13, wrapped around some commands can be useful for avoiding pop-up warnings that can be dispelled by pressing Enter.

HTH,

Thanks for the response!

That should be all as far as questions for now =) Sorry for all that hassle

In earlier versions of ZBrush the Layer had a label ‘3D Layer 0’ or whatever that was independent of the name. But that doesn’t appear to be the case with ZBrush 4. :frowning:

Yes that’s true, regardless of layer name it had proper indexing, it’s really annoying how it works now, i.e. the only way to set record mode for layer 2 rather than layer 1 (having same name) is to do what I mentioned, scroll down till layer 2 is at the top of the list. But yes I see what you mean, if you want to set layer selected by the user, there’s no way to make sure it’s that particular layer to set at the top or index it.

Really Thanks tho for all your help.

That should be all I think =)

Ah, thanks for reiterating that. I had rather assumed the scrollbar wouldn’t move when there were < 8 layers. So we do have something that will work. That is good.

Really Thanks tho for all your help.
That should be all I think =)

No problem. :slight_smile:

Heh, I take that back for 2 mins :rolleyes:

A question.
Say you have array variables like ArrayList_A(100) and ArrayList_B(100)

They’re both very similar arrays in nature.

I have a routine that selects either one of the 2 arrays based on certain conditions.

Is there a way to reference the selected array and then use the one reference variable throughout the rest of the routine or do I have to make many conditionals each time to choose whether to use ArrayList_A or ArrayList_B ??

Basically I want to choose which array to choose at beginning of routine with conditional.

like : “selectedArray = ArrayList_A” for instance, referencing it / pointer style or whatever, then continue the routine using ‘selectedArray’ variable only, how do you go about this? Or do I have use conditional for every use of either array making double code??

Questions, questions… :rolleyes:

Just pass the array as the arg for the routine. Then it should work OK:


[VarDef,listA(5),""]
[VarDef,listB(5),""]

[RoutineDef,ListGroceries,
	[Loop,5,
		[Note,[Var,list(n)],,1]
	,n]
,list]


[IButton,"List Fruit",,
	[VarSet,listA(0),"apples"]
	[VarSet,listA(1),"bananas"]
	[VarSet,listA(2),"peaches"]
	[VarSet,listA(3),"oranges"]
	[VarSet,listA(4),"lemons"]
[RoutineCall,ListGroceries,listA]
]

[IButton,"List Vegetables",,
	[VarSet,listB(0),"carrots"]
	[VarSet,listB(1),"cabbage"]
	[VarSet,listB(2),"tomatoes"]
	[VarSet,listB(3),"potatoes"]
	[VarSet,listB(4),"peas"]
[RoutineCall,ListGroceries,listB]
]

You could also have arrays of different lengths by having a second arg for the loop number:


[VarDef,listA(5),""]
[VarDef,listB(7),""]

[RoutineDef,ListGroceries,
	[Loop,no,
		[Note,[Var,list(n)],,1]
	,n]
,list,no]


[IButton,"List Fruit",,
	[VarSet,listA(0),"apples"]
	[VarSet,listA(1),"bananas"]
	[VarSet,listA(2),"peaches"]
	[VarSet,listA(3),"oranges"]
	[VarSet,listA(4),"lemons"]
[RoutineCall,ListGroceries,listA,5]
]

[IButton,"List Vegetables",,
	[VarSet,listB(0),"carrots"]
	[VarSet,listB(1),"cabbage"]
	[VarSet,listB(2),"tomatoes"]
	[VarSet,listB(3),"potatoes"]
	[VarSet,listB(4),"peas"]
	[VarSet,listB(5),"onions"]
	[VarSet,listB(6),"peppers"]	
[RoutineCall,ListGroceries,listB,7]
]