JSBModule.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. #include <Atomic/IO/Log.h>
  8. #include <Atomic/IO/File.h>
  9. #include <Atomic/IO/FileSystem.h>
  10. #include <Atomic/Resource/JSONFile.h>
  11. #include "Atomic/Core/ProcessUtils.h"
  12. #include "JSBind.h"
  13. #include "JSBPackage.h"
  14. #include "JSBModule.h"
  15. #include "JSBHeader.h"
  16. #include "JSBClass.h"
  17. #include "JSBEnum.h"
  18. #include "JSBModuleWriter.h"
  19. #include "JSBType.h"
  20. #include "CSharp/CSBModuleWriter.h"
  21. namespace ToolCore
  22. {
  23. JSBModule::JSBModule(Context* context, JSBPackage* package) : Object(context),
  24. package_(package)
  25. {
  26. }
  27. JSBModule::~JSBModule()
  28. {
  29. }
  30. Vector<SharedPtr<JSBClass>> JSBModule::GetClasses()
  31. {
  32. return classes_.Values();
  33. }
  34. Vector<SharedPtr<JSBEnum>> JSBModule::GetEnums()
  35. {
  36. return enums_.Values();
  37. }
  38. void JSBModule::PreprocessHeaders()
  39. {
  40. for (unsigned i = 0; i < headers_.Size(); i++)
  41. {
  42. headers_[i]->VisitPreprocess();
  43. }
  44. }
  45. void JSBModule::VisitHeaders()
  46. {
  47. for (unsigned i = 0; i < headers_.Size(); i++)
  48. {
  49. headers_[i]->VisitHeader();
  50. }
  51. // validate that all classes found
  52. for (unsigned i = 0; i < classnames_.Size(); i++)
  53. {
  54. JSBClass* cls = GetClass(classnames_[i]);
  55. if (!cls)
  56. {
  57. ErrorExit(ToString("Module class not found %s", classnames_[i].CString()));
  58. }
  59. }
  60. ProcessOverloads();
  61. ProcessExcludes();
  62. ProcessTypeScriptDecl();
  63. ProcessHaxeDecl();
  64. }
  65. void JSBModule::PreprocessClasses()
  66. {
  67. HashMap<StringHash, SharedPtr<JSBClass> >::Iterator itr;
  68. for (itr = classes_.Begin(); itr != classes_.End(); itr++)
  69. {
  70. itr->second_->Preprocess();
  71. }
  72. }
  73. void JSBModule::ProcessClasses()
  74. {
  75. HashMap<StringHash, SharedPtr<JSBClass> >::Iterator itr;
  76. for (itr = classes_.Begin(); itr != classes_.End(); itr++)
  77. {
  78. itr->second_->Process();
  79. }
  80. }
  81. void JSBModule::PostProcessClasses()
  82. {
  83. HashMap<StringHash, SharedPtr<JSBClass> >::Iterator itr;
  84. for (itr = classes_.Begin(); itr != classes_.End(); itr++)
  85. {
  86. itr->second_->PostProcess();
  87. }
  88. }
  89. void JSBModule::ProcessOverloads()
  90. {
  91. // overloads
  92. JSONValue root = moduleJSON_->GetRoot();
  93. JSONValue overloads = root.Get("overloads");
  94. if (overloads.IsObject())
  95. {
  96. Vector<String> childNames = overloads.GetObject().Keys();
  97. for (unsigned j = 0; j < childNames.Size(); j++)
  98. {
  99. String classname = childNames.At(j);
  100. JSBClass* klass = GetClass(classname);
  101. if (!klass)
  102. {
  103. ErrorExit("Bad overload klass");
  104. }
  105. JSONValue classoverloads = overloads.Get(classname);
  106. Vector<String> functionNames = classoverloads.GetObject().Keys();
  107. for (unsigned k = 0; k < functionNames.Size(); k++)
  108. {
  109. JSONValue _sig = classoverloads.Get(functionNames[k]);
  110. if (!_sig.IsArray())
  111. {
  112. ErrorExit("Bad overload defintion");
  113. }
  114. JSONArray sig = _sig.GetArray();
  115. Vector<String> values;
  116. for (unsigned x = 0; x < sig.Size(); x++)
  117. {
  118. values.Push(sig[x].GetString());
  119. }
  120. JSBFunctionSignature* fo = new JSBFunctionSignature(functionNames[k], values);
  121. klass->AddFunctionOverride(fo);
  122. }
  123. }
  124. }
  125. }
  126. void JSBModule::ProcessExcludes()
  127. {
  128. // excludes
  129. JSONValue root = moduleJSON_->GetRoot();
  130. JSONValue excludes = root.Get("excludes");
  131. if (excludes.IsObject())
  132. {
  133. Vector<String> childNames = excludes.GetObject().Keys();
  134. for (unsigned j = 0; j < childNames.Size(); j++)
  135. {
  136. String classname = childNames.At(j);
  137. JSBClass* klass = GetClass(classname);
  138. if (!klass)
  139. {
  140. ErrorExit("Bad exclude klass");
  141. }
  142. JSONValue classexcludes = excludes.Get(classname);
  143. Vector<String> functionNames = classexcludes.GetObject().Keys();
  144. for (unsigned k = 0; k < functionNames.Size(); k++)
  145. {
  146. JSONValue _sig = classexcludes.Get(functionNames[k]);
  147. if (!_sig.IsArray())
  148. {
  149. ErrorExit("Bad exclude defintion");
  150. }
  151. JSONArray sig = _sig.GetArray();
  152. Vector<String> values;
  153. for (unsigned x = 0; x < sig.Size(); x++)
  154. {
  155. values.Push(sig[x].GetString());
  156. }
  157. JSBFunctionSignature* fe = new JSBFunctionSignature(functionNames[k], values);
  158. klass->AddFunctionExclude(fe);
  159. }
  160. }
  161. }
  162. }
  163. void JSBModule::ProcessTypeScriptDecl()
  164. {
  165. // TypeScript declarations
  166. JSONValue root = moduleJSON_->GetRoot();
  167. JSONValue decl = root.Get("typescript_decl");
  168. if (decl.IsObject())
  169. {
  170. Vector<String> childNames = decl.GetObject().Keys();
  171. for (unsigned j = 0; j < childNames.Size(); j++)
  172. {
  173. String classname = childNames.At(j);
  174. JSBClass* klass = GetClass(classname);
  175. if (!klass)
  176. {
  177. ErrorExit("Bad TypeScript decl klass");
  178. }
  179. JSONArray classdecl = decl.Get(classname).GetArray();
  180. for (unsigned k = 0; k < classdecl.Size(); k++)
  181. {
  182. klass->AddTypeScriptDecl(classdecl[k].GetString());
  183. }
  184. }
  185. }
  186. }
  187. void JSBModule::ProcessHaxeDecl()
  188. {
  189. // Haxe declarations
  190. JSONValue root = moduleJSON_->GetRoot();
  191. JSONValue decl = root.Get("haxe_decl");
  192. if (decl.IsObject())
  193. {
  194. Vector<String> childNames = decl.GetObject().Keys();
  195. for (unsigned j = 0; j < childNames.Size(); j++)
  196. {
  197. String classname = childNames.At(j);
  198. JSBClass* klass = GetClass(classname);
  199. if (!klass)
  200. {
  201. ErrorExit("Bad Haxe decl class");
  202. }
  203. JSONArray classdecl = decl.Get(classname).GetArray();
  204. for (unsigned k = 0; k < classdecl.Size(); k++)
  205. {
  206. klass->AddHaxeDecl(classdecl[k].GetString());
  207. }
  208. }
  209. }
  210. }
  211. void JSBModule::ScanHeaders()
  212. {
  213. JSBind* jsbind = GetSubsystem<JSBind>();
  214. FileSystem* fs = GetSubsystem<FileSystem>();
  215. const String& sourceRoot = jsbind->GetSourceRootFolder();
  216. for (unsigned i = 0; i < sourceDirs_.Size(); i++)
  217. {
  218. const String& dir = sourceRoot + sourceDirs_[i] + "/";
  219. Vector<String> fileNames;
  220. fs->ScanDir(fileNames, dir, "*.h", SCAN_FILES, false);
  221. for (unsigned k = 0; k < fileNames.Size(); k++)
  222. {
  223. String filepath = dir + fileNames[k];
  224. SharedPtr<JSBHeader> header(new JSBHeader(context_, this, filepath));
  225. // Parse the C++ header
  226. header->Parse();
  227. headers_.Push(header);
  228. }
  229. }
  230. }
  231. JSBClass* JSBModule::GetClass(const String& name)
  232. {
  233. if (classes_.Contains(name))
  234. return classes_[name];
  235. return 0;
  236. }
  237. void JSBModule::RegisterClass(String name)
  238. {
  239. String nativeName = name;
  240. if (classnames_.Contains(name))
  241. {
  242. if (classRenames_.Contains(name))
  243. {
  244. name = classRenames_[name];
  245. }
  246. if (JSBPackage::GetClassAllPackages(nativeName))
  247. {
  248. ErrorExit(ToString("Class collision: %s", name.CString()));
  249. }
  250. JSBClass* cls = new JSBClass(context_, this, name, nativeName);
  251. classes_[nativeName] = cls;
  252. package_->RegisterClass(cls);
  253. }
  254. }
  255. void JSBModule::RegisterEnum(JSBEnum* jenum)
  256. {
  257. if (JSBPackage::GetClassAllPackages(jenum->GetName()))
  258. {
  259. ErrorExit(ToString("Enum collision: %s", jenum->GetName().CString()));
  260. }
  261. enums_[jenum->GetName()] = jenum;
  262. }
  263. JSBEnum* JSBModule::GetEnum(const String& name)
  264. {
  265. if (enums_.Contains(name))
  266. {
  267. return enums_[name];
  268. }
  269. return 0;
  270. }
  271. bool JSBModule::ContainsConstant(const String& constantName)
  272. {
  273. return constants_.Contains(constantName);
  274. }
  275. void JSBModule::RegisterConstant(const String& constantName, unsigned type)
  276. {
  277. // MAX_CASCADE_SPLITS is defined differently for desktop/mobile
  278. if (constantName == "MAX_CASCADE_SPLITS" && JSBPackage::ContainsConstantAllPackages(constantName))
  279. {
  280. return;
  281. }
  282. if (JSBPackage::ContainsConstantAllPackages(constantName))
  283. {
  284. ErrorExit(ToString("Constant collision: %s", constantName.CString()));
  285. }
  286. constants_[constantName] = new JSBPrimitiveType(type);
  287. }
  288. bool JSBModule::Load(const String& jsonFilename)
  289. {
  290. JSBind* jsbind = GetSubsystem<JSBind>();
  291. LOGINFOF("Loading Module: %s", jsonFilename.CString());
  292. SharedPtr<File> jsonFile(new File(context_, jsonFilename));
  293. if (!jsonFile->IsOpen())
  294. {
  295. LOGERRORF("Unable to open module json: %s", jsonFilename.CString());
  296. return false;
  297. }
  298. moduleJSON_ = new JSONFile(context_);
  299. if (!moduleJSON_->BeginLoad(*jsonFile))
  300. {
  301. LOGERRORF("Unable to parse module json: %s", jsonFilename.CString());
  302. return false;
  303. }
  304. JSONValue root = moduleJSON_->GetRoot();
  305. name_ = root.Get("name").GetString();
  306. JSONValue requires = root.Get("requires");
  307. if (requires.IsArray())
  308. {
  309. for (unsigned j = 0; j < requires.GetArray().Size(); j++)
  310. {
  311. requirements_.Push(requires[j].GetString());
  312. }
  313. }
  314. JSONArray classes = root.Get("classes").GetArray();
  315. for (unsigned i = 0; i < classes.Size(); i++)
  316. {
  317. classnames_.Push(classes[i].GetString());
  318. }
  319. JSONValue classes_rename = root.Get("classes_rename");
  320. if (classes_rename.IsObject())
  321. {
  322. Vector<String> childNames = classes_rename.GetObject().Keys();
  323. for (unsigned j = 0; j < childNames.Size(); j++)
  324. {
  325. String classname = childNames.At(j);
  326. String crename = classes_rename.Get(classname).GetString();
  327. classRenames_[classname] = crename;
  328. }
  329. }
  330. JSONValue includes = root.Get("includes");
  331. if (includes.IsArray())
  332. {
  333. for (unsigned j = 0; j < includes.GetArray().Size(); j++)
  334. {
  335. includes_.Push(includes.GetArray()[j].GetString());
  336. }
  337. }
  338. JSONValue sources = root.Get("sources");
  339. for (unsigned i = 0; i < sources.GetArray().Size(); i++)
  340. {
  341. sourceDirs_.Push(sources.GetArray()[i].GetString());
  342. }
  343. if (name_ == "Graphics")
  344. {
  345. #ifdef _MSC_VER
  346. if (jsbind->GetPlatform() == "ANDROID" || jsbind->GetPlatform() == "WEB")
  347. {
  348. sourceDirs_.Push("Source/Atomic/Graphics/OpenGL");
  349. }
  350. else
  351. {
  352. #ifdef ATOMIC_D3D11
  353. sourceDirs_.Push("Source/Atomic/Graphics/Direct3D11");
  354. #else
  355. sourceDirs_.Push("Source/Atomic/Graphics/Direct3D9");
  356. #endif
  357. }
  358. #else
  359. sourceDirs_.Push("Source/Atomic/Graphics/OpenGL");
  360. #endif
  361. }
  362. ScanHeaders();
  363. return true;
  364. }
  365. void JSBModule::GenerateSource(const String& outPath)
  366. {
  367. JSBModuleWriter writer(this);
  368. writer.GenerateSource(source_);
  369. String filepath = outPath + "/JSModule" + name_ + ".cpp";
  370. File file(context_);
  371. file.Open(filepath, FILE_WRITE);
  372. file.Write(source_.CString(), source_.Length());
  373. file.Close();
  374. }
  375. void JSBModule::GenerateCSharpSource(const String& outPath)
  376. {
  377. CSBModuleWriter writer(this);
  378. writer.GenerateSource(source_);
  379. String filepath = outPath + "/CSModule" + name_ + ".cpp";
  380. File file(context_);
  381. file.Open(filepath, FILE_WRITE);
  382. file.Write(source_.CString(), source_.Length());
  383. file.Close();
  384. }
  385. }