2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
9 // CampaignEditorDlg.cpp : implementation file
15 #include "campaigneditordlg.h"
16 #include "campaigntreeview.h"
17 #include "campaigntreewnd.h"
18 #include "management.h"
21 #include "missiongoals.h"
26 static char THIS_FILE[] = __FILE__;
29 int Cur_campaign_mission = -1;
30 int Cur_campaign_link = -1;
32 // determine the node number that would be allocated without actually allocating it yet.
33 int campaign_sexp_tree::get_new_node_position()
37 for (i=0; i<MAX_SEXP_TREE_SIZE; i++){
38 if (nodes[i].type == SEXPT_UNUSED){
46 // construct tree nodes for an sexp, adding them to the list and returning first node
47 int campaign_sexp_tree::load_sub_tree(int index)
52 cur = allocate_node(-1);
53 set_node(cur, (SEXPT_OPERATOR | SEXPT_VALID), "do-nothing"); // setup a default tree if none
57 // assumption: first token is an operator. I require this because it would cause problems
58 // with child/parent relations otherwise, and it should be this way anyway, since the
59 // return type of the whole sexp is boolean, and only operators can satisfy this.
60 SDL_assert(Sexp_nodes[index].subtype == SEXP_ATOM_OPERATOR);
61 cur = get_new_node_position();
62 load_branch(index, -1);
66 /////////////////////////////////////////////////////////////////////////////
69 IMPLEMENT_DYNCREATE(campaign_editor, CFormView)
71 campaign_editor *Campaign_tree_formp;
73 campaign_editor::campaign_editor()
74 : CFormView(campaign_editor::IDD)
76 //{{AFX_DATA_INIT(campaign_editor)
79 m_num_players = _T("");
82 m_loop_brief_anim = _T("");
83 m_loop_brief_sound = _T("");
86 m_tree.m_mode = MODE_CAMPAIGN;
88 m_tree.link_modified(&Campaign_modified);
92 campaign_editor::~campaign_editor()
96 void campaign_editor::DoDataExchange(CDataExchange* pDX)
98 CFormView::DoDataExchange(pDX);
99 //{{AFX_DATA_MAP(campaign_editor)
100 DDX_Control(pDX, IDC_SEXP_TREE, m_tree);
101 DDX_Control(pDX, IDC_FILELIST, m_filelist);
102 DDX_Text(pDX, IDC_NAME, m_name);
103 DDX_CBIndex(pDX, IDC_CAMPAIGN_TYPE, m_type);
104 DDX_Text(pDX, IDC_NUM_PLAYERS, m_num_players);
105 DDX_Text(pDX, IDC_DESC2, m_desc);
106 DDX_Text(pDX, IDC_MISSISON_LOOP_DESC, m_loop_desc);
107 DDX_Text(pDX, IDC_LOOP_BRIEF_ANIM, m_loop_brief_anim);
108 DDX_Text(pDX, IDC_LOOP_BRIEF_SOUND, m_loop_brief_sound);
111 DDV_MaxChars(pDX, m_desc, MISSION_DESC_LENGTH - 1);
112 DDV_MaxChars(pDX, m_loop_desc, MISSION_DESC_LENGTH - 1);
115 BEGIN_MESSAGE_MAP(campaign_editor, CFormView)
116 //{{AFX_MSG_MAP(campaign_editor)
117 ON_BN_CLICKED(ID_LOAD, OnLoad)
118 ON_BN_CLICKED(IDC_ALIGN, OnAlign)
119 ON_BN_CLICKED(ID_CPGN_CLOSE, OnCpgnClose)
120 ON_NOTIFY(NM_RCLICK, IDC_SEXP_TREE, OnRclickTree)
121 ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_SEXP_TREE, OnBeginlabeleditSexpTree)
122 ON_NOTIFY(TVN_ENDLABELEDIT, IDC_SEXP_TREE, OnEndlabeleditSexpTree)
123 ON_NOTIFY(TVN_SELCHANGED, IDC_SEXP_TREE, OnSelchangedSexpTree)
124 ON_BN_CLICKED(IDC_MOVE_UP, OnMoveUp)
125 ON_BN_CLICKED(IDC_MOVE_DOWN, OnMoveDown)
126 ON_COMMAND(ID_END_EDIT, OnEndEdit)
127 ON_EN_CHANGE(IDC_BRIEFING_CUTSCENE, OnChangeBriefingCutscene)
128 ON_CBN_SELCHANGE(IDC_CAMPAIGN_TYPE, OnSelchangeType)
129 ON_BN_CLICKED(IDC_GALATEA, OnGalatea)
130 ON_BN_CLICKED(IDC_BASTION, OnBastion)
131 ON_BN_CLICKED(IDC_TOGGLE_LOOP, OnToggleLoop)
132 ON_BN_CLICKED(IDC_LOOP_BRIEF_BROWSE, OnBrowseLoopAni)
133 ON_BN_CLICKED(IDC_LOOP_BRIEF_SOUND_BROWSE, OnBrowseLoopSound)
137 /////////////////////////////////////////////////////////////////////////////
138 // campaign_editor diagnostics
141 void campaign_editor::AssertValid() const
143 CFormView::AssertValid();
146 void campaign_editor::Dump(CDumpContext& dc) const
152 /////////////////////////////////////////////////////////////////////////////
153 // campaign_editor message handlers
155 void campaign_editor::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
160 void campaign_editor::OnLoad()
164 if (Cur_campaign_mission < 0){
168 if (Campaign_modified){
169 if (Campaign_wnd->save_modified()){
174 GetCurrentDirectory(512, buf);
176 strcat(buf, Campaign.missions[Cur_campaign_mission].name);
177 FREDDoc_ptr->SetPathName(buf);
178 Campaign_wnd->DestroyWindow();
180 // if (FREDDoc_ptr->OnOpenDocument(Campaign.missions[Cur_campaign_mission].name)) {
181 // Bypass_clear_mission = 1;
182 // Campaign_wnd->DestroyWindow();
185 // MessageBox("Failed to load mission!", "Error");
189 BOOL campaign_editor::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
195 r = CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
197 box = (CComboBox *) GetDlgItem(IDC_CAMPAIGN_TYPE);
199 for (i=0; i<MAX_CAMPAIGN_TYPES; i++){
200 box->AddString(campaign_types[i]);
207 void campaign_editor::load_campaign()
209 Cur_campaign_mission = Cur_campaign_link = -1;
212 if (!strlen(Campaign.filename))
213 strcpy(Campaign.filename, BUILTIN_CAMPAIGN);
215 if (mission_campaign_load(Campaign.filename, 0)) {
216 MessageBox("Couldn't open Campaign file!", "Error");
217 Campaign_wnd->OnCpgnFileNew();
221 Campaign_modified = 0;
222 Campaign_tree_viewp->construct_tree();
226 void campaign_editor::OnAlign()
228 Campaign_tree_viewp->sort_elements();
229 Campaign_tree_viewp->realign_tree();
230 Campaign_tree_viewp->Invalidate();
233 void campaign_editor::initialize( int init_files )
235 Cur_campaign_mission = Cur_campaign_link = -1;
236 m_tree.setup((CEdit *) GetDlgItem(IDC_HELP_BOX));
238 Campaign_tree_viewp->initialize();
240 // only initialize the file dialog box when the parameter says to. This should
241 // only happen when a campaign type changes
243 m_filelist.initialize();
246 m_name = Campaign.name;
247 m_type = Campaign.type;
248 m_num_players.Format("%d", Campaign.num_players);
251 m_desc = convert_multiline_string(Campaign.desc);
256 m_loop_desc = _T("");
258 m_loop_brief_anim = _T("");
259 m_loop_brief_sound = _T("");
261 // single player should hide the two dialog items about number of players allowed
262 if ( m_type == CAMPAIGN_TYPE_SINGLE ) {
263 GetDlgItem(IDC_NUM_PLAYERS)->ShowWindow( SW_HIDE );
264 GetDlgItem(IDC_PLAYERS_LABEL)->ShowWindow( SW_HIDE );
266 GetDlgItem(IDC_NUM_PLAYERS)->ShowWindow( SW_SHOW );
267 GetDlgItem(IDC_PLAYERS_LABEL)->ShowWindow( SW_SHOW );
273 void campaign_editor::mission_selected(int num)
277 bc_dialog = (CEdit *) GetDlgItem(IDC_BRIEFING_CUTSCENE);
279 // clear out the text for the briefing cutscene, and put in new text if specified
280 bc_dialog->SetWindowText("");
281 if ( strlen(Campaign.missions[num].briefing_cutscene) )
282 bc_dialog->SetWindowText(Campaign.missions[num].briefing_cutscene);
284 if (Campaign.missions[num].flags & CMISSION_FLAG_BASTION) {
285 ((CButton *) GetDlgItem(IDC_GALATEA)) -> SetCheck(0);
286 ((CButton *) GetDlgItem(IDC_BASTION)) -> SetCheck(1);
289 ((CButton *) GetDlgItem(IDC_GALATEA)) -> SetCheck(1);
290 ((CButton *) GetDlgItem(IDC_BASTION)) -> SetCheck(0);
294 void campaign_editor::update()
296 char buf[MISSION_DESC_LENGTH];
298 // get data from dlog box
301 // update campaign name
302 string_copy(Campaign.name, m_name, NAME_LENGTH);
303 Campaign.type = m_type;
305 // update campaign desc
306 deconvert_multiline_string(buf, m_desc, MISSION_DESC_LENGTH);
311 Campaign.desc = NULL;
313 Campaign.desc = strdup(buf);
316 // maybe update mission loop text
317 save_loop_desc_window();
319 // set the number of players in a multiplayer mission equal to the number of players in the first mission
320 if ( Campaign.type != CAMPAIGN_TYPE_SINGLE ) {
321 if ( Campaign.num_missions == 0 ) {
322 Campaign.num_players = 0;
326 get_mission_info(Campaign.missions[0].name, &a_mission);
327 Campaign.num_players = a_mission.num_players;
332 void campaign_editor::OnCpgnClose()
334 Campaign_wnd->OnClose();
337 void campaign_editor::load_tree(int save_first)
347 m_tree.DeleteAllItems();
350 update_loop_desc_window();
352 m_last_mission = Cur_campaign_mission;
353 if (Cur_campaign_mission < 0) {
354 GetDlgItem(IDC_SEXP_TREE)->EnableWindow(FALSE);
355 GetDlgItem(IDC_BRIEFING_CUTSCENE)->EnableWindow(FALSE);
359 GetDlgItem(IDC_SEXP_TREE)->EnableWindow(TRUE);
360 GetDlgItem(IDC_BRIEFING_CUTSCENE)->EnableWindow(TRUE);
362 GetDlgItem(IDC_MISSISON_LOOP_DESC)->EnableWindow(FALSE);
363 GetDlgItem(IDC_LOOP_BRIEF_ANIM)->EnableWindow(FALSE);
364 GetDlgItem(IDC_LOOP_BRIEF_SOUND)->EnableWindow(FALSE);
365 GetDlgItem(IDC_LOOP_BRIEF_BROWSE)->EnableWindow(FALSE);
366 GetDlgItem(IDC_LOOP_BRIEF_SOUND_BROWSE)->EnableWindow(FALSE);
368 for (i=0; i<Total_links; i++) {
369 if (Links[i].from == Cur_campaign_mission) {
370 Links[i].node = m_tree.load_sub_tree(Links[i].sexp);
373 if (Links[i].from == Links[i].to) {
374 strcpy(text, "Repeat mission");
375 } else if ( (Links[i].to == -1) && (Links[i].from != -1) ) {
376 strcpy(text, "End of Campaign");
378 sprintf(text, "Branch to %s", Campaign.missions[Links[i].to].name);
381 // insert item into tree
382 int image, sel_image;
383 if (Links[i].mission_loop) {
384 image = BITMAP_BLUE_DOT;
385 sel_image = BITMAP_GREEN_DOT;
387 image = BITMAP_BLACK_DOT;
388 sel_image = BITMAP_RED_DOT;
391 h = m_tree.insert(text, image, sel_image);
393 m_tree.SetItemData(h, Links[i].node);
394 m_tree.add_sub_tree(Links[i].node, h);
399 void campaign_editor::OnRclickTree(NMHDR* pNMHDR, LRESULT* pResult)
401 m_tree.right_clicked(MODE_CAMPAIGN);
405 void campaign_editor::OnBeginlabeleditSexpTree(NMHDR* pNMHDR, LRESULT* pResult)
407 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
409 if (m_tree.edit_label(pTVDispInfo->item.hItem) == 1) {
411 Campaign_modified = 1;
417 void campaign_editor::OnEndlabeleditSexpTree(NMHDR* pNMHDR, LRESULT* pResult)
419 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
421 *pResult = m_tree.end_label_edit(pTVDispInfo->item.hItem, pTVDispInfo->item.pszText);
424 int campaign_editor::handler(int code, int node, char *str)
430 for (i=0; i<Total_links; i++){
431 if ((Links[i].from == Cur_campaign_mission) && (Links[i].node == node)){
436 Campaign_tree_viewp->delete_link(i);
447 void campaign_editor::save_tree(int clear)
451 if (m_last_mission < 0){
452 return; // nothing to save
455 for (i=0; i<Total_links; i++){
456 if (Links[i].from == m_last_mission) {
457 sexp_unmark_persistent(Links[i].sexp);
458 free_sexp2(Links[i].sexp);
459 Links[i].sexp = m_tree.save_tree(Links[i].node);
460 sexp_mark_persistent(Links[i].sexp);
469 void campaign_editor::OnSelchangedSexpTree(NMHDR* pNMHDR, LRESULT* pResult)
474 // get handle of selected item
475 NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
476 h = pNMTreeView->itemNew.hItem;
479 // update help on sexp
480 m_tree.update_help(h);
482 // get handle of parent
483 while ((h2 = m_tree.GetParentItem(h))>0){
487 // get identifier of parent
488 node = m_tree.GetItemData(h);
489 for (i=0; i<Total_links; i++){
490 if ((Links[i].from == Cur_campaign_mission) && (Links[i].node == node)){
495 if (i == Total_links) {
496 Cur_campaign_link = -1;
500 // update mission loop text
502 save_loop_desc_window();
504 Cur_campaign_link = i;
505 update_loop_desc_window();
506 Campaign_tree_viewp->Invalidate();
510 void campaign_editor::OnMoveUp()
513 campaign_tree_link temp;
516 if (Cur_campaign_link >= 0) {
518 for (i=0; i<Total_links; i++){
519 if (Links[i].from == Cur_campaign_mission) {
520 if (i == Cur_campaign_link){
528 if ((last != -1) && (i < Total_links)) {
529 h1 = m_tree.GetParentItem(m_tree.handle(Links[i].node));
530 h2 = m_tree.GetParentItem(m_tree.handle(Links[last].node));
531 m_tree.swap_roots(h1, h2);
532 m_tree.SelectItem(m_tree.GetParentItem(m_tree.handle(Links[i].node)));
535 Links[last] = Links[i];
537 Cur_campaign_link = last;
541 GetDlgItem(IDC_SEXP_TREE)->SetFocus();
544 void campaign_editor::OnMoveDown()
547 campaign_tree_link temp;
550 if (Cur_campaign_link >= 0) {
552 for (i=0; i<Total_links; i++)
553 if (Links[i].from == Cur_campaign_mission)
554 if (i == Cur_campaign_link)
557 for (j=i+1; j<Total_links; j++)
558 if (Links[j].from == Cur_campaign_mission)
561 if (j < Total_links) {
562 h1 = m_tree.GetParentItem(m_tree.handle(Links[i].node));
563 h2 = m_tree.GetParentItem(m_tree.handle(Links[j].node));
564 m_tree.swap_roots(h1, h2);
565 m_tree.SelectItem(m_tree.GetParentItem(m_tree.handle(Links[i].node)));
570 Cur_campaign_link = j;
574 GetDlgItem(IDC_SEXP_TREE)->SetFocus();
577 void campaign_editor::swap_handler(int node1, int node2)
580 campaign_tree_link temp;
582 for (index1=0; index1<Total_links; index1++){
583 if ((Links[index1].from == Cur_campaign_mission) && (Links[index1].node == node1)){
588 SDL_assert(index1 < Total_links);
589 for (index2=0; index2<Total_links; index2++){
590 if ((Links[index2].from == Cur_campaign_mission) && (Links[index2].node == node2)){
595 SDL_assert(index2 < Total_links);
596 temp = Links[index1];
597 // Links[index1] = Links[index2];
598 while (index1 < index2) {
599 Links[index1] = Links[index1 + 1];
603 while (index1 > index2 + 1) {
604 Links[index1] = Links[index1 - 1];
608 // update Cur_campaign_link
609 Cur_campaign_link = index1;
611 Links[index1] = temp;
614 void campaign_editor::insert_handler(int old, int node)
618 for (i=0; i<Total_links; i++){
619 if ((Links[i].from == Cur_campaign_mission) && (Links[i].node == old)){
624 SDL_assert(i < Total_links);
625 Links[i].node = node;
629 void campaign_editor::OnEndEdit()
637 GetDlgItem(IDC_SEXP_TREE)->SetFocus();
642 void campaign_editor::OnChangeBriefingCutscene()
646 bc_dialog = (CEdit *) GetDlgItem(IDC_BRIEFING_CUTSCENE);
648 // maybe save off the current cutscene names.
649 if ( Cur_campaign_mission != -1 ) {
651 // see if the contents of the edit box have changed. Luckily, this returns 0 when the edit box is
653 if ( bc_dialog->GetModify() ) {
654 bc_dialog->GetWindowText( Campaign.missions[Cur_campaign_mission].briefing_cutscene, NAME_LENGTH );
655 Campaign_modified = 1;
661 // what to do when changing campaign type
662 void campaign_editor::OnSelchangeType()
664 // if campaign type is single player, then disable the multiplayer items
667 Campaign_modified = 1;
671 void campaign_editor::OnGalatea()
673 if (Cur_campaign_mission >= 0){
674 Campaign.missions[Cur_campaign_mission].flags &= ~CMISSION_FLAG_BASTION;
678 void campaign_editor::OnBastion()
680 if (Cur_campaign_mission >= 0){
681 Campaign.missions[Cur_campaign_mission].flags |= CMISSION_FLAG_BASTION;
685 // update the loop mission text
686 void campaign_editor::save_loop_desc_window()
688 char buffer[MISSION_DESC_LENGTH];
690 // update only if active link and there is a mission has mission loop
691 if ( (Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_loop ) {
692 deconvert_multiline_string(buffer, m_loop_desc, MISSION_DESC_LENGTH);
693 if (Links[Cur_campaign_link].mission_loop_txt) {
694 free(Links[Cur_campaign_link].mission_loop_txt);
696 if (Links[Cur_campaign_link].mission_loop_brief_anim) {
697 free(Links[Cur_campaign_link].mission_loop_brief_anim);
699 if (Links[Cur_campaign_link].mission_loop_brief_sound) {
700 free(Links[Cur_campaign_link].mission_loop_brief_sound);
703 if (strlen(buffer)) {
704 Links[Cur_campaign_link].mission_loop_txt = strdup(buffer);
706 Links[Cur_campaign_link].mission_loop_txt = NULL;
709 deconvert_multiline_string(buffer, m_loop_brief_anim, MAX_FILENAME_LEN);
711 Links[Cur_campaign_link].mission_loop_brief_anim = strdup(buffer);
713 Links[Cur_campaign_link].mission_loop_brief_anim = NULL;
716 deconvert_multiline_string(buffer, m_loop_brief_sound, MAX_FILENAME_LEN);
718 Links[Cur_campaign_link].mission_loop_brief_sound = strdup(buffer);
720 Links[Cur_campaign_link].mission_loop_brief_sound = NULL;
725 void campaign_editor::update_loop_desc_window()
727 bool enable_loop_desc_window;
729 enable_loop_desc_window = false;
730 if ((Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_loop) {
731 enable_loop_desc_window = true;
734 // maybe enable description window
735 GetDlgItem(IDC_MISSISON_LOOP_DESC)->EnableWindow(enable_loop_desc_window);
736 GetDlgItem(IDC_LOOP_BRIEF_ANIM)->EnableWindow(enable_loop_desc_window);
737 GetDlgItem(IDC_LOOP_BRIEF_SOUND)->EnableWindow(enable_loop_desc_window);
738 GetDlgItem(IDC_LOOP_BRIEF_BROWSE)->EnableWindow(enable_loop_desc_window);
739 GetDlgItem(IDC_LOOP_BRIEF_SOUND_BROWSE)->EnableWindow(enable_loop_desc_window);
742 if ((Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_loop_txt && enable_loop_desc_window) {
743 m_loop_desc = convert_multiline_string(Links[Cur_campaign_link].mission_loop_txt);
745 m_loop_desc = _T("");
749 if ((Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_loop_brief_anim && enable_loop_desc_window) {
750 m_loop_brief_anim = convert_multiline_string(Links[Cur_campaign_link].mission_loop_brief_anim);
752 m_loop_brief_anim = _T("");
756 if ((Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_loop_brief_sound && enable_loop_desc_window) {
757 m_loop_brief_sound = convert_multiline_string(Links[Cur_campaign_link].mission_loop_brief_sound);
759 m_loop_brief_sound = _T("");
766 void campaign_editor::OnToggleLoop()
768 // check if branch selected
769 if (Cur_campaign_link == -1) {
773 // store mission looop text
776 if ( (Cur_campaign_link >= 0) && Links[Cur_campaign_link].mission_loop ) {
777 if (Links[Cur_campaign_link].mission_loop_txt) {
778 free(Links[Cur_campaign_link].mission_loop_txt);
781 if (Links[Cur_campaign_link].mission_loop_brief_anim) {
782 free(Links[Cur_campaign_link].mission_loop_brief_anim);
785 if (Links[Cur_campaign_link].mission_loop_brief_sound) {
786 free(Links[Cur_campaign_link].mission_loop_brief_sound);
789 char buffer[MISSION_DESC_LENGTH];
791 deconvert_multiline_string(buffer, m_loop_desc, MISSION_DESC_LENGTH);
792 if (m_loop_desc && strlen(buffer)) {
793 Links[Cur_campaign_link].mission_loop_txt = strdup(buffer);
795 Links[Cur_campaign_link].mission_loop_txt = NULL;
798 deconvert_multiline_string(buffer, m_loop_brief_anim, MISSION_DESC_LENGTH);
799 if (m_loop_brief_anim && strlen(buffer)) {
800 Links[Cur_campaign_link].mission_loop_brief_anim = strdup(buffer);
802 Links[Cur_campaign_link].mission_loop_brief_anim = NULL;
805 deconvert_multiline_string(buffer, m_loop_brief_sound, MISSION_DESC_LENGTH);
806 if (m_loop_brief_sound && strlen(buffer)) {
807 Links[Cur_campaign_link].mission_loop_brief_sound = strdup(buffer);
809 Links[Cur_campaign_link].mission_loop_brief_sound = NULL;
813 // toggle to mission_loop setting
814 Links[Cur_campaign_link].mission_loop = !Links[Cur_campaign_link].mission_loop;
816 // reset loop desc window (gray if inactive)
817 update_loop_desc_window();
820 int bitmap1, bitmap2;
821 if (Links[Cur_campaign_link].mission_loop) {
822 bitmap2 = BITMAP_GREEN_DOT;
823 bitmap1 = BITMAP_BLUE_DOT;
825 bitmap1 = BITMAP_BLACK_DOT;
826 bitmap2 = BITMAP_RED_DOT;
829 // Search for item and update bitmap
830 HTREEITEM h = m_tree.GetRootItem();
832 if ((int) m_tree.GetItemData(h) == Links[Cur_campaign_link].node) {
833 m_tree.SetItemImage(h, bitmap1, bitmap2);
837 h = m_tree.GetNextSiblingItem(h);
841 Campaign_tree_viewp->Invalidate();
844 void campaign_editor::OnBrowseLoopAni()
850 // switch directories
851 pushed_dir = cfile_push_chdir(CF_TYPE_INTERFACE);
852 CFileDialog dlg(TRUE, "ani", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR, "Ani Files (*.ani)|*.ani");
854 if (dlg.DoModal() == IDOK) {
855 m_loop_brief_anim = dlg.GetFileName();
859 // move back to the proper directory
865 void campaign_editor::OnBrowseLoopSound()
871 // switch directories
872 pushed_dir = cfile_push_chdir(CF_TYPE_VOICE_CMD_BRIEF);
873 CFileDialog dlg(TRUE, "wav", NULL, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR, "Wave Files (*.wav)|*.wav||");
875 if (dlg.DoModal() == IDOK) {
876 m_loop_brief_sound = dlg.GetFileName();
880 // move back to the proper directory