]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/bgbitmapdlg.cpp
fix issue with looping audio streams
[taylor/freespace2.git] / src / fred2 / bgbitmapdlg.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Fred2/BgBitmapDlg.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Background space images manager dialog
16  *
17  * $Log$
18  * Revision 1.3  2002/06/09 04:41:16  relnev
19  * added copyright header
20  *
21  * Revision 1.2  2002/05/07 03:16:43  theoddone33
22  * The Great Newline Fix
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:08  root
25  * Initial import.
26  *
27  * 
28  * 11    7/02/99 4:30p Dave
29  * Much more sophisticated lightning support.
30  * 
31  * 10    6/08/99 5:42p Dave
32  * Fixed background bitmap division stuff.
33  * 
34  * 9     6/03/99 6:42p Dave
35  * 
36  * 8     6/03/99 6:37p Dave
37  * More TNT fun. Made perspective bitmaps more flexible.
38  * 
39  * 7     5/09/99 6:00p Dave
40  * Lots of cool new effects. E3 build tweaks.
41  * 
42  * 6     4/26/99 8:47p Dave
43  * Made all pof related nebula stuff customizable through Fred.
44  * 
45  * 5     4/07/99 6:21p Dave
46  * Fred and Freespace support for multiple background bitmaps and suns.
47  * Fixed link errors on all subprojects. Moved encrypt_init() to
48  * cfile_init() and lcl_init(), since its safe to call twice.
49  * 
50  * 4     1/25/99 5:03a Dave
51  * First run of stealth, AWACS and TAG missile support. New mission type
52  * :)
53  * 
54  * 3     11/14/98 5:37p Dave
55  * Put in support for full nebulas.
56  * 
57  * 2     10/07/98 6:28p Dave
58  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
59  * Fred. Globalized mission and campaign file extensions. Removed Silent
60  * Threat specific code.
61  *   
62  * 18    4/13/98 10:25p Hoffoss
63  * Added a flag for subspace missions, and for aboard the Galatea or
64  * Bastion.
65  * 
66  * 17    1/14/98 8:56a John
67  * Removed old nebula palette code that didn't matter what HUD colors were
68  * loaded.
69  * 
70  * 16    12/08/97 4:48p Hoffoss
71  * Moved starfield editor controls to background editor.
72  * 
73  * 15    11/25/97 4:48p Johnson
74  * Fixed bug with nebula selection.
75  * 
76  * 14    11/25/97 11:40a Hoffoss
77  * Added support for nebula placement editing.
78  * 
79  * 13    11/23/97 6:06p Hoffoss
80  * Renamed background bitmap editor to just background editor.
81  * 
82  * 12    11/21/97 2:55p Hoffoss
83  * Added Nebula support to Fred.  Implemented loading and saving nebula
84  * info to/from mission files.
85  * 
86  * 11    6/11/97 3:26p Hoffoss
87  * Added better verification of bitmap filename to BG editor.
88  * 
89  * 10    4/17/97 2:01p Hoffoss
90  * All dialog box window states are saved between sessions now.
91  * 
92  * 9     3/31/97 6:07p Hoffoss
93  * Fixed several errors, including BG editor not graying fields, BG editor
94  * not updating image when changed, Removed obsolete data from Weapon
95  * editor, priority not being saved when missions saved, priority not
96  * editable in initial orders editor.
97  * 
98  * 8     3/27/97 2:24p Hoffoss
99  * Fixed bug in image not updating when new image selected from listbox of
100  * combo box.
101  * 
102  * 7     3/21/97 4:24p Hoffoss
103  * Fixed bug in changing image to an external image file.
104  * 
105  * 6     3/17/97 1:54p Hoffoss
106  * fixed bugs in BG editor, and added delete button functionality.
107  * 
108  * 5     3/12/97 4:33p Hoffoss
109  * added spin controls to orient editor, light intensity level can be
110  * specified in BG editor.
111  * 
112  * 4     2/21/97 5:34p Hoffoss
113  * Added extensive modification detection and fixed a bug in initial
114  * orders editor.
115  * 
116  * 3     2/04/97 3:09p Hoffoss
117  * Background bitmap editor implemented fully.
118  * 
119  * 2     1/30/97 2:24p Hoffoss
120  * Added remaining mission file structures and implemented load/save of
121  * them.
122  *
123  * $NoKeywords: $
124  */
125
126 #include "stdafx.h"
127 #include "fred.h"
128 #include "bgbitmapdlg.h"
129 #include "starfield.h"
130 #include "bmpman.h"
131 #include "fredview.h"
132 #include "freddoc.h"
133 #include "palman.h"
134 #include "nebula.h"
135 #include "neb.h"
136 #include "neblightning.h"
137
138 #ifdef _DEBUG
139 #define new DEBUG_NEW
140 #undef THIS_FILE
141 static char THIS_FILE[] = __FILE__;
142 #endif
143
144 /////////////////////////////////////////////////////////////////////////////
145 // bg_bitmap_dlg dialog
146
147 bg_bitmap_dlg::bg_bitmap_dlg(CWnd* pParent) : CDialog(bg_bitmap_dlg::IDD, pParent)
148 {
149         //{{AFX_DATA_INIT(bg_bitmap_dlg)                
150         m_neb_intensity = _T("");       
151         m_nebula_color = -1;
152         m_nebula_index = -1;
153         m_bank = 0;
154         m_heading = 0;
155         m_pitch = 0;
156         m_subspace = FALSE;
157         m_fullneb = FALSE;
158
159         m_neb2_texture = 0;
160         
161         for(int idx=0; idx<MAX_NEB2_POOFS; idx++){
162                 m_poof[idx] = Neb2_poof_flags & (1<<idx) ? 1 : 0;
163         }
164
165         s_pitch = 0;
166         s_bank = 0;
167         s_heading = 0;
168         s_scale = 1.0f; 
169         s_index = -1;
170
171         b_pitch = 0;
172         b_bank = 0;
173         b_heading = 0;
174         b_scale_x = 1.0f; b_scale_y = 1.0f;
175         b_div_x = 1; b_div_y = 1;
176         b_index = -1;
177         //}}AFX_DATA_INIT       
178 }
179
180 void bg_bitmap_dlg::DoDataExchange(CDataExchange* pDX)
181 {
182         CDialog::DoDataExchange(pDX);
183         //{{AFX_DATA_MAP(bg_bitmap_dlg)                 
184         DDX_CBIndex(pDX, IDC_NEBCOLOR, m_nebula_color);
185         DDX_CBIndex(pDX, IDC_NEBPATTERN, m_nebula_index);
186         DDX_Text(pDX, IDC_BANK, m_bank);
187         DDX_Text(pDX, IDC_HEADING, m_heading);
188         DDX_Text(pDX, IDC_PITCH, m_pitch);
189         DDX_Text(pDX, IDC_NEB2_INTENSITY, m_neb_intensity);
190         DDX_Control(pDX, IDC_SLIDER1, m_slider);
191         DDX_Check(pDX, IDC_SUBSPACE, m_subspace);
192         DDX_Check(pDX, IDC_FULLNEB, m_fullneb);
193
194         DDX_CBIndex(pDX, IDC_NEB2_TEXTURE, m_neb2_texture);
195
196         DDX_Text(pDX, IDC_SUN1, s_name);
197         DDX_Text(pDX, IDC_SUN1_P, s_pitch);
198         DDV_MinMaxInt(pDX, s_pitch, 0, 359);
199         DDX_Text(pDX, IDC_SUN1_B, s_bank);
200         DDV_MinMaxInt(pDX, s_bank, 0, 359);
201         DDX_Text(pDX, IDC_SUN1_H, s_heading);
202         DDV_MinMaxInt(pDX, s_heading, 0, 359);
203         DDX_Text(pDX, IDC_SUN1_SCALE, s_scale);
204         DDV_MinMaxFloat(pDX, s_scale, 0.1f, 50.0f);
205
206         DDX_Text(pDX, IDC_SBITMAP, b_name);
207         DDX_Text(pDX, IDC_SBITMAP_P, b_pitch);
208         DDV_MinMaxInt(pDX, b_pitch, 0, 359);
209         DDX_Text(pDX, IDC_SBITMAP_B, b_bank);
210         DDV_MinMaxInt(pDX, b_bank, 0, 359);
211         DDX_Text(pDX, IDC_SBITMAP_H, b_heading);
212         DDV_MinMaxInt(pDX, b_heading, 0, 359);
213         DDX_Text(pDX, IDC_SBITMAP_SCALE_X, b_scale_x);
214         DDV_MinMaxFloat(pDX, b_scale_x, 0.001f, 18.0f);
215         DDX_Text(pDX, IDC_SBITMAP_SCALE_Y, b_scale_y);
216         DDV_MinMaxFloat(pDX, b_scale_y, 0.001f, 18.0f);
217         DDX_Text(pDX, IDC_SBITMAP_DIV_X, b_div_x);
218         DDV_MinMaxInt(pDX, b_div_x, 1, 5);
219         DDX_Text(pDX, IDC_SBITMAP_DIV_Y, b_div_y);
220         DDV_MinMaxInt(pDX, b_div_y, 1, 5);
221
222         DDX_Check(pDX, IDC_POOF0, m_poof[0]);
223         DDX_Check(pDX, IDC_POOF1, m_poof[1]);
224         DDX_Check(pDX, IDC_POOF2, m_poof[2]);
225         DDX_Check(pDX, IDC_POOF3, m_poof[3]);
226         DDX_Check(pDX, IDC_POOF4, m_poof[4]);
227         DDX_Check(pDX, IDC_POOF5, m_poof[5]);
228         //}}AFX_DATA_MAP
229 }
230
231 BEGIN_MESSAGE_MAP(bg_bitmap_dlg, CDialog)
232         //{{AFX_MSG_MAP(bg_bitmap_dlg)
233         ON_WM_CLOSE()   
234         ON_CBN_SELCHANGE(IDC_NEBCOLOR, OnSelchangeNebcolor)
235         ON_CBN_SELCHANGE(IDC_NEBPATTERN, OnSelchangeNebpattern)
236         ON_BN_CLICKED(IDC_FULLNEB, OnFullNeb)
237         ON_WM_HSCROLL()
238
239         ON_LBN_SELCHANGE(IDC_SUN1_LIST, OnSunChange)
240         ON_CBN_SELCHANGE(IDC_SUN1, OnSunDropdownChange)
241         ON_BN_CLICKED(IDC_ADD_SUN, OnAddSun)
242         ON_BN_CLICKED(IDC_DEL_SUN, OnDelSun)
243
244         ON_LBN_SELCHANGE(IDC_SBITMAP_LIST, OnBitmapChange)
245         ON_CBN_SELCHANGE(IDC_SBITMAP, OnBitmapDropdownChange)
246         ON_BN_CLICKED(IDC_ADD_SBITMAP, OnAddBitmap)
247         ON_BN_CLICKED(IDC_DEL_SBITMAP, OnDelBitmap)
248         //}}AFX_MSG_MAP
249 END_MESSAGE_MAP()
250
251 /////////////////////////////////////////////////////////////////////////////
252 // bg_bitmap_dlg message handlers
253
254 void bg_bitmap_dlg::create()
255 {
256         char buf[40];
257         int i;
258         CComboBox *box;
259
260         CDialog::Create(bg_bitmap_dlg::IDD);
261         theApp.init_window(&Bg_wnd_data, this);
262         
263         box = (CComboBox *) GetDlgItem(IDC_NEBCOLOR);
264         for (i=0; i<NUM_NEBULA_COLORS; i++){
265                 box->AddString(Nebula_colors[i]);
266         }       
267
268         m_slider.SetRange(100, MAX_STARS);
269         m_slider.SetPos(Num_stars);
270         sprintf(buf, "%d", Num_stars);
271         GetDlgItem(IDC_TOTAL)->SetWindowText(buf);
272
273         build_nebfile_list();   
274
275         // setup neb poof names
276         GetDlgItem(IDC_POOF0)->SetWindowText(Neb2_poof_filenames[0]);   
277         GetDlgItem(IDC_POOF1)->SetWindowText(Neb2_poof_filenames[1]);
278         GetDlgItem(IDC_POOF2)->SetWindowText(Neb2_poof_filenames[2]);
279         GetDlgItem(IDC_POOF3)->SetWindowText(Neb2_poof_filenames[3]);
280         GetDlgItem(IDC_POOF4)->SetWindowText(Neb2_poof_filenames[4]);
281         GetDlgItem(IDC_POOF5)->SetWindowText(Neb2_poof_filenames[5]);
282         for(i=0; i<MAX_NEB2_BITMAPS; i++){
283                 if(strlen(Neb2_bitmap_filenames[i]) > 0){
284                         ((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->AddString(Neb2_bitmap_filenames[i]);
285                 }
286         }
287         // if we have a texture selected already
288         if(strlen(Neb2_texture_name) > 0){
289                 m_neb2_texture = ((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->SelectString(-1, Neb2_texture_name);
290                 if(m_neb2_texture == CB_ERR){
291                         ((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->SetCurSel(0);
292                         m_neb2_texture = 0;
293                 }
294         } else {
295                 ((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->SetCurSel(0);
296         }
297
298         // setup lightning storm names
299         ((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->ResetContent();
300         ((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->AddString(CString("none"));
301         for(i=0; i<Num_storm_types; i++){
302                 ((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->AddString(CString(Storm_types[i].name));
303         }
304         ((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->SelectString(-1, Mission_parse_storm_name);
305                 
306         // if the nebula intensity wasn't set before - set it now
307         if(Neb2_awacs < 0.0f){
308                 m_neb_intensity = CString("3000");
309         } else {
310                 char whee[255] = "";
311                 m_neb_intensity = CString(itoa((int)Neb2_awacs, whee, 10));
312         }
313                 
314         // determine if a full Neb2 is active - load in the full nebula filenames or the partial neb
315         // filenames
316         m_fullneb = (The_mission.flags & MISSION_FLAG_FULLNEB) ? 1 : 0;
317         if(m_fullneb){
318                 ((CButton*)GetDlgItem(IDC_FULLNEB))->SetCheck(1);                                       
319         } else {
320                 // since there is no "none" option for the full nebulas
321                 m_nebula_index = Nebula_index + 1;              
322         
323                 m_nebula_color = Mission_palette;
324                 if (Nebula_index < 0){
325                         GetDlgItem(IDC_NEBCOLOR)->EnableWindow(FALSE);
326                 }
327
328                 m_pitch = Nebula_pitch;
329                 m_bank = Nebula_bank;
330                 m_heading = Nebula_heading;
331         }
332
333         // setup sun and sunglow controls
334         sun_data_init();        
335
336         // setup bitmap info
337         bitmap_data_init();
338         
339         // determine if subspace is active
340         m_subspace = (The_mission.flags & MISSION_FLAG_SUBSPACE) ? 1 : 0;       
341
342         UpdateData(FALSE);
343         OnFullNeb();
344         update_data();
345         update_map_window();
346         set_modified();
347 }
348
349 void bg_bitmap_dlg::OnClose() 
350 {
351         UpdateData(TRUE);
352         Mission_palette = m_nebula_color;
353         
354         if(m_fullneb){          
355                 The_mission.flags |= MISSION_FLAG_FULLNEB;
356                 Neb2_awacs = (float)atoi((LPCSTR)m_neb_intensity);
357
358                 // override dumb values with reasonable ones
359                 if(Neb2_awacs <= 0.00000001f){
360                         Neb2_awacs = 3000.0f;
361                 }
362
363                 // store poof flags
364                 Neb2_poof_flags = 0;
365                 for(int idx=0; idx<MAX_NEB2_POOFS; idx++){
366                         if(m_poof[idx]){
367                                 Neb2_poof_flags |= (1<<idx);
368                         }
369                 }
370
371                 // get the bitmap name
372                 strcpy(Neb2_texture_name, Neb2_bitmap_filenames[m_neb2_texture]);
373
374                 // init the nebula
375                 neb2_level_init();
376         } else {
377                 The_mission.flags &= ~MISSION_FLAG_FULLNEB;
378                 Nebula_index = m_nebula_index - 1;
379                 Neb2_awacs = -1.0f;
380                 strcpy(Neb2_texture_name, "");
381         }
382
383         // get selected storm
384         ((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->GetLBText(((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->GetCurSel(), Mission_parse_storm_name);
385
386         Nebula_pitch = m_pitch;
387         Nebula_bank = m_bank;
388         Nebula_heading = m_heading;
389         if (Nebula_index >= 0){
390                 nebula_init(Nebula_filenames[Nebula_index], m_pitch, m_bank, m_heading);
391         } else {
392                 nebula_close();
393         }
394
395         if (m_subspace){
396                 The_mission.flags |= MISSION_FLAG_SUBSPACE;                             
397         } else {
398                 The_mission.flags &= ~MISSION_FLAG_SUBSPACE;            
399         }
400
401         // close sun data
402         sun_data_close();
403
404         // close bitmap data
405         bitmap_data_close();
406
407         theApp.record_window_data(&Bg_wnd_data, this);
408         delete Bg_bitmap_dialog;
409         Bg_bitmap_dialog = NULL;
410 }
411
412 void bg_bitmap_dlg::update_data(int update)
413 {
414         if (update){
415                 UpdateData(TRUE);
416         }
417
418         UpdateData(FALSE);      
419 }
420
421 void bg_bitmap_dlg::OnSelchangeNebcolor() 
422 {
423         CWaitCursor wait;
424
425         UpdateData(TRUE);
426         Mission_palette = m_nebula_color;
427
428
429         char palette_filename[1024];
430
431         SDL_assert( Mission_palette >= 0 );
432         SDL_assert( Mission_palette <= 98 );
433
434         sprintf( palette_filename, "gamepalette%d-%02d", 1, Mission_palette+1 );
435
436         mprintf(( "Loading palette %s\n", palette_filename ));
437
438         palette_load_table(palette_filename);
439         
440         Update_window = 1;
441 }
442
443 void bg_bitmap_dlg::OnSelchangeNebpattern() 
444 {
445         CWaitCursor wait;
446
447         UpdateData(TRUE);
448
449         // fullneb indexes differently  
450         Nebula_index = m_nebula_index - 1;                      
451
452         GetDlgItem(IDC_NEBCOLOR)->EnableWindow(m_nebula_index ? TRUE : FALSE);
453         if (Nebula_index >= 0){         
454                 nebula_init(Nebula_filenames[Nebula_index], m_pitch, m_bank, m_heading);                
455         } else {
456                 nebula_close();
457         }
458
459         Update_window = 1;
460 }
461
462 void bg_bitmap_dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar) 
463 {
464         char buf[40];
465
466         CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
467
468         MODIFY(Num_stars, m_slider.GetPos());
469         sprintf(buf, "%d", Num_stars);
470         GetDlgItem(IDC_TOTAL)->SetWindowText(buf);
471 }
472
473 // when the user toggled the "Full Nebula" button
474 void bg_bitmap_dlg::OnFullNeb()
475 {               
476         // determine what state we're in        
477         UpdateData(TRUE);
478         if(m_fullneb){
479                 // enable all fullneb controls
480                 GetDlgItem(IDC_NEB2_INTENSITY)->EnableWindow(TRUE);
481                 GetDlgItem(IDC_NEB2_TEXTURE)->EnableWindow(TRUE);
482                 GetDlgItem(IDC_NEB2_LIGHTNING)->EnableWindow(TRUE);
483                 GetDlgItem(IDC_POOF0)->EnableWindow(TRUE);
484                 GetDlgItem(IDC_POOF1)->EnableWindow(TRUE);
485                 GetDlgItem(IDC_POOF2)->EnableWindow(TRUE);
486                 GetDlgItem(IDC_POOF3)->EnableWindow(TRUE);
487                 GetDlgItem(IDC_POOF4)->EnableWindow(TRUE);
488                 GetDlgItem(IDC_POOF5)->EnableWindow(TRUE);                                              
489
490                 // disable non-fullneb controls
491                 GetDlgItem(IDC_NEBPATTERN)->EnableWindow(FALSE);
492                 GetDlgItem(IDC_NEBCOLOR)->EnableWindow(FALSE);
493                 GetDlgItem(IDC_PITCH)->EnableWindow(FALSE);
494                 GetDlgItem(IDC_BANK)->EnableWindow(FALSE);
495                 GetDlgItem(IDC_HEADING)->EnableWindow(FALSE);
496
497                 // check all relevant poofs             
498                 ((CButton*)GetDlgItem(IDC_POOF0))->SetCheck(FALSE);
499                 if(m_poof[0]){
500                         ((CButton*)GetDlgItem(IDC_POOF0))->SetCheck(TRUE);
501                 }
502                 ((CButton*)GetDlgItem(IDC_POOF1))->SetCheck(FALSE);
503                 if(m_poof[1]){
504                         ((CButton*)GetDlgItem(IDC_POOF1))->SetCheck(TRUE);
505                 }
506                 ((CButton*)GetDlgItem(IDC_POOF2))->SetCheck(FALSE);
507                 if(m_poof[2]){
508                         ((CButton*)GetDlgItem(IDC_POOF2))->SetCheck(TRUE);
509                 }
510                 ((CButton*)GetDlgItem(IDC_POOF3))->SetCheck(FALSE);
511                 if(m_poof[3]){
512                         ((CButton*)GetDlgItem(IDC_POOF3))->SetCheck(TRUE);
513                 }
514                 ((CButton*)GetDlgItem(IDC_POOF4))->SetCheck(FALSE);
515                 if(m_poof[4]){
516                         ((CButton*)GetDlgItem(IDC_POOF4))->SetCheck(TRUE);
517                 }
518                 ((CButton*)GetDlgItem(IDC_POOF5))->SetCheck(FALSE);
519                 if(m_poof[5]){
520                         ((CButton*)GetDlgItem(IDC_POOF5))->SetCheck(TRUE);
521                 }
522         } else {
523                 // enable all non-fullneb controls
524                 GetDlgItem(IDC_NEBPATTERN)->EnableWindow(TRUE);
525                 GetDlgItem(IDC_NEBCOLOR)->EnableWindow(TRUE);
526                 GetDlgItem(IDC_PITCH)->EnableWindow(TRUE);
527                 GetDlgItem(IDC_BANK)->EnableWindow(TRUE);
528                 GetDlgItem(IDC_HEADING)->EnableWindow(TRUE);            
529
530                 // disable all fullneb controls
531                 GetDlgItem(IDC_NEB2_INTENSITY)->EnableWindow(FALSE);
532                 GetDlgItem(IDC_NEB2_TEXTURE)->EnableWindow(FALSE);
533                 GetDlgItem(IDC_NEB2_LIGHTNING)->EnableWindow(FALSE);
534                 GetDlgItem(IDC_POOF0)->EnableWindow(FALSE);
535                 GetDlgItem(IDC_POOF1)->EnableWindow(FALSE);
536                 GetDlgItem(IDC_POOF2)->EnableWindow(FALSE);
537                 GetDlgItem(IDC_POOF3)->EnableWindow(FALSE);
538                 GetDlgItem(IDC_POOF4)->EnableWindow(FALSE);
539                 GetDlgItem(IDC_POOF5)->EnableWindow(FALSE);             
540         }               
541 }
542
543 // clear and build the nebula filename list appropriately
544 void bg_bitmap_dlg::build_nebfile_list()
545 {
546         int i;
547         CComboBox *box = (CComboBox *) GetDlgItem(IDC_NEBPATTERN);
548
549         // wacky
550         SDL_assert(box != NULL);
551         if(box == NULL){
552                 return;
553         }
554         
555         // clear the box
556         box->ResetContent();
557
558         // add all necessary strings            
559         box->AddString("None");
560         for (i=0; i<NUM_NEBULAS; i++){
561                 box->AddString(Nebula_filenames[i]);
562         }       
563
564         // select the first elementccombobox
565         box->SetCurSel(0);
566         OnSelchangeNebpattern();
567 }
568
569 void bg_bitmap_dlg::sun_data_init()
570 {
571         int idx;
572
573         // force the range for pitch bank and heading
574         ((CSpinButtonCtrl *)GetDlgItem(IDC_SUN1_P_SPIN))->SetRange(0, 359);
575         ((CSpinButtonCtrl *)GetDlgItem(IDC_SUN1_B_SPIN))->SetRange(0, 359);
576         ((CSpinButtonCtrl *)GetDlgItem(IDC_SUN1_H_SPIN))->SetRange(0, 359);     
577
578         // add all suns to the drop down
579         idx=0;
580         while((idx < MAX_STARFIELD_BITMAPS) && (Sun_bitmaps[idx].bitmap != -1)){
581                 ((CComboBox*)GetDlgItem(IDC_SUN1))->AddString(Sun_bitmaps[idx].filename);
582                 
583                 // next
584                 idx++;
585         }
586         
587         // add all suns by bitmap filename to the list
588         for(idx=0; idx<Num_suns; idx++){        
589                 ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->AddString(Suns[idx].filename);
590         }               
591
592         // if we have at least one item, select it
593         if(Num_suns > 0){
594                 ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->SetCurSel(0);
595                 OnSunChange();
596         }
597 }
598
599 void bg_bitmap_dlg::sun_data_close()
600 {       
601         // if there is an active sun, save it
602         sun_data_save_current();        
603 }
604
605 void bg_bitmap_dlg::sun_data_save_current()
606 {       
607         // if we have an active item
608         if(s_index >= 0){
609                 // read out of the controls
610                 UpdateData(TRUE);
611
612                 // store the data
613                 strcpy(Suns[s_index].filename, (const char*)s_name);
614                 Suns[s_index].scale_x = (float)s_scale;
615                 Suns[s_index].scale_y = 1.0f;
616                 Suns[s_index].div_x = 1;
617                 Suns[s_index].div_y = 1;
618                 Suns[s_index].ang.p = (float)fl_radian(s_pitch);
619                 Suns[s_index].ang.b = (float)fl_radian(s_bank);
620                 Suns[s_index].ang.h = (float)fl_radian(s_heading);              
621         }
622 }
623
624 void bg_bitmap_dlg::OnSunChange()
625 {       
626         int drop_index;
627
628         // save the current sun
629         sun_data_save_current();
630
631         // select the new one
632         s_index = ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->GetCurSel();
633
634         // setup data   
635         if(s_index >= 0){                               
636                 s_pitch = (int)fl_degrees(Suns[s_index].ang.p);
637                 s_bank = (int)fl_degrees(Suns[s_index].ang.b);
638                 s_heading = (int)fl_degrees(Suns[s_index].ang.h);
639                 s_scale = Suns[s_index].scale_x;                
640                 s_name = CString(Suns[s_index].filename);
641
642                 // stuff back into the controls
643                 UpdateData(FALSE);
644
645                 // select the proper item from the dropdown
646                 drop_index = ((CComboBox*)GetDlgItem(IDC_SUN1))->FindString( -1, Suns[s_index].filename );
647                 SDL_assert(drop_index != CB_ERR);
648                 if(drop_index != CB_ERR){
649                         ((CComboBox*)GetDlgItem(IDC_SUN1))->SetCurSel(drop_index);
650                 }
651         }
652 }
653
654 void bg_bitmap_dlg::OnAddSun()
655 {
656         starfield_bitmap_instance *b;
657
658         // if we've already reached max suns
659         if(Num_suns >= MAX_STARFIELD_BITMAPS){
660                 MessageBox("Max suns reached!");
661                 return;
662         }
663
664         // save any current
665         sun_data_save_current();
666         
667         // select the first sun by default
668         b = &Suns[Num_suns++];
669         strcpy(b->filename, Sun_bitmaps[0].filename);
670         b->scale_x = 1.0f;
671         b->scale_y = 1.0f;
672         b->div_x = 1;
673         b->div_y = 1;
674         b->ang.p = 0;
675         b->ang.b = 0;
676         b->ang.h = 0;
677
678         // add to the listbox and select it
679         int add_index = ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->AddString(b->filename);
680         ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->SetCurSel(add_index);
681         
682         // call the OnSunChange function to setup all relvant data in the class
683         OnSunChange();
684 }
685
686 void bg_bitmap_dlg::OnDelSun()
687 {
688         int idx;
689
690         // if we don't have an active item
691         if(s_index < 0){
692                 return;
693         }
694         
695         // remove the item from the list
696         ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->DeleteString(s_index);
697
698         // remove it from the list
699         for(idx=s_index; idx<Num_suns-1; idx++){
700                 Suns[idx] = Suns[idx+1];
701                 strcpy(Suns[idx].filename, Suns[idx+1].filename);
702         }
703
704         // decrement the count
705         Num_suns--;
706
707         // no item selected, let the message handler assign a new one
708         s_index = -1;
709 }
710
711 void bg_bitmap_dlg::OnSunDropdownChange()
712 {       
713         // if we have no active sun, do nothing
714         if(s_index < 0){
715                 return;
716         }
717
718         int new_index = ((CComboBox*)GetDlgItem(IDC_SUN1))->GetCurSel();
719         SDL_assert(new_index != CB_ERR);
720
721         // get the new string
722         if(new_index != CB_ERR){
723                 ((CComboBox*)GetDlgItem(IDC_SUN1))->GetLBText(new_index, s_name);
724
725                 // change the name of the string in the listbox
726                 ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->DeleteString(s_index);
727                 ((CListBox*)GetDlgItem(IDC_SUN1_LIST))->InsertString(s_index, (const char*)s_name);
728         }       
729 }
730
731 void bg_bitmap_dlg::bitmap_data_init()
732 {
733         int idx;
734
735         // force the range for pitch bank and heading
736         ((CSpinButtonCtrl *)GetDlgItem(IDC_SBITMAP_P_SPIN))->SetRange(0, 359);
737         ((CSpinButtonCtrl *)GetDlgItem(IDC_SBITMAP_B_SPIN))->SetRange(0, 359);
738         ((CSpinButtonCtrl *)GetDlgItem(IDC_SBITMAP_H_SPIN))->SetRange(0, 359);  
739
740         // add all suns to the drop down
741         idx=0;
742         while((idx < MAX_STARFIELD_BITMAPS) && (Starfield_bitmaps[idx].bitmap != -1)){
743                 ((CComboBox*)GetDlgItem(IDC_SBITMAP))->AddString(Starfield_bitmaps[idx].filename);
744                 
745                 // next
746                 idx++;
747         }
748         
749         // add all suns by bitmap filename to the list
750         for(idx=0; idx<Num_starfield_bitmaps; idx++){   
751                 ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->AddString(Starfield_bitmap_instance[idx].filename);
752         }               
753
754         // if we have at least one item, select it
755         if(Num_starfield_bitmaps > 0){
756                 ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->SetCurSel(0);
757                 OnBitmapChange();
758         }
759 }
760
761 void bg_bitmap_dlg::bitmap_data_close()
762 {
763         // if there is an active sun, save it
764         bitmap_data_save_current();     
765 }
766
767 void bg_bitmap_dlg::bitmap_data_save_current()
768 {
769         // if we have an active item
770         if(b_index >= 0){
771                 // read out of the controls
772                 UpdateData(TRUE);
773
774                 // store the data
775                 strcpy(Starfield_bitmap_instance[b_index].filename, (const char*)b_name);
776                 Starfield_bitmap_instance[b_index].scale_x = (float)b_scale_x;
777                 Starfield_bitmap_instance[b_index].scale_y = (float)b_scale_y;
778                 Starfield_bitmap_instance[b_index].div_x = b_div_x;
779                 Starfield_bitmap_instance[b_index].div_y = b_div_y;
780                 Starfield_bitmap_instance[b_index].ang.p = (float)fl_radian(b_pitch);
781                 Starfield_bitmap_instance[b_index].ang.b = (float)fl_radian(b_bank);
782                 Starfield_bitmap_instance[b_index].ang.h = (float)fl_radian(b_heading);
783         }
784 }
785
786 void bg_bitmap_dlg::OnBitmapChange()
787 {
788         int drop_index;
789
790         // save the current bitmap
791         bitmap_data_save_current();
792
793         // select the new one
794         b_index = ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->GetCurSel();
795
796         // setup data   
797         if(b_index >= 0){               
798                 b_pitch = (int)fl_degrees(Starfield_bitmap_instance[b_index].ang.p);
799                 b_bank = (int)fl_degrees(Starfield_bitmap_instance[b_index].ang.b);
800                 b_heading = (int)fl_degrees(Starfield_bitmap_instance[b_index].ang.h);
801                 b_scale_x = Starfield_bitmap_instance[b_index].scale_x;
802                 b_scale_y = Starfield_bitmap_instance[b_index].scale_y;
803                 b_div_x = Starfield_bitmap_instance[b_index].div_x;
804                 b_div_y = Starfield_bitmap_instance[b_index].div_y;
805                 b_name = CString(Starfield_bitmap_instance[b_index].filename);
806
807                 // stuff back into the controls
808                 UpdateData(FALSE);
809
810                 // select the proper item from the dropdown
811                 drop_index = ((CComboBox*)GetDlgItem(IDC_SBITMAP))->FindString( -1, Starfield_bitmap_instance[b_index].filename );
812                 SDL_assert(drop_index != CB_ERR);
813                 if(drop_index != CB_ERR){
814                         ((CComboBox*)GetDlgItem(IDC_SBITMAP))->SetCurSel(drop_index);
815                 }
816         }
817 }
818
819 void bg_bitmap_dlg::OnAddBitmap()
820 {
821         starfield_bitmap_instance *b;
822
823         // if we've already reached max bitmaps
824         if(Num_starfield_bitmaps >= MAX_STARFIELD_BITMAPS){
825                 MessageBox("Max starfield bitmaps reached!");
826                 return;
827         }
828
829         // save any current
830         bitmap_data_save_current();
831         
832         // select the first sun by default
833         b = &Starfield_bitmap_instance[Num_starfield_bitmaps++];
834         strcpy(b->filename, Starfield_bitmaps[0].filename);
835         b->scale_x = 1.0f;
836         b->scale_y = 1.0f;
837         b->div_x = 1;
838         b->div_y = 1;
839         b->ang.p = 0;
840         b->ang.b = 0;
841         b->ang.h = 0;
842
843         // add to the listbox and select it
844         int add_index = ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->AddString(b->filename);
845         ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->SetCurSel(add_index);
846         
847         // call the OnBitmapChange function to setup all relvant data in the class
848         OnBitmapChange();
849 }
850
851 void bg_bitmap_dlg::OnDelBitmap()
852 {
853         int idx;
854
855         // if we don't have an active item
856         if(b_index < 0){
857                 return;
858         }
859         
860         // remove the item from the list
861         ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->DeleteString(b_index);
862
863         // remove it from the list
864         for(idx=b_index; idx<Num_starfield_bitmaps-1; idx++){
865                 Starfield_bitmap_instance[idx] = Starfield_bitmap_instance[idx+1];
866                 strcpy(Starfield_bitmap_instance[idx].filename, Starfield_bitmap_instance[idx+1].filename);
867         }
868
869         // decrement the count
870         Num_starfield_bitmaps--;
871
872         // no item selected, let the message handler assign a new one
873         b_index = -1;
874 }
875
876 void bg_bitmap_dlg::OnBitmapDropdownChange()
877 {
878         // if we have no active bitmap, do nothing
879         if(b_index < 0){
880                 return;
881         }
882
883         int new_index = ((CComboBox*)GetDlgItem(IDC_SBITMAP))->GetCurSel();
884         SDL_assert(new_index != CB_ERR);
885
886         // get the new string
887         if(new_index != CB_ERR){
888                 ((CComboBox*)GetDlgItem(IDC_SBITMAP))->GetLBText(new_index, b_name);
889
890                 // change the name of the string in the listbox
891                 ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->DeleteString(b_index);
892                 ((CListBox*)GetDlgItem(IDC_SBITMAP_LIST))->InsertString(b_index, (const char*)b_name);
893         }
894 }
895