MDL language documentation
Allegiance engine uses its own files format. The main format is the MDL format, of which two flavors exists:
- plain text MDL (mdl text format), and
- compiled MDL (mdl format).
Both formats are supported and use the same extension (.mdl). Visual inspection of the file is required to determine the format used. There is no known tool to convert compiled mdl in plaintext mdl.
The mdl text format uses a form of definition language to define objects. This is what a common piece of MDL code looks like:
use "effect"; frame = ModifiableNumber(1); object = ImportXFile("artifact.x", frame);
This sample uses an external .x file but the mdl language is complete enough to define meshes without using another file format (see samples/bgrnd03.mdl for a mdl only textured object) The mdl language scope goes beyond 3D models. It's used to defined most aspects of the game including 3D, sounds and UI panels.
MDL textual language
Syntax
As mentioned, MDL is a declarative, case-sensitive language. Most statements take the following form:
identifier = function(parameter1, parameter2);
- MDL is a loosely typed language. You don’t need to specify the types of variables.
- A semi-colon should end every statement, which can span multiple text lines.
- Integer constants can be written in two ways: normally (11) or as hex (0x0B).
- String constants are written like: “foostring”
- Boolean constants have two possible values, true and false.
- Comments are preceded by //.
There is a single built-in operator, the bitwise or operator |. For example, 0x01 | 0x02 evaluates to 0x03.
Note Even though the native Number-type is a floating-point number, it is converted (cast) to a 32-bit integer when performing the bitwise operation.
Namespaces
Namespaces are a central concept in MDL. Every MDL file is a namespace, whether textual or binary. For example, to be able to use variables, constants and functions from another file or namespace called "filename.mdl", you would use the following:
use "filename";
All use-declarations must be located at the beginning of the MDL-file. Importing a namespace like this naturally imports any other namespace that is use-d in the imported namespace.
The Allegiance engine also exports about 650 functions and constants into different namespaces. These are listed on the worksheet "From C++ exported to MDL", giving the parameters and a short note on the purpose / syntax. These exports can roughly be sorted into the following categories:
- Object creating functions ("constructors"), like ButtonPane(Image background, Number FacesFlag, bool toggles)
- Global constants, like pi, white, black and key constants like CommandVoteYes, CommandDropChaff
- Built-in windows, like the inventory, or the team window (F6) exporting data to be shown to their specific namespace.
In return, they expect certain controls, buttons to be specified in the MDL-file, so they can be imported back to the engine.
Some exports are seemingly only used in binary .mdl 3d models, e.g. LightsGeo and FrameData. Note that the exported namespaces are organized in a somewhat unintuitive hierarchy of imports / use-statements.
Structs
Structs are used once in the artwork shipped with Allegiance, in quickchatheader.mdl. They are also an exception to the loose typing. In a struct, you need to define the types that it contains. To be able to use the struct in c++-code, use the mdlc utility to generate an appropriate header. You can also use the keyword “extends” to use inheritance (also used in the same file).
The syntax is:
Struct structname extends parentstruct { identifier1 : type1; identifier2 : type2; list3 : [type3]; };
Defining a struct allows you to use the structname as a constructor / function that creates and returns an object.
Here's an example:
variableidentifier = structname(type1object, type2object, [type3obj1, type3obj2, type3obj3])
Lists
Some functions can take a variable number of arguments. A window can have several controls, a QuickChatMenu can have several entries. In this case, a list is used as an argument.
Lists in general take the form
Identifier = [item1, item2, item3];
Note In a function call, an empty list is simply discarded. The calls Add(5,3,[],[]) and Add(5,3) are equivalent.
Tuples
In lists and variable definitions, each expression can actually contain several expressions (which may be of different types), effectively becoming a kind of unnamed struct. This is called a pair, or more precisely a tuple -- this construct can contain any number of expressions.
Assigning a pair to an identifier / variable looks like:
Identifier = (item1, item2, item3);
Using tuples in a list then becomes
Identifier = [ (item11, item12), (item21, item22), (item31, item32) ];
Tuples are extensively used at the bottom of dialog.mdl as follows:
(image, side, off point, on point, transition time, consoles modes, undetectable)
let ... in
The let-construct allows you to write a number of temporary definitions, and evaluate one expression in the context of these definitions. This allows for temporarily redefining an identifier for a certain expression and making a non-global assignment (perhaps to split up a long expression into several lines?). It is never used in the .mdl-files shipped with the game. The syntax is:
Identifier = let <definitions> in <expression>;
For example, the following assigns 11 to Identifier:
Identifier = let Foo = 5; Bar = 6; in Add(Foo,Bar);
In practice
Following is a commented real life example: AutoDownloadDialog.mdl
[codebox]use "effect"; // import effect namespace for widgets/controls use "font"; // import fonts use "gamepanes"; // import more Panes/widgets/controls use "autodownloaddialogdata"; //import data specific for this dialog
///////////////////////////////////////////////////////////////////////////// // // AutoDownload Dialog // /////////////////////////////////////////////////////////////////////////////
// // Guts //
// Create a button AutoDownloadAbortButton = ButtonPane(
ImportImage("btnautodownloadabortbmp", true), //with an image, ButtonNormal, //a behavior false //no toggle behavior );
// Create a bunch of strings. The engine will take care of those. AutoDownloadCurrentFileStringPane = StringPane(
"", //with some content Color(1, 1, 1), //a color (?) Point(220, 13), //a position JustifyRight, //a justification smallFont //a font );
AutoDownloadApproxMinutes = StringPane(
"", // do not worry Color(1, 1, 1), // about parameters Point(120, 13), // just yet, however. JustifyLeft, // That's documented smallFont // elsewhere :) );
AutoDownloadTopBarStringPane = StringPane(
"Retrieving File List", // Did you know... Color(1, 1, 1), // a single typo will make Allegiance crash. Point(150, 13), // You can find an MDL syntax JustifyLeft, // checker in Cortex's blog. smallFont // Mind the commas! );
// all kinds of indentation, tabulations and (half-done) formatting are found in the code. // The above has been pretty printed for the purposes of this guide, but we'll stop doing this now // to dip you in the atmosphere :D
// more of the same AutoDownloadMidBarStringPane = StringPane("Analyzing Local Version", Color(1, 1, 1), Point(150, 13), JustifyLeft, smallFont); AutoDownloadLowBarStringPane = StringPane("Downloading Updated Files", Color(1, 1, 1), Point(150, 13), JustifyLeft, smallFont);
// Create the progress bars
FileListGaugePane =
GaugePane(
ImportImage("autodownloadgaugebmp", false), // with an image FileListPercentDone, // a progress (which is fed by the engine) Color(1, 0, 0), // a "marker" color Color(0, 1, 0) // and a "background" color
);
VerifyGaugePane = GaugePane(
ImportImage("autodownloadgaugebmp", false), VerifyPercentDone, Color(1, 0, 0), Color(0, 1, 0)
);
DownloadGaugePane = GaugePane(
ImportImage("autodownloadgaugebmp", false), DownloadPercentDone, Color(1, 0, 0), Color(0, 1, 0)
);
//
// AutoDownload Dialog
//
//We finally create the dialog
AutoDownloadDialog =
( ImagePane( ImportImage("autodownloaddialogbmp", false), //with a background [ //and a list of panes (AutoDownloadCurrentFileStringPane, Point(195,185)), //with more position parameters (AutoDownloadApproxMinutes, Point(100,185)), (FileListGaugePane, Point(91,68)), (VerifyGaugePane, Point(91,113)), (DownloadGaugePane, Point(91,158)), (AutoDownloadAbortButton, Point(210,200)), (AutoDownloadTopBarStringPane, Point(100,51)), (AutoDownloadMidBarStringPane, Point(100,96)), (AutoDownloadLowBarStringPane, Point(100,140)) ] ) );
// This ImagePane-object is imported back to the engine.
[/codebox]
Tools
MDLC – the mdl compiler
The MDL compiler offers a numbers of features, each with its own syntax. Here's a list of accepted MDLC syntaxes:
mdlc -convert input output.mdl
- -convert
- converts ASCII .mdl to binary .mdl
- input
- source filename without .mdl ending
- output.mdl
- destination filename with .mdl ending
mdlc -optimize input output
- -optimize
- optimize 3d-models in .mdl-format. Removes diffuse/specular/emissive color information and consolidates texture information. Precalculates certain transforms, etc... in one word: optimizes.
- input
- the file (stripped of its .mdl extension) to optimize
- output
- destination filename, without .mdl ending
mdlc -compressanim xframes yframes input output
- -compressanim
- applies a form of RLE (Run Length Encoding) to an animation (presumably a .bmp with the frames stored side-by-side in rows and columns).
- xframes
- the number of animation frames in one row
- yframes
- the number of animation frames in one column
- input
- the filename of the .bmp to compress
- output
- the destination filename, without the .mdl extension
mdlc -convert input output
- -convert
- converts a .bmp to bmp.mdl
- input
- filename of source bitmap
- output
- destination filename (without .mdl ending)
mdlc -info input
- -info
- prints some information about the model (how many triangles each LOD has)
- input
- the name of a .mdl-file (without .mdl-ending) describing a 3d-model with level-of-detail information
mdlc -genheader input output
- genheader
- Generates c++ code for handling any structs defined in a .mdl-file.
- input
- the .mdl (without .mdl-ending) that contains struct definitions.
- output
- filename for writing the code to
External Links
- Ksero's Excellent MDL Language Documentation A Zip-file including the complete MDL language reference.