[xiph-commits] r10060 - trunk/planarity
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Sun Sep 25 02:24:37 PDT 2005
Author: xiphmont
Date: 2005-09-25 02:24:23 -0700 (Sun, 25 Sep 2005)
New Revision: 10060
Added:
trunk/planarity/dialog_finish.c
trunk/planarity/dialog_finish.h
trunk/planarity/dialog_level.c
trunk/planarity/dialog_level.h
trunk/planarity/dialog_level_icons.c
trunk/planarity/dialog_pause.c
trunk/planarity/dialog_pause.h
trunk/planarity/gameboard_draw_box.c
trunk/planarity/gameboard_draw_button.c
trunk/planarity/gameboard_draw_button.h
trunk/planarity/gameboard_draw_buttonbar.c
trunk/planarity/gameboard_draw_curtain.c
trunk/planarity/gameboard_draw_edge.c
trunk/planarity/gameboard_draw_intersection.c
trunk/planarity/gameboard_draw_main.c
trunk/planarity/gameboard_draw_score.c
trunk/planarity/gameboard_draw_selection.c
trunk/planarity/gameboard_draw_text.c
trunk/planarity/gameboard_draw_vertex.c
trunk/planarity/gameboard_logic.c
trunk/planarity/gameboard_logic_button.c
trunk/planarity/gameboard_logic_buttonbar.c
trunk/planarity/gameboard_logic_buttonbar.h
trunk/planarity/gameboard_logic_mouse.c
trunk/planarity/gameboard_logic_push.c
trunk/planarity/graph_arrange.c
trunk/planarity/graph_arrange.h
trunk/planarity/graph_generate.c
trunk/planarity/graph_generate.h
trunk/planarity/graph_generate_mesh1.c
trunk/planarity/graph_score.c
trunk/planarity/main.h
trunk/planarity/timer.c
trunk/planarity/timer.h
Removed:
trunk/planarity/arrange.c
trunk/planarity/arrange.h
trunk/planarity/boardgen.c
trunk/planarity/box.c
trunk/planarity/box.h
trunk/planarity/button_base.c
trunk/planarity/button_base.h
trunk/planarity/buttonbar.c
trunk/planarity/buttonbar.h
trunk/planarity/buttons.c
trunk/planarity/buttons.h
trunk/planarity/finish.c
trunk/planarity/finish.h
trunk/planarity/gamestate.c
trunk/planarity/gamestate.h
trunk/planarity/generate.c
trunk/planarity/generate.h
trunk/planarity/pause.c
trunk/planarity/pause.h
Modified:
trunk/planarity/Makefile
trunk/planarity/gameboard.c
trunk/planarity/gameboard.h
trunk/planarity/graph.c
trunk/planarity/graph.h
trunk/planarity/levelstate.c
trunk/planarity/levelstate.h
trunk/planarity/main.c
trunk/planarity/version.h
Log:
Fully complete UI, code cleanup. Remaining tasks:
Move dialog_level static storage to gameboard struct
comments, comments, comments!
hand design about, oh, fifty-odd puzzle levels and new graph gen algos
Modified: trunk/planarity/Makefile
===================================================================
--- trunk/planarity/Makefile 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/Makefile 2005-09-25 09:24:23 UTC (rev 10060)
@@ -16,10 +16,24 @@
# work for on most modern linux distros without any of the
# bleeding-edge GTK 2.7/2.8 libs installed.
-SRC = graph.c arrange.c gameboard.c generate.c gamestate.c button_base.c\
- buttons.c buttonbar.c box.c pause.c finish.c levelstate.c main.c
-OBJ = graph.o arrange.o gameboard.o generate.o gamestate.o button_base.o\
- buttons.o buttonbar.o box.o pause.o finish.o levelstate.o main.o
+SRC = dialog_finish.c gameboard_logic.c dialog_pause.c gameboard_logic_button.c\
+ gameboard.c gameboard_logic_buttonbar.c gameboard_draw_box.c\
+ gameboard_logic_mouse.c gameboard_draw_button.c gameboard_logic_push.c\
+ gameboard_draw_buttonbar.c graph.c gameboard_draw_curtain.c\
+ graph_score.c graph_arrange.c gameboard_draw_edge.c graph_generate.c\
+ gameboard_draw_intersection.c graph_generate_mesh1.c gameboard_draw_main.c\
+ gameboard_draw_score.c main.c gameboard_draw_selection.c\
+ timer.c gameboard_draw_vertex.c levelstate.c dialog_level.c\
+ dialog_level_icons.c gameboard_draw_text.c
+OBJ = dialog_finish.o gameboard_logic.o dialog_pause.o gameboard_logic_button.o\
+ gameboard.o gameboard_logic_buttonbar.o gameboard_draw_box.o\
+ gameboard_logic_mouse.o gameboard_draw_button.o gameboard_logic_push.o\
+ gameboard_draw_buttonbar.o graph.o gameboard_draw_curtain.o\
+ graph_score.o graph_arrange.o gameboard_draw_edge.o graph_generate.o\
+ gameboard_draw_intersection.o graph_generate_mesh1.o gameboard_draw_main.o\
+ gameboard_draw_score.o main.o gameboard_draw_selection.o\
+ timer.o gameboard_draw_vertex.o levelstate.o dialog_level.o\
+ dialog_level_icons.o gameboard_draw_text.o
GCF = `pkg-config --static --cflags "gtk+-2.0 >= 2.7.2"`
# uncomment below for a normal dynamic build
@@ -54,7 +68,7 @@
$(STRIP) $(TARGET)
debug:
- $(MAKE) target CFLAGS="-g -Wall -W -Wno-unused-parameter -D__NO_MATH_INLINES $(GCF) $(ADD_DEF)"
+ $(MAKE) target CFLAGS="-g -Wall -W -Wno-unused-parameter -D__NO_MATH_INLINES $(GCF) $(ADD_DEF)" -lefence
profile:
$(MAKE) target CFLAGS="-pg -g -O2 -ffast-math $(GCF) $(ADD_DEF)" LIBS="$(LIBS) -lgprof-helper "
@@ -74,7 +88,7 @@
target: $(OBJ)
./touch-version
- $(LD) $(OBJ) $(CFLAGS) -o $(TARGET) $(LIBS) $(LDF)
+ $(LD) $(OBJ) $(CFLAGS) -o $(TARGET) $(LIBS) $(LDF)
static-target: $(OBJ)
./touch-version
Deleted: trunk/planarity/arrange.c
===================================================================
--- trunk/planarity/arrange.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/arrange.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,38 +0,0 @@
-#include <math.h>
-
-#include "graph.h"
-#include "arrange.h"
-#include "gamestate.h"
-
-void arrange_verticies_circle(graph *g){
- vertex *v = g->verticies;
- int n = g->vertex_num;
- int bw=get_orig_width();
- int bh=get_orig_height();
- int radius=min(bw,bh)*.45;
- int i;
- for(i=0;i<n;i++){
- int x = rint( radius * cos( i*M_PI*2./n));
- int y = rint( radius * sin( i*M_PI*2./n));
- move_vertex(g,v,x+(bw>>1),y+(bh>>1));
- v=v->next;
- }
-}
-
-void arrange_verticies_mesh(graph *g, int width, int height){
- vertex *v = g->verticies;
- int bw=get_orig_width();
- int bh=get_orig_height();
- int spacing=min((float)bw/width,(float)bh/height)*.9;
- int x,y;
-
- int xpad=(bw - (width-1)*spacing)/2;
- int ypad=(bh - (height-1)*spacing)/2;
-
- for(y=0;y<height;y++){
- for(x=0;x<width;x++){
- move_vertex(g,v,x*spacing+xpad,y*spacing+ypad);
- v=v->next;
- }
- }
-}
Deleted: trunk/planarity/arrange.h
===================================================================
--- trunk/planarity/arrange.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/arrange.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,2 +0,0 @@
-extern void arrange_verticies_circle(graph *g);
-extern void arrange_verticies_mesh(graph *g, int width, int height);
Deleted: trunk/planarity/boardgen.c
===================================================================
--- trunk/planarity/boardgen.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/boardgen.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,9 +0,0 @@
-char *board_level_to_name(int level){
-
-
-}
-
-int board_name_to_level(int level){
-
-
-}
Deleted: trunk/planarity/box.c
===================================================================
--- trunk/planarity/box.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/box.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,251 +0,0 @@
-#include <math.h>
-#include <gtk/gtk.h>
-#include "graph.h"
-#include "box.h"
-
-void topbox (cairo_t *c, double w, double h){
-
- double x0 = B_BORDER+B_RADIUS;
- double y0 = B_BORDER;
-
- double x1 = B_BORDER;
- double y1 = B_BORDER+B_RADIUS;
-
- double x2 = B_BORDER;
- double y2 = h-B_BORDER-B_RADIUS;
-
- double x3 = B_BORDER+B_RADIUS;
- double y3 = h-B_BORDER;
-
- double x4 = w/2 - B_HUMP - B_RADIUS;
- double y4 = h-B_BORDER;
-
- double x5 = x4+B_RADIUS;
- double y5 = y4;
-
-
- double x7 = w/2 + B_HUMP + B_RADIUS;
- double y7 = h-B_BORDER;
-
- double x8 = w - B_BORDER -B_RADIUS;
- double y8 = h-B_BORDER;
-
- double x9 = w - B_BORDER;
- double y9 = h-B_BORDER-B_RADIUS;
-
- double x10 = w - B_BORDER;
- double y10 = B_BORDER+B_RADIUS;
-
- double x11 = w - B_BORDER-B_RADIUS;
- double y11 = B_BORDER;
-
- cairo_set_line_width(c,B_LINE);
-
- cairo_move_to (c, x0, y0);
- cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
- cairo_line_to (c, x2,y2);
- cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
- cairo_line_to (c, x4,y4);
-
- {
- double hh = get_board_height()*.5+50;
-
- double radius = sqrt( (w*.5-x5) * (w*.5-x5) + (hh-y5) * (hh-y5));
- double siderad = atan( (x5-w*.5)/(hh-y5));
-
- double xx = sin(siderad+.05)*radius+w*.5;
- double yy = -cos(siderad+.05)*radius+hh;
- double x = sin(siderad+.1)*radius+w*.5;
- double y = -cos(siderad+.1)*radius+hh;
-
- cairo_curve_to (c, x4+B_RADIUS,y4, xx,yy, x,y);
- cairo_arc(c,w*.5,hh,radius,-M_PI*.5+siderad+.1,-M_PI*.5-siderad-.1);
-
- xx = -sin(siderad+.05)*radius+w*.5;
- yy = -cos(siderad+.05)*radius+hh;
- xx = -sin(siderad+.1)*radius+w*.5;
- yy = -cos(siderad+.1)*radius+hh;
-
- cairo_curve_to (c, xx,yy, x7-B_RADIUS,y7, x7,y7);
-
- }
-
- cairo_line_to (c, x8,y8);
- cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
- cairo_line_to (c, x10,y10);
- cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
- cairo_close_path (c);
-
- cairo_set_source_rgba (c, B_COLOR);
- cairo_fill_preserve (c);
- cairo_set_source_rgba (c, B_LINE_COLOR);
- cairo_stroke (c);
-
-}
-
-void bottombox (cairo_t *c, double w, double h){
-
- double x0 = B_BORDER+B_RADIUS;
- double y0 = h-B_BORDER;
-
- double x1 = B_BORDER;
- double y1 = h-B_BORDER-B_RADIUS;
-
- double x2 = B_BORDER;
- double y2 = B_BORDER+B_RADIUS;
-
- double x3 = B_BORDER+B_RADIUS;
- double y3 = B_BORDER;
-
- double x4 = w/2 - B_HUMP - B_RADIUS;
- double y4 = B_BORDER;
-
- double x5 = x4+B_RADIUS;
- double y5 = y4;
-
-
- double x7 = w/2 + B_HUMP + B_RADIUS;
- double y7 = B_BORDER;
-
- double x8 = w - B_BORDER -B_RADIUS;
- double y8 = B_BORDER;
-
- double x9 = w - B_BORDER;
- double y9 = B_BORDER+B_RADIUS;
-
- double x10 = w - B_BORDER;
- double y10 = h- B_BORDER -B_RADIUS;
-
- double x11 = w - B_BORDER-B_RADIUS;
- double y11 = h-B_BORDER;
-
- cairo_set_line_width(c,B_LINE);
-
- cairo_move_to (c, x0, y0);
- cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
- cairo_line_to (c, x2,y2);
- cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
- cairo_line_to (c, x4,y4);
-
- {
- double hh = get_board_height()*.5+50;
-
- double radius = sqrt( (w*.5-x5) * (w*.5-x5) + (y5+hh-h) * (y5+hh-h));
- double siderad = atan( (x5-w*.5)/(y5+hh-h));
-
- double xx = sin(siderad+.05)*radius+w*.5;
- double yy = cos(siderad+.05)*radius-hh+h;
- double x = sin(siderad+.1)*radius+w*.5;
- double y = cos(siderad+.1)*radius-hh+h;
-
- cairo_curve_to (c, x4+B_RADIUS,y4, xx,yy, x,y);
- cairo_arc_negative(c,w*.5,h-hh,radius,M_PI*.5-siderad-.1,M_PI*.5+siderad+.1);
-
- xx = -sin(siderad+.05)*radius+w*.5;
- yy = cos(siderad+.05)*radius-hh+h;
- xx = -sin(siderad+.1)*radius+w*.5;
- yy = cos(siderad+.1)*radius-hh+h;
-
- cairo_curve_to (c, xx,yy, x7-B_RADIUS,y7, x7,y7);
-
- }
-
- cairo_line_to (c, x8,y8);
- cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
- cairo_line_to (c, x10,y10);
- cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
- cairo_close_path (c);
-
- cairo_set_source_rgba (c, B_COLOR);
- cairo_fill_preserve (c);
- cairo_set_source_rgba (c, B_LINE_COLOR);
- cairo_stroke (c);
-
-}
-
-void centerbox (cairo_t *c, int x, int y, double w, double h){
-
- double x0 = B_BORDER+B_RADIUS;
- double y0 = h-B_BORDER;
-
- double x1 = B_BORDER;
- double y1 = h-B_BORDER-B_RADIUS;
-
- double x2 = B_BORDER;
- double y2 = B_BORDER+B_RADIUS;
-
- double x3 = B_BORDER+B_RADIUS;
- double y3 = B_BORDER;
-
- double x8 = w - B_BORDER -B_RADIUS;
- double y8 = B_BORDER;
-
- double x9 = w - B_BORDER;
- double y9 = B_BORDER+B_RADIUS;
-
- double x10 = w - B_BORDER;
- double y10 = h- B_BORDER -B_RADIUS;
-
- double x11 = w - B_BORDER-B_RADIUS;
- double y11 = h-B_BORDER;
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_line_width(c,B_LINE);
-
- cairo_move_to (c, x0, y0);
- cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
- cairo_line_to (c, x2,y2);
- cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
- cairo_line_to (c, x8,y8);
- cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
- cairo_line_to (c, x10,y10);
- cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
- cairo_close_path (c);
-
- cairo_set_source_rgba (c, B_COLOR);
- cairo_fill_preserve (c);
- cairo_set_source_rgba (c, B_LINE_COLOR);
- cairo_stroke (c);
-
- cairo_restore(c);
-}
-
-void borderbox_path (cairo_t *c, int x, int y, double w, double h){
-
- double x0 = x+ B_RADIUS;
- double y0 = y+ h;
-
- double x1 = x;
- double y1 = y+ h-B_RADIUS;
-
- double x2 = x;
- double y2 = y+ B_RADIUS;
-
- double x3 = x+ B_RADIUS;
- double y3 = y;
-
- double x8 = x+ w -B_RADIUS;
- double y8 = y;
-
- double x9 = x+ w;
- double y9 = y+ B_RADIUS;
-
- double x10 = x+ w;
- double y10 = y+ h -B_RADIUS;
-
- double x11 = x+ w -B_RADIUS;
- double y11 = y+h;
-
- cairo_move_to (c, x0, y0);
- cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
- cairo_line_to (c, x2,y2);
- cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
- cairo_line_to (c, x8,y8);
- cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
- cairo_line_to (c, x10,y10);
- cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
- cairo_close_path (c);
-
-}
-
Deleted: trunk/planarity/box.h
===================================================================
--- trunk/planarity/box.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/box.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,16 +0,0 @@
-#define B_LINE 1
-#define B_BORDER 6.5
-#define B_RADIUS 20
-#define B_HUMP 130
-#define B_COLOR .1,.1,.7,.1
-#define B_LINE_COLOR 0, 0,.7,.3
-#define TEXT_COLOR .0,.0,.7,.6
-
-
-#define SCOREHEIGHT 50
-
-
-extern void topbox (cairo_t *c, double w, double h);
-extern void bottombox (cairo_t *c, double w, double h);
-extern void centerbox (cairo_t *c, int x, int y, double w, double h);
-extern void borderbox_path (cairo_t *c, int x, int y, double w, double h);
Deleted: trunk/planarity/button_base.c
===================================================================
--- trunk/planarity/button_base.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/button_base.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,606 +0,0 @@
-#include <math.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "graph.h"
-#include "gameboard.h"
-#include "gamestate.h"
-#include "buttons.h"
-#include "button_base.h"
-
-
-/************************ manage the buttons for buttonbar and dialogs *********************/
-
-buttonstate states[NUMBUTTONS];
-
-int buttons_ready=0;
-static int allclear=1; // actually just a shirt-circuit
-static buttonstate *grabbed=0;
-
-/* determine the x/y/w/h box around the rollover text */
-static GdkRectangle rollover_box(buttonstate *b){
- GdkRectangle r;
- int width = get_board_width();
- int height = get_board_height();
-
- int x = b->x - b->ex.width/2 + b->ex.x_bearing -2;
- int y = b->y - BUTTON_RADIUS - BUTTON_TEXT_BORDER + b->ex.y_bearing -2;
-
- if(x<BUTTON_TEXT_BORDER)x=BUTTON_TEXT_BORDER;
- if(y<BUTTON_TEXT_BORDER)y=BUTTON_TEXT_BORDER;
- if(x+b->ex.width >= width - BUTTON_TEXT_BORDER)
- x = width - BUTTON_TEXT_BORDER - b->ex.width;
- if(y+b->ex.height >= height - BUTTON_TEXT_BORDER)
- y = height - BUTTON_TEXT_BORDER - b->ex.height;
-
- r.x=x;
- r.y=y;
- r.width=b->ex.width+5;
- r.height=b->ex.height+5;
-
- return r;
-}
-
-/* draw the actual rollover */
-static void stroke_rollover(Gameboard *g, buttonstate *b, cairo_t *c){
- cairo_matrix_t m;
-
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_matrix_init_scale (&m, BUTTON_TEXT_SIZE);
- cairo_set_font_matrix (c,&m);
-
- {
- GdkRectangle r=rollover_box(b);
-
- cairo_move_to (c, r.x - b->ex.x_bearing +2, r.y -b->ex.y_bearing+2 );
-
- cairo_set_line_width(c,3);
- cairo_set_source_rgba(c,1,1,1,.9);
- cairo_text_path (c, b->rollovertext);
- cairo_stroke(c);
-
- cairo_set_source_rgba(c,BUTTON_TEXT_COLOR);
- cairo_move_to (c, r.x - b->ex.x_bearing +2, r.y -b->ex.y_bearing+2 );
-
-
- cairo_show_text (c, b->rollovertext);
-
- }
-}
-
-/* request an expose for a button region*/
-static void invalidate_button(Gameboard *g,buttonstate *b){
- GdkRectangle r;
-
- r.x=b->x-BUTTON_RADIUS-1;
- r.y=b->y-BUTTON_RADIUS-1;
- r.width=BUTTON_RADIUS*2+2;
- r.height=BUTTON_RADIUS*2+2;
-
- gdk_window_invalidate_rect(g->w.window,&r,FALSE);
-}
-
-/* request an expose for a rollover region*/
-static void invalidate_rollover(Gameboard *g,buttonstate *b){
- GdkRectangle r = rollover_box(b);
- invalidate_button(g,b);
- gdk_window_invalidate_rect(g->w.window,&r,FALSE);
-}
-
-/* like invalidation, but just expands a rectangular region */
-static void expand_rectangle_button(buttonstate *b,GdkRectangle *r){
- int x=b->x-BUTTON_RADIUS-1;
- int y=b->y-BUTTON_RADIUS-1;
- int x2=x+BUTTON_RADIUS*2+2;
- int y2=y+BUTTON_RADIUS*2+2;
-
- int rx2=r->x+r->width;
- int ry2=r->y+r->height;
-
- if(r->width==0 || r->height==0){
- r->x=x;
- r->y=y;
- r->width=x2-x;
- r->height=y2-y;
- }
-
- if(x<r->x)
- r->x=x;
- if(y<r->y)
- r->y=y;
- if(rx2<x2)
- rx2=x2;
- r->width=rx2-r->x;
- if(ry2<y2)
- ry2=y2;
- r->height=ry2-r->y;
-}
-
-/* like invalidation, but just expands a rectangular region */
-static void expand_rectangle_rollover(buttonstate *b,GdkRectangle *r){
- GdkRectangle rr = rollover_box(b);
- int x=rr.x;
- int y=rr.y;
- int x2=x+rr.width;
- int y2=y+rr.height;
-
- int rx2=r->x+r->width;
- int ry2=r->y+r->height;
-
- if(r->width==0 || r->height==0){
- r->x=x;
- r->y=y;
- r->width=x2-x;
- r->height=y2-y;
- }
-
- if(x<r->x)
- r->x=x;
- if(y<r->y)
- r->y=y;
- if(rx2<x2)
- rx2=x2;
- r->width=rx2-r->x;
- if(ry2<y2)
- ry2=y2;
- r->height=ry2-r->y;
-}
-
-/* match x/y to a button if any */
-static buttonstate *find_button(int x,int y){
- int i;
- for(i=0;i<NUMBUTTONS;i++){
- buttonstate *b=states+i;
- if(b->position)
- if( (b->x-x)*(b->x-x) + (b->y-y)*(b->y-y) <= BUTTON_RADIUS*BUTTON_RADIUS+4)
- if(b->x != b->x_inactive)
- return b;
- }
- return 0;
-}
-
-/* set a button to pressed or lit */
-static void button_set_state(Gameboard *g, buttonstate *b, int rollover, int press){
- int i;
-
- if(b->rollover == rollover && b->press == press)return;
-
- for(i=0;i<NUMBUTTONS;i++){
- buttonstate *bb=states+i;
- if(bb->position){
- if(bb!=b){
- if(bb->rollover)
- invalidate_rollover(g,bb);
- if(bb->press)
- invalidate_button(g,bb);
-
- bb->rollover=0;
- bb->press=0;
- }else{
- if(bb->rollover != rollover)
- invalidate_rollover(g,bb);
- if(bb->press != press)
- invalidate_button(g,bb);
-
- bb->rollover=rollover;
- bb->press=press;
- }
- }
- }
- allclear=0;
-}
-
-/* cache buttons as small surfaces */
-static cairo_surface_t *cache_button(Gameboard *g,
- void (*draw)(cairo_t *c,
- double x,
- double y),
- double pR,double pG,double pB,double pA,
- double fR,double fG,double fB,double fA){
- cairo_surface_t *ret =
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- BUTTON_RADIUS*2+1,
- BUTTON_RADIUS*2+1);
-
- cairo_t *c = cairo_create(ret);
-
- cairo_save(c);
- cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
- cairo_set_source_rgba (c, 1,1,1,1);
- cairo_paint(c);
- cairo_restore(c);
-
- cairo_set_source_rgba(c,fR,fG,fB,fA);
- cairo_set_line_width(c,BUTTON_LINE_WIDTH);
- draw(c,BUTTON_RADIUS+.5,BUTTON_RADIUS+.5);
-
- cairo_set_source_rgba(c,pR,pG,pB,pA);
- cairo_stroke(c);
-
- cairo_destroy(c);
- return ret;
-}
-
-/* determine the x/y/w/h box around a button */
-static GdkRectangle button_box(buttonstate *b){
- GdkRectangle r;
-
- int x = b->x - BUTTON_RADIUS-1;
- int y = b->y - BUTTON_RADIUS-1;
- r.x=x;
- r.y=y;
- r.width = BUTTON_RADIUS*2+2;
- r.height= BUTTON_RADIUS*2+2;
-
- return r;
-}
-
-/* do the animation math for one button for one frame */
-static int animate_one(buttonstate *b, GdkRectangle *r){
- int ret=0;
-
- if(b->target_x_active != b->x_active){
- ret=1;
- if(b->target_x_active > b->x_active){
- b->x_active+=BUTTON_DELTA;
- if(b->x_active>b->target_x_active)
- b->x_active=b->target_x_active;
- }else{
- b->x_active-=BUTTON_DELTA;
- if(b->x_active<b->target_x_active)
- b->x_active=b->target_x_active;
- }
- }
-
- if(b->target_x_inactive != b->x_inactive){
- ret=1;
- if(b->target_x_inactive > b->x_inactive){
- b->x_inactive+=BUTTON_DELTA;
- if(b->x_inactive>b->target_x_inactive)
- b->x_inactive=b->target_x_inactive;
- }else{
- b->x_inactive-=BUTTON_DELTA;
- if(b->x_inactive<b->target_x_inactive)
- b->x_inactive=b->target_x_inactive;
- }
- }
-
- if(b->target_x != b->x){
- ret=1;
- expand_rectangle_button(b,r);
- if(b->rollover)
- expand_rectangle_rollover(b,r);
-
- if(b->target_x > b->x){
- b->x+=BUTTON_DELTA;
- if(b->x>b->target_x)b->x=b->target_x;
- }else{
- b->x-=BUTTON_DELTA;
- if(b->x<b->target_x)b->x=b->target_x;
- }
- expand_rectangle_button(b,r);
- if(b->rollover)
- expand_rectangle_rollover(b,r);
- }
-
- if(b->alphad != b->x_active - b->x){
- double alpha=0;
- if(b->x_inactive>b->x_active){
- if(b->x<=b->x_active)
- alpha=1.;
- else if (b->x>=b->x_inactive)
- alpha=0.;
- else
- alpha = (double)(b->x_inactive-b->x)/(b->x_inactive-b->x_active);
- }else if (b->x_inactive<b->x_active){
- if(b->x>=b->x_active)
- alpha=1.;
- else if (b->x<=b->x_inactive)
- alpha=0.;
- else
- alpha = (double)(b->x_inactive-b->x)/(b->x_inactive-b->x_active);
- }
- if(alpha != b->alpha){
- ret=1;
- expand_rectangle_button(b,r);
- b->alpha=alpha;
- }
- b->alphad = b->x_active - b->x;
- }
- return ret;
-}
-
-/******************** toplevel abstraction calls *********************/
-
-/* initialize the persistent caches; called once when gameboard is
- first created */
-void init_buttons(Gameboard *g){
- memset(states,0,sizeof(states));
-
- states[0].idle = cache_button(g, path_button_exit,
- BUTTON_QUIT_IDLE_PATH,
- BUTTON_QUIT_IDLE_FILL);
- states[0].lit = cache_button(g, path_button_exit,
- BUTTON_QUIT_LIT_PATH,
- BUTTON_QUIT_LIT_FILL);
-
- states[1].idle = cache_button(g, path_button_back,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[1].lit = cache_button(g, path_button_back,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[2].idle = cache_button(g, path_button_reset,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[2].lit = cache_button(g, path_button_reset,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[3].idle = cache_button(g, path_button_pause,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[3].lit = cache_button(g, path_button_pause,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[4].idle = cache_button(g, path_button_help,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[4].lit = cache_button(g, path_button_help,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[5].idle = cache_button(g, path_button_expand,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[5].lit = cache_button(g, path_button_expand,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[6].idle = cache_button(g, path_button_shrink,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[6].lit = cache_button(g, path_button_shrink,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[7].idle = cache_button(g, path_button_lines,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[7].lit = cache_button(g, path_button_lines,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[8].idle = cache_button(g, path_button_int,
- BUTTON_IDLE_PATH,
- BUTTON_IDLE_FILL);
- states[8].lit = cache_button(g, path_button_int,
- BUTTON_LIT_PATH,
- BUTTON_LIT_FILL);
- states[9].idle = cache_button(g, path_button_check,
- BUTTON_CHECK_IDLE_PATH,
- BUTTON_CHECK_IDLE_FILL);
- states[9].lit = cache_button(g, path_button_check,
- BUTTON_CHECK_LIT_PATH,
- BUTTON_CHECK_LIT_FILL);
- states[10].idle= cache_button(g, path_button_play,
- BUTTON_CHECK_IDLE_PATH,
- BUTTON_CHECK_IDLE_FILL);
- states[10].lit = cache_button(g, path_button_play,
- BUTTON_CHECK_LIT_PATH,
- BUTTON_CHECK_LIT_FILL);
-}
-
-/* cache the text extents of a rollover */
-void rollover_extents(Gameboard *g, buttonstate *b){
-
- cairo_matrix_t m;
-
- cairo_t *c = cairo_create(g->foreground);
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_matrix_init_scale (&m, BUTTON_TEXT_SIZE);
- cairo_set_font_matrix (c,&m);
-
- cairo_text_extents (c, b->rollovertext, &b->ex);
-
- cairo_destroy(c);
-}
-
-/* perform a single frame of animation for all buttons/rollovers */
-gboolean animate_button_frame(gpointer ptr){
- Gameboard *g=(Gameboard *)ptr;
- GdkRectangle expose;
- int ret=0,i,pos;
-
- if(!g->first_expose)return 1;
-
- /* avoid the normal expose event mechanism
- during the button animations. This direct method is much faster as
- it won't accidentally combine exposes over long stretches of
- alpha-blended surfaces. */
-
- for(pos=1;pos<=3;pos++){
- memset(&expose,0,sizeof(expose));
- for(i=0;i<NUMBUTTONS;i++)
- if(states[i].position == pos)
- ret|=animate_one(states+i,&expose);
- if(expose.width && expose.height)
- run_immediate_expose(g,
- expose.x,
- expose.y,
- expose.width,
- expose.height);
- }
- return ret;
-}
-
-/* the normal expose method for all buttons; called from the master
- widget's expose */
-void expose_buttons(Gameboard *g,cairo_t *c, int x,int y,int w,int h){
- int i;
-
- for(i=0;i<NUMBUTTONS;i++){
-
- buttonstate *b=states+i;
-
- if(b->position){
- GdkRectangle r = rollover_box(b);
- GdkRectangle br = button_box(b);
-
- if(x < br.x+br.width &&
- y < br.y+br.height &&
- x+w > br.x &&
- y+h > br.y) {
-
- cairo_set_source_surface(c,
- (b->rollover || b->press ? b->lit : b->idle),
- br.x,
- br.y);
-
- if(b->press)
- cairo_paint_with_alpha(c,b->alpha);
- cairo_paint_with_alpha(c,b->alpha);
-
- }
-
- if(b->rollover || b->press)
- if(x < r.x+r.width &&
- y < r.y+r.height &&
- x+w > r.x &&
- y+h > r.y)
-
- stroke_rollover(g,b,c);
- }
- }
-}
-
-/* resize the button bar; called from master resize in gameboard */
-void resize_buttons(int oldw,int oldh,int w,int h){
- int i;
- int dx=w/2-oldw/2;
- int dy=h/2-oldh/2;
-
- for(i=0;i<NUMBUTTONS;i++){
- if(states[i].position == 2){
- states[i].x+=dx;
- states[i].target_x+=dx;
- states[i].x_active+=dx;
- states[i].target_x_active+=dx;
- states[i].x_inactive+=dx;
- states[i].target_x_inactive+=dx;
- states[i].y+=dy;
- }
- }
-
- dx=w-oldw;
- dy=h-oldh;
-
- for(i=0;i<NUMBUTTONS;i++){
- if(states[i].position == 1){
- states[i].y+=dy;
- }
- }
-
- for(i=0;i<NUMBUTTONS;i++){
- if(states[i].position == 3){
- states[i].x+=dx;
- states[i].target_x+=dx;
- states[i].x_active+=dx;
- states[i].target_x_active+=dx;
- states[i].x_inactive+=dx;
- states[i].target_x_inactive+=dx;
- states[i].y+=dy;
- }
- }
-}
-
-/* clear all buttons to unpressed/unlit */
-void button_clear_state(Gameboard *g){
- int i;
- if(!allclear){
- for(i=0;i<NUMBUTTONS;i++){
- buttonstate *bb=states+i;
- if(bb->position){
- if(bb->rollover)
- invalidate_rollover(g,bb);
- if(bb->press)
- invalidate_button(g,bb);
-
- bb->rollover=0;
- bb->press=0;
- }
- }
- }
- allclear=1;
- grabbed=0;
-}
-
-/* handles mouse motion events; called out of gameboard's master
- motion handler; returns nonzero if it used focus */
-int button_motion_event(Gameboard *g, GdkEventMotion *event, int focusable){
- buttonstate *b = find_button((int)event->x,(int)event->y);
-
- if(buttons_ready){
- if(grabbed){
- if(grabbed==b)
- button_set_state(g,grabbed,1,1);
- else
- button_set_state(g,grabbed,0,0);
- return 1;
- }
-
- if(focusable && !grabbed){
-
- if(b){
- button_set_state(g,b,1,0);
- return 1;
- }
- }
-
- button_clear_state(g);
- }
- return 0;
-}
-
-/* handles mouse button press events; called out of gameboard's master
- mouse handler. returns nonzero if grabbing focus */
-int button_button_press(Gameboard *g, GdkEventButton *event, int focusable){
-
- if(buttons_ready){
- if(focusable){
-
- buttonstate *b = find_button((int)event->x,(int)event->y);
- if(b){
- button_set_state(g,b,1,1);
- grabbed = b;
- return 1;
- }
- }
-
- button_clear_state(g);
- }
- return 0;
-}
-
-/* handles mouse button press events; called out of gameboard's master
- mouse handler. returns nonzero if grabbing focus */
-int button_button_release(Gameboard *g, GdkEventButton *event, int focusable){
- if(focusable && buttons_ready){
-
- buttonstate *b = find_button((int)event->x,(int)event->y);
- if(b && grabbed==b){
- button_set_state(g,b,1,0);
-
- if(b->callback)
- b->callback(g);
-
-
- }
- }
-
- grabbed=0;
- return 0;
-}
Deleted: trunk/planarity/button_base.h
===================================================================
--- trunk/planarity/button_base.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/button_base.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,73 +0,0 @@
-#define NUMBUTTONS 11
-
-typedef struct {
- int position; // 0 inactive
- // 1 left
- // 2 center
- // 3 right
-
- int target_x;
- int target_x_inactive;
- int target_x_active;
-
- int x;
- int x_inactive;
- int x_active;
- int y;
-
- cairo_surface_t *idle;
- cairo_surface_t *lit;
-
- char *rollovertext;
- cairo_text_extents_t ex;
-
- int alphad;
- double alpha;
-
- int rollover;
- int press;
-
- void (*callback)();
-} buttonstate;
-
-buttonstate states[NUMBUTTONS];
-
-
-extern void init_buttons(Gameboard *g);
-extern void rollover_extents(Gameboard *g, buttonstate *b);
-extern gboolean animate_button_frame(gpointer ptr);
-extern void expose_buttons(Gameboard *g,cairo_t *c,int x, int y, int w, int h);
-extern void resize_buttons(int oldw,int oldh,int w,int h);
-extern int button_motion_event(Gameboard *g, GdkEventMotion *event, int focusable);
-extern int button_button_press(Gameboard *g, GdkEventButton *event, int focusable);
-extern int button_button_release(Gameboard *g, GdkEventButton *event, int focusable);
-extern void button_clear_state(Gameboard *g);
-extern int buttons_ready;
-
-#define BUTTON_QUIT_IDLE_FILL .7,.1,.1,.3
-#define BUTTON_QUIT_IDLE_PATH .7,.1,.1,.6
-
-#define BUTTON_QUIT_LIT_FILL .7,.1,.1,.5
-#define BUTTON_QUIT_LIT_PATH .7,.1,.1,.6
-
-#define BUTTON_IDLE_FILL .1,.1,.7,.3
-#define BUTTON_IDLE_PATH .1,.1,.7,.6
-
-#define BUTTON_LIT_FILL .1,.1,.7,.6
-#define BUTTON_LIT_PATH .1,.1,.7,.6
-
-#define BUTTON_CHECK_IDLE_FILL .1,.5,.1,.3
-#define BUTTON_CHECK_IDLE_PATH .1,.5,.1,.6
-
-#define BUTTON_CHECK_LIT_FILL .1,.5,.1,.6
-#define BUTTON_CHECK_LIT_PATH .1,.5,.1,.6
-
-#define BUTTON_RADIUS 14
-#define BUTTON_LINE_WIDTH 1
-#define BUTTON_TEXT_BORDER 15
-#define BUTTON_TEXT_COLOR .1,.1,.7,.8
-#define BUTTON_TEXT_SIZE 15.,18.
-
-#define BUTTON_ANIM_INTERVAL 15
-#define BUTTON_EXPOSE 50
-#define BUTTON_DELTA 3
Deleted: trunk/planarity/buttonbar.c
===================================================================
--- trunk/planarity/buttonbar.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/buttonbar.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,221 +0,0 @@
-#include <math.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "graph.h"
-#include "gameboard.h"
-#include "gamestate.h"
-#include "button_base.h"
-#include "buttonbar.h"
-#include "pause.h"
-
-/************************ the lower button bar *********************/
-
-static int checkbutton_deployed=0;
-static int sweeper=0;
-static gint timer = 0;
-static void (*undeploy_callback)(Gameboard *g);
-
-/* perform a single frame of animation for all buttons/rollovers */
-static gboolean buttonbar_animate_buttons(gpointer ptr){
- Gameboard *g=(Gameboard *)ptr;
- int ret=0;
-
- if(!g->first_expose)return 1;
-
- ret=animate_button_frame(g);
-
- if(!ret && timer!=0){
- g_source_remove(timer);
- timer=0;
- }
- return ret;
-}
-
-/* helper that wraps animate-buttons for removing the buttons at the
- end of a level */
-static gboolean buttonbar_deanimate_buttons(gpointer ptr){
- Gameboard *g=(Gameboard *)ptr;
- int ret=0,i;
- sweeper-=BUTTON_DELTA;
- if(sweeper< -(BUTTON_RADIUS +1)){
- sweeper= -(BUTTON_RADIUS +1);
- }else
- ret=1;
-
- {
-
- int width=get_board_width();
- int w2=width/2;
-
- for(i=0;i<NUMBUTTONS;i++){
- buttonstate *b=states+i;
- if(b->position){
- if(b->target_x>w2 && width-sweeper>b->target_x)
- b->target_x=width-sweeper;
- if(b->target_x<w2 && sweeper<b->target_x)
- b->target_x=sweeper;
- }
- }
- ret|=animate_button_frame(ptr);
- }
-
- if(!ret)
- // undeploy finished... call the undeploy callback
- undeploy_callback(g);
-
- return ret;
-}
-
-/******************** toplevel abstraction calls *********************/
-
-/* initialize the rather weird little animation engine */
-void setup_buttonbar(Gameboard *g){
-
- int count=BUTTONBAR_BORDER;
- int i;
- int w=get_board_width();
- int h=get_board_height();
-
- states[0].rollovertext="exit gPlanarity";
- states[1].rollovertext="back to menu";
- states[2].rollovertext="reset board";
- states[3].rollovertext="pause";
- states[4].rollovertext="help / about";
- states[5].rollovertext="expand";
- states[6].rollovertext="shrink";
- states[7].rollovertext="hide/show lines";
- states[8].rollovertext="mark intersections";
- states[9].rollovertext="click when finished!";
-
- states[0].callback = quit;
- states[2].callback = reset_board;
- states[3].callback = pause_game;
- states[4].callback = about_game;
- states[5].callback = expand;
- states[6].callback = shrink;
- states[7].callback = hide_show_lines;
- states[8].callback = mark_intersections;
- states[9].callback = finish_board;
-
- for(i=0;i<NUMBUTTONS;i++)
- states[i].position=0;
-
- states[0].position = 1; //left;
- states[1].position = 1; //left;
- states[2].position = 1; //left;
- states[3].position = 1; //left;
- states[4].position = 1; //left;
- states[5].position = 3; //right
- states[6].position = 3; //right
- states[7].position = 3; //right
- states[8].position = 3; //right
- states[9].position = 3; //right
-
- for(i=0;i<NUMBUTTONS;i++){
- buttonstate *b=states+i;
- if(b->position == 1){
- b->x=0;
- b->target_x=count;
- b->x_active=b->target_x_active=count;
- b->x_inactive=b->target_x_inactive=count-BUTTON_EXPOSE;
- b->y = h - BUTTONBAR_Y_FROM_BOTTOM;
- count += BUTTONBAR_SPACING;
- }
- }
- count -= BUTTONBAR_SPACING;
-
- // assumes we will always have at least as many buttons left as right
- sweeper=count;
-
- count=w-BUTTONBAR_BORDER;
- for(i=NUMBUTTONS-1;i>=0;i--){
- buttonstate *b=states+i;
- if(b->position == 3){
- b->x=w;
- b->target_x=count;
- b->x_active=b->target_x_active=count;
- b->x_inactive=b->target_x_inactive=count+BUTTON_EXPOSE;
- b->y = h - BUTTONBAR_Y_FROM_BOTTOM;
- if(i!=9 || checkbutton_deployed) // special-case the checkbutton
- count -= BUTTONBAR_SPACING;
- }
- }
-
- // special-case the checkbutton
- if(!checkbutton_deployed){
- states[9].target_x_inactive=states[9].target_x_active+BUTTONBAR_SPACING;
- states[9].x_inactive=states[9].target_x_inactive;
- states[9].target_x=states[9].target_x_inactive;
- }
-
- for(i=0;i<NUMBUTTONS;i++)
- if(states[i].position)
- rollover_extents(g,states+i);
-
-}
-
-/* effects animated 'rollout' of buttons when level begins */
-void deploy_buttonbar(Gameboard *g){
- if(!buttons_ready ){
- if(g->g->active_intersections <= get_objective())
- checkbutton_deployed=1;
- else
- checkbutton_deployed=0;
- setup_buttonbar(g);
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, buttonbar_animate_buttons, (gpointer)g);
- buttons_ready=1;
- }
-
-}
-
-/* effects animated rollout of 'check' button */
-void deploy_check(Gameboard *g){
- if(buttons_ready && !checkbutton_deployed){
- int i;
- for(i=5;i<9;i++){
- states[i].target_x-=BUTTONBAR_SPACING;
- states[i].target_x_active-=BUTTONBAR_SPACING;
- states[i].target_x_inactive-=BUTTONBAR_SPACING;
- }
- states[9].target_x=states[9].target_x_active;
- if(timer!=0)
- g_source_remove(timer);
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, buttonbar_animate_buttons, (gpointer)g);
- checkbutton_deployed=1;
- }
-}
-
-/* effects animated rollback of 'check' button */
-void undeploy_check(Gameboard *g){
- if(checkbutton_deployed){
- int i;
- for(i=5;i<9;i++){
- states[i].target_x+=BUTTONBAR_SPACING;
- states[i].target_x_active+=BUTTONBAR_SPACING;
- states[i].target_x_inactive+=BUTTONBAR_SPACING;
- }
- states[9].target_x=states[9].target_x_inactive;
- if(timer!=0)
- g_source_remove(timer);
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, buttonbar_animate_buttons, (gpointer)g);
- checkbutton_deployed=0;
- }
-}
-
-/* effects animated rollback of buttons at end of level */
-void undeploy_buttonbar(Gameboard *g, void (*callback)(Gameboard *g)){
- if(timer!=0)
- g_source_remove(timer);
-
- button_clear_state(g);
- buttons_ready=0;
- undeploy_callback=callback;
- checkbutton_deployed=0;
-
- g_timeout_add(BUTTON_ANIM_INTERVAL, buttonbar_deanimate_buttons, (gpointer)g);
-
-
-}
-
Deleted: trunk/planarity/buttonbar.h
===================================================================
--- trunk/planarity/buttonbar.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/buttonbar.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,21 +0,0 @@
-extern void setup_buttonbar(Gameboard *g);
-extern void deploy_buttonbar(Gameboard *g);
-extern void undeploy_buttonbar(Gameboard *g, void (*callback)());
-extern void deploy_check(Gameboard *g);
-extern void undeploy_check(Gameboard *g);
-
-#define BUTTONBAR_Y_FROM_BOTTOM 25
-#define BUTTONBAR_LINE_WIDTH 1
-#define BUTTONBAR_TEXT_BORDER 15
-#define BUTTONBAR_TEXT_COLOR .1,.1,.7,.8
-#define BUTTONBAR_TEXT_SIZE 15.,18.
-
-#define BUTTONBAR_ANIM_INTERVAL 15
-#define BUTTONBAR_EXPOSE 50
-#define BUTTONBAR_DELTA 3
-
-#define BUTTONBAR_LEFT 5
-#define BUTTONBAR_RIGHT 5
-#define BUTTONBAR_BUTTONS 5
-#define BUTTONBAR_BORDER 35
-#define BUTTONBAR_SPACING 35
Deleted: trunk/planarity/buttons.c
===================================================================
--- trunk/planarity/buttons.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/buttons.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,273 +0,0 @@
-#include <math.h>
-#include <gtk/gtk.h>
-
-#include "graph.h"
-#include "gameboard.h"
-#include "buttons.h"
-
-
-/************************* simple round icon drawing *********************/
-
-void path_button_help(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,-9,-2);
- cairo_curve_to(c,-8,-7, -4.5,-12, 0,-12);
- cairo_curve_to(c, 7,-12, 9,-6, 9,-4);
- cairo_curve_to(c, 9,0 ,6,2, 5,2);
-
- cairo_curve_to(c, 4,2, 2.5,3, 2.5,6);
- cairo_line_to(c,-2.5,6);
-
- cairo_curve_to(c,-2.5,3, -3,1, 0,-1);
- cairo_curve_to(c, 11,-4, -3,-12, -4,-2);
- cairo_close_path(c);
-
- cairo_move_to(c,-2.5,8);
- cairo_line_to(c,2.5,8);
- cairo_line_to(c,2.5,12);
- cairo_line_to(c,-2.5,12);
- cairo_close_path(c);
- cairo_fill_preserve(c);
-
- cairo_restore(c);
-
-}
-
-void path_button_pause(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_rectangle(c,-7,-9,5,18);
- cairo_rectangle(c,2,-9,5,18);
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_exit(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,-6,-9.5);
- cairo_line_to(c,0,-3.5);
- cairo_line_to(c,6,-9.5);
- cairo_line_to(c,9.5,-6);
- cairo_line_to(c,3.5,0);
- cairo_line_to(c,9.5,6);
- cairo_line_to(c,6,9.5);
- cairo_line_to(c,0,3.5);
- cairo_line_to(c,-6,9.5);
- cairo_line_to(c,-9.5,6);
- cairo_line_to(c,-3.5,0);
- cairo_line_to(c,-9.5,-6);
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_back(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,0,-11);
- cairo_line_to(c,-9,0);
- cairo_line_to(c,-3,0);
- cairo_line_to(c,-3,10);
- cairo_line_to(c,3,10);
- cairo_line_to(c,3,0);
- cairo_line_to(c,9,0);
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_reset(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,-11,-5);
- cairo_line_to(c,-12,1);
- cairo_line_to(c,-6,1);
- cairo_line_to(c,0, 11);
- cairo_line_to(c,6,1);
- cairo_line_to(c,12,1);
- cairo_line_to(c,11,-5);
- cairo_line_to(c,4,-5);
- cairo_line_to(c,0,2);
- cairo_line_to(c,-4,-5);
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_expand(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,-8.5,-3);
- cairo_line_to(c,-2.5,-3);
- cairo_line_to(c,-3,-8.5);
- cairo_line_to(c,3, -8.5);
- cairo_line_to(c,3,-3);
- cairo_line_to(c,8.5,-3);
- cairo_line_to(c,8.5,3);
- cairo_line_to(c,3,3);
- cairo_line_to(c,3,8.5);
- cairo_line_to(c,-3,8.5);
- cairo_line_to(c,-3,3);
- cairo_line_to(c,-8.5,3);
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_shrink(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,-10,-3);
- cairo_line_to(c,10,-3);
- cairo_line_to(c,10,3);
- cairo_line_to(c,-10,3);
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_lines(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,6,-4);
- cairo_arc(c,0,-4,6,0,2*M_PI);
-
- cairo_move_to(c,0,2);
- cairo_line_to(c,0,10);
- cairo_close_path(c);
-
- cairo_move_to(c,2.68328,5.36656-4);
- cairo_rel_line_to(c,4,8);
- cairo_close_path(c);
-
- cairo_move_to(c,-2.68328,5.36656-4);
- cairo_rel_line_to(c,-4,8);
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_int(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,8,0);
- cairo_line_to(c,0,8);
- cairo_line_to(c,-8,0);
- cairo_line_to(c,0,-8);
-
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_check(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,8,-8);
- cairo_curve_to(c, 7,-7, 11,-7.3, 10,-6);
- cairo_line_to(c,0,9);
- cairo_curve_to(c, -1,9.1, -2,11, -3,10);
- cairo_line_to(c,-11,4);
- cairo_curve_to(c, -12,3, -10,.5, -9,1);
- cairo_line_to(c,-3,3);
-
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
-void path_button_play(cairo_t *c, double x, double y){
-
- cairo_save(c);
- cairo_translate(c,x,y);
- cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
- cairo_set_line_width(c,1);
-
- cairo_arc(c,0,0,14,0,2*M_PI);
-
- cairo_move_to(c,-8,-8);
- cairo_line_to(c,10,0);
- cairo_line_to(c,-8,8);
- cairo_close_path(c);
-
- cairo_fill_preserve(c);
- cairo_restore(c);
-
-}
-
Deleted: trunk/planarity/buttons.h
===================================================================
--- trunk/planarity/buttons.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/buttons.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,45 +0,0 @@
-extern void path_button_help(cairo_t *c, double x, double y);
-extern void path_button_back(cairo_t *c, double x, double y);
-extern void path_button_reset(cairo_t *c, double x, double y);
-extern void path_button_pause(cairo_t *c, double x, double y);
-extern void path_button_exit(cairo_t *c, double x, double y);
-extern void path_button_expand(cairo_t *c, double x, double y);
-extern void path_button_shrink(cairo_t *c, double x, double y);
-extern void path_button_lines(cairo_t *c, double x, double y);
-extern void path_button_int(cairo_t *c, double x, double y);
-extern void path_button_check(cairo_t *c, double x, double y);
-extern void path_button_play(cairo_t *c, double x, double y);
-
-
-#define BUTTON_QUIT_IDLE_FILL .7,.1,.1,.3
-#define BUTTON_QUIT_IDLE_PATH .7,.1,.1,.6
-
-#define BUTTON_QUIT_LIT_FILL .7,.1,.1,.5
-#define BUTTON_QUIT_LIT_PATH .7,.1,.1,.6
-
-#define BUTTON_IDLE_FILL .1,.1,.7,.3
-#define BUTTON_IDLE_PATH .1,.1,.7,.6
-
-#define BUTTON_LIT_FILL .1,.1,.7,.6
-#define BUTTON_LIT_PATH .1,.1,.7,.6
-
-#define BUTTON_CHECK_IDLE_FILL .1,.5,.1,.3
-#define BUTTON_CHECK_IDLE_PATH .1,.5,.1,.6
-
-#define BUTTON_CHECK_LIT_FILL .1,.5,.1,.6
-#define BUTTON_CHECK_LIT_PATH .1,.5,.1,.6
-
-#define BUTTON_RADIUS 14
-#define BUTTON_Y_FROM_BOTTOM 25
-#define BUTTON_LINE_WIDTH 1
-#define BUTTON_TEXT_BORDER 15
-#define BUTTON_TEXT_COLOR .1,.1,.7,.8
-#define BUTTON_TEXT_SIZE 15.,18.
-
-#define BUTTON_ANIM_INTERVAL 15
-#define BUTTON_LEFT 5
-#define BUTTON_RIGHT 5
-#define BUTTON_BORDER 35
-#define BUTTON_SPACING 35
-#define BUTTON_EXPOSE 50
-#define BUTTON_DELTA 3
Added: trunk/planarity/dialog_finish.c
===================================================================
--- trunk/planarity/dialog_finish.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/dialog_finish.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,196 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "timer.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+#include "levelstate.h"
+#include "dialog_finish.h"
+#include "dialog_level.h"
+
+static void finish_post (Gameboard *g){
+ // back to buttonbar activity!
+ g->finish_dialog_active=0;
+ pop_curtain(g);
+ levelstate_next();
+ levelstate_go();
+ enter_game(g);
+}
+
+static void finish_level (Gameboard *g){
+ // back to buttonbar activity!
+ g->finish_dialog_active=0;
+ pop_curtain(g);
+ level_dialog(g,1);
+}
+
+static void finish_quit (Gameboard *g){
+ gtk_main_quit();
+}
+
+static void local_go (Gameboard *g){
+ undeploy_buttons(g,finish_post);
+}
+
+static void local_level (Gameboard *g){
+ undeploy_buttons(g,finish_level);
+}
+
+static void local_quit (Gameboard *g){
+ undeploy_buttons(g,finish_quit);
+}
+
+/* initialize the rather weird little animation engine */
+static void setup_finish_buttons(Gameboard *g,int bw, int bh){
+ int i;
+ int w=g->g.width;
+ int h=g->g.height;
+ buttonstate *states=g->b.states;
+
+ states[0].rollovertext="exit gPlanarity";
+ states[1].rollovertext="level selection menu";
+ states[10].rollovertext="play next level!";
+
+ states[0].callback = local_quit;
+ states[1].callback = local_level;
+ states[10].callback = local_go;
+
+ for(i=0;i<NUMBUTTONS;i++)
+ states[i].position=0;
+
+ states[0].position = 2; //center;
+ states[1].position = 2; //center;
+ states[10].position = 2; //center;
+
+ {
+ buttonstate *b=states;
+ b->x = b->x_target = w/2 - bw/2 + FINISH_BUTTON_BORDER;
+ b->y_active = h/2 + bh/2 - FINISH_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = 0;
+ }
+
+ {
+ buttonstate *b=states+1;
+ b->x = b->x_target = w/2;
+ b->y_active = h/2 + bh/2 - FINISH_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = SWEEP_DELTA;
+ }
+
+ {
+ buttonstate *b=states+10;
+ b->x = b->x_target = w/2 + bw/2 - FINISH_BUTTON_BORDER;
+ b->y_active = h/2 + bh/2 - FINISH_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = SWEEP_DELTA*2;
+ }
+
+ for(i=0;i<NUMBUTTONS;i++)
+ if(states[i].position)
+ rollover_extents(g,states+i);
+}
+
+static void draw_finishbox(Gameboard *g){
+ int w= g->g.width;
+ int h= g->g.height;
+
+ cairo_t *c = cairo_create(g->background);
+ borderbox_path(c,
+ w/2 - FINISHBOX_WIDTH/2,
+ h/2 - FINISHBOX_HEIGHT/2,
+ FINISHBOX_WIDTH,
+ FINISHBOX_HEIGHT);
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_fill(c);
+
+ centerbox(c,
+ w/2 - FINISHBOX_WIDTH/2,
+ h/2 - FINISHBOX_HEIGHT/2,
+ FINISHBOX_WIDTH,
+ SCOREHEIGHT);
+
+ centerbox(c,
+ w/2 - FINISHBOX_WIDTH/2 ,
+ h/2 + FINISHBOX_HEIGHT/2 - SCOREHEIGHT,
+ FINISHBOX_WIDTH,
+ SCOREHEIGHT);
+
+ {
+ cairo_matrix_t ma;
+ char *time = get_timer_string();
+ char buffer[160];
+ int time_bonus=graphscore_get_bonus(&g->g);
+
+ int y;
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&ma, 18.,18.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+
+ y=h/2-FINISHBOX_HEIGHT/2+SCOREHEIGHT/2;
+ render_text_centered(c,"Level Complete!", w/2,y);y+=45;
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_matrix_init_scale (&ma, 16.,16.);
+ cairo_set_font_matrix (c,&ma);
+
+ snprintf(buffer,160,"Elapsed: %s",time);
+ render_bordertext_centered(c,buffer, w/2,y);y+=24;
+
+
+ snprintf(buffer,160,"Objective: %d points",graphscore_get_score(&g->g));
+ render_bordertext_centered(c,buffer, w/2,y);y+=24;
+
+ snprintf(buffer,160,"Time bonus: %d points",time_bonus);
+ render_bordertext_centered(c,buffer, w/2,y);y+=35;
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ snprintf(buffer,160,"Final score: %d points",graphscore_get_score(&g->g)+time_bonus);
+ render_bordertext_centered(c,buffer, w/2,y);y+=24;
+
+ if(graphscore_get_score(&g->g)+time_bonus >= levelstate_get_hiscore()){
+ cairo_set_source_rgba (c, HIGH_COLOR);
+ render_bordertext_centered(c,"A high score!", w/2,y);y+=45;
+ cairo_set_source_rgba (c, TEXT_COLOR);
+ }else{
+ snprintf(buffer,160,"Previous best: %ld points",levelstate_get_hiscore());
+ render_bordertext_centered(c,buffer, w/2,y);y+=45;
+ }
+
+
+ render_bordertext_centered(c,"Total score to date:", w/2,y);
+ y+=21;
+ snprintf(buffer,160,"%ld points",levelstate_total_hiscore());
+ render_bordertext_centered(c,buffer, w/2,y);
+
+ }
+
+ cairo_destroy(c);
+}
+
+void finish_level_dialog(Gameboard *g){
+ g->finish_dialog_active=1;
+
+ // set up new buttons
+ setup_finish_buttons(g,FINISHBOX_WIDTH, FINISHBOX_HEIGHT);
+
+ // draw pausebox
+ push_curtain(g,draw_finishbox);
+
+ // deploy new buttons
+ deploy_buttons(g,0);
+}
+
Added: trunk/planarity/dialog_finish.h
===================================================================
--- trunk/planarity/dialog_finish.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/dialog_finish.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,6 @@
+#define FINISH_BUTTON_BORDER 35
+#define FINISH_BUTTON_Y 25
+#define FINISHBOX_WIDTH 220
+#define FINISHBOX_HEIGHT 330
+
+extern void finish_level_dialog(Gameboard *g);
Added: trunk/planarity/dialog_level.c
===================================================================
--- trunk/planarity/dialog_level.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/dialog_level.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,145 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "timer.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+#include "dialog_level.h"
+#include "levelstate.h"
+#include "main.h"
+
+static void unlevel_post (Gameboard *g){
+ g->level_dialog_active=0;
+ pop_curtain(g);
+ levelstate_go();
+ enter_game(g);
+}
+
+static void unlevel_quit (Gameboard *g){
+ gtk_main_quit();
+}
+
+static void local_go (Gameboard *g){
+ undeploy_buttons(g,unlevel_post);
+}
+
+static void local_quit (Gameboard *g){
+ undeploy_buttons(g,unlevel_quit);
+}
+
+/* initialize the rather weird little animation engine */
+static void setup_level_buttons(Gameboard *g,int bw, int bh){
+ int i;
+ int w=g->g.width;
+ int h=g->g.height;
+ buttonstate *states=g->b.states;
+
+ states[0].rollovertext="exit gPlanarity";
+ states[2].rollovertext="reset level";
+ states[10].rollovertext="play level!";
+
+ states[0].callback = local_quit;
+ states[2].callback = local_reset;
+ states[10].callback = local_go;
+
+ for(i=0;i<NUMBUTTONS;i++)
+ states[i].position=0;
+
+ states[0].position = 2; //center
+ states[2].position = 0; //undeployed by default (redundant)
+ states[10].position = 2; //center
+
+ {
+ buttonstate *b=states;
+ b->x = b->x_target = w/2 - bw/2 + LEVEL_BUTTON_BORDER;
+ b->y_active = h/2 + bh/2 - LEVEL_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = 0;
+ }
+
+ {
+ buttonstate *b=states+2;
+ b->x = b->x_target = w/2;
+ b->y_active = h/2 + bh/2 - LEVEL_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = SWEEP_DELTA;
+ }
+
+ {
+ buttonstate *b=states+10;
+ b->x = b->x_target = w/2 + bw/2 - LEVEL_BUTTON_BORDER;
+ b->y_active = h/2 + bh/2 - LEVEL_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = SWEEP_DELTA;
+ }
+
+ rollover_extents(g,states);
+ rollover_extents(g,states+2);
+ rollover_extents(g,states+10);
+}
+
+static void draw_levelbox(Gameboard *g){
+ int w= g->g.width;
+ int h= g->g.height;
+
+ cairo_t *c = cairo_create(g->background);
+ borderbox_path(c,
+ w/2 - LEVELBOX_WIDTH/2,
+ h/2 - LEVELBOX_HEIGHT/2,
+ LEVELBOX_WIDTH,
+ LEVELBOX_HEIGHT);
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_fill(c);
+
+ centerbox(c,
+ w/2 - LEVELBOX_WIDTH/2,
+ h/2 - LEVELBOX_HEIGHT/2,
+ LEVELBOX_WIDTH,
+ SCOREHEIGHT);
+
+ centerbox(c,
+ w/2 - LEVELBOX_WIDTH/2,
+ h/2 + LEVELBOX_HEIGHT/2 - SCOREHEIGHT,
+ LEVELBOX_WIDTH,
+ SCOREHEIGHT);
+
+ {
+ cairo_matrix_t ma;
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&ma, 18.,18.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+
+ render_text_centered(c,"Available Levels", w/2,h/2-LEVELBOX_HEIGHT/2+SCOREHEIGHT/2);
+
+ }
+
+ cairo_destroy(c);
+}
+
+void level_dialog(Gameboard *g, int advance){
+
+ g->level_dialog_active=1;
+ levelstate_write();
+
+ if(advance)
+ levelstate_next();
+
+ // set up new buttons
+ setup_level_buttons(g,LEVELBOX_WIDTH, LEVELBOX_HEIGHT);
+ level_icons_init(g);
+
+ // draw pausebox
+ push_curtain(g,draw_levelbox);
+
+ // deploy new buttons
+ deploy_buttons(g,0);
+}
+
Added: trunk/planarity/dialog_level.h
===================================================================
--- trunk/planarity/dialog_level.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/dialog_level.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,14 @@
+#define LEVEL_BUTTON_BORDER 35
+#define LEVEL_BUTTON_Y 25
+#define LEVELBOX_WIDTH 556
+#define LEVELBOX_HEIGHT 370
+
+#define ICON_DELTA 20
+
+extern void level_dialog(Gameboard *g,int advance);
+extern void render_level_icons(Gameboard *g, cairo_t *c, int ex,int ey, int ew, int eh);
+extern void level_icons_init(Gameboard *g);
+
+extern void level_mouse_motion(Gameboard *g, int x, int y);
+extern void level_mouse_press(Gameboard *g, int x, int y);
+extern void local_reset (Gameboard *g);
Added: trunk/planarity/dialog_level_icons.c
===================================================================
--- trunk/planarity/dialog_level_icons.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/dialog_level_icons.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,406 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "timer.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+#include "dialog_level.h"
+#include "levelstate.h"
+#include "main.h"
+
+typedef struct {
+ int num;
+ double alpha;
+ cairo_surface_t *icon;
+
+ int x;
+ int y;
+ int w;
+ int h;
+
+} onelevel;
+
+static onelevel level_icons[5];
+static int center_x;
+static int level_lit;
+static int reset_deployed;
+
+static void draw_forward_arrow(onelevel *l, cairo_t *c,int fill){
+ int w = l->w;
+ int h = l->h;
+ int cx = w/2;
+ int cy = h/2;
+ cairo_save(c);
+ cairo_translate(c,l->x+.5,l->y+.5);
+
+ cairo_set_line_width(c,B_LINE);
+
+ cairo_move_to(c,w-10,cy);
+ cairo_line_to(c,cx,h-10);
+ cairo_line_to(c,cx,(int)h*.75);
+ cairo_line_to(c,10,(int)h*.75);
+ cairo_line_to(c,10,(int)h*.25);
+ cairo_line_to(c,cx,(int)h*.25);
+ cairo_line_to(c,cx,10);
+ cairo_close_path(c);
+
+ if(fill){
+ cairo_set_source_rgba (c, B_COLOR);
+ cairo_fill_preserve (c);
+ }
+ cairo_set_source_rgba (c, B_LINE_COLOR);
+ cairo_stroke (c);
+ cairo_restore(c);
+}
+
+static void draw_backward_arrow(onelevel *l, cairo_t *c,int fill){
+ int w = l->w;
+ int h = l->h;
+ int cx = w/2;
+ int cy = h/2;
+ cairo_save(c);
+ cairo_translate(c,l->x-.5,l->y+.5);
+
+ cairo_set_line_width(c,B_LINE);
+
+ cairo_move_to(c,10,cy);
+ cairo_line_to(c,cx,h-10);
+ cairo_line_to(c,cx,(int)h*.75);
+ cairo_line_to(c,w-10,(int)h*.75);
+ cairo_line_to(c,w-10,(int)h*.25);
+ cairo_line_to(c,cx,(int)h*.25);
+ cairo_line_to(c,cx,10);
+ cairo_close_path(c);
+
+ if(fill){
+ cairo_set_source_rgba (c, B_COLOR);
+ cairo_fill_preserve (c);
+ }
+ cairo_set_source_rgba (c, B_LINE_COLOR);
+ cairo_stroke (c);
+ cairo_restore(c);
+}
+
+static void invalidate_icon(Gameboard *g,onelevel *l){
+ GdkRectangle r;
+
+ r.x=l->x+center_x;
+ r.y=l->y;
+ r.width=l->w;
+ r.height=l->h;
+
+ gdk_window_invalidate_rect (GTK_WIDGET(g)->window, &r, FALSE);
+}
+
+static void onelevel_init(Gameboard *g, int num, onelevel *l){
+ int current = get_level_num();
+ l->num = num+current;
+
+ if(l->icon)cairo_surface_destroy(l->icon);
+ l->icon = levelstate_get_icon(num + current);
+ l->alpha = 0.;
+
+ l->w = ICON_WIDTH;
+ l->h = ICON_HEIGHT;
+ l->x = (g->g.width/2) - (l->w*.5) + num*ICON_WIDTH*1.2;
+ l->y = (g->g.height - LEVELBOX_HEIGHT) / 2 + 120;
+
+}
+
+static void deploy_reset_button(Gameboard *g){
+ buttonstate *states=g->b.states;
+
+ if(!reset_deployed){
+ states[10].sweepdeploy += SWEEP_DELTA;
+
+ states[2].position = 2; //activate it
+ states[2].y_target = states[2].y_active;
+
+ reset_deployed=1;
+ }
+
+ // even if the button is already 'deployed', the animation may
+ // have been interrupted. Retrigger.
+
+ if(g->b.buttons_ready){
+ if(g->gtk_timer!=0)
+ g_source_remove(g->gtk_timer);
+ g->gtk_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
+ }
+
+}
+
+static void undeploy_reset_button(Gameboard *g){
+ buttonstate *states=g->b.states;
+
+ if(reset_deployed){
+
+ states[10].sweepdeploy -= SWEEP_DELTA;
+ states[2].y_target = states[2].y_inactive;
+
+ reset_deployed=0;
+ }
+
+ // even if the button is already 'undeployed', the animation may
+ // have been interrupted. Retrigger.
+ if(g->b.buttons_ready){
+ if(g->gtk_timer!=0)
+ g_source_remove(g->gtk_timer);
+ g->gtk_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
+ }
+}
+
+static void alpha_update(onelevel *l){
+ int distance = labs(l->x - level_icons[2].x + center_x);
+ double alpha = 1. - (distance/300.);
+ if(alpha<0.)alpha=0.;
+ //if(alpha>1.)alpha=1.;
+ l->alpha = alpha;
+}
+
+void level_icons_init(Gameboard *g){
+ int i;
+
+ for(i=0;i<5;i++)
+ onelevel_init(g,i-2,level_icons+i);
+
+ center_x = 0;
+ level_lit = 2;
+ reset_deployed = 0;
+
+ if(levelstate_in_progress())
+ deploy_reset_button(g);
+
+}
+
+void render_level_icons(Gameboard *g, cairo_t *c, int ex,int ey, int ew, int eh){
+ if(g->level_dialog_active){
+ int w= g->g.width;
+ int h= g->g.height;
+ int y = h/2-LEVELBOX_HEIGHT/2+SCOREHEIGHT/2;
+ int i;
+
+ int ex2 = ex+ew;
+ int ey2 = ey+eh;
+
+ for(i=0;i<5;i++){
+ onelevel *l=level_icons+i;
+ alpha_update(l);
+ if(l->num >= 0 && c){
+
+ int iw = l->w;
+ int ih = l->h;
+ int ix = l->x+center_x;
+ int iy = l->y;
+
+ if( l->alpha == 0.) continue;
+
+ if( ix+iw < ex ) continue;
+ if( ix > ex2 ) continue;
+ if( iy+ih < ey ) continue;
+ if( iy > ey2 ) continue;
+
+ if(l->icon){
+ cairo_set_source_surface(c,l->icon,ix,iy);
+ cairo_paint_with_alpha(c,l->alpha);
+ }
+
+ if(center_x==0){
+ if(i==2){
+ cairo_set_source_rgba (c, B_COLOR);
+ borderbox_path(c,ix+1.5,iy+1.5,iw-3,ih-3);
+ cairo_fill (c);
+ }
+
+ if(i==1)
+ draw_backward_arrow(l,c,i==level_lit);
+ if(i==3)
+ draw_forward_arrow(l,c,i==level_lit);
+ }
+ }
+ }
+
+ // render level related text
+ if(center_x == 0 && c){
+ char buffer[160];
+ cairo_matrix_t ma;
+
+ // above text
+ snprintf(buffer,160,"Level %d:",get_level_num()+1);
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+ cairo_matrix_init_scale (&ma, 20.,20.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+ render_bordertext_centered(c, buffer,w/2,y+45);
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_matrix_init_scale (&ma, 18.,18.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+ render_bordertext_centered(c, get_level_desc(),w/2,y+70);
+
+ if(levelstate_get_hiscore()==0){
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_ITALIC,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ snprintf(buffer,160,"[not yet completed]");
+ }else{
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ snprintf(buffer,160,"level high score: %ld",levelstate_get_hiscore());
+ }
+
+ cairo_matrix_init_scale (&ma, 18.,18.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+ render_bordertext_centered(c, buffer,w/2,y+245);
+
+ snprintf(buffer,160,"total score all levels: %ld",levelstate_total_hiscore());
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_matrix_init_scale (&ma, 18.,18.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+ render_bordertext_centered(c, buffer,w/2,y+265);
+
+
+
+
+ }
+ }
+}
+
+static gboolean animate_level_frame(gpointer ptr){
+ Gameboard *g = GAMEBOARD (ptr);
+ int i;
+
+ if(center_x == 0){
+ g_source_remove(g->gtk_timer);
+ g->gtk_timer=0;
+
+ if(levelstate_in_progress())
+ deploy_reset_button(g);
+ else
+ undeploy_reset_button(g);
+
+ expose_full(g);
+ return 0;
+ }
+
+ for(i=0;i<5;i++)
+ if(level_icons[i].alpha)
+ invalidate_icon(g, level_icons+i);
+
+ if(center_x < 0){
+ center_x += ICON_DELTA;
+ if(center_x > 0) center_x = 0;
+ }else{
+ center_x -= ICON_DELTA;
+ if(center_x < 0) center_x = 0;
+ }
+
+ // trick 'expose'; run it with a region that does nothing in order
+ // to update the visibility flags
+
+ render_level_icons(g, 0, 0, 0, 0, 0);
+
+ for(i=0;i<5;i++)
+ if(level_icons[i].alpha)
+ invalidate_icon(g, level_icons+i);
+
+ return 1;
+}
+
+static int find_icon(int x, int y){
+ int i;
+
+ for(i=1;i<4;i++){
+ onelevel *l=level_icons+i;
+ if(l->num>=0){
+ if(x >= l->x &&
+ x <= l->x + l->w &&
+ y >= l->y &&
+ y <= l->y + l->h)
+ return i;
+ }
+ }
+ return 2;
+}
+
+void local_reset (Gameboard *g){
+ levelstate_reset();
+ onelevel_init(g,0,level_icons+2);
+ invalidate_icon(g, level_icons+2);
+ undeploy_reset_button(g);
+}
+
+void level_mouse_motion(Gameboard *g, int x, int y){
+
+ int icon = find_icon(x,y);
+
+ if(icon != level_lit){
+ invalidate_icon(g, level_icons+level_lit);
+ level_lit = icon;
+ invalidate_icon(g, level_icons+level_lit);
+ }
+}
+
+void level_mouse_press(Gameboard *g, int x, int y){
+ int i;
+
+ level_mouse_motion(g, x, y);
+
+ if(level_lit == 1){
+ if(levelstate_prev()){
+ if(level_icons[4].icon)cairo_surface_destroy(level_icons[4].icon);
+ for(i=4;i>=1;i--){
+ level_icons[i].num = level_icons[i-1].num;
+ level_icons[i].icon = level_icons[i-1].icon;
+ }
+ level_icons[0].icon=0;
+ onelevel_init(g,-2,level_icons);
+
+ if(center_x==0)expose_full(g); // only needed to 'undraw' the text
+
+ center_x = level_icons[1].x - level_icons[2].x;
+ }
+ }
+
+ if(level_lit == 3){
+ if(levelstate_next()){
+
+ if(level_icons[0].icon)cairo_surface_destroy(level_icons[0].icon);
+ for(i=0;i<4;i++){
+ level_icons[i].num = level_icons[i+1].num;
+ level_icons[i].icon = level_icons[i+1].icon;
+ }
+ level_icons[4].icon=0;
+ onelevel_init(g,2,level_icons+4);
+
+ if(center_x==0)expose_full(g); // only needed to 'undraw' the text
+
+ center_x = level_icons[3].x - level_icons[2].x;
+
+ }
+ }
+
+ if(center_x){
+ if(g->gtk_timer)
+ g_source_remove(g->gtk_timer);
+ g->gtk_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_level_frame, (gpointer)g);
+ }
+
+}
+
+
+
Added: trunk/planarity/dialog_pause.c
===================================================================
--- trunk/planarity/dialog_pause.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/dialog_pause.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,232 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "timer.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+#include "dialog_pause.h"
+
+extern char *version;
+
+static void unpause_post (Gameboard *g){
+ // back to buttonbar activity!
+ pop_curtain(g);
+ deploy_buttonbar(g);
+ unpause_timer();
+ g->about_dialog_active=0;
+ g->pause_dialog_active=0;
+}
+
+static void unpause_quit (Gameboard *g){
+ gtk_main_quit();
+}
+
+static void local_unpause (Gameboard *g){
+ undeploy_buttons(g,unpause_post);
+}
+
+static void local_quit (Gameboard *g){
+ undeploy_buttons(g,unpause_quit);
+}
+
+/* initialize the rather weird little animation engine */
+static void setup_pause_buttons(Gameboard *g,int bw, int bh){
+ int i;
+ int w=g->g.width;
+ int h=g->g.height;
+ buttonstate *states=g->b.states;
+
+ states[0].rollovertext="exit gPlanarity";
+ states[10].rollovertext="resume game!";
+
+ states[0].callback = local_quit;
+ states[10].callback = local_unpause;
+
+ for(i=0;i<NUMBUTTONS;i++)
+ states[i].position=0;
+
+ states[0].position = 2; //center;
+ states[10].position = 2; //center;
+
+ {
+ buttonstate *b=states;
+ b->x = b->x_target = w/2 - bw/2 + PAUSE_BUTTON_BORDER;
+ b->y_active = h/2 + bh/2 - PAUSE_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = 0;
+ }
+
+ {
+ buttonstate *b=states+10;
+ b->x = b->x_target = w/2 + bw/2 - PAUSE_BUTTON_BORDER;
+ b->y_active = h/2 + bh/2 - PAUSE_BUTTON_Y;
+ b->y = b->y_target = b->y_inactive = b->y_active + BUTTON_EXPOSE;
+ b->sweepdeploy = SWEEP_DELTA;
+ }
+
+ for(i=0;i<NUMBUTTONS;i++)
+ if(states[i].position)
+ rollover_extents(g,states+i);
+}
+
+static void draw_pausebox(Gameboard *g){
+ int w= g->g.width;
+ int h= g->g.height;
+
+ cairo_t *c = cairo_create(g->background);
+ borderbox_path(c,
+ w/2 - PAUSEBOX_WIDTH/2,
+ h/2 - PAUSEBOX_HEIGHT/2,
+ PAUSEBOX_WIDTH,
+ PAUSEBOX_HEIGHT);
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_fill(c);
+
+ centerbox(c,
+ w/2 - PAUSEBOX_WIDTH/2,
+ h/2 - PAUSEBOX_HEIGHT/2,
+ PAUSEBOX_WIDTH,
+ SCOREHEIGHT);
+
+ centerbox(c,
+ w/2 - PAUSEBOX_WIDTH/2 ,
+ h/2 + PAUSEBOX_HEIGHT/2 - SCOREHEIGHT,
+ PAUSEBOX_WIDTH,
+ SCOREHEIGHT);
+
+ {
+ cairo_matrix_t ma;
+ char *time = get_timer_string();
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&ma, 18.,18.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+
+ render_text_centered(c,"Game Paused", w/2,h/2-PAUSEBOX_HEIGHT/2+SCOREHEIGHT/2);
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ render_bordertext_centered(c,"Time Elapsed:", w/2,h/2-30);
+ render_bordertext_centered(c,time, w/2,h/2);
+ }
+
+ cairo_destroy(c);
+}
+
+void pause_dialog(Gameboard *g){
+ g->pause_dialog_active=1;
+ // set up new buttons
+ setup_pause_buttons(g,PAUSEBOX_WIDTH, PAUSEBOX_HEIGHT);
+
+ // draw pausebox
+ push_curtain(g,draw_pausebox);
+
+ // deploy new buttons
+ deploy_buttons(g,0);
+}
+
+// the 'about' box is nearly identical, including the fact it pauses the game.
+// we just piggyback it here
+
+static void draw_aboutbox(Gameboard *g){
+ int w= g->g.width;
+ int h= g->g.height;
+
+ cairo_t *c = cairo_create(g->background);
+ borderbox_path(c,
+ w/2 - ABOUTBOX_WIDTH/2,
+ h/2 - ABOUTBOX_HEIGHT/2,
+ ABOUTBOX_WIDTH,
+ ABOUTBOX_HEIGHT);
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_fill(c);
+
+ centerbox(c,
+ w/2 - ABOUTBOX_WIDTH/2,
+ h/2 - ABOUTBOX_HEIGHT/2,
+ ABOUTBOX_WIDTH,
+ SCOREHEIGHT);
+
+ centerbox(c,
+ w/2 - ABOUTBOX_WIDTH/2 ,
+ h/2 + ABOUTBOX_HEIGHT/2 - SCOREHEIGHT,
+ ABOUTBOX_WIDTH,
+ SCOREHEIGHT);
+
+ {
+ cairo_matrix_t ma;
+ int y = h/2-ABOUTBOX_HEIGHT/2+SCOREHEIGHT/2;
+ cairo_select_font_face (c, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&ma, 18.,18.);
+ cairo_set_font_matrix (c,&ma);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+
+ render_text_centered(c,"gPlanarity", w/2,y);
+ cairo_select_font_face (c, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ y+=45;
+ render_bordertext_centered(c,"Untangle the mess!", w/2,y);
+ y+=30;
+
+ cairo_matrix_init_scale (&ma, 13.,13.);
+ cairo_set_font_matrix (c,&ma);
+ render_bordertext_centered(c,"Drag verticies to eliminate crossed lines.", w/2,y); y+=16;
+ render_bordertext_centered(c,"The objective may be a complete solution or", w/2,y); y+=16;
+ render_bordertext_centered(c,"getting as close as possible to solving an", w/2,y); y+=16;
+ render_bordertext_centered(c,"unsolvable puzzle. Work quickly and", w/2,y); y+=16;
+ render_bordertext_centered(c,"exceed the objective for bonus points!", w/2,y); y+=16;
+
+ y+=16;
+ cairo_move_to (c, w/2-100,y);
+ cairo_line_to (c, w/2+100,y);
+ cairo_stroke(c);
+ y+=32;
+
+ cairo_matrix_init_scale (&ma, 12.,13.);
+ cairo_set_font_matrix (c,&ma);
+ render_bordertext_centered(c,"gPlanarity written by Monty <monty at xiph.org>",w/2,y);y+=17;
+ render_bordertext_centered(c,"as a demonstration of Gtk+/Cairo",w/2,y);y+=32;
+
+ render_bordertext_centered(c,"Original Flash version of Planarity by",w/2,y);y+=17;
+ render_bordertext_centered(c,"John Tantalo <john.tantalo at case.edu>",w/2,y);y+=32;
+
+ render_bordertext_centered(c,"Original game concept by Mary Radcliffe",w/2,y);y+=17;
+
+
+ y = h/2+ABOUTBOX_HEIGHT/2-SCOREHEIGHT/2;
+ cairo_select_font_face (c, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&ma, 10.,11.);
+ cairo_set_font_matrix (c,&ma);
+ render_text_centered(c,version, w/2,y);
+
+ }
+
+ cairo_destroy(c);
+}
+
+void about_dialog(Gameboard *g){
+ g->about_dialog_active=1;
+
+ // set up new buttons
+ setup_pause_buttons(g,ABOUTBOX_WIDTH,ABOUTBOX_HEIGHT);
+
+ // draw about box
+ push_curtain(g,draw_aboutbox);
+
+ // deploy new buttons
+ deploy_buttons(g,0);
+}
Added: trunk/planarity/dialog_pause.h
===================================================================
--- trunk/planarity/dialog_pause.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/dialog_pause.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,10 @@
+#define PAUSE_BUTTON_BORDER 35
+#define PAUSE_BUTTON_Y 25
+#define PAUSEBOX_WIDTH 180
+#define PAUSEBOX_HEIGHT 250
+
+#define ABOUTBOX_WIDTH 320
+#define ABOUTBOX_HEIGHT 400
+
+extern void pause_dialog(Gameboard *g);
+extern void about_dialog(Gameboard *g);
Deleted: trunk/planarity/finish.c
===================================================================
--- trunk/planarity/finish.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/finish.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,250 +0,0 @@
-#include <math.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "graph.h"
-#include "gameboard.h"
-#include "gamestate.h"
-#include "button_base.h"
-#include "buttonbar.h"
-#include "finish.h"
-#include "box.h"
-
-static int ui_next=0;
-static gint timer;
-static void (*callback)(Gameboard *);
-
-/* perform a single frame of animation for all pause dialog buttons/rollovers */
-static gboolean finish_animate_buttons(gpointer ptr){
- Gameboard *g=(Gameboard *)ptr;
- int ret=0;
-
- ret=animate_button_frame(g);
-
- if(!ret && timer!=0){
- g_source_remove(timer);
- timer=0;
- }
-
- if(!ret && callback)
- // undeploy finished... call the undeploy callback
- callback(g);
-
- return ret;
-}
-
-static void finish_post (Gameboard *g){
- // back to buttonbar activity!
- ui_next=0;
- pop_background(g);
- levelstate_next();
- levelstate_go();
- gamestate_go();
-}
-
-static void finish_quit (Gameboard *g){
- gtk_main_quit();
-}
-
-static void undeploy_buttons(Gameboard *g){
- // undeploy pause buttons
- button_clear_state(g);
- buttons_ready=0;
-
- {
- buttonstate *b=states;
- b->target_x-=BUTTON_EXPOSE;
- }
- {
- buttonstate *b=states+1;
- b->target_x-=BUTTON_EXPOSE;
- }
- {
- buttonstate *b=states+10;
- b->target_x+=BUTTON_EXPOSE;
- }
-}
-
-static void local_go (Gameboard *g){
- undeploy_buttons(g);
- callback = finish_post;
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, finish_animate_buttons, (gpointer)g);
-}
-
-static void local_quit (Gameboard *g){
- undeploy_buttons(g);
- callback = finish_quit;
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, finish_animate_buttons, (gpointer)g);
-}
-
-/* initialize the rather weird little animation engine */
-static void setup_finish_buttons(Gameboard *g,int bw, int bh){
- int i;
- int w=get_board_width();
- int h=get_board_height();
-
- states[0].rollovertext="exit gPlanarity";
- states[1].rollovertext="level menu";
- states[10].rollovertext="next level!";
-
- states[0].callback = local_quit;
- states[1].callback = 0; // for now
- states[10].callback = local_go;
-
- for(i=0;i<NUMBUTTONS;i++)
- states[i].position=0;
-
- states[0].position = 2; //center;
- states[1].position = 2; //center;
- states[10].position = 2; //center;
-
- {
- buttonstate *b=states;
- b->target_x_active=
- b->x_active=
- b->target_x_active=
- b->target_x=
- w/2 - bw/2 + FINISH_BUTTON_BORDER;
- b->x=b->target_x_inactive=b->x_inactive=b->target_x - BUTTON_EXPOSE;
- b->y = h/2 + bh/2 - FINISH_BUTTON_Y;
- }
-
- {
- buttonstate *b=states+1;
- b->target_x_active=
- b->x_active=
- b->target_x_active=
- b->target_x= w/2;
- b->x=b->target_x_inactive=b->x_inactive=b->target_x - BUTTON_EXPOSE;
- b->y = h/2 + bh/2 - FINISH_BUTTON_Y;
- }
-
- {
- buttonstate *b=states+10;
- b->target_x_active=
- b->x_active=
- b->target_x_active=
- b->target_x=
- w/2 + bw/2 - FINISH_BUTTON_BORDER;
- b->x=b->target_x_inactive=b->x_inactive=b->target_x + BUTTON_EXPOSE;
- b->y = h/2 + bh/2 - FINISH_BUTTON_Y;
- }
-
- for(i=0;i<NUMBUTTONS;i++)
- if(states[i].position)
- rollover_extents(g,states+i);
-}
-
-static void render_text_centered(cairo_t *c, char *s, int x, int y){
- cairo_text_extents_t ex;
-
- cairo_text_extents (c, s, &ex);
- cairo_move_to (c, x-(ex.width/2)-ex.x_bearing, y-(ex.height/2)-ex.y_bearing);
- cairo_show_text (c, s);
-}
-
-static void draw_finishbox(Gameboard *g){
- int w= get_board_width();
- int h= get_board_height();
-
- cairo_t *c = cairo_create(g->background);
- borderbox_path(c,
- w/2 - FINISHBOX_WIDTH/2,
- h/2 - FINISHBOX_HEIGHT/2,
- FINISHBOX_WIDTH,
- FINISHBOX_HEIGHT);
- cairo_set_source_rgb(c,1,1,1);
- cairo_fill(c);
-
- centerbox(c,
- w/2 - FINISHBOX_WIDTH/2,
- h/2 - FINISHBOX_HEIGHT/2,
- FINISHBOX_WIDTH,
- SCOREHEIGHT);
-
- centerbox(c,
- w/2 - FINISHBOX_WIDTH/2 ,
- h/2 + FINISHBOX_HEIGHT/2 - SCOREHEIGHT,
- FINISHBOX_WIDTH,
- SCOREHEIGHT);
-
- {
- cairo_matrix_t ma;
- char time[160];
- char buffer[160];
- int ho = get_elapsed() / 3600;
- int mi = get_elapsed() / 60 - ho*60;
- int se = get_elapsed() - ho*3600 - mi*60;
- int y;
- int time_bonus=get_initial_intersections()-get_elapsed();
- if(time_bonus<0)time_bonus=0;
-
- if(ho){
- snprintf(time,160,"%d:%02d:%02d",ho,mi,se);
- }else if (mi){
- snprintf(time,160,"%d:%02d",mi,se);
- }else{
- snprintf(time,160,"%d seconds",se);
- }
-
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_matrix_init_scale (&ma, 18.,18.);
- cairo_set_font_matrix (c,&ma);
- cairo_set_source_rgba (c, TEXT_COLOR);
-
- y=h/2-FINISHBOX_HEIGHT/2+SCOREHEIGHT/2;
- render_text_centered(c,"Level Complete!", w/2,y);y+=45;
-
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
- cairo_matrix_init_scale (&ma, 16.,16.);
- cairo_set_font_matrix (c,&ma);
-
- snprintf(buffer,160,"Elapsed: %s",time);
- render_text_centered(c,buffer, w/2,y);y+=35;
-
-
- snprintf(buffer,160,"Score: %d",get_initial_intersections());
- render_text_centered(c,buffer, w/2,y);y+=24;
- snprintf(buffer,160,"Bonus: %d",time_bonus);
- render_text_centered(c,buffer, w/2,y);y+=45;
-
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
- snprintf(buffer,160,"Total score: %d",get_raw_score());
- render_text_centered(c,buffer, w/2,y);
-
- }
-
- cairo_destroy(c);
-}
-
-static void finish_post_undeploy(Gameboard *g){
- // set up new buttons
- setup_finish_buttons(g,FINISHBOX_WIDTH, FINISHBOX_HEIGHT);
-
- // draw pausebox
- push_curtain(g,draw_finishbox);
-
- // deploy new buttons
- callback=0;
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, finish_animate_buttons, (gpointer)g);
- buttons_ready=1;
-}
-
-void finish_level_dialog(Gameboard *g){
- // undeploy buttonbar
- ui_next=1;
- push_background(g,0);
- undeploy_buttonbar(g,finish_post_undeploy);
-}
-
-int finish_dialog_active(){
- return ui_next;
-}
Deleted: trunk/planarity/finish.h
===================================================================
--- trunk/planarity/finish.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/finish.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,7 +0,0 @@
-#define FINISH_BUTTON_BORDER 35
-#define FINISH_BUTTON_Y 25
-#define FINISHBOX_WIDTH 200
-#define FINISHBOX_HEIGHT 300
-
-extern void finish_level_dialog(Gameboard *g);
-extern int finish_dialog_active();
Modified: trunk/planarity/gameboard.c
===================================================================
--- trunk/planarity/gameboard.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -10,937 +10,36 @@
#include "graph.h"
#include "gameboard.h"
-#include "gamestate.h"
#include "levelstate.h"
-#include "button_base.h"
-#include "buttonbar.h"
-#include "box.h"
static GtkWidgetClass *parent_class = NULL;
-/* vertex area and draw operations ***********************************/
-
-// invalidate the box around a single vertex
-static void invalidate_region_vertex_off(GtkWidget *widget,
- vertex *v, int dx, int dy){
- if(v){
- GdkRectangle r;
- r.x = v->x - V_RADIUS - V_LINE + dx;
- r.y = v->y - V_RADIUS - V_LINE + dy;
- r.width = (V_RADIUS + V_LINE)*2;
- r.height = (V_RADIUS + V_LINE)*2;
-
- gdk_window_invalidate_rect (widget->window, &r, FALSE);
- }
-}
-
-void invalidate_region_vertex(Gameboard *g, vertex *v){
- invalidate_region_vertex_off(&g->w,v,0,0);
-}
-
-// invalidate the box around a single line
-static void invalidate_region_edges(GtkWidget *widget, vertex *v){
- GdkRectangle r;
-
- if(v){
- edge_list *el=v->edges;
- while (el){
- edge *e=el->edge;
- r.x = min(e->A->x,e->B->x) - E_LINE;
- r.y = min(e->A->y,e->B->y) - E_LINE;
- r.width = labs(e->B->x - e->A->x) + 1 + E_LINE*2;
- r.height = labs(e->B->y - e->A->y) + 1 + E_LINE*2;
- gdk_window_invalidate_rect (widget->window, &r, FALSE);
- el=el->next;
- }
- }
-}
-
-// invalidate the vertex and attached verticies
-static void invalidate_region_attached(GtkWidget *widget, vertex *v){
- if(v){
- edge_list *el=v->edges;
- while (el){
- edge *e=el->edge;
- if(e->A != v)invalidate_region_vertex(GAMEBOARD(widget),e->A);
- if(e->B != v)invalidate_region_vertex(GAMEBOARD(widget),e->B);
- el=el->next;
- }
- invalidate_region_vertex(GAMEBOARD(widget),v);
- }
-}
-
-// invalidate the selection box plus enough area to catch any verticies
-static void invalidate_region_selection(GtkWidget *widget){
- Gameboard *g = GAMEBOARD (widget);
- GdkRectangle r;
- r.x = g->selectionx - (V_RADIUS + V_LINE)*2;
- r.y = g->selectiony - (V_RADIUS + V_LINE)*2;
- r.width = g->selectionw + (V_RADIUS + V_LINE)*4;
- r.height = g->selectionh + (V_RADIUS + V_LINE)*4;
-
- gdk_window_invalidate_rect (widget->window, &r, FALSE);
-}
-
-// invalidate the selection box plus enough area to catch any verticies
-static void invalidate_region_verticies_selection(GtkWidget *widget){
- Gameboard *g = GAMEBOARD (widget);
- vertex *v=g->g->verticies;
- while(v){
- if(v->selected)
- invalidate_region_vertex_off(widget,v,g->dragx,g->dragy);
- v=v->next;
- }
-}
-
-static cairo_surface_t *cache_vertex(Gameboard *g){
- cairo_surface_t *ret=
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- (V_RADIUS+V_LINE)*2,
- (V_RADIUS+V_LINE)*2);
- cairo_t *c = cairo_create(ret);
-
- cairo_set_line_width(c,V_LINE);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
- cairo_set_source_rgb(c,V_FILL_IDLE_COLOR);
- cairo_fill_preserve(c);
- cairo_set_source_rgb(c,V_LINE_COLOR);
- cairo_stroke(c);
-
- cairo_destroy(c);
- return ret;
-}
-
-static cairo_surface_t *cache_vertex_sel(Gameboard *g){
- cairo_surface_t *ret=
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- (V_RADIUS+V_LINE)*2,
- (V_RADIUS+V_LINE)*2);
- cairo_t *c = cairo_create(ret);
-
- cairo_set_line_width(c,V_LINE);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
- cairo_set_source_rgb(c,V_FILL_LIT_COLOR);
- cairo_fill_preserve(c);
- cairo_set_source_rgb(c,V_LINE_COLOR);
- cairo_stroke(c);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS*.5,0,2*M_PI);
- cairo_set_source_rgb(c,V_FILL_IDLE_COLOR);
- cairo_fill(c);
-
- cairo_destroy(c);
- return ret;
-}
-
-static cairo_surface_t *cache_vertex_grabbed(Gameboard *g){
- cairo_surface_t *ret=
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- (V_RADIUS+V_LINE)*2,
- (V_RADIUS+V_LINE)*2);
- cairo_t *c = cairo_create(ret);
-
- cairo_set_line_width(c,V_LINE);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
- cairo_set_source_rgb(c,V_FILL_LIT_COLOR);
- cairo_fill_preserve(c);
- cairo_set_source_rgb(c,V_LINE_COLOR);
- cairo_stroke(c);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS*.5,0,2*M_PI);
- cairo_set_source_rgb(c,V_FILL_ADJ_COLOR);
- cairo_fill(c);
-
- cairo_destroy(c);
- return ret;
-}
-
-static cairo_surface_t *cache_vertex_lit(Gameboard *g){
- cairo_surface_t *ret=
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- (V_RADIUS+V_LINE)*2,
- (V_RADIUS+V_LINE)*2);
- cairo_t *c = cairo_create(ret);
-
- cairo_set_line_width(c,V_LINE);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
- cairo_set_source_rgb(c,V_FILL_LIT_COLOR);
- cairo_fill_preserve(c);
- cairo_set_source_rgb(c,V_LINE_COLOR);
- cairo_stroke(c);
-
- cairo_destroy(c);
- return ret;
-}
-
-static cairo_surface_t *cache_vertex_attached(Gameboard *g){
- cairo_surface_t *ret=
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- (V_RADIUS+V_LINE)*2,
- (V_RADIUS+V_LINE)*2);
- cairo_t *c = cairo_create(ret);
-
- cairo_set_line_width(c,V_LINE);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
- cairo_set_source_rgb(c,V_FILL_ADJ_COLOR);
- cairo_fill_preserve(c);
- cairo_set_source_rgb(c,V_LINE_COLOR);
- cairo_stroke(c);
-
- cairo_destroy(c);
- return ret;
-}
-
-static cairo_surface_t *cache_vertex_ghost(Gameboard *g){
- cairo_surface_t *ret=
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- (V_RADIUS+V_LINE)*2,
- (V_RADIUS+V_LINE)*2);
- cairo_t *c = cairo_create(ret);
-
- cairo_set_line_width(c,V_LINE);
- cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
- cairo_set_source_rgba(c,V_LINE_COLOR,.2);
- cairo_fill_preserve(c);
- cairo_set_source_rgba(c,V_LINE_COLOR,.4);
- cairo_stroke(c);
-
- cairo_destroy(c);
- return ret;
-}
-
-
-static void draw_vertex(cairo_t *c,vertex *v,cairo_surface_t *s){
- cairo_set_source_surface(c,
- s,
- v->x-V_LINE-V_RADIUS,
- v->y-V_LINE-V_RADIUS);
- cairo_paint(c);
-}
-
-static void setup_background_edge(cairo_t *c){
- cairo_set_line_width(c,E_LINE);
- cairo_set_source_rgba(c,E_LINE_B_COLOR);
-}
-
-static void setup_foreground_edge(cairo_t *c){
- cairo_set_line_width(c,E_LINE);
- cairo_set_source_rgba(c,E_LINE_F_COLOR);
-}
-
-static void draw_edge(cairo_t *c,edge *e){
- cairo_move_to(c,e->A->x,e->A->y);
- cairo_line_to(c,e->B->x,e->B->y);
-}
-
-static void finish_edge(cairo_t *c){
- cairo_stroke(c);
-}
-
-static void draw_selection_rectangle(Gameboard *g,cairo_t *c){
- cairo_set_source_rgba(c,SELECTBOX_COLOR);
- cairo_rectangle(c,g->selectionx,
- g->selectiony,
- g->selectionw,
- g->selectionh);
- cairo_fill(c);
-}
-
-static void midground_draw(Gameboard *g,cairo_t *c,int x,int y,int w,int h){
- /* Edges attached to the grabbed vertex are drawn here; they're the
- inactive edges. */
- if(g->grabbed_vertex && !g->hide_lines){
- edge_list *el=g->grabbed_vertex->edges;
- setup_foreground_edge(c);
- while(el){
- edge *e=el->edge;
- /* no need to check rectangle; if they're to be drawn, they'll
- always be in the rect */
- draw_edge(c,e);
- el=el->next;
- }
- finish_edge(c);
- }
-
- /* verticies are drawn in the foreground */
- {
- vertex *v = g->g->verticies;
- int clipx = x-V_RADIUS;
- int clipw = x+w+V_RADIUS;
- int clipy = y-V_RADIUS;
- int cliph = y+h+V_RADIUS;
-
- while(v){
-
- /* is the vertex in the expose rectangle? */
- if(v->x>=clipx && v->x<=clipw &&
- v->y>=clipy && v->y<=cliph){
-
- if(v == g->grabbed_vertex && !g->group_drag) {
- draw_vertex(c,v,g->vertex_grabbed);
- } else if( v->selected ){
- draw_vertex(c,v,g->vertex_sel);
- } else if ( v == g->lit_vertex){
- draw_vertex(c,v,g->vertex_lit);
- } else if (v->attached_to_grabbed && !g->group_drag){
- draw_vertex(c,v,g->vertex_attached);
- }else
- draw_vertex(c,v,g->vertex);
- }
-
- v=v->next;
- }
- }
-}
-
-static void background_draw(Gameboard *g,cairo_t *c){
- int width=get_board_width();
- int height=get_board_height();
- edge *e=g->g->edges;
-
- cairo_set_source_rgb(c,1,1,1);
- cairo_paint(c);
-
- if(!g->hide_lines){
- setup_background_edge(c);
- while(e){
- if(e->active){
- draw_edge(c,e);
- }
- e=e->next;
- }
- finish_edge(c);
- }
-
- // if there's a a group drag in progress, midground is drawn here
- if(g->group_drag)
- midground_draw(g,c,0,0,width,height);
-
-}
-
-static void background_addv(Gameboard *g,cairo_t *c, vertex *v){
- edge_list *el=v->edges;
-
- if(!g->hide_lines){
- setup_background_edge(c);
- while(el){
- edge *e=el->edge;
-
- if(e->active)
- draw_edge(c,e);
-
- el=el->next;
- }
- finish_edge(c);
- }
-}
-
-static void foreground_draw(Gameboard *g,cairo_t *c,
- int x,int y,int width,int height){
- /* if a group drag is in progress, draw the group ghosted in the foreground */
-
- if(g->group_drag){
- vertex *v = g->g->verticies;
- while(v){
-
- if( v->selected ){
- vertex tv;
- tv.x=v->x+g->dragx;
- tv.y=v->y+g->dragy;
- draw_vertex(c,&tv,g->vertex_ghost);
- }
-
- v=v->next;
- }
- }else
- midground_draw(g,c,x,y,width,height);
-
- if(g->selection_grab)
- draw_selection_rectangle(g,c);
-}
-
-static void update_background(GtkWidget *widget){
- Gameboard *g = GAMEBOARD (widget);
- GdkRectangle r;
- cairo_t *c = cairo_create(g->background);
-
- g->delayed_background=0;
-
- // render the far background plane
- background_draw(g,c);
- cairo_destroy(c);
-
- r.x=0;
- r.y=0;
- r.width=widget->allocation.width;
- r.height=widget->allocation.height;
-
- gdk_window_invalidate_rect (widget->window, &r, FALSE);
-
-}
-
-void update_full(Gameboard *g){
- update_background(&g->w);
-}
-
-// also updates score
-static void update_background_addv(GtkWidget *widget, vertex *v){
- Gameboard *g = GAMEBOARD (widget);
- cairo_t *c = cairo_create(g->background);
-
- g->delayed_background=0;
-
- // render the far background plane
- background_addv(g,c,v);
- cairo_destroy(c);
-
- invalidate_region_attached(widget,v);
-}
-
-static void update_background_delayed(GtkWidget *widget){
- Gameboard *g = GAMEBOARD (widget);
- g->delayed_background=1;
-}
-
-static void check_lit(GtkWidget *widget,int x, int y){
- Gameboard *g = GAMEBOARD (widget);
- vertex *v = find_vertex(g->g,x,y);
- if(v!=g->lit_vertex){
- invalidate_region_vertex(g,v);
- invalidate_region_vertex(g,g->lit_vertex);
- g->lit_vertex = v;
- }
-}
-
-static void score_update(Gameboard *g){
- /* Score, level, intersections */
- char level_string[160];
- char score_string[160];
- char int_string[160];
- char obj_string[160];
- cairo_text_extents_t extentsL;
- cairo_text_extents_t extentsS;
- cairo_text_extents_t extentsO;
- cairo_text_extents_t extentsI;
- cairo_matrix_t m;
-
- cairo_t *c = cairo_create(g->forescore);
-
- if(g->g->active_intersections <= get_objective()){
- deploy_check(g);
- }else{
- undeploy_check(g);
- }
-
-
- // clear the pane
- cairo_save(c);
- cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
- cairo_set_source_rgba (c, 1,1,1,1);
- cairo_paint(c);
- cairo_restore(c);
-
- topbox(c,get_board_width(),SCOREHEIGHT);
-
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_matrix_init_scale (&m, 12.,15.);
- cairo_set_font_matrix (c,&m);
- cairo_set_source_rgba (c, TEXT_COLOR);
-
- snprintf(level_string,160,"Level %d: \"%s\"",get_level_num()+1,get_level_name());
- snprintf(score_string,160,"Score: %d",get_score());
- snprintf(int_string,160,"Intersections: %d",g->g->active_intersections);
- snprintf(obj_string,160,"Objective: %s",get_objective_string());
-
- cairo_text_extents (c, level_string, &extentsL);
- cairo_text_extents (c, obj_string, &extentsO);
- cairo_text_extents (c, int_string, &extentsI);
- cairo_text_extents (c, score_string, &extentsS);
-
- /*
- text_h = extentsL.height;
- text_h = max(text_h,extentsO.height);
- text_h = max(text_h,extentsI.height);
- text_h = max(text_h,extentsS.height);
- */
-
- int ty1 = 23;
- int ty2 = 38;
-
- cairo_move_to (c, 15, ty1);
- cairo_show_text (c, int_string);
- cairo_move_to (c, 15, ty2);
- cairo_show_text (c, score_string);
-
- cairo_move_to (c, get_board_width()-extentsL.width-15, ty1);
- cairo_show_text (c, level_string);
- cairo_move_to (c, get_board_width()-extentsO.width-15, ty2);
- cairo_show_text (c, obj_string);
-
- cairo_destroy(c);
-
- // slightly lazy
- {
- GdkRectangle r;
- r.x=0;
- r.y=0;
- r.width=get_board_width();
- r.height = SCOREHEIGHT;
- gdk_window_invalidate_rect (g->w.window, &r, FALSE);
- }
-}
-
-#define CW 4
-static void cache_curtain(Gameboard *g){
- int x,y;
- cairo_t *c;
- g->curtains=
- cairo_surface_create_similar (cairo_get_target (g->wc),
- CAIRO_CONTENT_COLOR_ALPHA,
- CW,CW);
-
- c = cairo_create(g->curtains);
- cairo_save(c);
- cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
- cairo_set_source_rgba (c, 1,1,1,1);
- cairo_paint(c);
- cairo_restore(c);
-
- cairo_set_line_width(c,1);
- cairo_set_source_rgba (c, 0,0,0,.5);
-
- for(y=0;y<CW;y++){
- for(x=y&1;x<CW;x+=2){
- cairo_move_to(c,x+.5,y);
- cairo_rel_line_to(c,0,1);
- }
- }
- cairo_stroke(c);
- cairo_destroy(c);
-
- g->curtainp=cairo_pattern_create_for_surface (g->curtains);
- cairo_pattern_set_extend (g->curtainp, CAIRO_EXTEND_REPEAT);
-
-}
-
-static gint mouse_motion(GtkWidget *widget,
- GdkEventMotion *event){
- Gameboard *g = GAMEBOARD (widget);
-
- if(g->button_grabbed || paused_p()){
- g->button_grabbed =
- button_motion_event(g,event,
- (!g->lit_vertex && !g->grabbed_vertex && !g->selection_grab));
-
- if(paused_p())return TRUE;
- }
-
- if(!g->button_grabbed){
- if(g->grabbed_vertex){
- int x = (int)event->x;
- int y = (int)event->y;
- g->dragx = x-g->grabx;
- g->dragy = y-g->graby;
-
- invalidate_region_vertex(g,g->grabbed_vertex);
- invalidate_region_edges(widget,g->grabbed_vertex);
- move_vertex(g->g,g->grabbed_vertex,x+g->graboffx,y+g->graboffy);
- invalidate_region_vertex(g,g->grabbed_vertex);
- invalidate_region_edges(widget,g->grabbed_vertex);
- }else if (g->selection_grab){
- invalidate_region_selection(widget);
-
- g->selectionx = min(g->grabx, event->x);
- g->selectionw = labs(g->grabx - event->x);
- g->selectiony = min(g->graby, event->y);
- g->selectionh = labs(g->graby - event->y);
- select_verticies(g->g,
- g->selectionx,g->selectiony,
- g->selectionx+g->selectionw-1,
- g->selectiony+g->selectionh-1);
-
- invalidate_region_selection(widget);
- }else if(g->group_drag){
- invalidate_region_verticies_selection(widget);
- g->dragx = event->x - g->grabx;
- g->dragy = event->y - g->graby;
-
- // if this puts any of the dragged offscreen adjust the drag back
- // onscreen. It will avoid confusing/concerning users
- {
- vertex *v=g->g->verticies;
- int w=get_board_width();
- int h=get_board_height();
-
- while(v){
- if(v->selected){
- if(v->x + g->dragx >= w)
- g->dragx=w - v->x -1;
- if(v->x + g->dragx < 0 )
- g->dragx= -v->x;
- if(v->y + g->dragy >= h)
- g->dragy=h - v->y -1;
- if(v->y + g->dragy < 0 )
- g->dragy= -v->y;
- }
- v=v->next;
- }
- }
-
- invalidate_region_verticies_selection(widget);
- }else{
- check_lit(widget, (int)event->x,(int)event->y);
-
- button_motion_event(g,event,
- (!g->lit_vertex && !g->grabbed_vertex && !g->selection_grab));
-
- }
- }
- return TRUE;
-}
-
-static gboolean button_press (GtkWidget *widget,
- GdkEventButton *event){
- Gameboard *g = GAMEBOARD (widget);
-
- vertex *v = find_vertex(g->g,(int)event->x,(int)event->y);
- g->button_grabbed=0;
-
- if(paused_p()){
- // only buttongrabs
- if(button_button_press(g,event,1))
- g->button_grabbed=1;
- return TRUE;
- }
-
- if(!g->group_drag && event->state&GDK_SHIFT_MASK){
- if(v){
- if(v->selected){
- v->selected=0;
- g->selection_active--;
- }else{
- v->selected=1;
- g->selection_active++;
- }
- invalidate_region_vertex(g,g->lit_vertex);
- }else{
- // addending group drag
- g->selection_grab=1;
- g->grabx = (int)event->x;
- g->graby = (int)event->y;
- g->selectionx = g->grabx;
- g->selectionw = 0;
- g->selectiony = g->graby;
- g->selectionh = 0;
- }
- }else{
-
- if(g->selection_active){
- vertex *v = find_vertex(g->g,(int)event->x,(int)event->y);
- if(v && v->selected){
- // group drag
- g->group_drag=1;
- g->grabx = (int)event->x;
- g->graby = (int)event->y;
- g->dragx = 0;
- g->dragy = 0;
- // put the verticies into the background for faster update
- update_background(widget);
- }else{
-
- if(button_button_press(g,event,1)){
- g->button_grabbed=1;
- }else{
- deselect_verticies(g->g);
- update_background(widget);
- g->selection_active=0;
- g->group_drag=0;
- check_lit(widget,event->x,event->y);
- button_press(widget,event);
- }
- }
-
- }else if(g->lit_vertex){
- // vertex grab
- g->grabbed_vertex = g->lit_vertex;
- g->grabx = (int)event->x;
- g->graby = (int)event->y;
- g->graboffx = g->grabbed_vertex->x-g->grabx;
- g->graboffy = g->grabbed_vertex->y-g->graby;
-
- grab_vertex(g->g,g->grabbed_vertex);
- invalidate_region_attached(widget,g->grabbed_vertex);
- invalidate_region_edges(widget,g->grabbed_vertex);
-
- update_background_delayed(widget);
- }else{
-
- if(button_button_press(g,event,1)){
- g->button_grabbed=1;
- }else{
- // selection grab;
- g->selection_grab=1;
- g->grabx = (int)event->x;
- g->graby = (int)event->y;
- g->selectionx = g->grabx;
- g->selectionw = 0;
- g->selectiony = g->graby;
- g->selectionh = 0;
- }
- }
- }
-
- if(!g->button_grabbed)
- hide_intersections(g);
-
- return TRUE;
-}
-
-static gboolean button_release (GtkWidget *widget,
- GdkEventButton *event){
- Gameboard *g = GAMEBOARD (widget);
-
- button_button_release(g,event,1);
- if(paused_p())return TRUE;
-
- if(g->grabbed_vertex){
- ungrab_vertex(g->g,g->grabbed_vertex);
- update_background_addv(widget,g->grabbed_vertex);
- score_update(g);
- g->grabbed_vertex = 0;
- }
-
- if(g->selection_grab){
- invalidate_region_selection(widget);
- g->selection_grab=0;
- // are there selected verticies? Avoid accidentally misgrabbing one.
- if(num_selected_verticies(g->g)<=1){
- g->selection_active=0;
- deselect_verticies(g->g); // could have grabbed just one
- }else{
- commit_volatile_selection();
- g->selection_active=num_selected_verticies(g->g);
- }
- }
-
- if(g->group_drag){
- move_selected_verticies(g->g,g->dragx,g->dragy);
- update_background(widget); // cheating
- score_update(g);
- g->group_drag=0;
- }
-
- mouse_motion(widget,(GdkEventMotion *)event); // the cast is safe in
- // this case
-
- return TRUE;
-}
-
-static void size_request (GtkWidget *widget,GtkRequisition *requisition){
-
- requisition->width = get_orig_width();
- requisition->height = get_orig_height();
-
-}
-
static void gameboard_init (Gameboard *g){
-
// instance initialization
-
-
+ g->g.width=g->g.orig_width=800;
+ g->g.height=g->g.orig_height=600;
}
static void gameboard_destroy (GtkObject *object){
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-static void draw_intersection(cairo_t *c,double x, double y){
- cairo_move_to(c,x-INTERSECTION_RADIUS,y);
- cairo_rel_line_to(c,INTERSECTION_RADIUS,-INTERSECTION_RADIUS);
- cairo_rel_line_to(c,INTERSECTION_RADIUS,INTERSECTION_RADIUS);
- cairo_rel_line_to(c,-INTERSECTION_RADIUS,INTERSECTION_RADIUS);
- cairo_close_path(c);
+ // free local resources
}
-static void expose_intersections(Gameboard *g,cairo_t *c,
- int x,int y,int w,int h){
- if(g->show_intersections){
- cairo_set_source_rgba (c, INTERSECTION_COLOR);
- cairo_set_line_width(c, INTERSECTION_LINE_WIDTH);
-
- double xx=x-(INTERSECTION_LINE_WIDTH*.5 + INTERSECTION_RADIUS);
- double x2=w+x+(INTERSECTION_LINE_WIDTH + INTERSECTION_RADIUS*2);
- double yy=y-(INTERSECTION_LINE_WIDTH*.5 + INTERSECTION_RADIUS);
- double y2=h+y+(INTERSECTION_LINE_WIDTH + INTERSECTION_RADIUS*2);
-
- // walk the intersection list of all edges; draw if paired is a higher pointer
- edge *e=g->g->edges;
- while(e){
- intersection *i = e->i.next;
- while(i){
- if(i->paired > i){
- double ix=i->x, iy=i->y;
-
- if(ix >= xx && ix <= x2 && iy >= yy && iy <= y2)
- draw_intersection(c,ix,iy);
- }
- i=i->next;
- }
- e=e->next;
- }
- cairo_stroke(c);
- }
-}
-
-void pop_background(Gameboard *g){
- if(g->pushed_background){
- g->pushed_background=0;
- g->pushed_curtain=0;
- update_full(g);
- }
-}
-
-void push_background(Gameboard *g, void(*redraw_callback)(Gameboard *g)){
- cairo_t *c = cairo_create(g->background);
- int w = g->w.allocation.width;
- int h = g->w.allocation.height;
-
- if(g->pushed_background)
- pop_background(g);
-
- g->redraw_callback=redraw_callback;
-
- foreground_draw(g,c,0,0,w,h);
-
- // copy in the score and button surfaces
- cairo_set_source_surface(c,g->forescore,0,0);
- cairo_rectangle(c, 0,0,w,
- min(SCOREHEIGHT,h));
- cairo_fill(c);
-
- cairo_set_source_surface(c,g->forebutton,0,g->w.allocation.height-SCOREHEIGHT);
- cairo_rectangle(c, 0,0,w,h);
- cairo_fill(c);
-
- expose_intersections(g,c,0,0,w,h);
- cairo_destroy(c);
-
- if(redraw_callback)redraw_callback(g);
-
- g->pushed_background=1;
- {
- GdkRectangle r;
- r.x=0;
- r.y=0;
- r.width=w;
- r.height=h;
-
- gdk_window_invalidate_rect (g->w.window, &r, FALSE);
- }
-}
-
-void push_curtain(Gameboard *g,void(*redraw_callback)(Gameboard *g)){
- if(!g->pushed_background)push_background(g,0);
- if(!g->pushed_curtain){
- cairo_t *c = cairo_create(g->background);
- int w = g->w.allocation.width;
- int h = g->w.allocation.height;
- g->pushed_curtain=1;
-
- g->redraw_callback=redraw_callback;
- cairo_set_source (c, g->curtainp);
- cairo_paint(c);
- cairo_destroy(c);
-
- if(redraw_callback)redraw_callback(g);
-
- {
- GdkRectangle r;
- r.x=0;
- r.y=0;
- r.width=w;
- r.height=h;
-
- gdk_window_invalidate_rect (g->w.window, &r, FALSE);
- }
- }
-}
-
-void run_immediate_expose(Gameboard *g,
- int x, int y, int w, int h){
-
- if (w==0 || h==0) return;
-
- //fprintf(stderr,"(%d) %d/%d %d/%d\n",g->first_expose,x,w,y,h);
-
- cairo_t *c = cairo_create(g->foreground);
-
- // copy background to foreground draw buffer
- cairo_set_source_surface(c,g->background,0,0);
- cairo_rectangle(c,x,y,w,h);
- cairo_fill(c);
-
- if(!g->pushed_background){
- foreground_draw(g,c,x,y,w,h);
-
- // copy in any of the score or button surfaces?
- if(y<SCOREHEIGHT){
- cairo_set_source_surface(c,g->forescore,0,0);
- cairo_rectangle(c, x,y,w,
- min(SCOREHEIGHT-y,h));
- cairo_fill(c);
- }
- if(y+h>g->w.allocation.height-SCOREHEIGHT){
- cairo_set_source_surface(c,g->forebutton,0,g->w.allocation.height-SCOREHEIGHT);
- cairo_rectangle(c, x,y,w,h);
- cairo_fill(c);
- }
-
- expose_intersections(g,c,x,y,w,h);
- }
-
- expose_buttons(g,c,x,y,w,h);
-
- cairo_destroy(c);
-
- // blit to window
- cairo_set_source_surface(g->wc,g->foreground,0,0);
- cairo_rectangle(g->wc,x,y,w,h);
- cairo_fill(g->wc);
-
- if(g->delayed_background)update_background(&g->w);
- g->first_expose=1;
- //gdk_window_process_all_updates();
-}
-
static gint gameboard_expose (GtkWidget *widget,
GdkEventExpose *event){
-
Gameboard *g = GAMEBOARD (widget);
- run_immediate_expose(g,event->area.x,event->area.y,
- event->area.width,event->area.height);
+ gameboard_draw(g,event->area.x,event->area.y,
+ event->area.width,event->area.height);
return FALSE;
}
-static void paint_bottom_box (Gameboard *g){
- cairo_t *c = cairo_create(g->forebutton);
-
- cairo_save(c);
- cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
- cairo_set_source_rgba (c, 1,1,1,1);
- cairo_paint(c);
- cairo_restore(c);
-
- bottombox(c,g->w.allocation.width,SCOREHEIGHT);
- cairo_destroy(c);
+static void gameboard_size_request (GtkWidget *widget,
+ GtkRequisition *requisition){
+ Gameboard *g = GAMEBOARD (widget);
+ requisition->width = g->g.orig_width;
+ requisition->height = g->g.orig_height;
}
static void gameboard_realize (GtkWidget *widget){
@@ -1000,9 +99,6 @@
widget->allocation.width,
widget->allocation.height);
- // cache the vertex images that are drawn in quantity; the blit with
- // alpha is much faster than the render
-
g->vertex = cache_vertex(g);
g->vertex_lit = cache_vertex_lit(g);
g->vertex_attached = cache_vertex_attached(g);
@@ -1010,9 +106,9 @@
g->vertex_sel = cache_vertex_sel(g);
g->vertex_ghost = cache_vertex_ghost(g);
- update_background(widget);
- score_update(g);
- paint_bottom_box(g);
+ update_full(g);
+ update_score(g);
+ draw_buttonbar_box(g);
init_buttons(g);
cache_curtain(g);
}
@@ -1023,14 +119,15 @@
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (widget)){
- int oldw=get_board_width();
- int oldh=get_board_height();
+ int oldw=g->g.width;
+ int oldh=g->g.height;
- gdk_window_move_resize (widget->window, allocation->x, allocation->y,
- allocation->width, allocation->height);
-
-
- if (g->forescore)
+ g->g.width = allocation->width;
+ g->g.height = allocation->height;
+
+ if(g->wc)cairo_destroy(g->wc);
+
+ if (g->forescore)
cairo_surface_destroy(g->forescore);
if (g->forebutton)
cairo_surface_destroy(g->forebutton);
@@ -1039,6 +136,17 @@
if (g->foreground)
cairo_surface_destroy(g->foreground);
+ if (g->curtainp)
+ cairo_pattern_destroy(g->curtainp);
+ if (g->curtains)
+ cairo_surface_destroy(g->curtains);
+
+
+ gdk_window_move_resize (widget->window, allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ g->wc = gdk_cairo_create(widget->window);
+
g->background =
cairo_surface_create_similar (cairo_get_target (g->wc),
CAIRO_CONTENT_COLOR, // don't need alpha
@@ -1061,9 +169,11 @@
widget->allocation.width,
widget->allocation.height);
+ cache_curtain(g);
+
// recenter all the verticies; doesn't require recomputation
{
- vertex *v=g->g->verticies;
+ vertex *v=g->g.verticies;
int xd=(widget->allocation.width-oldw)*.5;
int yd=(widget->allocation.height-oldh)*.5;
@@ -1074,21 +184,15 @@
}
}
- // also verifies all verticies are onscreen
- resize_board(allocation->width,allocation->height);
+ // verify all verticies are onscreen
+ check_verticies();
- {
- int flag = g->pushed_background;
- if(flag)pop_background(g);
+ draw_buttonbar_box(g);
+ update_score(g);
+ update_full(g);
+
+ resize_buttons(g,oldw,oldh,widget->allocation.width,widget->allocation.height);
- update_background(widget);
- paint_bottom_box(g);
- score_update(g);
- resize_buttons(oldw,oldh,widget->allocation.width,widget->allocation.height);
-
- if(flag)push_background(g,g->redraw_callback);
-
- }
}
}
@@ -1106,10 +210,10 @@
widget_class->realize = gameboard_realize;
widget_class->expose_event = gameboard_expose;
- widget_class->size_request = size_request;
+ widget_class->size_request = gameboard_size_request;
widget_class->size_allocate = gameboard_size_allocate;
- widget_class->button_press_event = button_press;
- widget_class->button_release_event = button_release;
+ widget_class->button_press_event = mouse_press;
+ widget_class->button_release_event = mouse_release;
widget_class->motion_notify_event = mouse_motion;
}
@@ -1140,93 +244,8 @@
return gameboard_type;
}
-Gameboard *gameboard_new (graph *gr) {
+Gameboard *gameboard_new (void) {
GtkWidget *g = GTK_WIDGET (g_object_new (GAMEBOARD_TYPE, NULL));
Gameboard *gb = GAMEBOARD (g);
- gb->g=gr;
return gb;
}
-
-void gameboard_reset (Gameboard *g) {
- g->lit_vertex=0;
- g->grabbed_vertex=0;
- g->delayed_background=0;
-
- g->group_drag=0;
- g->button_grabbed=0;
- g->selection_grab=0;
- g->selection_active=num_selected_verticies(g->g);
-
- update_background(&g->w);
- score_update(g);
-}
-
-void hide_lines(Gameboard *g){
- g->hide_lines=1;
- update_background(&g->w);
-}
-
-void show_lines(Gameboard *g){
- g->hide_lines=0;
- update_background(&g->w);
-}
-
-int get_hide_lines(Gameboard *g){
- return g->hide_lines;
-}
-
-void show_intersections(Gameboard *g){
- if(!g->show_intersections){
- g->show_intersections=1;
- update_background(&g->w);
- }else{
- hide_intersections(g);
- }
-}
-
-void hide_intersections(Gameboard *g){
- if(g->show_intersections){
- g->show_intersections=0;
- update_background(&g->w);
- }
-}
-
-int selected(Gameboard *g){
- return g->selection_active;
-}
-
-/***************** save/load gameboard the widget state we want to be persistent **************/
-
-// there are only a few things; lines, intersections
-int gameboard_write(FILE *f, Gameboard *g){
-
- if(g->hide_lines)
- fprintf(f,"hide_lines 1\n");
- if(g->show_intersections)
- fprintf(f,"show_intersections 1\n");
-
- return 0;
-}
-
-int gameboard_read(FILE *f, Gameboard *g){
- char *line=NULL;
- size_t n=0;
- int i;
-
- g->hide_lines = 0;
- g->show_intersections = 0;
-
- while(getline(&line,&n,f)>0){
- if (sscanf(line,"hide_lines %d",&i)==1)
- if(i)
- g->hide_lines = 1;
-
- if (sscanf(line,"show_intersections %d",&i)==1)
- if(i)
- g->show_intersections = 1;
- }
-
- free(line);
-
- return 0;
-}
Modified: trunk/planarity/gameboard.h
===================================================================
--- trunk/planarity/gameboard.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,10 +1,8 @@
#include <glib.h>
#include <glib-object.h>
-#include <gtk/gtkcontainer.h>
-#include <gtk/gtksignal.h>
-#include <gtk/gtkdrawingarea.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
-
#define V_RADIUS 8
#define V_LINE 2
#define V_LINE_COLOR 0, 0, 0
@@ -18,9 +16,25 @@
#define SELECTBOX_COLOR .2,.8,.8,.3
#define INTERSECTION_COLOR 1,.1,.1,.8
-#define INTERSECTION_RADIUS 6
+#define INTERSECTION_RADIUS 10
#define INTERSECTION_LINE_WIDTH 2
+#define RESET_DELTA 2
+
+#define B_LINE 1
+#define B_BORDER 6.5
+#define B_RADIUS 20
+#define B_HUMP 130
+#define B_COLOR .1,.1,.7,.1
+#define B_LINE_COLOR 0, 0,.7,.3
+#define TEXT_COLOR .0,.0,.7,.6
+#define HIGH_COLOR .7,.0,.0,.6
+
+#define SCOREHEIGHT 50
+
+#define ICON_WIDTH 160
+#define ICON_HEIGHT 120
+
G_BEGIN_DECLS
#define GAMEBOARD_TYPE (gameboard_get_type ())
@@ -32,11 +46,51 @@
typedef struct _Gameboard Gameboard;
typedef struct _GameboardClass GameboardClass;
+#define NUMBUTTONS 11
+
+typedef struct {
+ int position; // 0 inactive
+ // 1 left
+ // 2 center
+ // 3 right
+ int x_target;
+ int x;
+
+ int y_target;
+ int y_inactive;
+ int y_active;
+ int y;
+ int sweepdeploy;
+
+ int alphad;
+ double alpha;
+
+ cairo_surface_t *idle;
+ cairo_surface_t *lit;
+
+ char *rollovertext;
+ cairo_text_extents_t ex;
+
+ int rollover;
+ int press;
+
+ void (*callback)();
+} buttonstate;
+
+typedef struct {
+ buttonstate states[NUMBUTTONS];
+ int buttons_ready;
+ int allclear; // short-circuit hint
+ int sweeper;
+ int sweeperd;
+ buttonstate *grabbed;
+} buttongroup;
+
struct _Gameboard{
GtkWidget w;
- graph *g;
- int pushed_background;
+ graph g;
+
int pushed_curtain;
void (*redraw_callback)(Gameboard *g);
@@ -55,7 +109,16 @@
cairo_surface_t *curtains;
int delayed_background;
+ int first_expose;
+ int hide_lines;
+ int show_intersections;
+ int finish_dialog_active;
+ int about_dialog_active;
+ int pause_dialog_active;
+ int level_dialog_active;
+ buttongroup b;
+
vertex *grabbed_vertex;
vertex *lit_vertex;
int group_drag;
@@ -75,11 +138,12 @@
int selectionw;
int selectionh;
- int hide_lines;
+ int checkbutton_deployed;
+ int buttonbar_sweeper;
+
+ gint gtk_timer;
+ void (*button_callback)(Gameboard *);
- int first_expose;
- int show_intersections;
-
};
struct _GameboardClass{
@@ -88,23 +152,101 @@
};
GType gameboard_get_type (void);
-Gameboard* gameboard_new (graph *g);
+Gameboard* gameboard_new (void);
G_END_DECLS
-extern void main_board(int argc, char *argv[]);
-extern void run_immediate_expose(Gameboard *g,int x, int y, int w, int h);
-extern void gameboard_reset(Gameboard *g);
-extern void hide_lines(Gameboard *g);
-extern void show_lines(Gameboard *g);
-extern int get_hide_lines(Gameboard *g);
-extern void show_intersections(Gameboard *g);
-extern void hide_intersections(Gameboard *g);
-extern void invalidate_region_vertex(Gameboard *g, vertex *v);
-extern int selected(Gameboard *g);
+extern void init_buttons(Gameboard *g);
+extern buttonstate *find_button(Gameboard *g,int x,int y);
+extern void button_set_state(Gameboard *g, buttonstate *b, int rollover, int press);
+extern void rollover_extents(Gameboard *g, buttonstate *b);
+extern gboolean animate_button_frame(gpointer ptr);
+extern void expose_buttons(Gameboard *g,cairo_t *c, int x,int y,int w,int h);
+extern void resize_buttons(Gameboard *g,int oldw,int oldh,int w,int h);
+extern void button_clear_state(Gameboard *g);
+
+extern void update_push(Gameboard *g, cairo_t *c);
+extern void push_curtain(Gameboard *g,void(*redraw_callback)(Gameboard *g));
+extern void pop_curtain(Gameboard *g);
+
+extern void prepare_reenter_game(Gameboard *g);
+extern void reenter_game(Gameboard *g);
+extern void enter_game(Gameboard *g);
+extern void quit_action(Gameboard *g);
+extern void finish_action(Gameboard *g);
+extern void expand_action(Gameboard *g);
+extern void shrink_action(Gameboard *g);
+extern void pause_action(Gameboard *g);
+extern void about_action(Gameboard *g);
+extern void level_action(Gameboard *g);
+extern void set_hide_lines(Gameboard *g, int state);
+extern void toggle_hide_lines(Gameboard *g);
+extern void set_show_intersections(Gameboard *g, int state);
+extern void toggle_show_intersections(Gameboard *g);
+extern void reset_action(Gameboard *g);
+extern int gameboard_write(char *basename, Gameboard *g);
+extern int gameboard_read(char *basename, Gameboard *g);
+
+extern void topbox (Gameboard *g,cairo_t *c, double w, double h);
+extern void bottombox (Gameboard *g,cairo_t *c, double w, double h);
+extern void centerbox (cairo_t *c, int x, int y, double w, double h);
+extern void borderbox_path (cairo_t *c, double x, double y, double w, double h);
+
+extern void setup_buttonbar(Gameboard *g);
+extern void deploy_buttonbar(Gameboard *g);
+extern void deploy_check(Gameboard *g);
+extern void undeploy_check(Gameboard *g);
+
+extern void update_draw(Gameboard *g);
extern void update_full(Gameboard *g);
-extern void pop_background(Gameboard *g);
-extern void push_background(Gameboard *g, void (*callback)(Gameboard *g));
-extern void push_curtain(Gameboard *g, void (*callback)(Gameboard *g));
-extern int gameboard_write(FILE *f, Gameboard *g);
-extern int gameboard_read(FILE *f, Gameboard *g);
+extern void expose_full(Gameboard *g);
+extern void update_full_delayed(Gameboard *g);
+extern void update_add_vertex(Gameboard *g, vertex *v);
+extern void gameboard_draw(Gameboard *g, int x, int y, int w, int h);
+extern void draw_foreground(Gameboard *g,cairo_t *c,
+ int x,int y,int width,int height);
+extern void draw_intersections(Gameboard *b,graph *g,cairo_t *c,
+ int x,int y,int w,int h);
+
+extern void draw_score(Gameboard *g);
+extern void update_score(Gameboard *g);
+
+extern void draw_vertex(cairo_t *c,vertex *v,cairo_surface_t *s);
+extern cairo_surface_t *cache_vertex(Gameboard *g);
+extern cairo_surface_t *cache_vertex_sel(Gameboard *g);
+extern cairo_surface_t *cache_vertex_grabbed(Gameboard *g);
+extern cairo_surface_t *cache_vertex_lit(Gameboard *g);
+extern cairo_surface_t *cache_vertex_attached(Gameboard *g);
+extern cairo_surface_t *cache_vertex_ghost(Gameboard *g);
+extern void invalidate_vertex_off(GtkWidget *widget, vertex *v, int dx, int dy);
+extern void invalidate_vertex(Gameboard *g, vertex *v);
+extern void invalidate_attached(GtkWidget *widget, vertex *v);
+extern void invalidate_edges(GtkWidget *widget, vertex *v);
+extern void draw_selection_rectangle(Gameboard *g,cairo_t *c);
+extern void invalidate_selection(GtkWidget *widget);
+extern void invalidate_verticies_selection(GtkWidget *widget);
+
+extern void cache_curtain(Gameboard *g);
+extern void draw_curtain(Gameboard *g);
+extern void draw_buttonbar_box (Gameboard *g);
+
+extern gint mouse_motion(GtkWidget *widget,GdkEventMotion *event);
+extern gboolean mouse_press (GtkWidget *widget,GdkEventButton *event);
+extern gboolean mouse_release (GtkWidget *widget,GdkEventButton *event);
+
+extern void setup_background_edge(cairo_t *c);
+extern void setup_foreground_edge(cairo_t *c);
+extern void draw_edge(cairo_t *c,edge *e);
+extern void finish_edge(cairo_t *c);
+
+extern cairo_surface_t *gameboard_read_icon(char *filename, char *ext,Gameboard *b);
+extern int gameboard_write_icon(char *filename, char *ext,Gameboard *b, graph *g,
+ int lines, int intersections);
+extern int gameboard_icon_exists(char *filename, char *ext);
+
+extern void deploy_buttons(Gameboard *g, void (*callback)(Gameboard *));
+extern void undeploy_buttons(Gameboard *g, void (*callback)(Gameboard *));
+
+extern GdkRectangle render_text_centered(cairo_t *c, char *s, int x, int y);
+extern GdkRectangle render_border_centered(cairo_t *c, char *s, int x, int y);
+extern GdkRectangle render_bordertext_centered(cairo_t *c, char *s, int x, int y);
Added: trunk/planarity/gameboard_draw_box.c
===================================================================
--- trunk/planarity/gameboard_draw_box.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_box.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,252 @@
+#include <math.h>
+#include <gtk/gtk.h>
+#include "graph.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+
+void topbox (Gameboard *g,cairo_t *c, double w, double h){
+
+ double x0 = B_BORDER+B_RADIUS;
+ double y0 = B_BORDER;
+
+ double x1 = B_BORDER;
+ double y1 = B_BORDER+B_RADIUS;
+
+ double x2 = B_BORDER;
+ double y2 = h-B_BORDER-B_RADIUS;
+
+ double x3 = B_BORDER+B_RADIUS;
+ double y3 = h-B_BORDER;
+
+ double x4 = w/2 - B_HUMP - B_RADIUS;
+ double y4 = h-B_BORDER;
+
+ double x5 = x4+B_RADIUS;
+ double y5 = y4;
+
+
+ double x7 = w/2 + B_HUMP + B_RADIUS;
+ double y7 = h-B_BORDER;
+
+ double x8 = w - B_BORDER -B_RADIUS;
+ double y8 = h-B_BORDER;
+
+ double x9 = w - B_BORDER;
+ double y9 = h-B_BORDER-B_RADIUS;
+
+ double x10 = w - B_BORDER;
+ double y10 = B_BORDER+B_RADIUS;
+
+ double x11 = w - B_BORDER-B_RADIUS;
+ double y11 = B_BORDER;
+
+ cairo_set_line_width(c,B_LINE);
+
+ cairo_move_to (c, x0, y0);
+ cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
+ cairo_line_to (c, x2,y2);
+ cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
+ cairo_line_to (c, x4,y4);
+
+ {
+ double hh = g->g.orig_height*.5+50;
+
+ double radius = sqrt( (w*.5-x5) * (w*.5-x5) + (hh-y5) * (hh-y5));
+ double siderad = atan( (x5-w*.5)/(hh-y5));
+
+ double xx = sin(siderad+.05)*radius+w*.5;
+ double yy = -cos(siderad+.05)*radius+hh;
+ double x = sin(siderad+.1)*radius+w*.5;
+ double y = -cos(siderad+.1)*radius+hh;
+
+ cairo_curve_to (c, x4+B_RADIUS,y4, xx,yy, x,y);
+ cairo_arc(c,w*.5,hh,radius,-M_PI*.5+siderad+.1,-M_PI*.5-siderad-.1);
+
+ xx = -sin(siderad+.05)*radius+w*.5;
+ yy = -cos(siderad+.05)*radius+hh;
+ xx = -sin(siderad+.1)*radius+w*.5;
+ yy = -cos(siderad+.1)*radius+hh;
+
+ cairo_curve_to (c, xx,yy, x7-B_RADIUS,y7, x7,y7);
+
+ }
+
+ cairo_line_to (c, x8,y8);
+ cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
+ cairo_line_to (c, x10,y10);
+ cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
+ cairo_close_path (c);
+
+ cairo_set_source_rgba (c, B_COLOR);
+ cairo_fill_preserve (c);
+ cairo_set_source_rgba (c, B_LINE_COLOR);
+ cairo_stroke (c);
+
+}
+
+void bottombox (Gameboard *g, cairo_t *c, double w, double h){
+
+ double x0 = B_BORDER+B_RADIUS;
+ double y0 = h-B_BORDER;
+
+ double x1 = B_BORDER;
+ double y1 = h-B_BORDER-B_RADIUS;
+
+ double x2 = B_BORDER;
+ double y2 = B_BORDER+B_RADIUS;
+
+ double x3 = B_BORDER+B_RADIUS;
+ double y3 = B_BORDER;
+
+ double x4 = w/2 - B_HUMP - B_RADIUS;
+ double y4 = B_BORDER;
+
+ double x5 = x4+B_RADIUS;
+ double y5 = y4;
+
+
+ double x7 = w/2 + B_HUMP + B_RADIUS;
+ double y7 = B_BORDER;
+
+ double x8 = w - B_BORDER -B_RADIUS;
+ double y8 = B_BORDER;
+
+ double x9 = w - B_BORDER;
+ double y9 = B_BORDER+B_RADIUS;
+
+ double x10 = w - B_BORDER;
+ double y10 = h- B_BORDER -B_RADIUS;
+
+ double x11 = w - B_BORDER-B_RADIUS;
+ double y11 = h-B_BORDER;
+
+ cairo_set_line_width(c,B_LINE);
+
+ cairo_move_to (c, x0, y0);
+ cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
+ cairo_line_to (c, x2,y2);
+ cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
+ cairo_line_to (c, x4,y4);
+
+ {
+ double hh = g->g.orig_height*.5+50;
+
+ double radius = sqrt( (w*.5-x5) * (w*.5-x5) + (y5+hh-h) * (y5+hh-h));
+ double siderad = atan( (x5-w*.5)/(y5+hh-h));
+
+ double xx = sin(siderad+.05)*radius+w*.5;
+ double yy = cos(siderad+.05)*radius-hh+h;
+ double x = sin(siderad+.1)*radius+w*.5;
+ double y = cos(siderad+.1)*radius-hh+h;
+
+ cairo_curve_to (c, x4+B_RADIUS,y4, xx,yy, x,y);
+ cairo_arc_negative(c,w*.5,h-hh,radius,M_PI*.5-siderad-.1,M_PI*.5+siderad+.1);
+
+ xx = -sin(siderad+.05)*radius+w*.5;
+ yy = cos(siderad+.05)*radius-hh+h;
+ xx = -sin(siderad+.1)*radius+w*.5;
+ yy = cos(siderad+.1)*radius-hh+h;
+
+ cairo_curve_to (c, xx,yy, x7-B_RADIUS,y7, x7,y7);
+
+ }
+
+ cairo_line_to (c, x8,y8);
+ cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
+ cairo_line_to (c, x10,y10);
+ cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
+ cairo_close_path (c);
+
+ cairo_set_source_rgba (c, B_COLOR);
+ cairo_fill_preserve (c);
+ cairo_set_source_rgba (c, B_LINE_COLOR);
+ cairo_stroke (c);
+
+}
+
+void centerbox (cairo_t *c, int x, int y, double w, double h){
+
+ double x0 = B_BORDER+B_RADIUS;
+ double y0 = h-B_BORDER;
+
+ double x1 = B_BORDER;
+ double y1 = h-B_BORDER-B_RADIUS;
+
+ double x2 = B_BORDER;
+ double y2 = B_BORDER+B_RADIUS;
+
+ double x3 = B_BORDER+B_RADIUS;
+ double y3 = B_BORDER;
+
+ double x8 = w - B_BORDER -B_RADIUS;
+ double y8 = B_BORDER;
+
+ double x9 = w - B_BORDER;
+ double y9 = B_BORDER+B_RADIUS;
+
+ double x10 = w - B_BORDER;
+ double y10 = h- B_BORDER -B_RADIUS;
+
+ double x11 = w - B_BORDER-B_RADIUS;
+ double y11 = h-B_BORDER;
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_line_width(c,B_LINE);
+
+ cairo_move_to (c, x0, y0);
+ cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
+ cairo_line_to (c, x2,y2);
+ cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
+ cairo_line_to (c, x8,y8);
+ cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
+ cairo_line_to (c, x10,y10);
+ cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
+ cairo_close_path (c);
+
+ cairo_set_source_rgba (c, B_COLOR);
+ cairo_fill_preserve (c);
+ cairo_set_source_rgba (c, B_LINE_COLOR);
+ cairo_stroke (c);
+
+ cairo_restore(c);
+}
+
+void borderbox_path (cairo_t *c, double x, double y, double w, double h){
+
+ double x0 = x+ B_RADIUS;
+ double y0 = y+ h;
+
+ double x1 = x;
+ double y1 = y+ h-B_RADIUS;
+
+ double x2 = x;
+ double y2 = y+ B_RADIUS;
+
+ double x3 = x+ B_RADIUS;
+ double y3 = y;
+
+ double x8 = x+ w -B_RADIUS;
+ double y8 = y;
+
+ double x9 = x+ w;
+ double y9 = y+ B_RADIUS;
+
+ double x10 = x+ w;
+ double y10 = y+ h -B_RADIUS;
+
+ double x11 = x+ w -B_RADIUS;
+ double y11 = y+h;
+
+ cairo_move_to (c, x0, y0);
+ cairo_curve_to (c, x1,y0, x1,y0, x1,y1);
+ cairo_line_to (c, x2,y2);
+ cairo_curve_to (c, x2,y3, x2,y3, x3,y3);
+ cairo_line_to (c, x8,y8);
+ cairo_curve_to (c, x9,y8, x9,y8, x9,y9);
+ cairo_line_to (c, x10,y10);
+ cairo_curve_to (c, x10,y11, x10,y11, x11,y11);
+ cairo_close_path (c);
+
+}
+
Added: trunk/planarity/gameboard_draw_button.c
===================================================================
--- trunk/planarity/gameboard_draw_button.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_button.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,273 @@
+#include <math.h>
+#include <gtk/gtk.h>
+
+#include "graph.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+
+
+/************************* simple round icon drawing *********************/
+
+void path_button_help(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,-9,-2);
+ cairo_curve_to(c,-8,-7, -4.5,-12, 0,-12);
+ cairo_curve_to(c, 7,-12, 9,-6, 9,-4);
+ cairo_curve_to(c, 9,0 ,6,2, 5,2);
+
+ cairo_curve_to(c, 4,2, 2.5,3, 2.5,6);
+ cairo_line_to(c,-2.5,6);
+
+ cairo_curve_to(c,-2.5,3, -3,1, 0,-1);
+ cairo_curve_to(c, 11,-4, -3,-12, -4,-2);
+ cairo_close_path(c);
+
+ cairo_move_to(c,-2.5,8);
+ cairo_line_to(c,2.5,8);
+ cairo_line_to(c,2.5,12);
+ cairo_line_to(c,-2.5,12);
+ cairo_close_path(c);
+ cairo_fill_preserve(c);
+
+ cairo_restore(c);
+
+}
+
+void path_button_pause(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_rectangle(c,-7,-9,5,18);
+ cairo_rectangle(c,2,-9,5,18);
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_exit(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,-6,-9.5);
+ cairo_line_to(c,0,-3.5);
+ cairo_line_to(c,6,-9.5);
+ cairo_line_to(c,9.5,-6);
+ cairo_line_to(c,3.5,0);
+ cairo_line_to(c,9.5,6);
+ cairo_line_to(c,6,9.5);
+ cairo_line_to(c,0,3.5);
+ cairo_line_to(c,-6,9.5);
+ cairo_line_to(c,-9.5,6);
+ cairo_line_to(c,-3.5,0);
+ cairo_line_to(c,-9.5,-6);
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_back(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,0,-11);
+ cairo_line_to(c,-9,0);
+ cairo_line_to(c,-3,0);
+ cairo_line_to(c,-3,10);
+ cairo_line_to(c,3,10);
+ cairo_line_to(c,3,0);
+ cairo_line_to(c,9,0);
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_reset(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,-11,-5);
+ cairo_line_to(c,-12,1);
+ cairo_line_to(c,-6,1);
+ cairo_line_to(c,0, 11);
+ cairo_line_to(c,6,1);
+ cairo_line_to(c,12,1);
+ cairo_line_to(c,11,-5);
+ cairo_line_to(c,4,-5);
+ cairo_line_to(c,0,2);
+ cairo_line_to(c,-4,-5);
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_expand(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,-8.5,-3);
+ cairo_line_to(c,-2.5,-3);
+ cairo_line_to(c,-3,-8.5);
+ cairo_line_to(c,3, -8.5);
+ cairo_line_to(c,3,-3);
+ cairo_line_to(c,8.5,-3);
+ cairo_line_to(c,8.5,3);
+ cairo_line_to(c,3,3);
+ cairo_line_to(c,3,8.5);
+ cairo_line_to(c,-3,8.5);
+ cairo_line_to(c,-3,3);
+ cairo_line_to(c,-8.5,3);
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_shrink(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,-10,-3);
+ cairo_line_to(c,10,-3);
+ cairo_line_to(c,10,3);
+ cairo_line_to(c,-10,3);
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_lines(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,6,-4);
+ cairo_arc(c,0,-4,6,0,2*M_PI);
+
+ cairo_move_to(c,0,2);
+ cairo_line_to(c,0,10);
+ cairo_close_path(c);
+
+ cairo_move_to(c,2.68328,5.36656-4);
+ cairo_rel_line_to(c,4,8);
+ cairo_close_path(c);
+
+ cairo_move_to(c,-2.68328,5.36656-4);
+ cairo_rel_line_to(c,-4,8);
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_int(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,8,0);
+ cairo_line_to(c,0,8);
+ cairo_line_to(c,-8,0);
+ cairo_line_to(c,0,-8);
+
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_check(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,8,-8);
+ cairo_curve_to(c, 7,-7, 11,-7.3, 10,-6);
+ cairo_line_to(c,0,9);
+ cairo_curve_to(c, -1,9.1, -2,11, -3,10);
+ cairo_line_to(c,-11,4);
+ cairo_curve_to(c, -12,3, -10,.5, -9,1);
+ cairo_line_to(c,-3,3);
+
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
+void path_button_play(cairo_t *c, double x, double y){
+
+ cairo_save(c);
+ cairo_translate(c,x,y);
+ cairo_set_fill_rule(c,CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_set_line_width(c,1);
+
+ cairo_arc(c,0,0,14,0,2*M_PI);
+
+ cairo_move_to(c,-8,-8);
+ cairo_line_to(c,10,0);
+ cairo_line_to(c,-8,8);
+ cairo_close_path(c);
+
+ cairo_fill_preserve(c);
+ cairo_restore(c);
+
+}
+
Added: trunk/planarity/gameboard_draw_button.h
===================================================================
--- trunk/planarity/gameboard_draw_button.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_button.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,46 @@
+extern void path_button_help(cairo_t *c, double x, double y);
+extern void path_button_back(cairo_t *c, double x, double y);
+extern void path_button_reset(cairo_t *c, double x, double y);
+extern void path_button_pause(cairo_t *c, double x, double y);
+extern void path_button_exit(cairo_t *c, double x, double y);
+extern void path_button_expand(cairo_t *c, double x, double y);
+extern void path_button_shrink(cairo_t *c, double x, double y);
+extern void path_button_lines(cairo_t *c, double x, double y);
+extern void path_button_int(cairo_t *c, double x, double y);
+extern void path_button_check(cairo_t *c, double x, double y);
+extern void path_button_play(cairo_t *c, double x, double y);
+
+
+#define BUTTON_QUIT_IDLE_FILL .7,.1,.1,.3
+#define BUTTON_QUIT_IDLE_PATH .7,.1,.1,.6
+
+#define BUTTON_QUIT_LIT_FILL .7,.1,.1,.5
+#define BUTTON_QUIT_LIT_PATH .7,.1,.1,.6
+
+#define BUTTON_IDLE_FILL .1,.1,.7,.3
+#define BUTTON_IDLE_PATH .1,.1,.7,.6
+
+#define BUTTON_LIT_FILL .1,.1,.7,.6
+#define BUTTON_LIT_PATH .1,.1,.7,.6
+
+#define BUTTON_CHECK_IDLE_FILL .1,.5,.1,.3
+#define BUTTON_CHECK_IDLE_PATH .1,.5,.1,.6
+
+#define BUTTON_CHECK_LIT_FILL .1,.5,.1,.6
+#define BUTTON_CHECK_LIT_PATH .1,.5,.1,.6
+
+#define BUTTON_RADIUS 14
+#define BUTTON_Y_FROM_BOTTOM 25
+#define BUTTON_LINE_WIDTH 1
+#define BUTTON_TEXT_BORDER 15
+#define BUTTON_TEXT_COLOR .1,.1,.7,.8
+#define BUTTON_TEXT_SIZE 15.,18.
+
+#define BUTTON_ANIM_INTERVAL 15
+#define BUTTON_LEFT 5
+#define BUTTON_RIGHT 5
+#define BUTTON_BORDER 35
+#define BUTTON_SPACING 35
+#define BUTTON_EXPOSE 50
+#define DEPLOY_DELTA 6
+#define SWEEP_DELTA 3
Added: trunk/planarity/gameboard_draw_buttonbar.c
===================================================================
--- trunk/planarity/gameboard_draw_buttonbar.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_buttonbar.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,21 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+void draw_buttonbar_box (Gameboard *g){
+ cairo_t *c = cairo_create(g->forebutton);
+
+ cairo_save(c);
+ cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
+ cairo_set_source_rgba (c, 1,1,1,1);
+ cairo_paint(c);
+ cairo_restore(c);
+
+ bottombox(g,c,g->g.width,SCOREHEIGHT);
+ cairo_destroy(c);
+}
+
Added: trunk/planarity/gameboard_draw_curtain.c
===================================================================
--- trunk/planarity/gameboard_draw_curtain.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_curtain.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,55 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+/* cache the curtain surface/pattern ******************************/
+
+#define CW 4
+void cache_curtain(Gameboard *g){
+ int x,y;
+ cairo_t *c;
+ g->curtains=
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ CW,CW);
+
+ c = cairo_create(g->curtains);
+ cairo_save(c);
+ cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
+ cairo_set_source_rgba (c, 1,1,1,1);
+ cairo_paint(c);
+ cairo_restore(c);
+
+ cairo_set_line_width(c,1);
+ cairo_set_source_rgba (c, 0,0,0,.5);
+
+ for(y=0;y<CW;y++){
+ for(x=y&1;x<CW;x+=2){
+ cairo_move_to(c,x+.5,y);
+ cairo_rel_line_to(c,0,1);
+ }
+ }
+ cairo_stroke(c);
+ cairo_destroy(c);
+
+ g->curtainp=cairo_pattern_create_for_surface (g->curtains);
+ cairo_pattern_set_extend (g->curtainp, CAIRO_EXTEND_REPEAT);
+
+}
+
+void draw_curtain(Gameboard *g){
+
+ cairo_t *c = cairo_create(g->background);
+
+ cairo_set_source (c, g->curtainp);
+ cairo_paint(c);
+ cairo_destroy(c);
+}
Added: trunk/planarity/gameboard_draw_edge.c
===================================================================
--- trunk/planarity/gameboard_draw_edge.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_edge.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,53 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+
+/******** draw edges ********************************************/
+
+void setup_background_edge(cairo_t *c){
+ cairo_set_line_width(c,E_LINE);
+ cairo_set_source_rgba(c,E_LINE_B_COLOR);
+}
+
+void setup_foreground_edge(cairo_t *c){
+ cairo_set_line_width(c,E_LINE);
+ cairo_set_source_rgba(c,E_LINE_F_COLOR);
+}
+
+void draw_edge(cairo_t *c,edge *e){
+ cairo_move_to(c,e->A->x,e->A->y);
+ cairo_line_to(c,e->B->x,e->B->y);
+}
+
+void finish_edge(cairo_t *c){
+ cairo_stroke(c);
+}
+
+/* invalidate edge region for efficient expose *******************/
+
+void invalidate_edges(GtkWidget *widget, vertex *v){
+ GdkRectangle r;
+
+ if(v){
+ edge_list *el=v->edges;
+ while (el){
+ edge *e=el->edge;
+ r.x = min(e->A->x,e->B->x) - E_LINE;
+ r.y = min(e->A->y,e->B->y) - E_LINE;
+ r.width = labs(e->B->x - e->A->x) + 1 + E_LINE*2;
+ r.height = labs(e->B->y - e->A->y) + 1 + E_LINE*2;
+ gdk_window_invalidate_rect (widget->window, &r, FALSE);
+ el=el->next;
+ }
+ }
+}
+
Added: trunk/planarity/gameboard_draw_intersection.c
===================================================================
--- trunk/planarity/gameboard_draw_intersection.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_intersection.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,82 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+static void draw_intersection(cairo_t *c,double x, double y){
+ cairo_move_to(c,x-INTERSECTION_RADIUS,y);
+ cairo_rel_line_to(c,INTERSECTION_RADIUS,-INTERSECTION_RADIUS);
+ cairo_rel_line_to(c,INTERSECTION_RADIUS,INTERSECTION_RADIUS);
+ cairo_rel_line_to(c,-INTERSECTION_RADIUS,INTERSECTION_RADIUS);
+ cairo_close_path(c);
+}
+
+static void draw_many_intersection(Gameboard *g,cairo_t *c){
+ cairo_matrix_t ma;
+ int x2 = g->g.width/2;
+ int y2 = g->g.height/2;
+ int r = INTERSECTION_RADIUS*10;
+
+ cairo_set_source_rgba (c, INTERSECTION_COLOR);
+ cairo_set_line_width(c, INTERSECTION_LINE_WIDTH*10);
+
+ cairo_move_to(c,x2-r,y2-r/4);
+ cairo_rel_line_to(c,r,-r);
+ cairo_rel_line_to(c,r,r);
+ cairo_rel_line_to(c,-r,r);
+ cairo_close_path(c);
+
+ cairo_stroke(c);
+
+ cairo_select_font_face (c, "Sans",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&ma, 30.,34.);
+ cairo_set_font_matrix (c,&ma);
+ render_bordertext_centered(c,"rather many, really",x2,y2+r/4);
+
+}
+
+void draw_intersections(Gameboard *b, graph *g, cairo_t *c,
+ int x,int y,int w,int h){
+
+ double xx=x-(INTERSECTION_LINE_WIDTH*.5 + INTERSECTION_RADIUS);
+ double x2=w+x+(INTERSECTION_LINE_WIDTH + INTERSECTION_RADIUS*2);
+ double yy=y-(INTERSECTION_LINE_WIDTH*.5 + INTERSECTION_RADIUS);
+ double y2=h+y+(INTERSECTION_LINE_WIDTH + INTERSECTION_RADIUS*2);
+
+ if(g->active_intersections > 1000){
+ // don't draw them all; potential for accidental CPU sink.
+ draw_many_intersection(b,c);
+ }else{
+ cairo_set_source_rgba (c, INTERSECTION_COLOR);
+ cairo_set_line_width(c, INTERSECTION_LINE_WIDTH);
+
+ // walk the intersection list of all edges; draw if paired is a higher pointer
+ edge *e=g->edges;
+ while(e){
+ intersection *i = e->i.next;
+ while(i){
+ if(i->paired > i){
+ double ix=i->x, iy=i->y;
+
+ if(ix >= xx && ix <= x2 && iy >= yy && iy <= y2)
+ draw_intersection(c,ix,iy);
+ }
+ cairo_stroke(c); // incremental stroke! It's easy to run
+ // the path longer than the X server
+ // allows.
+ i=i->next;
+ }
+ e=e->next;
+ }
+ }
+}
Added: trunk/planarity/gameboard_draw_main.c
===================================================================
--- trunk/planarity/gameboard_draw_main.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_main.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,366 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "graph.h"
+#include "gameboard.h"
+#include "dialog_level.h"
+#include "main.h"
+
+/* The gPlanarity gameboard consists of a background and a foreground.
+ The background is a predrawn backdrop of anything not currently
+ being animated. The foreground is 'active' elements of the UI and
+ anything that floats above them. There are also two translucent
+ bars, top and bottom, that hold the score and buttonbar
+ respectively. These are prerendered surfaces that are blitted onto
+ the foreground during exposes */
+
+/* the midground is a group of elements that may currently be animated
+ (thus rendered to the foreground) or not (thus rendered to the
+ background) */
+static void draw_midground(Gameboard *g,cairo_t *c,int x,int y,int w,int h){
+
+ /* Edges attached to the grabbed vertex are drawn here */
+
+ if(g->grabbed_vertex && !g->hide_lines){
+ edge_list *el=g->grabbed_vertex->edges;
+ setup_foreground_edge(c);
+ while(el){
+ edge *e=el->edge;
+ /* no need to check rectangle; if they're to be drawn, they'll
+ always be in the rect */
+ draw_edge(c,e);
+ el=el->next;
+ }
+ finish_edge(c);
+ }
+
+ /* verticies drawn over the edges */
+ {
+ vertex *v = g->g.verticies;
+ int clipx = x-V_RADIUS;
+ int clipw = x+w+V_RADIUS;
+ int clipy = y-V_RADIUS;
+ int cliph = y+h+V_RADIUS;
+
+ while(v){
+
+ /* is the vertex in the expose rectangle? */
+ if(v->x>=clipx && v->x<=clipw &&
+ v->y>=clipy && v->y<=cliph){
+
+ if(v == g->grabbed_vertex && !g->group_drag) {
+ draw_vertex(c,v,g->vertex_grabbed);
+ } else if( v->selected ){
+ draw_vertex(c,v,g->vertex_sel);
+ } else if ( v == g->lit_vertex){
+ draw_vertex(c,v,g->vertex_lit);
+ } else if (v->attached_to_grabbed && !g->group_drag){
+ draw_vertex(c,v,g->vertex_attached);
+ }else
+ draw_vertex(c,v,g->vertex);
+ }
+
+ v=v->next;
+ }
+ }
+}
+
+static void draw_background(Gameboard *g,cairo_t *c){
+ int width=g->g.width;
+ int height=g->g.height;
+ edge *e=g->g.edges;
+
+ cairo_set_source_rgb(c,1,1,1);
+ cairo_paint(c);
+
+ if(!g->hide_lines){
+ setup_background_edge(c);
+ while(e){
+ if(e->active){
+ draw_edge(c,e);
+ }
+ e=e->next;
+ }
+ finish_edge(c);
+ }
+
+ // if there's a a group drag in progress, midground is drawn here
+ if(g->group_drag)
+ draw_midground(g,c,0,0,width,height);
+
+}
+
+/* This draws the nominal foreground, that is, the elements that are
+ always foreground except when a 'background push' (dialog and
+ curtain over the board) is in place. */
+void draw_foreground(Gameboard *g,cairo_t *c,
+ int x,int y,int width,int height){
+
+ /* if a group drag is in progress, draw the group
+ ghosted in the foreground */
+
+ if(g->group_drag){
+ vertex *v = g->g.verticies;
+ while(v){
+
+ if( v->selected ){
+ vertex tv;
+ tv.x=v->x+g->dragx;
+ tv.y=v->y+g->dragy;
+ draw_vertex(c,&tv,g->vertex_ghost);
+ }
+
+ v=v->next;
+ }
+ }else
+ draw_midground(g,c,x,y,width,height);
+
+ if(g->selection_grab)
+ draw_selection_rectangle(g,c);
+}
+
+/* Several very-high-level drawing sequences triggered by various
+ actions in the game *********************************************/
+
+/* request that the background plane be redrawn from scratch to match
+ current game state and the full window invalidated to request an
+ expose. As other layers are always drawn on the fly, this is
+ effectively a full refresh of the screen.
+ This is done as sparingly as possible and only within large state
+ changes as it's not fast enough for animation. */
+
+void update_full(Gameboard *g){
+ cairo_t *c = cairo_create(g->background);
+
+ g->delayed_background=0;
+
+ // render the far background plane
+ draw_background(g,c);
+ update_push(g,c);
+ cairo_destroy(c);
+ expose_full(g);
+}
+
+void expose_full(Gameboard *g){
+ GtkWidget *widget = GTK_WIDGET(g);
+ GdkRectangle r;
+
+ r.x=0;
+ r.y=0;
+ r.width=g->g.width;
+ r.height=g->g.height;
+
+ gdk_window_invalidate_rect (widget->window, &r, FALSE);
+
+}
+
+void update_draw(Gameboard *g){
+ cairo_t *c = cairo_create(g->background);
+
+ g->delayed_background=0;
+
+ // render the far background plane
+ draw_background(g,c);
+ update_push(g,c);
+ cairo_destroy(c);
+
+ gameboard_draw(g,0,0,g->g.width,g->g.height);
+}
+
+/* request a full redraw update to be processed immediately *after*
+ the next expose. This is used to increase apparent interactivity
+ of a vertex 'grab' where the background must be redrawn, but the
+ vertex itself should react immediately */
+void update_full_delayed(Gameboard *g){
+ g->delayed_background=1;
+}
+
+/* specialized update request for when re-adding a grabbed vertex's
+ edges to the background. Doesn't require a full redraw. */
+void update_add_vertex(Gameboard *g, vertex *v){
+ GtkWidget *widget = GTK_WIDGET(g);
+ edge_list *el=v->edges;
+ cairo_t *c = cairo_create(g->background);
+
+ if(!g->hide_lines){
+ setup_background_edge(c);
+ while(el){
+ edge *e=el->edge;
+
+ if(e->active)
+ draw_edge(c,e);
+
+ el=el->next;
+ }
+ finish_edge(c);
+ }
+ cairo_destroy(c);
+
+ invalidate_attached(widget,v);
+}
+
+/* top level draw function called by expose. May also be called
+ directly to immediately render a region of the board without going
+ through the expose mechanism (necessary for some button draw
+ operations where expose combining causes huge, slow in-server alpha
+ blends that are undesirable) */
+void gameboard_draw(Gameboard *g, int x, int y, int w, int h){
+
+ if (w==0 || h==0) return;
+
+ cairo_t *c = cairo_create(g->foreground);
+
+ // copy background to foreground draw buffer
+ cairo_set_source_surface(c,g->background,0,0);
+ cairo_rectangle(c,x,y,w,h);
+ cairo_fill(c);
+
+ if(!g->pushed_curtain){
+ draw_foreground(g,c,x,y,w,h);
+
+ // copy in any of the score or button surfaces?
+ if(y<SCOREHEIGHT){
+ cairo_set_source_surface(c,g->forescore,0,0);
+ cairo_rectangle(c, x,y,w,
+ min(SCOREHEIGHT-y,h));
+ cairo_fill(c);
+ }
+ if(y+h>g->w.allocation.height-SCOREHEIGHT){
+ cairo_set_source_surface(c,g->forebutton,0,
+ g->w.allocation.height-SCOREHEIGHT);
+ cairo_rectangle(c, x,y,w,h);
+ cairo_fill(c);
+ }
+
+ if(g->show_intersections)
+ draw_intersections(g,&g->g,c,x,y,w,h);
+ }
+
+ render_level_icons(g,c,x,y,w,h);
+ expose_buttons(g,c,x,y,w,h);
+
+ cairo_destroy(c);
+
+ // blit to window
+ cairo_set_source_surface(g->wc,g->foreground,0,0);
+ cairo_rectangle(g->wc,x,y,w,h);
+ cairo_fill(g->wc);
+
+ if(g->delayed_background)update_full(g);
+ g->first_expose=1;
+
+}
+
+cairo_surface_t *gameboard_read_icon(char *filename, char *ext, Gameboard *b){
+ char *name=alloca(strlen(boarddir)+strlen(filename)+strlen(ext)+2);
+ name[0]=0;
+ strcat(name,boarddir);
+ strcat(name,filename);
+ strcat(name,".");
+ strcat(name,ext);
+
+ cairo_surface_t *s = cairo_image_surface_create_from_png(name);
+
+ if(s==NULL)
+ fprintf(stderr,"ERROR: Could not load board icon \"%s\"\n",
+ name);
+
+ cairo_t *c = cairo_create(s);
+ borderbox_path(c,1.5,1.5,ICON_WIDTH-3,ICON_HEIGHT-3);
+ cairo_set_operator (c, CAIRO_OPERATOR_DEST_OVER);
+ cairo_set_line_width(c,B_LINE);
+ //cairo_set_source_rgba (c, B_COLOR);
+ //cairo_fill_preserve (c);
+ cairo_set_source_rgba (c, B_LINE_COLOR);
+ cairo_stroke (c);
+
+ cairo_destroy(c);
+ return s;
+}
+
+int gameboard_write_icon(char *filename, char *ext, Gameboard *b, graph *g,
+ int lines, int intersections){
+ char *name=alloca(strlen(boarddir)+strlen(filename)+strlen(ext)+2);
+ name[0]=0;
+ strcat(name,boarddir);
+ strcat(name,filename);
+ strcat(name,".");
+ strcat(name,ext);
+
+ {
+ cairo_surface_t *s =
+ cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ ICON_WIDTH,
+ ICON_HEIGHT);
+ cairo_t *c = cairo_create(s);
+ edge *e=g->edges;
+ vertex *v = g->verticies;
+
+ cairo_save(c);
+ cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
+ cairo_set_source_rgba (c, 1,1,1,1);
+ cairo_paint(c);
+ cairo_restore(c);
+ cairo_scale(c,(float)ICON_WIDTH/g->width,(float)ICON_HEIGHT/g->height);
+
+ if(lines){
+ setup_background_edge(c);
+ while(e){
+ draw_edge(c,e);
+ e=e->next;
+ }
+ finish_edge(c);
+ }
+
+ cairo_set_line_width(c,V_LINE);
+ while(v){
+ // dirty, but we may not have the cached vertex surface yet.
+ cairo_arc(c,v->x,v->y,V_RADIUS,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_IDLE_COLOR);
+ cairo_fill_preserve(c);
+ cairo_set_source_rgb(c,V_LINE_COLOR);
+ cairo_stroke(c);
+
+ v=v->next;
+ }
+
+ if(intersections)
+ draw_intersections(b,g,c,0,0,g->width,g->height);
+
+ if(cairo_surface_write_to_png(s,name) != CAIRO_STATUS_SUCCESS){
+ fprintf(stderr,"ERROR: Could not save board icon \"%s\"\n",
+ name);
+ return -1;
+ }
+
+ cairo_destroy(c);
+ cairo_surface_destroy(s);
+ }
+
+ return 0;
+
+}
+
+int gameboard_icon_exists(char *filename, char *ext){
+ struct stat s;
+ char *name=alloca(strlen(boarddir)+strlen(filename)+strlen(ext)+2);
+ name[0]=0;
+ strcat(name,boarddir);
+ strcat(name,filename);
+ strcat(name,".");
+ strcat(name,ext);
+
+ if(stat(name,&s))return 0;
+ return 1;
+
+}
Added: trunk/planarity/gameboard_draw_score.c
===================================================================
--- trunk/planarity/gameboard_draw_score.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_score.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,88 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+#include "levelstate.h"
+
+void draw_score(Gameboard *g){
+ char level_string[160];
+ char score_string[160];
+ char int_string[160];
+ char obj_string[160];
+ cairo_text_extents_t extentsL;
+ cairo_text_extents_t extentsS;
+ cairo_text_extents_t extentsO;
+ cairo_text_extents_t extentsI;
+ cairo_matrix_t m;
+
+ cairo_t *c = cairo_create(g->forescore);
+
+ // clear the pane
+ cairo_save(c);
+ cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
+ cairo_set_source_rgba (c, 1,1,1,1);
+ cairo_paint(c);
+ cairo_restore(c);
+
+ topbox(g,c,g->g.width,SCOREHEIGHT);
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&m, 12.,15.);
+ cairo_set_font_matrix (c,&m);
+ cairo_set_source_rgba (c, TEXT_COLOR);
+
+ snprintf(level_string,160,"Level %d: %s",get_level_num()+1,get_level_desc());
+ snprintf(score_string,160,"Score: %d",graphscore_get_score(&g->g));
+ snprintf(int_string,160,"Intersections: %ld",g->g.active_intersections);
+ snprintf(obj_string,160,"Objective: %s",graphscore_objective_string(&g->g));
+
+ cairo_text_extents (c, level_string, &extentsL);
+ cairo_text_extents (c, obj_string, &extentsO);
+ cairo_text_extents (c, int_string, &extentsI);
+ cairo_text_extents (c, score_string, &extentsS);
+
+ /*
+ text_h = extentsL.height;
+ text_h = max(text_h,extentsO.height);
+ text_h = max(text_h,extentsI.height);
+ text_h = max(text_h,extentsS.height);
+ */
+
+ int ty1 = 23;
+ int ty2 = 38;
+
+ cairo_move_to (c, 15, ty1);
+ cairo_show_text (c, int_string);
+ cairo_move_to (c, 15, ty2);
+ cairo_show_text (c, score_string);
+
+ cairo_move_to (c, g->g.width-extentsL.width-15, ty1);
+ cairo_show_text (c, level_string);
+ cairo_move_to (c, g->g.width-extentsO.width-15, ty2);
+ cairo_show_text (c, obj_string);
+
+ cairo_destroy(c);
+}
+
+void update_score(Gameboard *g){
+ GdkRectangle r;
+ draw_score(g);
+
+ r.x=0;
+ r.y=0;
+ r.width=g->g.width;
+ r.height = SCOREHEIGHT;
+ gdk_window_invalidate_rect (g->w.window, &r, FALSE);
+
+}
+
Added: trunk/planarity/gameboard_draw_selection.c
===================================================================
--- trunk/planarity/gameboard_draw_selection.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_selection.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,45 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+
+// draw selection box
+void draw_selection_rectangle(Gameboard *g,cairo_t *c){
+ cairo_set_source_rgba(c,SELECTBOX_COLOR);
+ cairo_rectangle(c,g->selectionx,
+ g->selectiony,
+ g->selectionw,
+ g->selectionh);
+ cairo_fill(c);
+}
+
+// invalidate the selection box plus enough area to catch any verticies
+void invalidate_selection(GtkWidget *widget){
+ Gameboard *g = GAMEBOARD (widget);
+ GdkRectangle r;
+ r.x = g->selectionx - (V_RADIUS + V_LINE)*2;
+ r.y = g->selectiony - (V_RADIUS + V_LINE)*2;
+ r.width = g->selectionw + (V_RADIUS + V_LINE)*4;
+ r.height = g->selectionh + (V_RADIUS + V_LINE)*4;
+
+ gdk_window_invalidate_rect (widget->window, &r, FALSE);
+}
+
+// invalidate the selection box plus enough area to catch any verticies
+void invalidate_verticies_selection(GtkWidget *widget){
+ Gameboard *g = GAMEBOARD (widget);
+ vertex *v=g->g.verticies;
+ while(v){
+ if(v->selected)
+ invalidate_vertex_off(widget,v,g->dragx,g->dragy);
+ v=v->next;
+ }
+}
Added: trunk/planarity/gameboard_draw_text.c
===================================================================
--- trunk/planarity/gameboard_draw_text.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_text.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,52 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+GdkRectangle render_text_centered(cairo_t *c, char *s, int x, int y){
+ cairo_text_extents_t ex;
+ GdkRectangle r;
+
+ cairo_text_extents (c, s, &ex);
+
+ r.x=x-(ex.width/2)-ex.x_bearing;
+ r.y=y-(ex.height/2)-ex.y_bearing;
+ r.width=ex.width;
+ r.height=ex.height;
+
+ cairo_move_to (c, r.x, r.y);
+ cairo_show_text (c, s);
+
+ return r;
+}
+
+GdkRectangle render_border_centered(cairo_t *c, char *s, int x, int y){
+ cairo_text_extents_t ex;
+ GdkRectangle r;
+
+ cairo_text_extents (c, s, &ex);
+
+ r.x=x-(ex.width/2)-ex.x_bearing-2;
+ r.y=y-(ex.height/2)-ex.y_bearing-2;
+ r.width=ex.width+5;
+ r.height=ex.height+5;
+
+ cairo_save(c);
+ cairo_move_to (c, r.x+2, r.y+2 );
+ cairo_set_line_width(c,3);
+ cairo_set_source_rgba(c,1,1,1,.9);
+ cairo_text_path (c, s);
+ cairo_stroke(c);
+ cairo_restore(c);
+
+ return r;
+}
+
+GdkRectangle render_bordertext_centered(cairo_t *c, char *s, int x, int y){
+ GdkRectangle r = render_border_centered(c,s,x,y);
+ render_text_centered(c,s,x,y);
+ return r;
+}
Added: trunk/planarity/gameboard_draw_vertex.c
===================================================================
--- trunk/planarity/gameboard_draw_vertex.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_draw_vertex.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,184 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+/* draw/cache vertex surfaces; direct surface copies are faster than
+ always redrawing lots of circles */
+
+void draw_vertex(cairo_t *c,vertex *v,cairo_surface_t *s){
+ cairo_set_source_surface(c,
+ s,
+ v->x-V_LINE-V_RADIUS,
+ v->y-V_LINE-V_RADIUS);
+ cairo_paint(c);
+}
+
+// normal unlit vertex
+cairo_surface_t *cache_vertex(Gameboard *g){
+ cairo_surface_t *ret=
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ (V_RADIUS+V_LINE)*2,
+ (V_RADIUS+V_LINE)*2);
+ cairo_t *c = cairo_create(ret);
+
+ cairo_set_line_width(c,V_LINE);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_IDLE_COLOR);
+ cairo_fill_preserve(c);
+ cairo_set_source_rgb(c,V_LINE_COLOR);
+ cairo_stroke(c);
+
+ cairo_destroy(c);
+ return ret;
+}
+
+// selected vertex
+cairo_surface_t *cache_vertex_sel(Gameboard *g){
+ cairo_surface_t *ret=
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ (V_RADIUS+V_LINE)*2,
+ (V_RADIUS+V_LINE)*2);
+ cairo_t *c = cairo_create(ret);
+
+ cairo_set_line_width(c,V_LINE);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_LIT_COLOR);
+ cairo_fill_preserve(c);
+ cairo_set_source_rgb(c,V_LINE_COLOR);
+ cairo_stroke(c);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS*.5,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_IDLE_COLOR);
+ cairo_fill(c);
+
+ cairo_destroy(c);
+ return ret;
+}
+
+// grabbed vertex
+cairo_surface_t *cache_vertex_grabbed(Gameboard *g){
+ cairo_surface_t *ret=
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ (V_RADIUS+V_LINE)*2,
+ (V_RADIUS+V_LINE)*2);
+ cairo_t *c = cairo_create(ret);
+
+ cairo_set_line_width(c,V_LINE);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_LIT_COLOR);
+ cairo_fill_preserve(c);
+ cairo_set_source_rgb(c,V_LINE_COLOR);
+ cairo_stroke(c);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS*.5,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_ADJ_COLOR);
+ cairo_fill(c);
+
+ cairo_destroy(c);
+ return ret;
+}
+
+// vertex under mouse rollover
+cairo_surface_t *cache_vertex_lit(Gameboard *g){
+ cairo_surface_t *ret=
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ (V_RADIUS+V_LINE)*2,
+ (V_RADIUS+V_LINE)*2);
+ cairo_t *c = cairo_create(ret);
+
+ cairo_set_line_width(c,V_LINE);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_LIT_COLOR);
+ cairo_fill_preserve(c);
+ cairo_set_source_rgb(c,V_LINE_COLOR);
+ cairo_stroke(c);
+
+ cairo_destroy(c);
+ return ret;
+}
+
+// verticies attached to grabbed vertex
+cairo_surface_t *cache_vertex_attached(Gameboard *g){
+ cairo_surface_t *ret=
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ (V_RADIUS+V_LINE)*2,
+ (V_RADIUS+V_LINE)*2);
+ cairo_t *c = cairo_create(ret);
+
+ cairo_set_line_width(c,V_LINE);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
+ cairo_set_source_rgb(c,V_FILL_ADJ_COLOR);
+ cairo_fill_preserve(c);
+ cairo_set_source_rgb(c,V_LINE_COLOR);
+ cairo_stroke(c);
+
+ cairo_destroy(c);
+ return ret;
+}
+
+// vertex being dragged in a group
+cairo_surface_t *cache_vertex_ghost(Gameboard *g){
+ cairo_surface_t *ret=
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ (V_RADIUS+V_LINE)*2,
+ (V_RADIUS+V_LINE)*2);
+ cairo_t *c = cairo_create(ret);
+
+ cairo_set_line_width(c,V_LINE);
+ cairo_arc(c,V_RADIUS+V_LINE,V_RADIUS+V_LINE,V_RADIUS,0,2*M_PI);
+ cairo_set_source_rgba(c,V_LINE_COLOR,.2);
+ cairo_fill_preserve(c);
+ cairo_set_source_rgba(c,V_LINE_COLOR,.4);
+ cairo_stroke(c);
+
+ cairo_destroy(c);
+ return ret;
+}
+
+/* region invalidation operations; do exposes efficiently! **********/
+
+// invalidate the box around a single offset vertex
+void invalidate_vertex_off(GtkWidget *widget,
+ vertex *v, int dx, int dy){
+ if(v){
+ GdkRectangle r;
+ r.x = v->x - V_RADIUS - V_LINE + dx;
+ r.y = v->y - V_RADIUS - V_LINE + dy;
+ r.width = (V_RADIUS + V_LINE)*2;
+ r.height = (V_RADIUS + V_LINE)*2;
+
+ gdk_window_invalidate_rect (widget->window, &r, FALSE);
+ }
+}
+
+// invalidate the box around a single vertex
+void invalidate_vertex(Gameboard *g, vertex *v){
+ invalidate_vertex_off(&g->w,v,0,0);
+}
+
+// invalidate a vertex and any other attached verticies
+void invalidate_attached(GtkWidget *widget, vertex *v){
+ if(v){
+ edge_list *el=v->edges;
+ while (el){
+ edge *e=el->edge;
+ if(e->A != v)invalidate_vertex(GAMEBOARD(widget),e->A);
+ if(e->B != v)invalidate_vertex(GAMEBOARD(widget),e->B);
+ el=el->next;
+ }
+ invalidate_vertex(GAMEBOARD(widget),v);
+ }
+}
+
Added: trunk/planarity/gameboard_logic.c
===================================================================
--- trunk/planarity/gameboard_logic.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_logic.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,316 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "graph.h"
+#include "timer.h"
+#include "gameboard.h"
+#include "levelstate.h"
+#include "dialog_finish.h"
+#include "dialog_pause.h"
+#include "dialog_level.h"
+#include "main.h"
+
+/* game state helpers ************************************************************************************/
+
+void prepare_reenter_game(Gameboard *g){
+ g->lit_vertex=0;
+ g->grabbed_vertex=0;
+ g->delayed_background=0;
+
+ g->group_drag=0;
+ g->button_grabbed=0;
+ g->selection_grab=0;
+ g->selection_active=num_selected_verticies(&g->g);
+
+ update_full(g);
+ update_score(g);
+}
+
+void reenter_game(Gameboard *g){
+ deploy_buttonbar(g);
+ unpause_timer();
+}
+
+void enter_game(Gameboard *g){
+ set_timer(0);
+ prepare_reenter_game(g);
+ reenter_game(g);
+}
+
+static void scale(Gameboard *g,double scale){
+ int x=g->g.width/2;
+ int y=g->g.height/2;
+ int sel = num_selected_verticies(&g->g);
+ vertex *v;
+
+ // if selected, expand from center of selected mass
+ if(sel){
+ double xac=0;
+ double yac=0;
+
+ v=g->g.verticies;
+ while(v){
+ if(v->selected){
+ xac+=v->x;
+ yac+=v->y;
+ }
+ v=v->next;
+ }
+ x = xac / sel;
+ y = yac / sel;
+ }
+
+ v=g->g.verticies;
+ while(v){
+
+ if(!sel || v->selected){
+ int nx = rint((v->x - x)*scale+x);
+ int ny = rint((v->y - y)*scale+y);
+
+ if(nx<0)nx=0;
+ if(nx>=g->g.width)nx=g->g.width-1;
+ if(ny<0)ny=0;
+ if(ny>=g->g.height)ny=g->g.height-1;
+
+ deactivate_vertex(&g->g,v);
+ v->x = nx;
+ v->y = ny;
+ }
+ v=v->next;
+ }
+
+ v=g->g.verticies;
+ while(v){
+ activate_vertex(&g->g,v);
+ v=v->next;
+ }
+
+ update_full(g);
+}
+
+static void gtk_main_quit_wrapper(Gameboard *g){
+ gtk_main_quit();
+}
+
+static void level_wrapper(Gameboard *g){
+ level_dialog(g,0);
+}
+
+/* toplevel main gameboard action entry points; when a button is
+ clicked and decoded to a specific action or a game state change
+ triggers an action, one of the below functions is the entry
+ point **************************************************************************************************************/
+
+void quit_action(Gameboard *g){
+ pause_timer();
+ undeploy_buttons(g,gtk_main_quit_wrapper);
+}
+
+void level_action(Gameboard *g){
+ pause_timer();
+ undeploy_buttons(g,level_wrapper);
+}
+
+void finish_action(Gameboard *g){
+ if(g->g.active_intersections<=g->g.original_intersections){
+ pause_timer();
+ levelstate_finish();
+ undeploy_buttons(g,finish_level_dialog);
+ }
+}
+
+void pause_action(Gameboard *g){
+ pause_timer();
+ undeploy_buttons(g,pause_dialog);
+}
+
+void about_action(Gameboard *g){
+ pause_timer();
+ undeploy_buttons(g,about_dialog);
+}
+
+void expand_action(Gameboard *g){
+ scale(g,1.2);
+}
+
+void shrink_action(Gameboard *g){
+ scale(g,.8);
+}
+
+void set_hide_lines(Gameboard *g, int state){
+ g->hide_lines=state;
+ update_full(g);
+}
+
+void toggle_hide_lines(Gameboard *g){
+ g->hide_lines= !g->hide_lines;
+ update_full(g);
+}
+
+void set_show_intersections(Gameboard *g, int state){
+ if(g->show_intersections != state){
+ g->show_intersections=state;
+ expose_full(g);
+ }
+}
+
+void toggle_show_intersections(Gameboard *g){
+ g->show_intersections=!g->show_intersections;
+ expose_full(g);
+}
+
+void reset_action(Gameboard *g){
+ int flag=1;
+ vertex *v=g->g.verticies;
+
+ // hide intersections now; deactivating the verticies below will hide them anyway
+ g->show_intersections = 0;
+ expose_full(g);
+ gdk_window_process_all_updates();
+ gdk_flush();
+
+ // deactivate all the verticies so they can be moved en-masse
+ // without graph metadata updates at each move
+ while(v){
+ deactivate_vertex(&g->g,v);
+ v=v->next;
+ }
+
+ // animate
+ while(flag){
+ flag=0;
+
+ v=g->g.verticies;
+ while(v){
+ int bxd = (g->g.width - g->g.orig_width) >>1;
+ int byd = (g->g.height - g->g.orig_height) >>1;
+ int vox = v->orig_x + bxd;
+ int voy = v->orig_y + byd;
+
+ if(v->x != vox || v->y != voy){
+ flag=1;
+
+ invalidate_vertex(g,v);
+ if(v->x<vox){
+ v->x+=RESET_DELTA;
+ if(v->x>vox)v->x=vox;
+ }else{
+ v->x-=RESET_DELTA;
+ if(v->x<vox)v->x=vox;
+ }
+ if(v->y<voy){
+ v->y+=RESET_DELTA;
+ if(v->y>voy)v->y=voy;
+ }else{
+ v->y-=RESET_DELTA;
+ if(v->y<voy)v->y=voy;
+ }
+ invalidate_vertex(g,v);
+ }
+ v=v->next;
+ }
+ gdk_window_process_all_updates();
+ gdk_flush();
+
+ }
+
+ // reactivate all the verticies
+ activate_verticies(&g->g);
+
+ // it's a reset; show lines is default. This also has the side
+ // effect of forcing a full board redraw and expose
+ set_hide_lines(g,0);
+
+ // hey, the board could ahve come pre-solved
+ if(g->g.active_intersections <= g->g.objective){
+ deploy_check(g);
+ }else{
+ undeploy_check(g);
+ }
+
+ // reset timer
+ set_timer(0);
+ unpause_timer();
+}
+
+
+/***************** save/load gameboard the widget state we want to be persistent **************/
+
+// there are only a few things; lines, intersections
+int gameboard_write(char *basename, Gameboard *g){
+ char *name;
+ FILE *f;
+
+ name=alloca(strlen(boarddir)+strlen(basename)+1);
+ name[0]=0;
+ strcat(name,boarddir);
+ strcat(name,basename);
+
+ f = fopen(name,"wb");
+ if(f==NULL){
+ fprintf(stderr,"ERROR: Could not save board state for \"%s\":\n\t%s\n",
+ get_level_desc(),strerror(errno));
+ return errno;
+ }
+
+ graph_write(&g->g,f);
+
+ if(g->hide_lines)
+ fprintf(f,"hide_lines 1\n");
+ if(g->show_intersections)
+ fprintf(f,"show_intersections 1\n");
+
+ fclose(f);
+
+ return 0;
+}
+
+int gameboard_read(char *basename, Gameboard *g){
+ FILE *f;
+ char *name;
+ char *line=NULL;
+ size_t n=0;
+
+ name=alloca(strlen(boarddir)+strlen(basename)+3);
+ name[0]=0;
+ strcat(name,boarddir);
+ strcat(name,basename);
+
+ f = fopen(name,"rb");
+ if(f==NULL){
+ fprintf(stderr,"ERROR: Could not read saved board state for \"%s\":\n\t%s\n",
+ get_level_desc(),strerror(errno));
+ return errno;
+ }
+
+ graph_read(&g->g,f);
+
+ // get local game state
+ while(getline(&line,&n,f)>0){
+ int i;
+
+ if (sscanf(line,"hide_lines %d",&i)==1)
+ if(i)
+ g->hide_lines = 1;
+
+ if (sscanf(line,"show_intersections %d",&i)==1)
+ if(i)
+ g->show_intersections = 1;
+
+ }
+
+ fclose (f);
+ free(line);
+ request_resize(g->g.width,g->g.height);
+
+ return 0;
+}
+
Added: trunk/planarity/gameboard_logic_button.c
===================================================================
--- trunk/planarity/gameboard_logic_button.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_logic_button.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,619 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+
+
+/************************ manage the buttons for buttonbar and dialogs *********************/
+
+/* determine the x/y/w/h box around the rollover text */
+static GdkRectangle rollover_box(Gameboard *g, buttonstate *b){
+ GdkRectangle r;
+ int width = g->g.width;
+ int height = g->g.height;
+
+ int x = b->x - b->ex.width/2 + b->ex.x_bearing -2;
+ int y = b->y - BUTTON_RADIUS - BUTTON_TEXT_BORDER + b->ex.y_bearing -2;
+
+ if(x<BUTTON_TEXT_BORDER)x=BUTTON_TEXT_BORDER;
+ if(y<BUTTON_TEXT_BORDER)y=BUTTON_TEXT_BORDER;
+ if(x+b->ex.width >= width - BUTTON_TEXT_BORDER)
+ x = width - BUTTON_TEXT_BORDER - b->ex.width;
+ if(y+b->ex.height >= height - BUTTON_TEXT_BORDER)
+ y = height - BUTTON_TEXT_BORDER - b->ex.height;
+
+ r.x=x;
+ r.y=y;
+ r.width=b->ex.width+5;
+ r.height=b->ex.height+5;
+
+ return r;
+}
+
+/* draw the actual rollover */
+static void stroke_rollover(Gameboard *g, buttonstate *b, cairo_t *c){
+ cairo_matrix_t m;
+
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&m, BUTTON_TEXT_SIZE);
+ cairo_set_font_matrix (c,&m);
+
+ {
+ GdkRectangle r=rollover_box(g,b);
+
+ cairo_move_to (c, r.x - b->ex.x_bearing +2, r.y -b->ex.y_bearing+2 );
+
+ cairo_set_line_width(c,3);
+ cairo_set_source_rgba(c,1,1,1,.9);
+ cairo_text_path (c, b->rollovertext);
+ cairo_stroke(c);
+
+ cairo_set_source_rgba(c,BUTTON_TEXT_COLOR);
+ cairo_move_to (c, r.x - b->ex.x_bearing +2, r.y -b->ex.y_bearing+2 );
+
+
+ cairo_show_text (c, b->rollovertext);
+
+ }
+}
+
+/* request an expose for a button region*/
+static void invalidate_button(Gameboard *g,buttonstate *b){
+ GdkRectangle r;
+
+ r.x=b->x-BUTTON_RADIUS-1;
+ r.y=b->y-BUTTON_RADIUS-1;
+ r.width=BUTTON_RADIUS*2+2;
+ r.height=BUTTON_RADIUS*2+2;
+
+ gdk_window_invalidate_rect(g->w.window,&r,FALSE);
+}
+
+/* request an expose for a rollover region*/
+static void invalidate_rollover(Gameboard *g,buttonstate *b){
+ GdkRectangle r = rollover_box(g,b);
+ invalidate_button(g,b);
+ gdk_window_invalidate_rect(g->w.window,&r,FALSE);
+}
+
+/* like invalidation, but just expands a rectangular region */
+static void expand_rectangle_button(buttonstate *b,GdkRectangle *r){
+ int x=b->x-BUTTON_RADIUS-1;
+ int y=b->y-BUTTON_RADIUS-1;
+ int x2=x+BUTTON_RADIUS*2+2;
+ int y2=y+BUTTON_RADIUS*2+2;
+
+ int rx2=r->x+r->width;
+ int ry2=r->y+r->height;
+
+ if(r->width==0 || r->height==0){
+ r->x=x;
+ r->y=y;
+ r->width=x2-x;
+ r->height=y2-y;
+ }
+
+ if(x<r->x)
+ r->x=x;
+ if(y<r->y)
+ r->y=y;
+ if(rx2<x2)
+ rx2=x2;
+ r->width=rx2-r->x;
+ if(ry2<y2)
+ ry2=y2;
+ r->height=ry2-r->y;
+}
+
+/* like invalidation, but just expands a rectangular region */
+static void expand_rectangle_rollover(Gameboard *g,buttonstate *b,GdkRectangle *r){
+ GdkRectangle rr = rollover_box(g,b);
+ int x=rr.x;
+ int y=rr.y;
+ int x2=x+rr.width;
+ int y2=y+rr.height;
+
+ int rx2=r->x+r->width;
+ int ry2=r->y+r->height;
+
+ if(r->width==0 || r->height==0){
+ r->x=x;
+ r->y=y;
+ r->width=x2-x;
+ r->height=y2-y;
+ }
+
+ if(x<r->x)
+ r->x=x;
+ if(y<r->y)
+ r->y=y;
+ if(rx2<x2)
+ rx2=x2;
+ r->width=rx2-r->x;
+ if(ry2<y2)
+ ry2=y2;
+ r->height=ry2-r->y;
+}
+
+/* cache buttons as small surfaces */
+static cairo_surface_t *cache_button(Gameboard *g,
+ void (*draw)(cairo_t *c,
+ double x,
+ double y),
+ double pR,double pG,double pB,double pA,
+ double fR,double fG,double fB,double fA){
+ cairo_surface_t *ret =
+ cairo_surface_create_similar (cairo_get_target (g->wc),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ BUTTON_RADIUS*2+1,
+ BUTTON_RADIUS*2+1);
+
+ cairo_t *c = cairo_create(ret);
+
+ cairo_save(c);
+ cairo_set_operator(c,CAIRO_OPERATOR_CLEAR);
+ cairo_set_source_rgba (c, 1,1,1,1);
+ cairo_paint(c);
+ cairo_restore(c);
+
+ cairo_set_source_rgba(c,fR,fG,fB,fA);
+ cairo_set_line_width(c,BUTTON_LINE_WIDTH);
+ draw(c,BUTTON_RADIUS+.5,BUTTON_RADIUS+.5);
+
+ cairo_set_source_rgba(c,pR,pG,pB,pA);
+ cairo_stroke(c);
+
+ cairo_destroy(c);
+ return ret;
+}
+
+/* determine the x/y/w/h box around a button */
+static GdkRectangle button_box(buttonstate *b){
+ GdkRectangle r;
+
+ int x = b->x - BUTTON_RADIUS-1;
+ int y = b->y - BUTTON_RADIUS-1;
+ r.x=x;
+ r.y=y;
+ r.width = BUTTON_RADIUS*2+2;
+ r.height= BUTTON_RADIUS*2+2;
+
+ return r;
+}
+
+static int animate_x_axis(Gameboard *g, buttonstate *b, GdkRectangle *r){
+ int ret=0;
+
+ if(b->x_target != b->x){
+ ret=1;
+ expand_rectangle_button(b,r);
+ if(b->rollover)
+ expand_rectangle_rollover(g,b,r);
+
+ if(b->x_target > b->x){
+ b->x+=DEPLOY_DELTA;
+ if(b->x>b->x_target)b->x=b->x_target;
+ }else{
+ b->x-=DEPLOY_DELTA;
+ if(b->x<b->x_target)b->x=b->x_target;
+ }
+ expand_rectangle_button(b,r);
+ if(b->rollover)
+ expand_rectangle_rollover(g,b,r);
+ }
+
+ return ret;
+}
+static int animate_y_axis(Gameboard *g, buttonstate *b, GdkRectangle *r){
+ int ret=0;
+
+ if(b->y_target != b->y){
+ ret=1;
+ expand_rectangle_button(b,r);
+ if(b->rollover)
+ expand_rectangle_rollover(g,b,r);
+
+ if(b->y_target > b->y){
+ b->y+=DEPLOY_DELTA;
+ if(b->y>b->y_target)b->y=b->y_target;
+ }else{
+ b->y-=DEPLOY_DELTA;
+ if(b->y<b->y_target)b->y=b->y_target;
+ }
+ expand_rectangle_button(b,r);
+ if(b->rollover)
+ expand_rectangle_rollover(g,b,r);
+ }
+
+ if(b->alphad != b->y_active - b->y){
+ double alpha=0;
+ if(b->y_inactive>b->y_active){
+ if(b->y<=b->y_active)
+ alpha=1.;
+ else if (b->y>=b->y_inactive)
+ alpha=0.;
+ else
+ alpha = (double)(b->y_inactive-b->y)/(b->y_inactive-b->y_active);
+ }else if (b->y_inactive<b->y_active){
+ if(b->y>=b->y_active)
+ alpha=1.;
+ else if (b->y<=b->y_inactive)
+ alpha=0.;
+ else
+ alpha = (double)(b->y_inactive-b->y)/(b->y_inactive-b->y_active);
+ }
+ if(alpha != b->alpha){
+ ret=1;
+ expand_rectangle_button(b,r);
+ b->alpha=alpha;
+ }
+ b->alphad = b->y_active - b->y;
+ }
+
+ return ret;
+}
+
+/* do the animation math for one button for one frame */
+static int animate_one(Gameboard *g,buttonstate *b, GdkRectangle *r){
+ int ret=0;
+
+ /* does this button need to be deployed? */
+ if(g->b.sweeperd>0){
+ if(b->y_target != b->y_active){
+ if(g->b.sweeper >= b->sweepdeploy){
+ b->y_target=b->y_active;
+ ret=1;
+ }
+ }
+ }
+ /* does this button need to be undeployed? */
+ if(g->b.sweeperd<0){
+ if(b->y_target != b->y_inactive){
+ if(-g->b.sweeper >= b->sweepdeploy){
+ b->y_target=b->y_inactive;
+ ret=1;
+ }
+ }
+ }
+
+ ret |= animate_x_axis(g,b,r);
+ ret |= animate_y_axis(g,b,r);
+
+ return ret;
+}
+
+/******************** toplevel abstraction calls *********************/
+
+/* initialize the persistent caches; called once when gameboard is
+ first created */
+void init_buttons(Gameboard *g){
+ buttonstate *states=g->b.states;
+ memset(g->b.states,0,sizeof(g->b.states));
+
+ states[0].idle = cache_button(g, path_button_exit,
+ BUTTON_QUIT_IDLE_PATH,
+ BUTTON_QUIT_IDLE_FILL);
+ states[0].lit = cache_button(g, path_button_exit,
+ BUTTON_QUIT_LIT_PATH,
+ BUTTON_QUIT_LIT_FILL);
+
+ states[1].idle = cache_button(g, path_button_back,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[1].lit = cache_button(g, path_button_back,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[2].idle = cache_button(g, path_button_reset,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[2].lit = cache_button(g, path_button_reset,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[3].idle = cache_button(g, path_button_pause,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[3].lit = cache_button(g, path_button_pause,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[4].idle = cache_button(g, path_button_help,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[4].lit = cache_button(g, path_button_help,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[5].idle = cache_button(g, path_button_expand,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[5].lit = cache_button(g, path_button_expand,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[6].idle = cache_button(g, path_button_shrink,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[6].lit = cache_button(g, path_button_shrink,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[7].idle = cache_button(g, path_button_lines,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[7].lit = cache_button(g, path_button_lines,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[8].idle = cache_button(g, path_button_int,
+ BUTTON_IDLE_PATH,
+ BUTTON_IDLE_FILL);
+ states[8].lit = cache_button(g, path_button_int,
+ BUTTON_LIT_PATH,
+ BUTTON_LIT_FILL);
+ states[9].idle = cache_button(g, path_button_check,
+ BUTTON_CHECK_IDLE_PATH,
+ BUTTON_CHECK_IDLE_FILL);
+ states[9].lit = cache_button(g, path_button_check,
+ BUTTON_CHECK_LIT_PATH,
+ BUTTON_CHECK_LIT_FILL);
+ states[10].idle= cache_button(g, path_button_play,
+ BUTTON_CHECK_IDLE_PATH,
+ BUTTON_CHECK_IDLE_FILL);
+ states[10].lit = cache_button(g, path_button_play,
+ BUTTON_CHECK_LIT_PATH,
+ BUTTON_CHECK_LIT_FILL);
+}
+
+/* match x/y to a button if any */
+buttonstate *find_button(Gameboard *g, int x,int y){
+ int i;
+ buttonstate *states=g->b.states;
+
+ for(i=0;i<NUMBUTTONS;i++){
+ buttonstate *b=states+i;
+ if(b->position)
+ if( (b->x-x)*(b->x-x) + (b->y-y)*(b->y-y) <= BUTTON_RADIUS*BUTTON_RADIUS+4)
+ if(b->y != b->y_inactive)
+ return b;
+ }
+ return 0;
+}
+
+/* set a button to pressed or lit */
+void button_set_state(Gameboard *g, buttonstate *b, int rollover, int press){
+ int i;
+ buttonstate *states=g->b.states;
+
+ if(b->rollover == rollover && b->press == press)return;
+
+ for(i=0;i<NUMBUTTONS;i++){
+ buttonstate *bb=states+i;
+ if(bb->position){
+ if(bb!=b){
+ if(bb->rollover)
+ invalidate_rollover(g,bb);
+ if(bb->press)
+ invalidate_button(g,bb);
+
+ bb->rollover=0;
+ bb->press=0;
+ }else{
+ if(bb->rollover != rollover)
+ invalidate_rollover(g,bb);
+ if(bb->press != press)
+ invalidate_button(g,bb);
+
+ bb->rollover=rollover;
+ bb->press=press;
+ }
+ }
+ }
+ g->b.allclear=0;
+}
+
+/* cache the text extents of a rollover */
+void rollover_extents(Gameboard *g, buttonstate *b){
+
+ cairo_matrix_t m;
+
+ cairo_t *c = cairo_create(g->foreground);
+ cairo_select_font_face (c, "Arial",
+ CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_BOLD);
+
+ cairo_matrix_init_scale (&m, BUTTON_TEXT_SIZE);
+ cairo_set_font_matrix (c,&m);
+
+ cairo_text_extents (c, b->rollovertext, &b->ex);
+
+ cairo_destroy(c);
+}
+
+/* perform a single frame of animation for all buttons/rollovers */
+gboolean animate_button_frame(gpointer ptr){
+ Gameboard *g=(Gameboard *)ptr;
+ GdkRectangle expose;
+ buttonstate *states=g->b.states;
+ int ret=0,i,pos;
+
+ if(!g->first_expose)return 1;
+
+ g->b.sweeper += g->b.sweeperd;
+
+ /* avoid the normal expose event mechanism
+ during the button animations. This direct method is much faster as
+ it won't accidentally combine exposes over long stretches of
+ alpha-blended surfaces. */
+
+ for(pos=1;pos<=3;pos++){
+ memset(&expose,0,sizeof(expose));
+ for(i=0;i<NUMBUTTONS;i++)
+ if(states[i].position == pos)
+ ret|=animate_one(g,states+i,&expose);
+ if(expose.width && expose.height)
+ gameboard_draw(g,
+ expose.x,
+ expose.y,
+ expose.width,
+ expose.height);
+ }
+
+ if(!ret)g->b.sweeperd = 0;
+
+ if(!ret && g->gtk_timer!=0){
+ g_source_remove(g->gtk_timer);
+ g->gtk_timer=0;
+ }
+
+ if(!ret && g->button_callback)
+ // undeploy finished... call the undeploy callback
+ g->button_callback(g);
+
+ return ret;
+}
+
+/* the normal expose method for all buttons; called from the master
+ widget's expose */
+void expose_buttons(Gameboard *g,cairo_t *c, int x,int y,int w,int h){
+ int i;
+ buttonstate *states=g->b.states;
+
+ for(i=0;i<NUMBUTTONS;i++){
+
+ buttonstate *b=states+i;
+
+ if(b->position){
+ GdkRectangle r = rollover_box(g,b);
+ GdkRectangle br = button_box(b);
+
+ if(x < br.x+br.width &&
+ y < br.y+br.height &&
+ x+w > br.x &&
+ y+h > br.y) {
+
+ cairo_set_source_surface(c,
+ (b->rollover || b->press ? b->lit : b->idle),
+ br.x,
+ br.y);
+
+ if(b->press)
+ cairo_paint_with_alpha(c,b->alpha);
+ cairo_paint_with_alpha(c,b->alpha);
+
+ }
+
+ if((b->rollover || b->press) && b->y_target!=b->y_inactive)
+ if(x < r.x+r.width &&
+ y < r.y+r.height &&
+ x+w > r.x &&
+ y+h > r.y)
+
+ stroke_rollover(g,b,c);
+ }
+ }
+}
+
+/* resize the button bar; called from master resize in gameboard */
+void resize_buttons(Gameboard *g,int oldw,int oldh,int w,int h){
+ int i;
+ int dx=w/2-oldw/2;
+ int dy=h/2-oldh/2;
+ buttonstate *states=g->b.states;
+
+ for(i=0;i<NUMBUTTONS;i++){
+ if(states[i].position == 2){
+
+ states[i].x+=dx;
+ states[i].x_target+=dx;
+
+ states[i].y+=dy;
+ states[i].y_target+=dy;
+ states[i].y_active+=dy;
+ states[i].y_inactive+=dy;
+ }
+ }
+
+ dx=w-oldw;
+ dy=h-oldh;
+
+ for(i=0;i<NUMBUTTONS;i++){
+ if(states[i].position==1 ||
+ states[i].position==3){
+ states[i].y+=dy;
+ states[i].y_target+=dy;
+ states[i].y_active+=dy;
+ states[i].y_inactive+=dy;
+ }
+ }
+
+ for(i=0;i<NUMBUTTONS;i++){
+ if(states[i].position == 3){
+ states[i].x+=dx;
+ states[i].x_target+=dx;
+ }
+ }
+}
+
+/* clear all buttons to unpressed/unlit */
+void button_clear_state(Gameboard *g){
+ int i;
+ buttonstate *states=g->b.states;
+
+ if(!g->b.allclear){
+ for(i=0;i<NUMBUTTONS;i++){
+ buttonstate *bb=states+i;
+ if(bb->position){
+ if(bb->rollover)
+ invalidate_rollover(g,bb);
+ if(bb->press)
+ invalidate_button(g,bb);
+
+ bb->rollover=0;
+ bb->press=0;
+ }
+ }
+ }
+ g->b.allclear=1;
+ g->b.grabbed=0;
+}
+
+void deploy_buttons(Gameboard *g, void (*callback)(Gameboard *g)){
+
+ if(!g->b.buttons_ready){
+
+ // sweep across the buttons inward from the horizontal edges; when
+ // the sweep passes a button it is set to deploy by making the
+ // target y equal to the active y target.
+
+ g->b.sweeper = 0;
+ g->b.sweeperd = 1;
+
+ g->button_callback = callback;
+ g->gtk_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
+ g->b.buttons_ready=1;
+ }
+
+}
+
+void undeploy_buttons(Gameboard *g, void (*callback)(Gameboard *ptr)){
+
+ if(g->b.buttons_ready){
+
+ button_clear_state(g);
+ g->b.buttons_ready=0;
+
+ // sweep across the buttons outward from the center; when
+ // the sweep passes a button it is set to undeploy by making the
+ // target y equal to the inactive y target.
+
+ g->b.sweeper = 0;
+ g->b.sweeperd = -1;
+
+ g->button_callback = callback;
+ g->gtk_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
+ }else
+ callback(g);
+
+}
Added: trunk/planarity/gameboard_logic_buttonbar.c
===================================================================
--- trunk/planarity/gameboard_logic_buttonbar.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_logic_buttonbar.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,149 @@
+#include <math.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "graph.h"
+#include "timer.h"
+#include "gameboard.h"
+#include "gameboard_draw_button.h"
+#include "gameboard_logic_buttonbar.h"
+#include "dialog_finish.h"
+#include "dialog_pause.h"
+#include "dialog_level.h"
+
+/************************ the lower button bar *********************/
+
+/* initialize the rather weird little animation engine */
+void setup_buttonbar(Gameboard *g){
+
+ buttonstate *states=g->b.states;
+ int xcount=BUTTONBAR_BORDER;
+ int dcount=0;
+ int i;
+ int w=g->g.width;
+ int h=g->g.height;
+
+ states[0].rollovertext="exit gPlanarity";
+ states[1].rollovertext="level selection menu";
+ states[2].rollovertext="reset board";
+ states[3].rollovertext="pause";
+ states[4].rollovertext="help / about";
+ states[5].rollovertext="expand";
+ states[6].rollovertext="shrink";
+ states[7].rollovertext="hide/show lines";
+ states[8].rollovertext="mark intersections";
+ states[9].rollovertext="click when finished!";
+
+ states[0].callback = quit_action;
+ states[1].callback = level_action;
+ states[2].callback = reset_action;
+ states[3].callback = pause_action;
+ states[4].callback = about_action;
+ states[5].callback = expand_action;
+ states[6].callback = shrink_action;
+ states[7].callback = toggle_hide_lines;
+ states[8].callback = toggle_show_intersections;
+ states[9].callback = finish_action;
+
+ for(i=0;i<NUMBUTTONS;i++)
+ states[i].position=0;
+
+ states[0].position = 1; //left;
+ states[1].position = 1; //left;
+ states[2].position = 1; //left;
+ states[3].position = 1; //left;
+ states[4].position = 1; //left;
+ states[5].position = 3; //right
+ states[6].position = 3; //right
+ states[7].position = 3; //right
+ states[8].position = 3; //right
+ states[9].position = 3; //right
+
+ for(i=0;i<NUMBUTTONS;i++){
+ buttonstate *b=states+i;
+ if(b->position == 1){
+
+ b->x = b->x_target = xcount;
+ b->y_active = h - BUTTONBAR_Y_FROM_BOTTOM;
+ b->y = b->y_target = b->y_inactive = h - BUTTONBAR_Y_FROM_BOTTOM + BUTTON_EXPOSE;
+ b->sweepdeploy = dcount;
+ xcount += BUTTONBAR_SPACING;
+ dcount += SWEEP_DELTA;
+ rollover_extents(g,states+i);
+ }
+ }
+
+ xcount = w-BUTTONBAR_BORDER;
+ dcount = 0;
+ for(i=NUMBUTTONS-1;i>=0;i--){
+ buttonstate *b=states+i;
+ if(b->position == 3){
+
+ b->x = b->x_target = xcount;
+ b->y_active = h - BUTTONBAR_Y_FROM_BOTTOM;
+ b->y = b->y_target = b->y_inactive = h - BUTTONBAR_Y_FROM_BOTTOM + BUTTON_EXPOSE;
+ b->sweepdeploy = dcount;
+
+ if(i!=9 || g->checkbutton_deployed){ // special-case the checkbutton
+ xcount -= BUTTONBAR_SPACING;
+ dcount += SWEEP_DELTA;
+ }else{
+ states[9].position = 0; //deactivate it for the deploy
+ }
+ rollover_extents(g,states+i);
+ }
+ }
+}
+
+/* effects animated 'rollout' of buttons when level begins */
+void deploy_buttonbar(Gameboard *g){
+ if(!g->b.buttons_ready ){
+ if(g->g.active_intersections <= g->g.objective)
+ g->checkbutton_deployed=1;
+ else
+ g->checkbutton_deployed=0;
+ setup_buttonbar(g);
+ deploy_buttons(g,0);
+ }
+
+}
+
+/* effects animated rollout of 'check' button */
+void deploy_check(Gameboard *g){
+ buttonstate *states=g->b.states;
+ if(g->b.buttons_ready && !g->checkbutton_deployed){
+ int i;
+ for(i=5;i<9;i++){
+ states[i].x_target-=BUTTONBAR_SPACING;
+ states[i].sweepdeploy += SWEEP_DELTA;
+ }
+
+ states[9].position = 3; //activate it
+ states[9].y_target = states[9].y_active;
+ states[i].sweepdeploy = 0;
+
+ if(g->gtk_timer!=0)
+ g_source_remove(g->gtk_timer);
+ g->gtk_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
+ g->checkbutton_deployed=1;
+ }
+}
+
+/* effects animated rollback of 'check' button */
+void undeploy_check(Gameboard *g){
+ buttonstate *states=g->b.states;
+ if(g->checkbutton_deployed){
+ int i;
+ for(i=5;i<9;i++){
+ states[i].x_target+=BUTTONBAR_SPACING;
+ states[i].sweepdeploy -= SWEEP_DELTA;
+ }
+ states[9].y_target=states[9].y_inactive;
+
+ if(g->gtk_timer!=0)
+ g_source_remove(g->gtk_timer);
+ g->gtk_timer = g_timeout_add(BUTTON_ANIM_INTERVAL, animate_button_frame, (gpointer)g);
+ g->checkbutton_deployed=0;
+ }
+}
Added: trunk/planarity/gameboard_logic_buttonbar.h
===================================================================
--- trunk/planarity/gameboard_logic_buttonbar.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_logic_buttonbar.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,21 @@
+extern void setup_buttonbar(Gameboard *g);
+extern void deploy_buttonbar(Gameboard *g);
+extern void undeploy_buttonbar(Gameboard *g, void (*callback)());
+extern void deploy_check(Gameboard *g);
+extern void undeploy_check(Gameboard *g);
+
+#define BUTTONBAR_Y_FROM_BOTTOM 25
+#define BUTTONBAR_LINE_WIDTH 1
+#define BUTTONBAR_TEXT_BORDER 15
+#define BUTTONBAR_TEXT_COLOR .1,.1,.7,.8
+#define BUTTONBAR_TEXT_SIZE 15.,18.
+
+#define BUTTONBAR_ANIM_INTERVAL 15
+#define BUTTONBAR_EXPOSE 50
+#define BUTTONBAR_DELTA 3
+
+#define BUTTONBAR_LEFT 5
+#define BUTTONBAR_RIGHT 5
+#define BUTTONBAR_BUTTONS 5
+#define BUTTONBAR_BORDER 35
+#define BUTTONBAR_SPACING 35
Added: trunk/planarity/gameboard_logic_mouse.c
===================================================================
--- trunk/planarity/gameboard_logic_mouse.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_logic_mouse.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,317 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+#include "dialog_level.h"
+
+/* does the given x/y fall inside an on-screen vertex? */
+static void check_lit(Gameboard *g,int x, int y){
+ vertex *v = find_vertex(&g->g,x,y);
+ if(v!=g->lit_vertex){
+ invalidate_vertex(g,v);
+ invalidate_vertex(g,g->lit_vertex);
+ g->lit_vertex = v;
+ }
+}
+
+/* toplevel mouse motion handler */
+gint mouse_motion(GtkWidget *widget,
+ GdkEventMotion *event){
+ Gameboard *g = GAMEBOARD (widget);
+
+ /* the level selection dialog implements its own icon mouse management */
+ if(g->level_dialog_active)
+ level_mouse_motion(g,(int)event->x,(int)event->y);
+
+ /* similarly, if a vertex is grabbed, the only thing that can
+ happen is that we're dragging that vertex */
+
+ if(g->grabbed_vertex){
+ int x = (int)event->x;
+ int y = (int)event->y;
+ g->dragx = x-g->grabx;
+ g->dragy = y-g->graby;
+
+ invalidate_vertex(g,g->grabbed_vertex);
+ invalidate_edges(widget,g->grabbed_vertex);
+ move_vertex(&g->g,g->grabbed_vertex,x+g->graboffx,y+g->graboffy);
+ invalidate_vertex(g,g->grabbed_vertex);
+ invalidate_edges(widget,g->grabbed_vertex);
+ return TRUE;
+
+ }
+
+ /* if the selection is grabbed, we can only be dragging a selection box */
+ if (g->selection_grab){
+ invalidate_selection(widget);
+
+ g->selectionx = min(g->grabx, event->x);
+ g->selectionw = labs(g->grabx - event->x);
+ g->selectiony = min(g->graby, event->y);
+ g->selectionh = labs(g->graby - event->y);
+ select_verticies(&g->g,
+ g->selectionx,g->selectiony,
+ g->selectionx+g->selectionw-1,
+ g->selectiony+g->selectionh-1);
+
+ invalidate_selection(widget);
+ return TRUE;
+ }
+
+ /* if a selected vertex is grabbed (group drag) we're dragging
+ the ghosted selection */
+
+ if(g->group_drag){
+ invalidate_verticies_selection(widget);
+ g->dragx = event->x - g->grabx;
+ g->dragy = event->y - g->graby;
+
+ /* don't allow the drag to put a vertex offscreen; bound the drag at the edge */
+ {
+ vertex *v=g->g.verticies;
+ int w=g->g.width;
+ int h=g->g.height;
+
+ while(v){
+ if(v->selected){
+ if(v->x + g->dragx >= w)
+ g->dragx=w - v->x -1;
+ if(v->x + g->dragx < 0 )
+ g->dragx= -v->x;
+ if(v->y + g->dragy >= h)
+ g->dragy=h - v->y -1;
+ if(v->y + g->dragy < 0 )
+ g->dragy= -v->y;
+ }
+ v=v->next;
+ }
+ }
+
+ invalidate_verticies_selection(widget);
+ return TRUE;
+ }
+
+ /* A vertex rollover has priority over a button rollover. However,
+ a button grab disallows a rollover, as does the curtain. */
+ if(!g->pushed_curtain && !g->button_grabbed)
+ check_lit(g, (int)event->x,(int)event->y);
+
+ /* handle button rollovers and ongoing grabs; other grabs are
+ already disallowed, but also verify a vertex rollover isn't
+ already active (and that buttons are currently hot) */
+ if(!g->lit_vertex && g->b.buttons_ready){
+ buttonstate *b = find_button(g,(int)event->x,(int)event->y);
+
+ if(g->b.grabbed){
+ /* a button is grabbed; a rollover sees only the grabbed
+ button */
+ if(g->b.grabbed==b)
+ button_set_state(g,b,1,1);
+ else
+ button_set_state(g,b,0,0);
+ }else{
+ /* no button is grabbed; any button may see a rollover */
+ if(b)
+ button_set_state(g,b,1,0);
+ else
+ button_clear_state(g);
+ }
+ }
+
+ return TRUE;
+}
+
+/* toplevel mouse button press handler */
+gboolean mouse_press (GtkWidget *widget,
+ GdkEventButton *event){
+
+ if(event->type == GDK_BUTTON_PRESS){ // filter out doubleclicks
+
+ Gameboard *g = GAMEBOARD (widget);
+
+ vertex *v = find_vertex(&g->g,(int)event->x,(int)event->y);
+ buttonstate *b = find_button(g,(int)event->x,(int)event->y);
+ int old_intersections = g->show_intersections;
+
+ /* the level selection dialog implements its own icon mouse management */
+ if(g->level_dialog_active)
+ level_mouse_press(g,(int)event->x,(int)event->y);
+
+ button_clear_state(g);
+ g->button_grabbed=0;
+ set_show_intersections(g,0);
+
+ /* presses that affect board elements other than buttons can only
+ happen when the curtain isn't pushed. */
+ if(!g->pushed_curtain){
+
+ /* case: shift-click addition of a single new vertex to selection */
+ if(v && event->state&GDK_SHIFT_MASK){
+ if(v->selected){
+ v->selected=0;
+ g->selection_active--;
+ }else{
+ v->selected=1;
+ g->selection_active++;
+ }
+ invalidate_vertex(g,g->lit_vertex);
+ return TRUE;
+ }
+
+ /* case: shift-click drag of an additional region to add to selection */
+ if(event->state&GDK_SHIFT_MASK){
+ g->selection_grab=1;
+ g->grabx = (int)event->x;
+ g->graby = (int)event->y;
+ g->selectionx = g->grabx;
+ g->selectionw = 0;
+ g->selectiony = g->graby;
+ g->selectionh = 0;
+ return TRUE;
+ }
+
+ /* case: drag the selected group of verticies to new location */
+ if(g->selection_active && v && v->selected){
+ g->group_drag=1;
+ g->grabx = (int)event->x;
+ g->graby = (int)event->y;
+ g->dragx = 0;
+ g->dragy = 0;
+ // put the verticies into the background for faster update
+ update_full(g);
+ return TRUE;
+ }
+
+ /* if selection is active, we got this far, and we're not about to
+ take action based on pointing at a button, selection should be
+ inactivated */
+ if(g->selection_active && (g->lit_vertex || !b)){
+ deselect_verticies(&g->g);
+ g->selection_active=0;
+ g->group_drag=0;
+ // potentially pull verticies out of background (can happen if
+ // mouse went offscreen during a grab)
+ update_full(g);
+ }
+
+ /* case: grab/drag a single unselected vertex */
+ if(g->lit_vertex){
+ g->grabbed_vertex = g->lit_vertex;
+ g->grabx = (int)event->x;
+ g->graby = (int)event->y;
+ g->graboffx = g->grabbed_vertex->x-g->grabx;
+ g->graboffy = g->grabbed_vertex->y-g->graby;
+
+ grab_vertex(&g->g,g->grabbed_vertex);
+ invalidate_attached(widget,g->grabbed_vertex);
+ invalidate_edges(widget,g->grabbed_vertex);
+
+ // highlight vertex immediately; update the background after the
+ // vertex change
+ update_full_delayed(g);
+ return TRUE;
+ }
+ }
+
+ /* case: button click */
+ if(b){
+ // if intersections were visible, a button press is the only
+ // click that wouldn't auto-hide them, so restore the flag to
+ // its state before entry.
+ g->show_intersections=old_intersections;
+
+ button_set_state(g,b,1,1);
+ g->b.grabbed = b;
+ return TRUE;
+ }
+
+ /* clicking anywhere else wtith no modifiers initiates a new
+ selection drag (assuming curtain isn't pushed) */
+ if(!g->pushed_curtain){
+ g->selection_grab=1;
+ g->grabx = (int)event->x;
+ g->graby = (int)event->y;
+ g->selectionx = g->grabx;
+ g->selectionw = 0;
+ g->selectiony = g->graby;
+ g->selectionh = 0;
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* toplevel mouse button release handler */
+gboolean mouse_release (GtkWidget *widget,
+ GdkEventButton *event){
+ Gameboard *g = GAMEBOARD (widget);
+
+ /* case: button grabbed */
+ if(g->b.grabbed){
+ buttonstate *b = find_button(g,(int)event->x,(int)event->y);
+ if(b && g->b.grabbed==b){
+ button_set_state(g,b,1,0);
+ if(b->callback)
+ b->callback(g);
+ }
+ g->b.grabbed=0;
+ }
+
+ /* if the curtain is pushed, no sense checking for other grabs */
+ if(!g->pushed_curtain){
+
+ /* case: release a grabbed vertex */
+ if(g->grabbed_vertex){
+ ungrab_vertex(&g->g,g->grabbed_vertex);
+ update_add_vertex(g,g->grabbed_vertex);
+ update_score(g);
+ g->grabbed_vertex = 0;
+
+ if(g->g.active_intersections<=g->g.objective)
+ deploy_check(g);
+ else
+ undeploy_check(g);
+
+ }
+
+ /* case: release a selection grab */
+ if(g->selection_grab){
+ invalidate_selection(widget);
+ g->selection_grab=0;
+
+ /* are there selected verticies? If only one was selected, that's
+ usually due to an accidental drag while clicking. Treat a
+ single-vertex drag select as a nil selection */
+ if(num_selected_verticies(&g->g)<=1){
+ g->selection_active=0;
+ deselect_verticies(&g->g); // could have grabbed just one
+ }else{
+ commit_volatile_selection();
+ g->selection_active=num_selected_verticies(&g->g);
+ }
+ }
+
+ /* case: release a group drag */
+ if(g->group_drag){
+ move_selected_verticies(&g->g,g->dragx,g->dragy);
+ update_full(g); // cheating
+ update_score(g);
+ g->group_drag=0;
+ }
+ }
+
+ /* a release may result in a new mouse-over; look for it */
+ mouse_motion(widget,(GdkEventMotion *)event); // the cast is safe in this case
+
+ return TRUE;
+}
+
Added: trunk/planarity/gameboard_logic_push.c
===================================================================
--- trunk/planarity/gameboard_logic_push.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gameboard_logic_push.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,61 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+
+void update_push(Gameboard *g, cairo_t *c){
+
+ if(g->pushed_curtain){
+ int w = g->g.width;
+ int h = g->g.height;
+
+ draw_foreground(g,c,0,0,w,h);
+
+ // copy in the score and button surfaces
+ cairo_set_source_surface(c,g->forescore,0,0);
+ cairo_rectangle(c, 0,0,w,
+ min(SCOREHEIGHT,h));
+ cairo_fill(c);
+
+ cairo_set_source_surface(c,g->forebutton,0,g->w.allocation.height-SCOREHEIGHT);
+ cairo_rectangle(c, 0,0,w,h);
+ cairo_fill(c);
+
+ if(g->show_intersections)
+ draw_intersections(g,&g->g,c,0,0,w,h);
+
+ cairo_set_source (c, g->curtainp);
+ cairo_paint(c);
+
+ if(g->redraw_callback)g->redraw_callback(g);
+ }
+}
+
+void push_curtain(Gameboard *g,void(*redraw_callback)(Gameboard *g)){
+ if(!g->pushed_curtain){
+ cairo_t *c = cairo_create(g->background);
+ g->pushed_curtain=1;
+ g->redraw_callback=redraw_callback;
+
+ update_push(g,c);
+
+ cairo_destroy(c);
+ expose_full(g);
+
+ //gameboard_draw(g,0,0,w,h);
+ }
+}
+
+void pop_curtain(Gameboard *g){
+ if(g->pushed_curtain){
+ g->pushed_curtain=0;
+ update_full(g);
+ }
+}
Deleted: trunk/planarity/gamestate.c
===================================================================
--- trunk/planarity/gamestate.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gamestate.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,400 +0,0 @@
-#define _GNU_SOURCE
-#include <math.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <gtk/gtk.h>
-#include "graph.h"
-#include "gameboard.h"
-#include "generate.h"
-#include "gamestate.h"
-#include "buttons.h"
-#include "buttonbar.h"
-#include "finish.h"
-#include "pause.h"
-
-extern GtkWidget *toplevel_window;
-extern Gameboard *gameboard;
-extern graph maingraph;
-
-static int width=800;
-static int height=640;
-static int orig_width=800;
-static int orig_height=640;
-
-static int initial_intersections;
-static float intersection_mult=1.;
-static int objective=0;
-static int objective_lessthan=0;
-static char objective_string[80];
-static float objective_mult=1.;
-static int paused=0;
-static time_t begin_time_add=0;
-static time_t begin_time;
-
-
-time_t get_timer(){
- if(paused)
- return begin_time_add;
- else{
- time_t ret = time(NULL);
- return ret - begin_time + begin_time_add;
- }
-}
-
-void set_timer(time_t off){
- begin_time_add = off;
- begin_time = time(NULL);
-}
-
-void resize_board(int x, int y){
- width=x;
- height=y;
- check_verticies();
-}
-
-int get_board_width(){
- return width;
-}
-
-int get_board_height(){
- return height;
-}
-
-// graphs are originally generated to a 'nominal' minimum sized board.
-int get_orig_width(){
- return orig_width;
-}
-
-int get_orig_height(){
- return orig_height;
-}
-
-void gamestate_generate(int level){
- generate_mesh_1(&maingraph,level);
- impress_location(&maingraph);
- initial_intersections = maingraph.original_intersections;
-}
-
-void gamestate_go(){
- gameboard_reset(gameboard);
- set_timer(0);
- deploy_buttonbar(gameboard);
- unpause();
-}
-
-#define RESET_DELTA 2;
-
-void reset_board(){
- int flag=1;
- int hide_state = get_hide_lines(gameboard);
- hide_lines(gameboard);
-
- vertex *v=maingraph.verticies;
- while(v){
- deactivate_vertex(&maingraph,v);
- v=v->next;
- }
-
- while(flag){
- flag=0;
-
- v=maingraph.verticies;
- while(v){
- int bxd = (width - orig_width) >>1;
- int byd = (height - orig_height) >>1;
- int vox = v->orig_x + bxd;
- int voy = v->orig_y + byd;
-
- if(v->x != vox || v->y != voy){
- flag=1;
-
- invalidate_region_vertex(gameboard,v);
- if(v->x<vox){
- v->x+=RESET_DELTA;
- if(v->x>vox)v->x=vox;
- }else{
- v->x-=RESET_DELTA;
- if(v->x<vox)v->x=vox;
- }
- if(v->y<voy){
- v->y+=RESET_DELTA;
- if(v->y>voy)v->y=voy;
- }else{
- v->y-=RESET_DELTA;
- if(v->y<voy)v->y=voy;
- }
- invalidate_region_vertex(gameboard,v);
- }
- v=v->next;
- }
- gdk_window_process_all_updates();
- gdk_flush();
-
- }
-
- v=maingraph.verticies;
- while(v){
- activate_vertex(&maingraph,v);
- v=v->next;
- }
-
- if(!hide_state)show_lines(gameboard);
- if(maingraph.active_intersections <= get_objective()){
- deploy_check(gameboard);
- }else{
- undeploy_check(gameboard);
- }
- update_full(gameboard);
-
- // reset timer
- set_timer(0);
- unpause();
-}
-
-void pause(){
- begin_time_add = get_elapsed();
- paused=1;
-}
-
-void unpause(){
- paused=0;
- set_timer(begin_time_add);
-}
-
-int paused_p(){
- return paused;
-}
-
-void scale(double scale){
- int x=get_board_width()/2;
- int y=get_board_height()/2;
- int sel = selected(gameboard);
- // if selected, expand from center of selected mass
- if(sel){
- vertex *v=maingraph.verticies;
- double xac=0;
- double yac=0;
- while(v){
- if(v->selected){
- xac+=v->x;
- yac+=v->y;
- }
- v=v->next;
- }
- x = xac / selected(gameboard);
- y = yac / selected(gameboard);
- }
-
- vertex *v=maingraph.verticies;
- while(v){
-
- if(!sel || v->selected){
- int nx = rint((v->x - x)*scale+x);
- int ny = rint((v->y - y)*scale+y);
-
- if(nx<0)nx=0;
- if(nx>=width)nx=width-1;
- if(ny<0)ny=0;
- if(ny>=height)ny=height-1;
-
- deactivate_vertex(&maingraph,v);
- v->x = nx;
- v->y = ny;
- }
- v=v->next;
- }
-
- v=maingraph.verticies;
- while(v){
- activate_vertex(&maingraph,v);
- v=v->next;
- }
-
- update_full(gameboard);
-}
-
-void expand(){
- scale(1.2);
-}
-
-void shrink(){
- scale(.8);
-}
-
-void hide_show_lines(){
- if(get_hide_lines(gameboard))
- show_lines(gameboard);
- else
- hide_lines(gameboard);
-}
-
-void mark_intersections(){
- show_intersections(gameboard);
-}
-
-void finish_board(){
- if(maingraph.active_intersections<=initial_intersections){
- pause();
- levelstate_finish();
- undeploy_buttonbar(gameboard,finish_level_dialog);
- }
-}
-
-void quit(){
- pause();
- undeploy_buttonbar(gameboard,gtk_main_quit);
-}
-
-int get_score(){
- float intersection_score = (initial_intersections- maingraph.active_intersections)*
- intersection_mult;
-
- float obj_multiplier = 1;
-
- if(objective_lessthan)
- if(objective > maingraph.active_intersections)
- obj_multiplier += (objective-maingraph.active_intersections)*objective_mult;
-
- return rint( intersection_score * obj_multiplier );
-}
-
-int get_bonus(){
- float obj_multiplier = 1;
-
- if(objective_lessthan)
- if(objective > maingraph.active_intersections)
- obj_multiplier += (objective-maingraph.active_intersections)*objective_mult;
-
- if(get_elapsed()<initial_intersections)
- return rint ((initial_intersections-get_elapsed()) * obj_multiplier);
-
- return 0;
-}
-
-int get_initial_intersections(){
- return initial_intersections;
-}
-
-int get_objective(){
- return objective;
-}
-
-char *get_objective_string(){
- if(objective == 0)
- return "zero intersections";
- if(objective == 1){
- if(objective_lessthan){
- return "1 intersection or fewer";
- }else{
- return "1 intersection";
- }
- }else{
- snprintf(objective_string,80,"%d intersections%s",
- objective,(objective_lessthan?
- " or fewer":""));
- return objective_string;
- }
-}
-
-int write_board(char *boarddir, char *basename){
- char *name;
- FILE *f;
-
- name=alloca(strlen(boarddir)+strlen(basename)+3);
- name[0]=0;
- strcat(name,boarddir);
- strcat(name,basename);
-
- f = fopen(name,"wb");
- if(f==NULL){
- fprintf(stderr,"ERROR: Could not save board state for \"%s\":\n\t%s\n",
- get_level_string(),strerror(errno));
- return errno;
- }
-
- graph_write(&maingraph,f);
-
- fprintf(f,"objective %c %d\n",
- (objective_lessthan?'*':'='),objective);
- fprintf(f,"scoring %d %f %f %ld\n",
- initial_intersections,intersection_mult,objective_mult,(long)get_elapsed());
- fprintf(f,"board %d %d %d %d\n",
- width,height,orig_width,orig_height);
-
- gameboard_write(f, gameboard);
-
- fclose(f);
-
- strcat(name,".1");
- f = fopen(name,"wb");
- if(f==NULL){
- fprintf(stderr,"ERROR: Could not save board state for \"%s\":\n\t%s\n",
- get_level_string(),strerror(errno));
- return errno;
- }
- //gameboard_write_icon(f);
-
- fclose(f);
- return 0;
-}
-
-int read_board(char *boarddir,char *basename){
- FILE *f;
- char *name;
- char *line=NULL;
- size_t n=0;
-
- name=alloca(strlen(boarddir)+strlen(basename)+3);
- name[0]=0;
- strcat(name,boarddir);
- strcat(name,basename);
-
- f = fopen(name,"rb");
- if(f==NULL){
- if(errno != ENOENT){
- fprintf(stderr,"ERROR: Could not read saved board state for \"%s\":\n\t%s\n",
- get_level_string(),strerror(errno));
- }
- return errno;
- }
-
- graph_read(&maingraph,f);
-
- // get local game state
- while(getline(&line,&n,f)>0){
- int o;
- char c;
- long l;
-
- if (sscanf(line,"objective %c %d",&c,&o)==2){
-
- objective_lessthan = (c=='*');
- objective = o;
-
- }else if (sscanf(line,"scoring %d %f %f %ld",
- &initial_intersections,&intersection_mult,
- &objective_mult,&l)==4){
- paused=1;
- begin_time_add = l;
-
- }else{
- sscanf(line,"board %d %d %d %d",&width,&height,&orig_width,&orig_height);
-
- }
- }
-
-
- rewind(f);
-
- gameboard_read(f,gameboard);
- fclose (f);
- free(line);
-
- gtk_window_resize(GTK_WINDOW(toplevel_window),width,height);
- gameboard_reset(gameboard);
-
- return 0;
-}
-
Deleted: trunk/planarity/gamestate.h
===================================================================
--- trunk/planarity/gamestate.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/gamestate.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,30 +0,0 @@
-#include <time.h>
-
-extern void resize_board(int x, int y);
-extern int get_board_width();
-extern int get_board_height();
-extern int get_orig_width();
-extern int get_orig_height();
-extern void gamestate_generate(int level);
-extern void gamestate_go();
-extern void finish_board();
-extern void hide_show_lines();
-extern void mark_intersections();
-extern void reset_board();
-extern void expand();
-extern void shrink();
-extern int get_score();
-extern int get_bonus();
-extern int get_objective();
-extern char *get_objective_string();
-extern void quit();
-
-extern void pause();
-extern void unpause();
-extern int paused_p();
-extern time_t get_timer();
-extern void set_timer(time_t off);
-extern int get_initial_intersections();
-
-extern int read_board(char *boarddir,char *basename);
-extern int write_board(char *boarddir,char *basename);
Deleted: trunk/planarity/generate.c
===================================================================
--- trunk/planarity/generate.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/generate.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,228 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-
-#include "graph.h"
-#include "generate.h"
-#include "arrange.h"
-
-typedef struct {
- vertex **v;
- int width;
- int height;
-} mesh;
-
-typedef struct {
- int vnum[8];
- vertex *center;
- mesh *m;
-} neighbors_grid;
-
-typedef struct {
- int vnum[8];
- int num;
-} neighbors_list;
-
-static void populate_neighbors(int vnum, mesh *m,
- neighbors_grid *ng){
- int width = m->width;
- int y = vnum/width;
- int x = vnum - (y*width);
- int i;
-
- for(i=0;i<8;i++)ng->vnum[i]=-1;
-
-
- ng->center = m->v[vnum];
- ng->m = m;
-
- if(y-1 >= 0){
- if(x-1 >= 0) ng->vnum[0]= (y-1)*width+(x-1);
- ng->vnum[1]= (y-1)*width+x;
- if(x+1 < m->width) ng->vnum[2]= (y-1)*width+(x+1);
- }
-
- if(x-1 >= 0) ng->vnum[3]= y*width+(x-1);
- if(x+1 < m->width) ng->vnum[4]= y*width+(x+1);
-
- if(y+1 < m->height){
- if(x-1 >= 0) ng->vnum[5]= (y+1)*width+(x-1);
- ng->vnum[6]= (y+1)*width+x;
- if(x+1 < m->width) ng->vnum[7]= (y+1)*width+(x+1);
- }
-
-}
-
-// eliminate from neighbor structs the verticies that already have at
-// least one edge
-static void filter_spanned_neighbors(neighbors_grid *ng,
- neighbors_list *nl){
- int i;
- int count=0;
- for(i=0;i<8;i++)
- if(ng->vnum[i]==-1 || ng->m->v[ng->vnum[i]]->edges){
- ng->vnum[i]=-1;
- }else{
- nl->vnum[count++]=ng->vnum[i];
- }
- nl->num=count;
-
-}
-
-// eliminate from neighbor struct any verticies to which we can't make
-// an edge without crossing another edge. Only 0,2,5,7 possible.
-static void filter_intersections(neighbors_grid *ng){
- int i;
- for(i=0;i<8;i++){
- switch(i){
- case 0:
- if(ng->vnum[1] != -1 &&
- ng->vnum[3] != -1 &&
- exists_edge(ng->m->v[ng->vnum[1]],
- ng->m->v[ng->vnum[3]]))
- ng->vnum[i]=-1;
- break;
-
- case 2:
- if(ng->vnum[1] != -1 &&
- ng->vnum[4] != -1 &&
- exists_edge(ng->m->v[ng->vnum[1]],
- ng->m->v[ng->vnum[4]]))
- ng->vnum[i]=-1;
- break;
-
- case 5:
- if(ng->vnum[3] != -1 &&
- ng->vnum[6] != -1 &&
- exists_edge(ng->m->v[ng->vnum[3]],
- ng->m->v[ng->vnum[6]]))
- ng->vnum[i]=-1;
- break;
-
- case 7:
- if(ng->vnum[4] != -1 &&
- ng->vnum[6] != -1 &&
- exists_edge(ng->m->v[ng->vnum[4]],
- ng->m->v[ng->vnum[6]]))
- ng->vnum[i]=-1;
- break;
- }
- }
-}
-
-// eliminate verticies we've already connected to
-static void filter_edges(neighbors_grid *ng,
- neighbors_list *nl){
-
- vertex *v=ng->center;
- int count=0,i;
- for(i=0;i<8;i++){
- if(ng->vnum[i]!=-1){
- if(!exists_edge(v,ng->m->v[ng->vnum[i]]))
- nl->vnum[count++]=ng->vnum[i];
- else
- ng->vnum[i]=-1;
- }
- }
- nl->num=count;
-}
-
-static void random_populate(graph *g, int current, mesh *m, int min_connect, float prob){
- int num_edges=0,i;
- neighbors_grid ng;
- neighbors_list nl;
- populate_neighbors(current, m, &ng);
- filter_intersections(&ng);
- filter_edges(&ng,&nl);
-
- {
- edge_list *el=m->v[current]->edges;
- while(el){
- num_edges++;
- el=el->next;
- }
- }
-
- while(num_edges<min_connect && nl.num){
- int choice = random() % nl.num;
- add_edge(g,m->v[current], m->v[nl.vnum[choice]]);
- num_edges++;
- filter_intersections(&ng);
- filter_edges(&ng,&nl);
- }
-
- for(i=0;i<nl.num;i++)
- if(random()<RAND_MAX*prob){
- num_edges++;
- add_edge(g,m->v[current], m->v[nl.vnum[i]]);
- }
-}
-
-static void span_depth_first(graph *g,int current, mesh *m){
- neighbors_grid ng;
- neighbors_list nl;
-
- while(1){
- populate_neighbors(current, m, &ng);
- // don't reverse the order of the next two
- filter_intersections(&ng);
- filter_spanned_neighbors(&ng,&nl);
- if(nl.num == 0) break;
-
- {
- int choice = random() % nl.num;
- add_edge(g,m->v[current], m->v[nl.vnum[choice]]);
-
- span_depth_first(g,nl.vnum[choice], m);
- }
- }
-}
-
-void generate_mesh_1(graph *g, int order){
- int flag=0;
- mesh m;
- m.width=3;
- m.height=2;
- vertex *vlist;
-
- srandom(order);
- {
- while(order--){
- if(flag){
- flag=0;
- m.height+=1;
- }else{
- flag=1;
- m.width+=2;
- }
- }
- }
-
- vlist=new_board(g, m.width * m.height);
-
- /* a flat vector is easier to address while building the mesh */
- {
- int i;
- vertex *v=vlist;
- m.v=alloca(m.width*m.height * sizeof(*m.v));
- for(i=0;i<m.width*m.height;i++){
- m.v[i]=v;
- v=v->next;
- }
- }
-
- /* first walk a random spanning tree */
- span_depth_first(g, 0, &m);
-
- /* now iterate the whole mesh adding random edges */
- {
- int i;
- for(i=0;i<m.width*m.height;i++)
- random_populate(g, i, &m, 2, .25);
- }
-
- randomize_verticies(g);
- arrange_verticies_circle(g);
-
- //arrange_verticies_mesh(m.width,m.height);
-}
-
Deleted: trunk/planarity/generate.h
===================================================================
--- trunk/planarity/generate.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/generate.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1 +0,0 @@
-extern void generate_mesh_1(graph *g, int order);
Modified: trunk/planarity/graph.c
===================================================================
--- trunk/planarity/graph.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -5,7 +5,7 @@
#include <math.h>
#include "graph.h"
-#include "gamestate.h"
+#include "timer.h"
#include "gameboard.h"
#define CHUNK 64
@@ -393,8 +393,15 @@
while(num--)
get_vertex(g);
g->original_intersections = 0;
+ g->active_intersections = 0;
+ g->num_edges=0; // hopefully redundant
+ g->num_edges_active=0; // hopefully redundant
}
+void graph_release(graph *g){
+ set_num_verticies(g,0);
+}
+
void activate_vertex(graph *g,vertex *v){
edge_list *el=v->edges;
v->active=1;
@@ -463,61 +470,6 @@
return match;
}
-static void check_vertex_helper(graph *g, vertex *v, int reactivate){
- int flag=0;
-
- if(v->x>=get_board_width()){
- v->x=get_board_width()-1;
- flag=1;
- }
- if(v->x<0){
- v->x=0;
- flag=1;
- }
- if(v->y>=get_board_height()){
- v->y=get_board_height()-1;
- flag=0;
- }
- if(v->y<0){
- v->y=0;
- flag=1;
- }
- if(flag){
- if(v->edges){
- deactivate_vertex(g,v);
- if(reactivate)activate_vertex(g,v);
- }
- }
-}
-
-static void check_vertex(graph *g, vertex *v){
- check_vertex_helper(g,v,1);
-}
-
-void check_verticies(graph *g){
- vertex *v=g->verticies;
- while(v){
- vertex *next=v->next;
- check_vertex_helper(g,v,0);
- v=next;
- }
-
- v=g->verticies;
- while(v){
- vertex *next=v->next;
- activate_vertex(g,v);
- v=next;
- }
-}
-
-void move_vertex(graph *g, vertex *v, int x, int y){
- if(!v->grabbed) deactivate_vertex(g,v);
- v->x=x;
- v->y=y;
- check_vertex_helper(g,v,0);
- if(!v->grabbed) activate_vertex(g,v);
-}
-
// tenative selection; must be confirmed if next call should not clear
void select_verticies(graph *g,int x1, int y1, int x2, int y2){
vertex *v = g->verticies;
@@ -583,53 +535,6 @@
}
}
-void move_selected_verticies(graph *g,int dx, int dy){
- vertex *v = g->verticies;
- /* deactivate selected verticies */
- while(v){
- vertex *next=v->next;
- if(v->selected)
- deactivate_vertex(g,v);
- v=next;
- }
-
- /* move selected verticies and reactivate */
- v=g->verticies;
- while(v){
- vertex *next=v->next;
- if(v->selected){
- v->x+=dx;
- v->y+=dy;
- check_vertex(g,v);
- activate_vertex(g,v);
- }
- v=next;
- }
-
-}
-
-void scale_verticies(graph *g,float amount){
- vertex *v=g->verticies;
- int x=get_board_width()/2;
- int y=get_board_height()/2;
-
- while(v){
- vertex *next=v->next;
- deactivate_vertex(g,v);
- v->x=rint((v->x-x)*amount)+x;
- v->y=rint((v->y-y)*amount)+y;
- v=next;
- }
-
- v=g->verticies;
- while(v){
- vertex *next=v->next;
- check_vertex(g,v);
- activate_vertex(g,v);
- v=next;
- }
-}
-
static vertex *split_vertex_list(vertex *v){
vertex *half=v;
vertex *prevhalf=v;
@@ -682,6 +587,108 @@
g->verticies=randomize_helper(g->verticies);
}
+static void check_vertex_helper(graph *g, vertex *v, int reactivate){
+ int flag=0;
+
+ if(v->x>=g->width){
+ v->x=g->width-1;
+ flag=1;
+ }
+ if(v->x<0){
+ v->x=0;
+ flag=1;
+ }
+ if(v->y>=g->height){
+ v->y=g->height-1;
+ flag=0;
+ }
+ if(v->y<0){
+ v->y=0;
+ flag=1;
+ }
+ if(flag){
+ if(v->edges){
+ deactivate_vertex(g,v);
+ if(reactivate)activate_vertex(g,v);
+ }
+ }
+}
+
+static void check_vertex(graph *g, vertex *v){
+ check_vertex_helper(g,v,1);
+}
+
+void check_verticies(graph *g){
+ vertex *v=g->verticies;
+ while(v){
+ vertex *next=v->next;
+ check_vertex_helper(g,v,0);
+ v=next;
+ }
+
+ v=g->verticies;
+ while(v){
+ vertex *next=v->next;
+ activate_vertex(g,v);
+ v=next;
+ }
+}
+
+void move_vertex(graph *g, vertex *v, int x, int y){
+ if(!v->grabbed) deactivate_vertex(g,v);
+ v->x=x;
+ v->y=y;
+ check_vertex_helper(g,v,0);
+ if(!v->grabbed) activate_vertex(g,v);
+}
+
+void move_selected_verticies(graph *g,int dx, int dy){
+ vertex *v = g->verticies;
+ /* deactivate selected verticies */
+ while(v){
+ vertex *next=v->next;
+ if(v->selected)
+ deactivate_vertex(g,v);
+ v=next;
+ }
+
+ /* move selected verticies and reactivate */
+ v=g->verticies;
+ while(v){
+ vertex *next=v->next;
+ if(v->selected){
+ v->x+=dx;
+ v->y+=dy;
+ check_vertex(g,v);
+ activate_vertex(g,v);
+ }
+ v=next;
+ }
+
+}
+
+void scale_verticies(graph *g,float amount){
+ vertex *v=g->verticies;
+ int x=g->width/2;
+ int y=g->height/2;
+
+ while(v){
+ vertex *next=v->next;
+ deactivate_vertex(g,v);
+ v->x=rint((v->x-x)*amount)+x;
+ v->y=rint((v->y-y)*amount)+y;
+ v=next;
+ }
+
+ v=g->verticies;
+ while(v){
+ vertex *next=v->next;
+ check_vertex(g,v);
+ activate_vertex(g,v);
+ v=next;
+ }
+}
+
vertex *new_board(graph *g, int num_v){
set_num_verticies(g,num_v);
return g->verticies;
@@ -693,8 +700,8 @@
// centered on what the current board size is.
void impress_location(graph *g){
- int xd = (get_board_width()-get_orig_width())>>1;
- int yd = (get_board_height()-get_orig_height())>>1;
+ int xd = (g->width-g->orig_width)>>1;
+ int yd = (g->height-g->orig_height)>>1;
vertex *v=g->verticies;
while(v){
v->orig_x=v->x;
@@ -712,20 +719,32 @@
vertex *v=g->verticies;
edge *e=g->edges;
vertex **flat = alloca(g->vertex_num*sizeof(*flat));
+ int *iflat = alloca(g->vertex_num*sizeof(*iflat));
+ i=0;
while(v){
flat[v->num]=v;
+ iflat[v->num]=i++;
v=v->next;
}
- for(i=0;i<g->vertex_num;i++){
- v = flat[i];
+ fprintf(f,"scoring %ld %f %f %ld %c %d\n",
+ g->original_intersections,
+ g->intersection_mult, g->objective_mult, (long)get_timer(),
+ (g->objective_lessthan?'*':'='),g->objective);
+
+ fprintf(f,"board %d %d %d %d\n",
+ g->width,g->height,g->orig_width,g->orig_height);
+
+ v=g->verticies;
+ while(v){
fprintf(f,"vertex %d %d %d %d %d\n",
v->orig_x,v->orig_y,v->x,v->y,v->selected);
+ v=v->next;
}
while(e){
- fprintf(f,"edge %d %d\n",e->A->num,e->B->num);
+ fprintf(f,"edge %d %d\n",iflat[e->A->num],iflat[e->B->num]);
e=e->next;
}
@@ -733,13 +752,15 @@
}
int graph_read(graph *g,FILE *f){
- char *line=NULL;
- int i,x,y,ox,oy,sel,A,B,n=0;
+ char *line=NULL,c;
+ int i,x,y,ox,oy,sel,A,B;
+ unsigned int n=0;
vertex **flat,*v;
+ long l;
new_board(g,0);
- // get all verticies first
+ // get all verticies / scoring first
while(getline(&line,&n,f)>0){
if(sscanf(line,"vertex %d %d %d %d %d",
@@ -752,7 +773,23 @@
v->y=y;
v->selected=sel;
}
- }
+
+ if(sscanf(line,"scoring %ld %f %f %ld %c %d\n",
+ &g->original_intersections,
+ &g->intersection_mult, &g->objective_mult, &l,
+ &c,&g->objective)==6){
+
+ pause_timer();
+ set_timer(l);
+ if(c == '*')
+ g->objective_lessthan = 1;
+ else
+ g->objective_lessthan = 0;
+ }
+
+ sscanf(line,"board %d %d %d %d",&g->width,&g->height,&g->orig_width,&g->orig_height);
+
+ }
rewind(f);
flat=alloca(g->vertex_num*sizeof(*flat));
@@ -772,6 +809,7 @@
else
fprintf(stderr,"WARNING: edge references out of range vertex in save file\n");
}
+ sscanf(line,"int %ld",&g->original_intersections);
}
rewind(f);
Modified: trunk/planarity/graph.h
===================================================================
--- trunk/planarity/graph.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -47,13 +47,33 @@
vertex *verticies;
int vertex_num;
edge *edges;
- int active_intersections;
- int original_intersections;
+ long active_intersections;
int num_edges;
int num_edges_active;
+
+ int width;
+ int height;
+ int orig_width;
+ int orig_height;
+
+ // scoring related metadata
+ long original_intersections;
+ float intersection_mult;
+ int objective;
+ int objective_lessthan;
+ float objective_mult;
+
} graph;
+typedef struct graphmeta{
+ int num;
+ char *id;
+ char *desc;
+ void (*gen)(graph *,int arg);
+ int gen_arg;
+} graphmeta;
+
#include <stdio.h>
extern vertex *new_board(graph *g, int num_v);
@@ -70,8 +90,6 @@
extern void randomize_verticies(graph *g);
extern edge *add_edge(graph *g,vertex *A, vertex *B);
extern int exists_edge(vertex *a, vertex *b);
-extern int get_board_width();
-extern int get_board_height();
extern vertex *get_verticies();
extern edge *get_edges();
extern int num_selected_verticies(graph *g);
@@ -82,5 +100,10 @@
extern void commit_volatile_selection();
extern vertex *get_vertex();
extern void activate_verticies();
-extern int graph_write(graph *g,FILE *f);
-extern int graph_read(graph *g,FILE *f);
+extern int graph_write(graph *g, FILE *f);
+extern int graph_read(graph *g, FILE *f);
+extern void graph_release(graph *g);
+
+extern int graphscore_get_score(graph *g);
+extern int graphscore_get_bonus(graph *g);
+extern char *graphscore_objective_string(graph *g);
Added: trunk/planarity/graph_arrange.c
===================================================================
--- trunk/planarity/graph_arrange.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph_arrange.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,38 @@
+#include <math.h>
+
+#include "graph.h"
+#include "gameboard.h"
+#include "graph_arrange.h"
+
+void arrange_verticies_circle(graph *g){
+ vertex *v = g->verticies;
+ int n = g->vertex_num;
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int radius=min(bw,bh)*.45;
+ int i;
+ for(i=0;i<n;i++){
+ v->x = rint( radius * cos( i*M_PI*2./n) + (bw>>1));
+ v->y = rint( radius * sin( i*M_PI*2./n) + (bh>>1));
+ v=v->next;
+ }
+}
+
+void arrange_verticies_mesh(graph *g, int width, int height){
+ vertex *v = g->verticies;
+ int bw=g->orig_width;
+ int bh=g->orig_height;
+ int spacing=min((float)bw/width,(float)bh/height)*.9;
+ int x,y;
+
+ int xpad=(bw - (width-1)*spacing)/2;
+ int ypad=(bh - (height-1)*spacing)/2;
+
+ for(y=0;y<height;y++){
+ for(x=0;x<width;x++){
+ v->x=x*spacing+xpad;
+ v->y=y*spacing+ypad;
+ v=v->next;
+ }
+ }
+}
Added: trunk/planarity/graph_arrange.h
===================================================================
--- trunk/planarity/graph_arrange.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph_arrange.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,2 @@
+extern void arrange_verticies_circle(graph *g);
+extern void arrange_verticies_mesh(graph *g, int width, int height);
Added: trunk/planarity/graph_generate.c
===================================================================
--- trunk/planarity/graph_generate.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph_generate.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,114 @@
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include "graph.h"
+#include "graph_generate.h"
+
+typedef struct {
+ char *class;
+ int instancenum;
+ char *desc;
+ void (*gen)(graph *g, int num);
+ float intersection_mult;
+ float objective_mult;
+} gen_instance;
+
+#define FINITE_LEVELS 1
+static gen_instance i_list[FINITE_LEVELS]={
+ {"mesh1", 1, "\"original\" board number one", generate_mesh_1, 1.,1. },
+ //{"mesh1", 2, "\"original\" board number two", generate_mesh_1, 1.,1. },
+ //{"mesh1", 3, "\"original\" board number three", generate_mesh_1, 1.,1. },
+ //{"mesh1", 4, "\"original\" board number four", generate_mesh_1, 1.,1. },
+ //{"mesh1", 5, "\"original\" board number five", generate_mesh_1, 1.,1. },
+};
+
+#define LOOP_LEVELS 1
+static gen_instance i_list_loop[LOOP_LEVELS]={
+ {"mesh1", 2, "\"original\" board number %d", generate_mesh_1, 1.,1. },
+};
+
+int generate_find_number(char *id){
+ int i;
+ char buffer[160];
+
+ for(i=0;i<FINITE_LEVELS;i++){
+ snprintf(buffer,160,"%s %d",i_list[i].class,i_list[i].instancenum);
+ if(!strcmp(id,buffer))
+ return i;
+ }
+
+ {
+ char *arg = strchr(id,' ');
+ if(arg){
+ unsigned int len = arg-id;
+
+ for(i=0;i<LOOP_LEVELS;i++){
+ if(strlen(i_list_loop[i].class)==len &&
+ !strncmp(i_list_loop[i].class,id,len)){
+
+ // class match, determine the level number
+ int order = atoi(arg+1);
+ return FINITE_LEVELS + (order - i_list_loop[i].instancenum)*FINITE_LEVELS + i;
+
+
+ }
+ }
+ }
+ }
+
+ return -1;
+}
+
+int generate_get_meta(int num, graphmeta *gm){
+ if(num<FINITE_LEVELS){
+
+ /* part of the finite list */
+
+ gm->num = num;
+ gm->desc = i_list[num].desc;
+ if(asprintf(&gm->id,"%s %d",i_list[num].class,i_list[num].instancenum)==-1){
+ fprintf(stderr,"Couldn't allocate memory for level name.\n");
+ return -1;
+ }
+ return 0;
+ }else{
+
+ /* past the finite list; one of the loop levels */
+ int classnum = (num - FINITE_LEVELS) % LOOP_LEVELS;
+ int ordernum = (num - FINITE_LEVELS) / LOOP_LEVELS +
+ i_list_loop[classnum].instancenum;
+
+ gm->num = num;
+ if(asprintf(&gm->desc,i_list_loop[classnum].desc,ordernum)==-1){
+ fprintf(stderr,"Couldn't allocate memory for level desciption.\n");
+ return -1;
+ }
+
+ if(asprintf(&gm->id,"%s %d",i_list[classnum].class,ordernum)==-1){
+ fprintf(stderr,"Couldn't allocate memory for level name.\n");
+ return -1;
+ }
+
+ return 0;
+
+ }
+}
+
+void generate_board(graph *g,int num){
+ gen_instance *gi;
+ if(num<FINITE_LEVELS){
+ gi = i_list+num;
+
+ gi->gen(g,gi->instancenum);
+ }else{
+ int classnum = (num - FINITE_LEVELS) % LOOP_LEVELS;
+ int ordernum = (num - FINITE_LEVELS) / LOOP_LEVELS +
+ i_list_loop[classnum].instancenum;
+
+ gi = i_list_loop+classnum;
+ gi->gen(g,ordernum);
+ }
+
+ g->objective_mult = gi->objective_mult;
+ g->intersection_mult = gi->intersection_mult;
+}
Added: trunk/planarity/graph_generate.h
===================================================================
--- trunk/planarity/graph_generate.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph_generate.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,5 @@
+extern int generate_find_number(char *id);
+extern int generate_get_meta(int num, graphmeta *gm);
+extern void generate_board(graph *g,int num);
+
+extern void generate_mesh_1(graph *g, int order);
Added: trunk/planarity/graph_generate_mesh1.c
===================================================================
--- trunk/planarity/graph_generate_mesh1.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph_generate_mesh1.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,229 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "graph.h"
+#include "gameboard.h"
+#include "graph_generate.h"
+#include "graph_arrange.h"
+
+typedef struct {
+ vertex **v;
+ int width;
+ int height;
+} mesh;
+
+typedef struct {
+ int vnum[8];
+ vertex *center;
+ mesh *m;
+} neighbors_grid;
+
+typedef struct {
+ int vnum[8];
+ int num;
+} neighbors_list;
+
+static void populate_neighbors(int vnum, mesh *m,
+ neighbors_grid *ng){
+ int width = m->width;
+ int y = vnum/width;
+ int x = vnum - (y*width);
+ int i;
+
+ for(i=0;i<8;i++)ng->vnum[i]=-1;
+
+
+ ng->center = m->v[vnum];
+ ng->m = m;
+
+ if(y-1 >= 0){
+ if(x-1 >= 0) ng->vnum[0]= (y-1)*width+(x-1);
+ ng->vnum[1]= (y-1)*width+x;
+ if(x+1 < m->width) ng->vnum[2]= (y-1)*width+(x+1);
+ }
+
+ if(x-1 >= 0) ng->vnum[3]= y*width+(x-1);
+ if(x+1 < m->width) ng->vnum[4]= y*width+(x+1);
+
+ if(y+1 < m->height){
+ if(x-1 >= 0) ng->vnum[5]= (y+1)*width+(x-1);
+ ng->vnum[6]= (y+1)*width+x;
+ if(x+1 < m->width) ng->vnum[7]= (y+1)*width+(x+1);
+ }
+
+}
+
+// eliminate from neighbor structs the verticies that already have at
+// least one edge
+static void filter_spanned_neighbors(neighbors_grid *ng,
+ neighbors_list *nl){
+ int i;
+ int count=0;
+ for(i=0;i<8;i++)
+ if(ng->vnum[i]==-1 || ng->m->v[ng->vnum[i]]->edges){
+ ng->vnum[i]=-1;
+ }else{
+ nl->vnum[count++]=ng->vnum[i];
+ }
+ nl->num=count;
+
+}
+
+// eliminate from neighbor struct any verticies to which we can't make
+// an edge without crossing another edge. Only 0,2,5,7 possible.
+static void filter_intersections(neighbors_grid *ng){
+ int i;
+ for(i=0;i<8;i++){
+ switch(i){
+ case 0:
+ if(ng->vnum[1] != -1 &&
+ ng->vnum[3] != -1 &&
+ exists_edge(ng->m->v[ng->vnum[1]],
+ ng->m->v[ng->vnum[3]]))
+ ng->vnum[i]=-1;
+ break;
+
+ case 2:
+ if(ng->vnum[1] != -1 &&
+ ng->vnum[4] != -1 &&
+ exists_edge(ng->m->v[ng->vnum[1]],
+ ng->m->v[ng->vnum[4]]))
+ ng->vnum[i]=-1;
+ break;
+
+ case 5:
+ if(ng->vnum[3] != -1 &&
+ ng->vnum[6] != -1 &&
+ exists_edge(ng->m->v[ng->vnum[3]],
+ ng->m->v[ng->vnum[6]]))
+ ng->vnum[i]=-1;
+ break;
+
+ case 7:
+ if(ng->vnum[4] != -1 &&
+ ng->vnum[6] != -1 &&
+ exists_edge(ng->m->v[ng->vnum[4]],
+ ng->m->v[ng->vnum[6]]))
+ ng->vnum[i]=-1;
+ break;
+ }
+ }
+}
+
+// eliminate verticies we've already connected to
+static void filter_edges(neighbors_grid *ng,
+ neighbors_list *nl){
+
+ vertex *v=ng->center;
+ int count=0,i;
+ for(i=0;i<8;i++){
+ if(ng->vnum[i]!=-1){
+ if(!exists_edge(v,ng->m->v[ng->vnum[i]]))
+ nl->vnum[count++]=ng->vnum[i];
+ else
+ ng->vnum[i]=-1;
+ }
+ }
+ nl->num=count;
+}
+
+static void random_populate(graph *g, int current, mesh *m, int min_connect, float prob){
+ int num_edges=0,i;
+ neighbors_grid ng;
+ neighbors_list nl;
+ populate_neighbors(current, m, &ng);
+ filter_intersections(&ng);
+ filter_edges(&ng,&nl);
+
+ {
+ edge_list *el=m->v[current]->edges;
+ while(el){
+ num_edges++;
+ el=el->next;
+ }
+ }
+
+ while(num_edges<min_connect && nl.num){
+ int choice = random() % nl.num;
+ add_edge(g,m->v[current], m->v[nl.vnum[choice]]);
+ num_edges++;
+ filter_intersections(&ng);
+ filter_edges(&ng,&nl);
+ }
+
+ for(i=0;i<nl.num;i++)
+ if(random()<RAND_MAX*prob){
+ num_edges++;
+ add_edge(g,m->v[current], m->v[nl.vnum[i]]);
+ }
+}
+
+static void span_depth_first(graph *g,int current, mesh *m){
+ neighbors_grid ng;
+ neighbors_list nl;
+
+ while(1){
+ populate_neighbors(current, m, &ng);
+ // don't reverse the order of the next two
+ filter_intersections(&ng);
+ filter_spanned_neighbors(&ng,&nl);
+ if(nl.num == 0) break;
+
+ {
+ int choice = random() % nl.num;
+ add_edge(g,m->v[current], m->v[nl.vnum[choice]]);
+
+ span_depth_first(g,nl.vnum[choice], m);
+ }
+ }
+}
+
+void generate_mesh_1(graph *g, int order){
+ int flag=0;
+ mesh m;
+ m.width=3;
+ m.height=2;
+ vertex *vlist;
+
+ srandom(order);
+ {
+ while(--order){
+ if(flag){
+ flag=0;
+ m.height+=1;
+ }else{
+ flag=1;
+ m.width+=2;
+ }
+ }
+ }
+
+ vlist=new_board(g, m.width * m.height);
+
+ /* a flat vector is easier to address while building the mesh */
+ {
+ int i;
+ vertex *v=vlist;
+ m.v=alloca(m.width*m.height * sizeof(*m.v));
+ for(i=0;i<m.width*m.height;i++){
+ m.v[i]=v;
+ v=v->next;
+ }
+ }
+
+ /* first walk a random spanning tree */
+ span_depth_first(g, 0, &m);
+
+ /* now iterate the whole mesh adding random edges */
+ {
+ int i;
+ for(i=0;i<m.width*m.height;i++)
+ random_populate(g, i, &m, 2, .25);
+ }
+
+ randomize_verticies(g);
+ arrange_verticies_circle(g);
+
+ //arrange_verticies_mesh(m.width,m.height);
+}
+
Added: trunk/planarity/graph_score.c
===================================================================
--- trunk/planarity/graph_score.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/graph_score.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,51 @@
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include "graph.h"
+#include "timer.h"
+
+static char objective_string[160];
+
+int graphscore_get_score(graph *g){
+ int intersection_score = (int)ceil((g->original_intersections- g->active_intersections)*
+ g->intersection_mult);
+ float obj_multiplier = 1;
+
+ if(g->objective_lessthan)
+ if(g->objective > g->active_intersections)
+ obj_multiplier += (g->objective-g->active_intersections)*g->objective_mult;
+
+ return ceil( intersection_score * obj_multiplier );
+}
+
+int graphscore_get_bonus(graph *g){
+ float obj_multiplier = 1;
+
+ if(g->objective_lessthan)
+ if(g->objective > g->active_intersections)
+ obj_multiplier += (g->objective-g->active_intersections)*g->objective_mult;
+
+ if(get_timer()< g->original_intersections*g->intersection_mult)
+ return ceil ((g->original_intersections*g->intersection_mult-get_timer()) * obj_multiplier);
+
+ return 0;
+}
+
+char *graphscore_objective_string(graph *g){
+ if(g->objective == 0)
+ return "zero intersections";
+ if(g->objective == 1){
+ if(g->objective_lessthan){
+ return "1 intersection or fewer";
+ }else{
+ return "1 intersection";
+ }
+ }else{
+ snprintf(objective_string,160,"%d intersections%s",
+ g->objective,(g->objective_lessthan?
+ " or fewer":""));
+ return objective_string;
+ }
+}
+
+
Modified: trunk/planarity/levelstate.c
===================================================================
--- trunk/planarity/levelstate.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/levelstate.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,5 +1,17 @@
+#define _GNU_SOURCE
+#include <gtk/gtk.h>
+#include <gtk/gtkmain.h>
#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "graph.h"
#include "levelstate.h"
+#include "gameboard.h"
+#include "dialog_pause.h"
+#include "dialog_finish.h"
+#include "dialog_level.h"
+#include "main.h"
+#include "graph_generate.h"
#define CHUNK 64
#define SAVENAME "levelstate"
@@ -8,28 +20,42 @@
struct levelstate *prev;
struct levelstate *next;
- int num;
- char *name;
+ graphmeta gm;
+
+ int in_progress;
long highscore;
- int in_progress;
+
} levelstate;
-levelstate *head;
-levelstate *tail;
-levelstate *curr;
-levelstate *pool;
+static levelstate *head=0;
+static levelstate *tail=0;
+static levelstate *curr=0;
+static levelstate *pool=0;
+static int graph_dirty = 1;
+static int completed_boards = 0;
+static int aboutflag = 0;
+static int pauseflag = 0;
+static int finishflag = 0;
+static int selectflag = 0;
+
static levelstate *new_level(){
levelstate *ret;
-
+ int num=0;
+
if(pool==0){
int i;
pool = calloc(CHUNK,sizeof(*pool));
- for(i=0;i<CHUNK-1;i++) /* last addition's next points to nothing */
+ for(i=0;i<CHUNK-1;i++) /* last addition's ->next points to nothing */
pool[i].next=pool+i+1;
}
ret=pool;
+ if(tail)
+ num=tail->gm.num+1;
+
+ if(generate_get_meta(num, &ret->gm)) return 0;
+
pool=ret->next;
ret->next=0;
@@ -37,112 +63,153 @@
if(tail){
ret->prev->next=ret;
- ret->num=ret->prev->num+1;
}else{
head=ret;
- ret->num=0;
}
-
- ret->name=board_level_to_name(ret->num);
+ tail=ret;
+
ret->highscore=0;
ret->in_progress=0;
+
+ /* write out a 'fresh' board icon if it doesn't already exist */
+ if(!gameboard_icon_exists(ret->gm.id,"1")){
+ // generate a graph we can use to make the icon
+ graph g;
+ memset(&g,0,sizeof(g));
+ g.width=gameboard->g.width;
+ g.height=gameboard->g.height;
+ g.orig_width=gameboard->g.orig_width;
+ g.orig_height=gameboard->g.orig_height;
+
+ generate_board(&g,num);
+ impress_location(&g);
+
+ gameboard_write_icon(ret->gm.id,"1",gameboard,&g,1,1);
+
+ // releases the temporary graph memory
+ graph_release(&g);
+ }
+
return ret;
}
+static levelstate *ensure_level_num(int level){
-static levelstate *find_level(char *name){
- int level=board_name_to_level(name);
-
if(level<0)return 0;
if(!tail)new_level();
- if(level=<tail->num){
+ if(level <= tail->gm.num){
// find it in the existing levels
levelstate *l=tail;
while(l){
- if(level == l->num) return l;
+ if(level == l->gm.num) return l;
l=l->prev;
}
return 0;
}else{
// make new levels to fill
- while(tail->num<level)
+ while(tail->gm.num<level)
new_level();
return tail;
}
}
-int levelstate_write(char *statedir){
+static levelstate *ensure_level(char *name){
+ int level=generate_find_number(name);
+ return ensure_level_num(level);
+}
+
+int levelstate_write(){
FILE *f;
- char *name=alloca(strlen(statedir)+strlen(levelstate)+1);
+ char *name=alloca(strlen(statedir)+strlen(SAVENAME)+1);
name[0]=0;
- strcat(name,boarddir);
- strcat(name,levelstate);
+ strcat(name,statedir);
+ strcat(name,SAVENAME);
- if(curr->in_progress)
- write_board(curr->name);
+ if(!graph_dirty && (curr->in_progress || gameboard->finish_dialog_active)){
+ gameboard_write(curr->gm.id,gameboard);
+ gameboard_write_icon(curr->gm.id,"2",gameboard,&gameboard->g,
+ !gameboard->hide_lines,gameboard->show_intersections);
+ }
+
f = fopen(name,"wb");
if(f==NULL){
fprintf(stderr,"ERROR: Could not save game state file \"%s\":\n\t%s\n",
- name,strerror(errno));
+ curr->gm.id,strerror(errno));
return errno;
}
- fprintf(f,"current %d : %s\n",strlen(curr->name),curr->name);
+ fprintf(f,"current %d : %s\n",strlen(curr->gm.id),curr->gm.id);
{
levelstate *l=head;
while(l){
- fprintf(f,"level %ld %d %d %s\n",
+ fprintf(f,"level %ld %d %d : %s\n",
l->highscore,l->in_progress,
- strlen(l->name),l->name);
+ strlen(l->gm.id),l->gm.id);
l=l->next;
}
}
- if(about_dialog_active())
+ if(gameboard->about_dialog_active)
fprintf(f,"about 1\n");
- if(pause_dialog_active())
+ if(gameboard->pause_dialog_active)
fprintf(f,"pause 1\n");
- if(finish_dialog_active())
+ if(gameboard->finish_dialog_active)
fprintf(f,"finish 1\n");
- //if(level_dialog_active())
- //fprintf(f,"select 1\n");
+ if(gameboard->level_dialog_active)
+ fprintf(f,"select 1\n");
+ fclose(f);
return 0;
}
-int levelstate_read(char *statedir){
- char *cur_name;
- int count;
+// also functions as the levelstate init; always called once upon startup
+int levelstate_read(){
char *line=NULL;
size_t n=0;
- int aboutflag=0;
- int pauseflag=0;
- int finishflag=0;
+ FILE *f;
+ char *name=alloca(strlen(statedir)+strlen(SAVENAME)+1);
+ name[0]=0;
+ strcat(name,statedir);
+ strcat(name,SAVENAME);
+
+ if(!head)new_level();
+ if(!curr)curr=head;
+
+ f = fopen(name,"rb");
+ if(f==NULL){
+ if(errno!=ENOENT){
+ fprintf(stderr,"ERROR: Could not read game state file \"%s\":\n\t%s\n",
+ curr->gm.id,strerror(errno));
+ }
+ return errno;
+ }
- // first get all levels we've seen.
+ // get all levels we've seen.
while(getline(&line,&n,f)>0){
long l;
- int i,j;
+ int i;
+ unsigned int j;
if (sscanf(line,"level %ld %d %d : ",&l,&i,&j)==3){
char *name=strchr(line,':');
// guard against bad edits
if(name &&
(strlen(line) - (name - line + 2) >= j)){
- levelstate *l;
+ levelstate *le;
name += 2;
name[j]=0;
- l = find_level(name);
- if(l){
- l->highscore=l;
- l->in_progress=i;
+ le = ensure_level(name);
+ if(le){
+ if(l>0)completed_boards++;
+ le->highscore=l;
+ le->in_progress=i;
}
}
}
@@ -157,15 +224,13 @@
char *name=strchr(line,':');
// guard against bad edits
if(name &&
- (strlen(line) - (name - line + 2) >= j)){
- levelstate *l;
+ (strlen(line) - (name - line + 2) >= (unsigned)i)){
+ levelstate *le;
name += 2;
- name[j]=0;
- l = find_level(name);
- if(l){
- curr=l;
- break;
- }
+ name[i]=0;
+ le = ensure_level(name);
+ if(le)
+ curr=le;
}
}
@@ -180,24 +245,41 @@
if(sscanf(line,"finish %d",&i)==1)
if(i==1)
finishflag=1;
+
+ if(sscanf(line,"select %d",&i)==1)
+ if(i==1)
+ selectflag=1;
}
- if(!head)new_level();
- if(!curr)curr=head;
+ return 0;
+}
+
+void levelstate_resume(){
+
levelstate_go();
if(pauseflag){
- pause_game();
+ prepare_reenter_game(gameboard);
+ pause_dialog(gameboard);
}else if (aboutflag){
- about_game();
+ prepare_reenter_game(gameboard);
+ about_dialog(gameboard);
}else if (finishflag){
- finish_level_dialog();
+ prepare_reenter_game(gameboard);
+ finish_level_dialog(gameboard);
+ }else if (selectflag){
+ prepare_reenter_game(gameboard);
+ level_dialog(gameboard,0);
}else{
- gamestate_go();
+ prepare_reenter_game(gameboard);
+ reenter_game(gameboard);
}
+ aboutflag=0;
+ pauseflag=0;
+ finishflag=0;
+ selectflag=0;
- return 0;
}
long levelstate_total_hiscore(){
@@ -216,39 +298,80 @@
return curr->highscore;
}
-void levelstate_next(){
- if(curr->next)
+int levelstate_next(){
+ if(!curr->next)
+ new_level();
+
+ if(curr->next){
curr=curr->next;
+ graph_dirty=1;
+ return 1;
+ }
+ return 0;
}
-void levelstate_prev(){
- if(curr->prev)
+int levelstate_prev(){
+ if(curr->prev){
curr=curr->prev;
+ graph_dirty=1;
+ return 1;
+ }
+ return 0;
}
int get_level_num(){
- return curr->num;
+ return curr->gm.num;
}
-char *get_level_name(){
- return curr->name;
+char *get_level_desc(){
+ return curr->gm.desc;
}
void levelstate_finish(){
+ int score = graphscore_get_score(&gameboard->g) +
+ graphscore_get_bonus(&gameboard->g);
curr->in_progress=0;
- if(get_score() > curr->highscore)
- curr->highscore = get_score();
+ if(score > curr->highscore)
+ curr->highscore = score;
}
+void levelstate_reset(){
+ curr->in_progress=0;
+ graph_dirty=1;
+}
+
+int levelstate_in_progress(){
+ return curr->in_progress;
+}
+
/* commit to the currently selected level and set the game state to
readiness using it */
void levelstate_go(){
- if(!curr->in_progress || read_board(curr->name)){
- /* not on disk or couldn't load it. Get a fresh version */
- gamestate_generate(curr->level)
+ // we need to load the board if we're currently playing the board or sitting in the finish dialog right after
+ if(curr->in_progress || finishflag){
+ if(gameboard_read(curr->gm.id,gameboard)){
+ /* not on disk or couldn't load it. clear level state flags and get a fresh version */
+ aboutflag=0;
+ pauseflag=0;
+ finishflag=0;
+ selectflag=0;
+ generate_board(&gameboard->g,curr->gm.num);
+ activate_verticies(&gameboard->g);
+ impress_location(&gameboard->g);
+ }
+ }else{
+ /* no board in progress; fetch a new board */
+ generate_board(&gameboard->g,curr->gm.num);
+ activate_verticies(&gameboard->g);
+ impress_location(&gameboard->g);
}
-
curr->in_progress=1;
+ graph_dirty=0;
+}
+cairo_surface_t *levelstate_get_icon(int num){
+ levelstate *l=ensure_level_num(num);
+ if(l==0)return 0;
+ return gameboard_read_icon(l->gm.id,(l->in_progress?"2":"1"),gameboard);
}
Modified: trunk/planarity/levelstate.h
===================================================================
--- trunk/planarity/levelstate.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/levelstate.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,10 +1,14 @@
-extern int levelstate_write(char *statedir);
-extern int levelstate_read(char *statedir);
+extern int levelstate_write();
+extern int levelstate_read();
extern long levelstate_total_hiscore();
extern long levelstate_get_hiscore();
-extern void levelstate_next();
-extern void levelstate_prev();
+extern int levelstate_in_progress();
+extern int levelstate_next();
+extern int levelstate_prev();
extern int get_level_num();
-extern char *get_level_name();
+extern char *get_level_desc();
extern void levelstate_finish();
extern void levelstate_go();
+extern void levelstate_resume();
+extern void levelstate_reset();
+extern cairo_surface_t* levelstate_get_icon(int num);
Modified: trunk/planarity/main.c
===================================================================
--- trunk/planarity/main.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/main.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <gtk/gtk.h>
@@ -10,13 +11,13 @@
#include "graph.h"
#include "gameboard.h"
#include "levelstate.h"
+#include "main.h"
#define boardstate "/.gPlanarity/boards/"
#define mainstate "/.gPlanarity/"
-static char *boarddir;
-static char *statedir;
-
+char *boarddir;
+char *statedir;
Gameboard *gameboard;
GtkWidget *toplevel_window;
graph maingraph;
@@ -38,6 +39,21 @@
return 0;
}
+void request_resize(int width, int height){
+ gtk_window_resize(GTK_WINDOW(toplevel_window),width,height);
+}
+
+static void clean_exit(int sig){
+ signal(sig,SIG_IGN);
+ if(sig!=SIGINT)
+ fprintf(stderr,
+ "\nTrapped signal %d; saving state and exiting!\n",sig);
+
+ levelstate_write(statedir);
+ gtk_main_quit();
+ exit(0);
+}
+
int main(int argc, char *argv[]){
char *homedir = getenv("home");
if(!homedir)
@@ -85,16 +101,24 @@
g_signal_connect (G_OBJECT (toplevel_window), "delete-event",
G_CALLBACK (gtk_main_quit), NULL);
- gameboard = gameboard_new (&maingraph);
+ gameboard = gameboard_new();
+ levelstate_read();
gtk_container_add (GTK_CONTAINER (toplevel_window), GTK_WIDGET(gameboard));
gtk_widget_show_all (toplevel_window);
memset(&maingraph,0,sizeof(maingraph));
- levelstate_read(statedir);
+ /* get the setup processed before we fire up animations */
+ while (gtk_events_pending ())
+ gtk_main_iteration ();
+ gdk_flush();
+ levelstate_resume();
+ // signal(SIGINT,clean_exit);
+ //signal(SIGSEGV,clean_exit);
+
gtk_main ();
- levelstate_write(statedir);
+ levelstate_write();
return 0;
}
Added: trunk/planarity/main.h
===================================================================
--- trunk/planarity/main.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/main.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,5 @@
+extern char *boarddir;
+extern char *statedir;
+extern Gameboard *gameboard;
+
+extern void request_resize(int width, int height);
Deleted: trunk/planarity/pause.c
===================================================================
--- trunk/planarity/pause.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/pause.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,330 +0,0 @@
-#include <math.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "graph.h"
-#include "gameboard.h"
-#include "gamestate.h"
-#include "button_base.h"
-#include "buttonbar.h"
-#include "pause.h"
-#include "box.h"
-
-static int ui_paused=0;
-static int ui_about=0;
-static gint timer;
-static void (*callback)(Gameboard *);
-
-extern char *version;
-
-/* perform a single frame of animation for all pause dialog buttons/rollovers */
-static gboolean pause_animate_buttons(gpointer ptr){
- Gameboard *g=(Gameboard *)ptr;
- int ret=0;
-
- ret=animate_button_frame(g);
-
- if(!ret && timer!=0){
- g_source_remove(timer);
- timer=0;
- }
-
- if(!ret && callback)
- // undeploy finished... call the undeploy callback
- callback(g);
-
- return ret;
-}
-
-static void unpause_post (Gameboard *g){
- // back to buttonbar activity!
- pop_background(g);
- deploy_buttonbar(g);
- unpause();
- ui_paused=0;
- ui_about=0;
-}
-
-static void unpause_quit (Gameboard *g){
- gtk_main_quit();
-}
-
-static void undeploy_buttons(Gameboard *g){
- // undeploy pause buttons
- button_clear_state(g);
- buttons_ready=0;
-
- {
- buttonstate *b=states;
- b->target_x-=BUTTON_EXPOSE;
- }
- {
- buttonstate *b=states+10;
- b->target_x+=BUTTON_EXPOSE;
- }
-}
-
-static void local_unpause (Gameboard *g){
- undeploy_buttons(g);
- callback = unpause_post;
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, pause_animate_buttons, (gpointer)g);
-}
-
-static void local_quit (Gameboard *g){
- undeploy_buttons(g);
- callback = unpause_quit;
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, pause_animate_buttons, (gpointer)g);
-}
-
-/* initialize the rather weird little animation engine */
-static void setup_pause_buttons(Gameboard *g,int bw, int bh){
- int i;
- int w=get_board_width();
- int h=get_board_height();
-
- states[0].rollovertext="exit gPlanarity";
- states[10].rollovertext="resume game!";
-
- states[0].callback = local_quit;
- states[10].callback = local_unpause;
-
- for(i=0;i<NUMBUTTONS;i++)
- states[i].position=0;
-
- states[0].position = 2; //center;
- states[10].position = 2; //center;
-
- {
- buttonstate *b=states;
- b->target_x_active=
- b->x_active=
- b->target_x_active=
- b->target_x=
- w/2 - bw/2 + PAUSE_BUTTON_BORDER;
- b->x=b->target_x_inactive=b->x_inactive=b->target_x - BUTTON_EXPOSE;
- b->y = h/2 + bh/2 - PAUSE_BUTTON_Y;
- }
-
- {
- buttonstate *b=states+10;
- b->target_x_active=
- b->x_active=
- b->target_x_active=
- b->target_x=
- w/2 + bw/2 - PAUSE_BUTTON_BORDER;
- b->x=b->target_x_inactive=b->x_inactive=b->target_x + BUTTON_EXPOSE;
- b->y = h/2 + bh/2 - PAUSE_BUTTON_Y;
- }
-
- for(i=0;i<NUMBUTTONS;i++)
- if(states[i].position)
- rollover_extents(g,states+i);
-}
-
-static void render_text_centered(cairo_t *c, char *s, int x, int y){
- cairo_text_extents_t ex;
-
- cairo_text_extents (c, s, &ex);
- cairo_move_to (c, x-(ex.width/2)-ex.x_bearing, y-(ex.height/2)-ex.y_bearing);
- cairo_show_text (c, s);
-}
-
-static void draw_pausebox(Gameboard *g){
- int w= get_board_width();
- int h= get_board_height();
-
- cairo_t *c = cairo_create(g->background);
- borderbox_path(c,
- w/2 - PAUSEBOX_WIDTH/2,
- h/2 - PAUSEBOX_HEIGHT/2,
- PAUSEBOX_WIDTH,
- PAUSEBOX_HEIGHT);
- cairo_set_source_rgb(c,1,1,1);
- cairo_fill(c);
-
- centerbox(c,
- w/2 - PAUSEBOX_WIDTH/2,
- h/2 - PAUSEBOX_HEIGHT/2,
- PAUSEBOX_WIDTH,
- SCOREHEIGHT);
-
- centerbox(c,
- w/2 - PAUSEBOX_WIDTH/2 ,
- h/2 + PAUSEBOX_HEIGHT/2 - SCOREHEIGHT,
- PAUSEBOX_WIDTH,
- SCOREHEIGHT);
-
- {
- cairo_matrix_t ma;
- char time[160];
- int ho = get_elapsed() / 3600;
- int mi = get_elapsed() / 60 - ho*60;
- int se = get_elapsed() - ho*3600 - mi*60;
-
- if(ho){
- snprintf(time,160,"%d:%02d:%02d",ho,mi,se);
- }else if (mi){
- snprintf(time,160,"%d:%02d",mi,se);
- }else{
- snprintf(time,160,"%d seconds",se);
- }
-
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_matrix_init_scale (&ma, 18.,18.);
- cairo_set_font_matrix (c,&ma);
- cairo_set_source_rgba (c, TEXT_COLOR);
-
- render_text_centered(c,"Game Paused", w/2,h/2-PAUSEBOX_HEIGHT/2+SCOREHEIGHT/2);
- cairo_select_font_face (c, "Arial",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
- render_text_centered(c,"Time Elapsed:", w/2,h/2-30);
- render_text_centered(c,time, w/2,h/2);
- }
-
- cairo_destroy(c);
-}
-
-static void pause_game_post_undeploy(Gameboard *g){
- // set up new buttons
- setup_pause_buttons(g,PAUSEBOX_WIDTH, PAUSEBOX_HEIGHT);
-
- // draw pausebox
- push_curtain(g,draw_pausebox);
-
- // deploy new buttons
- callback=0;
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, pause_animate_buttons, (gpointer)g);
- buttons_ready=1;
-}
-
-void pause_game(Gameboard *g){
- // grab timer state
- ui_paused=1;
- pause();
-
- push_background(g,0);
- // undeploy buttonbar
- undeploy_buttonbar(g,pause_game_post_undeploy);
-}
-
-// the 'about' box is nearly identical, including the fact it pauses the game.
-// we just piggyback it here
-
-static void draw_aboutbox(Gameboard *g){
- int w= get_board_width();
- int h= get_board_height();
-
- cairo_t *c = cairo_create(g->background);
- borderbox_path(c,
- w/2 - ABOUTBOX_WIDTH/2,
- h/2 - ABOUTBOX_HEIGHT/2,
- ABOUTBOX_WIDTH,
- ABOUTBOX_HEIGHT);
- cairo_set_source_rgb(c,1,1,1);
- cairo_fill(c);
-
- centerbox(c,
- w/2 - ABOUTBOX_WIDTH/2,
- h/2 - ABOUTBOX_HEIGHT/2,
- ABOUTBOX_WIDTH,
- SCOREHEIGHT);
-
- centerbox(c,
- w/2 - ABOUTBOX_WIDTH/2 ,
- h/2 + ABOUTBOX_HEIGHT/2 - SCOREHEIGHT,
- ABOUTBOX_WIDTH,
- SCOREHEIGHT);
-
- {
- cairo_matrix_t ma;
- int y = h/2-ABOUTBOX_HEIGHT/2+SCOREHEIGHT/2;
- cairo_select_font_face (c, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_matrix_init_scale (&ma, 18.,18.);
- cairo_set_font_matrix (c,&ma);
- cairo_set_source_rgba (c, TEXT_COLOR);
-
- render_text_centered(c,"gPlanarity", w/2,y);
- cairo_select_font_face (c, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_NORMAL);
- y+=45;
- render_text_centered(c,"Untangle the mess!", w/2,y);
- y+=30;
-
- cairo_matrix_init_scale (&ma, 13.,13.);
- cairo_set_font_matrix (c,&ma);
- render_text_centered(c,"Drag verticies to eliminate crossed lines.", w/2,y); y+=16;
- render_text_centered(c,"The objective may be a complete solution or", w/2,y); y+=16;
- render_text_centered(c,"getting as close as possible to solving an", w/2,y); y+=16;
- render_text_centered(c,"unsolvable puzzle. Work quickly and", w/2,y); y+=16;
- render_text_centered(c,"exceed the objective for bonus points!", w/2,y); y+=16;
-
- y+=16;
- cairo_move_to (c, w/2-100,y);
- cairo_line_to (c, w/2+100,y);
- cairo_stroke(c);
- y+=32;
-
- cairo_matrix_init_scale (&ma, 12.,13.);
- cairo_set_font_matrix (c,&ma);
- render_text_centered(c,"gPlanarity written by Monty <monty at xiph.org>",w/2,y);y+=17;
- render_text_centered(c,"as a demonstration of Gtk+/Cairo",w/2,y);y+=32;
-
- render_text_centered(c,"Original Flash version of Planarity by",w/2,y);y+=17;
- render_text_centered(c,"John Tantalo <john.tantalo at case.edu>",w/2,y);y+=32;
-
- render_text_centered(c,"Original game concept by Mary Radcliffe",w/2,y);y+=17;
-
-
- y = h/2+ABOUTBOX_HEIGHT/2-SCOREHEIGHT/2;
- cairo_select_font_face (c, "Sans",
- CAIRO_FONT_SLANT_NORMAL,
- CAIRO_FONT_WEIGHT_BOLD);
-
- cairo_matrix_init_scale (&ma, 10.,11.);
- cairo_set_font_matrix (c,&ma);
- render_text_centered(c,version, w/2,y);
-
- }
-
- cairo_destroy(c);
-}
-
-static void about_game_post_undeploy(Gameboard *g){
- // set up new buttons
- setup_pause_buttons(g,ABOUTBOX_WIDTH,ABOUTBOX_HEIGHT);
-
- // draw about box
- push_curtain(g,draw_aboutbox);
-
- // deploy new buttons
- callback=0;
- timer = g_timeout_add(BUTTON_ANIM_INTERVAL, pause_animate_buttons, (gpointer)g);
- buttons_ready=1;
-}
-
-void about_game(Gameboard *g){
- // grab timer state
- ui_about=1;
- pause();
- push_background(g,0);
-
- // undeploy buttonbar
- undeploy_buttonbar(g,about_game_post_undeploy);
-}
-
-int pause_dialog_active(){
- return ui_paused;
-}
-
-int about_dialog_active(){
- return ui_about;
-}
Deleted: trunk/planarity/pause.h
===================================================================
--- trunk/planarity/pause.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/pause.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,13 +0,0 @@
-#define PAUSE_BUTTON_BORDER 35
-#define PAUSE_BUTTON_Y 25
-#define PAUSEBOX_WIDTH 180
-#define PAUSEBOX_HEIGHT 250
-
-#define ABOUTBOX_WIDTH 320
-#define ABOUTBOX_HEIGHT 400
-
-extern void pause_game(Gameboard *g);
-extern void about_game(Gameboard *g);
-
-extern int pause_dialog_active();
-extern int about_dialog_active();
Added: trunk/planarity/timer.c
===================================================================
--- trunk/planarity/timer.c 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/timer.c 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,52 @@
+#include <time.h>
+#include "timer.h"
+
+static int paused;
+static time_t begin_time_add;
+static time_t begin_time;
+static char timebuffer[160];
+
+time_t get_timer(){
+ if(paused)
+ return begin_time_add;
+ else{
+ time_t ret = time(NULL);
+ return ret - begin_time + begin_time_add;
+ }
+}
+
+char *get_timer_string(){
+ int ho = get_timer() / 3600;
+ int mi = get_timer() / 60 - ho*60;
+ int se = get_timer() - ho*3600 - mi*60;
+
+ if(ho){
+ snprintf(timebuffer,160,"%d:%02d:%02d",ho,mi,se);
+ }else if (mi){
+ snprintf(timebuffer,160,"%d:%02d",mi,se);
+ }else{
+ snprintf(timebuffer,160,"%d seconds",se);
+ }
+
+ return timebuffer;
+}
+
+void set_timer(time_t off){
+ begin_time_add = off;
+ begin_time = time(NULL);
+}
+
+void pause_timer(){
+ begin_time_add = get_timer();
+ paused=1;
+}
+
+void unpause_timer(){
+ paused=0;
+ set_timer(begin_time_add);
+}
+
+int timer_paused_p(){
+ return paused;
+}
+
Added: trunk/planarity/timer.h
===================================================================
--- trunk/planarity/timer.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/timer.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -0,0 +1,12 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+extern time_t get_timer();
+extern char *get_timer_string();
+extern void set_timer(time_t off);
+extern void pause_timer();
+extern void unpause_timer();
+extern int timer_paused_p();
+
Modified: trunk/planarity/version.h
===================================================================
--- trunk/planarity/version.h 2005-09-24 22:02:43 UTC (rev 10059)
+++ trunk/planarity/version.h 2005-09-25 09:24:23 UTC (rev 10060)
@@ -1,2 +1,2 @@
#define VERSION "$Id$ "
-/* DO NOT EDIT: Automated versioning hack [Fri Aug 19 22:20:08 EDT 2005] */
+/* DO NOT EDIT: Automated versioning hack [Sun Sep 25 05:19:27 EDT 2005] */
More information about the commits
mailing list