Professional Documents
Culture Documents
Fs2004 - Panels SDK
Fs2004 - Panels SDK
A Century of Flight
Software Development Kit
2004 Microsoft Corporation. All rights reserved.
Photoshop is a registered trademark of Adobe Systems Incorporated.
PhotoPaint is a trademark of Corel Corporation.
February 2004
Contents
Contents........................................................................................................................................i
Introduction.................................................................................................................................1
Creating a Panel and Gauges.....................................................................................................2
Panels and the Aircraft Container System...............................................................................3
The Panel Configuration File.....................................................................................................5
[Window Titles] section: Creating Panel Windows..................................................................6
[Views] section: Specifying the View Direction of Panels......................................................7
Variable..........................................................................................................................7
Description.....................................................................................................................7
[WindowXX] section: Describing Panel Windows................................................................10
Variable........................................................................................................................10
[VCockpitXX] section: Specifying Textures for Cockpits.....................................................15
Variable........................................................................................................................15
Description...................................................................................................................15
[Default View] section: Setting the View...............................................................................15
Placing Gauges on a Panel Background.................................................................................16
Sample Code for Gauges..........................................................................................................17
Creating a Gauge File...............................................................................................................19
Defining Variables and Resources...........................................................................................20
SDK.h: Defining Gauge Resources........................................................................................21
SDK.rc: Associating Resource IDs with .bmp Files...............................................................23
SDK.c: Naming and Positioning Gauges, Including Source Files, and Exporting Pointers for
Gauges.....................................................................................................................................24
The Sample Gauges...................................................................................................................26
Gauge...........................................................................................................................26
Description...................................................................................................................26
Setting Up the Gauge Header.................................................................................................26
GAUGE_HEADER_FS700................................................................................................28
Simulating System Failures....................................................................................................30
FAILURE_RECORD.........................................................................................................30
Identifying the System Undergoing Failure........................................................................31
FAILURE_KEY..........................................................................................................31
FAILURE_KEY..........................................................................................................32
Identifying the Failure Action.............................................................................................34
FAIL_ACTION............................................................................................................34
Using Gauge Macros...............................................................................................................35
Sliders Example..................................................................................................................35
MAKE_SLIDER..........................................................................................................35
DRAW_FLAGS...........................................................................................................39
PELEMENT_HEADER..............................................................................................39
Making the Background Image....................................................................................42
i
Defining Mouse Rectangles....................................................................................................44
Rectangles within Rectangles......................................................................................45
Generating Events........................................................................................................45
Using Callback Functions............................................................................................47
Creating Dynamic Mouse ToolTips.............................................................................49
Compiling and Using Your Gauges........................................................................................50
Using Token Variables.............................................................................................................52
UNIVERSAL_VAR Types.................................................................................................52
Accessing Token Variables.....................................................................................................52
To access a tokenized variable through the Panel API................................................53
Gauge Macros and Drawing Elements...................................................................................54
Shared Data Elements.............................................................................................................54
Drawing Element Header........................................................................................................56
Drawing Element Structures...................................................................................................58
Drawing Element Lists...........................................................................................................59
Gauge Macro Reference.........................................................................................................59
MAKE_STATIC.................................................................................................................59
MAKE_NEEDLE...............................................................................................................62
Using Non-Linearity Tables........................................................................................65
MAKE_STRING................................................................................................................66
Defining the Font Type................................................................................................72
Selecting a String by KEY_EVENT............................................................................73
MAKE_SLIDER.................................................................................................................76
MAKE_MOVING..............................................................................................................79
MAKE_ICON.....................................................................................................................81
MAKE_SPRITE.................................................................................................................84
Drawing Element Macros.........................................................................................................88
String Element Macros.............................................................................................................88
Functions....................................................................................................................................88
initialize_var...........................................................................................................................88
lookup_var..............................................................................................................................89
mouse_child_funct..................................................................................................................90
panel_window_toggle.............................................................................................................91
Token Variables........................................................................................................................93
Help IDs.....................................................................................................................................93
Event IDs....................................................................................................................................93
Using Named Variables to Enable Communication Between Gauges.................................94
XML Gauges..............................................................................................................................97
Calculated Expressions in XML Gauges................................................................................98
Common Operators.............................................................................................................99
Comparison Operators........................................................................................................99
Bit Operators.....................................................................................................................100
Logical Operators..............................................................................................................100
Numerical Operators.........................................................................................................100
String Operators................................................................................................................102
ii
Stack Operators.................................................................................................................102
Order of Execution for Operators.....................................................................................104
Appendix A: Tips on Creating Art for Panels and Gauges................................................105
Background...........................................................................................................................105
Learning About the Aircraft..................................................................................................105
Creating a Layout for the Panel............................................................................................106
Researching the Instruments.............................................................................................106
Creating the Layout...........................................................................................................106
Considering the Panel Height...........................................................................................106
Considering the Slope of the Sides...................................................................................106
Beginning Production...........................................................................................................107
Creating the Base Background..........................................................................................107
Adding Depth and Detail..................................................................................................107
Merging the Side Panels...................................................................................................107
Creating the Panel Edge and Shadow...............................................................................107
Compressing the File........................................................................................................107
Building the Gauges..............................................................................................................108
Separating the Gauge Elements........................................................................................108
Working at a Larger Size..................................................................................................108
Cleaning the Rings and Backgrounds...............................................................................108
Adding Depth and Details.................................................................................................108
Compiling the Gauge........................................................................................................109
Resizing the Gauge...........................................................................................................109
Palletizing the Artwork.........................................................................................................109
Creating a Final Composition...............................................................................................110
Appendix B Using Masks in Images...................................................................................111
How Do I Use a Mask Image? ............................................................................................111
Specifying Luminousity .......................................................................................................112
Imagetool and Luminousity .................................................................................................112
How Colors Affect the Display of Panels. .......................................................................113
Step-by-Step XML Example:...............................................................................................114
Questions about Using Masks in Images..............................................................................116
Appendix C Using Imagetool with Gauges........................................................................118
Converting .psds to .bmp-with-alpha format, maintaining alpha channel...........................118
GUI...................................................................................................................................118
Command-line...................................................................................................................118
Converting .psds to .bmp-with-alpha format, creating a gauge image ...........................118
GUI...................................................................................................................................119
Command-line...................................................................................................................119
Viewing images created with ImageTool.............................................................................119
Determining the format of an image.....................................................................................120
iii
Introduction
The Panels and Gauges SDK provides the information you need to create new gauges and panels
for aircraft in Flight Simulator 2004. This SDK includes the following:
A programming reference listing the functions and variables youll need to create your
own panels and gauges.
This document references, but doesnt include, the information contained in the Aircraft
Container SDK. That SDK provides details on how all files within the Aircraft Container
system interrelate. We will touch on this, but for specific details, please refer to that SDK.
Important: The information included in this document is intended as a guide for programmers.
It assumes that you are familiar with aviation terminology and technology, that you have an
understanding of the C programming language, and that you are familiar with XML.
1
Creating a Panel and Gauges
The process of creating a brand-new panel from scratch can involve all of the following steps
(not necessarily in this order):
1. Choose the aircraft for which you want the new panel.
2. Identify a relatively similar aircraft within Flight Simulator 2004 and use its .air file as
the basis for your planes flight dynamics and engine/mechanical variables.
3. Identify the gauges your panel will contain and create the necessary artwork. Place this
artwork in a resources folder for your gauge code to reference.
4. Create the panel background art for your gauges.
5. Create the different interior views referenced by the Panels.cfg file.
6. Create and compile the source code for each of the gauges you intend to place on your
panel.
7. Create an associated Panel.cfg file for your panel to place and configure the gauges.
8. Place the gauges on your panel background.
9. Place the necessary files in the appropriate folders for your aircraft.
2
Panels and the Aircraft Container System
In Flight Simulator 2004, all aircraft-specific files (except for the gauges themselves) are located
in the Aircraft folder, also called the container system. The aircraft folder includes a folder for
each aircraft available in Flight Simulator 2004 and a set of aircraft-specific files. The following
table describes what youll find in the Aircraft folder.
Model folder Contains the model file (.mdl) that defines the 3-D structure of the
aircraft, along with a model configuration file (Model.cfg).
Panel folder Contains bitmaps for the different cockpit interior views for the
aircraft, bitmaps for the panel backgrounds, and a panel
configuration file (Panel.cfg).
Sound folder Contains the various sound files used by the aircraft, as well as a
sound configuration file (Sound.cfg).
Texture folder Contains bitmaps for various textures applied to the interior and
exterior aircraft. Note: The exterior texture files are a special bitmap
format that contain level of detail (LOD) information. Editing and
saving one of these files with Paintbrush or some other tool will
cause this LOD information to be lost.
Aircraftname.air Contains the core simulation information for the aircraft specified in
the file name (Aircraftname). The simulation engine variables and
other details vary for each .air file. Therefore, when you create a
gauge, recognize that each .air file only presents a subset of all
possible token variables. For example, Cessna182S.air wouldnt
support the token variable TURBINE_ENGINE_1_EPR since a
Cessna 182S uses a reciprocating engine, not a turbine engine.
Important: Please read the Aircraft Container SDK documentation for information on setting up
your Aircraft.cfg and the overall aircraft container system. This information is critical to actually
getting your panel into an aircraft.
3
This document will cover only the Panel folder and the Panel Configuration files, both of which
are essential to creating a panel.
4
The Panel Configuration File
The primary folder used by the Panel system is the Panel folder. The Panel folder contains the
panel background image files (.bmps) and the panel configuration file (Panel.cfg). When Flight
Simulator 2004 loads an aircraft, it also loads the appropriate panel configuration file.
If you have more than one version of an aircraft and you want a different panel layout for the
second version, you will have more than one Panel folder. The name of the default Panel folder
is Panel. Additional Panel folders must have the name Panel.xxx, where xxx is an identifying key.
For example, the Cessna 172 ships with Panel and Panel.ifr folders for the 172 and IFR panels
that come with Flight Simulator 2004. The identification key is found in the Aircraft
configuration file. For more information, see Configuration sets and their [fltsim. ] sections in
the Aircraft Container SDK.
5
[Window Titles] section: Creating Panel Windows
The Panel system creates the aircraft's panel windows by using the [Window Titles] section.
The variables in this section are used to set the initial state of each panel window and each
interior view.
For each WindowXX variable in this section, the Panel system creates a panel window. It starts
with Window00 and creates panel windows until it reaches Window63 or until it finds a break
in the progression.
The order in which you assign panel windows doesnt matter, so long as you start WindowXX at
Window00.
When creating the panel window, the system looks for corresponding [WindowXX] sections later
in the configuration file. After the panel window is created, the gauges listed in the [WindowXX]
section are loaded.
For example, the Panel.cfg file for the Cessna 182s contains the following information in this
section:
[Window Titles]
Window00=Main Panel
Window01=Radio Stack
Window02=GPS
Window03=Annunciator
Window04=Compass
...
Note: The string you assign to each WindowXX (e.g., Window02=GPS) is the Title displayed for the
panel window when it's undocked. The string is also displayed on a submenu menu when you
click Instrument Panel on the Views menu. You should therefore make sure the label you use
for each window is appropriate.
6
[Views] section: Specifying the View Direction of Panels
This section specifies the view direction in which panels appear within the aircraft. You can set
the following views.
Variable Description
VIEW_FORWARD_WINDOWS Identifies which panel windows display
in the forward section of the aircraft.
These values must match the specific
ident= value in the corresponding
[windowXX] section. For example:
VIEW_FORWARD_WINDOWS=MAI
N_PANEL,RADIO_STACK_PANE
L,COMPASS_PANEL,ANNUNCIA
TOR_PANEL,GPS_PANEL
MAIN_PANEL
RADIO_STACK_PANEL
COMPASS_PANEL
ANNUNCIATOR_PANEL
ANNUNCIATOR2_PANEL
COLLECTIVE_PANEL
THROTTLE_PANEL
MINI_CONTROLS_PANEL
IFR_MAIN_PANEL
GPS_PANEL
OVERHEAD_PANEL
9
[WindowXX] section: Describing Panel Windows
This section describes a panel window (i.e., an individual panel): its shape, position, properties,
the background image, and what gauges belong to the panel.
Variable Description
file Specifies the bitmap file to load and use for the panel window
background. (Flight Simulator 2004 uses a background designed for
1024 by 768 resolution.) For example:
File=panel_background_1024.bmp
This .bmp file must be in the same directory as the Panel.cfg file.
size_mm Specifies the size of the panel window, in millimeters. For example:
size_mm=1024
size_mm=127, 185
Window_size_ratio = 0.8
10
Specifies the relative position of a panel window to the main
position window. For example:
position = 7
0 = upper-left corner
1 = upper-middle side
2 = upper-right corner
3 = middle-left side
4 = middle
5 = middle-right side
6 = lower-left corner
7 = lower-middle side
8 = lower-right corner
window_pos=0.85, 0.3
window_size=0.5, 0.5
Specifies the initial visible state of the panel window. For example:
visible
visible=1
11
Specifies a unique identifier to define the panel window. For
ident example:
ident=MAIN_PANEL
You must have an ident for each panel window. Valid entries are the
following:
MAIN_PANEL
THROTTLE_PANEL
RADIO_STACK_PANEL
COMPASS_PANEL
MINI_CONTROLS_PANEL
ANNUNCIATOR_PANEL
ANNUNCIATOR2_PANEL
IFR_MAIN_PANEL
COLLECTIVE_PANEL
GPS_PANEL
OVERHEAD_PANEL
If your panel windows description doesnt fit any of above, use any
number between 10000 and 19999.
Specifies whether the panel window is sizeable with the mouse or
sizeable not. For example:
sizeable=1
nomenu Specifies whether the menu will appear in the Flight Simulator
Views menu. A value of 1 specifies that the window will not appear
in the menu. By default, a panel window appears in the menu.
type Specifies the type of the panel window. Valid entries are PANEL
for aircraft panels, MINIPANEL for gauge windows shown in the
minipanel mode, or SPECIAL for pseudo panel windows.
Specifies size of the panel window in pixels:
pixel_size
pixel_size=100,200
12
13
Specifies which gauge file to load and the X,Y position of the
gauge00gaugeXX gauge. The Panel system starts loading gauges, starting from
gauge00 until it reaches gauge99. After that, it loads gauge100,
gauge101, and so on until it finds a break in the progression. This
comma-delimited variable exists primarily to specify which gauge
DLL file to load and the X, Y position of the gauge, in millimeters.
This will override the size_mm setting.
gauge##=gaugefile!gaugename, X, Y, W, H,
parameters
Where:
gauge00=Cessna!ADF, 545, 86
gauge01=Cessna172!Airspeed, 145, 56
...
gauge21=Cessna182s!Autopilot_Switch, 68, 111, 30, 40
...
gauge39=SimIcons!Kneeboard Icon, 326, 280
...
gauge99=Cessna!Weather Radar, 201, 324, , , Color
gauge100=Cessna!GPS, 304, 568, , , Full
14
[VCockpitXX] section: Specifying Textures for Cockpits
This section describes textures needed for creating virtual cockpits. You can get the details about
creating virtual cockpits in the Aircraft Container SDK. This section describes only the details
related to the panel.cfg file. In addition to file, size_mm, pixel_size variables from the
[WindowXX] section, the texture variable is also in this section.
Variable Description
Specifies a texture name used by the aircraft model for virtual cockpit.
Texture You must specify a name that starts with the dollar sign ($) and is no
longer than 15 symbols. For example:
texture=$cessna172_vcockpit
This section sets the overall view for the default 3-D window.
Variable Description
Specifies the X position of the default 3D window. For example:
X
X = 0
15
Placing Gauges on a Panel Background
After you build your gauges, you must place them on the panel background. Here are some
details about how to place gauges by editing Panel.cfg:
First, note that all panel backgrounds that ship with Flight Simulator 2004 now use only a
1024 version.
The 1024 panel background is exactly 1024 pixels wide.
The Panel.cfg file for every aircraft in Flight Simulator 2004 sets size_mm to 1024.
The Panel.cfg file also sets the window_size_ratio to 1.0, which produces a 1.0 ratio
between pixels and millimeters. Therefore, by following this standard, you can use pixels or
millimeters interchangeably for all references within Panel.cfg and in your source code
creating, in effect, design units that scale appropriately. However, if you deviate from this
standard, its still relatively easy to get the right coordinates. For example:
1. You create a 1024 panel background for the Bell 206 that is actually 750 pixels wide.
2. The Bell 206 panel.cfg sets size_mm to 750; it also sets windowsize_ratio to .732. A
simple calculation shows:
This means that pixels within the gauge bitmaps and pixels within the panel all can use the
same design units and require no translation.
16
Sample Code for Gauges
This SDK includes source code for several sample gauges, along with their associated resources.
Use these samples to learn how to build gauges and feel free to modify them in creating your
own gauges and panels. The following table shows the samples provided and a brief description.
\other Contains other files used with the sample panel and
gauges.
18
Creating a Gauge File
If you read through the sample makefile (\sample\makefile) youll see that the goal of that
sample is to create a file called SDK.gau. This is the gauge file used by the Panel system within
Flight Simulator 2004.
A gauge file is a Windows DLL with the extension .gau, which is loaded by the Panel system. A
gauge file can contain one to several individual gauges within the panel. The Panel system
interacts with each gauge using the exported interface defined by the gauge header file
(Gauges.h). The interface used by a gauge consists of a list of drawing elements and the exported
functions used to manage the gauge.
All .gau files within Flight Simulator 2004 reside within the .\Flight Simulator 9\Gauges folder.
(The FSEdit utility looks in this folder to determine the gauges available for its use.)
When compiled, the sample code generates a single SDK.gau containing six different gauges,
each illustrating a different type.
19
Defining Variables and Resources
Your gauges will need access to various resources and variables to function properly. The
sample code provided with this SDK accomplishes these key definitions in three files (found in
the \sample folder):
SDK.h
SDK.rc
SDK.c
Make sure to go through the following sections carefully because they describe whats
happening within each file. Read through the sources as you go through this information as well.
20
SDK.h: Defining Gauge Resources
When you open SDK.h youll first see a series of #define directives that set Version information
as well as some constants within the C preprocessor.
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define VERSION_BUILD 0
#ifndef VS_VERSION_INFO
#define VS_VERSION_INFO 0x0001
#endif
Depending on which C compiler youre using, you may need to tweak the preprocessor
information somewhat, but otherwise, you wont need to modify the #define directives.
The primary task youll need to accomplish inside SDK.h is to define the various resources
(bitmaps) used by all the gauges youre building into the target .gau file. The following code
fragment defines the constants used for resources (i.e., the resource_id) associated with the
Attitude Indicator sample (SDK.attitude.c):
// Attitude Bitmaps
//
#define BMP_ATTITUDE_SMALL_BACKGROUND 0x1000
#define BMP_ATTITUDE_SMALL_CARD1 0x1100
#define BMP_ATTITUDE_SMALL_MASK1 0x1101
#define BMP_ATTITUDE_SMALL_CARD2 0x1200
#define BMP_ATTITUDE_SMALL_MASK2 0x1201
21
The actual linking of these constants to specific .bmp files happens in SDK.rc as described later
in this document. There are some rules associated with setting these constants:
1. You can identify lower-resolution and higher-resolution bitmaps by incrementing the hex
value by 500. For example, you could set your defines for two different resolutions as
follows:
2. Bitmaps that you intend to apply as masks over other bitmaps should increment by 1 as in
this example. Note: Previously, the increment was 3.
The sample SDK.h provided defines constant values for all the bitmap resources used by the
sample gauge files.
22
SDK.rc: Associating Resource IDs with .bmp Files
The sample resource file associates the resource_id for all the resources in all the gauges with
the corresponding .bmp file. Open this file with your favorite editor and read along.
First, note that the SDK.rc file contains an include directive for SDK.h near the top:
#include sdk.h
Youll need to adjust this for whatever you name your .h file.
Just below this, youll find more versioning information, along with a block entitled
StringFileInfo as shown below:
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Your Company\0"
VALUE "FileDescription", "Flight Simulator 2004 Gauge\0"
VALUE "FileVersion", VERSION_STRING
VALUE "LegalCopyright", "Your Copyright.\0"
VALUE "ProductName", "Your Product\0"
VALUE "ProductVersion", VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
The next section is where each resource_id defined in SDK.h gets associated with the
appropriate .bmp file:
// Attitude Bitmaps
//
BMP_ATTITUDE_SMALL_BACKGROUND BITMAP DISCARDABLE
"res\\SDK.Attitude.bg.BMP"
BMP_ATTITUDE_SMALL_CARD1 BITMAP DISCARDABLE
"res\\SDK.Attitude.card1.BMP"
BMP_ATTITUDE_SMALL_MASK1 BITMAP DISCARDABLE
"res\\SDK.Attitude.mask1.BMP"
BMP_ATTITUDE_SMALL_CARD2 BITMAP DISCARDABLE
"res\\SDK.Attitude.card2.BMP"
BMP_ATTITUDE_SMALL_MASK2 BITMAP DISCARDABLE
"res\\SDK.Attitude.mask2.BMP"
23
Youll need to create similar resource_id assignments for all resource files used by your gauges.
The SDK.c file included with this SDK enables you to manage the various gauges from a single
file while still separating the individual gauge source files for easier maintenance. You dont
necessarily have to create a corresponding SDK.c file for your gauges, but there are some
specific things you need to do within your gauge code as explained below.
First, notice that SDK.c has #include statements for both Gauges.h and SDK.h. Make sure you
include Gauges.h and SDK.h in your gauge code as well. SDK.c then breaks out into sections for
each individual gauge, finishing up with a series of gauge table entries.
/////////////////////////////////////////////////////////////////////////////
// Attitude
/////////////////////////////////////////////////////////////////////////////
#define GAUGE_NAME "Attitude\0"
#define GAUGEHDR_VAR_NAME gaugehdr_attitude
#define GAUGE_W 100
#include "SDK.Attitude.c"
/////////////////////////////////////////////////////////////////////////////
// Control Surfaces
/////////////////////////////////////////////////////////////////////////////
#define GAUGE_NAME "Control_Surfaces\0"
#define GAUGEHDR_VAR_NAME gaugehdr_control_surfaces
#define GAUGE_W 100
#include "SDK.Control_Surfaces.c"
/////////////////////////////////////////////////////////////////////////////
// Fuel
/////////////////////////////////////////////////////////////////////////////
#define GAUGE_NAME "Fuel\0"
#define GAUGEHDR_VAR_NAME gaugehdr_fuel
#define GAUGE_W 100
#include "SDK.Fuel.c"
24
This code is then repeated for the remaining gauges. Heres whats happening with each
assignment:
GAUGE_NAME is assigned the string that becomes the gauges name. (Note that this string
must end with the carriage return \0 value.) This gauge name is used in the Panel.cfg file
under the [windowXX] section where each gauge is defined. For the fragment above,
panel.cfg would identify these gauges as:
gauge00=SDK!Attitude, 247, 58
gauge01=SDK!Control_Surfaces, 370, 160
gauge02=SDK!Fuel, 146, 57
GAUGEHDR_VAR_NAME is assigned the gauge name used by the Gauge Table (the
modules export table). The Gauge Table gets defined at the end of SDK.c.
GAUGE_W is assigned a value for the number of X-axis design units used by the gauge.
Note that the units used by the gauge correspond to the units used by the panel background.
For example, if your panel is 1000 units and a gauge is 100 units, then that gauge will be
1/10 the size of the panel. (You can override this in the Panel.cfg file.)
#include SDK_xxx.c simply pulls in the specific gauge code file for each gauge.
This code repeats for each gauge within SDK.c. Accordingly, each of the gauge code files
(SDK_xxx.c) ends with #undef for GAUGE_NAME, GAUGEHDR_VAR_NAME, and
GAUGE_W so theyre ready to reset with new values for the next gauge.
Finally, at the end of SDK.c, the Gauge Table assignments are made. The Gauge Table in the
sample file looks like this:
/////////////////////////////////////////////////////////////////////////////
// Gauge table entries
/////////////////////////////////////////////////////////////////////////////
GAUGE_TABLE_BEGIN()
GAUGE_TABLE_ENTRY(&gaugehdr_attitude)
GAUGE_TABLE_ENTRY(&gaugehdr_control_surfaces)
GAUGE_TABLE_ENTRY(&gaugehdr_fuel)
GAUGE_TABLE_ENTRY(&gaugehdr_fuel_selector)
GAUGE_TABLE_ENTRY(&gaugehdr_temperature)
GAUGE_TABLE_ENTRY(&gaugehdr_wiskey)
GAUGE_TABLE_END()
25
The Sample Gauges
Now that weve covered some of the basic constant and variable assignments for gauges, well
move on to code for the sample gauges. This SDK includes sample code for the following
gauges.
Gauge Description
Attitude indicator, sprite example.
SDK.attitude.c
Control Surfaces, slider example.
SDK.control_surfaces.c
Fuel gauge, needle example.
SDK.fuel.c
Fuel Selector, icon example.
SDK.fuel_selector.c
Temperature gauge, string and icon examples.
SDK.temperature.c
Whiskey Compass, moving image example.
SDK.wiskey.c
Simple GPS-like gauge, example of implementing owner draw
SDK.FlightMap.c gauges.
All of these files contain static image examples. The following sections describe the basic calls
made within a gauge source file, pointing out the individual distinctions for each gauge type.
At the beginning of each sample gauge source file, youll see a code fragment like this:
First, the code assigns values for the following variables used by the gauge header:
26
Then the code fills in values for GAUGE_HEADER_FS700, the gauge header macro. The gauge
header is a structure that defines the interface used by the Panel system to control the gauge
DLL. You must export the gauge header to expose the gauge interface to the Panel system.
27
GAUGE_HEADER_FS700
Use the GAUGE_HEADER_FS700 macro to create and export the gauge header
(GAUGEHDR). The GAUGE_HEADER_FS700 macro creates GAUGEHDR, filling in the
unique members of the structure:
The following example shows how to use the GAUGE_HEADER_FS700 macro in code:
28
The GAUGE_HEADER_FS700 macro has these members:
Member Description
default_size_mm The default X axis size of the gauge in design units. This value is set as
GAUGE_W in SDK.c.
pgauge_callback A pointer to a function for the entire gauge. This will pass a message to the
system. Use 0 if none.
user_data A 32-bit space you can use for any data you want. Use 0 if none.
parameters A field that contains a string. A pointer to this string is placed in the gauge
header for use in the gauge callback function (or wherever might be
appropriate). Use 0 if none.
29
Simulating System Failures
Flight Simulator 2004 can simulate several types of aircraft system failures. Almost all of the
sample gauge source files contain code that illustrates how to set up a simulated system failure.
FAILURE_RECORD
Youll use the FAILURE_RECORD structure to identify the systems thatshould they fail
would need to be reflected by the gauge. The structure inside Gauges.h looks like this:
The following code illustrates how you can build FAILURE_RECORD for a Fuel gauge:
FAILURE_RECORD fuel_fail[] =
{
{FAIL_SYSTEM_ELECTRICAL_PANELS, FAIL_ACTION_ZERO},
{FAIL_GAUGE_FUEL_INDICATORS, FAIL_ACTION_FREEZE},
{FAIL_NONE, FAIL_ACTION_NONE}
Each FAILURE_KEY enum value identifies the system undergoing failure; its associated
FAILURE_ACTION identifies what happens in the event of that failure.
30
Identifying the System Undergoing Failure
FAILURE_KEY
System failures are listed in the FAILURE_KEY enum values as shown below:
OLD_FAIL_SYSTEM_ELECTRICAL, // obsolete
FAIL_SYSTEM_ENGINE,
FAIL_SYSTEM_PITOT_STATIC,
FAIL_SYSTEM_VACUUM,
FAIL_GAUGE_ADF,
FAIL_GAUGE_AIRSPEED,
FAIL_GAUGE_ALTIMETER,
FAIL_GAUGE_ATTITUDE,
FAIL_GAUGE_COMMUNICATIONS,
FAIL_GAUGE_FUEL_INDICATORS,
FAIL_GAUGE_GYRO_HEADING,
FAIL_GAUGE_MAGNETIC_COMPASS,
FAIL_GAUGE_NAVIGATION, // this assumes no vors
FAIL_GAUGE_NAVIGATION_VOR1, // only vor1
FAIL_GAUGE_NAVIGATION_VOR2, // only vor2
FAIL_GAUGE_NAVIGATION_BOTH, // both vors
FAIL_GAUGE_TRANSPONDER,
FAIL_GAUGE_TURN_COORDINATOR,
FAIL_GAUGE_VERTICAL_SPEED,
FAIL_SYSTEM_ELECTRICAL_PANELS,
FAIL_SYSTEM_ELECTRICAL_AVIONICS,
FAIL_KEY_MAX
}
31
FAILURE_KEY
The following table describes the FAILURE_KEY enum values for Flight Simulator 2004.
32
FAIL_GAUGE_ TRANSPONDER Specifies a transponder gauge system failure.
33
Identifying the Failure Action
You can set up a gauge element to react to one or more of the system failures shown in the
FAILURE_RECORD by using one of the defined FAILURE_ACTION enum values:
FAIL_ACTION
The following table describes the FAIL_ACTION enum values for Flight Simulator 2004.
Member Description
34
Using Gauge Macros
Moving a little further down in the sources for the various sample gauges, youll see different
macros being used to pass parameters between the gauge and the panel system. These macros are
defined in Gauges.h, and you can use them to create various types of gauges. Lets continue
through the code to where macros first start appearingwell look specifically at the sliders
example and then cover all the gauge macros in detail later on.
Sliders Example
The SDK.control_surfaces.c example shows how to build a gauge using sliders that move over a
static image in the background. The code that follows uses the bitmaps listed in the table below
as resources:
MAKE_SLIDER
The code first creates the sliders using the MAKE_SLIDER macro. Heres the structure for the
MAKE_SLIDER macro from gauges.h:
35
Youll need to fill this structure out with slider-specific information, such as the following from
SDK.Control_Surfaces.c:
MAKE_SLIDER
(
cs_slider_trim,
BMP_CS_SMALL_TRIM,
NULL,
0,
IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY,
0,
20,44,
MODULE_VAR_NONE, NULL, 0,
ELEVATOR_TRIM, NULL, -100
)
NEXT_LIST NULL Sets the order in which parts of the gauge get
drawn. Set to NULL as this is a simple gauge
where the sliders do not overlap.
37
Set the X-axis values. (You can move a slider
SOURCE_VAR_X, MODULE_VAR_NONE on the X or Y axis.).
CALLBACK_X, , SOURCE_VAR_X identifies the token
SCALE_X NULL, variable the slider will use. Since Trim
0 goes only up and down, theres no token
variable so use
MODULE_VAR_NONE.
CALLBACK_X identifies the modifying
callback if any. None is needed, so set to
NULL.
SCALE_X sets the scaling value for the
range of X-axis movement of the
variable across the background image.
Here its 0. A slider moves from left to
right unless this value is preceded by a
minus (-) sign.
Set the Y-axis values. Here the Trim slider
SOURCE_VAR_Y, ELEVATOR_TRIM, does move on the Y-axis.
CALLBACK_Y, NULL, SOURCE_VAR_Y uses the
SCALE_Y -100 ELEVATOR_TRIM token variable. For
more information, see the discussion of
token variables later in this section.
CALLBACK_Y identifies the modifying
callback, which isnt used here.
SCALE_Y is the scaling value of the Y-
axis movement of the slider across the
background image. Divide the token
variable value returned by the range of
movement in pixels, and then multiply by
the units of measure. A slider moves from
top to bottom unless this value is
preceded by a minus (-) sign.
38
DRAW_FLAGS
The code in SDK.control_surfaces.c contains four separate MAKE_SLIDER macros, one for
each of the different sliders used.
PELEMENT_HEADER
After the final MAKE_SLIDER macro has been defined, youll see the following code:
PELEMENT_HEADER cs_sliders_list[] =
{
&cs_slider_trim.header,
39
&cs_slider_ailerons.header,
&cs_slider_elevator.header,
&cs_slider_rudder.header,
NULL
};
This PELEMENT_HEADER code signals the end of the series of macros and sets the order in
which these different parts of the gauge appear. The display order goes from top to bottom. This
works very well here since the various sliders do not overlap one another. Note that every macro
you define must have an associated PELEMENT_HEADER somewhere, and it must end with a
NULL.
The specific code fragment above sets the order for all sliders simultaneously. In cases where
sliders or other resources overlap, you could instead break these out separately. For example:
MAKE_SLIDER
(
cs_slider_ailerons,
BMP_CS_SMALL_AILERONS,
NULL,
0,
IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY,
0,
95, 6,
MAKE_SLIDER(
cs_slider_elevator,
BMP_CS_SMALL_ELEVATOR,
&cs_sliders_list1,
0,
IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY,
0,
98, 46,
MODULE_VAR_NONE, NULL, 0,
ELEVATOR_DEFLECTION, NULL, -70
)
PELEMENT_HEADER cs_sliders_list2[] =
{
&cs_slider_elevator.header,
NULL
}; \\ END OF SECOND SLIDER MACRO
MAKE_SLIDER
(
cs_slider_rudder,
BMP_CS_SMALL_RUDDER,
&cs_sliders_list2,
0,
IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY,
0,
94, 83,
40
RUDDER_DEFLECTION, NULL, 80,
MODULE_VAR_NONE, NULL, 0
)
PELEMENT_HEADER cs_sliders_list3[] =
{
&cs_slider_rudder.header,
NULL
}; \\ END OF THIRD SLIDER MACRO
Note that the NEXT LIST parameter for the second slider references &cs_sliders_list1,
&cs_sliders_list2, and so forth, indicating the links between each MAKE_SLIDER instance.
41
Making the Background Image
To set the background image for the gauge, use the MAKE_STATIC macro. You will always
use this macro with every gauge you create. First, heres the background resource used by
control_surfaces.c:
Youll create the static background image with the MAKE_STATIC macro. As an example,
heres the macro structure from Gauges.h:
And heres the code fragment from Control_surfaces.c that uses MAKE_STATIC:
MAKE_STATIC
(
cs_background,
BMP_CS_SMALL_BACKGROUND,
&cs_sliders_list,
NULL,
IMAGE_USE_TRANSPARENCY,
0,
0,0
)
42
The following table explains the different fields in MAKE_STATIC.
NAME cs_background Contains the unique name you assign to the macro
this specific name applies to the static
background image.
RES_ID BMP_CS_SMALL_ Contains the name of the resource file used by the
BACKGROUND slider as identified earlier by SDK.h.
NEXT_LIST &cs_sliders_list Sets the order in which parts of the gauge get
drawn. The example identifies the sliders.
DRAW_FLAGS IMAGE_USE_ Sets how the bitmap will display. These flags are
TRANSPARENCY the same for all macros.
Specifies whether or not to capture the current
ASI_FLAGS 0 value of the Altitude or Heading. This is a bitwise
field that Turns ON or OFF. If you set it to 0, then
Altitude and Heading will be manually tunable.
Valid entries are:
ASI_ALT_MANUALLY_TUNABLE
ASI_HEADING_MANUALLY_TUNABLE
Finally, the PELEMENT_HEADER for the macro gets set to identify this image as the gauge
background:
If you look back near the top of the code, youll see:
Here, the initial assignment of cs_list identifies this specific macro with the background image
for the gauge.
Were pretty much nearing the end of our sample code inside the Control_surfaces.c file. Lets
wrap up with a discussion of how to tell the mouse the gauge exists.
43
Defining Mouse Rectangles
By using mouse rectangles, you can specify how a gauge will interact with the mouse pointer
(i.e., mouse movement and mouse button clicks). For example, you can change the cursor or
display a ToolTip as the mouse enters the area you've defined as a mouse rectangle; you can also
trigger a Flight Simulator event or execute a callback function.
Note that the mouse rectangle you define is specific to the gauge itselfit works off the gauge
coordinates, not the panel background coordinates. This allows you to move the gauge around
the panel, while keeping the mouse rectangle intact.
To define a mouse rectangle, you use a combination of the mouse definition macros, as shown in
the following code example from the SDK.control_surfaces.c file:
MOUSE_BEGIN, MOUSE_PARENT, and MOUSE_END are all macros you can use when
defining mouse rectangles. You should look inside the Gauges.h file to get a detailed
understanding of how these macros are defined.
Parameter Description
name Contains the name of the MOUSERECT youve assigned to the rectangle.
helpid Contains the Help ID of the ToolTip message you want to appear when a mouse
cursor enters the rectangle. For foreign versions, the Help IDs point to localized
strings. There is currently no way to add more ToolTip IDs. For a complete list of
Help IDs, see the file HelpIDs.doc.
x, y Specifies the upper-left corner of the rectangle. For MOUSE_BEGIN, this value
will always be 0, 0.
MOUSE_END ends the definition of the rectangle. You can also create rectangles within
rectangles by using the capabilities of MOUSE_PARENT_* and MOUSE_CHILD_*.
44
Rectangles within Rectangles
You can also define sub-rectangles within the gauge rectangle using the MOUSE_PARENT and
MOUSE_PARENT_BEGIN macros. Both of these macros use the following parameters.
Parameter Description
x, y Specifies the X and Y position from the 0,0 position of the gauge.
Help ID Specifies the Help ID of the ToolTip text to display for the rectangle. For
foreign versions, the Help IDs point to localized strings. There is currently no
way to add more ToolTip IDs. For a complete list of Help IDs, see the file
HelpIDs.doc.
Generating Events
Parameter Description
45
Specifies under what conditions the event will be generated. It can be set to one
mouse_flags of the following values:
MOUSE_NONE
MOUSE_RIGHTSINGLE
MOUSE_MIDDLESINGLE
MOUSE_LEFTSINGLE
MOUSE_RIGHTDOUBLE
MOUSE_MIDDLEDOUBLE
MOUSE_LEFTDOUBLE
MOUSE_RIGHTDRAG
MOUSE_MIDDLEDRAG
MOUSE_LEFTDRAG
MOUSE_MOVE
MOUSE_DOWN_REPEAT
MOUSE_KEYBOARD
event_id Specifies the event to be sent to Flight Simulator 2004 by the mouse event. For
a complete list of events, see the associated file EventIDs.doc.
The following is an example of mouse rectangle setup code that generates the
KEY_FLAPS_DECR and KEY_FLAPS_INCR events:
MOUSE_BEGIN(mouse_rect, HELPID_B737_FLAPS, 0, 0)
MOUSE_CHILD_EVENT(0,0,44,85, CURSOR_DOWNARROW, MOUSE_LEFTSINGLE,
KEY_FLAPS_DECR)
MOUSE_CHILD_EVENT(44,0,44,85, CURSOR_UPARROW, MOUSE_LEFTSINGLE,
KEY_FLAPS_INCR)
MOUSE_END
46
Using Callback Functions
You can use the MOUSE_CHILD_FUNCT macro to specify a callback function when an event
specified by the mouse_flags parameter is triggered. You will need to define the callback
function with the mouse_child_funct function. The trigger_key_event and
panel_window_toggle functions are often used in the mouse event callback functions.
For specific information, see their descriptions in the Functions section below.
Parameter Description
function Specifies the callback function executed by the mouse event. You must define
47
this function using mouse_child_funct.
48
Heres a code snippet showing how youd use the MOUSE_CHILD_FUNCT macro to designate
a callback function:
The SDK.FlightMap.c file contains the following code example of how you can use dynamic
ToolTips (i.e., ToolTips whose text changes depending on the state of the gauge):
MOUSE_TOOLTIP_TEXT_STRING (
"Ground Speed: %1!d! knots, Track: %2!d!, Next Waypoint: %3!s!, Distance:
%4!.1f! nm", GPS_Args)
The first argument in MOUSE_TOOLTIP_TEXT_STRING above is the ToolTip text. Note that
changeable parts of the ToolTip text are specified by constructs such as %1!d!. These
constructs always start with a percent sign (%), followed by the argument number (in the
arguments array, GPS_Args). The argument number starts at 1 and increases sequentially. This
argument number is followed by a formatting argument. The formatting argument is placed
between exclamation marks (!), for example, !d!. This formatting argument is similar to the
arguments of the printf function (from the C Standard Library), where d (in the formatting
argument) prints an integer and f (in printf) prints a floating point number.
GPS_Args, in the code example above, is the name of the arguments array. The code below,
taken from the sample file, illustrates how this array is defined.
MOUSE_TOOLTIP_ARGS (GPS_Args)
MOUSE_TOOLTIP_ARG (MODULE_VAR_NONE, 0, NULL, NULL, NULL,
GPSARG_Get_GroundSpeed, NULL, NULL)
MOUSE_TOOLTIP_ARG (MODULE_VAR_NONE, 0, NULL, NULL, NULL,
GPSARG_Get_Track, NULL, NULL)
MOUSE_TOOLTIP_ARG (MODULE_VAR_NONE, 0, NULL, NULL, NULL, NULL, NULL,
GPSARG_Get_WP_ID)
MOUSE_TOOLTIP_ARG (MODULE_VAR_NONE, 0, NULL, NULL, NULL,
GPSARG_Get_WP_Distance, NULL, NULL)
MOUSE_TOOLTIP_ARGS_END
49
Arguments in the MOUSE_TOOLTIP_ARG macro follow this order:
First, the MODULE_VAR enum, which defines a module variable from which to get the
value.
Second, the scaling number, i.e., the numeric value of the module variable to be multiplied
by.
Next, pointers to three different lookup tables. If you dont want to use them, just use NULL
pointers.
All functions have the same argument but have a return result of different types. The arguments
are:
The numeric value of the module variable after scaling and lookup in the numeric lookup
table.
The id, which is the value from the id lookup table.
The pointer to the MODULE_VAR structure initialized to the first argument of the
MOUSE_TOOLTIP_ARG macro.
These functions can return: a numeric value, used together with numeric formats d or f; the
id value used as a HELPID enum by Flight Simulator; or a string value used with s format. For
details, see the SDK.FlightMap.c example.
Once youve finished defining the mouse rectangle(s) for your gauges, you can compile the files
and start the process of testing, debugging, and rebuildinguntil you wind up with gauges
youre happy with. You can create gauges using the Visual C++ compiler, version 4.0 or later.
The process used for compiling gauges with other compilers should be similar.
1. Before you start compiling your files, make sure your Visual C++ environment variables and
paths are set up correctly.
2. Change to the sample directory (\sample) and type nmake. This will build the Sdk.gau file,
which includes six different gauges you can place on a single panel.
50
4. Make sure you have the Panel.cfg file properly set up with the gauges positioned where you
want them.
5. Make sure you have your aircrafts Container system properly configured, i.e., pointing to
the right .air file, panel folder, etc.
6. Start Flight Simulator 2004, load your aircraft, and check out your new panel.
51
Using Token Variables
Gauges have access to information about the Flight Simulator simulation state. You can access
state information through a set of token variables. A complete list of token variables is available
in the file TokenVar.doc in this SDK.
The state information provided to the token variables depends on the aircrafts .air file. Each .air
file that ships with Flight Simulator 2004 provides access to different token variables. For
example, the Cessna 182 provides access to GROUND_ALTITUDE, as does every other
aircraft. The Cessna 182, however, doesnt provide access to the
TURB_ENGINE_1_VIBRATION variable because the Cessna 182s .air file specifies that this
aircraft has a reciprocating engine, not a turbine engine.
Therefore, its important to make sure that the .air file youre using for your aircraft and gauges
supports the token variables those gauges require.
UNIVERSAL_VAR Types
Each token variable returns a specific type of data. The following structure shows how the
UNIVERSAL_VAR variable is defined and the types that could be returned:
For a table of available module variables, see the file TokenVar.doc. The table lists the module
variable name and description. It also specifies which UNIVERSAL_VAR union member to use
with each variable.
Through the Panel API. For more information, see the following procedure.
52
To access a tokenized variable through the Panel API
2. To update the contents of the variable from Flight Simulator 2004 state information, use
lookup_var:
lookup_var(PMODULE_VAR module_var )
After the lookup_var function is called, the value of a MODULE_VAR variable is stored in the
var_value member of the structure.
Important: Token variables are read-only. Any attempt to set these variables through the
var_ptr variable may result in program crashes and incompatibility with future versions of
Flight Simulator.
The following code example shows how the MODULE_VAR variable is used. Note that this is a
callback function and, in this specific example, it is for a sprite element.
53
Gauge Macros and Drawing Elements
Each of the Gauge macros makes use of the drawing elements available in Flight Simulator
2004. These drawing elements are part of the macro definition in Gauges.h. Heres each macro
and its associated element.
MAKE_STATIC ELEMENT_STATIC_IMAGE
MAKE_NEEDLE ELEMENT_NEEDLE
MAKE_STRING ELEMENT_STRING
MAKE_SLIDER ELEMENT_SLIDER
MAKE_ICON ELEMENT_ICON
MAKE_MOVING ELEMENT_MOVING_IMAGE
MAKE_SPRITE ELEMENT_SPRITE
Each macro has twelve shared data elements, which aren't included in the declaration of each
structure. Instead, a #define HEADER is present that, when expanded, produces the twelve data
members. The following code examples show the drawing element ELEMENT_NEEDLE before
and after expansion.
Before expansion:
After expansion:
54
struct ELEMENT_HEADER next_element;
PFAILURE_RECORD failure_systems;
FLAGS image_flags;
FLAGS aircraft_special_instrumentation;
FLAGS reserved;
'Needle-specific data members.
};
55
Drawing Element Header
The first twelve data members are the same for all the drawing element structures. The data
members are described in the following table.
Member Description
Specifies the element type. Set this member to be one of the following
element_type elements:
ELEMENT_TYPE_STATIC_IMAGE
ELEMENT_TYPE_NEEDLE
ELEMENT_TYPE_STRING
ELEMENT_TYPE_SLIDER
ELEMENT_TYPE_ICON
ELEMENT_TYPE_MOVING_IMAGE
ELEMENT_TYPE_SPRITE
position Specifies the point that the drawing element pivots around. This value is
used by ELEMENT_NEEDLE and ELEMENT_SPRITE and ignored by
the other elements.
previous_position Specifies the previous position of the element relative to the gauge
position. Used by the Panel system. This value is ignored during
initialization.
ofs Specifies an offset (pivot point) for an element to rotate around. This
value is used by ELEMENT_NEEDLE and ELEMENT_SPRITE and
ignored by the other elements.
previous_element Points to the previous element. This value is set by the Panel system. This
value is ignored during initialization.
next_element Points to a list of graphical elements. The elements are drawn after the
current element. This value is used to determine the drawing order of all
the elements in your gauge.
56
Specifies how the element image will be rendered. This member can be a
image_flags combination of the following values:
IMAGE_USE_TRANSPARENCY - Renders the image using
transparency. If this flag is set, RGB color (0,0,0) is treated as
transparent in a 24-bit bitmap. Because non-transparent rendering is
faster than transparent rendering, you can use this flag to enhance
performance.
IMAGE_USE_ERASE - Before the graphical element is rendered, a
"snapshot" of the background is saved. As a result, the Panel system
can erase the element as needed by plotting the contents of the save
buffer to the screen. You can use this flag to increase performance and
save memory if an element never needs to be erased. Static images use
this flag extensively.
IMAGE_USE_BRIGHT - Maps the elements image colors to the
section of the Flight Simulator 2004 palette that doesn't change during
the transition from day to night. The image colors will not change.
IMAGE_NO_STATIC_BLENDING - This flag is only valid on static
images using IMAGE_USE_TRANSPARENCY and the first element
in the list.
IMAGE_USE_ALPHA The image contains alpha channel.
IMAGE_USE_LUMINOUS The image is bright when the interior
light is on.
IMAGE_USE_LUMINOUS_PARTIAL - Parts of the image are lit by
interior light (alpha channel).
IMAGE_HIDDEN_TREE - You can set this flag dynamically to hide
or show the element and all elements in the resource tree above it.
IMAGE_HIDDEN - You can set this flag dynamically to hide or
show the element.
Specifies how the element will react in a special instrument situation.
aircraft_special_ Currently this is used only with autopilot. This member can have the
instrumentation following values:
ASI_ALT_MANUALLY_TUNABLE - Sets a global flag that causes
Flight Simulator 2004 to recognize that autopilot altitude hold is
manually tunable. If this flag isn't set, turning on altitude hold
maintains the current altitude instead of the currently set altitude.
ASI_HEADING_MANUALLY_TUNABLE
Sets a global flag that causes Flight Simulator 2004 to recognize that
autopilot heading hold is manually tunable. If this flag isn't set, turning
on heading hold would maintain the current heading instead of the
currently set heading.
57
Drawing Element Structures
Each drawing element structure has one or more MODULE_VAR members. You can initialize
these members to one of the token variable values. Call the function element_install or
element_list_install to initialize the MODULE_VAR element(s).
The element_update or element_list_update function can be used to update the contents of the
MODULE_VAR. The elements themselves use the MODULE_VAR information at render time
to determine in what state they'll be rendered.
Graphical elements can use the MODULE_VAR structure member to determine the state in
which the element will be rendered. Sometimes, however, MODULE_VAR may not be a useful
value. You can get around this problem by using callbacks. For each of the MODULE_VAR
structures listed in the element structure, you can set an associated PMODULE_VAR_CB
pointer. The pointer points to a callback function that you can use to set the variable to a useful
value. The callback function is called by the Panel system after the variable has been updated
from the simulation state information. The callback function is generally used to normalize or
scale the MODULE_VAR value into a valid range. You can also use the callback function to
convert enumerated values, interpret a flag's variable, and so on.
For example, the following code uses a callback routine to clip the airspeed to a useful range that
can be used by the airspeed gauge. All elements use the same style callback routine in which the
argument to the function acts as a pointer to that element.
You can set any callback pointer to NULL so that no call will occur.
NOTE: Any assignments to the MODULE_VAR in a callback routine are discarded. The final
value set in MODULE_VAR is the return value of the callback function.
58
Drawing Element Lists
In code, the drawing elements are organized (using the next_element data member) in a tree
structure (the element list). This element list defines the drawing order of the gauge elements:
The first element in the list in the gauge header is drawn first.
Each subsequent element in the list is drawn in the order it appears in the list.
Before drawing the next element in the list, the current elements element-list pointer is
examined. If the pointer is not NULL, the elements element list is drawn using the same
logic.
You don't need to set the previous_element pointer. This pointer is initialized by the Panel
system when the gauge is initialized.
MAKE_STATIC
The MAKE_STATIC macro draws the simplest type of graphical element. Use MAKE_STATIC
to draw an image that never changes.
59
And heres the code fragment from Control_surfaces.c that uses MAKE_STATIC:
MAKE_STATIC
(
cs_background,
BMP_CS_SMALL_BACKGROUND,
&cs_sliders_list,
NULL,
IMAGE_USE_TRANSPARENCY,
0,
0,0
)
RES_ID BMP_CS_SMALL_ Contains the name of the resource file used by the
BACKGROUND macro as identified earlier by SDK.h.
NEXT_LIST &cs_sliders_list Sets the order in which parts of the gauge get
drawn. The example identifies the sliders.
DRAW_FLAGS IMAGE_USE_ Sets how the bitmap will display. These flags are
TRANSPARENCY the same for all macros.
Specifies whether to capture the current value of
ASI_FLAGS 0 the Altitude or Heading. This is a bitwise field
that Turns ON or OFF. If you set this field to 0,
Altitude and Heading will be manually tunable.
Valid entries are:
ASI_ALT_MANUALLY_TUNABLE
ASI_HEADING_MANUALLY_TUNABLE
60
61
MAKE_NEEDLE
Use MAKE_NEEDLE to draw an image that pivots around a specific point in another image.
MAKE_NEEDLE supports transparency and nonlinear gauges. For MAKE_NEEDLE, POS
(position) is the center of rotation in the background image; OFS (offset) is the center of rotation
in the needle image.
And heres the code fragment from SDK.fuel.c that uses this macro:
MAKE_NEEDLE
(
fuel_needle,
BMP_FUEL_SMALL_NEEDLE,
NULL,
fuel_fail,
IMAGE_USE_TRANSPARENCY | IMAGE_USE_ERASE,
0,
150, 150,
6, 12,
FUEL_QUANTITY_CENTER,fuel_needle_cb,
fuel_nonlinearity,
6
)
63
DRAW_FLAGS IMAGE_USE_ Sets how the bitmap will display. These
TRANSPARENCY | flags are the same for all macros.
IMAGE_USE_ERASE
Specifies whether to capture the current
ASI_FLAGS 0 value of the Altitude or Heading. This is
a bitwise field that Turns ON or OFF. If
you set it to 0, then Altitude and
Heading will be manually tunable. Valid
entries are:
ASI_ALT_MANUALLY_
TUNABLE
ASI_HEADING_MANUALLY_
TUNABLE
64
Using Non-Linearity Tables
In some cases, you might want a needle to move in a nonlinear manner. For example, an airspeed
gauge sometimes shows a greater angle between 0 and 50 knots than the angle between 100 and
150 knots. You can specify this behavior by using a non-linearity table.
Member Description
degrees Used internally by the Panel system: do not use. Must be set to 0.
In SDK.Fuel.c, the linearity table deals with the fuel quantity, which ranges from 0 to 75. Heres
the non-linearity table it uses:
NONLINEARITY fuel_nonlinearity[] =
{
{{30, 182}, 0, 0},
{{119, 47}, 25, 0},
{{246, 93}, 50, 0},
{{241, 221}, 75, 0}
};
At runtime, the value of the needle is examined and the angle to be drawn is interpolated from
the non-linearity table.
Values are listed in the table as they appear on the gauge (clockwise around the face). If gauge
values increase when rotating clockwise, values in the non-linearity table will start at the
minimum and increase. If gauge values decrease when rotating clockwise, then values in the
table will start with the maximum and decrease.
65
MAKE_STRING
Heres the code fragment from SDK.Temperature.c that uses the MAKE_STRING macro:
MAKE_STRING
(
temperature_string,
NULL,
temperature_fail,
IMAGE_USE_ERASE | IMAGE_USE_BRIGHT,
0,
28, 9,
60, 29,
3,
TOTAL_AIR_TEMP,
DISPLAY_UNITS,
MODULE_VAR_NONE,
RGB(255,0,0),
RGB(0,0,0),
RGB(92,92,92),
GAUGE_FONT_DEFAULT,
GAUGE_WEIGHT_DEFAULT,
GAUGE_CHARSET,
0,
DT_CENTER | DT_VCENTER | DT_SINGLELINE,
NULL,
temperature_string_cb
)
66
The following table explains the different fields in MAKE_STRING.
67
SOURCE_VAR_2 DISPLAY_UNITS Used to look up multiple token variables
to update the string. (e.g., Hours,
Minutes, Seconds). Sequence them
inside the callback function.
68
BACKCOLOR RGB(0,0,0), Defines the background color of the
string display.
Value Weight
FW_DONTCARE 0
FW_THIN 100
FW_EXTRALIGHT 200
FW_ULTRALIGHT 200
FW_LIGHT 300
FW_NORMAL 400
FW_REGULAR 400
FW_MEDIUM 500
FW_SEMIBOLD 600
FW_DEMIBOLD 600
FW_BOLD 700
FW_EXTRABOLD 800
FW_ULTRABOLD 800
FW_HEAVY 900
FW_BLACK 900
69
FONT_CHARSET GAUGE_CHARSET Specifies the font character set for the
string. A list of valid values can be
found in the CreateFont Win32 API.
70
Sets how to draw the text. There are
DRAW_TEXT_ DT_CENTER | three valid entries:
FLAGS DT_VCENTER | DT_CENTER
DT_SINGLELINE DT_VCENTER
DT_SINGLELINE
71
Defining the Font Type
To define the font type you must place #define statements (after the initial #include) in your
gauge code. For example, SDK.Temperature.c looks like this:
The first line in the code above is the default character set for English (UK and US). Most
instruments are labeled in English.
The second line defines the font set name. You want to define a font that will, with almost
certainty, exist on your users PC. Therefore, choose one of the following fonts: Courier New,
Arial, Times New Roman, or Helvetica.
The third line defines how the font will display. Here are the available options:
FW_THINFW_EXTRALIGHT
FW_LIGHT
FW_NORMAL
FW_MEDIUM
FW_SEMIBOLD
FW_BOLD
FW_EXTRABOLD
FW_HEAVY
72
Selecting a String by KEY_EVENT
You can use the SEQ_REC table to select a string automatically on certain KEY_EVENTs.
Flight Simulator 2004 allows the user to select certain gauge elements by using different
keyboard combinations. The SEQ_REC structure sets up the relationship between the current
selection state and the characters that can be selected for that state. The following code example
shows the SEQ_REC structure definition:
Member Description
sel_str Specifies the first character to select when the Flight Simulator 2004 selection state is
equal to the seq_id state.
To mark the end of the array you must add one blank record that sets seq_id, sel_str, and
sel_end to SELECT_NONE, 0, and 0, respectively. The following code example shows a sample
SEQ_REC definition:
SEQ_REC seq_com[] =
{
{SELECT_COM_WHOLE, 0, 2},
{SELECT_COM_FRACTION, 4, 5},
{SELECT_NONE, 0, 0}
};
The following table includes the gauge selection states available in Flight Simulator 2004.
SELECT_NONE No selection
SELECT_1 Unused
SELECT_ZOOM Zoom
SELECT_MAGNETO Magneto
73
SELECT_COM_WHOLE Communication frequency, whole number
75
MAKE_SLIDER
Use MAKE_SLIDER to move a drawing element around a gauge on the X and Y axes.
You can use MAKE_SLIDER to move an image in only one direction as well. Just set the
MODULE_VAR, for either X or Y, to MODULE_VAR_NONE.
Youll need to fill this structure out with slider-specific information, such as the following from
SDK.Control_Surfaces.c:
MAKE_SLIDER
(
cs_slider_trim,
BMP_CS_SMALL_TRIM,
NULL,
0,
IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY,
0,
20,44,
MODULE_VAR_NONE, NULL, 0,
ELEVATOR_TRIM, NULL, -100
)
76
The following table explains the different fields in MAKE_SLIDER.
77
Set the X or Y axis (you can move a
SOURCE_VAR_X, MODULE_VAR slider on the X or Y axis).
CALLBACK_X, _NONE, SOURCE_VAR_X identifies the
SCALE_X NULL, token variable the slider will use.
0 Since Trim only goes up and
down, theres no token variable so
use MODULE_VAR_NONE.
CALLBACK_X identifies the
modifying callback if any. None is
needed so set to NULL.
SCALE_X sets the scaling value
for the range of X-axis movement
of the variable across the
background image. Here its 0. A
slider moves from left to right
unless this value is preceded by a
minus (-) sign.
Set Y-axis values. Here the Trim slider
SOURCE_VAR_Y, ELEVATOR_TR does move on the Y-axis.
CALLBACK_Y, IM, SOURCE_VAR_Y uses the
SCALE_Y NULL, ELEVATOR_TRIM token
-100 variable. See the discussion of
token variables later in this
section.
CALLBACK_Y identifies the
modifying callback, which isnt
used here.
SCALE_Y is the scaling value of
the Y-axis movement of the slider
across the background image.
Divide the token variable value
returned by the range of movement
in pixels, and then multiply by the
units of measure. A slider moves
from left to right unless this value
is preceded by a minus (-) sign.
78
MAKE_MOVING
Youll need to fill this structure out with specific information, such as the following from
SDK.Wiskey.c:
MAKE_MOVING
(
wiskey_moving_card,
BMP_COMPASS_SMALL_CARD,
NULL,
wiskey_fail,
IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY,
0,
22,41,
WHISKEY_COMPASS_DEGREES, wiskey_moving_card_x_cb,
0, 360,
MODULE_VAR_NONE, wiskey_moving_card_y_cb,
0, 0
)
When you specify a mask with MAKE_MOVING, youre actually specifying the area within
which another part of the gauge can move and appear. Once that other part moves outside of that
area (as defined by MIN_X, MAX_X, MIN_Y, and MAX_Y) it wont display. These fields
identify the top left and bottom right corners of this area within the gauge background.
80
MAKE_ICON
Use MAKE_ICON to toggle between one of several images at a static location on a gauge. The
RES_ID member of the structure specifies the first icon image. The Panel system loads the first
icon image using RES_ID. The Panel system loads the next icon image by adding 1 to the
RES_ID. It then adds 1 more to RES_ID and loads the next image, and so on. The Panel system
continues this process as many times as NUM_ICONS specifies.
Icon images can be any size, although all images in the same MAKE_ICON have the same upper
left location.
Tip: If you specify IMAGE_USE_ERASE in the image flags for MAKE_ICON, the save buffer
will only be as large as the first image.
Youll need to fill this structure out with specific information, such as the following from
SDK.Fuel_Selector.c:
MAKE_ICON
(
fuel_selector_icon,
BMP_FUEL_SELECTOR_OFF,
NULL,
NULL,
IMAGE_USE_ERASE | IMAGE_USE_TRANSPARENCY,
0,
0,0,
FUEL_TANK_SELECTOR,fuel_selector_icon_cb,
ICON_SWITCH_TYPE_STEP_TO,
4,
0,
0
)
81
The following table explains the different fields in MAKE_ICON.
NEXT_LIST NULL Sets the order in which parts of the gauge get
drawn.
83
4
NUM_ICONS Specifies the number of icon bitmaps in the
gauge.
0 Specifies the scale of the icon. This value is
SCALE only used if SWITCH_TYPE is:
ICON_SWITCH_TYPE_SET_CUR_
USING_RANGE
or
ICON_SWITCH_TYPE_STEP_TO_
USING_RANGE
0 Specifies the offset of the icon. This value is
OFFSET only used if switch type is:
ICON_SWITCH_TYPE_SET_CUR_
USING_RANGE
or
ICON_SWITCH_TYPE_STEP_TO_
USING_RANGE
MAKE_SPRITE
Textures used for ELEMENT_SPRITE must be 256 x 256. When the gauge is loaded, the
RES_ID specifies the image to use for the texture. RES_ID + 1 specifies the mask image. The
mask doesn't have to be a specific size. The mask is placed on the gauge using the position
member. The texture slides and rotates underneath the mask.
84
Heres the MAKE_SPRITE structure as defined in Gauges.h:
Youll need to fill this structure out with specific information, such as the following from
SDK.Attitude.c:
MAKE_SPRITE
(
attitude_sprite_outer,
BMP_ATTITUDE_SMALL_CARD2,
NULL,
(PFAILURE_RECORD)&attitude_fail,
IMAGE_USE_TRANSPARENCY,
0,
16, 13,
137,134,
1.05, 1.05,
MODULE_VAR_NONE, NULL, 0,
MODULE_VAR_NONE, NULL, 0,
ATTITUDE_INDICATOR_BANK_DEGREES, NULL, -1
)
85
The following table explains the different fields in MAKE_SPRITE.
87
Drawing Element Macros
The following macros have been defined to manipulate drawing elements:
Functions
The following functions can be used in combination with various gauge and mouse rectangle
macros.
initialize_var
The initialize_var function initializes a token variable. Before a token variable can be used, you
must initialize it with initialize_var.
Syntax
initialize_var(PMODULE_VAR module_var)
88
Parameters
Parameter Description
PMODULE_VAR module_var Required. Pointer to a token variable to initialize.
Example
lookup_var
The lookup_var function updates the contents of a token variable. Before using the contents of
module_var, you must call the lookup_var function.
Syntax
lookup_var(PMODULE_VAR module_var)
Parameters
Parameter Description
PMODULE_VAR module_var Required. Pointer to a token variable to update.
Example
89
mouse_child_funct
Syntax
Parameters
Parameter Description
Specifies the point in the gauge that was clicked.
PPIXPOINT
relative_point
Returns one of the following mouse events:
FLAGS32 MOUSE_NONE
mouse_flags MOUSE_RIGHTSINGLE
MOUSE_MIDDLESINGLE
MOUSE_LEFTSINGLE
MOUSE_RIGHTDOUBLE
MOUSE_MIDDLEDOUBLE
MOUSE_LEFTDOUBLE
MOUSE_RIGHTDRAG
MOUSE_MIDDLEDRAG
MOUSE_LEFTDRAG
MOUSE_MOVE
MOUSE_DOWN_REPEAT
MOUSE_KEYBOARD
Return Values
90
Example
MOUSE_FUNCTION mouse_hdg_cb;
panel_window_toggle
Syntax
Parameters
Parameter Description
UINT32 panel_id Specifies the identification number of the window to toggle. The
identification number is specified in the Panel.cfg file in the [WindowXX]
section by the variable ident.
Return Values
0 Returns 0 if the window specified by panel_id exists and its visibility state
is successfully changed.
91
Non-zero Returns a non-zero number if there is an error.
92
Example
Token Variables
The token variables used by the Gauge system can be found in the associated file TokenVars.doc
in this SDK.
Help IDs
The Help IDs, as well as string table text associated with each Help ID, used by the Panel system
can be found in the associated file HelpIDs.doc in this SDK.
Event IDs
The Event IDs used by the Panel system can be found in the associated file EventIDs.doc in this
SDK.
93
Using Named Variables to Enable
Communication Between Gauges
You can use named variables to enable communication between two or more gauges. To
establish communication between gauges, need both server and client gauges. The terms
server and client just distinguish between variable ownership and variable usage:
The server gauge(s) provides one or more named variables for other gauges to access.
The client gauge(s) accesses one or more named variables from the server gauge(s).
A single gauge can be both a server (by providing one or more variables) and a client (by
accessing another gauge's variables) at the same time.
Syntax
Parameters
Parameter Description
PSTRINGZ name Specifies the name of the variable. Specify a unique and
descriptive name for the variable, such as
gaugename.variablename.
Parameter Description
94
PSTRINGZ name Specifies the name of the variable.
95
The initialize_var_by_name syntax has these parameters.
Parameter Description
PSTRINGZ name Specifies the name of the variable (the same name used in
register_var_by_name).
Remarks
When using named variables, dont call the lookup_var function (as you would with the
standard panel system variables). After initialize_var_by_name is called, the var_ptr field of the
MODULE_VAR structure contains a pointer to the named variable. The Panel system doesnt
recognize named variables, per se, but the system does maintain the name to the pointer link for
gauges to query. As a result, you cant use a named variable as a controlling variable for an
ELEMENT structure directly. Instead, use a MODULE_VAR_NONE structure and provide a
callback function that can query the variables value using the var_ptr field of the
MODULE_VAR structure.
Because named variables "work" via direct pointers between gauges, make sure that the server
gauge is loaded before, or at the same time as, the client gauge. You can make sure this happens
by either putting both gauges on the same panel window or by putting the server gauge on the
main panel window. This ensures that the server gauge is loaded and the named variable is
registered before the client gauge tries to connect to it.
Alternatively, you can check the returned var_ptr for NULL and the returned var_type (both in
the MODULE_VAR structure) for VAR_TYPE_NONE and execute (in the ELEMENT callback
function) the initialize_var_by_name function until it returns valid information. (You can also
call the initialize_var_by_name function every time you want to access the variable, but this
approach is a little slower than caching the information once it's received.). The server gauge
must keep checking the current value of the variable(s) it has made available, if the current
state/value of that variable has any effect.
You can use named variables at any point in the simulation when you want to pass information
between two or more gauges. Because named variables are shared by direct pointer access, you
can also "share out" an entire data structure using one named variable, as long as the server and
client gauges interpret the same data format.
You can place these gauges anywhere on a panel, as long as the server gauge is guaranteed to
load before or at the same time as the client gauge.
96
XML Gauges
Flight Simulator 2002 introduced a new kind of gauge, the XML gauge. If you look in the
\gauges subdirectory of the Flight Simulator 2004 directory you will find files with .cab
extensions (for example, Boeing747-400.cab). These .cab files contain XML gauges. Inside each
.cab file are compressed .xml and .bmp files; the .bmp files contain the art for the gauge and
the .xml files contain descriptions of the gauge.
Although an .xml file is a text file, it is best if you use a specialized XML editor to create and
edit these files. This SDK includes two files, Gauges.dtd and Gauges.xdr, which are very useful
if your XML editor supports schemas. You can use these files as a resource for all possible XML
fields and types of their values.
1. The first part provides generic information about the gauge: its name, its background image,
and its size .
2. The second part of the XML gauge is a list of elements of the gauge (marked by <Element>
tags). Each element is an image or a text string.
3. The third part of the XML gauge describes the gauges mouse rectangles.
The <Element> element is the core element in an .xml file. Each <Element >describes a part of
the gauge, be it a needle, a switch, or a drum with numbers. The <Element> starts with an image
or a text string. The <Image> element contains a Name attribute, which is the name of a .bmp
file. You can provide a single .bmp file packed in the same .cab file, or you can use two files for
different resolutions. Both .bmp files should have the same name, but they reside in different
subdirectories. For example, the file for low resolution would reside in the \1024\ folder and the
file for high resolution would reside in the \1280\ folder.
The gauge image is transformed by different XML elements. For example, <Visible> specifies
when the element is visible and <Rotate> rotates the element accordingly. (For examples, see
\gauges\ boeing747-400.cab\Primary Flight Display.xml.)
All these transformations have a <Value> element. This element specifies the source value,
which dictates by how much to transform the element. For example:
<Rotate>
<Value>(A:Plane heading degrees gyro, radians) /-/</Value>
</Rotate>
97
Calculated Expressions in XML Gauges
<Rotate>
...
<Value>(A:Indicated Altitude, feet)</value>
</Rotate>
E Environment You can get the current time from this parameter.
P Program related You can get the simulation rate from this parameter.
K Key code Variables of this kind are key codes that are sent from
gauges to Flight Simulator.
M Mouse variables This parameter reports the state of the mouse for use in
mouse click handlers.
For more information on possible parameters for A, E and P see the Parameters.doc
document in this SDK. A unit name is required after the parameter name. For
the list of recognizable unit names go to Units.doc document in this SDK.
Parameters of the G kind have names of Var1, Var2, Var9, etc. They give you the
values you assign to them. Dont put unit names after them.
Use your own names for parameters of L kind. Use unit names after them.
For more information on parameters of the K kind, see the EventIDs.doc document
in this SDK. Do not use unit names after these parameters.
98
Parameters of the M kind are:
Event the string representation of the event which triggered the mouse handler.
Examples of the string event are LeftSingle, RightDouble, MiddleDrag, Move, and
LeftRelease.
If you want a gauge to show altitude in thousands of feet, divide the value of the Indicated
Altitude parameter by 1000. For example:
To execute an arithmetic operation, put both operands first in the markup language
((A:Indicated Altitude, feet) and 1000 in the code above) and then include the symbol
of operation (/). This is how some programmable calculators performed arithmetic operations in
the past.
This convention works the following way: When the parser sees the first operand, it pushes that
operand onto the top of the internal stack. The parser then pushes the second operand onto the
stack. When the parser reaches the operation symbol, both operands are popped from the stack,
the operation is performed, and the result is pushed back onto the stack. Whatever value is on top
of the stack at the end of the execution is the result of the calculated expression.
There are a number of operations that you can use in calculated expressions. The following
sections list the operators youd use for various operations.
Common Operators
Some operators, like those in the following table, are well known to programmers.
Operator Operation
+ addition
- subtraction
/ division
* multiplication
% taking modulo
Comparison Operators
== true if equal
Bit Operators
&
|
>>
<<
Logical Operators
!
&&
||
Numerical Operators
100
asin eps log pi sqrt
atg
The following numerical functions are not obvious and require some explanation.
Operator Operation
flr Calculates nearest integer number which is less than the source number.
ceil Calculates nearest integer number which is bigger than the source.
rnor Normalizes an angle expressed in radians. The result of this operation is between
0 and 2.
rdeg Normalizes an angle expressed in degrees. The result of this operation is between
0 and 360.
101
String Operators
Operator Operation
To push a string into the stack, put the string between apostrophes (for example: LeftSingle).
The ? and case operators are selective operations. The third operand of the ? operation
defines which operand, first or second, is the result of the operation.
Stack Operators
The following set of operations enables you to work with the stack.
Operator Operation
l0, l1, l49 Loads values from the registers on the top of stack.
sp0, sp1, sp49 Stores the top value and pops it from the stack.
103
Order of Execution for Operators
The if{ facility pops the top value from the stack and, if its a true
value, executes operations between if{ and }. Note: there is no space
between if and {. The els{ operation follows, closing } of the
if{ operation. The els{ operation lets operations between els{ and
} execute only when the operand of the if{ operation evaluates to
false.
The goto facilities consist of the g0, g1, g2, g<any number> operation, which
jumps execution flow to the corresponding label. The :0, :1, :2, :<any number>
operation defines those labels.
104
Appendix A: Tips on Creating Art for Panels
and Gauges
This Appendix provides some general guidelines you might find useful as you create artwork for
your panels and gauges. It assumes you have some general familiarity with graphic design and
associated tools.
Background
In Flight Simulator 2004 2-D art is used to represent the aircraft panels in non-virtual cockpit
mode. The panel is broken down into many files stacked on top of one another. The cockpit
background is a separate bitmap that has the individual gauges placed over it. Currently, the
shadows of the gauges are placed on the panel background. The gauges themselves are not
realistically three-dimensional and do not represent accurate depth relationships. This limitation
is deliberate because it gives you the ability to position the gauges on the panel wherever you
prefer.
The most important feature of a Panel system is its readability. The panel should not only be
convincing, but it must look acceptable at any resolution.
Before beginning work on a panel, you should have a good understanding of what you will be
working on. Familiarize yourself with the aircraft and its capabilities. Gather as much
information as possible on the panel.
Once you have gone through the reference material for the plane, compare the panel with those
of other aircraft. You will always have to create the background of the specific cockpit, but
sometimes you can use gauges from a different panel. These gauges may resemble the gauges for
your aircraft even though they are not an exact replica. Originality is always important, but
sometimes choosing a generic gauge background or a set of type can save you an hour or two.
105
Creating a Layout for the Panel
Researching the Instruments
Now start thinking about the look and feel of the cockpit. Find out which instruments you should
include in the layout. Create a priority list of instruments and go through it with anyone with
knowledge about whats important to include in the cockpit. Talk with pilots and get an idea of
what people want to see. Unless you know a fair amount about aviation, you may overlook
something that is critical for efficient flight/navigation.
Once you have a list of what needs to be included on the panel, create a layout of what the panel
is going to look like. The layout can be the most difficult part of creating a panel. However, the
goal of the layout is very simple: you want the panel to retain its original look and feel while
allowing the most space for instruments. Even a few pixels can make a difference when making
room for instruments. Make sure that all the instruments stay in proportion to each other and
with the panel background. Remember, this is only a layout and it can look a little rough. Some
artists like to create layouts by drawing them,. while others find that cutting and pasting the raw
photographs in a program like Photoshop is easier.
One concern you may have when you create a layout will be the height of the panel. A panel that
is too high will decrease visibility for the user. This was a major concern in the first version of
Microsoft Combat Flight Simulator, which depended on visibility for game play. It was therefore
decided that the panel height in Combat Flight Simulator would be 50 percent of the screen size.
This was a fair compromise between game play and usability of the panel. Flight Simulator 2004
is not so dependent on outside viewing, so creating a taller panel is acceptable if it is a better
representation of the real-world layout.
The slope of the panels sides is another thing to consider. If the sides are pitched too steep,
performance will be lost due to the larger 3-D window. Raising the 3-D window a few pixels can
increase performance. If the sides are not pitched very much, the panel will appear flat, without
dimension.
106
Beginning Production
Creating the Base Background
You may want to begin with the panel background. This piece of art can take a long time to
create, especially when it is your first or second panel. Make sure that you spend the time needed
in making the background seamless. Use layers to your advantage in creating depth.
If the photograph that you work with is too difficult to clean up, use flat colors to make the
backgrounds base. Then add a gradation, usually lighter on top to darker on the bottom, and
some sort of noise or texture to give more depth. You can often achieve similar results by
cleaning a background with filters and gradation.
Once the base has been established, add subtle depth and detail. Scratches, nicks and paint chips
can add a lot of character and realism to a panel. Over time, you may want to create a library of
such details. Apply them through the aid of opacity and layer options. Each case is different.
Experiment with what looks best.
After you have established the base background, begin working on how the side panels will
merge into the background. Often, you can place a seam or crack over the two layers, which
helps blend the two together. You can take these cracks or seams from any cockpit photograph;
otherwise, you may have better luck drawing a seam, although you may find that drawn cracks
often appear a bit too perfect.
Over the base background and sides will be the edge of the panel and its shadow.
Make the edge of the panel as thin as possible without sacrificing the cockpits character. A thin
edge can look wimpy, while a thick edge, as real as it may be, will be a waste of space. You may
want to keep these two elements as separate layers for flexibility in making changes later.
Shadows are usually between 50 percent and 60 percent opacity, which gives the panel depth but
does not create shadows that are too overpowering. The lighting in Flight Simulator typically
represents an overhead softer light source (e.g., a hazy day at noon). If you choose a direction of
light, note that it may not match the outside of the plane or landscape. Use your artistic judgment
to make these decisions.
When the panel background is close to complete, make a copy and compress it into an 8-bit file.
If banding occurs in the shadowed areas, you may have to lighten or darken the shadow to make
it look smooth. This, of course, will vary depending on which program you use to compress your
files into 8-bit.
107
Building the Gauges
Separating the Gauge Elements
When creating instrument gauges, try keeping as many elements separate as possible. This will
enable you to easily add library elements to your instrument without having to do a lot of work.
Youll probably find it useful to work in a larger size than that which the gauge will be resized
to. If appropriate, start with the original scanned photograph and work from a copy. This will be
helpful as you clean up the instrument and still need a reference.
The first thing to do is clean up the ring and background of the instrument.
Make sure the lighting remains even across the ring (with no hot spots from the lighting). Hot
spots give a false impression of where the sun is coming from.
Create a copy of the inside of the gauge (the gauge face) where the glass covers it, and make this
a separate layer.
Remove the inside of the gauge from the original layer to clean up the edge of the ring.
Now you can lighten or darken the gauge background without changing the tone of the inside.
Working on the inside the gauge face, remove the needle and make it into a separate layer.
Next, clean up the existing art, or lay down a color, then add a texture or noise on top to add
depth. You may want to apply a different clouds filter to the gauge face to make it look a little
more natural.
With the ring layer over the face layer, create a little drop shadow from the ring to add depth to
the gauge. Make sure this is on a separate layer for flexibility. You may want to add a light-black
Gausian-blurred ring over the gauge face to show that it has a round feel to it. These are subtle
features that add reality to the artwork.
Now create another layer. With the original raw photograph as a guide, draw the tick marks of
the instrument. Try to make these tick marks bright and readable so they stand out when you
resize the gauge later.
Finally, return to the needle layer and strip the needle from the background. Make sure that the
tonality of the needle does not blend into the new gauge face.
108
Compiling the Gauge
To compile your gauge, create another layer and merge all of the gauge elements, except for the
needle, into that layer, while retaining the existing elements. Once youve done this, you have a
compiled gauge and all of its elements and its separate needle are ready for resizing.
Note! Make sure that you save your work before you begin resizing. (If you need to make any
adjustments to the gauge, you can change the element and then re-merge that element onto the
compiled layer without having to repeat a lot of work.)
Make a copy of the compiled instrument layer and place this into a separate file.
Copy the needle into the new file to resize both at once.
Now, add the type to the gauge (referring to the larger original file for reference). Explore the
fonts on your computer and choose one that matches the typeface of the gauge.
Create another layer and merge the compiled gauge with the type layer. Sharpen this layer and
the needle layer. Save this file for any future adjustments.
Next, make the two layers into separate files. When making these separate files, clean up the
edges of the file by giving it an aliased edge. It will save time later when you compress the 24-bit
file to 8-bit.
Make the backgrounds of the files true black (0,0,0 RGB value). True black appears transparent
in the simulation.
Place these files into a separate folder, which represents the 1024 art ready for 8-bit conversion.
You can use a number of programs to palletize your artwork. Try several and choose the one that
works best for you. Note that different pieces of the artwork do not need to use the same palette;
each piece can use its own palette.
Once youve converted the files to 8-bit, save them as a separate file and place them in a folder
labeled Completed Art (or something that lets you know the art is ready for final use).
Check to see if pixels with the values of 0,0,0 and 1,1,1 are where they should be.
109
Creating a Final Composition
Once all the artwork is complete, assemble the artwork into a final composition for the entire
panel.
Double-check to see if there are any mistakes or if something doesnt look right. It is inevitable
that you will have to change something. Make the appropriate adjustments and then add the new
artwork to the final composition.
110
Appendix B Using Masks in Images
A mask image allows a gauge designer to create a hole in a layer (think gauge layer, not a
Photoshop .psd layer) so that a piece of the gauge can be seen through another piece.
Method 1: Specify a transparent area in a static image that also displays other things (for
example, tick marks and other graphics associated with a gauge).
Method 2: Create a mask image used solely to specify which area of its associated element to
display. This is similar to specifying a transparent area in a static image, except that no
visible graphics need to be associated with this type of mask.
Method 2
Note that the magenta used in the Mask Image is actually of RGB value 1,1,1 (very close to
black). When you see these images in drawing programs, they appear completely black.
111
The apparent advantage of using method 2 is size savings. A monochrome bitmap can be used to
generate mask image #2.
In the example above, the TAS card (the rotating bit) is actually ABOVE the background in the
Z-order, even though it appears to be behind the background.
Specifying Luminousity
The panel and gauge developer can specify three colors in the panel.cfg for Day, Night, and
Luminous. Day and Night effectively determine the maximum and minimum brightness of the
panel. Luminous specifies the color that can be applied to the luminous sections of the gauges.
Here is a somewhat extreme example to demonstrate what these colors mean. In this example,
the colors for day, night, and luminous are defined as red, green, and blue. Note the subtle
difference between Dusk and Night the environmental lighting conditions determine what
percentage of the day color to use.
Dusk
Night
In the example above (which happens to be the Extras airspeed gauge), the luminous section of
the gauge (in the middle) has the luminous color applied, which is blue (0, 0, 255). When lights
are off, no .cfg-specified color is applied to the panel and its gauges the brightness of the
images are affected, however, by the environmental lighting (such as the height of the sun in the
sky, moonlight, etc.).
Typically lighting effects get applied to an entire panel, but the LUMINOUS COLOR is applied
to the section of the gauge(s) specified by this alpha channel. The area of the image with the
alpha channel looks different when viewed with Photoshop or Imagetool:
In Photoshop, the area of the alpha channel that appears WHITE will have the luminous color
applied.
112
In Imagetool, the area of the alpha channel that appears BLACK will have the luminous color
applied.
When Imagetool displays the image (not the alpha channel) of the bitmap, it displays the area
that will have the luminous color applied as completely BLACK (which some may find
confusing as black typically indicates transparency).
Note: You can create images with an alpha channel using either Adobe Photoshop or
Corel Painter. Corel Painter supports greyscale alpha channels and will save as a .psd (with
an alpha channel).
If lights are off: use the environmental lighting value (an 8-bit value) to scale the r,g,b
components of that pixel. Thus only brightness, not tinting, is affected.
For the luminous section of the panel, the luminous color is only used if the
environmental lighting (sunlight, which depends on the time of day) is less than a certain
value, which happens around dusk. Thus, during the day the luminous color is not
applied to the panel at all.
At night, each pixel is scaled by the luminous color specified in the panel.cfg. That is,
each RGB component of each pixel is scaled by the luminous color. For example, the red
component of a pixel would be changed to the current red value, multiplied by the red
value of the luminous color, and divided by 255 (since there are 8 bits per color channel)
as illustrated in the following formula:
R_New = R_Old*(R_Luminous/255).
For the non-luminous sections of gauges, the luminous color isnt used instead a
combination of the day and night values is used.
o If it is completely light out, the day color is used.
o If it is completely dark out, the night color is used to scale.
As the time transitions from day to night, the panels tint is gradually scaled between the
day and night colors. Thus, tint = night + (day night)*sunlight/255. (Where sunlight is
in the range between 0 and 255). The formula below illustrates this:
R_New = R_Old*(tint/255)
This tint value is then applied the same way that the luminous color is applied to
luminous sections of the panel.
113
Step-by-Step XML Example:
<Mouse>
<Tooltip ID="TOOLTIPTEXT_WHISKEY_COMPASS"/>
</Mouse>
</Gauge>
114
Examining the gauge, adding one image at a time:
(Image truncated)
(Image truncated)
Mask image for compass strip: This
image appears like this in Imagetool:
(Mask pixels in magenta)
115
Highlight RGB image (pure white)
Notice how the addition of the shadow and highlight alpha images increases the level of realism
in the gauge.
A: There can be a separate gauge element a static image that has Alpha=Yes set.
These are usually one of (if not the) topmost elements of a gauge in the z-order. They are
usually used to set highlights or shadows by using a white or black RGB image combined
with an alpha channel containing a gradient. See the Step-by-Step XML Example for more
information.
###
Q: Is it possible to use Imagetool to convert a 32-bit .bmp with alpha (from Photoshop) to
an 8-bit .bmp with alpha for use with FS?
A: Yes, Adobe Photoshop supports this file format now. However, Flight Simulator will not
recognize this file format, so Imagetool must be used to convert the image to 8-bit-with-
alpha. Run imagetool gauge <filename> from the command line.
###
A: By using Imagetool, you can convert .psds into .bmps. The visible layers in the .psd get
used to generate the bitmap. An alpha value < 108 results in a transparent pixel; an alpha
value ranging from 109-147 results in a mask pixel, and other values result in an opaque
pixel. This method is slightly superior to the method of specifying the mask pixels and
transparent pixels in the layer itself due to the fact that black and almost-black look almost
exactly the same an artist could accidentally specify a mask pixel where a transparent pixel
was desired.
116
Q: Can 3rd-party developers create gauges without .cabing their .xml and .bmps like we
do?
A: Yes, the .xml files and .bmps can simply be stored in a directory with the name of the
aircraft in the panel directory.
###
Q: How is it possible that we have an 8-bit format that can store an alpha channel? I
thought bitmaps had to be 32-bit to do such a thing.
A: An 8-bit format can indeed store an alpha channel. In Flight Simulators 8-bit indexed
format, the palette contains 32-bit colors, enough for an alpha image (these palettes usually
only contain 24-bit colors).
Note that Photoshop does not support such a file format. (You can neither save to this format
nor view the alpha channel for such a file see the 747s analog_attitude_alpha.bmp for an
example of a 256-color .bmp that has many colors AND an alpha channel.)
Imagetool will only create an alpha image from a 32-bit image. An alpha value < 108
results in a transparent pixel, 109-147 results in a mask pixel, and the rest result in an opaque
pixel.
However, it should be noted that if the -gaugealpha flag is specified, those numbers do not
apply the alpha channel is used to specify alpha-blending characteristics, not a mask for
another image.
###
Q: If you see grey in the alpha channel for an image in the Imagetool, what does that really
represent?
A: It depends. It could represent a section of mask pixels. Or it could represent the alpha-
blend level to apply to another image, depending on the context in which the image is used.
117
Appendix C Using Imagetool with Gauges
Imagetool includes many methods for manipulating images used in Flight Simulator. However,
most of those features are used for other areas of the simulation besides gauges (terrain, etc.).
Gauge developers can, however, create images of the correct format for use in Flight Sim gauges
by using ImageTool. The major uses of Imagetool for gauge developers are as follows:
GUI
1. Open the file by using the File->Open menu command.
2. In the Image->Format menu, choose the format you wish to convert to (8-Bit).
3. Save the file by using the File->Save menu command.
Command-line
1. Open a command window by running cmd.exe from the Start->Run dialog.
2. From the command line, run imagetool gaugealpha [filename] where [filename] is the
name of the file you wish to convert. (Note: This flag is not documented in the Usage
guidelines that appear when Imagetool -? is run.) By default the .bmp file generated
will have the same name as the .psd from which it was created. The image generated will
be 8-bit (palletized).
After converting the image to .bmp-with-alpha format by using one of the two methods above,
you can view the alpha channel in imagetool.
118
There are two ways to create a gauge image: by running the tool from the graphical user
interface (GUI) or from the command-line.
GUI
1. Open the file by using the File->Open menu command.
2. Select the Image->Make Gauge menu item.
3. Save the file by using the File->Save menu command.
Command-line
1. Open a command window by running cmd.exe from the Start->Run dialog.
2. From the command line, run imagetool gauge [filename] where [filename] is the
name of the file you wish to convert. By default the .bmp file that is generated will have
the same name as the .psd from which it was created. The image generated will be 8-bit
(palletized).
After converting the image to .bmp-with-alpha format by using one of the two methods above,
you can view newly created image and its alpha channel in imagetool.
If the alpha channel was maintained during the file conversion, the alpha channel is
applied in the following manner: the brighter the pixel in the alpha channel, the brighter
the RGB pixel is drawn.
On the other hand, if a gauge image is viewed, the alpha channel is not applied in the
default view only the RGB channel is visible.
Alpha channel
(as viewed in
ImageTool)
Default view in
ImageTool
To view the alpha channel separately, choose the menu option View -> Alpha Channel.
119
Determining the format of an image
To determine the format of an image, click on Image->Format in Image Tool.
120