Exemple #1
0
void SSCLoader::ProcessStops( TimingData &out, const RString sParam )
{
	vector<RString> arrayStopExpressions;
	split( sParam, ",", arrayStopExpressions );
	
	for( unsigned b=0; b<arrayStopExpressions.size(); b++ )
	{
		vector<RString> arrayStopValues;
		split( arrayStopExpressions[b], "=", arrayStopValues );
		if( arrayStopValues.size() != 2 )
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an invalid #STOPS value \"%s\" (must have exactly one '='), ignored.",
				     arrayStopExpressions[b].c_str() );
			continue;
		}
		
		const float fBeat = StringToFloat( arrayStopValues[0] );
		const float fNewStop = StringToFloat( arrayStopValues[1] );
		if( fBeat >= 0 && fNewStop > 0 )
			out.AddSegment( StopSegment(BeatToNoteRow(fBeat), fNewStop) );
		else
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an invalid Stop at beat %f, length %f.",
				     fBeat, fNewStop );
		}
	}
}
Exemple #2
0
void SSCLoader::ProcessScrolls( TimingData &out, const RString sParam )
{
	vector<RString> vs1;
	split( sParam, ",", vs1 );
	
	FOREACH_CONST( RString, vs1, s1 )
	{
		vector<RString> vs2;
		split( *s1, "=", vs2 );
		
		if( vs2.size() < 2 )
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an scroll change with %i values.",
				     static_cast<int>(vs2.size()) );
			continue;
		}

		const float fBeat = StringToFloat( vs2[0] );
		const float fRatio = StringToFloat( vs2[1] );

		if( fBeat < 0 )
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an scroll change with beat %f.",
				     fBeat );
			continue;
		}

		out.AddSegment( ScrollSegment(BeatToNoteRow(fBeat), fRatio) );
	}
