int w_Fixture_getShape(lua_State *L) { Fixture *t = luax_checkfixture(L, 1); StrongRef<Shape> shape(t->getShape(), Acquire::NORETAIN); if (shape.get() == nullptr) return 0; switch (shape->getType()) { case Shape::SHAPE_EDGE: luax_pushtype(L, PHYSICS_EDGE_SHAPE_ID, shape); break; case Shape::SHAPE_CHAIN: luax_pushtype(L, PHYSICS_CHAIN_SHAPE_ID, shape); break; case Shape::SHAPE_CIRCLE: luax_pushtype(L, PHYSICS_CIRCLE_SHAPE_ID, shape); break; case Shape::SHAPE_POLYGON: luax_pushtype(L, PHYSICS_POLYGON_SHAPE_ID, shape); break; default: luax_pushtype(L, PHYSICS_SHAPE_ID, shape); break; } return 1; }
int w_newFileData(lua_State *L) { // Single argument: treat as filepath or File. if (lua_gettop(L) == 1) { // We don't use luax_getfiledata because we want to use an ioError. if (lua_isstring(L, 1)) luax_convobj(L, 1, "filesystem", "newFile"); // Get FileData from the File. if (luax_istype(L, 1, FILESYSTEM_FILE_ID)) { File *file = luax_checkfile(L, 1); FileData *data = 0; try { data = file->read(); } catch (love::Exception &e) { return luax_ioError(L, "%s", e.what()); } luax_pushtype(L, FILESYSTEM_FILE_DATA_ID, data); data->release(); return 1; } else return luaL_argerror(L, 1, "filename or File expected"); } size_t length = 0; const char *str = luaL_checklstring(L, 1, &length); const char *filename = luaL_checkstring(L, 2); const char *decstr = lua_isstring(L, 3) ? lua_tostring(L, 3) : 0; FileData::Decoder decoder = FileData::FILE; if (decstr && !FileData::getConstant(decstr, decoder)) return luaL_error(L, "Invalid FileData decoder: %s", decstr); FileData *t = 0; switch (decoder) { case FileData::FILE: t = instance()->newFileData((void *)str, (int)length, filename); break; case FileData::BASE64: t = instance()->newFileData(str, filename); break; default: return luaL_error(L, "Invalid FileData decoder: %s", decstr); } luax_pushtype(L, FILESYSTEM_FILE_DATA_ID, t); t->release(); return 1; }
int w_Contact_getFixtures(lua_State *L) { Contact *t = luax_checkcontact(L, 1); Fixture *a = nullptr; Fixture *b = nullptr; luax_catchexcept(L, [&](){ t->getFixtures(a, b); }); luax_pushtype(L, PHYSICS_FIXTURE_ID, a); luax_pushtype(L, PHYSICS_FIXTURE_ID, b); return 2; }
int w_Joint_getBodies(lua_State *L) { Joint *t = luax_checkjoint(L, 1); Body *b1 = nullptr; Body *b2 = nullptr; luax_catchexcept(L, [&]() { b1 = t->getBodyA(); b2 = t->getBodyB(); }); luax_pushtype(L, b1); luax_pushtype(L, b2); return 2; }
int w_SpriteBatch_getTexture(lua_State *L) { SpriteBatch *t = luax_checkspritebatch(L, 1); Texture *tex = t->getTexture(); // FIXME: big hack right here. if (typeid(*tex) == typeid(Image)) luax_pushtype(L, GRAPHICS_IMAGE_ID, tex); else if (typeid(*tex) == typeid(Canvas)) luax_pushtype(L, GRAPHICS_CANVAS_ID, tex); else return luaL_error(L, "Unable to determine texture type."); return 1; }
int w_newImageData(lua_State *L) { // Case 1: Integers. if (lua_isnumber(L, 1)) { int w = (int) luaL_checknumber(L, 1); int h = (int) luaL_checknumber(L, 2); if (w <= 0 || h <= 0) return luaL_error(L, "Invalid image size."); size_t numbytes = 0; const char *bytes = nullptr; if (!lua_isnoneornil(L, 3)) bytes = luaL_checklstring(L, 3, &numbytes); ImageData *t = nullptr; luax_catchexcept(L, [&](){ t = instance()->newImageData(w, h); }); if (bytes) { if (numbytes != t->getSize()) { t->release(); return luaL_error(L, "The size of the raw byte string must match the ImageData's actual size in bytes."); } memcpy(t->getData(), bytes, t->getSize()); } luax_pushtype(L, IMAGE_IMAGE_DATA_ID, t); t->release(); return 1; } // Case 2: File(Data). love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1); ImageData *t = nullptr; luax_catchexcept(L, [&]() { t = instance()->newImageData(data); }, [&](bool) { data->release(); } ); luax_pushtype(L, IMAGE_IMAGE_DATA_ID, t); t->release(); return 1; }
int w_newChannel(lua_State *L) { Channel *c = instance()->newChannel(); luax_pushtype(L, c); c->release(); return 1; }
int w_newRasterizer(lua_State *L) { if (lua_type(L, 1) == LUA_TNUMBER || lua_type(L, 2) == LUA_TNUMBER || lua_isnone(L, 1)) { // First or second argument is a number: call newTrueTypeRasterizer. return w_newTrueTypeRasterizer(L); } else if (lua_isnoneornil(L, 2)) { // Single argument of another type: call Font::newRasterizer. Rasterizer *t = nullptr; filesystem::FileData *d = filesystem::luax_getfiledata(L, 1); luax_catchexcept(L, [&]() { t = instance()->newRasterizer(d); }, [&](bool) { d->release(); } ); luax_pushtype(L, FONT_RASTERIZER_ID, t); t->release(); return 1; } else { // Otherwise call newBMFontRasterizer. return w_newBMFontRasterizer(L); } }
int w_newFile(lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *str = 0; File::Mode mode = File::MODE_CLOSED; if (lua_isstring(L, 2)) { str = luaL_checkstring(L, 2); if (!File::getConstant(str, mode)) return luaL_error(L, "Incorrect file open mode: %s", str); } File *t = instance()->newFile(filename); if (mode != File::MODE_CLOSED) { try { if (!t->open(mode)) throw love::Exception("Could not open file."); } catch (love::Exception &e) { t->release(); return luax_ioError(L, "%s", e.what()); } } luax_pushtype(L, FILESYSTEM_FILE_ID, t); t->release(); return 1; }
int w_Body_getWorld(lua_State *L) { Body *t = luax_checkbody(L, 1); World *world = t->getWorld(); luax_pushtype(L, "World", PHYSICS_WORLD_T, world); return 1; }
int w_newSource(lua_State *L) { if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_ID) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_ID)) luax_convobj(L, 1, "sound", "newDecoder"); Source::Type stype = Source::TYPE_STREAM; const char *stypestr = lua_isnoneornil(L, 2) ? 0 : lua_tostring(L, 2); if (stypestr && !Source::getConstant(stypestr, stype)) return luaL_error(L, "Invalid source type: %s", stypestr); if (stype == Source::TYPE_STATIC && luax_istype(L, 1, SOUND_DECODER_ID)) luax_convobj(L, 1, "sound", "newSoundData"); Source *t = 0; luax_catchexcept(L, [&]() { if (luax_istype(L, 1, SOUND_SOUND_DATA_ID)) t = instance()->newSource(luax_totype<love::sound::SoundData>(L, 1, SOUND_SOUND_DATA_ID)); else if (luax_istype(L, 1, SOUND_DECODER_ID)) t = instance()->newSource(luax_totype<love::sound::Decoder>(L, 1, SOUND_DECODER_ID)); }); if (t) { luax_pushtype(L, AUDIO_SOURCE_ID, t); t->release(); return 1; } else return luax_typerror(L, 1, "Decoder or SoundData"); }
int w_lines(lua_State *L) { File *file; if (lua_isstring(L, 1)) { file = instance()->newFile(lua_tostring(L, 1)); bool success = false; luax_catchexcept(L, [&](){ success = file->open(File::MODE_READ); }); if (!success) { file->release(); return luaL_error(L, "Could not open file."); } luax_pushtype(L, FILESYSTEM_FILE_ID, file); file->release(); } else return luaL_argerror(L, 1, "expected filename."); lua_pushcclosure(L, w_File_lines_i, 1); return 1; }
int w_BezierCurve_getDerivative(lua_State *L) { BezierCurve *curve = luax_checkbeziercurve(L, 1); BezierCurve *deriv = new BezierCurve(curve->getDerivative()); luax_pushtype(L, MATH_BEZIER_CURVE_ID, deriv); deriv->release(); return 1; }
int w_getChannel(lua_State *L) { std::string name = luax_checkstring(L, 1); Channel *c = instance()->getChannel(name); luax_pushtype(L, c); c->release(); return 1; }
int w_SoundData_clone(lua_State *L) { SoundData *t = luax_checksounddata(L, 1), *c = nullptr; luax_catchexcept(L, [&](){ c = t->clone(); }); luax_pushtype(L, c); c->release(); return 1; }
int w_Mesh_getTexture(lua_State *L) { Mesh *t = luax_checkmesh(L, 1); Texture *tex = t->getTexture(); if (tex == nullptr) return 0; // FIXME: big hack right here. if (typeid(*tex) == typeid(Image)) luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, tex); else if (typeid(*tex) == typeid(Canvas)) luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, tex); else return luaL_error(L, "Unable to determine texture type."); return 1; }
int w_Fixture_getBody(lua_State *L) { Fixture *t = luax_checkfixture(L, 1); Body *body = t->getBody(); if (body == 0) return 0; luax_pushtype(L, PHYSICS_BODY_ID, body); return 1; }
int w_ChainShape_getChildEdge(lua_State *L) { ChainShape *c = luax_checkchainshape(L, 1); int index = (int) luaL_checknumber(L, 2) - 1; // Convert from 1-based index EdgeShape *e = 0; luax_catchexcept(L, [&](){ e = c->getChildEdge(index); }); luax_pushtype(L, PHYSICS_EDGE_SHAPE_ID, e); e->release(); return 1; }
int w_getRecordedData(lua_State *L) { love::sound::SoundData *sd = instance()->getRecordedData(); if (!sd) lua_pushnil(L); else { luax_pushtype(L, SOUND_SOUND_DATA_ID, sd); sd->release(); } return 1; }
int w_BezierCurve_getSegment(lua_State *L) { BezierCurve *curve = luax_checkbeziercurve(L, 1); double t1 = luaL_checknumber(L, 2); double t2 = luaL_checknumber(L, 3); BezierCurve *segment; luax_catchexcept(L, [&](){ segment = curve->getSegment(t1, t2); }); luax_pushtype(L, MATH_BEZIER_CURVE_ID, segment); segment->release(); return 1; }
int w_newCompressedData(lua_State *L) { love::filesystem::FileData *data = love::filesystem::luax_getfiledata(L, 1); CompressedImageData *t = nullptr; luax_catchexcept(L, [&]() { t = instance()->newCompressedData(data); }, [&](bool) { data->release(); } ); luax_pushtype(L, IMAGE_COMPRESSED_IMAGE_DATA_ID, t); t->release(); return 1; }
void Variant::toLua(lua_State *L) { switch (type) { case BOOLEAN: lua_pushboolean(L, data.boolean); break; case CHARACTER: lua_pushlstring(L, &data.character, 1); break; case NUMBER: lua_pushnumber(L, data.number); break; case STRING: lua_pushlstring(L, data.string.str, data.string.len); break; case LUSERDATA: lua_pushlightuserdata(L, data.userdata); break; case FUSERDATA: if (udatatype != INVALID_ID) { const char *name = NULL; love::types.find(udatatype, name); ((love::Object *) data.userdata)->retain(); luax_pushtype(L, name, flags, (love::Object *) data.userdata); } else lua_pushlightuserdata(L, data.userdata); // I know this is not the same // sadly, however, it's the most // I can do (at the moment). break; case TABLE: lua_newtable(L); for (size_t i = 0; i < data.table->size(); ++i) { std::pair<Variant*, Variant*> &kv = data.table->at(i); kv.first->toLua(L); kv.second->toLua(L); lua_settable(L, -3); } break; case NIL: default: lua_pushnil(L); break; } }
virtual void threadError(love::thread::LuaThread *thread, std::string error) { lua_rawgeti(L, LUA_REGISTRYINDEX, id); /* table */ lua_getfield(L, -1, "threaderror"); /* func table */ lua_remove(L, -2); /* func */ if (lua_isfunction(L, -1)) { luax_pushtype(L, "Thread", THREAD_THREAD_ID, thread); lua_pushstring(L, error.c_str()); if (lua_pcall(L, 2, 0, 0) != 0) { /* error */ printf("Error in LuaState: %s\n",lua_tostring(L, 1)); lua_pop(L, 1); } } else { lua_pop(L, 1); } };
int w_Image_getData(lua_State *L) { Image *i = luax_checkimage(L, 1); int n = 0; if (i->isCompressed()) { for (const auto &cdata : i->getCompressedData()) { luax_pushtype(L, IMAGE_COMPRESSED_IMAGE_DATA_ID, cdata.get()); n++; } } else { for (const auto &data : i->getImageData()) { luax_pushtype(L, IMAGE_IMAGE_DATA_ID, data.get()); n++; } } return n; }
int w_newImageRasterizer(lua_State *L) { Rasterizer *t = nullptr; convimagedata(L, 1); image::ImageData *d = luax_checktype<image::ImageData>(L, 1, IMAGE_IMAGE_DATA_ID); std::string glyphs = luax_checkstring(L, 2); int extraspacing = (int) luaL_optnumber(L, 3, 0); luax_catchexcept(L, [&](){ t = instance()->newImageRasterizer(d, glyphs, extraspacing); }); luax_pushtype(L, FONT_RASTERIZER_ID, t); t->release(); return 1; }
int w_stopRecording(lua_State *L) { if (luax_optboolean(L, 1, true)) { love::sound::SoundData *sd = instance()->stopRecording(true); if (!sd) lua_pushnil(L); else { luax_pushtype(L, SOUND_SOUND_DATA_ID, sd); sd->release(); } return 1; } instance()->stopRecording(false); return 0; }
int w_newThread(lua_State *L) { std::string name = "Thread code"; love::Data *data = nullptr; if (lua_isstring(L, 1)) { size_t slen = 0; const char *str = lua_tolstring(L, 1, &slen); // Treat the string as Lua code if it's long or has a newline. if (slen >= 1024 || memchr(str, '\n', slen)) { // Construct a FileData from the string. lua_pushvalue(L, 1); lua_pushstring(L, "string"); int idxs[] = {lua_gettop(L) - 1, lua_gettop(L)}; luax_convobj(L, idxs, 2, "filesystem", "newFileData"); lua_pop(L, 1); lua_replace(L, 1); } else luax_convobj(L, 1, "filesystem", "newFileData"); } else if (luax_istype(L, 1, love::filesystem::File::type)) luax_convobj(L, 1, "filesystem", "newFileData"); if (luax_istype(L, 1, love::filesystem::FileData::type)) { love::filesystem::FileData *fdata = luax_checktype<love::filesystem::FileData>(L, 1); name = std::string("@") + fdata->getFilename(); data = fdata; } else { data = luax_checktype<love::Data>(L, 1); } LuaThread *t = instance()->newThread(name, data); luax_pushtype(L, t); t->release(); return 1; }
int w_newTrueTypeRasterizer(lua_State *L) { Rasterizer *t = nullptr; TrueTypeRasterizer::Hinting hinting = TrueTypeRasterizer::HINTING_NORMAL; if (lua_type(L, 1) == LUA_TNUMBER || lua_isnone(L, 1)) { // First argument is a number: use the default TrueType font. int size = (int) luaL_optnumber(L, 1, 12); const char *hintstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2); if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting)) return luaL_error(L, "Invalid TrueType font hinting mode: %s", hintstr); luax_catchexcept(L, [&](){ t = instance()->newTrueTypeRasterizer(size, hinting); }); } else { love::Data *d = nullptr; if (luax_istype(L, 1, DATA_ID)) d = luax_checkdata(L, 1); else d = filesystem::luax_getfiledata(L, 1); int size = (int) luaL_optnumber(L, 2, 12); const char *hintstr = lua_isnoneornil(L, 3) ? nullptr : luaL_checkstring(L, 3); if (hintstr && !TrueTypeRasterizer::getConstant(hintstr, hinting)) return luaL_error(L, "Invalid TrueType font hinting mode: %s", hintstr); luax_catchexcept(L, [&]() { t = instance()->newTrueTypeRasterizer(d, size, hinting); }, [&](bool) { d->release(); } ); } luax_pushtype(L, FONT_RASTERIZER_ID, t); t->release(); return 1; }
int w_newBMFontRasterizer(lua_State *L) { Rasterizer *t = nullptr; filesystem::FileData *d = filesystem::luax_getfiledata(L, 1); std::vector<image::ImageData *> images; if (lua_istable(L, 2)) { for (int i = 1; i <= (int) luax_objlen(L, 2); i++) { lua_rawgeti(L, 2, i); convimagedata(L, -1); image::ImageData *id = luax_checktype<image::ImageData>(L, -1, IMAGE_IMAGE_DATA_ID); images.push_back(id); id->retain(); lua_pop(L, 1); } } else { for (int i = 2; i <= lua_gettop(L); i++) { convimagedata(L, i); image::ImageData *id = luax_checktype<image::ImageData>(L, i, IMAGE_IMAGE_DATA_ID); images.push_back(id); id->retain(); } } luax_catchexcept(L, [&]() { t = instance()->newBMFontRasterizer(d, images); }, [&](bool) { d->release(); for (auto id : images) id->release(); } ); luax_pushtype(L, FONT_RASTERIZER_ID, t); t->release(); return 1; }
int w_newGlyphData(lua_State *L) { Rasterizer *r = luax_checkrasterizer(L, 1); GlyphData *t = nullptr; // newGlyphData accepts a unicode character or a codepoint number. if (lua_type(L, 2) == LUA_TSTRING) { std::string glyph = luax_checkstring(L, 2); luax_catchexcept(L, [&](){ t = instance()->newGlyphData(r, glyph); }); } else { uint32 g = (uint32) luaL_checknumber(L, 2); t = instance()->newGlyphData(r, g); } luax_pushtype(L, FONT_GLYPH_DATA_ID, t); t->release(); return 1; }