/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include #include #include "squirrel.h" #include "script_squirrel/cobject/uc_binding.h" #include "script_squirrel/cobject/cobject.h" #include "script_squirrel/cobject/vector_decl.h" #include "script_squirrel/cobject/uv_decl.h" #include "squirrel_binding.h" #include "binding_helpers.h" #if __PLATFORM_NINTENDO_WII__ #include "platform/wii/script/wii_binding.h" #endif #include "geometry/bounding_box.h" #include "color/color.h" #include "geometry/rect.h" #include "filesystem/filesystem.h" #include "platform.h" namespace GS { namespace Script { //------------------------------------------------------------------------------ static bool BindingError(HSQUIRRELVM vm, const char *msg) { // if (sq_getforeignptr(vm)) // ((Script::VM *)sq_getforeignptr(vm))->Kill(); SquirrelVM::DumpCallStack(vm, String::Format("Binding error: %s", msg).c_str()); return false; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ bool CreateClassInstance(HSQUIRRELVM vm, const char *class_name, bool call) { sq_pushroottable(vm); sq_pushstring(vm, class_name, -1); if (SQ_FAILED(sq_get(vm, -2))) { sq_pop(vm, 1); return BindingError(vm, String::Format("Class '%s' is not declared.", class_name).c_str()); } if (call) { sq_pushroottable(vm); if (SQ_FAILED(sq_call(vm, 1, SQTrue, SQTrue))) { sq_pop(vm, 1); return BindingError(vm, String::Format("Failed to instantiate class '%s'.", class_name).c_str()); } } else sq_createinstance(vm, -1); sq_remove(vm, -2); // Remove root table. sq_remove(vm, -2); // Remove class. return true; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void PushColor(HSQUIRRELVM vm, const Color &c) { if (!CreateClassInstance(vm, "Vector", true)) BindingError(vm, "Failed to create Vector instance."); SetTableKey("x", sq_pushfloat, -1, c.x); SetTableKey("y", sq_pushfloat, -1, c.y); SetTableKey("z", sq_pushfloat, -1, c.z); SetTableKey("w", sq_pushfloat, -1, c.w); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void PushVector2(HSQUIRRELVM vm, const Vector2 &v) { if (!CreateClassInstance(vm, "Vector2", true)) BindingError(vm, "Failed to create Vector2 instance."); SetTableKey("x", sq_pushfloat, -1, v.x); SetTableKey("y", sq_pushfloat, -1, v.y); } void GetVector2(HSQUIRRELVM vm, SQInteger idx, Vector2 &v) { SQFloat x, y; GetTableKey("x", sq_getfloat, idx, x) GetTableKey("y", sq_getfloat, idx, y) v.Set(x, y); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void PushVector(HSQUIRRELVM vm, const Vector4 &v, bool push_w) { push_Vector(vm, v); } void GetVector(HSQUIRRELVM v, SQInteger idx, Vector4 &vo, bool get_w) { _CHECK_INST_PARAM_RAW(pv, idx, Vector4, Vector); vo = *pv; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void PushUV(HSQUIRRELVM vm, const Vector2 &uv) { if (!CreateClassInstance(vm, "UV", true)) BindingError(vm, "Failed to create UV instance."); SetTableKey("u", sq_pushfloat, -1, uv.x); SetTableKey("v", sq_pushfloat, -1, uv.y); } void GetUV(HSQUIRRELVM v, SQInteger idx, Vector2 &uv) { _CHECK_INST_PARAM_RAW(pv, idx, Vector2, UV); uv = *pv; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void PushMinMax(HSQUIRRELVM vm, const MinMax &v) { if (!CreateClassInstance(vm, "MinMax", true)) BindingError(vm, "Failed to create MinMax instance."); sq_pushstring(vm, "min", -1); sq_get(vm, -2); SetTableKey("x", sq_pushfloat, -1, v.mn.x) SetTableKey("y", sq_pushfloat, -1, v.mn.y) SetTableKey("z", sq_pushfloat, -1, v.mn.z) sq_pop(vm, 1); sq_pushstring(vm, "max", -1); sq_get(vm, -2); SetTableKey("x", sq_pushfloat, -1, v.mx.x) SetTableKey("y", sq_pushfloat, -1, v.mx.y) SetTableKey("z", sq_pushfloat, -1, v.mx.z) sq_pop(vm, 1); } void GetMinMax(HSQUIRRELVM vm, SQInteger idx, MinMax &v) { sq_pushstring(vm, "min", -1); sq_get(vm, -2); GetVector(vm, -1, v.mn); sq_pop(vm, 1); sq_pushstring(vm, "max", -1); sq_get(vm, -2); GetVector(vm, -1, v.mx); sq_pop(vm, 1); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void PushRect(HSQUIRRELVM vm, const fRect &r) { if (!CreateClassInstance(vm, "Rect")) BindingError(vm, "Failed to create Rect instance."); SetTableKey("sx", sq_pushfloat, -1, r.sx); SetTableKey("sy", sq_pushfloat, -1, r.sy); SetTableKey("ex", sq_pushfloat, -1, r.ex); SetTableKey("ey", sq_pushfloat, -1, r.ey); } void GetRect(HSQUIRRELVM vm, SQInteger idx, fRect &r) { SQFloat sx, sy, ex, ey; GetTableKey("sx", sq_getfloat, idx, sx) GetTableKey("sy", sq_getfloat, idx, sy) GetTableKey("ex", sq_getfloat, idx, ex) GetTableKey("ey", sq_getfloat, idx, ey) r.Set(sx, sy, ex, ey); } void PushRect(HSQUIRRELVM vm, const iRect &r) { PushRect(vm, r.AsFloat()); } void GetRect(HSQUIRRELVM vm, SQInteger idx, iRect &r) { fRect t; GetRect(vm, idx, t); r.Set(int(t.sx), int(t.sy), int(t.ex), int(t.ey)); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void sq_register(HSQUIRRELVM v, SQFUNCTION f, const char *fname, const SQChar *mask) { sq_pushroottable(v); sq_pushstring(v, (const SQChar *)fname, -1); sq_newclosure(v, f, 0); // Create a new function. sq_setnativeclosurename(v, -1, fname); sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, mask); sq_newslot(v, -3, false); sq_pop(v, 1); // Pop the root table. } //------------------------------------------------------------------------------ } // Script } // GS using namespace GS; using namespace GS::Script; //------------------------------------------ SQInteger SQAssert(HSQUIRRELVM vm) //------------------------------------------ { __SQ_GETSTART(2) __SQ_GETBOOL(c) __SQ_GETSTRING(d) if (!c) return sq_throwerror(vm, d); __SQ_GETEND __SQ_RETURN } //--------------------------------------- SQInteger SQPow(HSQUIRRELVM vm) //--------------------------------------- { __SQ_GETSTART(2) __SQ_GETFLOAT(v) __SQ_GETFLOAT(p) __SQ_GETEND __SQ_RETURNFLOAT(pow(v, p)) } //--------------------------------------- SQInteger SQExp(HSQUIRRELVM vm) //--------------------------------------- { __SQ_GETSTART(1) __SQ_GETFLOAT(v) __SQ_GETEND __SQ_RETURNFLOAT(exp(v)) } //--------------------------------------- SQInteger SQMod(HSQUIRRELVM vm) //--------------------------------------- { __SQ_GETSTART(2) __SQ_GETINT(v) __SQ_GETINT(m) __SQ_GETEND __SQ_RETURNINT(v % m) } //------------------------------------------ SQInteger SQAbsMod(HSQUIRRELVM vm) //------------------------------------------ { __SQ_GETSTART(2) __SQ_GETINT(v) __SQ_GETINT(m) __SQ_GETEND v %= m; if (v < 0) v = m + v; __SQ_RETURNINT(v) } //----------------------------------------------- SQInteger ObjectIsValid(HSQUIRRELVM vm) //----------------------------------------------- { void *p; if (!CObject::Get(vm, -1, &p)) return -1; sq_pop(vm, 1); __SQ_RETURNBOOL(asbool(p)); } //---------------------------------------------- SQInteger ObjectIsSame(HSQUIRRELVM vm) //---------------------------------------------- { void *a, *b; if (!CObject::Get(vm, -2, &a) || !CObject::Get(vm, -1, &b)) return -1; sq_pop(vm, 2); __SQ_RETURNBOOL(a == b); } //---------------------------------------------- SQInteger ShellExecute(HSQUIRRELVM vm) //---------------------------------------------- { __SQ_GETSTART(2) __SQ_GETSTRING(path) __SQ_GETSTRING(parm) int r = -1; #if __PLATFORM_WINDOWS__ if (path) { String cmd = parm ? String::Format("%s %s", path, parm).c_str() : path; __LOG_H__ << "Execute command '" << cmd << "'\n\n"; #if 0 char szBuffer[_MAX_PATH * 10 + 1]; DWORD dw; HANDLE hIn, hOut; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; STARTUPINFO si; if (CreatePipe(&hIn, &hOut, NULL, sizeof(szBuffer) * 2)) { memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_HIDE; si.hStdOutput = hOut; si.hStdError = hOut; //if (!CreateProcess("C:\\WINDOWS\\system32\\cmd.exe", (LPSTR)cmd.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) if (!CreateProcess(NULL, (LPSTR)cmd.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) __LOG_N__ << "Couldn't create process: " << GetLastError() << "\n"; else { CloseHandle(hOut); __LOG_N__ << "Reading ShellExecute...\n"; forever { if (ReadFile(hIn, szBuffer, sizeof(szBuffer) - 1, &dw, NULL) == 0) { if (GetLastError() == ERROR_NO_DATA) Sleep(1); else if (GetLastError() == ERROR_BROKEN_PIPE) { GetExitCodeProcess(pi.hProcess, &dw); r = dw; break; } else break; } else if (dw > 0) { szBuffer[dw] = 0; __LOG__ << szBuffer << "\n"; } if ((GetExitCodeProcess(pi.hProcess, &dw) == 0) || (dw != STILL_ACTIVE)) { r = dw; break; } } } CloseHandle(hIn); } else { __LOG_N__ << "Couldn't create pipe: " << GetLastError() << "\n"; } #else char psBuffer[256]; FILE *iopipe; if ((iopipe = _popen(cmd.c_str(), "r" )) != 0) while (!feof(iopipe)) if (fgets(psBuffer, 256, iopipe)) __LOG__ << psBuffer; r = _pclose(iopipe); #endif } #elif __PLATFORM_OSX__ __LOG_E__ << "ShellExecute(): STUB\n"; #elif __PLATFORM_LINUX__ r = path ? system(parm ? String::Format("%s %s", path, parm).c_str() : path) : -1; #endif __SQ_GETEND __SQ_RETURNINT(r) } //--------------------------------------- SQInteger Sleep(HSQUIRRELVM vm) //--------------------------------------- { __SQ_GETSTART(1) __SQ_GETINT(ms) __SQ_GETEND Platform::Get().Sleep(ms); __SQ_RETURN } //------------------------------------------------------------ void RegisterAllSquirrelBinding(HSQUIRRELVM vm) //------------------------------------------------------------ { /*# Topic: Script #*/ /*# Section: ScriptDebug Desc: Debugging #*/ /*# Func: __Assert Proto: void:bool,string Desc: Assert an expression, throw an engine exception and suspend the VM if not verified. #*/ sq_register(vm, SQAssert, "__Assert", _SC(".bs")); /*# Section: ScriptGeneric Desc: Generic #*/ /*# Func: SQPow Proto: float:float value,float pow Desc: Returns value raised to power. #*/ sq_register(vm, SQPow, "Pow", _SC(".ff")); /*# Func: SQExp Proto: float:float value Desc: Returns value in exponential . #*/ sq_register(vm, SQExp, "Exp", _SC(".f")); /*# Func: SQMod Proto: int:int value,int divider Desc: Returns integer modulo of a value. #*/ sq_register(vm, SQMod, "Mod", _SC(".ii")); /*# Func: SQAbsMod Proto: int:int value,int divider Desc: Returns integer modulo of the absolute of a given value. #*/ sq_register(vm, SQAbsMod, "AbsMod", _SC(".ii")); /*# Func: ObjectIsValid Proto: bool:Object Desc: Returns true if the given engine object is valid, false otherwise.
This function can be used to test the validity of all engine types like geometry, material, item, scene and others. #*/ sq_register(vm, ObjectIsValid, "ObjectIsValid", _SC(".x")); /*# Func: ObjectIsSame Proto: bool:Object,Object Desc: Returns true if two given engine object references are pointing to the same object. #*/ sq_register(vm, ObjectIsSame, "ObjectIsSame", _SC(".xx")); /*# Topic: System #*/ /*# Section: SystemGeneric Desc: Generic #*/ /*# Func: ShellExecute Proto: int:string path,string param Desc: Execute an external program, returns its return code. #*/ sq_register(vm, ShellExecute, "ShellExecute", _SC(".ss")); sq_register(vm, Sleep, "_Sleep", _SC(".i")); // Legacy support. #if 1 sq_register(vm, ObjectIsValid, "AIPathIsValid", _SC(".x")); sq_register(vm, ObjectIsValid, "GeometryIsValid", _SC(".x")); sq_register(vm, ObjectIsValid, "ItemIsValid", _SC(".x")); sq_register(vm, ObjectIsValid, "MetatagIsValid", _SC(".x")); sq_register(vm, ObjectIsValid, "TextureIsValid", _SC(".x")); sq_register(vm, ObjectIsValid, "WidgetIsValid", _SC(".x")); sq_register(vm, ObjectIsValid, "WindowIsValid", _SC(".x")); #endif sq_pushroottable(vm); /*# Enum: SystemConstant Values: SystemClockFrequency #*/ sq_pushstring(vm, "SystemClockFrequency", -1); sq_pushinteger(vm, Platform::Get().GetClockFrequency()); sq_newslot(vm, -3, true); // Register engine types. for (int n = 0; n < typetag_End; ++n) { String type_string = String::Format("EngineType%s", CObjectTypeToString((CObjectType)n)); sq_pushstring(vm, type_string.TrimChar(' ').c_str(), -1); sq_pushinteger(vm, n); sq_newslot(vm, -3, true); } // Newer faster bindings. RegisterUCBinding(vm); // RegisterClockBinding(vm); RegisterMatrixBinding(vm); RegisterAnimationBinding(vm); RegisterAIBinding(vm); RegisterSystemBinding(vm); RegisterRendererBinding(vm); RegisterMixerBinding(vm); RegisterSceneBinding(vm); RegisterInstanceBinding(vm); RegisterGroupBinding(vm); RegisterCameraBinding(vm); RegisterObjectBinding(vm); RegisterMaterialBinding(vm); RegisterLightBinding(vm); RegisterProfilerBinding(vm); RegisterItemBinding(vm); RegisterMotionBinding(vm); RegisterCollisionBinding(vm); RegisterPhysicBinding(vm); RegisterPictureBinding(vm); RegisterTextureBinding(vm); RegisterSoundBinding(vm); RegisterGeometryBinding(vm); RegisterIOBinding(vm); RegisterUIBinding(vm); RegisterNMLBinding(vm); RegisterResourceFactoryBinding(vm); RegisterRaytracerBinding(vm); RegisterProjectBinding(vm); RegisterTriggerBinding(vm); RegisterEmitterBinding(vm); RegisterHashBinding(vm); RegisterHTTPBinding(vm); RegisterFontBinding(vm); RegisterPlatformBinding(vm); RegisterMaterialShaderBinding(vm); #if __PLATFORM_NINTENDO_WII__ RegisterWiiBinding(vm); #endif sq_pop(vm, 1); }