wrap_Graphics.cpp 30 KB

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