Esenthel Builder.cpp 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. using namespace Edit;
  4. /******************************************************************************/
  5. Str VSPath=""; // leave empty for auto-detect or type full path like this: "C:/Program Files (x86)/Microsoft Visual Studio 14.0"
  6. Str AndroidNDKPath=""; // leave empty for auto-detect or type full path like this: "C:/Progs/AndroidNDK"
  7. Str EngineDataPath="Data/"; // this will get updated to full path
  8. Str EditorDataPath="Editor Data/"; // this will get updated to full path
  9. Str EnginePath="Engine/"; // this will get updated to full path
  10. Str EditorPath="Editor/"; // this will get updated to full path
  11. Str EditorSourcePath="Editor Source/_Build_/Esenthel/"; // this will get updated to full path
  12. Str ThirdPartyLibsPath="ThirdPartyLibs/"; // this will get updated to full path
  13. Str EsenthelPath; // this will be set to Esenthel Root full path
  14. const Str VSEngineProject="EsenthelEngine.sln";
  15. const Str VSEditorProject="Project.sln";
  16. const Str XcodeEngineProject="EsenthelEngine.xcodeproj";
  17. const Str XcodeEditorProject="Project.xcodeproj";
  18. const Str LinuxEngineProject="Linux/"; // if not empty then should include tail slash
  19. const Str LinuxEditorProject=""; // if not empty then should include tail slash
  20. const Str AndroidProject="Android/"; // if not empty then should include tail slash
  21. const Str OptionsFileName="Esenthel Builder.txt";
  22. /******************************************************************************/
  23. struct TaskBase;
  24. MemcThreadSafe<TaskBase*> Todo;
  25. struct TaskBase
  26. {
  27. CChar8 *name, *desc;
  28. void (*func)();
  29. Bool on, immediate;
  30. void call () {if(func)func();}
  31. void queue() {if(immediate)call();else Todo.include(this);}
  32. };
  33. struct Task
  34. {
  35. CheckBox cb;
  36. Button _queue;
  37. TaskBase *task;
  38. static void Queue(Task &task) {task.queue();}
  39. void queue( ) {if(task)task->queue();}
  40. void create(TaskBase &tb)
  41. {
  42. task=&tb;
  43. Gui+= cb .create().set(tb.on);
  44. Gui+=_queue.create(tb.name).func(Queue, T).desc(tb.desc);
  45. }
  46. void pos(Flt x, Flt y)
  47. {
  48. cb .rect(Rect_L(x , y, 0.05, 0.05));
  49. _queue.rect(Rect_L(x+0.06, y, 0.45, 0.05));
  50. Flt tw=_queue.textWidth(), rw=_queue.rect().w()-0.01; if(tw>rw)_queue.text_size*=rw/tw;
  51. }
  52. };
  53. /******************************************************************************/
  54. static CChar8 *Physics_t[]=
  55. {
  56. "PhysX (Recommended)", // 0
  57. "Bullet" , // 1
  58. }; ASSERT(PHYS_ENGINE_PHYSX==0 && PHYS_ENGINE_BULLET==1);
  59. void PhysXCompileWindows(Ptr=null);
  60. void PhysXCompileMac (Ptr=null);
  61. void PhysXCompileiOS (Ptr=null);
  62. void PhysXCompileLinux (Ptr=null);
  63. void PhysXCompileAndroid(Ptr=null);
  64. void PhysXCompileWeb (Ptr=null);
  65. void PhysXCompileAll (Ptr)
  66. {
  67. if(WINDOWS)PhysXCompileWindows();
  68. if(MAC )PhysXCompileMac ();
  69. if(MAC )PhysXCompileiOS ();
  70. if(LINUX )PhysXCompileLinux ();
  71. PhysXCompileAndroid();
  72. if(WINDOWS)PhysXCompileWeb ();
  73. }
  74. STRUCT(OptionsClass , ClosableWindow)
  75. //{
  76. Text t_vs_path, t_ndk_path, t_aac, t_physics;
  77. TextLine vs_path, ndk_path;
  78. CheckBox aac;
  79. ComboBox physics;
  80. Button physx_register, physx_download, physx_copy, physx_compile_win, physx_compile_mac, physx_compile_ios, physx_compile_linux, physx_compile_android, physx_compile_web, physx_compile_all, physx_del_temp, physx_del_lib, physx_recycle_all;
  81. static void OptionChanged(OptionsClass &options) {options.saveConfig();}
  82. static void PhysicsChanged(OptionsClass &options)
  83. {
  84. if(options.physics()==PHYS_ENGINE_PHYSX)Gui.msgBox(S, "PhysX License doesn't allow its source/libraries to be redistributed. In order to compile the Engine with PhysX support, you will have to download and compile it using the buttons below.");
  85. options.setVis();
  86. options.saveConfig();
  87. }
  88. static void PhysXRegister(OptionsClass &options) {Explore("https://developer.nvidia.com/gameworks-source-github");} // https://developer.nvidia.com/developer-program/signup, https://developer.nvidia.com/content/apply-access-nvidia-physx-source-code
  89. static void PhysXDownload(OptionsClass &options) {Explore("https://github.com/NVIDIAGameWorks/PhysX-3.4");}
  90. static void PhysXCopy (OptionsClass &options) {Explore(ThirdPartyLibsPath+"PhysX");}
  91. static void PhysXDelTemp (Ptr)
  92. {
  93. // Windows
  94. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win64/.vs");
  95. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win64/Debug");
  96. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win64/x64");
  97. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win64/Emscripten");
  98. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win64/vc140.pdb");
  99. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win32/.vs");
  100. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win32/Debug");
  101. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win32/Win32");
  102. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/vc14win32/vc140.pdb");
  103. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win64/.vs");
  104. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win64/Debug");
  105. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win64/x64");
  106. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win64/Emscripten");
  107. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win64/vc140.pdb");
  108. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win32/.vs");
  109. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win32/Debug");
  110. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win32/Win32");
  111. FDel(ThirdPartyLibsPath+"PhysX/PxShared/src/compiler/vc14win32/vc140.pdb");
  112. // FIXME delete web/ARM/UWP
  113. // Android, keep other *.o files as they're needed for linking with the Engine
  114. FDel(ThirdPartyLibsPath+"PhysX/Android/obj/local/arm64-v8a/libPhysX.a");
  115. FDel(ThirdPartyLibsPath+"PhysX/Android/obj/local/armeabi-v7a/libPhysX.a");
  116. FDel(ThirdPartyLibsPath+"PhysX/Android/obj/local/x86/libPhysX.a");
  117. // Mac/iOS
  118. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_osx64/build");
  119. FDel(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_ios64/build");
  120. // Linux is not deleted because *.o files are needed for linking with the Engine and *.a for Project
  121. }
  122. static void PhysXRecycle(Ptr)
  123. {
  124. for(FileFind ff(ThirdPartyLibsPath+"PhysX"); ff(); )if(ff.name!="Dummy" && ff.name!="Android")if(!FRecycle(ff.pathName()))ErrorDel(ff.pathName());
  125. FDelDirs(ThirdPartyLibsPath+"PhysX/Android/obj");
  126. }
  127. void setVis()
  128. {
  129. physx_register .visible(physics()==PHYS_ENGINE_PHYSX);
  130. physx_download .visible(physics()==PHYS_ENGINE_PHYSX);
  131. physx_copy .visible(physics()==PHYS_ENGINE_PHYSX);
  132. physx_compile_win .visible(physics()==PHYS_ENGINE_PHYSX);
  133. physx_compile_mac .visible(physics()==PHYS_ENGINE_PHYSX);
  134. physx_compile_ios .visible(physics()==PHYS_ENGINE_PHYSX);
  135. physx_compile_linux .visible(physics()==PHYS_ENGINE_PHYSX);
  136. physx_compile_android.visible(physics()==PHYS_ENGINE_PHYSX);
  137. physx_compile_web .visible(physics()==PHYS_ENGINE_PHYSX);
  138. physx_compile_all .visible(physics()==PHYS_ENGINE_PHYSX);
  139. physx_del_temp .visible(physics()==PHYS_ENGINE_PHYSX);
  140. physx_del_lib .visible(physics()==PHYS_ENGINE_PHYSX);
  141. physx_recycle_all .visible(physics()==PHYS_ENGINE_PHYSX);
  142. }
  143. void create()
  144. {
  145. Gui+=super::create(Rect_C(0, 0, 1.4, 0.60), "Options").hide(); button[2].show();
  146. Flt y=-0.05, h=0.06;
  147. T+=t_vs_path .create(Vec2(0.19, y), "Visual Studio Path"); T+= vs_path.create(Rect_L(0.38, y, 1.0, 0.05)); y-=h;
  148. T+=t_ndk_path.create(Vec2(0.19, y), "Android NDK Path"); T+=ndk_path.create(Rect_L(0.38, y, 1.0, 0.05)); y-=h;
  149. T+=t_aac .create(Vec2(0.19, y), "Use Patented AAC"); T+=aac.create(Rect_L(0.38, y, 0.05, 0.05)).func(OptionChanged, T).desc("If support AAC decoding which is currently covered by patents.\nIf disabled then playback of AAC sounds will not be available."); y-=h;
  150. T+=t_physics .create(Vec2(0.19, y), "Physics Engine"); T+=physics .create(Rect_L(0.38, y, 1.0, 0.05), Physics_t, Elms(Physics_t)).func(PhysicsChanged, T).set(PHYS_ENGINE_BULLET, QUIET); y-=h;
  151. T+=physx_register.create(Rect_L( 0.02, y, 0.50, 0.05), "1. Register to Access PhysX").func(PhysXRegister, T);
  152. T+=physx_download.create(Rect_L(physx_register.rect().max.x+0.01, y, 0.35, 0.05), "2. Download PhysX").func(PhysXDownload, T);
  153. T+=physx_copy .create(Rect_L(physx_download.rect().max.x+0.01, y, 0.35, 0.05), "3. Place PhysX here").func(PhysXCopy, T); y-=h;
  154. Flt x=0.02;
  155. if(WINDOWS){T+=physx_compile_win .create(Rect_L(x, y, 0.48, 0.05), "Compile PhysX for Windows").func(PhysXCompileWindows); x=physx_compile_win .rect().max.x+0.01;}
  156. if(MAC ){T+=physx_compile_mac .create(Rect_L(x, y, 0.41, 0.05), "Compile PhysX for Mac" ).func(PhysXCompileMac ); x=physx_compile_mac .rect().max.x+0.01;}
  157. if(MAC ){T+=physx_compile_ios .create(Rect_L(x, y, 0.41, 0.05), "Compile PhysX for iOS" ).func(PhysXCompileiOS ); x=physx_compile_ios .rect().max.x+0.01;}
  158. if(LINUX ){T+=physx_compile_linux .create(Rect_L(x, y, 0.43, 0.05), "Compile PhysX for Linux" ).func(PhysXCompileLinux ); x=physx_compile_linux .rect().max.x+0.01;}
  159. {T+=physx_compile_android.create(Rect_L(x, y, 0.46, 0.05), "Compile PhysX for Android").func(PhysXCompileAndroid); x=physx_compile_android.rect().max.x+0.01;}
  160. //if(WINDOWS){T+=physx_compile_web .create(Rect_L(x, y, 0.40, 0.05), "Compile PhysX for Web" ).func(PhysXCompileWeb ); x=physx_compile_web .rect().max.x+0.01;} FIXME
  161. y-=h;
  162. T+=physx_compile_all .create(Rect_C(clientWidth()/2, y, clientWidth()-0.02*2, 0.05), "Compile PhysX for All").func(PhysXCompileAll);
  163. y-=h*1.5;
  164. T+=physx_del_temp .create(Rect_L( 0.02, y, 0.46, 0.05), "Delete PhysX Temporaries" ).func(PhysXDelTemp).desc("This will delete all temporary files that were generated during compilation process, they're not needed anymore after successful compilation and can be deleted to free up disk space.");
  165. //T+=physx_del_lib .create(Rect_L(physx_del_temp.rect().max.x+0.01, y, 0.47, 0.05), "Delete PhysX Libraries" ).func(PhysXDelLib ).desc("This will delete all libraries that were generated during compilation process, you can use this if you don't want to use PhysX anymore.");
  166. T+=physx_recycle_all.create(Rect_L(physx_del_temp.rect().max.x+0.01, y, 0.48, 0.05), "Recycle Entire PhysX folder").func(PhysXRecycle).desc("This will move all PhysX folder contents into the Recycle Bin, you can use this if you don't want to use PhysX anymore or you want to make a fresh reinstall of PhysX to its latest version.");
  167. load();
  168. loadConfig();
  169. saveConfig(); // always save
  170. setVis();
  171. }
  172. Bool any()C
  173. {
  174. return vs_path().is() || ndk_path().is();
  175. }
  176. void load()
  177. {
  178. TextData data; if(data.load(OptionsFileName))
  179. {
  180. if(TextParam *param=data.findNode("Visual Studio Path")) vs_path.set(param->asText());
  181. if(TextParam *param=data.findNode( "Android NDK Path"))ndk_path.set(param->asText());
  182. }
  183. }
  184. void save()C
  185. {
  186. if(any())
  187. {
  188. TextData data;
  189. if( vs_path().is())data.nodes.New().set("Visual Studio Path", vs_path());
  190. if(ndk_path().is())data.nodes.New().set( "Android NDK Path", ndk_path());
  191. data.save(OptionsFileName);
  192. }else
  193. {
  194. FDelFile(OptionsFileName);
  195. }
  196. }
  197. static Str EsenthelConfig() {return EnginePath+"Esenthel Config.h";}
  198. void loadConfig()
  199. {
  200. FileText f; if(f.read(EsenthelConfig()))
  201. {
  202. Str s; f.getAll(s);
  203. aac .set(Contains(s, "SUPPORT_AAC 1"), QUIET);
  204. physics.set(Contains(s, "PHYSX 1") ? PHYS_ENGINE_PHYSX : PHYS_ENGINE_BULLET, QUIET); // remember that PhysX can be enabled only for certain platforms, so check if there's at least one "PHYSX 1" occurrence
  205. }else
  206. {
  207. activate(); // if no config available then show options
  208. }
  209. }
  210. void saveConfig()C
  211. {
  212. Str s=S+"// File automatically generated by \""+App.name()+"\"\n";
  213. s+=S+"#define SUPPORT_AAC "+aac()+'\n';
  214. //s+="#define PHYSX "+(physics()==PHYS_ENGINE_PHYSX)+'\n';
  215. if(physics()==PHYS_ENGINE_PHYSX)
  216. {
  217. s+="#if !IOS_SIMULATOR && !WINDOWS_NEW && !WEB\n"
  218. " #define PHYSX 1\n"
  219. "#else\n"
  220. " #define PHYSX 0\n"
  221. "#endif\n";
  222. }else s+="#define PHYSX 0\n";
  223. FileText f; f.writeMem(ANSI).putText(s);
  224. Bool changed; if(!OverwriteOnChange(f, EsenthelConfig(), &changed)){ErrorWrite(EsenthelConfig()); return;}
  225. if( changed)FTimeUTC(EnginePath+"H/_/Esenthel Config.h", DateTime().getUTC()); // set modification time to the default config as well, to make sure to force rebuild (this is needed for VS and possibly others too)
  226. }
  227. }Options;
  228. /******************************************************************************/
  229. Str DevEnvPath(C Str &vs_path)
  230. {
  231. if(vs_path.is())
  232. {
  233. Str devenv=Str(vs_path).tailSlash(true)+"Common7\\IDE\\devenv.exe" ; if(FExistSystem(devenv))return devenv; // pro
  234. devenv=Str(vs_path).tailSlash(true)+"Common7\\IDE\\VCExpress.exe"; if(FExistSystem(devenv))return devenv; // express
  235. devenv=Str(vs_path).tailSlash(true)+"Common7\\IDE\\WDExpress.exe"; if(FExistSystem(devenv))return devenv; // express for Windows Desktop
  236. }
  237. return S;
  238. }
  239. Str DevEnvPath()
  240. {
  241. if(Options.vs_path().is()){Str p=DevEnvPath(Options.vs_path()); if(p.is())return p;}
  242. if( VSPath.is()){Str p=DevEnvPath( VSPath ); if(p.is())return p;}
  243. return S;
  244. }
  245. Str NDKBuildPath(C Str &ndk_path)
  246. {
  247. if(ndk_path.is())
  248. {
  249. Str ndk_build=Str(ndk_path).tailSlash(true)+PLATFORM("ndk-build.cmd", "ndk-build");
  250. if(FExistSystem(ndk_build))return ndk_build;
  251. }
  252. return S;
  253. }
  254. Str NDKBuildPath()
  255. {
  256. if(Options.ndk_path().is()){Str p=NDKBuildPath(Options.ndk_path()); if(p.is())return p;}
  257. if( AndroidNDKPath.is()){Str p=NDKBuildPath( AndroidNDKPath ); if(p.is())return p;}
  258. return S;
  259. }
  260. Str ARPath()
  261. {
  262. #if WINDOWS
  263. return EnginePath+AndroidProject+"cygwin/ar.exe";
  264. #else
  265. return "ar";
  266. #endif
  267. }
  268. /******************************************************************************/
  269. Bool shut; // if 'Shut' called
  270. Int failed, // number of failures (like compilation thread failes)
  271. done;
  272. SyncLock lock;
  273. // BUILD OUTPUT
  274. Memc<Str> data, // list data
  275. data_new; // data currently added on a secondary thread, and to be added to the main data on the main thread
  276. List<Str> list; // list
  277. Region region; // region
  278. Button clear, copy;
  279. struct Build
  280. {
  281. Str exe, params, log;
  282. void (*pre)(), (*func)();
  283. Build& set (C Str &exe, C Str &params, C Str &log=S) {T.exe=exe; T.params=params; T.log=log; return T;}
  284. Build& set (void func() ) {T.func=func; return T;}
  285. Build& setPre(void func() ) {T.pre =func; return T;}
  286. Build() {pre=func=null;}
  287. static Str GetOutput(ConsoleProcess &cp, C Str &log, Str &processed)
  288. {
  289. Str out=cp.get();
  290. if(log.is())
  291. {
  292. FileText f; if(f.read(log))
  293. {
  294. Str all=f.getAll();
  295. out+=SkipStart(all, processed);
  296. processed=all;
  297. }
  298. }
  299. return out;
  300. }
  301. Bool run()
  302. {
  303. Bool ok=true;
  304. if(pre)pre();
  305. if(exe.is())
  306. {
  307. FDelFile(log);
  308. ConsoleProcess cp; cp.create(exe, params);
  309. Str processed, output; Memc<Str> outs;
  310. if(log.is())output="Compile start\n";
  311. for(; cp.active(); )
  312. {
  313. if(shut){cp.kill(); break;}
  314. cp.wait(25);
  315. output+=GetOutput(cp, log, processed);
  316. Split(outs, output, '\n');
  317. if(outs.elms()>=2)
  318. {
  319. SyncLocker locker(lock);
  320. for(; outs.elms()>=2; )
  321. {
  322. Swap(data_new.New(), outs[0]); outs.remove(0, true);
  323. }
  324. output=outs.last();
  325. }
  326. }
  327. ok=(cp.exitCode()==0);
  328. output+=GetOutput(cp, log, processed);
  329. ok|=(Contains(output, "========== Build: 1 succeeded") || Contains(output, "========== Build: 0 succeeded, 0 failed, 1 up-to-date"));
  330. Split(outs, output, '\n');
  331. {
  332. SyncLocker locker(lock);
  333. FREPA(outs)if(outs[i].is())Swap(data_new.New(), outs[i]);
  334. }
  335. cp.del();
  336. if(!ok)
  337. {
  338. // fail
  339. Gui.msgBox("Error", "Compilation failed.\nTasks aborted.");
  340. Todo.clear();
  341. }
  342. FDelFile(log);
  343. }
  344. if(ok && func)func();
  345. return ok;
  346. }
  347. };
  348. /******************************************************************************/
  349. Memb<Build> build_requests; // builds requested to be processed on secondary threads
  350. Threads build_threads;
  351. Memx<Task> Tasks;
  352. CheckBox All;
  353. Button DoSel, OptionsButton;
  354. /******************************************************************************/
  355. void OptionsToggle(Ptr) {Options.visibleToggleActivate();}
  356. void ToggleAll(Ptr) {REPAO(Tasks).cb.set(All());}
  357. void CopyOutput(Ptr) {Str s; FREPA(data){s+=data[i]; s+='\n';} ClipSet(s);}
  358. void Clear(Ptr) {list.setData(data.clear());}
  359. void DoSelected(Ptr) {FREPA(Tasks)if(Tasks[i].cb())Tasks[i].queue();}
  360. void BuildRun(Build &build, Ptr user, Int thread_index) {build.run();}
  361. /******************************************************************************/
  362. CChar8 *separator="/******************************************************************************/";
  363. CChar8 *copyright="/******************************************************************************\r\n"
  364. " * Copyright (c) Grzegorz Slazinski. All Rights Reserved. *\r\n"
  365. " * Esenthel Engine (http://www.esenthel.com) header file. *\r\n";
  366. /******************************************************************************/
  367. FILE_LIST_MODE Header(C FileFind &ff, Ptr)
  368. {
  369. if(ff.type==FSTD_FILE)if(ff.name!="Esenthel Config.h")
  370. {
  371. Str name=ff.pathName();
  372. // read from source file
  373. FileText f; f.read(name);
  374. Meml<Str> src; for(; !f.end(); )src.New()=f.fullLine();
  375. // remove empty line followed by "#ifdef"
  376. //SMFREP(src)if(_next_ && !SkipWhiteChars(src[i]).is() && Contains(src[_next_], "#ifdef"))src.remove(i);
  377. // hide EE_PRIVATE sections
  378. enum STACK_TYPE
  379. {
  380. STACK_NONE ,
  381. STACK_PRIVATE ,
  382. STACK_NOT_PRIVATE,
  383. };
  384. Memb<STACK_TYPE> stack ; // #if stack
  385. Int level=0; // EE_PRIVATE depth level
  386. for(MemlNode *node=src.first(); node;)
  387. {
  388. MemlNode *next=node->next();
  389. C Str &s =src[node];
  390. Str first=SkipWhiteChars(s);
  391. if(first.first()=='#') // if preprocessor command
  392. {
  393. if(Starts(first, "#if")) // #if #ifdef #ifndef
  394. {
  395. if(Starts(first, "#if EE_PRIVATE"))
  396. {
  397. stack.add(STACK_PRIVATE);
  398. level++;
  399. src.remove(node);
  400. }else
  401. if(Starts(first, "#if !EE_PRIVATE"))
  402. {
  403. stack.add(STACK_NOT_PRIVATE);
  404. src.remove(node);
  405. }else
  406. {
  407. stack.add(STACK_NONE);
  408. if(level)src.remove(node);
  409. }
  410. }else
  411. if(Starts(first, "#el")) // #else #elif
  412. {
  413. if(stack.elms() && stack.last()==STACK_PRIVATE)
  414. {
  415. stack.last()=STACK_NOT_PRIVATE; // #if !EE_PRIVATE
  416. level--;
  417. src.remove(node);
  418. }else
  419. if(stack.elms() && stack.last()==STACK_NOT_PRIVATE)
  420. {
  421. stack.last()=STACK_PRIVATE;
  422. level++;
  423. src.remove(node);
  424. }else
  425. {
  426. if(level)src.remove(node);
  427. }
  428. }else
  429. if(Starts(first, "#endif"))
  430. {
  431. if(stack.elms())
  432. {
  433. if(stack.last() || level)src.remove(node);
  434. if(stack.last()==STACK_PRIVATE)
  435. {
  436. level--;
  437. if(!level)
  438. {
  439. if(next->prev())
  440. {
  441. Str a=src[next->prev()],
  442. b=src[next ];
  443. if(!SkipWhiteChars(a).is() && Contains(b, separator))src.remove(next->prev());else // remove empty line followed by /**/
  444. if(!SkipWhiteChars(b).is() && Contains(a, separator)) // remove empty line preceeded by /**/
  445. {
  446. MemlNode *temp=next->next(); src.remove(next); next=temp;
  447. }
  448. }
  449. }
  450. }
  451. stack.removeLast();
  452. }else
  453. {
  454. Exit(S+"Invalid #endif at \""+name+'"');
  455. }
  456. }else
  457. {
  458. if(level)src.remove(node);
  459. }
  460. }else
  461. {
  462. if(level)src.remove(node);
  463. }
  464. node=next;
  465. }
  466. // remove double lines /**/
  467. SMFREP(src)if(_next_ && Contains(src[i], separator) && Equal(src[i], src[_next_]))src.remove(i);
  468. // remove double empty lines
  469. SMFREP(src)if(_next_ && !SkipWhiteChars(src[i]).is() && !SkipWhiteChars(src[_next_]).is())src.remove(i);
  470. // remove empty line followed by "}"
  471. SMFREP(src)if(_next_ && !SkipWhiteChars(src[i]).is() && Starts(SkipWhiteChars(src[_next_]), "}"))src.remove(i);
  472. // remove empty line preceeded by "}"
  473. SMFREP(src)if(!SkipWhiteChars(src[i]).is() && i->prev() && Starts(SkipWhiteChars(src[i->prev()]), "{"))src.remove(i);
  474. // write to destination file
  475. Str dest=EditorPath+"Bin/EsenthelEngine/"+SkipStartPath(name, EnginePath+"H"); FCreateDirs(GetPath(dest));
  476. f.write (dest);
  477. f.putText(copyright);
  478. MFREP(src)f.putLine(src[i]);
  479. f.del ();
  480. FTimeUTC(dest, ff.modify_time_utc);
  481. }
  482. return FILE_LIST_CONTINUE;
  483. }
  484. /******************************************************************************/
  485. static void Copy(C Str &src, C Str &dest, FILE_OVERWRITE_MODE overwrite=FILE_OVERWRITE_DIFFERENT)
  486. {
  487. if(!FCopy(src, dest, overwrite))
  488. {
  489. Gui.msgBox("Error", S+"Can't copy:\n\""+src+"\"\nto \n\""+dest+"\".\nTasks aborted.");
  490. Todo.clear();
  491. }
  492. }
  493. static void Del(C Str &name)
  494. {
  495. if(FExistSystem(name) && !FDel(name))
  496. {
  497. Gui.msgBox("Error", S+"Can't delete:\n\""+name+"\".\nTasks aborted.");
  498. Todo.clear();
  499. }
  500. }
  501. static void ReplaceDir(C Str &src, C Str &dest, FILE_OVERWRITE_MODE overwrite=FILE_OVERWRITE_DIFFERENT)
  502. {
  503. if(!FReplaceDir(src, dest, overwrite))
  504. {
  505. Gui.msgBox("Error", S+"Can't copy:\n\""+src+"\"\nto \n\""+dest+"\".\nTasks aborted.");
  506. Todo.clear();
  507. }
  508. }
  509. void CleanEngineLinuxDo()
  510. {
  511. FDel(EnginePath+LinuxEngineProject+"build");
  512. FDel(EnginePath+LinuxEngineProject+"dist");
  513. FDel(EnginePath+"stdafx.h.gch");
  514. FDel(EnginePath+"stdafx.h.pch");
  515. }
  516. void CleanEditorLinuxDo()
  517. {
  518. FDel(EditorSourcePath+LinuxEditorProject+"build");
  519. FDel(EditorSourcePath+"stdafx.h.gch");
  520. FDel(EditorSourcePath+"stdafx.h.pch");
  521. }
  522. void CleanLinuxDo()
  523. {
  524. CleanEngineLinuxDo();
  525. CleanEditorLinuxDo();
  526. }
  527. void CleanEngineWebDo()
  528. {
  529. FDel(EnginePath+"Emscripten");
  530. }
  531. void MakeWebLibs()
  532. {
  533. Str dest=EditorPath+"Bin/EsenthelEngine.bc";
  534. FDelFile(dest);
  535. Str params;
  536. params.space()+=S+'"'+EnginePath +"EsenthelEngine.bc\"";
  537. //params.space()+=S+'"'+ThirdPartyLibsPath+"Brotli/Windows/Emscripten/Release/Brotli.bc\"";
  538. params.space()+=S+'"'+ThirdPartyLibsPath+"Bullet/Windows/Emscripten/Release/BulletCollision.bc\"";
  539. params.space()+=S+'"'+ThirdPartyLibsPath+"Bullet/Windows/Emscripten/Release/BulletDynamics.bc\"";
  540. params.space()+=S+'"'+ThirdPartyLibsPath+"Bullet/Windows/Emscripten/Release/LinearMath.bc\"";
  541. params.space()+=S+'"'+ThirdPartyLibsPath+"FDK-AAC/Windows/Emscripten/Release/FDK-AAC.bc\"";
  542. params.space()+=S+'"'+ThirdPartyLibsPath+"Flac/Windows/Emscripten/Release/FLAC.bc\"";
  543. params.space()+=S+'"'+ThirdPartyLibsPath+"JpegTurbo/Web/Emscripten/Release/turbojpeg-static.bc\"";
  544. params.space()+=S+'"'+ThirdPartyLibsPath+"LZ4/Windows/Emscripten/Release/LZ4.bc\"";
  545. params.space()+=S+'"'+ThirdPartyLibsPath+"LZHAM/Windows/Emscripten/Release/LZHAM.bc\"";
  546. params.space()+=S+'"'+ThirdPartyLibsPath+"LZMA/Windows/Emscripten/Release/Lzma.bc\"";
  547. params.space()+=S+'"'+ThirdPartyLibsPath+"Ogg/Windows/Emscripten/Release/Ogg.bc\"";
  548. params.space()+=S+'"'+ThirdPartyLibsPath+"Opus/Windows/Emscripten/Release/celt.bc\"";
  549. params.space()+=S+'"'+ThirdPartyLibsPath+"Opus/Windows/Emscripten/Release/opus.bc\"";
  550. params.space()+=S+'"'+ThirdPartyLibsPath+"Opus/Windows/Emscripten/Release/silk_common.bc\"";
  551. params.space()+=S+'"'+ThirdPartyLibsPath+"Opus/Windows/Emscripten/Release/silk_float.bc\"";
  552. params.space()+=S+'"'+ThirdPartyLibsPath+"Opus/file/win32/VS2010/Emscripten/Release/opusfile.bc\"";
  553. params.space()+=S+'"'+ThirdPartyLibsPath+"Png/Windows/Emscripten/LIB Release/Png.bc\"";
  554. params.space()+=S+'"'+ThirdPartyLibsPath+"Recast/Windows/Emscripten/Release/Recast.bc\"";
  555. params.space()+=S+'"'+ThirdPartyLibsPath+"Snappy/Windows/Emscripten/Release/snappy.bc\"";
  556. params.space()+=S+'"'+ThirdPartyLibsPath+"SQLite/Windows/Emscripten/Release/SQLite.bc\"";
  557. params.space()+=S+'"'+ThirdPartyLibsPath+"Theora/Windows/Emscripten/Release/Theora.bc\"";
  558. params.space()+=S+'"'+ThirdPartyLibsPath+"Vorbis/Windows/Emscripten/Release/Vorbis.bc\"";
  559. params.space()+=S+'"'+ThirdPartyLibsPath+"Vorbis/Windows/Emscripten/Release/Vorbis File.bc\"";
  560. params.space()+=S+'"'+ThirdPartyLibsPath+"Webp/Windows/Emscripten/Release/WebP.bc\"";
  561. params.space()+=S+'"'+ThirdPartyLibsPath+"Zlib/Windows/Emscripten/Release/Zlib.bc\"";
  562. params.space()+=S+'"'+ThirdPartyLibsPath+"Zstd/Windows/bin/Emscripten/Release/zstdlib.bc\"";
  563. //if(Options.physics()==PHYS_ENGINE_PHYSX)params.space()+=S+'"'+ThirdPartyLibsPath+"PhysX/../PhysX.bc\""; FIXME
  564. params.space()+=S+"-o \""+dest+'"';
  565. Build().set("emcc.bat", params).run();
  566. if(!FExistSystem(dest))Gui.msgBox("Error", "Can't create Esenthel Web Lib BitCode");
  567. }
  568. /******************************************************************************/
  569. void TestDirForObjFiles(C Str &name, Str &obj_files)
  570. {
  571. if(FileFind(name, "o")()) // if it has any *.o files inside
  572. obj_files.space()+=Replace(UnixPath(name+"/*.o"), " ", "\\ ");
  573. }
  574. FILE_LIST_MODE GatherObjFiles(C FileFind &ff, Str &obj_files)
  575. {
  576. if(ff.type==FSTD_DIR)TestDirForObjFiles(ff.pathName(), obj_files);
  577. return FILE_LIST_CONTINUE;
  578. }
  579. void MakeLinuxLibs()
  580. {
  581. Str engine_lib=EditorPath+"Bin/EsenthelEngine.a";
  582. FDelFile(engine_lib);
  583. // get a list of all possible libraries
  584. Memc<Str> lib_paths;
  585. lib_paths.add(EnginePath+LinuxEngineProject+"build/Release"); // Esenthel Engine
  586. lib_paths.add(ThirdPartyLibsPath+"PVRTC/PVRTex/Linux_x86_64/Static/build/Release"); // PVRTC (because it's stored inside a separate folder)
  587. lib_paths.add(ThirdPartyLibsPath+"VP/Linux"); // VP (because it's manually built)
  588. if(Options.physics()==PHYS_ENGINE_PHYSX)lib_paths.add(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/linux64/build"); // PhysX (because it's stored inside a separate folder and should be linked only if PhysX is selected as physics engine)
  589. // iterate all Third Party Libs
  590. for(FileFind ff(ThirdPartyLibsPath); ff(); )if(ff.type==FSTD_DIR)lib_paths.add(ff.pathName()+"/Linux/build/Release");
  591. // get all *.o files from those paths
  592. Str obj_files; FREPA(lib_paths){TestDirForObjFiles(lib_paths[i], obj_files); FList(lib_paths[i], GatherObjFiles, obj_files);}
  593. // make lib
  594. Build().set(ARPath(), S+"-q \""+UnixPath(engine_lib)+"\" "+obj_files).run();
  595. if(!FExistSystem(engine_lib))Gui.msgBox("Error", "Can't create Esenthel Linux Lib");
  596. }
  597. Str EngineAndroidLibName(C Str &abi) {return EditorPath+"Bin/Android/EsenthelEngine-"+abi+".a";}
  598. void MakeAndroidLibs(C Str &abi)
  599. {
  600. Str engine_lib=EngineAndroidLibName(abi);
  601. FDelFile(engine_lib);
  602. // get a list of all possible libraries
  603. Memc<Str> lib_paths;
  604. lib_paths.add(EnginePath+AndroidProject+"obj/local/"+abi); // Esenthel Engine
  605. // iterate all Third Party Libs
  606. for(FileFind ff(ThirdPartyLibsPath); ff(); )if(ff.type==FSTD_DIR)
  607. if(Options.physics()==PHYS_ENGINE_PHYSX || ff.name!="PhysX") // link PhysX only if we want it
  608. lib_paths.add(ff.pathName()+"/Android/obj/local/"+abi);
  609. // get all *.o files from those paths
  610. Str obj_files; FREPA(lib_paths){TestDirForObjFiles(lib_paths[i], obj_files); FList(lib_paths[i], GatherObjFiles, obj_files);}
  611. // make lib
  612. if(FExistSystem(engine_lib))Gui.msgBox("Error", S+"Can't remove Esenthel Android "+abi+" Lib");else
  613. {
  614. Str params=S+"-q \""+UnixPath(engine_lib)+"\" "+obj_files;
  615. if(WINDOWS && params.length()>=32000)Gui.msgBox("Warning", "Command Line may exceed Windows 32768 character limit");
  616. if(Build().set(ARPath(), params).run())
  617. {
  618. if(!FExistSystem(engine_lib))Gui.msgBox("Error", S+"Can't create Esenthel Android "+abi+" Lib");
  619. }else
  620. {
  621. Explore(engine_lib); // creating archive can sometimes fail, in that case there's a temp generated file that needs to be deleted manually
  622. }
  623. }
  624. }
  625. void MakeAndroidLibs()
  626. {
  627. // #AndroidArchitecture
  628. MakeAndroidLibs("armeabi-v7a");
  629. MakeAndroidLibs("arm64-v8a");
  630. #if 0
  631. MakeAndroidLibs("x86");
  632. #else
  633. FDelFile(EngineAndroidLibName("x86"));
  634. #endif
  635. }
  636. /******************************************************************************/
  637. void UpdateHeaders()
  638. {
  639. // process engine headers
  640. FDelDirs(EditorPath+"Bin/EsenthelEngine"); // delete
  641. FList(EnginePath+"H", Header); // convert
  642. }
  643. /******************************************************************************/
  644. // ENGINE PAK
  645. /******************************************************************************/
  646. static Bool DesktopEnginePakFilter(C Str &full)
  647. {
  648. Str name=SkipStartPath(full, EngineDataPath), base=GetBase(name), path=GetPath(name);
  649. if(!SUPPORT_MLAA && base=="MLAA Area.img")return false;
  650. return true;
  651. }
  652. static Bool UniversalEnginePakFilter(C Str &full)
  653. {
  654. Str name=SkipStartPath(full, EngineDataPath), base=GetBase(name), path=GetPath(name);
  655. if(!SUPPORT_MLAA && base=="MLAA Area.img")return false;
  656. if(EqualPath(name, "Shader/3")
  657. || EqualPath(name, "Shader/GL")
  658. || base=="World Editor"
  659. )return false;
  660. return true;
  661. }
  662. static Bool MobileEnginePakFilter(C Str &full)
  663. {
  664. Str name=SkipStartPath(full, EngineDataPath), base=GetBase(name), path=GetPath(name);
  665. if(!SUPPORT_MLAA && base=="MLAA Area.img")return false;
  666. if(EqualPath(name, "Shader/3")
  667. || EqualPath(name, "Shader/4")
  668. || base=="World Editor"
  669. )return false;
  670. return true;
  671. }
  672. static DateTime LatestTime(C Pak &pak)
  673. {
  674. DateTime time; time.zero();
  675. REPA(pak)
  676. {
  677. C PakFile &pf=pak.file(i);
  678. if(!(pf.flag&PF_STD_DIR)) // not a directory
  679. if(pf.modify_time_utc>time)time=pf.modify_time_utc;
  680. }
  681. return time;
  682. }
  683. void CreateEnginePak()
  684. {
  685. // Desktop "Engine.pak"
  686. Str engine_pak_name=EditorPath+"Bin/Engine.pak";
  687. Pak engine_pak; if(!engine_pak.create(EngineDataPath, engine_pak_name, PAK_SHORTEN, null, null, COMPRESS_NONE, 9, DesktopEnginePakFilter))Gui.msgBox("Error", "Can't create Engine.pak");
  688. FTimeUTC(engine_pak_name, LatestTime(engine_pak)); // adjust pak date to latest date of its files
  689. // Windows Universal "Engine.pak"
  690. engine_pak_name=EditorPath+"Bin/Universal/Engine.pak";
  691. FCreateDir(GetPath(engine_pak_name));
  692. if(!engine_pak.create(EngineDataPath, engine_pak_name, PAK_SHORTEN, null, null, COMPRESS_NONE, 9, UniversalEnginePakFilter))Gui.msgBox("Error", "Can't create Universal Engine.pak");
  693. FTimeUTC(engine_pak_name, LatestTime(engine_pak)); // adjust pak date to latest date of its files
  694. // Mobile "Engine.pak"
  695. engine_pak_name=EditorPath+"Bin/Mobile/Engine.pak";
  696. FCreateDir(GetPath(engine_pak_name));
  697. if(!engine_pak.create(EngineDataPath, engine_pak_name, PAK_SHORTEN, null, null, COMPRESS_NONE, 9, MobileEnginePakFilter))Gui.msgBox("Error", "Can't create Mobile Engine.pak");
  698. FTimeUTC(engine_pak_name, LatestTime(engine_pak)); // adjust pak date to latest date of its files
  699. // Web "Engine.pak"
  700. engine_pak_name=EditorPath+"Bin/Web/Engine.pak";
  701. FCreateDir(GetPath(engine_pak_name));
  702. if(!engine_pak.create(EngineDataPath, engine_pak_name, PAK_SHORTEN, null, null, COMPRESS_LZ4, 9, MobileEnginePakFilter))Gui.msgBox("Error", "Can't create Web Engine.pak");
  703. FTimeUTC(engine_pak_name, LatestTime(engine_pak)); // adjust pak date to latest date of its files
  704. }
  705. /******************************************************************************/
  706. // EDITOR PAK
  707. /******************************************************************************/
  708. Bool FilterEditorPak(C Str &name)
  709. {
  710. Str engine=EngineDataPath+SkipStartPath(name, EditorDataPath);
  711. if(FileInfoSystem(engine).type==FSTD_FILE) // if file already exists in the Engine Data (Engine.pak) then skip (skip only files)
  712. {
  713. FRecycle(name); // remove to prevent uploading to GitHub
  714. return false;
  715. }
  716. return true;
  717. }
  718. void CreateEditorPak()
  719. {
  720. Str editor_pak_name=EditorPath+"Bin/Editor.pak";
  721. Pak editor_pak; if(!editor_pak.create(EditorDataPath, editor_pak_name, PAK_SHORTEN, null, null, COMPRESS_NONE, 9, FilterEditorPak))Gui.msgBox("Error", "Can't create Editor.pak");
  722. DateTime editor_pak_time; editor_pak_time.zero();
  723. if(editor_pak.totalFiles()) // adjust pak date to latest date of its files
  724. {
  725. REPA(editor_pak)
  726. {
  727. C PakFile &pf=editor_pak.file(i);
  728. if(!(pf.flag&PF_STD_DIR)) // not a directory
  729. {
  730. DateTime dt=pf.modify_time_utc;
  731. if(dt>editor_pak_time)editor_pak_time=dt;
  732. }
  733. }
  734. FTimeUTC(editor_pak_name, editor_pak_time);
  735. }
  736. }
  737. /******************************************************************************/
  738. void CompileVS(C Str &project, C Str &config, C Str &platform, void func()=null, void pre()=null)
  739. {
  740. Str msbuild=MSBuildPath(Options.vs_path().is() ? Options.vs_path() : VSPath); if(FExistSystem(msbuild) && !Contains(platform, "Emscripten") && !Contains(platform, "Web")) // MSBuild is not compatible with Emscripten
  741. {
  742. build_threads.queue(build_requests.New().set(msbuild, MSBuildParams(project, config, platform)).set(func).setPre(pre), BuildRun);
  743. }else
  744. {
  745. Str devenv=DevEnvPath();
  746. if(!devenv.is()){Options.show(); Gui.msgBox("Error", "Visual Studio Path unknown");}else
  747. {
  748. Str log=S+GetPath(App.exe())+"/vs_build_"+Replace(config+platform, ' ', '_')+".txt";
  749. build_threads.queue(build_requests.New().set(devenv, VSBuildParams(project, config, platform, log), log).set(func).setPre(pre), BuildRun);
  750. }
  751. }
  752. }
  753. void CleanXcode(C Str &project, C Str &config, C Str &platform, C Str &sdk=S)
  754. {
  755. build_threads.queue(build_requests.New().set("xcodebuild", XcodeBuildCleanParams(project, config, platform, sdk)), BuildRun);
  756. }
  757. void CompileXcode(C Str &project, C Str &config, C Str &platform, C Str &sdk=S, void func()=null)
  758. {
  759. build_threads.queue(build_requests.New().set("xcodebuild", XcodeBuildParams(project, config, platform, sdk)).set(func), BuildRun);
  760. }
  761. void CompileLinux(C Str &project, C Str &config, void func()=null)
  762. {
  763. build_threads.queue(build_requests.New().set("make", LinuxBuildParams(project, config)).set(func), BuildRun);
  764. }
  765. /******************************************************************************/
  766. void CopyEngineWindows64GL () {Copy(EnginePath+"EsenthelEngine64GL.lib" , EditorPath+"Bin/EsenthelEngine64DX11.lib");} // copy as DX11
  767. void CopyEngineWindows64DX9 () {Copy(EnginePath+"EsenthelEngine64DX9.lib" , EditorPath+"Bin/EsenthelEngine64DX9.lib");}
  768. void CopyEngineWindows32DX9 () {Copy(EnginePath+"EsenthelEngine32DX9.lib" , EditorPath+"Bin/EsenthelEngine32DX9.lib");}
  769. void CopyEngineWindows64DX11 () {Copy(EnginePath+"EsenthelEngine64DX11.lib", EditorPath+"Bin/EsenthelEngine64DX11.lib");}
  770. void CopyEngineWindows32DX11 () {Copy(EnginePath+"EsenthelEngine32DX11.lib", EditorPath+"Bin/EsenthelEngine32DX11.lib");}
  771. void CopyEngineWindowsUniversal64DX11 () {Copy(EnginePath+"EsenthelEngineUniversal64DX11.lib" , EditorPath+"Bin/EsenthelEngineUniversal64DX11.lib");}
  772. void CopyEngineWindowsUniversal32DX11 () {Copy(EnginePath+"EsenthelEngineUniversal32DX11.lib" , EditorPath+"Bin/EsenthelEngineUniversal32DX11.lib");}
  773. void CopyEngineWindowsUniversalArm32DX11() {Copy(EnginePath+"EsenthelEngineUniversalArm32DX11.lib", EditorPath+"Bin/EsenthelEngineUniversalArm32DX11.lib");}
  774. void CopyEngineDebugWindows64DX9 () {Copy(EnginePath+"EsenthelEngineDebug64DX9.lib" , EditorPath+"Bin/EsenthelEngine64DX9.lib");}
  775. void CopyEngineDebugWindows32DX9 () {Copy(EnginePath+"EsenthelEngineDebug32DX9.lib" , EditorPath+"Bin/EsenthelEngine32DX9.lib");}
  776. void CopyEngineDebugWindows64DX11 () {Copy(EnginePath+"EsenthelEngineDebug64DX11.lib", EditorPath+"Bin/EsenthelEngine64DX11.lib");}
  777. void CopyEngineDebugWindows32DX11 () {Copy(EnginePath+"EsenthelEngineDebug32DX11.lib", EditorPath+"Bin/EsenthelEngine32DX11.lib");}
  778. void CopyEngineDebugWindowsUniversal64DX11 () {Copy(EnginePath+"EsenthelEngineDebugUniversal64DX11.lib" , EditorPath+"Bin/EsenthelEngineUniversal64DX11.lib");}
  779. void CopyEngineDebugWindowsUniversal32DX11 () {Copy(EnginePath+"EsenthelEngineDebugUniversal32DX11.lib" , EditorPath+"Bin/EsenthelEngineUniversal32DX11.lib");}
  780. void CopyEngineDebugWindowsUniversalArm32DX11() {Copy(EnginePath+"EsenthelEngineDebugUniversalArm32DX11.lib", EditorPath+"Bin/EsenthelEngineUniversalArm32DX11.lib");}
  781. void CompileEngineWindows64GL () {CompileVS(EnginePath+VSEngineProject, "Release GL" , "1) 64 bit", CopyEngineWindows64GL);}
  782. void CompileEngineWindows64DX9 () {CompileVS(EnginePath+VSEngineProject, "Release DX9" , "1) 64 bit", CopyEngineWindows64DX9);}
  783. void CompileEngineWindows32DX9 () {CompileVS(EnginePath+VSEngineProject, "Release DX9" , "2) 32 bit", CopyEngineWindows32DX9);}
  784. void CompileEngineWindows64DX11 () {CompileVS(EnginePath+VSEngineProject, "Release DX11" , "1) 64 bit", CopyEngineWindows64DX11);}
  785. void CompileEngineWindows32DX11 () {CompileVS(EnginePath+VSEngineProject, "Release DX11" , "2) 32 bit", CopyEngineWindows32DX11);}
  786. void CompileEngineWindowsUniversal64DX11 () {CompileVS(EnginePath+VSEngineProject, "Release Universal DX11", "1) 64 bit", CopyEngineWindowsUniversal64DX11);}
  787. void CompileEngineWindowsUniversal32DX11 () {CompileVS(EnginePath+VSEngineProject, "Release Universal DX11", "2) 32 bit", CopyEngineWindowsUniversal32DX11);}
  788. void CompileEngineWindowsUniversalArm32DX11() {CompileVS(EnginePath+VSEngineProject, "Release Universal DX11", "3) ARM" , CopyEngineWindowsUniversalArm32DX11);}
  789. void CompileEngineWeb () {CompileVS(EnginePath+VSEngineProject, "Release GL" , "4) Web");}
  790. void CompileEngineDebugWindows64DX9 () {CompileVS(EnginePath+VSEngineProject, "Debug DX9" , "1) 64 bit", CopyEngineDebugWindows64DX9);}
  791. void CompileEngineDebugWindows32DX9 () {CompileVS(EnginePath+VSEngineProject, "Debug DX9" , "2) 32 bit", CopyEngineDebugWindows32DX9);}
  792. void CompileEngineDebugWindows64DX11 () {CompileVS(EnginePath+VSEngineProject, "Debug DX11" , "1) 64 bit", CopyEngineDebugWindows64DX11);}
  793. void CompileEngineDebugWindows32DX11 () {CompileVS(EnginePath+VSEngineProject, "Debug DX11" , "2) 32 bit", CopyEngineDebugWindows32DX11);}
  794. void CompileEngineDebugWindowsUniversal64DX11 () {CompileVS(EnginePath+VSEngineProject, "Debug Universal DX11", "1) 64 bit", CopyEngineDebugWindowsUniversal64DX11);}
  795. void CompileEngineDebugWindowsUniversal32DX11 () {CompileVS(EnginePath+VSEngineProject, "Debug Universal DX11", "2) 32 bit", CopyEngineDebugWindowsUniversal32DX11);}
  796. void CompileEngineDebugWindowsUniversalArm32DX11() {CompileVS(EnginePath+VSEngineProject, "Debug Universal DX11", "3) ARM" , CopyEngineDebugWindowsUniversalArm32DX11);}
  797. void DelEditorExe () {FDelFile(EditorSourcePath+"Esenthel.exe");} // VS has a bug that it won't rebuild the EXE if no changes were made in source (so if EXE was built with DX9 lib, and then we're compiling for DX11, then it may not be relinked)
  798. void CopyEditorWindows64DX11() { Copy(EditorSourcePath+"Esenthel.exe", EditorPath+"Esenthel.exe");}
  799. void CopyEditorWindows32DX9 () { Copy(EditorSourcePath+"Esenthel.exe", EditorPath+"Esenthel 32 DX9.exe");}
  800. void CompileEditorWindows64DX11() {CompileVS(EditorSourcePath+VSEditorProject, "Release DX11", "1) 64 bit", CopyEditorWindows64DX11, DelEditorExe);}
  801. void CompileEditorWindows32DX9 () {CompileVS(EditorSourcePath+VSEditorProject, "Release DX9" , "2) 32 bit", CopyEditorWindows32DX9 , DelEditorExe);}
  802. void CleanEngineWeb () {build_threads.queue(build_requests.New().set(CleanEngineWebDo), BuildRun);}
  803. void WebLibs() {build_threads.queue(build_requests.New().set(MakeWebLibs ), BuildRun);}
  804. void CleanEngineApple() {CleanXcode(EnginePath +XcodeEngineProject, "Release", "EsenthelEngine");
  805. CleanXcode(EnginePath +XcodeEngineProject, "Release", "EsenthelEngine Device");
  806. CleanXcode(EnginePath +XcodeEngineProject, "Release", "EsenthelEngine Simulator", "iphonesimulator");
  807. CleanXcode(EnginePath +XcodeEngineProject, "Debug" , "EsenthelEngine");
  808. CleanXcode(EnginePath +XcodeEngineProject, "Debug" , "EsenthelEngine Device");
  809. CleanXcode(EnginePath +XcodeEngineProject, "Debug" , "EsenthelEngine Simulator", "iphonesimulator");}
  810. void CleanEditorMac () {CleanXcode(EditorSourcePath+XcodeEditorProject, "Release", "Mac");}
  811. void CopyEngineMac () {Copy(EnginePath+"Build/Release/EsenthelEngine.a" , EditorPath+"Bin/EsenthelEngine.a");}
  812. void CopyEngineiOS () {Copy(EnginePath+"Build/Release-iphoneos/EsenthelEngine Device.a" , EditorPath+"Bin/EsenthelEngine Device.a");}
  813. void CopyEngineiOSSimulator() {Copy(EnginePath+"Build/Release-iphonesimulator/EsenthelEngine Simulator.a", EditorPath+"Bin/EsenthelEngine Simulator.a");}
  814. void CopyEngineDebugMac () {Copy(EnginePath+"Build/Debug/EsenthelEngine.a" , EditorPath+"Bin/EsenthelEngine.a");}
  815. void CopyEngineDebugiOS () {Copy(EnginePath+"Build/Debug-iphoneos/EsenthelEngine Device.a" , EditorPath+"Bin/EsenthelEngine Device.a");}
  816. void CopyEngineDebugiOSSimulator() {Copy(EnginePath+"Build/Debug-iphonesimulator/EsenthelEngine Simulator.a", EditorPath+"Bin/EsenthelEngine Simulator.a");}
  817. void CopyEditorMac() {ReplaceDir(EditorSourcePath+"Esenthel.app", EditorPath+"Esenthel.app");}
  818. void CompileEngineMac () {CompileXcode(EnginePath +XcodeEngineProject, "Release", "EsenthelEngine" , "" , CopyEngineMac);}
  819. void CompileEngineiOS () {CompileXcode(EnginePath +XcodeEngineProject, "Release", "EsenthelEngine Device" , "" , CopyEngineiOS);}
  820. void CompileEngineiOSSimulator () {CompileXcode(EnginePath +XcodeEngineProject, "Release", "EsenthelEngine Simulator", "iphonesimulator", CopyEngineiOSSimulator);}
  821. void CompileEngineDebugMac () {CompileXcode(EnginePath +XcodeEngineProject, "Debug" , "EsenthelEngine" , "" , CopyEngineDebugMac);}
  822. void CompileEngineDebugiOS () {CompileXcode(EnginePath +XcodeEngineProject, "Debug" , "EsenthelEngine Device" , "" , CopyEngineDebugiOS);}
  823. void CompileEngineDebugiOSSimulator() {CompileXcode(EnginePath +XcodeEngineProject, "Debug" , "EsenthelEngine Simulator", "iphonesimulator", CopyEngineDebugiOSSimulator);}
  824. void CompileEditorMac () {CompileXcode(EditorSourcePath+XcodeEditorProject, "Release", "Mac" , "" , CopyEditorMac);}
  825. void CopyEditorLinux () {Copy(EditorSourcePath+"Esenthel", EditorPath+"Esenthel");}
  826. void CleanLinux () {build_threads.queue(build_requests.New().set(CleanLinuxDo), BuildRun);}
  827. void CompileEngineLinux () {CompileLinux(EnginePath +LinuxEngineProject, "Release");}
  828. void CompileEditorLinux () {CompileLinux(EditorSourcePath+LinuxEditorProject, "Release", CopyEditorLinux);}
  829. void LinuxLibs() {build_threads.queue(build_requests.New().set(MakeLinuxLibs), BuildRun);}
  830. void CleanEngineAndroid()
  831. {
  832. FDelDirs(EnginePath+AndroidProject+"obj");
  833. }
  834. void CompileEngineAndroid()
  835. {
  836. Str ndk_build=NDKBuildPath();
  837. if(!ndk_build.is()){Options.show(); Gui.msgBox("Error", "Android NDK Path unknown");}else
  838. {
  839. Int build_threads_num=Cpu.threads();
  840. build_threads.queue(build_requests.New().set(ndk_build, S+"-j"+build_threads_num+" -C \""+EnginePath+AndroidProject+"\""), BuildRun);
  841. }
  842. }
  843. void AndroidLibs() {build_threads.queue(build_requests.New().set(MakeAndroidLibs), BuildRun);}
  844. void EnginePak() {build_threads.queue(build_requests.New().set(CreateEnginePak), BuildRun);}
  845. void EditorPak() {build_threads.queue(build_requests.New().set(CreateEditorPak), BuildRun);}
  846. void Headers() {build_threads.queue(build_requests.New().set(UpdateHeaders ), BuildRun);}
  847. void CodeEditorData()
  848. { // must be done on the main thread
  849. CE.create (null, true); // don't use GUI because we don't need it, also it would require "Editor.pak" which may not be available yet
  850. CE.genSymbols(EditorPath+"Bin");
  851. CE.del ();
  852. }
  853. TaskBase CompileEngineWindowsTB[]=
  854. {
  855. {null, null, CompileEngineWindows32DX9},
  856. {null, null, CompileEngineWindows64DX9},
  857. {null, null, CompileEngineWindows32DX11},
  858. {null, null, CompileEngineWindows64DX11},
  859. {null, null, CompileEngineWindowsUniversal64DX11},
  860. {null, null, CompileEngineWindowsUniversal32DX11},
  861. {null, null, CompileEngineWindowsUniversalArm32DX11},
  862. };
  863. TaskBase CompileEngineDebugWindowsTB[]=
  864. {
  865. {null, null, CompileEngineDebugWindows32DX9},
  866. {null, null, CompileEngineDebugWindows64DX9},
  867. {null, null, CompileEngineDebugWindows32DX11},
  868. {null, null, CompileEngineDebugWindows64DX11},
  869. {null, null, CompileEngineDebugWindowsUniversal64DX11},
  870. {null, null, CompileEngineDebugWindowsUniversal32DX11},
  871. {null, null, CompileEngineDebugWindowsUniversalArm32DX11},
  872. };
  873. TaskBase CompileEngineAppleTB[]=
  874. {
  875. {null, null, CompileEngineMac},
  876. {null, null, CompileEngineiOS},
  877. {null, null, CompileEngineiOSSimulator},
  878. };
  879. TaskBase CompileEngineDebugAppleTB[]=
  880. {
  881. {null, null, CompileEngineDebugMac},
  882. {null, null, CompileEngineDebugiOS},
  883. {null, null, CompileEngineDebugiOSSimulator},
  884. };
  885. void CompileEngineWindows () {FREPAO(CompileEngineWindowsTB ).queue();}
  886. void CompileEngineDebugWindows() {FREPAO(CompileEngineDebugWindowsTB).queue();}
  887. void CompileEngineApple () {FREPAO(CompileEngineAppleTB ).queue();}
  888. void CompileEngineDebugApple () {FREPAO(CompileEngineDebugAppleTB ).queue();}
  889. TaskBase CompileEditorWindowsTB[]=
  890. {
  891. {null, null, CompileEditorWindows64DX11},
  892. {null, null, CompileEditorWindows32DX9 },
  893. };
  894. void CompileEditorWindows() {FREPAO(CompileEditorWindowsTB).queue();}
  895. /******************************************************************************/
  896. // PHYSX
  897. /******************************************************************************/
  898. static Bool PatchPhysXProject(C Str &path)
  899. {
  900. for(FileFind ff(path, "vcxproj"); ff(); )
  901. {
  902. FileText f; if(f.read(ff.pathName()))
  903. {
  904. Str so=f.getAll(), s=so; Bool r=Contains(so, '\r');
  905. if(r)s.replace('\r', '\0');
  906. // VS 2017
  907. s=Replace(s, "<PlatformToolset>v140</PlatformToolset>" , "<PlatformToolset>v141_xp</PlatformToolset>" , true, true);
  908. s=Replace(s, "<TreatWarningAsError>true</TreatWarningAsError>" , "<TreatWarningAsError>false</TreatWarningAsError>" , true, true);
  909. // reduce size
  910. s=Replace(s, "<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>", "<DebugInformationFormat>None</DebugInformationFormat>", true, true);
  911. s=Replace(s, " /Fd\"$(TargetDir)\\$(TargetName).pdb\"" , S , true, true); // one file has this specified in "LowLevelCloth" project which results in PDB missing notification on compilation
  912. s=Replace(s, " /Zi" , S , true, true); // one file has this specified in "LowLevelCloth" project which results in PDB missing notification on compilation
  913. // static lib
  914. #if PHYSX_DLL
  915. if(ff.name=="PhysX.vcxproj"
  916. || ff.name=="PhysXCommon.vcxproj"
  917. || ff.name=="PhysXCooking.vcxproj"
  918. || ff.name=="PxFoundation.vcxproj")
  919. {
  920. s=Replace(s, "<ConfigurationType>StaticLibrary</ConfigurationType>", "<ConfigurationType>DynamicLibrary</ConfigurationType>", true, true);
  921. s=Replace(s, "<TargetExt>.lib</TargetExt>" , "<TargetExt>.dll</TargetExt>" , true, true);
  922. }
  923. s=Replace(s, ".rc\">\n\t\t\t<ExcludedFromBuild>true</ExcludedFromBuild>\n\t\t</", ".rc\">\n\t\t</");
  924. s=Replace(s, ".rc\">\n <ExcludedFromBuild>true</ExcludedFromBuild>\n </", ".rc\">\n </");
  925. s=Replace(s, ".rc\"><ExcludedFromBuild>true</ExcludedFromBuild></" , ".rc\"></" );
  926. #else
  927. s=Replace(s, "<ConfigurationType>DynamicLibrary</ConfigurationType>", "<ConfigurationType>StaticLibrary</ConfigurationType>", true, true);
  928. s=Replace(s, "<TargetExt>.dll</TargetExt>" , "<TargetExt>.lib</TargetExt>" , true, true);
  929. s=Replace(s, ".rc\">\n\t\t</", ".rc\">\n\t\t\t<ExcludedFromBuild>true</ExcludedFromBuild>\n\t\t</"); // projects have "*.rc" files included, because of which linking them into EsenthelEngine.lib file will fail, so we have to disable them
  930. s=Replace(s, ".rc\">\n </", ".rc\">\n <ExcludedFromBuild>true</ExcludedFromBuild>\n </");
  931. s=Replace(s, ".rc\"></" , ".rc\"><ExcludedFromBuild>true</ExcludedFromBuild></" );
  932. #endif
  933. // debug
  934. s=Replace(s, "$(ProjectName)DEBUG", "$(ProjectName)");
  935. s=Replace(s, "DEBUG</TargetName>", "</TargetName>");
  936. s=Replace(s, "DEBUG.lib</OutputFile>", ".lib</OutputFile>");
  937. s=Replace(s, "DEBUG_x64</TargetName>", "_x64</TargetName>");
  938. s=Replace(s, "DEBUG_x64.lib</OutputFile>", "_x64.lib</OutputFile>");
  939. s=Replace(s, "$(ProjectName)CHECKED", "$(ProjectName)");
  940. s=Replace(s, "CHECKED</TargetName>", "</TargetName>");
  941. s=Replace(s, "CHECKED.lib</OutputFile>", ".lib</OutputFile>");
  942. s=Replace(s, "CHECKED_x64</TargetName>", "_x64</TargetName>");
  943. s=Replace(s, "CHECKED_x64.lib</OutputFile>", "_x64.lib</OutputFile>");
  944. s=Replace(s, "<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>", "<RuntimeLibrary>MultiThreaded</RuntimeLibrary>");
  945. s=Replace(s, "_DEBUG", "NDEBUG", true, true);
  946. if(r)s=Replace(s, "\n", "\r\n");
  947. if(so!=s)
  948. {
  949. f.writeMem(f.encoding()).putText(s);
  950. if(!SafeOverwrite(f, ff.pathName()))return ErrorWrite(ff.pathName());
  951. }
  952. }
  953. }
  954. return true;
  955. }
  956. static void CopyPhysXWindows64()
  957. {
  958. Str files[]=
  959. {
  960. ThirdPartyLibsPath+"PhysX/PhysX/Bin/vc14win64/PhysX3_x64.dll",
  961. ThirdPartyLibsPath+"PhysX/PhysX/Bin/vc14win64/PhysX3Common_x64.dll",
  962. ThirdPartyLibsPath+"PhysX/PhysX/Bin/vc14win64/PhysX3Cooking_x64.dll",
  963. ThirdPartyLibsPath+"PhysX/PxShared/bin/vc14win64/PxFoundation_x64.dll",
  964. };
  965. if(PHYSX_DLL)FREPA(files)Copy(files[i], EditorPath+"Bin/"+GetBase(files[i]));
  966. else FREPA(files)Del ( EditorPath+"Bin/"+GetBase(files[i]));
  967. }
  968. static void CopyPhysXWindows32()
  969. {
  970. Str files[]=
  971. {
  972. ThirdPartyLibsPath+"PhysX/PhysX/Bin/vc14win32/PhysX3_x86.dll",
  973. ThirdPartyLibsPath+"PhysX/PhysX/Bin/vc14win32/PhysX3Common_x86.dll",
  974. ThirdPartyLibsPath+"PhysX/PhysX/Bin/vc14win32/PhysX3Cooking_x86.dll",
  975. ThirdPartyLibsPath+"PhysX/PxShared/bin/vc14win32/PxFoundation_x86.dll",
  976. };
  977. if(PHYSX_DLL)FREPA(files)Copy(files[i], EditorPath+"Bin/"+GetBase(files[i]));
  978. else FREPA(files)Del ( EditorPath+"Bin/"+GetBase(files[i]));
  979. }
  980. static void CopyPhysXLinux()
  981. {
  982. Str files[]=
  983. {
  984. ThirdPartyLibsPath+"PhysX/PhysX/Bin/linux64/libPhysX3_x64.so",
  985. ThirdPartyLibsPath+"PhysX/PhysX/Bin/linux64/libPhysX3Common_x64.so",
  986. ThirdPartyLibsPath+"PhysX/PhysX/Bin/linux64/libPhysX3Cooking_x64.so",
  987. ThirdPartyLibsPath+"PhysX/PxShared/bin/linux64/libPxFoundation_x64.so",
  988. };
  989. if(PHYSX_DLL)FREPA(files)Copy(files[i], EditorPath+"Bin/"+GetBase(files[i]));
  990. else FREPA(files)Del ( EditorPath+"Bin/"+GetBase(files[i]));
  991. }
  992. static void CompilePhysXWindows64() {Str path=ThirdPartyLibsPath+"PhysX/", projects=path+"PhysX/Source/compiler/vc14win64/"; if(PatchPhysXProject(projects) && PatchPhysXProject(path+"PxShared/src/compiler/vc14win64"))CompileVS(projects+"PhysX.sln", "Release", S, CopyPhysXWindows64);}
  993. static void CompilePhysXWindows32() {Str path=ThirdPartyLibsPath+"PhysX/", projects=path+"PhysX/Source/compiler/vc14win32/"; if(PatchPhysXProject(projects) && PatchPhysXProject(path+"PxShared/src/compiler/vc14win32"))CompileVS(projects+"PhysX.sln", "Release", S, CopyPhysXWindows32);}
  994. TaskBase CompilePhysXWindowsTB[]=
  995. {
  996. {null, null, CompilePhysXWindows64},
  997. {null, null, CompilePhysXWindows32},
  998. };
  999. static Bool PhysXCheck()
  1000. {
  1001. Str path=ThirdPartyLibsPath+"PhysX/", sub=path+"PhysX-3.4-master/", physx="PhysX", physx_ver="PhysX_3.4", shared="PxShared";
  1002. if(FExistSystem(sub))
  1003. {
  1004. if(FExistSystem(sub+physx_ver))
  1005. {
  1006. FDelDirs(sub+physx_ver+"/Media");
  1007. //FDelDirs(sub+physx_ver+"/Samples");
  1008. //FDelDirs(sub+physx_ver+"/Snippets");
  1009. if(FExistSystem(path+physx) && !FDelDirs(path+physx))return ErrorDel(path+physx);
  1010. if(!FRename(sub+physx_ver, path+physx))return ErrorMove(sub+physx_ver, path+physx);
  1011. }
  1012. if(FExistSystem(sub+shared))
  1013. {
  1014. if(FExistSystem(path+shared) && !FDelDirs(path+shared))return ErrorDel(path+shared);
  1015. if(!FRename(sub+shared, path+shared))return ErrorMove(sub+shared, path+shared);
  1016. }
  1017. if(FExistSystem(sub+"Externals/nvToolsExt"))
  1018. {
  1019. FCreateDirs(path+"Externals");
  1020. if(!FRename(sub+"Externals/nvToolsExt", path+"Externals/nvToolsExt"))return ErrorMove(sub+"Externals/nvToolsExt", path+"Externals/nvToolsExt");
  1021. }
  1022. if(!FDelDirs(sub))return ErrorDel(sub);
  1023. }
  1024. if(FExistSystem(path+physx_ver))
  1025. {
  1026. if(FExistSystem(path+physx) && !FDelDirs(path+physx))return ErrorDel(path+physx);
  1027. if(!FRename(path+physx_ver, path+physx))return ErrorMove(path+physx_ver, path+physx);
  1028. }
  1029. if(!FExistSystem(path+physx))return ErrorRead(path+physx);
  1030. // FIXME remove these in the future
  1031. FileText f;
  1032. if(f.read(path+"PhysX/Include/common/PxPhysXCommonConfig.h"))
  1033. {
  1034. Str so=f.getAll(), s=so;
  1035. s=Replace(s, "\n//#error Visual studio 2017 is not supported because of a compiler bug, support will be enabled once a fix is out.",
  1036. "\n#error Visual studio 2017 is not supported because of a compiler bug, support will be enabled once a fix is out."); // revert back the change made by older version of Esenthel Builder
  1037. s=Replace(s, "\n#error Visual studio 2017 is not supported because of a compiler bug, support will be enabled once a fix is out.",
  1038. "\n#error This version of Visual Studio is not supported because of a compiler bug, you will have to install at least VS 2017 version 15.5, at the time of writing this, it can be downloaded only from the Preview link - https://www.visualstudio.com/vs/preview/");
  1039. s=Replace(s, "#if (PX_VC == 15) && PX_WINDOWS", "#if PX_WINDOWS && _MSC_VER<1912"); // replace check for VS 2017 with a check for _MSC_VER (1912 = VS 2017 15.5)
  1040. if(so!=s)
  1041. {
  1042. f.writeMem(f.encoding()).putText(s);
  1043. if(!SafeOverwrite(f, path+"PhysX/Include/common/PxPhysXCommonConfig.h"))return ErrorWrite(path+"PhysX/Include/common/PxPhysXCommonConfig.h");
  1044. }
  1045. }
  1046. if(f.read(path+"PhysX/Source/PhysX/src/device/windows/PhysXIndicatorWindows.cpp")) // https://github.com/NVIDIAGameWorks/PhysX-3.4/issues/50
  1047. {
  1048. Str so=f.getAll(), s=so;
  1049. s=Replace(s, "\n#include <VersionHelpers.h>", "\n#undef _MSC_VER//#include <VersionHelpers.h>"); // this header is not available when compiling for WinXP support
  1050. if(so!=s)
  1051. {
  1052. f.writeMem(f.encoding()).putText(s);
  1053. if(!SafeOverwrite(f, path+"PhysX/Source/PhysX/src/device/windows/PhysXIndicatorWindows.cpp"))return ErrorWrite(path+"PhysX/Source/PhysX/src/device/windows/PhysXIndicatorWindows.cpp");
  1054. }
  1055. }
  1056. if(f.read(path+"PhysX/Source/LowLevelCloth/src/neon/NeonSolverKernel.cpp")) // https://github.com/NVIDIAGameWorks/PhysX-3.4/issues/45
  1057. {
  1058. Str so=f.getAll(), s=so;
  1059. s=Replace(s, ", PxProfileZone", ", profile::PxProfileZone");
  1060. s=Replace(s, "factory, profileZone)", "factory)");
  1061. s=Replace(s, "__ARM_NEON__", "__ARM_NEON");
  1062. s=Replace(s, "\n#error", "\n//#error");
  1063. if(so!=s)
  1064. {
  1065. f.writeMem(f.encoding()).putText(s);
  1066. if(!SafeOverwrite(f, path+"PhysX/Source/LowLevelCloth/src/neon/NeonSolverKernel.cpp"))return ErrorWrite(path+"PhysX/Source/LowLevelCloth/src/neon/NeonSolverKernel.cpp");
  1067. }
  1068. }
  1069. if(f.read(path+"PhysX/Source/LowLevelCloth/src/neon/NeonCollision.cpp")) // https://github.com/NVIDIAGameWorks/PhysX-3.4/issues/45
  1070. {
  1071. Str so=f.getAll(), s=so;
  1072. s=Replace(s, "__ARM_NEON__", "__ARM_NEON");
  1073. s=Replace(s, "\n#error", "\n//#error");
  1074. if(so!=s)
  1075. {
  1076. f.writeMem(f.encoding()).putText(s);
  1077. if(!SafeOverwrite(f, path+"PhysX/Source/LowLevelCloth/src/neon/NeonCollision.cpp"))return ErrorWrite(path+"PhysX/Source/LowLevelCloth/src/neon/NeonCollision.cpp");
  1078. }
  1079. }
  1080. if(f.read(path+"PhysX/Source/LowLevelCloth/src/neon/NeonSelfCollision.cpp")) // https://github.com/NVIDIAGameWorks/PhysX-3.4/issues/45
  1081. {
  1082. Str so=f.getAll(), s=so;
  1083. s=Replace(s, "__ARM_NEON__", "__ARM_NEON");
  1084. s=Replace(s, "\n#error", "\n//#error");
  1085. if(so!=s)
  1086. {
  1087. f.writeMem(f.encoding()).putText(s);
  1088. if(!SafeOverwrite(f, path+"PhysX/Source/LowLevelCloth/src/neon/NeonSelfCollision.cpp"))return ErrorWrite(path+"PhysX/Source/LowLevelCloth/src/neon/NeonSelfCollision.cpp");
  1089. }
  1090. }
  1091. if(f.read(path+"PhysX/Source/PhysXCooking/src/convex/ConvexMeshBuilder.cpp")) // https://github.com/NVIDIAGameWorks/PhysX-3.4/issues/49
  1092. {
  1093. Str so=f.getAll(), s=so;
  1094. s=Replace(s, "\t*dest++ = trig16[1];", "\t//*dest++ = trig16[1];");
  1095. s=Replace(s, "\t*dest++ = trig16[2];", "\t//*dest++ = trig16[2];");
  1096. if(so!=s)
  1097. {
  1098. f.writeMem(f.encoding()).putText(s);
  1099. if(!SafeOverwrite(f, path+"PhysX/Source/PhysXCooking/src/convex/ConvexMeshBuilder.cpp"))return ErrorWrite(path+"PhysX/Source/PhysXCooking/src/convex/ConvexMeshBuilder.cpp");
  1100. }
  1101. }
  1102. if(f.read(path+"PxShared/src/foundation/include/windows/PsWindowsIntrinsics.h")) // FIXME report this
  1103. {
  1104. Str so=f.getAll(), s=so;
  1105. s=Replace(s, "\n#include <mmintrin.h>", "\n//#include <mmintrin.h>");
  1106. if(so!=s)
  1107. {
  1108. f.writeMem(f.encoding()).putText(s);
  1109. if(!SafeOverwrite(f, path+"PxShared/src/foundation/include/windows/PsWindowsIntrinsics.h"))return ErrorWrite(path+"PxShared/src/foundation/include/windows/PsWindowsIntrinsics.h");
  1110. }
  1111. }
  1112. // static lib
  1113. Str files[]=
  1114. {
  1115. path+"PhysX/Include/cooking/Pxc.h",
  1116. path+"PhysX/Include/common/PxPhysXCommonConfig.h",
  1117. path+"PxShared/include/foundation/PxPreprocessor.h",
  1118. };
  1119. FREPA(files)if(f.read(files[i]))
  1120. {
  1121. Str s=f.getAll(); Int l=s.length();
  1122. #if PHYSX_DLL
  1123. s=Replace(s, " //__declspec(dllexport)", " __declspec(dllexport)");
  1124. s=Replace(s, " //__declspec(dllimport)", " __declspec(dllimport)");
  1125. #else
  1126. s=Replace(s, " __declspec(dllexport)", " //__declspec(dllexport)");
  1127. s=Replace(s, " __declspec(dllimport)", " //__declspec(dllimport)");
  1128. #endif
  1129. if(s.length()!=l)
  1130. {
  1131. f.writeMem(f.encoding()).putText(s);
  1132. if(!SafeOverwrite(f, files[i]))return ErrorWrite(files[i]);
  1133. }
  1134. }
  1135. return true;
  1136. }
  1137. void PhysXCompileWindows(Ptr) {if(PhysXCheck())FREPAO(CompilePhysXWindowsTB).queue();}
  1138. static void PhysXCompileMac1() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_osx64/PhysX.xcodeproj", "release", "PhysX");}
  1139. static void PhysXCompileMac2() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_osx64/PhysX.xcodeproj", "release", "PhysXCooking");}
  1140. static void PhysXCompileMac3() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_osx64/PhysX.xcodeproj", "release", "PhysXExtensions");}
  1141. static void PhysXCompileMac4() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_osx64/PhysX.xcodeproj", "release", "PhysXVehicle");}
  1142. TaskBase PhysXCompileMacTB[]=
  1143. {
  1144. {null, null, PhysXCompileMac1},
  1145. {null, null, PhysXCompileMac2},
  1146. {null, null, PhysXCompileMac3},
  1147. {null, null, PhysXCompileMac4},
  1148. };
  1149. static void PhysXCompileiOS1() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_ios64/PhysX.xcodeproj", "release", "PhysX");}
  1150. static void PhysXCompileiOS2() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_ios64/PhysX.xcodeproj", "release", "PhysXCooking");}
  1151. static void PhysXCompileiOS3() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_ios64/PhysX.xcodeproj", "release", "PhysXExtensions");}
  1152. static void PhysXCompileiOS4() {CompileXcode(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/xcode_ios64/PhysX.xcodeproj", "release", "PhysXVehicle");}
  1153. TaskBase PhysXCompileiOSTB[]=
  1154. {
  1155. {null, null, PhysXCompileiOS1},
  1156. {null, null, PhysXCompileiOS2},
  1157. {null, null, PhysXCompileiOS3},
  1158. {null, null, PhysXCompileiOS4},
  1159. };
  1160. void PhysXCompileMac(Ptr) {if(PhysXCheck())FREPAO(PhysXCompileMacTB).queue();}
  1161. void PhysXCompileiOS(Ptr) {if(PhysXCheck())FREPAO(PhysXCompileiOSTB).queue();}
  1162. static Str PhysXAndroidFiles, PhysXAndroidFolders;
  1163. static FILE_LIST_MODE ListPhysXAndroidFiles(C FileFind &ff, Ptr user)
  1164. {
  1165. if(ff.type==FSTD_DIR)
  1166. {
  1167. if(ff.name=="Windows" // skip files inside windows folders (they're meant only for Windows OS)
  1168. || ff.name=="Snippets"
  1169. || ff.name=="Samples"
  1170. || ff.name=="avx"
  1171. || ff.name=="PhysXCharacterKinematic"
  1172. || Ends(ff.pathName().replace('\\', '/'), "/pvd/src") // skip PVD as it's not used
  1173. )return FILE_LIST_SKIP;
  1174. //if(FileFind(ff.pathName(), "cpp")())PhysXAndroidFiles +=S+" \\\n\t" +UnixPath(GetRelativePath(ThirdPartyLibsPath+"PhysX/Android", ff.pathName()))+"/*.cpp"; this doesn't work
  1175. if(FileFind(ff.pathName(), "h" )()
  1176. || ff.name=="include" )PhysXAndroidFolders+=S+" \\\n\t-I"+UnixPath(GetRelativePath(ThirdPartyLibsPath+"PhysX/Android", ff.pathName()));
  1177. }else
  1178. if(ff.type==FSTD_FILE && GetExt(ff.name)=="cpp"
  1179. && !Contains(SkipStartPath(ff.pathName(), ThirdPartyLibsPath), "serialization", false, true)
  1180. )PhysXAndroidFiles+=S+" \\\n\t"+UnixPath(GetRelativePath(ThirdPartyLibsPath+"PhysX/Android/jni", ff.pathName()));
  1181. return FILE_LIST_CONTINUE;
  1182. }
  1183. static void PhysXCompileAndroid()
  1184. {
  1185. Str ndk_build=NDKBuildPath();
  1186. if(!ndk_build.is()){Options.show(); Gui.msgBox("Error", "Android NDK Path unknown");}else
  1187. {
  1188. PhysXAndroidFiles .clear();
  1189. PhysXAndroidFolders.clear();
  1190. FList(ThirdPartyLibsPath+"PhysX/PhysX" , ListPhysXAndroidFiles);
  1191. FList(ThirdPartyLibsPath+"PhysX/PxShared", ListPhysXAndroidFiles);
  1192. Str s=S+
  1193. "LOCAL_PATH := $(call my-dir)\n"
  1194. "include $(CLEAR_VARS)\n"
  1195. "LOCAL_MODULE := PhysX\n"
  1196. "LOCAL_CPP_FEATURES := # rtti exceptions\n"
  1197. "LOCAL_ARM_NEON := true # force NEON usage for all files\n"
  1198. "\n"
  1199. "LOCAL_CPPFLAGS := -O3 -fshort-wchar -ffast-math -fomit-frame-pointer -Wno-invalid-offsetof -Wno-invalid-noreturn -DPX_PHYSX_STATIC_LIB -DPX_COOKING -DPX_SUPPORT_PVD=0 -DNDEBUG"+PhysXAndroidFolders+"\n"
  1200. "\n"
  1201. //"LOCAL_SRC_FILES := $(wildcard"+PhysXAndroidFiles+" \\\n)\n" this doesn't work
  1202. "LOCAL_SRC_FILES :="+PhysXAndroidFiles+"\n"
  1203. "\n"
  1204. "include $(BUILD_STATIC_LIBRARY)\n";
  1205. FileText f; f.writeMem(ANSI).putText(s); // have to use ANSI because UTF8 for some reason fails
  1206. if(!OverwriteOnChange(f, ThirdPartyLibsPath+"PhysX/Android/jni/Android.mk")){ErrorWrite(ThirdPartyLibsPath+"PhysX/Android/jni/Android.mk"); return;}
  1207. Int build_threads_num=Cpu.threads();
  1208. build_threads.queue(build_requests.New().set(ndk_build, S+"-j"+build_threads_num+" -C \""+ThirdPartyLibsPath+"PhysX/Android"+"\""), BuildRun);
  1209. }
  1210. }
  1211. TaskBase PhysXCompileAndroidTB[]=
  1212. {
  1213. {null, null, PhysXCompileAndroid},
  1214. };
  1215. void PhysXCompileAndroid(Ptr) {if(PhysXCheck())FREPAO(PhysXCompileAndroidTB).queue();}
  1216. static void PhysXCompileLinux()
  1217. {
  1218. for(FileFind ff(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/linux64", "mk"); ff(); )
  1219. {
  1220. FileText f; if(f.read(ff.pathName()))
  1221. {
  1222. Str so, s; f.getAll(so); s=so;
  1223. s=Replace(s, " -Werror", S, true, true);
  1224. #if !PHYSX_DLL
  1225. //s=Replace(s, " -shared", S, true, true);
  1226. s=Replace(s, ".so" , ".a", true, true);
  1227. Str name=GetExtNot(SkipStart(ff.name, "Makefile.")); // "Makefile.LowLevel.mk" -> "LowLevel"
  1228. s=Replace(s, S+"$(CXX) -shared $("+name+"_release_obj) $("+name+"_release_lflags) -lc -o $@", S+"@$(AR) rcs $("+name+"_release_bin) $("+name+"_release_obj)");
  1229. #endif
  1230. if(s!=so)
  1231. {
  1232. f.writeMem(f.encoding()).putText(s);
  1233. if(!SafeOverwrite(f, ff.pathName())){ErrorWrite(ff.pathName()); Tasks.clear();}
  1234. }
  1235. }
  1236. }
  1237. build_threads.queue(build_requests.New().set("make", LinuxBuildParams(ThirdPartyLibsPath+"PhysX/PhysX/Source/compiler/linux64", S)+" release").set(CopyPhysXLinux), BuildRun);
  1238. }
  1239. TaskBase PhysXCompileLinuxTB[]=
  1240. {
  1241. {null, null, PhysXCompileLinux},
  1242. };
  1243. void PhysXCompileLinux(Ptr) {if(PhysXCheck())FREPAO(PhysXCompileLinuxTB).queue();}
  1244. void PhysXCompileWeb(Ptr)
  1245. {
  1246. // FIXME
  1247. if(PhysXCheck()){}
  1248. }
  1249. /******************************************************************************/
  1250. #define ANDROID_DEFAULT WINDOWS
  1251. #define WEB_DEFAULT false
  1252. TaskBase TaskBases[]=
  1253. {
  1254. #if WINDOWS
  1255. {"Compile Windows 64 DX11" , "Compile the Engine in Release mode for Windows 64-bit DX10+ only" , CompileEngineWindows64DX11 , false},
  1256. {"Compile Windows All" , "Compile the Engine in Release mode for all Windows targets" , CompileEngineWindows , true , true},
  1257. {"Compile Windows 64 DX11 (Debug)", "Compile the Engine in Debug mode for Windows 64-bit DX10+ only" , CompileEngineDebugWindows64DX11, false},
  1258. {"Compile Windows All (Debug)" , "Compile the Engine in Debug mode for all Windows targets" , CompileEngineDebugWindows , false, true},
  1259. #elif APPLE
  1260. {"Clean Apple" , "Clean temporary files generated during Engine compilation for Apple platforms" , CleanEngineApple , false},
  1261. {"Compile Mac" , "Compile the Engine in Release mode for Mac only" , CompileEngineMac , false},
  1262. {"Compile iOS" , "Compile the Engine in Release mode for iOS only" , CompileEngineiOS , false},
  1263. {"Compile Apple" , "Compile the Engine in Release mode for all Apple platforms (Mac, iOS, iOS Simulator)", CompileEngineApple , true , true},
  1264. {"Compile Mac (Debug)" , "Compile the Engine in Debug mode for Mac only" , CompileEngineDebugMac , false},
  1265. {"Compile iOS (Debug)" , "Compile the Engine in Debug mode for iOS only" , CompileEngineDebugiOS , false},
  1266. {"Compile Apple (Debug)" , "Compile the Engine in Debug mode for all Apple platforms (Mac, iOS, iOS Simulator)" , CompileEngineDebugApple , false, true},
  1267. #elif LINUX
  1268. {"Clean Linux" , "Clean temporary files generated during Engine/Editor compilation for Linux platform", CleanLinux , false},
  1269. {"Compile Linux" , "Compile the Engine in Release mode for Linux" , CompileEngineLinux , true },
  1270. {"Make Linux Libs" , "Make the Engine Linux Lib from the compilation result to the Editor Bin folder" , LinuxLibs , true },
  1271. #endif
  1272. {"Clean Android" , "Clean temporary files generated during Engine compilation for Android" , CleanEngineAndroid , false},
  1273. {"Compile Android" , "Compile the Engine in Release mode for Android" , CompileEngineAndroid , ANDROID_DEFAULT},
  1274. {"Make Android Libs" , "Make the Engine Android Libs from the compilation result to the Editor Bin folder" , AndroidLibs , ANDROID_DEFAULT},
  1275. #if WINDOWS
  1276. {"Clean Web" , "Clean temporary files generated during Engine compilation for the Web" , CleanEngineWeb , false},
  1277. {"Compile Web" , "Compile the Engine for Web" , CompileEngineWeb , WEB_DEFAULT},
  1278. {"Make Web Libs" , "Make the Engine Web Lib from the compilation result to the Editor Bin folder" , WebLibs , WEB_DEFAULT},
  1279. #endif
  1280. {"Copy Headers" , "Copy cleaned Engine Headers from the Engine folder to the Editor folder.\nCleaning removes all 'EE_PRIVATE' sections from the headers." , Headers , true },
  1281. {"Create \"Code Editor.dat\"", "Create \"Code Editor.dat\" file needed for Code Editor in the Engine's Editor.\nThis data is generated from the Engine headers in the Editor Bin folder, which are generated in the \"Copy Headers\" step.", CodeEditorData, true },
  1282. {"Create \"Engine.pak\"" , "Create \"Engine.pak\" file from the \"Data\" folder into the Editor Bin folder" , EnginePak , true },
  1283. {"Create \"Editor.pak\"" , "Create \"Editor.pak\" file from the \"Editor Data\" folder into the Editor Bin folder", EditorPak , true },
  1284. #if WINDOWS
  1285. {"Compile Editor" , "Compile the Editor" , CompileEditorWindows64DX11, false},
  1286. #elif APPLE
  1287. {"Compile Editor" , "Compile the Editor" , CompileEditorMac , false},
  1288. #elif LINUX
  1289. {"Compile Editor" , "Compile the Editor" , CompileEditorLinux , false},
  1290. #endif
  1291. };
  1292. Memc<TaskBase> CustomTasks;
  1293. /******************************************************************************/
  1294. void Resize(Flt=0, Flt=0)
  1295. {
  1296. D.scale(D.screenH()/Flt(D.resH())*(1000./1080));
  1297. region.rect(Rect(-D.w()+0.53, -D.h(), D.w(), D.h()));
  1298. clear.rect(Rect_RU(region.rect().ru()-Vec2(region.slidebarSize(), 0), 0.2, 0.05));
  1299. copy .rect(Rect_RU(clear.rect().lu(), 0.2, 0.05));
  1300. Flt x=-D.w()+0.02, y=D.h()-0.10, h=0.067;
  1301. OptionsButton.rect(Rect_L(x+0.06, y, 0.45, 0.05)); y-=h;
  1302. y-=0.02;
  1303. FREPA(Tasks){Tasks[i].pos(x, y); y-=h;}
  1304. y-=0.02;
  1305. All.rect(Rect_L(x , y, 0.05, 0.05));
  1306. DoSel.rect(Rect_L(x+0.06, y, 0.45, 0.05));
  1307. }
  1308. /******************************************************************************/
  1309. void InitPre()
  1310. {
  1311. App.flag=APP_RESIZABLE|APP_MINIMIZABLE|APP_MAXIMIZABLE|APP_NO_PAUSE_ON_WINDOW_MOVE_SIZE|APP_WORK_IN_BACKGROUND|APP_FULL_TOGGLE;
  1312. App.x=1;
  1313. App.y=1;
  1314. #if DEBUG
  1315. App.flag|=APP_BREAKPOINT_ON_ERROR|APP_MEM_LEAKS|APP_CALLSTACK_ON_ERROR;
  1316. #endif
  1317. D.screen_changed=Resize;
  1318. Flt scale=D.screenH()/1080.0f;
  1319. D.mode(800*scale, 630*scale);
  1320. App.name("Esenthel Builder");
  1321. for(Str path=GetPath(App.exe()); ; path=GetPath(path))
  1322. {
  1323. if(!path.is())Exit("Can't find Esenthel Root Path");
  1324. if(FExistSystem(path+"/Data")
  1325. && FExistSystem(path+"/Editor Data")
  1326. && FExistSystem(path+"/Editor")
  1327. && FExistSystem(path+"/Engine"))
  1328. {
  1329. EsenthelPath=path.tailSlash(true);
  1330. if(!FullPath( EngineDataPath)) EngineDataPath=EsenthelPath+ EngineDataPath;
  1331. if(!FullPath( EditorDataPath)) EditorDataPath=EsenthelPath+ EditorDataPath;
  1332. if(!FullPath( EnginePath)) EnginePath=EsenthelPath+ EnginePath;
  1333. if(!FullPath( EditorPath)) EditorPath=EsenthelPath+ EditorPath;
  1334. if(!FullPath( EditorSourcePath)) EditorSourcePath=EsenthelPath+ EditorSourcePath;
  1335. if(!FullPath(ThirdPartyLibsPath))ThirdPartyLibsPath=EsenthelPath+ThirdPartyLibsPath;
  1336. break;
  1337. }
  1338. }
  1339. DataPath(EngineDataPath);
  1340. }
  1341. void SetPaths()
  1342. {
  1343. // setup VS path if not specified
  1344. if(!VSPath.is())
  1345. {
  1346. Memc<VisualStudioInstallation> installs; GetVisualStudioInstallations(installs); REPA(installs) // go from the end to try the latest version first
  1347. {
  1348. C VisualStudioInstallation &install=installs[i]; if(CheckVisualStudio(install.ver))if(DevEnvPath(install.path).is())
  1349. {
  1350. VSPath=install.path; break;
  1351. }
  1352. }
  1353. }
  1354. // setup Android NDK path if not specified
  1355. if(!AndroidNDKPath.is())
  1356. {
  1357. Str AndroidSDKPath=GetPath(GetRegStr(RKG_LOCAL_MACHINE, "Software/Android SDK Tools/Path"));
  1358. if( AndroidSDKPath.is())for(FileFind ff(AndroidSDKPath); ff(); )
  1359. {
  1360. Str ndk_path=ff.pathName(); if(NDKBuildPath(ndk_path).is())
  1361. {
  1362. AndroidNDKPath=ndk_path; break;
  1363. }
  1364. }
  1365. }
  1366. }
  1367. Bool Init()
  1368. {
  1369. SetPaths();
  1370. Options.create();
  1371. Gui+=region.create();
  1372. ListColumn lc[]=
  1373. {
  1374. ListColumn(DATA_STR, 0, SIZE(Str), LCW_MAX_DATA_PARENT, u"Output"),
  1375. };
  1376. region+=list.create(lc, Elms(lc)); list.elmHeight(0.037).textSize(0.037); FlagDisable(list.flag, LIST_SORTABLE); region.slidebar[0].scrollOptions(0.75f); region.slidebar[1].scrollOptions(0.75f);
  1377. Gui+=copy .create("Copy" ).func(CopyOutput);
  1378. Gui+=clear.create("Clear").func(Clear);
  1379. Gui+=OptionsButton.create("Options").func(OptionsToggle);
  1380. #ifdef CUSTOM_TASKS
  1381. CUSTOM_TASKS
  1382. #endif
  1383. FREPA(TaskBases )Tasks.New().create(TaskBases [i]);
  1384. FREPA(CustomTasks)Tasks.New().create(CustomTasks[i]);
  1385. Gui+=All .create().func(ToggleAll).set(true, QUIET);
  1386. Gui+=DoSel.create("Do Selected").func(DoSelected).desc("Execute all selected tasks in order");
  1387. Resize();
  1388. build_threads.create(true, Cpu.threads(), 0, "BuildThreads");
  1389. return true;
  1390. }
  1391. /******************************************************************************/
  1392. void Shut()
  1393. {
  1394. Options.save();
  1395. shut=true;
  1396. build_threads.del();
  1397. }
  1398. /******************************************************************************/
  1399. Bool Update()
  1400. {
  1401. if(Kb.bp(KB_ESC))return false;
  1402. if(!App.active())Time.wait(1);
  1403. if(!build_threads.queued() && Todo.elms())
  1404. {
  1405. App.stayAwake(AWAKE_SYSTEM); // don't sleep when building
  1406. done++; // start with small progress
  1407. WindowSetProgress(Flt(done)/(Todo.elms()+done));
  1408. if(TaskBase *t=Todo.popFirst())t->call();
  1409. }
  1410. if(done && !build_threads.queued() && !Todo.elms()) // finished all tasks
  1411. {
  1412. done=0;
  1413. WindowSetNormal();
  1414. WindowFlash ();
  1415. App.stayAwake (AWAKE_OFF); // allow sleeping
  1416. }
  1417. if(data_new.elms())
  1418. {
  1419. Bool at_end=region.slidebar[1].wantedAtEnd(0.02f);
  1420. SyncLocker locker(lock);
  1421. FREPA(data_new)Swap(data.New(), data_new[i]);
  1422. data_new.clear();
  1423. list.setData(data);
  1424. if(at_end)region.scrollEndY();
  1425. }
  1426. Gui.update();
  1427. return true;
  1428. }
  1429. /******************************************************************************/
  1430. void Draw()
  1431. {
  1432. D.clear(TURQ);
  1433. TextStyleParams ts; ts.size=0.055; ts.align.set(1, -1); D.text(ts, -D.w()+0.01, D.h()-0.01, S+"Busy:"+build_threads.queued()+", Queued:"+Todo.elms());
  1434. Gui.draw();
  1435. }
  1436. /******************************************************************************/