2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant 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.
12 GtkRadiant 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.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 Camera plugin for GtkRadiant
24 Copyright (C) 2002 Splash Damage Ltd.
29 static GSList *g_pEditTypeRadio = NULL;
30 static GtkWidget *g_pEditModeEditRadioButton = NULL;
31 GtkWidget *g_pEditModeAddRadioButton = NULL;
32 static GtkWidget *g_pSecondsEntry = NULL;
33 static GtkWidget *g_pEventsList = NULL;
34 static GtkLabel *g_pCurrentTime = NULL;
35 static GtkLabel *g_pTotalTime = NULL;
36 static GtkAdjustment *g_pTimeLine = NULL;
37 static GtkWidget *g_pTrackCamera = NULL;
38 static GtkWidget *g_pCamName = NULL;
39 static char *g_cNull = '\0';
41 static gint ci_editmode_edit(GtkWidget *widget, gpointer data)
48 static gint ci_editmode_add(GtkWidget *widget, gpointer data)
55 /*static gint ci_delete_selected( GtkWidget *widget, gpointer data )
60 static gint ci_select_all( GtkWidget *widget, gpointer data )
65 static gint ci_new(GtkWidget *widget, gpointer data)
67 GtkWidget *w, *hbox; //, *name;
68 GtkWidget *fixed, *interpolated, *spline;
69 EMessageBoxReturn ret;
71 GSList *targetTypeRadio = NULL;
75 auto window = ui::Window(ui::window_type::TOP);
76 gtk_window_set_title(window, "New Camera");
77 window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
78 window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
79 gtk_window_set_transient_for(window, g_pCameraInspectorWnd);
81 g_object_set_data(G_OBJECT(window), "loop", &loop);
82 g_object_set_data(G_OBJECT(window), "ret", &ret);
84 gtk_widget_realize(window);
87 auto vbox = ui::VBox(FALSE, 5);
91 // -------------------------- //
93 hbox = ui::HBox(FALSE, 5);
94 vbox.pack_start(hbox, FALSE, FALSE, 0);
97 auto frame = ui::Frame("Type");
98 hbox.pack_start(frame, TRUE, TRUE, 0);
101 auto vbox2 = ui::VBox(FALSE, 5);
103 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5);
106 // -------------------------- //
108 fixed = gtk_radio_button_new_with_label(targetTypeRadio, "Fixed");
109 vbox2.pack_start(fixed, FALSE, FALSE, 3);
111 targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(fixed));
113 interpolated = gtk_radio_button_new_with_label(targetTypeRadio, "Interpolated");
114 vbox2.pack_start(interpolated, FALSE, FALSE, 3);
116 targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(interpolated));
118 spline = gtk_radio_button_new_with_label(targetTypeRadio, "Spline");
119 vbox2.pack_start(spline, FALSE, FALSE, 3);
121 targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(spline));
123 // -------------------------- //
125 w = gtk_hseparator_new();
126 vbox.pack_start(w, FALSE, FALSE, 2);
129 // -------------------------- //
131 hbox = ui::HBox(FALSE, 5);
132 vbox.pack_start(hbox, FALSE, FALSE, 0);
135 w = ui::Button("Ok");
136 hbox.pack_start(w, TRUE, TRUE, 0);
137 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
140 gtk_widget_set_can_default(w, true);
141 gtk_widget_grab_default(w);
143 w = ui::Button("Cancel");
144 hbox.pack_start(w, TRUE, TRUE, 0);
145 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
149 // -------------------------- //
151 gtk_window_set_position(window, GTK_WIN_POS_CENTER);
153 gtk_grab_add(window);
155 bool dialogError = TRUE;
156 while (dialogError) {
159 gtk_main_iteration();
165 if (gtk_toggle_button_get_active((GtkToggleButton *) fixed)) {
167 } else if (gtk_toggle_button_get_active((GtkToggleButton *) interpolated)) {
168 DoNewInterpolatedCamera();
169 } else if (gtk_toggle_button_get_active((GtkToggleButton *) spline)) {
175 gtk_grab_remove(window);
181 static gint ci_load(GtkWidget *widget, gpointer data)
188 static gint ci_save(GtkWidget *widget, gpointer data)
195 static gint ci_unload(GtkWidget *widget, gpointer data)
202 static gint ci_apply(GtkWidget *widget, gpointer data)
204 if (GetCurrentCam()) {
209 str = gtk_entry_get_text(GTK_ENTRY(g_pCamName));
212 GetCurrentCam()->GetCam()->setName(str);
216 str = gtk_entry_get_text(GTK_ENTRY(g_pSecondsEntry));
219 GetCurrentCam()->GetCam()->setBaseTime(atof(str));
224 GetCurrentCam()->GetCam()->buildCamera();
227 sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime());
228 gtk_entry_set_text(GTK_ENTRY(g_pSecondsEntry), buf);
230 sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime());
231 gtk_label_set_text(g_pCurrentTime, "0.00");
232 gtk_label_set_text(g_pTotalTime, buf);
234 gtk_adjustment_set_value(g_pTimeLine, 0.f);
235 g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000;
237 GetCurrentCam()->HasBeenModified();
243 static gint ci_preview(GtkWidget *widget, gpointer data)
245 if (GetCurrentCam()) {
246 g_iPreviewRunning = 1;
247 g_FuncTable.m_pfnSysUpdateWindows(W_XY_OVERLAY | W_CAMERA);
253 static gint ci_expose(GtkWidget *widget, gpointer data)
256 DoStartEdit(GetCurrentCam());
261 static gint ci_close(GtkWidget *widget, gpointer data)
263 gtk_widget_hide(g_pCameraInspectorWnd);
271 static GtkWidget *g_pPathListCombo = NULL;
272 static GtkLabel *g_pPathType = NULL;
274 static void RefreshPathListCombo(void)
276 if (!g_pPathListCombo) {
280 GList *combo_list = (GList *) NULL;
282 if (GetCurrentCam()) {
283 combo_list = g_list_append(combo_list, (void *) GetCurrentCam()->GetCam()->getPositionObj()->getName());
284 for (int i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++) {
285 combo_list = g_list_append(combo_list, (void *) GetCurrentCam()->GetCam()->getActiveTarget(i)->getName());
288 // add one empty string make gtk be quiet
289 combo_list = g_list_append(combo_list, (gpointer) g_cNull);
292 gtk_combo_set_popdown_strings(GTK_COMBO(g_pPathListCombo), combo_list);
293 g_list_free(combo_list);
296 static gint ci_pathlist_changed(GtkWidget *widget, gpointer data)
298 const char *str = gtk_entry_get_text(GTK_ENTRY(widget));
300 if (!str || !GetCurrentCam()) {
305 for (i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++) {
306 if (!strcmp(str, GetCurrentCam()->GetCam()->getActiveTarget(i)->getName())) {
311 if (i >= 0 && i < GetCurrentCam()->GetCam()->numTargets()) {
312 GetCurrentCam()->GetCam()->setActiveTarget(i);
316 gtk_label_set_text(g_pPathType, GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->typeStr());
319 g_iActiveTarget = -1;
321 gtk_label_set_text(g_pPathType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr());
326 if (g_pCameraInspectorWnd && gtk_widget_get_visible(g_pCameraInspectorWnd)) {
327 DoStartEdit(GetCurrentCam());
333 static void RefreshEventList(void)
339 gtk_clist_freeze(GTK_CLIST(g_pEventsList));
340 gtk_clist_clear(GTK_CLIST(g_pEventsList));
342 if (GetCurrentCam()) {
344 for (i = 0; i < GetCurrentCam()->GetCam()->numEvents(); i++) {
345 char rowbuf[3][128], *row[3];
346 // FIXME: sort by time?
347 sprintf(rowbuf[0], "%li", GetCurrentCam()->GetCam()->getEvent(i)->getTime());
349 strncpy(rowbuf[1], GetCurrentCam()->GetCam()->getEvent(i)->typeStr(), sizeof(rowbuf[0]));
351 strncpy(rowbuf[2], GetCurrentCam()->GetCam()->getEvent(i)->getParam(), sizeof(rowbuf[1]));
353 gtk_clist_append(GTK_CLIST(g_pEventsList), row);
356 // Total duration might have changed
357 sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime());
358 gtk_label_set_text(g_pCurrentTime, "0.00");
359 gtk_label_set_text(g_pTotalTime, buf);
361 gtk_adjustment_set_value(g_pTimeLine, 0.f);
362 g_pTimeLine->upper = (GetCurrentCam()->GetCam()->getTotalTime() * 1000);
365 gtk_clist_thaw(GTK_CLIST(g_pEventsList));
368 static gint ci_rename(GtkWidget *widget, gpointer data)
370 GtkWidget *w, *hbox, *name;
371 EMessageBoxReturn ret;
374 if (!GetCurrentCam()) {
379 auto window = ui::Window(ui::window_type::TOP);
380 gtk_window_set_title(window, "Rename Path");
381 window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
382 window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
383 gtk_window_set_transient_for(window, g_pCameraInspectorWnd);
385 g_object_set_data(G_OBJECT(window), "loop", &loop);
386 g_object_set_data(G_OBJECT(window), "ret", &ret);
388 gtk_widget_realize(window);
391 auto vbox = ui::VBox(FALSE, 5);
395 // -------------------------- //
397 hbox = ui::HBox(FALSE, 5);
398 vbox.pack_start(hbox, FALSE, FALSE, 0);
401 w = ui::Label("Name:");
402 hbox.pack_start(w, FALSE, FALSE, 0);
406 hbox.pack_start(name, FALSE, FALSE, 0);
409 if (g_iActiveTarget < 0) {
410 gtk_entry_set_text(GTK_ENTRY(name), GetCurrentCam()->GetCam()->getPositionObj()->getName());
412 gtk_entry_set_text(GTK_ENTRY(name), GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->getName());
415 // -------------------------- //
417 w = gtk_hseparator_new();
418 vbox.pack_start(w, FALSE, FALSE, 2);
421 // -------------------------- //
423 hbox = ui::HBox(FALSE, 5);
424 vbox.pack_start(hbox, FALSE, FALSE, 0);
427 w = ui::Button("Ok");
428 hbox.pack_start(w, TRUE, TRUE, 0);
429 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
432 gtk_widget_set_can_default(w, true);
433 gtk_widget_grab_default(w);
435 w = ui::Button("Cancel");
436 hbox.pack_start(w, TRUE, TRUE, 0);
437 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
441 // -------------------------- //
443 gtk_window_set_position(window, GTK_WIN_POS_CENTER);
445 gtk_grab_add(window);
447 bool dialogError = TRUE;
448 while (dialogError) {
451 gtk_main_iteration();
457 const char *str = gtk_entry_get_text(GTK_ENTRY(name));
461 if (g_iActiveTarget < 0) {
462 GetCurrentCam()->GetCam()->getPositionObj()->setName(str);
464 GetCurrentCam()->GetCam()->getActiveTarget(g_iActiveTarget)->setName(str);
467 GetCurrentCam()->GetCam()->buildCamera();
469 // Rebuild the listbox
470 RefreshPathListCombo();
477 gtk_grab_remove(window);
483 static gint ci_add_target(GtkWidget *widget, gpointer data)
485 GtkWidget *w, *hbox, *name;
486 GtkWidget *fixed, *interpolated, *spline;
487 EMessageBoxReturn ret;
489 GSList *targetTypeRadio = NULL;
492 if (!GetCurrentCam()) {
497 auto window = ui::Window(ui::window_type::TOP);
498 gtk_window_set_title(window, "Add Target");
499 window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
500 window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
501 gtk_window_set_transient_for(window, g_pCameraInspectorWnd);
503 g_object_set_data(G_OBJECT(window), "loop", &loop);
504 g_object_set_data(G_OBJECT(window), "ret", &ret);
506 gtk_widget_realize(window);
509 auto vbox = ui::VBox(FALSE, 5);
513 // -------------------------- //
515 hbox = ui::HBox(FALSE, 5);
516 vbox.pack_start(hbox, FALSE, FALSE, 0);
519 w = ui::Label("Name:");
520 hbox.pack_start(w, FALSE, FALSE, 0);
524 hbox.pack_start(name, TRUE, TRUE, 0);
527 sprintf(buf, "target%i", GetCurrentCam()->GetCam()->numTargets() + 1);
528 gtk_entry_set_text(GTK_ENTRY(name), buf);
530 // -------------------------- //
532 hbox = ui::HBox(FALSE, 5);
533 vbox.pack_start(hbox, FALSE, FALSE, 0);
536 auto frame = ui::Frame("Type");
537 hbox.pack_start(frame, TRUE, TRUE, 0);
540 auto vbox2 = ui::VBox(FALSE, 5);
542 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5);
545 // -------------------------- //
547 fixed = gtk_radio_button_new_with_label(targetTypeRadio, "Fixed");
548 vbox2.pack_start(fixed, FALSE, FALSE, 3);
550 targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(fixed));
552 interpolated = gtk_radio_button_new_with_label(targetTypeRadio, "Interpolated");
553 vbox2.pack_start(interpolated, FALSE, FALSE, 3);
555 targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(interpolated));
557 spline = gtk_radio_button_new_with_label(targetTypeRadio, "Spline");
558 vbox2.pack_start(spline, FALSE, FALSE, 3);
560 targetTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(spline));
562 // -------------------------- //
564 w = gtk_hseparator_new();
565 vbox.pack_start(w, FALSE, FALSE, 2);
568 // -------------------------- //
570 hbox = ui::HBox(FALSE, 5);
571 vbox.pack_start(hbox, FALSE, FALSE, 0);
574 w = ui::Button("Ok");
575 hbox.pack_start(w, TRUE, TRUE, 0);
576 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
579 gtk_widget_set_can_default(w, true);
580 gtk_widget_grab_default(w);
582 w = ui::Button("Cancel");
583 hbox.pack_start(w, TRUE, TRUE, 0);
584 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
588 // -------------------------- //
590 gtk_window_set_position(window, GTK_WIN_POS_CENTER);
592 gtk_grab_add(window);
594 bool dialogError = TRUE;
595 while (dialogError) {
598 gtk_main_iteration();
604 const char *str = gtk_entry_get_text(GTK_ENTRY(name));
610 if (gtk_toggle_button_get_active((GtkToggleButton *) fixed)) {
612 } else if (gtk_toggle_button_get_active((GtkToggleButton *) interpolated)) {
614 } else if (gtk_toggle_button_get_active((GtkToggleButton *) spline)) {
619 GetCurrentCam()->GetCam()->addTarget(str, static_cast<idCameraPosition::positionType>( type ));
621 // Rebuild the listbox
622 RefreshPathListCombo();
624 // Select the last item in the listbox
625 li = g_list_last(GTK_LIST(GTK_COMBO(g_pPathListCombo)->list)->children);
626 gtk_list_select_child(GTK_LIST(GTK_COMBO(g_pPathListCombo)->list), li->data);
628 // If this was the first one, refresh the event list
629 if (GetCurrentCam()->GetCam()->numTargets() == 1) {
633 // Go to editmode Add
634 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_pEditModeAddRadioButton), TRUE);
642 gtk_grab_remove(window);
648 static GtkWidget *g_pCamListCombo = NULL;
649 static GtkLabel *g_pCamType = NULL;
651 void RefreshCamListCombo(void)
653 if (!g_pCamListCombo) {
657 GList *combo_list = (GList *) NULL;
658 CCamera *combo_cam = firstCam;
661 //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() );
662 //if( combo_cam->HasBeenSaved() ) {
663 combo_list = g_list_append(combo_list, (void *) combo_cam->GetFileName());
666 sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() );
667 combo_list = g_list_append( combo_list, (void *)buf );
669 //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() ); // FIXME: this requires camera.dll to create unique names for new cams
671 combo_cam = combo_cam->GetNext();
674 // add one empty string make gtk be quiet
675 combo_list = g_list_append(combo_list, (gpointer) g_cNull);
677 gtk_combo_set_popdown_strings(GTK_COMBO(g_pCamListCombo), combo_list);
678 g_list_free(combo_list);
680 // select our current entry in the list
681 if (GetCurrentCam()) {
682 // stop editing on the current cam
683 //GetCurrentCam()->GetCam()->stopEdit(); // FIXME: this crashed on creating new cameras, why is it here?
685 GList *li = GTK_LIST(GTK_COMBO(g_pCamListCombo)->list)->children;
686 combo_cam = firstCam;
687 while (li && combo_cam) {
688 if (combo_cam == GetCurrentCam()) {
689 gtk_list_select_child(GTK_LIST(GTK_COMBO(g_pCamListCombo)->list), li->data);
693 combo_cam = combo_cam->GetNext();
697 RefreshPathListCombo();
700 static gint ci_camlist_changed(GtkWidget *widget, gpointer data)
702 const char *str = gtk_entry_get_text(GTK_ENTRY(widget));
704 CCamera *combo_cam = firstCam;
705 while (str && combo_cam) {
706 //if( !strcmp( str, combo_cam->GetCam()->getName() ) )
707 //if( combo_cam->HasBeenSaved() ) {
708 if (!strcmp(str, combo_cam->GetFileName())) {
713 sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() );
714 if( !strcmp( str, buf ) )
715 //if( !strcmp( str, combo_cam->GetCam()->getName() ) )
719 combo_cam = combo_cam->GetNext();
722 SetCurrentCam(combo_cam);
725 if (GetCurrentCam()) {
726 // Fill in our widgets fields for this camera
730 gtk_entry_set_text(GTK_ENTRY(g_pCamName), GetCurrentCam()->GetCam()->getName());
733 gtk_label_set_text(g_pCamType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr());
736 sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime());
737 gtk_entry_set_text(GTK_ENTRY(g_pSecondsEntry), buf);
739 sprintf(buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime());
740 gtk_label_set_text(g_pCurrentTime, "0.00");
741 gtk_label_set_text(g_pTotalTime, buf);
743 gtk_adjustment_set_value(g_pTimeLine, 0.f);
744 g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000;
747 gtk_entry_set_text(GTK_ENTRY(g_pCamName), "");
750 gtk_label_set_text(g_pCamType, "");
753 gtk_entry_set_text(GTK_ENTRY(g_pSecondsEntry), "30.00");
755 gtk_label_set_text(g_pCurrentTime, "0.00");
756 gtk_label_set_text(g_pTotalTime, "30.00");
758 gtk_adjustment_set_value(g_pTimeLine, 0.f);
759 g_pTimeLine->upper = 30000;
762 // Refresh event list
766 RefreshPathListCombo();
769 g_iActiveTarget = -1;
770 if (g_pCameraInspectorWnd && gtk_widget_get_visible(g_pCameraInspectorWnd)) {
771 DoStartEdit(GetCurrentCam());
782 EVENT_TARGET, // char(name)
784 EVENT_FOV, // int(time), int(targetfov)
789 EVENT_FADEOUT, // int(time)
790 EVENT_FADEIN, // int(time)
795 // { requires parameters, enabled }
796 const bool camEventFlags[][2] = {
813 const char *camEventStr[] = {
818 "Change Target <string:name>",
820 "FOV <int:duration> <int:targetfov>",
824 "Change to Camera <string:camera> (or <int:cameranum> <string:camera>",
825 "Fade Out <int:duration>",
826 "Fade In <int:duration>",
830 static gint ci_add(GtkWidget *widget, gpointer data)
832 GtkWidget *w, *hbox, *parameters;
833 GtkWidget *eventWidget[EVENT_COUNT];
834 EMessageBoxReturn ret;
836 GSList *eventTypeRadio = NULL;
839 if (!GetCurrentCam()) {
844 auto window = ui::Window(ui::window_type::TOP);
845 gtk_window_set_title(window, "Add Event");
846 window.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
847 window.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
848 gtk_window_set_transient_for(window, g_pCameraInspectorWnd);
850 g_object_set_data(G_OBJECT(window), "loop", &loop);
851 g_object_set_data(G_OBJECT(window), "ret", &ret);
853 gtk_widget_realize(window);
856 auto vbox = ui::VBox(FALSE, 5);
860 // -------------------------- //
862 hbox = ui::HBox(FALSE, 5);
863 vbox.pack_start(hbox, FALSE, FALSE, 0);
866 auto frame = ui::Frame("Type");
867 hbox.pack_start(frame, TRUE, TRUE, 0);
870 auto vbox2 = ui::VBox(FALSE, 5);
872 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 5);
875 // -------------------------- //
877 for (i = 1; i < EVENT_COUNT; i++) {
878 eventWidget[i] = gtk_radio_button_new_with_label(eventTypeRadio, camEventStr[i]);
879 vbox2.pack_start(eventWidget[i], FALSE, FALSE, 3);
880 eventWidget[i].show();
881 eventTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(eventWidget[i]));
882 if (camEventFlags[i][1] == false) {
883 gtk_widget_set_sensitive(eventWidget[i], FALSE);
887 // -------------------------- //
889 hbox = ui::HBox(FALSE, 5);
890 vbox.pack_start(hbox, FALSE, FALSE, 0);
893 w = ui::Label("Parameters:");
894 hbox.pack_start(w, FALSE, FALSE, 0);
897 parameters = ui::Entry();
898 hbox.pack_start(parameters, TRUE, TRUE, 0);
901 // -------------------------- //
903 w = gtk_hseparator_new();
904 vbox.pack_start(w, FALSE, FALSE, 2);
907 // -------------------------- //
909 hbox = ui::HBox(FALSE, 5);
910 vbox.pack_start(hbox, FALSE, FALSE, 0);
913 w = ui::Button("Ok");
914 hbox.pack_start(w, TRUE, TRUE, 0);
915 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDOK));
918 gtk_widget_set_can_default(w, true);
919 gtk_widget_grab_default(w);
921 w = ui::Button("Cancel");
922 hbox.pack_start(w, TRUE, TRUE, 0);
923 w.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(eIDCANCEL));
927 // -------------------------- //
929 gtk_window_set_position(window, GTK_WIN_POS_CENTER);
931 gtk_grab_add(window);
933 bool dialogError = TRUE;
934 while (dialogError) {
937 gtk_main_iteration();
943 const char *str = gtk_entry_get_text(GTK_ENTRY(parameters));
945 if (!camEventFlags[i][0] || (str && str[0])) {
949 for (type = 1; type < EVENT_COUNT; type++) {
950 if (gtk_toggle_button_get_active((GtkToggleButton *) eventWidget[type])) {
956 GetCurrentCam()->GetCam()->addEvent(static_cast<idCameraEvent::eventType>( type ), str,
957 (long) (g_pTimeLine->value));
959 // Refresh event list
967 gtk_grab_remove(window);
973 static gint ci_del(GtkWidget *widget, gpointer data)
975 // TODO: add support to splines lib
976 if (GetCurrentCam() && GTK_CLIST(g_pEventsList)->focus_row >= 0) {
977 GetCurrentCam()->GetCam()->removeEvent(GTK_CLIST(g_pEventsList)->focus_row);
978 // Refresh event list
985 static gint ci_timeline_changed(GtkAdjustment *adjustment)
989 sprintf(buf, "%.2f", adjustment->value / 1000.f);
990 gtk_label_set_text(g_pCurrentTime, buf);
992 // FIXME: this will never work completely perfect. Startcamera calls buildcamera, which sets all events to 'nottriggered'.
993 // So if you have a wait at the end of the path, this will go to nontriggered immediately when you go over it and the camera
994 // will have no idea where on the track it should be.
995 if (GetCurrentCam() && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(g_pTrackCamera))) {
997 vec3_t origin = {0.0f, 0.0f, 0.0f}, dir = {0.0f, 0.0f, 0.0f}, angles;
999 GetCurrentCam()->GetCam()->startCamera(0);
1001 GetCurrentCam()->GetCam()->getCameraInfo((long) (adjustment->value), &origin[0], &dir[0], &fov);
1002 VectorSet(angles, asin(dir[2]) * 180 / 3.14159, atan2(dir[1], dir[0]) * 180 / 3.14159, 0);
1003 g_CameraTable.m_pfnSetCamera(origin, angles);
1009 GtkWidget *CreateCameraInspectorDialog(void)
1011 GtkWidget *w, *hbox;
1013 // create the window
1014 auto window = ui::Window(ui::window_type::TOP);
1015 gtk_window_set_title(window, "Camera Inspector");
1016 window.connect("delete_event", G_CALLBACK(ci_close), NULL);
1017 window.connect("expose_event", G_CALLBACK(ci_expose), NULL);
1018 // window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1019 gtk_window_set_transient_for(window, g_pRadiantWnd);
1021 // don't use show, as you don't want to have it displayed on startup ;-)
1022 gtk_widget_realize(window);
1027 // -------------------------- //
1029 auto table = ui::Table(3, 2, FALSE);
1032 gtk_container_set_border_width(GTK_CONTAINER(table), 5);
1033 gtk_table_set_row_spacings(table, 5);
1034 gtk_table_set_col_spacings(table, 5);
1036 // the properties column
1037 // -------------------------- //
1039 vbox = ui::VBox(FALSE, 5);
1041 table.attach(vbox, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1043 // -------------------------- //
1045 hbox = ui::HBox(FALSE, 5);
1046 vbox.pack_start(hbox, FALSE, FALSE, 0);
1049 w = ui::Label("File:");
1050 hbox.pack_start(w, FALSE, FALSE, 0);
1053 g_pCamListCombo = gtk_combo_new();
1054 hbox.pack_start(g_pCamListCombo, TRUE, TRUE, 0);
1055 g_pCamListCombo.show();
1057 // -------------------------- //
1059 hbox = ui::HBox(FALSE, 5);
1060 vbox.pack_start(hbox, FALSE, FALSE, 0);
1063 w = ui::Label("Name:");
1064 hbox.pack_start(w, FALSE, FALSE, 0);
1067 g_pCamName = ui::Entry();
1068 hbox.pack_start(g_pCamName, FALSE, FALSE, 0);
1071 w = ui::Label("Type: ");
1072 hbox.pack_start(w, FALSE, FALSE, 0);
1076 hbox.pack_start(w, FALSE, FALSE, 0);
1078 g_pCamType = GTK_LABEL(w);
1080 RefreshCamListCombo();
1082 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(g_pCamListCombo)->entry), FALSE);
1083 (GTK_COMBO(g_pCamListCombo)->entry).connect("changed", G_CALLBACK(ci_camlist_changed), NULL);
1085 // -------------------------- //
1087 auto frame = ui::Frame("Path and Target editing");
1089 table.attach(frame, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1091 auto vbox = ui::VBox(FALSE, 5);
1093 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1096 // -------------------------- //
1098 hbox = ui::HBox(FALSE, 5);
1099 vbox.pack_start(hbox, FALSE, FALSE, 0);
1102 w = ui::Label("Edit:");
1103 hbox.pack_start(w, FALSE, FALSE, 0);
1106 g_pPathListCombo = gtk_combo_new();
1107 hbox.pack_start(g_pPathListCombo, TRUE, TRUE, 0);
1108 g_pPathListCombo.show();
1110 RefreshPathListCombo();
1112 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(g_pPathListCombo)->entry), FALSE);
1113 (GTK_COMBO(g_pPathListCombo)->entry).connect("changed", G_CALLBACK(ci_pathlist_changed), NULL);
1115 // -------------------------- //
1117 hbox = ui::HBox(FALSE, 5);
1118 vbox.pack_start(hbox, FALSE, FALSE, 0);
1121 g_pEditModeEditRadioButton = gtk_radio_button_new_with_label(g_pEditTypeRadio, "Edit Points");
1122 hbox.pack_start(g_pEditModeEditRadioButton, FALSE, FALSE, 3);
1123 g_pEditModeEditRadioButton.show();
1124 g_pEditTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(g_pEditModeEditRadioButton));
1126 g_pEditModeEditRadioButton.connect("clicked", G_CALLBACK(ci_editmode_edit), NULL);
1128 g_pEditModeAddRadioButton = gtk_radio_button_new_with_label(g_pEditTypeRadio, "Add Points");
1129 hbox.pack_start(g_pEditModeAddRadioButton, FALSE, FALSE, 3);
1130 g_pEditModeAddRadioButton.show();
1131 g_pEditTypeRadio = gtk_radio_button_get_group(GTK_RADIO_BUTTON(g_pEditModeAddRadioButton));
1133 g_pEditModeAddRadioButton.connect("clicked", G_CALLBACK(ci_editmode_add), NULL);
1135 // see if we should use a different default
1136 if (g_iEditMode == 1) {
1137 // Go to editmode Add
1138 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g_pEditModeAddRadioButton), TRUE);
1141 w = ui::Label("Type: ");
1142 hbox.pack_start(w, FALSE, FALSE, 0);
1146 hbox.pack_start(w, FALSE, FALSE, 0);
1148 g_pPathType = GTK_LABEL(w);
1150 // -------------------------- //
1152 hbox = ui::HBox(FALSE, 5);
1153 vbox.pack_start(hbox, FALSE, FALSE, 0);
1156 w = ui::Button("Rename...");
1157 hbox.pack_start(w, FALSE, TRUE, 0);
1158 w.connect("clicked", G_CALLBACK(ci_rename), NULL);
1161 w = ui::Button("Add Target...");
1162 hbox.pack_start(w, FALSE, TRUE, 0);
1163 w.connect("clicked", G_CALLBACK(ci_add_target), NULL);
1166 // not available in splines library
1167 /*w = gtk_button_new_with_label( "Delete Selected" );
1168 hbox.pack_start( w, FALSE, TRUE, 0);
1169 w.connect( "clicked", G_CALLBACK( ci_delete_selected ), NULL );
1172 w = gtk_button_new_with_label( "Select All" );
1173 hbox.pack_start( w, FALSE, TRUE, 0);
1174 w.connect( "clicked", G_CALLBACK( ci_select_all ), NULL );
1177 // -------------------------- //
1179 frame = ui::Frame("Time");
1181 table.attach(frame, {0, 1, 2, 3}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1183 vbox = ui::VBox(FALSE, 5);
1185 gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
1188 // -------------------------- //
1190 hbox = ui::HBox(FALSE, 5);
1191 vbox.pack_start(hbox, FALSE, FALSE, 0);
1194 w = ui::Label("Length (seconds):");
1195 hbox.pack_start(w, FALSE, FALSE, 0);
1198 g_pSecondsEntry = ui::Entry();
1199 hbox.pack_start(g_pSecondsEntry, FALSE, FALSE, 0);
1200 g_pSecondsEntry.show();
1202 // -------------------------- //
1204 hbox = ui::HBox(FALSE, 5);
1205 vbox.pack_start(hbox, FALSE, FALSE, 0);
1208 w = ui::Label("Current Time: ");
1209 hbox.pack_start(w, FALSE, FALSE, 0);
1212 w = ui::Label("0.00");
1213 hbox.pack_start(w, FALSE, FALSE, 0);
1215 g_pCurrentTime = GTK_LABEL(w);
1217 w = ui::Label(" of ");
1218 hbox.pack_start(w, FALSE, FALSE, 0);
1221 w = ui::Label("0.00");
1222 hbox.pack_start(w, FALSE, FALSE, 0);
1224 g_pTotalTime = GTK_LABEL(w);
1226 // -------------------------- //
1228 hbox = ui::HBox(FALSE, 5);
1229 vbox.pack_start(hbox, FALSE, FALSE, 0);
1232 g_pTimeLine = ui::Adjustment(0, 0, 30000, 100, 250, 0);
1233 g_pTimeLine.connect("value_changed", G_CALLBACK(ci_timeline_changed), NULL);
1234 w = ui::HScale(g_pTimeLine);
1235 hbox.pack_start(w, TRUE, TRUE, 0);
1237 gtk_scale_set_draw_value(GTK_SCALE(w), FALSE);
1239 // -------------------------- //
1241 hbox = ui::HBox(FALSE, 5);
1242 vbox.pack_start(hbox, FALSE, FALSE, 0);
1245 g_pTrackCamera = ui::CheckButton("Track Camera");
1246 hbox.pack_start(g_pTrackCamera, FALSE, FALSE, 0);
1247 g_pTrackCamera.show();
1249 // -------------------------- //
1251 hbox = ui::HBox(FALSE, 5);
1252 vbox.pack_start(hbox, FALSE, FALSE, 0);
1255 w = ui::Label("Events:");
1256 hbox.pack_start(w, FALSE, FALSE, 0);
1259 // -------------------------- //
1261 hbox = ui::HBox(FALSE, 5);
1262 vbox.pack_start(hbox, FALSE, FALSE, 0);
1265 auto scr = w = ui::ScrolledWindow();
1266 w.dimensions(0, 150);
1267 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1268 hbox.pack_start(w, TRUE, TRUE, 0);
1271 g_pEventsList = gtk_clist_new(3);
1272 scr.add(g_pEventsList);
1273 //g_pEventsList.connect( "select_row", G_CALLBACK (proplist_select_row), NULL);
1274 gtk_clist_set_selection_mode(GTK_CLIST(g_pEventsList), GTK_SELECTION_BROWSE);
1275 gtk_clist_column_titles_hide(GTK_CLIST(g_pEventsList));
1276 gtk_clist_set_column_auto_resize(GTK_CLIST(g_pEventsList), 0, TRUE);
1277 gtk_clist_set_column_auto_resize(GTK_CLIST(g_pEventsList), 1, TRUE);
1278 gtk_clist_set_column_auto_resize(GTK_CLIST(g_pEventsList), 2, TRUE);
1279 g_pEventsList.show();
1281 vbox = ui::VBox(FALSE, 5);
1282 hbox.pack_start(vbox, FALSE, FALSE, 0);
1285 w = ui::Button("Add...");
1286 vbox.pack_start(w, FALSE, FALSE, 0);
1287 w.connect("clicked", G_CALLBACK(ci_add), NULL);
1290 w = ui::Button("Del");
1291 vbox.pack_start(w, FALSE, FALSE, 0);
1292 w.connect("clicked", G_CALLBACK(ci_del), NULL);
1295 // -------------------------- //
1303 // the buttons column
1304 // -------------------------- //
1306 vbox = gtk_vbox_new( FALSE, 5 );
1308 table.attach(vbox, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL});
1310 w = gtk_button_new_with_label( "New..." );
1311 vbox.pack_start( w, FALSE, FALSE, 0 );
1312 w.connect( "clicked", G_CALLBACK( ci_new ), NULL );
1315 w = gtk_button_new_with_label( "Load..." );
1316 vbox.pack_start( w, FALSE, FALSE, 0 );
1317 w.connect( "clicked", G_CALLBACK( ci_load ), NULL );
1320 // -------------------------- //
1322 vbox = gtk_vbox_new( FALSE, 5 );
1324 table.attach( vbox, {1, 2, 1, 2}, {GTK_FILL, GTK_FILL});
1326 w = gtk_button_new_with_label( "Save..." );
1327 vbox.pack_start( w, FALSE, FALSE, 0 );
1328 w.connect( "clicked", G_CALLBACK( ci_save ), NULL );
1331 w = gtk_button_new_with_label( "Unload" );
1332 vbox.pack_start( w, FALSE, FALSE, 0 );
1333 w.connect( "clicked", G_CALLBACK( ci_unload ), NULL );
1336 hbox = gtk_hbox_new( FALSE, 5 );
1337 vbox.pack_start( hbox, TRUE, TRUE, 0 );
1340 w = gtk_button_new_with_label( "Apply" );
1341 vbox.pack_start( w, FALSE, FALSE, 0 );
1342 w.connect( "clicked", G_CALLBACK( ci_apply ), NULL );
1345 w = gtk_button_new_with_label( "Preview" );
1346 vbox.pack_start( w, FALSE, FALSE, 0 );
1347 w.connect( "clicked", G_CALLBACK( ci_preview ), NULL );
1350 // -------------------------- //
1352 vbox = gtk_vbox_new( FALSE, 5 );
1354 table.attach(vbox, {1, 2, 2, 3}, {GTK_FILL, GTK_FILL});
1356 hbox = gtk_hbox_new( FALSE, 5 );
1357 vbox.pack_start( hbox, TRUE, TRUE, 0 );
1360 w = gtk_button_new_with_label( "Close" );
1361 vbox.pack_start( w, FALSE, FALSE, 0 );
1362 w.connect( "clicked", G_CALLBACK( ci_close ), NULL );
1363 gtk_widget_set_can_default( w, true );
1364 gtk_widget_grab_default( w );
1367 // -------------------------- //