// load kerning informations
static void LoadKerning(GFont2D& Font, const FT_Face Face, const GReal Scale, const GString& MetricsFile) {

	FT_Vector v;
	FT_Error err;
	GInt32 i, j, k;
	GKerningEntry entry;
	GDynArray<GKerningEntry> kerningTable;

	if (MetricsFile.length() > 0)
		err = FT_Attach_File(Face, StrUtils::ToAscii(MetricsFile));

	// if the face has not kerning infos just return
	if ((Face->face_flags & FT_FACE_FLAG_KERNING) == 0)
		return;

	j = (GInt32)Face->num_glyphs;
	for	(i = 0; i < j; i++) {
		for (k = 0; k < j; k++) {
			// get kerning for pair (i, k)
			err = FT_Get_Kerning(Face, i, k, FT_KERNING_UNSCALED, &v);
			if ((err == 0) && ((v.x != 0) || (v.y != 0))) {
				entry.GlyphIndexLeft = i;
				entry.GlyphIndexRight = k;
				entry.Kerning.Set((GReal)v.x * Scale, (GReal)v.y * Scale);
				kerningTable.push_back(entry);
			}
		}
	}
	Font.SetKerning(kerningTable);
}
	static GString getDifficultyAuthor(T const *Diff)
	{
		GString candidate = GameState::GetInstance().GetSongDatabase()->GetArtistForDifficulty(Diff->ID);
		if (!candidate.length())
			candidate = Diff->Author;
		return candidate;
	}
