Ver Fonte

Using doxygen "groups" or "modules" as a major factor in keeping the documentation (reference material and all) with the source.
- specifically, check the TAML Reference module and the Module Manager module for the engine.

To do this:
First the reference material from github wiki is brought over as a *.dox file. doxygen understands markdown
95% well so not many tweaks are required. By usingn a .dox file, the large reference is kept together and not
injected within a specific class. Using the .dox is fairly standard practice.

The reference doc is placed in the dir that most closely represents it, such as module/module.dox or persistence/taml/taml.dox.

Classes in the module add themselves to their respective module with "/// @ingroup TAMLGroup" in the class header.

Now the markdown reference is inserted as a "module" and has references to all classes that are involved.

note: because the "modules" page in the output had lots of little groups, (such as dglThis and dglThat), I've also been pushing these groups into super groups to keep it organized (such as dglGroup which now wraps dglThis and dglThat).

Charlie Patterson há 12 anos atrás
pai
commit
ecc07608cb

+ 8 - 3
engine/source/console/console.h

@@ -129,7 +129,11 @@ struct EnumTable
 
 
 typedef const char *StringTableEntry;
 typedef const char *StringTableEntry;
 
 
+/// @defgroup tsScripting TorqueScript Bindings
+/// TorqueScrit bindings
+
 /// @defgroup console_callbacks Scripting Engine Callbacks
 /// @defgroup console_callbacks Scripting Engine Callbacks
+/// @ingroup tsScripting
 ///
 ///
 /// The scripting engine makes heavy use of callbacks to represent
 /// The scripting engine makes heavy use of callbacks to represent
 /// function exposed to the scripting language. StringCallback,
 /// function exposed to the scripting language. StringCallback,
@@ -157,6 +161,7 @@ typedef void (*ConsumerCallback)(ConsoleLogEntry::Level level, const char *conso
 /// @}
 /// @}
 
 
 /// @defgroup console_types Scripting Engine Type Functions
 /// @defgroup console_types Scripting Engine Type Functions
+/// @ingroup tsScripting
 ///
 ///
 /// @see Con::registerType
 /// @see Con::registerType
 /// @{
 /// @{
@@ -807,7 +812,7 @@ public:
 
 
 #  define ConsoleFunctionWithDocs(name,returnType,minArgs,maxArgs,argString)              \
 #  define ConsoleFunctionWithDocs(name,returnType,minArgs,maxArgs,argString)              \
       static returnType c##name(SimObject *, S32, const char **argv);                     \
       static returnType c##name(SimObject *, S32, const char **argv);                     \
-      static ConsoleConstructor g##name##obj(NULL,#name,c##name,"",minArgs,maxArgs);      \
+	  static ConsoleConstructor g##name##obj(NULL,#name,c##name,#argString,minArgs,maxArgs);      \
       static returnType c##name(SimObject *, S32 argc, const char **argv)
       static returnType c##name(SimObject *, S32 argc, const char **argv)
 
 
 #  define ConsoleFunctionGroupEnd(groupName) \
 #  define ConsoleFunctionGroupEnd(groupName) \
@@ -841,7 +846,7 @@ public:
          AssertFatal( dynamic_cast<className*>( object ), "Object passed to " #name " is not a " #className "!" );    \
          AssertFatal( dynamic_cast<className*>( object ), "Object passed to " #name " is not a " #className "!" );    \
          conmethod_return_##returnType ) c##className##name(static_cast<className*>(object),argc,argv);               \
          conmethod_return_##returnType ) c##className##name(static_cast<className*>(object),argc,argv);               \
       };                                                                                                              \
       };                                                                                                              \
-      static ConsoleConstructor className##name##obj(#className,#name,c##className##name##caster,"",minArgs,maxArgs); \
+	  static ConsoleConstructor className##name##obj(#className,#name,c##className##name##caster,#argString,minArgs,maxArgs); \
       static inline returnType c##className##name(className *object, S32 argc, const char **argv)
       static inline returnType c##className##name(className *object, S32 argc, const char **argv)
 
 
 #  define ConsoleStaticMethod(className,name,returnType,minArgs,maxArgs,usage1)                       \
 #  define ConsoleStaticMethod(className,name,returnType,minArgs,maxArgs,usage1)                       \
@@ -859,7 +864,7 @@ public:
          conmethod_return_##returnType ) c##className##name(argc,argv);                               \
          conmethod_return_##returnType ) c##className##name(argc,argv);                               \
       };                                                                                              \
       };                                                                                              \
       static ConsoleConstructor                                                                       \
       static ConsoleConstructor                                                                       \
-         className##name##obj(#className,#name,c##className##name##caster,"",minArgs,maxArgs);        \
+	  className##name##obj(#className,#name,c##className##name##caster,#argString,minArgs,maxArgs);        \
       static inline returnType c##className##name(S32 argc, const char **argv)
       static inline returnType c##className##name(S32 argc, const char **argv)
 
 
 #  define ConsoleMethodGroupEnd(className, groupName) \
 #  define ConsoleMethodGroupEnd(className, groupName) \

+ 10 - 0
engine/source/graphics/dgl.h

@@ -40,6 +40,9 @@ class Point2I;
 class Point2F;
 class Point2F;
 class Point3F;
 class Point3F;
 
 
+/// @defgroup dgl Cross-Platform OpenGL Support
+/// functions used to map Torque2D calls to OpenGL (or OpenGL ES) calls per platform
+
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 //-------------------------------------- Bitmap Drawing
 //-------------------------------------- Bitmap Drawing
 //
 //
@@ -57,6 +60,7 @@ enum GFlipConstants
 };
 };
 
 
 /// @defgroup dgl_bitmap_mod Bitmap Modulation
 /// @defgroup dgl_bitmap_mod Bitmap Modulation
+/// @ingroup dgl
 /// These functions control a modulation color that is used to modulate all drawn objects
 /// These functions control a modulation color that is used to modulate all drawn objects
 /// @{
 /// @{
 
 
@@ -86,6 +90,7 @@ void dglClearBitmapModulation();
 void dglSetTextAnchorColor(const ColorF&);
 void dglSetTextAnchorColor(const ColorF&);
 
 
 /// @defgroup dgl_bitmap_draw Bitmap Drawing Functions
 /// @defgroup dgl_bitmap_draw Bitmap Drawing Functions
+/// @ingroup dgl
 /// These functions allow you to draw a bitmap.
 /// These functions allow you to draw a bitmap.
 /// Each function will draw the bitmap in a specific way regarding stretching
 /// Each function will draw the bitmap in a specific way regarding stretching
 /// @{
 /// @{
@@ -137,6 +142,7 @@ void dglDrawBitmapStretchSR(TextureObject* texObject,
                             bool           bSilhouette = false);
                             bool           bSilhouette = false);
 /// @}
 /// @}
 /// @defgroup dgl_text Text Functions
 /// @defgroup dgl_text Text Functions
+/// @ingroup dgl
 /// These functions draw a string on the string with a given font
 /// These functions draw a string on the string with a given font
 /// @{
 /// @{
 
 
