wrap_Graphics.cpp 28 KB

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