nativescript.cpp 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973
  1. /*************************************************************************/
  2. /* nativescript.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "nativescript.h"
  31. #include <stdint.h>
  32. #include "gdnative/gdnative.h"
  33. #include "core/core_string_names.h"
  34. #include "core/global_constants.h"
  35. #include "core/io/file_access_encrypted.h"
  36. #include "core/os/file_access.h"
  37. #include "core/os/os.h"
  38. #include "core/project_settings.h"
  39. #include "scene/main/scene_tree.h"
  40. #include "scene/resources/resource_format_text.h"
  41. #include <stdlib.h>
  42. #ifndef NO_THREADS
  43. #include "core/os/thread.h"
  44. #endif
  45. #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
  46. #include "api_generator.h"
  47. #endif
  48. #ifdef TOOLS_ENABLED
  49. #include "editor/editor_node.h"
  50. #endif
  51. void NativeScript::_bind_methods() {
  52. ClassDB::bind_method(D_METHOD("set_class_name", "class_name"), &NativeScript::set_class_name);
  53. ClassDB::bind_method(D_METHOD("get_class_name"), &NativeScript::get_class_name);
  54. ClassDB::bind_method(D_METHOD("set_library", "library"), &NativeScript::set_library);
  55. ClassDB::bind_method(D_METHOD("get_library"), &NativeScript::get_library);
  56. ClassDB::bind_method(D_METHOD("set_script_class_name", "class_name"), &NativeScript::set_script_class_name);
  57. ClassDB::bind_method(D_METHOD("get_script_class_name"), &NativeScript::get_script_class_name);
  58. ClassDB::bind_method(D_METHOD("set_script_class_icon_path", "icon_path"), &NativeScript::set_script_class_icon_path);
  59. ClassDB::bind_method(D_METHOD("get_script_class_icon_path"), &NativeScript::get_script_class_icon_path);
  60. ClassDB::bind_method(D_METHOD("get_class_documentation"), &NativeScript::get_class_documentation);
  61. ClassDB::bind_method(D_METHOD("get_method_documentation", "method"), &NativeScript::get_method_documentation);
  62. ClassDB::bind_method(D_METHOD("get_signal_documentation", "signal_name"), &NativeScript::get_signal_documentation);
  63. ClassDB::bind_method(D_METHOD("get_property_documentation", "path"), &NativeScript::get_property_documentation);
  64. ADD_PROPERTY(PropertyInfo(Variant::STRING, "class_name"), "set_class_name", "get_class_name");
  65. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "library", PROPERTY_HINT_RESOURCE_TYPE, "GDNativeLibrary"), "set_library", "get_library");
  66. ADD_GROUP("Script Class", "script_class_");
  67. ADD_PROPERTY(PropertyInfo(Variant::STRING, "script_class_name"), "set_script_class_name", "get_script_class_name");
  68. ADD_PROPERTY(PropertyInfo(Variant::STRING, "script_class_icon_path", PROPERTY_HINT_FILE), "set_script_class_icon_path", "get_script_class_icon_path");
  69. ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &NativeScript::_new, MethodInfo("new"));
  70. }
  71. #define NSL NativeScriptLanguage::get_singleton()
  72. #ifdef TOOLS_ENABLED
  73. void NativeScript::_update_placeholder(PlaceHolderScriptInstance *p_placeholder) {
  74. NativeScriptDesc *script_data = get_script_desc();
  75. ERR_FAIL_COND(!script_data);
  76. List<PropertyInfo> info;
  77. get_script_property_list(&info);
  78. Map<StringName, Variant> values;
  79. for (List<PropertyInfo>::Element *E = info.front(); E; E = E->next()) {
  80. Variant value;
  81. get_property_default_value(E->get().name, value);
  82. values[E->get().name] = value;
  83. }
  84. p_placeholder->update(info, values);
  85. }
  86. void NativeScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
  87. placeholders.erase(p_placeholder);
  88. }
  89. #endif
  90. bool NativeScript::inherits_script(const Ref<Script> &p_script) const {
  91. #ifndef _MSC_VER
  92. #warning inheritance needs to be implemented in NativeScript
  93. #endif
  94. return false;
  95. }
  96. void NativeScript::set_class_name(String p_class_name) {
  97. class_name = p_class_name;
  98. }
  99. String NativeScript::get_class_name() const {
  100. return class_name;
  101. }
  102. void NativeScript::set_library(Ref<GDNativeLibrary> p_library) {
  103. if (!library.is_null()) {
  104. WARN_PRINT("Library in NativeScript already set. Do nothing.");
  105. return;
  106. }
  107. if (p_library.is_null()) {
  108. return;
  109. }
  110. library = p_library;
  111. lib_path = library->get_current_library_path();
  112. #ifndef NO_THREADS
  113. if (Thread::get_caller_id() != Thread::get_main_id()) {
  114. NSL->defer_init_library(p_library, this);
  115. } else
  116. #endif
  117. {
  118. NSL->init_library(p_library);
  119. NSL->register_script(this);
  120. }
  121. }
  122. Ref<GDNativeLibrary> NativeScript::get_library() const {
  123. return library;
  124. }
  125. void NativeScript::set_script_class_name(String p_type) {
  126. script_class_name = p_type;
  127. }
  128. String NativeScript::get_script_class_name() const {
  129. return script_class_name;
  130. }
  131. void NativeScript::set_script_class_icon_path(String p_icon_path) {
  132. script_class_icon_path = p_icon_path;
  133. }
  134. String NativeScript::get_script_class_icon_path() const {
  135. return script_class_icon_path;
  136. }
  137. bool NativeScript::can_instance() const {
  138. NativeScriptDesc *script_data = get_script_desc();
  139. #ifdef TOOLS_ENABLED
  140. // Only valid if this is either a tool script or a "regular" script.
  141. // (so an environment whre scripting is disabled (and not the editor) would not
  142. // create objects).
  143. return script_data && (is_tool() || ScriptServer::is_scripting_enabled());
  144. #else
  145. return script_data;
  146. #endif
  147. }
  148. Ref<Script> NativeScript::get_base_script() const {
  149. NativeScriptDesc *script_data = get_script_desc();
  150. if (!script_data)
  151. return Ref<Script>();
  152. NativeScript *script = (NativeScript *)NSL->create_script();
  153. Ref<NativeScript> ns = Ref<NativeScript>(script);
  154. ERR_FAIL_COND_V(!ns.is_valid(), Ref<Script>());
  155. ns->set_class_name(script_data->base);
  156. ns->set_library(get_library());
  157. return ns;
  158. }
  159. StringName NativeScript::get_instance_base_type() const {
  160. NativeScriptDesc *script_data = get_script_desc();
  161. if (!script_data)
  162. return "";
  163. return script_data->base_native_type;
  164. }
  165. ScriptInstance *NativeScript::instance_create(Object *p_this) {
  166. NativeScriptDesc *script_data = get_script_desc();
  167. if (!script_data) {
  168. return nullptr;
  169. }
  170. NativeScriptInstance *nsi = memnew(NativeScriptInstance);
  171. nsi->owner = p_this;
  172. nsi->script = Ref<NativeScript>(this);
  173. #ifndef TOOLS_ENABLED
  174. if (!ScriptServer::is_scripting_enabled()) {
  175. nsi->userdata = nullptr;
  176. } else {
  177. nsi->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data);
  178. }
  179. #else
  180. nsi->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data);
  181. #endif
  182. {
  183. MutexLock lock(owners_lock);
  184. instance_owners.insert(p_this);
  185. }
  186. return nsi;
  187. }
  188. PlaceHolderScriptInstance *NativeScript::placeholder_instance_create(Object *p_this) {
  189. #ifdef TOOLS_ENABLED
  190. PlaceHolderScriptInstance *sins = memnew(PlaceHolderScriptInstance(NSL, Ref<Script>(this), p_this));
  191. placeholders.insert(sins);
  192. _update_placeholder(sins);
  193. return sins;
  194. #else
  195. return nullptr;
  196. #endif
  197. }
  198. bool NativeScript::instance_has(const Object *p_this) const {
  199. return instance_owners.has((Object *)p_this);
  200. }
  201. bool NativeScript::has_source_code() const {
  202. return false;
  203. }
  204. String NativeScript::get_source_code() const {
  205. return "";
  206. }
  207. void NativeScript::set_source_code(const String &p_code) {
  208. }
  209. Error NativeScript::reload(bool p_keep_state) {
  210. return FAILED;
  211. }
  212. bool NativeScript::has_method(const StringName &p_method) const {
  213. NativeScriptDesc *script_data = get_script_desc();
  214. while (script_data) {
  215. if (script_data->methods.has(p_method))
  216. return true;
  217. script_data = script_data->base_data;
  218. }
  219. return false;
  220. }
  221. MethodInfo NativeScript::get_method_info(const StringName &p_method) const {
  222. NativeScriptDesc *script_data = get_script_desc();
  223. if (!script_data)
  224. return MethodInfo();
  225. while (script_data) {
  226. Map<StringName, NativeScriptDesc::Method>::Element *M = script_data->methods.find(p_method);
  227. if (M)
  228. return M->get().info;
  229. script_data = script_data->base_data;
  230. }
  231. return MethodInfo();
  232. }
  233. bool NativeScript::is_valid() const {
  234. return true;
  235. }
  236. bool NativeScript::is_tool() const {
  237. NativeScriptDesc *script_data = get_script_desc();
  238. if (script_data)
  239. return script_data->is_tool;
  240. return false;
  241. }
  242. ScriptLanguage *NativeScript::get_language() const {
  243. return NativeScriptLanguage::get_singleton();
  244. }
  245. bool NativeScript::has_script_signal(const StringName &p_signal) const {
  246. NativeScriptDesc *script_data = get_script_desc();
  247. while (script_data) {
  248. if (script_data->signals_.has(p_signal))
  249. return true;
  250. script_data = script_data->base_data;
  251. }
  252. return false;
  253. }
  254. void NativeScript::get_script_signal_list(List<MethodInfo> *r_signals) const {
  255. NativeScriptDesc *script_data = get_script_desc();
  256. if (!script_data)
  257. return;
  258. Set<MethodInfo> signals_;
  259. while (script_data) {
  260. for (Map<StringName, NativeScriptDesc::Signal>::Element *S = script_data->signals_.front(); S; S = S->next()) {
  261. signals_.insert(S->get().signal);
  262. }
  263. script_data = script_data->base_data;
  264. }
  265. for (Set<MethodInfo>::Element *E = signals_.front(); E; E = E->next()) {
  266. r_signals->push_back(E->get());
  267. }
  268. }
  269. bool NativeScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
  270. NativeScriptDesc *script_data = get_script_desc();
  271. OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P;
  272. while (!P && script_data) {
  273. P = script_data->properties.find(p_property);
  274. script_data = script_data->base_data;
  275. }
  276. if (!P)
  277. return false;
  278. r_value = P.get().default_value;
  279. return true;
  280. }
  281. void NativeScript::update_exports() {
  282. }
  283. void NativeScript::get_script_method_list(List<MethodInfo> *p_list) const {
  284. NativeScriptDesc *script_data = get_script_desc();
  285. if (!script_data)
  286. return;
  287. Set<MethodInfo> methods;
  288. while (script_data) {
  289. for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
  290. methods.insert(E->get().info);
  291. }
  292. script_data = script_data->base_data;
  293. }
  294. for (Set<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
  295. p_list->push_back(E->get());
  296. }
  297. }
  298. void NativeScript::get_script_property_list(List<PropertyInfo> *p_list) const {
  299. NativeScriptDesc *script_data = get_script_desc();
  300. Set<StringName> existing_properties;
  301. List<PropertyInfo>::Element *original_back = p_list->back();
  302. while (script_data) {
  303. List<PropertyInfo>::Element *insert_position = original_back;
  304. for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
  305. if (!existing_properties.has(E.key())) {
  306. insert_position = p_list->insert_after(insert_position, E.get().info);
  307. existing_properties.insert(E.key());
  308. }
  309. }
  310. script_data = script_data->base_data;
  311. }
  312. }
  313. Vector<ScriptNetData> NativeScript::get_rpc_methods() const {
  314. Vector<ScriptNetData> v;
  315. NativeScriptDesc *script_data = get_script_desc();
  316. while (script_data) {
  317. for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
  318. if (E->get().rpc_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
  319. ScriptNetData nd;
  320. nd.name = E->key();
  321. nd.mode = MultiplayerAPI::RPCMode(E->get().rpc_mode);
  322. v.push_back(nd);
  323. }
  324. }
  325. script_data = script_data->base_data;
  326. }
  327. return v;
  328. }
  329. uint16_t NativeScript::get_rpc_method_id(const StringName &p_method) const {
  330. NativeScriptDesc *script_data = get_script_desc();
  331. while (script_data) {
  332. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
  333. if (E) {
  334. return E->get().rpc_method_id;
  335. }
  336. script_data = script_data->base_data;
  337. }
  338. return UINT16_MAX;
  339. }
  340. StringName NativeScript::get_rpc_method(uint16_t p_id) const {
  341. ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
  342. NativeScriptDesc *script_data = get_script_desc();
  343. while (script_data) {
  344. for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
  345. if (E->get().rpc_method_id == p_id) {
  346. return E->key();
  347. }
  348. }
  349. script_data = script_data->base_data;
  350. }
  351. return StringName();
  352. }
  353. MultiplayerAPI::RPCMode NativeScript::get_rpc_mode_by_id(uint16_t p_id) const {
  354. ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
  355. NativeScriptDesc *script_data = get_script_desc();
  356. while (script_data) {
  357. for (Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.front(); E; E = E->next()) {
  358. if (E->get().rpc_method_id == p_id) {
  359. switch (E->get().rpc_mode) {
  360. case GODOT_METHOD_RPC_MODE_DISABLED:
  361. return MultiplayerAPI::RPC_MODE_DISABLED;
  362. case GODOT_METHOD_RPC_MODE_REMOTE:
  363. return MultiplayerAPI::RPC_MODE_REMOTE;
  364. case GODOT_METHOD_RPC_MODE_MASTER:
  365. return MultiplayerAPI::RPC_MODE_MASTER;
  366. case GODOT_METHOD_RPC_MODE_PUPPET:
  367. return MultiplayerAPI::RPC_MODE_PUPPET;
  368. case GODOT_METHOD_RPC_MODE_REMOTESYNC:
  369. return MultiplayerAPI::RPC_MODE_REMOTESYNC;
  370. case GODOT_METHOD_RPC_MODE_MASTERSYNC:
  371. return MultiplayerAPI::RPC_MODE_MASTERSYNC;
  372. case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
  373. return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
  374. default:
  375. return MultiplayerAPI::RPC_MODE_DISABLED;
  376. }
  377. }
  378. }
  379. script_data = script_data->base_data;
  380. }
  381. return MultiplayerAPI::RPC_MODE_DISABLED;
  382. }
  383. MultiplayerAPI::RPCMode NativeScript::get_rpc_mode(const StringName &p_method) const {
  384. NativeScriptDesc *script_data = get_script_desc();
  385. while (script_data) {
  386. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
  387. if (E) {
  388. switch (E->get().rpc_mode) {
  389. case GODOT_METHOD_RPC_MODE_DISABLED:
  390. return MultiplayerAPI::RPC_MODE_DISABLED;
  391. case GODOT_METHOD_RPC_MODE_REMOTE:
  392. return MultiplayerAPI::RPC_MODE_REMOTE;
  393. case GODOT_METHOD_RPC_MODE_MASTER:
  394. return MultiplayerAPI::RPC_MODE_MASTER;
  395. case GODOT_METHOD_RPC_MODE_PUPPET:
  396. return MultiplayerAPI::RPC_MODE_PUPPET;
  397. case GODOT_METHOD_RPC_MODE_REMOTESYNC:
  398. return MultiplayerAPI::RPC_MODE_REMOTESYNC;
  399. case GODOT_METHOD_RPC_MODE_MASTERSYNC:
  400. return MultiplayerAPI::RPC_MODE_MASTERSYNC;
  401. case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
  402. return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
  403. default:
  404. return MultiplayerAPI::RPC_MODE_DISABLED;
  405. }
  406. }
  407. script_data = script_data->base_data;
  408. }
  409. return MultiplayerAPI::RPC_MODE_DISABLED;
  410. }
  411. Vector<ScriptNetData> NativeScript::get_rset_properties() const {
  412. Vector<ScriptNetData> v;
  413. NativeScriptDesc *script_data = get_script_desc();
  414. while (script_data) {
  415. for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
  416. if (E.get().rset_mode != GODOT_METHOD_RPC_MODE_DISABLED) {
  417. ScriptNetData nd;
  418. nd.name = E.key();
  419. nd.mode = MultiplayerAPI::RPCMode(E.get().rset_mode);
  420. v.push_back(nd);
  421. }
  422. }
  423. script_data = script_data->base_data;
  424. }
  425. return v;
  426. }
  427. uint16_t NativeScript::get_rset_property_id(const StringName &p_variable) const {
  428. NativeScriptDesc *script_data = get_script_desc();
  429. while (script_data) {
  430. OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
  431. if (E) {
  432. return E.get().rset_property_id;
  433. }
  434. script_data = script_data->base_data;
  435. }
  436. return UINT16_MAX;
  437. }
  438. StringName NativeScript::get_rset_property(uint16_t p_id) const {
  439. ERR_FAIL_COND_V(p_id == UINT16_MAX, StringName());
  440. NativeScriptDesc *script_data = get_script_desc();
  441. while (script_data) {
  442. for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
  443. if (E.get().rset_property_id == p_id) {
  444. return E.key();
  445. }
  446. }
  447. script_data = script_data->base_data;
  448. }
  449. return StringName();
  450. }
  451. MultiplayerAPI::RPCMode NativeScript::get_rset_mode_by_id(uint16_t p_id) const {
  452. ERR_FAIL_COND_V(p_id == UINT16_MAX, MultiplayerAPI::RPC_MODE_DISABLED);
  453. NativeScriptDesc *script_data = get_script_desc();
  454. while (script_data) {
  455. for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.front(); E; E = E.next()) {
  456. if (E.get().rset_property_id == p_id) {
  457. switch (E.get().rset_mode) {
  458. case GODOT_METHOD_RPC_MODE_DISABLED:
  459. return MultiplayerAPI::RPC_MODE_DISABLED;
  460. case GODOT_METHOD_RPC_MODE_REMOTE:
  461. return MultiplayerAPI::RPC_MODE_REMOTE;
  462. case GODOT_METHOD_RPC_MODE_MASTER:
  463. return MultiplayerAPI::RPC_MODE_MASTER;
  464. case GODOT_METHOD_RPC_MODE_PUPPET:
  465. return MultiplayerAPI::RPC_MODE_PUPPET;
  466. case GODOT_METHOD_RPC_MODE_REMOTESYNC:
  467. return MultiplayerAPI::RPC_MODE_REMOTESYNC;
  468. case GODOT_METHOD_RPC_MODE_MASTERSYNC:
  469. return MultiplayerAPI::RPC_MODE_MASTERSYNC;
  470. case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
  471. return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
  472. default:
  473. return MultiplayerAPI::RPC_MODE_DISABLED;
  474. }
  475. }
  476. }
  477. script_data = script_data->base_data;
  478. }
  479. return MultiplayerAPI::RPC_MODE_DISABLED;
  480. }
  481. MultiplayerAPI::RPCMode NativeScript::get_rset_mode(const StringName &p_variable) const {
  482. NativeScriptDesc *script_data = get_script_desc();
  483. while (script_data) {
  484. OrderedHashMap<StringName, NativeScriptDesc::Property>::Element E = script_data->properties.find(p_variable);
  485. if (E) {
  486. switch (E.get().rset_mode) {
  487. case GODOT_METHOD_RPC_MODE_DISABLED:
  488. return MultiplayerAPI::RPC_MODE_DISABLED;
  489. case GODOT_METHOD_RPC_MODE_REMOTE:
  490. return MultiplayerAPI::RPC_MODE_REMOTE;
  491. case GODOT_METHOD_RPC_MODE_MASTER:
  492. return MultiplayerAPI::RPC_MODE_MASTER;
  493. case GODOT_METHOD_RPC_MODE_PUPPET:
  494. return MultiplayerAPI::RPC_MODE_PUPPET;
  495. case GODOT_METHOD_RPC_MODE_REMOTESYNC:
  496. return MultiplayerAPI::RPC_MODE_REMOTESYNC;
  497. case GODOT_METHOD_RPC_MODE_MASTERSYNC:
  498. return MultiplayerAPI::RPC_MODE_MASTERSYNC;
  499. case GODOT_METHOD_RPC_MODE_PUPPETSYNC:
  500. return MultiplayerAPI::RPC_MODE_PUPPETSYNC;
  501. default:
  502. return MultiplayerAPI::RPC_MODE_DISABLED;
  503. }
  504. }
  505. script_data = script_data->base_data;
  506. }
  507. return MultiplayerAPI::RPC_MODE_DISABLED;
  508. }
  509. String NativeScript::get_class_documentation() const {
  510. NativeScriptDesc *script_data = get_script_desc();
  511. ERR_FAIL_COND_V_MSG(!script_data, "", "Attempt to get class documentation on invalid NativeScript.");
  512. return script_data->documentation;
  513. }
  514. String NativeScript::get_method_documentation(const StringName &p_method) const {
  515. NativeScriptDesc *script_data = get_script_desc();
  516. ERR_FAIL_COND_V_MSG(!script_data, "", "Attempt to get method documentation on invalid NativeScript.");
  517. while (script_data) {
  518. Map<StringName, NativeScriptDesc::Method>::Element *method = script_data->methods.find(p_method);
  519. if (method) {
  520. return method->get().documentation;
  521. }
  522. script_data = script_data->base_data;
  523. }
  524. ERR_FAIL_V_MSG("", "Attempt to get method documentation for non-existent method.");
  525. }
  526. String NativeScript::get_signal_documentation(const StringName &p_signal_name) const {
  527. NativeScriptDesc *script_data = get_script_desc();
  528. ERR_FAIL_COND_V_MSG(!script_data, "", "Attempt to get signal documentation on invalid NativeScript.");
  529. while (script_data) {
  530. Map<StringName, NativeScriptDesc::Signal>::Element *signal = script_data->signals_.find(p_signal_name);
  531. if (signal) {
  532. return signal->get().documentation;
  533. }
  534. script_data = script_data->base_data;
  535. }
  536. ERR_FAIL_V_MSG("", "Attempt to get signal documentation for non-existent signal.");
  537. }
  538. String NativeScript::get_property_documentation(const StringName &p_path) const {
  539. NativeScriptDesc *script_data = get_script_desc();
  540. ERR_FAIL_COND_V_MSG(!script_data, "", "Attempt to get property documentation on invalid NativeScript.");
  541. while (script_data) {
  542. OrderedHashMap<StringName, NativeScriptDesc::Property>::Element property = script_data->properties.find(p_path);
  543. if (property) {
  544. return property.get().documentation;
  545. }
  546. script_data = script_data->base_data;
  547. }
  548. ERR_FAIL_V_MSG("", "Attempt to get property documentation for non-existent signal.");
  549. }
  550. Variant NativeScript::_new(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
  551. if (lib_path.empty() || class_name.empty() || library.is_null()) {
  552. r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
  553. return Variant();
  554. }
  555. NativeScriptDesc *script_data = get_script_desc();
  556. if (!script_data) {
  557. r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
  558. return Variant();
  559. }
  560. r_error.error = Callable::CallError::CALL_OK;
  561. REF ref;
  562. Object *owner = nullptr;
  563. if (!(script_data->base_native_type == "")) {
  564. owner = ClassDB::instance(script_data->base_native_type);
  565. } else {
  566. owner = memnew(Reference);
  567. }
  568. if (!owner) {
  569. r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL;
  570. return Variant();
  571. }
  572. Reference *r = Object::cast_to<Reference>(owner);
  573. if (r) {
  574. ref = REF(r);
  575. }
  576. NativeScriptInstance *instance = (NativeScriptInstance *)instance_create(owner);
  577. owner->set_script_instance(instance);
  578. if (!instance) {
  579. if (ref.is_null()) {
  580. memdelete(owner); //no owner, sorry
  581. }
  582. return Variant();
  583. }
  584. if (ref.is_valid()) {
  585. return ref;
  586. } else {
  587. return owner;
  588. }
  589. }
  590. NativeScript::NativeScript() {
  591. library = Ref<GDNative>();
  592. lib_path = "";
  593. class_name = "";
  594. }
  595. NativeScript::~NativeScript() {
  596. NSL->unregister_script(this);
  597. }
  598. #define GET_SCRIPT_DESC() script->get_script_desc()
  599. void NativeScriptInstance::_ml_call_reversed(NativeScriptDesc *script_data, const StringName &p_method, const Variant **p_args, int p_argcount) {
  600. if (script_data->base_data) {
  601. _ml_call_reversed(script_data->base_data, p_method, p_args, p_argcount);
  602. }
  603. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
  604. if (E) {
  605. godot_variant res = E->get().method.method((godot_object *)owner, E->get().method.method_data, userdata, p_argcount, (godot_variant **)p_args);
  606. godot_variant_destroy(&res);
  607. }
  608. }
  609. bool NativeScriptInstance::set(const StringName &p_name, const Variant &p_value) {
  610. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  611. while (script_data) {
  612. OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = script_data->properties.find(p_name);
  613. if (P) {
  614. P.get().setter.set_func((godot_object *)owner,
  615. P.get().setter.method_data,
  616. userdata,
  617. (godot_variant *)&p_value);
  618. return true;
  619. }
  620. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find("_set");
  621. if (E) {
  622. Variant name = p_name;
  623. const Variant *args[2] = { &name, &p_value };
  624. godot_variant result;
  625. result = E->get().method.method((godot_object *)owner,
  626. E->get().method.method_data,
  627. userdata,
  628. 2,
  629. (godot_variant **)args);
  630. bool handled = *(Variant *)&result;
  631. godot_variant_destroy(&result);
  632. if (handled) {
  633. return true;
  634. }
  635. }
  636. script_data = script_data->base_data;
  637. }
  638. return false;
  639. }
  640. bool NativeScriptInstance::get(const StringName &p_name, Variant &r_ret) const {
  641. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  642. while (script_data) {
  643. OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = script_data->properties.find(p_name);
  644. if (P) {
  645. godot_variant value;
  646. value = P.get().getter.get_func((godot_object *)owner,
  647. P.get().getter.method_data,
  648. userdata);
  649. r_ret = *(Variant *)&value;
  650. godot_variant_destroy(&value);
  651. return true;
  652. }
  653. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find("_get");
  654. if (E) {
  655. Variant name = p_name;
  656. const Variant *args[1] = { &name };
  657. godot_variant result;
  658. result = E->get().method.method((godot_object *)owner,
  659. E->get().method.method_data,
  660. userdata,
  661. 1,
  662. (godot_variant **)args);
  663. r_ret = *(Variant *)&result;
  664. godot_variant_destroy(&result);
  665. if (r_ret.get_type() != Variant::NIL) {
  666. return true;
  667. }
  668. }
  669. script_data = script_data->base_data;
  670. }
  671. return false;
  672. }
  673. void NativeScriptInstance::get_property_list(List<PropertyInfo> *p_properties) const {
  674. script->get_script_property_list(p_properties);
  675. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  676. while (script_data) {
  677. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find("_get_property_list");
  678. if (E) {
  679. godot_variant result;
  680. result = E->get().method.method((godot_object *)owner,
  681. E->get().method.method_data,
  682. userdata,
  683. 0,
  684. nullptr);
  685. Variant res = *(Variant *)&result;
  686. godot_variant_destroy(&result);
  687. ERR_FAIL_COND_MSG(res.get_type() != Variant::ARRAY, "_get_property_list must return an array of dictionaries.");
  688. Array arr = res;
  689. for (int i = 0; i < arr.size(); i++) {
  690. Dictionary d = arr[i];
  691. ERR_CONTINUE(!d.has("name"));
  692. ERR_CONTINUE(!d.has("type"));
  693. PropertyInfo info;
  694. info.type = Variant::Type(d["type"].operator int64_t());
  695. ERR_CONTINUE(info.type < 0 || info.type >= Variant::VARIANT_MAX);
  696. info.name = d["name"];
  697. ERR_CONTINUE(info.name == "");
  698. if (d.has("hint")) {
  699. info.hint = PropertyHint(d["hint"].operator int64_t());
  700. }
  701. if (d.has("hint_string")) {
  702. info.hint_string = d["hint_string"];
  703. }
  704. if (d.has("usage")) {
  705. info.usage = d["usage"];
  706. }
  707. p_properties->push_back(info);
  708. }
  709. }
  710. script_data = script_data->base_data;
  711. }
  712. return;
  713. }
  714. Variant::Type NativeScriptInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
  715. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  716. while (script_data) {
  717. OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = script_data->properties.find(p_name);
  718. if (P) {
  719. *r_is_valid = true;
  720. return P.get().info.type;
  721. }
  722. script_data = script_data->base_data;
  723. }
  724. return Variant::NIL;
  725. }
  726. void NativeScriptInstance::get_method_list(List<MethodInfo> *p_list) const {
  727. script->get_script_method_list(p_list);
  728. }
  729. bool NativeScriptInstance::has_method(const StringName &p_method) const {
  730. return script->has_method(p_method);
  731. }
  732. Variant NativeScriptInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
  733. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  734. while (script_data) {
  735. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
  736. if (E) {
  737. godot_variant result;
  738. #ifdef DEBUG_ENABLED
  739. current_method_call = p_method;
  740. #endif
  741. result = E->get().method.method((godot_object *)owner,
  742. E->get().method.method_data,
  743. userdata,
  744. p_argcount,
  745. (godot_variant **)p_args);
  746. #ifdef DEBUG_ENABLED
  747. current_method_call = "";
  748. #endif
  749. Variant res = *(Variant *)&result;
  750. godot_variant_destroy(&result);
  751. r_error.error = Callable::CallError::CALL_OK;
  752. return res;
  753. }
  754. script_data = script_data->base_data;
  755. }
  756. r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
  757. return Variant();
  758. }
  759. void NativeScriptInstance::notification(int p_notification) {
  760. #ifdef DEBUG_ENABLED
  761. if (p_notification == MainLoop::NOTIFICATION_CRASH) {
  762. if (current_method_call != StringName("")) {
  763. ERR_PRINT("NativeScriptInstance detected crash on method: " + current_method_call);
  764. current_method_call = "";
  765. }
  766. }
  767. #endif
  768. Variant value = p_notification;
  769. const Variant *args[1] = { &value };
  770. call_multilevel("_notification", args, 1);
  771. }
  772. String NativeScriptInstance::to_string(bool *r_valid) {
  773. if (has_method(CoreStringNames::get_singleton()->_to_string)) {
  774. Callable::CallError ce;
  775. Variant ret = call(CoreStringNames::get_singleton()->_to_string, nullptr, 0, ce);
  776. if (ce.error == Callable::CallError::CALL_OK) {
  777. if (ret.get_type() != Variant::STRING) {
  778. if (r_valid)
  779. *r_valid = false;
  780. ERR_FAIL_V_MSG(String(), "Wrong type for " + CoreStringNames::get_singleton()->_to_string + ", must be a String.");
  781. }
  782. if (r_valid)
  783. *r_valid = true;
  784. return ret.operator String();
  785. }
  786. }
  787. if (r_valid)
  788. *r_valid = false;
  789. return String();
  790. }
  791. void NativeScriptInstance::refcount_incremented() {
  792. Callable::CallError err;
  793. call("_refcount_incremented", nullptr, 0, err);
  794. if (err.error != Callable::CallError::CALL_OK && err.error != Callable::CallError::CALL_ERROR_INVALID_METHOD) {
  795. ERR_PRINT("Failed to invoke _refcount_incremented - should not happen");
  796. }
  797. }
  798. bool NativeScriptInstance::refcount_decremented() {
  799. Callable::CallError err;
  800. Variant ret = call("_refcount_decremented", nullptr, 0, err);
  801. if (err.error != Callable::CallError::CALL_OK && err.error != Callable::CallError::CALL_ERROR_INVALID_METHOD) {
  802. ERR_PRINT("Failed to invoke _refcount_decremented - should not happen");
  803. return true; // assume we can destroy the object
  804. }
  805. if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
  806. // the method does not exist, default is true
  807. return true;
  808. }
  809. return ret;
  810. }
  811. Ref<Script> NativeScriptInstance::get_script() const {
  812. return script;
  813. }
  814. Vector<ScriptNetData> NativeScriptInstance::get_rpc_methods() const {
  815. return script->get_rpc_methods();
  816. }
  817. uint16_t NativeScriptInstance::get_rpc_method_id(const StringName &p_method) const {
  818. return script->get_rpc_method_id(p_method);
  819. }
  820. StringName NativeScriptInstance::get_rpc_method(uint16_t p_id) const {
  821. return script->get_rpc_method(p_id);
  822. }
  823. MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode_by_id(uint16_t p_id) const {
  824. return script->get_rpc_mode_by_id(p_id);
  825. }
  826. MultiplayerAPI::RPCMode NativeScriptInstance::get_rpc_mode(const StringName &p_method) const {
  827. return script->get_rpc_mode(p_method);
  828. }
  829. Vector<ScriptNetData> NativeScriptInstance::get_rset_properties() const {
  830. return script->get_rset_properties();
  831. }
  832. uint16_t NativeScriptInstance::get_rset_property_id(const StringName &p_variable) const {
  833. return script->get_rset_property_id(p_variable);
  834. }
  835. StringName NativeScriptInstance::get_rset_property(uint16_t p_id) const {
  836. return script->get_rset_property(p_id);
  837. }
  838. MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode_by_id(uint16_t p_id) const {
  839. return script->get_rset_mode_by_id(p_id);
  840. }
  841. MultiplayerAPI::RPCMode NativeScriptInstance::get_rset_mode(const StringName &p_variable) const {
  842. return script->get_rset_mode(p_variable);
  843. }
  844. ScriptLanguage *NativeScriptInstance::get_language() {
  845. return NativeScriptLanguage::get_singleton();
  846. }
  847. void NativeScriptInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
  848. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  849. while (script_data) {
  850. Map<StringName, NativeScriptDesc::Method>::Element *E = script_data->methods.find(p_method);
  851. if (E) {
  852. godot_variant res = E->get().method.method((godot_object *)owner,
  853. E->get().method.method_data,
  854. userdata,
  855. p_argcount,
  856. (godot_variant **)p_args);
  857. godot_variant_destroy(&res);
  858. }
  859. script_data = script_data->base_data;
  860. }
  861. }
  862. void NativeScriptInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
  863. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  864. if (script_data) {
  865. _ml_call_reversed(script_data, p_method, p_args, p_argcount);
  866. }
  867. }
  868. NativeScriptInstance::~NativeScriptInstance() {
  869. NativeScriptDesc *script_data = GET_SCRIPT_DESC();
  870. if (!script_data)
  871. return;
  872. script_data->destroy_func.destroy_func((godot_object *)owner, script_data->destroy_func.method_data, userdata);
  873. if (owner) {
  874. MutexLock lock(script->owners_lock);
  875. script->instance_owners.erase(owner);
  876. }
  877. }
  878. NativeScriptLanguage *NativeScriptLanguage::singleton;
  879. void NativeScriptLanguage::_unload_stuff(bool p_reload) {
  880. Map<String, Ref<GDNative>> erase_and_unload;
  881. for (Map<String, Map<StringName, NativeScriptDesc>>::Element *L = library_classes.front(); L; L = L->next()) {
  882. String lib_path = L->key();
  883. Map<StringName, NativeScriptDesc> classes = L->get();
  884. if (p_reload) {
  885. Map<String, Ref<GDNative>>::Element *E = library_gdnatives.find(lib_path);
  886. Ref<GDNative> gdn;
  887. if (E) {
  888. gdn = E->get();
  889. }
  890. bool should_reload = false;
  891. if (gdn.is_valid()) {
  892. Ref<GDNativeLibrary> lib = gdn->get_library();
  893. if (lib.is_valid()) {
  894. should_reload = lib->is_reloadable();
  895. }
  896. }
  897. if (!should_reload) {
  898. continue;
  899. }
  900. }
  901. Map<String, Ref<GDNative>>::Element *E = library_gdnatives.find(lib_path);
  902. Ref<GDNative> gdn;
  903. if (E) {
  904. gdn = E->get();
  905. }
  906. for (Map<StringName, NativeScriptDesc>::Element *C = classes.front(); C; C = C->next()) {
  907. // free property stuff first
  908. for (OrderedHashMap<StringName, NativeScriptDesc::Property>::Element P = C->get().properties.front(); P; P = P.next()) {
  909. if (P.get().getter.free_func)
  910. P.get().getter.free_func(P.get().getter.method_data);
  911. if (P.get().setter.free_func)
  912. P.get().setter.free_func(P.get().setter.method_data);
  913. }
  914. // free method stuff
  915. for (Map<StringName, NativeScriptDesc::Method>::Element *M = C->get().methods.front(); M; M = M->next()) {
  916. if (M->get().method.free_func)
  917. M->get().method.free_func(M->get().method.method_data);
  918. }
  919. // free constructor/destructor
  920. if (C->get().create_func.free_func)
  921. C->get().create_func.free_func(C->get().create_func.method_data);
  922. if (C->get().destroy_func.free_func)
  923. C->get().destroy_func.free_func(C->get().destroy_func.method_data);
  924. }
  925. erase_and_unload.insert(lib_path, gdn);
  926. }
  927. for (Map<String, Ref<GDNative>>::Element *E = erase_and_unload.front(); E; E = E->next()) {
  928. String lib_path = E->key();
  929. Ref<GDNative> gdn = E->get();
  930. library_classes.erase(lib_path);
  931. if (gdn.is_valid() && gdn->get_library().is_valid()) {
  932. Ref<GDNativeLibrary> lib = gdn->get_library();
  933. void *terminate_fn;
  934. Error err = gdn->get_symbol(lib->get_symbol_prefix() + _terminate_call_name, terminate_fn, true);
  935. if (err == OK) {
  936. void (*terminate)(void *) = (void (*)(void *))terminate_fn;
  937. terminate((void *)&lib_path);
  938. }
  939. }
  940. }
  941. }
  942. NativeScriptLanguage::NativeScriptLanguage() {
  943. NativeScriptLanguage::singleton = this;
  944. #ifndef NO_THREADS
  945. has_objects_to_register = false;
  946. #endif
  947. #ifdef DEBUG_ENABLED
  948. profiling = false;
  949. #endif
  950. _init_call_type = "nativescript_init";
  951. _init_call_name = "nativescript_init";
  952. _terminate_call_name = "nativescript_terminate";
  953. _noarg_call_type = "nativescript_no_arg";
  954. _frame_call_name = "nativescript_frame";
  955. #ifndef NO_THREADS
  956. _thread_enter_call_name = "nativescript_thread_enter";
  957. _thread_exit_call_name = "nativescript_thread_exit";
  958. #endif
  959. }
  960. NativeScriptLanguage::~NativeScriptLanguage() {
  961. for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) {
  962. Ref<GDNative> lib = L->get();
  963. // only shut down valid libs, duh!
  964. if (lib.is_valid()) {
  965. // If it's a singleton-library then the gdnative module
  966. // manages the destruction at engine shutdown, not NativeScript.
  967. if (!lib->get_library()->is_singleton()) {
  968. lib->terminate();
  969. }
  970. }
  971. }
  972. NSL->library_classes.clear();
  973. NSL->library_gdnatives.clear();
  974. NSL->library_script_users.clear();
  975. }
  976. String NativeScriptLanguage::get_name() const {
  977. return "NativeScript";
  978. }
  979. void _add_reload_node() {
  980. #ifdef TOOLS_ENABLED
  981. NativeReloadNode *rn = memnew(NativeReloadNode);
  982. EditorNode::get_singleton()->add_child(rn);
  983. #endif
  984. }
  985. void NativeScriptLanguage::init() {
  986. #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
  987. List<String> args = OS::get_singleton()->get_cmdline_args();
  988. List<String>::Element *E = args.find("--gdnative-generate-json-api");
  989. if (E && E->next()) {
  990. if (generate_c_api(E->next()->get()) != OK) {
  991. ERR_PRINT("Failed to generate C API\n");
  992. }
  993. exit(0);
  994. }
  995. #endif
  996. #ifdef TOOLS_ENABLED
  997. EditorNode::add_init_callback(&_add_reload_node);
  998. #endif
  999. }
  1000. String NativeScriptLanguage::get_type() const {
  1001. return "NativeScript";
  1002. }
  1003. String NativeScriptLanguage::get_extension() const {
  1004. return "gdns";
  1005. }
  1006. Error NativeScriptLanguage::execute_file(const String &p_path) {
  1007. return OK; // Qué?
  1008. }
  1009. void NativeScriptLanguage::finish() {
  1010. _unload_stuff();
  1011. }
  1012. void NativeScriptLanguage::get_reserved_words(List<String> *p_words) const {
  1013. }
  1014. void NativeScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
  1015. }
  1016. void NativeScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
  1017. }
  1018. Ref<Script> NativeScriptLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const {
  1019. NativeScript *s = memnew(NativeScript);
  1020. s->set_class_name(p_class_name);
  1021. return Ref<NativeScript>(s);
  1022. }
  1023. bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, List<ScriptLanguage::Warning> *r_warnings, Set<int> *r_safe_lines) const {
  1024. return true;
  1025. }
  1026. Script *NativeScriptLanguage::create_script() const {
  1027. NativeScript *script = memnew(NativeScript);
  1028. return script;
  1029. }
  1030. bool NativeScriptLanguage::has_named_classes() const {
  1031. return true;
  1032. }
  1033. bool NativeScriptLanguage::supports_builtin_mode() const {
  1034. return true;
  1035. }
  1036. int NativeScriptLanguage::find_function(const String &p_function, const String &p_code) const {
  1037. return -1;
  1038. }
  1039. String NativeScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const {
  1040. return "";
  1041. }
  1042. void NativeScriptLanguage::auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {
  1043. }
  1044. void NativeScriptLanguage::add_global_constant(const StringName &p_variable, const Variant &p_value) {
  1045. }
  1046. // Debugging stuff here. Not used for now.
  1047. String NativeScriptLanguage::debug_get_error() const {
  1048. return "";
  1049. }
  1050. int NativeScriptLanguage::debug_get_stack_level_count() const {
  1051. return -1;
  1052. }
  1053. int NativeScriptLanguage::debug_get_stack_level_line(int p_level) const {
  1054. return -1;
  1055. }
  1056. String NativeScriptLanguage::debug_get_stack_level_function(int p_level) const {
  1057. return "";
  1058. }
  1059. String NativeScriptLanguage::debug_get_stack_level_source(int p_level) const {
  1060. return "";
  1061. }
  1062. void NativeScriptLanguage::debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
  1063. }
  1064. void NativeScriptLanguage::debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
  1065. }
  1066. void NativeScriptLanguage::debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {
  1067. }
  1068. String NativeScriptLanguage::debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) {
  1069. return "";
  1070. }
  1071. // Debugging stuff end.
  1072. void NativeScriptLanguage::reload_all_scripts() {
  1073. }
  1074. void NativeScriptLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
  1075. }
  1076. void NativeScriptLanguage::get_recognized_extensions(List<String> *p_extensions) const {
  1077. p_extensions->push_back("gdns");
  1078. }
  1079. void NativeScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) const {
  1080. }
  1081. void NativeScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_constants) const {
  1082. }
  1083. void NativeScriptLanguage::profiling_start() {
  1084. #ifdef DEBUG_ENABLED
  1085. MutexLock lock(mutex);
  1086. profile_data.clear();
  1087. profiling = true;
  1088. #endif
  1089. }
  1090. void NativeScriptLanguage::profiling_stop() {
  1091. #ifdef DEBUG_ENABLED
  1092. MutexLock lock(mutex);
  1093. profiling = false;
  1094. #endif
  1095. }
  1096. int NativeScriptLanguage::profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) {
  1097. #ifdef DEBUG_ENABLED
  1098. MutexLock lock(mutex);
  1099. int current = 0;
  1100. for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
  1101. if (current >= p_info_max)
  1102. break;
  1103. p_info_arr[current].call_count = d->get().call_count;
  1104. p_info_arr[current].self_time = d->get().self_time;
  1105. p_info_arr[current].total_time = d->get().total_time;
  1106. p_info_arr[current].signature = d->get().signature;
  1107. current++;
  1108. }
  1109. return current;
  1110. #else
  1111. return 0;
  1112. #endif
  1113. }
  1114. int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) {
  1115. #ifdef DEBUG_ENABLED
  1116. MutexLock lock(mutex);
  1117. int current = 0;
  1118. for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
  1119. if (current >= p_info_max)
  1120. break;
  1121. if (d->get().last_frame_call_count) {
  1122. p_info_arr[current].call_count = d->get().last_frame_call_count;
  1123. p_info_arr[current].self_time = d->get().last_frame_self_time;
  1124. p_info_arr[current].total_time = d->get().last_frame_total_time;
  1125. p_info_arr[current].signature = d->get().signature;
  1126. current++;
  1127. }
  1128. }
  1129. return current;
  1130. #else
  1131. return 0;
  1132. #endif
  1133. }
  1134. void NativeScriptLanguage::profiling_add_data(StringName p_signature, uint64_t p_time) {
  1135. #ifdef DEBUG_ENABLED
  1136. MutexLock lock(mutex);
  1137. Map<StringName, ProfileData>::Element *d = profile_data.find(p_signature);
  1138. if (d) {
  1139. d->get().call_count += 1;
  1140. d->get().total_time += p_time;
  1141. d->get().frame_call_count += 1;
  1142. d->get().frame_total_time += p_time;
  1143. } else {
  1144. ProfileData data;
  1145. data.signature = p_signature;
  1146. data.call_count = 1;
  1147. data.self_time = 0;
  1148. data.total_time = p_time;
  1149. data.frame_call_count = 1;
  1150. data.frame_self_time = 0;
  1151. data.frame_total_time = p_time;
  1152. data.last_frame_call_count = 0;
  1153. data.last_frame_self_time = 0;
  1154. data.last_frame_total_time = 0;
  1155. profile_data.insert(p_signature, data);
  1156. }
  1157. #endif
  1158. }
  1159. int NativeScriptLanguage::register_binding_functions(godot_instance_binding_functions p_binding_functions) {
  1160. // find index
  1161. int idx = -1;
  1162. for (int i = 0; i < binding_functions.size(); i++) {
  1163. if (!binding_functions[i].first) {
  1164. // free, we'll take it
  1165. idx = i;
  1166. break;
  1167. }
  1168. }
  1169. if (idx == -1) {
  1170. idx = binding_functions.size();
  1171. binding_functions.resize(idx + 1);
  1172. }
  1173. // set the functions
  1174. binding_functions.write[idx].first = true;
  1175. binding_functions.write[idx].second = p_binding_functions;
  1176. return idx;
  1177. }
  1178. void NativeScriptLanguage::unregister_binding_functions(int p_idx) {
  1179. ERR_FAIL_INDEX(p_idx, binding_functions.size());
  1180. for (Set<Vector<void *> *>::Element *E = binding_instances.front(); E; E = E->next()) {
  1181. Vector<void *> &binding_data = *E->get();
  1182. if (p_idx < binding_data.size() && binding_data[p_idx] && binding_functions[p_idx].second.free_instance_binding_data)
  1183. binding_functions[p_idx].second.free_instance_binding_data(binding_functions[p_idx].second.data, binding_data[p_idx]);
  1184. }
  1185. binding_functions.write[p_idx].first = false;
  1186. if (binding_functions[p_idx].second.free_func)
  1187. binding_functions[p_idx].second.free_func(binding_functions[p_idx].second.data);
  1188. }
  1189. void *NativeScriptLanguage::get_instance_binding_data(int p_idx, Object *p_object) {
  1190. ERR_FAIL_INDEX_V(p_idx, binding_functions.size(), nullptr);
  1191. ERR_FAIL_COND_V_MSG(!binding_functions[p_idx].first, nullptr, "Tried to get binding data for a nativescript binding that does not exist.");
  1192. Vector<void *> *binding_data = (Vector<void *> *)p_object->get_script_instance_binding(lang_idx);
  1193. if (!binding_data)
  1194. return nullptr; // should never happen.
  1195. if (binding_data->size() <= p_idx) {
  1196. // okay, add new elements here.
  1197. int old_size = binding_data->size();
  1198. binding_data->resize(p_idx + 1);
  1199. for (int i = old_size; i <= p_idx; i++) {
  1200. (*binding_data).write[i] = nullptr;
  1201. }
  1202. }
  1203. if (!(*binding_data)[p_idx]) {
  1204. const void *global_type_tag = get_global_type_tag(p_idx, p_object->get_class_name());
  1205. // no binding data yet, soooooo alloc new one \o/
  1206. (*binding_data).write[p_idx] = binding_functions[p_idx].second.alloc_instance_binding_data(binding_functions[p_idx].second.data, global_type_tag, (godot_object *)p_object);
  1207. }
  1208. return (*binding_data)[p_idx];
  1209. }
  1210. void *NativeScriptLanguage::alloc_instance_binding_data(Object *p_object) {
  1211. Vector<void *> *binding_data = new Vector<void *>;
  1212. binding_data->resize(binding_functions.size());
  1213. for (int i = 0; i < binding_functions.size(); i++) {
  1214. (*binding_data).write[i] = nullptr;
  1215. }
  1216. binding_instances.insert(binding_data);
  1217. return (void *)binding_data;
  1218. }
  1219. void NativeScriptLanguage::free_instance_binding_data(void *p_data) {
  1220. if (!p_data)
  1221. return;
  1222. Vector<void *> &binding_data = *(Vector<void *> *)p_data;
  1223. for (int i = 0; i < binding_data.size(); i++) {
  1224. if (!binding_data[i])
  1225. continue;
  1226. if (binding_functions[i].first && binding_functions[i].second.free_instance_binding_data) {
  1227. binding_functions[i].second.free_instance_binding_data(binding_functions[i].second.data, binding_data[i]);
  1228. }
  1229. }
  1230. binding_instances.erase(&binding_data);
  1231. delete &binding_data;
  1232. }
  1233. void NativeScriptLanguage::refcount_incremented_instance_binding(Object *p_object) {
  1234. void *data = p_object->get_script_instance_binding(lang_idx);
  1235. if (!data)
  1236. return;
  1237. Vector<void *> &binding_data = *(Vector<void *> *)data;
  1238. for (int i = 0; i < binding_data.size(); i++) {
  1239. if (!binding_data[i])
  1240. continue;
  1241. if (!binding_functions[i].first)
  1242. continue;
  1243. if (binding_functions[i].second.refcount_incremented_instance_binding) {
  1244. binding_functions[i].second.refcount_incremented_instance_binding(binding_data[i], p_object);
  1245. }
  1246. }
  1247. }
  1248. bool NativeScriptLanguage::refcount_decremented_instance_binding(Object *p_object) {
  1249. void *data = p_object->get_script_instance_binding(lang_idx);
  1250. if (!data)
  1251. return true;
  1252. Vector<void *> &binding_data = *(Vector<void *> *)data;
  1253. bool can_die = true;
  1254. for (int i = 0; i < binding_data.size(); i++) {
  1255. if (!binding_data[i])
  1256. continue;
  1257. if (!binding_functions[i].first)
  1258. continue;
  1259. if (binding_functions[i].second.refcount_decremented_instance_binding) {
  1260. can_die = can_die && binding_functions[i].second.refcount_decremented_instance_binding(binding_data[i], p_object);
  1261. }
  1262. }
  1263. return can_die;
  1264. }
  1265. void NativeScriptLanguage::set_global_type_tag(int p_idx, StringName p_class_name, const void *p_type_tag) {
  1266. if (!global_type_tags.has(p_idx)) {
  1267. global_type_tags.insert(p_idx, HashMap<StringName, const void *>());
  1268. }
  1269. HashMap<StringName, const void *> &tags = global_type_tags[p_idx];
  1270. tags.set(p_class_name, p_type_tag);
  1271. }
  1272. const void *NativeScriptLanguage::get_global_type_tag(int p_idx, StringName p_class_name) const {
  1273. if (!global_type_tags.has(p_idx))
  1274. return nullptr;
  1275. const HashMap<StringName, const void *> &tags = global_type_tags[p_idx];
  1276. if (!tags.has(p_class_name))
  1277. return nullptr;
  1278. const void *tag = tags.get(p_class_name);
  1279. return tag;
  1280. }
  1281. #ifndef NO_THREADS
  1282. void NativeScriptLanguage::defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script) {
  1283. MutexLock lock(mutex);
  1284. libs_to_init.insert(lib);
  1285. scripts_to_register.insert(script);
  1286. has_objects_to_register = true;
  1287. }
  1288. #endif
  1289. void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) {
  1290. MutexLock lock(mutex);
  1291. // See if this library was "registered" already.
  1292. const String &lib_path = lib->get_current_library_path();
  1293. ERR_FAIL_COND_MSG(lib_path.length() == 0, lib->get_name() + " does not have a library for the current platform.");
  1294. Map<String, Ref<GDNative>>::Element *E = library_gdnatives.find(lib_path);
  1295. if (!E) {
  1296. Ref<GDNative> gdn;
  1297. gdn.instance();
  1298. gdn->set_library(lib);
  1299. // TODO check the return value?
  1300. gdn->initialize();
  1301. library_gdnatives.insert(lib_path, gdn);
  1302. library_classes.insert(lib_path, Map<StringName, NativeScriptDesc>());
  1303. if (!library_script_users.has(lib_path))
  1304. library_script_users.insert(lib_path, Set<NativeScript *>());
  1305. void *proc_ptr;
  1306. Error err = gdn->get_symbol(lib->get_symbol_prefix() + _init_call_name, proc_ptr);
  1307. if (err != OK) {
  1308. ERR_PRINT(String("No " + _init_call_name + " in \"" + lib_path + "\" found").utf8().get_data());
  1309. } else {
  1310. ((void (*)(godot_string *))proc_ptr)((godot_string *)&lib_path);
  1311. }
  1312. } else {
  1313. // already initialized. Nice.
  1314. }
  1315. }
  1316. void NativeScriptLanguage::register_script(NativeScript *script) {
  1317. MutexLock lock(mutex);
  1318. library_script_users[script->lib_path].insert(script);
  1319. }
  1320. void NativeScriptLanguage::unregister_script(NativeScript *script) {
  1321. MutexLock lock(mutex);
  1322. Map<String, Set<NativeScript *>>::Element *S = library_script_users.find(script->lib_path);
  1323. if (S) {
  1324. S->get().erase(script);
  1325. if (S->get().size() == 0) {
  1326. library_script_users.erase(S);
  1327. }
  1328. }
  1329. #ifndef NO_THREADS
  1330. scripts_to_register.erase(script);
  1331. #endif
  1332. }
  1333. void NativeScriptLanguage::call_libraries_cb(const StringName &name) {
  1334. // library_gdnatives is modified only from the main thread, so it's safe not to use mutex here
  1335. for (Map<String, Ref<GDNative>>::Element *L = library_gdnatives.front(); L; L = L->next()) {
  1336. if (L->get().is_null()) {
  1337. continue;
  1338. }
  1339. if (L->get()->is_initialized()) {
  1340. void *proc_ptr;
  1341. Error err = L->get()->get_symbol(L->get()->get_library()->get_symbol_prefix() + name, proc_ptr);
  1342. if (!err) {
  1343. ((void (*)())proc_ptr)();
  1344. }
  1345. }
  1346. }
  1347. }
  1348. void NativeScriptLanguage::frame() {
  1349. #ifndef NO_THREADS
  1350. if (has_objects_to_register) {
  1351. MutexLock lock(mutex);
  1352. for (Set<Ref<GDNativeLibrary>>::Element *L = libs_to_init.front(); L; L = L->next()) {
  1353. init_library(L->get());
  1354. }
  1355. libs_to_init.clear();
  1356. for (Set<NativeScript *>::Element *S = scripts_to_register.front(); S; S = S->next()) {
  1357. register_script(S->get());
  1358. }
  1359. scripts_to_register.clear();
  1360. has_objects_to_register = false;
  1361. }
  1362. #endif
  1363. #ifdef DEBUG_ENABLED
  1364. {
  1365. MutexLock lock(mutex);
  1366. for (Map<StringName, ProfileData>::Element *d = profile_data.front(); d; d = d->next()) {
  1367. d->get().last_frame_call_count = d->get().frame_call_count;
  1368. d->get().last_frame_self_time = d->get().frame_self_time;
  1369. d->get().last_frame_total_time = d->get().frame_total_time;
  1370. d->get().frame_call_count = 0;
  1371. d->get().frame_self_time = 0;
  1372. d->get().frame_total_time = 0;
  1373. }
  1374. }
  1375. #endif
  1376. call_libraries_cb(_frame_call_name);
  1377. }
  1378. #ifndef NO_THREADS
  1379. void NativeScriptLanguage::thread_enter() {
  1380. call_libraries_cb(_thread_enter_call_name);
  1381. }
  1382. void NativeScriptLanguage::thread_exit() {
  1383. call_libraries_cb(_thread_exit_call_name);
  1384. }
  1385. #endif // NO_THREADS
  1386. bool NativeScriptLanguage::handles_global_class_type(const String &p_type) const {
  1387. return p_type == "NativeScript";
  1388. }
  1389. String NativeScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const {
  1390. if (!p_path.empty()) {
  1391. Ref<NativeScript> script = ResourceLoader::load(p_path, "NativeScript");
  1392. if (script.is_valid()) {
  1393. if (r_base_type)
  1394. *r_base_type = script->get_instance_base_type();
  1395. if (r_icon_path)
  1396. *r_icon_path = script->get_script_class_icon_path();
  1397. return script->get_script_class_name();
  1398. }
  1399. if (r_base_type)
  1400. *r_base_type = String();
  1401. if (r_icon_path)
  1402. *r_icon_path = String();
  1403. }
  1404. return String();
  1405. }
  1406. void NativeReloadNode::_bind_methods() {
  1407. ClassDB::bind_method(D_METHOD("_notification"), &NativeReloadNode::_notification);
  1408. }
  1409. void NativeReloadNode::_notification(int p_what) {
  1410. #ifdef TOOLS_ENABLED
  1411. switch (p_what) {
  1412. case NOTIFICATION_WM_FOCUS_OUT: {
  1413. if (unloaded)
  1414. break;
  1415. MutexLock lock(NSL->mutex);
  1416. NSL->_unload_stuff(true);
  1417. for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) {
  1418. Ref<GDNative> gdn = L->get();
  1419. if (gdn.is_null()) {
  1420. continue;
  1421. }
  1422. // Don't unload what should not be reloaded!
  1423. if (!gdn->get_library()->is_reloadable()) {
  1424. continue;
  1425. }
  1426. // singleton libraries might have alive pointers living inside the
  1427. // editor. Also reloading a singleton library would mean that
  1428. // the singleton entry will not be called again, as this only
  1429. // happens at engine startup.
  1430. if (gdn->get_library()->is_singleton()) {
  1431. continue;
  1432. }
  1433. gdn->terminate();
  1434. }
  1435. unloaded = true;
  1436. } break;
  1437. case NOTIFICATION_WM_FOCUS_IN: {
  1438. if (!unloaded)
  1439. break;
  1440. MutexLock lock(NSL->mutex);
  1441. Set<StringName> libs_to_remove;
  1442. for (Map<String, Ref<GDNative>>::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) {
  1443. Ref<GDNative> gdn = L->get();
  1444. if (gdn.is_null()) {
  1445. continue;
  1446. }
  1447. if (!gdn->get_library()->is_reloadable()) {
  1448. continue;
  1449. }
  1450. // since singleton libraries are not unloaded there is no point
  1451. // in loading them again.
  1452. if (gdn->get_library()->is_singleton()) {
  1453. continue;
  1454. }
  1455. if (!gdn->initialize()) {
  1456. libs_to_remove.insert(L->key());
  1457. continue;
  1458. }
  1459. NSL->library_classes.insert(L->key(), Map<StringName, NativeScriptDesc>());
  1460. // here the library registers all the classes and stuff.
  1461. void *proc_ptr;
  1462. Error err = gdn->get_symbol(gdn->get_library()->get_symbol_prefix() + "nativescript_init", proc_ptr);
  1463. if (err != OK) {
  1464. ERR_PRINT(String("No godot_nativescript_init in \"" + L->key() + "\" found").utf8().get_data());
  1465. } else {
  1466. ((void (*)(void *))proc_ptr)((void *)&L->key());
  1467. }
  1468. for (Map<String, Set<NativeScript *>>::Element *U = NSL->library_script_users.front(); U; U = U->next()) {
  1469. for (Set<NativeScript *>::Element *S = U->get().front(); S; S = S->next()) {
  1470. NativeScript *script = S->get();
  1471. if (script->placeholders.size() == 0)
  1472. continue;
  1473. for (Set<PlaceHolderScriptInstance *>::Element *P = script->placeholders.front(); P; P = P->next()) {
  1474. script->_update_placeholder(P->get());
  1475. }
  1476. }
  1477. }
  1478. }
  1479. unloaded = false;
  1480. for (Set<StringName>::Element *R = libs_to_remove.front(); R; R = R->next()) {
  1481. NSL->library_gdnatives.erase(R->get());
  1482. }
  1483. } break;
  1484. default: {
  1485. };
  1486. }
  1487. #endif
  1488. }
  1489. RES ResourceFormatLoaderNativeScript::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, bool p_no_cache) {
  1490. return ResourceFormatLoaderText::singleton->load(p_path, p_original_path, r_error);
  1491. }
  1492. void ResourceFormatLoaderNativeScript::get_recognized_extensions(List<String> *p_extensions) const {
  1493. p_extensions->push_back("gdns");
  1494. }
  1495. bool ResourceFormatLoaderNativeScript::handles_type(const String &p_type) const {
  1496. return (p_type == "Script" || p_type == "NativeScript");
  1497. }
  1498. String ResourceFormatLoaderNativeScript::get_resource_type(const String &p_path) const {
  1499. String el = p_path.get_extension().to_lower();
  1500. if (el == "gdns")
  1501. return "NativeScript";
  1502. return "";
  1503. }
  1504. Error ResourceFormatSaverNativeScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
  1505. ResourceFormatSaverText rfst;
  1506. return rfst.save(p_path, p_resource, p_flags);
  1507. }
  1508. bool ResourceFormatSaverNativeScript::recognize(const RES &p_resource) const {
  1509. return Object::cast_to<NativeScript>(*p_resource) != nullptr;
  1510. }
  1511. void ResourceFormatSaverNativeScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
  1512. if (Object::cast_to<NativeScript>(*p_resource)) {
  1513. p_extensions->push_back("gdns");
  1514. }
  1515. }