Leviathan  0.8.0.0
Leviathan game engine
CommonEngineBind.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "BindDefinitions.h"
3 
4 #include "Addons/GameModule.h"
6 #include "Entities/Components.h"
7 #include "Entities/GameWorld.h"
9 #include "Events/DelegateSlot.h"
10 #include "Events/Event.h"
11 #include "Events/EventHandler.h"
12 #include "FileSystem.h"
14 #include "Rendering/Graphics.h"
18 #include "Script/ScriptExecutor.h"
19 #include "Sound/SoundDevice.h"
21 #include "Utility/Random.h"
22 #include "Window.h"
23 
24 #include "Engine.h"
25 
26 #include "add_on/autowrapper/aswrappedcall.h"
27 
28 
29 using namespace Leviathan;
30 // ------------------------------------ //
31 
32 // Proxies etc.
33 // ------------------------------------ //
34 
35 // This is an assert that prints the callstack for ease of use (and
36 // should probably also print local variables) (actually doesn't print
37 // anything as the callstack printing code is in exception handling so
38 // we just raise one)
39 void AngelScriptAssertWrapper(asIScriptGeneric* gen)
40 {
41  bool check = gen->GetArgByte(0);
42 
43  if(check)
44  return;
45 
46  // Assertion failed //
47  void* messagePtr = nullptr;
48 
49  if(gen->GetArgCount() >= 1)
50  messagePtr = gen->GetArgObject(1);
51 
52  std::string message;
53 
54  if(!messagePtr) {
55 
56  message = "No message specified in assert() call";
57 
58  } else {
59 
60  // Type check for safety //
61  LEVIATHAN_ASSERT(gen->GetEngine()->GetTypeIdByDecl("string") == gen->GetArgTypeId(1),
62  "AngelScriptAssertWrapper got invalid type of message object in generic call");
63 
64  message = *static_cast<std::string*>(messagePtr);
65  }
66 
67  LOG_WRITE("[SCRIPT] [ASSERT] FAILED. Message: " + message);
68  // Callstack is printed by the executor of this script when they get our exception
69  // LOG_WRITE("Callstack:");
70 
71  asIScriptContext* ctx = asGetActiveContext();
72 
73  if(!ctx) {
74 
75  LOG_ERROR("Assertion couldn't retrieve active context");
76 
77  // Close game
79  return;
80  }
81 
82  // TODO: allow making script assertions fatal
83  ctx->SetException(("Assertion failed: " + message).c_str());
84 }
85 
88 {
89  asIScriptContext* ctx = asGetActiveContext();
90 
91  if(!ctx) {
92 
93  LOG_ERROR("PrintASCallStack couldn't retrieve active context");
94  return;
95  }
96 
98 }
99 
101 {
102  return !Engine::Get()->GetNoGui();
103 }
104 
105 // Event
106 GenericEvent* WrapperGenericEventFactory(const std::string& name)
107 {
108  return new GenericEvent(name, NamedVars());
109 }
110 
112 {
113  try {
114  return new Event(type, nullptr);
115 
116  } catch(const Exception& e) {
117 
118  Logger::Get()->Error("Failed to construct Event for script, exception: ");
119  e.PrintToLog();
120 
121  return nullptr;
122  }
123 }
124 
126  const std::string& blockname, const std::string& valuestr)
127 {
128  return new ScriptSafeVariableBlock(new StringBlock(valuestr), blockname);
129 }
130 
131 template<typename TType>
133  const std::string& blockname, TType value)
134 {
135  return new ScriptSafeVariableBlock(new DataBlock<TType>(value), blockname);
136 }
137 
138 // Sound
140  SoundDevice* self, const std::string& filename, bool looping)
141 {
142  auto source = self->Play2DSound(filename, looping);
143 
144  if(source)
145  source->AddRef();
146 
147  return source.get();
148 }
149 
150 // ------------------------------------ //
151 static std::string GetLeviathanVersionProxy()
152 {
153  return Leviathan::VERSIONS;
154 }
155 
156 static void LOG_WRITEProxy(const std::string& str)
157 {
158  LOG_WRITE(str);
159 }
160 
161 static void LOG_INFOProxy(const std::string& str)
162 {
163  LOG_INFO(str);
164 }
165 
166 static void LOG_WARNINGProxy(const std::string& str)
167 {
168  LOG_WARNING(str);
169 }
170 
171 static void LOG_ERRORProxy(const std::string& str)
172 {
173  LOG_ERROR(str);
174 }
175 
176 static void DelegateRegisterProxy(Delegate* obj, asIScriptFunction* callback)
177 {
178  if(!callback)
179  return;
180 
181  obj->Register(
182  Script::ScriptDelegateSlot::MakeShared<Script::ScriptDelegateSlot>(callback));
183 }
184 
186 {
187 
188  return new NamedVars();
189 }
190 
191 static void InvokeProxy(Engine* obj, asIScriptFunction* callback)
192 {
193  obj->Invoke([=]() {
194  try {
195  ScriptRunningSetup ssetup;
196  auto result = ScriptExecutor::Get()->RunScript<void>(callback, nullptr, ssetup);
197 
198  if(result.Result != SCRIPT_RUN_RESULT::Success)
199  LOG_WARNING("InvokeProxy: failed to run script callback");
200 
201  } catch(...) {
202 
203  LOG_ERROR("Invoke proxy passing exception up the call chain");
204  callback->Release();
205  throw;
206  }
207  callback->Release();
208  });
209 }
210 
211 
212 static void QueueTaskDelayed(
213  ThreadingManager* self, asIScriptFunction* callback, int milliseconds)
214 {
215  // This is wrapped to ensure that if the task is never run but discarded that the resource
216  // is cleanly released
217  // TODO: as is said in BindThreadingManager exposing custom task types to script would be
218  // better
219  auto wrapped = std::shared_ptr<asIScriptFunction>(
220  callback, [](asIScriptFunction* obj) { obj->Release(); });
221 
222  self->QueueTask(std::make_shared<DelayedTask>(
223  [wrapped]() {
224  try {
225  ScriptRunningSetup ssetup;
226  auto result =
227  ScriptExecutor::Get()->RunScript<void>(wrapped.get(), nullptr, ssetup);
228 
229  if(result.Result != SCRIPT_RUN_RESULT::Success)
230  LOG_WARNING("Script queued task: failed to run script callback");
231 
232  } catch(...) {
233 
234  LOG_ERROR("Queued task proxy passing exception up the call chain");
235  throw;
236  }
237  },
238  MillisecondDuration(milliseconds)));
239 }
240 
241 // ------------------------------------ //
242 static float PIProxy = PI;
243 
244 static float EPSILONProxy = EPSILON;
245 
246 // static int TICKSPEEDProxy = TICKSPEED;
247 
250 
251 
252 // ------------------------------------ //
253 // Start of the actual bind
254 namespace Leviathan {
255 
256 bool BindDataBlock(asIScriptEngine* engine);
257 
259 bool BindNamedVars(asIScriptEngine* engine)
260 {
262 
263  if(!BindDataBlock(engine))
264  return false;
265 
266  if(engine->RegisterObjectBehaviour("NamedVars", asBEHAVE_FACTORY, "NamedVars@ f()",
267  asFUNCTION(NamedVarsFactory), asCALL_CDECL) < 0) {
269  }
270 
271  if(engine->RegisterObjectMethod("NamedVars",
272  "ScriptSafeVariableBlock@ GetSingleValueByName(const string &in name)",
273  asMETHOD(NamedVars, GetScriptCompatibleValue), asCALL_THISCALL) < 0) {
275  }
276 
277  if(engine->RegisterObjectMethod("NamedVars",
278  "bool AddValue(ScriptSafeVariableBlock@ value)",
279  asMETHOD(NamedVars, AddScriptCompatibleValue), asCALL_THISCALL) < 0) {
281  }
282 
283  if(engine->RegisterObjectMethod("NamedVars",
284  "string Serialize(const string &in lineprefix = \"\") const",
285  asMETHOD(NamedVars, Serialize), asCALL_THISCALL) < 0) {
287  }
288 
289  return true;
290 }
291 // ------------------------------------ //
292 // Called by BindNamedVars
293 bool BindDataBlock(asIScriptEngine* engine)
294 {
295  ANGELSCRIPT_REGISTER_REF_TYPE("ScriptSafeVariableBlock", ScriptSafeVariableBlock);
296 
297  // Some factories //
298  if(engine->RegisterObjectBehaviour("ScriptSafeVariableBlock", asBEHAVE_FACTORY,
299  "ScriptSafeVariableBlock@ f(const string &in blockname, const string &in value)",
300  asFUNCTION(ScriptSafeVariableBlockFactoryString), asCALL_CDECL) < 0) {
302  }
303 
304  if(engine->RegisterObjectBehaviour("ScriptSafeVariableBlock", asBEHAVE_FACTORY,
305  "ScriptSafeVariableBlock@ f(const string &in blockname, float value)",
306  asFUNCTION(ScriptSafeVariableBlockFactoryGeneric<float>), asCALL_CDECL) < 0) {
308  }
309 
310  if(engine->RegisterObjectBehaviour("ScriptSafeVariableBlock", asBEHAVE_FACTORY,
311  "ScriptSafeVariableBlock@ f(const string &in blockname, int value)",
312  asFUNCTION(ScriptSafeVariableBlockFactoryGeneric<int>), asCALL_CDECL) < 0) {
314  }
315 
316  if(engine->RegisterObjectBehaviour("ScriptSafeVariableBlock", asBEHAVE_FACTORY,
317  "ScriptSafeVariableBlock@ f(const string &in blockname, double value)",
318  asFUNCTION(ScriptSafeVariableBlockFactoryGeneric<double>), asCALL_CDECL) < 0) {
320  }
321 
322  if(engine->RegisterObjectBehaviour("ScriptSafeVariableBlock", asBEHAVE_FACTORY,
323  "ScriptSafeVariableBlock@ f(const string &in blockname, int8 value)",
324  asFUNCTION(ScriptSafeVariableBlockFactoryGeneric<char>), asCALL_CDECL) < 0) {
326  }
327 
328  if(engine->RegisterObjectBehaviour("ScriptSafeVariableBlock", asBEHAVE_FACTORY,
329  "ScriptSafeVariableBlock@ f(const string &in blockname, bool value)",
330  asFUNCTION(ScriptSafeVariableBlockFactoryGeneric<bool>), asCALL_CDECL) < 0) {
332  }
333 
334  // Implicit casts for normal types //
335  if(engine->RegisterObjectMethod("ScriptSafeVariableBlock", "string opImplConv() const",
336  WRAP_MFN(ScriptSafeVariableBlock, ConvertAndReturnVariable<std::string>),
337  asCALL_GENERIC) < 0) {
339  }
340 
341  if(engine->RegisterObjectMethod("ScriptSafeVariableBlock", "int opImplConv() const",
342  WRAP_MFN(ScriptSafeVariableBlock, ConvertAndReturnVariable<int>),
343  asCALL_GENERIC) < 0) {
345  }
346 
347  if(engine->RegisterObjectMethod("ScriptSafeVariableBlock", "int8 opImplConv() const",
348  WRAP_MFN(ScriptSafeVariableBlock, ConvertAndReturnVariable<char>),
349  asCALL_GENERIC) < 0) {
351  }
352 
353  if(engine->RegisterObjectMethod("ScriptSafeVariableBlock", "float opImplConv() const",
354  WRAP_MFN(ScriptSafeVariableBlock, ConvertAndReturnVariable<float>),
355  asCALL_GENERIC) < 0) {
357  }
358 
359  if(engine->RegisterObjectMethod("ScriptSafeVariableBlock", "double opImplConv() const",
360  WRAP_MFN(ScriptSafeVariableBlock, ConvertAndReturnVariable<double>),
361  asCALL_GENERIC) < 0) {
363  }
364 
365  if(engine->RegisterObjectMethod("ScriptSafeVariableBlock", "bool opImplConv() const",
366  WRAP_MFN(ScriptSafeVariableBlock, ConvertAndReturnVariable<bool>),
367  asCALL_GENERIC) < 0) {
369  }
370 
371  // type check //
372  if(engine->RegisterObjectMethod("ScriptSafeVariableBlock", "bool IsValidType()",
373  asMETHOD(ScriptSafeVariableBlock, IsValidType), asCALL_THISCALL) < 0) {
375  }
376 
377 
378  return true;
379 }
380 // ------------------------------------ //
381 bool BindEvents(asIScriptEngine* engine)
382 {
383  // Bind event type enum //
384  if(engine->RegisterEnum("EVENT_TYPE") < 0) {
386  }
387 
392 
393  // bind event //
395 
396  if(engine->RegisterObjectBehaviour("Event", asBEHAVE_FACTORY, "Event@ f(EVENT_TYPE type)",
397  asFUNCTION(WrapperEventFactory), asCALL_CDECL) < 0) {
399  }
400 
401  // bind generic event //
403 
404  // Factory //
405  if(engine->RegisterObjectBehaviour("GenericEvent", asBEHAVE_FACTORY,
406  "GenericEvent@ f(const string &in typename)",
407  asFUNCTION(WrapperGenericEventFactory), asCALL_CDECL) < 0) {
409  }
410 
411  // Data get function //
412  if(engine->RegisterObjectMethod("GenericEvent", "NamedVars@ GetNamedVars()",
413  asMETHOD(GenericEvent, GetNamedVarsRefCounted), asCALL_THISCALL) < 0) {
415  }
416 
417  if(engine->RegisterObjectMethod("GenericEvent", "string GetType() const",
418  asMETHOD(GenericEvent, GetType), asCALL_THISCALL) < 0) {
420  }
421 
422  // Event handler which cannot be instantiated or copied around //
423  if(engine->RegisterObjectType("EventHandler", 0, asOBJ_REF | asOBJ_NOHANDLE) < 0) {
425  }
426 
427  // Script event firing //
428  if(engine->RegisterObjectMethod("EventHandler", "void CallEvent(GenericEvent@ event)",
429  asMETHODPR(EventHandler, CallEvent, (GenericEvent*), void), asCALL_THISCALL) < 0) {
431  }
432 
433  // Event listener //
435 
436  if(engine->RegisterFuncdef("int OnEventCallback(Event@ event)") < 0) {
438  }
439 
440  if(engine->RegisterFuncdef("int OnGenericEventCallback(GenericEvent@ event)") < 0) {
442  }
443 
444  if(engine->RegisterObjectBehaviour("EventListener", asBEHAVE_FACTORY,
445  "EventListener@ f(OnEventCallback@ onevent, OnGenericEventCallback@ ongeneric)",
446  asFUNCTION(Script::EventListenerFactory), asCALL_CDECL) < 0) {
448  }
449 
450  if(engine->RegisterObjectMethod("EventListener", "bool RegisterForEvent(EVENT_TYPE type)",
451  asMETHOD(Script::EventListener, RegisterForEventType), asCALL_THISCALL) < 0) {
453  }
454 
455  if(engine->RegisterObjectMethod("EventListener",
456  "bool RegisterForEvent(const string &in name)",
457  asMETHOD(Script::EventListener, RegisterForEventGeneric), asCALL_THISCALL) < 0) {
459  }
460 
461 
462  return true;
463 }
464 // ------------------------------------ //
465 bool BindRandom(asIScriptEngine* engine)
466 {
467 
468  if(engine->RegisterObjectType("Random", 0, asOBJ_REF | asOBJ_NOCOUNT) < 0) {
470  }
471 
472  // TODO: constructor and reference counting for proper use from scripts
473 
474  if(engine->RegisterObjectMethod("Random", "int GetNumber(int min, int max)",
475  asMETHODPR(Random, GetNumber, (int, int), int), asCALL_THISCALL) < 0) {
477  }
478 
479  if(engine->RegisterObjectMethod("Random", "float GetNumber(float min, float max)",
480  asMETHODPR(Random, GetNumber, (float, float), float), asCALL_THISCALL) < 0) {
482  }
483 
484  if(engine->RegisterObjectMethod("Random", "float GetFloat(float min, float max)",
485  asMETHOD(Random, GetFloat), asCALL_THISCALL) < 0) {
487  }
488 
489  return true;
490 }
491 // ------------------------------------ //
492 bool BindThreadingManager(asIScriptEngine* engine)
493 {
494  if(engine->RegisterObjectType("ThreadingManager", 0, asOBJ_REF | asOBJ_NOCOUNT) < 0) {
496  }
497 
498  if(engine->RegisterFuncdef("void BackgroundThreadTask()") < 0) {
500  }
501 
502  // TODO: allow constructing task wrappers
503  if(engine->RegisterObjectMethod("ThreadingManager",
504  "void QueueTaskDelayed(BackgroundThreadTask@ callback, int milliseconds)",
505  asFUNCTION(QueueTaskDelayed), asCALL_CDECL_OBJFIRST) < 0) {
507  }
508 
509  return true;
510 }
511 // ------------------------------------ //
512 bool BindWindow(asIScriptEngine* engine)
513 {
514  if(engine->RegisterObjectType("Window", 0, asOBJ_REF | asOBJ_NOCOUNT) < 0) {
516  }
517 
518  if(engine->RegisterObjectMethod("Window", "void SaveScreenShot(const string &in filename)",
519  asMETHOD(Window, SaveScreenShot), asCALL_THISCALL) < 0) {
521  }
522 
523  if(engine->RegisterObjectMethod("Window", "float GetAspectRatio() const",
524  asMETHOD(Window, SaveScreenShot), asCALL_THISCALL) < 0) {
526  }
527 
528  if(engine->RegisterObjectMethod("Window",
529  "void GetSize(int32 &out width, int32 &out height) const",
530  asMETHOD(Window, GetSize), asCALL_THISCALL) < 0) {
532  }
533 
534  if(engine->RegisterObjectMethod("Window",
535  "void GetPosition(int32 &out x, int32 &out y) const", asMETHOD(Window, GetPosition),
536  asCALL_THISCALL) < 0) {
538  }
539 
540  if(engine->RegisterObjectMethod("Window",
541  "void GetRelativeMouse(int32 &out x, int32 &out y) const",
542  asMETHOD(Window, GetRelativeMouse), asCALL_THISCALL) < 0) {
544  }
545 
546  if(engine->RegisterObjectMethod("Window",
547  "void GetUnclampedRelativeMouse(int32 &out x, int32 &out y) const",
548  asMETHOD(Window, GetUnclampedRelativeMouse), asCALL_THISCALL) < 0) {
550  }
551 
552  if(engine->RegisterObjectMethod("Window",
553  "void GetNormalizedRelativeMouse(float &out x, float &out y) const",
554  asMETHOD(Window, GetNormalizedRelativeMouse), asCALL_THISCALL) < 0) {
556  }
557 
558  if(engine->RegisterObjectMethod("Window", "bool IsMouseOutsideWindowClientArea() const",
559  asMETHOD(Window, IsMouseOutsideWindowClientArea), asCALL_THISCALL) < 0) {
561  }
562 
563  if(engine->RegisterObjectMethod("Window", "bool IsWindowFocused() const",
564  asMETHOD(Window, IsWindowFocused), asCALL_THISCALL) < 0) {
566  }
567 
568  if(engine->RegisterObjectMethod("Window", "int GetWindowNumber() const",
569  asMETHOD(Window, GetWindowNumber), asCALL_THISCALL) < 0) {
571  }
572 
573 
574  if(engine->SetDefaultNamespace("Window") < 0) {
576  }
577 
578  if(engine->RegisterGlobalFunction("int GetGlobalWindowCount()",
579  asFUNCTION(Window::GetGlobalWindowCount), asCALL_CDECL) < 0) {
581  }
582 
583  if(engine->SetDefaultNamespace("") < 0) {
585  }
586 
587  return true;
588 }
589 
590 bool BindGraphics(asIScriptEngine* engine)
591 {
592  if(engine->RegisterObjectType("Graphics", 0, asOBJ_REF | asOBJ_NOCOUNT) < 0) {
594  }
595 
596  // Use the shader constructor taking a string instead
597  // if(engine->RegisterObjectMethod("Graphics",
598  // "bs::HShader LoadShaderByName(const string &in name)",
599  // asMETHOD(Graphics, LoadShaderByName), asCALL_THISCALL) < 0) {
600  // ANGELSCRIPT_REGISTERFAIL;
601  // }
602 
603  return true;
604 }
605 // ------------------------------------ //
606 bool BindEngine(asIScriptEngine* engine)
607 {
608  if(engine->RegisterObjectType("Engine", 0, asOBJ_REF | asOBJ_NOHANDLE) < 0) {
610  }
611 
612  // Global get function //
613  if(engine->RegisterGlobalFunction(
614  "Engine& GetEngine()", asFUNCTION(Engine::Get), asCALL_CDECL) < 0) {
616  }
617 
618  // Engine owned singletons //
619  if(!BindRandom(engine))
620  return false;
621 
622  if(engine->RegisterObjectMethod("Engine", "Random& GetRandom()",
623  asMETHOD(Engine, GetRandom), asCALL_THISCALL) < 0) {
625  }
626 
627  if(engine->RegisterObjectMethod("Engine", "EventHandler& GetEventHandler()",
628  asMETHOD(Engine, GetEventHandler), asCALL_THISCALL) < 0) {
630  }
631 
632  if(engine->RegisterObjectMethod("Engine", "SoundDevice& GetSoundDevice()",
633  asMETHOD(Engine, GetSoundDevice), asCALL_THISCALL) < 0) {
635  }
636 
637  if(engine->RegisterObjectMethod("Engine", "FileSystem& GetFileSystem()",
638  asMETHOD(Engine, GetFileSystem), asCALL_THISCALL) < 0) {
640  }
641 
642  if(engine->RegisterObjectMethod("Engine", "ThreadingManager& GetThreadingManager()",
643  asMETHOD(Engine, GetThreadingManager), asCALL_THISCALL) < 0) {
645  }
646 
647  if(engine->RegisterObjectMethod("Engine", "Window& GetWindowEntity()",
648  asMETHOD(Engine, GetWindowEntity), asCALL_THISCALL) < 0) {
650  }
651 
652  if(engine->RegisterObjectMethod("Engine", "Graphics& GetGraphics()",
653  asMETHOD(Engine, GetGraphics), asCALL_THISCALL) < 0) {
655  }
656 
657  // ------------------------------------ //
658 
659  if(engine->RegisterObjectMethod("Engine", "int64 GetTimeSinceLastTick()",
660  asMETHOD(Engine, GetTimeSinceLastTick), asCALL_THISCALL) < 0) {
662  }
663 
664  // TODO: restore once confirmed nothing is misusing this
665  // if(engine->RegisterObjectMethod("Engine", "int GetCurrentTick()",
666  // asMETHOD(Engine, GetCurrentTick), asCALL_THISCALL) < 0) {
667  // ANGELSCRIPT_REGISTERFAIL;
668  // }
669 
670  if(engine->RegisterObjectMethod("Engine", "int GetWindowOpenCount()",
671  asMETHOD(Engine, GetWindowOpenCount), asCALL_THISCALL) < 0) {
673  }
674 
675  if(engine->RegisterObjectMethod(
676  "Engine", "void MarkQuit()", asMETHOD(Engine, MarkQuit), asCALL_THISCALL) < 0) {
678  }
679 
680  if(engine->RegisterObjectMethod("Engine", "bool IsOnMainThread()",
681  asMETHOD(Engine, IsOnMainThread), asCALL_THISCALL) < 0) {
683  }
684 
685  if(engine->RegisterFuncdef("void InvokeCallbackFunc()") < 0) {
687  }
688 
689  if(engine->RegisterObjectMethod("Engine", "void Invoke(InvokeCallbackFunc@ callback)",
690  asFUNCTION(InvokeProxy), asCALL_CDECL_OBJFIRST) < 0) {
692  }
693 
694  return true;
695 }
696 // ------------------------------------ //
697 bool BindApplication(asIScriptEngine* engine)
698 {
699 
700  if(engine->RegisterEnum("NETWORKED_TYPE") < 0) {
702  }
703 
708 
709  if(engine->RegisterObjectType("LeviathanApplication", 0, asOBJ_REF | asOBJ_NOCOUNT) < 0) {
711  }
712 
713  // Global get function //
714  if(engine->RegisterGlobalFunction("LeviathanApplication& GetLeviathanApplication()",
715  asFUNCTION(LeviathanApplication::Get), asCALL_CDECL) < 0) {
717  }
718 
719  if(engine->RegisterObjectMethod("LeviathanApplication", "void MarkAsClosing()",
720  asMETHOD(LeviathanApplication, MarkAsClosing), asCALL_THISCALL) < 0) {
722  }
723 
724  if(engine->RegisterObjectMethod("LeviathanApplication", "bool Quitting()",
725  asMETHOD(LeviathanApplication, Quitting), asCALL_THISCALL) < 0) {
727  }
728 
729  if(engine->RegisterObjectMethod("LeviathanApplication",
730  "NETWORKED_TYPE GetProgramNetType() const",
731  asMETHOD(LeviathanApplication, GetProgramNetType), asCALL_THISCALL) < 0) {
733  }
734 
735  return true;
736 }
737 // ------------------------------------ //
738 bool BindGameModule(asIScriptEngine* engine)
739 {
740 
742 
743  // Bind simple name get function //
744  if(engine->RegisterObjectMethod("GameModule", "string GetDescription(bool full = false)",
745  asMETHOD(GameModule, GetDescription), asCALL_THISCALL) < 0) {
747  }
748 
749 
750  return true;
751 }
752 // ------------------------------------ //
753 bool BindDelegates(asIScriptEngine* engine)
754 {
755 
756  if(engine->RegisterFuncdef("void DelegateCallbackFunc(NamedVars@ values)") < 0) {
758  }
759 
761 
762  if(engine->RegisterObjectMethod("Delegate", "void Call(NamedVars@ values) const",
763  asMETHODPR(Delegate, Call, (NamedVars*)const, void), asCALL_THISCALL) < 0) {
765  }
766 
767  if(engine->RegisterObjectMethod("Delegate",
768  "void Register(DelegateCallbackFunc@ callback)", asFUNCTION(DelegateRegisterProxy),
769  asCALL_CDECL_OBJFIRST) < 0) {
771  }
772 
773 
774  return true;
775 }
776 
777 bool BindAudioSource(asIScriptEngine* engine)
778 {
780 
781  if(engine->RegisterObjectMethod("AudioSource", "void Resume()",
782  asMETHOD(AudioSource, Resume), asCALL_THISCALL) < 0) {
784  }
785 
786  if(engine->RegisterObjectMethod(
787  "AudioSource", "void Pause()", asMETHOD(AudioSource, Pause), asCALL_THISCALL) < 0) {
789  }
790 
791  if(engine->RegisterObjectMethod(
792  "AudioSource", "void Stop()", asMETHOD(AudioSource, Stop), asCALL_THISCALL) < 0) {
794  }
795 
796  if(engine->RegisterObjectMethod("AudioSource", "bool IsPlaying() const",
797  asMETHOD(AudioSource, IsPlaying), asCALL_THISCALL) < 0) {
799  }
800 
801  if(engine->RegisterObjectMethod("AudioSource", "void SetVolume(float volume)",
802  asMETHOD(AudioSource, SetVolume), asCALL_THISCALL) < 0) {
804  }
805 
806  if(engine->RegisterObjectMethod("AudioSource", "bool HasInternalSource() const",
807  asMETHOD(AudioSource, HasInternalSource), asCALL_THISCALL) < 0) {
809  }
810 
811  return true;
812 }
813 
814 bool BindSound(asIScriptEngine* engine)
815 {
817 
818  if(!BindAudioSource(engine))
819  return false;
820 
821  if(engine->RegisterObjectType("SoundDevice", 0, asOBJ_REF | asOBJ_NOHANDLE) < 0) {
823  }
824 
825  if(engine->RegisterObjectMethod("SoundDevice",
826  "void Play2DSoundEffect(const string &in filename)",
827  asMETHOD(SoundDevice, Play2DSoundEffect), asCALL_THISCALL) < 0) {
829  }
830 
831  if(engine->RegisterObjectMethod("SoundDevice",
832  "AudioSource@ Play2DSound(const string &in filename, bool looping)",
833  asFUNCTION(SoundDevicePlay2DProxy), asCALL_CDECL_OBJFIRST) < 0) {
835  }
836 
837  return true;
838 }
839 
840 bool BindFileSystem(asIScriptEngine* engine)
841 {
842  // Many of the filesystem methods aren't safe to expose to every
843  // script so they are hidden by default
844  if(engine->RegisterEnum("FILEGROUP") < 0) {
846  }
847 
853 
854  if(engine->RegisterObjectType("FileSystem", 0, asOBJ_REF | asOBJ_NOHANDLE) < 0) {
856  }
857 
858  const auto oldMask =
859  engine->SetDefaultAccessMask(static_cast<AccessFlags>(ScriptAccess::FullFileSystem));
860 
861  if(engine->RegisterObjectMethod("FileSystem",
862  "string SearchForFile(FILEGROUP which, const string &in name, const string &in "
863  "extensions, bool searchall = true)",
864  asMETHOD(FileSystem, SearchForFile), asCALL_THISCALL) < 0) {
866  }
867 
868  // Restore access for non-full access requiring static stuff
869  engine->SetDefaultAccessMask(oldMask);
870 
871  // ------------------------------------ //
872  // Static methods
873  if(engine->SetDefaultNamespace("FileSystem") < 0) {
875  }
876 
877  // And back to protected functions
878  engine->SetDefaultAccessMask(static_cast<AccessFlags>(ScriptAccess::FullFileSystem));
879 
880  if(engine->RegisterGlobalFunction("bool FileExists(const string &in filepath)",
881  asFUNCTION(FileSystem::FileExists), asCALL_CDECL) < 0) {
882 
884  }
885 
886  // Restore settings //
887  engine->SetDefaultAccessMask(oldMask);
888  if(engine->SetDefaultNamespace("") < 0) {
890  }
891 
892  return true;
893 }
894 
895 } // namespace Leviathan
896 
897 bool Leviathan::BindEngineCommon(asIScriptEngine* engine)
898 {
899  if(!BindNamedVars(engine))
900  return false;
901 
902  if(!BindEvents(engine))
903  return false;
904 
905  if(!BindSound(engine))
906  return false;
907 
908  if(!BindFileSystem(engine))
909  return false;
910 
911  if(!BindGraphics(engine))
912  return false;
913 
914  if(!BindThreadingManager(engine))
915  return false;
916 
917  if(!BindWindow(engine))
918  return false;
919 
920  if(!BindEngine(engine))
921  return false;
922 
923  if(!BindApplication(engine))
924  return false;
925 
926  if(!BindGameModule(engine))
927  return false;
928 
929  if(!BindDelegates(engine))
930  return false;
931 
932 
933  // ------------------ Global functions ------------------ //
934  if(engine->RegisterGlobalFunction("string GetLeviathanVersion()",
935  asFUNCTION(GetLeviathanVersionProxy), asCALL_CDECL) < 0) {
937  }
938 
939  if(engine->RegisterGlobalFunction("void LOG_WRITE(const string &in message)",
940  asFUNCTION(LOG_WRITEProxy), asCALL_CDECL) < 0) {
942  }
943 
944  if(engine->RegisterGlobalFunction("void LOG_INFO(const string &in message)",
945  asFUNCTION(LOG_INFOProxy), asCALL_CDECL) < 0) {
947  }
948 
949  if(engine->RegisterGlobalFunction("void LOG_WARNING(const string &in message)",
950  asFUNCTION(LOG_WARNINGProxy), asCALL_CDECL) < 0) {
952  }
953 
954  if(engine->RegisterGlobalFunction("void LOG_ERROR(const string &in message)",
955  asFUNCTION(LOG_ERRORProxy), asCALL_CDECL) < 0) {
957  }
958  // LOG_FATAL not bound
959  // Use assert instead
960 
961  if(engine->RegisterGlobalFunction("void Print(const string &in message)",
962  asFUNCTION(Logger::Print), asCALL_CDECL) < 0) {
964  }
965 
966  if(engine->RegisterGlobalFunction("void assert(bool expression, const string &in message)",
967  asFUNCTION(AngelScriptAssertWrapper), asCALL_GENERIC) < 0) {
969  }
970  if(engine->RegisterGlobalFunction("void assert(bool expression)",
971  asFUNCTION(AngelScriptAssertWrapper), asCALL_GENERIC) < 0) {
973  }
974 
975  if(engine->RegisterGlobalFunction(
976  "bool IsInGraphicalMode()", asFUNCTION(IsInGraphicalMode), asCALL_CDECL) < 0) {
978  }
979 
980  if(engine->RegisterGlobalFunction(
981  "void PrintCallStack()", asFUNCTION(PrintASCallStack), asCALL_CDECL) < 0) {
983  }
984 
985  // ------------------------------------ //
986  // Global vars
987  if(engine->RegisterGlobalProperty("const float PI", &PIProxy) < 0) {
988 
990  }
991 
992  if(engine->RegisterGlobalProperty("const float EPSILON", &EPSILONProxy) < 0) {
993 
995  }
996 
997  if(engine->RegisterGlobalProperty(
998  "const float DEGREES_TO_RADIANS", &DEGREES_TO_RADIANSProxy) < 0) {
999 
1001  }
1002 
1003  if(engine->RegisterGlobalProperty(
1004  "const float RADIANS_TO_DEGREES", &RADIANS_TO_DEGREESProxy) < 0) {
1005 
1007  }
1008 
1009  // if(engine->RegisterGlobalProperty("const int TICKSPEED", &TICKSPEEDProxy) < 0) {
1010 
1011  // ANGELSCRIPT_REGISTERFAIL;
1012  // }
1013 
1014  return true;
1015 }
bool BindEngine(asIScriptEngine *engine)
bool BindEvents(asIScriptEngine *engine)
ScriptRunResult< ReturnT > RunScript(const std::shared_ptr< ScriptModule > &module, ScriptRunningSetup &parameters, Args &&... args)
Runs a function in a script.
Class that represents a statically defined event.
Definition: Event.h:106
static DLLEXPORT int GetGlobalWindowCount()
Definition: Window.h:180
static std::string GetLeviathanVersionProxy()
void PrintASCallStack()
Prints current angelscript callstack.
DLLEXPORT void Invoke(const std::function< void()> &function)
Runs function on the main thread before the next tick.
Definition: Engine.cpp:1169
#define LOG_INFO(x)
Definition: Define.h:90
#define LOG_ERROR(x)
Definition: Define.h:92
bool BindNamedVars(asIScriptEngine *engine)
bool BindDelegates(asIScriptEngine *engine)
static void LOG_ERRORProxy(const std::string &str)
Random number generator based on Mersenne Twister.
Definition: Random.h:15
Manages loading the audio library and provides some helpers.
Definition: SoundDevice.h:15
AudioSource * SoundDevicePlay2DProxy(SoundDevice *self, const std::string &filename, bool looping)
bool BindDataBlock(asIScriptEngine *engine)
static void LOG_WARNINGProxy(const std::string &str)
Allows object to register for events that can be fired from anywhere.
Definition: EventHandler.h:15
#define ANGELSCRIPT_REGISTER_REF_TYPE(RegisterName, ClassName)
Definition: BindHelpers.h:92
bool BindWindow(asIScriptEngine *engine)
EVENT_TYPE
Engine events that are triggered at certain times.
Definition: Event.h:12
Class for indexing and searching game data directory.
Definition: FileSystem.h:65
bool BindGraphics(asIScriptEngine *engine)
static void LOG_INFOProxy(const std::string &str)
static void LOG_WRITEProxy(const std::string &str)
bool BindEngineCommon(asIScriptEngine *engine)
The main class of the Leviathan Game Engine.
Definition: Engine.h:37
static DLLEXPORT void PrintCallstack(asIScriptContext *ctx, LErrorReporter &output)
Base class for all exceptions thrown by Leviathan.
Definition: Exceptions.h:10
An object which can accept BaseDelegateSlot derived callbacks that can be called when the event repre...
Definition: DelegateSlot.h:52
#define LOG_WARNING(x)
Definition: Define.h:91
#define ANGELSCRIPT_REGISTER_ENUM_VALUE(enum, x)
Definition: BindHelpers.h:107
bool BindRandom(asIScriptEngine *engine)
static DLLEXPORT ScriptExecutor * Get()
bool BindThreadingManager(asIScriptEngine *engine)
Class that represents a dynamically defined event.
Definition: Event.h:140
bool BindFileSystem(asIScriptEngine *engine)
static float RADIANS_TO_DEGREESProxy
bool GetNoGui()
Definition: Engine.h:261
Reference counted version for scripts of VariableBlock.
Definition: DataBlock.h:840
DLLEXPORT void MarkAsClosing()
Thread safely marks the game to close sometime.
Manages delayed execution of functions through use of QueuedTask and subclasses.
#define LOG_WRITE(x)
Definition: Define.h:93
bool BindApplication(asIScriptEngine *engine)
Only set when the derived class forgot to set it.
static float EPSILONProxy
bool BindGameModule(asIScriptEngine *engine)
Small ReferenceCounted wrapper around an audio buffer.
Definition: AudioBuffer.h:21
constexpr float EPSILON
Definition: Define.h:70
static float PIProxy
NETWORKED_TYPE
Type of networked application.
Definition: CommonNetwork.h:22
FORCE_INLINE void AddRef() const
std::chrono::duration< int64_t, std::milli > MillisecondDuration
Definition: TimeIncludes.h:14
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100
static void InvokeProxy(Engine *obj, asIScriptFunction *callback)
bool IsInGraphicalMode()
EventListener * EventListenerFactory(asIScriptFunction *onevent, asIScriptFunction *ongeneric)
ScriptSafeVariableBlock * ScriptSafeVariableBlockFactoryGeneric(const std::string &blockname, TType value)
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
static DLLEXPORT bool FileExists(const std::string &name)
Definition: FileSystem.cpp:451
static DLLEXPORT LeviathanApplication * Get()
Definition: Application.cpp:32
Main DataBlock class.
Definition: DataBlock.h:37
Event * WrapperEventFactory(EVENT_TYPE type)
constexpr float RADIANS_TO_DEGREES
Definition: Define.h:69
bool BindAudioSource(asIScriptEngine *engine)
GenericEvent * WrapperGenericEventFactory(const std::string &name)
constexpr float PI
Definition: Define.h:65
void AngelScriptAssertWrapper(asIScriptGeneric *gen)
constexpr float DEGREES_TO_RADIANS
Definition: Define.h:68
static void QueueTaskDelayed(ThreadingManager *self, asIScriptFunction *callback, int milliseconds)
#define ANGELSCRIPT_REGISTERFAIL
Definition: BindHelpers.h:12
static float DEGREES_TO_RADIANSProxy
Small ReferenceCounted wrapper around an audio source.
Definition: AudioSource.h:16
DLLEXPORT void Register(const BaseDelegateSlot::pointer &callback)
Registers a new callback.
bool BindSound(asIScriptEngine *engine)
static DLLEXPORT void Print(const std::string &message)
Script wrapper.
Definition: Logger.cpp:223
DataBlock< std::string > StringBlock
Definition: DataBlock.h:386
Represents a scriptable part of a program.
Definition: GameModule.h:18
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:86
Base class for all leviathan programs.
Definition: Application.h:16
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
ScriptSafeVariableBlock * ScriptSafeVariableBlockFactoryString(const std::string &blockname, const std::string &valuestr)
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
static void DelegateRegisterProxy(Delegate *obj, asIScriptFunction *callback)
virtual DLLEXPORT void PrintToLog() const noexcept
Definition: Exceptions.cpp:35
An EventListener that scripts can use to listen for events.
static NamedVars * NamedVarsFactory()