GError GPlugLoader::LoadFilePlug(const GChar8 *FullLibraryName) {

    GPlugHandle handle = NULL;

	// we don't wanna a null filename
	if (!FullLibraryName)
		return G_INVALID_PARAMETER;
	// unplug current library
	UnloadPlug();

	#if defined(G_OS_WIN) && !defined(__CYGWIN__)
		handle = LoadLibraryA(FullLibraryName);
	#elif defined(G_OS_HPUX)
		// BIND_FIRST is necessary for some reason
		handle = shl_load(FullLibraryName, BIND_DEFERRED | BIND_FIRST | BIND_VERBOSE, 0);
	// other Unix (it works also on MacOSX and Tiger)
	#else 
		handle = dlopen(FullLibraryName, RTLD_LAZY | RTLD_GLOBAL);
		// dlopen will not work with files in the current directory unless
		// they are prefaced with './'  (DB - Nov 5, 2003).
		// So we must check if file was expressed as a local file (without path)
		GString fPath = StrUtils::ExtractFilePath(FullLibraryName);
		if ((!handle) && (fPath.length() <= 0)) {
			GString localLibraryName = GString("./") + GString(FullLibraryName);
			handle = dlopen(StrUtils::ToAscii(localLibraryName), RTLD_LAZY | RTLD_GLOBAL);
		}
	#endif

	if (!handle)
		return G_INVALID_FORMAT;

	gPlugHandle = handle;
	return G_NO_ERROR;
}
void ReadMetadata (GString line, OsuLoadInfo* Info)
{
	auto Command = line.substr(0, line.find_first_of(":")); // Lines are Information:Content
	auto Content = line.substr(line.find_first_of(":") + 1, line.length() - line.find_first_of(":"));

#ifdef VERBOSE_DEBUG
	printf("Command found: %s | Contents: %s\n", Command.c_str(), Content.c_str());
#endif

	Utility::Trim(Content);
	if (Command == "Title")
	{
		Info->OsuSong->SongName = Content;
	}else if (Command == "Artist")
	{
		Info->OsuSong->SongAuthor = Content;
	}else if (Command == "Version")
	{
		Info->Diff->Name = Content;
	}else if (Command == "TitleUnicode")
	{
		if (Content.length() > 1)
			Info->OsuSong->SongName = Content;
	}else if (Command == "ArtistUnicode")
	{
		if (Content.length() > 1)
			Info->OsuSong->SongAuthor = Content;
	}
	else if (Command == "Creator")
	{
		Info->Diff->Author = Content;
	}
}
void InitApp() {

#ifdef _DEBUG
    SysUtils::RedirectIOToConsole();
#endif

    GString s;

    gKernel = new GKernel();
    gFont = (GFont2D *)gKernel->CreateNew(G_FONT2D_CLASSID);
    // Depth Into The Screen
    gX = -0.4f;
    gY = -0.3f;
    gZ = -2.3f;
    // build path for data (textures)
    gDataPath = SysUtils::AmanithPath();
    if (gDataPath.length() > 0)
        gDataPath += "data/";
    s = StrUtils::OSFixPath(gDataPath + "crazk.ttf", G_FALSE);
    gFont->Load(StrUtils::ToAscii(s), "scale=0");
    gWireFrame = G_TRUE;
    gFillDraw = G_TRUE;
    gDeviation = (GReal)0.000003;
    gCurrentChar = 'S';
    gChar = gFont->CharByCode(gCurrentChar, 0);
    GenerateTessellation(gChar, gDeviation);
}
// Inserts a filename, if it already exists, updates it.
// Returns the ID of the filename.
int SongDatabase::InsertFilename(Directory Fn)
{
	int ret;
	int idOut;
	int lmt;
	SC(sqlite3_bind_text(st_FilenameQuery, 1, Fn.c_path(), Fn.path().length(), SQLITE_STATIC));

	if (sqlite3_step(st_FilenameQuery) == SQLITE_ROW)
	{
		idOut = sqlite3_column_int(st_FilenameQuery, 0);
		lmt = sqlite3_column_int(st_FilenameQuery, 1);

		int lastLmt = Utility::GetLMT(Fn.path());

		// Update the last-modified-time of this file, and its hash if it has changed.
		if (lmt != lastLmt)
		{
			GString Hash = Utility::GetSha256ForFile(Fn);
			SC(sqlite3_bind_int(st_UpdateLMT, 1, lastLmt));
			SC(sqlite3_bind_text(st_UpdateLMT, 2, Hash.c_str(), Hash.length(), SQLITE_STATIC));
			SC(sqlite3_bind_text(st_UpdateLMT, 3, Fn.c_path(), Fn.path().length(), SQLITE_STATIC));
			SCS(sqlite3_step(st_UpdateLMT));
			SC(sqlite3_reset(st_UpdateLMT));
		}
	}else
	{
		GString Hash = Utility::GetSha256ForFile(Fn);

		// There's no entry, got to insert it.
		SC(sqlite3_bind_text(st_FilenameInsertQuery, 1, Fn.c_path(), Fn.path().length(), SQLITE_STATIC));
		SC(sqlite3_bind_int(st_FilenameInsertQuery, 2, Utility::GetLMT(Fn.path())));
		SC(sqlite3_bind_text(st_FilenameInsertQuery, 3, Hash.c_str(), Hash.length(), SQLITE_STATIC));
		SCS(sqlite3_step(st_FilenameInsertQuery)); // This should not fail. Otherwise, there are bigger problems to worry about...
		SC(sqlite3_reset(st_FilenameInsertQuery));

		// okay, then return the ID.
		SC(sqlite3_reset(st_FilenameQuery));
		SC(sqlite3_bind_text(st_FilenameQuery, 1, Fn.c_path(), Fn.path().length(), SQLITE_STATIC));
		sqlite3_step(st_FilenameQuery);
		idOut = sqlite3_column_int(st_FilenameQuery, 0);
	}

	SC(sqlite3_reset(st_FilenameQuery));
	return idOut;
}
GError GProperty::SetName(const GString& NewName) {

	if (NewName.length() <= 0)
		return G_INVALID_PARAMETER;

	gName = NewName;
	gUpperName = StrUtils::Upper(gName);
	return G_NO_ERROR;
}
Exemple #8
0
	GString SJIStoU8 (GString Line)
	{
#ifdef WIN32
		wchar_t u16s[MAX_STRING_SIZE];
		char mbs[MAX_STRING_SIZE];
		size_t len = MultiByteToWideChar(932, 0, Line.c_str(), Line.length(), u16s, MAX_STRING_SIZE);
		len = WideCharToMultiByte(CP_UTF8, 0, u16s, len, mbs, MAX_STRING_SIZE, NULL, NULL);
		mbs[len] = 0;
		return GString(mbs);
#elif defined(DARWIN)
        // Note: for OS X/Darwin/More than likely most BSD variants, iconv behaves a bit differently.
        iconv_t conv;
        char buf[MAX_STRING_SIZE];
        char* out = buf;
        size_t srcLength = Line.length();
        size_t dstLength = MAX_STRING_SIZE;
        const char* in = Line.c_str();
        
        conv = iconv_open("UTF-8", "SHIFT_JIS");
        iconv(conv, (char**)&in, &srcLength, (char**)&out, &dstLength);
        iconv_close(conv);
        // We have to use buf instead of out here.  For whatever reason, iconv on Darwin doesn't get us what we would expect if we just use out.
        return GString(buf);
#else
        char buf[MAX_STRING_SIZE];
		iconv_t conv;
		char** out = &buf;
		const char* in = Line.c_str();
		size_t BytesLeftSrc = Line.length();
		size_t BytesLeftDst = MAX_STRING_SIZE;

		conv = iconv_open("UTF-8", "SHIFT_JIS");
		bool success = (iconv(conv, (char **)&in, &BytesLeftSrc, out, &BytesLeftDst) > -1);

		iconv_close(conv);
		if (success)
			return GString(*out);
		else
		{
			Log::Printf("Failure converting character sets.");
			return GString();
		}
#endif
	}
