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