]> git.cworth.org Git - grrobot/blobdiff - src/grr_board_view.c
Update to 2020
[grrobot] / src / grr_board_view.c
index a03a708e9a152b01231ca785993bb03a7fc9bf57..ca1d0e1414334b9192a4c802733af6f4cc951ea1 100644 (file)
@@ -1,6 +1,6 @@
 /* grr_board_view - GTK+ widget for displaying an rr_board
  *
- * Copyright © 2003 Carl Worth
+ * Copyright Â© 2003 Carl Worth
  *
  * Permission to use, copy, modify, distribute, and sell this software
  * and its documentation for any purpose is hereby granted without
@@ -30,7 +30,9 @@
 #include <string.h>
 
 #include <cairo.h>
-#include <xsvg.h>
+#include <cairo-xlib.h>
+#include <librsvg/rsvg.h>
+#include <librsvg/rsvg-cairo.h>
 
 #include <gtk/gtkmain.h>
 #include <gtk/gtksignal.h>
@@ -130,12 +132,17 @@ grr_board_view_init (grr_board_view_t *view)
     view->client = NULL;
     
     view->button = 0;
+
+    view->time = 60.0;
+    view->drift_correct = 0.0;
     view->timer = 0;
+    view->zap_time = 0.0;
 
     view->cell_width = 0;
     view->cell_height = 0;
 
-    view->cell_icon = grr_icon_create ("cell");
+    view->cell1_icon = grr_icon_create ("cell1");
+    view->cell2_icon = grr_icon_create ("cell2");
     view->wall_icon = grr_icon_create ("wall");
 
     for (i=0; i < RR_NUM_ROBOTS; i++) {
@@ -332,6 +339,8 @@ grr_board_view_expose (GtkWidget      *widget,
     rr_board_t *board;
     Display *dpy;
     Drawable drawable;
+    Visual *visual;
+    cairo_surface_t *surface;
     cairo_t *xrs;
     GdkDrawable *real_drawable;
     gint x_off, y_off;
@@ -346,14 +355,7 @@ grr_board_view_expose (GtkWidget      *widget,
     view = GRR_BOARD_VIEW (widget);
     board = view->board;
 
-    /* Unabstract X from GTK+ */
-    gdk_window_get_internal_paint_info (widget->window, &real_drawable, &x_off, &y_off);
-    dpy = gdk_x11_drawable_get_xdisplay (real_drawable);
-    drawable = gdk_x11_drawable_get_xid (real_drawable);
-
-    /* Ignore GTK+ and use Cairo for drawing. */
-    xrs = cairo_create ();
-    cairo_set_target_drawable (xrs, dpy, drawable);
+    xrs = gdk_cairo_create (widget->window);
 
     new_cell_width = widget->allocation.width / view->board_width;
     if (new_cell_width == 0)
@@ -376,7 +378,9 @@ grr_board_view_expose (GtkWidget      *widget,
                 view->cell_width / GRR_SVG_ASSUMED_WIDTH,
                 view->cell_height / GRR_SVG_ASSUMED_HEIGHT);
 
