-
-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
363 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
================================== | ||
Getting Started With the Felix GUI | ||
================================== | ||
|
||
Felix comes with a library to create platform | ||
independent graphical user interfaces. It uses | ||
the Simple Direct Media Layer, version 2, SDL2 | ||
system with add-ons to do this. | ||
|
||
SDL2 runs on Linux, OSX, Windows, iOS and Android | ||
and is designed for implementation of portable games. | ||
|
||
Installation | ||
============ | ||
|
||
For the Felix GUI to work, *development versions* of | ||
the following components must be installed: | ||
|
||
.. code-block:: text | ||
SDL2 | ||
SDL2_image | ||
SDL2_ttf | ||
SDL2_gfx | ||
On Linux using apt package manager do this: | ||
|
||
.. code-block:: text | ||
sudo apt-get install libsdl2-dev | ||
sudo apt-get install libsdl2_image-dev | ||
sudo apt-get install libsdl2_ttf-dev | ||
sudo apt-get install libsdl2_gfx-dev | ||
Felix already contains database entries for these | ||
packages, but at the time of writing this tutorial, | ||
the libraries are expected to be in `/usr/local` | ||
which is where you would put them if you built them yourself. | ||
|
||
However Debian filesystem layout standards used by Linux OS | ||
such as Ubuntu that use `apt` package manager put components | ||
in `/usr/` instead. So unfortunately you will have to modify the | ||
database by hand by editing these files | ||
|
||
.. code-block:: text | ||
build/release/host/config/sdl2.fpc | ||
build/release/host/config/sdl2_image.fpc | ||
build/release/host/config/sdl2_ttf.fpc | ||
replacing `/usr/local` with just `/usr`. To preserved these modifications | ||
across upgrades, you should also copy the files: | ||
|
||
.. code-block:: bash | ||
cp build/release/host/config/sdl2.fpc $HOME/.felix/config | ||
cp build/release/host/config/sdl2_image.fpc $HOME/.felix/config | ||
cp build/release/host/config/sdl2_ttf.fpc $HOME/.felix/config | ||
I hope this problem can be reduced in future versions, but it is | ||
likely to be an issue for some time because most developers will have | ||
a libraries installed in both places, depending on whether they're | ||
using a package manager to install them, or building from source. | ||
|
||
To check your installation works, do this: | ||
|
||
.. code-block:: bash | ||
make tutopt-check | ||
and a series of tests will run which use the Felix GUI and SDL2. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
GUI Basics | ||
========== | ||
|
||
We will now show how to do basic GUI programming. | ||
The first thing we want to do is open a window! | ||
|
||
.. code-block:: felix | ||
include "gui/__init__"; | ||
open FlxGui; | ||
println$ "Basic Window Test"; | ||
FlxGui::init(); | ||
var w = create_resizable_window("Felix:gui_01_window_01",100,100,400,400); | ||
w.add$ mk_drawable FlxGuiSurface::clear lightgrey; | ||
w.update(); | ||
w.show(); | ||
sleep(15.0); | ||
The Felix gui is not included by default, so we have to first | ||
include the library with | ||
|
||
.. code-block:: felix | ||
include "gui/__init__"; | ||
Although this makes the library available, we would have to prefix | ||
the names of all functions in the library with :code:`FlxGui::` to use them. | ||
Since programmers hate typing stuff, we will open the library, so the | ||
functions are all in the current scope and can be used without | ||
the prefix. | ||
|
||
.. code-block:: felix | ||
open FlxGui; | ||
Next, we will print a diganostic to standard output so we know | ||
which program is running, and then initialise library. | ||
Initialisation is a requirement imposed by SDL, which has a lot | ||
of work to do on some platforms to connect to the GUI devices | ||
such as the screen, touch (haptic) inputs, joysticks, mice, | ||
keyboards, audio, and other multi-media hardware. | ||
|
||
.. code-block:: felix | ||
println$ "Basic Window Test"; | ||
FlxGui::init(); | ||
Now it it time for the fun! We will create a resizable window: | ||
|
||
.. code-block:: felix | ||
var w = create_resizable_window("Felix:gui_01_window_01",100,100,400,400); | ||
The first parameter is the title of the window, which should appear | ||
on the titlebar (it doesn't on OSX! Because there is no pause to | ||
accept input). | ||
|
||
The next four parameters describe the window geometry. | ||
The first two are the x and y coordinates. The SDL coordinate | ||
system puts the origin in the top left corner, and x increases | ||
down the screen. | ||
|
||
The unit of measurement is approximately the pixel. | ||
I say approximately because on a Mac with a Retina display, | ||
each pixel is often four displayt elements on the screen. | ||
To confuse the issue, the Mac can do hardware scaling. | ||
You'll just have to experiment! | ||
|
||
The second two values are the width and height | ||
of the window's client area, this does not include the title bar. | ||
However the x and y coordinates are the top left corner of the | ||
whole window including the title bar! | ||
|
||
What we have created is a data structure representing the window. | ||
The next thing we want to do is put some coloured pixels in it. | ||
|
||
.. code-block:: felix | ||
w.add$ mk_drawable FlxGuiSurface::clear lightgrey; | ||
This is an example of a fundamental operation, to add to a windows | ||
display surface, the commands for drawing something. | ||
|
||
The :code:`w.add` method adds a *drawable* to a list of drawables | ||
kept for window :code:`w`. | ||
|
||
The :code:`mk_drawable` method is a function which constructs a | ||
drawable object. Its first argument is the actual drawing command, | ||
:code:`FlxGuiSurface::clear` which clears a whole surface. | ||
The second argument is an argument to that command, in this | ||
case :code:`lightgrey`, which tells the clearing command what | ||
colour to write on the surface it is clearing. | ||
|
||
We have not actually drawn on the window at the point. | ||
What we have done is packaged up the drawing instructions, | ||
and *scheduled* them for drawing later. | ||
|
||
To actually draw, we do this: | ||
|
||
.. code-block:: felix | ||
w.update(); | ||
Now we have drawn the objects we scheduled to be drawn | ||
on the systems internal representation of the window's | ||
surface but still, nothing appears on the screen! | ||
|
||
This is because the window has not be shown yet. | ||
We've been drawing on it whilst it was invisible. | ||
So we now make it visible: | ||
|
||
|
||
.. code-block:: felix | ||
w.show(); | ||
FInally, we want the window to hang around for 15 seconds so | ||
you can admire your fine art work. | ||
|
||
.. code-block:: felix | ||
sleep(15.0); | ||
This causes the program to sleep for 15 seconds. The argument | ||
is a double precision floating point number representing | ||
a delay in seconds. The decimal point is mandatory and trailing | ||
zero is mandatory! | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
Putting Stuff in the Window | ||
=========================== | ||
|
||
Now we have created a window, we want to put stuff on it! | ||
|
||
.. code-block:: felix | ||
include "gui/__init__"; | ||
open FlxGui; | ||
println$ "Basic Drawing Test"; | ||
FlxGui::init(); | ||
var w = create_resizable_window("Felix:gui_03_draw_01",100,100,400,600); | ||
w.add$ mk_drawable FlxGui::clear lightgrey; | ||
var font_name = dflt_sans_serif_font(); | ||
var font : font_t = get_font(font_name, 12); | ||
var lineskip = get_lineskip font; | ||
w.add$ mk_drawable FlxGui::write (10,10,font,black,"Basic Drawing Test"); | ||
fun / (x:string, y:string) => Filename::join (x,y); | ||
var imgfile = #Config::std_config.FLX_SHARE_DIR / "src" / "web" / "images" / "FelixWork.jpg"; | ||
var ppic : surface_t = surface (IMG_Load imgfile.cstr); | ||
w.add$ mk_drawable blit (20,20, ppic.get_sdl_surface ()); | ||
w.add$ mk_drawable draw_line (RGB(0,0,255), 100,110,200,110); | ||
w.add$ mk_drawable draw_line (RGB(0,0,255), 100,210,200,210); | ||
w.add$ mk_drawable draw_line (RGB(0,0,255), 100,110,100,210); | ||
w.add$ mk_drawable draw_line (RGB(0,0,255), 200,110,200,210); | ||
w.update(); | ||
w.show(); | ||
sleep(15.0); | ||
Here, the program is as before, except we now do three basic | ||
ways to draw on a window. | ||
|
||
First, we want to be able to put ordinary text on the window. | ||
To do that, we have to first create a font to write the text | ||
with: | ||
|
||
.. code-block:: felix | ||
var font_name = dflt_sans_serif_font(); | ||
var font : font_t = get_font(font_name, 12); | ||
var lineskip = get_lineskip font; | ||
The first line gets the name of a default sans serif font | ||
file which is packaged with Felix so you don't have to figure | ||
out where all the fonts on your system are. | ||
|
||
The second line actually creates the font from the file | ||
at a particular size, in this case 12 point. The size is | ||
a conventional printers measure. You'll just have to get used | ||
to what it means! | ||
|
||
The third line helps tell how big the font it. We retrieve | ||
from the font the distance in pixels we should allow | ||
between lines, for readable text. Anything less and | ||
the characters would bump into each other. | ||
|
||
Now we have a font, we schedule drawing some text on the window: | ||
|
||
.. code-block:: felix | ||
w.add$ mk_drawable FlxGui::write (10,10,font,black,"Basic Drawing Test"); | ||
This is our usual machinery for adding a drawable object to the | ||
windows list of drawables, to be drawn when we say to `update`. | ||
The drawing function is :code:`FlxGui::write`. Notice we used | ||
the fully qualified name of the function, to avoid confusiuon | ||
with other functions named `write`. | ||
|
||
The argument to write is the x and y coordinates of the initial | ||
base point, the font to use, the colour to write in, and the | ||
actual text to write. | ||
|
||
Text is always written with respect to a base point. | ||
The base point is origin of the first character which is | ||
approximately the left edge of the character, and the | ||
point at which an invisible underline would occur: | ||
in other words, under the main body of the character, | ||
but on top of any descender that letter like `g` have. | ||
|
||
The exact location is font dependent. Font rendering | ||
is an arcane art, not an exact science so you will have | ||
to practice to get text to appear where you it has | ||
the correct visual significance. | ||
|
||
|
||
Now we are going to put a picture in the window. | ||
The image is a JPEG image, and is supplied for testing | ||
purposed in Felix at a known location. | ||
|
||
First we define a little helper function: | ||
|
||
.. code-block:: felix | ||
fun / (x:string, y:string) => Filename::join (x,y); | ||
What this says is that when we try to divide one string | ||
by another string, we actually mean to join the strings | ||
together using :code:`Filename::join` which is a standard | ||
function which sticks a `/` character between strings on unix | ||
platforms, and a slosh on Windows. | ||
|
||
The file is here: | ||
|
||
.. code-block:: felix | ||
var imgfile = #Config::std_config.FLX_SHARE_DIR / "src" / "web" / "images" / "FelixWork.jpg"; | ||
The prefix of this code finds the share subdirectory of the | ||
Felix installation, which contains the picture we went in the | ||
images subdirectory of the web subdirectory of the src subdirectory. | ||
|
||
|
||
Now to schedule the drawing we do this: | ||
|
||
.. code-block:: felix | ||
var ppic : surface_t = surface (IMG_Load imgfile.cstr); | ||
w.add$ mk_drawable blit (20,20, ppic.get_sdl_surface ()); | ||
The first line loads the image file into memoy using a low | ||
level primitive from SDL2_image. That primitve requires | ||
a C char pointer, not a C++ string, which is what Felix uses, | ||
so we use :code:`cstr` to convert. Then the `surface` function | ||
translates the loaded file into an SDL surface object. | ||
|
||
In the second line we add the drawable to the window based | ||
on the :code:`blit` function. This copies one surface to another. | ||
We copy the image surface to the window surface at position 20,20 | ||
in the window, and use the :code:`get_sdl_surface()` method to | ||
translate the Felix surface object into a lower level SDL surface. | ||
|
||
Its all a bit mysterious, so you just have to so some thing | ||
by copying the patterns that work. | ||
|
||
Finally, we draw a blue rectangle on top of the picture. | ||
I'm sure you can figure out how that works! | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,9 @@ Contents: | |
|
||
hello | ||
pythagoras | ||
gui01 | ||
gui02 | ||
gui03 | ||
|
||
Indices and tables | ||
================== | ||
|