2015-05-01 07:50:34 -06:00
# include "global.h"
# include "ActorUtil.h"
# include "IniFile.h"
# include "RageFile.h"
# include "RageFileManager.h"
# include "RageLog.h"
# include "RageTypes.h"
# include "LuaManager.h"
# include "LuaBinding.h"
# include "XmlFile.h"
# include "XmlFileUtil.h"
# include <vector>
# include <map>
# include <set>
# define TWEEN_QUEUE_MAX 50
RString unique_name ( ) ;
void convert_xmls_in_dir ( RString const & dirname ) ;
void convert_xml_file ( RString const & fname , RString const & dirname ) ;
RString maybe_conv_pos ( RString pos , RString ( * conv_func ) ( float p ) ) ;
RString add_extension_to_relative_path_from_found_file (
RString const & relative_path , RString const & found_file ) ;
RString unique_name ( RString const & type )
{
static char const * name_chars = " abcdefghijklmnopqrstuvwxyz " ;
static int name_count = 0 ;
int curr_name = name_count ;
RString ret = " xtl_ " + type + " _ " ; // Minimize the chance of a name collision.
ret = ret + name_chars [ curr_name % 26 ] ;
while ( curr_name / 26 > 0 )
{
curr_name = curr_name / 26 ;
ret = ret + name_chars [ curr_name % 26 ] ;
}
+ + name_count ;
return ret ;
}
void convert_xmls_in_dir ( RString const & dirname )
{
2022-07-10 18:28:56 +03:00
std : : vector < RString > listing ;
2015-05-01 07:50:34 -06:00
FILEMAN - > GetDirListing ( dirname , listing , false , true ) ;
2022-07-10 18:28:56 +03:00
for ( std : : vector < RString > : : iterator curr_file = listing . begin ( ) ;
2015-05-01 07:50:34 -06:00
curr_file ! = listing . end ( ) ; + + curr_file )
{
switch ( ActorUtil : : GetFileType ( * curr_file ) )
{
case FT_Xml :
convert_xml_file ( * curr_file , dirname ) ;
break ;
case FT_Directory :
convert_xmls_in_dir ( ( * curr_file ) + " / " ) ;
break ;
default : // Ignore anything not xml or directory.
break ;
}
}
}
RString convert_xpos ( float x )
{
2019-06-22 12:35:38 -07:00
return " SCREEN_CENTER_X + " + std : : to_string ( x - 320.0f ) ;
2015-05-01 07:50:34 -06:00
}
RString convert_ypos ( float y )
{
2019-06-22 12:35:38 -07:00
return " SCREEN_CENTER_Y + " + std : : to_string ( y - 240.0f ) ;
2015-05-01 07:50:34 -06:00
}
RString maybe_conv_pos ( RString pos , RString ( * conv_func ) ( float p ) )
{
float f ;
if ( pos > > f )
{
return conv_func ( f ) ;
}
return pos ;
}
size_t after_slash_or_zero ( RString const & s )
{
size_t ret = s . rfind ( ' / ' ) ;
2022-07-10 18:28:56 +03:00
if ( ret ! = std : : string : : npos )
2015-05-01 07:50:34 -06:00
{
return ret + 1 ;
}
return 0 ;
}
RString add_extension_to_relative_path_from_found_file (
RString const & relative_path , RString const & found_file )
{
size_t rel_last_slash = after_slash_or_zero ( relative_path ) ;
size_t found_last_slash = after_slash_or_zero ( found_file ) ;
return relative_path . Left ( rel_last_slash ) +
2022-07-10 18:28:56 +03:00
found_file . substr ( found_last_slash , std : : string : : npos ) ;
2015-05-01 07:50:34 -06:00
}
2022-07-10 18:28:56 +03:00
bool verify_arg_count ( RString cmd , std : : vector < RString > & args , size_t req )
2015-05-01 07:50:34 -06:00
{
if ( args . size ( ) < req )
{
LuaHelpers : : ReportScriptError ( " Not enough args to " + cmd + " command. " ) ;
return false ;
}
return true ;
}
2022-07-10 18:28:56 +03:00
typedef void ( * arg_converter_t ) ( std : : vector < RString > & args ) ;
2015-05-01 07:50:34 -06:00
2022-07-10 18:28:56 +03:00
std : : map < RString , arg_converter_t > arg_converters ;
std : : map < RString , size_t > tween_counters ;
std : : set < RString > fields_that_are_strings ;
std : : map < RString , RString > chunks_to_replace ;
2015-05-01 07:50:34 -06:00
# define COMMON_ARG_VERIFY(count) if(!verify_arg_count(args[0], args, count)) return;
2022-07-10 18:28:56 +03:00
void x_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
COMMON_ARG_VERIFY ( 2 ) ;
float pos ;
if ( args [ 1 ] > > pos )
{
args [ 1 ] = convert_xpos ( pos ) ;
}
}
2022-07-10 18:28:56 +03:00
void y_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
COMMON_ARG_VERIFY ( 2 ) ;
float pos ;
if ( args [ 1 ] > > pos )
{
args [ 1 ] = convert_ypos ( pos ) ;
}
}
2022-07-10 18:28:56 +03:00
void string_arg_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
COMMON_ARG_VERIFY ( 2 ) ;
args [ 1 ] = " \" " + args [ 1 ] + " \" " ;
}
2022-07-10 18:28:56 +03:00
void lower_string_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
args [ 0 ] . MakeLower ( ) ;
}
2022-07-10 18:28:56 +03:00
void hidden_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
COMMON_ARG_VERIFY ( 2 ) ;
args [ 0 ] = " visible " ;
if ( args [ 1 ] = = " 1 " )
{
2016-08-05 12:01:48 -06:00
args [ 1 ] = " false " ;
2015-05-01 07:50:34 -06:00
}
else
{
2016-08-05 12:01:48 -06:00
args [ 1 ] = " true " ;
2015-05-01 07:50:34 -06:00
}
}
2022-07-10 18:28:56 +03:00
void diffuse_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
COMMON_ARG_VERIFY ( 2 ) ;
RString retarg ;
for ( size_t i = 1 ; i < args . size ( ) ; + + i )
{
retarg + = args [ i ] ;
if ( i < args . size ( ) - 1 )
{
retarg + = " , " ;
}
}
args [ 1 ] = " color(' " + retarg + " ') " ;
args . resize ( 2 ) ;
}
// Prototype for a function that is created by a macro in another translation unit and has no visible prototype, don't do this unless you have a good reason.
const RString & BlendModeToString ( BlendMode ) ;
const RString & CullModeToString ( CullMode ) ;
2022-07-10 18:28:56 +03:00
void blend_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
COMMON_ARG_VERIFY ( 2 ) ;
for ( int i = 0 ; i < NUM_BlendMode ; + + i )
{
RString blend_str = BlendModeToString ( static_cast < BlendMode > ( i ) ) ;
blend_str . MakeLower ( ) ;
if ( args [ 1 ] = = blend_str )
{
args [ 1 ] = " \" BlendMode_ " + BlendModeToString ( static_cast < BlendMode > ( i ) ) + " \" " ;
break ;
}
}
}
2022-07-10 18:28:56 +03:00
void cull_conv ( std : : vector < RString > & args )
2015-05-01 07:50:34 -06:00
{
COMMON_ARG_VERIFY ( 2 ) ;
for ( int i = 0 ; i < NUM_CullMode ; + + i )
{
RString cull_str = CullModeToString ( static_cast < CullMode > ( i ) ) ;
cull_str . MakeLower ( ) ;
if ( args [ 1 ] = = cull_str )
{
args [ 1 ] = " \" CullMode_ " + CullModeToString ( static_cast < CullMode > ( i ) ) + " \" " ;
break ;
}
}
}
# undef COMMON_ARG_VERIFY
void init_parser_helpers ( )
{
arg_converters [ " x " ] = & x_conv ;
arg_converters [ " y " ] = & y_conv ;
arg_converters [ " queuecommand " ] = & string_arg_conv ;
arg_converters [ " playcommand " ] = & string_arg_conv ;
arg_converters [ " effectclock " ] = & string_arg_conv ;
arg_converters [ " EffectMagnitude " ] = & lower_string_conv ;
arg_converters [ " ZoomToWidth " ] = & lower_string_conv ;
arg_converters [ " ZoomToHeight " ] = & lower_string_conv ;
arg_converters [ " blend " ] = & blend_conv ;
arg_converters [ " cullmode " ] = & cull_conv ;
arg_converters [ " hidden " ] = & hidden_conv ;
arg_converters [ " diffuse " ] = & diffuse_conv ;
arg_converters [ " effectcolor1 " ] = & diffuse_conv ;
arg_converters [ " effectcolor2 " ] = & diffuse_conv ;
tween_counters [ " sleep " ] = 2 ;
tween_counters [ " linear " ] = 1 ;
tween_counters [ " accelerate " ] = 1 ;
tween_counters [ " decelerate " ] = 1 ;
tween_counters [ " spring " ] = 1 ;
tween_counters [ " tween " ] = 1 ;
tween_counters [ " queuecommand " ] = 1 ;
fields_that_are_strings . insert ( " Texture " ) ;
fields_that_are_strings . insert ( " Text " ) ;
fields_that_are_strings . insert ( " AltText " ) ;
fields_that_are_strings . insert ( " File " ) ;
fields_that_are_strings . insert ( " Font " ) ;
fields_that_are_strings . insert ( " Meshes " ) ;
fields_that_are_strings . insert ( " Materials " ) ;
fields_that_are_strings . insert ( " Bones " ) ;
chunks_to_replace [ " hidden(0) " ] = " visible(true) " ;
chunks_to_replace [ " hidden(1) " ] = " visible(false) " ;
chunks_to_replace [ " effectdelay " ] = " effect_hold_at_full " ;
chunks_to_replace [ " IsPlayerEnabled(0) " ] = " IsPlayerEnabled(PLAYER_1) " ;
chunks_to_replace [ " IsPlayerEnabled(1) " ] = " IsPlayerEnabled(PLAYER_2) " ;
}
2015-05-08 23:55:38 -06:00
void convert_lua_chunk ( RString & chunk_text )
{
2022-07-10 18:28:56 +03:00
for ( std : : map < RString , RString > : : iterator chunk = chunks_to_replace . begin ( ) ;
2015-05-08 23:55:38 -06:00
chunk ! = chunks_to_replace . end ( ) ; + + chunk )
{
chunk_text . Replace ( chunk - > first , chunk - > second ) ;
}
}
2015-05-01 07:50:34 -06:00
// 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
// condition.
2022-07-10 18:28:56 +03:00
typedef std : : map < RString , RString > condition_set_t ;
typedef std : : map < RString , RString > field_cont_t ;
2015-05-01 07:50:34 -06:00
struct frame_t
{
int frame ;
float delay ;
frame_t ( ) : frame ( 0 ) , delay ( 0.0f ) { }
} ;
struct actor_template_t
{
RString type ;
field_cont_t fields ;
RString condition ;
RString name ;
2022-07-10 18:28:56 +03:00
std : : vector < frame_t > frames ;
std : : vector < actor_template_t > children ;
2015-05-01 07:50:34 -06:00
RString x ;
RString y ;
void make_space_for_frame ( int id ) ;
void store_cmd ( RString const & cmd_name , RString const & full_cmd ) ;
void store_field ( RString const & field_name , RString const & value , bool cmd_convert , RString const & pref = " " , RString const & suf = " " ) ;
void store_field ( RString const & field_name , XNodeValue const * value , bool cmd_convert , RString const & pref = " " , RString const & suf = " " ) ;
void rename_field ( RString const & old_name , RString const & new_name ) ;
RString get_field ( RString const & field_name ) ;
void load_frames_from_file ( RString const & fname , RString const & rel_path ) ;
void load_model_from_file ( RString const & fname , RString const & rel_path ) ;
void load_node ( XNode const & node , RString const & dirname , condition_set_t & conditions ) ;
void output_to_file ( RageFile * file , RString const & indent ) ;
} ;
void actor_template_t : : make_space_for_frame ( int id )
{
if ( id > = static_cast < int > ( frames . size ( ) ) )
{
frames . resize ( id + 1 ) ;
}
}
void actor_template_t : : store_cmd ( RString const & cmd_name , RString const & full_cmd )
{
if ( full_cmd . Left ( 1 ) = = " % " )
{
RString cmd_text = full_cmd . Right ( full_cmd . size ( ) - 1 ) ;
2015-05-08 23:55:38 -06:00
convert_lua_chunk ( cmd_text ) ;
2015-05-01 07:50:34 -06:00
fields [ cmd_name ] = cmd_text ;
return ;
}
2022-07-10 18:28:56 +03:00
std : : vector < RString > cmds ;
2015-05-01 07:50:34 -06:00
split ( full_cmd , " ; " , cmds , true ) ;
size_t queue_size = 0 ;
// If someone has a simfile that uses a playcommand that pushes tween
// states onto the queue, queue size counting will have to be made much
// more complex to prevent that from causing an overflow.
2022-07-10 18:28:56 +03:00
for ( std : : vector < RString > : : iterator cmd = cmds . begin ( ) ; cmd ! = cmds . end ( ) ; + + cmd )
2015-05-01 07:50:34 -06:00
{
2022-07-10 18:28:56 +03:00
std : : vector < RString > args ;
2015-05-01 07:50:34 -06:00
split ( * cmd , " , " , args , true ) ;
if ( ! args . empty ( ) )
{
2022-07-10 18:28:56 +03:00
for ( std : : vector < RString > : : iterator arg = args . begin ( ) ; arg ! = args . end ( ) ; + + arg )
2015-05-01 07:50:34 -06:00
{
size_t first_nonspace = 0 ;
size_t last_nonspace = arg - > size ( ) ;
while ( ( * arg ) [ first_nonspace ] = = ' ' )
{
+ + first_nonspace ;
}
while ( ( * arg ) [ last_nonspace ] = = ' ' )
{
- - last_nonspace ;
}
* arg = arg - > substr ( first_nonspace , last_nonspace - first_nonspace ) ;
}
2022-07-10 18:28:56 +03:00
std : : map < RString , arg_converter_t > : : iterator conv = arg_converters . find ( args [ 0 ] ) ;
2015-05-01 07:50:34 -06:00
if ( conv ! = arg_converters . end ( ) )
{
conv - > second ( args ) ;
}
2022-07-10 18:28:56 +03:00
std : : map < RString , size_t > : : iterator counter = tween_counters . find ( args [ 0 ] ) ;
2015-05-01 07:50:34 -06:00
if ( counter ! = tween_counters . end ( ) )
{
queue_size + = counter - > second ;
}
}
* cmd = join ( " , " , args ) ;
}
// This code is probably actually useless, OITG has the same tween queue size
// and the real reason I saw overflows in converted files was a bug in
// foreground loading that ran InitCommand twice. -Kyz
if ( queue_size > = TWEEN_QUEUE_MAX )
{
size_t num_to_make = ( queue_size / TWEEN_QUEUE_MAX ) + 1 ;
size_t states_per = ( queue_size / num_to_make ) + 1 ;
size_t states_in_curr = 0 ;
RString this_name = cmd_name ;
2022-07-10 18:28:56 +03:00
std : : vector < RString > curr_cmd ;
for ( std : : vector < RString > : : iterator cmd = cmds . begin ( ) ; cmd ! = cmds . end ( ) ; + + cmd )
2015-05-01 07:50:34 -06:00
{
curr_cmd . push_back ( * cmd ) ;
2022-07-10 18:28:56 +03:00
std : : vector < RString > args ;
2015-05-01 07:50:34 -06:00
split ( * cmd , " , " , args , true ) ;
if ( ! args . empty ( ) )
{
2022-07-10 18:28:56 +03:00
std : : map < RString , size_t > : : iterator counter = tween_counters . find ( args [ 0 ] ) ;
2015-05-01 07:50:34 -06:00
if ( counter ! = tween_counters . end ( ) )
{
states_in_curr + = counter - > second ;
if ( states_in_curr > = states_per - 1 )
{
RString next_name = unique_name ( " cmd " ) ;
curr_cmd . push_back ( " queuecommand, \" " + next_name + " \" " ) ;
fields [ this_name ] = " cmd( " + join ( " ; " , curr_cmd ) + " ) " ;
curr_cmd . clear ( ) ;
this_name = next_name ;
states_in_curr = 0 ;
}
}
}
}
if ( ! curr_cmd . empty ( ) )
{
fields [ this_name ] = " cmd( " + join ( " ; " , curr_cmd ) + " ) " ;
}
}
else
{
fields [ cmd_name ] = " cmd( " + join ( " ; " , cmds ) + " ) " ;
}
}
void actor_template_t : : store_field ( RString const & field_name , RString const & value , bool cmd_convert , RString const & pref , RString const & suf )
{
// OITG apparently allowed "Oncommand" as valid.
if ( field_name . Right ( 7 ) . MakeLower ( ) ! = " command " )
{
cmd_convert = false ;
}
if ( cmd_convert )
{
RString real_field_name = field_name . Left ( field_name . size ( ) - 7 ) + " Command " ;
store_cmd ( real_field_name , value ) ;
}
else
{
fields [ field_name ] = pref + value + suf ;
}
}
void actor_template_t : : store_field ( RString const & field_name , XNodeValue const * value , bool cmd_convert , RString const & pref , RString const & suf )
{
RString val ;
value - > GetValue ( val ) ;
store_field ( field_name , val , cmd_convert , pref , suf ) ;
}
void actor_template_t : : rename_field ( RString const & old_name , RString const & new_name )
{
field_cont_t : : iterator old_field = fields . find ( old_name ) ;
if ( old_field = = fields . end ( ) )
{
return ;
}
fields [ new_name ] = old_field - > second ;
fields . erase ( old_field ) ;
}
RString actor_template_t : : get_field ( RString const & field_name )
{
field_cont_t : : iterator field = fields . find ( field_name ) ;
if ( field = = fields . end ( ) )
{
return " " ;
}
return field - > second ;
}
void actor_template_t : : load_frames_from_file ( RString const & fname , RString const & rel_path )
{
IniFile ini ;
if ( ! ini . ReadFile ( fname ) )
{
LOG - > Trace ( " Failed to read sprite file %s: %s " , fname . c_str ( ) , ini . GetError ( ) . c_str ( ) ) ;
return ;
}
XNode const * sprite_node = ini . GetChild ( " Sprite " ) ;
2019-06-22 12:35:38 -07:00
if ( sprite_node ! = nullptr )
2015-05-01 07:50:34 -06:00
{
FOREACH_CONST_Attr ( sprite_node , attr )
{
// Frame and Delay fields have names of the form "Frame0000" where the
// "0000" part is the id of the frame.
RString field_type = attr - > first . Left ( 5 ) ;
if ( field_type = = " Frame " )
{
2021-02-15 20:36:51 +00:00
int id = StringToInt ( attr - > first . Right ( attr - > first . size ( ) - 5 ) ) ;
2015-05-01 07:50:34 -06:00
make_space_for_frame ( id ) ;
attr - > second - > GetValue ( frames [ id ] . frame ) ;
}
else if ( field_type = = " Delay " )
{
2021-02-15 20:36:51 +00:00
int id = StringToInt ( attr - > first . Right ( attr - > first . size ( ) - 5 ) ) ;
2015-05-01 07:50:34 -06:00
make_space_for_frame ( id ) ;
attr - > second - > GetValue ( frames [ id ] . delay ) ;
}
else if ( field_type = = " Textu " )
{
store_field ( " Texture " , attr - > second , false , rel_path , " " ) ;
}
else
{
// Unrecognized, ignore.
}
}
}
}
void actor_template_t : : load_model_from_file ( RString const & fname , RString const & rel_path )
{
IniFile ini ;
if ( ! ini . ReadFile ( fname ) )
{
LOG - > Trace ( " Failed to read model file %s: %s " , fname . c_str ( ) , ini . GetError ( ) . c_str ( ) ) ;
return ;
}
XNode const * model_node = ini . GetChild ( " Model " ) ;
2019-06-22 12:35:38 -07:00
if ( model_node ! = nullptr )
2015-05-01 07:50:34 -06:00
{
FOREACH_CONST_Attr ( model_node , attr )
{
store_field ( attr - > first , attr - > second , false , rel_path , " " ) ;
}
}
}
void actor_template_t : : load_node ( XNode const & node , RString const & dirname , condition_set_t & conditions )
{
type = node . GetName ( ) ;
bool type_set_by_automagic = false ;
2015-05-05 21:41:15 -06:00
# define set_type(auto_type) type_set_by_automagic= true; type= auto_type;
2015-05-01 07:50:34 -06:00
FOREACH_CONST_Attr ( & node , attr )
{
if ( attr - > first = = " Name " )
{
attr - > second - > GetValue ( name ) ;
}
else if ( attr - > first = = " Condition " )
{
RString cond_str ;
attr - > second - > GetValue ( cond_str ) ;
condition_set_t : : iterator cond = conditions . find ( cond_str ) ;
if ( cond = = conditions . end ( ) )
{
condition = unique_name ( " cond " ) ;
conditions [ cond_str ] = condition ;
}
else
{
condition = cond - > second ;
}
}
else if ( attr - > first = = " Type " | | attr - > first = = " Class " )
{
if ( ! type_set_by_automagic )
{
attr - > second - > GetValue ( type ) ;
}
}
else if ( attr - > first = = " __TEXT__ " )
{
// Ignore. This attribute seems to be put in by the xml parser, and
// not part of the actual xml code.
}
2015-05-05 21:41:15 -06:00
else if ( attr - > first = = " Text " )
{
set_type ( " BitmapText " ) ;
store_field ( attr - > first , attr - > second , true ) ;
}
2015-05-01 07:50:34 -06:00
else if ( attr - > first = = " File " )
{
RString relative_path ;
attr - > second - > GetValue ( relative_path ) ;
RString sfname = dirname + relative_path ;
if ( FILEMAN - > IsADirectory ( sfname ) )
{
2015-05-05 21:41:15 -06:00
set_type ( " LoadActor " ) ;
2015-05-01 07:50:34 -06:00
store_field ( " File " , attr - > second , false ) ;
}
else
{
2022-07-10 18:28:56 +03:00
std : : vector < RString > files_in_dir ;
2015-05-01 07:50:34 -06:00
FILEMAN - > GetDirListing ( sfname + " * " , files_in_dir , false , true ) ;
int handled_level = 0 ;
RString found_file = " " ;
2022-07-10 18:28:56 +03:00
for ( std : : vector < RString > : : iterator file = files_in_dir . begin ( ) ;
2015-05-01 07:50:34 -06:00
file ! = files_in_dir . end ( ) & & handled_level < 2 ; + + file )
{
RString extension = GetExtension ( * file ) ;
FileType file_type = ActorUtil : : GetFileType ( * file ) ;
RString this_relative =
add_extension_to_relative_path_from_found_file ( relative_path , * file ) ;
switch ( file_type )
{
case FT_Xml :
this_relative = SetExtension ( this_relative , " lua " ) ;
2022-11-08 06:59:56 -07:00
[[fallthrough]] ;
2015-05-01 07:50:34 -06:00
case FT_Lua :
2015-05-05 21:41:15 -06:00
set_type ( " LoadActor " ) ;
2015-05-01 07:50:34 -06:00
store_field ( " File " , this_relative , false ) ;
handled_level = 2 ;
break ;
case FT_Ini :
break ;
case FT_Bitmap :
case FT_Movie :
if ( handled_level < 2 )
{
2015-05-05 21:41:15 -06:00
set_type ( " Sprite " ) ;
2015-05-01 07:50:34 -06:00
store_field ( " File " , this_relative , false ) ;
handled_level = 1 ;
}
break ;
case FT_Sound :
2015-05-05 21:41:15 -06:00
set_type ( " ActorSound " ) ;
2015-05-01 07:50:34 -06:00
store_field ( " File " , this_relative , false ) ;
handled_level = 1 ;
break ;
case FT_Sprite :
2015-05-05 21:41:15 -06:00
set_type ( " Sprite " ) ;
2015-05-01 07:50:34 -06:00
load_frames_from_file ( dirname + this_relative , Dirname ( relative_path ) ) ;
handled_level = 2 ;
break ;
case FT_Model :
2015-05-05 21:41:15 -06:00
set_type ( " Model " ) ;
2015-05-01 07:50:34 -06:00
store_field ( " Meshes " , this_relative , false ) ;
store_field ( " Materials " , this_relative , false ) ;
store_field ( " Bones " , this_relative , false ) ;
handled_level = 2 ;
break ;
2016-03-24 18:30:29 -04:00
default :
break ;
2015-05-01 07:50:34 -06:00
}
if ( ! handled_level )
{
if ( extension = = " model " )
{
2015-05-05 21:41:15 -06:00
set_type ( " Model " ) ;
2015-05-01 07:50:34 -06:00
load_model_from_file ( dirname + this_relative , Dirname ( relative_path ) ) ;
handled_level = 2 ;
}
}
}
if ( ! handled_level )
{
if ( ! files_in_dir . empty ( ) )
{
RString this_relative =
add_extension_to_relative_path_from_found_file ( relative_path , files_in_dir [ 0 ] ) ;
store_field ( " File " , this_relative , false ) ;
}
else
{
store_field ( " File " , attr - > second , false ) ;
}
}
}
}
else
{
store_field ( attr - > first , attr - > second , true ) ;
}
}
if ( type = = " BitmapText " )
{
rename_field ( " Texture " , " Font " ) ;
rename_field ( " File " , " Font " ) ;
}
if ( type = = " Sprite " )
{
rename_field ( " File " , " Texture " ) ;
}
XNode const * xren = node . GetChild ( " children " ) ;
2019-06-22 12:35:38 -07:00
if ( xren ! = nullptr )
2015-05-01 07:50:34 -06:00
{
FOREACH_CONST_Child ( xren , child )
{
actor_template_t chill_plate ;
chill_plate . load_node ( * child , dirname , conditions ) ;
children . push_back ( chill_plate ) ;
}
}
if ( ! x . empty ( ) | | ! y . empty ( ) )
{
RString pos_init = " xy, " + x + " , " + y ;
field_cont_t : : iterator init = fields . find ( " InitCommand " ) ;
if ( init ! = fields . end ( ) )
{
pos_init = pos_init + " ;queuecommand,xtl_passed_initCommand " ;
fields [ " xtl_passed_initCommand " ] = init - > second ;
}
fields [ " InitCommand " ] = " cmd( " + pos_init + " ) " ;
}
}
void actor_template_t : : output_to_file ( RageFile * file , RString const & indent )
{
if ( ! condition . empty ( ) )
{
file - > Write ( indent + " optional_actor( " + condition + " _result, \n " ) ;
}
if ( type = = " LoadActor " )
{
file - > Write ( indent + " LoadActor(' " + get_field ( " File " ) + " ') .. { \n " ) ;
}
else
{
file - > Write ( indent + " Def. " + type + " { \n " ) ;
}
RString subindent = indent + " " ;
if ( name . empty ( ) )
{
name = unique_name ( " actor " ) ;
}
file - > Write ( subindent + " Name= \" " + name + " \" , \n " ) ;
if ( ! frames . empty ( ) )
{
file - > Write ( subindent + " Frames= { \n " ) ;
RString frameindent = subindent + " " ;
2022-07-10 18:28:56 +03:00
for ( std : : vector < frame_t > : : iterator frame = frames . begin ( ) ;
2015-05-01 07:50:34 -06:00
frame ! = frames . end ( ) ; + + frame )
{
2019-06-22 12:35:38 -07:00
file - > Write ( frameindent + " {Frame= " + std : : to_string ( frame - > frame ) +
" , Delay= " + std : : to_string ( frame - > delay ) + " }, \n " ) ;
2015-05-01 07:50:34 -06:00
}
file - > Write ( indent + " }, \n " ) ;
}
for ( field_cont_t : : iterator field = fields . begin ( ) ;
field ! = fields . end ( ) ; + + field )
{
2022-07-10 18:28:56 +03:00
std : : set < RString > : : iterator is_string = fields_that_are_strings . find ( field - > first ) ;
2015-05-01 07:50:34 -06:00
if ( is_string ! = fields_that_are_strings . end ( ) )
{
file - > Write ( subindent + field - > first + " = \" " + field - > second + " \" , \n " ) ;
}
else
{
file - > Write ( subindent + field - > first + " = " + field - > second + " , \n " ) ;
}
}
2022-07-10 18:28:56 +03:00
for ( std : : vector < actor_template_t > : : iterator child = children . begin ( ) ;
2015-05-01 07:50:34 -06:00
child ! = children . end ( ) ; + + child )
{
child - > output_to_file ( file , subindent ) ;
file - > Write ( " , \n " ) ;
}
file - > Write ( indent + " } " ) ;
if ( ! condition . empty ( ) )
{
file - > Write ( " ) " ) ;
}
}
void convert_xml_file ( RString const & fname , RString const & dirname )
{
if ( arg_converters . empty ( ) )
{
init_parser_helpers ( ) ;
}
LOG - > Trace ( " Beginning conversion of entry: %s " , fname . c_str ( ) ) ;
XNode xml ;
if ( ! XmlFileUtil : : LoadFromFileShowErrors ( xml , fname ) )
{
LOG - > Trace ( " Error when loading xml. " ) ;
return ;
}
actor_template_t plate ;
condition_set_t conditions ;
plate . load_node ( xml , dirname , conditions ) ;
RageFile * file = new RageFile ;
RString out_name = fname . Left ( fname . size ( ) - 4 ) + " .lua " ;
if ( ! file - > Open ( out_name , RageFile : : WRITE ) )
{
LOG - > Trace ( " Could not open %s: %s " , out_name . c_str ( ) , file - > GetError ( ) . c_str ( ) ) ;
return ;
}
LOG - > Trace ( " Saving conversion to: %s " , out_name . c_str ( ) ) ;
for ( condition_set_t : : iterator cond = conditions . begin ( ) ;
cond ! = conditions . end ( ) ; + + cond )
{
2015-05-08 23:55:38 -06:00
RString cond_text = cond - > first ;
convert_lua_chunk ( cond_text ) ;
file - > Write ( " local " + cond - > second + " _result= " + cond_text + " \n \n " ) ;
2015-05-01 07:50:34 -06:00
}
if ( ! conditions . empty ( ) )
{
file - > Write ( " local function optional_actor(cond, actor) \n "
" if cond then return actor end \n "
" return Def.Actor{} \n "
" end \n \n " ) ;
}
file - > Write ( " return " ) ;
plate . output_to_file ( file , " " ) ;
file - > Write ( " \n " ) ;
file - > Close ( ) ;
delete file ;
}
int LuaFunc_convert_xml_bgs ( lua_State * L ) ;
int LuaFunc_convert_xml_bgs ( lua_State * L )
{
RString dir = SArg ( 1 ) ;
2022-07-10 18:28:56 +03:00
std : : vector < RString > xml_list ;
2015-05-01 07:50:34 -06:00
convert_xmls_in_dir ( dir + " / " ) ;
return 0 ;
}
LUAFUNC_REGISTER_COMMON ( convert_xml_bgs ) ;
/*
* (c) 2014 Eric Reese
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/