// remove the specified property form internal list
GBool GAnimElement::RemoveProperty(const GString& Name) {

	if (Name.length() <= 0)
		return G_FALSE;

	GUInt32 propIndex;
	GProperty *tmpProp;

	tmpProp = FindProperty(Name, propIndex);
	return RemoveProperty(propIndex);
}
Exemple #10
0
	std::wstring Widen(GString Line)
	{
		wchar_t u16s[2048]; // Ought to be enough for everyone.

#ifndef WIN32
		mbstowcs(u16s, Line.c_str(), 2048);
#else
		memset(u16s, 0, sizeof(wchar_t) * 2048);
		size_t len = MultiByteToWideChar(CP_UTF8, 0, Line.c_str(), Line.length(), u16s, 2048);
#endif
		return std::wstring(u16s);
	}
int InitGL(GLvoid) {

	gKernel = new GKernel();
	gImage = (GPixelMap *)gKernel->CreateNew(G_PIXELMAP_CLASSID);

	// build path for data (textures)
	gDataPath = SysUtils::AmanithPath();
	if (gDataPath.length() > 0)
		gDataPath += "data/";

	gRotAngle = 0;
	gRotationVel = (GReal)0.05;
	gStrokeOpacity = 1;
	gFillOpacity = 1;
	gZoomFactor = 2;
	gAnim = G_FALSE;
	gTranslation.Set(256, 256);
	gStrokeCompOp = G_SRC_OVER_OP;
	gFillCompOp = G_SRC_OVER_OP;

	gDrawBoard->SetRenderingQuality(G_HIGH_RENDERING_QUALITY);

	GString s;
	GError err;
	GDynArray<GKeyValue> colKeys;

	// color gradient
	colKeys.clear();
	colKeys.push_back(GKeyValue((GReal)0.00, GVector4((GReal)0.95, (GReal)0.92, (GReal)0.0, (GReal)1.0)));
	colKeys.push_back(GKeyValue((GReal)1.00, GVector4((GReal)0.1, (GReal)0.3, (GReal)0.8, (GReal)0.7)));
	gLinGrad = gDrawBoard->CreateLinearGradient(GPoint2(-60, -44), GPoint2(60, 44), colKeys, G_HERMITE_COLOR_INTERPOLATION, G_PAD_COLOR_RAMP_SPREAD);

	// background
	s = gDataPath + "compground.png";
	err = gImage->Load(StrUtils::ToAscii(s), "expandpalette=true");
	if (err == G_NO_ERROR) {
		gBackGround = gDrawBoard->CreatePattern(gImage, G_LOW_IMAGE_QUALITY, G_REPEAT_TILE);
		gBackGround->SetLogicalWindow(GPoint2(0, 0), GPoint2(512, 512));
	}
	else
		gBackGround = NULL;

	gDrawBoard->SetStrokeWidth(10);
	gDrawBoard->SetStrokeGradient(gLinGrad);
	gDrawBoard->SetFillGradient(gLinGrad);
	gDrawBoard->SetFillPattern(gBackGround);
	DrawTitle();

	return TRUE;
}
Exemple #12
0
	vector<GString> TokenSplit(const GString& str, const GString &token, bool compress)
	{
		vector<GString> ret;
		size_t len = str.length();
		auto it = &str[0];
		auto next = strpbrk(str.c_str(), token.c_str()); // next token instance
		for (; next != nullptr; next = strpbrk(it, token.c_str()))
		{
			if (!compress || it - next != 0)
				ret.push_back(GString(it, next));
			it = next + 1;
		}

		if (it != next && len)
			ret.push_back(GString(it, &str[len]));
		return ret;
	}
