wrap_Graphics.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. /**
  2. * Copyright (c) 2006-2011 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 <image/ImageData.h>
  22. #include <font/Rasterizer.h>
  23. #include <scripts/graphics.lua.h>
  24. #include <cassert>
  25. namespace love
  26. {
  27. namespace graphics
  28. {
  29. namespace opengl
  30. {
  31. static Graphics * instance = 0;
  32. int w_checkMode(lua_State * L)
  33. {
  34. int w = luaL_checkint(L, 1);
  35. int h = luaL_checkint(L, 2);
  36. bool fs = luax_toboolean(L, 3);
  37. luax_pushboolean(L, instance->checkMode(w, h, fs));
  38. return 1;
  39. }
  40. int w_setMode(lua_State * L)
  41. {
  42. int w = luaL_checkint(L, 1);
  43. int h = luaL_checkint(L, 2);
  44. bool fs = luax_optboolean(L, 3, false);
  45. bool vsync = luax_optboolean(L, 4, true);
  46. int fsaa = luaL_optint(L, 5, 0);
  47. luax_pushboolean(L, instance->setMode(w, h, fs, vsync, fsaa));
  48. return 1;
  49. }
  50. int w_getMode(lua_State * L)
  51. {
  52. int w, h, fsaa;
  53. bool fs, vsync;
  54. instance->getMode(&w, &h, &fs, &vsync, &fsaa);
  55. lua_pushnumber(L, w);
  56. lua_pushnumber(L, h);
  57. lua_pushboolean(L, fs);
  58. lua_pushboolean(L, vsync);
  59. lua_pushnumber(L, fsaa);
  60. return 5;
  61. }
  62. int w_toggleFullscreen(lua_State * L)
  63. {
  64. luax_pushboolean(L, instance->toggleFullscreen());
  65. return 1;
  66. }
  67. int w_reset(lua_State *)
  68. {
  69. instance->reset();
  70. return 0;
  71. }
  72. int w_clear(lua_State *)
  73. {
  74. instance->clear();
  75. return 0;
  76. }
  77. int w_present(lua_State *)
  78. {
  79. instance->present();
  80. return 0;
  81. }
  82. int w_setIcon(lua_State * L)
  83. {
  84. Image * image = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
  85. instance->setIcon(image);
  86. return 0;
  87. }
  88. int w_setCaption(lua_State * L)
  89. {
  90. const char * str = luaL_checkstring(L, 1);
  91. instance->setCaption(str);
  92. return 0;
  93. }
  94. int w_getCaption(lua_State * L)
  95. {
  96. return instance->getCaption(L);
  97. }
  98. int w_getWidth(lua_State * L)
  99. {
  100. lua_pushnumber(L, instance->getWidth());
  101. return 1;
  102. }
  103. int w_getHeight(lua_State * L)
  104. {
  105. lua_pushnumber(L, instance->getHeight());
  106. return 1;
  107. }
  108. int w_isCreated(lua_State * L)
  109. {
  110. luax_pushboolean(L, instance->isCreated());
  111. return 1;
  112. }
  113. int w_getModes(lua_State * L)
  114. {
  115. return instance->getModes(L);
  116. }
  117. int w_setScissor(lua_State * L)
  118. {
  119. if(lua_gettop(L) == 0)
  120. {
  121. instance->setScissor();
  122. return 0;
  123. }
  124. int x = luaL_checkint(L, 1);
  125. int y = luaL_checkint(L, 2);
  126. int w = luaL_checkint(L, 3);
  127. int h = luaL_checkint(L, 4);
  128. if (w < 0 || h < 0)
  129. return luaL_error(L, "Can't set scissor with negative width and/or height.");
  130. instance->setScissor(x, y, w, h);
  131. return 0;
  132. }
  133. int w_getScissor(lua_State * L)
  134. {
  135. return instance->getScissor(L);
  136. }
  137. int w_newStencil(lua_State * L)
  138. {
  139. // just return the function
  140. if (!lua_isfunction(L, 1))
  141. return luaL_typerror(L, 1, "function");
  142. lua_settop(L, 1);
  143. return 1;
  144. }
  145. static int setStencil(lua_State * L, bool invert)
  146. {
  147. // stencils require the default fb to work properly
  148. Canvas::TemporaryUnbinder unbinder;
  149. // no argument -> clear mask
  150. if (lua_isnoneornil(L, 1)) {
  151. instance->discardStencil();
  152. return 0;
  153. }
  154. if (!lua_isfunction(L, 1))
  155. return luaL_typerror(L, 1, "mask");
  156. instance->defineStencil();
  157. lua_call(L, lua_gettop(L) - 1, 0); // call mask(...)
  158. instance->useStencil(invert);
  159. return 0;
  160. }
  161. int w_setStencil(lua_State * L)
  162. {
  163. return setStencil(L, false);
  164. }
  165. int w_setInvertedStencil(lua_State * L)
  166. {
  167. return setStencil(L, true);
  168. }
  169. int w_newImage(lua_State * L)
  170. {
  171. // Convert to File, if necessary.
  172. if(lua_isstring(L, 1))
  173. luax_convobj(L, 1, "filesystem", "newFile");
  174. // Convert to ImageData, if necessary.
  175. if(luax_istype(L, 1, FILESYSTEM_FILE_T))
  176. luax_convobj(L, 1, "image", "newImageData");
  177. love::image::ImageData * data = luax_checktype<love::image::ImageData>(L, 1, "ImageData", IMAGE_IMAGE_DATA_T);
  178. // Create the image.
  179. Image * image = 0;
  180. try {
  181. image = instance->newImage(data);
  182. } catch (love::Exception & e) {
  183. luaL_error(L, e.what());
  184. }
  185. if(image == 0)
  186. return luaL_error(L, "Could not load image.");
  187. // Push the type.
  188. luax_newtype(L, "Image", GRAPHICS_IMAGE_T, (void*)image);
  189. return 1;
  190. }
  191. int w_newQuad(lua_State * L)
  192. {
  193. float x = (float) luaL_checknumber(L, 1);
  194. float y = (float) luaL_checknumber(L, 2);
  195. float w = (float) luaL_checknumber(L, 3);
  196. float h = (float) luaL_checknumber(L, 4);
  197. float sw = (float) luaL_checknumber(L, 5);
  198. float sh = (float) luaL_checknumber(L, 6);
  199. Quad * frame = instance->newQuad(x, y, w, h, sw, sh);
  200. if (frame == 0)
  201. return luaL_error(L, "Could not create frame.");
  202. luax_newtype(L, "Quad", GRAPHICS_QUAD_T, (void*)frame);
  203. return 1;
  204. }
  205. int w_newFont1(lua_State * L)
  206. {
  207. // Convert to File, if necessary.
  208. if(lua_isstring(L, 1))
  209. luax_convobj(L, 1, "filesystem", "newFile");
  210. // Convert to Data, if necessary.
  211. if(luax_istype(L, 1, FILESYSTEM_FILE_T)) {
  212. love::filesystem::File * f = luax_checktype<love::filesystem::File>(L, 1, "File", FILESYSTEM_FILE_T);
  213. Data * d;
  214. try {
  215. d = f->read();
  216. }
  217. catch (love::Exception & e) {
  218. return luaL_error(L, e.what());
  219. }
  220. lua_remove(L, 1); // get rid of the file
  221. luax_newtype(L, "Data", DATA_T, (void*)d);
  222. lua_insert(L, 1); // put it at the bottom of the stack
  223. }
  224. // Convert to Rasterizer, if necessary.
  225. if(luax_istype(L, 1, DATA_T)) {
  226. int idxs[] = {1, 2};
  227. luax_convobj(L, idxs, 2, "font", "newRasterizer");
  228. }
  229. love::font::Rasterizer * rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
  230. // Create the font.
  231. Font * font = instance->newFont(rasterizer);
  232. if(font == 0)
  233. return luaL_error(L, "Could not load font.");
  234. // Push the type.
  235. luax_newtype(L, "Font", GRAPHICS_FONT_T, (void*)font);
  236. return 1;
  237. }
  238. int w_newImageFont(lua_State * L)
  239. {
  240. // filter for glyphs, defaults to linear/linear
  241. Image::Filter img_filter;
  242. // Convert to ImageData if necessary.
  243. if(lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T) || (luax_istype(L, 1, DATA_T) && !luax_istype(L, 1, IMAGE_IMAGE_DATA_T)))
  244. luax_convobj(L, 1, "image", "newImageData");
  245. else if(luax_istype(L, 1, GRAPHICS_IMAGE_T)) {
  246. Image * i = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
  247. img_filter = i->getFilter();
  248. love::image::ImageData * id = i->getData();
  249. luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void*)id, false);
  250. lua_replace(L, 1);
  251. }
  252. // Convert to Rasterizer if necessary.
  253. if(luax_istype(L, 1, IMAGE_IMAGE_DATA_T)) {
  254. int idxs[] = {1, 2};
  255. luax_convobj(L, idxs, 2, "font", "newRasterizer");
  256. }
  257. love::font::Rasterizer * rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
  258. // Create the font.
  259. Font * font = instance->newFont(rasterizer, img_filter);
  260. if(font == 0)
  261. return luaL_error(L, "Could not load font.");
  262. // Push the type.
  263. luax_newtype(L, "Font", GRAPHICS_FONT_T, (void*)font);
  264. return 1;
  265. }
  266. int w_newSpriteBatch(lua_State * L)
  267. {
  268. Image * image = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
  269. int size = luaL_optint(L, 2, 1000);
  270. SpriteBatch::UsageHint usage = SpriteBatch::USAGE_DYNAMIC;
  271. if (lua_gettop(L) > 2)
  272. {
  273. if (!SpriteBatch::getConstant(luaL_checkstring(L, 3), usage))
  274. usage = SpriteBatch::USAGE_DYNAMIC;
  275. }
  276. SpriteBatch * t = NULL;
  277. try {
  278. t = instance->newSpriteBatch(image, size, usage);
  279. } catch(love::Exception& e) {
  280. return luaL_error(L, e.what());
  281. }
  282. luax_newtype(L, "SpriteBatch", GRAPHICS_SPRITE_BATCH_T, (void*)t);
  283. return 1;
  284. }
  285. int w_newParticleSystem(lua_State * L)
  286. {
  287. Image * image = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
  288. int size = luaL_checkint(L, 2);
  289. ParticleSystem * t = instance->newParticleSystem(image, size);
  290. luax_newtype(L, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T, (void*)t);
  291. return 1;
  292. }
  293. int w_newCanvas(lua_State * L)
  294. {
  295. // check if width and height are given. else default to screen dimensions.
  296. int width = luaL_optint(L, 1, instance->getWidth());
  297. int height = luaL_optint(L, 2, instance->getHeight());
  298. glGetError(); // clear opengl error flag
  299. Canvas * canvas = NULL;
  300. try {
  301. canvas = instance->newCanvas(width, height);
  302. } catch (Exception& e) {
  303. return luaL_error(L, e.what());
  304. }
  305. if (NULL == canvas)
  306. return luaL_error(L, "Canvas not created, but no error thrown. I don't even...");
  307. luax_newtype(L, "Canvas", GRAPHICS_CANVAS_T, (void*)canvas);
  308. return 1;
  309. }
  310. int w_newPixelEffect(lua_State * L)
  311. {
  312. if (!PixelEffect::isSupported())
  313. return luaL_error(L, "Sorry, your graphics card does not support pixel effects.");
  314. try {
  315. luaL_checkstring(L, 1);
  316. luax_getfunction(L, "graphics", "_effectCodeToGLSL");
  317. lua_pushvalue(L, 1);
  318. lua_pcall(L, 1, 1, 0);
  319. const char* code = lua_tostring(L, -1);
  320. PixelEffect * effect = instance->newPixelEffect(code);
  321. luax_newtype(L, "PixelEffect", GRAPHICS_PIXELEFFECT_T, (void*)effect);
  322. } catch (love::Exception& e) {
  323. // memory is freed in Graphics::newPixelEffect
  324. luax_getfunction(L, "graphics", "_transformGLSLErrorMessages");
  325. lua_pushstring(L, e.what());
  326. lua_pcall(L, 1,1, 0);
  327. const char* err = lua_tostring(L, -1);
  328. return luaL_error(L, err);
  329. }
  330. return 1;
  331. }
  332. int w_setColor(lua_State * L)
  333. {
  334. Color c;
  335. if (lua_istable(L, 1)) {
  336. lua_pushinteger(L, 1);
  337. lua_gettable(L, -2);
  338. c.r = (unsigned char)luaL_checkint(L, -1);
  339. lua_pop(L, 1);
  340. lua_pushinteger(L, 2);
  341. lua_gettable(L, -2);
  342. c.g = (unsigned char)luaL_checkint(L, -1);
  343. lua_pop(L, 1);
  344. lua_pushinteger(L, 3);
  345. lua_gettable(L, -2);
  346. c.b = (unsigned char)luaL_checkint(L, -1);
  347. lua_pop(L, 1);
  348. lua_pushinteger(L, 4);
  349. lua_gettable(L, -2);
  350. c.a = (unsigned char)luaL_optint(L, -1, 255);
  351. lua_pop(L, 1);
  352. }
  353. else
  354. {
  355. c.r = (unsigned char)luaL_checkint(L, 1);
  356. c.g = (unsigned char)luaL_checkint(L, 2);
  357. c.b = (unsigned char)luaL_checkint(L, 3);
  358. c.a = (unsigned char)luaL_optint(L, 4, 255);
  359. }
  360. instance->setColor(c);
  361. return 0;
  362. }
  363. int w_getColor(lua_State * L)
  364. {
  365. Color c = instance->getColor();
  366. lua_pushinteger(L, c.r);
  367. lua_pushinteger(L, c.g);
  368. lua_pushinteger(L, c.b);
  369. lua_pushinteger(L, c.a);
  370. return 4;
  371. }
  372. int w_setBackgroundColor(lua_State * L)
  373. {
  374. Color c;
  375. if (lua_istable(L, 1)) {
  376. lua_pushinteger(L, 1);
  377. lua_gettable(L, -2);
  378. c.r = (unsigned char)luaL_checkint(L, -1);
  379. lua_pop(L, 1);
  380. lua_pushinteger(L, 2);
  381. lua_gettable(L, -2);
  382. c.g = (unsigned char)luaL_checkint(L, -1);
  383. lua_pop(L, 1);
  384. lua_pushinteger(L, 3);
  385. lua_gettable(L, -2);
  386. c.b = (unsigned char)luaL_checkint(L, -1);
  387. lua_pop(L, 1);
  388. lua_pushinteger(L, 4);
  389. lua_gettable(L, -2);
  390. c.a = (unsigned char)luaL_optint(L, -1, 255);
  391. lua_pop(L, 1);
  392. }
  393. else
  394. {
  395. c.r = (unsigned char)luaL_checkint(L, 1);
  396. c.g = (unsigned char)luaL_checkint(L, 2);
  397. c.b = (unsigned char)luaL_checkint(L, 3);
  398. c.a = (unsigned char)luaL_optint(L, 4, 255);
  399. }
  400. instance->setBackgroundColor(c);
  401. return 0;
  402. }
  403. int w_getBackgroundColor(lua_State * L)
  404. {
  405. Color c = instance->getBackgroundColor();
  406. lua_pushinteger(L, c.r);
  407. lua_pushinteger(L, c.g);
  408. lua_pushinteger(L, c.b);
  409. lua_pushinteger(L, c.a);
  410. return 4;
  411. }
  412. int w_setFont1(lua_State * L)
  413. {
  414. // The second parameter is an optional int.
  415. int size = luaL_optint(L, 2, 12);
  416. Font * font;
  417. bool created = false;
  418. // If the first parameter isn't a Font, create a new one
  419. if (!luax_istype(L, 1, GRAPHICS_FONT_T)) {
  420. created = true;
  421. lua_pushinteger(L, size); // push the size
  422. lua_insert(L, 2); // move it to its proper place
  423. // Convert to File, if necessary.
  424. if(lua_isstring(L, 1))
  425. luax_convobj(L, 1, "filesystem", "newFile");
  426. // Convert to Data, if necessary.
  427. if(luax_istype(L, 1, FILESYSTEM_FILE_T)) {
  428. love::filesystem::File * f = luax_checktype<love::filesystem::File>(L, 1, "File", FILESYSTEM_FILE_T);
  429. Data * d;
  430. try {
  431. d = f->read();
  432. } catch (love::Exception & e) {
  433. return luaL_error(L, e.what());
  434. }
  435. lua_remove(L, 1); // get rid of the file
  436. luax_newtype(L, "Data", DATA_T, (void*)d);
  437. lua_insert(L, 1); // put it at the bottom of the stack
  438. }
  439. // Convert to Rasterizer, if necessary.
  440. if(luax_istype(L, 1, DATA_T)) {
  441. int idxs[] = {1, 2};
  442. luax_convobj(L, idxs, 2, "font", "newRasterizer");
  443. }
  444. love::font::Rasterizer * rasterizer = luax_checktype<love::font::Rasterizer>(L, 1, "Rasterizer", FONT_RASTERIZER_T);
  445. // Create the font.
  446. font = instance->newFont(rasterizer);
  447. if(font == 0)
  448. return luaL_error(L, "Could not load font.");
  449. }
  450. else font = luax_checktype<Font>(L, 1, "Font", GRAPHICS_FONT_T);
  451. instance->setFont(font);
  452. if (created)
  453. font->release();
  454. return 0;
  455. }
  456. int w_getFont(lua_State * L)
  457. {
  458. Font * f = instance->getFont();
  459. if(f == 0)
  460. return 0;
  461. f->retain();
  462. luax_newtype(L, "Font", GRAPHICS_FONT_T, (void*)f);
  463. return 1;
  464. }
  465. int w_setBlendMode(lua_State * L)
  466. {
  467. Graphics::BlendMode mode;
  468. const char * str = luaL_checkstring(L, 1);
  469. if(!Graphics::getConstant(str, mode))
  470. return luaL_error(L, "Invalid blend mode: %s", str);
  471. instance->setBlendMode(mode);
  472. return 0;
  473. }
  474. int w_setColorMode(lua_State * L)
  475. {
  476. Graphics::ColorMode mode;
  477. const char * str = luaL_checkstring(L, 1);
  478. if(!Graphics::getConstant(str, mode))
  479. return luaL_error(L, "Invalid color mode: %s", str);
  480. instance->setColorMode(mode);
  481. return 0;
  482. }
  483. int w_getBlendMode(lua_State * L)
  484. {
  485. Graphics::BlendMode mode = instance->getBlendMode();
  486. const char * str;
  487. if(!Graphics::getConstant(mode, str))
  488. return luaL_error(L, "Invalid blend mode: %s", str);
  489. lua_pushstring(L, str);
  490. return 1;
  491. }
  492. int w_getColorMode(lua_State * L)
  493. {
  494. Graphics::ColorMode mode = instance->getColorMode();
  495. const char * str;
  496. if(!Graphics::getConstant(mode, str))
  497. return luaL_error(L, "Invalid color mode: %s", str);
  498. lua_pushstring(L, str);
  499. return 1;
  500. }
  501. int w_setLineWidth(lua_State * L)
  502. {
  503. float width = (float)luaL_checknumber(L, 1);
  504. instance->setLineWidth(width);
  505. return 0;
  506. }
  507. int w_setLineStyle(lua_State * L)
  508. {
  509. Graphics::LineStyle style;
  510. const char * str = luaL_checkstring(L, 1);
  511. if(!Graphics::getConstant(str, style))
  512. return luaL_error(L, "Invalid line style: %s", str);
  513. instance->setLineStyle(style);
  514. return 0;
  515. }
  516. int w_setLine(lua_State * L)
  517. {
  518. float width = (float)luaL_checknumber(L, 1);
  519. Graphics::LineStyle style = Graphics::LINE_SMOOTH;
  520. if(lua_gettop(L) >= 2)
  521. {
  522. const char * str = luaL_checkstring(L, 2);
  523. if(!Graphics::getConstant(str, style))
  524. return luaL_error(L, "Invalid line style: %s", str);
  525. }
  526. instance->setLine(width, style);
  527. return 0;
  528. }
  529. int w_getLineWidth(lua_State * L)
  530. {
  531. lua_pushnumber(L, instance->getLineWidth());
  532. return 1;
  533. }
  534. int w_getLineStyle(lua_State * L)
  535. {
  536. Graphics::LineStyle style = instance->getLineStyle();
  537. const char *str;
  538. Graphics::getConstant(style, str);
  539. lua_pushstring(L, str);
  540. return 1;
  541. }
  542. int w_setPointSize(lua_State * L)
  543. {
  544. float size = (float)luaL_checknumber(L, 1);
  545. instance->setPointSize(size);
  546. return 0;
  547. }
  548. int w_setPointStyle(lua_State * L)
  549. {
  550. Graphics::PointStyle style = Graphics::POINT_SMOOTH;
  551. if(lua_gettop(L) >= 2)
  552. {
  553. const char * str = luaL_checkstring(L, 1);
  554. if(!Graphics::getConstant(str, style))
  555. return luaL_error(L, "Invalid point style: %s", str);
  556. }
  557. instance->setPointStyle(style);
  558. return 0;
  559. }
  560. int w_setPoint(lua_State * L)
  561. {
  562. float size = (float)luaL_checknumber(L, 1);
  563. Graphics::PointStyle style;
  564. const char * str = luaL_checkstring(L, 2);
  565. if(!Graphics::getConstant(str, style))
  566. return luaL_error(L, "Invalid point style: %s", str);
  567. instance->setPoint(size, style);
  568. return 0;
  569. }
  570. int w_getPointSize(lua_State * L)
  571. {
  572. lua_pushnumber(L, instance->getPointSize());
  573. return 1;
  574. }
  575. int w_getPointStyle(lua_State * L)
  576. {
  577. lua_pushinteger(L, instance->getPointStyle());
  578. return 1;
  579. }
  580. int w_getMaxPointSize(lua_State * L)
  581. {
  582. lua_pushnumber(L, instance->getMaxPointSize());
  583. return 1;
  584. }
  585. int w_newScreenshot(lua_State * L)
  586. {
  587. love::image::Image * image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
  588. love::image::ImageData * i = instance->newScreenshot(image);
  589. luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)i);
  590. return 1;
  591. }
  592. int w_setRenderTarget(lua_State * L)
  593. {
  594. // called with nil or none -> reset to default buffer
  595. if (lua_isnoneornil(L,1)) {
  596. Canvas::bindDefaultCanvas();
  597. return 0;
  598. }
  599. Canvas * canvas = luax_checkcanvas(L, 1);
  600. // this unbinds the previous fbo
  601. canvas->startGrab();
  602. return 0;
  603. }
  604. int w_getRenderTarget(lua_State * L)
  605. {
  606. Canvas *canvas = Canvas::current;
  607. if (canvas) {
  608. canvas->retain();
  609. luax_newtype(L, "Canvas", GRAPHICS_CANVAS_T, (void*) canvas);
  610. }
  611. else
  612. lua_pushnil(L);
  613. return 1;
  614. }
  615. int w_setPixelEffect(lua_State * L)
  616. {
  617. if (lua_isnoneornil(L,1)) {
  618. PixelEffect::detach();
  619. return 0;
  620. }
  621. PixelEffect * effect = luax_checkpixeleffect(L, 1);
  622. effect->attach();
  623. return 0;
  624. }
  625. int w_isSupported(lua_State * L)
  626. {
  627. bool supported = true;
  628. size_t len = lua_gettop(L);
  629. Graphics::Support support;
  630. for (unsigned int i = 1; i <= len; i++)
  631. {
  632. const char * str = luaL_checkstring(L, i);
  633. if(!Graphics::getConstant(str, support))
  634. supported = false;
  635. switch(support)
  636. {
  637. case Graphics::SUPPORT_CANVAS:
  638. if (!Canvas::isSupported())
  639. supported = false;
  640. break;
  641. case Graphics::SUPPORT_PIXELEFFECT:
  642. if (!PixelEffect::isSupported())
  643. supported = false;
  644. break;
  645. default:
  646. supported = false;
  647. }
  648. if (!supported)
  649. break;
  650. }
  651. lua_pushboolean(L, supported);
  652. return 1;
  653. }
  654. /**
  655. * Draws an Image at the specified coordinates, with rotation and
  656. * scaling along both axes.
  657. * @param x The x-coordinate.
  658. * @param y The y-coordinate.
  659. * @param angle The amount of rotation.
  660. * @param sx The scale factor along the x-axis. (1 = normal).
  661. * @param sy The scale factor along the y-axis. (1 = normal).
  662. * @param ox The offset along the x-axis.
  663. * @param oy The offset along the y-axis.
  664. * @param kx Shear along the x-axis.
  665. * @param ky Shear along the y-axis.
  666. **/
  667. int w_draw(lua_State * L)
  668. {
  669. Drawable * drawable = luax_checktype<Drawable>(L, 1, "Drawable", GRAPHICS_DRAWABLE_T);
  670. float x = (float)luaL_optnumber(L, 2, 0.0f);
  671. float y = (float)luaL_optnumber(L, 3, 0.0f);
  672. float angle = (float)luaL_optnumber(L, 4, 0.0f);
  673. float sx = (float)luaL_optnumber(L, 5, 1.0f);
  674. float sy = (float)luaL_optnumber(L, 6, sx);
  675. float ox = (float)luaL_optnumber(L, 7, 0);
  676. float oy = (float)luaL_optnumber(L, 8, 0);
  677. float kx = (float)luaL_optnumber(L, 9, 0);
  678. float ky = (float)luaL_optnumber(L, 10, 0);
  679. drawable->draw(x, y, angle, sx, sy, ox, oy, kx, ky);
  680. return 0;
  681. }
  682. /**
  683. * Draws an Quad of an Image at the specified coordinates,
  684. * with rotation and scaling along both axes.
  685. *
  686. * @param q The Quad to draw.
  687. * @param x The x-coordinate.
  688. * @param y The y-coordinate.
  689. * @param angle The amount of rotation.
  690. * @param sx The scale factor along the x-axis. (1 = normal).
  691. * @param sy The scale factor along the y-axis. (1 = normal).
  692. * @param ox The offset along the x-axis.
  693. * @param oy The offset along the y-axis.
  694. * @param kx Shear along the x-axis.
  695. * @param ky Shear along the y-axis.
  696. **/
  697. int w_drawq(lua_State * L)
  698. {
  699. Image * image = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
  700. Quad * q = luax_checkframe(L, 2);
  701. float x = (float)luaL_checknumber(L, 3);
  702. float y = (float)luaL_checknumber(L, 4);
  703. float angle = (float)luaL_optnumber(L, 5, 0);
  704. float sx = (float)luaL_optnumber(L, 6, 1);
  705. float sy = (float)luaL_optnumber(L, 7, sx);
  706. float ox = (float)luaL_optnumber(L, 8, 0);
  707. float oy = (float)luaL_optnumber(L, 9, 0);
  708. float kx = (float)luaL_optnumber(L, 10, 0);
  709. float ky = (float)luaL_optnumber(L, 11, 0);
  710. image->drawq(q, x, y, angle, sx, sy, ox, oy, kx, ky);
  711. return 0;
  712. }
  713. int w_drawTest(lua_State * L)
  714. {
  715. Image * image = luax_checktype<Image>(L, 1, "Image", GRAPHICS_IMAGE_T);
  716. float x = (float)luaL_optnumber(L, 2, 0.0f);
  717. float y = (float)luaL_optnumber(L, 3, 0.0f);
  718. float angle = (float)luaL_optnumber(L, 4, 0.0f);
  719. float sx = (float)luaL_optnumber(L, 5, 1.0f);
  720. float sy = (float)luaL_optnumber(L, 6, sx);
  721. float ox = (float)luaL_optnumber(L, 7, 0);
  722. float oy = (float)luaL_optnumber(L, 8, 0);
  723. instance->drawTest(image, x, y, angle, sx, sy, ox, oy);
  724. return 0;
  725. }
  726. int w_print1(lua_State * L)
  727. {
  728. const char * str = luaL_checkstring(L, 1);
  729. float x = (float)luaL_checknumber(L, 2);
  730. float y = (float)luaL_checknumber(L, 3);
  731. float angle = (float)luaL_optnumber(L, 4, 0.0f);
  732. float sx = (float)luaL_optnumber(L, 5, 1.0f);
  733. float sy = (float)luaL_optnumber(L, 6, sx);
  734. float ox = (float)luaL_optnumber(L, 7, 0.0f);
  735. float oy = (float)luaL_optnumber(L, 8, 0.0f);
  736. float kx = (float)luaL_optnumber(L, 9, 0.0f);
  737. float ky = (float)luaL_optnumber(L, 10, 0.0f);
  738. try
  739. {
  740. instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky);
  741. }
  742. catch (love::Exception e)
  743. {
  744. return luaL_error(L, "Decoding error: %s", e.what());
  745. }
  746. return 0;
  747. }
  748. int w_printf1(lua_State * L)
  749. {
  750. const char * str = luaL_checkstring(L, 1);
  751. float x = (float)luaL_checknumber(L, 2);
  752. float y = (float)luaL_checknumber(L, 3);
  753. float wrap = (float)luaL_checknumber(L, 4);
  754. Graphics::AlignMode align = Graphics::ALIGN_LEFT;
  755. if(lua_gettop(L) >= 5)
  756. {
  757. const char * str = luaL_checkstring(L, 5);
  758. if(!Graphics::getConstant(str, align))
  759. return luaL_error(L, "Incorrect alignment: %s", str);
  760. }
  761. try
  762. {
  763. instance->printf(str, x, y, wrap, align);
  764. }
  765. catch (love::Exception e)
  766. {
  767. return luaL_error(L, "Decoding error: %s", e.what());
  768. }
  769. return 0;
  770. }
  771. int w_point(lua_State * L)
  772. {
  773. float x = (float)luaL_checknumber(L, 1);
  774. float y = (float)luaL_checknumber(L, 2);
  775. instance->point(x, y);
  776. return 0;
  777. }
  778. int w_line(lua_State * L)
  779. {
  780. int args = lua_gettop(L);
  781. bool is_table = false;
  782. if (args == 1 && lua_istable(L, 1)) {
  783. args = lua_objlen(L, 1);
  784. is_table = true;
  785. }
  786. if (args % 2 != 0)
  787. return luaL_error(L, "Number of vertices must be a multiple of two");
  788. else if (args < 4)
  789. return luaL_error(L, "Need at least two vertices to draw a line");
  790. float* coords = new float[args];
  791. if (is_table) {
  792. for (int i = 0; i < args; ++i) {
  793. lua_pushnumber(L, i + 1);
  794. lua_rawget(L, 1);
  795. coords[i] = luax_tofloat(L, -1);
  796. lua_pop(L, 1);
  797. }
  798. } else {
  799. for (int i = 0; i < args; ++i)
  800. coords[i] = luax_tofloat(L, i + 1);
  801. }
  802. instance->polyline(coords, args);
  803. delete[] coords;
  804. return 0;
  805. }
  806. int w_triangle(lua_State * L)
  807. {
  808. Graphics::DrawMode mode;
  809. const char * str = luaL_checkstring(L, 1);
  810. if(!Graphics::getConstant(str, mode))
  811. return luaL_error(L, "Incorrect draw mode %s", str);
  812. float x1 = (float)luaL_checknumber(L, 2);
  813. float y1 = (float)luaL_checknumber(L, 3);
  814. float x2 = (float)luaL_checknumber(L, 4);
  815. float y2 = (float)luaL_checknumber(L, 5);
  816. float x3 = (float)luaL_checknumber(L, 6);
  817. float y3 = (float)luaL_checknumber(L, 7);
  818. instance->triangle(mode, x1, y1, x2, y2, x3, y3);
  819. return 0;
  820. }
  821. int w_rectangle(lua_State * L)
  822. {
  823. Graphics::DrawMode mode;
  824. const char * str = luaL_checkstring(L, 1);
  825. if(!Graphics::getConstant(str, mode))
  826. return luaL_error(L, "Incorrect draw mode %s", str);
  827. float x = (float)luaL_checknumber(L, 2);
  828. float y = (float)luaL_checknumber(L, 3);
  829. float w = (float)luaL_checknumber(L, 4);
  830. float h = (float)luaL_checknumber(L, 5);
  831. instance->rectangle(mode, x, y, w, h);
  832. return 0;
  833. }
  834. int w_quad(lua_State * L)
  835. {
  836. Graphics::DrawMode mode;
  837. const char * str = luaL_checkstring(L, 1);
  838. if(!Graphics::getConstant(str, mode))
  839. return luaL_error(L, "Incorrect draw mode %s", str);
  840. float x1 = (float)luaL_checknumber(L, 2);
  841. float y1 = (float)luaL_checknumber(L, 3);
  842. float x2 = (float)luaL_checknumber(L, 4);
  843. float y2 = (float)luaL_checknumber(L, 5);
  844. float x3 = (float)luaL_checknumber(L, 6);
  845. float y3 = (float)luaL_checknumber(L, 7);
  846. float x4 = (float)luaL_checknumber(L, 8);
  847. float y4 = (float)luaL_checknumber(L, 9);
  848. instance->quad(mode, x1, y1, x2, y2, x3, y3, x4, y4);
  849. return 0;
  850. }
  851. int w_circle(lua_State * L)
  852. {
  853. Graphics::DrawMode mode;
  854. const char * str = luaL_checkstring(L, 1);
  855. if(!Graphics::getConstant(str, mode))
  856. return luaL_error(L, "Incorrect draw mode %s", str);
  857. float x = (float)luaL_checknumber(L, 2);
  858. float y = (float)luaL_checknumber(L, 3);
  859. float radius = (float)luaL_checknumber(L, 4);
  860. int points;
  861. if (lua_gettop(L) > 4)
  862. points = lua_tointeger(L, 5);
  863. else
  864. points = radius > 10 ? radius : 10;
  865. instance->circle(mode, x, y, radius, points);
  866. return 0;
  867. }
  868. int w_arc(lua_State * L)
  869. {
  870. Graphics::DrawMode mode;
  871. const char * str = luaL_checkstring(L, 1);
  872. if(!Graphics::getConstant(str, mode))
  873. return luaL_error(L, "Incorrect draw mode %s", str);
  874. float x = (float)luaL_checknumber(L, 2);
  875. float y = (float)luaL_checknumber(L, 3);
  876. float radius = (float)luaL_checknumber(L, 4);
  877. float angle1 = (float)luaL_checknumber(L, 5);
  878. float angle2 = (float)luaL_checknumber(L, 6);
  879. int points = luaL_optint(L, 7, 10);
  880. instance->arc(mode, x, y, radius, angle1, angle2, points);
  881. return 0;
  882. }
  883. int w_polygon(lua_State * L)
  884. {
  885. int args = lua_gettop(L) - 1;
  886. Graphics::DrawMode mode;
  887. const char * str = luaL_checkstring(L, 1);
  888. if(!Graphics::getConstant(str, mode))
  889. return luaL_error(L, "Invalid draw mode: %s", str);
  890. bool is_table = false;
  891. float* coords;
  892. if (args == 1 && lua_istable(L, 2)) {
  893. args = lua_objlen(L, 2);
  894. is_table = true;
  895. }
  896. if (args % 2 != 0)
  897. return luaL_error(L, "Number of vertices must be a multiple of two");
  898. else if (args < 6)
  899. return luaL_error(L, "Need at least three vertices to draw a polygon");
  900. // fetch coords
  901. coords = new float[args + 2];
  902. if (is_table) {
  903. for (int i = 0; i < args; ++i) {
  904. lua_pushnumber(L, i + 1);
  905. lua_rawget(L, 2);
  906. coords[i] = luax_tofloat(L, -1);
  907. lua_pop(L, 1);
  908. }
  909. } else {
  910. for (int i = 0; i < args; ++i)
  911. coords[i] = luax_tofloat(L, i + 2);
  912. }
  913. // make a closed loop
  914. coords[args] = coords[0];
  915. coords[args+1] = coords[1];
  916. instance->polygon(mode, coords, args+2);
  917. delete[] coords;
  918. return 0;
  919. }
  920. int w_push(lua_State *L)
  921. {
  922. try
  923. {
  924. instance->push();
  925. }
  926. catch (love::Exception e)
  927. {
  928. return luaL_error(L, e.what());
  929. }
  930. return 0;
  931. }
  932. int w_pop(lua_State *L)
  933. {
  934. try
  935. {
  936. instance->pop();
  937. }
  938. catch (love::Exception e)
  939. {
  940. return luaL_error(L, e.what());
  941. }
  942. return 0;
  943. }
  944. int w_rotate(lua_State * L)
  945. {
  946. float deg = (float)luaL_checknumber(L, 1);
  947. instance->rotate(deg);
  948. return 0;
  949. }
  950. int w_scale(lua_State * L)
  951. {
  952. float sx = (float)luaL_optnumber(L, 1, 1.0f);
  953. float sy = (float)luaL_optnumber(L, 2, sx);
  954. instance->scale(sx, sy);
  955. return 0;
  956. }
  957. int w_translate(lua_State * L)
  958. {
  959. float x = (float)luaL_checknumber(L, 1);
  960. float y = (float)luaL_checknumber(L, 2);
  961. instance->translate(x, y);
  962. return 0;
  963. }
  964. int w_shear(lua_State * L)
  965. {
  966. float kx = (float)luaL_checknumber(L, 1);
  967. float ky = (float)luaL_checknumber(L, 2);
  968. instance->shear(kx, ky);
  969. return 0;
  970. }
  971. int w_hasFocus(lua_State * L)
  972. {
  973. luax_pushboolean(L, instance->hasFocus());
  974. return 1;
  975. }
  976. // List of functions to wrap.
  977. static const luaL_Reg functions[] = {
  978. { "checkMode", w_checkMode },
  979. { "setMode", w_setMode },
  980. { "getMode", w_getMode },
  981. { "toggleFullscreen", w_toggleFullscreen },
  982. { "reset", w_reset },
  983. { "clear", w_clear },
  984. { "present", w_present },
  985. { "newImage", w_newImage },
  986. { "newQuad", w_newQuad },
  987. { "newFont1", w_newFont1 },
  988. { "newImageFont", w_newImageFont },
  989. { "newSpriteBatch", w_newSpriteBatch },
  990. { "newParticleSystem", w_newParticleSystem },
  991. { "newCanvas", w_newCanvas },
  992. { "newPixelEffect", w_newPixelEffect },
  993. { "setColor", w_setColor },
  994. { "getColor", w_getColor },
  995. { "setBackgroundColor", w_setBackgroundColor },
  996. { "getBackgroundColor", w_getBackgroundColor },
  997. { "setFont1", w_setFont1 },
  998. { "getFont", w_getFont },
  999. { "setBlendMode", w_setBlendMode },
  1000. { "setColorMode", w_setColorMode },
  1001. { "getBlendMode", w_getBlendMode },
  1002. { "getColorMode", w_getColorMode },
  1003. { "setLineWidth", w_setLineWidth },
  1004. { "setLineStyle", w_setLineStyle },
  1005. { "setLine", w_setLine },
  1006. { "getLineWidth", w_getLineWidth },
  1007. { "getLineStyle", w_getLineStyle },
  1008. { "setPointSize", w_setPointSize },
  1009. { "setPointStyle", w_setPointStyle },
  1010. { "setPoint", w_setPoint },
  1011. { "getPointSize", w_getPointSize },
  1012. { "getPointStyle", w_getPointStyle },
  1013. { "getMaxPointSize", w_getMaxPointSize },
  1014. { "newScreenshot", w_newScreenshot },
  1015. { "setRenderTarget", w_setRenderTarget },
  1016. { "getRenderTarget", w_getRenderTarget },
  1017. { "setPixelEffect", w_setPixelEffect },
  1018. { "isSupported", w_isSupported },
  1019. { "draw", w_draw },
  1020. { "drawq", w_drawq },
  1021. { "drawTest", w_drawTest },
  1022. { "print1", w_print1 },
  1023. { "printf1", w_printf1 },
  1024. { "setCaption", w_setCaption },
  1025. { "getCaption", w_getCaption },
  1026. { "setIcon", w_setIcon },
  1027. { "getWidth", w_getWidth },
  1028. { "getHeight", w_getHeight },
  1029. { "isCreated", w_isCreated },
  1030. { "getModes", w_getModes },
  1031. { "setScissor", w_setScissor },
  1032. { "getScissor", w_getScissor },
  1033. { "newStencil", w_newStencil },
  1034. { "setStencil", w_setStencil },
  1035. { "setInvertedStencil", w_setInvertedStencil },
  1036. { "point", w_point },
  1037. { "line", w_line },
  1038. { "triangle", w_triangle },
  1039. { "rectangle", w_rectangle },
  1040. { "quad", w_quad },
  1041. { "circle", w_circle },
  1042. { "arc", w_arc },
  1043. { "polygon", w_polygon },
  1044. { "push", w_push },
  1045. { "pop", w_pop },
  1046. { "rotate", w_rotate },
  1047. { "scale", w_scale },
  1048. { "translate", w_translate },
  1049. { "shear", w_shear },
  1050. { "hasFocus", w_hasFocus },
  1051. { 0, 0 }
  1052. };
  1053. // Types for this module.
  1054. static const lua_CFunction types[] = {
  1055. luaopen_font,
  1056. luaopen_image,
  1057. luaopen_frame,
  1058. luaopen_spritebatch,
  1059. luaopen_particlesystem,
  1060. luaopen_canvas,
  1061. luaopen_pixeleffect,
  1062. 0
  1063. };
  1064. int luaopen_love_graphics(lua_State * L)
  1065. {
  1066. if(instance == 0)
  1067. {
  1068. try
  1069. {
  1070. instance = new Graphics();
  1071. }
  1072. catch(Exception & e)
  1073. {
  1074. return luaL_error(L, e.what());
  1075. }
  1076. }
  1077. else
  1078. instance->retain();
  1079. WrappedModule w;
  1080. w.module = instance;
  1081. w.name = "graphics";
  1082. w.flags = MODULE_T;
  1083. w.functions = functions;
  1084. w.types = types;
  1085. luax_register_module(L, w);
  1086. if (luaL_loadbuffer(L, (const char *)graphics_lua, sizeof(graphics_lua), "graphics.lua") == 0)
  1087. lua_call(L, 0, 0);
  1088. return 0;
  1089. }
  1090. } // opengl
  1091. } // graphics
  1092. } // love