I wish we had a few more interactive UI methods added to RhinoScript. Currently the few methods are working really well(Rhino.GetCursor, PointPick, WindowPick) but adding a few more, if at all possible, would open up a lot more possibilities.
How about having mouse buttons state check: (LMBPressed, RMBPressed, MMBPressed - all returning True/False)
Or KeyPressed - returning the key(s) or Null if nothing pressed ?
This is more of a general request that aims at expanding what can be done interactively with RhinoScript with a bit more extra effort (which I hope is adding these methods).
I do realize RS is unlikely to get a full-fledge UI and events capability and for that an advanced Python scripting or real programming needs to be involved. But it is actually quite amazing how much can be done in basic RhinoScirpt / Python only so far. Currently some level of interactivity can be achieved by the methods I mentioned (GetCursorPos, PointPick, OnCancel / Esc as the only ‘key’ we can read) used in the loops. With being able to read mouse click state it can take it to the whole next level. I was actually looking into making some more complex UI for a script that would involve drawing TextDots and lines in the screen space or being able to interact/get out of the endless loops by reading the mouse or keyboard input. So far I can get some of that by reading the mouse position or Esc key pressed, but why not LMB, RMB or other keys ?
Please take a look at the attached sample script - it has no purpose other than demonstrating a concept of interactivity with RS. While in the loop, we can change object colors (see the menu once you get your mouse to the top of left of the viewport) or adding points on object dynamically with mouse over. All that while rotating the object.
Here is a somewhat ‘skippy’ capture of how it works: http://screencast.com/t/bDwJZ9Fwm
Does it make sense? Are these doable and possible additions to the current set of RS methods ?
I’ve added a new GetAsyncKeyState method to RhinoScript that just calls the equivalent Windows API function. This will be available in the next WIP.
For example:
Const VK_SHIFT = &h10
Dim nShift
nShift = Rhino.GetAsyncKeyState(VK_SHIFT)
If nShift And &h8000 Then
Rhino.Print "Shift key is down"
Else
Rhino.Print "Shift key is not down"
End If
Ha, just kidding, but it actually may be a good test of the new functionality and the possibilities it should open up.
I will definitely share some results! Probably will not be as good as @Holo’s Call of Duty for Rhino3D…
Yeah, online massive Rhino Sandbox Modelling and Virtual architectural tour mode with voice chat would be a dream.
These days I use Unity quite much for 1:1 evaluation of landscapes and architecture and being able to be “on the ground” at the correct eye level is by the most important thing for immersion.
OT: I used to be a Caligari TrueSpace user and those guys were pioneers on all sorts of 3D modeling tools, they had virtual vidgets, full Direct X shader support with shadows, reflection, refraction and sub surface scattering already back in 2008 and also had an online sandbox modelling tool up and running before anybody else even knew what the cloud was going to be nicknamed. Too bad Microsoft bought them up and terminated the project just after purchase.
Just ran a quick test of the new method with the keyboard – all works quite nice (detecting multiple keys pressed at once and all…). The only ‘issue’ I ran into so far is, I want to get rid of printing what is pressed into command line.
Tried sending backspace after each key press but it does not work.
Do you have any suggestions of how that can be handled cleaner?
Here is what I am was trying:
Call Main()
Sub Main()
Const W = &h57
Const S = &h53
Const D = &h44
Const A = &h41
Dim blnW,blnS,blnD,blnA
Dim i,idSphere
idSphere = Rhino.AddSphere(array(0, 0, 0), 10)
Rhino.Prompt("Test...")
For i=0 To 100000
blnW = Rhino.GetAsyncKeyState(W)
blnS = Rhino.GetAsyncKeyState(S)
blnD = Rhino.GetAsyncKeyState(D)
blnA = Rhino.GetAsyncKeyState(A)
Rhino.EnableRedraw False
If blnW Then
Call Rhino.MoveObject(idSphere, array(0, 0, 0), array(0, 0, 5))
Call Rhino.SendKeystrokes(Chr(08), False)
End If
If blnS Then
Call Rhino.MoveObject(idSphere, array(0, 0, 0), array(0, 0, -5))
Call Rhino.SendKeystrokes(Chr(08), False)
End If
If blnD Then
Call Rhino.MoveObject(idSphere, array(0, 0, 0), array(0, 5, 0))
Call Rhino.SendKeystrokes(Chr(08), False)
End If
If blnA Then
Call Rhino.MoveObject(idSphere, array(0, 0, 0), array(0, -5, 0))
Call Rhino.SendKeystrokes(Chr(08), False)
End If
Rhino.EnableRedraw True
Next
End Sub
Here is another test (attached) - with temp dirty workaround with clearing the command history after each key press, plus a test of LMB functionality… (click on object selects, not on object creates, plus moving with A W S D).
GetAsyncKeyState simply determines whether a key is up or down at the time the function is called. It won’t prevent a key press event from being queued up (in Rhino’s message queue). So, I don’t have a good solution for what you’ve described (keystrokes appearing on Rhino’s command line).
I see. Would it be possible to have an additional argument in the method (boolean) that if the key is pressed to supress that key’s input to Rhino? It would help to avoid the command line or RMB gymnastics.
No. Again GetAsyncKeyState doesn’t ‘play’ in Rhino’s message queue.
It might be possible to hook the keyboard and intercept keyboard input before Rhino gets it. You’d have to specify what keys you wanted to listen for. I’ll give it some thought.
I figured this may be not that simple, but actually specifying what keys/mouse buttons I am listening for was the original wish. We got much more with the GetAsyncKeyState method and it is already making a lot more possible, but to make it clean and fully useful, overriding the Rhino keyboard/mouse input (as a toggle option) would be most desirable.
In Polish we have a saying ‘to lick a cake thru the glass’ and this is how getting keys/mouse event feels like now with the GetAsyncKeyState method.
I also like the idea of GetChar method that @stevebaer and @Holo mentioned, if it acts exacly like GetString (with command options) but gets a key/mouse press…
@Jarek, @Holo, the next Rhino WIP will contain a new Rhino.GetChar RhinoScript method which pauses for user input of a keyboard character. The pressed key shouldn’t echo to the command line. I’ve attached a sample of its usage (below).