Exemple #3
0
Vector2 ParseVector2(const std::string& line)
{
	std::vector<std::string> tokens = Tokenize(line, " \t");
	assert(tokens.size() > 3);
	const float x = StringToFloat(tokens[1]);
	const float y = StringToFloat(tokens[2]);
	return Vector2(x, y);
}
Exemple #4
0
void CTab3::OnBnClickedRotationApply()
{
	// TODO: Add your control notification handler code here
	if ( m_shape == NULL )
	{
		return;
	}

	// Get strings from edits
	char strX[256];
	m_rotX.GetWindowText ( strX, 256 );

	char strY[256];
	m_rotY.GetWindowText ( strY, 256 );

	char strZ[256];
	m_rotZ.GetWindowText ( strZ, 256 );

	// COnvert to float
	float answerX, answerY, answerZ;

	// If successfull
	if ( StringToFloat ( strX, &answerX ) &&
		 StringToFloat ( strY, &answerY ) && 
		 StringToFloat ( strZ, &answerZ ) )
	{
		// Create a rotation matrix
		hduMatrix m;

		// Apply the rotation matrix
		m.multRight ( hduMatrix::createRotation ( 0, 1, 0, answerY/RAD_2_DEG ) );
		m.multRight ( hduMatrix::createRotation ( 0, 0, 1, answerZ/RAD_2_DEG ) );
		m.multRight ( hduMatrix::createRotation ( 1, 0, 0, answerX/RAD_2_DEG ) );

		// Convert to 16 element array
		float rotation[16]=
		{
			m[0][0], m[1][0], m[2][0], m[3][0],
			m[0][1], m[1][1], m[2][1], m[3][1],
			m[0][2], m[1][2], m[2][2], m[3][2],
			m[0][3], m[1][3], m[2][3], m[3][3]
		};

		// Save document for undo
		if ( m_doc != NULL )
		{
			m_doc->saveState ( );
		}

		// Set rotation
		m_shape->setRotation ( rotation );
	}
	else
	{
		MessageBox ( "Please enter a number for the x, y and z fields." );
	}
}
Exemple #5
0
Vector2 StringToVector2( const String& s )
{
	StringList split = SplitString(s);
	Vector2 retVal;

	if( split.size() > 0 )
		retVal.X = StringToFloat(split[0]);

	if( split.size() > 1 )
		retVal.Y = StringToFloat(split[1]);

	return retVal;
}
Exemple #6
0
float SMLoader::RowToBeat( RString line, const int rowsPerBeat )
{
	RString backup = line;
	Trim(line, "r");
	Trim(line, "R");
	if( backup != line )
	{
		return StringToFloat( line ) / rowsPerBeat;
	}
	else
	{
		return StringToFloat( line );
	}
}
Exemple #7
0
void SMSetDisplayBPM(SMSongTagInfo& info)
{
	// #DISPLAYBPM:[xxx][xxx:xxx]|[*];
	if((*info.params)[1] == "*")
	{ info.song->m_DisplayBPMType = DISPLAY_BPM_RANDOM; }
	else
	{
		info.song->m_DisplayBPMType = DISPLAY_BPM_SPECIFIED;
		info.song->m_fSpecifiedBPMMin = StringToFloat((*info.params)[1]);
		if((*info.params)[2].empty())
		{ info.song->m_fSpecifiedBPMMax = info.song->m_fSpecifiedBPMMin; }
		else
		{ info.song->m_fSpecifiedBPMMax = StringToFloat((*info.params)[2]); }
	}
}
Exemple #8
0
void SSCLoader::ProcessLabels( TimingData &out, const RString sParam )
{
	vector<RString> arrayLabelExpressions;
	split( sParam, ",", arrayLabelExpressions );
	
	for( unsigned b=0; b<arrayLabelExpressions.size(); b++ )
	{
		vector<RString> arrayLabelValues;
		split( arrayLabelExpressions[b], "=", arrayLabelValues );
		if( arrayLabelValues.size() != 2 )
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an invalid #LABELS value \"%s\" (must have exactly one '='), ignored.",
				     arrayLabelExpressions[b].c_str() );
			continue;
		}
		
		const float fBeat = StringToFloat( arrayLabelValues[0] );
		RString sLabel = arrayLabelValues[1];
		TrimRight(sLabel);
		if( fBeat >= 0.0f )
			out.AddSegment( LabelSegment(BeatToNoteRow(fBeat), sLabel) );
		else 
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an invalid Label at beat %f called %s.",
				     fBeat, sLabel.c_str() );
		}
		
	}
}
Exemple #9
0
void CTab2::OnEnChangeEditDynamic1()
{
	// TODO:  If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.

	// TODO:  Add your control notification handler code here
	if ( m_shape == NULL )
	{
		return;
	}

	// Get string from edit
	char str[256];
	m_dynamic1.GetWindowText ( str, 256 );

	// COnvert to float
	float answer;

	// If successfull
	if ( StringToFloat ( str, &answer ) && answer >= 0.0 && answer <= 1.0 )
	{
		// Set the value of the slider
		m_dynamic_friction.SetPos((int)(answer*100.0));

		// Set the shape
		m_shape->setDynamicFriction ( answer );
	}
	else
	{
		MessageBox ( "Please enter a number from 0 to 1, for example: 0.453" );
	}
}
///
/// Real number form validator
///
bool wxRealFormValidator::OnCheckValue( wxProperty *property, wxPropertyFormView *WXUNUSED(view),
                                       wxWindow *parentWindow)
{
    if (m_realMin == 0.0 && m_realMax == 0.0)
        return true;

    // The item used for viewing the real number: should be a text item.
    wxWindow *m_propertyWindow = property->GetWindow();
    if (!m_propertyWindow || !m_propertyWindow->IsKindOf(CLASSINFO(wxTextCtrl)))
        return false;

    wxString value(((wxTextCtrl *)m_propertyWindow)->GetValue());

    float val = 0.0;
    if (!StringToFloat(WXSTRINGCAST value, &val))
    {
        wxChar buf[200];
        wxSprintf(buf, wxT("Value %s is not a valid real number!"), (const wxChar *)value);
        wxMessageBox(buf, wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
        return false;
    }

    if (val < m_realMin || val > m_realMax)
    {
        wxChar buf[200];
        wxSprintf(buf, wxT("Value must be a real number between %.2f and %.2f!"), m_realMin, m_realMax);
        wxMessageBox(buf, wxT("Property value error"), wxOK | wxICON_EXCLAMATION, parentWindow);
        return false;
    }
    return true;
}
Exemple #11
0
bool ProcessFileLine(const String& line, const String& reference)
{
	StringList mValues;
	mValues = SplitString(line, "\t", true);

	if(mValues.size() == 8)
	{
		//add as first animation frame
		AddAnimationReference(reference, mValues[0], StringToInt(mValues[2]), StringToInt(mValues[3]),
								StringToInt(mValues[4]), StringToInt(mValues[5]), StringToInt(mValues[6]),
								StringToFloat(mValues[7]));

	}
	else if(mValues.size() == 6)
	{
		//add as additional animation frame
		AddAnimationReference(reference, mValues[0], StringToInt(mValues[2]), StringToInt(mValues[3]),
								StringToInt(mValues[4]), StringToInt(mValues[5]));
	}
	else if(mValues.size() == 5)
	{
		//add as single image
		AddSpriteReference(reference, mValues[0], StringToInt(mValues[1]), StringToInt(mValues[2]),
								StringToInt(mValues[3]), StringToInt(mValues[4]));
	}
	else
		return false;

	return true;
}
Exemple #12
0
	void ToggleButton::Draw() {
		float f;
		if ( StringToFloat( var->Get(), f ) ) {
			color = ( f != 0 ) ? onColor : offColor;
		}
		Button::Draw();
	}
Exemple #13
0
	ToggleButton::ToggleButton( const string & tbTextureFilename, const string & tbVarName ) 
	: Button( tbTextureFilename ), onColor( .4f, 1.f, .4f, .9f ), offColor( .65f, .65f, .65f, .75f ) {
		var = FindVar( tbVarName.c_str() );
		float f;
		if ( StringToFloat( var->Get(), f ) ) {
			color = ( f != 0 ) ? onColor : offColor;
		}
	}
bool ScreenTextEntry::FloatValidate( const RString &sAnswer, RString &sErrorOut )
{
	float f;
	if( StringToFloat(sAnswer, f) )
		return true;
	sErrorOut = ssprintf( INVALID_FLOAT.GetValue(), sAnswer.c_str() );
	return false;
}
Exemple #15
0
KDfloat32 KD_APIENTRY Strtof(const KDchar *s, KDchar **endptr)
{
    EVENT("(const KDchar *s = 0x%0.8p, KDchar **endptr = 0x%0.8p)", s, endptr);

    KDfloat32 returnValue;
    const Error error = StringToFloat(s, endptr, &returnValue);
    if (error.isError()) SetGlobalError(error);
    return returnValue;
}
Exemple #16
0
void ActorFactorySetEndColor(const String& input)
{
	ACTORFACTORY_GETDELEGATE(pDel, ParticleActorFactoryDelegate);

	float r,g,b;
	r=g=b=0.0f;

	StringList colors = SplitString(input);
	int size = colors.size();
	if( size > 0 )
		r = StringToFloat(colors[0]);
	if( size > 1 )
		g = StringToFloat(colors[1]);
	if( size > 2 )
		b = StringToFloat(colors[2]);

	pDel->SetEndColor( r, g, b	);
}
PreviewWindow::PreviewWindow(wxWindow *parent, int x, int y, int w, int h, long style, const wxString &name):
	wxPanel(parent, x, y, w, h, style, name), wheelPosition(0), zoomFactor(0.2f), drawTrajectory(true)
{
	Connect(this->GetId(), wxEVT_PAINT, wxPaintEventHandler(PreviewWindow::OnPaint));
	Connect(this->GetId(), wxEVT_MOTION, wxMouseEventHandler(PreviewWindow::OnMouseMove));
	Connect(this->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(PreviewWindow::OnWheelMoved));

	SetBackgroundStyle(wxBG_STYLE_CUSTOM);

	CIniFile ini;
	originSize = StringToFloat(ini.GetValue("originSize", "UI", iniFile));
	zoomFactor = StringToFloat(ini.GetValue("zoomCoefficient", "UI", iniFile));
	lineWidth = StringToFloat(ini.GetValue("lineWidth", "UI", iniFile));
	rapidColour = ParseColour(ini.GetValue("rapidColour", "UI", iniFile));
	normalColour = ParseColour(ini.GetValue("normalColour", "UI", iniFile));
	cCWColour = ParseColour(ini.GetValue("CWColour", "UI", iniFile));
	cCCWColour = ParseColour(ini.GetValue("CCWColour", "UI", iniFile));
	trajectoryColour = ParseColour(ini.GetValue("trajectoryColour", "UI", iniFile));
	backgroundColour = ParseColour(ini.GetValue("backgroundColour", "UI", iniFile));
}
void AxisSettings::SendConfig(MyDevice* d)
{
	//Send acceleration
	CIniFile ini;
	unsigned char buffer[64] = {0};
	buffer[0] = 1;
	buffer[1] = RECEIVER_CONFIG;
	buffer[2] = CONFIG_REC_AXIS;
	buffer[3] = CONFIG_AXIS_ACCELERATION;
	*((float*)(buffer + 4)) = StringToFloat(ini.GetValue("maxLinearAcceleration", "axis", iniFile));
	d->SendRawData(buffer, sizeof(buffer));
	//Send update period
	buffer[3] = CONFIG_AXIS_UPDATE_PERIOD;
	*((uint32_t*)(buffer + 4)) = StringToInt(ini.GetValue("updatePeriod", "axis", iniFile));
	d->SendRawData(buffer, sizeof(buffer));
	//Send jerk
	buffer[3] = CONFIG_AXIS_JERK;
	*((float*)(buffer + 4)) = StringToFloat(ini.GetValue("maxLinearJerk", "axis", iniFile));
	d->SendRawData(buffer, sizeof(buffer));
}
Exemple #19
0
void CTab3::OnBnClickedSizeApply()
{
	// TODO: Add your control notification handler code here
	if ( m_shape == NULL )
	{
		return;
	}

	// Get strings from edits
	char strX[256];
	m_sizeX.GetWindowText ( strX, 256 );

	char strY[256];
	m_sizeY.GetWindowText ( strY, 256 );

	char strZ[256];
	m_sizeZ.GetWindowText ( strZ, 256 );

	// COnvert to float
	float answerX, answerY, answerZ;

	// If successfull
	if ( StringToFloat ( strX, &answerX ) &&
		 StringToFloat ( strY, &answerY ) && 
		 StringToFloat ( strZ, &answerZ ) )
	{
		// Save document for undo
		if ( m_doc != NULL )
		{
			m_doc->saveState ( );
		}

		// Set the shape
		m_shape->setSize ( answerX, answerY, answerZ );
	}
	else
	{
		MessageBox ( "Please enter a number for the x, y and z fields." );
	}
}
void GCodeInterpreter::LoadConfiguration()
{
	CIniFile ini;
	rapidFeed=StringToFloat(ini.GetValue("defaultRapidFeed", "gcode", iniFile));
	standardFeed=StringToFloat(ini.GetValue("defaultStandardFeed", "gcode", iniFile));
	maxAcceleration=StringToFloat(ini.GetValue("maxLinearAcceleration", "axis", iniFile));
	maxJerk=StringToFloat(ini.GetValue("maxLinearJerk", "axis", iniFile));
	maxRapidTollerance=StringToFloat(ini.GetValue("maxRapidTollerance", "gcode", iniFile));
	maxStandardTollerance=StringToFloat(ini.GetValue("maxStandardTollerance", "gcode", iniFile));
	unitMultiply=StringToFloat(ini.GetValue("defaultUnits", "gcode", iniFile));
	string temp = ini.GetValue("defaultWorkingPlane", "gcode", iniFile);
	if(temp == "XY")
		workingPlane = XY;
	else if(temp == "YZ")
		workingPlane = YZ;
	else if(temp == "XY")
		workingPlane = XY;
	else
	{
		wxString text = wxT("Špatnì nastavená pracovní rovina v ini souboru. Použít XY a pokraèovat?");
		if(wxMessageBox(text, wxT("Chyba!"), wxYES_NO | wxICON_EXCLAMATION) == wxNO)
				throw(exception("Operace ukonèena"));
		workingPlane = XY;
	}

	temp = ini.GetValue("defaultCoordType", "gcode", iniFile);
	if(temp == "absolute" || temp == "abs" || temp == "ABS")
		coordType = ABS;
	else if(temp == "relative" || temp == "rel" || temp == "REL" 
		|| temp == "incremental" || temp == "inc" || temp == "INC")
		coordType = INC;
	else
	{
		wxString text = wxT("Špatnì nastavený typ souøadnic v ini souboru. Použít absolutní a pokraèovat?");
		if(wxMessageBox(text, wxT("Chyba!"), wxYES_NO | wxICON_EXCLAMATION) == wxNO)
				throw(exception("Operace ukonèena"));
		coordType = ABS;
	}

	temp = ini.GetValue("defaultArcCoordType", "gcode", iniFile);
	if(temp == "absolute" || temp == "abs" || temp == "ABS")
		arcCoordType = ABS;
	else if(temp == "relative" || temp == "rel" || temp == "REL" 
		|| temp == "incremental" || temp == "inc" || temp == "INC")
		arcCoordType = INC;
	else
	{
		wxString text = wxT("Špatnì nastavený typ souøadnic pro oblouky v ini souboru. Použít absolutní a pokraèovat?");
		if(wxMessageBox(text, wxT("Chyba!"), wxYES_NO | wxICON_EXCLAMATION) == wxNO)
				throw(exception("Operace ukonèena"));
		arcCoordType = ABS;
	}

}
Exemple #21
0
	void ToggleButton::Pressed() {
		if ( var == NULL ) {
			return;
		}
		char cmd[128];
		r3Sprintf( cmd, "toggle %s", var->Name().Str().c_str() );
		ExecuteCommand( cmd );
		
		float f;
		if ( StringToFloat( var->Get(), f ) ) {
			color = ( f != 0 ) ? onColor : offColor;
		}
		
	}
Exemple #22
0
void RadarValues::FromString( RString sRadarValues )
{
	vector<RString> saValues;
	split( sRadarValues, ",", saValues, true );

	if( saValues.size() != NUM_RadarCategory )
	{
		MakeUnknown();
		return;
	}

	FOREACH_ENUM( RadarCategory, rc )
		m_Values.f[rc] = StringToFloat( saValues[rc] );
    
}
Exemple #23
0
void ActorFactorySetGravity(const String& input)
{
	ACTORFACTORY_GETDELEGATE(pDel, ParticleActorFactoryDelegate);

	StringList values = SplitString(input);
	int size = values.size();

	Vector2 gravity(0.0f, 0.0f);	

	// X and Y are specified.
	if (size == 2)
	{
		gravity.X = StringToFloat(values[0]);
		gravity.Y = StringToFloat(values[1]);
	}
	// If only one value specified, assume it's just vertical.
	else if (size == 1 )
	{
		gravity.X = 0.0f;
		gravity.Y = StringToFloat(values[0]);
	}

	pDel->SetGravity(gravity);
}
Exemple #24
0
void SSCLoader::ProcessWarps( TimingData &out, const RString sParam, const float fVersion )
{
	vector<RString> arrayWarpExpressions;
	split( sParam, ",", arrayWarpExpressions );
	
	for( unsigned b=0; b<arrayWarpExpressions.size(); b++ )
	{
		vector<RString> arrayWarpValues;
		split( arrayWarpExpressions[b], "=", arrayWarpValues );
		if( arrayWarpValues.size() != 2 )
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an invalid #WARPS value \"%s\" (must have exactly one '='), ignored.",
				     arrayWarpExpressions[b].c_str() );
			continue;
		}
		
		const float fBeat = StringToFloat( arrayWarpValues[0] );
		const float fNewBeat = StringToFloat( arrayWarpValues[1] );
		// Early versions were absolute in beats. They should be relative.
		if( ( fVersion < VERSION_SPLIT_TIMING && fNewBeat > fBeat ) )
		{
			out.AddSegment( WarpSegment(BeatToNoteRow(fBeat), fNewBeat - fBeat) );
		}
		else if( fNewBeat > 0 )
			out.AddSegment( WarpSegment(BeatToNoteRow(fBeat), fNewBeat) );
		else
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an invalid Warp at beat %f, BPM %f.",
				     fBeat, fNewBeat );
		}
	}
}
Exemple #25
0
static void ReadTimeSigs( const NameToData_t &mapNameToData, MeasureToTimeSig_t &out )
{
	NameToData_t::const_iterator it;
	for( it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it )
	{
		const RString &sName = it->first;
		if( sName.size() != 6 || sName[0] != '#' || !IsAnInt(sName.substr(1, 5)) )
			continue;
		
		// this is step or offset data.  Looks like "#00705"
		const RString &sData = it->second;
		int iMeasureNo	= atoi( sName.substr(1, 3).c_str() );
		int iBMSTrackNo	= atoi( sName.substr(4, 2).c_str() );
		if( iBMSTrackNo == BMS_TRACK_TIME_SIG )
			out[iMeasureNo] = StringToFloat( sData );
	}
}
Exemple #26
0
CollisionResponse* PlaySoundCollisionResponse::FactoryMethod( const StringList& input )
{
	if( input.size() > 0 )
	{
		Sound* pSound = theSound.LoadSound(input[0].c_str());
		if (pSound)
		{
			PlaySoundCollisionResponse* pColResponse = new PlaySoundCollisionResponse();
			pColResponse->_volume = 1.0f;
			pColResponse->_sound = pSound;

			if( input.size() > 1 )
			{
				pColResponse->_volume = StringToFloat(input[1] );
			}

			return pColResponse;
		}
	}

	return NULL;
}
Exemple #27
0
void SSCLoader::ProcessCombos( TimingData &out, const RString line, const int rowsPerBeat )
{
	vector<RString> arrayComboExpressions;
	split( line, ",", arrayComboExpressions );
	
	for( unsigned f=0; f<arrayComboExpressions.size(); f++ )
	{
		vector<RString> arrayComboValues;
		split( arrayComboExpressions[f], "=", arrayComboValues );
		unsigned size = arrayComboValues.size();
		if( size < 2 )
		{
			LOG->UserLog("Song file",
				     this->GetSongTitle(),
				     "has an invalid #COMBOS value \"%s\" (must have at least one '='), ignored.",
				     arrayComboExpressions[f].c_str() );
			continue;
		}
		const float fComboBeat = StringToFloat( arrayComboValues[0] );
		const int iCombos = StringToInt( arrayComboValues[1] );
		const int iMisses = (size == 2 ? iCombos : StringToInt(arrayComboValues[2]));
		out.AddSegment( ComboSegment( BeatToNoteRow(fComboBeat), iCombos, iMisses ) );
	}
}
Exemple #28
0
void SMSetOffset(SMSongTagInfo& info)
{
	info.song->m_SongTiming.m_fBeat0OffsetInSeconds = StringToFloat((*info.params)[1]);
}
float CStringUtils::StringToFloat(const nstring & str)
{
	return StringToFloat(str.c_str());
}
Exemple #30
0
bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut )
{
	ASSERT_M( NOTESKIN != NULL, "The Noteskin Manager must be loaded in order to process mods." );

	RString sBit = sOneMod;
	sBit.MakeLower();
	Trim( sBit );

	/* "drunk"
	 * "no drunk"
	 * "150% drunk"
	 * "*2 100% drunk": approach at 2x normal speed */

	float level = 1;
	float speed = 1;
	vector<RString> asParts;
	split( sBit, " ", asParts, true );

	FOREACH_CONST( RString, asParts, s )
	{
		if( *s == "no" )
		{
			level = 0;
		}
		else if( isdigit((*s)[0]) || (*s)[0] == '-' )
		{
			/* If the last character is a *, they probably said "123*" when
			 * they meant "*123". */
			if( s->Right(1) == "*" )
			{
				// XXX: We know what they want, is there any reason not to handle it?
				// Yes. We should be strict in handling the format. -Chris
				sErrorOut = ssprintf("Invalid player options \"%s\"; did you mean '*%d'?", s->c_str(), StringToInt(*s) );
				return false;
			}
			else
			{
				level = StringToFloat( *s ) / 100.0f;
			}
		}
		else if( *s[0]=='*' )
		{
			sscanf( *s, "*%f", &speed );
			if( !isfinite(speed) )
				speed = 1.0f;
		}
	}

	sBit = asParts.back();

#define SET_FLOAT( opt ) { m_ ## opt = level; m_Speed ## opt = speed; }
	const bool on = (level > 0.5f);

	static Regex mult("^([0-9]+(\\.[0-9]+)?)x$");
	vector<RString> matches;
	if( mult.Compare(sBit, matches) )
	{
		StringConversion::FromString( matches[0], level );
		SET_FLOAT( fScrollSpeed )
		SET_FLOAT( fTimeSpacing )
		m_fTimeSpacing = 0;
		m_fMaxScrollBPM = 0;
	}
	else if( sscanf( sBit, "c%f", &level ) == 1 )
	{
		if( !isfinite(level) || level <= 0.0f )
			level = CMOD_DEFAULT;
		SET_FLOAT( fScrollBPM )
		SET_FLOAT( fTimeSpacing )
		m_fTimeSpacing = 1;
		m_fMaxScrollBPM = 0;
	}
	// oITG's m-mods
	else if( sscanf( sBit, "m%f", &level ) == 1 )
	{
		// OpenITG doesn't have this block:
		/*
		if( !isfinite(level) || level <= 0.0f )
			level = CMOD_DEFAULT;
		*/
		SET_FLOAT( fMaxScrollBPM )
		m_fTimeSpacing = 0;
	}

	else if( sBit == "clearall" )				Init();
	else if( sBit == "resetspeed" )
	{
		/* level is set to the values from Init() because all speed related
		   fields are being reset to initial values, and they each have different
		   initial values.  -kyz */
		level= 0;
		SET_FLOAT(fMaxScrollBPM);
		SET_FLOAT(fTimeSpacing);
		level= 1.0f;
		SET_FLOAT(fScrollSpeed);
		level= CMOD_DEFAULT;
		SET_FLOAT(fScrollBPM)
	}