]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/debriefingeditordlg.cpp
Initial revision
[taylor/freespace2.git] / src / fred2 / debriefingeditordlg.cpp
1 /*
2  * $Logfile: /Freespace2/code/FRED2/DebriefingEditorDlg.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Debriefing editor dialog.  Used to edit mission debriefings of course.
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:08  root
11  * Initial revision
12  *
13  * 
14  * 2     10/07/98 6:28p Dave
15  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
16  * Fred. Globalized mission and campaign file extensions. Removed Silent
17  * Threat specific code.
18  * 
19  * 1     10/07/98 3:01p Dave
20  * 
21  * 1     10/07/98 3:00p Dave
22  * 
23  * 20    7/07/98 2:09p Hoffoss
24  * Fixed bug where sexp for debriefing stages get cleared when inserting
25  * or deleting stages.
26  * 
27  * 19    4/30/98 8:23p John
28  * Fixed some bugs with Fred caused by my new cfile code.
29  * 
30  * 18    4/22/98 9:56a Sandeep
31  * 
32  * 17    4/20/98 4:40p Hoffoss
33  * Added a button to 4 editors to play the chosen wave file.
34  * 
35  * 16    4/17/98 1:41p Allender
36  * took out function calls in NDEBUG mode
37  * 
38  * 15    4/06/98 10:43a John
39  * Fixed bugs with inserting/deleting stages
40  * 
41  * 14    4/03/98 12:39p Hoffoss
42  * Changed starting directory for browse buttons in several editors.
43  * 
44  * 13    4/03/98 11:34a John
45  * Fixed the stuff I broke in Fred from the new breifing
46  * 
47  * 12    3/17/98 2:06p Hoffoss
48  * Made enter key not close the dialog box (default windows behavior, even
49  * when no ok button.  Talk about stupid. :)
50  * 
51  * 11    2/09/98 9:25p Allender
52  * team v team support.  multiple pools and breifings
53  * 
54  * 10    2/04/98 4:32p Allender
55  * support for multiple briefings and debriefings.  Changes to mission
56  * type (now a bitfield).  Bitfield defs for multiplayer modes
57  * 
58  * 9     1/02/98 3:29p Duncan
59  * Fixed bug with sexp tree freeing.
60  * 
61  * 8     11/10/97 12:09p Johnson
62  * Fixed sexp free error in debriefing editor.
63  * 
64  * 7     11/10/97 11:58a Johnson
65  * Added support to debriefing editor for "press cancel to go to reference
66  * of sexp".
67  * 
68  * 6     10/28/97 6:07p Jasen
69  * Added some debugging code to detect sexp leaks.  Looks there are some I
70  * will need to investigate more.
71  * 
72  * 5     10/27/97 2:06p Hoffoss
73  * Fixed editor to allow correct character limit for recommendation text.
74  * 
75  * 4     10/14/97 12:06p Hoffoss
76  * Recoded debriefing editor to utilize new format.
77  * 
78  * 3     10/14/97 10:35a Hoffoss
79  * Hacked the hell out of this file to allow Fred to compile for now.
80  * Next step is to fix it all.
81  * 
82  * 2     7/08/97 2:03p Hoffoss
83  * Debriefing editor coded and implemented.
84  *
85  * $NoKeywords: $
86  */
87
88 #include "stdafx.h"
89 #include <mmsystem.h>
90 #include "fred.h"
91 #include "debriefingeditordlg.h"
92 #include "freddoc.h"
93 #include "missionbriefcommon.h"
94 #include "sexp.h"
95 #include "cfile.h"
96
97 #ifdef _DEBUG
98 #define new DEBUG_NEW
99 #undef THIS_FILE
100 static char THIS_FILE[] = __FILE__;
101 #endif
102
103 /////////////////////////////////////////////////////////////////////////////
104 // debriefing_editor_dlg dialog
105
106 debriefing_editor_dlg::debriefing_editor_dlg(CWnd* pParent /*=NULL*/)
107         : CDialog(debriefing_editor_dlg::IDD, pParent)
108 {
109         //{{AFX_DATA_INIT(debriefing_editor_dlg)
110         m_text = _T("");
111         m_voice = _T("");
112         m_stage_title = _T("");
113         m_rec_text = _T("");
114         m_current_debriefing = -1;
115         //}}AFX_DATA_INIT
116
117         modified = 0;
118         m_cur_stage = 0;
119         m_last_stage = -1;
120         select_sexp_node = -1;
121 }
122
123 void debriefing_editor_dlg::DoDataExchange(CDataExchange* pDX)
124 {
125         CDialog::DoDataExchange(pDX);
126         //{{AFX_DATA_MAP(debriefing_editor_dlg)
127         DDX_Control(pDX, IDC_TREE, m_tree);
128         DDX_Text(pDX, IDC_TEXT, m_text);
129         DDX_Text(pDX, IDC_VOICE, m_voice);
130         DDX_Text(pDX, IDC_STAGE_TITLE, m_stage_title);
131         DDX_Text(pDX, IDC_REC_TEXT, m_rec_text);
132         //}}AFX_DATA_MAP
133
134         DDV_MaxChars(pDX, m_text, MAX_BRIEF_LEN - 1);
135         DDV_MaxChars(pDX, m_voice, MAX_FILENAME_LEN - 1);
136         DDV_MaxChars(pDX, m_rec_text, MAX_RECOMMENDATION_LEN - 1);
137 }
138
139 BEGIN_MESSAGE_MAP(debriefing_editor_dlg, CDialog)
140         //{{AFX_MSG_MAP(debriefing_editor_dlg)
141         ON_BN_CLICKED(IDC_NEXT, OnNext)
142         ON_BN_CLICKED(IDC_PREV, OnPrev)
143         ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
144         ON_BN_CLICKED(IDC_ADD_STAGE, OnAddStage)
145         ON_BN_CLICKED(IDC_DELETE_STAGE, OnDeleteStage)
146         ON_BN_CLICKED(IDC_INSERT_STAGE, OnInsertStage)
147         ON_NOTIFY(NM_RCLICK, IDC_TREE, OnRclickTree)
148         ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_TREE, OnBeginlabeleditTree)
149         ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE, OnEndlabeleditTree)
150         ON_WM_CLOSE()
151         ON_WM_INITMENU()
152         ON_BN_CLICKED(IDC_PLAY, OnPlay)
153         //}}AFX_MSG_MAP
154 END_MESSAGE_MAP()
155
156 /////////////////////////////////////////////////////////////////////////////
157 // debriefing_editor_dlg message handlers
158
159 void debriefing_editor_dlg::OnInitMenu(CMenu* pMenu)
160 {
161         int i;
162         CMenu *m;
163
164         // disable any items we should disable
165         m = pMenu->GetSubMenu(0);
166
167         // uncheck all menu items
168         for (i = 0; i < Num_teams; i++ )
169                 m->CheckMenuItem( i, MF_BYPOSITION | MF_UNCHECKED );
170
171         for ( i = Num_teams; i < MAX_TEAMS; i++ )
172                 m->EnableMenuItem(i, MF_BYPOSITION | MF_GRAYED);
173
174
175         // put a check next to the currently selected item
176         m->CheckMenuItem(m_current_debriefing, MF_BYPOSITION | MF_CHECKED );
177
178         CDialog::OnInitMenu(pMenu);
179 }
180
181 BOOL debriefing_editor_dlg::OnInitDialog()
182 {
183         int i, n;
184
185         CDialog::OnInitDialog();
186         m_play_bm.LoadBitmap(IDB_PLAY);
187         ((CButton *) GetDlgItem(IDC_PLAY)) -> SetBitmap(m_play_bm);
188
189         m_current_debriefing = 0;
190         UpdateData(FALSE);
191
192         Debriefing = &Debriefings[m_current_debriefing];
193
194         m_tree.link_modified(&modified);  // provide way to indicate trees are modified in dialog
195         n = m_tree.select_sexp_node = select_sexp_node;
196         select_sexp_node = -1;
197         if (n != -1) {
198                 for (i=0; i<Debriefing->num_stages; i++)
199                         if (query_node_in_sexp(n, Debriefing->stages[i].formula))
200                                 break;
201
202                 if (i < Debriefing->num_stages) {
203                         m_cur_stage = i;
204                         update_data();
205                         GetDlgItem(IDC_TREE) -> SetFocus();
206                         m_tree.hilite_item(m_tree.select_sexp_node);
207                         set_modified();
208                         return FALSE;
209                 }
210         }
211
212         update_data();
213         set_modified();
214
215         // hard coded stuff to deal with the multiple briefings per mission.
216
217         return TRUE;
218 }
219
220 void debriefing_editor_dlg::update_data(int update)
221 {
222         int enable, save_debriefing;
223         debrief_stage *ptr;
224
225         save_debriefing = m_current_debriefing;
226
227         if (update)
228                 UpdateData(TRUE);
229
230         // based on the game type, enable the multiple briefings combo box (or disable it)
231
232         // set up the pointer to the briefing that we are editing
233         if ( save_debriefing != m_current_debriefing )
234                 Debriefing = &Debriefings[save_debriefing];
235         else
236                 Debriefing = &Debriefings[m_current_debriefing];
237
238         if (m_last_stage >= 0) {
239                 ptr = &Debriefing->stages[m_last_stage];
240                 if (ptr->formula >= 0)
241                         free_sexp2(ptr->formula);
242
243                 ptr->formula = m_tree.save_tree();
244                 deconvert_multiline_string(ptr->new_text, m_text, MAX_DEBRIEF_LEN);
245                 deconvert_multiline_string(ptr->new_recommendation_text, m_rec_text, MAX_RECOMMENDATION_LEN);
246                 string_copy(ptr->voice, m_voice, MAX_FILENAME_LEN);
247         }
248
249         // now get new stage data
250         if ((m_cur_stage >= 0) && (m_cur_stage < Debriefing->num_stages)) {
251                 ptr = &Debriefing->stages[m_cur_stage];
252                 m_stage_title.Format("Stage %d of %d", m_cur_stage + 1, Debriefing->num_stages);
253                 m_tree.load_tree(ptr->formula);
254                 m_text = convert_multiline_string(ptr->new_text);
255                 m_rec_text = convert_multiline_string(ptr->new_recommendation_text);
256                 m_voice = ptr->voice;
257                 enable = TRUE;
258
259         } else {
260                 m_stage_title = _T("No stages");
261                 m_tree.clear_tree();
262                 m_text = _T("");
263                 m_rec_text = _T("");
264                 m_voice = _T("");
265                 enable = FALSE;
266                 m_cur_stage = -1;
267         }
268
269         if (m_cur_stage == Debriefing->num_stages - 1)
270                 GetDlgItem(IDC_NEXT) -> EnableWindow(FALSE);
271         else
272                 GetDlgItem(IDC_NEXT) -> EnableWindow(enable);
273
274         if (m_cur_stage)
275                 GetDlgItem(IDC_PREV) -> EnableWindow(enable);
276         else
277                 GetDlgItem(IDC_PREV) -> EnableWindow(FALSE);
278
279         if (Debriefing->num_stages >= MAX_DEBRIEF_STAGES)
280                 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(FALSE);
281         else
282                 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(TRUE);
283
284         if (Debriefing->num_stages) {
285                 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(enable);
286                 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(enable);
287
288         } else {
289                 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(FALSE);
290                 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(FALSE);
291         }
292
293         GetDlgItem(IDC_VOICE) -> EnableWindow(enable);
294         GetDlgItem(IDC_BROWSE) -> EnableWindow(enable);
295         GetDlgItem(IDC_TEXT) -> EnableWindow(enable);
296         GetDlgItem(IDC_REC_TEXT) -> EnableWindow(enable);
297         GetDlgItem(IDC_TREE) -> EnableWindow(enable);
298
299         m_last_stage = m_cur_stage;
300         UpdateData(FALSE);
301
302         #ifndef NDEBUG
303         count_free_sexp_nodes();
304         #endif
305 }
306
307 void debriefing_editor_dlg::OnNext() 
308 {
309         m_cur_stage++;
310         update_data();
311 }
312
313 void debriefing_editor_dlg::OnPrev() 
314 {
315         m_cur_stage--;
316         update_data();
317 }
318
319 void debriefing_editor_dlg::OnBrowse() 
320 {
321         int z;
322         CString name;
323
324         UpdateData(TRUE);
325
326         if (The_mission.game_type & MISSION_TYPE_TRAINING)
327                 z = cfile_push_chdir(CF_TYPE_VOICE_TRAINING);
328         else
329                 z = cfile_push_chdir(CF_TYPE_VOICE_DEBRIEFINGS);
330
331         CFileDialog dlg(TRUE, "wav", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
332                 "Wave Files (*.wav)|*.wav||");
333
334         if (dlg.DoModal() == IDOK) {
335                 m_voice = dlg.GetFileName();
336                 UpdateData(FALSE);
337         }
338
339         if (!z)
340                 cfile_pop_dir();
341 }
342
343 void debriefing_editor_dlg::OnAddStage() 
344 {
345         int i;
346
347         if (Debriefing->num_stages >= MAX_DEBRIEF_STAGES)
348                 return;
349
350         m_cur_stage = i = Debriefing->num_stages++;
351         copy_stage(i - 1, i, 1);
352         update_data(1);
353 }
354
355 void debriefing_editor_dlg::OnDeleteStage() 
356 {
357         int i, z;
358
359         if (m_cur_stage < 0)
360                 return;
361         
362         Assert(Debriefing->num_stages);
363         z = m_cur_stage;
364         m_cur_stage = -1;
365         update_data(1);
366         for (i=z+1; i<Debriefing->num_stages; i++) {
367                 copy_stage(i, i - 1);
368         }
369
370         Debriefing->num_stages--;
371         m_cur_stage = z;
372         if (m_cur_stage >= Debriefing->num_stages)
373                 m_cur_stage = Debriefing->num_stages - 1;
374
375         update_data(0);
376 }
377
378 void debriefing_editor_dlg::OnInsertStage() 
379 {
380         int i, z;
381
382         if (Debriefing->num_stages >= MAX_DEBRIEF_STAGES)
383                 return;
384
385         if (!Debriefing->num_stages) {
386                 OnAddStage();
387                 return;
388         }
389
390         z = m_cur_stage;
391         m_cur_stage = -1;
392         update_data(1);
393         for (i=Debriefing->num_stages; i>z; i--) {
394                 copy_stage(i - 1, i);
395         }
396
397         Debriefing->num_stages++;
398         copy_stage(z, z + 1);
399         Debriefing->stages[z].formula = -1;
400         m_cur_stage = z;
401         update_data(0);
402 }
403
404 void debriefing_editor_dlg::copy_stage(int from, int to, int clear_formula)
405 {
406         if ((from < 0) || (from >= Debriefing->num_stages)) {
407                 strcpy(Debriefing->stages[to].new_text, "<Text here>");
408                 strcpy(Debriefing->stages[to].voice, "none.wav");
409                 Debriefing->stages[to].formula = -1;
410                 return;
411         }
412
413         
414         if (clear_formula)
415                 Debriefing->stages[to].formula = -1;
416         else
417                 Debriefing->stages[to].formula = Debriefing->stages[from].formula;
418
419         strcpy( Debriefing->stages[to].new_text, Debriefing->stages[from].new_text );
420         strcpy( Debriefing->stages[to].voice, Debriefing->stages[from].voice );
421         strcpy( Debriefing->stages[to].new_recommendation_text, Debriefing->stages[from].new_recommendation_text );
422 }
423
424 void debriefing_editor_dlg::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult) 
425 {
426         m_tree.right_clicked(); 
427         *pResult = 0;
428 }
429
430 void debriefing_editor_dlg::OnBeginlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
431 {
432         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
433
434         if (m_tree.edit_label(pTVDispInfo->item.hItem) == 1)    {
435                 *pResult = 0;
436                 modified = 1;
437
438         } else
439                 *pResult = 1;
440 }
441
442 void debriefing_editor_dlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
443 {
444         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
445
446         *pResult = m_tree.end_label_edit(pTVDispInfo->item.hItem, pTVDispInfo->item.pszText);
447 }
448
449 void debriefing_editor_dlg::OnClose() 
450 {
451         m_cur_stage = -1;
452         update_data(1);
453         CDialog::OnClose();
454 }
455
456 void debriefing_editor_dlg::OnOK()
457 {
458 }
459
460 BOOL debriefing_editor_dlg::OnCommand(WPARAM wParam, LPARAM lParam) 
461 {
462         int id;
463
464         // deal with figuring out menu stuff
465         id = LOWORD(wParam);
466         if ( (id >= ID_TEAM_1) && (id < ID_TEAM_3) ) {
467                 update_data(1);
468
469                 // set the current debriefing
470                 m_current_debriefing = id - ID_TEAM_1;
471
472                 // put user back at first stage for this team (or no current stage is there are none).
473                 Debriefing = &Debriefings[m_current_debriefing];
474                 if ( Debriefing->num_stages > 0 )
475                         m_cur_stage = 0;
476                 else
477                         m_cur_stage = -1;
478
479                 m_last_stage = -1;
480                 update_data(0);
481         }
482         
483         return CDialog::OnCommand(wParam, lParam);
484 }
485
486 BOOL debriefing_editor_dlg::DestroyWindow() 
487 {
488         m_play_bm.DeleteObject();
489         return CDialog::DestroyWindow();
490 }
491
492 void debriefing_editor_dlg::OnPlay() 
493 {
494         char path[MAX_PATH_LEN + 1];
495         GetDlgItem(IDC_VOICE)->GetWindowText(m_voice);
496
497         int size, offset;
498         cf_find_file_location((char *) (LPCSTR) m_voice, CF_TYPE_ANY, path, &size, &offset );
499
500         PlaySound(path, NULL, SND_ASYNC | SND_FILENAME);
501 }