Asset.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. #include <Atomic/IO/Log.h>
  8. #include <Atomic/IO/File.h>
  9. #include <Atomic/IO/FileSystem.h>
  10. #include "../ToolSystem.h"
  11. #include "../Project/Project.h"
  12. #include "AssetDatabase.h"
  13. #include "AudioImporter.h"
  14. #include "ModelImporter.h"
  15. #include "FolderImporter.h"
  16. #include "SceneImporter.h"
  17. #include "MaterialImporter.h"
  18. #include "TextureImporter.h"
  19. #include "PrefabImporter.h"
  20. #include "JavascriptImporter.h"
  21. #include "JSONImporter.h"
  22. #include "SpriterImporter.h"
  23. #include "TMXImporter.h"
  24. #include "PEXImporter.h"
  25. #include "TextImporter.h"
  26. #include "NETAssemblyImporter.h"
  27. #include "TypeScriptImporter.h"
  28. #include "ParticleEffectImporter.h"
  29. #include "AssetEvents.h"
  30. #include "Asset.h"
  31. namespace ToolCore
  32. {
  33. Asset::Asset(Context* context) :
  34. Object(context),
  35. dirty_(false),
  36. isFolder_(false),
  37. fileTimestamp_(0xffffffff)
  38. {
  39. }
  40. Asset::~Asset()
  41. {
  42. }
  43. void Asset::UpdateFileTimestamp()
  44. {
  45. FileSystem* fs = GetSubsystem<FileSystem>();
  46. if (fs->FileExists(path_))
  47. {
  48. fileTimestamp_ = fs->GetLastModifiedTime(path_);
  49. }
  50. }
  51. Asset* Asset::GetParent()
  52. {
  53. AssetDatabase* db = GetSubsystem<AssetDatabase>();
  54. String pathName;
  55. String fileName;
  56. String ext;
  57. SplitPath(path_, pathName, fileName, ext);
  58. return db->GetAssetByPath(RemoveTrailingSlash(pathName));
  59. }
  60. String Asset::GetRelativePath()
  61. {
  62. Project* project =GetSubsystem<ToolSystem>()->GetProject();
  63. String path = path_;
  64. path.Replace(project->GetResourcePath(), "", false);
  65. return path;
  66. }
  67. bool Asset::CheckCacheFile()
  68. {
  69. if (importer_.Null())
  70. return true;
  71. FileSystem* fs = GetSubsystem<FileSystem>();
  72. AssetDatabase* db = GetSubsystem<AssetDatabase>();
  73. String cachePath = db->GetCachePath();
  74. String cacheFile = cachePath + guid_;
  75. unsigned modifiedTime = fs->GetLastModifiedTime(path_);
  76. if (importer_->RequiresCacheFile()) {
  77. if (!fs->FileExists(cacheFile) || fs->GetLastModifiedTime(cacheFile) < modifiedTime)
  78. return false;
  79. }
  80. if (fs->GetLastModifiedTime(GetDotAssetFilename()) < modifiedTime)
  81. {
  82. return false;
  83. }
  84. return true;
  85. }
  86. bool Asset::Import()
  87. {
  88. if (importer_.Null())
  89. return true;
  90. return importer_->Import();
  91. }
  92. bool Asset::Preload()
  93. {
  94. if (importer_.Null())
  95. return true;
  96. // disabled preload for now, as this is on a background thread and causing init problems
  97. return true;
  98. //return importer_->Preload();
  99. }
  100. void Asset::PostImportError(const String& message)
  101. {
  102. VariantMap eventData;
  103. eventData[AssetImportError::P_PATH] = path_;
  104. eventData[AssetImportError::P_GUID] = guid_;
  105. eventData[AssetImportError::P_ERROR] = message;
  106. SendEvent(E_ASSETIMPORTERROR, eventData);
  107. }
  108. // load .asset
  109. bool Asset::Load()
  110. {
  111. FileSystem* fs = GetSubsystem<FileSystem>();
  112. AssetDatabase* db = GetSubsystem<AssetDatabase>();
  113. String assetFilename = GetDotAssetFilename();
  114. SharedPtr<File> file(new File(context_, assetFilename));
  115. json_ = new JSONFile(context_);
  116. json_->Load(*file);
  117. file->Close();
  118. JSONValue root = json_->GetRoot();
  119. assert(root.Get("version").GetInt() == ASSET_VERSION);
  120. guid_ = root.Get("guid").GetString();
  121. db->RegisterGUID(guid_);
  122. dirty_ = false;
  123. if (!CheckCacheFile())
  124. {
  125. LOGINFOF("CheckCacheFile:false - %s", path_.CString());
  126. dirty_ = true;
  127. }
  128. // handle import
  129. if (importer_.NotNull())
  130. importer_->LoadSettings(root);
  131. json_ = 0;
  132. return true;
  133. }
  134. // save .asset
  135. bool Asset::Save()
  136. {
  137. FileSystem* fs = GetSubsystem<FileSystem>();
  138. String assetFilename = GetDotAssetFilename();
  139. json_ = new JSONFile(context_);
  140. JSONValue& root = json_->GetRoot();
  141. root.Set("version", JSONValue(ASSET_VERSION));
  142. root.Set("guid", JSONValue(guid_));
  143. // handle import
  144. if (importer_.NotNull())
  145. {
  146. importer_->SaveSettings(root);
  147. SharedPtr<File> file(new File(context_, assetFilename, FILE_WRITE));
  148. json_->Save(*file);
  149. file->Close();
  150. }
  151. json_ = 0;
  152. return true;
  153. }
  154. String Asset::GetDotAssetFilename()
  155. {
  156. assert(path_.Length());
  157. FileSystem* fs = GetSubsystem<FileSystem>();
  158. String assetFilename = path_ + ".asset";
  159. if (fs->DirExists(path_)) {
  160. assetFilename = RemoveTrailingSlash(path_) + ".asset";
  161. }
  162. return assetFilename;
  163. }
  164. bool Asset::CreateImporter()
  165. {
  166. assert(importer_.Null());
  167. FileSystem* fs = GetSubsystem<FileSystem>();
  168. if (fs->DirExists(path_))
  169. {
  170. name_ = GetFileName(RemoveTrailingSlash(path_));
  171. isFolder_ = true;
  172. importer_ = new FolderImporter(context_, this);
  173. }
  174. else
  175. {
  176. String ext = Atomic::GetExtension(path_);
  177. name_ = GetFileName(path_);
  178. Vector<String> textureFormats;
  179. textureFormats.Push(".jpg");
  180. textureFormats.Push(".png");
  181. textureFormats.Push(".tga");
  182. textureFormats.Push(".dds");
  183. // todo, externalize recognizers
  184. if (ext == ".fbx" || ext == ".blend" || ext == ".dae" || ext == ".mdl")
  185. {
  186. importer_ = new ModelImporter(context_, this);
  187. }
  188. if (ext == ".ogg" || ext == ".wav")
  189. {
  190. importer_ = new AudioImporter(context_, this);
  191. }
  192. else if (ext == ".prefab")
  193. {
  194. importer_ = new PrefabImporter(context_, this);
  195. }
  196. else if (ext == ".js")
  197. {
  198. importer_ = new JavascriptImporter(context_, this);
  199. }
  200. else if (ext == ".ts")
  201. {
  202. importer_ = new TypeScriptImporter(context_, this);
  203. }
  204. else if (ext == ".json")
  205. {
  206. importer_ = new JSONImporter(context_, this);
  207. }
  208. else if (ext == ".scene")
  209. {
  210. importer_ = new SceneImporter(context_, this);
  211. }
  212. else if (ext == ".material")
  213. {
  214. importer_ = new MaterialImporter(context_, this);
  215. }
  216. else if (ext == ".scml")
  217. {
  218. importer_ = new SpriterImporter(context_, this);
  219. }
  220. else if (ext == ".tmx")
  221. {
  222. importer_ = new TMXImporter(context_, this);
  223. }
  224. else if (ext == ".pex")
  225. {
  226. importer_ = new PEXImporter(context_, this);
  227. }
  228. else if (ext == ".peffect")
  229. {
  230. importer_ = new ParticleEffectImporter(context_, this);
  231. }
  232. else if (ext == ".txt")
  233. {
  234. importer_ = new TextImporter(context_, this);
  235. }
  236. else if (ext == ".dll")
  237. {
  238. // TODO: check for native dll
  239. #ifdef ATOMIC_DOTNET
  240. importer_ = new NETAssemblyImporter(context_, this);
  241. #endif
  242. }
  243. else if (textureFormats.Contains(ext))
  244. {
  245. importer_ = new TextureImporter(context_, this);
  246. }
  247. }
  248. if (importer_.Null())
  249. return false;
  250. return true;
  251. }
  252. String Asset::GetCachePath() const
  253. {
  254. AssetDatabase* db = GetSubsystem<AssetDatabase>();
  255. String cachePath = db->GetCachePath();
  256. cachePath += guid_;
  257. return cachePath;
  258. }
  259. String Asset::GetExtension() const
  260. {
  261. return Atomic::GetExtension(path_);
  262. }
  263. bool Asset::SetPath(const String& path)
  264. {
  265. assert(!guid_.Length());
  266. assert(!path_.Length());
  267. // need to update path, not set, which should only be done on first import
  268. assert(importer_.Null());
  269. FileSystem* fs = GetSubsystem<FileSystem>();
  270. AssetDatabase* db = GetSubsystem<AssetDatabase>();
  271. path_ = path;
  272. // create importer based on path
  273. if (!CreateImporter())
  274. return false;
  275. String assetFilename = GetDotAssetFilename();
  276. if (fs->FileExists(assetFilename))
  277. {
  278. // load the json, todo: handle fail
  279. Load();
  280. }
  281. else
  282. {
  283. dirty_ = true;
  284. guid_ = db->GenerateAssetGUID();
  285. Save();
  286. }
  287. // TODO: handle failed
  288. return true;
  289. }
  290. bool Asset::Move(const String& newPath)
  291. {
  292. if (importer_.Null())
  293. return false;
  294. String oldPath = path_;
  295. bool result = importer_->Move(newPath);
  296. if (result)
  297. {
  298. VariantMap eventData;
  299. eventData[AssetMoved::P_ASSET] = this;
  300. eventData[AssetMoved::P_OLDPATH] = oldPath;
  301. SendEvent(E_ASSETMOVED, eventData);
  302. }
  303. return result;
  304. }
  305. bool Asset::Rename(const String& newName)
  306. {
  307. if (importer_.Null())
  308. return false;
  309. bool result = importer_->Rename(newName);
  310. if (result)
  311. {
  312. VariantMap eventData;
  313. eventData[AssetRenamed::P_ASSET] = this;
  314. SendEvent(E_ASSETRENAMED, eventData);
  315. }
  316. return result;
  317. }
  318. Resource* Asset::GetResource(const String &typeName)
  319. {
  320. if (importer_)
  321. return importer_->GetResource(typeName);
  322. return 0;
  323. }
  324. Node* Asset::InstantiateNode(Node* parent, const String& name)
  325. {
  326. if (!parent)
  327. return 0;
  328. if (importer_)
  329. return importer_->InstantiateNode(parent, name);
  330. return 0;
  331. }
  332. }