scegra.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. #include "scegra.h"
  2. #include "eruta.h"
  3. #include "bevec.h"
  4. #include "image.h"
  5. #include "rebox.h"
  6. #include "bad.h"
  7. #include "draw.h"
  8. #include "str.h"
  9. #include "flags.h"
  10. #include "store.h"
  11. #include "state.h"
  12. #include "laytext.h"
  13. #include <string.h>
  14. #define SCEGRA_TEXT_MAX 128
  15. enum ScegraNodeFlags_ {
  16. SCEGRA_NODE_HIDE = 1
  17. };
  18. enum ScegraNodeKind_ {
  19. SCEGRA_NODE_UNKNOWN = 0,
  20. SCEGRA_NODE_BITMAP,
  21. SCEGRA_NODE_BOX,
  22. SCEGRA_NODE_LINE,
  23. SCEGRA_NODE_TRIANGLE,
  24. SCEGRA_NODE_SPLINE,
  25. SCEGRA_NODE_PIXEL,
  26. SCEGRA_NODE_POLYGON,
  27. SCEGRA_NODE_PRIM,
  28. SCEGRA_NODE_TEXT,
  29. SCEGRA_NODE_LONGTEXT,
  30. };
  31. /* A very simple scene graph, mainly for drawing the UI that will be managed from
  32. * the scripting side of things. To avoid memory allocation, limit the amount of
  33. * vertices allowed to SCERGRA_VERTEX_MAX (32) and characters allowed for a
  34. * string to 128. (enough to fill the screen with a font of 5 pixels wide).
  35. * Of course this is all for a LINE of text, the scegra will use multiple text
  36. * text lines for multiline displays.
  37. */
  38. struct ScegraRound_ {
  39. float start_theta, delta_theta;
  40. };
  41. struct ScegraBitmap_ {
  42. BeVec src_pos, src_size;
  43. float angle;
  44. int image_id;
  45. };
  46. struct ScegraBox_ {
  47. BeVec round;
  48. };
  49. struct ScegraLine_ {
  50. float _unused;
  51. };
  52. struct ScegraTriangle_ {
  53. float x1, y1, x2, y2, x3, y3;
  54. };
  55. struct ScegraSpline_ {
  56. float vertices[8];
  57. };
  58. struct ScegraPixel_ {
  59. float x1, y1;
  60. };
  61. struct ScegraPolygon_ {
  62. float vertices[SCEGRA_VERTEX_MAX];
  63. int vertex_count;
  64. };
  65. struct ScegraPrim_ {
  66. ALLEGRO_VERTEX vertices[SCEGRA_VERTEX_MAX];
  67. int vertex_count;
  68. };
  69. struct ScegraText_ {
  70. float x1, x2, y, diff;
  71. char text[SCEGRA_TEXT_MAX];
  72. int from, until;
  73. };
  74. /* For long text that can scroll and display letter per letter. */
  75. struct ScegraLongText_ {
  76. float x1, x2, y, diff;
  77. char * text;
  78. int line_start, line_stop, line_pos; /* Current text "window". */
  79. int line_max, line_height; /* text constants. */
  80. int page_lines; /* Text "window" size for one "page" of text in amount of lines. */
  81. int paused;
  82. double delay_total;
  83. };
  84. /** Union: ScegraData.
  85. * A union of different types of vertex data for drawing the various primitives
  86. * and bitmaps.
  87. */
  88. union ScegraData_ {
  89. struct ScegraPixel_ pixel;
  90. struct ScegraLine_ line;
  91. struct ScegraTriangle_ triangle;
  92. struct ScegraBox_ box;
  93. struct ScegraBitmap_ bitmap;
  94. struct ScegraPolygon_ polygon;
  95. struct ScegraRound_ round;
  96. struct ScegraSpline_ spline;
  97. struct ScegraPrim_ prim;
  98. struct ScegraText_ text;
  99. struct ScegraLongText_ longtext;
  100. };
  101. typedef union ScegraData_ ScegraData;
  102. struct ScegraNode_ {
  103. int id;
  104. int z;
  105. int step;
  106. int kind;
  107. int flags;
  108. double delay;
  109. BeVec pos;
  110. BeVec size;
  111. BeVec speed;
  112. struct ScegraStyle_ style;
  113. union ScegraData_ data;
  114. ScegraDraw * draw;
  115. ScegraUpdate * update;
  116. ScegraDone * done;
  117. };
  118. /* Scene graph struct. */
  119. struct Scegra_ {
  120. ScegraNode * nodes;
  121. int node_max;
  122. };
  123. #define SCEGRA_NODES_MAX 10000
  124. #define SCEGRA_LONGTEXT_LINE_POS_MAX 99999
  125. /* Static storage for nodes. */
  126. static ScegraNode scegra_nodes[SCEGRA_NODES_MAX];
  127. /* Nodes pointers sorted in drawing order. */
  128. static ScegraNode * scegra_nodes_todraw[SCEGRA_NODES_MAX];
  129. /* How many nodes to draw this time. */
  130. static int scegra_to_draw = 0;
  131. void
  132. scegranode_done(ScegraNode * self) {
  133. if (!self) return;
  134. if (self->done) self->done(self);
  135. self->id = -1;
  136. self->z = -1;
  137. }
  138. ScegraNode *
  139. scegranode_initall(ScegraNode * node, int kind, int id, BeVec pos, BeVec siz,
  140. ScegraData data,
  141. ScegraStyle style, ScegraDraw * draw, ScegraUpdate * update) {
  142. if(!node) return NULL;
  143. scegranode_done(node);
  144. node->id = id;
  145. node->z = id;
  146. node->pos = pos;
  147. node->size = siz;
  148. node->speed = bevec0();
  149. node->data = data;
  150. node->style = style;
  151. node->draw = draw;
  152. node->update = update;
  153. node->step = 0;
  154. node->flags = 0;
  155. node->done = NULL;
  156. node->kind = kind;
  157. node->delay = 0.05;
  158. return node;
  159. }
  160. /* Gets pointer to the font for this scegra node, or to a default font. */
  161. static Font * scegra_get_font(ScegraNode * self) {
  162. Font * font;
  163. /* Use default font if font not loaded. */
  164. font = store_get_font(self->style.font_id);
  165. if (!font) font = state_font(state_get());
  166. return font;
  167. }
  168. /** Gets the current text page for a longtext. */
  169. int scegranode_page(ScegraNode * node) {
  170. struct ScegraLongText_ * lt;
  171. if (!node) return -2;
  172. if (node->id < 0) return -1;
  173. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  174. lt = &node->data.longtext;
  175. return lt->line_start / lt->page_lines;
  176. }
  177. /** Gets the last page number for a longtext or negative on error. */
  178. int scegranode_last_page(ScegraNode * node) {
  179. struct ScegraLongText_ * lt;
  180. if (!node) return -2;
  181. if (node->id < 0) return -1;
  182. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  183. lt = &node->data.longtext;
  184. return lt->line_max / lt->page_lines;
  185. }
  186. /** Advances long text to the given page. Automatically unpauses as well. */
  187. int scegranode_page_(ScegraNode * node, int page) {
  188. struct ScegraLongText_ * lt;
  189. int line;
  190. if (!node) return -2;
  191. if (node->id < 0) return -1;
  192. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  193. if (page < 0) return -4;
  194. lt = &node->data.longtext;
  195. line = page * lt->page_lines;
  196. /* Check for page overflow. */
  197. if (line >= lt->line_max) {
  198. return -5;
  199. }
  200. lt->paused = false;
  201. lt->line_start = line;
  202. /* Negative delay is instant display. */
  203. if (node->delay < 0) {
  204. lt->line_stop = lt->line_start + lt->page_lines;
  205. lt->line_pos = SCEGRA_LONGTEXT_LINE_POS_MAX;
  206. } else {
  207. lt->line_stop = lt->line_start + 1;
  208. lt->line_pos = 0;
  209. }
  210. return page;
  211. }
  212. void
  213. scegranode_longtext_done(ScegraNode * self) {
  214. free(self->data.longtext.text);
  215. self->data.longtext.text = NULL;
  216. }
  217. void scegra_update_generic(ScegraNode * self, double dt) {
  218. self->pos = bevec_add(self->pos, bevec_mul(self->speed, dt));
  219. }
  220. /* This function is the helper callback that implements
  221. * updating scrolled/partial text for Longtexts.
  222. */
  223. static bool scegra_update_custom_partial_text(int line_num, const char *line,
  224. int size, void *extra) {
  225. ScegraNode * self = extra;
  226. struct ScegraLongText_ * st = &self->data.longtext;
  227. st->line_max = line_num;
  228. /* Don't draw lines before start but keep on drawing (for later lines) */
  229. if (line_num < st->line_start) return true;
  230. /* Don't draw lines after stop, but keep calculating to get correct amount of lines */
  231. if (line_num >= st->line_stop) return true;
  232. /* Reveal letter by letter on last line */
  233. if (line_num == (st->line_stop - 1)) {
  234. /* Advance the position automatically if not paused. */
  235. if (!st->paused) {
  236. st->line_pos++;
  237. }
  238. /* Reached eol, advance to next line. */
  239. if (st->line_pos >= size) {
  240. /* Is if the text window is full, pause, otherwise show the next line. */
  241. if ((st->line_stop - st->line_start) >= st->page_lines) {
  242. st->paused = true;
  243. } else {
  244. st->line_stop++;
  245. st->line_pos = 0;
  246. }
  247. }
  248. }
  249. (void) line;
  250. return true;
  251. }
  252. /* Updates the longtext, enables scrolling and per character display. */
  253. void scegra_update_longtext(ScegraNode * self, double dt) {
  254. scegra_update_generic(self, dt);
  255. float width = self->size.x - self->style.margin * 2;
  256. struct ScegraLongText_ * st = &self->data.longtext;
  257. char * text = self->data.longtext.text ?
  258. self->data.longtext.text : "NULL";
  259. /* Delay advence of characters somewhat. */
  260. st->delay_total += dt;
  261. if (st->delay_total < self->delay) return;
  262. st->delay_total = 0;
  263. st->line_max = 0;
  264. al_do_multiline_text(scegra_get_font(self), width,
  265. (const char *) text, scegra_update_custom_partial_text, self);
  266. st->line_max++;
  267. /* pause if the last line is reached, and prevent overflow. */
  268. if (st->line_stop > st->line_max) {
  269. st->paused = true;
  270. st->line_pos = SCEGRA_LONGTEXT_LINE_POS_MAX;
  271. st->line_stop = st->line_max;
  272. }
  273. }
  274. /* Returns TRUE if the longtext node is at the end of the text to display,
  275. * false if not (more text to display) */
  276. int scegranode_longtext_at_end(ScegraNode * node) {
  277. struct ScegraLongText_ * lt;
  278. if (!node) return FALSE;
  279. if (node->id < 0) return FALSE;
  280. if (node->kind != SCEGRA_NODE_LONGTEXT) return FALSE;
  281. lt = &node->data.longtext;
  282. return ((lt->line_stop >= lt->line_max) &&
  283. (lt->line_pos >= SCEGRA_LONGTEXT_LINE_POS_MAX));
  284. }
  285. void scegra_draw_box(ScegraNode * self) {
  286. BeVec p2;
  287. p2 = bevec_add(self->pos, self->size);
  288. float thick = self->style.border_thickness;
  289. if (self->style.background_image_id >= 0) {
  290. ALLEGRO_BITMAP * bmp = store_get_bitmap(self->style.background_image_id);
  291. /* XXX: need another param for corner size or is the autodetect OK? */
  292. image_blitscale9(bmp, self->pos.x, self->pos.y, self->size.x, self->size.y,
  293. -1, -1);
  294. // self->data.box.round.x, self->data.box.round.y);
  295. } else {
  296. al_draw_filled_rounded_rectangle(self->pos.x, self->pos.y, p2.x, p2.y,
  297. self->data.box.round.x, self->data.box.round.y, self->style.background_color
  298. );
  299. }
  300. if (self->style.border_thickness > 0.0f) {
  301. al_draw_rounded_rectangle(self->pos.x + thick/2, self->pos.y + thick/2, p2.x - thick/2, p2.y - thick/2,
  302. self->data.box.round.x - thick/4, self->data.box.round.y - thick/4, self->style.border_color,
  303. thick);
  304. }
  305. }
  306. /* Calculates the x and y position where to draw text, taking alignment and
  307. * margin into consideration. */
  308. static BeVec
  309. scegra_calculate_text_position(ScegraNode * self) {
  310. BeVec result;
  311. int flags = self->style.text_flags;
  312. result.x = self->pos.x + self->style.margin;
  313. result.y = self->pos.y + self->style.margin;
  314. if (flags & ALLEGRO_ALIGN_CENTER) {
  315. result.x = self->pos.x + self->style.margin + self->size.x / 2;
  316. } else if (flags & ALLEGRO_ALIGN_RIGHT) {
  317. result.x = self->pos.x + self->size.x - self->style.margin;
  318. }
  319. return result;
  320. }
  321. void scegra_draw_text(ScegraNode * self) {
  322. Font * font;
  323. int flags;
  324. BeVec pos = scegra_calculate_text_position(self);
  325. font = scegra_get_font(self);
  326. flags = self->style.text_flags | ALLEGRO_ALIGN_INTEGER;
  327. /* Draw the text twice, once offset in bg color to produce a shadow,
  328. and once normally with foreground color. */
  329. al_draw_text(font, self->style.background_color, pos.x + 1, pos.y + 1,
  330. flags, self->data.text.text);
  331. al_draw_text(font, self->style.color, pos.x, pos.y,
  332. flags, self->data.text.text);
  333. }
  334. /** Calculates the amount of lines that scegra_draw_partial_text can draw
  335. * at most with this text. */
  336. static int scegra_partial_text_lines(ALLEGRO_FONT * font, float w,
  337. const char * text)
  338. {
  339. (void) font; (void) w; (void) text;
  340. return 0; /* XXX todo */
  341. }
  342. /* This function is the helper callback that implements the actual drawing
  343. * for scegra_draw_partial_text.
  344. */
  345. static bool scegra_draw_custom_partial_text(int line_num, const char *line,
  346. int size, void *extra) {
  347. float x, y;
  348. ScegraNode * self = extra;
  349. struct ScegraLongText_ * st = &self->data.longtext;
  350. ALLEGRO_USTR_INFO info;
  351. int real_size, flags;
  352. double width;
  353. ALLEGRO_FONT * font;
  354. BeVec pos;
  355. font = scegra_get_font(self);
  356. flags = self->style.text_flags | ALLEGRO_ALIGN_INTEGER;
  357. pos = scegra_calculate_text_position(self);
  358. /* Don't draw lines before start but keep on drawing (for later lines) */
  359. if (line_num < st->line_start) return true;
  360. /* Don't draw lines after stop, drawing is done */
  361. if (line_num >= st->line_stop) return false;
  362. real_size = size;
  363. /* calculate position */
  364. x = pos.x;
  365. y = pos.y + (st->line_height * (line_num - st->line_start));
  366. /* Reveal letter by letter on last line */
  367. if (line_num == (st->line_stop - 1)) {
  368. real_size = (st->line_pos < size) ? st->line_pos : size;
  369. /* Draw continuation marker if paused. */
  370. if (st->paused) {
  371. float x1, y1, x2, y2, x3, y3;
  372. y2 = y + 8;
  373. x2 = x + self->size.x - self->style.margin;
  374. x1 = x2 - 8;
  375. y1 = y2;
  376. x3 = x2 - 4;
  377. y3 = y2 + 8;
  378. al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, self->style.color);
  379. }
  380. }
  381. al_draw_ustr(font, self->style.background_color,
  382. x + 1, y + 1, flags, al_ref_buffer(&info, line, real_size));
  383. al_draw_ustr(font, self->style.color,
  384. x, y, flags, al_ref_buffer(&info, line, real_size));
  385. return true;
  386. }
  387. /* Allows to draw a multi line text partially, from line_start up to
  388. * line_stop
  389. * Scraws scrolling text from a prefilled struct. */
  390. void scegra_draw_partial_text(ScegraNode * self) {
  391. float width = self->size.x - self->style.margin * 2;
  392. struct ScegraLongText_ * st = &self->data.longtext;
  393. char * text = self->data.longtext.text ?
  394. self->data.longtext.text : "NULL";
  395. /* It's a bit of a hack that this ends up here... */
  396. if (st->line_height < 1.0) {
  397. st->line_height = al_get_font_line_height(scegra_get_font(self));
  398. }
  399. al_do_multiline_text(scegra_get_font(self), width,
  400. (const char *) text, scegra_draw_custom_partial_text, self);
  401. }
  402. void scegra_draw_longtext(ScegraNode * self) {
  403. Font * font;
  404. int flags;
  405. const char * text;
  406. float width;
  407. BeVec pos = scegra_calculate_text_position(self);
  408. font = scegra_get_font(self);
  409. flags = self->style.text_flags | ALLEGRO_ALIGN_INTEGER;
  410. text = self->data.longtext.text ?
  411. self->data.longtext.text : "NULL";
  412. width = self->size.x - self->style.margin * 2;
  413. scegra_draw_partial_text(self);
  414. /* Draw the text twice, once offset in bg color to produce a shadow,
  415. and once normally with foreground color. */
  416. /*
  417. al_draw_multiline_text(font, self->style.background_color,
  418. pos.x + 1, pos.y + 1, width, 0, flags, text);
  419. al_draw_multiline_text(font, self->style.color,
  420. pos.x, pos.y, width, 0, flags, text);
  421. **/
  422. }
  423. void scegra_draw_image(ScegraNode * self) {
  424. Image * image;
  425. int flags = self->style.image_flags;
  426. float angle = self->data.bitmap.angle;
  427. float cx, cy, dx, dy, xscale, yscale;
  428. cx = self->data.bitmap.src_pos.x + self->data.bitmap.src_size.x / 2;
  429. cy = self->data.bitmap.src_pos.y + self->data.bitmap.src_size.y / 2;
  430. dx = self->pos.x + self->size.x / 2;
  431. dy = self->pos.y + self->size.y / 2;
  432. xscale = self->size.x / self->data.bitmap.src_size.x;
  433. yscale = self->size.y / self->data.bitmap.src_size.y;
  434. image = store_get_bitmap(self->data.bitmap.image_id);
  435. /* Draw missing image rectangle. */
  436. if (!image) {
  437. BeVec p2;
  438. p2 = bevec_add(self->pos, self->size);
  439. al_draw_filled_rounded_rectangle(self->pos.x, self->pos.y, p2.x, p2.y,
  440. self->data.box.round.x, self->data.box.round.y, self->style.background_color
  441. );
  442. } else {
  443. al_draw_tinted_scaled_rotated_bitmap(image, self->style.color, cx, cy, dx, dy, xscale, yscale, angle, flags);
  444. }
  445. }
  446. ScegraStyle * scegrastyle_initempty(ScegraStyle * self) {
  447. if (!self) return NULL;
  448. self->background_image_id = -1;
  449. self->color = al_map_rgba_f(1.0,1.0,1.0,1.0);
  450. self->background_color = al_map_rgba_f(0.0,0.0,0.0,0.0);
  451. self->border_color = al_map_rgba_f(1.0,1.0,1.0,1.0);
  452. self->font_id = -1;
  453. self->line_join_style = 0;
  454. self->line_miter_limit = 1;
  455. self->border_thickness = -1;
  456. self->image_flags = 0;
  457. self->text_flags = 0;
  458. self->margin = 0;
  459. return self;
  460. }
  461. ScegraNode *
  462. scegranode_init_box(ScegraNode * self, int id, BeVec pos, BeVec siz, BeVec round, ScegraStyle style) {
  463. ScegraData data;
  464. if (!self) return NULL;
  465. data.box.round = round;
  466. scegranode_initall(self, SCEGRA_NODE_BOX,
  467. id, pos, siz, data, style, scegra_draw_box, scegra_update_generic);
  468. return self;
  469. }
  470. ScegraNode *
  471. scegranode_init_text(ScegraNode * self, int id, BeVec pos, BeVec siz, const char * text, ScegraStyle style) {
  472. ScegraData data;
  473. if (!self) return NULL;
  474. strncpy(data.text.text, text, SCEGRA_TEXT_MAX);
  475. data.text.text[SCEGRA_TEXT_MAX - 1] = '\0';
  476. scegranode_initall(self, SCEGRA_NODE_TEXT,
  477. id, pos, siz, data, style, scegra_draw_text, scegra_update_generic);
  478. return self;
  479. }
  480. int scegranode_set_longtext_text(ScegraNode * self, const char * text) {
  481. free(self->data.longtext.text);
  482. self->data.longtext.text = cstr_dup((char *)text);
  483. if (!self->data.longtext.text) return -1;
  484. self->data.longtext.line_start = 0;
  485. self->data.longtext.line_stop = 1;
  486. self->data.longtext.line_pos = 0;
  487. self->data.longtext.delay_total = 0.0;
  488. scegranode_page_(self, 0);
  489. return 0;
  490. }
  491. ScegraNode *
  492. scegranode_init_longtext
  493. (ScegraNode * self, int id, BeVec pos, BeVec siz, char * text, ScegraStyle style) {
  494. ScegraData data;
  495. if (!self) return NULL;
  496. memset(&data.longtext, 0, sizeof(data.longtext));
  497. data.longtext.page_lines = 4;
  498. data.longtext.line_start = 0;
  499. data.longtext.line_stop = 1;
  500. data.longtext.paused = 0;
  501. scegranode_initall(self, SCEGRA_NODE_LONGTEXT,
  502. id, pos, siz, data, style, scegra_draw_longtext, scegra_update_longtext);
  503. scegranode_set_longtext_text(self, text);
  504. self->done = scegranode_longtext_done;
  505. scegranode_page_(self, 0);
  506. return self;
  507. }
  508. ScegraNode *
  509. scegranode_init_image_ex(
  510. ScegraNode * self, int id, BeVec pos, BeVec siz, int image_id, ScegraStyle style,
  511. BeVec spos, BeVec ssiz, float angle, int flags) {
  512. ScegraData data;
  513. if (!self) return NULL;
  514. data.bitmap.angle = angle;
  515. data.bitmap.image_id = image_id;
  516. data.bitmap.src_pos = spos;
  517. data.bitmap.src_size = ssiz;
  518. scegranode_initall(self, SCEGRA_NODE_BITMAP,
  519. id, pos, siz, data, style, scegra_draw_image, scegra_update_generic);
  520. self->style.image_flags = flags;
  521. return self;
  522. }
  523. ScegraNode *
  524. scegranode_init_image(ScegraNode * self, int id, BeVec pos, BeVec siz, int image_id, ScegraStyle style) {
  525. int w, h;
  526. if (siz.x <= 0.0) { if (store_get_bitmap_width(image_id, &w)) siz.x = w; }
  527. if (siz.y <= 0.0) { if (store_get_bitmap_height(image_id, &h)) siz.y = h; }
  528. return scegranode_init_image_ex(self, id, pos, siz, image_id, style, bevec0(), siz, 0.0, 0);
  529. }
  530. /* Returns nonzero if the scegranode is in use, false if not */
  531. static int scegranode_in_use_p(ScegraNode * node) {
  532. return node->id != -1;
  533. }
  534. /* Returns nonzero if the scene graph node id is in use. Also returns
  535. * false if the ID is out of range. */
  536. int scegra_id_in_use_p(int index) {
  537. ScegraNode * node = scegra_get_node(index);
  538. if (!node) return FALSE;
  539. return scegranode_in_use_p(node);
  540. }
  541. /* Returns the first free ID that is larger than the minimum. Returns
  542. * negative if no more ID's are free. */
  543. int scegra_get_free_id(int minimum) {
  544. int index;
  545. if (minimum < 0) return -1;
  546. for (index = minimum; index < SCEGRA_NODES_MAX; index++) {
  547. if (!scegra_id_in_use_p(index)) {
  548. return index;
  549. }
  550. }
  551. return -1;
  552. }
  553. /* Returns maximum amount of nodes. */
  554. int scegra_nodes_max() {
  555. return SCEGRA_NODES_MAX;
  556. }
  557. /* Initializes the simple 2D scene graph */
  558. void scegra_init() {
  559. int index;
  560. for (index = 0; index < SCEGRA_NODES_MAX; index++) {
  561. ScegraNode * node = scegra_nodes + index;
  562. node->id = -1; /* Negative id means unused; */
  563. }
  564. scegra_to_draw = 0;
  565. }
  566. /* End the use of the simple 2D scene graph */
  567. void scegra_done() {
  568. int index;
  569. for (index = 0; index < SCEGRA_NODES_MAX; index++) {
  570. ScegraNode * node = scegra_nodes + index;
  571. scegranode_done(node);
  572. }
  573. scegra_to_draw = 0;
  574. }
  575. /* Compares a scene graph node with another, for drawing order. Things with low
  576. z come before those with high z, and with same z, low id comes before high id.
  577. qsort compatible. No NULL values allowed!!! */
  578. static inline int scegranode_compare_for_drawing(const void * p1, const void * p2) {
  579. register const ScegraNode * self = *((ScegraNode **) p1);
  580. register const ScegraNode * other = *((ScegraNode **) p2);
  581. register int self_val, other_val;
  582. /* Compare Z if no nulls. */
  583. self_val = self->z;
  584. other_val = other->z;
  585. if (self_val < other_val) return -1;
  586. if (self_val > other_val) return 1;
  587. /* compare id if z is equal */
  588. self_val = self->id;
  589. other_val = other->id;
  590. if (self_val < other_val) return -1;
  591. if (self_val > other_val) return 1;
  592. return 0;
  593. }
  594. /* Updates the 2d scene graph. */
  595. void scegra_update(double dt) {
  596. register int index;
  597. scegra_to_draw = 0;
  598. for (index = 0; index < SCEGRA_NODES_MAX; index++) {
  599. register ScegraNode * node = scegra_nodes + index;
  600. if (node->id < 0) continue; /* Negative id means unused; */
  601. if(node->update) {
  602. node->update(node, dt);
  603. }
  604. /* Only add node to draw array if not hidden and drawable. */
  605. if((!flags_get(node->flags, SCEGRA_NODE_HIDE)) && (node->draw)) {
  606. scegra_nodes_todraw[scegra_to_draw] = node;
  607. scegra_to_draw++;
  608. }
  609. }
  610. /* Sort scene graph nodes for drawing. */
  611. qsort(scegra_nodes_todraw, scegra_to_draw,
  612. sizeof(ScegraNode*), scegranode_compare_for_drawing);
  613. }
  614. /* Draws the 2d scene graph. */
  615. void scegra_draw() {
  616. int index;
  617. /* All nodes in the todraw will be drawn up to scegra_to_draw,
  618. there are no other drawable bodes in there. */
  619. for (index = 0; index < scegra_to_draw; index++) {
  620. ScegraNode * node = scegra_nodes_todraw[index];
  621. node->draw(node);
  622. }
  623. }
  624. /* Returns true if out of bounds for the scene graph, or false if ok. */
  625. int scegra_out_of_bounds(int index) {
  626. if (index < 0) return TRUE;
  627. if (index > scegra_nodes_max()) return TRUE;
  628. return FALSE;
  629. }
  630. /* Returns a node from the scene graph or NULL if out of bounds. */
  631. ScegraNode * scegra_get_node(int index) {
  632. if (scegra_out_of_bounds(index)) return NULL;
  633. return scegra_nodes + index;
  634. }
  635. /* Returns the ID of the scene graph node at index. -1 means it's free,
  636. *-2 means out of range. */
  637. int scegra_get_id(int index) {
  638. ScegraNode * node = scegra_get_node(index);
  639. if (!node) return -2;
  640. return node->id;
  641. }
  642. /* Sets the scene graph node as not in use. */
  643. int scegra_disable_node(int index) {
  644. ScegraNode * node = scegra_get_node(index);
  645. if (!node) return -2;
  646. scegranode_done(node);
  647. return node->id = -1;
  648. }
  649. /* Initializes the node as a box. */
  650. int scegra_make_box(int id, BeVec pos, BeVec siz, BeVec round, ScegraStyle style) {
  651. ScegraNode * node = scegra_get_node(id);
  652. if (!node) return -2;
  653. scegranode_init_box(node, id, pos, siz, round, style);
  654. return node->id;
  655. }
  656. /* Initialies the node at index as a text. Text can only span one line and must be short.
  657. Line wrapping must be implemented by making many text nodes for every line of text. */
  658. int scegra_make_text(int id, BeVec pos, BeVec siz, const char * text, ScegraStyle style) {
  659. ScegraNode * node = scegra_get_node(id);
  660. if (!node) return -2;
  661. scegranode_init_text(node, id, pos, siz, text, style);
  662. return node->id;
  663. }
  664. /* Initialies the node at index as a long text. Long text is arbitrary size and will
  665. * wrap automatically to the width of the scegra element. */
  666. int scegra_make_longtext(int id, BeVec pos, BeVec siz, char * text, ScegraStyle style) {
  667. ScegraNode * node = scegra_get_node(id);
  668. if (!node) return -2;
  669. scegranode_init_longtext(node, id, pos, siz, text, style);
  670. return node->id;
  671. }
  672. /* Initializes the node at index as an image node. */
  673. int scegra_make_image(int id, BeVec pos, BeVec siz, int image_id, ScegraStyle style) {
  674. ScegraNode * node = scegra_get_node(id);
  675. if (!node) return -2;
  676. scegranode_init_image(node, id, pos, siz, image_id, style);
  677. return node->id;
  678. }
  679. /* Gets the style of the scegra object, or if not active, gets a default style. */
  680. ScegraStyle scegra_get_style(int sindex) {
  681. ScegraStyle style;
  682. ScegraNode * snode = scegra_get_node(sindex);
  683. if (snode && (snode->id >= 0)) {
  684. style = snode->style;
  685. } else {
  686. scegrastyle_initempty(&style);
  687. }
  688. return style;
  689. }
  690. /* Initializes the node as a box with a style copied from the node at sindex,
  691. * or if that is not in use, a default style. */
  692. int scegra_make_box_style_from(int id, BeVec pos, BeVec siz, BeVec round, int sindex) {
  693. return scegra_make_box(id, pos, siz, round, scegra_get_style(sindex));
  694. }
  695. /* Initializes the node as a text with a style copied from the node at sindex,
  696. * or if that is not in use, a default style. */
  697. int scegra_make_text_style_from(int id, BeVec pos, BeVec siz, const char * text, int sindex) {
  698. return scegra_make_text(id, pos, siz, text, scegra_get_style(sindex));
  699. }
  700. /* Initializes the node as a text long with a style copied from the node at sindex,
  701. * or if that is not in use, a default style. */
  702. int scegra_make_longtext_style_from(int id, BeVec pos, BeVec siz, const char * text, int sindex) {
  703. return scegra_make_longtext(id, pos, siz, (char *)text, scegra_get_style(sindex));
  704. }
  705. /* Initializes the node as a image with a style copied from the node at sindex,
  706. * or if that is not in use, a default style. */
  707. int scegra_make_image_style_from(int id, BeVec pos, BeVec siz, int image_id, int sindex) {
  708. return scegra_make_image(id, pos, siz, image_id, scegra_get_style(sindex));
  709. }
  710. /* Returns the Z level of the scene graph node at index. -1 means it's free,
  711. *-2 means out of range. */
  712. int scegra_z(int index) {
  713. ScegraNode * node = scegra_get_node(index);
  714. if (!node) return -2;
  715. if (node->id < 0) return -1;
  716. return node->z;
  717. }
  718. /* Sets the Z level of the scene graph node at index. -1 means it's free,
  719. *-2 means out of range. */
  720. int scegra_z_(int index, int z) {
  721. ScegraNode * node = scegra_get_node(index);
  722. if (!node) return -2;
  723. if (node->id < 0) return -1;
  724. return node->z = z;
  725. }
  726. /* Sets the FG color of the scegra node (used to draw, e.g. text or lines (but not borders) */
  727. int scegra_color_(int index, int r, int g, int b, int a) {
  728. ScegraNode * node = scegra_get_node(index);
  729. if (!node) return -2;
  730. if (node->id < 0) return -1;
  731. node->style.color = al_map_rgba(r, g, b, a);
  732. return node->z;
  733. }
  734. /* Sets the border color of the scegra node (used to draw, e.g. text or lines (but not borders) */
  735. int scegra_border_color_(int index, int r, int g, int b, int a) {
  736. ScegraNode * node = scegra_get_node(index);
  737. if (!node) return -2;
  738. if (node->id < 0) return -1;
  739. node->style.border_color = al_map_rgba(r, g, b, a);
  740. return node->z;
  741. }
  742. /* Sets the background color of the scegra node (used to draw, e.g. text or lines (but not borders) */
  743. int scegra_background_color_(int index, int r, int g, int b, int a) {
  744. ScegraNode * node = scegra_get_node(index);
  745. if (!node) return -2;
  746. if (node->id < 0) return -1;
  747. node->style.background_color = al_map_rgba(r, g, b, a);
  748. return node->z;
  749. }
  750. /* Sets the border thickness. Set 0 or negative to disable border. */
  751. int scegra_border_thickness_(int index, float t) {
  752. ScegraNode * node = scegra_get_node(index);
  753. if (!node) return -2;
  754. if (node->id < 0) return -1;
  755. node->style.border_thickness = t;
  756. return node->z;
  757. }
  758. /* Sets the margin. Set 0 or negative to disable border. */
  759. int scegra_margin_(int index, float m) {
  760. ScegraNode * node = scegra_get_node(index);
  761. if (!node) return -2;
  762. if (node->id < 0) return -1;
  763. node->style.margin = m;
  764. return node->z;
  765. }
  766. /* Sets the scegra node's position. */
  767. int scegra_position_(int index, float x, float y) {
  768. ScegraNode * node = scegra_get_node(index);
  769. if (!node) return -2;
  770. if (node->id < 0) return -1;
  771. node->pos = bevec(x, y);
  772. return node->z;
  773. }
  774. /* Sets the scegra node's size. */
  775. int scegra_size_(int index, float w, float h) {
  776. ScegraNode * node = scegra_get_node(index);
  777. if (!node) return -2;
  778. if (node->id < 0) return -1;
  779. node->size = bevec(w, h);
  780. return node->z;
  781. }
  782. /* Sets the scegra node's speed. */
  783. int scegra_speed_(int index, float x, float y) {
  784. ScegraNode * node = scegra_get_node(index);
  785. if (!node) return -2;
  786. if (node->id < 0) return -1;
  787. node->speed = bevec(x, y);
  788. return node->z;
  789. }
  790. /* Sets the scegra node's background image id . */
  791. int scegra_background_image_id_(int index, int rindex) {
  792. ScegraNode * node = scegra_get_node(index);
  793. if (!node) return -2;
  794. if (node->id < 0) return -1;
  795. node->style.background_image_id = rindex;
  796. return node->z;
  797. }
  798. /* Sets the scegra node's background font id . */
  799. int scegra_font_id_(int index, int rindex) {
  800. ScegraNode * node = scegra_get_node(index);
  801. if (!node) return -2;
  802. if (node->id < 0) return -1;
  803. node->style.font_id = rindex;
  804. return node->z;
  805. }
  806. /* Sets the scegra node's foreground image id . */
  807. int scegra_image_id_(int index, int rindex) {
  808. ScegraNode * node = scegra_get_node(index);
  809. if (!node) return -2;
  810. if (node->id < 0) return -1;
  811. node->data.bitmap.image_id = rindex;
  812. return node->z;
  813. }
  814. /* Sets the scegra node to be visible or hidden depending on is_visible. */
  815. int scegra_visible_(int index, int is_visible) {
  816. int result;
  817. ScegraNode * node = scegra_get_node(index);
  818. if (!node) return -2;
  819. if (node->id < 0) return -1;
  820. result = flags_get(node->flags, SCEGRA_NODE_HIDE) ? 1 : 0;
  821. flags_put(&node->flags, SCEGRA_NODE_HIDE, !is_visible);
  822. return result;
  823. }
  824. /* Sets the scegra node's drawing angle for images. */
  825. int scegra_angle_(int index, float angle) {
  826. ScegraNode * node = scegra_get_node(index);
  827. if (!node) return -2;
  828. if (node->id < 0) return -1;
  829. node->data.bitmap.angle = angle;
  830. return node->z;
  831. }
  832. /* Sets the scegra node's drawing flags for images. */
  833. int scegra_image_flags_(int index, int flags) {
  834. ScegraNode * node = scegra_get_node(index);
  835. if (!node) return -2;
  836. if (node->id < 0) return -1;
  837. node->style.image_flags = flags;
  838. return node->z;
  839. }
  840. /* Sets the scegra node's drawing flags for texts. */
  841. int scegra_text_flags_(int index, int flags) {
  842. ScegraNode * node = scegra_get_node(index);
  843. if (!node) return -2;
  844. if (node->id < 0) return -1;
  845. node->style.text_flags = flags;
  846. return node->z;
  847. }
  848. /* Updates the scegra node's text if it is a text or longtext. Returns the node's z value
  849. * on sucess or negative on failure, if it is not a text or longtext node. */
  850. int scegra_text_(int index, const char * text) {
  851. ScegraNode * node = scegra_get_node(index);
  852. if (!node) return -2;
  853. if (node->id < 0) return -1;
  854. if (node->kind == SCEGRA_NODE_TEXT) {
  855. strncpy(node->data.text.text, text, SCEGRA_TEXT_MAX);
  856. } else if (node->kind == SCEGRA_NODE_LONGTEXT) {
  857. scegranode_longtext_done(node);
  858. scegranode_set_longtext_text(node, text);
  859. } else {
  860. return -3;
  861. }
  862. return node->z;
  863. }
  864. /* Somewhat unrelated, show or hide the system mouse cursor.
  865. * Returns the state after calling, true means show, false means not shown.
  866. */
  867. int scegra_show_system_mouse_cursor(int show) {
  868. ALLEGRO_DISPLAY * display;
  869. display = al_get_current_display();
  870. if(!display) return FALSE;
  871. if (show) {
  872. return al_show_mouse_cursor(display);
  873. } else {
  874. return (!al_hide_mouse_cursor(display));
  875. }
  876. }
  877. /** Gets the speed of the scregra node. Returns negative on error. */
  878. int scegra_speed(int index, float * x, float * y) {
  879. ScegraNode * node = scegra_get_node(index);
  880. if (!x || !y) return -3;
  881. if (!node) return -2;
  882. if (node->id < 0) return -1;
  883. (*x) = node->speed.x;
  884. (*y) = node->speed.y;
  885. return node->z;
  886. }
  887. /** Gets the size of the scregra node. Returns negative on error. */
  888. int scegra_size(int index, float * w, float * h) {
  889. ScegraNode * node = scegra_get_node(index);
  890. if (!w || !h) return -3;
  891. if (!node) return -2;
  892. if (node->id < 0) return -1;
  893. (*w) = node->size.x;
  894. (*h) = node->size.y;
  895. return node->z;
  896. }
  897. int scegra_position(int index, float *x, float * y) {
  898. /** Gets the positiob of the scregra node. Returns negative on error. */
  899. ScegraNode * node = scegra_get_node(index);
  900. if (!x || !y) return -3;
  901. if (!node) return -2;
  902. if (node->id < 0) return -1;
  903. (*x) = node->pos.x;
  904. (*y) = node->pos.y;
  905. return node->z;
  906. }
  907. int scegra_border_thickness(int index, float * t);
  908. int scegra_background_color(int index, int * r, int * g,int * b,int * a);
  909. int scegra_border_color(int index,int * r,int * g,int * b, int * a);
  910. int scegra_color(int index, int * r, int * g, int * b,int * a);
  911. /** Returns the natural size of the bitmap of the image. Will be
  912. * set to -1 if the bitmap isn't loaded yet.
  913. */
  914. int scegra_image_bitmap_size(int index, int * w, int * h) {
  915. int image_id;
  916. ScegraNode * node = scegra_get_node(index);
  917. if (!w || !h) return -3;
  918. if (!node) return -2;
  919. if (node->id < 0) return -1;
  920. image_id = node->data.bitmap.image_id;
  921. if(!store_get_bitmap_width(image_id, w)) (*w) = -1;
  922. if(!store_get_bitmap_height(image_id, h)) (*h) = -1;
  923. return node->z;
  924. }
  925. /** Sets the last line to display for a long text */
  926. int scegra_line_stop_(int index, int stop) {
  927. ScegraNode * node = scegra_get_node(index);
  928. if (!node) return -2;
  929. if (node->id < 0) return -1;
  930. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  931. node->data.longtext.line_stop = stop;
  932. return node->z;
  933. }
  934. /** Sets the first line to display for a long text */
  935. int scegra_line_start_(int index, int start) {
  936. ScegraNode * node = scegra_get_node(index);
  937. if (!node) return -2;
  938. if (node->id < 0) return -1;
  939. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  940. node->data.longtext.line_start = start;
  941. return node->z;
  942. }
  943. /** Sets display delay between individual characters for a long text */
  944. int scegra_delay_(int index, double delay) {
  945. ScegraNode * node = scegra_get_node(index);
  946. if (!node) return -2;
  947. if (node->id < 0) return -1;
  948. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  949. node->delay = delay;
  950. return node->z;
  951. }
  952. /** Gets the last line to display for a long text or negative on error*/
  953. int scegra_line_stop(int index) {
  954. ScegraNode * node = scegra_get_node(index);
  955. if (!node) return -2;
  956. if (node->id < 0) return -1;
  957. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  958. return node->data.longtext.line_stop;
  959. }
  960. /** Gets the first line to display for a long text */
  961. int scegra_line_start(int index) {
  962. ScegraNode * node = scegra_get_node(index);
  963. if (!node) return -2;
  964. if (node->id < 0) return -1;
  965. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  966. return node->data.longtext.line_start;
  967. }
  968. /** Gets display delay between individual characters for a long text */
  969. double scegra_delay(int index) {
  970. ScegraNode * node = scegra_get_node(index);
  971. if (!node) return -2;
  972. if (node->id < 0) return -1;
  973. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  974. return node->delay;
  975. }
  976. /** Sets amount of shown lines for a long text */
  977. int scegra_page_lines_(int index, int lines) {
  978. ScegraNode * node = scegra_get_node(index);
  979. if (!node) return -2;
  980. if (node->id < 0) return -1;
  981. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  982. node->data.longtext.page_lines = lines;
  983. return node->z;
  984. }
  985. /** Gets amount of lines for a "page" of long text */
  986. int scegra_page_lines(int index) {
  987. ScegraNode * node = scegra_get_node(index);
  988. if (!node) return -2;
  989. if (node->id < 0) return -1;
  990. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  991. return node->data.longtext.page_lines;
  992. }
  993. /** Sets paused state of long text */
  994. int scegra_paused_(int index, int paused) {
  995. ScegraNode * node = scegra_get_node(index);
  996. if (!node) return -2;
  997. if (node->id < 0) return -1;
  998. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  999. node->data.longtext.paused = paused;
  1000. return node->z;
  1001. }
  1002. /** Gets paused state of long text */
  1003. int scegra_paused(int index) {
  1004. ScegraNode * node = scegra_get_node(index);
  1005. if (!node) return -2;
  1006. if (node->id < 0) return -1;
  1007. if (node->kind != SCEGRA_NODE_LONGTEXT) return -3;
  1008. return node->data.longtext.paused;
  1009. }
  1010. /** Gets the current text page for a longtext. */
  1011. int scegra_page(int index) {
  1012. ScegraNode * node = scegra_get_node(index);
  1013. return scegranode_page(node);
  1014. }
  1015. /** Gets the number of the last text page for a longtext. */
  1016. int scegra_last_page(int index) {
  1017. ScegraNode * node = scegra_get_node(index);
  1018. return scegranode_last_page(node);
  1019. }
  1020. /** Returns nonzero if the long text is at the end of it's display. */
  1021. int scegra_at_end(int index) {
  1022. ScegraNode * node = scegra_get_node(index);
  1023. return scegranode_longtext_at_end(node);
  1024. }
  1025. /** Advances long text to the given page. Automatically unpauses as well. */
  1026. int scegra_page_(int index, int page) {
  1027. ScegraNode * node = scegra_get_node(index);
  1028. return scegranode_page_(node, page);
  1029. }
  1030. /** Advances long text to the next page. Automatically unpauses as well. */
  1031. int scegra_next_page(int index) {
  1032. int page = scegra_page(index);
  1033. if (page < 0) return page;
  1034. return scegra_page_(index, page + 1);
  1035. }
  1036. /** Advances long text to the previous page. Automatically unpauses as well. */
  1037. int scegra_previous_page(int index) {
  1038. int page = scegra_page(index);
  1039. if (page < 0) return page;
  1040. return scegra_page_(index, page - 1);
  1041. }
  1042. /*
  1043. void scegra_drawframe(ScegraNode * self) {
  1044. draw_frame(self->box.at.x, self->box.at.y,
  1045. self->box.size.x, self->box.size.y,
  1046. self->style.bordersize, self->style.forecolor,
  1047. self->style.backcolor);
  1048. }
  1049. void scegra_drawroundframe(ScegraNode * self) {
  1050. draw_roundframe(self->box.at.x , self->box.at.y,
  1051. self->box.size.x, self->box.size.y,
  1052. self->style.bordersize, self->style.forecolor,
  1053. self->style.backcolor);
  1054. }
  1055. */
  1056. /*
  1057. * ALLEGRO drawing functions:
  1058. *
  1059. al_draw_arc (3) - Allegro 5 API
  1060. al_draw_bitmap (3) - Allegro 5 API
  1061. al_draw_bitmap_region (3) - Allegro 5 API
  1062. al_draw_circle (3) - Allegro 5 API
  1063. al_draw_ellipse (3) - Allegro 5 API
  1064. al_draw_elliptical_arc (3) - Allegro 5 API
  1065. al_draw_filled_circle (3) - Allegro 5 API
  1066. al_draw_filled_ellipse (3) - Allegro 5 API
  1067. al_draw_filled_pieslice (3) - Allegro 5 API
  1068. al_draw_filled_polygon (3) - Allegro 5 API
  1069. al_draw_filled_polygon_with_holes (3) - Allegro 5 API
  1070. al_draw_filled_rectangle (3) - Allegro 5 API
  1071. al_draw_filled_rounded_rectangle (3) - Allegro 5 API
  1072. al_draw_filled_triangle (3) - Allegro 5 API
  1073. al_draw_indexed_prim (3) - Allegro 5 API
  1074. al_draw_justified_text (3) - Allegro 5 API
  1075. al_draw_justified_textf (3) - Allegro 5 API
  1076. al_draw_justified_ustr (3) - Allegro 5 API
  1077. q (3) - Allegro 5 API
  1078. al_draw_pieslice (3) - Allegro 5 API
  1079. al_draw_pixel (3) - Allegro 5 API
  1080. al_draw_polygon (3) - Allegro 5 API
  1081. al_draw_polygon_with_holes (3) - Allegro 5 API
  1082. al_draw_polyline (3) - Allegro 5 API
  1083. al_draw_polyline_ex (3) - Allegro 5 API
  1084. al_draw_prim (3) - Allegro 5 API
  1085. al_draw_rectangle (3) - Allegro 5 API
  1086. al_draw_ribbon (3) - Allegro 5 API
  1087. al_draw_rotated_bitmap (3) - Allegro 5 API
  1088. al_draw_rounded_rectangle (3) - Allegro 5 API
  1089. al_draw_scaled_bitmap (3) - Allegro 5 API
  1090. al_draw_scaled_rotated_bitmap (3) - Allegro 5 API
  1091. al_draw_soft_line (3) - Allegro 5 API
  1092. al_draw_soft_triangle (3) - Allegro 5 API
  1093. al_draw_spline (3) - Allegro 5 API
  1094. al_draw_text (3) - Allegro 5 API
  1095. al_draw_textf (3) - Allegro 5 API
  1096. al_draw_tinted_bitmap (3) - Allegro 5 API
  1097. al_draw_tinted_bitmap_region (3) - Allegro 5 API
  1098. al_draw_tinted_rotated_bitmap (3) - Allegro 5 API
  1099. al_draw_tinted_scaled_bitmap (3) - Allegro 5 API
  1100. al_draw_tinted_scaled_rotated_bitmap (3) - Allegro 5 API
  1101. al_draw_tinted_scaled_rotated_bitm... (3) - Allegro 5 API
  1102. al_draw_triangle (3) - Allegro 5 API
  1103. al_draw_ustr (3) - Allegro 5 API
  1104. al_draw_vertex_buffer (3) - Allegro 5 API
  1105. So the most important drawing functions I'll implement and
  1106. group together are:
  1107. * Circle / arc drawing and Ellipse / elliptical arc drawing.
  1108. * Rectangle drawing and Rounded rectangle drawing.
  1109. * Triangle drawing.
  1110. * Polygon drawing.
  1111. * Line drawing.
  1112. * Point drawing.
  1113. * Spline Drawing.
  1114. * Bitmap Drawing.
  1115. */
  1116. #define TUPLE(A,B) tuple_##A##B
  1117. #define DEFINE_TUPLE(A, B) typedef struct TUPLE(A,B) { A head; B tail; } TUPLE(A,B)
  1118. #define TUPLE_HEAD(T) (T).head
  1119. #define TUPLE_TAIL(T) (T).tail
  1120. #define TUPLEPTR_HEAD(T) (T)->head
  1121. #define TUPLEPTR_TAIL(T) (T)->tail
  1122. typedef char * charp;
  1123. DEFINE_TUPLE(int, charp);