Exemple #13
0
// returns if difficulty exists in the database. And difficulty ID.
bool SongDatabase::DifficultyExists(int FileID, GString DifficultyName, int *IDOut)
{
	int ret;
	SC(sqlite3_bind_int (st_GetDiffIDFile, 1, FileID));
	SC(sqlite3_bind_text(st_GetDiffIDFile, 2, DifficultyName.c_str(), DifficultyName.length(), SQLITE_STATIC));
	int r = sqlite3_step(st_GetDiffIDFile);

	if (IDOut)
	{
		if (r == SQLITE_ROW)
			*IDOut = sqlite3_column_int(st_GetDiffIDFile, 0);
		else
			*IDOut = 0;
	}

	SC(sqlite3_reset(st_GetDiffIDFile));
	return r == SQLITE_ROW;
}
Exemple #14
0
int KeyTranslate(GString K)
{
	for (uint32 i = 0; i < SpecialKeys.size(); i++)
	{
		GString Key = K; Utility::ToLower(Key);
		GString Target = GString(SpecialKeys.at(i).KeyString);  Utility::ToLower(Target);
		if (Key == Target)
			return SpecialKeys.at(i).boundkey;
	}

	if (K.length())
	{
		if (Utility::IsNumeric(K.c_str()))
			return atoi(K.c_str());
		else
			return (int)K[0];
	}
	else
		return 0;
}
void InitApp() {

#ifdef _DEBUG
	SysUtils::RedirectIOToConsole();
#endif

	GError err;

	// create a new kernel
	gKernel = new GKernel();

	// build path for data
	GString dataPath = SysUtils::AmanithPath();
	if (dataPath.length() > 0)
		dataPath += "data/";

	// load glyphs and triangulate them
	err = LoadAndTesselateGlyphs(dataPath + "cards.ttf", (GReal)1e-7);
	if (err != G_NO_ERROR) {
		perror("Fail to load cards.ttf");
		abort();
	}
	// load cards and animations
	err = LoadCardsAndAnimations(dataPath + "cards.xml");
	if (err != G_NO_ERROR) {
		perror("Fail to load cards.xml");
		abort();
	}
	// load and initialize background
	LoadBackGraoundAndLogo(dataPath + "stars.png");
	// initialize random generator
	GMath::SeedRandom();
	// begin with 7 cards
	gMaxCards = 7;
	gLogicTick = 0.13;
	gBackGroundTime = 0;
	gBackGroundTimeStep = 0.0003;
	gAnimCards.resize(gMaxCards);
}
Exemple #16
0
GString RemoveComments(const GString Str)
{
	GString Result;
	int k = 0;
	int AwatingEOL = 0;
	ptrdiff_t len = Str.length() - 1;

	for (ptrdiff_t i = 0; i < len; i++)
	{
		if (AwatingEOL)
		{
			if (Str[i] != '\n')
				continue;
			else
			{
				AwatingEOL = 0;
				continue;
			}
		}
		else
		{
			if (Str[i] == '/' && Str[i + 1] == '/')
			{
				AwatingEOL = true;
				continue;
			}
			else
			{
				Result.push_back(Str.at(i));
				k++;
			}
		}
	}

	Utility::ReplaceAll(Result, "[\\n\\r ]", "");
	return Result;
}
Exemple #17
0
void ReadDifficulty (GString line, OsuLoadInfo* Info)
{
	GString Command = line.substr(0, line.find_first_of(":")); // Lines are Information:Content
	GString Content = line.substr(line.find_first_of(":") + 1, line.length() - line.find_first_of(":"));
	Utility::Trim(Content);

	// We ignore everything but the key count!
	if (Command == "CircleSize")
	{
		Info->Diff->Channels = atoi(Content.c_str());
	}else if (Command == "SliderMultiplier")
	{
		Info->SliderVelocity = latof(Content.c_str()) * 100;
	}
	else if (Command == "HPDrainRate")
	{
		Info->TimingInfo->HP = latof(Content.c_str());
	}
	else if (Command == "OverallDifficulty")
	{
		Info->TimingInfo->OD = latof(Content.c_str());
	}

}
Exemple #18
0
	GString GetSVGText(int diffIndex, double intervalduration = 1, double peakMargin = 1.2)
	{
		std::stringstream out;
		vector<int> dataPoints = GetDataPoints(diffIndex, intervalduration);
		auto peak_it = std::max_element(dataPoints.begin(), dataPoints.end());
		float peakf = *peak_it;
		double peak = *peak_it * peakMargin;

		out << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n";

		auto ptIdx = 0;
		float ImageHeight = CfgValNPS("GraphHeight", 300);
		float GraphYOffset = CfgValNPS("GraphYOffs", 50);
		float GraphXOffset = CfgValNPS("GraphXOffs", 100);
		
		float IntervalWidth = 10;
		float GraphWidth = dataPoints.size() * IntervalWidth;

		float RealGraphWidth = CfgValNPS("Width", 1000);
		float XRatio = RealGraphWidth / GraphWidth;

		Vec2 BL(GraphXOffset, GraphYOffset + ImageHeight);
		Vec2 BR(RealGraphWidth, 0);
		Vec2 TL(GraphXOffset, GraphYOffset);
		BR += BL;

		GString DiffAuth = Song->GetDifficulty(diffIndex)->Author;

		if (!DiffAuth.length())
			DiffAuth = "an anonymous charter";

		float avgNPS = Song->GetDifficulty(diffIndex)->TotalScoringObjects / Song->GetDifficulty(diffIndex)->Duration;

		out << Utility::Format("<text x=\"%d\" y=\"%d\" fill=\"black\">%s - %s (%s) by %s (Max NPS: %.2f/Avg NPS: %.2f)</text>\n",
			20, 20,
			Song->SongName, Song->SongAuthor, Song->GetDifficulty(diffIndex)->Name, DiffAuth,
			peakf / intervalduration,
			avgNPS);

		out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(0,0,0);stroke-width:4\"/>\n",
			BL.x, BL.y, BR.x, BR.y);

		out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(0,0,0);stroke-width:4\"/>\n",
			TL.x, TL.y, BL.x, BL.y);

		auto ptAmt = 5;
		for (auto i = 1; i <= ptAmt; i++)
		{
			float X = (BL.x - GraphXOffset / 2);
			float Y = (BL.y - i * (ImageHeight / ptAmt / peakMargin));
			float Value = (peakf * i / ptAmt / intervalduration);
			out << Utility::Format("\t<text x=\"%d\" y=\"%d\" fill=\"black\">%.2f</text>\n",
				X, Y, Value);

			out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(0,0,0);stroke-width:0.5\"/>\n",
				X, Y, GraphXOffset + RealGraphWidth, Y);
		}

		for (auto point : dataPoints)
		{
			double relativeFreq = point / peak;
			double relFreqNext;
			int x1, y1, x2, y2;

			if (ptIdx + 1 < dataPoints.size())
			{
				relFreqNext = dataPoints[ptIdx + 1] / peak;
			}
			else
				relFreqNext = 0;

			x1 = IntervalWidth * ptIdx * XRatio + GraphXOffset;
			y1 = ImageHeight - ImageHeight * relativeFreq + GraphYOffset;

			x2 = IntervalWidth * (ptIdx + 1) * XRatio + GraphXOffset;
			y2 = ImageHeight - ImageHeight * relFreqNext  + GraphYOffset;

			out << Utility::Format("\t<line x1 = \"%d\" y1 = \"%d\" x2 = \"%d\" y2 = \"%d\" style = \"stroke:rgb(255,0,0);stroke-width:2\"/>\n",
				x1, y1, x2, y2);


			ptIdx++;
		}

		out << "</svg>";
		return out.str();
	}
