JSCore.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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/Core/ProcessUtils.h>
  5. #include "JSCore.h"
  6. #include "JSEventHelper.h"
  7. #include "JSVM.h"
  8. namespace Atomic
  9. {
  10. static int Object_SubscribeToEvent(duk_context* ctx)
  11. {
  12. int top = duk_get_top(ctx);
  13. Object* sender = NULL;
  14. StringHash eventType = StringHash::ZERO;
  15. if ( top == 2 ) // General notification: subscribeToEvent("ScreenMode", function() {});
  16. {
  17. if (duk_is_string(ctx, 0) && duk_is_function(ctx, 1))
  18. {
  19. eventType = duk_to_string(ctx, 0);
  20. }
  21. }
  22. else if (top == 3) // Listen to specific object sender subscribeToEvent(graphics, "ScreenMode", function() {});
  23. {
  24. if (duk_is_object(ctx, 0) && duk_is_string(ctx, 1) && duk_is_function(ctx, 2))
  25. {
  26. sender = js_to_class_instance<Object>(ctx, 0, 0);
  27. eventType = duk_to_string(ctx, 1);
  28. }
  29. }
  30. if ( eventType == StringHash::ZERO)
  31. {
  32. duk_push_string(ctx, "Object.subscribeToEvent() - Bad Arguments");
  33. duk_throw(ctx);
  34. }
  35. duk_push_this(ctx);
  36. // event receiver
  37. Object* object = js_to_class_instance<Object>(ctx, -1, 0);
  38. duk_get_prop_string(ctx, -1, "__eventHelper");
  39. // need to setup the handler
  40. if (duk_is_null_or_undefined(ctx, -1))
  41. {
  42. duk_pop(ctx); // pop null or undefined
  43. // construct a new event helper
  44. js_push_class_object_instance(ctx, new JSEventHelper(object->GetContext()));
  45. duk_push_object(ctx);
  46. duk_put_prop_string(ctx, -2, "__eventHelperFunctions");
  47. // dup so when we set the helper is left on stack
  48. duk_dup_top(ctx);
  49. duk_put_prop_string(ctx, -3, "__eventHelper");
  50. }
  51. JSEventHelper* helper = js_to_class_instance<JSEventHelper>(ctx, -1, 0);
  52. duk_get_prop_string(ctx, -1, "__eventHelperFunctions");
  53. assert(duk_is_object(ctx, -1));
  54. assert(duk_is_function(ctx, sender ? 2 : 1));
  55. duk_dup(ctx, sender ? 2 : 1);
  56. duk_put_prop_string(ctx, -2, eventType.ToString().CString());
  57. duk_pop(ctx);
  58. if (sender)
  59. helper->AddEventHandler(sender, eventType);
  60. else
  61. helper->AddEventHandler(eventType);
  62. return 0;
  63. }
  64. // so we don't keep allocating these
  65. static VariantMap sendEventVMap;
  66. static int Object_SendEvent(duk_context* ctx)
  67. {
  68. int top = duk_get_top(ctx);
  69. duk_push_this(ctx);
  70. // event sender
  71. Object* sender = js_to_class_instance<Object>(ctx, -1, 0);
  72. if (top == 1)
  73. {
  74. sender->SendEvent(duk_to_string(ctx, 0));
  75. }
  76. else if (top == 2)
  77. {
  78. if (duk_is_object(ctx, 1)) {
  79. js_object_to_variantmap(ctx, 1, sendEventVMap);
  80. sender->SendEvent(duk_to_string(ctx, 0), sendEventVMap);
  81. }
  82. }
  83. return 0;
  84. }
  85. static int Atomic_GetArguments(duk_context* ctx)
  86. {
  87. duk_push_array(ctx);
  88. for (unsigned i = 0; i < GetArguments().Size(); i++)
  89. {
  90. duk_push_string(ctx, GetArguments()[i].CString());
  91. duk_put_prop_index(ctx, -2, i);
  92. }
  93. return 1;
  94. }
  95. void jsapi_init_core(JSVM* vm)
  96. {
  97. duk_context* ctx = vm->GetJSContext();
  98. duk_get_global_string(ctx, "Atomic");
  99. duk_push_c_function(ctx, Atomic_GetArguments, 0);
  100. duk_put_prop_string(ctx, -2, "getArguments");
  101. duk_pop(ctx); // pop Atomic object
  102. js_class_get_prototype(ctx, "Atomic", "AObject");
  103. duk_push_c_function(ctx, Object_SubscribeToEvent, DUK_VARARGS);
  104. duk_put_prop_string(ctx, -2, "subscribeToEvent");
  105. duk_push_c_function(ctx, Object_SendEvent, DUK_VARARGS);
  106. duk_put_prop_string(ctx, -2, "sendEvent");
  107. duk_pop(ctx); // pop AObject prototype
  108. }
  109. }