wrap_Graphics.cpp 30 KB

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