-       grr_icon_predraw (view->cell_icon, xrs,
+       grr_icon_predraw (view->cell1_icon, xrs,
+                         view->cell_width, view->cell_height);
+       grr_icon_predraw (view->cell2_icon, xrs,
                          view->cell_width, view->cell_height);
 
        grr_icon_predraw (view->wall_icon, xrs,
@@ -440,21 +444,19 @@ grr_board_view_expose (GtkWidget      *widget,
            cairo_save (xrs);
            cairo_translate (xrs, i * view->cell_width, j * view->cell_height);
 
-           grr_icon_draw_predrawn (view->cell_icon, xrs);
+           if ((i+j) % 2 == 0)
+               grr_icon_draw_predrawn (view->cell1_icon, xrs, 1.0);
+           else
+               grr_icon_draw_predrawn (view->cell2_icon, xrs, 1.0);
 
-           if (target) {
-               if (target && target != goal_target) {
-                   cairo_save (xrs);
-                   cairo_set_alpha (xrs, 0.25);
-                   grr_icon_draw_predrawn (view->target_icon[rr_target_idx (target)], xrs);
-                   cairo_restore (xrs);
-               } else {
-                   grr_icon_draw_predrawn (view->target_icon[rr_target_idx (target)], xrs);
-               }
-           }
+           if (target)
+               grr_icon_draw_predrawn (view->target_icon[rr_target_idx (target)],
+                                       xrs,
+                                       target == goal_target ? 1.0 : 0.25);
 
            if (robot)
-               grr_icon_draw_predrawn (view->robot_icon[rr_robot_idx (robot)], xrs);
+               grr_icon_draw_predrawn (view->robot_icon[rr_robot_idx (robot)],
+                                       xrs, 1.0);
 
            cairo_restore (xrs);
        }
@@ -470,8 +472,32 @@ grr_board_view_expose (GtkWidget      *widget,
        cairo_scale (xrs,
                     2 * view->cell_width / GRR_SVG_ASSUMED_WIDTH,
                     2 * view->cell_height / GRR_SVG_ASSUMED_HEIGHT);
+       cairo_rectangle (xrs, 0, 0, GRR_SVG_ASSUMED_WIDTH, GRR_SVG_ASSUMED_HEIGHT);
+       cairo_set_source_rgb (xrs, 1, 1, 1);
+       cairo_fill (xrs);
        grr_icon_draw (view->target_icon[rr_target_idx (goal_target)], xrs);
        cairo_restore (xrs);
+
+       /* Draw clock */
+       if (view->time < 60.0) {
+           cairo_save (xrs);
+           cairo_new_path (xrs);
+           cairo_move_to (xrs,
+                          (double) view->board_width / 2 * view->cell_width,
+                          (double) view->board_height / 2 * view->cell_height);
+           cairo_arc (xrs,
+                      (double) view->board_width / 2 * view->cell_width,
+                      (double) view->board_height / 2 * view->cell_height,
+                      .9 * view->cell_width,
+                      - M_PI_2,
+                      2 * M_PI * (60.0 - view->time) / 60.0 - M_PI_2);
+           cairo_close_path (xrs);
+
+           cairo_set_source_rgba (xrs, 0.0, 0.0, 0.0, 0.5);
+           cairo_fill (xrs);
+
+           cairo_restore (xrs);
+       }
     }
 
     /* Draw walls */
@@ -661,3 +687,96 @@ grr_board_view_mark_damage (grr_board_view_t *view, int i, int j)
     grr_board_view_transform_cell_to_pixel (view, i, j, &x, &y);
     gtk_widget_queue_draw_area (GTK_WIDGET (view), x, y, view->cell_width, view->cell_height);
 }
+
+#define TIMER_INTERVAL_MS 100.0
+
+static void
+grr_board_view_refresh_timer (grr_board_view_t *view)
+{
+    int x, y;
+
+    grr_board_view_transform_cell_to_pixel (view,
+                                           view->board_width / 2 - 1,
+                                           view->board_height / 2 -1,
+                                           &x, &y);
+    gtk_widget_queue_draw_area (GTK_WIDGET (view),
+                               x, y,
+                               2 * view->cell_width,
+                               2 * view->cell_height);
+}
+
+static gboolean
+grr_board_view_decrement_timer (void *widget)
+{
+    grr_board_view_t *view = widget;
+
+    view->time -= TIMER_INTERVAL_MS / 1000.0;
+    view->time += view->drift_correct;
+
+    if (view->zap_time) {
+       view->time -= view->zap_time;
+       view->zap_time += 1.0;
+    }
+
+    grr_board_view_refresh_timer (view);
+
+    if (view->time < 0) {
+       grr_board_view_stop_timer (view);
+       return FALSE;
+    }
+
+    return TRUE;
+}
+
+void
+grr_board_view_set_timer (grr_board_view_t *view, double time)
+{
+    /* XXX: It would be good to adjust the clock for latency somewhere... */
+    if (view->timer) {
+       double correction_time;
+       /* Correct any drift within the next 10 seconds, or half the
+          remaining time --- whichever is less. */
+       if (time >= 20.0)
+           correction_time = 10.0;
+       else
+           correction_time = time / 2.0;
+       view->drift_correct = (time - view->time) / (correction_time * TIMER_INTERVAL_MS);
+    } else {
+       view->time = time;
+       view->drift_correct = 0.0;
+       view->zap_time = 0.0;
+    }
+}
+
+void
+grr_board_view_start_timer (grr_board_view_t *view)
+{
+    if (view->timer)
+       return;
+
+    view->timer = gtk_timeout_add (TIMER_INTERVAL_MS, grr_board_view_decrement_timer, view);
+}
+
+void
+grr_board_view_stop_timer (grr_board_view_t *view)
+{
+    if (view->timer == 0)
+       return;
+
+    gtk_timeout_remove (view->timer);
+    view->timer = 0;
+    view->time = 0.0;
+    view->drift_correct = 0.0;
+    view->zap_time = 0.0;
+
+    grr_board_view_refresh_timer (view);
+}
+
+void
+grr_board_view_zap_timer (grr_board_view_t *view)
+{
+    view->zap_time = 4;
+
+    grr_board_view_refresh_timer (view);
+}
+