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 the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "stdafx.h"
14 #include "FRED.h"
15 #include "BgBitmapDlg.h"
16 #include "backgroundchooser.h"
17 #include "starfield/starfield.h"
18 #include "bmpman/bmpman.h"
19 #include "graphics/light.h"
20 #include "FREDView.h"
21 #include "FREDDoc.h"
22 #include "starfield/nebula.h"
23 #include "nebula/neb.h"
24 #include "nebula/neblightning.h"
25 #include "parse/parselo.h"
26 #include "mission/missionparse.h"
27 
28 #ifdef _DEBUG
29 #undef THIS_FILE
30 static char THIS_FILE[] = __FILE__;
31 #endif
32 
33 /////////////////////////////////////////////////////////////////////////////
34 // bg_bitmap_dlg dialog
35 
36 // FRED has a fixed number of checkboxes and supports only up to this number of nebula poofs
37 #define MAX_NEB2_POOF_CHECKBOXES	6
38 
bg_bitmap_dlg(CWnd * pParent)39 bg_bitmap_dlg::bg_bitmap_dlg(CWnd* pParent) : CDialog(bg_bitmap_dlg::IDD, pParent)
40 {
41 	//{{AFX_DATA_INIT(bg_bitmap_dlg)
42 	m_neb_intensity = _T("");
43 	m_envmap = _T("");
44 	m_nebula_color = -1;
45 	m_nebula_index = -1;
46 	m_bank = 0;
47 	m_heading = 0;
48 	m_pitch = 0;
49 	m_neb2_texture = 0;
50 	m_subspace = FALSE;
51 	m_fullneb = FALSE;
52 	m_toggle_trails = FALSE;
53 
54 	for (int i = 0; i < MAX_NEB2_POOFS; ++i)
55 		m_poofs[i] = Neb2_poof_flags & (1 << i) ? 1 : 0;
56 
57 	s_pitch = 0;
58 	s_bank = 0;
59 	s_heading = 0;
60 	s_scale = 1.0f;
61 	s_index = -1;
62 	b_pitch = 0;
63 	b_bank = 0;
64 	b_heading = 0;
65 	b_scale_x = 1.0f; b_scale_y = 1.0f;
66 	b_div_x = 1; b_div_y = 1;
67 	b_index = -1;
68 
69 	m_skybox_model = _T("");
70 	m_skybox_pitch = 0;
71 	m_skybox_bank = 0;
72 	m_skybox_heading = 0;
73 	m_sky_flag_1 = The_mission.skybox_flags & MR_NO_LIGHTING ? 1 : 0;
74 	m_sky_flag_2 = The_mission.skybox_flags & MR_ALL_XPARENT ? 1 : 0;
75 	m_sky_flag_3 = The_mission.skybox_flags & MR_NO_ZBUFFER ? 1 : 0;
76 	m_sky_flag_4 = The_mission.skybox_flags & MR_NO_CULL ? 1 : 0;
77 	m_sky_flag_5 = The_mission.skybox_flags & MR_NO_GLOWMAPS ? 1 : 0;
78 	m_sky_flag_6 = The_mission.skybox_flags & MR_FORCE_CLAMP ? 1 : 0;
79 	//}}AFX_DATA_INIT
80 }
81 
DoDataExchange(CDataExchange * pDX)82 void bg_bitmap_dlg::DoDataExchange(CDataExchange* pDX)
83 {
84 	CDialog::DoDataExchange(pDX);
85 	//{{AFX_DATA_MAP(bg_bitmap_dlg)
86 	DDX_Control(pDX, IDC_AMBIENT_B_SLIDER, m_amb_blue);
87 	DDX_Control(pDX, IDC_AMBIENT_G_SLIDER, m_amb_green);
88 	DDX_Control(pDX, IDC_AMBIENT_R_SLIDER, m_amb_red);
89 	DDX_Text(pDX, IDC_NEB2_INTENSITY, m_neb_intensity);
90 	DDX_CBIndex(pDX, IDC_NEBCOLOR, m_nebula_color);
91 	DDX_CBIndex(pDX, IDC_NEBPATTERN, m_nebula_index);
92 	DDX_Text(pDX, IDC_BANK, m_bank);
93 	DDX_Text(pDX, IDC_HEADING, m_heading);
94 	DDX_Text(pDX, IDC_PITCH, m_pitch);
95 	DDX_Control(pDX, IDC_SLIDER1, m_slider);
96 	DDX_CBIndex(pDX, IDC_NEB2_TEXTURE, m_neb2_texture);
97 	DDX_Check(pDX, IDC_SUBSPACE, m_subspace);
98 	DDX_Check(pDX, IDC_FULLNEB, m_fullneb);
99 
100 	for (int i = 0; i < MAX_NEB2_POOF_CHECKBOXES; ++i)
101 		DDX_Check(pDX, IDC_POOF0 + i, m_poofs[i]);
102 
103 	DDX_Check(pDX, IDC_NEB_TOGGLE_TRAILS, m_toggle_trails);
104 	DDX_Text(pDX, IDC_SUN1, s_name);
105 	DDX_Text(pDX, IDC_SUN1_P, s_pitch);
106 	DDV_MinMaxInt(pDX, s_pitch, 0, 359);
107 	DDX_Text(pDX, IDC_SUN1_B, s_bank);
108 	DDV_MinMaxInt(pDX, s_bank, 0, 359);
109 	DDX_Text(pDX, IDC_SUN1_H, s_heading);
110 	DDV_MinMaxInt(pDX, s_heading, 0, 359);
111 	DDX_Text(pDX, IDC_SUN1_SCALE, s_scale);
112 	DDV_MinMaxFloat(pDX, s_scale, 0.1f, 50.0f);
113 	DDX_Text(pDX, IDC_SBITMAP, b_name);
114 	DDX_Text(pDX, IDC_SBITMAP_P, b_pitch);
115 	DDV_MinMaxInt(pDX, b_pitch, 0, 359);
116 	DDX_Text(pDX, IDC_SBITMAP_B, b_bank);
117 	DDV_MinMaxInt(pDX, b_bank, 0, 359);
118 	DDX_Text(pDX, IDC_SBITMAP_H, b_heading);
119 	DDV_MinMaxInt(pDX, b_heading, 0, 359);	DDX_Text(pDX, IDC_SBITMAP_SCALE_X, b_scale_x);
120 	DDV_MinMaxFloat(pDX, b_scale_x, .001f, 18.0f);
121 	DDX_Text(pDX, IDC_SBITMAP_SCALE_Y, b_scale_y);
122 	DDV_MinMaxFloat(pDX, b_scale_y, .001f, 18.0f);
123 	DDX_Text(pDX, IDC_SBITMAP_DIV_X, b_div_x);
124 	DDV_MinMaxInt(pDX, b_div_x, 1, 5);
125 	DDX_Text(pDX, IDC_SBITMAP_DIV_Y, b_div_y);
126 	DDV_MinMaxInt(pDX, b_div_y, 1, 5);
127 	DDX_Text(pDX, IDC_SKYBOX_FNAME, m_skybox_model);
128 	DDX_Text(pDX, IDC_SKYBOX_P, m_skybox_pitch);
129 	DDV_MinMaxInt(pDX, m_skybox_pitch, 0, 359);
130 	DDX_Text(pDX, IDC_SKYBOX_B, m_skybox_bank);
131 	DDV_MinMaxInt(pDX, m_skybox_bank, 0, 359);
132 	DDX_Text(pDX, IDC_SKYBOX_H, m_skybox_heading);
133 	DDV_MinMaxInt(pDX, m_skybox_heading, 0, 359);
134 	DDX_Text(pDX, IDC_ENVMAP, m_envmap);
135 	DDX_Check(pDX, IDC_SKY_FLAG_NO_LIGHTING, m_sky_flag_1);
136 	DDX_Check(pDX, IDC_SKY_FLAG_XPARENT, m_sky_flag_2);
137 	DDX_Check(pDX, IDC_SKY_FLAG_NO_ZBUFF, m_sky_flag_3);
138 	DDX_Check(pDX, IDC_SKY_FLAG_NO_CULL, m_sky_flag_4);
139 	DDX_Check(pDX, IDC_SKY_FLAG_NO_GLOW, m_sky_flag_5);
140 	DDX_Check(pDX, IDC_SKY_FLAG_CLAMP, m_sky_flag_6);
141 	DDX_Text(pDX, IDC_NEB_FAR_MULTIPLIER, m_neb_far_multi);
142 	DDX_Text(pDX, IDC_NEB_NEAR_MULTIPLIER, m_neb_near_multi);
143 	//}}AFX_DATA_MAP
144 }
145 
146 BEGIN_MESSAGE_MAP(bg_bitmap_dlg, CDialog)
147 	//{{AFX_MSG_MAP(bg_bitmap_dlg)
148 	ON_WM_CLOSE()
149 	ON_CBN_SELCHANGE(IDC_NEBCOLOR, OnSelchangeNebcolor)
150 	ON_CBN_SELCHANGE(IDC_NEBPATTERN, OnSelchangeNebpattern)
151 	ON_BN_CLICKED(IDC_FULLNEB, OnFullNeb)
152 	ON_WM_HSCROLL()
153 	ON_LBN_SELCHANGE(IDC_SUN1_LIST, OnSunChange)
154 	ON_BN_CLICKED(IDC_ADD_SUN, OnAddSun)
155 	ON_BN_CLICKED(IDC_DEL_SUN, OnDelSun)
156 	ON_CBN_SELCHANGE(IDC_SUN1, OnSunDropdownChange)
157 	ON_LBN_SELCHANGE(IDC_SBITMAP_LIST, OnBitmapChange)
158 	ON_BN_CLICKED(IDC_ADD_SBITMAP, OnAddBitmap)
159 	ON_BN_CLICKED(IDC_DEL_SBITMAP, OnDelBitmap)
160 	ON_CBN_SELCHANGE(IDC_SBITMAP, OnBitmapDropdownChange)
161 	ON_NOTIFY(UDN_DELTAPOS, IDC_SBITMAP_P_SPIN, OnDeltaposSbitmapPSpin)
162 	ON_NOTIFY(UDN_DELTAPOS, IDC_SBITMAP_B_SPIN, OnDeltaposSbitmapBSpin)
163 	ON_NOTIFY(UDN_DELTAPOS, IDC_SBITMAP_H_SPIN, OnDeltaposSbitmapHSpin)
164 	ON_EN_KILLFOCUS(IDC_SBITMAP_SCALE_X, OnKillfocusSbitmapScaleX)
165 	ON_EN_KILLFOCUS(IDC_SBITMAP_SCALE_Y, OnKillfocusSbitmapScaleY)
166 	ON_EN_KILLFOCUS(IDC_SBITMAP_DIV_X, OnKillfocusSbitmapDivX)
167 	ON_EN_KILLFOCUS(IDC_SBITMAP_DIV_Y, OnKillfocusSbitmapDivY)
168 	ON_EN_KILLFOCUS(IDC_SBITMAP_P, OnKillfocusSbitmapP)
169 	ON_EN_KILLFOCUS(IDC_SBITMAP_B, OnKillfocusSbitmapB)
170 	ON_EN_KILLFOCUS(IDC_SBITMAP_H, OnKillfocusSbitmapH)
171 	ON_NOTIFY(UDN_DELTAPOS, IDC_SUN1_P_SPIN, OnDeltaposSun1PSpin)
172 	ON_NOTIFY(UDN_DELTAPOS, IDC_SUN1_H_SPIN, OnDeltaposSun1HSpin)
173 	ON_NOTIFY(UDN_DELTAPOS, IDC_SUN1_B_SPIN, OnDeltaposSun1BSpin)
174 	ON_EN_KILLFOCUS(IDC_SUN1_P, OnKillfocusSun1P)
175 	ON_EN_KILLFOCUS(IDC_SUN1_H, OnKillfocusSun1H)
176 	ON_EN_KILLFOCUS(IDC_SUN1_B, OnKillfocusSun1B)
177 	ON_EN_KILLFOCUS(IDC_SUN1_SCALE, OnKillfocusSun1Scale)
178 	ON_BN_CLICKED(IDC_ADD_BACKGROUND, OnAddBackground)
179 	ON_BN_CLICKED(IDC_REMOVE_BACKGROUND, OnRemoveBackground)
180 	ON_BN_CLICKED(IDC_IMPORT_BACKGROUND, OnImportBackground)
181 	ON_BN_CLICKED(IDC_SWAP_BACKGROUND, OnSwapBackground)
182 	ON_CBN_SELCHANGE(IDC_BACKGROUND_NUM, OnBackgroundDropdownChange)
183 	ON_BN_CLICKED(IDC_SKYBOX_MODEL, OnSkyboxBrowse)
184 	ON_NOTIFY(UDN_DELTAPOS, IDC_SKYBOX_P_SPIN, OnDeltaposSkyboxPSpin)
185 	ON_NOTIFY(UDN_DELTAPOS, IDC_SKYBOX_B_SPIN, OnDeltaposSkyboxBSpin)
186 	ON_NOTIFY(UDN_DELTAPOS, IDC_SKYBOX_H_SPIN, OnDeltaposSkyboxHSpin)
187 	ON_EN_KILLFOCUS(IDC_SKYBOX_P, OnKillfocusSkyboxP)
188 	ON_EN_KILLFOCUS(IDC_SKYBOX_B, OnKillfocusSkyboxB)
189 	ON_EN_KILLFOCUS(IDC_SKYBOX_H, OnKillfocusSkyboxH)
190 	ON_BN_CLICKED(IDC_ENVMAP_BROWSE, OnEnvmapBrowse)
191 	//}}AFX_MSG_MAP
192 END_MESSAGE_MAP()
193 
194 const static float delta = .00001f;
195 
196 /////////////////////////////////////////////////////////////////////////////
197 // bg_bitmap_dlg message handlers
198 
create()199 void bg_bitmap_dlg::create()
200 {
201 	char buf[40];
202 	int i;
203 	CComboBox *box;
204 
205 	CDialog::Create(bg_bitmap_dlg::IDD);
206 	theApp.init_window(&Bg_wnd_data, this);
207 
208 	box = (CComboBox *) GetDlgItem(IDC_NEBCOLOR);
209 	for (i=0; i<NUM_NEBULA_COLORS; i++){
210 		box->AddString(Nebula_colors[i]);
211 	}
212 
213 	m_slider.SetRange(0, MAX_STARS);
214 	m_slider.SetPos(Num_stars);
215 	sprintf(buf, "%d", Num_stars);
216 	GetDlgItem(IDC_TOTAL)->SetWindowText(buf);
217 
218 	build_nebfile_list();
219 
220 	// setup neb poof names
221 	for (i = 0; i < MAX_NEB2_POOF_CHECKBOXES; ++i)
222 		GetDlgItem(IDC_POOF0 + i)->SetWindowText(Poof_info[i].name);
223 
224 	m_skybox_model = _T(The_mission.skybox_model);
225 	m_envmap = _T(The_mission.envmap_name);
226 
227 	angles skybox_angles;
228 	vm_extract_angles_matrix(&skybox_angles, &The_mission.skybox_orientation);
229 	m_skybox_pitch = fl2ir(fl_degrees(skybox_angles.p));
230 	m_skybox_bank = fl2ir(fl_degrees(skybox_angles.b));
231 	m_skybox_heading = fl2ir(fl_degrees(skybox_angles.h));
232 
233 	//make sure angle values are in the 0-359 degree range
234 	if (m_skybox_pitch < 0)
235 		m_skybox_pitch = m_skybox_pitch + 360;
236 	if (m_skybox_bank < 0)
237 		m_skybox_bank = m_skybox_bank + 360;
238 	if (m_skybox_heading < 0)
239 		m_skybox_heading = m_skybox_heading + 360;
240 
241 
242 	for(i=0; i<MAX_NEB2_BITMAPS; i++){
243 		if(strlen(Neb2_bitmap_filenames[i]) > 0){ //-V805
244 			((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->AddString(Neb2_bitmap_filenames[i]);
245 		}
246 	}
247 	// if we have a texture selected already
248 	if(strlen(Neb2_texture_name) > 0){ //-V805
249 		m_neb2_texture = ((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->SelectString(-1, Neb2_texture_name);
250 		if(m_neb2_texture == CB_ERR){
251 			((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->SetCurSel(0);
252 			m_neb2_texture = 0;
253 		}
254 	} else {
255 		((CComboBox*)GetDlgItem(IDC_NEB2_TEXTURE))->SetCurSel(0);
256 	}
257 
258 	// setup lightning storm names
259 	((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->ResetContent();
260 	((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->AddString(CString("none"));
261 	for(size_t j=0; j<Storm_types.size(); j++){
262 		((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->AddString(CString(Storm_types[j].name));
263 	}
264 	((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->SelectString(-1, Mission_parse_storm_name);
265 
266 	// if the nebula intensity wasn't set before - set it now
267 	if(Neb2_awacs < 0.0f){
268 		m_neb_intensity = CString("3000");
269 	} else {
270 		char whee[25] = "";
271 		m_neb_intensity = CString(itoa((int)Neb2_awacs, whee, 10));
272 	}
273 
274 	// determine if a full Neb2 is active - load in the full nebula filenames or the partial neb
275 	// filenames
276 	m_fullneb = (The_mission.flags[Mission::Mission_Flags::Fullneb]) ? 1 : 0;
277 	if(m_fullneb){
278 		((CButton*)GetDlgItem(IDC_FULLNEB))->SetCheck(1);
279 	} else {
280 		// since there is no "none" option for the full nebulas
281 		m_nebula_index = Nebula_index + 1;
282 
283 		m_nebula_color = Mission_palette;
284 		if (Nebula_index < 0){
285 			GetDlgItem(IDC_NEBCOLOR)->EnableWindow(FALSE);
286 		}
287 
288 		m_pitch = Nebula_pitch;
289 		m_bank = Nebula_bank;
290 		m_heading = Nebula_heading;
291 	}
292 
293 	m_toggle_trails = (The_mission.flags[Mission::Mission_Flags::Toggle_ship_trails]) ? 1 : 0;
294 	((CButton*)GetDlgItem(IDC_NEB_TOGGLE_TRAILS))->SetCheck(m_toggle_trails);
295 
296 	// setup background numbering
297 	for (i = 0; i < (int)Backgrounds.size(); i++)
298 	{
299 		char temp[NAME_LENGTH];
300 		sprintf(temp, "Background %d", i + 1);
301 
302 		((CComboBox*) GetDlgItem(IDC_BACKGROUND_NUM))->AddString(temp);
303 		((CComboBox*) GetDlgItem(IDC_BACKGROUND_SWAP_NUM))->AddString(temp);
304 	}
305 	((CComboBox*) GetDlgItem(IDC_BACKGROUND_NUM))->SetCurSel(0);
306 	((CComboBox*) GetDlgItem(IDC_BACKGROUND_SWAP_NUM))->SetCurSel(0);
307 
308 	// we can't remove the only remaining background
309 	GetDlgItem(IDC_REMOVE_BACKGROUND)->EnableWindow(Backgrounds.size() > 1);
310 
311 	// setup sun and sunglow controls
312 	sun_data_init();
313 
314 	// setup bitmap info
315 	bitmap_data_init();
316 
317 	// determine if subspace is active
318 	m_subspace = (The_mission.flags[Mission::Mission_Flags::Subspace]) ? 1 : 0;
319 
320 	m_amb_red.SetRange(1,255);
321 	m_amb_green.SetRange(1,255);
322 	m_amb_blue.SetRange(1,255);
323 
324 	m_amb_red.SetPos(The_mission.ambient_light_level & 0xff);
325 	m_amb_green.SetPos((The_mission.ambient_light_level >> 8) & 0xff);
326 	m_amb_blue.SetPos((The_mission.ambient_light_level >> 16) & 0xff);
327 
328 	sprintf(buf, "Red: %d", m_amb_red.GetPos());
329 	GetDlgItem(IDC_AMBIENT_R_TEXT)->SetWindowText(buf);
330 	sprintf(buf, "Green: %d", m_amb_green.GetPos());
331 	GetDlgItem(IDC_AMBIENT_G_TEXT)->SetWindowText(buf);
332 	sprintf(buf, "Blue: %d", m_amb_blue.GetPos());
333 	GetDlgItem(IDC_AMBIENT_B_TEXT)->SetWindowText(buf);
334 
335 	m_neb_near_multi = Neb2_fog_near_mult;
336 	m_neb_far_multi = Neb2_fog_far_mult;
337 
338 	UpdateData(FALSE);
339 	OnFullNeb();
340 	update_data();
341 	update_map_window();
342 	set_modified();
343 }
344 
OnOK()345 void bg_bitmap_dlg::OnOK()
346 {
347 	OnClose();
348 }
349 
OnCancel()350 void bg_bitmap_dlg::OnCancel()
351 {
352 	OnClose();
353 }
354 
OnClose()355 void bg_bitmap_dlg::OnClose()
356 {
357 	UpdateData(TRUE);
358 	Mission_palette = m_nebula_color;
359 
360 	if(m_fullneb){
361 		The_mission.flags.set(Mission::Mission_Flags::Fullneb);
362 		Neb2_awacs = (float)atoi((LPCSTR)m_neb_intensity);
363 
364 		// override dumb values with reasonable ones
365 		if(Neb2_awacs <= 0.00000001f){
366 			Neb2_awacs = 3000.0f;
367 		}
368 
369 		// store poof flags
370 		Neb2_poof_flags = 0;
371 		for (int i = 0; i < MAX_NEB2_POOFS; ++i)
372 		{
373 			if (m_poofs[i])
374 				Neb2_poof_flags |= (1 << i);
375 		}
376 
377 		// get the bitmap name
378 		strcpy_s(Neb2_texture_name, Neb2_bitmap_filenames[m_neb2_texture]);
379 
380 		// init the nebula
381 		neb2_level_init();
382 	} else {
383         The_mission.flags.remove(Mission::Mission_Flags::Fullneb);
384 		Nebula_index = m_nebula_index - 1;
385 		Neb2_awacs = -1.0f;
386 		strcpy_s(Neb2_texture_name, "");
387 	}
388 
389 	// check for no ship trails -C
390     The_mission.flags.set(Mission::Mission_Flags::Toggle_ship_trails, m_toggle_trails != 0);
391 
392 	// get selected storm
393 	((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->GetLBText(((CComboBox*)GetDlgItem(IDC_NEB2_LIGHTNING))->GetCurSel(), Mission_parse_storm_name);
394 
395 	Nebula_pitch = m_pitch;
396 	Nebula_bank = m_bank;
397 	Nebula_heading = m_heading;
398 	if (Nebula_index >= 0){
399 		nebula_init(Nebula_filenames[Nebula_index], m_pitch, m_bank, m_heading);
400 	} else {
401 		nebula_close();
402 	}
403 
404     The_mission.flags.set(Mission::Mission_Flags::Subspace, m_subspace != 0);
405 
406 	string_copy(The_mission.skybox_model, m_skybox_model, NAME_LENGTH, 1);
407 	string_copy(The_mission.envmap_name, m_envmap, NAME_LENGTH, 1);
408 
409 	angles skybox_angles;
410 	skybox_angles.p = fl_radians(m_skybox_pitch);
411 	skybox_angles.b = fl_radians(m_skybox_bank);
412 	skybox_angles.h = fl_radians(m_skybox_heading);
413 	vm_angles_2_matrix(&The_mission.skybox_orientation, &skybox_angles);
414 
415 	//store the skybox flags
416 	The_mission.skybox_flags = 0;
417 	if(m_sky_flag_1) {
418 		The_mission.skybox_flags |= MR_NO_LIGHTING;
419 	}
420 	if(m_sky_flag_2) {
421 		The_mission.skybox_flags |= MR_ALL_XPARENT;
422 	}
423 	if(m_sky_flag_3) {
424 		The_mission.skybox_flags |= MR_NO_ZBUFFER;
425 	}
426 	if(m_sky_flag_4) {
427 		The_mission.skybox_flags |= MR_NO_CULL;
428 	}
429 	if(m_sky_flag_5) {
430 		The_mission.skybox_flags |= MR_NO_GLOWMAPS;
431 	}
432 	if(m_sky_flag_6) {
433 		The_mission.skybox_flags |= MR_FORCE_CLAMP;
434 	}
435 
436 	Neb2_fog_near_mult = m_neb_near_multi;
437 	Neb2_fog_far_mult = m_neb_far_multi;
438 
439 	// close sun data
440 	sun_data_close();
441 
442 	// close bitmap data
443 	bitmap_data_close();
444 
445 	// reset the background
446 	stars_pack_backgrounds();
447 	stars_load_first_valid_background();
448 
449 	// close window stuff
450 	theApp.record_window_data(&Bg_wnd_data, this);
451 	delete Bg_bitmap_dialog;
452 	Bg_bitmap_dialog = NULL;
453 }
454 
update_data(int update)455 void bg_bitmap_dlg::update_data(int update)
456 {
457 	if (update){
458 		UpdateData(TRUE);
459 	}
460 
461 	UpdateData(FALSE);
462 }
463 
OnSelchangeNebcolor()464 void bg_bitmap_dlg::OnSelchangeNebcolor()
465 {
466 	CWaitCursor wait;
467 
468 	UpdateData(TRUE);
469 	Mission_palette = m_nebula_color;
470 
471 	Update_window = 1;
472 }
473 
OnSelchangeNebpattern()474 void bg_bitmap_dlg::OnSelchangeNebpattern()
475 {
476 	CWaitCursor wait;
477 
478 	UpdateData(TRUE);
479 
480 	// fullneb indexes differently
481 	Nebula_index = m_nebula_index - 1;
482 
483 	GetDlgItem(IDC_NEBCOLOR)->EnableWindow(m_nebula_index ? TRUE : FALSE);
484 	if (Nebula_index >= 0){
485 		nebula_init(Nebula_filenames[Nebula_index], m_pitch, m_bank, m_heading);
486 	} else {
487 		nebula_close();
488 	}
489 
490 	Update_window = 1;
491 }
492 
OnHScroll(UINT nSBCode,UINT nPos,CScrollBar * pScrollBar)493 void bg_bitmap_dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar)
494 {
495 	char buf[40];
496 
497 	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
498 
499 	MODIFY(Num_stars, m_slider.GetPos());
500 	sprintf(buf, "%d", Num_stars);
501 	GetDlgItem(IDC_TOTAL)->SetWindowText(buf);
502 
503 	int col = 0;
504 
505 	col |= m_amb_red.GetPos();
506 	col |= m_amb_green.GetPos() << 8;
507 	col |= m_amb_blue.GetPos() << 16;
508 
509 	sprintf(buf, "Red: %d", m_amb_red.GetPos());
510 	GetDlgItem(IDC_AMBIENT_R_TEXT)->SetWindowText(buf);
511 	sprintf(buf, "Green: %d", m_amb_green.GetPos());
512 	GetDlgItem(IDC_AMBIENT_G_TEXT)->SetWindowText(buf);
513 	sprintf(buf, "Blue: %d", m_amb_blue.GetPos());
514 	GetDlgItem(IDC_AMBIENT_B_TEXT)->SetWindowText(buf);
515 
516 	The_mission.ambient_light_level = col;
517 	gr_set_ambient_light(m_amb_red.GetPos(), m_amb_green.GetPos(), m_amb_blue.GetPos());
518 }
519 
520 // when the user toggled the "Full Nebula" button
OnFullNeb()521 void bg_bitmap_dlg::OnFullNeb()
522 {
523 	// determine what state we're in
524 	UpdateData(TRUE);
525 	if(m_fullneb){
526 		// enable all fullneb controls
527 		GetDlgItem(IDC_NEB2_INTENSITY)->EnableWindow(TRUE);
528 		GetDlgItem(IDC_NEB2_TEXTURE)->EnableWindow(TRUE);
529 		GetDlgItem(IDC_NEB2_LIGHTNING)->EnableWindow(TRUE);
530 
531 		for (int i = 0; i < MAX_NEB2_POOF_CHECKBOXES; ++i)
532 			GetDlgItem(IDC_POOF0 + i)->EnableWindow(TRUE);
533 
534 		GetDlgItem(IDC_NEB_TOGGLE_TRAILS)->EnableWindow(TRUE);
535 
536 		// disable non-fullneb controls
537 		GetDlgItem(IDC_NEBPATTERN)->EnableWindow(FALSE);
538 		GetDlgItem(IDC_NEBCOLOR)->EnableWindow(FALSE);
539 		GetDlgItem(IDC_PITCH)->EnableWindow(FALSE);
540 		GetDlgItem(IDC_BANK)->EnableWindow(FALSE);
541 		GetDlgItem(IDC_HEADING)->EnableWindow(FALSE);
542 
543 		// check all relevant poofs
544 		for (int i = 0; i < MAX_NEB2_POOF_CHECKBOXES; ++i)
545 		{
546 			((CButton*)GetDlgItem(IDC_POOF0 + i))->SetCheck(FALSE);
547 			if (m_poofs[i])
548 				((CButton*)GetDlgItem(IDC_POOF0 + i))->SetCheck(TRUE);
549 		}
550 	} else {
551 		// enable all non-fullneb controls
552 		GetDlgItem(IDC_NEBPATTERN)->EnableWindow(TRUE);
553 		GetDlgItem(IDC_NEBCOLOR)->EnableWindow(TRUE);
554 		GetDlgItem(IDC_PITCH)->EnableWindow(TRUE);
555 		GetDlgItem(IDC_BANK)->EnableWindow(TRUE);
556 		GetDlgItem(IDC_HEADING)->EnableWindow(TRUE);
557 
558 		// disable all fullneb controls
559 		GetDlgItem(IDC_NEB2_INTENSITY)->EnableWindow(FALSE);
560 		GetDlgItem(IDC_NEB2_TEXTURE)->EnableWindow(FALSE);
561 		GetDlgItem(IDC_NEB2_LIGHTNING)->EnableWindow(FALSE);
562 
563 		for (int i = 0; i < MAX_NEB2_POOF_CHECKBOXES; ++i)
564 			GetDlgItem(IDC_POOF0 + i)->EnableWindow(FALSE);
565 
566 		GetDlgItem(IDC_NEB_TOGGLE_TRAILS)->EnableWindow(FALSE);
567 	}
568 }
569 
570 // clear and build the nebula filename list appropriately
build_nebfile_list()571 void bg_bitmap_dlg::build_nebfile_list()
572 {
573 	int i;
574 	CComboBox *box = (CComboBox *) GetDlgItem(IDC_NEBPATTERN);
575 
576 	// wacky
577 	Assert(box != NULL);
578 	if(box == NULL){
579 		return;
580 	}
581 
582 	// clear the box
583 	box->ResetContent();
584 
585 	// add all necessary strings
586 	box->AddString("None");
587 	for (i=0; i<NUM_NEBULAS; i++){
588 		box->AddString(Nebula_filenames[i]);
589 	}
590 
591 	// select the first elementccombobox
592 	box->SetCurSel(0);
593 	OnSelchangeNebpattern();
594 }
595 
sun_data_init()596 void bg_bitmap_dlg::sun_data_init()
597 {
598 	int idx;
599 	CComboBox *ccb = (CComboBox*) GetDlgItem(IDC_SUN1);
600 	CListBox *clb = (CListBox*) GetDlgItem(IDC_SUN1_LIST);
601 	background_t *background = &Backgrounds[get_active_background()];
602 
603 	// clear if necessary
604 	ccb->ResetContent();
605 	clb->ResetContent();
606 
607 	// add all suns to the drop down
608 	for (idx = 0; idx < stars_get_num_entries(true, true); idx++)
609 	{
610 		ccb->AddString(stars_get_name_FRED(idx, true));
611  	}
612 
613 	// add all suns by bitmap filename to the list
614 	for (idx = 0; idx < (int)background->suns.size(); idx++)
615 	{
616 		clb->AddString(background->suns[idx].filename);
617 	}
618 
619 	// if we have at least one item, select it
620 	if (!background->suns.empty())
621 	{
622 		clb->SetCurSel(0);
623 		OnSunChange();
624 	}
625 }
626 
sun_data_close()627 void bg_bitmap_dlg::sun_data_close()
628 {
629 	// if there is an active sun, save it
630 	sun_data_save_current();
631 }
632 
sun_data_save_current()633 void bg_bitmap_dlg::sun_data_save_current()
634 {
635 	// if we have an active item
636 	if (s_index >= 0)
637 	{
638 		background_t *background = &Backgrounds[get_active_background()];
639 		starfield_list_entry *sle = &background->suns[s_index];
640 
641 		// read out of the controls
642 		UpdateData(TRUE);
643 
644 		// store the data
645 		strcpy_s(sle->filename, s_name);
646 		sle->ang.p = (float) fl_radians(s_pitch);
647 		sle->ang.b = (float) fl_radians(s_bank);
648 		sle->ang.h = (float) fl_radians(s_heading);
649 		sle->scale_x = (float) s_scale;
650 		sle->scale_y = 1.0f;
651 		sle->div_x = 1;
652 		sle->div_y = 1;
653 	}
654 }
655 
OnSunChange()656 void bg_bitmap_dlg::OnSunChange()
657 {
658 	// save the current sun
659 	sun_data_save_current();
660 
661 	// select the new one
662 	s_index = ((CListBox*) GetDlgItem(IDC_SUN1_LIST))->GetCurSel();
663 
664 	// setup data
665 	if (s_index >= 0)
666 	{
667 		int drop_index;
668 		background_t *background = &Backgrounds[get_active_background()];
669 		starfield_list_entry *sle = &background->suns[s_index];
670 
671 		s_name = CString(sle->filename);
672 		s_pitch = fl2ir(fl_degrees(sle->ang.p) + delta);
673 		s_bank = fl2ir(fl_degrees(sle->ang.b) + delta);
674 		s_heading = fl2ir(fl_degrees(sle->ang.h) + delta);
675 		s_scale = sle->scale_x;
676 
677 		// stuff back into the controls
678 		UpdateData(FALSE);
679 
680 		// select the proper item from the dropdown
681 		drop_index = ((CComboBox*) GetDlgItem(IDC_SUN1))->FindString(-1, sle->filename);
682 		if(drop_index != CB_ERR)
683 			((CComboBox*) GetDlgItem(IDC_SUN1))->SetCurSel(drop_index);
684 	}
685 
686 	// refresh the background
687 	stars_load_background(get_active_background());
688 }
689 
OnAddSun()690 void bg_bitmap_dlg::OnAddSun()
691 {
692 	starfield_list_entry sle;
693 
694 	// save any current
695 	sun_data_save_current();
696 
697 	// select the first sun by default
698 	strcpy_s(sle.filename, stars_get_name_FRED(0, true));
699 
700 	sle.ang.p = 0;
701 	sle.ang.b = 0;
702 	sle.ang.h = 0;
703 	sle.scale_x = 1.0f;
704 	sle.scale_y = 1.0f;
705 	sle.div_x = 1;
706 	sle.div_y = 1;
707 
708 	Backgrounds[get_active_background()].suns.push_back(sle);
709 
710 	// add to the listbox and select it
711 	int add_index = ((CListBox*) GetDlgItem(IDC_SUN1_LIST))->AddString(sle.filename);
712 	((CListBox*) GetDlgItem(IDC_SUN1_LIST))->SetCurSel(add_index);
713 
714 	// call the OnSunChange function to setup all relevant data in the class
715 	OnSunChange();
716 }
717 
OnDelSun()718 void bg_bitmap_dlg::OnDelSun()
719 {
720 	// if we don't have an active item
721 	if(s_index < 0)
722 		return;
723 
724 	// remove the item from the list
725 	((CListBox*) GetDlgItem(IDC_SUN1_LIST))->DeleteString(s_index);
726 
727 	// remove it from the list
728 	background_t *background = &Backgrounds[get_active_background()];
729 	background->suns.erase(background->suns.begin() + s_index);
730 
731 	// no item selected, let the message handler assign a new one
732 	s_index = -1;
733 
734 	// refresh the background
735 	stars_load_background(get_active_background());
736 }
737 
OnSunDropdownChange()738 void bg_bitmap_dlg::OnSunDropdownChange()
739 {
740 	// if we have no active sun, do nothing
741 	if (s_index < 0)
742 		return;
743 
744 	int new_index = ((CComboBox*) GetDlgItem(IDC_SUN1))->GetCurSel();
745 	Assert(new_index != CB_ERR);
746 
747 	// get the new string
748 	if(new_index != CB_ERR)
749 	{
750 		((CComboBox*) GetDlgItem(IDC_SUN1))->GetLBText(new_index, s_name);
751 
752 		// change the name of the string in the listbox
753 		((CListBox*) GetDlgItem(IDC_SUN1_LIST))->DeleteString(s_index);
754 		((CListBox*) GetDlgItem(IDC_SUN1_LIST))->InsertString(s_index, (const char*) s_name);
755 
756 		OnSunChange();
757 	}
758 }
759 
bitmap_data_init()760 void bg_bitmap_dlg::bitmap_data_init()
761 {
762 	int idx;
763 	CComboBox *ccb = (CComboBox*) GetDlgItem(IDC_SBITMAP);
764 	CListBox *clb = (CListBox*) GetDlgItem(IDC_SBITMAP_LIST);
765 	background_t *background = &Backgrounds[get_active_background()];
766 
767 	// clear if necessary
768 	ccb->ResetContent();
769 	clb->ResetContent();
770 
771 	// add all bitmaps to the drop down
772 	for (idx = 0; idx < stars_get_num_entries(false, true); idx++)
773 	{
774 		ccb->AddString(stars_get_name_FRED(idx, false));
775  	}
776 
777 	// add all bitmaps by bitmap filename to the list
778 	for (idx = 0; idx < (int)background->bitmaps.size(); idx++)
779 	{
780 		clb->AddString(background->bitmaps[idx].filename);
781 	}
782 
783 	// if we have at least one item, select it
784 	if (!background->bitmaps.empty())
785 	{
786 		clb->SetCurSel(0);
787 		OnBitmapChange();
788 	}
789 }
790 
bitmap_data_close()791 void bg_bitmap_dlg::bitmap_data_close()
792 {
793 	// if there is an active bitmap, save it
794 	bitmap_data_save_current();
795 }
796 
bitmap_data_save_current()797 void bg_bitmap_dlg::bitmap_data_save_current()
798 {
799 	// if we have an active item
800 	if (b_index >= 0)
801 	{
802 		background_t *background = &Backgrounds[get_active_background()];
803 		starfield_list_entry *sle = &background->bitmaps[b_index];
804 
805 		// read out of the controls
806 		UpdateData(TRUE);
807 
808 		// store the data
809 		strcpy_s(sle->filename, b_name);
810 		sle->ang.p = (float) fl_radians(b_pitch);
811 		sle->ang.b = (float) fl_radians(b_bank);
812 		sle->ang.h = (float) fl_radians(b_heading);
813 		sle->scale_x = (float) b_scale_x;
814 		sle->scale_y = (float) b_scale_y;
815 		sle->div_x = b_div_x;
816 		sle->div_y = b_div_y;
817 	}
818 }
819 
OnBitmapChange()820 void bg_bitmap_dlg::OnBitmapChange()
821 {
822 	// save the current bitmap
823 	bitmap_data_save_current();
824 
825 	// select the new one
826 	b_index = ((CListBox*) GetDlgItem(IDC_SBITMAP_LIST))->GetCurSel();
827 
828 	// setup data
829 	if (b_index >= 0)
830 	{
831 		int drop_index;
832 		background_t *background = &Backgrounds[get_active_background()];
833 		starfield_list_entry *sle = &background->bitmaps[b_index];
834 
835 		b_name = CString(sle->filename);
836 		b_pitch = fl2ir(fl_degrees(sle->ang.p) + delta);
837 		b_bank = fl2ir(fl_degrees(sle->ang.b) + delta);
838 		b_heading = fl2ir(fl_degrees(sle->ang.h) + delta);
839 		b_scale_x = sle->scale_x;
840 		b_scale_y = sle->scale_y;
841 		b_div_x = sle->div_x;
842 		b_div_y = sle->div_y;
843 
844 		// stuff back into the controls
845 		UpdateData(FALSE);
846 
847 		// select the proper item from the dropdown
848 		drop_index = ((CComboBox*) GetDlgItem(IDC_SBITMAP))->FindString(-1, sle->filename);
849 		if(drop_index != CB_ERR)
850 			((CComboBox*) GetDlgItem(IDC_SBITMAP))->SetCurSel(drop_index);
851 	}
852 
853 	// refresh the background
854 	stars_load_background(get_active_background());
855 }
856 
OnAddBitmap()857 void bg_bitmap_dlg::OnAddBitmap()
858 {
859 	starfield_list_entry sle;
860 
861 	// save any current
862 	bitmap_data_save_current();
863 
864 	// select the first bitmap by default
865 	strcpy_s(sle.filename, stars_get_name_FRED(0, false));
866 
867 	sle.ang.p = 0;
868 	sle.ang.b = 0;
869 	sle.ang.h = 0;
870 	sle.scale_x = 1.0f;
871 	sle.scale_y = 1.0f;
872 	sle.div_x = 1;
873 	sle.div_y = 1;
874 
875 	Backgrounds[get_active_background()].bitmaps.push_back(sle);
876 
877 	// add to the listbox and select it
878 	int add_index = ((CListBox*) GetDlgItem(IDC_SBITMAP_LIST))->AddString(sle.filename);
879 	((CListBox*) GetDlgItem(IDC_SBITMAP_LIST))->SetCurSel(add_index);
880 
881 	// call the OnBitmapChange function to setup all relevant data in the class
882 	OnBitmapChange();
883 }
884 
OnDelBitmap()885 void bg_bitmap_dlg::OnDelBitmap()
886 {
887 	// if we don't have an active item
888 	if(b_index < 0)
889 		return;
890 
891 	// remove the item from the list
892 	((CListBox*) GetDlgItem(IDC_SBITMAP_LIST))->DeleteString(b_index);
893 
894 	// remove it from the list
895 	background_t *background = &Backgrounds[get_active_background()];
896 	background->bitmaps.erase(background->bitmaps.begin() + b_index);
897 
898 	// no item selected, let the message handler assign a new one
899 	b_index = -1;
900 
901 	// refresh the background
902 	stars_load_background(get_active_background());
903 }
904 
OnBitmapDropdownChange()905 void bg_bitmap_dlg::OnBitmapDropdownChange()
906 {
907 	// if we have no active bitmap, do nothing
908 	if (b_index < 0)
909 		return;
910 
911 	int new_index = ((CComboBox*) GetDlgItem(IDC_SBITMAP))->GetCurSel();
912 	Assert(new_index != CB_ERR);
913 
914 	// get the new string
915 	if(new_index != CB_ERR)
916 	{
917 		((CComboBox*) GetDlgItem(IDC_SBITMAP))->GetLBText(new_index, b_name);
918 
919 		// change the name of the string in the listbox
920 		((CListBox*) GetDlgItem(IDC_SBITMAP_LIST))->DeleteString(b_index);
921 		((CListBox*) GetDlgItem(IDC_SBITMAP_LIST))->InsertString(b_index, (const char*) b_name);
922 
923 		OnBitmapChange();
924 	}
925 }
926 
get_data_spinner(NM_UPDOWN * pUD,int id,int * var,int min,int max)927 void bg_bitmap_dlg::get_data_spinner(NM_UPDOWN* pUD, int id, int *var, int min, int max)
928 {
929 	if (pUD->iDelta > 0)
930 	{
931 		(*var)--;
932 
933 		//go min->max
934 		if (*var == (min-1))
935 		{
936 			*var = max;
937 		}
938 
939 		this->SetDlgItemInt(id, *var);
940 	}
941 	else
942 	{
943 		(*var)++;
944 
945 		//go max->min
946 		if (*var == (max+1))
947 		{
948 			*var=min;
949 		}
950 
951 		this->SetDlgItemInt(id, *var);
952 	}
953 }
954 
955 
get_data_float(int id,float * var,float min,float max)956 void bg_bitmap_dlg::get_data_float(int id, float *var, float min, float max)
957 {
958 	char buf[16];
959 	char max_ch[16];
960 	char min_ch[16];
961 
962 	this->GetDlgItemText(id, buf, 16);
963 
964 	*var = (float)atof(buf);
965 	sprintf(max_ch,"%.3f",max);
966 	sprintf(min_ch,"%.3f",min);
967 	CString error_msg = "Please Enter a number between ";
968 	error_msg += min_ch;
969 	error_msg += " and ";
970 	error_msg += max_ch;
971 
972 	if (*var < min)
973 	{
974 		*var = min;
975 		this->SetDlgItemText(id, min_ch);
976 		MessageBox(error_msg, "Error", MB_OK | MB_ICONWARNING);
977 	}
978 
979 	if (*var > max)
980 	{
981 		*var = max;
982 		this->SetDlgItemText(id, max_ch);
983 		MessageBox(error_msg, "Error", MB_OK | MB_ICONWARNING);
984 	}
985 }
986 
987 
get_data_int(int id,int * var,int min,int max)988 void bg_bitmap_dlg::get_data_int(int id, int *var, int min, int max)
989 {
990 	char max_ch[16];
991 	char min_ch[16];
992 
993 	*var=this->GetDlgItemInt(id);
994 
995 	sprintf(max_ch,"%d",max);
996 	sprintf(min_ch,"%d",min);
997 	CString error_msg = "Please Enter a number between ";
998 	error_msg += min_ch;
999 	error_msg += " and ";
1000 	error_msg += max_ch;
1001 
1002 	if (*var < min)
1003 	{
1004 		*var = min;
1005 		SetDlgItemInt(id, min);
1006 		MessageBox(error_msg, "Error", MB_OK | MB_ICONWARNING);
1007 	}
1008 
1009 	if (*var > max)
1010 	{
1011 		*var = max;
1012 		SetDlgItemInt(id, max);
1013 		MessageBox(error_msg, "Error", MB_OK | MB_ICONWARNING);
1014 	}
1015 }
1016 
OnDeltaposSbitmapPSpin(NMHDR * pNMHDR,LRESULT * pResult)1017 void bg_bitmap_dlg::OnDeltaposSbitmapPSpin(NMHDR* pNMHDR, LRESULT* pResult)
1018 {
1019 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1020 
1021 	if (b_index < 0) return;
1022 	get_data_spinner(pNMUpDown, IDC_SBITMAP_P, &b_pitch, 0, 359);
1023 	OnBitmapChange();
1024 	*pResult = 0;
1025 }
1026 
OnDeltaposSbitmapBSpin(NMHDR * pNMHDR,LRESULT * pResult)1027 void bg_bitmap_dlg::OnDeltaposSbitmapBSpin(NMHDR* pNMHDR, LRESULT* pResult)
1028 {
1029 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1030 
1031 	if (b_index < 0) return;
1032 	get_data_spinner(pNMUpDown, IDC_SBITMAP_B, &b_bank, 0, 359);
1033 	OnBitmapChange();
1034 	*pResult = 0;
1035 }
1036 
OnDeltaposSbitmapHSpin(NMHDR * pNMHDR,LRESULT * pResult)1037 void bg_bitmap_dlg::OnDeltaposSbitmapHSpin(NMHDR* pNMHDR, LRESULT* pResult)
1038 {
1039 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1040 
1041 	if (b_index < 0) return;
1042 	get_data_spinner(pNMUpDown, IDC_SBITMAP_H, &b_heading, 0, 359);
1043 	OnBitmapChange();
1044 	*pResult = 0;
1045 }
1046 
OnKillfocusSbitmapScaleX()1047 void bg_bitmap_dlg::OnKillfocusSbitmapScaleX()
1048 {
1049 	if (b_index < 0) return;
1050 	get_data_float(IDC_SBITMAP_SCALE_X, &b_scale_x, 0.001f, 18.0f);
1051 	OnBitmapChange();
1052 }
1053 
OnKillfocusSbitmapScaleY()1054 void bg_bitmap_dlg::OnKillfocusSbitmapScaleY()
1055 {
1056 	if (b_index < 0) return;
1057 	get_data_float(IDC_SBITMAP_SCALE_Y, &b_scale_y, 0.001f, 18.0f);
1058 	OnBitmapChange();
1059 }
1060 
OnKillfocusSbitmapDivX()1061 void bg_bitmap_dlg::OnKillfocusSbitmapDivX()
1062 {
1063 	if (b_index < 0) return;
1064 	get_data_int(IDC_SBITMAP_DIV_X, &b_div_x, 1,5);
1065 	OnBitmapChange();
1066 }
1067 
OnKillfocusSbitmapDivY()1068 void bg_bitmap_dlg::OnKillfocusSbitmapDivY()
1069 {
1070 	if (b_index < 0) return;
1071 	get_data_int(IDC_SBITMAP_DIV_Y, &b_div_y, 1,5);
1072 	OnBitmapChange();
1073 }
1074 
OnKillfocusSbitmapP()1075 void bg_bitmap_dlg::OnKillfocusSbitmapP()
1076 {
1077 	if (b_index < 0) return;
1078 	get_data_int(IDC_SBITMAP_P, &b_pitch, 0, 359);
1079 	OnBitmapChange();
1080 }
1081 
OnKillfocusSbitmapB()1082 void bg_bitmap_dlg::OnKillfocusSbitmapB()
1083 {
1084 	if (b_index < 0) return;
1085 	get_data_int(IDC_SBITMAP_B, &b_bank, 0, 359);
1086 	OnBitmapChange();
1087 }
1088 
OnKillfocusSbitmapH()1089 void bg_bitmap_dlg::OnKillfocusSbitmapH()
1090 {
1091 	if (b_index < 0) return;
1092 	get_data_int(IDC_SBITMAP_H, &b_heading, 0, 359);
1093 	OnBitmapChange();
1094 }
1095 
OnDeltaposSun1PSpin(NMHDR * pNMHDR,LRESULT * pResult)1096 void bg_bitmap_dlg::OnDeltaposSun1PSpin(NMHDR* pNMHDR, LRESULT* pResult)
1097 {
1098 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1099 
1100 	if (s_index < 0) return;
1101 	//G5K - why?	pNMUpDown->iDelta *= -1;
1102 	get_data_spinner(pNMUpDown, IDC_SUN1_P, &s_pitch, 0, 359);
1103 	OnSunChange();
1104 	*pResult = 0;
1105 }
1106 
OnDeltaposSun1BSpin(NMHDR * pNMHDR,LRESULT * pResult)1107 void bg_bitmap_dlg::OnDeltaposSun1BSpin(NMHDR* pNMHDR, LRESULT* pResult)
1108 {
1109 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1110 
1111 	if (s_index < 0) return;
1112 	//G5K - why?	pNMUpDown->iDelta *= -1;
1113 	get_data_spinner(pNMUpDown, IDC_SUN1_B, &s_bank, 0, 359);
1114 	OnSunChange();
1115 	*pResult = 0;
1116 }
1117 
OnDeltaposSun1HSpin(NMHDR * pNMHDR,LRESULT * pResult)1118 void bg_bitmap_dlg::OnDeltaposSun1HSpin(NMHDR* pNMHDR, LRESULT* pResult)
1119 {
1120 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1121 
1122 	if (s_index < 0) return;
1123 	//G5K - why?	pNMUpDown->iDelta *= -1;
1124 	get_data_spinner(pNMUpDown, IDC_SUN1_H, &s_heading, 0, 359);
1125 	OnSunChange();
1126 	*pResult = 0;
1127 }
1128 
OnKillfocusSun1P()1129 void bg_bitmap_dlg::OnKillfocusSun1P()
1130 {
1131 	if (s_index < 0) return;
1132 	get_data_int(IDC_SUN1_P, &s_pitch, 0, 359);
1133 	OnSunChange();
1134 }
1135 
OnKillfocusSun1H()1136 void bg_bitmap_dlg::OnKillfocusSun1H()
1137 {
1138 	if (s_index < 0) return;
1139 	get_data_int(IDC_SUN1_H, &s_heading, 0, 359);
1140 	OnSunChange();
1141 }
1142 
OnKillfocusSun1B()1143 void bg_bitmap_dlg::OnKillfocusSun1B()
1144 {
1145 	if (s_index < 0) return;
1146 	get_data_int(IDC_SUN1_B, &s_bank, 0, 359);
1147 	OnSunChange();
1148 }
1149 
OnKillfocusSun1Scale()1150 void bg_bitmap_dlg::OnKillfocusSun1Scale()
1151 {
1152 	if (s_index < 0) return;
1153 	get_data_float(IDC_SUN1_SCALE, &s_scale, 0.1f, 50.0f);
1154 	OnSunChange();
1155 }
1156 
OnDeltaposSkyboxPSpin(NMHDR * pNMHDR,LRESULT * pResult)1157 void bg_bitmap_dlg::OnDeltaposSkyboxPSpin(NMHDR* pNMHDR, LRESULT* pResult)
1158 {
1159 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1160 
1161 	get_data_spinner(pNMUpDown, IDC_SKYBOX_P, &m_skybox_pitch, 0, 359);
1162 	OnOrientationChange();
1163 	*pResult = 0;
1164 }
1165 
OnDeltaposSkyboxBSpin(NMHDR * pNMHDR,LRESULT * pResult)1166 void bg_bitmap_dlg::OnDeltaposSkyboxBSpin(NMHDR* pNMHDR, LRESULT* pResult)
1167 {
1168 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1169 
1170 	get_data_spinner(pNMUpDown, IDC_SKYBOX_B, &m_skybox_bank, 0, 359);
1171 	OnOrientationChange();
1172 	*pResult = 0;
1173 }
1174 
OnDeltaposSkyboxHSpin(NMHDR * pNMHDR,LRESULT * pResult)1175 void bg_bitmap_dlg::OnDeltaposSkyboxHSpin(NMHDR* pNMHDR, LRESULT* pResult)
1176 {
1177 	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
1178 
1179 	get_data_spinner(pNMUpDown, IDC_SKYBOX_H, &m_skybox_heading, 0, 359);
1180 	OnOrientationChange();
1181 	*pResult = 0;
1182 }
1183 
OnKillfocusSkyboxP()1184 void bg_bitmap_dlg::OnKillfocusSkyboxP()
1185 {
1186 	get_data_int(IDC_SKYBOX_P, &m_skybox_pitch, 0, 359);
1187 	OnOrientationChange();
1188 }
1189 
OnKillfocusSkyboxB()1190 void bg_bitmap_dlg::OnKillfocusSkyboxB()
1191 {
1192 	get_data_int(IDC_SKYBOX_B, &m_skybox_bank, 0, 359);
1193 	OnOrientationChange();
1194 }
1195 
OnKillfocusSkyboxH()1196 void bg_bitmap_dlg::OnKillfocusSkyboxH()
1197 {
1198 	get_data_int(IDC_SKYBOX_H, &m_skybox_heading, 0, 359);
1199 	OnOrientationChange();
1200 }
1201 
1202 
1203 extern void parse_one_background(background_t *background);
1204 
OnImportBackground()1205 void bg_bitmap_dlg::OnImportBackground()
1206 {
1207 	CFileDialog cfd(TRUE, ".fs2", NULL, 0, "FreeSpace2 Missions (*.fs2)|*.fs2||\0");
1208 	char filename[256], error_str[1024];
1209 	int temp, count;
1210 	char *saved_mp;
1211 
1212 	//warn on pressing the button
1213 	if (!stars_background_empty(Backgrounds[get_active_background()]))
1214 	{
1215 		if (MessageBox("This action will erase any stars and bitmaps already placed.  Continue?", "Fred2", MB_ICONWARNING | MB_YESNO) == IDNO)
1216 			return;
1217 	}
1218 
1219 	//check if cancel was pressed
1220 	if (cfd.DoModal() == IDCANCEL)
1221 		return;
1222 
1223 	strcpy_s(filename, cfd.GetPathName());
1224 
1225 	try
1226 	{
1227 		// parse in the new file
1228 		read_file_text(filename);
1229 		reset_parse();
1230 
1231 		if (!skip_to_start_of_string("#Background bitmaps"))
1232 			return;
1233 
1234 		// skip beginning stuff
1235 		required_string("#Background bitmaps");
1236 		required_string("$Num stars:");
1237 		stuff_int(&temp);
1238 		required_string("$Ambient light level:");
1239 		stuff_int(&temp);
1240 
1241 		saved_mp = Mp;
1242 
1243 		// see if we have more than one background in this mission
1244 		count = 0;
1245 		while (skip_to_string("$Bitmap List:"))
1246 			count++;
1247 
1248 		Mp = saved_mp;
1249 
1250 		// pick one (if count is 0, it's retail with just one background)
1251 		if (count > 0)
1252 		{
1253 			int i, which = 0;
1254 
1255 			if (count > 1)
1256 			{
1257 				BackgroundChooser dlg(count);
1258 				if (dlg.DoModal() == IDCANCEL)
1259 					return;
1260 
1261 				which = dlg.GetChosenBackground();
1262 			}
1263 
1264 			for (i = 0; i < which + 1; i++)
1265 				skip_to_string("$Bitmap List:");
1266 		}
1267 
1268 		// now parse the background we've selected
1269 		parse_one_background(&Backgrounds[get_active_background()]);
1270 
1271 		reinitialize_lists();
1272 	}
1273 	catch (const parse::ParseException& e)
1274 	{
1275 		mprintf(("BGBITMAPDLG: Unable to parse '%s'!  Error message = %s.\n", filename, e.what()));
1276 		sprintf(error_str, "Could not parse file: %s\n\nError message: %s", filename, e.what());
1277 
1278 		MessageBox((LPCTSTR)error_str, (LPCTSTR) "Unable to import mission background!", MB_ICONERROR | MB_OK);
1279 		return;
1280 	}
1281 }
1282 
reinitialize_lists()1283 void bg_bitmap_dlg::reinitialize_lists()
1284 {
1285 	b_index = -1;
1286 	s_index = -1;
1287 
1288 	// repopulate
1289 	sun_data_init();
1290 	bitmap_data_init();
1291 
1292 	// refresh the background
1293 	stars_load_background(get_active_background());
1294 }
1295 
get_active_background()1296 int bg_bitmap_dlg::get_active_background()
1297 {
1298 	// find out which background we're editing
1299 	int idx = ((CComboBox *) GetDlgItem(IDC_BACKGROUND_NUM))->GetCurSel();
1300 	if (idx < 0 || idx >= (int)Backgrounds.size())
1301 		idx = 0;
1302 
1303 	return idx;
1304 }
1305 
get_swap_background()1306 int bg_bitmap_dlg::get_swap_background()
1307 {
1308 	// find out which background we're swapping
1309 	int idx = ((CComboBox *) GetDlgItem(IDC_BACKGROUND_SWAP_NUM))->GetCurSel();
1310 	if (idx < 0 || idx >= (int)Backgrounds.size())
1311 		idx = 0;
1312 
1313 	return idx;
1314 }
1315 
OnBackgroundDropdownChange()1316 void bg_bitmap_dlg::OnBackgroundDropdownChange()
1317 {
1318 	reinitialize_lists();
1319 }
1320 
OnAddBackground()1321 void bg_bitmap_dlg::OnAddBackground()
1322 {
1323 	int new_index = (int)Backgrounds.size();
1324 
1325 	// add new combo box entry
1326 	char temp[NAME_LENGTH];
1327 	sprintf(temp, "Background %d", new_index + 1);
1328 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_NUM))->AddString(temp);
1329 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_SWAP_NUM))->AddString(temp);
1330 
1331 	// add the background slot
1332 	Backgrounds.emplace_back();
1333 
1334 	// select the new entry
1335 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_NUM))->SetCurSel(new_index);
1336 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_SWAP_NUM))->SetCurSel(new_index);
1337 
1338 	// can remove all but one background
1339 	if (Backgrounds.size() > 1)
1340 		GetDlgItem(IDC_REMOVE_BACKGROUND)->EnableWindow(TRUE);
1341 
1342 	// refresh dialog
1343 	reinitialize_lists();
1344 }
1345 
OnRemoveBackground()1346 void bg_bitmap_dlg::OnRemoveBackground()
1347 {
1348 	int old_index = get_active_background();
1349 
1350 	//warn on pressing the button
1351 	if (!stars_background_empty(Backgrounds[old_index]))
1352 	{
1353 		if (MessageBox("Are you sure you want to remove the current background and all of its stars and bitmaps?", "Fred2", MB_ICONWARNING | MB_YESNO) == IDNO)
1354 			return;
1355 	}
1356 
1357 	// remove the last combo box entry (not the current one, because they are numbered in order)
1358 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_NUM))->DeleteString((int)Backgrounds.size() - 1);
1359 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_SWAP_NUM))->DeleteString((int)Backgrounds.size() - 1);
1360 
1361 	// remove the background slot
1362 	Backgrounds.erase(Backgrounds.begin() + old_index);
1363 
1364 	// if the index is no longer valid, adjust it
1365 	if (old_index >= (int)Backgrounds.size())
1366 		old_index--;
1367 
1368 	// select the old entry
1369 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_NUM))->SetCurSel(old_index);
1370 	((CComboBox*)GetDlgItem(IDC_BACKGROUND_SWAP_NUM))->SetCurSel(old_index);
1371 
1372 	// can remove all but one background
1373 	if (Backgrounds.size() <= 1)
1374 		GetDlgItem(IDC_REMOVE_BACKGROUND)->EnableWindow(FALSE);
1375 
1376 	// refresh dialog
1377 	reinitialize_lists();
1378 }
1379 
OnSwapBackground()1380 void bg_bitmap_dlg::OnSwapBackground()
1381 {
1382 	int idx1 = get_active_background();
1383 	int idx2 = get_swap_background();
1384 
1385 	// don't swap if they're the same
1386 	if (idx1 == idx2)
1387 	{
1388 		MessageBox("Cannot swap a background with itself.", "FRED2", MB_OK);
1389 		return;
1390 	}
1391 
1392 	// swap
1393 	stars_swap_backgrounds(idx1, idx2);
1394 
1395 	// refresh dialog
1396 	reinitialize_lists();
1397 }
1398 
1399 
1400 char *Model_file_ext =	"Model Files (*.pof)|*.pof|"
1401 						"|";
1402 
1403 char *Image_file_ext =	"DDS Files (*.dds)|*.dds|"
1404 						"|";
1405 
OnSkyboxBrowse()1406 void bg_bitmap_dlg::OnSkyboxBrowse()
1407 {
1408 	CString filename;
1409 	int z;
1410 
1411 	UpdateData(TRUE);
1412 
1413 	// get list of
1414 	z = cfile_push_chdir(CF_TYPE_DATA);
1415 	CFileDialog dlg(TRUE, NULL, filename, OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR, Model_file_ext);
1416 
1417 	// if we have a result
1418 	if (dlg.DoModal() == IDOK) {
1419 		m_skybox_model = dlg.GetFileName();
1420 //	} else {
1421 //		m_skybox_model = _T("");
1422 	}
1423 
1424 	UpdateData(FALSE);
1425 
1426 	// restore directory
1427 	if ( !z )
1428 		cfile_pop_dir();
1429 
1430 	// load/display new skybox model (if one was selected)
1431 	stars_set_background_model( (char*)(LPCTSTR)m_skybox_model, NULL );
1432 }
1433 
OnOrientationChange()1434 void bg_bitmap_dlg::OnOrientationChange()
1435 {
1436 	angles temp_angles;
1437 	matrix temp_orient;
1438 	temp_angles.p = fl_radians(m_skybox_pitch);
1439 	temp_angles.b = fl_radians(m_skybox_bank);
1440 	temp_angles.h = fl_radians(m_skybox_heading);
1441 	vm_angles_2_matrix(&temp_orient, &temp_angles);
1442 	stars_set_background_orientation( &temp_orient );
1443 }
1444 
OnEnvmapBrowse()1445 void bg_bitmap_dlg::OnEnvmapBrowse()
1446 {
1447 	CString filename;
1448 	int z;
1449 
1450 	UpdateData(TRUE);
1451 
1452 	ENVMAP = -1;
1453 
1454 	// get list of
1455 	z = cfile_push_chdir(CF_TYPE_DATA);
1456 	CFileDialog dlg(TRUE, NULL, filename, OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR, Image_file_ext);
1457 
1458 	// if we have a result
1459 	if (dlg.DoModal() == IDOK) {
1460 		m_envmap = dlg.GetFileName();
1461 //	} else {
1462 //		m_envmap = _T("");
1463 	}
1464 
1465 	UpdateData(FALSE);
1466 
1467 	// restore directory
1468 	if ( !z )
1469 		cfile_pop_dir();
1470 
1471 	// set the new envmap
1472 	ENVMAP = bm_load( (char*)(LPCTSTR)m_envmap );
1473 }
1474