DMX: Difference between revisions
(→Programming: third-party libraries) |
(→Model) |
||
Line 46: | Line 46: | ||
=== Model === | === Model === | ||
The [[DMX model]] replaces [[SMD]]. It can be exported by Valve's official Maya plugin (<code>sourcesdk/maya/2009/plug-ins/valveSource/</code>) and the [[Blender SMD Tools]]. | |||
There are some DMX-related tools in the SDK: | |||
* [[dmxedit]] | |||
* [[dmxconvert]] | |||
* | |||
=== Source Filmmaker sessions === | === Source Filmmaker sessions === |
Revision as of 02:25, 27 September 2013
DMX (Data Model eXchange) stores a Datamodel object, encoded in either binary or ASCII. The SDK tool dmxconvert (available in Source Filmmaker and Counter-Strike: Global Offensive's SDK) can convert a DMX between the two formats.
The internal structure or "format" of a DMX is defined by the user.
Header
All DMX files start with this header:
<!-- dmx encoding [encoding name] [encoding version] format [format name] [format version] -->
Encodings
KeyValues2
This ASCII encoding is the successor to KeyValues. It's good if you have a small DMX and want it hand-editable.


Binary
Compared to KeyValues2, binary DMX is:
- Small, especially when storing large ints or accurate floats
- Fast, as values do not have to be converted to or from human-readable characters
- Robust, since it does not have to worry about delimiters, line breaks or unclosed quote blocks
- Inscrutable, because it contains native binary data
Binary is good for large DMXes.
See DMX/Binary for a technical description of the encoding.
Formats
These are the formats used by Valve.
Particle System
Created by the Particle Editor and read by the engine, usually with the extension pcf
. There should be no reason to manipulate these yourself.
Model
The DMX model replaces SMD. It can be exported by Valve's official Maya plugin (sourcesdk/maya/2009/plug-ins/valveSource/
) and the Blender SMD Tools.
There are some DMX-related tools in the SDK:
Source Filmmaker sessions
See Source Filmmaker.
Programming
Handling DMX files has many similarities to handling KeyValues. The big architectural differences are that:
- Where KVs had keys, Datamodel has
CDmxElement
objects containingCDmxAttribute
(which can point to further elements). - There is support for arrays.
- Attribute values are accessed through a single templated function, not lots of different ones.
- Each element can have multiple parents. Each element has a 128-bit ID to support this.
Source API
Source has two DMX APIs: CDmxElement
and CDmElement
. The former is a lightweight implementation designed for use in game code; the latter is designed around the needs of the engine tools and includes heavyweight features like undo levels and element factories. The mod SDK only supports CDmxElement
.
For a full list of attribute types, see the bottom of public\datamodel\dmattributetypes.h
.

CUtlString
objects, not char
!Creating

SerializeDMX()
overload that requires a file path does not work. You must serialize to a buffer then write out manually. [todo tested in ?]#include "cbase.h"
#include "dmxloader/dmxloader.h"
#include "dmxloader/dmxelement.h"
CON_COMMAND( dmx_create, "Makes a simple DMX" )
{
DECLARE_DMX_CONTEXT();
CDmxElement* DMX = CreateDmxElement("MyElementTypeName");
DMX->AddAttribute("C++ templates")->SetValue<bool>(true);
DMX->AddAttribute("Hello")->SetValue("world"); // non-templated shortcut for strings
DMX->AddAttribute("An_Array")->GetArrayForEdit<float>().AddToTail(3.141);
CUtlBuffer buf;
SerializeDMX(buf,DMX);
FileHandle_t fh = filesystem->Open("test.dmx","w","DEFAULT_WRITE_PATH");
filesystem->Write(buf.Base(),buf.TellPut(),fh);
filesystem->Close(fh);
}
Iterator
This code will print string, int, float and bool values in the given DMX to the console.
#include "cbase.h"
#include "dmxloader/dmxloader.h"
#include "dmxloader/dmxelement.h"
void IterateDmxElement(CDmxElement* pRoot)
{
for (int i=0;i<pRoot->AttributeCount();i++)
{
CDmxAttribute* pCur = pRoot->GetAttribute(i);
CDmxElement* subElem;
Warning( "%s: ",pCur->GetName() );
switch (pCur->GetType())
{
case AT_ELEMENT:
subElem = pCur->GetValue<CDmxElement*>();
if (subElem)
IterateDmxElement(subElem);
break;
case AT_STRING:
Msg( "STRING | %s\n",pCur->GetValue<CUtlString>().Get() );
break;
case AT_INT:
Msg( "INT | %i\n",pCur->GetValue<int>() );
break;
case AT_FLOAT:
Msg( "FLOAT | %f\n",pCur->GetValue<float>() );
break;
case AT_BOOL:
Msg( "BOOL | %s\n",pCur->GetValue<bool>() ? "true" : "false" );
break;
default:
Msg("Unknown type %i\n",pCur->GetType());
break;
}
}
}
CON_COMMAND(dmx_iterate, "Prints a DMX file to the console")
{
DECLARE_DMX_CONTEXT();
CDmxElement* DMX = (CDmxElement*)DMXAlloc( 50000000 );
if (UnserializeDMX(args[1],"MOD",false,&DMX))
{
IterateDmxElement(DMX);
}
else
Warning("Could not read DMX file %s\n",args[1]);
}
KeyValues2
dmxloader.lib has several "TextDMX" functions that are not referenced in the SDK's headers. Among them are:
bool UnserializeTextDMX(const char* pFilename,CUtlBuffer & buf,CDmxElement** ppRoot); // fails
bool SerializeTextDMX(const char* pFilename,CUtlBuffer & buf,CDmxElement* pRoot); // produces invalid files
They are both underdeveloped. It's possible that only CDmElement
supports KeyValues2.
Third-party libraries
There are currently two other Datamodel/DMX libraries:
- Datamodel.NET (CLR/C#)
- datamodel.py (Python)