From 74a4e547b35f162350dcf205aa453fd32820d249 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 11 May 2004 17:44:30 +0000 Subject: [PATCH] Framework alteration: we now support a `game_ui' structure in addition to the `game_state'. The new structure is intended to contain ephemeral data pertaining to the game's user interface rather than the actual game: things stored in the UI structure are not restored in an Undo, for example. make_move() is passed the UI to modify as it wishes; it is now allowed to return the _same_ game_state it was passed, to indicate that although no move has been made there has been a UI operation requiring a redraw. git-svn-id: svn://svn.tartarus.org/sgt/puzzles@4207 cda61777-01e9-0310-a592-d414129be87e --- cube.c | 14 ++++++++++++-- fifteen.c | 14 ++++++++++++-- gtk.c | 41 +++++++++++++++++++++++++++++++++++++++-- midend.c | 27 ++++++++++++++++++++++----- net.c | 13 +++++++++++-- nullgame.c | 14 ++++++++++++-- puzzles.h | 14 ++++++++++++-- rect.c | 14 ++++++++++++-- sixteen.c | 14 ++++++++++++-- windows.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 10 files changed, 188 insertions(+), 22 deletions(-) diff --git a/cube.c b/cube.c index 5e0b449..2ce7a4f 100644 --- a/cube.c +++ b/cube.c @@ -950,7 +950,16 @@ void free_game(game_state *state) sfree(state); } -game_state *make_move(game_state *from, int x, int y, int button) +game_ui *new_ui(game_state *state) +{ + return NULL; +} + +void free_ui(game_ui *ui) +{ +} + +game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button) { int direction; int pkey[2], skey[2], dkey[2]; @@ -1309,7 +1318,8 @@ void game_free_drawstate(game_drawstate *ds) } void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *state, float animtime, float flashtime) + game_state *state, game_ui *ui, + float animtime, float flashtime) { int i, j; struct bbox bb = find_bbox(&state->params); diff --git a/fifteen.c b/fifteen.c index de5a340..78060f5 100644 --- a/fifteen.c +++ b/fifteen.c @@ -349,7 +349,16 @@ void free_game(game_state *state) sfree(state); } -game_state *make_move(game_state *from, int x, int y, int button) +game_ui *new_ui(game_state *state) +{ + return NULL; +} + +void free_ui(game_ui *ui) +{ +} + +game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button) { int gx, gy, dx, dy, ux, uy, up, p; game_state *ret; @@ -519,7 +528,8 @@ static void draw_tile(frontend *fe, game_state *state, int x, int y, } void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *state, float animtime, float flashtime) + game_state *state, game_ui *ui, + float animtime, float flashtime) { int i, pass, bgcolour; diff --git a/gtk.c b/gtk.c index 87f1151..3e7fe4d 100644 --- a/gtk.c +++ b/gtk.c @@ -283,7 +283,7 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event, if (!fe->pixmap) return TRUE; - if (event->type != GDK_BUTTON_PRESS) + if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) return TRUE; if (event->button == 2 || (event->state & GDK_SHIFT_MASK)) @@ -295,6 +295,36 @@ static gint button_event(GtkWidget *widget, GdkEventButton *event, else return FALSE; /* don't even know what button! */ + if (event->type == GDK_BUTTON_RELEASE) + button += LEFT_RELEASE - LEFT_BUTTON; + + if (!midend_process_key(fe->me, event->x, event->y, button)) + gtk_widget_destroy(fe->window); + + return TRUE; +} + +static gint motion_event(GtkWidget *widget, GdkEventMotion *event, + gpointer data) +{ + frontend *fe = (frontend *)data; + int button; + + if (!fe->pixmap) + return TRUE; + + if (event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) + return TRUE; + + if (event->state & (GDK_BUTTON2_MASK | GDK_SHIFT_MASK)) + button = MIDDLE_DRAG; + else if (event->state & GDK_BUTTON1_MASK) + button = LEFT_DRAG; + else if (event->state & GDK_BUTTON3_MASK) + button = RIGHT_DRAG; + else + return FALSE; /* don't even know what button! */ + if (!midend_process_key(fe->me, event->x, event->y, button)) gtk_widget_destroy(fe->window); @@ -893,6 +923,10 @@ static frontend *new_window(void) GTK_SIGNAL_FUNC(key_event), fe); gtk_signal_connect(GTK_OBJECT(fe->area), "button_press_event", GTK_SIGNAL_FUNC(button_event), fe); + gtk_signal_connect(GTK_OBJECT(fe->area), "button_release_event", + GTK_SIGNAL_FUNC(button_event), fe); + gtk_signal_connect(GTK_OBJECT(fe->area), "motion_notify_event", + GTK_SIGNAL_FUNC(motion_event), fe); gtk_signal_connect(GTK_OBJECT(fe->area), "expose_event", GTK_SIGNAL_FUNC(expose_area), fe); gtk_signal_connect(GTK_OBJECT(fe->window), "map_event", @@ -900,7 +934,10 @@ static frontend *new_window(void) gtk_signal_connect(GTK_OBJECT(fe->area), "configure_event", GTK_SIGNAL_FUNC(configure_area), fe); - gtk_widget_add_events(GTK_WIDGET(fe->area), GDK_BUTTON_PRESS_MASK); + gtk_widget_add_events(GTK_WIDGET(fe->area), + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_BUTTON_MOTION_MASK); gtk_widget_show(fe->area); gtk_widget_show(fe->window); diff --git a/midend.c b/midend.c index cacd66e..a2aee45 100644 --- a/midend.c +++ b/midend.c @@ -27,6 +27,7 @@ struct midend_data { game_state **states; game_drawstate *drawstate; game_state *oldstate; + game_ui *ui; float anim_time, anim_pos; float flash_time, flash_pos; }; @@ -56,6 +57,7 @@ midend_data *midend_new(frontend *fe, void *randseed, int randseedsize) me->npresets = me->presetsize = 0; me->anim_time = me->anim_pos = 0.0F; me->flash_time = me->flash_pos = 0.0F; + me->ui = NULL; return me; } @@ -99,6 +101,9 @@ void midend_new_game(midend_data *me) me->states[me->nstates++] = new_game(me->params, me->seed); me->statepos = 1; me->drawstate = game_new_drawstate(me->states[0]); + if (me->ui) + free_ui(me->ui); + me->ui = new_ui(me->states[0]); } void midend_restart_game(midend_data *me) @@ -106,6 +111,8 @@ void midend_restart_game(midend_data *me) while (me->nstates > 1) free_game(me->states[--me->nstates]); me->statepos = me->nstates; + free_ui(me->ui); + me->ui = new_ui(me->states[0]); } static int midend_undo(midend_data *me) @@ -180,9 +187,18 @@ int midend_process_key(midend_data *me, int x, int y, int button) free_game(oldstate); return 0; } else { - game_state *s = make_move(me->states[me->statepos-1], x, y, button); - - if (s) { + game_state *s = make_move(me->states[me->statepos-1], me->ui, + x, y, button); + + if (s == me->states[me->statepos-1]) { + /* + * make_move() is allowed to return its input state to + * indicate that although no move has been made, the UI + * state has been updated and a redraw is called for. + */ + midend_redraw(me); + return 1; + } else if (s) { while (me->nstates > me->statepos) free_game(me->states[--me->nstates]); ensure(me); @@ -222,11 +238,12 @@ void midend_redraw(midend_data *me) if (me->oldstate && me->anim_time > 0 && me->anim_pos < me->anim_time) { game_redraw(me->frontend, me->drawstate, me->oldstate, - me->states[me->statepos-1], me->anim_pos, + me->states[me->statepos-1], me->ui, me->anim_pos, me->flash_pos); } else { game_redraw(me->frontend, me->drawstate, NULL, - me->states[me->statepos-1], 0.0, me->flash_pos); + me->states[me->statepos-1], me->ui, 0.0, + me->flash_pos); } end_draw(me->frontend); } diff --git a/net.c b/net.c index 0774de3..616609f 100644 --- a/net.c +++ b/net.c @@ -724,10 +724,19 @@ static unsigned char *compute_active(game_state *state) return active; } +game_ui *new_ui(game_state *state) +{ + return NULL; +} + +void free_ui(game_ui *ui) +{ +} + /* ---------------------------------------------------------------------- * Process a move. */ -game_state *make_move(game_state *state, int x, int y, int button) +game_state *make_move(game_state *state, game_ui *ui, int x, int y, int button) { game_state *ret; int tx, ty, orig; @@ -1141,7 +1150,7 @@ static void draw_tile(frontend *fe, game_state *state, int x, int y, int tile, } void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *state, float t, float ft) + game_state *state, game_ui *ui, float t, float ft) { int x, y, tx, ty, frame; unsigned char *active; diff --git a/nullgame.c b/nullgame.c index 8df09e9..b4b94fe 100644 --- a/nullgame.c +++ b/nullgame.c @@ -109,7 +109,16 @@ void free_game(game_state *state) sfree(state); } -game_state *make_move(game_state *from, int x, int y, int button) +game_ui *new_ui(game_state *state) +{ + return NULL; +} + +void free_ui(game_ui *ui) +{ +} + +game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button) { return NULL; } @@ -152,7 +161,8 @@ void game_free_drawstate(game_drawstate *ds) } void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *state, float animtime, float flashtime) + game_state *state, game_ui *ui, + float animtime, float flashtime) { } diff --git a/puzzles.h b/puzzles.h index b7d2804..46c0f15 100644 --- a/puzzles.h +++ b/puzzles.h @@ -18,6 +18,12 @@ enum { LEFT_BUTTON = 0x1000, MIDDLE_BUTTON, RIGHT_BUTTON, + LEFT_DRAG, + MIDDLE_DRAG, + RIGHT_DRAG, + LEFT_RELEASE, + MIDDLE_RELEASE, + RIGHT_RELEASE, CURSOR_UP, CURSOR_DOWN, CURSOR_LEFT, @@ -36,6 +42,7 @@ typedef struct midend_data midend_data; typedef struct random_state random_state; typedef struct game_params game_params; typedef struct game_state game_state; +typedef struct game_ui game_ui; typedef struct game_drawstate game_drawstate; #define ALIGN_VNORMAL 0x000 @@ -165,13 +172,16 @@ char *validate_seed(game_params *params, char *seed); game_state *new_game(game_params *params, char *seed); game_state *dup_game(game_state *state); void free_game(game_state *state); -game_state *make_move(game_state *from, int x, int y, int button); +game_ui *new_ui(game_state *state); +void free_ui(game_ui *ui); +game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button); void game_size(game_params *params, int *x, int *y); float *game_colours(frontend *fe, game_state *state, int *ncolours); game_drawstate *game_new_drawstate(game_state *state); void game_free_drawstate(game_drawstate *ds); void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *newstate, float anim_time, float flash_time); + game_state *newstate, game_ui *ui, float anim_time, + float flash_time); float game_anim_length(game_state *oldstate, game_state *newstate); float game_flash_length(game_state *oldstate, game_state *newstate); int game_wants_statusbar(void); diff --git a/rect.c b/rect.c index 87e86bf..d7d1319 100644 --- a/rect.c +++ b/rect.c @@ -857,7 +857,16 @@ static unsigned char *get_correct(game_state *state) return ret; } -game_state *make_move(game_state *from, int x, int y, int button) +game_ui *new_ui(game_state *state) +{ + return NULL; +} + +void free_ui(game_ui *ui) +{ +} + +game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button) { float xf, yf, dx, dy; int hxr, hyr, vxr, vyr; @@ -1005,7 +1014,8 @@ void draw_tile(frontend *fe, game_state *state, int x, int y, int correct) } void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *state, float animtime, float flashtime) + game_state *state, game_ui *ui, + float animtime, float flashtime) { int x, y; unsigned char *correct; diff --git a/sixteen.c b/sixteen.c index 1b0b4ea..cce11d9 100644 --- a/sixteen.c +++ b/sixteen.c @@ -358,7 +358,16 @@ void free_game(game_state *state) sfree(state); } -game_state *make_move(game_state *from, int x, int y, int button) +game_ui *new_ui(game_state *state) +{ + return NULL; +} + +void free_ui(game_ui *ui) +{ +} + +game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button) { int cx, cy; int dx, dy, tx, ty, n; @@ -534,7 +543,8 @@ static void draw_arrow(frontend *fe, int x, int y, int xdx, int xdy) } void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *state, float animtime, float flashtime) + game_state *state, game_ui *ui, + float animtime, float flashtime) { int i, bgcolour; diff --git a/windows.c b/windows.c index 4213e4c..7689993 100644 --- a/windows.c +++ b/windows.c @@ -939,7 +939,50 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, button = LEFT_BUTTON; else button = RIGHT_BUTTON; - + + if (!midend_process_key(fe->me, LOWORD(lParam), + HIWORD(lParam), button)) + PostQuitMessage(0); + + SetCapture(hwnd); + } + break; + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + { + int button; + + /* + * Shift-clicks count as middle-clicks, since otherwise + * two-button Windows users won't have any kind of + * middle click to use. + */ + if (message == WM_MBUTTONUP || (wParam & MK_SHIFT)) + button = MIDDLE_RELEASE; + else if (message == WM_LBUTTONUP) + button = LEFT_RELEASE; + else + button = RIGHT_RELEASE; + + if (!midend_process_key(fe->me, LOWORD(lParam), + HIWORD(lParam), button)) + PostQuitMessage(0); + + ReleaseCapture(); + } + break; + case WM_MOUSEMOVE: + { + int button; + + if (wParam & (MK_MBUTTON | MK_SHIFT)) + button = MIDDLE_DRAG; + else if (wParam & MK_LBUTTON) + button = LEFT_DRAG; + else + button = RIGHT_DRAG; + if (!midend_process_key(fe->me, LOWORD(lParam), HIWORD(lParam), button)) PostQuitMessage(0); -- 2.11.0