06ba5e51399375b89bef3035827d1cba31047536
[familia.git] / src / ui / drawing_area.c
1 #include <gtk/gtk.h>
2 #include <gtk/gtkgl.h>
3 #include <GL/gl.h>
4 #include <GL/glu.h>
5 #include <assert.h>
6
7 #include "../debug.h"
8 #include "drawing_area.h"
9 #include "../math/3d.h"
10 #include "../graphics/constants.h"
11 #include "../graphics/individual.h"
12 #include "../graphics/family.h"
13 #include "../storage/storage.h"
14
15 extern GLdouble camera_pos_x;
16 extern GLdouble camera_pos_y;
17 extern GLdouble camera_pos_z;
18
19 GtkDrawingArea * drawing_area = NULL;
20
21 /**
22  * The "draw" signal handler. All the OpenGL re-drawing should
23  * be done here. This is repeatedly called as the painting routine
24  * every time the 'draw' event is signalled.
25  */
26 gboolean drawing_area_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
27 {
28         unsigned int i;
29         unsigned int individuals_no;
30         unsigned int families_no;
31         struct familia_storage * storage;
32         struct position * pos;
33
34         /*** OpenGL BEGIN ***/
35         if (!gtk_widget_begin_gl (widget)) {
36                 return FALSE;
37         }
38
39         glMatrixMode (GL_MODELVIEW);
40         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
41         glLoadIdentity ();
42
43         gluLookAt (camera_pos_x, camera_pos_y, camera_pos_z, 0.0, 0.0, -100.0, 0.0, 1.0, 0.0);
44
45         storage = familia_storage_get_current();
46         individuals_no = storage->individuals_no;
47
48         for (i = 0; i < individuals_no; i++) {
49                 pos = calculate_individual_position(storage->individuals[i]);
50
51         glPushMatrix ();
52                 glTranslatef(
53                         (pos != NULL) ? pos->x : 0,
54                         (pos != NULL) ? pos->y : 0,
55                         (pos != NULL) ? pos->z : -10
56                 );
57                 glColor3f (1.0, 1.0, 1.0);
58                 graphics_render_individual();
59         glPopMatrix ();
60
61                 if (pos != NULL) {
62                         free(pos);
63                         pos = NULL;
64                 }
65         }
66
67         families_no = storage->families_no;
68
69         for (i = 0; i < families_no; i++) {
70         glPushMatrix ();
71                 glTranslatef(i * (GR_FAM_RADIUS + 1), -3, -10);
72                 glColor3f (1.0, 1.0, 1.0);
73                 graphics_render_family();
74         glPopMatrix ();
75         }
76
77         gtk_widget_end_gl (widget, TRUE);
78         /*** OpenGL END ***/
79
80         return TRUE;
81 }
82
83 /**
84  * The "configure_event" signal handler. Any processing required when
85  * the OpenGL-capable drawing area is re-configured should be done here.
86  * Almost always it will be used to resize the OpenGL viewport when
87  * the window is resized.
88  */
89 gboolean drawing_area_configure_event (GtkWidget *widget,
90                                         GdkEventConfigure *event, gpointer data)
91 {
92         GtkAllocation allocation;
93
94         /* OpenGL widget width */
95         GLfloat w;
96         /* OpenGL widget height */
97         GLfloat h;
98         /* Aspect ratio */
99         GLfloat aspect = 0;
100
101         gtk_widget_get_allocation (widget, &allocation);
102         w = allocation.width;
103         h = allocation.height;
104
105         aspect = w / h;
106         /*** OpenGL BEGIN ***/
107         if (!gtk_widget_begin_gl (widget))
108                 return FALSE;
109
110         glViewport (0, 0, w, h);
111
112         glMatrixMode (GL_PROJECTION);
113         glLoadIdentity ();
114         gluPerspective (60.0, aspect, 0.1, 60.0);
115         glMatrixMode(GL_MODELVIEW);
116
117         gtk_widget_end_gl (widget, FALSE);
118         /*** OpenGL END ***/
119
120         return TRUE;
121 }
122
123 /**
124  * The "realize" signal handler. All the OpenGL initialization
125  * should be performed here, such as default background colour,
126  * certain states etc.
127  */
128 void drawing_area_realize (GtkWidget *widget, gpointer data)
129 {
130         /*** OpenGL BEGIN ***/
131         if (!gtk_widget_begin_gl (widget)) {
132                 return;
133         }
134
135         glClearColor (0.0, 0.0, 0.0, 0.0);
136         glShadeModel (GL_FLAT);
137
138         gtk_widget_end_gl (widget, FALSE);
139         /*** OpenGL END ***/
140
141         return;
142 }
143
144 /**
145  * The "unrealize" signal handler. Any processing required when
146  * the OpenGL-capable window is unrealized should be done here.
147  */
148 void drawing_area_unrealize (GtkWidget *widget, gpointer data)
149 {
150         /* Code */
151 }
152
153 /**
154  * The "scroll-event" signal handler. Responsible for correctly scrolling
155  * drawing area.
156  */
157 void drawing_area_event_scroll (GtkWidget *widget,
158                                 GdkEventScroll *event, gpointer user_data)
159 {
160         assert(event->type == GDK_SCROLL);
161
162         switch(event->direction) {
163                 case GDK_SCROLL_UP:
164                         camera_pos_y++;
165                         gtk_widget_queue_draw(widget);
166                         break;
167                 case GDK_SCROLL_DOWN:
168                         camera_pos_y--;
169                         gtk_widget_queue_draw(widget);
170                         break;
171         }
172 }