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:

Button structure

Button structure

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.

Button Script GUI

Button Script GUI

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.

Action Button example structure

Action Button example structure

It looks like this ( normal and pressed state):

Action Button example - normal and pressed

Action Button example - normal and pressed

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