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