// // Lol Engine // // Copyright © 2010—2018 Sam Hocevar // © 2014—2015 Benjamin “Touky” Huet // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #include using namespace lol; //DefaultThreadManager -------------------------------------------------------- void DefaultThreadManager::AddJob(ThreadJob* job) { DispatchJob(job); } bool DefaultThreadManager::GetWorkResult(array& results) { results += m_job_result; m_job_result.clear(); return results.count() > 0; } //FileUpdateTesterJob --------------------------------------------------------- class FileUpdateTesterJob : public ThreadJob { friend class FileUpdateTester; public: std::string GetName() const { return ""; } FileUpdateTesterJob() : ThreadJob(ThreadJobType::NONE) { } FileUpdateTesterJob(std::string const &path) : ThreadJob(ThreadJobType::WORK_TODO), m_path(path) { } std::string const &GetPath() { return m_path; } long int GetTime() { return m_time; } bool HasUpdated() { return m_updated; } void Restart() { SetJobType(ThreadJobType::WORK_TODO); m_updated = false; } protected: virtual bool DoWork() { array pathlist = sys::get_path_list(m_path); File f; for (auto const &path : pathlist) { f.Open(path, FileAccess::Read); if (f.IsValid()) { long int new_time = f.GetModificationTime(); if (!m_ready) { m_time = new_time; m_ready = true; } else if (new_time > m_time) { m_time = new_time; m_updated = true; } return true; } } return false; } //----------------- bool m_ready = false; std::string m_path; long int m_time = 0; bool m_updated = false; }; //FileUpdateTester ------------------------------------------------------------ FileUpdateTester::~FileUpdateTester() { ASSERT(!m_files.size(), "Files need to be unregistered before destroying FileUpdateTester"); } //File interface -------------------------------------------------------------- FileUpdateTester::Status* FileUpdateTester::RegisterFile(std::string const& path) { DispatchJob(new FileUpdateTesterJob(path)); m_files[path] = new FileUpdateTester::Status(); return m_files[path]; } void FileUpdateTester::UnregisterFile(std::string const& path) { ASSERT(has_key(m_files, path)); delete m_files[path]; m_files.erase(path); } void FileUpdateTester::UnregisterFile(FileUpdateTester::Status*& status) { ASSERT(status); for (auto const &key : keys(m_files)) { if (m_files[key] == status) { UnregisterFile(key); status = nullptr; return; } } ASSERT(false, "Status wasn't found"); } //----------------------------------------------------------------------------- void FileUpdateTester::tick_game(float seconds) { // Reset update for this frame for (auto &kv : m_files) kv.second->SetUpdated(false); super::tick_game(seconds); if (!GetDispatchCount() && m_job_done.count()) { if (m_frame_count++ < m_frame_skip) return; m_frame_count = 0; DispatchJob(m_job_done); m_job_done.clear(); } } //----------------------------------------------------------------------------- void FileUpdateTester::TreatResult(ThreadJob* result) { FileUpdateTesterJob* job = static_cast(result); if (job->HasUpdated()) { m_files[job->GetPath()]->SetTime(job->GetTime()); m_files[job->GetPath()]->SetUpdated(true); } job->Restart(); m_job_done << job; } //AsyncImageJob --------------------------------------------------------------- class AsyncImageJob : public ThreadJob { public: std::string GetName() const { return ""; } AsyncImageJob() : ThreadJob(ThreadJobType::NONE) { } AsyncImageJob(std::string const &path) : ThreadJob(ThreadJobType::WORK_TODO), m_path(path) { } std::string const& GetPath() { return m_path; } Image const& GetImage() { return m_image; } protected: virtual bool DoWork() { return m_image.load(m_path); } std::string m_path; Image m_image; }; //----------------------------------------------------------------------------- Image* AsyncImageLoader::Load(std::string const &path) { //Create a job AsyncImageJob* job = new AsyncImageJob(path); //Create a dummy image Image* image = new Image(m_dummy_image); //Link the two m_images[path] = image; //Add job DispatchJob(job); //return Dummy image return image; } //----------------------------------------------------------------------------- bool AsyncImageLoader::CheckStatus(Image* image) { if (m_loaded_images.find(image) != INDEX_NONE) { m_loaded_images.remove_item(image); return true; } return false; } //----------------------------------------------------------------------------- void AsyncImageLoader::TreatResult(ThreadJob* result) { AsyncImageJob* job = dynamic_cast(result); ASSERT(job); //Copy image if work is OK if (job->GetJobType() == ThreadJobType::WORK_SUCCEEDED) { Image* src = m_images[job->GetPath()]; m_images.erase(job->GetPath()); src->Copy(job->GetImage()); m_loaded_images.push_unique(src); } else { msg::error("AsyncImageJob FAILED. See load image error above.\n"); } //Delete all that delete(result); }