wrap_Graphics.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507
  1. /**
  2. * Copyright (c) 2006-2014 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "wrap_Graphics.h"
  21. #include "OpenGL.h"
  22. #include "graphics/Texture.h"
  23. #include "image/ImageData.h"
  24. #include "image/Image.h"
  25. #include "font/Rasterizer.h"
  26. #include "filesystem/wrap_Filesystem.h"
  27. #include "scripts/graphics.lua.h"
  28. #include <cassert>
  29. namespace love
  30. {
  31. namespace graphics
  32. {
  33. namespace opengl
  34. {
  35. #define instance() (Module::getInstance<Graphics>(Module::M_GRAPHICS))
  36. int w_reset(lua_State *)
  37. {
  38. instance()->reset();
  39. return 0;
  40. }
  41. int w_clear(lua_State *)
  42. {
  43. instance()->clear();
  44. return 0;
  45. }
  46. int w_present(lua_State *)
  47. {
  48. instance()->present();
  49. return 0;
  50. }
  51. int w_isCreated(lua_State *L)
  52. {
  53. luax_pushboolean(L, instance()->isCreated());
  54. return 1;
  55. }
  56. int w_getWidth(lua_State *L)
  57. {
  58. lua_pushinteger(L, instance()->getWidth());
  59. return 1;
  60. }
  61. int w_getHeight(lua_State *L)
  62. {
  63. lua_pushinteger(L, instance()->getHeight());
  64. return 1;
  65. }
  66. int w_getDimensions(lua_State *L)
  67. {
  68. lua_pushinteger(L, instance()->getWidth());
  69. lua_pushinteger(L, instance()->getHeight());
  70. return 2;
  71. }
  72. int w_setScissor(lua_State *L)
  73. {
  74. int nargs = lua_gettop(L);
  75. if (nargs == 0 || (nargs == 4 && lua_isnil(L, 1) && lua_isnil(L, 2)
  76. && lua_isnil(L, 3) && lua_isnil(L, 4)))
  77. {
  78. instance()->setScissor();
  79. return 0;
  80. }
  81. int x = luaL_checkint(L, 1);
  82. int y = luaL_checkint(L, 2);
  83. int w = luaL_checkint(L, 3);
  84. int h = luaL_checkint(L, 4);
  85. if (w < 0 || h < 0)
  86. return luaL_error(L, "Can't set scissor with negative width and/or height.");
  87. instance()->setScissor(x, y, w, h);
  88. return 0;
  89. }
  90. int w_getScissor(lua_State *L)
  91. {
  92. int x, y, w, h;
  93. if (!instance()->getScissor(x, y, w, h))
  94. return 0;
  95. lua_pushinteger(L, x);
  96. lua_pushinteger(L, y);
  97. lua_pushinteger(L, w);
  98. lua_pushinteger(L, h);
  99. return 4;
  100. }
  101. static int setStencil(lua_State *L, bool invert)
  102. {
  103. // no argument -> clear stencil
  104. if (lua_isnoneornil(L, 1))
  105. {
  106. instance()->discardStencil();
  107. return 0;
  108. }
  109. luaL_checktype(L, 1, LUA_TFUNCTION);
  110. instance()->defineStencil();
  111. lua_call(L, lua_gettop(L) - 1, 0); // call stencil(...)
  112. instance()->useStencil(invert);
  113. return 0;
  114. }
  115. int w_setStencil(lua_State *L)
  116. {
  117. return setStencil(L, false);
  118. }
  119. int w_setInvertedStencil(lua_State *L)
  120. {
  121. return setStencil(L, true);
  122. }
  123. int w_getMaxTextureSize(lua_State *L)
  124. {
  125. lua_pushinteger(L, instance()->getSystemLimit(Graphics::LIMIT_TEXTURE_SIZE));
  126. return 1;
  127. }
  128. int w_newImage(lua_State *L)
  129. {
  130. love::image::ImageData *data = nullptr;
  131. love::image::CompressedData *cdata = nullptr;
  132. Image::Format format = Image::FORMAT_NORMAL;
  133. const char *fstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
  134. if (fstr != nullptr && !Image::getConstant(fstr, format))
  135. return luaL_error(L, "Invalid Image format: %s", fstr);
  136. bool releasedata = false;
  137. // Convert to ImageData / CompressedData, if necessary.
  138. if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
  139. {
  140. love::image::Image *image = Module::getInstance<love::image::Image>(Module::M_IMAGE);
  141. if (image == nullptr)
  142. return luaL_error(L, "Cannot load images without the love.image module.");
  143. love::filesystem::FileData *fdata = love::filesystem::luax_getfiledata(L, 1);
  144. if (image->isCompressed(fdata))
  145. {
  146. luax_catchexcept(L,
  147. [&]() { cdata = image->newCompressedData(fdata); },
  148. [&]() { fdata->release(); }
  149. );
  150. }
  151. else
  152. {
  153. luax_catchexcept(L,
  154. [&]() { data = image->newImageData(fdata); },
  155. [&]() { fdata->release(); }
  156. );
  157. }
  158. // Lua's GC won't release the image data, so we should do it ourselves.
  159. releasedata = true;
  160. }
  161. else if (luax_istype(L, 1, IMAGE_COMPRESSED_DATA_T))
  162. cdata = luax_checktype<love::image::CompressedData>(L, 1, "CompressedData", IMAGE_COMPRESSED_DATA_T);
  163. else
  164. data = luax_checktype<love::image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
  165. if (!data && !cdata)
  166. return luaL_error(L, "Error creating image (could not load data.)");
  167. // Create the image.
  168. Image *image = nullptr;
  169. luax_catchexcept(L,
  170. [&]() {
  171. if (cdata)
  172. image = instance()->newImage(cdata, format);
  173. else if (data)
  174. image = instance()->newImage(data, format);
  175. },
  176. [&]() {
  177. if (releasedata && data)
  178. data->release();
  179. else if (releasedata && cdata)
  180. cdata->release();
  181. }
  182. );
  183. if (image == nullptr)
  184. return luaL_error(L, "Could not load image.");
  185. // Push the type.
  186. luax_pushtype(L, "Image", GRAPHICS_IMAGE_T, image);
  187. return 1;
  188. }
  189. int w_newQuad(lua_State *L)
  190. {
  191. Quad::Viewport v;
  192. v.x = (float) luaL_checknumber(L, 1);
  193. v.y = (float) luaL_checknumber(L, 2);
  194. v.w = (float) luaL_checknumber(L, 3);
  195. v.h = (float) luaL_checknumber(L, 4);
  196. float sw = (float) luaL_checknumber(L, 5);
  197. float sh = (float) luaL_checknumber(L, 6);
  198. Quad *quad = instance()->newQuad(v, sw, sh);
  199. luax_pushtype(L, "Quad", GRAPHICS_QUAD_T, quad);
  200. return 1;
  201. }
  202. int w_newFont(lua_State *L)
  203. {
  204. // Convert to Rasterizer, if necessary.
  205. if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
  206. {
  207. int idxs[] = {1, 2};
  208. luax_convobj(L, idxs, 2, "font", "newRasterizer");
  209. }
  210. love::font::Rasterizer *rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
  211. Font *font = 0;
  212. luax_catchexcept(L, [&]() {
  213. font = instance()->newFont(rasterizer, instance()->getDefaultFilter()); }
  214. );
  215. if (font == 0)
  216. return luaL_error(L, "Could not load font.");
  217. // Push the type.
  218. luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
  219. return 1;
  220. }
  221. int w_newImageFont(lua_State *L)
  222. {
  223. // filter for glyphs
  224. Texture::Filter filter = instance()->getDefaultFilter();
  225. // Convert to ImageData if necessary.
  226. if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
  227. luax_convobj(L, 1, "image", "newImageData");
  228. else if (luax_istype(L, 1, GRAPHICS_IMAGE_T))
  229. {
  230. Image *i = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
  231. filter = i->getFilter();
  232. love::image::ImageData *id = i->getImageData();
  233. if (!id)
  234. return luaL_argerror(L, 1, "Image cannot be compressed.");
  235. luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, id, false);
  236. lua_replace(L, 1);
  237. }
  238. // Convert to Rasterizer if necessary.
  239. if (luax_istype(L, 1, IMAGE_IMAGE_DATA_T))
  240. {
  241. luaL_checkstring(L, 2);
  242. int idxs[] = {1, 2};
  243. luax_convobj(L, idxs, 2, "font", "newRasterizer");
  244. }
  245. love::font::Rasterizer *rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
  246. // Create the font.
  247. Font *font = instance()->newFont(rasterizer, filter);
  248. if (font == 0)
  249. return luaL_error(L, "Could not load font.");
  250. // Push the type.
  251. luax_pushtype(L, "Font", GRAPHICS_FONT_T, font);
  252. return 1;
  253. }
  254. int w_newSpriteBatch(lua_State *L)
  255. {
  256. Texture *texture = luax_checktexture(L, 1);
  257. int size = luaL_optint(L, 2, 1000);
  258. SpriteBatch::UsageHint usage = SpriteBatch::USAGE_DYNAMIC;
  259. if (lua_gettop(L) > 2)
  260. {
  261. const char *usagestr = luaL_checkstring(L, 3);
  262. if (!SpriteBatch::getConstant(usagestr, usage))
  263. return luaL_error(L, "Invalid SpriteBatch usage hint: %s", usagestr);
  264. }
  265. SpriteBatch *t = nullptr;
  266. luax_catchexcept(L,
  267. [&](){ t = instance()->newSpriteBatch(texture, size, usage); }
  268. );
  269. luax_pushtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, t);
  270. return 1;
  271. }
  272. int w_newParticleSystem(lua_State *L)
  273. {
  274. Texture *texture = luax_checktexture(L, 1);
  275. lua_Number size = luaL_optnumber(L, 2, 1000);
  276. ParticleSystem *t = 0;
  277. if (size < 1.0 || size > ParticleSystem::MAX_PARTICLES)
  278. return luaL_error(L, "Invalid ParticleSystem size");
  279. luax_catchexcept(L,
  280. [&](){ t = instance()->newParticleSystem(texture, int(size)); }
  281. );
  282. luax_pushtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, t);
  283. return 1;
  284. }
  285. int w_newCanvas(lua_State *L)
  286. {
  287. // check if width and height are given. else default to screen dimensions.
  288. int width = luaL_optint(L, 1, instance()->getWidth());
  289. int height = luaL_optint(L, 2, instance()->getHeight());
  290. const char *str = luaL_optstring(L, 3, "normal");
  291. int msaa = luaL_optint(L, 4, 0);
  292. Canvas::Format format;
  293. if (!Canvas::getConstant(str, format))
  294. return luaL_error(L, "Invalid Canvas format: %s", str);
  295. Canvas *canvas = nullptr;
  296. luax_catchexcept(L,
  297. [&](){ canvas = instance()->newCanvas(width, height, format, msaa); }
  298. );
  299. if (canvas == nullptr)
  300. return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
  301. luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
  302. return 1;
  303. }
  304. int w_newShader(lua_State *L)
  305. {
  306. if (!Shader::isSupported())
  307. return luaL_error(L, "Sorry, your graphics card does not support shaders.");
  308. // clamp stack to 2 elements
  309. lua_settop(L, 2);
  310. // read any filepath arguments
  311. for (int i = 1; i <= 2; i++)
  312. {
  313. if (!lua_isstring(L, i))
  314. continue;
  315. // call love.filesystem.isFile(arg_i)
  316. luax_getfunction(L, "filesystem", "isFile");
  317. lua_pushvalue(L, i);
  318. lua_call(L, 1, 1);
  319. bool isFile = luax_toboolean(L, -1);
  320. lua_pop(L, 1);
  321. if (isFile)
  322. {
  323. luax_getfunction(L, "filesystem", "read");
  324. lua_pushvalue(L, i);
  325. lua_call(L, 1, 1);
  326. lua_replace(L, i);
  327. }
  328. }
  329. bool has_arg1 = lua_isstring(L, 1);
  330. bool has_arg2 = lua_isstring(L, 2);
  331. // require at least one string argument
  332. if (!(has_arg1 || has_arg2))
  333. luaL_checkstring(L, 1);
  334. luax_getfunction(L, "graphics", "_shaderCodeToGLSL");
  335. // push vertexcode and pixelcode strings to the top of the stack
  336. lua_pushvalue(L, 1);
  337. lua_pushvalue(L, 2);
  338. // call effectCodeToGLSL, returned values will be at the top of the stack
  339. if (lua_pcall(L, 2, 2, 0) != 0)
  340. return luaL_error(L, "%s", lua_tostring(L, -1));
  341. Shader::ShaderSources sources;
  342. // vertex shader code
  343. if (lua_isstring(L, -2))
  344. {
  345. std::string vertexcode(luaL_checkstring(L, -2));
  346. sources[Shader::TYPE_VERTEX] = vertexcode;
  347. }
  348. else if (has_arg1 && has_arg2)
  349. return luaL_error(L, "Could not parse vertex shader code (missing 'position' function?)");
  350. // pixel shader code
  351. if (lua_isstring(L, -1))
  352. {
  353. std::string pixelcode(luaL_checkstring(L, -1));
  354. sources[Shader::TYPE_PIXEL] = pixelcode;
  355. }
  356. else if (has_arg1 && has_arg2)
  357. return luaL_error(L, "Could not parse pixel shader code (missing 'effect' function?)");
  358. if (sources.empty())
  359. {
  360. // Original args had source code, but effectCodeToGLSL couldn't translate it
  361. for (int i = 1; i <= 2; i++)
  362. {
  363. if (lua_isstring(L, i))
  364. return luaL_argerror(L, i, "missing 'position' or 'effect' function?");
  365. }
  366. }
  367. bool should_error = false;
  368. try
  369. {
  370. Shader *shader = instance()->newShader(sources);
  371. luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
  372. }
  373. catch (love::Exception &e)
  374. {
  375. luax_getfunction(L, "graphics", "_transformGLSLErrorMessages");
  376. lua_pushstring(L, e.what());
  377. // Function pushes the new error string onto the stack.
  378. lua_pcall(L, 1, 1, 0);
  379. should_error = true;
  380. }
  381. if (should_error)
  382. return lua_error(L);
  383. return 1;
  384. }
  385. int w_newMesh(lua_State *L)
  386. {
  387. // Check first argument: table of vertices or number of vertices.
  388. int ttype = lua_type(L, 1);
  389. if (ttype != LUA_TTABLE && ttype != LUA_TNUMBER)
  390. luaL_argerror(L, 1, "table or number expected");
  391. // Second argument: optional texture.
  392. Texture *tex = nullptr;
  393. if (!lua_isnoneornil(L, 2))
  394. tex = luax_checktexture(L, 2);
  395. // Third argument: optional draw mode.
  396. const char *str = 0;
  397. Mesh::DrawMode mode = Mesh::DRAW_MODE_FAN;
  398. str = lua_isnoneornil(L, 3) ? 0 : luaL_checkstring(L, 3);
  399. if (str && !Mesh::getConstant(str, mode))
  400. return luaL_error(L, "Invalid mesh draw mode: %s", str);
  401. Mesh *t = nullptr;
  402. if (ttype == LUA_TTABLE)
  403. {
  404. size_t vertex_count = lua_objlen(L, 1);
  405. std::vector<Vertex> vertices;
  406. vertices.reserve(vertex_count);
  407. bool use_colors = false;
  408. // Get the vertices from the table.
  409. for (size_t i = 1; i <= vertex_count; i++)
  410. {
  411. lua_rawgeti(L, 1, i);
  412. if (lua_type(L, -1) != LUA_TTABLE)
  413. return luax_typerror(L, 1, "table of tables");
  414. for (int j = 1; j <= 8; j++)
  415. lua_rawgeti(L, -j, j);
  416. Vertex v;
  417. v.x = (float) luaL_checknumber(L, -8);
  418. v.y = (float) luaL_checknumber(L, -7);
  419. v.s = (float) luaL_optnumber(L, -6, 0.0);
  420. v.t = (float) luaL_optnumber(L, -5, 0.0);
  421. v.r = (unsigned char) luaL_optinteger(L, -4, 255);
  422. v.g = (unsigned char) luaL_optinteger(L, -3, 255);
  423. v.b = (unsigned char) luaL_optinteger(L, -2, 255);
  424. v.a = (unsigned char) luaL_optinteger(L, -1, 255);
  425. // Enable per-vertex coloring if any color is not the default.
  426. if (!use_colors && (v.r != 255 || v.g != 255 || v.b != 255 || v.a != 255))
  427. use_colors = true;
  428. lua_pop(L, 9);
  429. vertices.push_back(v);
  430. }
  431. luax_catchexcept(L, [&](){ t = instance()->newMesh(vertices, mode); });
  432. t->setVertexColors(use_colors);
  433. }
  434. else
  435. {
  436. int count = luaL_checkint(L, 1);
  437. luax_catchexcept(L, [&](){ t = instance()->newMesh(count, mode); });
  438. }
  439. if (tex)
  440. t->setTexture(tex);
  441. luax_pushtype(L, "Mesh", GRAPHICS_MESH_T, t);
  442. return 1;
  443. }
  444. int w_setColor(lua_State *L)
  445. {
  446. Color c;
  447. if (lua_istable(L, 1))
  448. {
  449. for (int i = 1; i <= 4; i++)
  450. lua_rawgeti(L, 1, i);
  451. c.r = (unsigned char)luaL_checkint(L, -4);
  452. c.g = (unsigned char)luaL_checkint(L, -3);
  453. c.b = (unsigned char)luaL_checkint(L, -2);
  454. c.a = (unsigned char)luaL_optint(L, -1, 255);
  455. lua_pop(L, 4);
  456. }
  457. else
  458. {
  459. c.r = (unsigned char)luaL_checkint(L, 1);
  460. c.g = (unsigned char)luaL_checkint(L, 2);
  461. c.b = (unsigned char)luaL_checkint(L, 3);
  462. c.a = (unsigned char)luaL_optint(L, 4, 255);
  463. }
  464. instance()->setColor(c);
  465. return 0;
  466. }
  467. int w_getColor(lua_State *L)
  468. {
  469. Color c = instance()->getColor();
  470. lua_pushinteger(L, c.r);
  471. lua_pushinteger(L, c.g);
  472. lua_pushinteger(L, c.b);
  473. lua_pushinteger(L, c.a);
  474. return 4;
  475. }
  476. int w_setBackgroundColor(lua_State *L)
  477. {
  478. Color c;
  479. if (lua_istable(L, 1))
  480. {
  481. for (int i = 1; i <= 4; i++)
  482. lua_rawgeti(L, 1, i);
  483. c.r = (unsigned char)luaL_checkint(L, -4);
  484. c.g = (unsigned char)luaL_checkint(L, -3);
  485. c.b = (unsigned char)luaL_checkint(L, -2);
  486. c.a = (unsigned char)luaL_optint(L, -1, 255);
  487. lua_pop(L, 4);
  488. }
  489. else
  490. {
  491. c.r = (unsigned char)luaL_checkint(L, 1);
  492. c.g = (unsigned char)luaL_checkint(L, 2);
  493. c.b = (unsigned char)luaL_checkint(L, 3);
  494. c.a = (unsigned char)luaL_optint(L, 4, 255);
  495. }
  496. instance()->setBackgroundColor(c);
  497. return 0;
  498. }
  499. int w_getBackgroundColor(lua_State *L)
  500. {
  501. Color c = instance()->getBackgroundColor();
  502. lua_pushinteger(L, c.r);
  503. lua_pushinteger(L, c.g);
  504. lua_pushinteger(L, c.b);
  505. lua_pushinteger(L, c.a);
  506. return 4;
  507. }
  508. int w_setFont(lua_State *L)
  509. {
  510. Font *font = luax_checktype<Font>(L, 1, "Font", GRAPHICS_FONT_T);
  511. instance()->setFont(font);
  512. return 0;
  513. }
  514. int w_getFont(lua_State *L)
  515. {
  516. Font *f = instance()->getFont();
  517. if (f == 0)
  518. return 0;
  519. f->retain();
  520. luax_pushtype(L, "Font", GRAPHICS_FONT_T, f);
  521. return 1;
  522. }
  523. int w_setColorMask(lua_State *L)
  524. {
  525. bool mask[4];
  526. if (lua_gettop(L) <= 1 && lua_isnoneornil(L, 1))
  527. {
  528. // Enable all color components if no argument is given.
  529. mask[0] = mask[1] = mask[2] = mask[3] = true;
  530. }
  531. else
  532. {
  533. for (int i = 0; i < 4; i++)
  534. mask[i] = luax_toboolean(L, i + 1);
  535. }
  536. instance()->setColorMask(mask);
  537. return 0;
  538. }
  539. int w_getColorMask(lua_State *L)
  540. {
  541. const bool *mask = instance()->getColorMask();
  542. for (int i = 0; i < 4; i++)
  543. luax_pushboolean(L, mask[i]);
  544. return 4;
  545. }
  546. int w_setBlendMode(lua_State *L)
  547. {
  548. Graphics::BlendMode mode;
  549. const char *str = luaL_checkstring(L, 1);
  550. if (!Graphics::getConstant(str, mode))
  551. return luaL_error(L, "Invalid blend mode: %s", str);
  552. luax_catchexcept(L, [&](){ instance()->setBlendMode(mode); });
  553. return 0;
  554. }
  555. int w_getBlendMode(lua_State *L)
  556. {
  557. const char *str;
  558. Graphics::BlendMode mode;
  559. luax_catchexcept(L, [&](){ mode = instance()->getBlendMode(); });
  560. if (!Graphics::getConstant(mode, str))
  561. return luaL_error(L, "Unknown blend mode");
  562. lua_pushstring(L, str);
  563. return 1;
  564. }
  565. int w_setDefaultFilter(lua_State *L)
  566. {
  567. Texture::FilterMode min;
  568. Texture::FilterMode mag;
  569. const char *minstr = luaL_checkstring(L, 1);
  570. const char *magstr = luaL_optstring(L, 2, minstr);
  571. if (!Texture::getConstant(minstr, min))
  572. return luaL_error(L, "Invalid filter mode: %s", minstr);
  573. if (!Texture::getConstant(magstr, mag))
  574. return luaL_error(L, "Invalid filter mode: %s", magstr);
  575. float anisotropy = (float) luaL_optnumber(L, 3, 1.0);
  576. Texture::Filter f;
  577. f.min = min;
  578. f.mag = mag;
  579. f.anisotropy = anisotropy;
  580. instance()->setDefaultFilter(f);
  581. return 0;
  582. }
  583. int w_getDefaultFilter(lua_State *L)
  584. {
  585. const Texture::Filter &f = instance()->getDefaultFilter();
  586. const char *minstr;
  587. const char *magstr;
  588. if (!Texture::getConstant(f.min, minstr))
  589. return luaL_error(L, "Unknown minification filter mode");
  590. if (!Texture::getConstant(f.mag, magstr))
  591. return luaL_error(L, "Unknown magnification filter mode");
  592. lua_pushstring(L, minstr);
  593. lua_pushstring(L, magstr);
  594. lua_pushnumber(L, f.anisotropy);
  595. return 3;
  596. }
  597. int w_setDefaultMipmapFilter(lua_State *L)
  598. {
  599. Texture::FilterMode filter = Texture::FILTER_NONE;
  600. if (!lua_isnoneornil(L, 1))
  601. {
  602. const char *str = luaL_checkstring(L, 1);
  603. if (!Texture::getConstant(str, filter))
  604. return luaL_error(L, "Invalid filter mode: %s", str);
  605. }
  606. float sharpness = (float) luaL_optnumber(L, 2, 0);
  607. instance()->setDefaultMipmapFilter(filter, sharpness);
  608. return 0;
  609. }
  610. int w_getDefaultMipmapFilter(lua_State *L)
  611. {
  612. Texture::FilterMode filter;
  613. float sharpness;
  614. instance()->getDefaultMipmapFilter(&filter, &sharpness);
  615. const char *str;
  616. if (Texture::getConstant(filter, str))
  617. lua_pushstring(L, str);
  618. else
  619. lua_pushnil(L);
  620. lua_pushnumber(L, sharpness);
  621. return 2;
  622. }
  623. int w_setLineWidth(lua_State *L)
  624. {
  625. float width = (float)luaL_checknumber(L, 1);
  626. instance()->setLineWidth(width);
  627. return 0;
  628. }
  629. int w_setLineStyle(lua_State *L)
  630. {
  631. Graphics::LineStyle style;
  632. const char *str = luaL_checkstring(L, 1);
  633. if (!Graphics::getConstant(str, style))
  634. return luaL_error(L, "Invalid line style: %s", str);
  635. instance()->setLineStyle(style);
  636. return 0;
  637. }
  638. int w_setLineJoin(lua_State *L)
  639. {
  640. Graphics::LineJoin join;
  641. const char *str = luaL_checkstring(L, 1);
  642. if (!Graphics::getConstant(str, join))
  643. return luaL_error(L, "Invalid line join mode: %s", str);
  644. instance()->setLineJoin(join);
  645. return 0;
  646. }
  647. int w_getLineWidth(lua_State *L)
  648. {
  649. lua_pushnumber(L, instance()->getLineWidth());
  650. return 1;
  651. }
  652. int w_getLineStyle(lua_State *L)
  653. {
  654. Graphics::LineStyle style = instance()->getLineStyle();
  655. const char *str;
  656. if (!Graphics::getConstant(style, str))
  657. return luaL_error(L, "Unknown line style");
  658. lua_pushstring(L, str);
  659. return 1;
  660. }
  661. int w_getLineJoin(lua_State *L)
  662. {
  663. Graphics::LineJoin join = instance()->getLineJoin();
  664. const char *str;
  665. if (!Graphics::getConstant(join, str))
  666. return luaL_error(L, "Unknown line join");
  667. lua_pushstring(L, str);
  668. return 1;
  669. }
  670. int w_setPointSize(lua_State *L)
  671. {
  672. float size = (float)luaL_checknumber(L, 1);
  673. instance()->setPointSize(size);
  674. return 0;
  675. }
  676. int w_setPointStyle(lua_State *L)
  677. {
  678. Graphics::PointStyle style;
  679. const char *str = luaL_checkstring(L, 1);
  680. if (!Graphics::getConstant(str, style))
  681. return luaL_error(L, "Invalid point style: %s", str);
  682. instance()->setPointStyle(style);
  683. return 0;
  684. }
  685. int w_getPointSize(lua_State *L)
  686. {
  687. lua_pushnumber(L, instance()->getPointSize());
  688. return 1;
  689. }
  690. int w_getPointStyle(lua_State *L)
  691. {
  692. Graphics::PointStyle style = instance()->getPointStyle();
  693. const char *str;
  694. if (!Graphics::getConstant(style, str))
  695. return luaL_error(L, "Unknown point style");
  696. lua_pushstring(L, str);
  697. return 1;
  698. }
  699. int w_getMaxPointSize(lua_State *L)
  700. {
  701. lua_pushnumber(L, instance()->getSystemLimit(Graphics::LIMIT_POINT_SIZE));
  702. return 1;
  703. }
  704. int w_setWireframe(lua_State *L)
  705. {
  706. instance()->setWireframe(luax_toboolean(L, 1));
  707. return 0;
  708. }
  709. int w_isWireframe(lua_State *L)
  710. {
  711. luax_pushboolean(L, instance()->isWireframe());
  712. return 1;
  713. }
  714. int w_newScreenshot(lua_State *L)
  715. {
  716. love::image::Image *image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
  717. bool copyAlpha = luax_optboolean(L, 1, false);
  718. love::image::ImageData *i = 0;
  719. luax_catchexcept(L, [&](){ i = instance()->newScreenshot(image, copyAlpha); });
  720. luax_pushtype(L, "ImageData", IMAGE_IMAGE_DATA_T, i);
  721. return 1;
  722. }
  723. int w_setCanvas(lua_State *L)
  724. {
  725. // discard stencil testing
  726. instance()->discardStencil();
  727. // called with none -> reset to default buffer
  728. if (lua_isnoneornil(L, 1))
  729. {
  730. instance()->setCanvas();
  731. return 0;
  732. }
  733. bool is_table = lua_istable(L, 1);
  734. std::vector<Canvas *> canvases;
  735. if (is_table)
  736. {
  737. for (size_t i = 1; i <= lua_objlen(L, 1); i++)
  738. {
  739. lua_rawgeti(L, 1, i);
  740. canvases.push_back(luax_checkcanvas(L, -1));
  741. lua_pop(L, 1);
  742. }
  743. }
  744. else
  745. {
  746. for (int i = 1; i <= lua_gettop(L); i++)
  747. canvases.push_back(luax_checkcanvas(L, i));
  748. }
  749. luax_catchexcept(L, [&]() {
  750. if (canvases.size() > 0)
  751. instance()->setCanvas(canvases);
  752. else
  753. instance()->setCanvas();
  754. });
  755. return 0;
  756. }
  757. int w_getCanvas(lua_State *L)
  758. {
  759. const std::vector<Canvas *> canvases = instance()->getCanvas();
  760. int n = 0;
  761. if (!canvases.empty())
  762. {
  763. for (Canvas *c : canvases)
  764. {
  765. c->retain();
  766. luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, c);
  767. n++;
  768. }
  769. }
  770. else
  771. {
  772. lua_pushnil(L);
  773. n = 1;
  774. }
  775. return n;
  776. }
  777. int w_setShader(lua_State *L)
  778. {
  779. if (lua_isnoneornil(L,1))
  780. {
  781. instance()->setShader();
  782. return 0;
  783. }
  784. Shader *shader = luax_checkshader(L, 1);
  785. instance()->setShader(shader);
  786. return 0;
  787. }
  788. int w_getShader(lua_State *L)
  789. {
  790. Shader *shader = instance()->getShader();
  791. if (shader)
  792. {
  793. shader->retain();
  794. luax_pushtype(L, "Shader", GRAPHICS_SHADER_T, shader);
  795. }
  796. else
  797. lua_pushnil(L);
  798. return 1;
  799. }
  800. int w_isSupported(lua_State *L)
  801. {
  802. bool supported = true;
  803. for (int i = 1; i <= lua_gettop(L); i++)
  804. {
  805. const char *str = luaL_checkstring(L, i);
  806. Graphics::Support feature;
  807. if (!Graphics::getConstant(str, feature))
  808. return luaL_error(L, "Invalid graphics feature: %s", str);
  809. if (!instance()->isSupported(feature))
  810. {
  811. supported = false;
  812. break;
  813. }
  814. }
  815. luax_pushboolean(L, supported);
  816. return 1;
  817. }
  818. int w_getCanvasFormats(lua_State *L)
  819. {
  820. lua_createtable(L, 0, (int) Canvas::FORMAT_MAX_ENUM);
  821. for (int i = 0; i < (int) Canvas::FORMAT_MAX_ENUM; i++)
  822. {
  823. Canvas::Format format = (Canvas::Format) i;
  824. const char *name = nullptr;
  825. if (!Canvas::getConstant(format, name))
  826. continue;
  827. luax_pushboolean(L, Canvas::isFormatSupported(format));
  828. lua_setfield(L, -2, name);
  829. }
  830. return 1;
  831. }
  832. int w_getCompressedImageFormats(lua_State *L)
  833. {
  834. lua_createtable(L, 0, (int) image::CompressedData::FORMAT_MAX_ENUM);
  835. for (int i = 0; i < (int) image::CompressedData::FORMAT_MAX_ENUM; i++)
  836. {
  837. image::CompressedData::Format format = (image::CompressedData::Format) i;
  838. const char *name = nullptr;
  839. if (format == image::CompressedData::FORMAT_UNKNOWN)
  840. continue;
  841. if (!image::CompressedData::getConstant(format, name))
  842. continue;
  843. luax_pushboolean(L, Image::hasCompressedTextureSupport(format));
  844. lua_setfield(L, -2, name);
  845. }
  846. return 1;
  847. }
  848. int w_getRendererInfo(lua_State *L)
  849. {
  850. Graphics::RendererInfo info;
  851. luax_catchexcept(L, [&](){ info = instance()->getRendererInfo(); });
  852. luax_pushstring(L, info.name);
  853. luax_pushstring(L, info.version);
  854. luax_pushstring(L, info.vendor);
  855. luax_pushstring(L, info.device);
  856. return 4;
  857. }
  858. int w_getSystemLimit(lua_State *L)
  859. {
  860. const char *limitstr = luaL_checkstring(L, 1);
  861. Graphics::SystemLimit limittype;
  862. if (!Graphics::getConstant(limitstr, limittype))
  863. return luaL_error(L, "Invalid system limit type: %s", limitstr);
  864. lua_pushnumber(L, instance()->getSystemLimit(limittype));
  865. return 1;
  866. }
  867. int w_draw(lua_State *L)
  868. {
  869. Drawable *drawable = nullptr;
  870. Texture *texture = nullptr;
  871. Quad *quad = nullptr;
  872. int startidx = 2;
  873. if (luax_istype(L, 2, GRAPHICS_QUAD_T))
  874. {
  875. texture = luax_checktexture(L, 1);
  876. quad = luax_totype<Quad>(L, 2, "Quad", GRAPHICS_QUAD_T);
  877. startidx = 3;
  878. }
  879. else if (lua_isnil(L, 2) && !lua_isnoneornil(L, 3))
  880. {
  881. return luax_typerror(L, 2, "Quad");
  882. }
  883. else
  884. {
  885. drawable = luax_checktype<Drawable>(L, 1, "Drawable", GRAPHICS_DRAWABLE_T);
  886. startidx = 2;
  887. }
  888. float x = (float) luaL_optnumber(L, startidx + 0, 0.0);
  889. float y = (float) luaL_optnumber(L, startidx + 1, 0.0);
  890. float a = (float) luaL_optnumber(L, startidx + 2, 0.0);
  891. float sx = (float) luaL_optnumber(L, startidx + 3, 1.0);
  892. float sy = (float) luaL_optnumber(L, startidx + 4, sx);
  893. float ox = (float) luaL_optnumber(L, startidx + 5, 0.0);
  894. float oy = (float) luaL_optnumber(L, startidx + 6, 0.0);
  895. float kx = (float) luaL_optnumber(L, startidx + 7, 0.0);
  896. float ky = (float) luaL_optnumber(L, startidx + 8, 0.0);
  897. if (texture && quad)
  898. texture->drawq(quad, x, y, a, sx, sy, ox, oy, kx, ky);
  899. else if (drawable)
  900. drawable->draw(x, y, a, sx, sy, ox, oy, kx, ky);
  901. return 0;
  902. }
  903. int w_print(lua_State *L)
  904. {
  905. std::string str = luax_checkstring(L, 1);
  906. float x = (float)luaL_optnumber(L, 2, 0.0);
  907. float y = (float)luaL_optnumber(L, 3, 0.0);
  908. float angle = (float)luaL_optnumber(L, 4, 0.0f);
  909. float sx = (float)luaL_optnumber(L, 5, 1.0f);
  910. float sy = (float)luaL_optnumber(L, 6, sx);
  911. float ox = (float)luaL_optnumber(L, 7, 0.0f);
  912. float oy = (float)luaL_optnumber(L, 8, 0.0f);
  913. float kx = (float)luaL_optnumber(L, 9, 0.0f);
  914. float ky = (float)luaL_optnumber(L, 10, 0.0f);
  915. luax_catchexcept(L,
  916. [&](){ instance()->print(str, x, y, angle, sx, sy, ox, oy, kx,ky); }
  917. );
  918. return 0;
  919. }
  920. int w_printf(lua_State *L)
  921. {
  922. std::string str = luax_checkstring(L, 1);
  923. float x = (float)luaL_checknumber(L, 2);
  924. float y = (float)luaL_checknumber(L, 3);
  925. float wrap = (float)luaL_checknumber(L, 4);
  926. float angle = 0.0f;
  927. float sx = 1.0f, sy = 1.0f;
  928. float ox = 0.0f, oy = 0.0f;
  929. float kx = 0.0f, ky = 0.0f;
  930. Graphics::AlignMode align = Graphics::ALIGN_LEFT;
  931. if (lua_gettop(L) >= 5)
  932. {
  933. if (!lua_isnil(L, 5))
  934. {
  935. const char *str = luaL_checkstring(L, 5);
  936. if (!Graphics::getConstant(str, align))
  937. return luaL_error(L, "Incorrect alignment: %s", str);
  938. }
  939. angle = (float) luaL_optnumber(L, 6, 0.0f);
  940. sx = (float) luaL_optnumber(L, 7, 1.0f);
  941. sy = (float) luaL_optnumber(L, 8, sx);
  942. ox = (float) luaL_optnumber(L, 9, 0.0f);
  943. oy = (float) luaL_optnumber(L, 10, 0.0f);
  944. kx = (float) luaL_optnumber(L, 11, 0.0f);
  945. ky = (float) luaL_optnumber(L, 12, 0.0f);
  946. }
  947. luax_catchexcept(L,
  948. [&](){ instance()->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky); }
  949. );
  950. return 0;
  951. }
  952. int w_point(lua_State *L)
  953. {
  954. float x = (float)luaL_checknumber(L, 1);
  955. float y = (float)luaL_checknumber(L, 2);
  956. instance()->point(x, y);
  957. return 0;
  958. }
  959. int w_line(lua_State *L)
  960. {
  961. int args = lua_gettop(L);
  962. bool is_table = false;
  963. if (args == 1 && lua_istable(L, 1))
  964. {
  965. args = lua_objlen(L, 1);
  966. is_table = true;
  967. }
  968. if (args % 2 != 0)
  969. return luaL_error(L, "Number of vertex components must be a multiple of two");
  970. else if (args < 4)
  971. return luaL_error(L, "Need at least two vertices to draw a line");
  972. float *coords = new float[args];
  973. if (is_table)
  974. {
  975. for (int i = 0; i < args; ++i)
  976. {
  977. lua_rawgeti(L, 1, i + 1);
  978. coords[i] = luax_tofloat(L, -1);
  979. lua_pop(L, 1);
  980. }
  981. }
  982. else
  983. {
  984. for (int i = 0; i < args; ++i)
  985. coords[i] = luax_tofloat(L, i + 1);
  986. }
  987. instance()->polyline(coords, args);
  988. delete[] coords;
  989. return 0;
  990. }
  991. int w_rectangle(lua_State *L)
  992. {
  993. Graphics::DrawMode mode;
  994. const char *str = luaL_checkstring(L, 1);
  995. if (!Graphics::getConstant(str, mode))
  996. return luaL_error(L, "Incorrect draw mode %s", str);
  997. float x = (float)luaL_checknumber(L, 2);
  998. float y = (float)luaL_checknumber(L, 3);
  999. float w = (float)luaL_checknumber(L, 4);
  1000. float h = (float)luaL_checknumber(L, 5);
  1001. instance()->rectangle(mode, x, y, w, h);
  1002. return 0;
  1003. }
  1004. int w_circle(lua_State *L)
  1005. {
  1006. Graphics::DrawMode mode;
  1007. const char *str = luaL_checkstring(L, 1);
  1008. if (!Graphics::getConstant(str, mode))
  1009. return luaL_error(L, "Incorrect draw mode %s", str);
  1010. float x = (float)luaL_checknumber(L, 2);
  1011. float y = (float)luaL_checknumber(L, 3);
  1012. float radius = (float)luaL_checknumber(L, 4);
  1013. int points;
  1014. if (lua_isnoneornil(L, 5))
  1015. points = radius > 10 ? (int)(radius) : 10;
  1016. else
  1017. points = luaL_checkint(L, 5);
  1018. instance()->circle(mode, x, y, radius, points);
  1019. return 0;
  1020. }
  1021. int w_arc(lua_State *L)
  1022. {
  1023. Graphics::DrawMode mode;
  1024. const char *str = luaL_checkstring(L, 1);
  1025. if (!Graphics::getConstant(str, mode))
  1026. return luaL_error(L, "Incorrect draw mode %s", str);
  1027. float x = (float)luaL_checknumber(L, 2);
  1028. float y = (float)luaL_checknumber(L, 3);
  1029. float radius = (float)luaL_checknumber(L, 4);
  1030. float angle1 = (float)luaL_checknumber(L, 5);
  1031. float angle2 = (float)luaL_checknumber(L, 6);
  1032. int points;
  1033. if (lua_isnoneornil(L, 7))
  1034. points = radius > 10 ? (int)(radius) : 10;
  1035. else
  1036. points = luaL_checkint(L, 7);
  1037. instance()->arc(mode, x, y, radius, angle1, angle2, points);
  1038. return 0;
  1039. }
  1040. int w_polygon(lua_State *L)
  1041. {
  1042. int args = lua_gettop(L) - 1;
  1043. Graphics::DrawMode mode;
  1044. const char *str = luaL_checkstring(L, 1);
  1045. if (!Graphics::getConstant(str, mode))
  1046. return luaL_error(L, "Invalid draw mode: %s", str);
  1047. bool is_table = false;
  1048. float *coords;
  1049. if (args == 1 && lua_istable(L, 2))
  1050. {
  1051. args = lua_objlen(L, 2);
  1052. is_table = true;
  1053. }
  1054. if (args % 2 != 0)
  1055. return luaL_error(L, "Number of vertex components must be a multiple of two");
  1056. else if (args < 6)
  1057. return luaL_error(L, "Need at least three vertices to draw a polygon");
  1058. // fetch coords
  1059. coords = new float[args + 2];
  1060. if (is_table)
  1061. {
  1062. for (int i = 0; i < args; ++i)
  1063. {
  1064. lua_rawgeti(L, 2, i + 1);
  1065. coords[i] = luax_tofloat(L, -1);
  1066. lua_pop(L, 1);
  1067. }
  1068. }
  1069. else
  1070. {
  1071. for (int i = 0; i < args; ++i)
  1072. coords[i] = luax_tofloat(L, i + 2);
  1073. }
  1074. // make a closed loop
  1075. coords[args] = coords[0];
  1076. coords[args+1] = coords[1];
  1077. instance()->polygon(mode, coords, args+2);
  1078. delete[] coords;
  1079. return 0;
  1080. }
  1081. int w_push(lua_State *L)
  1082. {
  1083. Graphics::StackType stype = Graphics::STACK_TRANSFORM;
  1084. const char *sname = lua_isnoneornil(L, 1) ? nullptr : luaL_checkstring(L, 1);
  1085. if (sname && !Graphics::getConstant(sname, stype))
  1086. return luaL_error(L, "Invalid graphics stack type: %s", sname);
  1087. luax_catchexcept(L, [&](){ instance()->push(stype); });
  1088. return 0;
  1089. }
  1090. int w_pop(lua_State *L)
  1091. {
  1092. luax_catchexcept(L, [&](){ instance()->pop(); });
  1093. return 0;
  1094. }
  1095. int w_rotate(lua_State *L)
  1096. {
  1097. float angle = (float)luaL_checknumber(L, 1);
  1098. instance()->rotate(angle);
  1099. return 0;
  1100. }
  1101. int w_scale(lua_State *L)
  1102. {
  1103. float sx = (float)luaL_optnumber(L, 1, 1.0f);
  1104. float sy = (float)luaL_optnumber(L, 2, sx);
  1105. instance()->scale(sx, sy);
  1106. return 0;
  1107. }
  1108. int w_translate(lua_State *L)
  1109. {
  1110. float x = (float)luaL_checknumber(L, 1);
  1111. float y = (float)luaL_checknumber(L, 2);
  1112. instance()->translate(x, y);
  1113. return 0;
  1114. }
  1115. int w_shear(lua_State *L)
  1116. {
  1117. float kx = (float)luaL_checknumber(L, 1);
  1118. float ky = (float)luaL_checknumber(L, 2);
  1119. instance()->shear(kx, ky);
  1120. return 0;
  1121. }
  1122. int w_origin(lua_State * /*L*/)
  1123. {
  1124. instance()->origin();
  1125. return 0;
  1126. }
  1127. // List of functions to wrap.
  1128. static const luaL_Reg functions[] =
  1129. {
  1130. { "reset", w_reset },
  1131. { "clear", w_clear },
  1132. { "present", w_present },
  1133. { "newImage", w_newImage },
  1134. { "newQuad", w_newQuad },
  1135. { "newFont", w_newFont },
  1136. { "newImageFont", w_newImageFont },
  1137. { "newSpriteBatch", w_newSpriteBatch },
  1138. { "newParticleSystem", w_newParticleSystem },
  1139. { "newCanvas", w_newCanvas },
  1140. { "newShader", w_newShader },
  1141. { "newMesh", w_newMesh },
  1142. { "setColor", w_setColor },
  1143. { "getColor", w_getColor },
  1144. { "setBackgroundColor", w_setBackgroundColor },
  1145. { "getBackgroundColor", w_getBackgroundColor },
  1146. { "setFont", w_setFont },
  1147. { "getFont", w_getFont },
  1148. { "setColorMask", w_setColorMask },
  1149. { "getColorMask", w_getColorMask },
  1150. { "setBlendMode", w_setBlendMode },
  1151. { "getBlendMode", w_getBlendMode },
  1152. { "setDefaultFilter", w_setDefaultFilter },
  1153. { "getDefaultFilter", w_getDefaultFilter },
  1154. { "setDefaultMipmapFilter", w_setDefaultMipmapFilter },
  1155. { "getDefaultMipmapFilter", w_getDefaultMipmapFilter },
  1156. { "setLineWidth", w_setLineWidth },
  1157. { "setLineStyle", w_setLineStyle },
  1158. { "setLineJoin", w_setLineJoin },
  1159. { "getLineWidth", w_getLineWidth },
  1160. { "getLineStyle", w_getLineStyle },
  1161. { "getLineJoin", w_getLineJoin },
  1162. { "setPointSize", w_setPointSize },
  1163. { "setPointStyle", w_setPointStyle },
  1164. { "getPointSize", w_getPointSize },
  1165. { "getPointStyle", w_getPointStyle },
  1166. { "setWireframe", w_setWireframe },
  1167. { "isWireframe", w_isWireframe },
  1168. { "newScreenshot", w_newScreenshot },
  1169. { "setCanvas", w_setCanvas },
  1170. { "getCanvas", w_getCanvas },
  1171. { "setShader", w_setShader },
  1172. { "getShader", w_getShader },
  1173. { "isSupported", w_isSupported },
  1174. { "getCanvasFormats", w_getCanvasFormats },
  1175. { "getCompressedImageFormats", w_getCompressedImageFormats },
  1176. { "getRendererInfo", w_getRendererInfo },
  1177. { "getSystemLimit", w_getSystemLimit },
  1178. { "draw", w_draw },
  1179. { "print", w_print },
  1180. { "printf", w_printf },
  1181. { "isCreated", w_isCreated },
  1182. { "getWidth", w_getWidth },
  1183. { "getHeight", w_getHeight },
  1184. { "getDimensions", w_getDimensions },
  1185. { "setScissor", w_setScissor },
  1186. { "getScissor", w_getScissor },
  1187. { "setStencil", w_setStencil },
  1188. { "setInvertedStencil", w_setInvertedStencil },
  1189. { "point", w_point },
  1190. { "line", w_line },
  1191. { "rectangle", w_rectangle },
  1192. { "circle", w_circle },
  1193. { "arc", w_arc },
  1194. { "polygon", w_polygon },
  1195. { "push", w_push },
  1196. { "pop", w_pop },
  1197. { "rotate", w_rotate },
  1198. { "scale", w_scale },
  1199. { "translate", w_translate },
  1200. { "shear", w_shear },
  1201. { "origin", w_origin },
  1202. // Deprecated since 0.9.1.
  1203. { "getMaxImageSize", w_getMaxTextureSize },
  1204. { "getMaxPointSize", w_getMaxPointSize },
  1205. { 0, 0 }
  1206. };
  1207. // Types for this module.
  1208. static const lua_CFunction types[] =
  1209. {
  1210. luaopen_font,
  1211. luaopen_image,
  1212. luaopen_quad,
  1213. luaopen_spritebatch,
  1214. luaopen_particlesystem,
  1215. luaopen_canvas,
  1216. luaopen_shader,
  1217. luaopen_mesh,
  1218. 0
  1219. };
  1220. extern "C" int luaopen_love_graphics(lua_State *L)
  1221. {
  1222. Graphics *instance = instance();
  1223. if (instance == nullptr)
  1224. {
  1225. luax_catchexcept(L, [&](){ instance = new Graphics(); });
  1226. }
  1227. else
  1228. instance->retain();
  1229. WrappedModule w;
  1230. w.module = instance;
  1231. w.name = "graphics";
  1232. w.flags = MODULE_GRAPHICS_T;
  1233. w.functions = functions;
  1234. w.types = types;
  1235. int n = luax_register_module(L, w);
  1236. if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "graphics.lua") == 0)
  1237. lua_call(L, 0, 0);
  1238. return n;
  1239. }
  1240. } // opengl
  1241. } // graphics
  1242. } // love