Added docs for xml converter. Added XmlToLua.h. Condition code in xml is now passed through the lua converter to handle renamed things.
This commit is contained in:
@@ -210,6 +210,7 @@
|
||||
<Function name='collectgarbage'/>
|
||||
<Function name='color'/>
|
||||
<Function name='commify'/>
|
||||
<Function name='convert_xml_bgs'/>
|
||||
<Function name='dofile'/>
|
||||
<Function name='error'/>
|
||||
<Function name='fapproach'/>
|
||||
|
||||
@@ -121,6 +121,11 @@ save yourself some time, copy this for undocumented things:
|
||||
<Function name='ConnectToServer' return='bool' arguments='string sAddress'>
|
||||
Tries to connect to the server at <code>sAddress</code>.
|
||||
</Function>
|
||||
<Function name='convert_xml_bgs' return='' arguments='string dir'>
|
||||
Recursively searches <code>dir</code> for xml files of actors and
|
||||
converts them to equivalent lua files. See Docs/Themerdocs/XmlToLua.txt
|
||||
for details.
|
||||
</Function>
|
||||
<Function name='create_spline' return='CubicSplineN' arguments=''>
|
||||
Creates a CubicSplineN for you to use. Make sure you destroy the CubicSplineN when you're done with it, or you will have a memory leak.
|
||||
</Function>
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
StepMania 5 has an xml converter inside it intended to assist authors who want
|
||||
to convert the xml scripted background and foreground animations written for
|
||||
StepMania 3.95 or OpenITG to work with StepMania 5.
|
||||
|
||||
The primary way to invoke the converter is to use the debug menu.
|
||||
While on the Select Music screen, navigate to the song with xml that needs to
|
||||
be converted. Hold F3, press F6 to change to the theme section, then press 0
|
||||
to convert the xml in the folder of the current song.
|
||||
|
||||
The other way is to use a theme that provides some interface to the
|
||||
convert_xml_bgs lua function.
|
||||
|
||||
|
||||
Since the converter recursively searches for all xml files in the folder
|
||||
given, if you have foo/default.xml, it will be converted to foo/default.lua.
|
||||
If foo/bar/default.xml exists, foo/bar/default.lua will be created.
|
||||
|
||||
When the converter finds an xml file, it parses it and attempts to create lua
|
||||
that results in the same actors. Some things are converted without problems,
|
||||
others are beyond the scope of the converter and are not handled.
|
||||
|
||||
Do not run the converter on a song that you have already converted. When it
|
||||
finds the xml files, it will overwrite the lua files with new ones, which
|
||||
means any fixes applied after conversion will be wiped out.
|
||||
|
||||
The converter does not delete the xml files after conversion because you
|
||||
probably need them to double check things.
|
||||
|
||||
|
||||
|
||||
# Known working conversions
|
||||
|
||||
## Naming
|
||||
Actors and conditions are assigned autogenerated unique names with the prefix
|
||||
"xtl_actor_" or "xtl_cond_". This is so that if some error message tells you
|
||||
the name of an actor, you can find it in the code. If an actor has a Name
|
||||
field, that will be used instead of the autogenerated unique name.
|
||||
|
||||
## Type guessing
|
||||
|
||||
Typically, the Type or Class field is used, unless the File field points to
|
||||
something that has to be a certain type.
|
||||
|
||||
* ActorFrames with children are handled.
|
||||
|
||||
* File field conditions:
|
||||
* Images and .sprite files are converted to Sprites.
|
||||
* .txt and .model files are converted to Models.
|
||||
* Folders are converted to use LoadActor, which has its own rules for
|
||||
guessing the actor type.
|
||||
* Sound files are converted to ActorSound.
|
||||
|
||||
* If there is a Text field, the actor is assumed to be a BitmapText.
|
||||
|
||||
|
||||
## Field conversion
|
||||
|
||||
Any field that ends with "Command" is recognized as a command and passes
|
||||
through command conversion.
|
||||
Anything else passes through unchanged, unless it's known to be a string
|
||||
field. String fields will be strings after conversion.
|
||||
This may cause syntax errors if a field is meant to be a string and it's not
|
||||
a string after conversion. This happens because in XML, all fields are
|
||||
stored in strings and the only way to know which ones are supposed to be
|
||||
strings after conversion is to keep a list of field names.
|
||||
String fields:
|
||||
* AltText
|
||||
* Bones
|
||||
* File
|
||||
* Font
|
||||
* Materials
|
||||
* Meshes
|
||||
* Text
|
||||
* Texture
|
||||
|
||||
|
||||
## Command conversion
|
||||
|
||||
Commands that use the normal style are converted to use SM5's cmd syntax.
|
||||
These commands are passed through a parser that looks for certain things that
|
||||
require special handling:
|
||||
* x coords are changed to use (SCREEN_CENTER_X + (x - 320)), to put them in
|
||||
the same position relative to the center. This is only applied if the
|
||||
coord was a simple number, expressions are not changed.
|
||||
* y coords are changed similarly to x coords.
|
||||
* queuecommand, playcommand, and effectclock all have their arguments changed
|
||||
to strings.
|
||||
* EffectMagnitude, ZoomToWidth, and ZoomToHeight are renamed to the lowercase
|
||||
names SM5 uses.
|
||||
* blend and cullmode have their args converted to SM5's enum values.
|
||||
* hidden is converted to visible, and its arg is converted to a bool.
|
||||
* diffuse, effectcolor1, and effectcolor2 have their args converted to use
|
||||
the color function.
|
||||
|
||||
|
||||
Commands that use lua functions are converted with the lua mostly unchanged.
|
||||
A very short list of things in lua are recognized and replaced with their
|
||||
SM5 equivalents.
|
||||
* "hidden(0)" becomes "visible(true)"
|
||||
* "hidden(1)" becomes "visible(false)"
|
||||
* "effectdelay" becomes "effect_hold_at_full"
|
||||
* "IsPlayerEnabled(0)" becomes "IsPlayerEnabled(PLAYER_1)"
|
||||
* "IsPlayerEnabled(1)" becomes "IsPlayerEnabled(PLAYER_2)"
|
||||
|
||||
The list is short and the strings must match exactly because symbolically
|
||||
parsing the lua into tokens to recognize other ways of doing the same thing
|
||||
is beyond the scope of the converter.
|
||||
|
||||
|
||||
## Condition conversion
|
||||
|
||||
Because conditions are lua code to execute, they are passed through the same
|
||||
converter as lua commands.
|
||||
It is common practice for many actors to have identical conditions, so all
|
||||
conditions are collected in a list, so they can be evaluated once when the
|
||||
file is loaded, and then the actors can just use the result.
|
||||
So after conversion you might see something like this:
|
||||
```
|
||||
xtl_cond_a_result= GAMESTATE:IsPlayerEnabled(PLAYER_1)
|
||||
local function optional_actor(cond, actor)
|
||||
if cond then return actor end
|
||||
return Def.Actor{}
|
||||
end
|
||||
```
|
||||
The optional_actor function is a convenient way to insert a blank, unrendered
|
||||
actor instead of one that actually does something.
|
||||
You'll see it used like this:
|
||||
```
|
||||
optional_actor(xtl_cond_a_result,
|
||||
Def.Sprite{
|
||||
Name= "xtl_actor_g",
|
||||
InitCommand= cmd(x,0;y,0),
|
||||
Texture= "foo 3x1.png",
|
||||
}),
|
||||
```
|
||||
|
||||
|
||||
|
||||
# Known unhandled things
|
||||
|
||||
Some things like difficulty use strings as enum values in SM5. Lua code that
|
||||
uses GetDifficulty or other things that now return enum strings must be
|
||||
edited after conversion to use the enum strings.
|
||||
|
||||
There are probably renamed functions that the converter does not handle.
|
||||
|
||||
GAMESTATE:ApplyGameCommand applies mods instantly, ignoring the tween
|
||||
speeds. Lua code that changes mods should use the PlayerOptions API instead.
|
||||
This means fetching a PlayerOptions object and converting mod strings to
|
||||
function names and args, which isn't hard with an editor with regex find and
|
||||
replace.
|
||||
|
||||
Actor sizes are not changed, so if an actor is meant to be the size of the
|
||||
screen, it will probably not cover the screen when Stepmania isn't a 4:3
|
||||
aspect ratio. Use SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_CENTER_X,
|
||||
SCREEN_CENTER_Y, _screen.w, _screen.h, _screen.cx, or _screen.cy for
|
||||
positioning and sizing. Actor:FullScreen exists to stretch an actor to cover
|
||||
the screen.
|
||||
@@ -118,6 +118,7 @@ list(APPEND SMDATA_FILE_TYPES_HPP
|
||||
"IniFile.h"
|
||||
"MsdFile.h"
|
||||
"XmlFile.h"
|
||||
"XmlToLua.h"
|
||||
"XmlFileUtil.h"
|
||||
)
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "Song.h"
|
||||
#include "ScreenSyncOverlay.h"
|
||||
#include "ThemeMetric.h"
|
||||
#include "XmlToLua.h"
|
||||
|
||||
static bool g_bIsDisplayed = false;
|
||||
static bool g_bIsSlow = false;
|
||||
@@ -1116,8 +1117,7 @@ class DebugLineClearErrors : public IDebugLine
|
||||
}
|
||||
};
|
||||
|
||||
void convert_xmls_in_dir(RString const& dirname);
|
||||
class DebugLineConvrtXML : public IDebugLine
|
||||
class DebugLineConvertXML : public IDebugLine
|
||||
{
|
||||
virtual RString GetDisplayTitle() { return CONVERT_XML.GetValue(); }
|
||||
virtual RString GetDisplayValue() { return RString(); }
|
||||
@@ -1319,7 +1319,7 @@ DECLARE_ONE( DebugLineReloadTheme );
|
||||
DECLARE_ONE( DebugLineReloadOverlayScreens );
|
||||
DECLARE_ONE( DebugLineToggleErrors );
|
||||
DECLARE_ONE( DebugLineClearErrors );
|
||||
DECLARE_ONE( DebugLineConvrtXML );
|
||||
DECLARE_ONE( DebugLineConvertXML );
|
||||
DECLARE_ONE( DebugLineWriteProfiles );
|
||||
DECLARE_ONE( DebugLineWritePreferences );
|
||||
DECLARE_ONE( DebugLineMenuTimer );
|
||||
|
||||
+13
-6
@@ -245,6 +245,15 @@ void init_parser_helpers()
|
||||
chunks_to_replace["IsPlayerEnabled(1)"]= "IsPlayerEnabled(PLAYER_2)";
|
||||
}
|
||||
|
||||
void convert_lua_chunk(RString& chunk_text)
|
||||
{
|
||||
for(map<RString, RString>::iterator chunk= chunks_to_replace.begin();
|
||||
chunk != chunks_to_replace.end(); ++chunk)
|
||||
{
|
||||
chunk_text.Replace(chunk->first, chunk->second);
|
||||
}
|
||||
}
|
||||
|
||||
// Conditions are mapped by condition string.
|
||||
// So condition_set_t::iterator->first is the lua to execute for the
|
||||
// condition, and condition_set_t::iterator->second is the name of the
|
||||
@@ -293,11 +302,7 @@ void actor_template_t::store_cmd(RString const& cmd_name, RString const& full_cm
|
||||
if(full_cmd.Left(1) == "%")
|
||||
{
|
||||
RString cmd_text= full_cmd.Right(full_cmd.size()-1);
|
||||
for(map<RString, RString>::iterator chunk= chunks_to_replace.begin();
|
||||
chunk != chunks_to_replace.end(); ++chunk)
|
||||
{
|
||||
cmd_text.Replace(chunk->first, chunk->second);
|
||||
}
|
||||
convert_lua_chunk(cmd_text);
|
||||
fields[cmd_name]= cmd_text;
|
||||
return;
|
||||
}
|
||||
@@ -739,7 +744,9 @@ void convert_xml_file(RString const& fname, RString const& dirname)
|
||||
for(condition_set_t::iterator cond= conditions.begin();
|
||||
cond != conditions.end(); ++cond)
|
||||
{
|
||||
file->Write("local " + cond->second + "_result= " + cond->first + "\n\n");
|
||||
RString cond_text= cond->first;
|
||||
convert_lua_chunk(cond_text);
|
||||
file->Write("local " + cond->second + "_result= " + cond_text + "\n\n");
|
||||
}
|
||||
if(!conditions.empty())
|
||||
{
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#ifndef XmlToLua_H
|
||||
#define XmlToLua_H
|
||||
void convert_xmls_in_dir(RString const& dirname);
|
||||
#endif
|
||||
Reference in New Issue
Block a user