2 * $Logfile: /Freespace2/code/Fred2/BriefingEditorDlg.cpp $
7 * Briefing editor dialog box class.
10 * Revision 1.1 2002/05/03 03:28:08 root
14 * 9 7/19/99 3:01p Dave
15 * Fixed icons. Added single transport icon.
17 * 8 7/18/99 5:19p Dave
18 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
20 * 7 7/09/99 5:54p Dave
21 * Seperated cruiser types into individual types. Added tons of new
22 * briefing icons. Campaign screen.
24 * 6 5/20/99 1:46p Andsager
25 * Add briefing view copy and paste between stages
27 * 5 4/23/99 12:01p Johnson
30 * 4 11/30/98 5:32p Dave
31 * Fixed up Fred support for software mode.
33 * 3 10/16/98 4:28p Andsager
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.
41 * 1 10/07/98 3:02p Dave
43 * 1 10/07/98 3:00p Dave
45 * 63 5/21/98 4:20p Dave
46 * Fixed bug with briefing editor when no current stage selected.
48 * 62 5/21/98 12:58a Hoffoss
49 * Fixed warnings optimized build turned up.
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
56 * 60 4/30/98 8:23p John
57 * Fixed some bugs with Fred caused by my new cfile code.
59 * 59 4/22/98 9:56a Sandeep
61 * 58 4/20/98 4:40p Hoffoss
62 * Added a button to 4 editors to play the chosen wave file.
64 * 57 4/16/98 2:49p Johnson
65 * Fixed initialization for new icons in briefing.
67 * 56 4/07/98 6:32p Dave
68 * Fixed function I forget to change back.
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.
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.
79 * 53 4/06/98 5:37p Hoffoss
80 * Added sexp tree support to briefings in Fred.
82 * 52 4/06/98 10:43a John
83 * Fixed bugs with inserting/deleting stages
85 * 51 4/03/98 12:39p Hoffoss
86 * Changed starting directory for browse buttons in several editors.
88 * 50 4/03/98 11:34a John
89 * Fixed the stuff I broke in Fred from the new breifing
91 * 49 3/26/98 6:40p Lawrance
92 * Don't store icon text for briefings
94 * 48 3/21/98 7:36p Lawrance
95 * Move jump nodes to own lib.
97 * 47 3/19/98 4:24p Hoffoss
98 * Added remaining support for command brief screen (ANI and WAVE file
101 * 46 3/17/98 2:00p Hoffoss
102 * Added ability to make an icon from a jump node in briefing editor.
104 * 45 2/18/98 6:44p Hoffoss
105 * Added support for lines between icons in briefings for Fred.
107 * 44 2/09/98 9:25p Allender
108 * team v team support. multiple pools and breifings
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
114 * 42 1/28/98 7:19p Lawrance
115 * Get fading/highlighting animations working
117 * 41 12/28/97 5:52p Lawrance
118 * Add support for debriefing success/fail music.
120 * 40 11/04/97 4:33p Hoffoss
121 * Made saving keep the current briefing state intact.
123 * 39 11/04/97 11:31a Duncan
124 * Made make icon button gray if at max icons already.
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
131 * 37 10/19/97 11:32p Hoffoss
132 * Added support for briefing cuts in Fred.
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.
138 * 35 9/30/97 5:56p Hoffoss
139 * Added music selection combo boxes to Fred.
145 #include <mmsystem.h>
147 #include "briefingeditordlg.h"
149 #include "missionbriefcommon.h"
150 #include "missionparse.h"
151 #include "fredrender.h"
152 #include "management.h"
153 #include "linklist.h"
156 #include "eventmusic.h"
157 #include "starfield.h"
158 #include "jumpnode.h"
162 #define new DEBUG_NEW
164 static char THIS_FILE[] = __FILE__;
168 #define NAVBUOY_NAME "Terran NavBuoy"
170 static int Max_icons_for_lines;
172 /////////////////////////////////////////////////////////////////////////////
173 // briefing_editor_dlg dialog
175 briefing_editor_dlg::briefing_editor_dlg(CWnd* pParent /*=NULL*/)
176 : CDialog(briefing_editor_dlg::IDD, pParent)
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;
184 i = ++Max_icons_for_lines + 1;
189 } while (z < MAX_BRIEF_STAGE_LINES);
191 //{{AFX_DATA_INIT(briefing_editor_dlg)
194 m_icon_label = _T("");
195 m_stage_title = _T("");
199 m_icon_text = _T("");
202 m_change_local = FALSE;
204 m_briefing_music = -1;
207 m_current_briefing = -1;
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
213 // copy view initialization
217 void briefing_editor_dlg::DoDataExchange(CDataExchange* pDX)
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);
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);
246 BEGIN_MESSAGE_MAP(briefing_editor_dlg, CDialog)
247 //{{AFX_MSG_MAP(briefing_editor_dlg)
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)
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)
273 /////////////////////////////////////////////////////////////////////////////
274 // briefing_editor_dlg message handlers
276 void briefing_editor_dlg::OnInitMenu(CMenu* pMenu)
281 // disable any items we should disable
282 m = pMenu->GetSubMenu(0);
284 // uncheck all menu items
285 for (i=0; i<Num_teams; i++)
286 m->CheckMenuItem(i, MF_BYPOSITION | MF_UNCHECKED);
288 for (i=Num_teams; i<MAX_TEAMS; i++)
289 m->EnableMenuItem(i, MF_BYPOSITION | MF_GRAYED);
291 // put a check next to the currently selected item
292 m->CheckMenuItem(m_current_briefing, MF_BYPOSITION | MF_CHECKED );
294 CDialog::OnInitMenu(pMenu);
297 void briefing_editor_dlg::create()
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]);
308 box = (CComboBox *) GetDlgItem(IDC_TEAM);
309 for (i=0; i<Num_team_names; i++)
310 box->AddString(Team_names[i]);
312 box = (CComboBox *) GetDlgItem(IDC_SHIP_TYPE);
313 for (i=0; i<Num_ship_types; i++)
314 box->AddString(Ship_info[i].name);
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);
321 m_play_bm.LoadBitmap(IDB_PLAY);
322 ((CButton *) GetDlgItem(IDC_PLAY)) -> SetBitmap(m_play_bm);
324 m_current_briefing = 0;
325 Briefing = &Briefings[m_current_briefing];
326 m_briefing_music = Mission_music[SCORE_BRIEFING] + 1;
333 void briefing_editor_dlg::focus_sexp(int select_sexp_node)
337 n = m_tree.select_sexp_node = select_sexp_node;
339 for (i=0; i<Briefing->num_stages; i++)
340 if (query_node_in_sexp(n, Briefing->stages[i].formula))
343 if (i < Briefing->num_stages) {
346 GetDlgItem(IDC_TREE) -> SetFocus();
347 m_tree.hilite_item(m_tree.select_sexp_node);
352 void briefing_editor_dlg::OnOK()
356 void briefing_editor_dlg::OnCancel()
361 void briefing_editor_dlg::OnClose()
363 int bs, i, j, s, t, dup = 0;
364 briefing_editor_dlg *ptr;
370 for ( bs = 0; bs < Num_teams; bs++ ) {
371 for (s=0; s<Briefing[bs].num_stages; s++) {
372 sp = &Briefing[bs].stages[s];
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))
383 MessageBox("You have duplicate icons names. You should resolve these.", "Warning");
385 theApp.record_window_data(&Briefing_wnd_data, this);
386 ptr = Briefing_dialog;
387 Briefing_dialog = NULL;
391 void briefing_editor_dlg::reset_editor()
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()
401 stage_saved = m_cur_stage;
402 icon_saved = m_cur_icon;
405 void briefing_editor_dlg::restore_editor_state()
407 m_cur_stage = stage_saved;
408 m_cur_icon = icon_saved;
411 void briefing_editor_dlg::update_data(int update)
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;
416 brief_stage *ptr = NULL;
421 // save off current data before we update over it with new briefing stage/team stuff
422 Briefing = save_briefing;
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))
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);
436 i |= BS_BACKWARD_CUT;
438 i &= ~BS_BACKWARD_CUT;
443 i &= ~BS_FORWARD_CUT;
445 MODIFY(ptr->flags, i);
446 ptr->formula = m_tree.save_tree();
447 switch (m_lines.GetCheck()) {
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)) )
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;
468 // remove all existing lines between any 2 marked icons
471 if ( icon_marked[ptr->lines[i].start_icon] && icon_marked[ptr->lines[i].end_icon] ) {
473 for (l=i; l<ptr->num_lines; l++)
474 ptr->lines[l] = ptr->lines[l + 1];
480 if (m_last_icon >= 0) {
481 valid = (m_id != ptr->icons[m_last_icon].id);
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) {
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);
492 m_id = ptr->icons[m_last_icon].id;
499 for (i=0; i<ptr->num_icons; i++)
500 if ((i != m_last_icon) && (ptr->icons[i].id == m_id)) {
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);
506 m_id = ptr->icons[m_last_icon].id;
511 if (valid && !m_change_local) {
513 reset_icon_loop(m_last_stage);
514 while (get_next_icon(ptr->icons[m_last_icon].id))
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) {
523 reset_icon_loop(m_last_stage);
524 while (get_next_icon(m_id))
525 strcpy(iconp->label, buf);
528 strcpy(ptr->icons[m_last_icon].label, buf);
530 ptr->icons[m_last_icon].flags |= BI_HIGHLIGHT;
532 ptr->icons[m_last_icon].flags &= ~BI_HIGHLIGHT;
534 if ((ptr->icons[m_last_icon].type != m_icon_image) && !m_change_local) {
536 reset_icon_loop(m_last_stage);
537 while (get_next_icon(m_id))
538 iconp->type = m_icon_image;
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) {
544 reset_icon_loop(m_last_stage);
545 while (get_next_icon(m_id))
546 iconp->team = (1 << m_icon_team);
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) {
552 reset_icon_loop(m_last_stage);
553 while (get_next_icon(m_id))
554 iconp->ship_class = m_ship_type;
557 MODIFY(ptr->icons[m_last_icon].ship_class, m_ship_type);
558 deconvert_multiline_string(buf2, m_icon_text, MAX_ICON_TEXT_LEN);
560 if (stricmp(ptr->icons[m_last_icon].text, buf2) && !m_change_local) {
562 reset_icon_loop(m_last_stage);
563 while (get_next_icon(m_id))
564 strcpy(iconp->text, buf2);
567 strcpy(ptr->icons[m_last_icon].text, buf2);
572 if (!::IsWindow(m_hWnd))
575 // set briefing pointer to correct team
576 Briefing = &Briefings[m_current_briefing];
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);
589 m_stage_title = _T("No stages");
593 m_cut_prev = m_cut_next = 0;
599 if (m_cur_stage == Briefing->num_stages - 1)
600 GetDlgItem(IDC_NEXT) -> EnableWindow(FALSE);
602 GetDlgItem(IDC_NEXT) -> EnableWindow(enable);
605 GetDlgItem(IDC_PREV) -> EnableWindow(enable);
607 GetDlgItem(IDC_PREV) -> EnableWindow(FALSE);
609 if (Briefing->num_stages >= MAX_BRIEF_STAGES)
610 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(FALSE);
612 GetDlgItem(IDC_ADD_STAGE) -> EnableWindow(TRUE);
614 if (Briefing->num_stages) {
615 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(enable);
616 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(enable);
618 GetDlgItem(IDC_DELETE_STAGE) -> EnableWindow(FALSE);
619 GetDlgItem(IDC_INSERT_STAGE) -> EnableWindow(FALSE);
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);
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;
648 m_icon_label = _T("");
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);
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))
673 objp = GET_NEXT(objp);
676 if (m_cur_stage >= 0)
677 ptr = &Briefing->stages[m_cur_stage];
679 if (valid && !invalid && (m_cur_stage >= 0) && (ptr->num_icons < MAX_STAGE_ICONS))
680 GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(TRUE);
682 GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(FALSE);
684 if (m_cur_stage >= 0)
685 for (i=0; i<ptr->num_icons; i++)
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) {
694 icon_marked[objp->instance] = 1;
700 objp = GET_NEXT(objp);
703 if (valid && !invalid && (m_cur_stage >= 0))
704 GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(TRUE);
706 GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(FALSE);
709 lines = 1; // default lines checkbox to checked
711 if (m_cur_stage >= 0) {
712 for (i=0; i<ptr->num_lines; i++)
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)) ) {
722 count++; // track number of marked lines (lines between 2 icons that are both marked)
726 // at least 1 line missing between 2 marked icons, so use mixed state
727 if (l == ptr->num_lines)
733 // not even 1 line between any 2 marked icons? Set checkbox to unchecked.
738 if (m_cur_stage >= 0){
739 i = calc_num_lines_for_icons(valid) + ptr->num_lines - count;
742 if ((valid > 1) && !invalid && (m_cur_stage >= 0) && (i <= MAX_BRIEF_STAGE_LINES))
743 GetDlgItem(IDC_LINES) -> EnableWindow(TRUE);
745 GetDlgItem(IDC_LINES) -> EnableWindow(FALSE);
747 m_lines.SetCheck(lines);
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]);
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);
766 obj_merge_created_list();
769 m_last_stage = m_cur_stage;
772 m_last_icon = m_cur_icon;
774 save_briefing = Briefing;
777 // Given a number of icons, figure out how many lines would be required to connect each one
778 // with all of the others.
780 int briefing_editor_dlg::calc_num_lines_for_icons(int num)
787 // Basically, this is # lines = (# icons - 1) factorial
794 void briefing_editor_dlg::OnNext()
802 void briefing_editor_dlg::OnPrev()
810 void briefing_editor_dlg::OnBrowse()
817 if (The_mission.game_type & MISSION_TYPE_TRAINING)
818 z = cfile_push_chdir(CF_TYPE_VOICE_TRAINING);
820 z = cfile_push_chdir(CF_TYPE_VOICE_BRIEFINGS);
822 CFileDialog dlg(TRUE, "wav", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
823 "Wave Files (*.wav)|*.wav||");
825 if (dlg.DoModal() == IDOK) {
826 m_voice = dlg.GetFileName();
834 void briefing_editor_dlg::OnAddStage()
838 if (Briefing->num_stages >= MAX_BRIEF_STAGES)
841 m_cur_stage = i = Briefing->num_stages++;
842 copy_stage(i - 1, i);
846 void briefing_editor_dlg::OnDeleteStage()
853 Assert(Briefing->num_stages);
857 for (i=z+1; i<Briefing->num_stages; i++) {
861 Briefing->num_stages--;
863 if (m_cur_stage >= Briefing->num_stages)
864 m_cur_stage = Briefing->num_stages - 1;
869 void briefing_editor_dlg::draw_icon(object *objp)
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);
878 void briefing_editor_dlg::batch_render()
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);
891 void briefing_editor_dlg::icon_select(int num)
897 void briefing_editor_dlg::OnInsertStage()
901 if (Briefing->num_stages >= MAX_BRIEF_STAGES)
904 if (!Briefing->num_stages) {
912 for (i=Briefing->num_stages; i>z; i--) {
916 Briefing->num_stages++;
917 copy_stage(z, z + 1);
922 void briefing_editor_dlg::copy_stage(int from, int to)
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;
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;
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 );
950 void briefing_editor_dlg::update_positions()
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);
967 Briefing->stages[s].icons[z].pos = Objects[icon_obj[i]].pos;
973 void briefing_editor_dlg::OnMakeIcon()
976 int z, len, team, ship, waypoint, jump_node, count = -1;
977 int cargo = 0, cargo_count = 0, freighter_count = 0;
979 vector min, max, pos;
982 if (Briefing->stages[m_cur_stage].num_icons >= MAX_STAGE_ICONS)
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;
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)
997 if (ptr->pos.x > max.x)
999 if (ptr->pos.y < min.y)
1001 if (ptr->pos.y > max.y)
1003 if (ptr->pos.z < min.z)
1005 if (ptr->pos.z > max.z)
1008 switch (ptr->type) {
1011 ship = ptr->instance;
1015 waypoint = ptr->instance;
1019 jump_node = ptr->instance;
1027 team = Ships[ship].team;
1029 z = ship_query_general_type(ship);
1030 if (z == SHIP_TYPE_CARGO)
1033 if (z == SHIP_TYPE_FREIGHTER)
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)
1048 ptr = GET_NEXT(ptr);
1051 if (cargo_count && cargo_count == freighter_count)
1054 vm_vec_avg(&pos, &min, &max);
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;
1065 if (len >= MAX_LABEL_LEN - 1)
1066 len = MAX_LABEL_LEN - 1;
1068 strncpy(iconp->label, name, len);
1069 iconp->label[len] = 0;
1070 // iconp->text[0] = 0;
1075 iconp->id = Cur_brief_id++;
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;
1084 iconp->type = ICON_CORVETTE;
1088 iconp->type = ICON_GAS_MINER;
1092 iconp->type = ICON_SUPERCAP;
1096 iconp->type = ICON_SENTRYGUN;
1100 iconp->type = ICON_AWACS;
1105 iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO;
1107 iconp->type = count ? ICON_CARGO_WING : ICON_CARGO;
1112 iconp->type = ICON_SUPPORT_SHIP;
1116 iconp->type = count ? ICON_FIGHTER_WING : ICON_FIGHTER;
1120 iconp->type = count ? ICON_BOMBER_WING : ICON_BOMBER;
1125 iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO;
1127 iconp->type = count ? ICON_FREIGHTER_WING_NO_CARGO : ICON_FREIGHTER_NO_CARGO;
1132 iconp->type = count ? ICON_CRUISER_WING : ICON_CRUISER;
1136 iconp->type = count ? ICON_TRANSPORT_WING : ICON_TRANSPORT;
1141 iconp->type = ICON_CAPITAL;
1145 if (Ships[ship].ship_info_index == ship_info_lookup(NAVBUOY_NAME))
1146 iconp->type = ICON_WAYPOINT;
1148 iconp->type = ICON_ASTEROID_FIELD;
1154 else if(jump_node >= 0){
1155 iconp->ship_class = ship_info_lookup(NAVBUOY_NAME);
1156 iconp->type = ICON_JUMP_NODE;
1160 iconp->ship_class = ship_info_lookup(NAVBUOY_NAME);
1161 iconp->type = ICON_WAYPOINT;
1164 if (!m_change_local){
1165 propagate_icon(m_cur_icon);
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();
1172 set_cur_object_index(icon_obj[m_cur_icon]);
1173 GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(FALSE);
1174 GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(TRUE);
1178 void briefing_editor_dlg::OnDeleteIcon()
1180 delete_icon(m_cur_icon);
1183 void briefing_editor_dlg::delete_icon(int num)
1193 Assert(m_cur_stage >= 0);
1194 Assert(Briefing->stages[m_cur_stage].num_icons);
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;
1210 Briefing->stages[m_cur_stage].num_icons--;
1217 void briefing_editor_dlg::OnGotoView()
1219 if (m_cur_stage < 0)
1222 view_pos = Briefing->stages[m_cur_stage].camera_pos;
1223 view_orient = Briefing->stages[m_cur_stage].camera_orient;
1227 void briefing_editor_dlg::OnSaveView()
1229 if (m_cur_stage < 0)
1232 Briefing->stages[m_cur_stage].camera_pos = view_pos;
1233 Briefing->stages[m_cur_stage].camera_orient = view_orient;
1236 void briefing_editor_dlg::OnSelchangeIconImage()
1241 void briefing_editor_dlg::OnSelchangeTeam()
1246 int briefing_editor_dlg::check_mouse_hit(int x, int y)
1251 if (m_cur_stage < 0)
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)) {
1264 void briefing_editor_dlg::OnPropagateIcons()
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);
1274 ptr = GET_NEXT(ptr);
1278 void briefing_editor_dlg::propagate_icon(int num)
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)
1287 if (find_icon(Briefing->stages[m_cur_stage].icons[num].id, s) >= 0)
1288 continue; // don't change if icon exists here already.
1290 Briefing->stages[s].icons[i] = Briefing->stages[m_cur_stage].icons[num];
1291 Briefing->stages[s].num_icons++;
1295 int briefing_editor_dlg::find_icon(int id, int stage)
1300 for (i=0; i<Briefing->stages[stage].num_icons; i++)
1301 if (Briefing->stages[stage].icons[i].id == id)
1307 void briefing_editor_dlg::reset_icon_loop(int stage)
1309 stage_loop = stage + 1;
1313 int briefing_editor_dlg::get_next_icon(int id)
1317 if (icon_loop >= Briefing->stages[stage_loop].num_icons) {
1319 if (stage_loop > Briefing->num_stages)
1326 iconp = &Briefing->stages[stage_loop].icons[icon_loop];
1327 if ((id >= 0) && (iconp->id == id))
1332 BOOL briefing_editor_dlg::OnCommand(WPARAM wParam, LPARAM lParam)
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;
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 )
1353 return CDialog::OnCommand(wParam, lParam);
1356 void briefing_editor_dlg::OnLines()
1358 if (m_lines.GetCheck() == 1)
1359 m_lines.SetCheck(0);
1361 m_lines.SetCheck(1);
1366 void briefing_editor_dlg::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult)
1368 m_tree.right_clicked();
1372 void briefing_editor_dlg::OnBeginlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult)
1374 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
1376 if (m_tree.edit_label(pTVDispInfo->item.hItem) == 1) {
1384 void briefing_editor_dlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult)
1386 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
1388 *pResult = m_tree.end_label_edit(pTVDispInfo->item.hItem, pTVDispInfo->item.pszText);
1391 BOOL briefing_editor_dlg::DestroyWindow()
1393 m_play_bm.DeleteObject();
1394 return CDialog::DestroyWindow();
1397 void briefing_editor_dlg::OnPlay()
1399 char path[MAX_PATH_LEN + 1];
1400 GetDlgItem(IDC_VOICE)->GetWindowText(m_voice);
1403 cf_find_file_location((char *) (LPCSTR) m_voice, CF_TYPE_ANY, path, &size, &offset );
1405 PlaySound(path, NULL, SND_ASYNC | SND_FILENAME);
1408 void briefing_editor_dlg::OnCopyView()
1410 // TODO: Add your control notification handler code here
1412 m_copy_view_set = 1;
1413 m_copy_view_pos = view_pos;
1414 m_copy_view_orient = view_orient;
1417 void briefing_editor_dlg::OnPasteView()
1419 // TODO: Add your control notification handler code here
1420 if (m_cur_stage < 0)
1423 if (m_copy_view_set == 0) {
1424 MessageBox("No view set", "Unable to copy view");
1426 Briefing->stages[m_cur_stage].camera_pos = m_copy_view_pos;
1427 Briefing->stages[m_cur_stage].camera_orient = m_copy_view_orient;