wrap_Graphics.cpp 32 KB

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