ModelImporter.cpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. #include <Atomic/Core/ProcessUtils.h>
  2. #include <Atomic/IO/Log.h>
  3. #include <Atomic/IO/File.h>
  4. #include <Atomic/IO/FileSystem.h>
  5. #include <Atomic/Scene/Node.h>
  6. #include <Atomic/Atomic3D/AnimatedModel.h>
  7. #include <Atomic/Atomic3D/Animation.h>
  8. #include <Atomic/Atomic3D/StaticModel.h>
  9. #include <Atomic/Atomic3D/Model.h>
  10. #include <Atomic/Resource/ResourceCache.h>
  11. #include <Atomic/Resource/XMLFile.h>
  12. #include "../Import/OpenAssetImporter.h"
  13. #include "Asset.h"
  14. #include "AssetDatabase.h"
  15. #include "ModelImporter.h"
  16. namespace ToolCore
  17. {
  18. /// Node + Model (static or animated)
  19. ModelImporter::ModelImporter(Context* context, Asset *asset) : AssetImporter(context, asset)
  20. {
  21. SetDefaults();
  22. }
  23. ModelImporter::~ModelImporter()
  24. {
  25. }
  26. void ModelImporter::SetDefaults()
  27. {
  28. AssetImporter::SetDefaults();
  29. scale_ = 1.0f;
  30. importAnimations_ = false;
  31. animationInfo_.Clear();
  32. }
  33. bool ModelImporter::ImportModel()
  34. {
  35. LOGDEBUGF("Importing Model: %s", asset_->GetPath().CString());
  36. SharedPtr<OpenAssetImporter> importer(new OpenAssetImporter(context_));
  37. importer->SetVerboseLog(true);
  38. importer->SetScale(scale_);
  39. importer->SetExportAnimations(false);
  40. importer->SetImportNode(importNode_);
  41. if (importer->Load(asset_->GetPath()))
  42. {
  43. importer->ExportModel(asset_->GetCachePath());
  44. return true;
  45. }
  46. else
  47. {
  48. asset_->PostImportError(importer->GetErrorMessage());
  49. }
  50. return false;
  51. }
  52. bool ModelImporter::ImportAnimation(const String& filename, const String& name, float startTime, float endTime)
  53. {
  54. SharedPtr<OpenAssetImporter> importer(new OpenAssetImporter(context_));
  55. //importer->SetVerboseLog(true);
  56. importer->SetScale(scale_);
  57. importer->SetExportAnimations(true);
  58. importer->SetStartTime(startTime);
  59. importer->SetEndTime(endTime);
  60. if (importer->Load(filename))
  61. {
  62. importer->ExportModel(asset_->GetCachePath(), name, true);
  63. const Vector<OpenAssetImporter::AnimationInfo>& infos = importer->GetAnimationInfos();
  64. for (unsigned i = 0; i < infos.Size(); i++)
  65. {
  66. const OpenAssetImporter::AnimationInfo& info = infos.At(i);
  67. String pathName, fileName, extension;
  68. SplitPath(info.cacheFilename_, pathName, fileName, extension);
  69. ResourceCache* cache = GetSubsystem<ResourceCache>();
  70. AnimatedModel* animatedModel = importNode_->GetComponent<AnimatedModel>();
  71. if (animatedModel)
  72. {
  73. Model* model = animatedModel->GetModel();
  74. if (model)
  75. {
  76. SharedPtr<Animation> animation = cache->GetTempResource<Animation>(fileName + extension);
  77. if (animation)
  78. model->AddAnimationResource(animation);
  79. }
  80. }
  81. LOGINFOF("Import Info: %s : %s", info.name_.CString(), fileName.CString());
  82. }
  83. return true;
  84. }
  85. return false;
  86. }
  87. bool ModelImporter::ImportAnimations()
  88. {
  89. if (!animationInfo_.Size())
  90. {
  91. if (!ImportAnimation(asset_->GetPath(), "RootAnim"))
  92. return false;
  93. }
  94. // embedded animations
  95. for (unsigned i = 0; i < animationInfo_.Size(); i++)
  96. {
  97. const SharedPtr<AnimationImportInfo>& info = animationInfo_[i];
  98. if (!ImportAnimation(asset_->GetPath(), info->GetName(), info->GetStartTime(), info->GetEndTime()))
  99. return false;
  100. }
  101. // add @ animations
  102. FileSystem* fs = GetSubsystem<FileSystem>();
  103. String pathName, fileName, ext;
  104. SplitPath(asset_->GetPath(), pathName, fileName, ext);
  105. Vector<String> results;
  106. fs->ScanDir(results, pathName, ext, SCAN_FILES, false);
  107. for (unsigned i = 0; i < results.Size(); i++)
  108. {
  109. const String& result = results[i];
  110. if (result.Contains("@"))
  111. {
  112. Vector<String> components = GetFileName(result).Split('@');
  113. if (components.Size() == 2 && components[1].Length() && components[0] == fileName)
  114. {
  115. String animationName = components[1];
  116. AssetDatabase* db = GetSubsystem<AssetDatabase>();
  117. Asset* asset = db->GetAssetByPath(pathName + result);
  118. assert(asset);
  119. assert(asset->GetImporter()->GetType() == ModelImporter::GetTypeStatic());
  120. ModelImporter* importer = (ModelImporter*) asset->GetImporter();
  121. if (!importer->animationInfo_.Size())
  122. {
  123. if (!ImportAnimation(asset->GetPath(), animationName))
  124. return false;
  125. }
  126. else
  127. {
  128. // embedded animations
  129. for (unsigned i = 0; i < importer->animationInfo_.Size(); i++)
  130. {
  131. const SharedPtr<AnimationImportInfo>& info = importer->animationInfo_[i];
  132. if (!ImportAnimation(asset->GetPath(), info->GetName(), info->GetStartTime(), info->GetEndTime()))
  133. return false;
  134. }
  135. }
  136. }
  137. }
  138. }
  139. return true;
  140. }
  141. bool ModelImporter::Import()
  142. {
  143. String ext = asset_->GetExtension();
  144. String modelAssetFilename = asset_->GetPath();
  145. importNode_ = new Node(context_);
  146. if (ext == ".mdl")
  147. {
  148. FileSystem* fs = GetSubsystem<FileSystem>();
  149. ResourceCache* cache = GetSubsystem<ResourceCache>();
  150. // mdl files are native file format that doesn't need to be converted
  151. // doesn't allow scale, animations legacy primarily for ToonTown
  152. if (!fs->Copy(asset_->GetPath(), asset_->GetCachePath() + ".mdl"))
  153. {
  154. importNode_= 0;
  155. return false;
  156. }
  157. Model* mdl = cache->GetResource<Model>( asset_->GetCachePath() + ".mdl");
  158. if (!mdl)
  159. {
  160. importNode_= 0;
  161. return false;
  162. }
  163. // Force a reload, though file watchers will catch this delayed and load again
  164. cache->ReloadResource(mdl);
  165. importNode_->CreateComponent<StaticModel>()->SetModel(mdl);
  166. }
  167. else
  168. {
  169. // skip external animations, they will be brought in when importing their
  170. // corresponding model
  171. if (!modelAssetFilename.Contains("@"))
  172. {
  173. ImportModel();
  174. if (importAnimations_)
  175. {
  176. ImportAnimations();
  177. }
  178. AnimatedModel* animatedModel = importNode_->GetComponent<AnimatedModel>();
  179. if (animatedModel)
  180. {
  181. Model* model = animatedModel->GetModel();
  182. if (model && model->GetAnimationCount())
  183. {
  184. // resave with animation info
  185. File mdlFile(context_);
  186. if (!mdlFile.Open(asset_->GetCachePath() + ".mdl", FILE_WRITE))
  187. {
  188. ErrorExit("Could not open output file " + asset_->GetCachePath() + ".mdl");
  189. return false;
  190. }
  191. model->Save(mdlFile);
  192. }
  193. }
  194. }
  195. }
  196. File outFile(context_);
  197. if (!outFile.Open(asset_->GetCachePath(), FILE_WRITE))
  198. ErrorExit("Could not open output file " + asset_->GetCachePath());
  199. importNode_->SaveXML(outFile);
  200. importNode_ = 0;
  201. return true;
  202. }
  203. unsigned ModelImporter::GetAnimationCount()
  204. {
  205. return animationInfo_.Size();
  206. }
  207. void ModelImporter::SetAnimationCount(unsigned count)
  208. {
  209. if (animationInfo_.Size() >= count)
  210. {
  211. animationInfo_.Resize(count);
  212. }
  213. else
  214. {
  215. for (unsigned i = animationInfo_.Size(); i < count; i++)
  216. {
  217. SharedPtr<AnimationImportInfo> info(new AnimationImportInfo(context_));
  218. animationInfo_.Push(info);
  219. }
  220. }
  221. }
  222. bool ModelImporter::LoadSettingsInternal()
  223. {
  224. if (!AssetImporter::LoadSettingsInternal())
  225. return false;
  226. JSONValue import = jsonRoot_.GetChild("ModelImporter", JSON_OBJECT);
  227. SetDefaults();
  228. if (import.HasMember("scale"))
  229. scale_ = import.GetFloat("scale");
  230. if (import.HasMember("importAnimations"))
  231. importAnimations_ = import.GetBool("importAnimations");
  232. if (import.HasMember("animInfo"))
  233. {
  234. JSONValue animInfo = import.GetChild("animInfo");
  235. for (unsigned i = 0; i < animInfo.GetSize(); i++)
  236. {
  237. JSONValue anim = animInfo.GetChild(i);
  238. SharedPtr<AnimationImportInfo> info(new AnimationImportInfo(context_));
  239. info->name_ = anim.GetString("name");
  240. info->SetStartTime(anim.GetFloat("startTime"));
  241. info->SetEndTime(anim.GetFloat("endTime"));
  242. animationInfo_.Push(info);
  243. }
  244. }
  245. return true;
  246. }
  247. bool ModelImporter::SaveSettingsInternal()
  248. {
  249. if (!AssetImporter::SaveSettingsInternal())
  250. return false;
  251. JSONValue save = jsonRoot_.CreateChild("ModelImporter");
  252. save.SetFloat("scale", scale_);
  253. save.SetBool("importAnimations", importAnimations_);
  254. JSONValue animInfo = save.CreateChild("animInfo", JSON_ARRAY);
  255. for (unsigned i = 0; i < animationInfo_.Size(); i++)
  256. {
  257. const SharedPtr<AnimationImportInfo>& info = animationInfo_[i];
  258. JSONValue jinfo = animInfo.CreateChild();
  259. jinfo.SetString("name", info->GetName());
  260. jinfo.SetFloat("startTime", info->GetStartTime());
  261. jinfo.SetFloat("endTime", info->GetEndTime());
  262. }
  263. return true;
  264. }
  265. Resource* ModelImporter::GetResource(const String& typeName)
  266. {
  267. ResourceCache* cache = GetSubsystem<ResourceCache>();
  268. Model* model = cache->GetResource<Model>(asset_->GetCachePath() + ".mdl");
  269. return model;
  270. }
  271. Node* ModelImporter::InstantiateNode(Node* parent, const String& name)
  272. {
  273. SharedPtr<File> file(new File(context_, asset_->GetCachePath()));
  274. SharedPtr<XMLFile> xml(new XMLFile(context_));
  275. if (!xml->Load(*file))
  276. return 0;
  277. Node* node = parent->CreateChild(name);
  278. node->LoadXML(xml->GetRoot());
  279. node->SetName(asset_->GetName());
  280. return node;
  281. }
  282. }