1 /*
2   shift.c
3 
4   Shift Magic Tool Plugin
5   Tux Paint - A simple drawing program for children.
6 
7   Copyright (c) 2002-2008 by Bill Kendrick and others; see AUTHORS.txt
8   bill@newbreedsoftware.com
9   http://www.tuxpaint.org/
10 
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2 of the License, or
14   (at your option) any later version.
15 
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20 
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24   (See COPYING.txt)
25 
26   Last updated: July 8, 2008
27   $Id$
28 */
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include "tp_magic_api.h"
33 #include "SDL_image.h"
34 #include "SDL_mixer.h"
35 
36 #include "math.h"
37 
38 /* Our globals: */
39 
40 static int shift_x, shift_y;
41 static Mix_Chunk *shift_snd;
42 
43 
44 /* Local function prototypes: */
45 
46 static void shift_doit(magic_api * api, int which, SDL_Surface * canvas,
47                        SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect, int crosshairs);
48 Uint32 shift_api_version(void);
49 int shift_init(magic_api * api);
50 int shift_get_tool_count(magic_api * api);
51 SDL_Surface *shift_get_icon(magic_api * api, int which);
52 char *shift_get_name(magic_api * api, int which);
53 char *shift_get_description(magic_api * api, int which, int mode);
54 void shift_drag(magic_api * api, int which, SDL_Surface * canvas,
55                 SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect);
56 void shift_click(magic_api * api, int which, int mode,
57                  SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
58 void shift_release(magic_api * api, int which,
59                    SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect);
60 void shift_shutdown(magic_api * api);
61 void shift_set_color(magic_api * api, Uint8 r, Uint8 g, Uint8 b);
62 int shift_requires_colors(magic_api * api, int which);
63 
64 void shift_switchin(magic_api * api, int which, int mode, SDL_Surface * canvas);
65 void shift_switchout(magic_api * api, int which, int mode, SDL_Surface * canvas);
66 int shift_modes(magic_api * api, int which);
67 
68 
69 
shift_api_version(void)70 Uint32 shift_api_version(void)
71 {
72   return (TP_MAGIC_API_VERSION);
73 }
74 
75 
76 // No setup required:
shift_init(magic_api * api)77 int shift_init(magic_api * api)
78 {
79   char fname[1024];
80 
81   snprintf(fname, sizeof(fname), "%s/sounds/magic/shift.ogg", api->data_directory);
82   shift_snd = Mix_LoadWAV(fname);
83 
84   return (1);
85 }
86 
87 // We have multiple tools:
shift_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)88 int shift_get_tool_count(magic_api * api ATTRIBUTE_UNUSED)
89 {
90   return (1);
91 }
92 
93 // Load our icons:
shift_get_icon(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)94 SDL_Surface *shift_get_icon(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
95 {
96   char fname[1024];
97 
98   snprintf(fname, sizeof(fname), "%s/images/magic/shift.png", api->data_directory);
99 
100   return (IMG_Load(fname));
101 }
102 
103 // Return our names, localized:
shift_get_name(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)104 char *shift_get_name(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
105 {
106   return (strdup(gettext_noop("Shift")));
107 }
108 
109 // Return our descriptions, localized:
shift_get_description(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED)110 char *shift_get_description(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
111 {
112   return (strdup(gettext_noop("Click and drag to shift your picture around on the canvas.")));
113 }
114 
115 
116 // Affect the canvas on drag:
shift_drag(magic_api * api,int which,SDL_Surface * canvas,SDL_Surface * last,int ox,int oy,int x,int y,SDL_Rect * update_rect)117 void shift_drag(magic_api * api, int which, SDL_Surface * canvas,
118                 SDL_Surface * last, int ox, int oy, int x, int y, SDL_Rect * update_rect)
119 {
120   if (ox == x && oy == y)
121     return;                     /* No-op */
122 
123   shift_doit(api, which, canvas, last, ox, oy, x, y, update_rect, 1);
124 }
125 
shift_doit(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last,int ox ATTRIBUTE_UNUSED,int oy ATTRIBUTE_UNUSED,int x,int y,SDL_Rect * update_rect,int crosshairs)126 static void shift_doit(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, SDL_Surface * canvas,
127                        SDL_Surface * last, int ox ATTRIBUTE_UNUSED, int oy ATTRIBUTE_UNUSED, int x, int y,
128                        SDL_Rect * update_rect, int crosshairs)
129 {
130   SDL_Rect dest;
131   int dx, dy;
132 
133 
134 
135   dx = x - shift_x;
136   dy = y - shift_y;
137 
138   while (dx < -canvas->w)
139     dx += canvas->w;
140   while (dx > canvas->w)
141     dx -= canvas->w;
142 
143   while (dy < -canvas->h)
144     dy += canvas->h;
145   while (dy > canvas->h)
146     dy -= canvas->h;
147 
148 
149   /* Center */
150 
151   dest.x = dx;
152   dest.y = dy;
153 
154   SDL_BlitSurface(last, NULL, canvas, &dest);
155 
156 
157   if (dy > 0)
158     {
159       if (dx > 0)
160         {
161           /* Top Left */
162 
163           dest.x = dx - canvas->w;
164           dest.y = dy - canvas->h;
165 
166           SDL_BlitSurface(last, NULL, canvas, &dest);
167         }
168 
169 
170       /* Top */
171 
172       dest.x = dx;
173       dest.y = dy - canvas->h;
174 
175       SDL_BlitSurface(last, NULL, canvas, &dest);
176 
177 
178       if (dx < 0)
179         {
180           /* Top Right */
181 
182           dest.x = dx + canvas->w;
183           dest.y = dy - canvas->h;
184 
185           SDL_BlitSurface(last, NULL, canvas, &dest);
186         }
187     }
188 
189 
190   if (dx > 0)
191     {
192       /* Left */
193 
194       dest.x = dx - canvas->w;
195       dest.y = dy;
196 
197       SDL_BlitSurface(last, NULL, canvas, &dest);
198     }
199 
200   if (dx < 0)
201     {
202       /* Right */
203 
204       dest.x = dx + canvas->w;
205       dest.y = dy;
206 
207       SDL_BlitSurface(last, NULL, canvas, &dest);
208     }
209 
210 
211   if (dy < 0)
212     {
213       if (dx > 0)
214         {
215           /* Bottom Left */
216 
217           dest.x = dx - canvas->w;
218           dest.y = dy + canvas->h;
219 
220           SDL_BlitSurface(last, NULL, canvas, &dest);
221         }
222 
223 
224       /* Bottom */
225 
226       dest.x = dx;
227       dest.y = dy + canvas->h;
228 
229       SDL_BlitSurface(last, NULL, canvas, &dest);
230 
231 
232       if (dx < 0)
233         {
234           /* Bottom Right */
235 
236           dest.x = dx + canvas->w;
237           dest.y = dy + canvas->h;
238 
239           SDL_BlitSurface(last, NULL, canvas, &dest);
240         }
241     }
242 
243 
244   if (crosshairs)
245     {
246       dest.x = (canvas->w / 2) - 1;
247       dest.y = 0;
248       dest.w = 3;
249       dest.h = canvas->h;
250 
251       SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, 255, 255, 255));
252 
253       dest.x = 0;
254       dest.y = (canvas->h / 2) - 1;
255       dest.w = canvas->w;
256       dest.h = 3;
257 
258       SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, 255, 255, 255));
259 
260 
261       dest.x = canvas->w / 2;
262       dest.y = 0;
263       dest.w = 1;
264       dest.h = canvas->h;
265 
266       SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, 0, 0, 0));
267 
268       dest.x = 0;
269       dest.y = canvas->h / 2;
270       dest.w = canvas->w;
271       dest.h = 1;
272 
273       SDL_FillRect(canvas, &dest, SDL_MapRGB(canvas->format, 0, 0, 0));
274     }
275 
276 
277   /* Update everything! */
278 
279   update_rect->x = 0;
280   update_rect->y = 0;
281   update_rect->w = canvas->w;
282   update_rect->h = canvas->h;
283 
284   api->playsound(shift_snd, (x * 255) / canvas->w, 255);
285 }
286 
287 // Affect the canvas on click:
shift_click(magic_api * api,int which,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas,SDL_Surface * last,int x,int y,SDL_Rect * update_rect)288 void shift_click(magic_api * api, int which, int mode ATTRIBUTE_UNUSED,
289                  SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect)
290 {
291   shift_x = x;
292   shift_y = y;
293 
294   shift_doit(api, which, canvas, last, x, y, x, y, update_rect, 1);
295 }
296 
297 // Affect the canvas on release:
shift_release(magic_api * api,int which,SDL_Surface * canvas,SDL_Surface * last,int x,int y,SDL_Rect * update_rect)298 void shift_release(magic_api * api, int which,
299                    SDL_Surface * canvas, SDL_Surface * last, int x, int y, SDL_Rect * update_rect)
300 {
301   shift_doit(api, which, canvas, last, x, y, x, y, update_rect, 0);
302   api->stopsound();
303 }
304 
305 
306 // No setup happened:
shift_shutdown(magic_api * api ATTRIBUTE_UNUSED)307 void shift_shutdown(magic_api * api ATTRIBUTE_UNUSED)
308 {
309   if (shift_snd != NULL)
310     Mix_FreeChunk(shift_snd);
311 }
312 
313 // Record the color from Tux Paint:
shift_set_color(magic_api * api ATTRIBUTE_UNUSED,Uint8 r ATTRIBUTE_UNUSED,Uint8 g ATTRIBUTE_UNUSED,Uint8 b ATTRIBUTE_UNUSED)314 void shift_set_color(magic_api * api ATTRIBUTE_UNUSED,
315                      Uint8 r ATTRIBUTE_UNUSED, Uint8 g ATTRIBUTE_UNUSED, Uint8 b ATTRIBUTE_UNUSED)
316 {
317 }
318 
319 // Use colors:
shift_requires_colors(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)320 int shift_requires_colors(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
321 {
322   return 0;
323 }
324 
shift_switchin(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED)325 void shift_switchin(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
326                     SDL_Surface * canvas ATTRIBUTE_UNUSED)
327 {
328 }
329 
shift_switchout(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED,int mode ATTRIBUTE_UNUSED,SDL_Surface * canvas ATTRIBUTE_UNUSED)330 void shift_switchout(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED,
331                      SDL_Surface * canvas ATTRIBUTE_UNUSED)
332 {
333 }
334 
shift_modes(magic_api * api ATTRIBUTE_UNUSED,int which ATTRIBUTE_UNUSED)335 int shift_modes(magic_api * api ATTRIBUTE_UNUSED, int which ATTRIBUTE_UNUSED)
336 {
337   return (MODE_PAINT_WITH_PREVIEW);
338 }
339