Skip to content

Introduction to Squirrel Programming

liquid8d edited this page Jun 14, 2015 · 15 revisions

#About Squirrel Squirrel is the scripting language built into Attract-Mode which allows users to extend the functionality of the frontend.

You can view some of the scripts used in the following folders on your Attract-Mode installation:

modules/
plugins/
layouts/

Some are contained in folders, but each of them use text files with the .nut extension which uses the Squirrel language format.

#Getting Started It's helpful to have some basic programming understanding, but isn't required. Since Squirrel is a programming language it has its own syntax in regards to variables, functions, objects and classes. We'll try to keep things simple here, but you can learn more about Squirrel at these links:

Squirrel 3.0 Reference Manual
Squirrel 3.0 Standard Library Manual

##Squirrel Syntax ###Variables A variable is a way to store a value or a reference to something in your script.

    local myInteger = 100;
    ::myString = "This is global";

A variable can be an integer (negative or positive number), a float (decimal number) a string (text), a boolean (true/false), arrays and tables (multiple values), functions (mini-script) or an instance to a class (a reference to an object).

Variable names should be short but understandable - usually with a lowercase first letter and uppercase for additional words or use all lowercase with an underscore (_) to separate words. There can be no spaces or most special characters.

Variables can be stored local to the script, or stored in the Squirrel root table using :: in front of the variable name to be access globally from any script.

Note that each variable line ends with a semi-colon as with most programming languages.

###Functions A function is a way to separate a block of code that performs a certain function. You might make a 'debug' function that prints some text:

function debug( text )
{
    print( "Debug: " + text + "\n" );
    return true;
}

Functions can then be called anywhere else in the script, meaning you don't have to keep re-writing the code.

Functions can include variables that are passed to it allowing it to perform calculations. If desired, you can return a value from your function which can then be assigned to a variable.

A function can be on a single line, but is sometimes better to span across multiple lines for readability. A function does not have to have the semi-colon at the end of it.

Squirrel provides many useful built-in functions, for example the print( str ) function used above.

###Tables To store multiple values within a single variable, you can use what Squirrel calls a table.

local myTable = {
  firstValue: "This is the first value",
  secondValue: 100
}

A table begins with the opening curly brace and ends with the closing curly brace. Each item you include in the table will be a variable name, followed by a colon, then the variables value. If you include more than one variable, each one should be separated with a comma.

A table can be on a single line, but is sometimes better to span across multiple lines for readability. A table does not have to have the semi-colon at the end of it.

##Frontend Binding To interact with Attract-Mode from a Squirrel script, an fe table is made accessible to you in any .nut file you create. A table contains variables and functions that will be useful to you. For example, if you want to know the directory your script or layout is running from:

print( fe.script_dir + "\n" );

A full list of the functions and variables that can be found using fe can be seen at: Layout and Plugin Programming Reference

We will use the fe table as we go on, so you can reference that if you want to know more about a certain variable or function we use.

#Layouts Now that we understand a bit about Squirrel, we can start creating layouts. In a nutshell, a layout controls what objects are displayed on the screen and where, but they can do much more.

##First Steps Create a folder
Layouts are stored in your Attract-Mode folder in the layouts/ folder. All layouts should be in their own folder - the only exception is the screensaver.nut which is the layout file for the frontend screensaver.

Create a layout.nut file
For a layout to work, you must create a file named layout.nut in your layout folder. This is where we will write a script to describe our layout. Open your layout.nut file in any text editor. Any will do, but a list of recommended editors can be found here.

First, we want to make sure that our layout will work correctly regardless of someones resolution, so the first thing we will do is tell fe we want the layout to be a specific resolution.

In your layout.nut file add the following lines:

fe.layout.width = 640;
fe.layout.height = 480;

While you don't have to specify the layout width/height - it would default to your screen resolution which may be different for each user. This ensures that Attract-Mode will scale your layout for other users to fit the resolution that you designed the layout for.

The next thing we want to do is add some objects to our layout. At least one object must be added for a layout to be shown.

Using the fe table described above, Attract-Mode provides function to do exactly that:

fe.add_text( str, x, y, w, h );
fe.add_artwork( art, x, y, w, h );
fe.add_listbox( x, y, w, h);
fe.add_image( img, x, y, w, h );

We'll walk through adding each of these to your layout one by one.

##Text We'll start by adding a single text object that contains the game title. Add the following line to your layout.nut file:

local title = fe.add_text( "[Title]", 0, 10, fe.layout.width, 35 );

Here we running the fe.add_text function telling it the text we want, the x, y coordinates on the screen and the width, height of the text object. We assigned the result to the title variable. We used a special fe variable to set the width to the full width of our layout.

While we don't have to assign the functions result to a variable, this will allow us to access the text object further in our code.

Since we have the text object (title), we can now use the Attract-Mode functions and variables for a Text object. Add this line to your layout.nut:

title.set_rgb( 0, 255, 0 );

This will set the title text color to bright green ( 0 Red, 255 Green (max), 0 Blue)

Your layout.nut should now look like this:

fe.layout.width = 640;
fe.layout.height = 480;
local title = fe.add_text( "[Title]", 0, 10, fe.layout.width, 35 );
title.set_rgb( 0, 255, 0 );

