Nice thing about viz3 scripting is that you can create some parts of code to be reusable. This means, when you construct them the proper way – it is easy to adopt them to new projects later on. In my experiance most often used is a button script. So in this short tutorial I’m going to show you how you can create simple button script that you can use at any time later on in your interactive scenes.
Inside of a button
First lets talk for a while about button behavior. When creating a button there are few things we have to remember to put in our code. Here’s a list of them:
- type of button – there are two basic types of button: standard push button and two state button. The second one has two states (on/off) and should react independently on both of those states
- visual faces of button – basically there are following states of button visuals: normal, pressed, hover, disabled. I’ll talk about each of these in a moment.
- interaction with user – button should have at least click event defined. When user clicks it – this event should be triggered
When you take a look at a standart Windows button you may notice it has several faces. First one (normal) is displayed when button appears on a form and mouse cursor is somewhere else. When you move cursor over the button, it changes its face to hover. This face visuals are most often represented as if the button was lit (glow aroud the border) or something similar. When a button is pressed its face changes to pressed. Of course there’s also a disabled face to notify user that a button exists but is inactive at the moment.
We can of course implement all those faces in our viz button script, but lets think for a while. If our interactive scene is displayed on touchscreen we can exclude hover state from our list. Why? Because it will never occur. Touchscreens controls mouse cursor in a discreet way, so the cursor doesn’t move actually without being pressed. It jumps to certain position triggering press event at the same time. So basically it’s unlikely we ever get hover state. Disabled state, on the other hand, can be achieved by using Alpha plugin placed on our buttons group. When a button is disabled we just have to change its alpha to, lets say 50%, and we’re done.
In following button script I decided to implement only two faces: normal and pressed as predefined visuals and disabled face will be achieved by changing Alpha of whole button group. Here’s how my structure looks:
Implementation
First of all lets start with defining proper GUI for our script. I think user should have acces to following settings of our button:
- enabled property – user should be allowed to set if a button is enabled or not
- button type – this property will define how button reacts on interaction from user
- target script container – this will link script plugin placed on another container allowing to run specific subroutines on button events
- OnPressed action and parameter – this will define which action and with what parameter to run on our target script when button is pressed
- OnReleased action and parameter – this will define which action and with what parameter to run on our target script when button is released. This action should never be triggered when button is a one state button
- method to invoke – this will define which subroutine should be called in target script when one of the above events will occur
Having this in mind I registered these parameters in our button script. Whats more I added some behavior to simplify script usage. Basically when button type is set to one state button – OnReleased part is disabled.
It would also be nice if our script could take care of its underlying structure. To accomplish that I’ve written simple subroutine called CheckStructure(). It’s called when our script is initialized. What it does it checks if proper structure of groups exists and if not – creates it.
Now we need to implement our button’s behavior. I used OnLButtonDown and OnLButtonUp events for that but you may modify it to use 6DOF events in no time. I also encapsulated parts of code responsible for changing button states into subroutines. This way our code looks cleaner.
Usage
Using this button script is pretty simple. We drop our script on some group. The script is initialized automatically and it creates underlying button structure. Now we need to create the look of our button and set its parameters. That’s it. We have a working button in just a few moments. Here’s a simple example – Action Button.
It looks like this ( normal and pressed state):
You may have noticed we’ve forgotten about event handling script. Actually this script is very simple. Below I put a code template for it. All you need to do is to put your code insinde OnExecAction event. Have fun :-)
Sub OnInit()
End Sub
Sub OnInitParameters()
RegisterParameterString("current_param", "Parameter:", "", 30, 100, "")
RegisterParameterString("current_action", "Action:", "", 30, 100, "")
RegisterPushButton("run", " Run ", 0)
End Sub
Sub OnEnter()
End Sub
Sub OnExecAction(buttonId As Integer)
If (buttonId = 0) Then
' your code goes here
End If
End Sub
Full script code of our button script
Dim TargetContainer As Container
Dim IsTwoState As Boolean = False
Dim IsPressed As Boolean = False
Dim IsEnabled As Boolean = True
Dim Structure_Visuals As Container
Dim Structure_FaceNormal As Container
Dim Structure_FacePressed As Container
Sub OnInit()
' check If proper structure exists
' If not create one
CheckStructure()
IsPressed = False
End Sub
Sub OnEnter()
End Sub
Sub OnLeave()
End Sub
Sub OnInitParameters()
Dim btnTypes As Array[String]
btnTypes.Push("One state button")
btnTypes.Push("Two state button")
RegisterParameterBool("enabled", "Enabled", True)
RegisterRadioButton("button_type", "Button type", 0, btnTypes)
RegisterParameterContainer("target", "Target script container")
RegisterParameterString("param_on", "Parameter (OnPressed)", "", 30, 100, "")
RegisterParameterString("action_on", "Action (OnPressed)", "", 30, 100, "")
RegisterParameterString("param_off", "Parameter (OnReleased)", "", 30, 100, "")
RegisterParameterString("action_off", "Action (OnReleased)", "", 30, 100, "")
RegisterParameterString("method", "Invoke method", "run", 30, 100, "")
End Sub
Sub OnParameterChanged(parameterName As String)
If (parameterName = "button_type") Then
IsPressed = False
If (GetParameterInt("button_type") = 0) Then
IsTwoState = False
UpdateVisuals()
Else
IsTwoState = True
UpdateVisuals()
End If
ChangeGUIStatus(IsTwoState)
ElseIf (parameterName = "enabled") Then
SetEnabled(GetParameterBool("enabled"))
ElseIf (parameterName = "target") Then
TargetContainer = GetParameterContainer("target")
End If
End Sub
Sub ChangeGUIStatus(enable As Boolean)
If (enable) Then
SendGUIStatus("param_off", ENABLED)
SendGUIStatus("action_off", ENABLED)
Else
SendGUIStatus("param_off", DISABLED)
SendGUIStatus("action_off", DISABLED)
End If
End Sub
' Button has been pressed
Sub OnLButtonDown()
If (IsEnabled) Then
' update visuals
If (IsTwoState) Then
' ignore
Else
' update button face
IsPressed = True
UpdateVisuals()
End If
End If
End Sub
' Button has been released
Sub OnLButtonUp()
If (IsEnabled) Then
' update visuals
If (IsTwoState) Then
If (IsPressed) Then
IsPressed = False
Else
IsPressed = True
End If
Else
IsPressed = False
End If
' update button visuals
UpdateVisuals()
' invoke method on target container
RunMethod()
End If
End Sub
' ****************************************
' ********** STRUCTURE METHODS ***********
' ****************************************
Function CheckStructure() As Boolean
Dim normalFace As Container
Dim pressedFace As Container
Dim structureModified As Boolean = False
println "Checking button structure..."
' check if Visuals structure exists
Structure_Visuals = this.FindSubContainer("Visuals")
If (Structure_Visuals = Null) Then
println "Adding Visuals"
Structure_Visuals = this.AddContainer(TL_DOWN)
Structure_Visuals.Name = "Visuals"
structureModified = True
End If
' check if pressed visuals structure exists
Structure_FacePressed = Structure_Visuals.FindSubContainer("Face_Pressed")
If (Structure_FacePressed = Null) Then
println "Adding Visuals/Face_Pressed"
Structure_FacePressed = Structure_Visuals.AddContainer(TL_DOWN)
Structure_FacePressed.Name = "Face_Pressed"
structureModified = True
End If
' check if normal visuals structure exists
Structure_FaceNormal = Structure_Visuals.FindSubContainer("Face_Normal")
If (Structure_FaceNormal = Null) Then
println "Adding Visuals/Face_Normal"
Structure_FaceNormal = Structure_Visuals.AddContainer(TL_DOWN)
Structure_FaceNormal.Name = "Face_Normal"
structureModified = True
End If
' initialize normal button state
Structure_Visuals.ShowOneChildContainer(Structure_FaceNormal.GetLocalIndex())
Structure_FacePressed.Update()
' update scene tree
If (structureModified) Then
Scene.UpdateSceneTree()
println "Updating Scene Tree..."
End If
println "...done"
CheckStructure = True
End Function
Sub UpdateVisuals()
If (IsPressed) Then
Structure_Visuals.ShowOneChildContainer(Structure_FacePressed.GetLocalIndex())
Else
Structure_Visuals.ShowOneChildContainer(Structure_FaceNormal.GetLocalIndex())
End If
End Sub
' ****************************************
' ********** BEHAVIOUR METHODS ***********
' ****************************************
Sub SetEnabled(value As Boolean)
IsEnabled = value
If (IsEnabled) Then
this.Alpha.Value = 100
Else
this.Alpha.Value = 50
End If
End Sub
Sub ToggleOn()
If (IsTwoState) And (IsEnabled) Then
If (IsPressed = False) Then
IsPressed = True
UpdateVisuals()
RunMethod()
End If
End If
End Sub
Sub ToggleOff()
If (IsTwoState) And (IsEnabled) Then
If (IsPressed) Then
IsPressed = False
UpdateVisuals()
RunMethod()
End If
End If
End Sub
Sub RunMethod()
Dim cmd As String
Dim param As String
Dim method As String
If (IsTwoState) Then
If (IsPressed) Then
' on pressed method
param = GetParameterString("param_on")
method = GetParameterString("action_on")
Else
' on released method
param = GetParameterString("param_off")
method = GetParameterString("action_off")
End If
Else
' default one state button action (OnPressed)
param = GetParameterString("param_on")
method = GetParameterString("action_on")
End If
If (method <> "") And (TargetContainer <> Null) Then
TargetContainer.ScriptPluginInstance.SetParameterString("current_param", param)
TargetContainer.ScriptPluginInstance.SetParameterString("current_action", method)
TargetContainer.ScriptPluginInstance.PushButton(GetParameterString("method"))
End If
End Sub
GHTime Code(s): 9c223 498a9 31be2 



