wrap_Graphics.cpp 27 KB

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