Exemple #1
0
std::shared_ptr<VSRG::Song> SongLoader::LoadFromMeta(const VSRG::Song* Meta, std::shared_ptr<VSRG::Difficulty> &CurrentDiff, std::filesystem::path &FilenameOut, uint8_t &Index)
{
    std::shared_ptr<VSRG::Song> Out;

    std::filesystem::path fn = DB->GetDifficultyFilename(CurrentDiff->ID);
    FilenameOut = fn;

    Out = LoadSong7KFromFilename(fn, "", nullptr);
    if (!Out) return nullptr;

    // Copy relevant data
    Out->SongDirectory = Meta->SongDirectory;

    Index = 0;
    /* Find out Difficulty IDs to the recently loaded song's difficulty! */
    bool DifficultyFound = false;
    for (auto k : Out->Difficulties)
    {
        DB->AddDifficulty(Meta->ID, k->Filename, k.get(), MODE_VSRG);
        if (k->ID == CurrentDiff->ID) // We've got a match; move onward.
        {
            CurrentDiff = k;
            DifficultyFound = true;
            break; // We're done here, we've found the difficulty we were trying to load
        }
        Index++;
    }

    if (!DifficultyFound)
        return nullptr;

    return Out;
}
Exemple #2
0
void Application::Run()
{
	double T1 = glfwGetTime();
	bool RunLoop = true;

	if (RunMode == MODE_PLAY)
	{
		Game = new ScreenMainMenu(NULL);
		((ScreenMainMenu*)Game)->Init();

	}else if (RunMode == MODE_VSRGPREVIEW)
	{
		Game = new ScreenGameplay7K();
		VSRG::Song* Sng = LoadSong7KFromFilename(InFile.path(), InFile.ParentDirectory().path(), NULL);
		((ScreenGameplay7K*)Game)->Init (Sng, difIndex, Upscroll);
	}else if (RunMode == MODE_CONVERT)
	{
		VSRG::Song* Sng = LoadSong7KFromFilename(InFile.Filename().path(), InFile.ParentDirectory().path(), NULL);

		if (Sng) 
		{
		// if (ConvertMode == CONV_OM) // for now this is the default
			ConvertToOM (Sng, OutFile.path(), Author);
		}

		RunLoop = false;
	}else if (RunMode == MODE_GENCACHE)
	{
		std::vector<VSRG::Song*> Songs;

		GameState::Printf("Generating cache...\n");

		std::vector<String> Directories;
		Configuration::GetConfigListS("SongDirectories", Directories);

		for (std::vector<String>::iterator i = Directories.begin(); 
			i != Directories.end();
			i++)
		{
			FileManager::GetSongList7K(Songs, *i);
		}

		for (std::vector<VSRG::Song*>::iterator i = Songs.begin(); i != Songs.end(); i++)
			delete *i;

		RunLoop = false;
	}

	GameState::Printf("Time: %fs\n", glfwGetTime() - T1);

	if (!RunLoop)
		return;

	while (Game->IsScreenRunning() && !WindowFrame.ShouldCloseWindow())
	{
		double newTime = glfwGetTime();
		double delta = newTime - oldTime;
		ImageLoader::UpdateTextures();

		WindowFrame.ClearWindow();

		Game->Run(delta);

		MixerUpdate();
		WindowFrame.SwapBuffers();
		oldTime = newTime;
	}
}
Exemple #3
0
void SongLoader::LoadSong7KFromDir(std::filesystem::path songPath, std::vector<VSRG::Song*> &VecOut)
{
	if (!std::filesystem::is_directory(songPath))
		return;

    std::vector<std::filesystem::path> Listing = Utility::GetFileListing(songPath);
    std::filesystem::path SongDirectory = std::filesystem::absolute(songPath);

    /*
        Procedure:
        1.- Check all files if cache needs to be renewed or created.
        2.- If it needs to, load the song again.
        3.- If it loaded the song for either reason, rewrite the difficulty cache.
        4.- If it does not need to be renewed or created, just read the metadata and leave it like that.
    */

    bool RenewCache = false;

    /*
        We want the following:
        All BMS must be packed together.
        All osu!mania charts must be packed together.
        OJNs must be their own chart.
        SMs must be their own chart. (And SSCs have priority if more loaders are supported later)
        All FCFs to be grouped together

        Therefore; it's not the song directory which we check, but the difficulties' files.
    */

    /* First we need to see whether these file need to be renewed.*/
    for (auto i = Listing.begin(); i != Listing.end(); ++i)
    {
        auto File = *i;
        std::wstring Ext = File.extension().wstring();

        /*
            Some people leave nameless, blank .bms files on their folder.
            This causes the cache to do a full reload, so we check if
            we should just ignore this file.
            It'll be loaded in any case, but not considered for cache.
        */
        std::string Fname = File.filename().string();

		if (VSRGValidExtension(Ext) &&
			Fname.length() &&
			DB->CacheNeedsRenewal(File))
				RenewCache = true;
    }

    // Files were modified- we have to reload the charts.
    if (RenewCache)
    {
		CfgVar NoFileGrouping("NoFileGrouping");
        // First, pack BMS charts together.
        std::map<std::string, VSRG::Song*> bmsk;
        VSRG::Song *BMSSong = new VSRG::Song;

        // Every OJN gets its own Song object.
        VSRG::Song *OJNSong = new VSRG::Song;
        OJNSong->SongDirectory = SongDirectory;

        // osu!mania charts are packed together, with FTB charts.
        VSRG::Song *osuSong = new VSRG::Song;
        osuSong->SongDirectory = SongDirectory;

        // Stepmania charts get their own song objects too.
        VSRG::Song *smSong = new VSRG::Song;
        smSong->SongDirectory = SongDirectory;

        for (auto File : Listing)
        {
            std::wstring Ext = File.extension().wstring();
			File = File.filename();

            // We want to group charts with the same title together.
            if (ValidBMSExtension(Ext) || Ext == L".bmson")
            {
                BMSSong->SongDirectory = SongDirectory;

                try
                {
                    LoadSong7KFromFilename(File, SongDirectory, BMSSong);
                }
                catch (std::exception &ex)
                {
                    Log::Logf("\nSongLoader::LoadSong7KFromDir(): Exception \"%s\" occurred while loading file \"%s\"\n",
                        ex.what(), File.filename().c_str());
                    Utility::DebugBreak();
                }

                // We found a chart with the same title (and subtitle) already.

				if (!NoFileGrouping) {
					std::string key;
					if (Configuration::GetConfigf("SeparateBySubtitle"))
						key = BMSSong->SongName + BMSSong->Subtitle;
					else
						key = BMSSong->SongName;

					if (bmsk.find(key) != bmsk.end())
					{
						VSRG::Song *oldSng = bmsk[key];

						if (BMSSong->Difficulties.size()) // BMS charts don't have more than one difficulty anyway.
							oldSng->Difficulties.push_back(BMSSong->Difficulties[0]);

						BMSSong->Difficulties.clear();
						delete BMSSong;
					}
					else // Ah then, don't delete it.
					{
						bmsk[key] = BMSSong;
					}

					BMSSong = new VSRG::Song;
				} else
				{
					VSRGUpdateDatabaseDifficulties(DB, BMSSong);
					PushVSRGSong(VecOut, BMSSong);
					BMSSong = new VSRG::Song;
				}
            }

            if (Ext == L".ojn")
            {
                LoadSong7KFromFilename(File, SongDirectory, OJNSong);
                VSRGUpdateDatabaseDifficulties(DB, OJNSong);
                PushVSRGSong(VecOut, OJNSong);
                OJNSong = new VSRG::Song;
                OJNSong->SongDirectory = SongDirectory;
            }

            if (Ext == L".osu" || Ext == L".fcf")
                LoadSong7KFromFilename(File, SongDirectory, osuSong);

            if (Ext == L".sm" || Ext == L".ssc")
            {
                LoadSong7KFromFilename(File, SongDirectory, smSong);
                VSRGUpdateDatabaseDifficulties(DB, smSong);
                PushVSRGSong(VecOut, smSong);
                smSong = new VSRG::Song;
                smSong->SongDirectory = SongDirectory;
            }
        }

        // PushVSRGSong() handles the cleanup.
        for (auto i = bmsk.begin();
        i != bmsk.end(); ++i)
        {
            VSRGUpdateDatabaseDifficulties(DB, i->second);
            PushVSRGSong(VecOut, i->second);
        }

        VSRGUpdateDatabaseDifficulties(DB, OJNSong);
        PushVSRGSong(VecOut, OJNSong);

        VSRGUpdateDatabaseDifficulties(DB, osuSong);
        PushVSRGSong(VecOut, osuSong);

        VSRGUpdateDatabaseDifficulties(DB, smSong);
        PushVSRGSong(VecOut, smSong);
    }
    else // We can reload from cache. We do this on a per-file basis.
    {
        // We need to get the song IDs for every file; it's guaranteed that they exist, in theory.
        int ID = -1;
        std::vector<int> IDList;

        for (auto File : Listing)
        {
            std::wstring Ext = File.extension().wstring();
            if (VSRGValidExtension(Ext))
            {
                int CurrentID = DB->GetSongIDForFile(File, nullptr);
                if (CurrentID != ID)
                {
                    ID = CurrentID;
                    IDList.push_back(ID);
                }
            }
        }

        // So now we have our list with song IDs that are present on the current directory.
        // Time to load from cache.
        for (auto i = IDList.begin();
        i != IDList.end();
            ++i)
        {
            VSRG::Song *New = new VSRG::Song;
            Log::Logf("Song ID %d load from cache...", *i);
			try {
				DB->GetSongInformation7K(*i, New);
				New->SongDirectory = SongDirectory;

				PushVSRGSong(VecOut, New);
				Log::Logf(" ok\n");
			}
			catch (std::exception &e) {
				Log::Logf("Error loading from cache: %s\n", e.what());
			}
        }
    }
}
Exemple #4
0
#include "pch.h"
#include "../src/GameGlobal.h"
#include "../src/Song.h"
#include "../src/SongDC.h"
#include "../src/Song7K.h"
#include "../src/SongLoader.h"
#include "../src/BackgroundAnimation.h"

#include "../src/Logging.h"
#include "../src/ext/catch.hpp"

/*
	So much of the testing was already done by debugging the main .exe
	further new code will comply for use in test-driven development (2016-05-23)
	but for now I'll use this to make debugging easier. -az
*/

TEST_CASE("osu storyboard compliance")
{
	Interruptible stub;
	auto song = LoadSong7KFromFilename("tests/files/esb.osu");
	
	REQUIRE(song != nullptr);
	REQUIRE(song->Difficulties.size() != 0);

	Log::Printf("Loading BGA...\n");
	auto bga = BackgroundAnimation::CreateBGAFromSong(0, *song, &stub, true);

	bga->SetAnimationTime(65.0f);
}