Correct one other leaked change that broke encoding (damn some of this
[xiph/unicode.git] / planarity / dialog_level_icons.c
blob0aab095f6b80b2c9c69620328b33ee3e83dc2301
1 /*
3 * gPlanarity:
4 * The geeky little puzzle game with a big noodly crunch!
5 *
6 * gPlanarity copyright (C) 2005 Monty <monty@xiph.org>
7 * Original Flash game by John Tantalo <john.tantalo@case.edu>
8 * Original game concept by Mary Radcliffe
10 * gPlanarity is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
15 * gPlanarity is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Postfish; see the file COPYING. If not, write to the
22 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <math.h>
28 #include <string.h>
29 #include <gtk/gtk.h>
30 #include <gdk/gdk.h>
32 #include "graph.h"
33 #include "timer.h"
34 #include "gameboard.h"
35 #include "gameboard_draw_button.h"
36 #include "dialog_level.h"
37 #include "levelstate.h"
38 #include "main.h"
40 static void draw_forward_arrow(graph *g,dialog_level_oneicon *l, cairo_t *c,int fill){
41 int w = l->w;
42 int h = l->h;
43 int cx = w/2;
44 int cy = h/2;
45 cairo_save(c);
46 cairo_translate(c,l->x+g->width/2+.5,l->y+g->height/2+.5);
48 cairo_set_line_width(c,B_LINE);
50 cairo_move_to(c,w-10,cy);
51 cairo_line_to(c,cx,h-10);
52 cairo_line_to(c,cx,(int)h*.75);
53 cairo_line_to(c,10,(int)h*.75);
54 cairo_line_to(c,10,(int)h*.25);
55 cairo_line_to(c,cx,(int)h*.25);
56 cairo_line_to(c,cx,10);
57 cairo_close_path(c);
59 if(fill){
60 cairo_set_source_rgba (c, B_COLOR);
61 cairo_fill_preserve (c);
63 cairo_set_source_rgba (c, B_LINE_COLOR);
64 cairo_stroke (c);
65 cairo_restore(c);
68 static void draw_backward_arrow(graph *g,dialog_level_oneicon *l, cairo_t *c,int fill){
69 int w = l->w;
70 int h = l->h;
71 int cx = w/2;
72 int cy = h/2;
73 cairo_save(c);
74 cairo_translate(c,l->x+g->width/2-.5,l->y+g->height/2+.5);
76 cairo_set_line_width(c,B_LINE);
78 cairo_move_to(c,10,cy);
79 cairo_line_to(c,cx,h-10);
80 cairo_line_to(c,cx,(int)h*.75);
81 cairo_line_to(c,w-10,(int)h*.75);
82 cairo_line_to(c,w-10,(int)h*.25);
83 cairo_line_to(c,cx,(int)h*.25);
84 cairo_line_to(c,cx,10);
85 cairo_close_path(c);
87 if(fill){
88 cairo_set_source_rgba (c, B_COLOR);
89 cairo_fill_preserve (c);
91 cairo_set_source_rgba (c, B_LINE_COLOR);
92 cairo_stroke (c);
93 cairo_restore(c);
96 static void invalidate_icon(Gameboard *g,dialog_level_oneicon *l){
97 int cx = g->g.width/2;
98 int cy = g->g.height/2;
99 GdkRectangle r;
101 r.x=l->x+cx+g->d.center_x;
102 r.y=l->y+cy;
103 r.width=l->w;
104 r.height=l->h;
106 gdk_window_invalidate_rect (GTK_WIDGET(g)->window, &r, FALSE);
109 static void dialog_level_oneicon_init(Gameboard *g, int num, dialog_level_oneicon *l){
110 int current = get_level_num();
111 l->num = num+current;
113 if(l->icon)cairo_surface_destroy(l->icon);
114 l->icon = levelstate_get_icon(num + current);
115 l->alpha = 0.;
117 l->w = ICON_WIDTH;
118 l->h = ICON_HEIGHT;
119 l->x = num*ICON_WIDTH*1.2 - (l->w*.5);
120 l->y = 120 - (LEVELBOX_HEIGHT) / 2;
124 static void deploy_reset_button(Gameboard *g){
125 buttonstate *states=g->b.states;
127 if(!g->d.reset_deployed){
128 states[10].sweepdeploy += SWEEP_DELTA;
130 states[2].position = 2; //activate it
131 states[2].y_target = states[2].y_active;
133 g->d.reset_deployed=1;
135 if(g->b.buttons_ready){
136 if(g->button_timer!=0)
137 g_source_remove(g->button_timer);
138 g->button_callback=0;
139 g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
144 static void undeploy_reset_button(Gameboard *g){
145 buttonstate *states=g->b.states;
147 if(g->d.reset_deployed){
149 states[10].sweepdeploy -= SWEEP_DELTA;
150 states[2].y_target = states[2].y_inactive;
152 g->d.reset_deployed=0;
154 if(g->b.buttons_ready){
155 if(g->button_timer!=0)
156 g_source_remove(g->button_timer);
157 g->button_callback = 0;
158 g->button_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
163 static void alpha_update(Gameboard *g,dialog_level_oneicon *l){
164 int distance = labs(l->x - g->d.level_icons[2].x + g->d.center_x);
165 double alpha = 1. - (distance/300.);
166 if(alpha<0.)alpha=0.;
167 //if(alpha>1.)alpha=1.;
168 l->alpha = alpha;
171 void level_icons_init(Gameboard *g){
172 int i;
174 for(i=0;i<5;i++)
175 dialog_level_oneicon_init(g,i-2,g->d.level_icons+i);
177 g->d.center_x = 0;
178 g->d.center_done=1;
179 g->d.level_lit = 2;
180 g->d.reset_deployed = 0;
182 if(levelstate_in_progress())
183 deploy_reset_button(g);
185 memset(&g->d.text1,0,sizeof(g->d.text1));
186 memset(&g->d.text2,0,sizeof(g->d.text2));
187 memset(&g->d.text3,0,sizeof(g->d.text3));
188 memset(&g->d.text4,0,sizeof(g->d.text4));
191 void render_level_icons(Gameboard *g, cairo_t *c, int ex,int ey, int ew, int eh){
192 if(g->level_dialog_active){
193 int w= g->g.width;
194 int h= g->g.height;
195 int y = h/2-LEVELBOX_HEIGHT/2+SCOREHEIGHT/2;
196 int i;
198 int ex2 = ex+ew;
199 int ey2 = ey+eh;
201 for(i=0;i<5;i++){
202 dialog_level_oneicon *l=g->d.level_icons+i;
203 alpha_update(g,l);
204 if(l->num >= 0 && l->num < levelstate_limit() && c){
206 int iw = l->w;
207 int ih = l->h;
208 int ix = l->x+g->d.center_x+w/2;
209 int iy = l->y+h/2;
211 if( l->alpha == 0.) continue;
213 if( ix+iw < ex ) continue;
214 if( ix > ex2 ) continue;
215 if( iy+ih < ey ) continue;
216 if( iy > ey2 ) continue;
218 if(l->icon && cairo_surface_status(l->icon)==CAIRO_STATUS_SUCCESS){
219 cairo_set_source_surface(c,l->icon,ix,iy);
220 cairo_paint_with_alpha(c,l->alpha);
223 if(g->d.center_x==0 && g->d.center_done){
224 if(i==2){
225 cairo_set_source_rgba (c, B_COLOR);
226 borderbox_path(c,ix+1.5,iy+1.5,iw-3,ih-3);
227 cairo_fill (c);
230 if(i==1)
231 draw_backward_arrow(&g->g,l,c,i==g->d.level_lit);
232 if(i==3)
233 draw_forward_arrow(&g->g,l,c,i==g->d.level_lit);
238 // render level related text
239 if(g->d.center_x == 0 && g->d.center_done && c){
240 char buffer[160];
242 // above text
243 if(g->d.text1.width==0 ||
244 (ey<g->d.text1.y+g->d.text1.height && ey2>g->d.text1.y)){
246 snprintf(buffer,160,_("Level %d:"),get_level_num()+1);
247 set_font(c,20,20,0,1);
248 cairo_set_source_rgba (c, TEXT_COLOR);
249 g->d.text1=render_bordertext_centered(c, buffer,w/2,y+45);
252 if(g->d.text2.width==0 ||
253 (ey<g->d.text2.y+g->d.text2.height && ey2>g->d.text2.y)){
254 set_font(c,18,18,0,0);
255 cairo_set_source_rgba (c, TEXT_COLOR);
256 g->d.text2=render_bordertext_centered(c, get_level_desc(),w/2,y+70);
259 if(g->d.text3.width==0 ||
260 (ey<g->d.text3.y+g->d.text3.height && ey2>g->d.text3.y)){
262 if(levelstate_get_hiscore()==0){
263 set_font(c,18,18,1,0);
264 snprintf(buffer,160,_("[not yet completed]"));
265 }else{
266 set_font(c,18,18,0,0);
267 snprintf(buffer,160,_("level high score: %ld"),levelstate_get_hiscore());
270 cairo_set_source_rgba (c, TEXT_COLOR);
271 g->d.text3=render_bordertext_centered(c, buffer,w/2,y+245);
274 if(g->d.text4.width==0 ||
275 (ey<g->d.text4.y+g->d.text4.height && ey2>g->d.text4.y)){
277 snprintf(buffer,160,_("total score all levels: %ld"),levelstate_total_hiscore());
279 set_font(c,18,18,0,0);
280 cairo_set_source_rgba (c, TEXT_COLOR);
281 g->d.text4=render_bordertext_centered(c, buffer,w/2,y+265);
283 }else{
284 memset(&g->d.text1,0,sizeof(g->d.text1));
285 memset(&g->d.text2,0,sizeof(g->d.text2));
286 memset(&g->d.text3,0,sizeof(g->d.text3));
287 memset(&g->d.text4,0,sizeof(g->d.text4));
292 static gboolean animate_level_frame(gpointer ptr){
293 Gameboard *g = GAMEBOARD (ptr);
294 int i;
296 if(g->d.center_x == 0){
297 g->d.center_done=1;
298 g_source_remove(g->d.icon_timer);
299 g->d.icon_timer=0;
301 if(levelstate_in_progress())
302 deploy_reset_button(g);
304 expose_full(g);
305 return 0;
308 g->d.center_done=0;
309 for(i=0;i<5;i++)
310 if(g->d.level_icons[i].alpha)
311 invalidate_icon(g, g->d.level_icons+i);
313 if(g->d.center_x < 0){
314 g->d.center_x += ICON_DELTA;
315 if(g->d.center_x > 0) g->d.center_x = 0;
316 }else{
317 g->d.center_x -= ICON_DELTA;
318 if(g->d.center_x < 0) g->d.center_x = 0;
321 // trick 'expose'; run it with a region that does nothing in order
322 // to update the visibility flags
324 render_level_icons(g, 0, 0, 0, 0, 0);
326 for(i=0;i<5;i++)
327 if(g->d.level_icons[i].alpha)
328 invalidate_icon(g, g->d.level_icons+i);
330 return 1;
333 static int find_icon(Gameboard *b,graph *g, int x, int y){
334 int i;
335 int w= g->width;
336 int h= g->height;
338 x-=w/2;
339 y-=h/2;
341 for(i=1;i<4;i++){
342 dialog_level_oneicon *l=b->d.level_icons+i;
343 if(l->num>=0 && l->num<levelstate_limit()){
344 if(x >= l->x &&
345 x <= l->x + l->w &&
346 y >= l->y &&
347 y <= l->y + l->h)
348 return i;
351 return 2;
354 void local_reset (Gameboard *g){
355 levelstate_reset();
356 dialog_level_oneicon_init(g,0,g->d.level_icons+2);
357 invalidate_icon(g, g->d.level_icons+2);
358 undeploy_reset_button(g);
361 void level_mouse_motion(Gameboard *g, int x, int y){
363 int icon = find_icon(g,&g->g,x,y);
365 if(icon != g->d.level_lit){
366 invalidate_icon(g, g->d.level_icons+g->d.level_lit);
367 g->d.level_lit = icon;
368 invalidate_icon(g, g->d.level_icons+g->d.level_lit);
372 void level_mouse_press(Gameboard *g, int x, int y){
373 int i;
375 level_mouse_motion(g, x, y);
377 if(g->d.level_lit == 1){
378 if(levelstate_prev()){
380 if(!levelstate_in_progress())
381 undeploy_reset_button(g);
383 if(g->d.level_icons[4].icon)
384 cairo_surface_destroy(g->d.level_icons[4].icon);
385 for(i=4;i>=1;i--){
386 g->d.level_icons[i].num = g->d.level_icons[i-1].num;
387 g->d.level_icons[i].icon = g->d.level_icons[i-1].icon;
389 g->d.level_icons[0].icon=0;
390 dialog_level_oneicon_init(g,-2,g->d.level_icons);
392 if(g->d.center_x==0 && g->d.center_done)expose_full(g); // only needed to 'undraw' the text
394 g->d.center_x = g->d.level_icons[1].x - g->d.level_icons[2].x;
398 if(g->d.level_lit == 3){
399 if(levelstate_next()){
401 if(!levelstate_in_progress())
402 undeploy_reset_button(g);
404 if(g->d.level_icons[0].icon)
405 cairo_surface_destroy(g->d.level_icons[0].icon);
406 for(i=0;i<4;i++){
407 g->d.level_icons[i].num = g->d.level_icons[i+1].num;
408 g->d.level_icons[i].icon = g->d.level_icons[i+1].icon;
410 g->d.level_icons[4].icon=0;
411 dialog_level_oneicon_init(g,2,g->d.level_icons+4);
413 if(g->d.center_x==0 && g->d.center_done)expose_full(g); // only needed to 'undraw' the text
415 g->d.center_x = g->d.level_icons[3].x - g->d.level_icons[2].x;
420 if(g->d.center_x){
421 if(g->d.icon_timer)
422 g_source_remove(g->d.icon_timer);
423 g->d.icon_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_level_frame, (gpointer)g);