F-Gen Tutorial 01 - Basic Scripting

F-Gen uses a scripting language called "Squirrel". This first tutorial will teach you first how to test a simple script file, then how to add some simple Falcon force effects. Finally, it will teach you how to attach a script file to a Windows application.


Table of Contents:

Part 1 - Running a Script

Part 2 - Detecting Buttons and Keyboard Keys

Part 3 - Scripting a Recoil Force

Part 4 - Scripting a Continuous Force

Part 5 - Scripting a Default Control Box

Part 6 - Creating Your Own Functions

Part 7 - Creating a Force Whose Direction You Can Change

Part 8 - Attaching Your Script to an Application

Part 9 - Creating a Tuning Slider

Part 10 - Tuning Keyboard Settings

Part 11 - Sending Keyboard Commands from a Script

Part 12 - Getting the Current Falcon Position

Part 13 - Accessing a Plugin

Part 14 - Creating a Plugin (requires some C++ knowledge)


Part 1 - Running a Script

This part of the tutorial will first teach you how to test a simple script, and then walk you through the basics of that script.

First, download the test script: tutorial script.

Unzip the file to a location of your choice (the Windows Desktop works fine). When you open the new "fgen_tutorial" directory, you will see two files. "fgen_tutorial.nut" is the script file. You will also see a shortcut to a tool called "fgsq.exe". This tool allows you to test a script.

