JSScene.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  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 <Atomic/Resource/ResourceCache.h>
  5. #include <Atomic/Resource/XMLFile.h>
  6. #include <Atomic/IO/File.h>
  7. #include <Atomic/Scene/Node.h>
  8. #include <Atomic/Scene/Scene.h>
  9. #include <Atomic/Graphics/Camera.h>
  10. #ifdef ATOMIC_3D
  11. #include <Atomic/Physics/RigidBody.h>
  12. #endif
  13. #include "JSScene.h"
  14. #include "JSComponent.h"
  15. #include "JSVM.h"
  16. namespace Atomic
  17. {
  18. void jsapi_init_scene_serializable(JSVM* vm);
  19. static int Node_CreateJSComponent(duk_context* ctx)
  20. {
  21. String path = duk_require_string(ctx, 0);
  22. bool hasArgs = false;
  23. int argIdx = -1;
  24. if (duk_get_top(ctx) > 1 && duk_is_object(ctx, 1))
  25. {
  26. hasArgs = true;
  27. argIdx = 1;
  28. }
  29. duk_push_this(ctx);
  30. Node* node = js_to_class_instance<Node>(ctx, -1, 0);
  31. ResourceCache* cache = node->GetContext()->GetSubsystem<ResourceCache>();
  32. JSComponentFile* file = cache->GetResource<JSComponentFile>(path);
  33. if (!file)
  34. {
  35. LOGERRORF("Unable to load component file %s", path.CString());
  36. duk_push_undefined(ctx);
  37. return 1;
  38. }
  39. JSComponent* jsc = file->CreateJSComponent();
  40. node->AddComponent(jsc, jsc->GetID(), LOCAL);
  41. jsc->InitInstance(hasArgs, argIdx);
  42. js_push_class_object_instance(ctx, jsc, "JSComponent");
  43. return 1;
  44. }
  45. static int Node_GetJSComponent(duk_context* ctx)
  46. {
  47. String path = duk_require_string(ctx, 0);
  48. duk_push_this(ctx);
  49. Node* node = js_to_class_instance<Node>(ctx, -1, 0);
  50. PODVector<JSComponent*> components;
  51. node->GetComponents<JSComponent>(components, true);
  52. for (unsigned i = 0; i < components.Size(); i++)
  53. {
  54. JSComponent* component = components[i];
  55. if (component->MatchScriptName(path)) {
  56. js_push_class_object_instance(ctx, component, "Component");
  57. return 1;
  58. }
  59. }
  60. duk_push_null(ctx);
  61. return 1;
  62. }
  63. static int Node_GetChildrenWithComponent(duk_context* ctx)
  64. {
  65. StringHash type = duk_to_string(ctx, 0);
  66. bool recursive = false;
  67. if (duk_get_top(ctx) == 2)
  68. if (duk_get_boolean(ctx, 1))
  69. recursive = true;
  70. duk_push_this(ctx);
  71. Node* node = js_to_class_instance<Node>(ctx, -1, 0);
  72. PODVector<Node*> dest;
  73. node->GetChildrenWithComponent(dest, type, recursive);
  74. duk_push_array(ctx);
  75. for (unsigned i = 0; i < dest.Size(); i++)
  76. {
  77. js_push_class_object_instance(ctx, dest[i], "Node");
  78. duk_put_prop_index(ctx, -2, i);
  79. }
  80. return 1;
  81. }
  82. static int Node_GetChildrenWithName(duk_context* ctx)
  83. {
  84. StringHash nameHash = duk_to_string(ctx, 0);
  85. bool recursive = false;
  86. if (duk_get_top(ctx) == 2)
  87. if (duk_get_boolean(ctx, 1))
  88. recursive = true;
  89. duk_push_this(ctx);
  90. Node* node = js_to_class_instance<Node>(ctx, -1, 0);
  91. PODVector<Node*> dest;
  92. node->GetChildrenWithName(dest, nameHash, recursive);
  93. duk_push_array(ctx);
  94. for (unsigned i = 0; i < dest.Size(); i++)
  95. {
  96. js_push_class_object_instance(ctx, dest[i], "Node");
  97. duk_put_prop_index(ctx, -2, i);
  98. }
  99. return 1;
  100. }
  101. static int Node_GetComponents(duk_context* ctx)
  102. {
  103. bool recursive = false;
  104. StringHash typeHash = Component::GetTypeStatic();
  105. if (duk_get_top(ctx) > 0)
  106. {
  107. if (duk_is_string(ctx, 0) && strlen(duk_get_string(ctx, 0)))
  108. typeHash = duk_get_string(ctx, 0);
  109. }
  110. if (duk_get_top(ctx) > 1)
  111. recursive = duk_require_boolean(ctx, 1) ? true : false;
  112. duk_push_this(ctx);
  113. Node* node = js_to_class_instance<Node>(ctx, -1, 0);
  114. PODVector<Component*> dest;
  115. node->GetComponents(dest, typeHash, recursive);
  116. duk_push_array(ctx);
  117. for (unsigned i = 0; i < dest.Size(); i++)
  118. {
  119. if (js_push_class_object_instance(ctx, dest[i], "Component"))
  120. duk_put_prop_index(ctx, -2, i);
  121. }
  122. return 1;
  123. }
  124. static int Node_GetChildAtIndex(duk_context* ctx)
  125. {
  126. duk_push_this(ctx);
  127. Node* node = js_to_class_instance<Node>(ctx, -1, 0);
  128. unsigned idx = (unsigned) duk_to_number(ctx, 0);
  129. if (node->GetNumChildren() <= idx)
  130. {
  131. duk_push_null(ctx);
  132. return 1;
  133. }
  134. Node* child = node->GetChild(idx);
  135. js_push_class_object_instance(ctx, child, "Node");
  136. return 1;
  137. }
  138. static int Node_SaveXML(duk_context* ctx)
  139. {
  140. File* file = js_to_class_instance<File>(ctx, 0, 0);
  141. duk_push_this(ctx);
  142. Node* node = js_to_class_instance<Node>(ctx, -1, 0);
  143. duk_push_boolean(ctx, node->SaveXML(*file) ? 1 : 0);
  144. return 1;
  145. }
  146. static int Node_CreateChildPrefab(duk_context* ctx)
  147. {
  148. const char* childName = duk_require_string(ctx, 0);
  149. const char* prefabName = duk_require_string(ctx, 1);
  150. duk_push_this(ctx);
  151. Node* parent = js_to_class_instance<Node>(ctx, -1, 0);
  152. Node* prefabNode = parent->CreateChild(childName);
  153. ResourceCache* cache = parent->GetSubsystem<ResourceCache>();
  154. XMLFile* xmlfile = cache->GetResource<XMLFile>(prefabName);
  155. prefabNode->LoadXML(xmlfile->GetRoot());
  156. prefabNode->SetTemporary(true);
  157. prefabNode->SetPosition(Vector3::ZERO);
  158. prefabNode->SetRotation(Quaternion::IDENTITY);
  159. #ifdef ATOMIC_3D
  160. PODVector<RigidBody*> bodies;
  161. prefabNode->GetComponents<RigidBody>(bodies, true);
  162. for (unsigned i = 0; i < bodies.Size(); i++)
  163. {
  164. RigidBody* body = bodies[i];
  165. body->SetTransform(body->GetNode()->GetWorldPosition(), body->GetNode()->GetWorldRotation());
  166. }
  167. #endif
  168. js_push_class_object_instance(ctx, prefabNode, "Node");
  169. return 1;
  170. }
  171. static int Scene_LoadXML(duk_context* ctx)
  172. {
  173. JSVM* vm = JSVM::GetJSVM(ctx);
  174. String filename = duk_to_string(ctx, 0);
  175. ResourceCache* cache = vm->GetSubsystem<ResourceCache>();
  176. SharedPtr<File> file = cache->GetFile(filename);
  177. if (!file->IsOpen())
  178. {
  179. duk_push_false(ctx);
  180. return 1;
  181. }
  182. duk_push_this(ctx);
  183. Scene* scene = js_to_class_instance<Scene>(ctx, -1, 0);
  184. bool success = scene->LoadXML(*file);
  185. if (success)
  186. duk_push_true(ctx);
  187. else
  188. duk_push_false(ctx);
  189. return 1;
  190. }
  191. static int Scene_GetMainCamera(duk_context* ctx)
  192. {
  193. duk_push_this(ctx);
  194. Scene* scene = js_to_class_instance<Scene>(ctx, -1, 0);
  195. PODVector<Node*> cameraNodes;
  196. Camera* camera = 0;
  197. scene->GetChildrenWithComponent(cameraNodes, Camera::GetTypeStatic(), true);
  198. if (cameraNodes.Size())
  199. {
  200. camera = cameraNodes[0]->GetComponent<Camera>();
  201. }
  202. if (!camera)
  203. {
  204. duk_push_null(ctx);
  205. return 1;
  206. }
  207. js_push_class_object_instance(ctx, camera, "Camera");
  208. return 1;
  209. }
  210. void jsapi_init_scene(JSVM* vm)
  211. {
  212. duk_context* ctx = vm->GetJSContext();
  213. jsapi_init_scene_serializable(vm);
  214. js_class_get_prototype(ctx, "Atomic", "Node");
  215. duk_push_c_function(ctx, Node_GetChildrenWithComponent, DUK_VARARGS);
  216. duk_put_prop_string(ctx, -2, "getChildrenWithComponent");
  217. duk_push_c_function(ctx, Node_GetChildrenWithName, DUK_VARARGS);
  218. duk_put_prop_string(ctx, -2, "getChildrenWithName");
  219. duk_push_c_function(ctx, Node_GetComponents, DUK_VARARGS);
  220. duk_put_prop_string(ctx, -2, "getComponents");
  221. duk_push_c_function(ctx, Node_CreateJSComponent, DUK_VARARGS);
  222. duk_put_prop_string(ctx, -2, "createJSComponent");
  223. duk_push_c_function(ctx, Node_GetJSComponent, 1);
  224. duk_put_prop_string(ctx, -2, "getJSComponent");
  225. duk_push_c_function(ctx, Node_GetChildAtIndex, 1);
  226. duk_put_prop_string(ctx, -2, "getChildAtIndex");
  227. duk_push_c_function(ctx, Node_SaveXML, 1);
  228. duk_put_prop_string(ctx, -2, "saveXML");
  229. duk_push_c_function(ctx, Node_CreateChildPrefab, 2);
  230. duk_put_prop_string(ctx, -2, "createChildPrefab");
  231. duk_pop(ctx);
  232. js_class_get_prototype(ctx, "Atomic", "Scene");
  233. duk_push_c_function(ctx, Scene_LoadXML, 1);
  234. duk_put_prop_string(ctx, -2, "loadXML");
  235. duk_push_c_function(ctx, Scene_GetMainCamera, 0);
  236. duk_put_prop_string(ctx, -2, "getMainCamera");
  237. duk_pop(ctx);
  238. }
  239. }