wrap_Graphics.cpp 32 KB

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