1 /* hf_creation_dialog.c - height field creation interface functions
2 *
3 * Copyright (C) 2001, 2006 Patrice St-Gelais
4 * patrstg@users.sourceforge.net
5 * http://geomorph.sourceforge.net
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include "hf_creation_dialog.h"
23 #include "render.h"
24 #include "hf.h"
25 #include "hf_wrapper.h"
26 #include "gl_preview.h"
27
28 #define NBSIZES 6
29 void size_callb (gpointer data,GtkWidget *wdg);
30
31 omenu_list_type sizes_list[NBSIZES] = {
32 {NULL,128,NULL,"128",size_callb},
33 {NULL,256,NULL,"256",size_callb},
34 {NULL,512,NULL,"512",size_callb},
35 {NULL,1024,NULL,"1024",size_callb},
36 {NULL,2048,NULL,"2048",size_callb},
37 {NULL,4096,NULL,"4096",size_callb},
38 };
39
40 // Toolbar icons for HF creation algorithm
41 #define NBHFTYPES 4
42 #include "../icons/uniform.xpm"
43 #include "../icons/subdiv1.xpm"
44 #include "../icons/subdiv2.xpm"
45 // #include "../icons/waves.xpm"
46 // #include "../icons/waves1.xpm"
47 #include "../icons/surfadd.xpm"
48
49 extern gchar* DEFAULT_TERRAIN;
50
51 command_item_struct hftypes[NBHFTYPES] = {
52 {"Type", "Uniform", "Uniform color",0, (gchar **) uniform_xpm, GDK_LEFT_PTR, hfuniform_callb, NULL, NULL,TRUE},
53 {"Type", "Subdiv1", "Subdivision 1",0, (gchar **) subdiv1_xpm, GDK_LEFT_PTR, hfsubdiv1_callb,NULL, NULL,FALSE},
54 {"Type", "Subdiv2", "Subdivision 2",0, (gchar **) subdiv2_xpm, GDK_LEFT_PTR, hfsubdiv2_callb, NULL, NULL,FALSE},
55 {"Type", "SurfSum", "Progressive sum of surfaces",0, (gchar **) surfadd_xpm, GDK_LEFT_PTR, hfsurfadd_callb, NULL, NULL,FALSE}
56 };
57
58 /***************************************************************************/
59
set_size_menu_from_size(gpointer hfo_ptr,gint size)60 void set_size_menu_from_size (gpointer hfo_ptr, gint size) {
61 hf_options_struct *hfo = (hf_options_struct *) hfo_ptr;
62 static gchar label[5];
63 if (hfo->creation_widgets && hfo->creation_widgets->size_menu) {
64 sprintf(label, "%-4u", (guint) size);
65 // printf("LABEL: %s\n",label);
66 set_option_menu_from_label (hfo->creation_widgets->size_menu->omenu_ptr, label);
67 }
68 }
69
size_callb(gpointer data,GtkWidget * wdg)70 void size_callb (gpointer data,GtkWidget *wdg) {
71 // Sets size when creating a new HF
72 gint hf_size;
73 static gchar area_label[12];
74 omenu_struct_type *opt_menu;
75 hf_wrapper_struct *hfw;
76 hf_options_struct *hfo;
77 opt_menu = (omenu_struct_type *) data;
78 // printf("DATA in SIZE_CALLB: %d;\n",data);
79 hfo = (hf_options_struct *) opt_menu->data;
80 // printf("HFO in SIZE_CALLB: %d;\n",hfo);
81 if (!hfo)
82 return;
83
84 hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
85
86 hf_size = opt_menu->list[opt_menu->current_index].num;
87 if (!hfw)
88 return;
89 if (!hfw->hf_struct)
90 return;
91 if (hf_size == hfw->hf_struct->max_x)
92 // No change!
93 return;
94
95 sprintf(area_label, "%d x %d", hf_size, hf_size);
96 gtk_frame_set_label(GTK_FRAME(hfw->draw_area_frame), area_label);
97
98 hf_free(hfw->hf_struct);
99 hfw->hf_options->hf_size = hf_size;
100 hfw->hf_struct = (hf_struct_type *) hf_new(hf_size);
101 hfw->display_scale = get_display_scale(hf_size);
102 hfw->hf_buf8 = (unsigned char *) x_malloc((RIGHT_SHIFT(hf_size, hfw->display_scale)) * (RIGHT_SHIFT(hf_size,hfw->display_scale))*sizeof(unsigned char), "unsigned char (hfw->buf8 in size_callb)");
103 hfw->if_rgb = FALSE;
104 hfw->area_size = RIGHT_SHIFT(hf_size,hfw->display_scale);
105 set_current_button (hfw->sbs, hfw->display_scale);
106 hfw->size_change_request = TRUE;
107
108 gtk_widget_set_size_request (hfw->draw_area_frame, hfw->area_size+SCALE_PAD, hfw->area_size+SCALE_PAD);
109
110 // printf("SIZE_CALLB: HFW: %d; HF_SIZE: %d; DISPLAY_SCALE: %d; AREA_SIZE: %d\n", hfw, hf_size, hfw->display_scale, hfw->area_size);
111
112 init_render_struct(hfw->hf_options->render_str,
113 hfw->dirname,
114 hfw->filename,
115 &hfw->creation_mode,
116 hfw->if_modified,
117 hfw->gl_preview,
118 hfw->hf_struct->hf_buf,
119 hfw->hf_struct->max_x,
120 hfw->hf_struct->max_y);
121
122 gl_set_input_grid (hfw->gl_preview, hfw->hf_struct->hf_buf, hfw->hf_struct->max_x, hfw->hf_struct->max_y, HF_TYPE_ID);
123 gl_update_details_display (hfw->gl_preview);
124 gtk_drawing_area_size(GTK_DRAWING_AREA(hfw->area),
125 hfw->area_size, hfw->area_size);
126 }
127
hf_types_toolbar_new(GtkWidget * window,GtkTooltips * tooltips,GtkWidget ** tb_widget,gpointer hf_options_ptr)128 GtkWidget *hf_types_toolbar_new(GtkWidget *window, GtkTooltips *tooltips,
129 GtkWidget** tb_widget, gpointer hf_options_ptr) {
130 GtkWidget *hbox;
131 GtkWidget *tb;
132 hbox = gtk_hbox_new(FALSE, 0);
133 gtk_widget_show(GTK_WIDGET(hbox));
134 define_label_in_box("Type", hbox, FALSE, FALSE, DEF_PAD*0.5);
135 tb = standard_toolbar_new(NBHFTYPES,
136 hftypes,
137 tooltips,
138 window,
139 hf_options_ptr,
140 GTK_ORIENTATION_HORIZONTAL,
141 GTK_TOOLBAR_ICONS,
142 TRUE);
143 gtk_box_pack_start(GTK_BOX(hbox), tb, FALSE, FALSE, DEF_PAD*0.5);
144 if (tb_widget)
145 *tb_widget = tb;
146 return hbox;
147 }
148
hf_creation_dialog_new(GtkWidget * window,GtkTooltips * tooltips,gpointer hf_options_ptr,gpointer widget_list_ptr)149 GtkWidget * hf_creation_dialog_new(GtkWidget *window, GtkTooltips *tooltips,
150 gpointer hf_options_ptr, gpointer widget_list_ptr) {
151 // Initializes the dialog for creating height fields
152 // Four parts, from top to bottom:
153 // 1. Kind / type of HF
154 // 2. Shape filters
155 // 3. Generic options (size...)
156 // 4. Options for the current HF
157 // Returns a vbox container, allowing to add / substract particular controls
158 // "window" only needed for heritance of characteristics in child toolbar(s)
159 // "tooltips" needed for packing tooltips, could have only one for the whole app.
160 // gpointer hf_options_ptr_pgtr: is normally the address of the current hf_options pointer
161 // (hf_options_struct **)
162
163 GtkWidget *dialog, *hbox, *vbox, *frame;
164 gint default_hf_size;
165 omenu_struct_type *opt_menu;
166 hf_creation_wdg_struct *wdg_str;
167 // printf("HFO PTR in HF_CREATION_DIALOG_NEW: %d - %x\n",hf_options_ptr, hf_options_ptr);
168 wdg_str = (hf_creation_wdg_struct *) x_calloc(sizeof(hf_creation_wdg_struct),1, "hf_creation_wdg_struct");
169 *((hf_creation_wdg_struct **) widget_list_ptr) = wdg_str;
170
171 ((hf_options_struct *)hf_options_ptr)->creation_widgets = wdg_str;
172
173 frame = options_frame_new("HeightField");
174
175 vbox = gtk_vbox_new(FALSE, 0);
176 gtk_widget_show(vbox);
177
178 // 1st generic option: HF size - a power of 2
179 // Default: some % of screen width
180
181 hbox = gtk_hbox_new(FALSE, DEF_PAD);
182 gtk_widget_show(hbox);
183 define_label_in_box("Size", hbox, FALSE, FALSE, DEF_PAD);
184
185 default_hf_size = hf_default_size();
186
187 create_omenu_with_callb_data (&opt_menu, sizes_list,
188 NBSIZES,
189 find_omenu_num(sizes_list, default_hf_size, NBSIZES),
190 hf_options_ptr);
191 gtk_box_pack_start(GTK_BOX(hbox), opt_menu->omenu_ptr, FALSE, FALSE, 0);
192
193 wdg_str->size_menu = opt_menu;
194
195 gtk_box_pack_start (GTK_BOX (hbox), create_render_bar (window, tooltips, ((hf_options_struct *)hf_options_ptr)->render_str), FALSE, FALSE, 0);
196
197 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
198
199 gtk_box_pack_start(GTK_BOX(vbox),
200 hf_types_toolbar_new(window, tooltips, &wdg_str->hf_types_toolbar,hf_options_ptr), FALSE, FALSE, 0);
201
202 // Other generic options ?
203
204 gtk_container_add(GTK_CONTAINER(frame), vbox);
205 dialog = gtk_vbox_new(FALSE,0);
206 gtk_box_pack_start(GTK_BOX(dialog), frame, FALSE, FALSE, 0);
207 gtk_widget_show(dialog);
208
209 return dialog;
210 }
211
hf_commit_creation(gpointer data)212 void hf_commit_creation (gpointer data) {
213 // Commit the filter
214 filter_dialog_struct *fds;
215 hf_wrapper_struct *hfw;
216 hfw = (hf_wrapper_struct *) data;
217 // printf("HFW, HFW->creation_mode in hf_commit_creation: %d, %d\n",data,hfw->creation_mode);
218 // printf("HFW->window->window: %d->%d\n",hfw->window,hfw->window->window);
219 hfw->creation_mode = FALSE; // Supposed to be done in hf_wrapper_copy...
220 // hfw->hf_options->current_calculation = NULL;
221 hfw->apply_filter = FALSE;
222
223 // Backup the filter definition and nullify it - we 1st commit the HF without the filter
224 if (hfw->hf_options->fd_struct) {
225 set_filter_defaults (hfw->hf_options->fd_struct);
226 }
227
228 record_action(hfw, hfw->hf_options->last_creation_action);
229 if (hfw->hf_options->fd_struct) {
230 fds = hfw->hf_options->fd_struct;
231 if (fds->current_filter) {
232 filter_apply(hfw->hf_struct,
233 fds->current_filter,
234 hfw->hf_options->dist_matrix,
235 fds->revert_filter,
236 fds->filter_level,
237 fds->merge_oper);
238 // Now we commit the HF with the filter
239 record_action(hfw,_("Shape filter"));
240
241 }
242 }
243 // If we are in the shape filter subdialog in the tools dialog:
244 if (hfw->hf_options->img)
245 hfw->hf_options->fd_struct = hfw->hf_options->img->fd_struct;
246 else
247 hfw->hf_options->fd_struct = NULL;
248
249 // "expose_event" seems required to display the cursor ?
250 emit_expose_event(hfw->area);
251 }
252
253 // HF creation
254
hfuniform_callb(GtkWidget * wdg,gpointer hf_options_ptr)255 void hfuniform_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
256 // Display / connect callback for uniform hf (a simple scale from 0 to 0xFFFF)
257
258 hf_wrapper_struct *hfw;
259 hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
260
261 if (!hfo)
262 return;
263 if (wdg)
264 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
265 return;
266
267 // printf("IN hfuniform_callb: hfo: %d;\n", hfo);
268
269 // Options dialog
270 if (!hfo->uniform_dialog) {
271 // NB hfw->hf_options->uniform_value allocated in hf_options_new()
272 hfo->uniform_dialog = uniform_dialog_new(hfo,
273 *hfo->uniform_value);
274 gtk_box_pack_start(GTK_BOX(hfo->creation_container), hfo->uniform_dialog, FALSE, FALSE, 0);
275 }
276 if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
277 gtk_widget_hide(hfo->current_dialog);
278 gtk_widget_show(hfo->uniform_dialog);
279 hfo->last_creation_action = _("Uniform");
280 hfo->current_dialog = hfo->uniform_dialog;
281 hfo->current_calculation = (gpointer) uniform;
282 hfo->current_callb = hfuniform_callb;
283 hfo->current_options = (gpointer) hfo->uniform_value;
284 hfo->flag_uniform_done = FALSE;
285 if (hfo->hfw_ptr_ptr) {
286 hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
287 if (hfw)
288 gener_hf(hfw);
289 }
290 }
291
hfsubdiv1_callb(GtkWidget * wdg,gpointer hf_options_ptr)292 void hfsubdiv1_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
293 // Display / connect callback
294 // Simple subdivision, square / diamond dots
295
296 hf_wrapper_struct *hfw;
297 hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
298 if (!hfo)
299 return;
300 if (wdg)
301 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
302 return;
303
304 // printf("IN hfsubdiv1_callb: hfo: %d;\n", hfo);
305
306 // Options dialog - we create it at the 1st pass
307 if (!hfo->subdiv1_dialog) {
308 // We create the struct which will receive the data
309 hfo->subdiv1_options = subdiv1_opt_new();
310 // Dialog creation (with some defaults from subdiv1_opt_new())
311 hfo->subdiv1_dialog = subdiv1_dialog_new(hfo);
312 gtk_box_pack_start(GTK_BOX(hfo->creation_container), hfo->subdiv1_dialog, FALSE, FALSE, 0);
313 }
314 if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
315 gtk_widget_hide(hfo->current_dialog);
316 gtk_widget_show(hfo->subdiv1_dialog);
317 hfo->last_creation_action = _("Subdiv1");
318 hfo->current_dialog= hfo->subdiv1_dialog;
319 hfo->current_calculation = (gpointer) subdiv1;
320 hfo->current_callb = hfsubdiv1_callb;
321 hfo->current_options = (gpointer) hfo->subdiv1_options;
322 if (hfo->hfw_ptr_ptr) {
323 hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
324 if (hfw)
325 gener_hf(hfw);
326 }
327 }
328
hfsubdiv2_callb(GtkWidget * wdg,gpointer hf_options_ptr)329 void hfsubdiv2_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
330 // Display / connect callback
331 // Simple subdivision, square / diamond dots
332
333 static gint frq = 50;
334 hf_wrapper_struct *hfw;
335 hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
336 if (!hfo)
337 return;
338 if (wdg)
339 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
340 return;
341
342 // printf("IN hfsubdiv2_callb: hfo: %d;\n", hfo);
343
344 // Options dialog - we create it at the 1st pass
345 if (!hfo->subdiv2_dialog) {
346 // We create the struct which will receive the data
347 hfo->subdiv2_options = subdiv2_opt_new(&frq,1);
348 // Dialog creation (with some defaults from subdiv2_opt_new())
349 hfo->subdiv2_dialog = subdiv2_dialog_new(hfo);
350 gtk_box_pack_start(GTK_BOX(hfo->creation_container), hfo->subdiv2_dialog, FALSE, FALSE, 0);
351 }
352 if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
353 gtk_widget_hide(hfo->current_dialog);
354 gtk_widget_show(hfo->subdiv2_dialog);
355 hfo->last_creation_action = _("Subdiv2");
356 hfo->current_dialog = hfo->subdiv2_dialog;
357 hfo->current_calculation = (gpointer) subdiv2;
358 hfo->current_callb = hfsubdiv2_callb;
359 hfo->current_options = (gpointer) hfo->subdiv2_options;
360 if (hfo->hfw_ptr_ptr) {
361 hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
362 if (hfw)
363 gener_hf(hfw);
364 }
365 }
366
hfsurfadd_callb(GtkWidget * wdg,gpointer hf_options_ptr)367 void hfsurfadd_callb(GtkWidget *wdg, gpointer hf_options_ptr) {
368 // Progressive addition of surfaces
369
370 hf_wrapper_struct *hfw;
371 hf_options_struct *hfo = (hf_options_struct *) hf_options_ptr;
372 if (!hfo)
373 return;
374
375 if (wdg)
376 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wdg)))
377 return;
378
379 // printf("IN hfsurfadd_callb: hfo: %d;\n", hfo);
380
381 // Options dialog - we create it at the 1st pass
382 if (!hfo->surfadd_dialog) {
383 // We create the struct which will receive the data
384 hfo->surfadd_options = surfadd_opt_new();
385 hfo->surfadd_options->dist_matrix = hfo->dist_matrix;
386 // Dialog creation (with some defaults from surfadd_opt_new())
387 hfo->surfadd_dialog = surfadd_dialog_new(hfo);
388 hfo->surfadd_options->current_filter =
389 &((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->current_filter;
390 hfo->surfadd_options->revert_filter =
391 &((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->revert_filter;
392 hfo->surfadd_options->filter_merge =
393 &((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->merge_oper;
394 hfo->surfadd_options->filter_level =
395 &((hf_wrapper_struct *)hfo->primit_surf)->hf_options->fd_struct->filter_level;
396 gtk_container_add(GTK_CONTAINER(hfo->creation_container),
397 hfo->surfadd_dialog);
398 }
399 if (hfo->current_dialog && GTK_IS_WIDGET(hfo->current_dialog))
400 gtk_widget_hide(hfo->current_dialog);
401 gtk_widget_show(hfo->surfadd_dialog);
402 hfo->last_creation_action = _("SurfSum");
403 hfo->current_dialog = hfo->surfadd_dialog;
404 hfo->current_calculation = (gpointer) surfadd;
405 hfo->current_callb = hfsurfadd_callb;
406 hfo->current_options = (gpointer) hfo->surfadd_options;
407
408 if (hfo->hfw_ptr_ptr) {
409 hfw = (hf_wrapper_struct *) * (hf_wrapper_struct **) hfo->hfw_ptr_ptr;
410 if (hfw)
411 gener_hf(hfw);
412 }
413 }
414