Logo Search packages:      
Sourcecode: papaya version File versions  Download package

BSXSceneGTK.cpp

#include <gtk/gtk.h>
#include "BSXSceneGTK.h"

BSXSceneGTK::BSXSceneGTK() {
  window = NULL;
  buffer = NULL;
  drawing_area = NULL;
}

BSXSceneGTK::~BSXSceneGTK() {
  if (window) {
    gtk_widget_hide(window);
    gtk_widget_destroy(window);
  }

  gdk_pixmap_unref(buffer);
}

void bsx_gtk_expose_event(GtkWidget * widget, GdkEvent * event, gpointer data) {
  BSXSceneGTK * scene = (BSXSceneGTK *)data;
  scene->expose();
}

void BSXSceneGTK::redraw() {

  if (!window) {
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "BSX Graphics Window");
    gtk_widget_show(window);
  }

  if (!buffer) {
    buffer = gdk_pixmap_new(window->window, 512, 256, -1);
    gdk_pixmap_ref(buffer);
  }

  if (!drawing_area) {
    drawing_area = gtk_drawing_area_new();
#ifdef USE_GTK_2
    gtk_widget_set_size_request(GTK_WIDGET(drawing_area), 512, 256);
#else
    gtk_drawing_area_size(GTK_DRAWING_AREA(drawing_area), 512, 256);
#endif
    gtk_container_add(GTK_CONTAINER(window), drawing_area);
    gtk_widget_show(drawing_area);

#ifdef USE_GTK_2
    g_signal_connect_data(G_OBJECT(drawing_area), "expose_event",
                    G_CALLBACK(bsx_gtk_expose_event), this,
                    NULL, (GConnectFlags)0);
#else
    gtk_signal_connect(GTK_OBJECT(drawing_area), "expose_event",
                   GTK_SIGNAL_FUNC(bsx_gtk_expose_event), this);
#endif
  }

  // Assign a graphics context.
  GdkGC * gc = gdk_gc_new(drawing_area->window);
  gdk_gc_copy(gc, drawing_area->style->white_gc);

  // Erase the contents of the offscreen pixmap.
  gdk_draw_rectangle(buffer, gc, true, 0, 0, 512, 256);

  // Draw the scene.
  if (getScene())
    drawObject(gc, getScene()->data, false);

  // Draw the objects.
  for (ObjectList::iterator i = objects.begin();
       i != objects.end();
       ++i) {
    BSXObject * object = (*i);
    if (object && object->entry && object->entry->data)
      drawObject(gc, object->entry->data, object->x, object->y, true);
  }
  // Transfer the pixmap to the drawing area.
  gdk_draw_pixmap(drawing_area->window, gc, buffer, 0, 0, 0, 0, drawing_area->allocation.width, drawing_area->allocation.height);

  // @@ Free the GC?
  gdk_gc_destroy(gc);

}

void BSXSceneGTK::expose() {
  GdkGC * gc = gdk_gc_new(drawing_area->window);
  if (drawing_area) {
    gdk_draw_pixmap(drawing_area->window, gc, buffer, 0, 0, 0, 0, 512, 256);
  }
}

int popHexValue(char * in) {
  char buf[3];
  int result = 0;

  buf[0] = in[0];
  buf[1] = in[1];
  buf[2] = '\0';

  sscanf(buf, "%x", &result);

  return result;
}

void BSXSceneGTK::drawObject(GdkGC * gc, char * data, bool object) {
  drawObject(gc, data, 0, 0, object);
}

void BSXSceneGTK::drawObject(GdkGC * gc, char * data, uint8_t x, uint8_t y, bool object) {

  // parse the data string and draw the object.

  int poly_count = 0;
  int current_poly = 0;

  if (!data)
    return;

  if (*data == '\0' || *(data + 1) == '\0')
    return;

  poly_count = popHexValue(data);
  data++;
  data++;

  for (current_poly = 0; current_poly < poly_count; current_poly++) {
    data = drawPolygon(gc, data, x, y, object);
  }


}

