2 Copyright (c) 2001, Loki software, inc.
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
8 Redistributions of source code must retain the above copyright notice, this list
9 of conditions and the following disclaimer.
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
15 Neither the name of Loki software nor the names of its contributors may be used
16 to endorse or promote products derived from this software without specific prior
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // Some small dialogs that don't need much
34 // Leonardo Zide (leo@lokigames.com)
39 #include "debugging/debugging.h"
44 #include "iscenegraph.h"
45 #include "iselection.h"
47 #include <gdk/gdkkeysyms.h>
48 #include <gtk/gtkmain.h>
49 #include <gtk/gtkentry.h>
50 #include <gtk/gtkhbox.h>
51 #include <gtk/gtkvbox.h>
52 #include <gtk/gtkframe.h>
53 #include <gtk/gtklabel.h>
54 #include <gtk/gtktable.h>
55 #include <gtk/gtkbutton.h>
56 #include <gtk/gtkcombobox.h>
57 #include <gtk/gtkscrolledwindow.h>
58 #include <gtk/gtktextview.h>
59 #include <gtk/gtktextbuffer.h>
60 #include <gtk/gtktreeview.h>
61 #include <gtk/gtkcellrenderertext.h>
62 #include <gtk/gtktreeselection.h>
63 #include <gtk/gtkliststore.h>
66 #include "math/aabb.h"
67 #include "container/array.h"
68 #include "generic/static.h"
69 #include "stream/stringstream.h"
71 #include "gtkutil/messagebox.h"
72 #include "gtkutil/image.h"
75 #include "brushmanip.h"
78 #include "texwindow.h"
80 #include "mainframe.h"
81 #include "preferences.h"
87 // =============================================================================
88 // Project settings dialog
90 class GameComboConfiguration
93 const char* basegame_dir;
95 const char* known_dir;
99 GameComboConfiguration() :
100 basegame_dir(g_pGameDescription->getRequiredKeyValue("basegame")),
101 basegame(g_pGameDescription->getRequiredKeyValue("basegamename")),
102 known_dir(g_pGameDescription->getKeyValue("knowngame")),
103 known(g_pGameDescription->getKeyValue("knowngamename")),
104 custom(g_pGameDescription->getRequiredKeyValue("unknowngamename"))
109 typedef LazyStatic<GameComboConfiguration> LazyStaticGameComboConfiguration;
111 inline GameComboConfiguration& globalGameComboConfiguration()
113 return LazyStaticGameComboConfiguration::instance();
119 gamecombo_t(int _game, const char* _fs_game, bool _sensitive)
120 : game(_game), fs_game(_fs_game), sensitive(_sensitive)
127 gamecombo_t gamecombo_for_dir(const char* dir)
129 if(string_equal(dir, globalGameComboConfiguration().basegame_dir))
131 return gamecombo_t(0, "", false);
133 else if(string_equal(dir, globalGameComboConfiguration().known_dir))
135 return gamecombo_t(1, dir, false);
139 return gamecombo_t(string_empty(globalGameComboConfiguration().known_dir) ? 1 : 2, dir, true);
143 gamecombo_t gamecombo_for_gamename(const char* gamename)
145 if ((strlen(gamename) == 0) || !strcmp(gamename, globalGameComboConfiguration().basegame))
147 return gamecombo_t(0, "", false);
149 else if (!strcmp(gamename, globalGameComboConfiguration().known))
151 return gamecombo_t(1, globalGameComboConfiguration().known_dir, false);
155 return gamecombo_t(string_empty(globalGameComboConfiguration().known_dir) ? 1 : 2, "", true);
159 inline void path_copy_clean(char* destination, const char* source)
161 char* i = destination;
163 while(*source != '\0')
165 *i++ = (*source == '\\') ? '/' : *source;
169 if(i != destination && *(i-1) != '/')
178 GtkComboBox* game_select;
179 GtkEntry* fsgame_entry;
182 gboolean OnSelchangeComboWhatgame(GtkWidget *widget, GameCombo* combo)
184 const char *gamename;
187 gtk_combo_box_get_active_iter(combo->game_select, &iter);
188 gtk_tree_model_get(gtk_combo_box_get_model(combo->game_select), &iter, 0, (gpointer*)&gamename, -1);
191 gamecombo_t gamecombo = gamecombo_for_gamename(gamename);
193 gtk_entry_set_text(combo->fsgame_entry, gamecombo.fs_game);
194 gtk_widget_set_sensitive(GTK_WIDGET(combo->fsgame_entry), gamecombo.sensitive);
202 bool do_mapping_mode;
203 const char* sp_mapping_mode;
204 const char* mp_mapping_mode;
207 do_mapping_mode(!string_empty(g_pGameDescription->getKeyValue("show_gamemode"))),
208 sp_mapping_mode("Single Player mapping mode"),
209 mp_mapping_mode("Multiplayer mapping mode")
214 typedef LazyStatic<MappingMode> LazyStaticMappingMode;
216 inline MappingMode& globalMappingMode()
218 return LazyStaticMappingMode::instance();
221 class ProjectSettingsDialog
224 GameCombo game_combo;
225 GtkComboBox* gamemode_combo;
228 GtkWindow* ProjectSettingsDialog_construct(ProjectSettingsDialog& dialog, ModalDialog& modal)
230 GtkWindow* window = create_dialog_window(MainFrame_getWindow(), "Project Settings", G_CALLBACK(dialog_delete_callback), &modal);
233 GtkTable* table1 = create_dialog_table(1, 2, 4, 4, 4);
234 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(table1));
236 GtkVBox* vbox = create_dialog_vbox(4);
237 gtk_table_attach(table1, GTK_WIDGET(vbox), 1, 2, 0, 1,
238 (GtkAttachOptions) (GTK_FILL),
239 (GtkAttachOptions) (GTK_FILL), 0, 0);
241 GtkButton* button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &modal);
242 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
245 GtkButton* button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &modal);
246 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
250 GtkFrame* frame = create_dialog_frame("Project settings");
251 gtk_table_attach(table1, GTK_WIDGET(frame), 0, 1, 0, 1,
252 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
253 (GtkAttachOptions) (GTK_FILL), 0, 0);
255 GtkTable* table2 = create_dialog_table((globalMappingMode().do_mapping_mode) ? 4 : 3, 2, 4, 4, 4);
256 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(table2));
259 GtkLabel* label = GTK_LABEL(gtk_label_new("Select mod"));
260 gtk_widget_show(GTK_WIDGET(label));
261 gtk_table_attach(table2, GTK_WIDGET(label), 0, 1, 0, 1,
262 (GtkAttachOptions) (GTK_FILL),
263 (GtkAttachOptions) (0), 0, 0);
264 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
267 dialog.game_combo.game_select = GTK_COMBO_BOX(gtk_combo_box_new_text());
269 gtk_combo_box_append_text(dialog.game_combo.game_select, globalGameComboConfiguration().basegame);
270 if(globalGameComboConfiguration().known[0] != '\0')
271 gtk_combo_box_append_text(dialog.game_combo.game_select, globalGameComboConfiguration().known);
272 gtk_combo_box_append_text(dialog.game_combo.game_select, globalGameComboConfiguration().custom);
274 gtk_widget_show(GTK_WIDGET(dialog.game_combo.game_select));
275 gtk_table_attach(table2, GTK_WIDGET(dialog.game_combo.game_select), 1, 2, 0, 1,
276 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
277 (GtkAttachOptions) (0), 0, 0);
279 g_signal_connect(G_OBJECT(dialog.game_combo.game_select), "changed", G_CALLBACK(OnSelchangeComboWhatgame), &dialog.game_combo);
283 GtkLabel* label = GTK_LABEL(gtk_label_new("fs_game"));
284 gtk_widget_show(GTK_WIDGET(label));
285 gtk_table_attach(table2, GTK_WIDGET(label), 0, 1, 1, 2,
286 (GtkAttachOptions) (GTK_FILL),
287 (GtkAttachOptions) (0), 0, 0);
288 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
291 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
292 gtk_widget_show(GTK_WIDGET(entry));
293 gtk_table_attach(table2, GTK_WIDGET(entry), 1, 2, 1, 2,
294 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
295 (GtkAttachOptions) (0), 0, 0);
297 dialog.game_combo.fsgame_entry = entry;
300 if(globalMappingMode().do_mapping_mode)
302 GtkLabel* label = GTK_LABEL(gtk_label_new("Mapping mode"));
303 gtk_widget_show(GTK_WIDGET(label));
304 gtk_table_attach(table2, GTK_WIDGET(label), 0, 1, 3, 4,
305 (GtkAttachOptions) (GTK_FILL),
306 (GtkAttachOptions) (0), 0, 0);
307 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
309 GtkComboBox* combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
310 gtk_combo_box_append_text(combo, globalMappingMode().sp_mapping_mode);
311 gtk_combo_box_append_text(combo, globalMappingMode().mp_mapping_mode);
313 gtk_widget_show(GTK_WIDGET(combo));
314 gtk_table_attach(table2, GTK_WIDGET(combo), 1, 2, 3, 4,
315 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
316 (GtkAttachOptions) (0), 0, 0);
318 dialog.gamemode_combo = combo;
324 // initialise the fs_game selection from the project settings into the dialog
325 const char* dir = gamename_get();
326 gamecombo_t gamecombo = gamecombo_for_dir(dir);
328 gtk_combo_box_set_active(dialog.game_combo.game_select, gamecombo.game);
329 gtk_entry_set_text(dialog.game_combo.fsgame_entry, gamecombo.fs_game);
330 gtk_widget_set_sensitive(GTK_WIDGET(dialog.game_combo.fsgame_entry), gamecombo.sensitive);
332 if(globalMappingMode().do_mapping_mode)
334 const char *gamemode = gamemode_get();
335 if (string_empty(gamemode) || string_equal(gamemode, "sp"))
337 gtk_combo_box_set_active(dialog.gamemode_combo, 0);
341 gtk_combo_box_set_active(dialog.gamemode_combo, 1);
348 void ProjectSettingsDialog_ok(ProjectSettingsDialog& dialog)
350 const char* dir = gtk_entry_get_text(dialog.game_combo.fsgame_entry);
352 const char* new_gamename = path_equal(dir, globalGameComboConfiguration().basegame_dir)
356 if(!path_equal(new_gamename, gamename_get()))
358 ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Changing Game Name");
360 EnginePath_Unrealise();
362 gamename_set(new_gamename);
364 EnginePath_Realise();
367 if(globalMappingMode().do_mapping_mode)
369 // read from gamemode_combo
370 int active = gtk_combo_box_get_active(dialog.gamemode_combo);
371 if(active == -1 || active == 0)
382 void DoProjectSettings()
384 if(ConfirmModified("Edit Project Settings"))
387 ProjectSettingsDialog dialog;
389 GtkWindow* window = ProjectSettingsDialog_construct(dialog, modal);
391 if(modal_dialog_show(window, modal) == eIDOK)
393 ProjectSettingsDialog_ok(dialog);
396 gtk_widget_destroy(GTK_WIDGET(window));
400 // =============================================================================
401 // Arbitrary Sides dialog
403 void DoSides (int type, int axis)
406 GtkEntry* sides_entry;
408 GtkWindow* window = create_dialog_window(MainFrame_getWindow(), "Arbitrary sides", G_CALLBACK(dialog_delete_callback), &dialog);
410 GtkAccelGroup* accel = gtk_accel_group_new();
411 gtk_window_add_accel_group(window, accel);
414 GtkHBox* hbox = create_dialog_hbox(4, 4);
415 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
417 GtkLabel* label = GTK_LABEL(gtk_label_new("Sides:"));
418 gtk_widget_show(GTK_WIDGET(label));
419 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
422 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
423 gtk_widget_show(GTK_WIDGET(entry));
424 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), FALSE, FALSE, 0);
426 gtk_widget_grab_focus(GTK_WIDGET(entry));
429 GtkVBox* vbox = create_dialog_vbox(4);
430 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
432 GtkButton* button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &dialog);
433 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
434 widget_make_default(GTK_WIDGET(button));
435 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
438 GtkButton* button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &dialog);
439 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
440 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
445 if(modal_dialog_show(window, dialog) == eIDOK)
447 const char *str = gtk_entry_get_text(sides_entry);
449 Scene_BrushConstructPrefab(GlobalSceneGraph(), (EBrushPrefab)type, atoi(str), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()));
452 gtk_widget_destroy(GTK_WIDGET(window));
455 // =============================================================================
456 // About dialog (no program is complete without one)
458 void about_button_changelog (GtkWidget *widget, gpointer data)
460 StringOutputStream log(256);
461 log << AppPath_get() << "changelog.txt";
462 OpenURL(log.c_str());
465 void about_button_credits (GtkWidget *widget, gpointer data)
467 StringOutputStream cred(256);
468 cred << AppPath_get() << "credits.html";
469 OpenURL(cred.c_str());
475 ModalDialogButton ok_button(dialog, eIDOK);
477 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "About GtkRadiant", dialog);
480 GtkVBox* vbox = create_dialog_vbox(4, 4);
481 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
484 GtkHBox* hbox = create_dialog_hbox(4);
485 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, TRUE, 0);
488 GtkVBox* vbox2 = create_dialog_vbox(4);
489 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox2), TRUE, FALSE, 0);
491 GtkFrame* frame = create_dialog_frame(0, GTK_SHADOW_IN);
492 gtk_box_pack_start(GTK_BOX (vbox2), GTK_WIDGET(frame), FALSE, FALSE, 0);
494 GtkImage* image = new_local_image("logo.bmp");
495 gtk_widget_show(GTK_WIDGET(image));
496 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(image));
502 GtkLabel* label = GTK_LABEL(gtk_label_new("GtkRadiant " RADIANT_VERSION "\n"
504 RADIANT_ABOUTMSG "\n\n"
505 "By qeradiant.com\n\n"
506 "This program is free software\n"
507 "licensed under the GNU GPL.\n\n"
508 "GtkRadiant is unsupported, however\n"
509 "you may report your problems at\n"
510 "http://zerowing.idsoftware.com/bugzilla"
513 gtk_widget_show(GTK_WIDGET(label));
514 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
515 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
516 gtk_label_set_justify(label, GTK_JUSTIFY_LEFT);
520 GtkVBox* vbox2 = create_dialog_vbox(4);
521 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox2), FALSE, TRUE, 0);
523 GtkButton* button = create_modal_dialog_button("OK", ok_button);
524 gtk_box_pack_start (GTK_BOX (vbox2), GTK_WIDGET(button), FALSE, FALSE, 0);
527 GtkButton* button = create_dialog_button("Credits", G_CALLBACK(about_button_credits), 0);
528 gtk_box_pack_start (GTK_BOX (vbox2), GTK_WIDGET(button), FALSE, FALSE, 0);
531 GtkButton* button = create_dialog_button("Changelog", G_CALLBACK(about_button_changelog), 0);
532 gtk_box_pack_start (GTK_BOX (vbox2), GTK_WIDGET(button), FALSE, FALSE, 0);
537 GtkFrame* frame = create_dialog_frame("OpenGL Properties");
538 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(frame), FALSE, FALSE, 0);
540 GtkTable* table = create_dialog_table(3, 2, 4, 4, 4);
541 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(table));
543 GtkLabel* label = GTK_LABEL(gtk_label_new("Vendor:"));
544 gtk_widget_show(GTK_WIDGET(label));
545 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 0, 1,
546 (GtkAttachOptions) (GTK_FILL),
547 (GtkAttachOptions) (0), 0, 0);
548 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
551 GtkLabel* label = GTK_LABEL(gtk_label_new("Version:"));
552 gtk_widget_show(GTK_WIDGET(label));
553 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 1, 2,
554 (GtkAttachOptions) (GTK_FILL),
555 (GtkAttachOptions) (0), 0, 0);
556 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
559 GtkLabel* label = GTK_LABEL(gtk_label_new("Renderer:"));
560 gtk_widget_show(GTK_WIDGET(label));
561 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 2, 3,
562 (GtkAttachOptions) (GTK_FILL),
563 (GtkAttachOptions) (0), 0, 0);
564 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
567 GtkLabel* label = GTK_LABEL(gtk_label_new(reinterpret_cast<const char*>(glGetString(GL_VENDOR))));
568 gtk_widget_show(GTK_WIDGET(label));
569 gtk_table_attach(table, GTK_WIDGET(label), 1, 2, 0, 1,
570 (GtkAttachOptions) (GTK_FILL),
571 (GtkAttachOptions) (0), 0, 0);
572 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
575 GtkLabel* label = GTK_LABEL(gtk_label_new(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
576 gtk_widget_show(GTK_WIDGET(label));
577 gtk_table_attach(table, GTK_WIDGET(label), 1, 2, 1, 2,
578 (GtkAttachOptions) (GTK_FILL),
579 (GtkAttachOptions) (0), 0, 0);
580 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
583 GtkLabel* label = GTK_LABEL(gtk_label_new(reinterpret_cast<const char*>(glGetString(GL_RENDERER))));
584 gtk_widget_show(GTK_WIDGET(label));
585 gtk_table_attach(table, GTK_WIDGET(label), 1, 2, 2, 3,
586 (GtkAttachOptions) (GTK_FILL),
587 (GtkAttachOptions) (0), 0, 0);
588 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
592 GtkFrame* frame = create_dialog_frame("OpenGL Extensions");
593 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(frame), TRUE, TRUE, 0);
595 GtkScrolledWindow* sc_extensions = create_scrolled_window(GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, 4);
596 gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(sc_extensions));
598 GtkWidget* text_extensions = gtk_text_view_new();
599 gtk_text_view_set_editable(GTK_TEXT_VIEW(text_extensions), FALSE);
600 gtk_container_add (GTK_CONTAINER (sc_extensions), text_extensions);
601 GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_extensions));
602 gtk_text_buffer_set_text(buffer, reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)), -1);
603 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_extensions), GTK_WRAP_WORD);
604 gtk_widget_show(text_extensions);
611 modal_dialog_show(window, dialog);
613 gtk_widget_destroy(GTK_WIDGET(window));
616 // =============================================================================
617 // TextureLayout dialog
619 EMessageBoxReturn DoTextureLayout (float *fx, float *fy)
622 ModalDialogButton ok_button(dialog, eIDOK);
623 ModalDialogButton cancel_button(dialog, eIDCANCEL);
627 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "Patch texture layout", dialog);
629 GtkAccelGroup* accel = gtk_accel_group_new();
630 gtk_window_add_accel_group(window, accel);
633 GtkHBox* hbox = create_dialog_hbox(4, 4);
634 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
636 GtkVBox* vbox = create_dialog_vbox(4);
637 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
639 GtkLabel* label = GTK_LABEL(gtk_label_new("Texture will be fit across the patch based\n"
640 "on the x and y values given. Values of 1x1\n"
641 "will \"fit\" the texture. 2x2 will repeat\n"
643 gtk_widget_show(GTK_WIDGET(label));
644 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), TRUE, TRUE, 0);
645 gtk_label_set_justify(label, GTK_JUSTIFY_LEFT);
648 GtkTable* table = create_dialog_table(2, 2, 4, 4);
649 gtk_widget_show(GTK_WIDGET(table));
650 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), TRUE, TRUE, 0);
652 GtkLabel* label = GTK_LABEL(gtk_label_new("Texture x:"));
653 gtk_widget_show(GTK_WIDGET(label));
654 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 0, 1,
655 (GtkAttachOptions) (GTK_FILL),
656 (GtkAttachOptions) (0), 0, 0);
657 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
660 GtkLabel* label = GTK_LABEL(gtk_label_new("Texture y:"));
661 gtk_widget_show(GTK_WIDGET(label));
662 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 1, 2,
663 (GtkAttachOptions) (GTK_FILL),
664 (GtkAttachOptions) (0), 0, 0);
665 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
668 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
669 gtk_widget_show(GTK_WIDGET(entry));
670 gtk_table_attach(table, GTK_WIDGET(entry), 1, 2, 0, 1,
671 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
672 (GtkAttachOptions) (0), 0, 0);
674 gtk_widget_grab_focus(GTK_WIDGET(entry));
679 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
680 gtk_widget_show(GTK_WIDGET(entry));
681 gtk_table_attach(table, GTK_WIDGET(entry), 1, 2, 1, 2,
682 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
683 (GtkAttachOptions) (0), 0, 0);
690 GtkVBox* vbox = create_dialog_vbox(4);
691 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
693 GtkButton* button = create_modal_dialog_button("OK", ok_button);
694 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
695 widget_make_default(GTK_WIDGET(button));
696 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
699 GtkButton* button = create_modal_dialog_button("Cancel", cancel_button);
700 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
701 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
707 gtk_entry_set_text(x, "4.0");
708 gtk_entry_set_text(y, "4.0");
711 EMessageBoxReturn ret = modal_dialog_show(window, dialog);
714 *fx = static_cast<float>(atof(gtk_entry_get_text(x)));
715 *fy = static_cast<float>(atof(gtk_entry_get_text(y)));
718 gtk_widget_destroy(GTK_WIDGET(window));
723 // =============================================================================
724 // Text Editor dialog
726 // master window widget
727 static GtkWidget *text_editor = 0;
728 static GtkWidget *text_widget; // slave, text widget from the gtk editor
730 static gint editor_delete (GtkWidget *widget, gpointer data)
732 if (gtk_MessageBox (widget, "Close the shader editor ?", "Radiant", eMB_YESNO, eMB_ICONQUESTION) == eIDNO)
735 gtk_widget_hide (text_editor);
740 static void editor_save (GtkWidget *widget, gpointer data)
742 FILE *f = fopen ((char*)g_object_get_data (G_OBJECT (data), "filename"), "w");
743 gpointer text = g_object_get_data (G_OBJECT (data), "text");
747 gtk_MessageBox (GTK_WIDGET(data), "Error saving file !");
751 char *str = gtk_editable_get_chars (GTK_EDITABLE (text), 0, -1);
752 fwrite (str, 1, strlen (str), f);
756 static void editor_close (GtkWidget *widget, gpointer data)
758 if (gtk_MessageBox (text_editor, "Close the shader editor ?", "Radiant", eMB_YESNO, eMB_ICONQUESTION) == eIDNO)
761 gtk_widget_hide (text_editor);
764 static void CreateGtkTextEditor()
767 GtkWidget *vbox, *hbox, *button, *scr, *text;
769 dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
771 g_signal_connect(G_OBJECT(dlg), "delete_event",
772 G_CALLBACK(editor_delete), 0);
773 gtk_window_set_default_size (GTK_WINDOW (dlg), 600, 300);
775 vbox = gtk_vbox_new (FALSE, 5);
776 gtk_widget_show (vbox);
777 gtk_container_add(GTK_CONTAINER(dlg), GTK_WIDGET(vbox));
778 gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
780 scr = gtk_scrolled_window_new (0, 0);
781 gtk_widget_show (scr);
782 gtk_box_pack_start(GTK_BOX(vbox), scr, TRUE, TRUE, 0);
783 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
784 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
786 text = gtk_text_view_new();
787 gtk_container_add (GTK_CONTAINER (scr), text);
788 gtk_widget_show (text);
789 g_object_set_data (G_OBJECT (dlg), "text", text);
790 gtk_text_view_set_editable (GTK_TEXT_VIEW(text), TRUE);
792 hbox = gtk_hbox_new (FALSE, 5);
793 gtk_widget_show (hbox);
794 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, TRUE, 0);
796 button = gtk_button_new_with_label ("Close");
797 gtk_widget_show (button);
798 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
799 g_signal_connect(G_OBJECT(button), "clicked",
800 G_CALLBACK(editor_close), dlg);
801 gtk_widget_set_usize (button, 60, -2);
803 button = gtk_button_new_with_label ("Save");
804 gtk_widget_show (button);
805 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
806 g_signal_connect(G_OBJECT(button), "clicked",
807 G_CALLBACK(editor_save), dlg);
808 gtk_widget_set_usize (button, 60, -2);
814 static void DoGtkTextEditor (const char* filename, guint cursorpos)
817 CreateGtkTextEditor(); // build it the first time we need it
820 FILE *f = fopen (filename, "r");
824 globalOutputStream() << "Unable to load file " << filename << " in shader editor.\n";
825 gtk_widget_hide (text_editor);
829 fseek (f, 0, SEEK_END);
831 void *buf = malloc (len);
835 fread (buf, 1, len, f);
837 gtk_window_set_title (GTK_WINDOW (text_editor), filename);
839 GtkTextBuffer* text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_widget));
840 gtk_text_buffer_set_text(text_buffer, (char*)buf, len);
842 old_filename = g_object_get_data (G_OBJECT (text_editor), "filename");
845 g_object_set_data (G_OBJECT (text_editor), "filename", strdup (filename));
847 // trying to show later
848 gtk_widget_show (text_editor);
854 // only move the cursor if it's not exceeding the size..
855 // NOTE: this is erroneous, cursorpos is the offset in bytes, not in characters
856 // len is the max size in bytes, not in characters either, but the character count is below that limit..
857 // thinking .. the difference between character count and byte count would be only because of CR/LF?
859 GtkTextIter text_iter;
860 // character offset, not byte offset
861 gtk_text_buffer_get_iter_at_offset(text_buffer, &text_iter, cursorpos);
862 gtk_text_buffer_place_cursor(text_buffer, &text_iter);
866 gtk_widget_queue_draw(text_widget);
874 // =============================================================================
875 // Light Intensity dialog
877 EMessageBoxReturn DoLightIntensityDlg (int *intensity)
880 GtkEntry* intensity_entry;
881 ModalDialogButton ok_button(dialog, eIDOK);
882 ModalDialogButton cancel_button(dialog, eIDCANCEL);
884 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "Light intensity", dialog, -1, -1);
886 GtkAccelGroup *accel_group = gtk_accel_group_new();
887 gtk_window_add_accel_group(window, accel_group);
890 GtkHBox* hbox = create_dialog_hbox(4, 4);
891 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
893 GtkVBox* vbox = create_dialog_vbox(4);
894 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
896 GtkLabel* label = GTK_LABEL(gtk_label_new("ESC for default, ENTER to validate"));
897 gtk_widget_show(GTK_WIDGET(label));
898 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 0);
901 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
902 gtk_widget_show(GTK_WIDGET(entry));
903 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(entry), TRUE, TRUE, 0);
905 gtk_widget_grab_focus(GTK_WIDGET(entry));
907 intensity_entry = entry;
911 GtkVBox* vbox = create_dialog_vbox(4);
912 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
915 GtkButton* button = create_modal_dialog_button("OK", ok_button);
916 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
917 widget_make_default(GTK_WIDGET(button));
918 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
921 GtkButton* button = create_modal_dialog_button("Cancel", cancel_button);
922 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
923 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
929 sprintf (buf, "%d", *intensity);
930 gtk_entry_set_text(intensity_entry, buf);
932 EMessageBoxReturn ret = modal_dialog_show(window, dialog);
934 *intensity = atoi (gtk_entry_get_text(intensity_entry));
936 gtk_widget_destroy(GTK_WIDGET(window));
941 // =============================================================================
942 // Add new shader tag dialog
944 EMessageBoxReturn DoShaderTagDlg (CopiedString* tag, char* title)
948 ModalDialogButton ok_button(dialog, eIDOK);
949 ModalDialogButton cancel_button(dialog, eIDCANCEL);
951 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), title, dialog, -1, -1);
953 GtkAccelGroup *accel_group = gtk_accel_group_new();
954 gtk_window_add_accel_group(window, accel_group);
957 GtkHBox* hbox = create_dialog_hbox(4, 4);
958 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
960 GtkVBox* vbox = create_dialog_vbox(4);
961 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
963 //GtkLabel* label = GTK_LABEL(gtk_label_new("Enter one ore more tags separated by spaces"));
964 GtkLabel* label = GTK_LABEL(gtk_label_new("ESC to cancel, ENTER to validate"));
965 gtk_widget_show(GTK_WIDGET(label));
966 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 0);
969 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
970 gtk_widget_show(GTK_WIDGET(entry));
971 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(entry), TRUE, TRUE, 0);
973 gtk_widget_grab_focus(GTK_WIDGET(entry));
979 GtkVBox* vbox = create_dialog_vbox(4);
980 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
983 GtkButton* button = create_modal_dialog_button("OK", ok_button);
984 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
985 widget_make_default(GTK_WIDGET(button));
986 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
989 GtkButton* button = create_modal_dialog_button("Cancel", cancel_button);
990 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
991 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
996 EMessageBoxReturn ret = modal_dialog_show(window, dialog);
999 *tag = gtk_entry_get_text(textentry);
1002 gtk_widget_destroy(GTK_WIDGET(window));
1007 EMessageBoxReturn DoShaderInfoDlg (const char* name, const char* filename, char* title)
1010 ModalDialogButton ok_button(dialog, eIDOK);
1012 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), title, dialog, -1, -1);
1014 GtkAccelGroup *accel_group = gtk_accel_group_new();
1015 gtk_window_add_accel_group(window, accel_group);
1018 GtkHBox* hbox = create_dialog_hbox(4, 4);
1019 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
1021 GtkVBox* vbox = create_dialog_vbox(4);
1022 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
1024 GtkLabel* label = GTK_LABEL(gtk_label_new("The selected shader"));
1025 gtk_widget_show(GTK_WIDGET(label));
1026 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 0);
1029 GtkLabel* label = GTK_LABEL(gtk_label_new(name));
1030 gtk_widget_show(GTK_WIDGET(label));
1031 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 0);
1034 GtkLabel* label = GTK_LABEL(gtk_label_new("is located in file"));
1035 gtk_widget_show(GTK_WIDGET(label));
1036 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 0);
1039 GtkLabel* label = GTK_LABEL(gtk_label_new(filename));
1040 gtk_widget_show(GTK_WIDGET(label));
1041 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 0);
1044 GtkButton* button = create_modal_dialog_button("OK", ok_button);
1045 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
1046 widget_make_default(GTK_WIDGET(button));
1047 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
1052 EMessageBoxReturn ret = modal_dialog_show(window, dialog);
1054 gtk_widget_destroy(GTK_WIDGET(window));
1062 #include <gdk/gdkwin32.h>
1066 // use the file associations to open files instead of builtin Gtk editor
1067 bool g_TextEditor_useWin32Editor = true;
1069 // custom shader editor
1070 bool g_TextEditor_useCustomEditor = false;
1071 CopiedString g_TextEditor_editorCommand("");
1074 void DoTextEditor (const char* filename, int cursorpos)
1077 if (g_TextEditor_useWin32Editor)
1079 globalOutputStream() << "opening file '" << filename << "' (line " << cursorpos << " info ignored)\n";
1080 ShellExecute((HWND)GDK_WINDOW_HWND (GTK_WIDGET(MainFrame_getWindow())->window), "open", filename, 0, 0, SW_SHOW );
1084 // check if a custom editor is set
1085 if(g_TextEditor_useCustomEditor && !g_TextEditor_editorCommand.empty())
1087 StringOutputStream strEditCommand(256);
1088 strEditCommand << g_TextEditor_editorCommand.c_str() << " \"" << filename << "\"";
1090 globalOutputStream() << "Launching: " << strEditCommand.c_str() << "\n";
1091 // note: linux does not return false if the command failed so it will assume success
1092 if (Q_Exec(0, const_cast<char*>(strEditCommand.c_str()), 0, true) == false)
1094 globalOutputStream() << "Failed to execute " << strEditCommand.c_str() << ", using default\n";
1098 // the command (appeared) to run successfully, no need to do anything more
1104 DoGtkTextEditor (filename, cursorpos);