Now, lets give the script a test run. Make sure your Falcon is plugged in, and run the F-Gen Manager (you don't actually need to run the Manager, but its a good way to make sure the Falcon is running properly).

Now, drag and drop the script file (fgen_tutorial.nut) onto the shortcut for fgsq.exe. You will likely see the Falcon light blink, and a popup console will appear, looking like this:

In general, the comments in red are messages from F-Gen, while most comments in white are comments from the script. Now hit "ENTER" on the keyboard to shutdown the script, which will now look like this:

Anytime you want to test your scripts, you can just drag and drop the script onto the shortcut to fgsq.exe.

Now its time to take a look at the script. Open "fgen_tutorial.nut" in your favorite text editor. Windows Notepad works fine (which is included with all versions of Windows... you can find it by clicking on the Desktop START button, bringing up the program list, and looking under "Accessories and System").

You should see five "functions" in the script, along with several "print" calls and some comments (anything after a "//" is a comment... something ignored by the script, but allowing you to add descriptions). These five "functions" are called by F-Gen at particular times when your script is in use.

function HapticsInitialize - this function is called exactly once, when the script is first loaded. It is called before any other function, and can be used to set up anything your script needs.

function HapticsActivated - this function is called whenever your script becomes active. Thus, it is called just after HapticsInitialize, as well as any time you switch to another window and then return to the application running the script (in this case fgsq.exe).

function HapticsThink - this function is called repeatedly when your script is active. It is inside this function that you will do most of your scripting.

function HapticsDeactivated - this function is called whenever the script stops being active (such as switching focus to a different window).

function HapticsShutdown - this function is called exactly once, when the script is shut down (this usually happens when the application running the script is closed).

Notice that inside several of the functions there are "print" calls, which match the text displayed in fgsq.exe. For example, in HapticsInitialize, there is a call that looks like "print("Initialize Script\n");" - this prints the words "Initialize Script" to the fgsq.exe console. The "\n" at the end of the text means add a new line at the end (the next print call will start on the next line). Also note the ";" at the very end of the print call. All individual script instructions need to end with a semicolon (this tells the script that the instruction is complete).

Now on to part 2 of the script... detecting buttons and keyboard keys in your script.


Part 2 - Detecting Buttons and Keyboard Keys

This part of the tutorial guides you through detecting Falcon button and keyboard keys, and using them to print messages to the console. To see what the finished script should look like once you are done with this part of the tutorial, download it here: fgen_tutorial_01b_btns.nut.

Now add the following to your HapticsThink function:

Now run your script in fgsq.exe. Once the script is active, start clicking the Falcon's main (logo) button. You should see a message every time you click down on the button, and another message every time you release the button.

This introduces a new scripting concept... the "if" and "if...else" script commands. The "if" command says that if the command after the "if" is true, then do the things in the brackets following. You can then add an "else" if needed, to say what to do if the command after the "if" was false.

Now add this into the HapticsThink function:

Now run the script, and click the Falcon left (triangle) button. As long as the button is down, you should see a steady stream of messages in the fgsq.exe console. Using these three commands (devicebuttonisdown, devicewasbuttonjustpressed, and devicewasbuttonjustreleased), you can check the status of any of the four Falcon buttons.

Time now to detect keyboard presses... add the following to the top of your script (before the HapticsInitialize function):

This creates a keyboard "listener" you can use to get information about the keyboard. Now add the following to your HapticsThink function:

This new script code first updates the keyboard listener (making sure the keyboard values are current), and then uses the commands isinputdown, wasinputjustpressed, and wasinputjustreleased to check keyboard keys. If you now run your script, you should see that if you hit the "1" key, you get a fgsq.exe console message every time the "1" key is pressed or released. If you hit the zero key, you should get a steady stream of messages as long as the zero key is down.

Now that you can detect buttons and the keyboard, its time to move on to the next part of the tutorial, where you will add your first Falcon force.


Part 3 - Scripting a Recoil Force

This part of the tutorial guides you through setting up and adding a simple recoil force to your script. To see what the final script should look like, download it here: fgen_tutorial_01c_recoil.nut.

To generate a Falcon force effect, you first have to do some setup. At the top of your script file (before the HapticsInitialize function) add the following:

This creates a list, or "stack", of empty Falcon effects, and then defines a type of effect, in this case an "envelope" effect. An envelope effect is an effect that follows a pattern of forces.

Now add this to your HapticsActivated function:

This set of four commands activates your "stack" of effects (don't worry for now about the details of what each of these commands does). Now add the following to your HapticsDeactivated function:

This set of four commands deactivates your effects stack.

We are now ready to define a simple recoil effect. Above the HapticsInitialize function, but after defining the effects stack and "envelope" effect type, add the following:

This creates an envelope type effect, and sets how it runs. The 1st line creates the effect, the next three lines define the direction and size of the force (in this case no sideways or vertical forces, but a force of 20 newtons backwards). The remaining three lines set how fast the effect ramps up, how long it holds at maximum, and how fast it then ramps down (in this case, ramp up over 30 milliseconds, and then no hold or ramp-down time).

One final step left. In your HapticsThink function, add "gSimpleRecoil.fire();" into the "if" command that checks if the Falcon LOGO button has just been pressed:

Now run the script in fgsq.exe. Every time you click the Falcon LOGO button you should feel a recoil force.


Part 4 - Scripting a Continuous Force

This part of the tutorial will first show you how to use keyboard keys to select between several several force effects, and then show you how to create a second effect that loops the recoil. To see what the final script should look like, download it here: fgen_tutorial_01d_looprecoil.nut.

To start, add the following somewhere at the top of your script (above the HapticsInitialize function);

This creates a "global" variable called gEffectType, that holds an initial value of 1. A global variable is a variable that retains its value permanently unless changed. Now modify the portion of the script that detects if the LOGO button was just pressed (and fires off the simple recoil) to look like this:

What this addition does is tell the script to only launch the simple recoil effect if the effect type is set to 1.

Next, we need to modify the keyboard checking so that keyboard keys will change gEffectType. Make the keyboard part of HapticsThink look like this:

Give the script a quick test... you will now notice that if you hit the "0" or "2" keyboard keys, the recoil when you hit the Falcon LOGO button stops occuring. If you then hit the "1" key, the recoil returns.

Now its time to add a second force effect... a looping recoil that will occur when gEffectType is set to 2 and you hold down the Falcon LOGO button. The way we are going to do this is to create some timing code that will allow us to repeatedly call the simple recoil. At the top of the script (above HapticsInitialize), add the following:

This creates a way to grab timing values (through gScriptTime), and adds a global variable (gLoopRecoilTimer) that holds the amount of time (in fractions of a second) until the next recoil. Next, at the top of the HapticsThink function, before you do anything else, add this:

This updates the script timing, and then creates a "local" variable called elapsedTime that holds the amount of time (in fractions of a second) since the last time HapticsThink was called. A local variable is a temporary variable inside a function, whose value gets erased once the function exits.

Finally, adjust the part of HapticsThink that checks if the Falcon TRIANGLE button is down to look like the following. Note that the first change is to have it now check for the Falcon LOGO button instead:

This addition checks if the LOGO button is being held down... if so, it subtracts the elapsed time from the gLoopRecoilTimer. If the timer is now zero or less, then we fire off a recoil effect and reset the timer for another tenth of a second wait.

Run the script in fgsq.exe, and now if you hit the "2" key on the keyboard and then hold down the Falcon LOGO button, you will get a repeating recoil until you let go of the button.


Part 5 - Scripting a Default Control Box

This part of the tutorial will show how to create a "Control Box". A Control Box is a special type of Falcon effect that adds mouse control to the script, as well as soft force walls to the left, right, top, and bottom of the Falcon movement space. If you move the Falcon within these walls, you control the mouse cursor directly. If you press into one of the walls, then the cursor is pushed in that direction. If you've played around with the F-Gen Manager and using the Falcon to control the mouse cursor in Windows, then you should already have an idea of how this works.

To see what the final script should look like, grab it here: fgen_tutorial_01e_controlbox.nut.

The first thing we are going to do is create a seperate effects stack for the control box. We could just use the current effects stack (which we are using for the recoils), but eventually we may want to be able to tune the control box seperately from other effects. Add the following to the top of your script:

Then, in the HapticsActivated function, add what's needed to activate the new control effects stack:

Next, add what's needed to deactivate the control effects stack in HapticsDeactivated:

One final step left... In HapticsInitialize you need to launch the control box as follows:

Once again, run your script in fgsq.exe... you should now be able to move the mouse cursor around the screen using the Falcon.


Part 6 - Creating Your Own Functions

This part of the tutorial will show you how to create and use your own functions. In the process, we will do a little clean up of your current script, by moving the activating and deactivating of effects stacks to a seperate function. To see what the final script will look like, download it here: fgen_tutorial_01f_functions.nut.

Just before the HapticsInitialize function, add the following:

This creates a (so far) empty function with two "parameters" or values that are passed in to the function. The first paramenter (deviceHandle) references the Falcon, and the second parameter (bConnect) will be either "true" or "false" depending on whether you want to activate or deactivate the effects stacks.

Now look at the script instructions you have in HapticsActivated and HapticsDeactivated. For each effects stacks (so far gEffectsStack and gControlBoxStack), there are four instructions used to activate and deactivate them... for example, to activate the gEffectsStack effects, you call the following four commands:

To deactivate the gEffectsStack effects, you would replace the call to "adddevice" with a call to "removedevice", and replace the call to "deviceconnectstack" with "devicedisconnectstack". Thus, your new function ConnectOrDisconnectStacks should end up looking like this:

Now, go to HapticsActivated, remove all the effects stacks instructions in the function, and replace them with a call to your new function:

Do the same in HapticsDeactivated, though changing the "true" to "false":

We have now greatly simplified the HapticsActivated and HapticsDeactivated functions, as well as providing a central location for dealing with effects stacks (the function ConnectOrDisconnectStacks). Note that you can create your own functions to do anything you might need.


Part 7 - Creating a Force Whose Direction You Can Change

This part of the tutorial will teach you how to create a "constant" force, whose force vector you can change based on keyboard presses. To see the final script for this part, download it here: fgen_tutorial_01g_constForce.nut

First we will create a new, third effects stack for this new effect. At the top of your script, add the following:

Next, add "gMovementStack" to ConnectOrDisconnectStacks. By now it should be pretty obvious how to do this, but if you have trouble, take a look at the final script for this tutorial part.

Now create the effect parameters for the movement effect, as well as a variable to hold the effect. Just after defining "gMovementStack" and "gConstantEffectID", add the following:

Next we need to launch the movement force. In HapticsActivated, add this:

Then in HapticsDeactivated, deactivate the force:

Now lets give the movement force a quick test. Add the following to HapticsThink:

Run the script... if you now hold down the "A" key on the keyboard, you should feel a force to the left. If you let go of the "A" key, the force goes away. From here its easy to expand this code to handle keyboard keys that set the force in any direction:

When you now run the script, you can use the "A" and "D" keys to push left and right, the "W" and "S" keys to push up and down, and the "E" and "Z" keys to push forward or back. You can also do combinations... hold both "A" and "W" down at the same time to push both left and up.


Part 8 - Attaching Your Script to an Application

Now it is time to attach the script you have now built to a Windows application.

First, bring up the F-Gen Manager, and click on the "NEW" button at the bottom:

This will bring up a "create a new profile" window:

Now you just need to fill out the profile. First give it a name (I picked "FGen_Tutorial"). Next, click the "Application Profile" button, and then browse for the application executable of your choice (I picked Windows Notepad, which you should be able to find in "C:\WINDOWS\System32\notepad.exe"). Finally, go to the bottom of the ProfileCreator, and browse for your script file (which, for me, was in Desktop/tutorial_script/fgen_tutorial.nut). Save the profile.

Now, if you have the F-Gen Manager running, everytime you launch the application you chose (Notepad, for me), the Falcon will restart and run using your script. You may need to exit out of the F-Gen Manager and restart it before F-Gen recognizes your new profile, however.


Part 9 - Creating a Tuning Slider

Now that you have your script attached to an application through the F-Gen Manager, you can create adjustable settings that you can access through the F-Gen Mamager "Forces" tab. To start, we will create a slider for adjusting the strength of the recoil forces. To see the final script for this part, download it here: fgen_tutorial_01i_slider.nut

First, at the very top of your script (before creating the effects stacks), add the following:

This creates the slider, with a range between 0.0 and 2.0, set at a default setting of 1.0. The current value of the slider is loaded into the variable "gRecoilTuneScale" when the script is run. To then use this value to adjust the recoil forces, change the line of the script that sets up the recoil effects stack... replace the "1.0" with this variable, as follows:

Now, when you access the F-Gen Manager profile that uses your script, and then click on the "Forces" tab, you should see the slider.

You should now be able to create a second slider for the movement effects stack (see the script for this tutorial part if you have any trouble).


Part 10 - Tuning Keyboard Settings

This part of the tuturial will show you how to set up tunable keyboard settings, so you can change the keys used to do actions in your script, using the F-Gen Manager. To see the final script for this part, download it here: fgen_tutorial_01j_tunekeys.nut

We are going to create settings to change the keys used for selecting what type of recoil (currently, your script uses "0", "1" and "2"). At the top of your script, add the following:

This creates a list of three tunable key items, and then places them in a drop-down list you can access in the F-Gen Manager "Forces" tab.

Next, we need to load the current values for each key setting into variables we can access in the script:

Finally, replace the keyboard keys you use to select the recoil type in HapticsThink with these new variables:

Now if you access a F-Gen Manager profile that uses this script and then click on the "Forces" tab, you will see a drop-down box that lets you select each keyboard action and change which key is used for that action.


Part 11 - Sending Keyboard Commands from a Script

If you need to send keyboard keys from a script (especially complex keyboard commands you can't set up in the F-Gen Manager), you can do it in your script. This chapter will show you how to use a Falcon button to send a multi-key command. Download the tutorial script here: fgen_tutorial_02_sendkeys.nut

This test script will show you how to send "CTRL + Y" from your script.

The first thing for emulating keyboard keys is to set up global variables for each key you want to use. At the top of your script, create the following:

The "inputsender" command creates the key setup for each key you want to control (in this case, the left-ctrl key, and the Y key).

You can create a script function that will send the "Ctrl + Y" command"... this function will press both keyboard keys, then release both keys.

Call this function anytime you need to trigger a "Ctrl + Y" keyboard command... for example, to hit this keyboard combo anytime you tap the top Falcon button, you might add the following to your HapticsThink function:


Part 12 - Getting the Current Falcon Position

This will be a very short chapter. If you ever need to get the current position of the Falcon handle, here is how to do it. Download the tutorial script here: fgen_tutorial_02_FalconPos.nut

To grab the position of the Falcon handle at any time, you simply need to use the command "deviceaxis". You need to pass in the deviceHandle of the Falcon (usually passed in by the core script functions like HapticsThink), and the number of the axis. For example:


Part 13 - Accessing a Plugin

You can access various plugins in your scripts. These plugins add features to F-Gen. This tutorial will show you how to access a simple plugin and use it. Download the plugin and script for this tutorial here: fgen_tutorial_02_plugin.zip

Inside the ZIP file, you will find two files... the squirrel script for this tutorial, and a DLL. This DLL file is the plugin. Copy the DLL to your "Program Files/Novint/F-Gen/plugins" directory.

This particular test plugin adds the ability to send debugging information to a log file, adding the following new functions to F-Gen:

It also adds one other test function (testAddInts), which simply adds two integers together returns the result (I know you can do this directly in the scripts, but its just an example of how to get a return value from a plugin function).

At the top of the script, tell your script that you want to use this plugin, by adding:

Note that "debugLog_open()" is called in the HapticsActivated function, and that "debugLog_close()" is called in the HapticsDeactivated function.

The rest of the tutorial script should be fairly obvious... at the top of HapticsThink I increment a frame counter (using the plugin function), and then if you tap the Falcon LOGO button, the script prints out the current frame count and the Falcon handle position to the log file.

The log file can then be found in "Program Files/Novint/F-Gen", called "testScriptLOG.txt".


Part 14 - Creating a Plugin (requires some C++ knowledge)

You can create your own plugins for F-Gen, though it requires some knowledge of C++ programming. You will need a copy of Microsoft Visual Studio C++ and it helps if you have an idea what a DLL, or Dynamically Loaded Library is.

You can find the Visual Studio project for the "SQTestDLL.dll" plugin used in the previous tutorial part (Part 13) here: fgen_tutorial_pluginDLL.zip

Open the project (the SQTestDLL.vcproj file), which should launch Visual Studio. First look under "Header Files" and open "SQTestDLL.h". Note that each of the functions the plugin creates is defined using "SQ_GLOBAL_METHOD". The first parameter is the name of the function. The second parameter is an integer defining how many inputs the function has, and then the remaining parameters (if any) define those inputs.

Now open "SQTestDLL.cpp" under "Source Files". You will see each of the functions defined in SQTestDLL.h. Note that each one has an "SQ_" in front of the function name, and each function returns "SQRESULT". Also notice that the first input to each function is a "HSQUIRREVM v"... this allows access to the squirrel script when returning values. Finally, notice each function has an associated "SQ_BIND_GLOBAL_METHOD" call.

If a function does not return a value (such as the debugLog_open function), it just returns "SQ_OK".

If a function does return a value (such as the testAddInts function), then you must first push the return result on the script stack (using something like "sq_pushinteger" or "sq_pushfloat"), and then return the number of returned values.

You can get more information about plugins, including things like exporting classes to a script, in the F-Gen SDK Examples directory.