]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/briefingeditordlg.cpp
Initial revision
[taylor/freespace2.git] / src / fred2 / briefingeditordlg.cpp
1 /*
2  * $Logfile: /Freespace2/code/Fred2/BriefingEditorDlg.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Briefing editor dialog box class.
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:08  root
11  * Initial revision
12  *
13  * 
14  * 9     7/19/99 3:01p Dave
15  * Fixed icons. Added single transport icon.
16  * 
17  * 8     7/18/99 5:19p Dave
18  * Jump node icon. Fixed debris fogging. Framerate warning stuff.
19  * 
20  * 7     7/09/99 5:54p Dave
21  * Seperated cruiser types into individual types. Added tons of new
22  * briefing icons. Campaign screen.
23  * 
24  * 6     5/20/99 1:46p Andsager
25  * Add briefing view copy and paste between stages
26  * 
27  * 5     4/23/99 12:01p Johnson
28  * Added SIF_HUGE_SHIP
29  * 
30  * 4     11/30/98 5:32p Dave
31  * Fixed up Fred support for software mode.
32  * 
33  * 3     10/16/98 4:28p Andsager
34  * Fix fred dependency
35  * 
36  * 2     10/07/98 6:28p Dave
37  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
38  * Fred. Globalized mission and campaign file extensions. Removed Silent
39  * Threat specific code.
40  * 
41  * 1     10/07/98 3:02p Dave
42  * 
43  * 1     10/07/98 3:00p Dave
44  * 
45  * 63    5/21/98 4:20p Dave
46  * Fixed bug with briefing editor when no current stage selected.
47  * 
48  * 62    5/21/98 12:58a Hoffoss
49  * Fixed warnings optimized build turned up.
50  * 
51  * 61    5/14/98 4:47p Hoffoss
52  * Made it so when you switch to a new team's debriefing (via menu), it
53  * updates the camera position to what it should be for new briefing
54  * stage.
55  * 
56  * 60    4/30/98 8:23p John
57  * Fixed some bugs with Fred caused by my new cfile code.
58  * 
59  * 59    4/22/98 9:56a Sandeep
60  * 
61  * 58    4/20/98 4:40p Hoffoss
62  * Added a button to 4 editors to play the chosen wave file.
63  * 
64  * 57    4/16/98 2:49p Johnson
65  * Fixed initialization for new icons in briefing.
66  * 
67  * 56    4/07/98 6:32p Dave
68  * Fixed function I forget to change back.
69  * 
70  * 55    4/07/98 6:27p Dave
71  * Implemented a more boiler-plate solution to the multiple team briefing
72  * problem in this editor.
73  * 
74  * 54    4/07/98 4:51p Dave
75  * (Hoffoss) Fixed a boat load of bugs caused by the new change to
76  * multiple briefings.  Allender's code changed to support this in the
77  * briefing editor wasn't quite correct.
78  * 
79  * 53    4/06/98 5:37p Hoffoss
80  * Added sexp tree support to briefings in Fred.
81  * 
82  * 52    4/06/98 10:43a John
83  * Fixed bugs with inserting/deleting stages
84  * 
85  * 51    4/03/98 12:39p Hoffoss
86  * Changed starting directory for browse buttons in several editors.
87  * 
88  * 50    4/03/98 11:34a John
89  * Fixed the stuff I broke in Fred from the new breifing
90  * 
91  * 49    3/26/98 6:40p Lawrance
92  * Don't store icon text for briefings
93  * 
94  * 48    3/21/98 7:36p Lawrance
95  * Move jump nodes to own lib.
96  * 
97  * 47    3/19/98 4:24p Hoffoss
98  * Added remaining support for command brief screen (ANI and WAVE file
99  * playing).
100  * 
101  * 46    3/17/98 2:00p Hoffoss
102  * Added ability to make an icon from a jump node in briefing editor.
103  * 
104  * 45    2/18/98 6:44p Hoffoss
105  * Added support for lines between icons in briefings for Fred.
106  * 
107  * 44    2/09/98 9:25p Allender
108  * team v team support.  multiple pools and breifings
109  * 
110  * 43    2/04/98 4:31p Allender
111  * support for multiple briefings and debriefings.  Changes to mission
112  * type (now a bitfield).  Bitfield defs for multiplayer modes
113  * 
114  * 42    1/28/98 7:19p Lawrance
115  * Get fading/highlighting animations working
116  * 
117  * 41    12/28/97 5:52p Lawrance
118  * Add support for debriefing success/fail music.
119  * 
120  * 40    11/04/97 4:33p Hoffoss
121  * Made saving keep the current briefing state intact.
122  * 
123  * 39    11/04/97 11:31a Duncan
124  * Made make icon button gray if at max icons already.
125  * 
126  * 38    11/03/97 4:07p Jasen
127  * Fixed bug in briefing editor caused by changes in TEAM_* defines in the
128  * past and whoever made these changes failed to update this editor along
129  * with it.
130  * 
131  * 37    10/19/97 11:32p Hoffoss
132  * Added support for briefing cuts in Fred.
133  * 
134  * 36    10/12/97 11:23p Mike
135  * About ten fixes/changes in the docking system.
136  * Also, renamed SIF_REARM_REPAIR to SIF_SUPPORT.
137  * 
138  * 35    9/30/97 5:56p Hoffoss
139  * Added music selection combo boxes to Fred.
140  *
141  * $NoKeywords: $
142  */
143
144 #include "stdafx.h"
145 #include <mmsystem.h>
146 #include "fred.h"
147 #include "briefingeditordlg.h"
148 #include "freddoc.h"
149 #include "missionbriefcommon.h"
150 #include "missionparse.h"
151 #include "fredrender.h"
152 #include "management.h"
153 #include "linklist.h"
154 #include "mainfrm.h"
155 #include "bmpman.h"
156 #include "eventmusic.h"
157 #include "starfield.h"
158 #include "jumpnode.h"
159 #include "cfile.h"
160
161 #ifdef _DEBUG
162 #define new DEBUG_NEW
163 #undef THIS_FILE
164 static char THIS_FILE[] = __FILE__;
165 #endif
166
167 #define ID_MENU         9000
168 #define NAVBUOY_NAME "Terran NavBuoy"
169
170 static int Max_icons_for_lines;
171
172 /////////////////////////////////////////////////////////////////////////////
173 // briefing_editor_dlg dialog
174
175 briefing_editor_dlg::briefing_editor_dlg(CWnd* pParent /*=NULL*/)
176         : CDialog(briefing_editor_dlg::IDD, pParent)
177 {
178         int i, z;
179
180         // figure out max icons we can have with lines to each other less than max allowed lines.
181         // Basically, # lines = (# icons - 1) factorial
182         Max_icons_for_lines = 0;
183         do {
184                 i = ++Max_icons_for_lines + 1;
185                 z = 0;
186                 while (--i)
187                         z += i;
188
189         } while (z < MAX_BRIEF_STAGE_LINES);
190
191         //{{AFX_DATA_INIT(briefing_editor_dlg)
192         m_hilight = FALSE;
193         m_icon_image = -1;
194         m_icon_label = _T("");
195         m_stage_title = _T("");
196         m_text = _T("");
197         m_time = _T("");
198         m_voice = _T("");
199         m_icon_text = _T("");
200         m_icon_team = -1;
201         m_ship_type = -1;
202         m_change_local = FALSE;
203         m_id = 0;
204         m_briefing_music = -1;
205         m_cut_next = FALSE;
206         m_cut_prev = FALSE;
207         m_current_briefing = -1;
208         //}}AFX_DATA_INIT
209         m_cur_stage = 0;
210         m_last_stage = m_cur_icon = m_last_icon = -1;
211         m_tree.link_modified(&modified);  // provide way to indicate trees are modified in dialog
212
213         // copy view initialization
214         m_copy_view_set = 0;
215 }
216
217 void briefing_editor_dlg::DoDataExchange(CDataExchange* pDX)
218 {
219         CDialog::DoDataExchange(pDX);
220         //{{AFX_DATA_MAP(briefing_editor_dlg)
221         DDX_Control(pDX, IDC_TREE, m_tree);
222         DDX_Control(pDX, IDC_LINES, m_lines);
223         DDX_Check(pDX, IDC_HILIGHT, m_hilight);
224         DDX_CBIndex(pDX, IDC_ICON_IMAGE, m_icon_image);
225         DDX_Text(pDX, IDC_ICON_LABEL, m_icon_label);
226         DDX_Text(pDX, IDC_STAGE_TITLE, m_stage_title);
227         DDX_Text(pDX, IDC_TEXT, m_text);
228         DDX_Text(pDX, IDC_TIME, m_time);
229         DDX_Text(pDX, IDC_VOICE, m_voice);
230         DDX_Text(pDX, IDC_ICON_TEXT, m_icon_text);
231         DDX_CBIndex(pDX, IDC_TEAM, m_icon_team);
232         DDX_CBIndex(pDX, IDC_SHIP_TYPE, m_ship_type);
233         DDX_Check(pDX, IDC_LOCAL, m_change_local);
234         DDX_Text(pDX, IDC_ID, m_id);
235         DDX_CBIndex(pDX, IDC_BRIEFING_MUSIC, m_briefing_music);
236         DDX_Check(pDX, IDC_CUT_NEXT, m_cut_next);
237         DDX_Check(pDX, IDC_CUT_PREV, m_cut_prev);
238         //}}AFX_DATA_MAP
239
240         DDV_MaxChars(pDX, m_text, MAX_BRIEF_LEN - 1);
241         DDV_MaxChars(pDX, m_voice, MAX_FILENAME_LEN - 1);
242         DDV_MaxChars(pDX, m_icon_label, MAX_LABEL_LEN - 1);
243         DDV_MaxChars(pDX, m_icon_text, MAX_ICON_TEXT_LEN - 1);
244 }
245
246 BEGIN_MESSAGE_MAP(briefing_editor_dlg, CDialog)
247         //{{AFX_MSG_MAP(briefing_editor_dlg)
248         ON_WM_CLOSE()
249         ON_BN_CLICKED(IDC_NEXT, OnNext)
250         ON_BN_CLICKED(IDC_PREV, OnPrev)
251         ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
252         ON_BN_CLICKED(IDC_ADD_STAGE, OnAddStage)
253         ON_BN_CLICKED(IDC_DELETE_STAGE, OnDeleteStage)
254         ON_BN_CLICKED(IDC_INSERT_STAGE, OnInsertStage)
255         ON_BN_CLICKED(IDC_MAKE_ICON, OnMakeIcon)
256         ON_BN_CLICKED(IDC_DELETE_ICON, OnDeleteIcon)
257         ON_BN_CLICKED(IDC_GOTO_VIEW, OnGotoView)
258         ON_BN_CLICKED(IDC_SAVE_VIEW, OnSaveView)
259         ON_CBN_SELCHANGE(IDC_ICON_IMAGE, OnSelchangeIconImage)
260         ON_CBN_SELCHANGE(IDC_TEAM, OnSelchangeTeam)
261         ON_BN_CLICKED(IDC_PROPAGATE_ICONS, OnPropagateIcons)
262         ON_WM_INITMENU()
263         ON_BN_CLICKED(IDC_LINES, OnLines)
264         ON_NOTIFY(NM_RCLICK, IDC_TREE, OnRclickTree)
265         ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_TREE, OnBeginlabeleditTree)
266         ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE, OnEndlabeleditTree)
267         ON_BN_CLICKED(IDC_PLAY, OnPlay)
268         ON_BN_CLICKED(IDC_COPY_VIEW, OnCopyView)
269         ON_BN_CLICKED(IDC_PASTE_VIEW, OnPasteView)
270         //}}AFX_MSG_MAP
271 END_MESSAGE_MAP()
272
273 /////////////////////////////////////////////////////////////////////////////
274 // briefing_editor_dlg message handlers
275
276 void briefing_editor_dlg::OnInitMenu(CMenu* pMenu)
277 {
278         int i;
279         CMenu *m;
280
281         // disable any items we should disable
282         m = pMenu->GetSubMenu(0);
283
284         // uncheck all menu items
285         for (i=0; i<Num_teams; i++)
286                 m->CheckMenuItem(i, MF_BYPOSITION | MF_UNCHECKED);
287
288         for (i=Num_teams; i<MAX_TEAMS; i++)
289                 m->EnableMenuItem(i, MF_BYPOSITION | MF_GRAYED);
290
291         // put a check next to the currently selected item
292         m->CheckMenuItem(m_current_briefing, MF_BYPOSITION | MF_CHECKED );
293
294         CDialog::OnInitMenu(pMenu);
295 }
296
297 void briefing_editor_dlg::create()
298 {
299         int i;
300         CComboBox *box;
301
302         CDialog::Create(IDD);
303         theApp.init_window(&Briefing_wnd_data, this);
304         box = (CComboBox *) GetDlgItem(IDC_ICON_IMAGE);
305         for (i=0; i<MAX_BRIEF_ICONS; i++)
306                 box->AddString(Icon_names[i]);
307
308         box = (CComboBox *) GetDlgItem(IDC_TEAM);
309         for (i=0; i<Num_team_names; i++)
310                 box->AddString(Team_names[i]);
311
312         box = (CComboBox *) GetDlgItem(IDC_SHIP_TYPE);
313         for (i=0; i<Num_ship_types; i++)
314                 box->AddString(Ship_info[i].name);
315
316         box = (CComboBox *) GetDlgItem(IDC_BRIEFING_MUSIC);
317         box->AddString("None");
318         for (i=0; i<Num_music_files; i++)
319                 box->AddString(Spooled_music[i].name);
320
321         m_play_bm.LoadBitmap(IDB_PLAY);
322         ((CButton *) GetDlgItem(IDC_PLAY)) -> SetBitmap(m_play_bm);
323
324         m_current_briefing = 0;
325         Briefing = &Briefings[m_current_briefing];
326         m_briefing_music = Mission_music[SCORE_BRIEFING] + 1;
327         UpdateData(FALSE);
328         update_data();
329         OnGotoView();
330         update_map_window();
331 }
332
333 void briefing_editor_dlg::focus_sexp(int select_sexp_node)
334 {
335         int i, n;
336
337         n = m_tree.select_sexp_node = select_sexp_node;
338         if (n != -1) {
339                 for (i=0; i<Briefing->num_stages; i++)
340                         if (query_node_in_sexp(n, Briefing->stages[i].formula))
341                                 break;
342
343                 if (i < Briefing->num_stages) {
344                         m_cur_stage = i;
345                         update_data();
346                         GetDlgItem(IDC_TREE) -> SetFocus();
347                         m_tree.hilite_item(m_tree.select_sexp_node);
348                 }
349         }
350 }
351
352 void briefing_editor_dlg::OnOK()
353 {
354 }
355
356 void briefing_editor_dlg::OnCancel()
357 {
358         OnClose();
359 }
360
361 void briefing_editor_dlg::OnClose() 
362 {
363         int bs, i, j, s, t, dup = 0;
364         briefing_editor_dlg *ptr;
365         brief_stage *sp;
366
367         m_cur_stage = -1;
368         update_data(1);
369
370         for ( bs = 0; bs < Num_teams; bs++ ) {
371                 for (s=0; s<Briefing[bs].num_stages; s++) {
372                         sp = &Briefing[bs].stages[s];
373                         t = sp->num_icons;
374                         for (i=0; i<t-1; i++)
375                                 for (j=i+1; j<t; j++) {
376                                         if ((sp->icons[i].id >= 0) && (sp->icons[i].id == sp->icons[j].id))
377                                                 dup = 1;
378                                 }
379                 }
380         }
381
382         if (dup)
383                 MessageBox("You have duplicate icons names.  You should resolve these.", "Warning");
384
385         theApp.record_window_data(&Briefing_wnd_data, this);
386         ptr = Briefing_dialog;
387         Briefing_dialog = NULL;
388         delete ptr;
389 }
390
391 void briefing_editor_dlg::reset_editor()
392 {
393         m_cur_stage = -1;
394         update_data(0);
395 }
396
397 // some kind of hackish code to get around the problem if saving (which implicitly loads,
398 // which implicitly clears all mission info) not affecting the editor's state at save.
399 void briefing_editor_dlg::save_editor_state()
400 {
401         stage_saved = m_cur_stage;
402         icon_saved = m_cur_icon;
403 }
404
405 void briefing_editor_dlg::restore_editor_state()
406 {
407         m_cur_stage = stage_saved;
408         m_cur_icon = icon_saved;
409 }
410
411 void briefing_editor_dlg::update_data(int update)
412 {
413         char buf[MAX_LABEL_LEN], buf2[MAX_ICON_TEXT_LEN], buf3[MAX_BRIEF_LEN];
414         int i, j, l, lines, count, enable = TRUE, valid = 0, invalid = 0;
415         object *objp;
416         brief_stage *ptr = NULL;
417
418         if (update)
419                 UpdateData(TRUE);
420
421         // save off current data before we update over it with new briefing stage/team stuff
422         Briefing = save_briefing;
423
424         Mission_music[SCORE_BRIEFING] = m_briefing_music - 1;
425         if (m_last_stage >= 0) {
426                 ptr = &Briefing->stages[m_last_stage];
427                 deconvert_multiline_string(buf3, m_text, MAX_BRIEF_LEN);
428                 if (stricmp(ptr->new_text, buf3))
429                         set_modified();
430
431                 strcpy(ptr->new_text, buf3);
432                 MODIFY(ptr->camera_time, atoi(m_time));
433                 string_copy(ptr->voice, m_voice, MAX_FILENAME_LEN, 1);
434                 i = ptr->flags;
435                 if (m_cut_prev)
436                         i |= BS_BACKWARD_CUT;
437                 else
438                         i &= ~BS_BACKWARD_CUT;
439
440                 if (m_cut_next)
441                         i |= BS_FORWARD_CUT;
442                 else
443                         i &= ~BS_FORWARD_CUT;
444
445                 MODIFY(ptr->flags, i);
446                 ptr->formula = m_tree.save_tree();
447                 switch (m_lines.GetCheck()) {
448                         case 1:
449                                 // add lines between every pair of 2 marked icons if there isn't one already.
450                                 for (i=0; i<ptr->num_icons - 1; i++)
451                                         for (j=i+1; j<ptr->num_icons; j++) {
452                                                 if ( icon_marked[i] && icon_marked[j] ) {
453                                                         for (l=0; l<ptr->num_lines; l++)
454                                                                 if ( ((ptr->lines[l].start_icon == i) && (ptr->lines[l].end_icon == j)) || ((ptr->lines[l].start_icon == j) && (ptr->lines[l].end_icon == i)) )
455                                                                         break;
456
457                                                         if ((l == ptr->num_lines) && (l < MAX_BRIEF_STAGE_LINES)) {
458                                                                 ptr->lines[l].start_icon = i;
459                                                                 ptr->lines[l].end_icon = j;
460                                                                 ptr->num_lines++;
461                                                         }
462                                                 }
463                                         }
464
465                                 break;
466
467                         case 0:
468                                 // remove all existing lines between any 2 marked icons
469                                 i = ptr->num_lines;
470                                 while (i--)
471                                         if ( icon_marked[ptr->lines[i].start_icon] && icon_marked[ptr->lines[i].end_icon] ) {
472                                                 ptr->num_lines--;
473                                                 for (l=i; l<ptr->num_lines; l++)
474                                                         ptr->lines[l] = ptr->lines[l + 1];
475                                         }
476
477                                 break;
478                 }
479
480                 if (m_last_icon >= 0) {
481                         valid = (m_id != ptr->icons[m_last_icon].id);
482                         if (m_id >= 0) {
483                                 if (valid && !m_change_local) {
484                                         for (i=m_last_stage+1; i<Briefing->num_stages; i++) {
485                                                 if (find_icon(m_id, i) >= 0) {
486                                                         char msg[1024];
487
488                                                         valid = 0;
489                                                         sprintf(msg, "Icon ID #%d is already used in a later stage.  You can only\n"
490                                                                 "change to that ID locally.  Icon ID has been reset back to %d", m_id, ptr->icons[m_last_icon].id);
491
492                                                         m_id = ptr->icons[m_last_icon].id;
493                                                         MessageBox(msg);
494                                                         break;
495                                                 }
496                                         }
497                                 }
498
499                                 for (i=0; i<ptr->num_icons; i++)
500                                         if ((i != m_last_icon) && (ptr->icons[i].id == m_id)) {
501                                                 char msg[1024];
502
503                                                 sprintf(msg, "Icon ID #%d is already used in this stage.  Icon ID has been reset back to %d",
504                                                         m_id, ptr->icons[m_last_icon].id);
505
506                                                 m_id = ptr->icons[m_last_icon].id;
507                                                 MessageBox(msg);
508                                                 break;
509                                         }
510
511                                 if (valid && !m_change_local) {
512                                         set_modified();
513                                         reset_icon_loop(m_last_stage);
514                                         while (get_next_icon(ptr->icons[m_last_icon].id))
515                                                 iconp->id = m_id;
516                                 }
517                         }
518
519                         ptr->icons[m_last_icon].id = m_id;
520                         string_copy(buf, m_icon_label, MAX_LABEL_LEN);
521                         if (stricmp(ptr->icons[m_last_icon].label, buf) && !m_change_local) {
522                                 set_modified();
523                                 reset_icon_loop(m_last_stage);
524                                 while (get_next_icon(m_id))
525                                         strcpy(iconp->label, buf);
526                         }
527
528                         strcpy(ptr->icons[m_last_icon].label, buf);
529                         if ( m_hilight )
530                                 ptr->icons[m_last_icon].flags |= BI_HIGHLIGHT;
531                         else
532                                 ptr->icons[m_last_icon].flags &= ~BI_HIGHLIGHT;
533
534                         if ((ptr->icons[m_last_icon].type != m_icon_image) && !m_change_local) {
535                                 set_modified();
536                                 reset_icon_loop(m_last_stage);
537                                 while (get_next_icon(m_id))
538                                         iconp->type = m_icon_image;
539                         }
540
541                         ptr->icons[m_last_icon].type = m_icon_image;
542                         if ((ptr->icons[m_last_icon].team != (1 << m_icon_team)) && !m_change_local) {
543                                 set_modified();
544                                 reset_icon_loop(m_last_stage);
545                                 while (get_next_icon(m_id))
546                                         iconp->team = (1 << m_icon_team);
547                         }
548
549                         ptr->icons[m_last_icon].team = (1 << m_icon_team);
550                         if ((ptr->icons[m_last_icon].ship_class != m_ship_type) && !m_change_local) {
551                                 set_modified();
552                                 reset_icon_loop(m_last_stage);
553                                 while (get_next_icon(m_id))
554                                         iconp->ship_class = m_ship_type;
555                         }
556
557                         MODIFY(ptr->icons[m_last_icon].ship_class, m_ship_type);
558                         deconvert_multiline_string(buf2, m_icon_text, MAX_ICON_TEXT_LEN);
559 /*
560                         if (stricmp(ptr->icons[m_last_icon].text, buf2) && !m_change_local) {
561                                 set_modified();
562                                 reset_icon_loop(m_last_stage);
563                                 while (get_next_icon(m_id))
564                                         strcpy(iconp->text, buf2);
565                         }
566
567                         strcpy(ptr->icons[m_last_icon].text, buf2);
568 */
569                 }
570         }
571
572         if (!::IsWindow(m_hWnd))
573                 return;
574
575         // set briefing pointer to correct team
576         Briefing = &Briefings[m_current_briefing];
577
578         if ((m_cur_stage >= 0) && (m_cur_stage < Briefing->num_stages)) {
579                 ptr = &Briefing->stages[m_cur_stage];
580                 m_stage_title.Format("Stage %d of %d", m_cur_stage + 1, Briefing->num_stages);
581                 m_text = convert_multiline_string(ptr->new_text);
582                 m_time.Format("%d", ptr->camera_time);
583                 m_voice = ptr->voice;
584                 m_cut_prev = (ptr->flags & BS_BACKWARD_CUT) ? 1 : 0;
585                 m_cut_next = (ptr->flags & BS_FORWARD_CUT) ? 1 : 0;
586                 m_tree.load_tree(ptr->formula);
587
588         } else {
589                 m_stage_title = _T("No stages");
590                 m_text = _T("");
591                 m_time = _T("");
592                 m_voice = _T("");
593                 m_cut_prev = m_cut_next = 0;
594                 m_tree.clear_tree();
595                 enable = FALSE;
596                 m_cur_stage = -1;
597         }
598
599         if (m_cur_stage == Briefing->num_stages - 1)
600                 GetDlgItem(IDC_NEXT) -> EnableWindow(FALSE);
601         else
602                 GetDlgItem(IDC_NEXT) -> EnableWindow(enable);
603
604         if (m_cur_stage)
605                 GetDlgItem(IDC_PREV) -> EnableWindow(enable);
606         else
607                 GetDlgItem(IDC_PREV) -> EnableWindow(FALSE);
608
609         if (Briefing->num_stages >= MAX_BRIEF_STAGES)
610                 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(FALSE);
611         else
612                 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(TRUE);
613
614         if (Briefing->num_stages) {
615                 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(enable);
616                 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(enable);
617         } else {
618                 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(FALSE);
619                 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(FALSE);
620         }
621
622         GetDlgItem(IDC_TIME) -> EnableWindow(enable);
623         GetDlgItem(IDC_VOICE) -> EnableWindow(enable);
624         GetDlgItem(IDC_BROWSE) -> EnableWindow(enable);
625         GetDlgItem(IDC_TEXT) -> EnableWindow(enable);
626         GetDlgItem(IDC_SAVE_VIEW) -> EnableWindow(enable);
627         GetDlgItem(IDC_GOTO_VIEW) -> EnableWindow(enable);
628         GetDlgItem(IDC_CUT_PREV) -> EnableWindow(enable);
629         GetDlgItem(IDC_CUT_NEXT) -> EnableWindow(enable);
630         GetDlgItem(IDC_TREE) -> EnableWindow(enable);
631         GetDlgItem(IDC_PLAY) -> EnableWindow(enable);
632
633         if ((m_cur_stage >= 0) && (m_cur_icon >= 0) && (m_cur_icon < ptr->num_icons)) {
634                 m_hilight = (ptr->icons[m_cur_icon].flags & BI_HIGHLIGHT)?1:0;
635                 m_icon_image = ptr->icons[m_cur_icon].type;
636                 m_icon_team = bitmask_2_bitnum(ptr->icons[m_cur_icon].team);
637                 m_icon_label = ptr->icons[m_cur_icon].label;
638                 m_ship_type = ptr->icons[m_cur_icon].ship_class;
639 //              m_icon_text = convert_multiline_string(ptr->icons[m_cur_icon].text);
640                 m_id = ptr->icons[m_cur_icon].id;
641                 enable = TRUE;
642
643         } else {
644                 m_hilight = FALSE;
645                 m_icon_image = -1;
646                 m_icon_team = -1;
647                 m_ship_type = -1;
648                 m_icon_label = _T("");
649                 m_cur_icon = -1;
650                 m_id = 0;
651                 enable = FALSE;
652         }
653
654         GetDlgItem(IDC_ICON_TEXT) -> EnableWindow(enable);
655         GetDlgItem(IDC_ICON_LABEL) -> EnableWindow(enable);
656         GetDlgItem(IDC_ICON_IMAGE) -> EnableWindow(enable);
657         GetDlgItem(IDC_SHIP_TYPE) -> EnableWindow(enable);
658         GetDlgItem(IDC_HILIGHT) -> EnableWindow(enable);
659         GetDlgItem(IDC_TEAM) -> EnableWindow(enable);
660         GetDlgItem(IDC_ID) -> EnableWindow(enable);
661         GetDlgItem(IDC_DELETE_ICON) -> EnableWindow(enable);
662
663         valid = invalid = 0;
664         objp = GET_FIRST(&obj_used_list);
665         while (objp != END_OF_LIST(&obj_used_list)) {
666                 if (objp->flags & OF_MARKED) {
667                         if ((objp->type == OBJ_SHIP) || (objp->type == OBJ_START) || (objp->type == OBJ_WAYPOINT) || (objp->type == OBJ_JUMP_NODE))
668                                 valid = 1;
669                         else
670                                 invalid = 1;
671                 }
672
673                 objp = GET_NEXT(objp);
674         }
675
676         if (m_cur_stage >= 0)
677                 ptr = &Briefing->stages[m_cur_stage];
678
679         if (valid && !invalid && (m_cur_stage >= 0) && (ptr->num_icons < MAX_STAGE_ICONS))
680                 GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(TRUE);
681         else
682                 GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(FALSE);
683
684         if (m_cur_stage >= 0)
685                 for (i=0; i<ptr->num_icons; i++)
686                         icon_marked[i] = 0;
687
688         valid = invalid = 0;
689         objp = GET_FIRST(&obj_used_list);
690         while (objp != END_OF_LIST(&obj_used_list)) {
691                 if (objp->flags & OF_MARKED) {
692                         if (objp->type == OBJ_POINT) {
693                                 valid++;
694                                 icon_marked[objp->instance] = 1;
695
696                         } else
697                                 invalid++;
698                 }
699
700                 objp = GET_NEXT(objp);
701         }
702
703         if (valid && !invalid && (m_cur_stage >= 0))
704                 GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(TRUE);
705         else
706                 GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(FALSE);
707
708         count = 0;
709         lines = 1;  // default lines checkbox to checked
710         
711         if (m_cur_stage >= 0) {
712                 for (i=0; i<ptr->num_lines; i++)
713                         line_marked[i] = 0;
714
715                 // go through and locate all lines between marked icons
716                 for (i=0; i<ptr->num_icons - 1; i++)
717                         for (j=i+1; j<ptr->num_icons; j++) {
718                                 if ( icon_marked[i] && icon_marked[j] ) {
719                                         for (l=0; l<ptr->num_lines; l++)
720                                                 if ( ((ptr->lines[l].start_icon == i) && (ptr->lines[l].end_icon == j)) || ((ptr->lines[l].start_icon == j) && (ptr->lines[l].end_icon == i)) ) {
721                                                         line_marked[l] = 1;
722                                                         count++;  // track number of marked lines (lines between 2 icons that are both marked)
723                                                         break;
724                                                 }
725
726                                         // at least 1 line missing between 2 marked icons, so use mixed state
727                                         if (l == ptr->num_lines)
728                                                 lines = 2;
729                                 }
730                         }
731         }
732
733         // not even 1 line between any 2 marked icons?  Set checkbox to unchecked.
734         if (!count)
735                 lines = 0;
736
737         i = 0;
738         if (m_cur_stage >= 0){
739                 i = calc_num_lines_for_icons(valid) + ptr->num_lines - count;
740         }
741
742         if ((valid > 1) && !invalid && (m_cur_stage >= 0) && (i <= MAX_BRIEF_STAGE_LINES))
743                 GetDlgItem(IDC_LINES) -> EnableWindow(TRUE);
744         else
745                 GetDlgItem(IDC_LINES) -> EnableWindow(FALSE);
746
747         m_lines.SetCheck(lines);
748
749         UpdateData(FALSE);
750         if ((m_last_stage != m_cur_stage) || (Briefing != save_briefing)) {
751                 if (m_last_stage >= 0) {
752                         for (i=0; i<save_briefing->stages[m_last_stage].num_icons; i++) {
753                                 // save positions of all icons, in case they have moved
754                                 save_briefing->stages[m_last_stage].icons[i].pos = Objects[icon_obj[i]].pos;
755                                 // release objects being used by last stage
756                                 obj_delete(icon_obj[i]);
757                         }
758                 }
759
760                 if (m_cur_stage >= 0) {
761                         for (i=0; i<ptr->num_icons; i++) {
762                                 // create an object for each icon for display/manipulation purposes
763                                 icon_obj[i] = obj_create(OBJ_POINT, -1, i, NULL, &ptr->icons[i].pos, 0.0f, OF_RENDERS);
764                         }
765
766                         obj_merge_created_list();
767                 }
768
769                 m_last_stage = m_cur_stage;
770         }
771
772         m_last_icon = m_cur_icon;
773         Update_window = 1;
774         save_briefing = Briefing;
775 }
776
777 // Given a number of icons, figure out how many lines would be required to connect each one
778 // with all of the others.
779 //
780 int briefing_editor_dlg::calc_num_lines_for_icons(int num)
781 {
782         int lines = 0;
783
784         if (num < 2)
785                 return 0;
786
787         // Basically, this is # lines = (# icons - 1) factorial
788         while (--num)
789                 lines += num;
790
791         return lines;
792 }
793
794 void briefing_editor_dlg::OnNext()
795 {
796         m_cur_stage++;
797         m_cur_icon = -1;
798         update_data();
799         OnGotoView();
800 }
801
802 void briefing_editor_dlg::OnPrev()
803 {
804         m_cur_stage--;
805         m_cur_icon = -1;
806         update_data();
807         OnGotoView();
808 }
809
810 void briefing_editor_dlg::OnBrowse() 
811 {
812         int z;
813         CString name;
814
815         UpdateData(TRUE);
816
817         if (The_mission.game_type & MISSION_TYPE_TRAINING)
818                 z = cfile_push_chdir(CF_TYPE_VOICE_TRAINING);
819         else
820                 z = cfile_push_chdir(CF_TYPE_VOICE_BRIEFINGS);
821
822         CFileDialog dlg(TRUE, "wav", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
823                 "Wave Files (*.wav)|*.wav||");
824
825         if (dlg.DoModal() == IDOK) {
826                 m_voice = dlg.GetFileName();
827                 UpdateData(FALSE);
828         }
829
830         if (!z)
831                 cfile_pop_dir();
832 }
833
834 void briefing_editor_dlg::OnAddStage() 
835 {
836         int i;
837
838         if (Briefing->num_stages >= MAX_BRIEF_STAGES)
839                 return;
840
841         m_cur_stage = i = Briefing->num_stages++;
842         copy_stage(i - 1, i);
843         update_data(1);
844 }
845
846 void briefing_editor_dlg::OnDeleteStage() 
847 {
848         int i, z;
849
850         if (m_cur_stage < 0)
851                 return;
852         
853         Assert(Briefing->num_stages);
854         z = m_cur_stage;
855         m_cur_stage = -1;
856         update_data(1);
857         for (i=z+1; i<Briefing->num_stages; i++)        {
858                 copy_stage(i, i-1);
859         }
860
861         Briefing->num_stages--;
862         m_cur_stage = z;
863         if (m_cur_stage >= Briefing->num_stages)
864                 m_cur_stage = Briefing->num_stages - 1;
865
866         update_data(0);
867 }
868
869 void briefing_editor_dlg::draw_icon(object *objp)
870 {
871         if (m_cur_stage < 0)
872                 return;
873
874         brief_render_icon(m_cur_stage, objp->instance, 1.0f/30.0f, objp->flags & OF_MARKED,
875                 (float) True_rw / BRIEF_GRID_W, (float) True_rh / BRIEF_GRID_H);
876 }
877
878 void briefing_editor_dlg::batch_render()
879 {
880         int i, num_lines;
881
882
883         if (m_cur_stage < 0)
884                 return;
885
886         num_lines = Briefing->stages[m_cur_stage].num_lines;
887         for (i=0; i<num_lines; i++)
888                 brief_render_icon_line(m_cur_stage, i);
889 }
890
891 void briefing_editor_dlg::icon_select(int num)
892 {
893         m_cur_icon = num;
894         update_data(1);
895 }
896
897 void briefing_editor_dlg::OnInsertStage() 
898 {
899         int i, z;
900
901         if (Briefing->num_stages >= MAX_BRIEF_STAGES)
902                 return;
903
904         if (!Briefing->num_stages) {
905                 OnAddStage();
906                 return;
907         }
908
909         z = m_cur_stage;
910         m_cur_stage = -1;
911         update_data(1);
912         for (i=Briefing->num_stages; i>z; i--)  {
913                 copy_stage(i-1, i);
914         }
915
916         Briefing->num_stages++;
917         copy_stage(z, z + 1);
918         m_cur_stage = z;
919         update_data(0);
920 }
921
922 void briefing_editor_dlg::copy_stage(int from, int to)
923 {
924         if ((from < 0) || (from >= Briefing->num_stages)) {
925                 strcpy(Briefing->stages[to].new_text, "<Text here>");
926                 strcpy(Briefing->stages[to].voice, "none.wav");
927                 Briefing->stages[to].camera_pos = view_pos;
928                 Briefing->stages[to].camera_orient = view_orient;
929                 Briefing->stages[to].camera_time = 500;
930                 Briefing->stages[to].num_icons = 0;
931                 Briefing->stages[to].formula = Locked_sexp_true;
932                 return;
933         }
934
935         // Copy all the data in the stage structure.
936         strcpy( Briefing->stages[to].new_text, Briefing->stages[from].new_text );
937         strcpy( Briefing->stages[to].voice, Briefing->stages[from].voice );
938         Briefing->stages[to].camera_pos = Briefing->stages[from].camera_pos;
939         Briefing->stages[to].camera_orient = Briefing->stages[from].camera_orient;
940         Briefing->stages[to].camera_time = Briefing->stages[from].camera_time;
941         Briefing->stages[to].flags = Briefing->stages[from].flags;
942         Briefing->stages[to].num_icons = Briefing->stages[from].num_icons;
943         Briefing->stages[to].num_lines = Briefing->stages[from].num_lines;
944         Briefing->stages[to].formula = Briefing->stages[from].formula;
945
946         memmove( Briefing->stages[to].icons, Briefing->stages[from].icons, sizeof(brief_icon)*MAX_STAGE_ICONS );
947         memmove( Briefing->stages[to].lines, Briefing->stages[from].lines, sizeof(brief_line)*MAX_BRIEF_STAGE_LINES );
948 }
949
950 void briefing_editor_dlg::update_positions()
951 {
952         int i, s, z;
953         vector v1, v2;
954
955         if (m_cur_stage < 0)
956                 return;
957
958         for (i=0; i<Briefing->stages[m_cur_stage].num_icons; i++) {
959                 v1 = Briefing->stages[m_cur_stage].icons[i].pos;
960                 v2 = Objects[icon_obj[i]].pos;
961                 if ((v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z)) {
962                         Briefing->stages[m_cur_stage].icons[i].pos = Objects[icon_obj[i]].pos;
963                         if (!m_change_local)  // propagate changes through rest of stages..
964                                 for (s=m_cur_stage+1; s<Briefing->num_stages; s++) {
965                                         z = find_icon(Briefing->stages[m_cur_stage].icons[i].id, s);
966                                         if (z >= 0)
967                                                 Briefing->stages[s].icons[z].pos = Objects[icon_obj[i]].pos;
968                                 }
969                 }
970         }
971 }
972
973 void briefing_editor_dlg::OnMakeIcon() 
974 {
975         char *name;
976         int z, len, team, ship, waypoint, jump_node, count = -1;
977         int cargo = 0, cargo_count = 0, freighter_count = 0;
978         object *ptr;
979         vector min, max, pos;
980         brief_icon *iconp;
981
982         if (Briefing->stages[m_cur_stage].num_icons >= MAX_STAGE_ICONS)
983                 return;
984
985         m_cur_icon = Briefing->stages[m_cur_stage].num_icons++;
986         iconp = &Briefing->stages[m_cur_stage].icons[m_cur_icon];
987         ship = waypoint = jump_node = -1;
988         team = TEAM_FRIENDLY;
989
990         vm_vec_make(&min, 9e19f, 9e19f, 9e19f);
991         vm_vec_make(&max, -9e19f, -9e19f, -9e19f);
992         ptr = GET_FIRST(&obj_used_list);
993         while (ptr != END_OF_LIST(&obj_used_list)) {
994                 if (ptr->flags & OF_MARKED) {
995                         if (ptr->pos.x < min.x)
996                                 min.x = ptr->pos.x;
997                         if (ptr->pos.x > max.x)
998                                 max.x = ptr->pos.x;
999                         if (ptr->pos.y < min.y)
1000                                 min.y = ptr->pos.y;
1001                         if (ptr->pos.y > max.y)
1002                                 max.y = ptr->pos.y;
1003                         if (ptr->pos.z < min.z)
1004                                 min.z = ptr->pos.z;
1005                         if (ptr->pos.z > max.z)
1006                                 max.z = ptr->pos.z;
1007                         
1008                         switch (ptr->type) {
1009                                 case OBJ_SHIP:
1010                                 case OBJ_START:
1011                                         ship = ptr->instance;
1012                                         break;
1013
1014                                 case OBJ_WAYPOINT:
1015                                         waypoint = ptr->instance;
1016                                         break;
1017                                 
1018                                 case OBJ_JUMP_NODE:
1019                                         jump_node = ptr->instance;
1020                                         break;
1021
1022                                 default:
1023                                         Int3();
1024                         }
1025
1026                         if (ship >= 0) {
1027                                 team = Ships[ship].team;
1028
1029                                 z = ship_query_general_type(ship);
1030                                 if (z == SHIP_TYPE_CARGO)
1031                                         cargo_count++;
1032
1033                                 if (z == SHIP_TYPE_FREIGHTER)
1034                                 {
1035                                         z = Ai_info[Ships[ship].ai_index].dock_objnum;
1036                                         if (z) {  // docked with anything?
1037                                                 if ((Objects[z].flags & OF_MARKED) && (Objects[z].type == OBJ_SHIP)) {
1038                                                         if (ship_query_general_type(Objects[z].instance) == SHIP_TYPE_CARGO)
1039                                                                 freighter_count++;
1040                                                 }
1041                                         }
1042                                 }
1043                         }
1044
1045                         count++;
1046                 }
1047
1048                 ptr = GET_NEXT(ptr);
1049         }
1050
1051         if (cargo_count && cargo_count == freighter_count)
1052                 cargo = 1;
1053
1054         vm_vec_avg(&pos, &min, &max);
1055         if (ship >= 0)
1056                 name = Ships[ship].ship_name;
1057         else if (waypoint >= 0)
1058                 name = Waypoint_lists[waypoint / 65536].name;
1059         else if (jump_node >= 0)
1060                 name = Jump_nodes[jump_node].name;
1061         else
1062                 return;
1063
1064         len = strlen(name);
1065         if (len >= MAX_LABEL_LEN - 1)
1066                 len = MAX_LABEL_LEN - 1;
1067
1068         strncpy(iconp->label, name, len);
1069         iconp->label[len] = 0;
1070 //      iconp->text[0] = 0;
1071         iconp->type = 0;
1072         iconp->team = team;
1073         iconp->pos = pos;
1074         iconp->flags = 0;
1075         iconp->id = Cur_brief_id++;
1076         if (ship >= 0) {
1077                 iconp->ship_class = Ships[ship].ship_info_index;
1078                 switch (Ship_info[Ships[ship].ship_info_index].flags & SIF_ALL_SHIP_TYPES) {
1079                         case SIF_KNOSSOS_DEVICE:
1080                                 iconp->type = ICON_KNOSSOS_DEVICE;
1081                                 break;
1082
1083                         case SIF_CORVETTE:
1084                                 iconp->type = ICON_CORVETTE;
1085                                 break;
1086
1087                         case SIF_GAS_MINER:
1088                                 iconp->type = ICON_GAS_MINER;
1089                                 break;
1090
1091                         case SIF_SUPERCAP:
1092                                 iconp->type = ICON_SUPERCAP;
1093                                 break;
1094
1095                         case SIF_SENTRYGUN:
1096                                 iconp->type = ICON_SENTRYGUN;
1097                                 break;
1098
1099                         case SIF_AWACS:
1100                                 iconp->type = ICON_AWACS;
1101                                 break;
1102
1103                         case SIF_CARGO:
1104                                 if (cargo)
1105                                         iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO;
1106                                 else
1107                                         iconp->type = count ? ICON_CARGO_WING : ICON_CARGO;
1108
1109                                 break;
1110
1111                         case SIF_SUPPORT:
1112                                 iconp->type = ICON_SUPPORT_SHIP;
1113                                 break;
1114
1115                         case SIF_FIGHTER:
1116                                 iconp->type = count ? ICON_FIGHTER_WING : ICON_FIGHTER;
1117                                 break;
1118
1119                         case SIF_BOMBER:
1120                                 iconp->type = count ? ICON_BOMBER_WING : ICON_BOMBER;
1121                                 break;
1122
1123                         case SIF_FREIGHTER:
1124                                 if (cargo)
1125                                         iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO;
1126                                 else
1127                                         iconp->type = count ? ICON_FREIGHTER_WING_NO_CARGO : ICON_FREIGHTER_NO_CARGO;
1128
1129                                 break;
1130
1131                         case SIF_CRUISER:
1132                                 iconp->type = count ? ICON_CRUISER_WING : ICON_CRUISER;
1133                                 break;
1134
1135                         case SIF_TRANSPORT:
1136                                 iconp->type = count ? ICON_TRANSPORT_WING : ICON_TRANSPORT;
1137                                 break;
1138
1139                         case SIF_CAPITAL:                       
1140                         case SIF_DRYDOCK:
1141                                 iconp->type = ICON_CAPITAL;
1142                                 break;                  
1143
1144                         default:
1145                                 if (Ships[ship].ship_info_index == ship_info_lookup(NAVBUOY_NAME))
1146                                         iconp->type = ICON_WAYPOINT;
1147                                 else
1148                                         iconp->type = ICON_ASTEROID_FIELD;
1149
1150                                 break;
1151                 }
1152         }
1153         // jumpnodes
1154         else if(jump_node >= 0){
1155                 iconp->ship_class = ship_info_lookup(NAVBUOY_NAME);
1156                 iconp->type = ICON_JUMP_NODE;
1157         } 
1158         // everything else
1159         else {
1160                 iconp->ship_class = ship_info_lookup(NAVBUOY_NAME);
1161                 iconp->type = ICON_WAYPOINT;
1162         }
1163
1164         if (!m_change_local){
1165                 propagate_icon(m_cur_icon);
1166         }
1167
1168         icon_obj[m_cur_icon] = obj_create(OBJ_POINT, -1, m_cur_icon, NULL, &pos, 0.0f, OF_RENDERS);
1169         Assert(icon_obj[m_cur_icon] >= 0);
1170         obj_merge_created_list();
1171         unmark_all();
1172         set_cur_object_index(icon_obj[m_cur_icon]);
1173         GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(FALSE);
1174         GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(TRUE);
1175         update_data(1);
1176 }
1177
1178 void briefing_editor_dlg::OnDeleteIcon()
1179 {
1180         delete_icon(m_cur_icon);
1181 }
1182
1183 void briefing_editor_dlg::delete_icon(int num)
1184 {
1185         int i, z;
1186
1187         if (num < 0)
1188                 num = m_cur_icon;
1189
1190         if (num < 0)
1191                 return;
1192
1193         Assert(m_cur_stage >= 0);
1194         Assert(Briefing->stages[m_cur_stage].num_icons);
1195         z = m_cur_icon;
1196         if (z == num)
1197                 z = -1;
1198         if (z > num)
1199                 z--;
1200
1201         m_cur_icon = -1;
1202         update_data(1);
1203         obj_delete(icon_obj[num]);
1204         for (i=num+1; i<Briefing->stages[m_cur_stage].num_icons; i++) {
1205                 Briefing->stages[m_cur_stage].icons[i-1] = Briefing->stages[m_cur_stage].icons[i];
1206                 icon_obj[i-1] = icon_obj[i];
1207                 Objects[icon_obj[i-1]].instance = i - 1;
1208         }
1209
1210         Briefing->stages[m_cur_stage].num_icons--;
1211         if (z >= 0) {
1212                 m_cur_icon = z;
1213                 update_data(0);
1214         }
1215 }
1216
1217 void briefing_editor_dlg::OnGotoView()
1218 {
1219         if (m_cur_stage < 0)
1220                 return;
1221
1222         view_pos = Briefing->stages[m_cur_stage].camera_pos;
1223         view_orient = Briefing->stages[m_cur_stage].camera_orient;
1224         Update_window = 1;
1225 }
1226
1227 void briefing_editor_dlg::OnSaveView()
1228 {
1229         if (m_cur_stage < 0)
1230                 return;
1231
1232         Briefing->stages[m_cur_stage].camera_pos = view_pos;
1233         Briefing->stages[m_cur_stage].camera_orient = view_orient;
1234 }
1235
1236 void briefing_editor_dlg::OnSelchangeIconImage()
1237 {
1238         update_data(1);
1239 }
1240
1241 void briefing_editor_dlg::OnSelchangeTeam()
1242 {
1243         update_data(1);
1244 }
1245
1246 int briefing_editor_dlg::check_mouse_hit(int x, int y)
1247 {
1248         int i;
1249         brief_icon *ptr;
1250
1251         if (m_cur_stage < 0)
1252                 return -1;
1253
1254         for (i=0; i<Briefing->stages[m_cur_stage].num_icons; i++) {
1255                 ptr = &Briefing->stages[m_cur_stage].icons[i];
1256                 if ((x > ptr->x) && (x < ptr->x + ptr->w) && (y > ptr->y) && (y < ptr->y + ptr->h))     {
1257                         return icon_obj[i];
1258                 }
1259         }
1260
1261         return -1;
1262 }
1263
1264 void briefing_editor_dlg::OnPropagateIcons() 
1265 {
1266         object *ptr;
1267
1268         ptr = GET_FIRST(&obj_used_list);
1269         while (ptr != END_OF_LIST(&obj_used_list)) {
1270                 if ((ptr->type == OBJ_POINT) && (ptr->flags & OF_MARKED)) {
1271                         propagate_icon(ptr->instance);
1272                 }
1273
1274                 ptr = GET_NEXT(ptr);
1275         }
1276 }
1277
1278 void briefing_editor_dlg::propagate_icon(int num)
1279 {
1280         int i, s;
1281
1282         for (s=m_cur_stage+1; s<Briefing->num_stages; s++) {
1283                 i = Briefing->stages[s].num_icons;
1284                 if (i >= MAX_STAGE_ICONS)
1285                         continue;
1286
1287                 if (find_icon(Briefing->stages[m_cur_stage].icons[num].id, s) >= 0)
1288                         continue;  // don't change if icon exists here already.
1289
1290                 Briefing->stages[s].icons[i] = Briefing->stages[m_cur_stage].icons[num];
1291                 Briefing->stages[s].num_icons++;
1292         }
1293 }
1294
1295 int briefing_editor_dlg::find_icon(int id, int stage)
1296 {
1297         int i;
1298
1299         if (id >= 0)
1300                 for (i=0; i<Briefing->stages[stage].num_icons; i++)
1301                         if (Briefing->stages[stage].icons[i].id == id)
1302                                 return i;
1303
1304         return -1;
1305 }
1306
1307 void briefing_editor_dlg::reset_icon_loop(int stage)
1308 {
1309         stage_loop = stage + 1;
1310         icon_loop = -1;
1311 }
1312
1313 int briefing_editor_dlg::get_next_icon(int id)
1314 {
1315         while (1) {
1316                 icon_loop++;
1317                 if (icon_loop >= Briefing->stages[stage_loop].num_icons) {
1318                         stage_loop++;
1319                         if (stage_loop > Briefing->num_stages)
1320                                 return 0;
1321
1322                         icon_loop = -1;
1323                         continue;
1324                 }
1325
1326                 iconp = &Briefing->stages[stage_loop].icons[icon_loop];
1327                 if ((id >= 0) && (iconp->id == id))
1328                         return 1;
1329         }
1330 }
1331
1332 BOOL briefing_editor_dlg::OnCommand(WPARAM wParam, LPARAM lParam) 
1333 {
1334         int id;
1335
1336         // deal with figuring out menu stuff
1337         id = LOWORD(wParam);
1338         if ( (id >= ID_TEAM_1) && (id < ID_TEAM_3) ) {
1339                 m_current_briefing = id - ID_TEAM_1;
1340
1341                 // put user back at first stage for this team (or no current stage is there are none).
1342                 Briefing = &Briefings[m_current_briefing];
1343                 if ( Briefing->num_stages > 0 )
1344                         m_cur_stage = 0;
1345                 else
1346                         m_cur_stage = -1;
1347
1348                 update_data(1);
1349                 OnGotoView();
1350                 return 1;
1351         }
1352
1353         return CDialog::OnCommand(wParam, lParam);
1354 }
1355
1356 void briefing_editor_dlg::OnLines() 
1357 {
1358         if (m_lines.GetCheck() == 1)
1359                 m_lines.SetCheck(0);
1360         else
1361                 m_lines.SetCheck(1);
1362
1363         update_data(1);
1364 }
1365
1366 void briefing_editor_dlg::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult) 
1367 {
1368         m_tree.right_clicked(); 
1369         *pResult = 0;
1370 }
1371
1372 void briefing_editor_dlg::OnBeginlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
1373 {
1374         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
1375
1376         if (m_tree.edit_label(pTVDispInfo->item.hItem) == 1)    {
1377                 *pResult = 0;
1378                 modified = 1;
1379
1380         } else
1381                 *pResult = 1;
1382 }
1383
1384 void briefing_editor_dlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult) 
1385 {
1386         TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
1387
1388         *pResult = m_tree.end_label_edit(pTVDispInfo->item.hItem, pTVDispInfo->item.pszText);
1389 }
1390
1391 BOOL briefing_editor_dlg::DestroyWindow() 
1392 {
1393         m_play_bm.DeleteObject();
1394         return CDialog::DestroyWindow();
1395 }
1396
1397 void briefing_editor_dlg::OnPlay() 
1398 {
1399         char path[MAX_PATH_LEN + 1];
1400         GetDlgItem(IDC_VOICE)->GetWindowText(m_voice);
1401
1402         int size, offset;
1403         cf_find_file_location((char *) (LPCSTR) m_voice, CF_TYPE_ANY, path, &size, &offset );
1404
1405         PlaySound(path, NULL, SND_ASYNC | SND_FILENAME);
1406 }
1407
1408 void briefing_editor_dlg::OnCopyView() 
1409 {
1410         // TODO: Add your control notification handler code here
1411
1412         m_copy_view_set = 1;
1413         m_copy_view_pos = view_pos;
1414         m_copy_view_orient = view_orient;
1415 }
1416
1417 void briefing_editor_dlg::OnPasteView() 
1418 {
1419         // TODO: Add your control notification handler code here
1420         if (m_cur_stage < 0)
1421                 return;
1422
1423         if (m_copy_view_set == 0) {
1424                 MessageBox("No view set", "Unable to copy view");
1425         } else {
1426                 Briefing->stages[m_cur_stage].camera_pos = m_copy_view_pos;
1427                 Briefing->stages[m_cur_stage].camera_orient = m_copy_view_orient;
1428                 
1429                 update_data(1);
1430                 OnGotoView();
1431         }
1432 }