JSAPI.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  2. // Please see LICENSE.md in repository root for license information
  3. // https://github.com/AtomicGameEngine/AtomicGameEngine
  4. #include "JSAPI.h"
  5. #include "JSVM.h"
  6. /*
  7. // script can new an instance
  8. // script can get an engine ptr back (which may be to a previously script new'd instance)
  9. // script should always get the same JS Object back which means a lookup table (strong ref)
  10. // we can look directly at the tval (exposed from duktape internals) to see if the reference count is 1
  11. // script owned
  12. // new'd script side, script holds a RefCounted reference
  13. // native owned
  14. // native script classes not derived from refcounted
  15. // if not inherited from RefCounted can script access?
  16. // if so, script side will always need to delete?
  17. */
  18. namespace Atomic
  19. {
  20. void js_class_get_prototype(duk_context* ctx, const char* classname)
  21. {
  22. duk_get_global_string(ctx, "Atomic");
  23. duk_get_prop_string(ctx, -1, classname);
  24. duk_get_prop_string(ctx, -1, "prototype");
  25. duk_remove(ctx, -2); // remove class object
  26. duk_remove(ctx, -2); // remove Atomic object
  27. }
  28. void js_constructor_basecall(duk_context* ctx, const char* baseclass)
  29. {
  30. int top = duk_get_top(ctx);
  31. duk_get_global_string(ctx, "Atomic");
  32. duk_get_prop_string(ctx, -1, baseclass);
  33. assert(duk_is_function(ctx, -1));
  34. duk_push_this(ctx);
  35. duk_call_method(ctx, 0);
  36. duk_pop_n(ctx, 2);
  37. assert (top == duk_get_top(ctx));
  38. }
  39. void js_class_declare(JSVM* vm, const char* classname, duk_c_function constructor)
  40. {
  41. duk_context* ctx = vm->GetJSContext();
  42. duk_get_global_string(ctx, "Atomic");
  43. duk_push_c_function(ctx, constructor, DUK_VARARGS);
  44. duk_put_prop_string(ctx, -2, classname);
  45. duk_pop(ctx);
  46. }
  47. void js_class_push_propertyobject(JSVM* vm, const char* classname)
  48. {
  49. duk_context* ctx = vm->GetJSContext();
  50. String pname;
  51. pname.AppendWithFormat("__%s__Properties", classname);
  52. duk_get_global_string(ctx, "Atomic");
  53. duk_push_object(ctx);
  54. duk_dup(ctx, -1);
  55. duk_put_prop_string(ctx, -3, pname.CString());
  56. duk_remove(ctx, -2); // remove Atomic object
  57. }
  58. void js_setup_prototype(JSVM* vm, const char* classname, const char* basename, bool hasProperties)
  59. {
  60. duk_context* ctx = vm->GetJSContext();
  61. String pname;
  62. pname.AppendWithFormat("__%s__Properties", classname);
  63. int top = duk_get_top(ctx);
  64. duk_get_global_string(ctx, "Atomic");
  65. duk_get_prop_string(ctx, -1, classname);
  66. assert(duk_is_c_function(ctx, -1));
  67. if (!strlen(basename))
  68. {
  69. // prototype
  70. duk_push_object(ctx);
  71. duk_dup(ctx, -2); // AObject constructor function
  72. duk_put_prop_string(ctx, -2, "constructor");
  73. duk_put_prop_string(ctx, -2, "prototype");
  74. duk_pop_n(ctx, 2);
  75. assert (top == duk_get_top(ctx));
  76. return;
  77. }
  78. // prototype
  79. duk_get_global_string(ctx, "Object");
  80. duk_get_prop_string(ctx, -1, "create");
  81. assert(duk_is_function(ctx, -1));
  82. duk_remove(ctx, -2); // remove Object
  83. duk_get_global_string(ctx, "Atomic");
  84. duk_get_prop_string(ctx, -1, basename);
  85. assert(duk_is_function(ctx, -1));
  86. duk_get_prop_string(ctx, -1, "prototype");
  87. assert(duk_is_object(ctx, -1));
  88. duk_remove(ctx, -2); // remove basename
  89. int numargs = 1;
  90. if (hasProperties)
  91. {
  92. duk_get_prop_string(ctx, -2, pname.CString());
  93. assert(duk_is_object(ctx, -1));
  94. duk_remove(ctx, -3); // remove Atomic
  95. numargs++;
  96. }
  97. else
  98. duk_remove(ctx, -2); // remove Atomic
  99. duk_call(ctx, numargs);
  100. assert(duk_is_object(ctx, -1));
  101. duk_dup(ctx, -2);
  102. duk_put_prop_string(ctx, -2, "constructor");
  103. //duk_dup(ctx, -1);
  104. duk_put_prop_string(ctx, -2, "prototype");
  105. // pop the classname object
  106. duk_pop(ctx);
  107. // pop the Atomic Object
  108. duk_pop(ctx);
  109. assert (top == duk_get_top(ctx));
  110. }
  111. void js_push_variant(duk_context *ctx, const Variant& v)
  112. {
  113. VariantType type = v.GetType();
  114. RefCounted* ref;
  115. Object* object;
  116. Vector2& vector2 = (Vector2&) Vector2::ZERO;
  117. Vector3& vector3 = (Vector3&) Vector3::ZERO;
  118. switch (type)
  119. {
  120. case VAR_PTR:
  121. ref = v.GetPtr();
  122. if (!ref || !ref->IsObject())
  123. {
  124. duk_push_null(ctx);
  125. break;
  126. }
  127. object = (Object*) ref;
  128. // check that class is supported
  129. duk_get_global_string(ctx, "Atomic");
  130. // will not handle renamed classes!
  131. duk_get_prop_string(ctx, -1, object->GetTypeName().CString());
  132. if (!duk_is_function(ctx, -1))
  133. object = NULL;
  134. duk_pop_n(ctx, 2);
  135. if (object)
  136. js_push_class_object_instance(ctx, object);
  137. else
  138. duk_push_undefined(ctx);
  139. break;
  140. case VAR_BOOL:
  141. duk_push_boolean(ctx, v.GetBool() ? 1 : 0);
  142. break;
  143. case VAR_INT:
  144. duk_push_number(ctx, v.GetInt());
  145. break;
  146. case VAR_FLOAT:
  147. duk_push_number(ctx, v.GetFloat());
  148. break;
  149. case VAR_STRING:
  150. duk_push_string(ctx, v.GetString().CString());
  151. break;
  152. case VAR_VECTOR2:
  153. vector2 = v.GetVector2();
  154. duk_push_array(ctx);
  155. duk_push_number(ctx, vector2.x_);
  156. duk_put_prop_index(ctx, -1, 0);
  157. duk_push_number(ctx, vector2.y_);
  158. duk_put_prop_index(ctx, -1, 1);
  159. break;
  160. case VAR_VECTOR3:
  161. vector3 = v.GetVector3();
  162. duk_push_array(ctx);
  163. duk_push_number(ctx, vector3.x_);
  164. duk_put_prop_index(ctx, -1, 0);
  165. duk_push_number(ctx, vector3.y_);
  166. duk_put_prop_index(ctx, -1, 1);
  167. duk_push_number(ctx, vector3.z_);
  168. duk_put_prop_index(ctx, -1, 1);
  169. break;
  170. default:
  171. duk_push_undefined(ctx);
  172. break;
  173. }
  174. }
  175. }