bool CDx9FragmentProgram::load(const GString str)
{
	return load(str.c_str(),str.length());
}
QGLWidgetTest::QGLWidgetTest(const QGLFormat& Format, QWidget *parent) : QGLWidget(Format, parent) {
#else
QGLWidgetTest::QGLWidgetTest(QWidget * parent) : QGLWidget(parent) {
#endif

#ifdef _DEBUG
	SysUtils::RedirectIOToConsole();
#endif

	GError err;

	// create a new kernel
	gKernel = new GKernel();
	// build path for data
	GString dataPath = SysUtils::AmanithPath();
	if (dataPath.length() > 0)
		dataPath += "data/";

	// load glyphs and triangulate them
	err = LoadAndTesselateGlyphs(dataPath + "cards.ttf", (GReal)1e-7);
	if (err != G_NO_ERROR) {
		perror("Fail to load cards.ttf");
		abort();
	}
	// load cards and animations
	err = LoadCardsAndAnimations(dataPath + "cards.xml");
	if (err != G_NO_ERROR) {
		perror("Fail to load cards.xml");
		abort();
	}
	// load and initialize background
	LoadBackGraoundAndLogo(dataPath + "stars.png");
	// initialize random generator
	GMath::SeedRandom();
	// begin with 9 cards
	gMaxCards = 9;
	gBlockAnim = G_FALSE;
	gLogicTick = 0.5;
	gAnimCards.resize(gMaxCards);
	// resize the window
	QWidget *d = (QWidget *)QApplication::desktop();
	GInt32 winSize = GMath::Min(d->width(), d->height());
	this->resize(winSize-64, winSize-64);
}

//------------------------------------------------------------
void QGLWidgetTest::LoadBackGraoundAndLogo(const GString& FileName) {

	GError err;

	// create and load background texture
	gBackGround = (GPixelMap *)gKernel->CreateNew(G_PIXELMAP_CLASSID);
	if (!gBackGround)  {
		perror("Fail to create background GPixelMap");
		abort();
	}
	// use 'expandpalette' option just to ensure full color format (so artists can manipulate starts.png as
	// they want to do
	err = gBackGround->Load(StrUtils::ToAscii(FileName), "expandpalette=true");
	if (err != G_NO_ERROR) {
		perror("Fail to load stars.png");
		abort();
	}

	gBackGroundAnimUV = (GAnimTRSNode2D *)gKernel->CreateNew(G_ANIMTRSNODE2D_CLASSID);
	gBackGroundAnimColor = (GThreeHermiteProperty1D *)gKernel->CreateNew(G_THREEHERMITEPROPERTY1D_CLASSID);
	if (!gBackGroundAnimUV || !gBackGroundAnimColor) {
		perror("Fail to create background animations");
		abort();
	}
	// set uv animation
	gBackGroundAnimUV->SetPivotPosition(GPoint2(0.5, 0.5), G_FALSE);
	GHermiteProperty1D *p;
	GDynArray<GKeyValue> tmpKeys;

	// x-position
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimUV->Property("transform")->Property("position")->Property("x");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)-2));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.33, (GReal)2));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.67, (GReal)0));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)-2));
	p->SetKeys(tmpKeys);
	// y-position
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimUV->Property("transform")->Property("position")->Property("y");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)1));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.33, (GReal)2));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.67, (GReal)-2));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)1));
	p->SetKeys(tmpKeys);
	// rotation
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimUV->Property("transform")->Property("rotation");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)0));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.25, (GReal)1.57 * 2));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.50, (GReal)3.14 * 2));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.75, (GReal)4.71 * 2));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)6.28 * 2));
	p->SetKeys(tmpKeys);
	// x-scale
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimUV->Property("transform")->Property("scale")->Property("x");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)1));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.33, (GReal)3));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.67, (GReal)0.9));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)1));
	p->SetKeys(tmpKeys);
	// y-scale
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimUV->Property("transform")->Property("scale")->Property("y");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)1));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.33, (GReal)3));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.67, (GReal)0.9));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)1));
	p->SetKeys(tmpKeys);

	// red color
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimColor->Property("x");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)0.7));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.50, (GReal)0.0));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.75, (GReal)0.0));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)0.7));
	p->SetKeys(tmpKeys);
	// green color
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimColor->Property("y");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)0.0));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.50, (GReal)0.1));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.75, (GReal)0.7));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)0.0));
	p->SetKeys(tmpKeys);
	// blue color
	tmpKeys.clear();
	p = (GHermiteProperty1D *)gBackGroundAnimColor->Property("z");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)0.5));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.50, (GReal)0.6));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.75, (GReal)0.3));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)0.5));
	p->SetKeys(tmpKeys);

	// now set up logo
	gAnimLogo = (GAnimTRSNode2D *)gKernel->CreateNew(G_ANIMTRSNODE2D_CLASSID);	
	gAnimLogo->SetPivotPosition(GPoint2((GReal)0.550, (GReal)0.540), G_FALSE);

	gAnimLogo->Property("transform")->Property("position")->Property("x")->SetDefaultValue(GKeyValue((GReal)0.6));
	gAnimLogo->Property("transform")->Property("position")->Property("y")->SetDefaultValue(GKeyValue((GReal)-1.23));

	// x-scale
	tmpKeys.clear();
	gAnimLogo->Property("transform")->Property("scale")->Property("y")->SetDefaultValue(GKeyValue((GReal)1.5));
	p = (GHermiteProperty1D *)gAnimLogo->Property("transform")->Property("scale")->Property("x");
	p->SetOORAfter(G_LOOP_OOR);
	tmpKeys.push_back(GKeyValue((GTimeValue)0.00, (GReal)1.5));
	tmpKeys.push_back(GKeyValue((GTimeValue)0.50, (GReal)-1.5));
	tmpKeys.push_back(GKeyValue((GTimeValue)1.00, (GReal)1.5));
	p->SetKeys(tmpKeys);

	gBackGroundTime = 0;
	gBackGroundTimeStep = (GReal)0.001;
}
Exemple #21
0
void ReadObjects (GString line, OsuLoadInfo* Info)
{
	auto Spl = Utility::TokenSplit(line);

	int Track = GetTrackFromPosition(latof(Spl[0].c_str()), Info->Diff->Channels);
	int Hitsound;
	NoteData Note;

	SplitResult Spl2;

	/* 
		A few of these "ifs" are just since v11 and v12 store hold endtimes in different locations.
		Or not include some information at all...
	*/
	int splitType = 5;
	if (Spl.size() == 7)
		splitType = 6;
	else if (Spl.size() == 5)
		splitType = 4;
	
	if (splitType != 4) // only 5 entries
		Spl2 = Utility::TokenSplit(Spl[splitType], ":");


	double startTime = latof(Spl[2].c_str()) / 1000.0;
	int NoteType = atoi(Spl[3].c_str());

	if (NoteType & NOTE_HOLD)
	{
		float endTime;
		if (splitType == 5 && Spl2.size())
			endTime = latof(Spl2[0].c_str()) / 1000.0;
		else if (splitType == 6)
			endTime = latof(Spl[5].c_str()) / 1000.0;
		else // what really? a hold that doesn't bother to tell us when it ends?
			endTime = 0;

		Note.StartTime = startTime;
		Note.EndTime = endTime;

		if (startTime > endTime) { // Okay then, we'll transform this into a regular note..
			Log::Printf("NoteLoaderOM: object at track %d has startTime > endTime (%f and %f)\n", Track, startTime, endTime);
			Note.EndTime = 0;

			Info->Diff->TotalScoringObjects += 1;
			Info->Diff->TotalNotes++;
		}else {
			Info->Diff->TotalScoringObjects += 2;
			Info->Diff->TotalHolds++;
		}
	}else if (NoteType & NOTE_NORMAL)
	{
		Note.StartTime = startTime;
		Info->Diff->TotalNotes++;
		Info->Diff->TotalScoringObjects++;

	}else if (NoteType & NOTE_SLIDER)
	{
		// 6=repeats 7=length
		float sliderRepeats = latof(Spl[6].c_str());
		float sliderLength = latof(Spl[7].c_str());

		float Multiplier = Info->GetSliderMultiplierAt(startTime);

		float finalSize = sliderLength * sliderRepeats * Multiplier;
		float beatDuration = (finalSize / Info->SliderVelocity); 
		float bpm = (60000.0 / Info->GetBeatspaceAt(startTime));
		float finalLength = beatDuration * spb(bpm);

		if (0 > finalLength)
			Log::LogPrintf("Line %d: o!m loader warning: object at track %d has startTime > endTime (%f and %f)\n", Info->Line, Track, startTime, finalLength + startTime);

		Note.StartTime = startTime;
		Note.EndTime = finalLength + startTime;

		Info->Diff->TotalScoringObjects += 2;
		Info->Diff->TotalHolds++;
	}

	Hitsound = atoi(Spl[4].c_str());

	GString Sample = GetSampleFilename(Info, Spl2, NoteType, Hitsound, startTime);

	if (Sample.length())
	{
		if (Info->Sounds.find(Sample) == Info->Sounds.end())
		{
			Info->Sounds[Sample] = Info->last_sound_index;
			Info->last_sound_index++;
		}

		Note.Sound = Info->Sounds[Sample];
	}

	Info->Diff->TotalObjects++;
	Info->Notes[Track].push_back(Note);

	Info->Diff->Duration = max(max (Note.StartTime, Note.EndTime)+1, Info->Diff->Duration);
}
shared_ptr<osb::SpriteList> ReadOSBEvents(std::istream& event_str)
{
	auto list = make_shared<osb::SpriteList>();
	int previous_lead = 100;
	shared_ptr<osb::BGASprite> sprite = nullptr;
	shared_ptr<osb::Loop> loop = nullptr;
	bool readingLoop = false;

	GString line;
	while (std::getline(event_str, line))
	{
		int lead_spaces;
		line = line.substr(line.find("//")); // strip comments
		lead_spaces = line.find_first_not_of("\t _");
		line = line.substr(lead_spaces, line.length() - lead_spaces + 1);

		vector<GString> split_result;
		boost::split(split_result, line, boost::is_any_of(","));
		for (auto &&s : split_result) boost::algorithm::to_lower(s);

		if (!line.length() || !split_result.size()) continue;

		if (lead_spaces < previous_lead && !readingLoop)
		{
			if (split_result[0] == "sprite")
			{
				Vec2 new_position(latof(split_result[3]), latof(split_result[4]));
				sprite = make_shared<osb::BGASprite>(split_result[1], OriginFromString(split_result[2]), new_position);
				list->push_back(sprite);
			}
		} else {
			if (!sprite)
				throw std::runtime_error("OSB command unpaired with sprite.");

			// If it's a loop, check if we're out of it.
			// If we're out of it, read a regular event, otherwise, read an event to the loop
			if (readingLoop)
			{
				if (lead_spaces < previous_lead) {
					readingLoop = false;

					// We're done reading the loop - unroll it.
					auto loop_events = loop->Unroll();
					for (auto i = 0; i < osb::EVT_COUNT; i++)
						for (auto evt : (*loop_events)[i])
							sprite->AddEvent(evt);
				}
				else
					loop->AddEvent(ParseEvent(split_result));
			}
			
			// It's not a command on the loop, or we weren't reading a loop in the first place.
			// Read a regular command.

			// Not "else" because we do want to execute this if we're no longer reading the loop.
			if (!readingLoop) {
				auto ev = ParseEvent(split_result);

				// A loop began - set that we are reading a loop and set this loop as where to add the following commands.
				if (ev->GetEventType() == osb::EVT_LOOP)
				{
					loop = static_pointer_cast<osb::Loop>(ev);
					readingLoop = true;
				}else // add this event, if not a loop to this sprite. It'll be unrolled once outside.
					sprite->AddEvent(ev);
			}
		}

		previous_lead = lead_spaces;
	}

	return list;
}
Exemple #23
0
void NoteLoaderOM::LoadObjectsFromFile(GString filename, GString prefix, Song *Out)
{
#if (!defined _WIN32) || (defined STLP)
	std::ifstream filein (filename.c_str());
#else
	std::ifstream filein (Utility::Widen(filename).c_str());
#endif
	std::regex versionfmt("osu file format v(\\d+)");

	if (!filein.is_open())
		throw std::exception("Could not open file.");

	auto Diff = make_shared<Difficulty>();
	OsuLoadInfo Info;

	Info.TimingInfo = make_shared<OsuManiaTimingInfo>();
	Info.OsuSong = Out;
	Info.SliderVelocity = 1.4;
	Info.Diff = Diff;
	Info.last_sound_index = 1;

	Diff->Data = make_shared<DifficultyLoadInfo>();
	Diff->Data->TimingInfo = Info.TimingInfo;

	// osu! stores bpm information as the time in ms that a beat lasts.
	Diff->BPMType = Difficulty::BT_BEATSPACE;
	Out->SongDirectory = prefix;

	Diff->Filename = filename;
	Out->SongDirectory = prefix + "/";

	/* 
		Just like BMS, osu!mania charts have timing data separated by files
		and a set is implied using folders.
	*/

	GString Line;

	getline(filein, Line);
	int version = -1;
	std::smatch sm;

	// "search" was picked instead of "match" since a line can have a bunch of 
	// junk before the version declaration
	if (regex_search(Line.cbegin(), Line.cend(), sm, versionfmt))
		version = atoi(sm[1].str().c_str());
	else
		throw std::exception("Invalid .osu file.");

	// "osu file format v"
	if (version < 10) // why
		throw std::exception(Utility::Format("Unsupported osu! file version (%d < 10)", version).c_str());

	Info.Version = version;

	osuReadingMode ReadingMode = RNotKnown, ReadingModeOld = RNotKnown;

	try {
		while (filein)
		{
			Info.Line++;
			getline(filein, Line);
			Utility::ReplaceAll(Line, "\r", "");

			if (!Line.length())
				continue;

			SetReadingMode(Line, ReadingMode);

			if (ReadingMode != ReadingModeOld || ReadingMode == RNotKnown) // Skip this line since it changed modes, or it's not a valid section yet
			{
				if (ReadingModeOld == RTiming)
					stable_sort(Info.HitsoundSections.begin(), Info.HitsoundSections.end());
				if (ReadingModeOld == RGeneral)
					if (!Info.ReadAModeTag)
						throw std::exception("Not an osu!mania chart.");
				ReadingModeOld = ReadingMode;
				continue;
			}

			switch (ReadingMode)
			{
			case RGeneral: 
				if (!ReadGeneral(Line, &Info))  // don't load charts that we can't work with
				{
					throw std::exception("osu! file unusable on raindrop.");
				}
						   break;
			case RMetadata: ReadMetadata(Line, &Info); break;
			case RDifficulty: ReadDifficulty(Line, &Info); break;
			case REvents: ReadEvents(Line, &Info); break;
			case RTiming: ReadTiming(Line, &Info); break;
			case RHitobjects: ReadObjects(Line, &Info); break;
			default: break;
			}
		}

		if (Diff->TotalObjects)
		{
			// Calculate an alleged offset
			Offsetize(&Info);

			// Okay then, convert timing data into a measure-based format raindrop can use.
			MeasurizeFromTimingData(&Info);

			CopyTimingData(&Info);

			// Then copy notes into these measures.
			PushNotesToMeasures(&Info);

			// Copy all sounds we registered
			for (auto i : Info.Sounds)
				Diff->SoundList[i.second] = i.first;

			// Calculate level as NPS
			Diff->Level = Diff->TotalScoringObjects / Diff->Duration;
			Out->Difficulties.push_back(Diff);
		}
	} catch (std::exception &e)
	{
		// rethrow with line info
		throw std::exception(Utility::Format("Line %d: %s", Info.Line, e.what()).c_str());
	}
}