Save your layout.nut file. Open Attract-Mode, hit TAB (for Settings), select your current Display and change the layout to the one you created (as named by the folder you created). Hit ESC to go back to your layout and you should see a single text line at the top-left of your screen. Using up and down this will change the current game.

A full list of what you can alter with a Text object can be found here.

That's it! You made your first layout. Just a text with the title isn't very fancy. Let's spruce it up.

##Artwork Attract-Mode makes displaying artwork easy by having the user specify their artwork folders. By default for Mame: the flyer, marquee, snap and wheel folders are supplied asking the user to tell it where the artwork for each is. More can be added, though!

Let's add the snap artwork to our layout. Add the following to your layout.nut:

local snap = fe.add_artwork( "snap", 338, 70, 287, 214 );

Notice we specified the "snap" artwork. We set it to some pretty specific sizes here - you'll see why later. Basically though, the snap x (338) is set a little past the center of the 640 width layout, and snap y (70) down a bit from the top (so it won't overlap with the title).

Your layout.nut should now look like this:

fe.layout.width = 640;
fe.layout.height = 480;
local title = fe.add_text( "[Title]", 0, 10, fe.layout.width, 35 );
title.set_rgb( 0, 255, 0 );
local snap = fe.add_artwork( "snap", 338, 70, 287, 214 );

Save your layout.nut and open Attract-Mode again. You should now see your snap or video of the selected game. If you don't, make sure you have the correct location for the snap artwork path in your Emulator configuration.

A full list of what you can alter with the Artwork object can be found here.

##Listbox A Listbox creates a simple list of games that can be navigated in our layout. . Add the following lines to your layout.nut:

local list = fe.add_listbox( 9, 75, 311, 385 );
list.rows = 20;
list.charsize = 16;

Again we have some specific sizes here. x is a little off the left side, y is a bit down from the top (not to overlap with the title), and the width and height makes it fit in the lower left side of the layout.

We are also setting some listbox variables - rows is how many games will be displayed in the list, and charsize is the font size of each text item.

Save your layout.nut file. It should now look like this:

fe.layout.width = 640;
fe.layout.height = 480;
local title = fe.add_text( "[Title]", 0, 10, fe.layout.width, 35 );
title.set_rgb( 0, 255, 0 );
local snap = fe.add_artwork( "snap", 338, 70, 287, 214 );
local list = fe.add_listbox( 0, 50, 300, 590 );
list.rows = 20;
list.charsize = 16;

A full list of what you can alter with the ListBox object can be found here.

##Image Artwork images are automatically found from the path provided by the user - but you can add any image to your layout.

We'll add a background image to the layout. BUT - we have to be careful. Objects in Attract-Mode are drawn in the order that you add them in your layout. This means if we add a background image AFTER our other objects, it will be drawn ON TOP. Since we don't want that - at least for now :) - we will add this line ABOVE all the other objects. Add these lines above your title object in your layout.nut:

local bg = fe.add_image( "bg.png", 0, 0, fe.layout.width, fe.layout.height );
bg.set_rgb( 0, 100, 230 );

This will now look for a 'bg.png' file in your layout folder. If it doesn't exist, the image won't show up. You can use this bg.png file I created just for this layout or you can add your own. You can change the filename if you want. But make sure to copy it into your layout folder.

Your layout.nut file should now look like:

fe.layout.width = 640;
fe.layout.height = 480;
local bg = fe.add_image( "bg.png", 0, 0, fe.layout.width, fe.layout.height );
bg.set_rgb( 0, 100, 230 );
local title = fe.add_text( "[Title]", 0, 10, fe.layout.width, 35 );
title.set_rgb( 0, 255, 0 );
local snap = fe.add_artwork( "snap", 338, 70, 287, 214 );
local list = fe.add_listbox( 9, 75, 311, 385 );
list.rows = 20;
list.charsize = 14;

Save your layout.nut file and run Attract-Mode again. Now you should see all your objects, with a background!

##Wrapup Now we have a pretty functional layout. Let's add a couple finishing touches:

If you used the bg.png provided here, you'll notice there is an open space for an image or text. Let's add another artwork at the end of your layout.nut file:

local marquee = fe.add_artwork( "marquee", 338, 303, 287, 75 );
marquee.preserve_aspect_ratio = true;

We'll also use a special variable called 'preserve_aspect_ratio' which makes the image fit in our specified size, but doesn't stretch it.

And we'll add some text information right below the marquee:

fe.add_text("[DisplayName]", 338, 385, 300, 20);
fe.add_text("[FilterName]", 338, 405, 300, 20);
fe.add_text("[ListEntry] of [ListSize]", 338, 425, 300, 30);

Notice all of our text uses special strings enclosed in brackets. This means Attract-Mode will fill in the correct information when you go through your games. You can put your own text in there if you want, or combine multiple Magic Tokens with regular text.

Intro Layout

Hey! Looks pretty good. Play around with some of the objects properties until you have everything the way you like. You can remove any of the objects we put in, or add more if you want.

Next we'll get to some more advanced stuff.

#Plugins Coming Soon

#Modules Coming Soon