@@ -163,6 +169,7 @@ U32 dglDrawTextN(GFont *font, const Point2I &ptDraw, const UTF8  *in_string, U32
 // Drawing primitives
 // Drawing primitives
 
 
 /// @defgroup dgl_primitive Primitive Drawing
 /// @defgroup dgl_primitive Primitive Drawing
+/// @ingroup dgl
 /// Easy functions for drawing lines and (un)textured rectangles in 2d or 3d space
 /// Easy functions for drawing lines and (un)textured rectangles in 2d or 3d space
 /// @{
 /// @{
 
 
@@ -191,6 +198,7 @@ void dglSolidCube(const Point3F &extent, const Point3F & enter);
 // Matrix functions
 // Matrix functions
 
 
 /// @defgroup dgl_matrix Matrix Functions
 /// @defgroup dgl_matrix Matrix Functions
+/// @ingroup dgl
 /// These functions manipulate the current matrix.  The current matrix could be modelivew, projection, or texture
 /// These functions manipulate the current matrix.  The current matrix could be modelivew, projection, or texture
 /// @note Make sure you specify which matrix you want to manipulate with a call to glMatrixMode(enum matrix); before calling dglLoadMatrix() or dglMultMatrix()
 /// @note Make sure you specify which matrix you want to manipulate with a call to glMatrixMode(enum matrix); before calling dglLoadMatrix() or dglMultMatrix()
 /// @{
 /// @{
@@ -208,6 +216,7 @@ void dglGetProjection(MatrixF *m);
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
 // Camera functions
 // Camera functions
 /// @defgroup dgl_camera_func Camera functions
 /// @defgroup dgl_camera_func Camera functions
+/// @ingroup dgl
 /// @{
 /// @{
 
 
 /// Returns the pixel scale, namely:
 /// Returns the pixel scale, namely:
@@ -223,6 +232,7 @@ F32 dglProjectRadius(F32 dist, F32 radius);
 /// @}
 /// @}
 
 
 /// @defgroup dgl_view Viewing Volume Functions
 /// @defgroup dgl_view Viewing Volume Functions
+/// @ingroup dgl
 /// These functions set up the view cube of the window.
 /// These functions set up the view cube of the window.
 /// @{
 /// @{
 
 

+ 2 - 0
engine/source/module/moduleCallbacks.h

@@ -29,6 +29,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup moduleGroup
+/// @see moduleGroup
 class ModuleCallbacks
 class ModuleCallbacks
 {
 {
     friend class ModuleManager;
     friend class ModuleManager;

+ 2 - 0
engine/source/module/moduleDefinition.h

@@ -49,6 +49,8 @@ class ModuleManager;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup moduleGroup
+/// @see moduleGroup
 class ModuleDefinition : public SimSet
 class ModuleDefinition : public SimSet
 {
 {
     friend class ModuleManager;
     friend class ModuleManager;

+ 543 - 0
engine/source/module/moduleManager.dox

@@ -0,0 +1,543 @@
+/*! @defgroup moduleGroup Module Manager Reference
+
+## Overview
+
+The module system is designed to provide users with a unit of reuse for both code and assets.  The module system includes vital ingredients that make this possible including:
+
+- Module Identity
+- Module Versioning
+- Module Deprecation
+- Module Grouping
+- Module Types
+- Module Dependencies
+- Module Meta-data
+- Module Load/Unload Notifications
+- Module Synchronization/Publishing
+
+Essentially a module can contain code and/or data (typically assets) and its code can be tasked for almost any purpose.  For instance, a module might represent a sub-system in your game or perhaps a plug-in tool for your editor, even an asset-pack.
+
+## Prerequisite Knowledge
+
+The module system use [TAML](Taml-Guide) to load-up module definition files that declare a module so basic knowledge of that is essential.  At the very least, knowing how to modify the TAML XML format is required.
+
+Although not essential, a basic working knowledge of the [Asset System](Asset-Manager-Guide) would be useful.
+
+## TorqueScript Bindings
+
+- [Module Manager](https://github.com/GarageGames/Torque2D/blob/master/engine/source/module/moduleManager_ScriptBinding.h)
+- [Module Definition](https://github.com/GarageGames/Torque2D/blob/master/engine/source/module/moduleDefinition_ScriptBinding.h)
+
+## Module System
+
+This document refers to the "Module System" but in actual fact, this is an engine type named "ModuleManager".  At engine start-up an instance of this is automatically generated inside the engine itself.  This instance is exposed to the scripts by the named object "ModuleDatabase".  It is named this because in Torque you cannot name an object the same as its type name.  The terms "Module System", "ModuleManager" & "ModuleDatabase" can be used interchangeably to mean the same thing however in scripts you need to use "ModuleDatabase" to access the primary module database.
+
+## Declaring Modules
+
+Before going into the details of modules, it's important to understand how simple the definition of a module is.  A module is nothing more than a folder with a single TAML file describing the module itself.  This is analogous to an asset which is a file or files represented by an asset definition TAML file.  The TAML file that describes a module is known as a module definition.
+
+All modules have a unique Id known as a "module Id".  A module Id is nothing more than an arbitrary string.  Its only requirement is that it is unique to all modules in the system.  It can be as short or as long as you required however keeping it short and simple is recommended.
+
+The contents of a module are completely irrelevant to the module system, all it cares about is knowing that the module exists.  A module is a "unit of reuse" meaning that if you have something you'd like to be kept together such as a set of code or collection of assets then a module is what you need to use.
+
+## Module Scanning
+
+The module system initially has no modules.  There are no fixed or special modules to understand.  The only modules that the module system knows about are the ones it finds when you ask it to scan a location on disk.  You can ask it to scan several locations if you so wish gathering modules from anywhere.  When you ask the module system to scan a location on disk, it simply searches for module definitions.
+
+You can ask it to scan like this:
+@code{cpp}
+// Scan for modules.
+ModuleDatabase.scanModules( "MyModules" );
+@endcode
+
+The function "scanModules" will scan for modules defined in the path you specify.  You can specify any path you so choose, in this case it's a sub-folder named "MyModules".  By default, this function will automatically recurse all sub-folders of the location you specify searching for module definitions.  If you don't want it to do that then you can pass a second argument that specifies whether you want to search the root of the location you specify only i.e. if you specify "false" as the second argument then it'll scan the root only.
+
+The module system will scan for files ending in "module.taml" (this can be changed) and will check to see if the file contains a type "ModuleDefinition".
+
+A bare minimum module definition file would look like this:
+@code{xml}
+<ModuleDefinition
+	ModuleId="AICode"
+	VersionId="1"/>
+@endcode
+As you can see, this would create a type "ModuleDefintion".  This type is what the module system uses to define a module.  The bare minimum information that is required for a module is its "ModuleId" and its "VersionId".  The module Id as already stated is the modules unique identification.  The version Id is a serial Id that represents the modules version.  As you'll see, you are free to create multiple modules with the same Module Id that are at different versions i.e. different Version Id.  This is how the module system allows the same module to exist concurrently at different versions.
+
+When the module system finds a module definition, it first validates it.  As part of this validation, the module system ensures that the same module Id at the same version Id doesn't already exist.  If it does then a warning is issued and the module definition is ignored.
+
+## The Module Definition
+
+As you can see, the module definition is a simple type that contains fields that describe the module itself.  So far we've only seen the bare minimum configuration so here's a complete list:
+
+- ModuleId - A unique string Id for the module.  It can contain any characters except a comma or semi-colon (the asset scope character).
+- VersionId - The version Id.  Breaking changes to a module should use a higher version Id.
+- BuildId - The build Id.  Non-breaking changes to a module should use a higher build Id.  Optional: If not specified then the build Id will be zero.
+- Enabled - Whether the module is enabled or not.  When disabled, it is effectively ignored.  Optional: If not specified then the module is enabled.
+- Deprecated - Whether the module is deprecated or not.  Optional: If not specified then the module is not deprecated.
+- Description - The description typically used for debugging purposes but can be used for anything.
+- Author - The author of the module.
+- Group - The module group used typically when loading modules as a group.
+- Type - The module type typically used to distinguish modules during module enumeration.  Optional: If not specified then the type is empty although this can still be used as a pseudo 'global' type for instance.
+- Dependencies - A comma-separated list of module Ids/VersionIds (<ModuleId>=<VersionId>,<ModuleId>=<VersionId>,etc) which this module depends upon. Optional: If not specified then no dependencies are assumed.
+- ScriptFile - The name of the script file to compile when loading the module.  Optional.
+- CreateFunction - The name of the function used to create the module.  Optional: If not specified then no create function is called.
+- DestroyFunction - The name of the function used to destroy the module.  Optional: If not specified then no destroy function is called.
+- ScopeSet - The scope set used to control the lifetime scope of objects that the module uses.  Objects added to this set are destroyed automatically when the module is unloaded.
+- AssetTagsManifest - The name of tags asset manifest file if this module contains asset tags.  Optional: If not specified then no asset tags will be found for this module.  Currently, only a single asset tag manifest should exist.
+- Synchronized - Whether the module should be synchronized or not.  Optional: If not specified then the module is not synchronized.
+- CriticalMerge - Whether the merging of a module prior to a restart is critical or not.  Optional: If not specified then the module is not merge critical.
+
+## Module Layout
+
+As you've seen, a module is identified by its Module Id however, part of that identity is its Version Id and together they form a unique module i.e. a module at a specific version.  This means that you can have the same Module Id but at different versions known to the module system.  This raise the question of how they are organized on disk.  The module system does not mandate any specific way to organize modules, you can store a module anywhere, all that really matters is that the module definition file is scanned for so that module is known to the module system.
+
+So for hand-crafted games, situate them however you like.  For an editor system to generate and manipulate modules, it's far better to create some nomenclature to ensure that modules don't clash.  This has led to a standard for layout that whilst not mandatory (the module system doesn't care about it) it creates an environment that is well known and consistent for future editors.
+
+The standard layout is to have modules inside a folder with the same name as the module Id itself.  Within that folder a sub-folder with the same name as the version Id of the module.  Finally, within that is the module itself containing at least the module definition.
+
+This leads to a layout like this:
+
+| Module Id | Version Id | Folder |
+|--- | --- | --- |
+| RedModule | 1 | RedModule\1\... |
+| RedModule | 2 | RedModule\2\... |
+| GreenModule | 1 | GreenModule\1\... |
+| BlueModule | 1 | BlueModule\1\... |
+
+These modules however could've equally been organized like this:
+
+| Module Id | Version Id | Folder |
+|--- | --- | --- |
+| RedModule | 1 | RedModule1\... |
+| RedModule | 2 | RedModule2\... |
+| GreenModule | 1 | GreenModule\1\... |
+| BlueModule | 1 | BlueModule\1\... |
+
+... but as you can see, the "RedModule" are in folders named "RedModule1" and "RedModule2" to stop them clashing.  Also, they are not in a common root folder i.e. "RedModule".
+
+The choice is totally yours however but having the module exist inside a sub-folder named as the Version Id is a standard which will be used moving forward and affords many advantages for editors in the future.
+
+## Module Identity
+
+In addition to the Module Id and Version Id, there exists a third setting of Build Id.  Whilst this may not seem important when you are hand crafting modules (even version Id may not), it becomes very important when using the module systems synchronization features.  Synchronization is a feature that supports editor infrastructure for synchronizing application projects based upon modules and will be covered later in the document.
+
+For now, know that the version Id signifies a breaking change to a module i.e. version 2 has braking changes from version 1.  That may actually not be the case but this is the meaning of the version Id to the module system i.e. version 2 is incompatible and cannot be used in substitution for version 1.  Build Id is a non-breaking change where a module has been modified.  The build Id does not generate a new module, it is simply a replacement for an existing module.  Again, this relates to synchronization and indicates that an incoming module is a different build of an existing module Id and version Id module and it needs to be replaced.
+
+The build Id does not change the location of a module, it exists only as a field defined within the module definition like this:
+@code{xml}
+<ModuleDefinition
+	ModuleId="AICode"
+	VersionId="1"
+	BuildId="234"/>
+@endcode
+
+## Module Loading and Unloading
+
+When it comes time to load or unload a module, the process is extremely simple.  There are actually two ways to load and unload modules:
+
+- Explicit
+- Group
+
+An explicit load or unload is when you ask for a specific module at a specific version Id to be loaded or unloaded like so:
+@code{cpp}
+ModuleDatabase.LoadExplicit( "RedModule", 2 );
+@endcode
+Whilst this is a simple operation, it is fraught with problems when the complexity and number of the modules increases.  The initial downside to this approach is that the code itself has to know both the name and the version of the module it needs to load.  This couples the loading code with knowledge of the module Ids and Version Ids.  This isn't necessarily bad for a simple setup but it doesn't scale well.
+
+As an example, let's say that we have the RedModule (at versions 1 and 2), GreenModule and BlueModule.  They are all related functionality, let's say they're our "color handling" modules.  If we want to load them all we end up doing the following:
+
+@code{cpp}
+ModuleDatabase.LoadExplicit( "RedModule", 2 );
+ModuleDatabase.LoadExplicit( "GreenModule", 1 );
+ModuleDatabase.LoadExplicit( "BlueModule", 1 );
+@endcode
+Okay, so that's not too bad but consider that you might not want to load all the modules initially.  This will mean you end up with these kinds of explicit loads all over the place.  Again, this doesn't scale well.
+
+Also, to unload it you've got to do this:
+
+@code{cpp}
+ModuleDatabase.UnloadExplicit( "RedModule", 2 );
+ModuleDatabase.UnloadExplicit( "GreenModule", 1 );
+ModuleDatabase.UnloadExplicit( "BlueModule", 1 );
+@endcode
+
+A far better approach is to group these modules together and load them up as one.  To do this, you simply assign each module into a group by setting their group field like so:
+@code{xml}
+<ModuleDefinition
+	ModuleId="RedModule"
+	VersionId="1"
+	Group="Colors"/>
+@endcode
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="RedModule"
+	VersionId="2"
+	Group="Colors"/>
+@endcode
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="GreenModule"
+	VersionId="1"
+	Group="Colors"/>
+@endcode
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="BlueModule"
+	VersionId="1"
+	Group="Colors"/>
+@endcode
+
+As you can see, the "Group" field has been set to "Colors".  This can be any string containing any characters you wish.  It could've equally been "All my color modules" but this is a group name and using sentences would be kind of odd looking and the potential for typos is high.
+
+To load that group you then simply do:
+@code{cpp}
+ModuleManager.LoadGroup( "Colors" );
+@endcode
+
+If you wanted to unload the group you simply do:
+@code{cpp}
+ModuleManager.UnloadGroup( "Colors" );
+@endcode
+
+The code above, doesn't know what modules its loading, it's just stating that at this point in time it needs to load the "color" modules.  Imagine this were editor tooling and you wanted to load all the "plug-in" modules, this could be used for that.  Equally, you might load the "AI" modules etc.  The main point to consider is that you can add a module, assign it to a group and not have to find the code that both loads and unloads it and make modifications.  This then becomes purely data-driven.
+
+You may be wondering what "RedModule" versions it loaded?  Well the answer is that in the absence of any module dependencies it will simply load the latest version of any module Id so in the examples above, the RedModule at version 2 is loaded and unloaded.
+
+## Module Dependencies
+
+When a module is loaded, it may require services or data provided by another module.  This means that you must ensure that the module it depends upon is loaded before the module itself is loaded.  Also, it means you must ensure that the module is depends upon is not only unloaded after the module that depends on it but also that the module it depends on is never unloaded whilst the module itself is loaded.  In simpler terms, if one module depends on another then it must be ready and "running" before a module is loaded and always be like that whilst the module itself is operating.
+
+It's possible to perform this organization yourself however, as was seen in the previous section, this doesn't scale well as more and more modules depend on each other.
+
+The module system however can easily handle this module dependency situation for you and all it asks from you is to define in a module definition, which modules at specific versions the module depends on.
+
+For example, let's say we have a module Id of "Game" which depends on services in another module Id of "GameCore".  To keep things simple, both modules are at version 1 for now:
+@code{xml}
+<ModuleDefinition
+	ModuleId="GameCore"
+	VersionId="1"/>
+@endcode
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="Game"
+	VersionId="1"
+	Dependencies="GameCore=1"/>
+@endcode
+
+We then want to load explicitly our "Game" module like this:
+
+@code{cpp}
+ModuleManager.LoadExplicit( "Game", 1 );
+@endcode
+
+When we do this, the module system validates the "Game" module and checks for any dependencies.  As you can see, the "Game" module has specified that it depends on module "GameCore" at version "1".  This tells the module system that it needs to ensure that the "GameCore" at version "1" is loaded first so that's what it does prior to loading the "Game" module itself.
+
+It should be noted that if the "GameCore" is already loaded (perhaps it was loaded explicitly or another module was loaded that depended on it) then it simply increases a reference count i.e. you don't have to worry about modules being loaded twice.
+
+If you were then to unload the "Game" module like this:
+
+@code{cpp}
+ModuleManager.UnloadExplicit( "Game", 1 );
+@endcode
+
+... the module system would first look for the "Game" module dependencies and see the "GameCore" dependency.  It then reduces the reference count for "GameCore" and if it is zero i.e. nothing is currently referencing the "GameCore" module then it unloads it.  It then proceeds to unload the "Game" module itself.
+
+You specify as many module dependencies as you like by using comma separation like so:
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="Game"
+	VersionId="1"
+	Dependencies="GameCore=1,AICore=2,AudioCore=1,PlugInCore=6"/>
+@endcode
+
+The golden rule for module dependencies is that if you have a module that depends on another module being loaded whether that be because you directly uses its functions directly or indirectly use its data, you must always declare a dependency on it.
+
+Module dependencies are very powerful and they allow for very complex loading and unload situations and dependencies.  For instance, if you load a module explicitly, not only will any dependencies be loaded but also their dependencies will be loaded as well.  This is completely recursive i.e. module dependencies form a dependency directed-graph.  The module system can also detect cycles in the loading dependencies which obviously cannot be satisfied and refuse to load as well as raising a warning to the log.
+
+Furthermore, module dependencies applies any time a module is loaded or unloaded so this means if you load a module group, any of the groups modules get their dependencies loaded as well.
+
+A final and critical rule to consider is that the module system uses the module Id to mean a unique piece of functionality.  This means that it will NOT allow the same module Id at different versions to be loaded under any circumstances.  If you attempt to do this you'll simply get a warning output to the log and the module won't load.  Having multiple versions of the same module on the disk doesn't mean they can be loaded at the same time.  This is expected because otherwise, those modules would potentially conflict in their operation.
+
+## Module Disabling
+
+By default every module is enabled but there may be times when you don't want it to be loaded by the module system.  Instead of having to move the module outside of the folders being scanned by your application you can simply disable the module like so:
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="BlueModule"
+	VersionId="1"
+	Enabled="0"/>
+@endcode
+
+The module system will acknowledge the module by outputing to the log that the module was found but not loaded because it was disabled.  Also, you should be careful when disabling modules that are depended on by other modules as doing so will also stop those modules from loading.
+
+## Module Deprecation
+
+You can mark a module as being deprecated.  This won't stop the module from being loaded however it will output a warning to the log saying that a deprecated module is being loaded.  This can serve as a hint to use a newer version of a module or perhaps a different module Id altogether.  It is also useful for an editor in indicating to the end-user that a module is deprecated.
+
+You flag a module as deprecated like so:
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="RedModule"
+	VersionId="1"
+	Deprecated="1"/>
+@endcode
+
+## Module Description and Author
+
+Whilst the module system doesn't actually use either the module description or author, they are both useful fields for identification and can be used to display to the end-user for various purposes.
+
+You can configure these like so:
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="GreenModule"
+	VersionId="1"
+	Description="The really useful green module."
+	Author="Mr Green, GreenSoft Inc."/>
+@endcode
+
+## Module Type
+
+You can assign a module to a type and whilst the module system doesn't use this, it can prove extremely useful when finding modules using the "find" functions that the module system provides (covered later in the document).  Typicaly the type is used to filter modules from each other.  For instance, let's say you had a bunch of modules that provided "art" packs, you could assign the type as "ArtPack" like so:
+@code{xml}
+<ModuleDefinition
+	ModuleId="PlatformArtPack"
+	VersionId="1"
+	Description="Lots of cool platform assets."
+	Type="ArtPack"/>
+@endcode
+
+You can then use the "find" functions (detailed later) to find modules of the type "ArtPack".  You are free to use anything here as it is simply a string.  You can think of the "Type" as analogous to a category.
+
+## Module Scripts
+
+So far we've seen how to load and unload modules as well as how to configure various aspects but we've not yet seen how to actually utilize them in a real situation.
+
+The most common use for a module is to host code.  When a module is loaded, it's common to want to define code to run and even automatically run a specific function.  Also, when unloading the module it's common to want to also run a specific function.  If you are not hosting code then none of this section is relevant and you can omit the fields it refers to.
+
+A module allows by using three fields:
+
+- ScriptFile
+- CreateFunction
+- DestroyFunction
+
+You typically set them up like so:
+
+@code{xml}
+<ModuleDefinition
+	ModuleId="BlueModule"
+	VersionId="1"
+	ScriptFile="main.cs"
+	CreateFunction="create"
+	DestroyFunction="destroy"/>
+@endcode
+
+The script file field allows you to specify a [TorqueScript](TorqueScript-Overview) file to compile when the module is loaded for the first time.  In the example above, it will execute the file "main.cs" that resides alongside the module definition TAML file itself.  This file can be named anything you like and does not have to be "main.cs".
+
+Compiling a TorqueScript file is useful in that any functions defined by the compilation suddenly become available to be called by other code.  It is however useful to execute a "create" function when the module loads that enables you to perform an action when the module is loaded.  The same goes for executing a "destroy" function when the module is unloaded.  You define these with the "CreateFunction" and "DestroyFunction" fields.
+
+These functions however are not global functions i.e. they are NOT defined like this:
+@code{cpp}
+function create()
+{
+}
+
+function destroy()
+{
+}
+@endcode
+
+The reason they are not like this is because there is a high likelyhood of those functions already being defined in which case Torque replaces the previous functions which can cause extremely hard to track bugs.  Instead, the module system requires that you do this:
+@code{cpp}
+function BlueModule::create(%this)
+{
+}
+
+function BlueModule::destroy(%this)
+{
+}
+@endcode
+This works because when a module is loaded, the module system generates an object named the same as the module Id that is being loaded.  This is known as the modules "ScopeSet" and will be covered in the next section.
+
+You should try to stick to using the namespace of the module Id i.e. "BlueModule" shown above if possible to avoid function naming conflicts however if you are careful about your naming then you can avoid this situation.  The potential for conflict can be high however if you are not in a position to supervise all the module functions that will be working together in the application i.e. if you were to accept third-party modules.
+
+Obviously, caution is indicated here.
+
+It's important to remember that whilst the "ScriptFile" will be compiled only once when the module is initially loaded, both the "CreateFunction" and the "DestroyFunction" will be call whenever the module is loaded or unloaded.
+
+## ScopeSet
+
+As shown in the previous section, the module system will generate a named object and call both the specified "CreateFunction" and "DestroyFunction" on it.  This "ScopeSet" is extremely useful for other reasons however.  The actual object created as the "ScopeSet" is a "[SimSet](https://github.com/GarageGames/Torque2D/blob/master/engine/source/sim/simSet.cc)" and because of this you are free to add any objects you wish to it.  The reason you might do this is because of the fact that the "ScopeSet" is not only deleted when the module is unloaded but it also deletes any objects that have been added to it.
+
+In other words, the "ScopeSet" is useful as an aid to deleting objects you want removed when the module unloads.  These are typically objects such as GUI controls but can be anything.
+
+## Module Manager
+
+So far we've only seen a handful of module system functions but there are many more.  For typically day-to-day use, most of the others won't be useful as a majority are designed for administering modules by an editor system.  There are however several that are extremely useful depending on how you use modules.
+
+Here's a tour of all the functions that are exposed by the module system organized by features:
+
+### Module Scanning
+
+When you scan for modules, the module system will use by default the extension "module.taml".  You are free to change this using:
+@code{cpp}
+ModuleDatabase.SetModuleExtension( "FunkyModules.taml" );
+@endcode
+
+You are free to specify whatever you like for an extension.
+
+### Module Loading and Unload
+
+You've already seen some of the module load and unload functions but a complete list being used is:
+@code{cpp}
+// Load the module group "CoreStuff".
+ModuleDatabase.LoadGroup( "CoreStuff" );
+
+// Unload the module group "CoreStuff".
+ModuleDatabase.UnloadGroup( "CoreStuff" );
+
+// Explicitly load the module "Game" at version "3".
+ModuleDatabase.LoadExplicit( "Game", 3 );
+
+// Explicitly unload the module "Game" at version "3".
+ModuleDatabase.UnloadExplicit( "Game", 3 );
+@endcode
+
+### Module Searching
+
+It's important to not only be able to load and unload modules but be able to find them in the first place!  This is important when you are dynamically loading modules.  This might be because you're using certain modules as dynamic asset content or maybe code plug-ins.  No matter the use, being able to find modules is important.
+
+In all cases, when you "find" a module you get a Torque object.  This object is actually the "ModuleDefinition" instance that was loaded when scanning for module definitions.  Each module has one and it has all the fields previously described.
+
+A brief example of these functions are presented however you should refer to the reference documentation for more details.
+
+Let's start with the most basic find function:
+@code{cpp}
+// Find the "Game" module at version 3.
+%module = ModuleDatabase.findModule( "Game", 3 );
+
+// Output its description.
+echo( %module.Description );
+@endcode
+
+As you can see, you can find any Module Id at a specific Version Id and the object returned is the module definition itself.  This allows you to access all the module definitons state including things like its description, author, dependencies etc.
+
+Another find mechanism allows you to find all modules or only modules that are currently loaded.  Whilst this may seem very specific, it's extremely useful for a module editor:
+
+@code{cpp}
+// Find all modules 
+%allModules = ModuleDatabase.findModules( false );
+
+// Find only loaded modules 
+%loadedModules = ModuleDatabase.findModules( true );
+@endcode
+In this case you get a space-separated list of module-definition objects.
+
+
+A more useful find mechanism is to be able to find modules by their "Type" field.  Recall that you can assign a "Type" to any module to indicate its usage such as "ArtPack" or "PlugIn" etc.
+
+Here's how you search for modules of a specific "Type":
+
+@code{cpp}
+// Find all "ArtPack" modules.
+%artPacks = ModuleDatabase.findModuleTypes( "ArtPack" );
+@endcode
+
+### Module Copying and Synchronization
+
+	This is a complex topic and will be detailed later!
+
+The following methods will be detailed:
+- copyModules()
+- synchronizeDependencies()
+
+### Module Merging and Updates
+
+	This is a complex topic and will be detailed later!
+
+The following methods will be detailed:
+- isModuleMergeAvailable()
+- canMergeModules()
+- mergeModules
+
+### Module Events and Listeners
+
+When a module system performs an important action it raises a corresponding event.  The following events are raised:
+
+- onModuleRegister - Called when a module is scanned, validated and finally registered.
+- onModulePreLoad - Called prior to a module loading
+- onModulePostLoad - Called after a module has been loaded
+- onModulePreUnload - Called prior to a module unloading
+- onModulePostUnload - Called after a module has been unloaded
+
+The module system allows you to register your own objects to receive these notifications by using the following methods:
+
+- addListener()
+- removeListener()
+
+When you perform these actions from TorqueScript, you can designate an object as a listener.  When this happens, the module system will then perform the above callbacks on the object(s) you specify like so:
+@code{cpp}
+// Create a listener object.
+new ScriptObject(MyModuleListener);
+
+// Add my object as a listener.
+ModuleDatabase.addListener(MyModuleListener);
+@endcode
+
+If you were to do the above then you could receive notifications like so:
+@code{cpp}
+function MyModuleListener::onModuleRegister( %module )
+{
+}
+
+function MyModuleListener::onModulePreLoad( %module )
+{
+}
+
+function MyModuleListener::onModulePostLoad( %module )
+{
+}
+
+function MyModuleListener::onModulePreUnload( %module )
+{
+}
+
+function MyModuleListener::onModulePostUnload( %module )
+{
+}
+@endcode
+
+If knowing when modules are registered, loading or unloaded is required then this functionality will provide that information.
+
+If the object designated as a listener implements the interface class "[ModuleCallbacks](https://github.com/GarageGames/Torque2D/blob/master/engine/source/module/moduleCallbacks.h)" then it will additionally receive direct callbacks in C++.
+
+## Modules with Assets
+
+As has been shown, when a module is loaded or unloaded, events are raised which allows third parties to be notified of those events.  This is utilized to great effect by the [Asset System](https://github.com/GarageGames/Torque2D/wiki/Asset-Manager-Guide).  When a module is loaded, the asset system needs to scan for assets in the module and likewise, when a module is unloaded, it needs to remove those assets.  It does this by listening for the module load and unload events and performing the appropriate actions.
+
+The asset system registers itself as a listener to module events [here](https://github.com/GarageGames/Torque2D/blob/master/engine/source/game/defaultGame.cc) in "initializeGame()".  More information on the actions it takes can be found in the asset system documentation.
+
+## Multiple Module Systems
+
+As already stated, the module system is simply an engine type of "ModuleManager" which the engine initially creates as a named object of "ModuleDatabase".  This is known as the primary module system however, you are free to generate more than one module system if you so desire.  This can be useful in more advanced module management scenarios.
+
+For instance, you may want to keep track, loading/unloading a specific set of modules in a different location than your primary modules and whilst you are free to scan modules in multiple locations using the primary module system, it may be convenient to use a separate module manager instance.  A good reason for this is because currently, there is no way to "unregister" a module.  If you were to use a separate module manager then simply deleting the module manager instance would result in the modules being removed from memory.
+
+There are other advanced scenarios such as when manipulating modules on the disk including copying and merging modules for product updates.  All these features were used by separate module managers in previous projects.
+
+As an example, you are free to do this:
+@code{cpp}
+// Create my module manager.
+%myModuleManager = new ModuleManager();
+
+// Scan for modules using my module manager.
+%myModuleManager.ScanModules( "MyModuleStuff" );
+@endcode
+You should be extremely careful to not load the same modules loaded by other module managers as that will cause undefined results.  When using this method you should preferably be scanning/working with modules in completely different locations.
+
+*/

+ 2 - 0
engine/source/module/moduleManager.h

@@ -50,6 +50,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup moduleGroup
+/// @see moduleGroup
 class ModuleManager : public SimObject
 class ModuleManager : public SimObject
 {
 {
 private:
 private:

+ 2 - 0
engine/source/persistence/taml/binary/tamlBinaryReader.h

@@ -33,6 +33,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlBinaryReader
 class TamlBinaryReader
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/binary/tamlBinaryWriter.h

@@ -29,6 +29,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlBinaryWriter
 class TamlBinaryWriter
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/json/tamlJSONParser.h

@@ -33,6 +33,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlJSONParser : public TamlParser
 class TamlJSONParser : public TamlParser
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/json/tamlJSONReader.h

@@ -37,6 +37,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlJSONReader
 class TamlJSONReader
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/json/tamlJSONWriter.h

@@ -38,6 +38,8 @@ extern StringTableEntry JSON_RFC4627_NAME_MANGLING_FORMAT;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlJSONWriter
 class TamlJSONWriter
 {
 {
 public:
 public:

+ 468 - 0
engine/source/persistence/taml/taml.dox

@@ -0,0 +1,468 @@
+/*! @defgroup tamlGroup TAML Reference
+
+## Introduction
+
+TAML is an acronym of Torque Application Mark-up Language.  It decribes a method of persisting type instances in various output formats.  TAML is designed to be extremely easy to use and provides a nice consistent method of persisting information.
+
+## Prerequisite Knowledge
+
+This document assumes knowledge of the [TorqueScript Syntax](TorqueScript-Syntax) only.
+
+## TorqueScript Bindings
+
+- [Taml](https://github.com/GarageGames/Torque2D/blob/master/engine/source/persistence/taml/taml_ScriptBinding.h)
+
+## Starting Out
+
+TAML was designed to be easy to use and in that sense, the following code should be easy to understand:
+
+@code{.cpp}
+// Create a sprite.
+%obj = new Sprite();
+
+
+// Write it out.
+TamlWrite( %obj, "stuff.taml" );
+@endcode
+
+This will write the following XML file:
+
+@code{.xml}
+<Sprite/>
+@endcode
+
+That's pretty simple and shows a basic principle when the output format is XML in that an XML element denotes a type to be created, in this case it's the "Sprite" type.  It should also be clear that nothing else related to the "Sprite" has been written.  This is another feature that TAML provides in that it allows type designers to specify whether additional state like fields are written or not, typically based upon whether they are at their default values or not.
+
+To read this back in we would use:
+
+@code{.cpp}
+%obj = TamlRead( "stuff.taml" );
+@endcode
+
+Again, pretty simple.  Given the two global functions shown you have nearly everything you need to know to actually use the TAML system because you can both write and read objects.
+
+This document however breaks down TAML into more detail beyond what you may need on a day-to-day basis but also includes information on the structure of its XML format which is an easily editable format to work with.
+
+## TAML instance
+
+The global functions shown above are simplified ways of writing and reading objects.  They are simplified because they hide the fact that TAML is actually a type you can create.
+
+For instance, the previous write and read examples could've been done using the following:
+
+@code{.cpp}
+// Create a sprite.
+%obj = new Sprite();
+
+// Create an instance of TAML.
+%taml = new Taml();
+
+// Write it out.
+%taml.write( %obj, "stuff.taml" );
+
+// Read it in using the same TAML instance.
+%readObj = %taml.read( "stuff.taml" );
+
+// Delete the instance of Taml.
+%taml.delete();
+@endcode
+
+The "TamlWrite()" and "TamlRead()" essentially remove the need to generate a TAML instance and delete if afterwards.  Whilst this is convenient in many cases, these functions don't expose all the other features that TAML provides therefore it becomes necesssary to use a TAML instance when you wish to use them.
+
+There is an exception to this, both the "TamlWrite()" and "TamlRead()" support additional arguments to specify the formats to use however that will be covered below.
+
+## Multiple formats
+
+TAML currently supports two named formats of:
+
+- XML
+- Binary
+
+The XML format offers an easily edited format which is useful during game construction to edit outside of any editor.  XML however is more verbose and typically produces larger file sizes however this disadvantage is greatly outweighed by the fact that it is easily editable.
+
+The Binary format is not easily edited but produces smaller file sizes, especially when compression is used.
+
+TAML can easily be extended to support more format types as long as the the format can encapsulate the state that TAML compiles when it analyses an object.  Also, all formats must obviously be lossless and produce identical results in that if you were to read from one format and save to another then read that back and save back to the original format, the output should be identical.  Currently both the XML and Binary formats strictly adhere to this principle.
+
+There are two ways to select which format to use for writing and reading, one explicit and the other implicit.
+
+Here's a couple of explicit method examples:
+
+@code{.cpp}
+// Create a sprite.
+%obj = new Sprite();
+
+// Create an instance of TAML.
+%taml = new Taml();
+
+// Set the XML format.
+%taml.Format = Xml;
+
+// Write it out.
+%taml.write( %obj, "stuff.taml" );
+
+// Read it in.
+%readObj = %taml.read( "stuff.taml" );
+
+// Delete the instance of Taml.
+%taml.delete();
+@endcode
+
+@code{.cpp}
+// Create a sprite.
+%obj = new Sprite();
+
+// Create an instance of TAML.
+%taml = new Taml();
+
+// Set the Binary format.
+%taml.Format = Binary;
+
+// Write it out.
+%taml.write( %obj, "stuff.baml" );
+
+// Read it in.
+%readObj = %taml.read( "stuff.baml" );
+
+// Delete the instance of Taml.
+%taml.delete();
+@endcode
+
+As you can see, the format was set using the field "Format" but an alternate is using the method "setFormat()".  You can currently specify either "xml" or "binary" for the format.  The TAML instance will then use that format for all subsequent write and read operations.
+
+In the examples the extensions ".taml" and ".baml" were used to denote an XML file and a Binary file respectively however these extensions and filenames can be whatever you choose.
+
+Explicit formatting provides very fine control over write and read operations however it's common to not actually know the format but instead establish an extension to denote a format type just like you would expect for other file types.
+
+Implicit formatting also known as "auto format" works without you having to select the format mode.  Auto format does this by looking at the specified filename in the write or read operation and uses its extension to determine which format to use.
+
+Taml comes with defaults for the filename extensions for both XML and Binary, these being "taml" and "baml" respectively but you are free to change those easily.
+
+Here's an example auto-format:
+
+@code{.cpp}
+// Create a sprite.
+%obj = new Sprite();
+
+// Create an instance of TAML.
+%taml = new Taml();
+
+// Write it out in XML.
+%taml.write( %obj, "stuff.taml" );
+
+// Write it out in Binary.
+%taml.write( %obj, "stuff.baml" );
+
+// Read it in.
+%readObj1 = %taml.read( "stuff.taml" );
+%readObj2 = %taml.read( "stuff.baml" );
+
+// Delete the instance of Taml.
+%taml.delete();
+@endcode
+
+As you can see, there's no format specification anywhere.  Again, this is because TAML determined that the "taml" extension is associated with XML and the "baml" extension with Binary.
+
+You can change these meanings and reuse a TAML instance if you so desire like so:
+
+@code{.cpp}
+// Create a sprite.
+%obj = new Sprite();
+
+// Create an instance of TAML.
+%taml = new Taml()
+
+%taml.AutoFormatXmlExtension = "xml";
+%taml.AutoFormatBinaryExtension = "bin";
+
+// Write it out in XML.
+%taml.write( %obj, "stuff.xml" );
+
+// Write it out in Binary.
+%taml.write( %obj, "stuff.bin" );
+
+// Read it in.
+%readObj1 = %taml.read( "stuff.xml" );
+%readObj2 = %taml.read( "stuff.bin" );
+
+// Delete the instance of Taml.
+%taml.delete();
+@endcode
+
+Currently, TAML only supports a single file extension specification but it's a trivial matter to change this to support multiple extensions should it be required.
+
+When using the Binary format you can also specify whether binary compression is used or not.  This is used by default and you should not turn it off unless you have a good reason to do so.
+
+It is controlled with the following:
+
+- setBinaryCompression(true/false)
+- getBinaryCompression()
+- "BinaryCompression" field.
+
+## TamlRead and TamlWrite
+
+Given the various methods for explicit and implicit format control, it's worth knowing that the simplified "TamlWrite()" and "TamlRead()" expose the ability to specify an explicit format like so:
+
+@code{.cpp}
+// Create a sprite.
+%obj = new Sprite();
+
+// Write it out in XML.
+TamlWrite( %obj, "stuff.txt", xml );
+
+// Write it out in Binary.
+TamlWrite( %obj, "stuff.dat1", binary );
+
+// Write it out in Binary (with compression off).
+TamlWrite( %obj, "stuff.dat2", binary, false );
+@endcode
+
+## Writing Defaults
+
+When TAML determines that it needs to write out an object it checks each field to see if it should be written or not.  It does this internally using a mechanism that allows a type to say whether it currently wants to write the field or not.  In nearly all cases this decision is simply based upon whether the field is at its default or not.
+
+You can control whether TAML asks this question or not or put another way, whether it simply writes out all fields or only the ones that are not at their defaults.
+
+Writing out fields that are at their defaults results in larger files which are slower to read.  Also, setting fields that are already at their default when reading is a waste of time.  Some may prefer to have all the available fields for an object written out, sometimes used as a crude way of knowing what is available but this is not only an expensive way of doing things, it's also confusing to interpret because it's not easy to see how one object is configured differently than another as all fields are written.
+
+If you do wish to write all fields that are at defaults, you can control it using the following:
+
+- setWriteDefaults(true/false)
+- getWriteDefaults()
+- "WriteDefaults" field.
+
+By default, writing defaults is off.
+
+## Progenitor Update
+
+When you generate an instance of any type in TorqueScript, the instance is flagged with the filename of the script that created it.  
+
+For instance, let's say the following method is called and is compiled in the file "\T2D\foo.cs":
+
+@code{.cpp}
+function bar()
+{
+	# Create a sprite (this could be any SimObject).
+	%sprite = new Sprite();
+	
+	# Echo the progenitor file.
+	echo( %sprite.getProgenitorFile() );
+}
+@endcode
+
+The above example would output "\T2D\foo.cs" as that is the script it was created in.
+
+This is extremely useful for debugging however, what does this have to do with TAML?  Because TAML can generate object instances as well and those instances are not defined inside a script but inside a TAML formatted file it makes sense for TAML to update the progenitor file to refer to the TAML formatted file itself.
+
+By default TAML will do this however you can control whether it does so or not using the following:
+
+- setProgenitorUpdate(true/false)
+- getProgenitorUpdate()
+- "ProgenitorUpdate" field.
+
+If you turn-off progenitor updates then the progenitor file will be the last executing script that caused the TAML file to be read.
+
+## Advanced TAML
+
+The remainder of the document is more advanced and covers how TAML writes and reads state for objects.  This is useful when designing types as you must always take persistence into account as part of the design.  It's no good designing a type or a full system only to have to then figure out how to write and read its states afterwards.
+
+## TAML compilation
+
+When you specify an object to write, this doesn't necessarily mean that it's the only object that will get written.  This is due to the fact that various objects "own" or "contain" other objects, otherwise known as "children" objects.
+
+When TAML writes an object it performs several stages of compilation:
+
+1. Find all static and dynamic fields to write
+2. Find any child objects to write
+3. Find any custom state to write
+
+### Static and Dynamic Field Compilation
+
+This stage is actually in two parts.  The first part is iterating all the static fields and querying whether the field should be written or not.  Note that this query is only done if the TAML option of "WriteDefaults" is not active as described previously.
+
+This is done by simply using the Torque field system which allows a developer to specify for each field a setter, getter and write-field functions like so:
+
+@code{.cpp}
+addProtectedField("Angle", TypeF32, NULL, &setAngle, &getAngle, &writeAngle, "");
+@endcode
+
+In this example, the protected field is specifying a setter, getter and write functions although combinations of these are allowed.
+
+The "writeAngle" method is called by anything that needs to know if the field should be written or not.  In this case it's TAML calling it.  The "writeAngle" method in this example is defined as a method that determines if the angle is at its default or not.
+
+TAML quickly iterates all the static fields querying this and produces a list of static fields that need writing.
+
+Following this, TAML quickly iterates any dynamic fields that exist and adds them all because dynamic fields are just that, dynamic, and do not have any code related to them that can determine their meaning or if they should be written or not.
+
+### Children Object Compilation
+
+TAML will query the type to see if it implements the type [TamlChildren](https://github.com/GarageGames/Torque2D/blob/master/engine/source/persistence/taml/tamlChildren.h).  If it does then it queries how many children the object contains.  It then iterates each of those children perform a full compilation on each i.e. it will check for fields, for child objects and custom state as is being described here.
+
+This is the key to how writing a single object produces multiple objects being written.  This only occurs for types that have been specifically written to do this by implementing the "TamlChildren" type.  Notable types that do this are [SimSet](https://github.com/GarageGames/Torque2D/blob/master/engine/source/sim/simSet.h) which can contain as many other [SimObject](https://github.com/GarageGames/Torque2D/blob/master/engine/source/sim/simObject.h) as required and [Scene](https://github.com/GarageGames/Torque2D/blob/master/engine/source/2d/scene/Scene.h) which contains [SceneObject](https://github.com/GarageGames/Torque2D/blob/master/engine/source/2d/sceneobject/SceneObject.h).
+
+The [SimSet](https://github.com/GarageGames/Torque2D/blob/master/engine/source/sim/simSet.h) type is particularly useful as it allows you to persist a generic list of objects like so:
+
+@code{.cpp}
+%list = new SimSet();
+
+// Add some objects.
+%list.add( new ScriptObject() );
+%list.add( new ScriptObject() );
+%list.add( new ScriptObject() );
+
+// Write out the list.
+TamlWrite( %list, "list.taml" );
+
+@endcode
+
+... which produces the following XML output:
+
+@code{.xml}
+<SimSet>
+   <ScriptObject/>
+   <ScriptObject/>
+   <ScriptObject/>
+</SimSet>
+@endcode
+
+### Custom State
+
+When designing types you can simply expose state using Torques field system as long as the order at which fields are set is not critical.  If that serves your purposes then you do not need to perform any special work.
+
+_WIP_
+
+## XML Format
+
+Whilst the Binary format is difficult to describe and is not intended for editing anyway, the XML format is easy to describe and is intended for editing.
+
+As an example, here's a basic structure set up in the scripts:
+
+@code{.cpp}
+%bookList = new SimSet()
+{
+    Title="My Book List";
+};
+
+// Blatantly obvious advert: http://www.packtpub.com/torque-3d-game-development-cookbook/book
+%book1 = new ScriptObject()
+{
+    Title="Torque 3D Game Development Cookbook";
+    Author="Dave Wyand";
+};
+
+%book2 = new ScriptObject()
+{
+    Title="Graphics Programming Black Book (Special Edition)";
+    Author="Michael Abrash";
+};
+
+%book3 = new ScriptObject()
+{
+    Title="Programming with Graphics";
+    Author="Garry Marshall";
+};
+
+%bookList.add( %book1 );
+%bookList.add( %book2 );
+%bookList.add( %book3 );
+
+TamlWrite( %bookList, "booklist.taml" );
+@endcode
+
+This produces the following in XML format:
+
+@code{.xml}
+<SimSet
+	Title="My Book List">
+	<ScriptObject
+		Title="Torque 3D Game Development Cookbook"
+		Author="Dave Wyand"/>
+	<ScriptObject
+		Title="Graphics Programming Black Book (Special Edition)"
+		Author="Michael Abrash"/>				
+	<ScriptObject
+		Title="Programming with Graphics"
+		Author="Garry Marshall"/>				
+</SimSet>
+@endcode
+
+The XML schema used here is pretty simple.  Each [XML element](http://www.w3schools.com/xml/xml_elements.asp) represents an engine type to be created.  Each [XML attribute](http://www.w3schools.com/xml/xml_attributes.asp) represents a field to be set.  The field might be a static or dynamic Torque field, both are represented by the fields' name only.
+
+The relative position of each XML element is also important as the XML file represents an [XML Tree](http://www.w3schools.com/xml/xml_tree.asp).  The root element is the object which was originally written and is the object that will be returned when the file is subsequently read again.
+
+XML Elements that appear as children of other XML elements are indeed children objects and are added to the parent object.  As seen in previous examples, the parent object might be a [Scene](https://github.com/GarageGames/Torque2D/blob/master/engine/source/2d/scene/Scene.h) or in this example a [SimSet](https://github.com/GarageGames/Torque2D/blob/master/engine/source/sim/simSet.h).
+
+TAML also supports object referencing allow the same object to be referenced more than once inside a TAML file.
+
+For instance, let's say we did this:
+
+@code{.cpp}
+%list = new SimSet();
+
+%obj = new ScriptObject();
+%list.add( %obj );
+%list.add( %obj );
+%list.add( %obj );
+
+TamlWrite( %list, "list.taml" );
+@endcode
+
+In this example, we add the same object several times to the parent object.  This produces the following XML format:
+
+@code{.xml}
+<SimSet>
+	<ScriptObject TamlId="1"/>
+	<ScriptObject TamlRefId="1"/>
+	<ScriptObject TamlRefId="1"/>
+</SimSet>
+@endcode
+
+What this example shows are two new fields of "TamlId" and "TamlRefId".  These fields represent an automatically assigned object Id and a reference to an automatically assigned object Id respectively.
+
+The output format associates the first occurance of the object with its automatically assigned Id using TamlId="1".  This establishes the identity of this object.  If any subsequent XML elements refer to this object then they use TamlRefId="1".  This informs TAML to NOT create a new instance of the type but to simply use the reference to the previously created one.
+
+In the above example, this causes the first "ScriptObject" type to be created and added to the "SimSet" then the following two occurences of "ScriptObject" are treated as simply references to the first "ScriptObject" created and these are added to the "SimSet" resulting in a "SimSet" listing three of the same object.
+
+The actual Id used here is not available on the "ScriptObject" (or any other object involved) as it is completely dealt with by TAML itself.  The actual values used for Ids are not important (apart from being >0), simply that any Ids and references to Ids match up appropriately.
+
+### Named Objects
+
+TAML will quite happily persist named Torque objects however you must take extreme care when doing so because it is very easy to read such TAML files more than once causing previously named objects to be left orphaned.
+
+Writing a named object simply causes the "Name" field to be written like so:
+
+@code{.cpp}
+TamlWrite( new ScriptObject(Fred), "test.taml" );
+@endcode
+
+@code{.xml}
+<ScriptObject Name="Fred"/>
+@endcode
+
+When this is first read it produces a "ScriptObject" with the name "Fred" however, if it was read again then the original object known solely by the name "Fred" would be lost, replaced by the newly named object.
+
+Whilst this global namespace for Torque objects is very useful, especially for GUI files, careful consideration to persisting such objects should be taken.
+
+
+## TAML Callbacks
+
+TAML provides a [TamlCallbacks](https://github.com/GarageGames/Torque2D/blob/master/engine/source/persistence/taml/tamlCallbacks.h) type which defines all the callbacks that TAML will perform on any object being written or read.  This type is implemented by [SimObject](https://github.com/GarageGames/Torque2D/blob/master/engine/source/sim/simObject.h) so is available to every object that TAML can process.
+
+Each callback is virtual therefore allowing any derived type to hook into the callback but you must always ensure that you additionally call the parent type.
+
+The callbacks and their meaning as as follows:
+
+- onTamlPreWrite() - Called prior to TAML writing the object.
+- onTamlPostWrite() - Called after TAML has finished writing the object.
+- onTamlPreRead() - Called prior to TAML reading the objects state.
+- onTamlPostRead() - Called after TAML has read the objects state.
+- onTamlAddParent() - Called after 'onTamlPostRead()' and has added the object to a parent object i.e. it is a child.
+- onTamlCustomWrite() - Called during the writing of the object to allow custom properties to be written.
+- onTamlCustomRead() - Called during the reading of the object to allow custom properties to be read.
+
+Whilst these callbacks can be used for almost any purpose, they do have some typical uses.
+
+The "onTamlPreWrite()" and "onTamlPostWrite()" can be used for preparation of an object prior to writing and post-write clean-up.  This kind of work should be avoided so as to not cause side-effects during writing but it can be useful in certain circumstances.
+
+The "onTamlPostRead()" and "onTamlAddParent()" can useful when some specific initialization is required after reading or adding to a parent.  Again, this should be avoided as the need for some specific initialization actions after the state has been set isn't a good design configuration but can be useful in certain circumstances.
+
+*/

+ 2 - 0
engine/source/persistence/taml/taml.h

@@ -69,6 +69,8 @@ extern StringTableEntry tamlNamedObjectName;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class Taml : public SimObject
 class Taml : public SimObject
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/tamlCallbacks.h

@@ -30,6 +30,8 @@ class SimObject;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlCallbacks
 class TamlCallbacks
 {
 {
     friend class Taml;
     friend class Taml;

+ 2 - 0
engine/source/persistence/taml/tamlChildren.h

@@ -33,6 +33,8 @@ class SimObject;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlChildren
 class TamlChildren
 {
 {
 public:
 public:

+ 6 - 0
engine/source/persistence/taml/tamlCustom.h

@@ -65,6 +65,8 @@ typedef Vector<TamlCustomField*> TamlCustomFieldVector;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlCustomField : public IFactoryObjectReset
 class TamlCustomField : public IFactoryObjectReset
 {
 {
 public:
 public:
@@ -278,6 +280,8 @@ private:
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlCustomNode : public IFactoryObjectReset
 class TamlCustomNode : public IFactoryObjectReset
 {
 {
 public:
 public:
@@ -599,6 +603,8 @@ private:
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlCustomNodes : public IFactoryObjectReset
 class TamlCustomNodes : public IFactoryObjectReset
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/tamlParser.h

@@ -31,6 +31,8 @@ class TamlVisitor;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlParser
 class TamlParser
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/tamlVisitor.h

@@ -31,6 +31,8 @@ class TamlParser;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlVisitor
 class TamlVisitor
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/tamlWriteNode.h

@@ -41,6 +41,8 @@ class TamlCallbacks;
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlWriteNode
 class TamlWriteNode
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/xml/tamlXmlParser.h

@@ -33,6 +33,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlXmlParser : public TamlParser
 class TamlXmlParser : public TamlParser
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/xml/tamlXmlReader.h

@@ -37,6 +37,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlXmlReader
 class TamlXmlReader
 {
 {
 public:
 public:

+ 2 - 0
engine/source/persistence/taml/xml/tamlXmlWriter.h

@@ -33,6 +33,8 @@
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+/// @ingroup tamlGroup
+/// @see tamlGroup
 class TamlXmlWriter
 class TamlXmlWriter
 {
 {
 public:
 public:

+ 5 - 1
tools/documentation/config/torque2DReference.cfg

@@ -1487,6 +1487,8 @@ MAN_LINKS              = NO
 # generate an XML file that captures the structure of
 # generate an XML file that captures the structure of
 # the code including all documentation.
 # the code including all documentation.
 
 
+# T2D
+
 GENERATE_XML           = NO
 GENERATE_XML           = NO
 
 
 # The XML_OUTPUT tag is used to specify where the XML pages will be put.
 # The XML_OUTPUT tag is used to specify where the XML pages will be put.
@@ -1512,7 +1514,9 @@ XML_DTD                =
 # and cross-referencing information) to the XML output. Note that
 # and cross-referencing information) to the XML output. Note that
 # enabling this will significantly increase the size of the XML output.
 # enabling this will significantly increase the size of the XML output.
 
 
-XML_PROGRAMLISTING     = YES
+# T2D
+
+XML_PROGRAMLISTING     = NO
 
 
 #---------------------------------------------------------------------------
 #---------------------------------------------------------------------------
 # configuration options for the AutoGen Definitions output
 # configuration options for the AutoGen Definitions output

+ 4 - 1
tools/documentation/config/torqueScriptReference.cfg

@@ -699,7 +699,10 @@ INPUT_ENCODING         = UTF-8
 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
 # *.f90 *.f *.for *.vhd *.vhdl
 # *.f90 *.f *.for *.vhd *.vhdl
 
 
-FILE_PATTERNS          = *_ScriptBinding.h
+# T2D: note that we allow any suffix after "_ScriptBinding".  The goal it to include,
+# for example, Trigger_ScriptBinding.h and Trigger_ScriptBinding.dox
+
+FILE_PATTERNS          = *_ScriptBinding.*
 
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories
 # should be searched for input files as well. Possible values are YES and NO.
 # should be searched for input files as well. Possible values are YES and NO.