2003-02-16 04:01:45 +00:00
|
|
|
#include "global.h"
|
2002-09-09 00:22:02 +00:00
|
|
|
#include "NotesWriterDWI.h"
|
|
|
|
|
#include "NoteTypes.h"
|
|
|
|
|
#include "NoteData.h"
|
|
|
|
|
#include "RageUtil.h"
|
|
|
|
|
#include "RageLog.h"
|
2006-09-16 03:44:47 +00:00
|
|
|
#include "RageFileManager.h"
|
2003-07-22 07:47:27 +00:00
|
|
|
#include "RageFile.h"
|
2003-08-07 06:36:34 +00:00
|
|
|
#include "NoteDataUtil.h"
|
2003-12-04 22:20:41 +00:00
|
|
|
#include "RageFile.h"
|
2005-07-03 02:51:29 +00:00
|
|
|
#include "song.h"
|
|
|
|
|
#include "Steps.h"
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2006-11-04 23:36:11 +00:00
|
|
|
static RString OptimizeDWIString( RString holds, RString taps );
|
|
|
|
|
|
2003-07-07 01:12:30 +00:00
|
|
|
/* Output is an angle bracket expression without angle brackets, eg. "468". */
|
2006-11-04 23:36:11 +00:00
|
|
|
static RString NotesToDWIString( const TapNote tnCols[6] )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2003-07-07 01:12:30 +00:00
|
|
|
const char dirs[] = { '4', 'C', '2', '8', 'D', '6' };
|
2006-01-22 01:00:06 +00:00
|
|
|
RString taps, holds, ret;
|
2003-07-07 01:12:30 +00:00
|
|
|
for( int col = 0; col < 6; ++col )
|
|
|
|
|
{
|
2004-10-23 23:41:49 +00:00
|
|
|
switch( tnCols[col].type )
|
2003-11-12 08:13:02 +00:00
|
|
|
{
|
2004-09-12 05:56:24 +00:00
|
|
|
case TapNote::empty:
|
|
|
|
|
case TapNote::mine:
|
2003-07-07 01:12:30 +00:00
|
|
|
continue;
|
2003-11-12 08:13:02 +00:00
|
|
|
}
|
2003-07-07 01:12:30 +00:00
|
|
|
|
2004-10-23 23:41:49 +00:00
|
|
|
if( tnCols[col].type == TapNote::hold_head )
|
2003-07-07 01:12:30 +00:00
|
|
|
holds += dirs[col];
|
|
|
|
|
else
|
|
|
|
|
taps += dirs[col];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( holds.size() + taps.size() == 0 )
|
|
|
|
|
return "0";
|
|
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
// RString combine = taps;
|
2003-07-07 01:12:30 +00:00
|
|
|
// for( unsigned i = 0; i < holds.size(); ++i )
|
|
|
|
|
// combine += ssprintf("%c!%c", holds[i], holds[i]);
|
|
|
|
|
|
|
|
|
|
// if( holds.size() + taps.size() > 1 )
|
|
|
|
|
// combine = ssprintf("<%s>", combine.c_str() );
|
|
|
|
|
|
|
|
|
|
// return combine;
|
|
|
|
|
|
|
|
|
|
/* More than one. */
|
|
|
|
|
return OptimizeDWIString( holds, taps );
|
|
|
|
|
/* struct DWICharLookup {
|
2002-09-09 00:22:02 +00:00
|
|
|
char c;
|
|
|
|
|
bool bCol[6];
|
|
|
|
|
} const lookup[] = {
|
2002-11-16 09:12:55 +00:00
|
|
|
{ '0', { 0, 0, 0, 0, 0, 0 } },
|
|
|
|
|
{ '1', { 1, 0, 1, 0, 0, 0 } },
|
|
|
|
|
{ '2', { 0, 0, 1, 0, 0, 0 } },
|
|
|
|
|
{ '3', { 0, 0, 1, 0, 0, 1 } },
|
|
|
|
|
{ '4', { 1, 0, 0, 0, 0, 0 } },
|
|
|
|
|
{ '6', { 0, 0, 0, 0, 0, 1 } },
|
|
|
|
|
{ '7', { 1, 0, 0, 1, 0, 0 } },
|
|
|
|
|
{ '8', { 0, 0, 0, 1, 0, 0 } },
|
|
|
|
|
{ '9', { 0, 0, 0, 1, 0, 1 } },
|
|
|
|
|
{ 'A', { 0, 0, 1, 1, 0, 0 } },
|
|
|
|
|
{ 'B', { 1, 0, 0, 0, 0, 1 } },
|
|
|
|
|
{ 'C', { 0, 1, 0, 0, 0, 0 } },
|
|
|
|
|
{ 'D', { 0, 0, 0, 0, 1, 0 } },
|
|
|
|
|
{ 'E', { 1, 1, 0, 0, 0, 0 } },
|
|
|
|
|
{ 'F', { 0, 1, 1, 0, 0, 0 } },
|
|
|
|
|
{ 'G', { 0, 1, 0, 1, 0, 0 } },
|
|
|
|
|
{ 'H', { 0, 1, 0, 0, 0, 1 } },
|
|
|
|
|
{ 'I', { 1, 0, 0, 0, 1, 0 } },
|
|
|
|
|
{ 'J', { 0, 0, 1, 0, 1, 0 } },
|
|
|
|
|
{ 'K', { 0, 0, 0, 1, 1, 0 } },
|
|
|
|
|
{ 'L', { 0, 0, 0, 0, 1, 1 } },
|
|
|
|
|
{ 'M', { 0, 1, 0, 0, 1, 0 } },
|
2002-09-09 00:22:02 +00:00
|
|
|
};
|
|
|
|
|
const int iNumLookups = sizeof(lookup) / sizeof(*lookup);
|
|
|
|
|
|
|
|
|
|
for( int i=0; i<iNumLookups; i++ )
|
|
|
|
|
{
|
|
|
|
|
const DWICharLookup& l = lookup[i];
|
|
|
|
|
if( l.bCol[0]==bCol1 && l.bCol[1]==bCol2 && l.bCol[2]==bCol3 && l.bCol[3]==bCol4 && l.bCol[4]==bCol5 && l.bCol[5]==bCol6 )
|
|
|
|
|
return l.c;
|
|
|
|
|
}
|
2002-10-24 01:51:01 +00:00
|
|
|
LOG->Warn( "Failed to find the DWI character for the row %d %d %d %d %d %d", bCol1, bCol2, bCol3, bCol4, bCol5, bCol6 );
|
2003-07-07 01:12:30 +00:00
|
|
|
return '0';*/
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-04 23:36:11 +00:00
|
|
|
static RString NotesToDWIString( TapNote tnCol1, TapNote tnCol2, TapNote tnCol3, TapNote tnCol4, TapNote tnCol5, TapNote tnCol6 )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2004-10-23 23:41:49 +00:00
|
|
|
TapNote tnCols[6];
|
|
|
|
|
tnCols[0] = tnCol1;
|
|
|
|
|
tnCols[1] = tnCol2;
|
|
|
|
|
tnCols[2] = tnCol3;
|
|
|
|
|
tnCols[3] = tnCol4;
|
|
|
|
|
tnCols[4] = tnCol5;
|
|
|
|
|
tnCols[5] = tnCol6;
|
|
|
|
|
return NotesToDWIString( tnCols );
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-04 23:36:11 +00:00
|
|
|
static RString NotesToDWIString( TapNote tnCol1, TapNote tnCol2, TapNote tnCol3, TapNote tnCol4 )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2004-10-23 23:41:49 +00:00
|
|
|
return NotesToDWIString( tnCol1, TAP_EMPTY, tnCol2, tnCol3, TAP_EMPTY, tnCol4 );
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-04 23:36:11 +00:00
|
|
|
static char OptimizeDWIPair( char c1, char c2 )
|
2003-07-07 01:12:30 +00:00
|
|
|
{
|
|
|
|
|
typedef pair<char,char> cpair;
|
|
|
|
|
static map< cpair, char > joins;
|
|
|
|
|
static bool Initialized = false;
|
|
|
|
|
if(!Initialized)
|
|
|
|
|
{
|
|
|
|
|
Initialized = true;
|
|
|
|
|
/* The first character in the pair is always the lowest. */
|
|
|
|
|
joins[ cpair('2', '4') ] = '1';
|
|
|
|
|
joins[ cpair('2', '6') ] = '3';
|
|
|
|
|
joins[ cpair('4', '8') ] = '7';
|
|
|
|
|
joins[ cpair('6', '8') ] = '9';
|
|
|
|
|
joins[ cpair('2', '8') ] = 'A';
|
|
|
|
|
joins[ cpair('4', '6') ] = 'B';
|
|
|
|
|
joins[ cpair('C', 'D') ] = 'M';
|
|
|
|
|
joins[ cpair('4', 'C') ] = 'E';
|
|
|
|
|
joins[ cpair('2', 'C') ] = 'F';
|
|
|
|
|
joins[ cpair('8', 'C') ] = 'G';
|
|
|
|
|
joins[ cpair('6', 'C') ] = 'H';
|
|
|
|
|
joins[ cpair('4', 'D') ] = 'I';
|
|
|
|
|
joins[ cpair('2', 'D') ] = 'J';
|
|
|
|
|
joins[ cpair('8', 'D') ] = 'K';
|
|
|
|
|
joins[ cpair('6', 'D') ] = 'L';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( c1 > c2 )
|
|
|
|
|
swap( c1, c2 );
|
|
|
|
|
|
|
|
|
|
map< cpair, char >::const_iterator it = joins.find( cpair(c1, c2) );
|
|
|
|
|
ASSERT( it != joins.end() );
|
|
|
|
|
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-04 23:36:11 +00:00
|
|
|
RString OptimizeDWIString( RString holds, RString taps )
|
2003-07-07 01:12:30 +00:00
|
|
|
{
|
|
|
|
|
/* First, sort the holds and taps in ASCII order. This puts 2468 first.
|
|
|
|
|
* This way 1379 combinations will always be found first, so we'll always
|
|
|
|
|
* do eg. 1D, not 2I. */
|
|
|
|
|
sort( holds.begin(), holds.end() );
|
|
|
|
|
sort( taps.begin(), taps.end() );
|
|
|
|
|
|
|
|
|
|
/* Combine characters as much as possible. */
|
2006-01-22 01:00:06 +00:00
|
|
|
RString comb_taps, comb_holds;
|
2003-07-07 01:12:30 +00:00
|
|
|
|
|
|
|
|
/* 24 -> 1 */
|
|
|
|
|
while( taps.size() > 1 )
|
|
|
|
|
{
|
|
|
|
|
comb_taps += OptimizeDWIPair( taps[0], taps[1] );
|
|
|
|
|
taps.erase(0, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2!24!4 -> 1!1 */
|
|
|
|
|
while( holds.size() > 1 )
|
|
|
|
|
{
|
|
|
|
|
const char to = OptimizeDWIPair( holds[0], holds[1] );
|
|
|
|
|
holds.erase(0, 2);
|
|
|
|
|
comb_holds += ssprintf( "%c!%c", to, to );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT( taps.size() <= 1 );
|
|
|
|
|
ASSERT( holds.size() <= 1 );
|
|
|
|
|
|
|
|
|
|
/* 24!4 -> 1!4 */
|
|
|
|
|
while( holds.size() == 1 && taps.size() == 1 )
|
|
|
|
|
{
|
|
|
|
|
const char to = OptimizeDWIPair( taps[0], holds[0] );
|
|
|
|
|
comb_holds += ssprintf( "%c!%c", to, holds[0] );
|
|
|
|
|
taps.erase(0, 1);
|
|
|
|
|
holds.erase(0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now we have at most one single tap and one hold remaining, and any
|
|
|
|
|
* number of taps and holds in comb_taps and comb_holds. */
|
2006-01-22 01:00:06 +00:00
|
|
|
RString ret;
|
2003-07-07 01:12:30 +00:00
|
|
|
ret += taps;
|
|
|
|
|
ret += comb_taps;
|
|
|
|
|
if( holds.size() == 1 )
|
|
|
|
|
ret += ssprintf( "%c!%c", holds[0], holds[0] );
|
|
|
|
|
ret += comb_holds;
|
|
|
|
|
|
|
|
|
|
if( ret.size() == 1 || (ret.size() == 3 && ret[1] == '!') )
|
|
|
|
|
return ret;
|
|
|
|
|
else
|
|
|
|
|
return ssprintf( "<%s>", ret.c_str() );
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-04 23:36:11 +00:00
|
|
|
static void WriteDWINotesField( RageFile &f, const Steps &out, int start )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
|
|
|
|
NoteData notedata;
|
2004-10-23 17:43:49 +00:00
|
|
|
out.GetNoteData( notedata );
|
2005-02-12 08:18:31 +00:00
|
|
|
NoteDataUtil::InsertHoldTails( notedata );
|
2002-09-09 00:22:02 +00:00
|
|
|
|
|
|
|
|
const int iLastMeasure = int( notedata.GetLastBeat()/BEATS_PER_MEASURE );
|
2002-09-09 02:23:03 +00:00
|
|
|
for( int m=0; m<=iLastMeasure; m++ ) // foreach measure
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2002-12-13 22:07:59 +00:00
|
|
|
NoteType nt = NoteDataUtil::GetSmallestNoteTypeForMeasure( notedata, m );
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2003-12-04 20:42:42 +00:00
|
|
|
double fCurrentIncrementer = 0;
|
2002-09-09 02:23:03 +00:00
|
|
|
switch( nt )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2002-09-09 02:23:03 +00:00
|
|
|
case NOTE_TYPE_4TH:
|
|
|
|
|
case NOTE_TYPE_8TH:
|
2003-07-07 00:16:52 +00:00
|
|
|
fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
|
2002-09-09 02:23:03 +00:00
|
|
|
break;
|
|
|
|
|
case NOTE_TYPE_12TH:
|
2002-09-11 04:49:07 +00:00
|
|
|
case NOTE_TYPE_24TH:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "[" );
|
2002-09-09 02:23:03 +00:00
|
|
|
fCurrentIncrementer = 1.0/24 * BEATS_PER_MEASURE;
|
|
|
|
|
break;
|
|
|
|
|
case NOTE_TYPE_16TH:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "(" );
|
2002-09-09 02:23:03 +00:00
|
|
|
fCurrentIncrementer = 1.0/16 * BEATS_PER_MEASURE;
|
|
|
|
|
break;
|
2002-09-11 04:49:07 +00:00
|
|
|
case NOTE_TYPE_32ND:
|
2003-11-04 08:44:26 +00:00
|
|
|
case NOTE_TYPE_64TH:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "{" );
|
2002-09-11 04:49:07 +00:00
|
|
|
fCurrentIncrementer = 1.0/64 * BEATS_PER_MEASURE;
|
2002-09-09 02:23:03 +00:00
|
|
|
break;
|
2003-11-04 08:44:26 +00:00
|
|
|
case NOTE_TYPE_48TH:
|
2003-11-13 07:40:49 +00:00
|
|
|
case NOTE_TYPE_192ND:
|
2006-10-07 04:39:48 +00:00
|
|
|
case NoteType_Invalid:
|
2003-11-04 08:44:26 +00:00
|
|
|
// since, for whatever reason, the only way to do
|
|
|
|
|
// 48ths is through a block of 192nds...
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "`" );
|
2003-07-06 23:37:16 +00:00
|
|
|
fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
|
2003-11-04 08:44:26 +00:00
|
|
|
break;
|
2003-12-04 07:47:23 +00:00
|
|
|
default:
|
2004-06-16 00:38:31 +00:00
|
|
|
ASSERT_M(0, ssprintf("nt = %d",nt) );
|
2003-12-04 07:47:23 +00:00
|
|
|
break;
|
2002-09-09 02:23:03 +00:00
|
|
|
}
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2002-09-09 02:23:03 +00:00
|
|
|
double fFirstBeatInMeasure = m * BEATS_PER_MEASURE;
|
|
|
|
|
double fLastBeatInMeasure = (m+1) * BEATS_PER_MEASURE;
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2002-09-11 04:49:07 +00:00
|
|
|
for( double b=fFirstBeatInMeasure; b<=fLastBeatInMeasure-1/64.0f; b+=fCurrentIncrementer ) // need the -0.0001 to account for rounding errors
|
2002-09-09 02:23:03 +00:00
|
|
|
{
|
|
|
|
|
int row = BeatToNoteRow( (float)b );
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
RString str;
|
2003-08-07 06:36:34 +00:00
|
|
|
switch( out.m_StepsType )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2003-08-07 06:16:17 +00:00
|
|
|
case STEPS_TYPE_DANCE_SINGLE:
|
|
|
|
|
case STEPS_TYPE_DANCE_COUPLE:
|
|
|
|
|
case STEPS_TYPE_DANCE_DOUBLE:
|
2003-07-06 23:37:16 +00:00
|
|
|
str = NotesToDWIString(
|
2002-10-25 04:37:00 +00:00
|
|
|
notedata.GetTapNote(start+0, row),
|
|
|
|
|
notedata.GetTapNote(start+1, row),
|
|
|
|
|
notedata.GetTapNote(start+2, row),
|
2003-07-06 23:37:16 +00:00
|
|
|
notedata.GetTapNote(start+3, row) );
|
2002-09-11 04:49:07 +00:00
|
|
|
|
|
|
|
|
// Blank out the notes so we don't write them again if the incrementer is small
|
2002-10-25 04:37:00 +00:00
|
|
|
notedata.SetTapNote(start+0, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+1, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+2, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+3, row, TAP_EMPTY);
|
2002-09-09 00:22:02 +00:00
|
|
|
break;
|
2003-08-07 06:16:17 +00:00
|
|
|
case STEPS_TYPE_DANCE_SOLO:
|
2003-07-06 23:37:16 +00:00
|
|
|
str = NotesToDWIString(
|
2002-10-25 04:37:00 +00:00
|
|
|
notedata.GetTapNote(0, row),
|
|
|
|
|
notedata.GetTapNote(1, row),
|
|
|
|
|
notedata.GetTapNote(2, row),
|
|
|
|
|
notedata.GetTapNote(3, row),
|
|
|
|
|
notedata.GetTapNote(4, row),
|
2003-07-06 23:37:16 +00:00
|
|
|
notedata.GetTapNote(5, row) );
|
2002-09-11 04:49:07 +00:00
|
|
|
|
|
|
|
|
// Blank out the notes so we don't write them again if the incrementer is small
|
2002-10-25 04:37:00 +00:00
|
|
|
notedata.SetTapNote(start+0, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+1, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+2, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+3, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+4, row, TAP_EMPTY);
|
|
|
|
|
notedata.SetTapNote(start+5, row, TAP_EMPTY);
|
2002-09-09 00:22:02 +00:00
|
|
|
break;
|
2002-09-11 04:49:07 +00:00
|
|
|
default:
|
|
|
|
|
ASSERT(0); // not a type supported by DWI. We shouldn't have called in here if that's the case
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( str );
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
2002-09-09 02:23:03 +00:00
|
|
|
switch( nt )
|
|
|
|
|
{
|
|
|
|
|
case NOTE_TYPE_4TH:
|
|
|
|
|
case NOTE_TYPE_8TH:
|
|
|
|
|
break;
|
|
|
|
|
case NOTE_TYPE_12TH:
|
2002-09-11 04:49:07 +00:00
|
|
|
case NOTE_TYPE_24TH:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "]" );
|
2002-09-09 02:23:03 +00:00
|
|
|
break;
|
|
|
|
|
case NOTE_TYPE_16TH:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( ")" );
|
2002-09-09 02:23:03 +00:00
|
|
|
break;
|
2003-07-06 23:37:16 +00:00
|
|
|
case NOTE_TYPE_32ND:
|
2003-11-04 08:44:26 +00:00
|
|
|
case NOTE_TYPE_64TH:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "}" );
|
2003-07-06 23:37:16 +00:00
|
|
|
break;
|
2003-11-04 08:44:26 +00:00
|
|
|
case NOTE_TYPE_48TH:
|
2003-11-13 07:40:49 +00:00
|
|
|
case NOTE_TYPE_192ND:
|
2006-10-07 04:39:48 +00:00
|
|
|
case NoteType_Invalid:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "'" );
|
2002-09-09 02:23:03 +00:00
|
|
|
break;
|
2003-11-04 08:44:26 +00:00
|
|
|
default:
|
|
|
|
|
ASSERT(0);
|
|
|
|
|
// fall though
|
2002-09-09 02:23:03 +00:00
|
|
|
}
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( "" );
|
2002-09-09 02:23:03 +00:00
|
|
|
}
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
2006-11-04 23:36:11 +00:00
|
|
|
static bool WriteDWINotesTag( RageFile &f, const Steps &out )
|
2002-09-09 02:23:03 +00:00
|
|
|
{
|
2004-05-27 06:39:20 +00:00
|
|
|
if( out.GetDifficulty() == DIFFICULTY_EDIT )
|
|
|
|
|
return false; // not supported by DWI
|
|
|
|
|
|
2003-11-01 22:09:56 +00:00
|
|
|
/* Flush dir cache when writing steps, so the old size isn't cached. */
|
2006-09-16 03:44:47 +00:00
|
|
|
FILEMAN->FlushDirCache( Dirname(f.GetRealPath()) );
|
2003-11-01 22:09:56 +00:00
|
|
|
|
2003-08-03 00:13:55 +00:00
|
|
|
LOG->Trace( "Steps::WriteDWINotesTag" );
|
2002-09-09 02:23:03 +00:00
|
|
|
|
2003-08-07 06:36:34 +00:00
|
|
|
switch( out.m_StepsType )
|
2002-09-09 02:23:03 +00:00
|
|
|
{
|
2003-12-04 22:20:41 +00:00
|
|
|
case STEPS_TYPE_DANCE_SINGLE: f.Write( "#SINGLE:" ); break;
|
|
|
|
|
case STEPS_TYPE_DANCE_COUPLE: f.Write( "#COUPLE:" ); break;
|
|
|
|
|
case STEPS_TYPE_DANCE_DOUBLE: f.Write( "#DOUBLE:" ); break;
|
|
|
|
|
case STEPS_TYPE_DANCE_SOLO: f.Write( "#SOLO:" ); break;
|
2002-09-09 02:23:03 +00:00
|
|
|
default: return false; // not a type supported by DWI
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-21 22:23:01 +00:00
|
|
|
switch( out.GetDifficulty() )
|
2002-09-09 02:23:03 +00:00
|
|
|
{
|
2003-12-04 22:20:41 +00:00
|
|
|
case DIFFICULTY_BEGINNER: f.Write( "BEGINNER:" ); break;
|
|
|
|
|
case DIFFICULTY_EASY: f.Write( "BASIC:" ); break;
|
|
|
|
|
case DIFFICULTY_MEDIUM: f.Write( "ANOTHER:" ); break;
|
|
|
|
|
case DIFFICULTY_HARD: f.Write( "MANIAC:" ); break;
|
|
|
|
|
case DIFFICULTY_CHALLENGE: f.Write( "SMANIAC:" ); break;
|
2003-01-21 22:23:01 +00:00
|
|
|
default: ASSERT(0); return false;
|
2002-09-09 02:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ssprintf("%d:", out.GetMeter()) );
|
2002-09-09 02:23:03 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2006-01-22 01:00:06 +00:00
|
|
|
bool NotesWriterDWI::Write( RString sPath, const Song &out )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2003-12-04 22:20:41 +00:00
|
|
|
RageFile f;
|
|
|
|
|
if( !f.Open( sPath, RageFile::WRITE ) )
|
2006-09-03 05:16:09 +00:00
|
|
|
{
|
2006-09-24 03:57:26 +00:00
|
|
|
LOG->UserLog( "Song file", sPath, "couldn't be opened for writing: %s", f.GetError().c_str() );
|
2006-09-03 05:16:09 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2003-02-11 23:52:18 +00:00
|
|
|
/* Write transliterations, if we have them, since DWI doesn't support UTF-8. */
|
2006-12-01 22:15:26 +00:00
|
|
|
f.PutLine( ssprintf("#TITLE:%s;", DwiEscape(out.GetTranslitFullTitle()).c_str()) );
|
|
|
|
|
f.PutLine( ssprintf("#ARTIST:%s;", DwiEscape(out.GetTranslitArtist()).c_str()) );
|
2005-01-23 21:55:01 +00:00
|
|
|
ASSERT( out.m_Timing.m_BPMSegments[0].m_iStartIndex == 0 );
|
2006-12-01 22:15:26 +00:00
|
|
|
f.PutLine( ssprintf("#FILE:%s;", DwiEscape(out.m_sMusicFile).c_str()) );
|
2005-01-23 21:55:01 +00:00
|
|
|
f.PutLine( ssprintf("#BPM:%.3f;", out.m_Timing.m_BPMSegments[0].GetBPM()) );
|
2007-01-03 05:05:28 +00:00
|
|
|
f.PutLine( ssprintf("#GAP:%ld;", -lrintf( out.m_Timing.m_fBeat0OffsetInSeconds*1000 )) );
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ssprintf("#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds) );
|
|
|
|
|
f.PutLine( ssprintf("#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds) );
|
2003-02-28 08:55:56 +00:00
|
|
|
if( out.m_sCDTitleFile.size() )
|
2006-12-01 22:15:26 +00:00
|
|
|
f.PutLine( ssprintf("#CDTITLE:%s;", DwiEscape(out.m_sCDTitleFile).c_str()) );
|
2003-05-23 01:14:43 +00:00
|
|
|
switch( out.m_DisplayBPMType )
|
|
|
|
|
{
|
|
|
|
|
case Song::DISPLAY_ACTUAL:
|
|
|
|
|
// write nothing
|
|
|
|
|
break;
|
|
|
|
|
case Song::DISPLAY_SPECIFIED:
|
2003-06-16 17:28:58 +00:00
|
|
|
if( out.m_fSpecifiedBPMMin == out.m_fSpecifiedBPMMax )
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ssprintf("#DISPLAYBPM:%i;\n", (int) out.m_fSpecifiedBPMMin) );
|
2003-05-23 01:14:43 +00:00
|
|
|
else
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ssprintf("#DISPLAYBPM:%i..%i;\n", (int) out.m_fSpecifiedBPMMin, (int) out.m_fSpecifiedBPMMax) );
|
2003-05-23 01:14:43 +00:00
|
|
|
break;
|
|
|
|
|
case Song::DISPLAY_RANDOM:
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( "#DISPLAYBPM:*" );
|
2003-05-23 01:14:43 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2002-09-09 00:22:02 +00:00
|
|
|
|
2003-12-18 04:48:26 +00:00
|
|
|
if( !out.m_Timing.m_StopSegments.empty() )
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "#FREEZE:" );
|
2002-09-09 02:33:57 +00:00
|
|
|
|
2003-12-18 04:48:26 +00:00
|
|
|
for( unsigned i=0; i<out.m_Timing.m_StopSegments.size(); i++ )
|
2002-09-09 02:33:57 +00:00
|
|
|
{
|
2003-12-18 04:48:26 +00:00
|
|
|
const StopSegment &fs = out.m_Timing.m_StopSegments[i];
|
2005-01-23 21:55:01 +00:00
|
|
|
f.Write( ssprintf("%.3f=%.3f", fs.m_iStartRow * 4.0f / ROWS_PER_BEAT,
|
2003-12-04 22:20:41 +00:00
|
|
|
roundf(fs.m_fStopSeconds*1000)) );
|
2003-12-18 04:48:26 +00:00
|
|
|
if( i != out.m_Timing.m_StopSegments.size()-1 )
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "," );
|
2002-09-09 02:33:57 +00:00
|
|
|
}
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ";" );
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
|
|
|
|
|
2003-12-18 04:48:26 +00:00
|
|
|
if( out.m_Timing.m_BPMSegments.size() > 1)
|
2002-09-09 00:22:02 +00:00
|
|
|
{
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "#CHANGEBPM:" );
|
2003-12-18 04:48:26 +00:00
|
|
|
for( unsigned i=1; i<out.m_Timing.m_BPMSegments.size(); i++ )
|
2002-09-09 02:33:57 +00:00
|
|
|
{
|
2003-12-18 04:48:26 +00:00
|
|
|
const BPMSegment &bs = out.m_Timing.m_BPMSegments[i];
|
2005-01-23 21:55:01 +00:00
|
|
|
f.Write( ssprintf("%.3f=%.3f", bs.m_iStartIndex * 4.0f / ROWS_PER_BEAT, bs.GetBPM() ) );
|
2003-12-18 04:48:26 +00:00
|
|
|
if( i != out.m_Timing.m_BPMSegments.size()-1 )
|
2003-12-04 22:20:41 +00:00
|
|
|
f.Write( "," );
|
2002-09-09 02:33:57 +00:00
|
|
|
}
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ";" );
|
2002-09-09 00:22:02 +00:00
|
|
|
}
|
2002-09-09 02:33:57 +00:00
|
|
|
|
2004-06-04 23:36:50 +00:00
|
|
|
const vector<Steps*>& vpSteps = out.GetAllSteps();
|
|
|
|
|
for( unsigned i=0; i<vpSteps.size(); i++ )
|
2002-09-09 02:23:03 +00:00
|
|
|
{
|
2004-06-04 23:36:50 +00:00
|
|
|
const Steps* pSteps = vpSteps[i];
|
|
|
|
|
if( pSteps->IsAutogen() )
|
2002-10-08 08:22:04 +00:00
|
|
|
continue; // don't save autogen notes
|
|
|
|
|
|
2004-06-04 23:36:50 +00:00
|
|
|
if( !WriteDWINotesTag( f, *pSteps ))
|
2002-09-09 02:23:03 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-06-04 23:36:50 +00:00
|
|
|
WriteDWINotesField( f, *pSteps, 0 );
|
|
|
|
|
if( pSteps->m_StepsType==STEPS_TYPE_DANCE_DOUBLE ||
|
|
|
|
|
pSteps->m_StepsType==STEPS_TYPE_DANCE_COUPLE )
|
2002-09-09 02:23:03 +00:00
|
|
|
{
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ":" );
|
2004-06-04 23:36:50 +00:00
|
|
|
WriteDWINotesField( f, *pSteps, 4 );
|
2002-09-09 02:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
2003-12-04 22:20:41 +00:00
|
|
|
f.PutLine( ";" );
|
2002-09-09 02:23:03 +00:00
|
|
|
}
|
|
|
|
|
|
2002-09-09 00:22:02 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2004-05-31 21:55:14 +00:00
|
|
|
|
2003-07-07 01:12:30 +00:00
|
|
|
/*
|
2006-12-01 22:15:26 +00:00
|
|
|
* (c) 2001-2006 Chris Danford, Glenn Maynard
|
2004-05-31 21:55:14 +00:00
|
|
|
* 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.
|
2003-07-07 01:12:30 +00:00
|
|
|
*/
|