struct bsx_colour_entry {
  int index;
  uint16_t r;
  uint16_t g;
  uint16_t b;
};
//black, blue, forestgreen, skyblue, indianred, hotpink, brown, lightgrey, dimgrey, deepskyblue, green, cyan, tomato, magenta, yellow and white.

struct bsx_colour_entry bsx_colour_table[] = {
  { 0, 0x0000, 0x0000, 0x0000 },
  { 1, 0x0000, 0x0000, 0xffff },
  { 2, 0x2300, 0x8e00, 0x2300 },
  { 3, 0x3200, 0x9900, 0xcc00 },
  { 4, 0x4f00, 0x2f00, 0x2f00 },
  { 5, 0xbc00, 0x8f00, 0x8f00 }, // Should be hot pink
  { 6, 0xa500, 0x2a00, 0x2a00 },
  { 7, 0xa800, 0xa800, 0xa800 },
  { 8, 0x5400, 0x5400, 0x5400 },
  { 9, 0x5f00, 0x9f00, 0x9f00 }, // should be deep sky blue
  { 10, 0x0000, 0xffff, 0x0000 },
  { 11, 0x0000, 0xffff, 0xffff },
  { 12, 0xffff, 0x0000, 0x0000 }, // should be tomato
  { 13, 0xffff, 0x0000, 0xffff },
  { 14, 0xffff, 0xffff, 0x0000 },
  { 15, 0xffff, 0xffff, 0xffff }
};

void setColour(GdkColor * colour, int c) {
  colour->red = bsx_colour_table[c].r;
  colour->green = bsx_colour_table[c].g;
  colour->blue = bsx_colour_table[c].b;
}

char * BSXSceneGTK::drawPolygon(GdkGC * gc, char * data, uint8_t x, uint8_t y, bool object) {

  int vertex_count = 0;
  int colour = 0;
  int current_vertex = 0;

  GdkPoint * points;

  float xscale = (float)drawing_area->allocation.width / 256.0;
  float yscale = (float)drawing_area->allocation.height / 256.0;

  xscale = 2.0;
  yscale = 1.0;
  
  if (*data == '\0' || *(data + 1) == '\0')
    return data;
  vertex_count = popHexValue(data);
  data++;
  data++;
  if (*data == '\0' || *(data + 1) == '\0')
    return data;
  colour = popHexValue(data);
  data++;
  data++;

  // Set the GC colour accordingly.

  GdkColor current_colour = {0x0000, 0x0000, 0x0000, 0x0000};
  setColour(&current_colour, colour);

  gdk_color_alloc(gdk_colormap_get_system(), &current_colour);
  gdk_gc_set_foreground(gc, &current_colour);

  points = (GdkPoint *) malloc(sizeof(GdkPoint) * vertex_count);

  for (current_vertex = 0; current_vertex < vertex_count; current_vertex++) {
    int cx, cy;

    if (*data  == '\0' || *(data + 1) == '\0')
      return data;
    cx = popHexValue(data);
    data += 2;

    if (*data  == '\0' || *(data + 1) == '\0')
      return data;
    cy = popHexValue(data);
    data += 2;

    if (object) {
      cx *= 2; // stretch to fit horizontal size
      cx -= 256; // shift 256 pixels for no apparent reason
      cx = 32 * x + cx; // shift right 32 pixels for each offset value
      
      cy = 384 - cy; // shift down 384 pixels
      cy = -4 * y + cy; // shift up offset pixels
    }
    else {
      cy = (int)yscale * (256 - cy);
      cx = (int)xscale * cx;
    }

    points[current_vertex].x = (gint16)(cx);
    points[current_vertex].y = (gint16)(cy);

  }

  gdk_draw_polygon(buffer, gc, true, points, vertex_count);

  return data;
}


Generated by  Doxygen 1.6.0   Back to index