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