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 ){
47 static gint ci_editmode_add( GtkWidget *widget, gpointer data ){
53 /*static gint ci_delete_selected( GtkWidget *widget, gpointer data )
58 static gint ci_select_all( GtkWidget *widget, gpointer data )
63 static gint ci_new( GtkWidget *widget, gpointer data ){
64 GtkWidget *w, *hbox; //, *name;
65 GtkWidget *fixed, *interpolated, *spline;
66 EMessageBoxReturn ret;
68 GSList *targetTypeRadio = NULL;
72 auto window = ui::Window( ui::window_type::TOP );
73 gtk_window_set_title( window, "New Camera" );
74 window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
75 window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
76 gtk_window_set_transient_for( window, g_pCameraInspectorWnd );
78 g_object_set_data( G_OBJECT( window ), "loop", &loop );
79 g_object_set_data( G_OBJECT( window ), "ret", &ret );
81 gtk_widget_realize( window );
84 auto vbox = ui::VBox( FALSE, 5 );
88 // -------------------------- //
90 hbox = ui::HBox( FALSE, 5 );
91 vbox.pack_start( hbox, FALSE, FALSE, 0 );
94 auto frame = ui::Frame( "Type" );
95 hbox.pack_start( frame, TRUE, TRUE, 0 );
98 auto vbox2 = ui::VBox( FALSE, 5 );
100 gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 );
103 // -------------------------- //
105 fixed = gtk_radio_button_new_with_label( targetTypeRadio, "Fixed" );
106 vbox2.pack_start( fixed, FALSE, FALSE, 3 );
108 targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( fixed ) );
110 interpolated = gtk_radio_button_new_with_label( targetTypeRadio, "Interpolated" );
111 vbox2.pack_start( interpolated, FALSE, FALSE, 3 );
113 targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( interpolated ) );
115 spline = gtk_radio_button_new_with_label( targetTypeRadio, "Spline" );
116 vbox2.pack_start( spline, FALSE, FALSE, 3 );
118 targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( spline ) );
120 // -------------------------- //
122 w = gtk_hseparator_new();
123 vbox.pack_start( w, FALSE, FALSE, 2 );
126 // -------------------------- //
128 hbox = ui::HBox( FALSE, 5 );
129 vbox.pack_start( hbox, FALSE, FALSE, 0 );
132 w = ui::Button( "Ok" );
133 hbox.pack_start( w, TRUE, TRUE, 0 );
134 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
137 gtk_widget_set_can_default( w, true );
138 gtk_widget_grab_default( w );
140 w = ui::Button( "Cancel" );
141 hbox.pack_start( w, TRUE, TRUE, 0 );
142 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
146 // -------------------------- //
148 gtk_window_set_position( window, GTK_WIN_POS_CENTER );
150 gtk_grab_add( window );
152 bool dialogError = TRUE;
153 while ( dialogError ) {
156 gtk_main_iteration();
160 if ( ret == eIDOK ) {
161 if ( gtk_toggle_button_get_active( (GtkToggleButton*)fixed ) ) {
164 else if ( gtk_toggle_button_get_active( (GtkToggleButton*)interpolated ) ) {
165 DoNewInterpolatedCamera();
167 else if ( gtk_toggle_button_get_active( (GtkToggleButton*)spline ) ) {
173 gtk_grab_remove( window );
179 static gint ci_load( GtkWidget *widget, gpointer data ){
185 static gint ci_save( GtkWidget *widget, gpointer data ){
191 static gint ci_unload( GtkWidget *widget, gpointer data ){
197 static gint ci_apply( GtkWidget *widget, gpointer data ){
198 if ( GetCurrentCam() ) {
203 str = gtk_entry_get_text( GTK_ENTRY( g_pCamName ) );
206 GetCurrentCam()->GetCam()->setName( str );
210 str = gtk_entry_get_text( GTK_ENTRY( g_pSecondsEntry ) );
213 GetCurrentCam()->GetCam()->setBaseTime( atof( str ) );
218 GetCurrentCam()->GetCam()->buildCamera();
221 sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime() );
222 gtk_entry_set_text( GTK_ENTRY( g_pSecondsEntry ), buf );
224 sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime() );
225 gtk_label_set_text( g_pCurrentTime, "0.00" );
226 gtk_label_set_text( g_pTotalTime, buf );
228 gtk_adjustment_set_value( g_pTimeLine, 0.f );
229 g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000;
231 GetCurrentCam()->HasBeenModified();
237 static gint ci_preview( GtkWidget *widget, gpointer data ){
238 if ( GetCurrentCam() ) {
239 g_iPreviewRunning = 1;
240 g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA );
246 static gint ci_expose( GtkWidget *widget, gpointer data ){
248 DoStartEdit( GetCurrentCam() );
253 static gint ci_close( GtkWidget *widget, gpointer data ){
254 gtk_widget_hide( g_pCameraInspectorWnd );
262 static GtkWidget *g_pPathListCombo = NULL;
263 static GtkLabel *g_pPathType = NULL;
265 static void RefreshPathListCombo( void ){
266 if ( !g_pPathListCombo ) {
270 GList *combo_list = (GList*)NULL;
272 if ( GetCurrentCam() ) {
273 combo_list = g_list_append( combo_list, (void *)GetCurrentCam()->GetCam()->getPositionObj()->getName() );
274 for ( int i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++ ) {
275 combo_list = g_list_append( combo_list, (void *)GetCurrentCam()->GetCam()->getActiveTarget( i )->getName() );
279 // add one empty string make gtk be quiet
280 combo_list = g_list_append( combo_list, (gpointer)g_cNull );
283 gtk_combo_set_popdown_strings( GTK_COMBO( g_pPathListCombo ), combo_list );
284 g_list_free( combo_list );
287 static gint ci_pathlist_changed( GtkWidget *widget, gpointer data ){
288 const char *str = gtk_entry_get_text( GTK_ENTRY( widget ) );
290 if ( !str || !GetCurrentCam() ) {
295 for ( i = 0; i < GetCurrentCam()->GetCam()->numTargets(); i++ ) {
296 if ( !strcmp( str, GetCurrentCam()->GetCam()->getActiveTarget( i )->getName() ) ) {
301 if ( i >= 0 && i < GetCurrentCam()->GetCam()->numTargets() ) {
302 GetCurrentCam()->GetCam()->setActiveTarget( i );
306 gtk_label_set_text( g_pPathType, GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->typeStr() );
310 g_iActiveTarget = -1;
312 gtk_label_set_text( g_pPathType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr() );
317 if ( g_pCameraInspectorWnd && gtk_widget_get_visible( g_pCameraInspectorWnd ) ) {
318 DoStartEdit( GetCurrentCam() );
324 static void RefreshEventList( void ){
329 gtk_clist_freeze( GTK_CLIST( g_pEventsList ) );
330 gtk_clist_clear( GTK_CLIST( g_pEventsList ) );
332 if ( GetCurrentCam() ) {
334 for ( i = 0; i < GetCurrentCam()->GetCam()->numEvents(); i++ ) {
335 char rowbuf[3][128], *row[3];
336 // FIXME: sort by time?
337 sprintf( rowbuf[0], "%li", GetCurrentCam()->GetCam()->getEvent( i )->getTime() ); row[0] = rowbuf[0];
338 strncpy( rowbuf[1], GetCurrentCam()->GetCam()->getEvent( i )->typeStr(), sizeof( rowbuf[0] ) ); row[1] = rowbuf[1];
339 strncpy( rowbuf[2], GetCurrentCam()->GetCam()->getEvent( i )->getParam(), sizeof( rowbuf[1] ) ); row[2] = rowbuf[2];
340 gtk_clist_append( GTK_CLIST( g_pEventsList ), row );
343 // Total duration might have changed
344 sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime() );
345 gtk_label_set_text( g_pCurrentTime, "0.00" );
346 gtk_label_set_text( g_pTotalTime, buf );
348 gtk_adjustment_set_value( g_pTimeLine, 0.f );
349 g_pTimeLine->upper = ( GetCurrentCam()->GetCam()->getTotalTime() * 1000 );
352 gtk_clist_thaw( GTK_CLIST( g_pEventsList ) );
355 static gint ci_rename( GtkWidget *widget, gpointer data ){
356 GtkWidget *w, *hbox, *name;
357 EMessageBoxReturn ret;
360 if ( !GetCurrentCam() ) {
365 auto window = ui::Window( ui::window_type::TOP );
366 gtk_window_set_title( window, "Rename Path" );
367 window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
368 window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
369 gtk_window_set_transient_for( window, g_pCameraInspectorWnd );
371 g_object_set_data( G_OBJECT( window ), "loop", &loop );
372 g_object_set_data( G_OBJECT( window ), "ret", &ret );
374 gtk_widget_realize( window );
377 auto vbox = ui::VBox( FALSE, 5 );
381 // -------------------------- //
383 hbox = ui::HBox( FALSE, 5 );
384 vbox.pack_start( hbox, FALSE, FALSE, 0 );
387 w = ui::Label( "Name:" );
388 hbox.pack_start( w, FALSE, FALSE, 0 );
392 hbox.pack_start( name, FALSE, FALSE, 0 );
395 if ( g_iActiveTarget < 0 ) {
396 gtk_entry_set_text( GTK_ENTRY( name ), GetCurrentCam()->GetCam()->getPositionObj()->getName() );
399 gtk_entry_set_text( GTK_ENTRY( name ), GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->getName() );
402 // -------------------------- //
404 w = gtk_hseparator_new();
405 vbox.pack_start( w, FALSE, FALSE, 2 );
408 // -------------------------- //
410 hbox = ui::HBox( FALSE, 5 );
411 vbox.pack_start( hbox, FALSE, FALSE, 0 );
414 w = ui::Button( "Ok" );
415 hbox.pack_start( w, TRUE, TRUE, 0 );
416 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
419 gtk_widget_set_can_default( w, true );
420 gtk_widget_grab_default( w );
422 w = ui::Button( "Cancel" );
423 hbox.pack_start( w, TRUE, TRUE, 0 );
424 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
428 // -------------------------- //
430 gtk_window_set_position( window, GTK_WIN_POS_CENTER );
432 gtk_grab_add( window );
434 bool dialogError = TRUE;
435 while ( dialogError ) {
438 gtk_main_iteration();
442 if ( ret == eIDOK ) {
443 const char *str = gtk_entry_get_text( GTK_ENTRY( name ) );
445 if ( str && str[0] ) {
447 if ( g_iActiveTarget < 0 ) {
448 GetCurrentCam()->GetCam()->getPositionObj()->setName( str );
451 GetCurrentCam()->GetCam()->getActiveTarget( g_iActiveTarget )->setName( str );
454 GetCurrentCam()->GetCam()->buildCamera();
456 // Rebuild the listbox
457 RefreshPathListCombo();
465 gtk_grab_remove( window );
471 static gint ci_add_target( GtkWidget *widget, gpointer data ){
472 GtkWidget *w, *hbox, *name;
473 GtkWidget *fixed, *interpolated, *spline;
474 EMessageBoxReturn ret;
476 GSList *targetTypeRadio = NULL;
479 if ( !GetCurrentCam() ) {
484 auto window = ui::Window( ui::window_type::TOP );
485 gtk_window_set_title( window, "Add Target" );
486 window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
487 window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
488 gtk_window_set_transient_for( window, g_pCameraInspectorWnd );
490 g_object_set_data( G_OBJECT( window ), "loop", &loop );
491 g_object_set_data( G_OBJECT( window ), "ret", &ret );
493 gtk_widget_realize( window );
496 auto vbox = ui::VBox( FALSE, 5 );
500 // -------------------------- //
502 hbox = ui::HBox( FALSE, 5 );
503 vbox.pack_start( hbox, FALSE, FALSE, 0 );
506 w = ui::Label( "Name:" );
507 hbox.pack_start( w, FALSE, FALSE, 0 );
511 hbox.pack_start( name, TRUE, TRUE, 0 );
514 sprintf( buf, "target%i", GetCurrentCam()->GetCam()->numTargets() + 1 );
515 gtk_entry_set_text( GTK_ENTRY( name ), buf );
517 // -------------------------- //
519 hbox = ui::HBox( FALSE, 5 );
520 vbox.pack_start( hbox, FALSE, FALSE, 0 );
523 auto frame = ui::Frame( "Type" );
524 hbox.pack_start( frame, TRUE, TRUE, 0 );
527 auto vbox2 = ui::VBox( FALSE, 5 );
529 gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 );
532 // -------------------------- //
534 fixed = gtk_radio_button_new_with_label( targetTypeRadio, "Fixed" );
535 vbox2.pack_start( fixed, FALSE, FALSE, 3 );
537 targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( fixed ) );
539 interpolated = gtk_radio_button_new_with_label( targetTypeRadio, "Interpolated" );
540 vbox2.pack_start( interpolated, FALSE, FALSE, 3 );
542 targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( interpolated ) );
544 spline = gtk_radio_button_new_with_label( targetTypeRadio, "Spline" );
545 vbox2.pack_start( spline, FALSE, FALSE, 3 );
547 targetTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( spline ) );
549 // -------------------------- //
551 w = gtk_hseparator_new();
552 vbox.pack_start( w, FALSE, FALSE, 2 );
555 // -------------------------- //
557 hbox = ui::HBox( FALSE, 5 );
558 vbox.pack_start( hbox, FALSE, FALSE, 0 );
561 w = ui::Button( "Ok" );
562 hbox.pack_start( w, TRUE, TRUE, 0 );
563 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
566 gtk_widget_set_can_default( w, true );
567 gtk_widget_grab_default( w );
569 w = ui::Button( "Cancel" );
570 hbox.pack_start( w, TRUE, TRUE, 0 );
571 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
575 // -------------------------- //
577 gtk_window_set_position( window, GTK_WIN_POS_CENTER );
579 gtk_grab_add( window );
581 bool dialogError = TRUE;
582 while ( dialogError ) {
585 gtk_main_iteration();
589 if ( ret == eIDOK ) {
590 const char *str = gtk_entry_get_text( GTK_ENTRY( name ) );
592 if ( str && str[0] ) {
596 if ( gtk_toggle_button_get_active( (GtkToggleButton*)fixed ) ) {
599 else if ( gtk_toggle_button_get_active( (GtkToggleButton*)interpolated ) ) {
602 else if ( gtk_toggle_button_get_active( (GtkToggleButton*)spline ) ) {
607 GetCurrentCam()->GetCam()->addTarget( str, static_cast<idCameraPosition::positionType>( type ) );
609 // Rebuild the listbox
610 RefreshPathListCombo();
612 // Select the last item in the listbox
613 li = g_list_last( GTK_LIST( GTK_COMBO( g_pPathListCombo )->list )->children );
614 gtk_list_select_child( GTK_LIST( GTK_COMBO( g_pPathListCombo )->list ), li->data );
616 // If this was the first one, refresh the event list
617 if ( GetCurrentCam()->GetCam()->numTargets() == 1 ) {
621 // Go to editmode Add
622 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_pEditModeAddRadioButton ), TRUE );
631 gtk_grab_remove( window );
637 static GtkWidget *g_pCamListCombo = NULL;
638 static GtkLabel *g_pCamType = NULL;
640 void RefreshCamListCombo( void ){
641 if ( !g_pCamListCombo ) {
645 GList *combo_list = (GList*)NULL;
646 CCamera *combo_cam = firstCam;
648 while ( combo_cam ) {
649 //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() );
650 //if( combo_cam->HasBeenSaved() ) {
651 combo_list = g_list_append( combo_list, (void *)combo_cam->GetFileName() );
654 sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() );
655 combo_list = g_list_append( combo_list, (void *)buf );
657 //combo_list = g_list_append( combo_list, (void *)combo_cam->GetCam()->getName() ); // FIXME: this requires camera.dll to create unique names for new cams
659 combo_cam = combo_cam->GetNext();
663 // add one empty string make gtk be quiet
664 combo_list = g_list_append( combo_list, (gpointer)g_cNull );
666 gtk_combo_set_popdown_strings( GTK_COMBO( g_pCamListCombo ), combo_list );
667 g_list_free( combo_list );
669 // select our current entry in the list
670 if ( GetCurrentCam() ) {
671 // stop editing on the current cam
672 //GetCurrentCam()->GetCam()->stopEdit(); // FIXME: this crashed on creating new cameras, why is it here?
674 GList *li = GTK_LIST( GTK_COMBO( g_pCamListCombo )->list )->children;
675 combo_cam = firstCam;
676 while ( li && combo_cam ) {
677 if ( combo_cam == GetCurrentCam() ) {
678 gtk_list_select_child( GTK_LIST( GTK_COMBO( g_pCamListCombo )->list ), li->data );
682 combo_cam = combo_cam->GetNext();
686 RefreshPathListCombo();
689 static gint ci_camlist_changed( GtkWidget *widget, gpointer data ){
690 const char *str = gtk_entry_get_text( GTK_ENTRY( widget ) );
692 CCamera *combo_cam = firstCam;
693 while ( str && combo_cam ) {
694 //if( !strcmp( str, combo_cam->GetCam()->getName() ) )
695 //if( combo_cam->HasBeenSaved() ) {
696 if ( !strcmp( str, combo_cam->GetFileName() ) ) {
701 sprintf( buf, "Unsaved Camera %i", combo_cam->GetCamNum() );
702 if( !strcmp( str, buf ) )
703 //if( !strcmp( str, combo_cam->GetCam()->getName() ) )
707 combo_cam = combo_cam->GetNext();
710 SetCurrentCam( combo_cam );
713 if ( GetCurrentCam() ) {
714 // Fill in our widgets fields for this camera
718 gtk_entry_set_text( GTK_ENTRY( g_pCamName ), GetCurrentCam()->GetCam()->getName() );
721 gtk_label_set_text( g_pCamType, GetCurrentCam()->GetCam()->getPositionObj()->typeStr() );
724 sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getBaseTime() );
725 gtk_entry_set_text( GTK_ENTRY( g_pSecondsEntry ), buf );
727 sprintf( buf, "%.2f", GetCurrentCam()->GetCam()->getTotalTime() );
728 gtk_label_set_text( g_pCurrentTime, "0.00" );
729 gtk_label_set_text( g_pTotalTime, buf );
731 gtk_adjustment_set_value( g_pTimeLine, 0.f );
732 g_pTimeLine->upper = GetCurrentCam()->GetCam()->getTotalTime() * 1000;
736 gtk_entry_set_text( GTK_ENTRY( g_pCamName ), "" );
739 gtk_label_set_text( g_pCamType, "" );
742 gtk_entry_set_text( GTK_ENTRY( g_pSecondsEntry ), "30.00" );
744 gtk_label_set_text( g_pCurrentTime, "0.00" );
745 gtk_label_set_text( g_pTotalTime, "30.00" );
747 gtk_adjustment_set_value( g_pTimeLine, 0.f );
748 g_pTimeLine->upper = 30000;
751 // Refresh event list
755 RefreshPathListCombo();
758 g_iActiveTarget = -1;
759 if ( g_pCameraInspectorWnd && gtk_widget_get_visible( g_pCameraInspectorWnd ) ) {
760 DoStartEdit( GetCurrentCam() );
771 EVENT_TARGET, // char(name)
773 EVENT_FOV, // int(time), int(targetfov)
778 EVENT_FADEOUT, // int(time)
779 EVENT_FADEIN, // int(time)
784 // { requires parameters, enabled }
785 const bool camEventFlags[][2] = {
802 const char *camEventStr[] = {
807 "Change Target <string:name>",
809 "FOV <int:duration> <int:targetfov>",
813 "Change to Camera <string:camera> (or <int:cameranum> <string:camera>",
814 "Fade Out <int:duration>",
815 "Fade In <int:duration>",
819 static gint ci_add( GtkWidget *widget, gpointer data ){
820 GtkWidget *w, *hbox, *parameters;
821 GtkWidget *eventWidget[EVENT_COUNT];
822 EMessageBoxReturn ret;
824 GSList *eventTypeRadio = NULL;
827 if ( !GetCurrentCam() ) {
832 auto window = ui::Window( ui::window_type::TOP );
833 gtk_window_set_title( window, "Add Event" );
834 window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
835 window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
836 gtk_window_set_transient_for( window, g_pCameraInspectorWnd );
838 g_object_set_data( G_OBJECT( window ), "loop", &loop );
839 g_object_set_data( G_OBJECT( window ), "ret", &ret );
841 gtk_widget_realize( window );
844 auto vbox = ui::VBox( FALSE, 5 );
848 // -------------------------- //
850 hbox = ui::HBox( FALSE, 5 );
851 vbox.pack_start( hbox, FALSE, FALSE, 0 );
854 auto frame = ui::Frame( "Type" );
855 hbox.pack_start( frame, TRUE, TRUE, 0 );
858 auto vbox2 = ui::VBox( FALSE, 5 );
860 gtk_container_set_border_width( GTK_CONTAINER( vbox2 ), 5 );
863 // -------------------------- //
865 for ( i = 1; i < EVENT_COUNT; i++ ) {
866 eventWidget[i] = gtk_radio_button_new_with_label( eventTypeRadio, camEventStr[i] );
867 vbox2.pack_start( eventWidget[i], FALSE, FALSE, 3 );
868 eventWidget[i].show();
869 eventTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( eventWidget[i] ) );
870 if ( camEventFlags[i][1] == false ) {
871 gtk_widget_set_sensitive( eventWidget[i], FALSE );
875 // -------------------------- //
877 hbox = ui::HBox( FALSE, 5 );
878 vbox.pack_start( hbox, FALSE, FALSE, 0 );
881 w = ui::Label( "Parameters:" );
882 hbox.pack_start( w, FALSE, FALSE, 0 );
885 parameters = ui::Entry();
886 hbox.pack_start( parameters, TRUE, TRUE, 0 );
889 // -------------------------- //
891 w = gtk_hseparator_new();
892 vbox.pack_start( w, FALSE, FALSE, 2 );
895 // -------------------------- //
897 hbox = ui::HBox( FALSE, 5 );
898 vbox.pack_start( hbox, FALSE, FALSE, 0 );
901 w = ui::Button( "Ok" );
902 hbox.pack_start( w, TRUE, TRUE, 0 );
903 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
906 gtk_widget_set_can_default( w, true );
907 gtk_widget_grab_default( w );
909 w = ui::Button( "Cancel" );
910 hbox.pack_start( w, TRUE, TRUE, 0 );
911 w.connect( "clicked", G_CALLBACK( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
915 // -------------------------- //
917 gtk_window_set_position( window, GTK_WIN_POS_CENTER );
919 gtk_grab_add( window );
921 bool dialogError = TRUE;
922 while ( dialogError ) {
925 gtk_main_iteration();
929 if ( ret == eIDOK ) {
930 const char *str = gtk_entry_get_text( GTK_ENTRY( parameters ) );
932 if ( !camEventFlags[i][0] || ( str && str[0] ) ) {
936 for ( type = 1; type < EVENT_COUNT; type++ ) {
937 if ( gtk_toggle_button_get_active( (GtkToggleButton*)eventWidget[type] ) ) {
943 GetCurrentCam()->GetCam()->addEvent( static_cast<idCameraEvent::eventType>( type ), str, (long)( g_pTimeLine->value ) );
945 // Refresh event list
954 gtk_grab_remove( window );
960 static gint ci_del( GtkWidget *widget, gpointer data ){
961 // TODO: add support to splines lib
962 if ( GetCurrentCam() && GTK_CLIST( g_pEventsList )->focus_row >= 0 ) {
963 GetCurrentCam()->GetCam()->removeEvent( GTK_CLIST( g_pEventsList )->focus_row );
964 // Refresh event list
971 static gint ci_timeline_changed( GtkAdjustment *adjustment ){
974 sprintf( buf, "%.2f", adjustment->value / 1000.f );
975 gtk_label_set_text( g_pCurrentTime, buf );
977 // FIXME: this will never work completely perfect. Startcamera calls buildcamera, which sets all events to 'nottriggered'.
978 // 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
979 // will have no idea where on the track it should be.
980 if ( GetCurrentCam() && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( g_pTrackCamera ) ) ) {
982 vec3_t origin = { 0.0f, 0.0f, 0.0f }, dir = { 0.0f, 0.0f, 0.0f}, angles;
984 GetCurrentCam()->GetCam()->startCamera( 0 );
986 GetCurrentCam()->GetCam()->getCameraInfo( (long)( adjustment->value ), &origin[0], &dir[0], &fov );
987 VectorSet( angles, asin( dir[2] ) * 180 / 3.14159, atan2( dir[1], dir[0] ) * 180 / 3.14159, 0 );
988 g_CameraTable.m_pfnSetCamera( origin, angles );
994 GtkWidget *CreateCameraInspectorDialog( void ){
998 auto window = ui::Window( ui::window_type::TOP );
999 gtk_window_set_title( window, "Camera Inspector" );
1000 window.connect( "delete_event", G_CALLBACK( ci_close ), NULL );
1001 window.connect( "expose_event", G_CALLBACK( ci_expose ), NULL );
1002 // window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
1003 gtk_window_set_transient_for( window, g_pRadiantWnd );
1005 // don't use show, as you don't want to have it displayed on startup ;-)
1006 gtk_widget_realize( window );
1011 // -------------------------- //
1013 auto table = ui::Table( 3, 2, FALSE );
1016 gtk_container_set_border_width( GTK_CONTAINER( table ), 5 );
1017 gtk_table_set_row_spacings(table, 5);
1018 gtk_table_set_col_spacings(table, 5);
1020 // the properties column
1021 // -------------------------- //
1023 vbox = ui::VBox( FALSE, 5 );
1025 table.attach(vbox, {0, 1, 0, 1}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1027 // -------------------------- //
1029 hbox = ui::HBox( FALSE, 5 );
1030 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1033 w = ui::Label( "File:" );
1034 hbox.pack_start( w, FALSE, FALSE, 0 );
1037 g_pCamListCombo = gtk_combo_new();
1038 hbox.pack_start( g_pCamListCombo, TRUE, TRUE, 0 );
1039 g_pCamListCombo.show();
1041 // -------------------------- //
1043 hbox = ui::HBox( FALSE, 5 );
1044 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1047 w = ui::Label( "Name:" );
1048 hbox.pack_start( w, FALSE, FALSE, 0 );
1051 g_pCamName = ui::Entry();
1052 hbox.pack_start( g_pCamName, FALSE, FALSE, 0 );
1055 w = ui::Label( "Type: " );
1056 hbox.pack_start( w, FALSE, FALSE, 0 );
1059 w = ui::Label( "" );
1060 hbox.pack_start( w, FALSE, FALSE, 0 );
1062 g_pCamType = GTK_LABEL( w );
1064 RefreshCamListCombo();
1066 gtk_editable_set_editable( GTK_EDITABLE( GTK_COMBO( g_pCamListCombo )->entry ), FALSE );
1067 ( GTK_COMBO( g_pCamListCombo )->entry ).connect( "changed", G_CALLBACK( ci_camlist_changed ), NULL );
1069 // -------------------------- //
1071 auto frame = ui::Frame( "Path and Target editing" );
1073 table.attach(frame, {0, 1, 1, 2}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1075 auto vbox = ui::VBox( FALSE, 5 );
1077 gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1080 // -------------------------- //
1082 hbox = ui::HBox( FALSE, 5 );
1083 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1086 w = ui::Label( "Edit:" );
1087 hbox.pack_start( w, FALSE, FALSE, 0 );
1090 g_pPathListCombo = gtk_combo_new();
1091 hbox.pack_start( g_pPathListCombo, TRUE, TRUE, 0 );
1092 g_pPathListCombo.show();
1094 RefreshPathListCombo();
1096 gtk_editable_set_editable( GTK_EDITABLE( GTK_COMBO( g_pPathListCombo )->entry ), FALSE );
1097 ( GTK_COMBO( g_pPathListCombo )->entry ).connect( "changed", G_CALLBACK( ci_pathlist_changed ), NULL );
1099 // -------------------------- //
1101 hbox = ui::HBox( FALSE, 5 );
1102 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1105 g_pEditModeEditRadioButton = gtk_radio_button_new_with_label( g_pEditTypeRadio, "Edit Points" );
1106 hbox.pack_start( g_pEditModeEditRadioButton, FALSE, FALSE, 3 );
1107 g_pEditModeEditRadioButton.show();
1108 g_pEditTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( g_pEditModeEditRadioButton ) );
1110 g_pEditModeEditRadioButton.connect( "clicked", G_CALLBACK( ci_editmode_edit ), NULL );
1112 g_pEditModeAddRadioButton = gtk_radio_button_new_with_label( g_pEditTypeRadio, "Add Points" );
1113 hbox.pack_start( g_pEditModeAddRadioButton, FALSE, FALSE, 3 );
1114 g_pEditModeAddRadioButton.show();
1115 g_pEditTypeRadio = gtk_radio_button_get_group( GTK_RADIO_BUTTON( g_pEditModeAddRadioButton ) );
1117 g_pEditModeAddRadioButton.connect( "clicked", G_CALLBACK( ci_editmode_add ), NULL );
1119 // see if we should use a different default
1120 if ( g_iEditMode == 1 ) {
1121 // Go to editmode Add
1122 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_pEditModeAddRadioButton ), TRUE );
1125 w = ui::Label( "Type: " );
1126 hbox.pack_start( w, FALSE, FALSE, 0 );
1129 w = ui::Label( "" );
1130 hbox.pack_start( w, FALSE, FALSE, 0 );
1132 g_pPathType = GTK_LABEL( w );
1134 // -------------------------- //
1136 hbox = ui::HBox( FALSE, 5 );
1137 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1140 w = ui::Button( "Rename..." );
1141 hbox.pack_start( w, FALSE, TRUE, 0 );
1142 w.connect( "clicked", G_CALLBACK( ci_rename ), NULL );
1145 w = ui::Button( "Add Target..." );
1146 hbox.pack_start( w, FALSE, TRUE, 0 );
1147 w.connect( "clicked", G_CALLBACK( ci_add_target ), NULL );
1150 // not available in splines library
1151 /*w = gtk_button_new_with_label( "Delete Selected" );
1152 hbox.pack_start( w, FALSE, TRUE, 0);
1153 w.connect( "clicked", G_CALLBACK( ci_delete_selected ), NULL );
1156 w = gtk_button_new_with_label( "Select All" );
1157 hbox.pack_start( w, FALSE, TRUE, 0);
1158 w.connect( "clicked", G_CALLBACK( ci_select_all ), NULL );
1161 // -------------------------- //
1163 frame = ui::Frame( "Time" );
1165 table.attach(frame, {0, 1, 2, 3}, {GTK_EXPAND | GTK_FILL, GTK_FILL});
1167 vbox = ui::VBox( FALSE, 5 );
1169 gtk_container_set_border_width( GTK_CONTAINER( vbox ), 5 );
1172 // -------------------------- //
1174 hbox = ui::HBox( FALSE, 5 );
1175 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1178 w = ui::Label( "Length (seconds):" );
1179 hbox.pack_start( w, FALSE, FALSE, 0 );
1182 g_pSecondsEntry = ui::Entry();
1183 hbox.pack_start( g_pSecondsEntry, FALSE, FALSE, 0 );
1184 g_pSecondsEntry.show();
1186 // -------------------------- //
1188 hbox = ui::HBox( FALSE, 5 );
1189 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1192 w = ui::Label( "Current Time: " );
1193 hbox.pack_start( w, FALSE, FALSE, 0 );
1196 w = ui::Label( "0.00" );
1197 hbox.pack_start( w, FALSE, FALSE, 0 );
1199 g_pCurrentTime = GTK_LABEL( w );
1201 w = ui::Label( " of " );
1202 hbox.pack_start( w, FALSE, FALSE, 0 );
1205 w = ui::Label( "0.00" );
1206 hbox.pack_start( w, FALSE, FALSE, 0 );
1208 g_pTotalTime = GTK_LABEL( w );
1210 // -------------------------- //
1212 hbox = ui::HBox( FALSE, 5 );
1213 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1216 g_pTimeLine = ui::Adjustment( 0, 0, 30000, 100, 250, 0 );
1217 g_pTimeLine.connect( "value_changed", G_CALLBACK( ci_timeline_changed ), NULL );
1218 w = ui::HScale( g_pTimeLine );
1219 hbox.pack_start( w, TRUE, TRUE, 0 );
1221 gtk_scale_set_draw_value( GTK_SCALE( w ), FALSE );
1223 // -------------------------- //
1225 hbox = ui::HBox( FALSE, 5 );
1226 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1229 g_pTrackCamera = ui::CheckButton( "Track Camera" );
1230 hbox.pack_start( g_pTrackCamera, FALSE, FALSE, 0 );
1231 g_pTrackCamera.show();
1233 // -------------------------- //
1235 hbox = ui::HBox( FALSE, 5 );
1236 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1239 w = ui::Label( "Events:" );
1240 hbox.pack_start( w, FALSE, FALSE, 0 );
1243 // -------------------------- //
1245 hbox = ui::HBox( FALSE, 5 );
1246 vbox.pack_start( hbox, FALSE, FALSE, 0 );
1249 auto scr = w = ui::ScrolledWindow();
1250 w.dimensions( 0, 150 );
1251 gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( w ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
1252 hbox.pack_start( w, TRUE, TRUE, 0 );
1255 g_pEventsList = gtk_clist_new( 3 );
1256 scr.add(g_pEventsList);
1257 //g_pEventsList.connect( "select_row", G_CALLBACK (proplist_select_row), NULL);
1258 gtk_clist_set_selection_mode( GTK_CLIST( g_pEventsList ), GTK_SELECTION_BROWSE );
1259 gtk_clist_column_titles_hide( GTK_CLIST( g_pEventsList ) );
1260 gtk_clist_set_column_auto_resize( GTK_CLIST( g_pEventsList ), 0, TRUE );
1261 gtk_clist_set_column_auto_resize( GTK_CLIST( g_pEventsList ), 1, TRUE );
1262 gtk_clist_set_column_auto_resize( GTK_CLIST( g_pEventsList ), 2, TRUE );
1263 g_pEventsList.show();
1265 vbox = ui::VBox( FALSE, 5 );
1266 hbox.pack_start( vbox, FALSE, FALSE, 0 );
1269 w = ui::Button( "Add..." );
1270 vbox.pack_start( w, FALSE, FALSE, 0 );
1271 w.connect( "clicked", G_CALLBACK( ci_add ), NULL );
1274 w = ui::Button( "Del" );
1275 vbox.pack_start( w, FALSE, FALSE, 0 );
1276 w.connect( "clicked", G_CALLBACK( ci_del ), NULL );
1279 // -------------------------- //
1287 // the buttons column
1288 // -------------------------- //
1290 vbox = gtk_vbox_new( FALSE, 5 );
1292 table.attach(vbox, {1, 2, 0, 1}, {GTK_FILL, GTK_FILL});
1294 w = gtk_button_new_with_label( "New..." );
1295 vbox.pack_start( w, FALSE, FALSE, 0 );
1296 w.connect( "clicked", G_CALLBACK( ci_new ), NULL );
1299 w = gtk_button_new_with_label( "Load..." );
1300 vbox.pack_start( w, FALSE, FALSE, 0 );
1301 w.connect( "clicked", G_CALLBACK( ci_load ), NULL );
1304 // -------------------------- //
1306 vbox = gtk_vbox_new( FALSE, 5 );
1308 table.attach( vbox, {1, 2, 1, 2}, {GTK_FILL, GTK_FILL});
1310 w = gtk_button_new_with_label( "Save..." );
1311 vbox.pack_start( w, FALSE, FALSE, 0 );
1312 w.connect( "clicked", G_CALLBACK( ci_save ), NULL );
1315 w = gtk_button_new_with_label( "Unload" );
1316 vbox.pack_start( w, FALSE, FALSE, 0 );
1317 w.connect( "clicked", G_CALLBACK( ci_unload ), NULL );
1320 hbox = gtk_hbox_new( FALSE, 5 );
1321 vbox.pack_start( hbox, TRUE, TRUE, 0 );
1324 w = gtk_button_new_with_label( "Apply" );
1325 vbox.pack_start( w, FALSE, FALSE, 0 );
1326 w.connect( "clicked", G_CALLBACK( ci_apply ), NULL );
1329 w = gtk_button_new_with_label( "Preview" );
1330 vbox.pack_start( w, FALSE, FALSE, 0 );
1331 w.connect( "clicked", G_CALLBACK( ci_preview ), NULL );
1334 // -------------------------- //
1336 vbox = gtk_vbox_new( FALSE, 5 );
1338 table.attach(vbox, {1, 2, 2, 3}, {GTK_FILL, GTK_FILL});
1340 hbox = gtk_hbox_new( FALSE, 5 );
1341 vbox.pack_start( hbox, TRUE, TRUE, 0 );
1344 w = gtk_button_new_with_label( "Close" );
1345 vbox.pack_start( w, FALSE, FALSE, 0 );
1346 w.connect( "clicked", G_CALLBACK( ci_close ), NULL );
1347 gtk_widget_set_can_default( w, true );
1348 gtk_widget_grab_default( w );
1351 // -------------------------- //