1 /*
2 * Draws fretwork
3 *
4 * Last updated: 2019-08-29
5 */
6
7 #include "tp_magic_api.h"
8 #include "SDL_image.h"
9 #include "SDL_mixer.h"
10 #include <stdbool.h>
11
12 #define SEG_NONE 0
13
14 #define SEG_LEFT 1
15 #define SEG_RIGHT 2
16 #define SEG_TOP 4
17 #define SEG_BOTTOM 8
18
19 #define SEG_LEFT_RIGHT (SEG_LEFT | SEG_RIGHT)
20 #define SEG_TOP_BOTTOM (SEG_TOP | SEG_BOTTOM)
21 #define SEG_RIGHT_TOP (SEG_RIGHT | SEG_TOP)
22 #define SEG_RIGHT_BOTTOM (SEG_RIGHT | SEG_BOTTOM)
23 #define SEG_LEFT_TOP (SEG_LEFT | SEG_TOP)
24 #define SEG_LEFT_BOTTOM (SEG_LEFT | SEG_BOTTOM)
25 #define SEG_LEFT_RIGHT_TOP (SEG_LEFT | SEG_RIGHT | SEG_TOP)
26 #define SEG_LEFT_RIGHT_BOTTOM (SEG_LEFT | SEG_RIGHT | SEG_BOTTOM)
27 #define SEG_LEFT_TOP_BOTTOM (SEG_LEFT | SEG_TOP | SEG_BOTTOM)
28 #define SEG_RIGHT_TOP_BOTTOM (SEG_RIGHT | SEG_TOP | SEG_BOTTOM)
29 #define SEG_LEFT_RIGHT_TOP_BOTTOM (SEG_LEFT | SEG_RIGHT | SEG_TOP | SEG_BOTTOM)
30
31 Mix_Chunk *fretwork_snd;
32 unsigned int img_w, img_h;
33 unsigned int fretwork_segments_x, fretwork_segments_y; //how many segments do we have?
34 inline int fretwork_math_ceil(int x, int y); //ceil() in cstdlib returns float and is relative slow, so we'll use our one
35 static Uint8 *fretwork_status_of_segments; //a place to store an info about bitmap used for selected segment
36 static char **fretwork_images; //the pathes to all the images needed
37 static unsigned int fretwork_segment_modified; //which segment was modified this time?
38 static unsigned int fretwork_segment_modified_last = 0; //which segment was last modified
39 static unsigned int fretwork_segment_to_add = 0; //a segment that should be added to solve corner joint
40 static unsigned int fretwork_segment_last_clicked;
41 static Uint8 fretwork_r, fretwork_g, fretwork_b;
42 static unsigned int fretwork_full_runs; //The count of the clicks in full mode
43 static unsigned int fretwork_segment_start_rectangle; //the segment were the update_rectangle will start
44 static unsigned int fretwork_update_rectangle_width; //the width of the update_rectangle
45 static unsigned int fretwork_update_rectangle_height; //the height of the update_rectangle
46 static SDL_Rect modification_rect;
47 static SDL_Surface *canvas_backup;
48 static SDL_Surface *fretwork_one_back, *fretwork_three_back, *fretwork_four_back, *fretwork_corner_back;
49
50
51 // Housekeeping functions
52
53 Uint32 fretwork_api_version(void);
54 int fretwork_modes(magic_api * api, int which);
55 void fretwork_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
56 static void fretwork_colorize(magic_api * api, SDL_Surface * dest, SDL_Surface * src);
57 int fretwork_init(magic_api * api);
58 int fretwork_get_tool_count(magic_api * api);
59 SDL_Surface *fretwork_get_icon(magic_api * api, int which);
60 char *fretwork_get_name(magic_api * api, int which);
61 char *fretwork_get_description(magic_api * api, int which, int mode);
62 int fretwork_requires_colors(magic_api * api, int which);
63 void fretwork_release(magic_api * api, int which,
64 SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect);
65 void fretwork_shutdown(magic_api * api);
66 void fretwork_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot);
67 void fretwork_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas, SDL_Surface * snapshot);
68 inline void fretwork_extract_coords_from_segment(unsigned int segment, Sint16 * x, Sint16 * y);
69 void fretwork_click(magic_api * api, int which, int mode,
70 SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect);
71
72
73
74 void fretwork_drag(magic_api * api, int which, SDL_Surface * canvas,
75 SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect);
76 static void fretwork_draw_wrapper(void *ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y);
77 inline unsigned int fretwork_get_segment(int x, int y);
78
79
80 SDL_Surface *fretwork_one, *fretwork_three, *fretwork_four, *fretwork_corner;
81
fretwork_api_version(void)82 Uint32 fretwork_api_version(void)
83 {
84 return (TP_MAGIC_API_VERSION);
85 }
86
fretwork_modes(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)87 int fretwork_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
88 {
89 return (MODE_PAINT | MODE_FULLSCREEN);
90 }
91
fretwork_set_color(magic_api * api,Uint8 r,Uint8 g,Uint8 b)92 void fretwork_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b)
93 {
94 fretwork_r = r;
95 fretwork_g = g;
96 fretwork_b = b;
97 fretwork_colorize(api, fretwork_one, fretwork_one_back);
98 fretwork_colorize(api, fretwork_three, fretwork_three_back);
99 fretwork_colorize(api, fretwork_four, fretwork_four_back);
100 fretwork_colorize(api, fretwork_corner, fretwork_corner_back);
101 }
102
103 /* Adapted from flower.c */
fretwork_colorize(magic_api * api,SDL_Surface * dest,SDL_Surface * src)104 static void fretwork_colorize(magic_api * api, SDL_Surface * dest, SDL_Surface * src)
105 {
106 int x, y;
107 Uint8 r, g, b, a;
108
109 SDL_LockSurface(src);
110 SDL_LockSurface(dest);
111
112 for (y = 0; y < src->h; y++)
113 {
114 for (x = 0; x < src->w; x++)
115 {
116 SDL_GetRGBA(api->getpixel(src, x, y), src->format, &r, &g, &b, &a);
117
118 api->putpixel(dest, x, y, SDL_MapRGBA(dest->format, fretwork_r, fretwork_g, fretwork_b, a));
119 }
120 }
121
122 SDL_UnlockSurface(src);
123 SDL_UnlockSurface(dest);
124 }
125
126
fretwork_init(magic_api * api)127 int fretwork_init(magic_api * api)
128 {
129 char fname[1024];
130 Uint8 i; //is always < 4, so Uint8 seems to be a good idea
131
132 fretwork_images = (char **)malloc(sizeof(char *) * 4);
133
134 for (i = 0; i < 4; i++)
135 fretwork_images[i] = (char *)malloc(sizeof(char) * 1024);
136
137 snprintf(fretwork_images[0], 1024 * sizeof(char), "%s/images/magic/fretwork_one.png", api->data_directory);
138 snprintf(fretwork_images[1], 1024 * sizeof(char), "%s/images/magic/fretwork_three.png", api->data_directory);
139 snprintf(fretwork_images[2], 1024 * sizeof(char), "%s/images/magic/fretwork_four.png", api->data_directory);
140 snprintf(fretwork_images[3], 1024 * sizeof(char), "%s/images/magic/fretwork_corner.png", api->data_directory);
141
142 fretwork_one = IMG_Load(fretwork_images[0]);
143 fretwork_three = IMG_Load(fretwork_images[1]);
144 fretwork_four = IMG_Load(fretwork_images[2]);
145 fretwork_corner = IMG_Load(fretwork_images[3]);
146 fretwork_one_back = IMG_Load(fretwork_images[0]);
147 fretwork_three_back = IMG_Load(fretwork_images[1]);
148 fretwork_four_back = IMG_Load(fretwork_images[2]);
149 fretwork_corner_back = IMG_Load(fretwork_images[3]);
150
151 img_w = fretwork_one->w;
152 img_h = fretwork_one->h;
153
154 snprintf(fname, sizeof(fname), "%s/sounds/magic/fretwork.ogg", api->data_directory);
155 fretwork_snd = Mix_LoadWAV(fname);
156
157 return (1);
158 }
159
fretwork_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)160 int fretwork_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
161 {
162 return 1;
163 }
164
fretwork_get_icon(magic_api * api,int which ATTRIBUTE_UNUSED)165 SDL_Surface *fretwork_get_icon(magic_api * api, int which ATTRIBUTE_UNUSED)
166 {
167 char fname[1024];
168
169 snprintf(fname, sizeof(fname), "%s/images/magic/fretwork.png", api->data_directory);
170
171 return (IMG_Load(fname));
172 }
173
fretwork_get_name(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)174 char *fretwork_get_name(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
175 {
176 return strdup(gettext_noop("Fretwork"));
177 }
178
fretwork_get_description(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode)179 char *fretwork_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode)
180 {
181 if (mode == MODE_PAINT)
182 return strdup(gettext_noop("Click and drag to draw repetitive patterns. "));
183 else
184 return strdup(gettext_noop("Click to surround your picture with repetitive patterns."));
185 }
186
fretwork_requires_colors(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)187 int fretwork_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
188 {
189 return 1;
190 }
191
fretwork_release(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED,SDL_Surface * snapshot ATTRIBUTE_UNUSED,int x ATTRIBUTE_UNUSED,int y ATTRIBUTE_UNUSED,SDL_Rect * update_rect ATTRIBUTE_UNUSED)192 void fretwork_release(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED,
193 SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * snapshot ATTRIBUTE_UNUSED,
194 int x ATTRIBUTE_UNUSED, int y ATTRIBUTE_UNUSED, SDL_Rect * update_rect ATTRIBUTE_UNUSED)
195 {
196 }
197
fretwork_shutdown(magic_api * api ATTRIBUTE_UNUSED)198 void fretwork_shutdown(magic_api * api ATTRIBUTE_UNUSED)
199 {
200 Uint8 i;
201
202 if (fretwork_snd != NULL)
203 Mix_FreeChunk(fretwork_snd);
204 SDL_FreeSurface(fretwork_one);
205 SDL_FreeSurface(fretwork_three);
206 SDL_FreeSurface(fretwork_four);
207 SDL_FreeSurface(fretwork_corner);
208 SDL_FreeSurface(fretwork_one_back);
209 SDL_FreeSurface(fretwork_three_back);
210 SDL_FreeSurface(fretwork_four_back);
211 SDL_FreeSurface(fretwork_corner_back);
212 SDL_FreeSurface(canvas_backup);
213
214 for (i = 0; i < 4; i++)
215 free(fretwork_images[i]);
216 free(fretwork_images);
217 if (fretwork_status_of_segments != NULL)
218 free(fretwork_status_of_segments);
219 }
220
fretwork_switchin(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * snapshot ATTRIBUTE_UNUSED)221 void fretwork_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
222 SDL_Surface * canvas, SDL_Surface * snapshot ATTRIBUTE_UNUSED)
223 {
224 //we've to compute the quantity of segments in each direction
225
226 canvas_backup = SDL_CreateRGBSurface(SDL_ANYFORMAT, canvas->w, canvas->h, canvas->format->BitsPerPixel,
227 canvas->format->Rmask, canvas->format->Gmask, canvas->format->Bmask,
228 canvas->format->Amask);
229
230 SDL_BlitSurface(canvas, NULL, canvas_backup, NULL);
231 fretwork_segments_x = fretwork_math_ceil(canvas->w, img_w);
232 fretwork_segments_y = fretwork_math_ceil(canvas->h, img_h);
233 fretwork_status_of_segments = (Uint8 *) calloc(fretwork_segments_x * fretwork_segments_y + 1, sizeof(Uint8)); //segments starts at 1, while fretwork_status_of_segments[] starts at 0
234 fretwork_full_runs = 1;
235 }
236
237
fretwork_switchout(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED,SDL_Surface * snapshot ATTRIBUTE_UNUSED)238 void fretwork_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
239 SDL_Surface * canvas ATTRIBUTE_UNUSED, SDL_Surface * snapshot ATTRIBUTE_UNUSED)
240 {
241 free(fretwork_status_of_segments);
242 fretwork_status_of_segments = NULL;
243 }
244
245 // Interactivity functions
246
247
fretwork_math_ceil(int x,int y)248 inline int fretwork_math_ceil(int x, int y)
249 {
250 int temp;
251
252 temp = (int)x / y;
253 if (x % y)
254 return temp + 1;
255 else
256 return temp;
257 }
258
fretwork_get_segment(int x,int y)259 inline unsigned int fretwork_get_segment(int x, int y)
260 {
261 int xx; //segments are numerated just like pixels
262 int yy; //in computer graphics: left upper (=1), ... ,right upper,
263
264 //left bottom, ... , right bottom
265 xx = fretwork_math_ceil(x, img_w);
266 yy = fretwork_math_ceil(y, img_h);
267
268 return (yy - 1) * fretwork_segments_x + xx;
269 }
270
fretwork_extract_coords_from_segment(unsigned int segment,Sint16 * x,Sint16 * y)271 inline void fretwork_extract_coords_from_segment(unsigned int segment, Sint16 * x, Sint16 * y)
272 {
273 *x = ((segment % fretwork_segments_x) - 1) * img_w; //useful to set update_rect as small as possible
274 *y = (int)(segment / fretwork_segments_x) * img_h;
275 }
276
277 /* static void fretwork_flip(void * ptr, SDL_Surface * dest, SDL_Surface * src) */
278 /* { */
279 /* magic_api * api = (magic_api *) ptr; */
280
281 /* Sint16 x, y; */
282
283 /* for (x=0; x<dest->w; x++) */
284 /* for (y=0; y<dest->h; y++) */
285 /* api->putpixel(dest, x, y, api->getpixel(src, x, src->h-y)); */
286 /* } */
287
fretwork_flip_flop(void * ptr,SDL_Surface * dest,SDL_Surface * src)288 static void fretwork_flip_flop(void *ptr, SDL_Surface * dest, SDL_Surface * src)
289 {
290 magic_api *api = (magic_api *) ptr;
291 Sint16 x, y;
292
293 for (x = 0; x < dest->w; x++)
294 for (y = 0; y < dest->h; y++)
295 api->putpixel(dest, dest->w - 1 - x, dest->h - 1 - y, api->getpixel(src, x, y));
296 }
297
fretwork_rotate(void * ptr,SDL_Surface * dest,SDL_Surface * src,_Bool direction)298 static void fretwork_rotate(void *ptr, SDL_Surface * dest, SDL_Surface * src, _Bool direction)
299 //src and dest must have same size
300 {
301 magic_api *api = (magic_api *) ptr;
302 Sint16 x, y;
303
304 if (direction) //rotate -90 degs
305 {
306 for (x = 0; x < dest->w; x++)
307 for (y = 0; y < dest->h; y++)
308 api->putpixel(dest, x, y, api->getpixel(src, y, src->h - 1 - x));
309 }
310 else //rotate +90 degs
311 {
312 for (x = 0; x < dest->w; x++)
313 for (y = 0; y < dest->h; y++)
314 api->putpixel(dest, x, y, api->getpixel(src, src->h - y - 1, x));
315 }
316
317 }
318
319
fretwork_click(magic_api * api,int which,int mode,SDL_Surface * canvas,SDL_Surface * snapshot,int x,int y,SDL_Rect * update_rect)320 void fretwork_click(magic_api * api, int which, int mode,
321 SDL_Surface * canvas, SDL_Surface * snapshot, int x, int y, SDL_Rect * update_rect)
322 {
323 int left_x, right_x, top_y, bottom_y;
324
325 fretwork_segment_modified_last = 0;
326 if (mode == MODE_PAINT)
327 {
328 fretwork_segment_last_clicked = fretwork_get_segment(x, y);
329 fretwork_drag(api, which, canvas, snapshot, x, y, x, y, update_rect);
330 }
331 else
332 {
333 if (fretwork_full_runs <= min(fretwork_segments_x, fretwork_segments_y) / 2)
334 {
335 left_x = img_w * fretwork_full_runs;
336 right_x = img_w * fretwork_segments_x - img_w * fretwork_full_runs;
337 top_y = img_h * fretwork_full_runs;
338 bottom_y = img_h * fretwork_segments_y - img_h * (fretwork_full_runs - 1);
339
340 //left line
341 api->line((void *)api, which, canvas, snapshot, left_x, top_y, left_x, bottom_y, img_w / 2,
342 fretwork_draw_wrapper);
343
344 //top line
345 api->line((void *)api, which, canvas, snapshot, left_x, top_y, right_x, top_y, img_w / 2,
346 fretwork_draw_wrapper);
347
348 //bottom line
349 api->line((void *)api, which, canvas, snapshot, left_x, bottom_y, right_x, bottom_y, img_w / 2,
350 fretwork_draw_wrapper);
351
352 //right line
353 api->line((void *)api, which, canvas, snapshot, right_x, top_y, right_x, bottom_y, img_w / 2,
354 fretwork_draw_wrapper);
355
356 fretwork_full_runs += 1;
357 update_rect->x = 0;
358 update_rect->y = 0;
359 update_rect->w = canvas->w;
360 update_rect->h = canvas->h;
361 }
362 }
363 }
364
fretwork_select_image(Uint16 segment)365 static Uint8 fretwork_select_image(Uint16 segment)
366 {
367 int take_up, take_down;
368 int val_up, val_down, val_left, val_right;
369 int from_top = 0, from_bottom = 0, from_left = 0, from_right = 0;
370 int from_top_right = 0, from_top_left = 0, from_bottom_right = 0, from_bottom_left = 0;
371 int TOP = 0, BOTTOM = 0, LEFT = 0, RIGHT = 0;
372
373 //Checking from were we come...
374 if (fretwork_segment_modified_last > 0)
375 {
376 if (segment == fretwork_segment_modified_last + 1)
377 from_left = 1;
378 else if (segment == fretwork_segment_modified_last - 1)
379 from_right = 1;
380 else if (segment == fretwork_segment_modified_last - fretwork_segments_x)
381 from_bottom = 1;
382 else if (segment == fretwork_segment_modified_last + fretwork_segments_x)
383 from_top = 1;
384
385 // Very very few cases will reach this, segments are joining by the corner
386 // We need to add a new segment to join by side, adding clockwise
387 else if (segment == fretwork_segment_modified_last + fretwork_segments_x + 1)
388 {
389 from_top_left = 1;
390 fretwork_segment_to_add = segment - fretwork_segments_x;
391 }
392 else if (segment == fretwork_segment_modified_last + fretwork_segments_x - 1)
393 {
394 from_top_right = 1;
395 fretwork_segment_to_add = segment + 1;
396 }
397 else if (segment == fretwork_segment_modified_last - fretwork_segments_x - 1)
398 {
399 from_bottom_right = 1;
400 fretwork_segment_to_add = segment + fretwork_segments_x;
401 }
402 else if (segment == fretwork_segment_modified_last - fretwork_segments_x + 1)
403 {
404 from_bottom_left = 1;
405 fretwork_segment_to_add = segment - 1;
406 }
407 }
408
409 take_up = segment - fretwork_segments_x;
410 if (take_up <= 0)
411 val_up = SEG_NONE;
412 else
413 val_up = fretwork_status_of_segments[take_up];
414
415 take_down = segment + fretwork_segments_x;
416 if (take_down > (signed)(fretwork_segments_x * fretwork_segments_y))
417 val_down = SEG_NONE;
418 else
419 val_down = fretwork_status_of_segments[take_down];
420
421 if ((segment % fretwork_segments_x) == 1)
422 val_left = SEG_NONE;
423 else
424 val_left = fretwork_status_of_segments[segment - 1];
425
426 if ((segment % fretwork_segments_x) == 0)
427 val_right = SEG_NONE;
428 else
429 val_right = fretwork_status_of_segments[segment + 1];
430
431 if (from_left || (val_left & SEG_RIGHT) || from_bottom_left)
432 {
433 LEFT = 1;
434 }
435 if (from_right || (val_right & SEG_LEFT) || from_top_right)
436 RIGHT = 1;
437 if (from_top || (val_up & SEG_BOTTOM) || from_top_left)
438 TOP = 1;
439 if (from_bottom || (val_down & SEG_TOP) || from_bottom_right)
440 BOTTOM = 1;
441
442
443 if (TOP && BOTTOM && LEFT && RIGHT)
444 return SEG_LEFT_RIGHT_TOP_BOTTOM;
445 if (LEFT && RIGHT && TOP)
446 return SEG_LEFT_RIGHT_TOP;
447 if (LEFT && RIGHT && BOTTOM)
448 return SEG_LEFT_RIGHT_BOTTOM;
449 if (TOP && BOTTOM && LEFT)
450 return SEG_LEFT_TOP_BOTTOM;
451 if (TOP && BOTTOM && RIGHT)
452 return SEG_RIGHT_TOP_BOTTOM;
453 if (LEFT && RIGHT)
454 return SEG_LEFT_RIGHT;
455 if (TOP && BOTTOM)
456 return SEG_TOP_BOTTOM;
457 if (LEFT && TOP)
458 return SEG_LEFT_TOP;
459 if (LEFT && BOTTOM)
460 return SEG_LEFT_BOTTOM;
461 if (RIGHT && TOP)
462 return SEG_RIGHT_TOP;
463 if (RIGHT && BOTTOM)
464 return SEG_RIGHT_BOTTOM;
465 if (LEFT | RIGHT)
466 return SEG_LEFT_RIGHT;
467 //if (TOP||BOTTOM)
468 return SEG_TOP_BOTTOM;
469 }
470
471
fretwork_draw(void * ptr,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last ATTRIBUTE_UNUSED,int x,int y ATTRIBUTE_UNUSED,unsigned int segment)472 static void fretwork_draw(void *ptr, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas,
473 SDL_Surface * last ATTRIBUTE_UNUSED, int x, int y ATTRIBUTE_UNUSED, unsigned int segment)
474 {
475 magic_api *api = (magic_api *) ptr;
476 SDL_Surface *result, *temp;
477 Uint8 image;
478 _Bool use_temp;
479
480 use_temp = 0;
481 if ((segment < 1) | (segment > fretwork_segments_x * fretwork_segments_y))
482 return;
483 fretwork_extract_coords_from_segment(segment, &modification_rect.x, &modification_rect.y);
484 modification_rect.h = img_w;
485 modification_rect.w = img_h;
486
487 image = fretwork_select_image(segment); //select the image to display
488
489 if (fretwork_status_of_segments[segment] == image)
490 return;
491
492 fretwork_status_of_segments[segment] = image; //and write it to global table
493
494 result = SDL_CreateRGBSurface(SDL_ANYFORMAT, img_w, img_h, fretwork_one->format->BitsPerPixel,
495 fretwork_one->format->Rmask, fretwork_one->format->Gmask, fretwork_one->format->Bmask,
496 fretwork_one->format->Amask);
497
498 temp = SDL_CreateRGBSurface(SDL_ANYFORMAT, img_w, img_h, fretwork_one->format->BitsPerPixel,
499 fretwork_one->format->Rmask, fretwork_one->format->Gmask, fretwork_one->format->Bmask,
500 fretwork_one->format->Amask);
501
502 SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
503
504 switch (image)
505 {
506 case 0:
507 case SEG_TOP_BOTTOM:
508 SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
509 SDL_BlitSurface(fretwork_one, NULL, result, NULL);
510 break;
511
512 case SEG_LEFT_RIGHT:
513 SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
514 fretwork_rotate(api, temp, fretwork_one, 1);
515 use_temp = 1;
516 break;
517
518 case SEG_LEFT_RIGHT_TOP_BOTTOM:
519 SDL_BlitSurface(canvas_backup, &modification_rect, result, NULL);
520 SDL_BlitSurface(fretwork_four, NULL, result, NULL);
521 break;
522
523 case SEG_LEFT_RIGHT_TOP:
524 SDL_BlitSurface(fretwork_three, NULL, result, NULL);
525 break;
526
527 case SEG_LEFT_RIGHT_BOTTOM:
528 fretwork_flip_flop(api, temp, fretwork_three);
529 use_temp = 1;
530 break;
531
532 case SEG_LEFT_TOP_BOTTOM:
533 fretwork_rotate(api, temp, fretwork_three, 0);
534 use_temp = 1;
535 break;
536
537 case SEG_RIGHT_TOP_BOTTOM:
538 fretwork_rotate(api, temp, fretwork_three, 1);
539 use_temp = 1;
540 break;
541
542 case SEG_RIGHT_TOP:
543 SDL_BlitSurface(fretwork_corner, NULL, result, NULL);
544 break;
545
546 case SEG_RIGHT_BOTTOM:
547 fretwork_rotate(api, temp, fretwork_corner, 1);
548 use_temp = 1;
549 break;
550
551 case SEG_LEFT_TOP:
552 fretwork_rotate(api, temp, fretwork_corner, 0);
553 use_temp = 1;
554 break;
555
556 case SEG_LEFT_BOTTOM:
557 fretwork_flip_flop(api, temp, fretwork_corner);
558 use_temp = 1;
559 break;
560 }
561
562 if (use_temp)
563 SDL_BlitSurface(temp, NULL, result, NULL);
564
565 SDL_FreeSurface(temp);
566 SDL_BlitSurface(result, NULL, canvas, &modification_rect);
567 SDL_FreeSurface(result);
568 api->playsound(fretwork_snd, (x * 255) / canvas->w, 255);
569 }
570
571
fretwork_draw_wrapper(void * ptr,int which,SDL_Surface * canvas,SDL_Surface * last,int x,int y)572 static void fretwork_draw_wrapper(void *ptr, int which, SDL_Surface * canvas, SDL_Surface * last, int x, int y)
573 {
574 fretwork_segment_modified = fretwork_get_segment(x, y);
575
576 fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_modified);
577
578 if (fretwork_segment_modified_last > 0)
579
580 {
581 fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_modified_last);
582 fretwork_extract_coords_from_segment(fretwork_segment_start_rectangle, &modification_rect.x,
583 &modification_rect.y);
584 modification_rect.w = fretwork_update_rectangle_width * img_w;
585 modification_rect.h = fretwork_update_rectangle_height * img_h;
586 }
587
588 if (fretwork_segment_to_add > 0)
589 {
590 fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_to_add);
591 fretwork_draw((void *)ptr, which, canvas, last, x, y, fretwork_segment_modified_last);
592 fretwork_segment_to_add = 0;
593 }
594
595 fretwork_segment_modified_last = fretwork_segment_modified;
596 }
597
fretwork_drag(magic_api * api,int which,SDL_Surface * canvas,SDL_Surface * snapshot,int ox,int oy,int x,int y,SDL_Rect * update_rect)598 void fretwork_drag(magic_api * api, int which,
599 SDL_Surface * canvas, SDL_Surface * snapshot, int ox, int oy, int x, int y, SDL_Rect * update_rect)
600 {
601 int start_x, end_x, start_y, end_y, segment_start, segment_end, w, h;
602
603 if ((x < canvas->w) && (y < canvas->h) && (ox < canvas->w) && (oy < canvas->h) && ((signed)x > 0) && ((signed)y > 0)
604 && ((signed)ox > 0) && ((signed)oy > 0))
605 {
606 api->line((void *)api, which, canvas, snapshot, ox, oy, x, y, img_w / 2, fretwork_draw_wrapper);
607 // This should be improved, maybe passed to fretwork_draw()
608 start_x = min(ox, x);
609 end_x = max(ox, x);
610 start_y = min(oy, y);
611 end_y = max(oy, y);
612 segment_start = fretwork_get_segment(start_x - img_w, start_y - img_h);
613 segment_end = fretwork_get_segment(end_x + img_w, end_y + img_h);
614
615 x = ((segment_start % fretwork_segments_x) - 1) * img_w;
616 y = (int)(segment_start / fretwork_segments_x) * img_h;
617 w = ((segment_end % fretwork_segments_x) - 1) * img_w - x + img_w;
618 h = (int)(segment_end / fretwork_segments_x) * img_h - y + img_h;
619
620 update_rect->x = x;
621 update_rect->y = y;
622 update_rect->w = w;
623 update_rect->h = h;
624 }
625
626 }
627