radiant/texwindow: fix crash when assigning a tag, fix #146
[xonotic/netradiant.git] / contrib / camera / funchandlers.cpp
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
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.
11
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.
16
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
20  */
21
22 /*
23    Camera plugin for GtkRadiant
24    Copyright (C) 2002 Splash Damage Ltd.
25  */
26
27 #include "camera.h"
28 #include "globaldefs.h"
29
30 extern GtkWidget *g_pEditModeAddRadioButton;
31
32 char* Q_realpath( const char *path, char *resolved_path, size_t size ){
33 #if GDEF_OS_POSIX
34         return realpath( path, resolved_path );
35 #elif GDEF_OS_WINDOWS
36         return _fullpath( resolved_path, path, size );
37 #else
38 #error "unsupported platform"
39 #endif
40 }
41
42 static void DoNewCamera( idCameraPosition::positionType type ){
43         CCamera *cam = AllocCam();
44
45         if ( cam ) {
46                 char buf[128];
47                 sprintf( buf, "camera%i", cam->GetCamNum() );
48
49                 cam->GetCam()->startNewCamera( type );
50                 cam->GetCam()->setName( buf );
51                 cam->GetCam()->buildCamera();
52
53                 sprintf( buf, "Unsaved Camera %i", cam->GetCamNum() );
54                 cam->SetFileName( buf, false );
55
56                 SetCurrentCam( cam );
57                 RefreshCamListCombo();
58
59                 // Go to editmode Add
60                 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( g_pEditModeAddRadioButton ), TRUE );
61
62                 // Show the camera inspector
63                 DoCameraInspector();
64
65                 // Start edit mode (if not initiated by DoCameraInspector)
66                 if ( !g_bEditOn ) {
67                         DoStartEdit( GetCurrentCam() );
68                 }
69         }
70         else {
71                 g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, "No free cameras available.", "Create Camera Error", eMB_OK );
72         }
73 }
74
75 void DoNewFixedCamera(){
76         DoNewCamera( idCameraPosition::FIXED );
77 }
78
79 void DoNewInterpolatedCamera(){
80         DoNewCamera( idCameraPosition::INTERPOLATED );
81 }
82
83 void DoNewSplineCamera(){
84         DoNewCamera( idCameraPosition::SPLINE );
85 }
86
87 void DoCameraInspector(){
88         g_pCameraInspectorWnd.show();
89 }
90
91 void DoPreviewCamera(){
92         if ( GetCurrentCam() ) {
93                 g_iPreviewRunning = 1;
94                 g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA );
95         }
96 }
97
98 void DoLoadCamera(){
99         char basepath[PATH_MAX];
100
101         if ( firstCam && firstCam->HasBeenSaved() ) {
102                 ExtractFilePath( firstCam->GetFileName(), basepath );
103         }
104         else{
105                 strcpy( basepath, g_FuncTable.m_pfnGetGamePath() );
106         }
107
108         const gchar *filename = g_FuncTable.m_pfnFileDialog( (GtkWidget *)g_pRadiantWnd, TRUE, "Open Camera File", basepath, "camera" );
109
110         if ( filename ) {
111                 CCamera *cam = AllocCam();
112                 char fullpathtofile[PATH_MAX];
113
114                 if ( cam ) {
115                         Q_realpath( filename, fullpathtofile, PATH_MAX );
116
117                         // see if this camera file was already loaded
118                         CCamera *checkCam = firstCam->GetNext(); // not the first one as we just allocated it
119                         while ( checkCam ) {
120                                 if ( !strcmp( fullpathtofile, checkCam->GetFileName() ) ) {
121                                         char error[PATH_MAX + 64];
122                                         FreeCam( cam );
123                                         sprintf( error, "Camera file \'%s\' is already loaded", fullpathtofile );
124                                         g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, error, "Load error", eMB_OK );
125                                         //g_free( filename );
126                                         return;
127                                 }
128                                 checkCam = checkCam->GetNext();
129                         }
130
131                         if ( loadCamera( cam->GetCamNum(), fullpathtofile ) ) {
132                                 cam->GetCam()->buildCamera();
133                                 cam->SetFileName( filename, true );
134                                 SetCurrentCam( cam );
135                                 RefreshCamListCombo();
136                                 g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA );
137                         }
138                         else {
139                                 char error[PATH_MAX + 64];
140                                 FreeCam( cam );
141                                 sprintf( error, "An error occured during the loading of \'%s\'", fullpathtofile );
142                                 g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, error, "Load error", eMB_OK );
143                         }
144
145                         //g_free( filename );
146                 }
147                 else {
148                         g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, "No free camera slots available", "Load error", eMB_OK );
149                 }
150         }
151 }
152
153 void DoSaveCamera() {
154         char basepath[PATH_MAX];
155
156         if ( !GetCurrentCam() ) {
157                 return;
158         }
159
160         if ( GetCurrentCam()->GetFileName()[0] ) {
161                 ExtractFilePath( GetCurrentCam()->GetFileName(), basepath );
162         }
163         else{
164                 strcpy( basepath, g_FuncTable.m_pfnGetGamePath() );
165         }
166
167         const gchar *filename = g_FuncTable.m_pfnFileDialog( g_pRadiantWnd, FALSE, "Save Camera File", basepath, "camera" );
168
169         if ( filename ) {
170                 char fullpathtofile[PATH_MAX + 8];
171
172                 Q_realpath( filename, fullpathtofile, PATH_MAX );
173
174                 // File dialog from windows (and maybe the gtk one from radiant) doesn't handle default extensions properly.
175                 // Add extension and check again if file exists
176                 if ( strcmp( fullpathtofile + ( strlen( fullpathtofile ) - 7 ), ".camera" ) ) {
177                         strcat( fullpathtofile, ".camera" );
178
179                         if ( FileExists( fullpathtofile ) ) {
180                                 if ( g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, "File already exists.\nOverwrite?", "Save Camera File", eMB_YESNO ) == eIDNO ) {
181                                         return;
182                                 }
183                         }
184                 }
185
186                 // see if this camera file was already loaded
187                 CCamera *checkCam = firstCam;
188                 while ( checkCam ) {
189                         if ( checkCam == GetCurrentCam() ) {
190                                 checkCam = checkCam->GetNext();
191                                 if ( !checkCam ) { // we only have one camera file opened so no need to check further
192                                         break;
193                                 }
194                         }
195                         else if ( !strcmp( fullpathtofile, checkCam->GetFileName() ) ) {
196                                 char error[PATH_MAX + 64];
197                                 sprintf( error, "Camera file \'%s\' is currently loaded by " RADIANT_NAME "\nPlease select a different filename.", fullpathtofile );
198                                 g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, error, "Save error", eMB_OK );
199                                 return;
200                         }
201                         checkCam = checkCam->GetNext();
202                 }
203
204                 // FIXME: check for existing directory
205
206                 GetCurrentCam()->GetCam()->save( fullpathtofile );
207                 GetCurrentCam()->SetFileName( fullpathtofile, true );
208                 RefreshCamListCombo();
209         }
210 }
211
212 void DoUnloadCamera() {
213         if ( !GetCurrentCam() ) {
214                 return;
215         }
216
217         if ( !GetCurrentCam()->HasBeenSaved() ) {
218                 char buf[PATH_MAX + 64];
219                 sprintf( buf, "Do you want to save the changes for camera '%s'?", GetCurrentCam()->GetCam()->getName() );
220                 if ( g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, buf, "Warning", eMB_YESNO ) == eIDYES ) {
221                         DoSaveCamera();
222                 }
223         }
224         else if ( GetCurrentCam()->HasBeenSaved() == 2 ) {
225                 char buf[PATH_MAX + 64];
226                 sprintf( buf, "Do you want to save the changes made to camera file '%s'?", GetCurrentCam()->GetFileName() );
227                 if ( g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, buf, "Warning", eMB_YESNO ) == eIDYES ) {
228                         DoSaveCamera();
229                 }
230         }
231
232         if ( g_pCurrentEditCam ) {
233                 DoStopEdit();
234                 g_pCurrentEditCam = NULL;
235         }
236
237         FreeCam( GetCurrentCam() );
238         SetCurrentCam( NULL );
239         RefreshCamListCombo();
240 }
241
242 CCamera *g_pCurrentEditCam = NULL;
243
244 void DoStartEdit( CCamera *cam ) {
245         if ( g_pCurrentEditCam ) {
246                 DoStopEdit();
247                 g_pCurrentEditCam = NULL;
248         }
249
250         if ( cam ) {
251                 g_bEditOn = true;
252
253                 if ( !Listener ) {
254                         Listener = new CListener;
255                 }
256
257                 cam->GetCam()->startEdit( g_iActiveTarget < 0 ? true : false );
258
259                 g_pCurrentEditCam = cam;
260
261                 g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA );
262         }
263 }
264
265 void DoStopEdit( void ) {
266         g_bEditOn = false;
267
268         if ( Listener ) {
269                 delete Listener;
270                 Listener = NULL;
271         }
272
273         if ( g_pCurrentEditCam ) {
274                 // stop editing on the current cam
275                 g_pCurrentEditCam->GetCam()->stopEdit();
276                 g_pCurrentEditCam = NULL;
277
278                 g_FuncTable.m_pfnSysUpdateWindows( W_XY_OVERLAY | W_CAMERA );
279         }
280 }