You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

236 rivejä
6.1 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2018 Sam Hocevar <sam@hocevar.net>
  5. // © 2014—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
  6. //
  7. // Lol Engine is free software. It comes without any warranty, to
  8. // the extent permitted by applicable law. You can redistribute it
  9. // and/or modify it under the terms of the Do What the Fuck You Want
  10. // to Public License, Version 2, as published by the WTFPL Task Force.
  11. // See http://www.wtfpl.net/ for more details.
  12. //
  13. #include <lol/engine-internal.h>
  14. using namespace lol;
  15. //DefaultThreadManager --------------------------------------------------------
  16. void DefaultThreadManager::AddJob(ThreadJob* job)
  17. {
  18. DispatchJob(job);
  19. }
  20. bool DefaultThreadManager::GetWorkResult(array<ThreadJob*>& results)
  21. {
  22. results += m_job_result;
  23. m_job_result.clear();
  24. return results.count() > 0;
  25. }
  26. //FileUpdateTesterJob ---------------------------------------------------------
  27. class FileUpdateTesterJob : public ThreadJob
  28. {
  29. friend class FileUpdateTester;
  30. public:
  31. std::string GetName() const { return "<FileUpdateTesterJob>"; }
  32. FileUpdateTesterJob()
  33. : ThreadJob(ThreadJobType::NONE)
  34. {
  35. }
  36. FileUpdateTesterJob(std::string const &path)
  37. : ThreadJob(ThreadJobType::WORK_TODO),
  38. m_path(path)
  39. {
  40. }
  41. std::string const &GetPath() { return m_path; }
  42. long int GetTime() { return m_time; }
  43. bool HasUpdated() { return m_updated; }
  44. void Restart()
  45. {
  46. SetJobType(ThreadJobType::WORK_TODO);
  47. m_updated = false;
  48. }
  49. protected:
  50. virtual bool DoWork()
  51. {
  52. array<std::string> pathlist = sys::get_path_list(m_path);
  53. File f;
  54. for (auto const &path : pathlist)
  55. {
  56. f.Open(path, FileAccess::Read);
  57. if (f.IsValid())
  58. {
  59. long int new_time = f.GetModificationTime();
  60. if (!m_ready)
  61. {
  62. m_time = new_time;
  63. m_ready = true;
  64. }
  65. else if (new_time > m_time)
  66. {
  67. m_time = new_time;
  68. m_updated = true;
  69. }
  70. return true;
  71. }
  72. }
  73. return false;
  74. }
  75. //-----------------
  76. bool m_ready = false;
  77. std::string m_path;
  78. long int m_time = 0;
  79. bool m_updated = false;
  80. };
  81. //FileUpdateTester ------------------------------------------------------------
  82. FileUpdateTester::~FileUpdateTester()
  83. {
  84. ASSERT(!m_files.size(), "Files need to be unregistered before destroying FileUpdateTester");
  85. }
  86. //File interface --------------------------------------------------------------
  87. FileUpdateTester::Status* FileUpdateTester::RegisterFile(std::string const& path)
  88. {
  89. DispatchJob(new FileUpdateTesterJob(path));
  90. m_files[path] = new FileUpdateTester::Status();
  91. return m_files[path];
  92. }
  93. void FileUpdateTester::UnregisterFile(std::string const& path)
  94. {
  95. ASSERT(has_key(m_files, path));
  96. delete m_files[path];
  97. m_files.erase(path);
  98. }
  99. void FileUpdateTester::UnregisterFile(FileUpdateTester::Status*& status)
  100. {
  101. ASSERT(status);
  102. for (auto const &key : keys(m_files))
  103. {
  104. if (m_files[key] == status)
  105. {
  106. UnregisterFile(key);
  107. status = nullptr;
  108. return;
  109. }
  110. }
  111. ASSERT(false, "Status wasn't found");
  112. }
  113. //-----------------------------------------------------------------------------
  114. void FileUpdateTester::tick_game(float seconds)
  115. {
  116. // Reset update for this frame
  117. for (auto &kv : m_files)
  118. kv.second->SetUpdated(false);
  119. super::tick_game(seconds);
  120. if (!GetDispatchCount() && m_job_done.count())
  121. {
  122. if (m_frame_count++ < m_frame_skip)
  123. return;
  124. m_frame_count = 0;
  125. DispatchJob(m_job_done);
  126. m_job_done.clear();
  127. }
  128. }
  129. //-----------------------------------------------------------------------------
  130. void FileUpdateTester::TreatResult(ThreadJob* result)
  131. {
  132. FileUpdateTesterJob* job = static_cast<FileUpdateTesterJob*>(result);
  133. if (job->HasUpdated())
  134. {
  135. m_files[job->GetPath()]->SetTime(job->GetTime());
  136. m_files[job->GetPath()]->SetUpdated(true);
  137. }
  138. job->Restart();
  139. m_job_done << job;
  140. }
  141. //AsyncImageJob ---------------------------------------------------------------
  142. class AsyncImageJob : public ThreadJob
  143. {
  144. public:
  145. std::string GetName() const { return "<AsyncImageJob>"; }
  146. AsyncImageJob()
  147. : ThreadJob(ThreadJobType::NONE)
  148. {
  149. }
  150. AsyncImageJob(std::string const &path)
  151. : ThreadJob(ThreadJobType::WORK_TODO),
  152. m_path(path)
  153. {
  154. }
  155. std::string const& GetPath() { return m_path; }
  156. Image const& GetImage() { return m_image; }
  157. protected:
  158. virtual bool DoWork()
  159. {
  160. return m_image.load(m_path);
  161. }
  162. std::string m_path;
  163. Image m_image;
  164. };
  165. //-----------------------------------------------------------------------------
  166. Image* AsyncImageLoader::Load(std::string const &path)
  167. {
  168. //Create a job
  169. AsyncImageJob* job = new AsyncImageJob(path);
  170. //Create a dummy image
  171. Image* image = new Image(m_dummy_image);
  172. //Link the two
  173. m_images[path] = image;
  174. //Add job
  175. DispatchJob(job);
  176. //return Dummy image
  177. return image;
  178. }
  179. //-----------------------------------------------------------------------------
  180. bool AsyncImageLoader::CheckStatus(Image* image)
  181. {
  182. if (m_loaded_images.find(image) != INDEX_NONE)
  183. {
  184. m_loaded_images.remove_item(image);
  185. return true;
  186. }
  187. return false;
  188. }
  189. //-----------------------------------------------------------------------------
  190. void AsyncImageLoader::TreatResult(ThreadJob* result)
  191. {
  192. AsyncImageJob* job = dynamic_cast<AsyncImageJob*>(result);
  193. ASSERT(job);
  194. //Copy image if work is OK
  195. if (job->GetJobType() == ThreadJobType::WORK_SUCCEEDED)
  196. {
  197. Image* src = m_images[job->GetPath()];
  198. m_images.erase(job->GetPath());
  199. src->Copy(job->GetImage());
  200. m_loaded_images.push_unique(src);
  201. }
  202. else
  203. {
  204. msg::error("AsyncImageJob FAILED. See load image error above.\n");
  205. }
  206. //Delete all that
  207. delete(result);
  208. }