2
0

Import 1.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. /******************************************************************************
  5. 'Proj' is used because various world (area/object) methods operate on 'Proj'.
  6. /******************************************************************************/
  7. State StateImport(UpdateImport, DrawImport, InitImport, ShutImport);
  8. Str ImportSrc;
  9. BackgroundFileFind ImportBFF;
  10. IMPORT_PHASE ImportPhase=IMPORT_GET_FILES;
  11. Memc<BackgroundFileFind::File> ImportFiles, ImportManual;
  12. Map<Str, UID> ImportElms(ImportComparePath); // doesn't need to be thread-safe
  13. Memc<Str> ImportMtrlImages;
  14. Memc<Str> ImportObjMeshes;
  15. Map<UID, Matrix> ImportObjMatrix(Compare); // doesn't need to be thread-safe
  16. /******************************************************************************/
  17. int ImportComparePath(C Str &a, C Str &b) {return ComparePath(a, b);}
  18. Elm* ImportFind(C Str &name, ELM_TYPE type)
  19. {
  20. if(C UID *id=ImportElms.find(SkipStartPath(name, ImportSrc)))if(Elm *elm=Proj.findElm(*id, type))return elm;
  21. return null;
  22. }
  23. UID ImportFindID(C Str &name, ELM_TYPE type)
  24. {
  25. if(Elm *elm=ImportFind(name, type))return elm->id;
  26. return UIDZero;
  27. }
  28. Str ImportFindGamePath(C Str &name, ELM_TYPE type)
  29. {
  30. if(Elm *elm=ImportFind(name, type))return Proj.gamePath(*elm);
  31. return S;
  32. }
  33. /******************************************************************************/
  34. void Clean(GuiObj &obj)
  35. { // don't clean children because this function is already called for all elements
  36. switch(obj.type())
  37. {
  38. case GO_BUTTON:
  39. {
  40. if(!FExist(obj.asButton().image.name()))obj.asButton().image=null;
  41. if(!FExist(obj.asButton().skin .name()))obj.asButton().skin =null;
  42. }break;
  43. case GO_CHECKBOX:
  44. {
  45. if(!FExist(obj.asCheckBox().skin.name()))obj.asCheckBox().skin=null;
  46. }break;
  47. case GO_COMBOBOX:
  48. {
  49. if(!FExist(obj.asComboBox().image .name()))obj.asComboBox().image=null;
  50. if(!FExist(obj.asComboBox().skin().name()))obj.asComboBox().skin(null, false);
  51. }break;
  52. case GO_IMAGE:
  53. {
  54. if(!FExist(obj.asImage().image.name()))obj.asImage().image=null;
  55. }break;
  56. case GO_MENU:
  57. {
  58. if(!FExist(obj.asMenu().skin().name()))obj.asMenu().skin(null, false);
  59. }break;
  60. case GO_PROGRESS:
  61. {
  62. if(!FExist(obj.asProgress().skin.name()))obj.asProgress().skin=null;
  63. }break;
  64. case GO_REGION:
  65. {
  66. Clean(obj.asRegion().view);
  67. REPA(obj.asRegion().slidebar)Clean(obj.asRegion().slidebar[i]);
  68. if(!FExist(obj.asRegion().skin().name()))obj.asRegion().skin(null, false);
  69. }break;
  70. case GO_SLIDEBAR:
  71. {
  72. REPA(obj.asSlideBar().button)Clean(obj.asSlideBar().button[i]);
  73. if(!FExist(obj.asSlideBar().skin().name()))obj.asSlideBar().skin(null);
  74. }break;
  75. case GO_SLIDER:
  76. {
  77. if(!FExist(obj.asSlider().skin.name()))obj.asSlider().skin=null;
  78. }break;
  79. case GO_TAB:
  80. {
  81. if(!FExist(obj.asTab().image.name()))obj.asTab().image=null;
  82. if(!FExist(obj.asTab().skin .name()))obj.asTab().skin =null;
  83. }break;
  84. case GO_TABS:
  85. {
  86. REPA(obj.asTabs())Clean(obj.asTabs().tab(i));
  87. if(!FExist(obj.asTabs().skin().name()))obj.asTabs().skin(null);
  88. }break;
  89. case GO_TEXT:
  90. {
  91. if(!FExist(obj.asText().skin.name()))obj.asText().skin=null;
  92. if(!FExist(obj.asText().text_style.name()))obj.asText().text_style=null;
  93. }break;
  94. case GO_TEXTLINE:
  95. {
  96. Clean(obj.asTextLine().reset);
  97. if(!FExist(obj.asTextLine().skin().name()))obj.asTextLine().skin(null, false);
  98. }break;
  99. case GO_WINDOW:
  100. {
  101. REPA(obj.asWindow().button)Clean(obj.asWindow().button[i]);
  102. if(!FExist(obj.asWindow().skin().name()))obj.asWindow().skin(null);
  103. }break;
  104. }
  105. }
  106. /******************************************************************************/
  107. void Adjust(GuiObj &obj) // here all objects should adjust paths for resources accessed using file names
  108. { // don't adjust children because this function is already called for all elements (calling it twice would make destroy paths because it would search in the original project for a path that was already adjusted)
  109. switch(obj.type())
  110. {
  111. case GO_BUTTON:
  112. {
  113. obj.asButton().image=ImportFindGamePath(obj.asButton().image.name(), ELM_IMAGE );
  114. obj.asButton().skin =ImportFindGamePath(obj.asButton().skin .name(), ELM_GUI_SKIN);
  115. }break;
  116. case GO_CHECKBOX:
  117. {
  118. obj.asCheckBox().skin=ImportFindGamePath(obj.asCheckBox().skin.name(), ELM_GUI_SKIN);
  119. }break;
  120. case GO_COMBOBOX:
  121. {
  122. obj.asComboBox().image=ImportFindGamePath(obj.asComboBox().image .name(), ELM_IMAGE );
  123. obj.asComboBox().skin (ImportFindGamePath(obj.asComboBox().skin().name(), ELM_GUI_SKIN), false);
  124. }break;
  125. case GO_IMAGE:
  126. {
  127. obj.asImage().image=ImportFindGamePath(obj.asImage().image.name(), ELM_IMAGE);
  128. }break;
  129. case GO_MENU:
  130. {
  131. obj.asMenu().skin(ImportFindGamePath(obj.asMenu().skin().name(), ELM_GUI_SKIN), false);
  132. }break;
  133. case GO_PROGRESS:
  134. {
  135. obj.asProgress().skin=ImportFindGamePath(obj.asProgress().skin.name(), ELM_GUI_SKIN);
  136. }break;
  137. case GO_REGION:
  138. {
  139. Adjust(obj.asRegion().view);
  140. REPA(obj.asRegion().slidebar)Adjust(obj.asRegion().slidebar[i]);
  141. obj.asRegion().skin(ImportFindGamePath(obj.asRegion().skin().name(), ELM_GUI_SKIN), false);
  142. }break;
  143. case GO_SLIDEBAR:
  144. {
  145. REPA(obj.asSlideBar().button)Adjust(obj.asSlideBar().button[i]);
  146. obj.asSlideBar().skin(ImportFindGamePath(obj.asSlideBar().skin().name(), ELM_GUI_SKIN));
  147. }break;
  148. case GO_SLIDER:
  149. {
  150. obj.asSlider().skin=ImportFindGamePath(obj.asSlider().skin.name(), ELM_GUI_SKIN);
  151. }break;
  152. case GO_TAB:
  153. {
  154. obj.asTab().image=ImportFindGamePath(obj.asTab().image.name(), ELM_IMAGE );
  155. obj.asTab().skin =ImportFindGamePath(obj.asTab().skin .name(), ELM_GUI_SKIN);
  156. }break;
  157. case GO_TABS:
  158. {
  159. REPA(obj.asTabs())Adjust(obj.asTabs().tab(i));
  160. obj.asTabs().skin(ImportFindGamePath(obj.asTabs().skin().name(), ELM_GUI_SKIN));
  161. }break;
  162. case GO_TEXT:
  163. {
  164. obj.asText().skin=ImportFindGamePath(obj.asText().skin.name(), ELM_GUI_SKIN);
  165. obj.asText().text_style=ImportFindGamePath(obj.asText().text_style.name(), ELM_TEXT_STYLE);
  166. }break;
  167. case GO_TEXTLINE:
  168. {
  169. Adjust(obj.asTextLine().reset);
  170. obj.asTextLine().skin(ImportFindGamePath(obj.asTextLine().skin().name(), ELM_GUI_SKIN), false);
  171. }break;
  172. case GO_WINDOW:
  173. {
  174. REPA(obj.asWindow().button)Adjust(obj.asWindow().button[i]);
  175. obj.asWindow().skin(ImportFindGamePath(obj.asWindow().skin().name(), ELM_GUI_SKIN));
  176. }break;
  177. }
  178. }
  179. /******************************************************************************/
  180. void Adjust(MaterialPtr &mtrl)
  181. {
  182. mtrl=ImportFindGamePath(mtrl.name(), ELM_MTRL);
  183. }
  184. void Adjust(Mesh &mesh)
  185. {
  186. REP(mesh.lods())
  187. {
  188. MeshLod &lod=mesh.lod(i); REPA(lod.parts)
  189. {
  190. MeshPart &part=lod.parts[i];
  191. MaterialPtr m[4]=
  192. {
  193. part.multiMaterial(0),
  194. part.multiMaterial(1),
  195. part.multiMaterial(2),
  196. part.multiMaterial(3),
  197. };
  198. REPA(m)Adjust(m[i]);
  199. part.multiMaterial(m[0], m[1], m[2], m[3]);
  200. REP(part.variations())if(i)
  201. {
  202. MaterialPtr m=part.variation(i); Adjust(m); part.variation(i, m);
  203. }
  204. }
  205. }
  206. }
  207. void Adjust(Heightmap &heightmap)
  208. {
  209. REP(heightmap.materials())Adjust(ConstCast(heightmap.material(i)));
  210. }
  211. void Adjust(EditObject &obj)
  212. {
  213. REPA(obj)
  214. {
  215. Param &p=obj[i];
  216. if(p.type==PARAM_ENUM)
  217. if(p.enum_type=Enums(ImportFindGamePath(Enums.name(p.enum_type), ELM_ENUM))) // adjust Enum*
  218. {
  219. int e=p.enum_type->find(p.value.s);
  220. if(InRange(e, *p.enum_type))p.value.id=(*p.enum_type)[e].id; // adjust enum ID
  221. }
  222. }
  223. }
  224. /******************************************************************************/
  225. bool ImportFunc(Thread &thread) // 'ObjType' must be initialized because loading old format 'Object' assumes that it is set correctly
  226. {
  227. ThreadMayUseGPUData();
  228. ObjType.del();
  229. Enum obj_type; // adjusted obj_type to project elm.id
  230. FREPA(ImportFiles)
  231. {
  232. if(thread.wantStop())return false;
  233. UpdateProgress.set(i, ImportFiles.elms());
  234. WindowSetProgress(UpdateProgress());
  235. if(ImportFiles[i].type==FSTD_FILE)
  236. {
  237. C Str &file=ImportFiles[i].name; Str name=GetBaseNoExt(file), ext=GetExt(file), path=GetPath(file);
  238. if(ext=="enum") // enum
  239. {
  240. Enum game; if(game.load(file))
  241. {
  242. if(EqualPath(file, "enum/obj_type.enum"))
  243. {
  244. ObjType=obj_type=game;
  245. FREPA(game)
  246. {
  247. Elm &elm=Proj.Project::newElm(game[i].name, UIDZero, ELM_OBJ_CLASS);
  248. ConstCast(obj_type[i].id)=elm.id; // adjust enum ID
  249. EditObject edit; edit.setType(true, elm.id, Proj.edit_path).setAccess(true, OBJ_ACCESS_CUSTOM);
  250. if(elm.name=="OBJ_LIGHT_POINT")edit.setEditorType(EditObjType.elmID(EDIT_OBJ_LIGHT_POINT));else
  251. if(elm.name=="OBJ_LIGHT_CONE" )edit.setEditorType(EditObjType.elmID(EDIT_OBJ_LIGHT_CONE ));else
  252. if(elm.name=="OBJ_PARTICLES" )edit.setEditorType(EditObjType.elmID(EDIT_OBJ_PARTICLES ));
  253. Save(edit, Proj.editPath(elm));
  254. Object game; edit.copyTo(game, Proj, false, null, null); Save(game, Proj.gamePath(elm));
  255. elm.objClassData()->newData();
  256. elm.objClassData()->from(edit);
  257. }
  258. }else
  259. {
  260. Elm &elm=Proj.Project::newElm(game.name, Proj.getPathID(path), ELM_ENUM);
  261. ElmEnum *enum_data=elm.enumData();
  262. enum_data->newData();
  263. enum_data->src_file=MakeFullPath(file, FILE_DATA);
  264. FCopy(file, Proj.gamePath(elm));
  265. EditEnums edit; edit.create(game); Save(edit, Proj.editPath(elm));
  266. *ImportElms(file)=elm.id;
  267. }
  268. }
  269. }else
  270. if(ext=="anim") // animation
  271. {
  272. Animation game; if(game.load(file))
  273. {
  274. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_ANIM);
  275. elm.animData()->newData();
  276. elm.animData()->loop(game.loop()).linear(game.linear());
  277. FCopy(file, Proj.gamePath(elm));
  278. *ImportElms(file)=elm.id;
  279. }
  280. }else
  281. if(ext=="font") // font
  282. {
  283. Font game; if(game.load(file))
  284. {
  285. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_FONT);
  286. elm.fontData()->newData();
  287. FCopy(file, Proj.gamePath(elm));
  288. EditFont edit; edit.german=game.hasChar(u'ä'); edit.french=game.hasChar(u'à'); edit.polish=game.hasChar(u'ą'); edit.russian=game.hasChar(u'л'); edit.chinese=game.hasChar(u'嗨');
  289. edit.german_time.getUTC(); edit.french_time.getUTC(); edit.polish_time.getUTC(); edit.russian_time.getUTC(); edit.chinese_time.getUTC();
  290. edit.size=game.height(); edit.font=name;
  291. edit.size_time.getUTC(); edit.font_time.getUTC();
  292. Save(edit, Proj.editPath(elm));
  293. *ImportElms(file)=elm.id;
  294. }
  295. }else
  296. if(ext=="ogg" || ext=="wav") // sound
  297. {
  298. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_SOUND);
  299. elm.soundData()->newData();
  300. FCopy(file, Proj.gamePath(elm));
  301. *ImportElms(file)=elm.id;
  302. }else
  303. if(ext=="ogm" || ext=="ogv" || ext=="theora" || ext=="webm") // video
  304. {
  305. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_VIDEO);
  306. elm.videoData()->newData();
  307. FCopy(file, Proj.gamePath(elm));
  308. *ImportElms(file)=elm.id;
  309. }else
  310. if(ext=="mtrl") // material
  311. {
  312. Material game; if(game.load(file))
  313. {
  314. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_MTRL);
  315. EditMaterial edit; edit.create(game); // create from material
  316. // set textures
  317. Image base_1, detail_map; if(game.base_1)UpdateMtrlTex(*game.base_1, base_1); if(game.detail_map)UpdateMtrlTex(*game.detail_map, detail_map);
  318. if(game. base_0)ImageProps(*game. base_0, &edit. base_0_tex, null, ForceHQMtrlBase0 ? FORCE_HQ : 0 );else edit. base_0_tex.zero();
  319. if(game. base_1)ImageProps( base_1, &edit. base_1_tex, null, ForceHQMtrlBase1 ? FORCE_HQ : 0 );else edit. base_1_tex.zero();
  320. if(game. detail_map)ImageProps( detail_map, &edit. detail_tex, null, (ForceHQMtrlDetail ? FORCE_HQ : 0)|IGNORE_ALPHA);else edit. detail_tex.zero();
  321. if(game. macro_map)ImageProps(*game. macro_map, &edit. macro_tex, null, IGNORE_ALPHA);else edit. macro_tex.zero();
  322. if(game.reflection_map)ImageProps(*game.reflection_map, &edit.reflection_tex, null, IGNORE_ALPHA);else edit.reflection_tex.zero();
  323. if(game. light_map)ImageProps(*game. light_map, &edit. light_tex, null, IGNORE_ALPHA);else edit. light_tex.zero();
  324. if(edit. base_0_tex.valid())if(Proj.includeTex(edit. base_0_tex))game. base_0->save(Proj.texPath(edit. base_0_tex));
  325. if(edit. base_1_tex.valid())if(Proj.includeTex(edit. base_1_tex)) base_1. save(Proj.texPath(edit. base_1_tex));
  326. if(edit. detail_tex.valid())if(Proj.includeTex(edit. detail_tex)) detail_map. save(Proj.texPath(edit. detail_tex));
  327. if(edit. macro_tex.valid())if(Proj.includeTex(edit. macro_tex))game. macro_map->save(Proj.texPath(edit. macro_tex));
  328. if(edit.reflection_tex.valid())if(Proj.includeTex(edit.reflection_tex))game.reflection_map->save(Proj.texPath(edit.reflection_tex));
  329. if(edit. light_tex.valid())if(Proj.includeTex(edit. light_tex))game. light_map->save(Proj.texPath(edit. light_tex));
  330. Str b0=MakeFullPath(game.base_0.name(), FILE_DATA), b1=MakeFullPath(game.base_1.name(), FILE_DATA), d=MakeFullPath(game.detail_map.name(), FILE_DATA), m=MakeFullPath(game.macro_map.name(), FILE_DATA), r=MakeFullPath(game.reflection_map.name(), FILE_DATA), l=MakeFullPath(game.light_map.name(), FILE_DATA);
  331. ImportMtrlImages.binaryInclude(SkipStartPath(b0, ImportSrc), ImportComparePath); b0.tailSlash(true);
  332. ImportMtrlImages.binaryInclude(SkipStartPath(b1, ImportSrc), ImportComparePath); b1.tailSlash(true);
  333. ImportMtrlImages.binaryInclude(SkipStartPath(d , ImportSrc), ImportComparePath); d .tailSlash(true);
  334. ImportMtrlImages.binaryInclude(SkipStartPath(m , ImportSrc), ImportComparePath);
  335. ImportMtrlImages.binaryInclude(SkipStartPath(r , ImportSrc), ImportComparePath);
  336. ImportMtrlImages.binaryInclude(SkipStartPath(l , ImportSrc), ImportComparePath);
  337. edit. color_map=(b0.is() ? b0+"xyz" : S); edit. color_map_time.getUTC();
  338. edit. alpha_map.clear(); edit. alpha_map_time.getUTC();
  339. edit. bump_map.clear(); edit. bump_map_time.getUTC();
  340. edit. glow_map.clear(); edit. glow_map_time.getUTC();
  341. edit. normal_map.clear(); edit. normal_map_time.getUTC();
  342. edit.specular_map.clear(); edit. specular_map_time.getUTC();
  343. edit.detail_color =(d.is() ? d+"x" : S); edit. detail_map_time.getUTC();
  344. edit.detail_bump =(d.is() ? d+"z" : S);
  345. edit.detail_normal=(d.is() ? d+"wy" : S);
  346. edit. macro_map=m; edit. macro_map_time.getUTC();
  347. edit.reflection_map=r; edit.reflection_map_time.getUTC();
  348. edit. light_map=l; edit. light_map_time.getUTC();
  349. if(b1.is())
  350. {
  351. edit. bump_map=(b0.is() ? b0+"w" : S);
  352. edit. normal_map=b1+"wy";
  353. edit. alpha_map=b1+"z";
  354. edit. glow_map=b1+"z";
  355. edit.specular_map=b1+"x";
  356. }else
  357. if(b0.is())
  358. {
  359. edit.alpha_map=b0+"w";
  360. }
  361. // save
  362. Save(edit, Proj.editPath(elm));
  363. edit.copyTo(game, Proj); Save(game, Proj.gamePath(elm));
  364. // finalize
  365. ElmMaterial *mtrl_data=elm.mtrlData();
  366. mtrl_data->newData();
  367. mtrl_data->src_file=MakeFullPath(file, FILE_DATA);
  368. mtrl_data->from(edit);
  369. *ImportElms(file)=elm.id;
  370. }
  371. }else
  372. if(ext=="obj") // object (only create elements but don't set data)
  373. {
  374. Object game; if(game.load(file))
  375. {
  376. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_OBJ);
  377. elm.objData()->newData();
  378. *ImportElms(file)=elm.id;
  379. }
  380. }
  381. }
  382. }
  383. // 2nd phase (images after materials, text styles after fonts, objects after creating them before)
  384. ImportPhase=IMPORT_IMPORT1;
  385. FREPA(ImportFiles)
  386. {
  387. if(thread.wantStop())return false;
  388. UpdateProgress.set(i, ImportFiles.elms());
  389. WindowSetProgress(UpdateProgress());
  390. if(ImportFiles[i].type==FSTD_FILE)
  391. {
  392. C Str &file=ImportFiles[i].name; Str name=GetBaseNoExt(file), ext=GetExt(file), path=GetPath(file);
  393. if(ext=="img") // image
  394. {
  395. Image game;
  396. if(!ImportMtrlImages.binaryHas(file, ImportComparePath)) // if not material texture
  397. if(game.load(file))
  398. if(game.is())
  399. {
  400. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_IMAGE);
  401. ElmImage *image_data=elm.imageData();
  402. image_data->newData();
  403. image_data->src_file=MakeFullPath(file, FILE_DATA);
  404. if(ImageTI[game.type()].compressed)elm.imageData()->type=ElmImage::COMPRESSED;else
  405. if( game.type()==IMAGE_A8 )elm.imageData()->type=ElmImage::ALPHA;else
  406. elm.imageData()->type=ElmImage::FULL;
  407. elm.imageData()->mode=game.mode();
  408. elm.imageData()->mipMaps(game.mipMaps()>1);
  409. elm.imageData()->pow2(IsPow2(game.w()) && IsPow2(game.h()));
  410. elm.imageData()->hasAlpha(HasAlpha(game));
  411. elm.imageData()->hasColor(HasColor(game));
  412. game.ExportWEBP(Proj.editPath(elm), 1, 1);
  413. FCopy(file, Proj.gamePath(elm));
  414. *ImportElms(file)=elm.id;
  415. }
  416. }else
  417. if(ext=="txds") // text styles
  418. {
  419. TextStyle game; if(game.load(file))
  420. {
  421. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_TEXT_STYLE);
  422. EditTextStyle edit; edit.create(game, ImportFindID(game.font().name(), ELM_FONT)); Save(edit, Proj.editPath(elm));
  423. edit.copyTo(game, Proj); Save(game, Proj.gamePath(elm));
  424. elm.textStyleData()->newData();
  425. elm.textStyleData()->from(edit);
  426. *ImportElms(file)=elm.id;
  427. }
  428. }else
  429. if(ext=="obj") // object
  430. {
  431. if(Elm *elm=ImportFind(file, ELM_OBJ))
  432. {
  433. Object game; game.load(file);
  434. UID type=obj_type.elmID(ObjType.find(game.type())); // adjust ID in case source uses ID not listed in ObjType
  435. EditObjectPtr base; if(Elm *base_elm=ImportFind(game.base().name(), ELM_OBJ))base=Proj.editPath(*base_elm);else if(type.valid())base=Proj.editPath(type);
  436. game.type(false); type.zero(); // clear type as it is always taken from base (OBJ_CLASS)
  437. if(game.access()==OBJ_ACCESS_CUSTOM)game.access(false); // use access from base
  438. else base=null; // we're not using custom class, so disable base
  439. EditObject edit; edit.create(game, type, base); Adjust(edit); Save(edit, Proj.editPath(*elm));
  440. UID *mesh_id=null, *phys_id=null;
  441. Matrix matrix=game.matrixFinal(); Pose transform=matrix;
  442. ImportObjMeshes.binaryInclude(Str(game.mesh().name()), ImportComparePath);
  443. *ImportObjMatrix(elm->id)=~matrix;
  444. if(game.mesh() && game.mesh()->is()
  445. || game.phys() && game.phys()->is())
  446. {
  447. Elm &mesh_elm=Proj.Project::newElm(ElmNameMesh, elm->id, ELM_MESH); mesh_id=&mesh_elm.id;
  448. ElmMesh *mesh_data=mesh_elm.meshData();
  449. mesh_data->newData();
  450. mesh_data->src_file=MakeFullPath(game.mesh().name(), FILE_DATA);
  451. mesh_data->transform=transform;
  452. mesh_data->obj_id=elm->id;
  453. Mesh edit_mesh, game_mesh; if(game.mesh())edit_mesh.create(*game.mesh());
  454. edit_mesh.setBase().delRender();
  455. // adjust materials
  456. Adjust(edit_mesh);
  457. edit_mesh.drawGroupEnum(null);
  458. // skeleton
  459. if(edit_mesh.skeleton())
  460. {
  461. Skeleton skel=*edit_mesh.skeleton(); EditSkeleton edit_skel; edit_skel.create(skel, null); skel.transform(matrix);
  462. Elm &skel_elm=Proj.Project::newElm(ElmNameSkel, mesh_elm.id, ELM_SKEL); mesh_elm.meshData()->skel_id=skel_elm.id;
  463. ElmSkel *skel_data=skel_elm.skelData();
  464. skel_data->newData();
  465. skel_data->src_file=MakeFullPath(Skeletons.name(edit_mesh.skeleton()), FILE_DATA);
  466. skel_data->mesh_id =mesh_elm.id;
  467. skel_data->transform=transform;
  468. Save(edit_skel, Proj.editPath(skel_elm));
  469. Save( skel, Proj.gamePath(skel_elm));
  470. edit_mesh.skeleton(null);
  471. }
  472. Skeleton *body_skel; Proj.getMeshSkels(mesh_elm.meshData(), null, &body_skel);
  473. EditToGameMesh(edit_mesh, game_mesh, body_skel, null, &matrix);
  474. Save(edit_mesh, Proj.editPath(mesh_elm), Proj.game_path); // must use 'game_path'
  475. Save(game_mesh, Proj.gamePath(mesh_elm));
  476. mesh_elm.meshData()->from(game_mesh);
  477. // phys body
  478. if(game.phys() && game.phys()->is())
  479. {
  480. PhysBody phys=*game.phys(); phys.transform(matrix);
  481. Elm &phys_elm=Proj.Project::newElm(ElmNamePhys, mesh_elm.id, ELM_PHYS); phys_id=&phys_elm.id; mesh_elm.meshData()->phys_id=phys_elm.id;
  482. Save(phys, Proj.gamePath(phys_elm));
  483. ElmPhys *phys_data=phys_elm.physData();
  484. phys_data->newData();
  485. phys_data->src_file=MakeFullPath(game.phys().name(), FILE_DATA);
  486. phys_data->density =phys.density;
  487. phys_data->mesh_id =mesh_elm.id;
  488. phys_data->transform=transform;
  489. phys_data->from(phys);
  490. }
  491. }
  492. edit.copyTo(game, Proj, true, mesh_id, phys_id); Save(game, Proj.gamePath(*elm));
  493. elm->objData()->from(edit); if(mesh_id)elm->objData()->mesh_id=*mesh_id;
  494. }
  495. }
  496. }
  497. }
  498. // 3rd phase (Panels after importing images, non-object meshes after importing all objects, particles after importing images)
  499. ImportPhase=IMPORT_IMPORT2;
  500. FREPA(ImportFiles)
  501. {
  502. if(thread.wantStop())return false;
  503. UpdateProgress.set(i, ImportFiles.elms());
  504. WindowSetProgress(UpdateProgress());
  505. if(ImportFiles[i].type==FSTD_FILE)
  506. {
  507. C Str &file=ImportFiles[i].name; Str name=GetBaseNoExt(file), ext=GetExt(file), path=GetPath(file);
  508. if(ext=="gstl") // Panel (old GuiStyle)
  509. {
  510. Panel game; if(game.load(file))
  511. {
  512. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_PANEL);
  513. EditPanel edit;
  514. edit.create(game, ImportFindID(game. center_image.name(), ELM_IMAGE),
  515. ImportFindID(game. border_image.name(), ELM_IMAGE),
  516. ImportFindID(game. top_image.name(), ELM_IMAGE),
  517. ImportFindID(game. bottom_image.name(), ELM_IMAGE),
  518. ImportFindID(game. left_right_image.name(), ELM_IMAGE),
  519. ImportFindID(game. top_corner_image.name(), ELM_IMAGE),
  520. ImportFindID(game.bottom_corner_image.name(), ELM_IMAGE),
  521. ImportFindID(game. panel_image.name(), ELM_PANEL_IMAGE)); Save(edit, Proj.editPath(elm));
  522. edit.copyTo(game, Proj); Save(game, Proj.gamePath(elm));
  523. elm.panelData()->newData();
  524. elm.panelData()->from(edit);
  525. *ImportElms(file)=elm.id;
  526. }
  527. }else
  528. if(ext=="mesh") // mesh
  529. {
  530. Mesh edit_mesh;
  531. if(!ImportObjMeshes.binaryHas(file, ImportComparePath)) // if not object mesh
  532. if(edit_mesh.load(file))
  533. if(edit_mesh.is())
  534. {
  535. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_OBJ);
  536. elm.objData()->newData();
  537. *ImportElms(file)=elm.id; // src mesh is now ELM_OBJ
  538. EditObject edit; Save(edit, Proj.editPath(elm));
  539. UID *mesh_id=null, *phys_id=null;
  540. Elm &mesh_elm=Proj.Project::newElm(ElmNameMesh, elm.id, ELM_MESH); mesh_id=&mesh_elm.id;
  541. ElmMesh *mesh_data=mesh_elm.meshData();
  542. mesh_data->newData();
  543. mesh_data->src_file=file;
  544. mesh_data->obj_id=elm.id;
  545. edit_mesh.setBase().delRender();
  546. // adjust materials
  547. Adjust(edit_mesh);
  548. edit_mesh.drawGroupEnum(null);
  549. // skeleton
  550. if(edit_mesh.skeleton())
  551. {
  552. Elm &skel_elm=Proj.Project::newElm(ElmNameSkel, elm.id, ELM_SKEL); mesh_elm.meshData()->skel_id=skel_elm.id;
  553. ElmSkel *skel_data=skel_elm.skelData();
  554. skel_data->newData();
  555. skel_data->src_file=MakeFullPath(Skeletons.name(edit_mesh.skeleton()), FILE_DATA);
  556. skel_data->mesh_id=mesh_elm.id;
  557. EditSkeleton edit_skel; edit_skel.create(*edit_mesh.skeleton(), null);
  558. Save( edit_skel , Proj.editPath(skel_elm));
  559. Save(*edit_mesh.skeleton(), Proj.gamePath(skel_elm));
  560. edit_mesh.skeleton(null);
  561. }
  562. Skeleton *body_skel; Proj.getMeshSkels(mesh_elm.meshData(), null, &body_skel);
  563. Mesh game_mesh; EditToGameMesh(edit_mesh, game_mesh, body_skel, null, null);
  564. Save(edit_mesh, Proj.editPath(mesh_elm), Proj.game_path); // must use 'game_path'
  565. Save(game_mesh, Proj.gamePath(mesh_elm));
  566. mesh_elm.meshData()->from(game_mesh);
  567. // phys body
  568. /*if(phys)
  569. {
  570. Elm &phys_elm=Proj.Project.newElm(name, elm.id, ELM_PHYS); phys_id=&phys_elm.id; mesh_elm.meshData().phys_id=phys_elm.id;
  571. Save(phys, Proj.gamePath(phys_elm));
  572. phys_elm.physData().newData();
  573. phys_elm.physData().density=phys.density;
  574. phys_elm.physData().mesh_id=mesh_elm.id;
  575. phys_elm.physData().from(phys);
  576. phys_elm.physData().src_file=MakeFullDataPath(phys.name());
  577. }*/
  578. Object game; edit.copyTo(game, Proj, true, mesh_id, phys_id); Save(game, Proj.gamePath(elm));
  579. elm.objData()->from(edit); if(mesh_id)elm.objData()->mesh_id=*mesh_id;
  580. }
  581. }else
  582. if(ext=="particle") // particles
  583. {
  584. Particles p;
  585. if(p.load(file))
  586. {
  587. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_OBJ);
  588. EditObject edit;
  589. Object game;
  590. if(Elm *elm=ImportFind(p. image.name(), ELM_IMAGE))edit.New().setName( "Image").setAsIDArray(elm->id).id.set( 5, 0, 0, 0);
  591. if(Elm *elm=ImportFind(p.palette_image.name(), ELM_IMAGE))edit.New().setName("Palette Image").setAsIDArray(elm->id).id.set(34, 0, 0, 0);
  592. if( p.image_x_frames> 1 )edit.New().setName("Image Frames X" ).forceInt (p.image_x_frames).id.set( 6, 0, 0, 0);
  593. if( p.image_y_frames> 1 )edit.New().setName("Image Frames Y" ).forceInt (p.image_y_frames).id.set( 7, 0, 0, 0);
  594. if(!Equal(p.image_speed , 1))edit.New().setName("Image Speed" ).forceFlt (p.image_speed ).id.set( 8, 0, 0, 0);
  595. if(! p.reborn )edit.New().setName("Reborn" ).forceBool (p.reborn ).id.set( 9, 0, 0, 0);
  596. edit.New().setName("Palette Mode" ).forceBool (p.palette() ).id.set(10, 0, 0, 0);
  597. if( p.paletteIndex() )edit.New().setName("Palette Index" ).forceBool (p.paletteIndex()!=0).id.set(11, 0, 0, 0);
  598. if( p.smooth_fade )edit.New().setName("Smooth Fade" ).forceBool (p.smooth_fade ).id.set(12, 0, 0, 0);
  599. edit.New().setName("Elements" ).forceInt (p.p.elms() ).id.set(13, 0, 0, 0);
  600. edit.New().setName("Color" ).forceColor(p.color ).id.set( 1, 0, 0, 0);
  601. if( p.glow )edit.New().setName("Glow" ).forceInt (p.glow ).id.set(14, 0, 0, 0);
  602. edit.New().setName("Radius" ).forceFlt (p.radius ).id.set(15, 0, 0, 0);
  603. if(!Equal(p.radius_random , 0))edit.New().setName("Radius Random" ).forceFlt (p.radius_random ).id.set(32, 0, 0, 0);
  604. if(!Equal(p.radius_growth , 1))edit.New().setName("Radius Growth" ).forceFlt (p.radius_growth ).id.set(16, 0, 0, 0);
  605. if(!Equal(p.offset_range , 0))edit.New().setName("Offset Range" ).forceFlt (p.offset_range ).id.set(17, 0, 0, 0);
  606. if(!Equal(p.offset_speed , 1))edit.New().setName("Offset Speed" ).forceFlt (p.offset_speed ).id.set(18, 0, 0, 0);
  607. edit.New().setName("Life" ).forceFlt (p.life ).id.set(19, 0, 0, 0);
  608. if(!Equal(p.life_random , 0))edit.New().setName("Life Random" ).forceFlt (p.life_random ).id.set(33, 0, 0, 0);
  609. if(!Equal(p.glue , 0))edit.New().setName("Glue" ).forceFlt (p.glue ).id.set(20, 0, 0, 0);
  610. if(!Equal(p.damping , 0))edit.New().setName("Velocity Damping" ).forceFlt (p.damping ).id.set(21, 0, 0, 0);
  611. if(!Equal(p.ang_vel , 0))edit.New().setName("Angular Velocity" ).forceFlt (p.ang_vel ).id.set(22, 0, 0, 0);
  612. edit.New().setName("Random Velocity" ).forceFlt (p.vel_random ).id.set(23, 0, 0, 0);
  613. if(!Equal(p.vel_constant.x, 0))edit.New().setName("Initial Velocity X").forceFlt (p.vel_constant.x).id.set(24, 0, 0, 0);
  614. if(!Equal(p.vel_constant.y, 0))edit.New().setName("Initial Velocity Y").forceFlt (p.vel_constant.y).id.set(25, 0, 0, 0);
  615. if(!Equal(p.vel_constant.z, 0))edit.New().setName("Initial Velocity Z").forceFlt (p.vel_constant.z).id.set(26, 0, 0, 0);
  616. if(!Equal(p.accel.x , 0))edit.New().setName("Acceleration X" ).forceFlt (p.accel.x ).id.set(27, 0, 0, 0);
  617. if(!Equal(p.accel.y , 0))edit.New().setName("Acceleration Y" ).forceFlt (p.accel.y ).id.set(28, 0, 0, 0);
  618. if(!Equal(p.accel.z , 0))edit.New().setName("Acceleration Z" ).forceFlt (p.accel.z ).id.set(29, 0, 0, 0);
  619. if( p.sourceType()==PARTICLE_STATIC_SHAPE)edit.New().setName("Source Shape").forceInt(p.shape.type ).id.set(30, 0, 0, 0);
  620. if(!p.inside_shape )edit.New().setName("Inside Source" ).forceBool (p.inside_shape ).id.set(31, 0, 0, 0);
  621. Save(edit, Proj.editPath(elm)); edit.copyTo(game, Proj, true, null, null);
  622. Save(game, Proj.gamePath(elm));
  623. elm.objData()->newData(); elm.objData()->from(edit);
  624. *ImportElms(file)=elm.id;
  625. }
  626. }
  627. }
  628. }
  629. // 4th phase (gui objects after importing images text styles and Panels, worlds after importing all objects and meshes)
  630. ImportPhase=IMPORT_IMPORT3;
  631. FREPA(ImportFiles)
  632. {
  633. if(thread.wantStop())return false;
  634. UpdateProgress.set(i, ImportFiles.elms());
  635. WindowSetProgress(UpdateProgress());
  636. C Str &file=ImportFiles[i].name; Str name=GetBaseNoExt(file), ext=GetExt(file), path=GetPath(file);
  637. if(ImportFiles[i].type==FSTD_FILE)
  638. {
  639. if(ext=="gobj") // gui objects
  640. {
  641. GuiObjs game; if(game.load(file))
  642. {
  643. REP(GO_NUM)if(C MembConst<const_mem_addr GuiObj> *objs=game.objects(GUI_OBJ_TYPE(i)))REPA(*objs)Adjust((*objs)[i]);
  644. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_GUI);
  645. Save(game, Proj.gamePath(elm));
  646. elm.guiData()->newData();
  647. *ImportElms(file)=elm.id;
  648. }
  649. }
  650. }else
  651. if(ImportFiles[i].type==FSTD_DIR)
  652. {
  653. if(ext=="world") // world
  654. {
  655. EE1WorldSettings settings;
  656. Str edit=file; edit.tailSlash(true)+="Edit/";
  657. if(settings.load(edit+"Settings"))
  658. {
  659. Elm &elm=Proj.Project::newElm(name, Proj.getPathID(path), ELM_WORLD);
  660. *ImportElms(file)=elm.id;
  661. elm.worldData()->newData();
  662. elm.worldData()->area_size= settings.areaSize();
  663. elm.worldData()->hm_res =NearestPow2(settings.hmRes ());
  664. elm.worldData()->ctrlRadius(settings.path.ctrlRadius());
  665. elm.worldData()->ctrlHeight(settings.path.ctrlHeight());
  666. elm.worldData()->maxClimb (settings.path.maxClimb ());
  667. elm.worldData()->maxSlope (settings.path.maxSlope ());
  668. elm.worldData()->cellSize (settings.path.cellSize ());
  669. elm.worldData()->cellHeight(settings.path.cellHeight());
  670. Proj.makeGameVer(elm); // create paths and save world settings (call this after setting them)
  671. WorldVer *world_ver=Proj.worldVerRequire(elm.id); world_ver->changed=true;
  672. for(FileFind ff(MakeFullPath(edit+"Area", FILE_DATA)); ff(); )if(ff.type==FSTD_FILE && !GetExt(ff.name).is())
  673. {
  674. if(thread.wantStop())return false;
  675. VecI2 xy=TextVecI2(ff.name);
  676. File f; if(f.readStdTry(ff.pathName()))
  677. {
  678. Heightmap h;
  679. Memt<Game::Area::Data::AreaObj> objs; // !! Warning: this should actually be Edit.Obj !! however we'd need 'Object.loadData' method which is hidden, and 'AreaObj' provides same save/load functionality as 'Edit.Obj'
  680. for(ChunkReader cr(f); File *f=cr(); )
  681. {
  682. if(cr.name()=="Heightmap")switch(cr.ver())
  683. {
  684. case 0: h.load(*f); break;
  685. }else
  686. if(cr.name()=="Object")switch(cr.ver())
  687. {
  688. case 1: REP(f->getInt())if(!objs.New().load(*f)){objs.removeLast(); break;} break;
  689. }
  690. }
  691. if(h.is() || objs.elms())
  692. {
  693. Area area(xy, null); area.ver=world_ver->areas(xy); // create AreaVer (needed for rebuild)
  694. Memt<Obj> area_objs;
  695. if(h.is())
  696. {
  697. Adjust(h);
  698. Swap(SCAST(Heightmap, *New(Delete(area.hm))), h);
  699. if(area.ver)
  700. {
  701. area.ver->hm_height_time.getUTC();
  702. area.ver->hm_mtrl_time .getUTC();
  703. area.ver->hm_color_time .getUTC();
  704. }
  705. world_ver->rebuildAreaNeighbor(xy, AREA_REBUILD_HM|AREA_REBUILD_HM_MESH|AREA_REBUILD_HM_MESH_SIMPLIFY|AREA_REBUILD_HM_PHYS); // rebuild after settings AreaVer
  706. }
  707. REPA(objs)
  708. {
  709. Game::Area::Data::AreaObj &src =objs[i];
  710. UID type=obj_type.elmID(ObjType.find(src.type())); // adjust ID in case source uses ID not listed in ObjType
  711. EditObjectPtr base;
  712. if(src.access()!=OBJ_ACCESS_CUSTOM)type.zero(); // clear class if we're not using custom
  713. Elm *base_elm=ImportFind(src.base().name(), ELM_OBJ); if(!base_elm)base_elm=ImportFind(src.mesh().name(), ELM_OBJ); // if object base was not found, then try checking its mesh (because earlier we've imported non-object meshes as objects)
  714. if( base_elm) // create only if we've found ELM_OBJ base
  715. {
  716. base=Proj.editPath(*base_elm);
  717. Obj &obj=area_objs.New();
  718. obj.ObjData::create(src, type, base);
  719. Adjust(obj.params);
  720. if(C Matrix *matrix=ImportObjMatrix.find(base_elm->id))obj.matrix=(*matrix)*obj.matrix; // object meshes are already transformed
  721. world_ver->changedObj(obj, xy);
  722. }
  723. }
  724. if(area_objs.elms())
  725. {
  726. FREPA(area_objs)area.objs.add(&area_objs[i]);
  727. if(area.ver)area.ver->obj_ver.randomize();
  728. world_ver->rebuildAreaNeighbor(xy, AREA_REBUILD_GAME_AREA_OBJS); // rebuild after settings AreaVer
  729. }
  730. world_ver->rebuildAreaNeighbor(xy, AREA_REBUILD_EMBED_OBJ|AREA_REBUILD_WATER|AREA_REBUILD_PATH); // rebuild after settings AreaVer
  731. area.saveEdit(Proj.editAreaPath(elm.id, xy));
  732. area.objs.del(); // delete obj pointer container manually before objects are deleted (otherwise Area destructor would be accessing removed objects)
  733. }
  734. }
  735. }
  736. Pak global;
  737. if(global.load(MakeFullPath(edit+"Global/Waypoints.pak", FILE_DATA)))FREPA(global)if(global.file(i).data_size) // waypoints
  738. {
  739. EE1EditWaypoint src; File f; if(f.readTry(global.file(i), global))if(src.load(f, global.file(i).name))
  740. {
  741. EditWaypoint edit; edit.create(src, src.name); Save(edit, Proj.editWaypointPath(elm.id, src.id));
  742. Game::Waypoint game; edit.copyTo(game ); Save(game, Proj.gameWaypointPath(elm.id, src.id));
  743. world_ver->changedWaypoint(src.id);
  744. }
  745. }
  746. if(global.load(MakeFullPath(edit+"Global/Lakes.pak", FILE_DATA)))FREPA(global)if(global.file(i).data_size) // lakes
  747. {
  748. EE1EditLake src; File f; if(f.readTry(global.file(i), global))if(src.load(f, global.file(i).name))
  749. {
  750. Lake lake; lake.setDepth(src.depth); Swap(lake.polys, src.polys); lake.polys_time.getUTC();
  751. Save(lake, Proj.editLakePath(elm.id, src.id));
  752. world_ver->changedLake(src.id);
  753. }
  754. }
  755. if(global.load(MakeFullPath(edit+"Global/Rivers.pak", FILE_DATA)))FREPA(global)if(global.file(i).data_size) // rivers
  756. {
  757. EE1EditRiver src; File f; if(f.readTry(global.file(i), global))if(src.load(f, global.file(i).name))
  758. {
  759. River river; river.setDepth(src.depth); FREPA(src.vtxs)river.vtxs.New().set(src.vtxs[i].radius, src.vtxs[i].pos); Swap(river.edges, src.edges); river.vtx_edge_time.getUTC();
  760. Save(river, Proj.editRiverPath(elm.id, src.id));
  761. world_ver->changedRiver(src.id);
  762. }
  763. }
  764. }
  765. }
  766. }
  767. }
  768. // move materials used by only one object to inside of the obj
  769. REPA(Proj.elms)
  770. {
  771. Elm &elm=Proj.elms[i]; if(ElmMesh *mesh_data=elm.meshData())
  772. {
  773. REPA(mesh_data->mtrl_ids)
  774. {
  775. C UID &mtrl_id=mesh_data->mtrl_ids[i];
  776. REPA(Proj.elms) // check other meshes
  777. {
  778. Elm &elm_other=Proj.elms[i]; if(ElmMesh *mesh_data=elm_other.meshData())if(&elm_other!=&elm)if(mesh_data->mtrl_ids.binaryHas(mtrl_id, Compare))goto used;
  779. }
  780. if(Elm *mtrl_elm=Proj.findElm(mtrl_id, ELM_MTRL))if(Elm *obj=Proj.meshToObjElm(&elm))mtrl_elm->setParent(obj); // set to object
  781. used:;
  782. }
  783. }
  784. }
  785. ImportPhase=IMPORT_FINISHED;
  786. return false;
  787. }
  788. bool ImportFilter(C Str &name)
  789. {
  790. Str ext=GetExt(name);
  791. if( ext=="world" || ext=="atlas") // world and atlas
  792. if(FileInfoSystem(name).type==FSTD_DIR) // folder
  793. {
  794. BackgroundFileFind::File &file=ImportManual.New(); file.get(name); file.name=name; // add this element manually
  795. return false; // skip files inside those folders
  796. }
  797. return true;
  798. }
  799. /******************************************************************************/
  800. bool InitImport()
  801. {
  802. ImportSrc.tailSlash(false);
  803. if(FileInfoSystem(ImportSrc).type!=FSTD_DIR)StateProjectList.set(StateFadeTime);else
  804. {
  805. UID id; id.randomizeValid(); Str name=GetBase(ImportSrc); if(name=="Data")name=GetBase(GetPath(ImportSrc)); Str path=ProjectsPath+EncodeFileName(id);
  806. Str error; LOAD_RESULT result=Proj.Project::open(id, name, path, error); // open using 'Project' method
  807. if(!FExistSystem(path) || !LoadOK(result)){StateProjectList.set(StateFadeTime); Gui.msgBox(S, S+"Can't write to:\"\n"+ProjectsPath+'"');}else
  808. {
  809. DataPath(ImportSrc);
  810. ImportPhase=IMPORT_GET_FILES;
  811. ImportBFF.find(ImportSrc, ImportFilter);
  812. UpdateProgress.create(Rect_C(0, -0.1f, 1, 0.045f));
  813. }
  814. }
  815. return true;
  816. }
  817. void ShutImport()
  818. {
  819. UpdateThread .del(); // delete the thread first
  820. UpdateProgress.del();
  821. if(ImportPhase!=IMPORT_FINISHED)
  822. {
  823. FDelDirs(Proj.path); // delete what was imported until now
  824. Proj.Project::del();
  825. }
  826. ImportBFF .del();
  827. ImportFiles .del(); ImportManual.del(); // delete after BFF
  828. ImportElms .del();
  829. ImportMtrlImages.del();
  830. ImportObjMeshes .del();
  831. ImportObjMatrix .del();
  832. DataPath(S);
  833. WindowSetNormal();
  834. }
  835. /******************************************************************************/
  836. bool UpdateImport()
  837. {
  838. if(Kb.bp(KB_ESC)){StateProjectList.set(StateFadeTime); Gui.msgBox(S, "Importing breaked on user request");} // cancel importing
  839. if(ImportPhase==IMPORT_GET_FILES)
  840. {
  841. if(ImportBFF.finished())
  842. {
  843. ImportBFF.getFiles(ImportFiles);
  844. FREPA(ImportManual)Swap(ImportFiles.New(), ImportManual[i]);
  845. REPAO(ImportFiles).name=SkipStartPath(ImportFiles[i].name, ImportSrc);
  846. ImportFiles.sort(BackgroundFileFind::Compare);
  847. ImportPhase=IMPORT_IMPORT;
  848. UpdateThread.create(ImportFunc); // create thread after all other stuff
  849. }
  850. }
  851. if(ImportPhase==IMPORT_FINISHED)
  852. {
  853. WindowFlash();
  854. Proj.save();
  855. Str error; Proj.open(Proj.id, Proj.name, Proj.path, error); // reopen using 'ProjectEx' method
  856. SetProjectState();
  857. }
  858. Time.wait(1000/30); // limit to 30 fps
  859. Server.update(null, true);
  860. if(Ms.bp(3))WindowToggle();
  861. return true;
  862. }
  863. /******************************************************************************/
  864. void DrawImport()
  865. {
  866. D.clear(BackgroundColor());
  867. D.text(Rect(Vec2(0, 0.2f)), S+"Importing Project\n\""+ImportSrc+'"');
  868. switch(ImportPhase)
  869. {
  870. case IMPORT_GET_FILES:
  871. {
  872. D.text(0, 0, "Getting list of files");
  873. }break;
  874. case IMPORT_IMPORT :
  875. case IMPORT_IMPORT1:
  876. case IMPORT_IMPORT2:
  877. case IMPORT_IMPORT3:
  878. {
  879. D.text(0, 0, S+"Importing files "+(ImportPhase-IMPORT_IMPORT+1)+"/4");
  880. GuiPC gpc;
  881. gpc.visible=gpc.enabled=true;
  882. gpc.client_rect=gpc.clip.set(-D.w(), -D.h(), D.w(), D.h());
  883. gpc.offset.zero();
  884. UpdateProgress.draw(gpc);
  885. D.clip();
  886. }break;
  887. }
  888. }
  889. /******************************************************************************/
  890. /******************************************************************************/
  891. EE1WorldSettings& EE1WorldSettings::reset()
  892. {
  893. ::EE::Game::WorldSettings::reset();
  894. path .reset();
  895. return T;
  896. }
  897. bool EE1WorldSettings::load(C Str &name) {File f; if(f.readStdTry(name))return load(f); reset(); return false;}
  898. bool EE1WorldSettings::load( File &f )
  899. {
  900. switch(f.decUIntV()) // version
  901. {
  902. case 1:
  903. {
  904. if(!::EE::Game::WorldSettings::load(f))return false;
  905. if(!path .load(f))return false;
  906. }return true;
  907. case 0:
  908. {
  909. reset();
  910. f.skip(-1); if(!::EE::Game::WorldSettings::load(f))return false;
  911. path.reset().areaSize(areaSize());
  912. }return true;
  913. }
  914. reset(); return false;
  915. }
  916. bool EE1ObjGlobal::load(File &f)
  917. {
  918. switch(f.decUIntV()) // version
  919. {
  920. case 1: {Rect rect; f>>rect;} return true;
  921. case 0: {RectI area; f>>area;} return true;
  922. default: return false;
  923. }
  924. }
  925. bool EE1EditWaypoint::loadData(File &f)
  926. {
  927. File temp; temp.writeMem().putUInt(CC4('W','P','N','T')); f.copy(temp);
  928. temp.pos(0); return Game::Waypoint::load(temp);
  929. }
  930. bool EE1EditWaypoint::load(File &f, C Str &name)
  931. {
  932. if(id.fromHex(name))switch(f.decUIntV()) // version
  933. {
  934. case 1: if(EE1ObjGlobal::load(f))
  935. {
  936. GetStr(f, T.name);
  937. return loadData(f);
  938. }break;
  939. case 0:
  940. {
  941. RectI area; f>>area; GetStr(f, T.name);
  942. }return loadData(f);
  943. }
  944. return false;
  945. }
  946. bool EE1EditLake::load(File &f, C Str &name)
  947. {
  948. if(id.fromHex(name))if(::EE1ObjGlobal::load(f))switch(f.decUIntV())
  949. {
  950. case 0:
  951. {
  952. f>>depth;
  953. polys.clear(); REP(f.getInt()){Memc<Vec> &poly=polys.New(); poly.setNum(f.getInt()); FREPA(poly)f>>poly[i];}
  954. GetStr(f, material);
  955. }return true;
  956. }
  957. return false;
  958. }
  959. bool EE1EditRiver::load(File &f, C Str &name)
  960. {
  961. if(id.fromHex(name))if(::EE1ObjGlobal::load(f))switch(f.decUIntV())
  962. {
  963. case 0:
  964. {
  965. f>>depth;
  966. vtxs .setNum(f.getInt()); FREPA(vtxs )f>>vtxs [i];
  967. edges.setNum(f.getInt()); FREPA(edges)f>>edges[i];
  968. GetStr(f, material);
  969. }return true;
  970. }
  971. return false;
  972. }
  973. EE1EditWaypoint::EE1EditWaypoint() : id(UIDZero) {}
  974. EE1EditLake::EE1EditLake() : id(UIDZero), depth(1) {}
  975. EE1EditRiver::EE1EditRiver() : id(UIDZero), depth(1) {}
  976. /******************************************************************************/