bool ReadGeneral (GString line, OsuLoadInfo* Info) { GString Command = line.substr(0, line.find_first_of(" ")); // Lines are Information:<space>Content GString Content = line.substr(line.find_first_of(":") + 1); Content = Content.substr(Content.find_first_not_of(" ")); if (Command == "AudioFilename:") { if (Content == "virtual") { Info->Diff->IsVirtual = true; return true; } else { #ifdef VERBOSE_DEBUG printf("Audio filename found: %s\n", Content.c_str()); #endif Utility::Trim(Content); Info->OsuSong->SongFilename = Content; Info->OsuSong->SongPreviewSource = Content; } }else if (Command == "Mode:") { Info->ReadAModeTag = true; if (Content != "3") // It's not a osu!mania chart, so we can't use it. return false; }else if (Command == "SampleSet:") { Utility::ToLower(Content); Utility::Trim(Content); Info->DefaultSampleset = Content; } else if (Command == "PreviewTime:") { if (Content != "-1") { if (Info->OsuSong->PreviewTime == 0) Info->OsuSong->PreviewTime = latof(Content) / 1000; } } else if (Command == "SpecialStyle:") { if (Content == "1") Info->Diff->Data->Turntable = true; } return true; }
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; }