// select previous entry in current list
void tech_prev_entry()
{
	//unload the current animation, we load another one for the new current entry
	techroom_unload_animation();

	Cur_entry--;
	if (Cur_entry < 0) {
		Cur_entry = Current_list_size - 1;

		// scroll to end of list
		List_offset = Cur_entry - Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() + 1;
		if (List_offset < 0) {
			// this happens when there are not enough items to scroll
			List_offset = 0;
		}
		Tech_slider.force_currentItem(Tech_slider.get_numberItems());
	} else {
		// maybe adjust list position by 1
		if (List_offset > Cur_entry) {
			tech_scroll_list_up();
			Tech_slider.forceUp();
		}
	}

	techroom_select_new_entry();
	gamesnd_play_iface(SND_SCROLL);
}
// calculate the starting display index
int popup_calc_starting_index(popup_info *pi)
{
	// we're basically ignoring any titles here. 
	if(pi->nlines <= Popup_max_display[gr_screen.res]){
		return 0;
	}

	// otherwise, we want to see what item index the slider is on
	return Popup_slider.get_currentItem();
}
// select next entry in current list
void tech_next_entry()
{
	//unload the current animation, we load another one for the new current entry
	techroom_unload_animation();

	Cur_entry++;
	if (Cur_entry >= Current_list_size) {
		Cur_entry = 0;

		// scroll to beginning of list
		List_offset = 0;
		Tech_slider.force_currentItem(Cur_entry);
	} else {
		// maybe adjust list position by 1
		if (List_offset + Tech_list_coords[gr_screen.res][SHIP_H_COORD] / gr_get_font_height() <= Cur_entry) {
			tech_scroll_list_down();
			Tech_slider.forceDown();
		}
	}

	techroom_select_new_entry();
	gamesnd_play_iface(SND_SCROLL);
}
// button press
void fiction_viewer_button_pressed(int button)
{
	switch (button)
	{
		case FVW_BUTTON_ACCEPT:
			fiction_viewer_exit();
			gamesnd_play_iface(SND_COMMIT_PRESSED);
			break;

		case FVW_BUTTON_SCROLL_UP:
			fiction_viewer_scroll_up();
			Fiction_viewer_slider.forceUp();
			break;

		case FVW_BUTTON_SCROLL_DOWN:
			fiction_viewer_scroll_down();
			Fiction_viewer_slider.forceDown();
			break;

		default:
			Int3();	// unrecognized button
			break;
	}
}
int techroom_button_pressed(int num)
{
	switch (num) {
		case SHIPS_DATA_TAB:
		case WEAPONS_DATA_TAB:
		case INTEL_DATA_TAB:
			fsspeech_stop();
			techroom_change_tab(num);
			break;

		case SIMULATOR_TAB:
			fsspeech_stop();
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
			return 1;

		case CUTSCENES_TAB:
			fsspeech_stop();
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN);
			return 1;

		case CREDITS_TAB:
			fsspeech_stop();
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_CREDITS);
			return 1;

		case PREV_ENTRY_BUTTON:
			tech_prev_entry();
			break;

		case NEXT_ENTRY_BUTTON:
			tech_next_entry();
			break;

		case SCROLL_LIST_UP:
			tech_scroll_list_up();
			Tech_slider.forceUp();
			break;

		case SCROLL_LIST_DOWN:
			tech_scroll_list_down();
			Tech_slider.forceDown();
			break;

		case SCROLL_INFO_UP:
			tech_scroll_info_up();
			break;

		case SCROLL_INFO_DOWN:
			tech_scroll_info_down();
			break;

		case HELP_BUTTON:
			launch_context_help();
			gamesnd_play_iface(SND_HELP_PRESSED);
			break;

		case OPTIONS_BUTTON:
			gamesnd_play_iface(SND_SWITCH_SCREENS);
			gameseq_post_event(GS_EVENT_OPTIONS_MENU);
			break;

		case EXIT_BUTTON:
			fsspeech_stop();
			gamesnd_play_iface(SND_COMMIT_PRESSED);
			gameseq_post_event(GS_EVENT_MAIN_MENU);
			break;
	}

	return 0;
}
void techroom_change_tab(int num)
{
	int i, multi = 0, mask, mask2, font_height, max_num_entries_viewable;	

	//unload the current animation, we load another one for the new current entry
	if(Tab != SHIPS_DATA_TAB)
		techroom_unload_animation();

	Tab = num;
	List_offset = 0;
	Cur_entry = 0;
	multi = Player->flags & PLAYER_FLAGS_IS_MULTI;

	for (i=0; i<LIST_BUTTONS_MAX; i++){
		List_buttons[i].disable();
	}

	// disable some stuff in multiplayer
	if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
		Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
		Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
	}

	switch (Tab) {
		case SHIPS_DATA_TAB:
			mask = multi ? SIF_IN_TECH_DATABASE_M : SIF_IN_TECH_DATABASE;
			mask2 = multi ? SIF2_DEFAULT_IN_TECH_DATABASE_M : SIF2_DEFAULT_IN_TECH_DATABASE;
			
			// load ship info if necessary
			if ( Ships_loaded == 0 ) {
				if (Ship_list == NULL) {
					Ship_list = new tech_list_entry[Ship_info.size()];

					if (Ship_list == NULL)
						Error(LOCATION, "Couldn't init ships list!");
				}

				Ship_list_size = 0;

				for (auto it = Ship_info.begin(); it != Ship_info.end(); ++it)
				{
					if (Techroom_show_all || (it->flags & mask) || (it->flags2 & mask2))
					{
						// this ship should be displayed, fill out the entry struct
						Ship_list[Ship_list_size].bitmap = -1;
						Ship_list[Ship_list_size].index = std::distance(Ship_info.begin(), it);
						Ship_list[Ship_list_size].animation.num_frames = 0;			// no anim for ships
						Ship_list[Ship_list_size].has_anim = 0;				// no anim for ships
						Ship_list[Ship_list_size].name = *it->tech_title ? it->tech_title : (*it->alt_name ? it->alt_name : it->name);
						Ship_list[Ship_list_size].desc = it->tech_desc;
						Ship_list[Ship_list_size].model_num = -1;
						Ship_list[Ship_list_size].textures_loaded = 0;

						Ship_list_size++;
					}				
				}

				// make sure that at least the default entry is cleared out if we didn't grab anything
				if (!Ship_info.empty() && !Ship_list_size) {
					Ship_list[0].index = -1;
					Ship_list[0].desc = NULL;
					Ship_list[0].name = NULL;
					Ship_list[0].bitmap = -1;
					Ship_list[0].has_anim = 0;
					Ship_list[0].animation.num_frames = 0;
					Ship_list[0].model_num = -1;
					Ship_list[0].textures_loaded = 0;
				}

				Ships_loaded = 1;
			}

			Current_list = Ship_list;
			Current_list_size = Ship_list_size;

			font_height = gr_get_font_height();
			max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
			Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);

			// no anim to start here
			break;

		case WEAPONS_DATA_TAB:
				
			// load weapon info & anims if necessary
			if ( Weapons_loaded == 0 ) {
				if (Weapon_list == NULL) {
					Weapon_list = new tech_list_entry[Num_weapon_types];

					if (Weapon_list == NULL)
						Error(LOCATION, "Couldn't init ships list!");
				}

				Weapon_list_size = 0;
				mask = multi ? WIF_PLAYER_ALLOWED : WIF_IN_TECH_DATABASE;
				mask2 = WIF2_DEFAULT_IN_TECH_DATABASE;

				for (i=0; i<Num_weapon_types; i++)
				{
					if (Techroom_show_all || (Weapon_info[i].wi_flags & mask) || (Weapon_info[i].wi_flags2 & mask2))
					{ 
						// we have a weapon that should be in the tech db, so fill out the entry struct
						Weapon_list[Weapon_list_size].index = i;
						Weapon_list[Weapon_list_size].desc = Weapon_info[i].tech_desc;
						Weapon_list[Weapon_list_size].has_anim = 1;
						Weapon_list[Weapon_list_size].name = *Weapon_info[i].tech_title ? Weapon_info[i].tech_title : Weapon_info[i].name;
						Weapon_list[Weapon_list_size].bitmap = -1;
						Weapon_list[Weapon_list_size].animation.num_frames = 0;
						Weapon_list[Weapon_list_size].model_num = -1;
						Weapon_list[Weapon_list_size].textures_loaded = 0;
						// copy the weapon animation filename
						strncpy(Weapon_list[Weapon_list_size].tech_anim_filename, Weapon_info[i].tech_anim_filename, MAX_FILENAME_LEN - 1);

						Weapon_list_size++;
					}				
				}

				// make sure that at least the default entry is cleared out if we didn't grab anything
				if (Num_weapon_types && !Weapon_list_size) {
					Weapon_list[0].index = -1;
					Weapon_list[0].desc = NULL;
					Weapon_list[0].name = NULL;
					Weapon_list[0].bitmap = -1;
					Weapon_list[0].has_anim = 0;
					Weapon_list[0].animation.num_frames = 0;
					Weapon_list[0].model_num = -1;
					Weapon_list[0].textures_loaded = 0;
				}

				Weapons_loaded = 1;
			}

			Current_list = Weapon_list;
			Current_list_size = Weapon_list_size;

			font_height = gr_get_font_height();
			max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
			Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);

			break;

		case INTEL_DATA_TAB:

			// load intel if necessary
			if ( Intel_loaded == 0 ) {
				// now populate the entry structs
				Intel_list_size = 0;

				for (i=0; i<Intel_info_size; i++) {
					if (Techroom_show_all || (Intel_info[i].flags & IIF_IN_TECH_DATABASE) || (Intel_info[i].flags & IIF_DEFAULT_IN_TECH_DATABASE)) {
						// leave option for no animation if string == "none"
						if (!strcmp(Intel_info[i].anim_filename, "none")) {
							Intel_list[Intel_list_size].has_anim = 0;
							Intel_list[Intel_list_size].animation.num_frames = 0;
						} else {
							// try and load as an animation
							Intel_list[Intel_list_size].has_anim = 0;
							Intel_list[Intel_list_size].bitmap = -1;
							strncpy(Intel_list[Intel_list_size].tech_anim_filename, Intel_info[i].anim_filename, NAME_LENGTH - 1);
						}

						Intel_list[Intel_list_size].desc = Intel_info[i].desc;
						Intel_list[Intel_list_size].index = i;
						Intel_list[Intel_list_size].name = Intel_info[i].name;
						Intel_list[Intel_list_size].model_num = -1;
						Intel_list[Intel_list_size].textures_loaded = 0;

						Intel_list_size++;
					}
				}

				// make sure that at least the default entry is cleared out if we didn't grab anything
				if (Intel_info_size && !Intel_list_size) {
					Intel_list[0].index = -1;
					Intel_list[0].desc = NULL;
					Intel_list[0].name = NULL;
					Intel_list[0].bitmap = -1;
					Intel_list[0].has_anim = 0;
					Intel_list[0].animation.num_frames = 0;
					Intel_list[0].model_num = -1;
					Intel_list[0].textures_loaded = 0;
				}

				Intel_loaded = 1;
			}

			// index lookup on intel is a pretty pointless, but it keeps everything 
			// consistent and doesn't really hurt anything
			Current_list = Intel_list;
			Current_list_size = Intel_list_size;

			font_height = gr_get_font_height();
			max_num_entries_viewable = Tech_list_coords[gr_screen.res][SHIP_H_COORD] / font_height;
			Tech_slider.set_numberItems(Current_list_size > max_num_entries_viewable ? Current_list_size-max_num_entries_viewable : 0);

			break;
	}

	// reset the entry
	Cur_entry = 0;
	techroom_select_new_entry();

}
void techroom_init()
{
	int i, idx;
	techroom_buttons *b;

	Ships_loaded = 0;
	Weapons_loaded = 0;
	Intel_loaded = 0;

	Techroom_show_all = 0;

	// set up UI stuff
	Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
	Ui_window.set_mask_bmap(Tech_mask_filename[gr_screen.res]);

	Tech_background_bitmap = bm_load(Tech_background_filename[gr_screen.res]);
	if (Tech_background_bitmap < 0) {
		// failed to load bitmap, not a good thing
		Error(LOCATION,"Couldn't load techroom background bitmap");
	}

	for (i=0; i<NUM_BUTTONS; i++) {
		b = &Buttons[gr_screen.res][i];

		b->button.create(&Ui_window, "", b->x, b->y, 60, 30, b->flags & REPEAT, 1);
		// set up callback for when a mouse first goes over a button
		if (b->filename) {
			b->button.set_bmaps(b->filename);
			b->button.set_highlight_action(common_play_highlight_sound);
		} else {
			b->button.hide();
		}

		b->button.link_hotspot(b->hotspot);
	}

	// common tab button text
	Ui_window.add_XSTR("Technical Database", 1055, Buttons[gr_screen.res][TECH_DATABASE_TAB].xt,  Buttons[gr_screen.res][TECH_DATABASE_TAB].yt, &Buttons[gr_screen.res][TECH_DATABASE_TAB].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[gr_screen.res][SIMULATOR_TAB].xt,  Buttons[gr_screen.res][SIMULATOR_TAB].yt, &Buttons[gr_screen.res][SIMULATOR_TAB].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Cutscenes", 1057, Buttons[gr_screen.res][CUTSCENES_TAB].xt,  Buttons[gr_screen.res][CUTSCENES_TAB].yt, &Buttons[gr_screen.res][CUTSCENES_TAB].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Credits", 1058, Buttons[gr_screen.res][CREDITS_TAB].xt,  Buttons[gr_screen.res][CREDITS_TAB].yt, &Buttons[gr_screen.res][CREDITS_TAB].button, UI_XSTR_COLOR_GREEN);

	// common ship/weapon/intel text
	Ui_window.add_XSTR("Ships", 293, Buttons[gr_screen.res][SHIPS_DATA_TAB].xt,  Buttons[gr_screen.res][SHIPS_DATA_TAB].yt, &Buttons[gr_screen.res][SHIPS_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Weapons", 1553, Buttons[gr_screen.res][WEAPONS_DATA_TAB].xt,  Buttons[gr_screen.res][WEAPONS_DATA_TAB].yt, &Buttons[gr_screen.res][WEAPONS_DATA_TAB].button, UI_XSTR_COLOR_GREEN);
	Ui_window.add_XSTR("Intelligence", 1066, Buttons[gr_screen.res][INTEL_DATA_TAB].xt,  Buttons[gr_screen.res][INTEL_DATA_TAB].yt, &Buttons[gr_screen.res][INTEL_DATA_TAB].button, UI_XSTR_COLOR_GREEN);

	// common help/options/commit text
	Ui_window.add_XSTR("Exit", 1418, Buttons[gr_screen.res][EXIT_BUTTON].xt,  Buttons[gr_screen.res][EXIT_BUTTON].yt, &Buttons[gr_screen.res][EXIT_BUTTON].button, UI_XSTR_COLOR_PINK);		

	if (Player->flags & PLAYER_FLAGS_IS_MULTI) {
		Buttons[gr_screen.res][SIMULATOR_TAB].button.disable();
		Buttons[gr_screen.res][CUTSCENES_TAB].button.disable();
	}

	// set some hotkeys
	Buttons[gr_screen.res][PREV_ENTRY_BUTTON].button.set_hotkey(KEY_LEFT);
	Buttons[gr_screen.res][NEXT_ENTRY_BUTTON].button.set_hotkey(KEY_RIGHT);
	Buttons[gr_screen.res][SCROLL_INFO_UP].button.set_hotkey(KEY_UP);
	Buttons[gr_screen.res][SCROLL_INFO_DOWN].button.set_hotkey(KEY_DOWN);


	for (i=0; i<LIST_BUTTONS_MAX; i++) {
		List_buttons[i].create(&Ui_window, "", 0, 0, 60, 30, 0, 1);
		List_buttons[i].hide();
		List_buttons[i].disable();
	}

	View_window.create(&Ui_window, "", Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_W_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_H_COORD], 1, 1);
	View_window.hide();

	Buttons[gr_screen.res][HELP_BUTTON].button.set_hotkey(KEY_F1);
	Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
	Buttons[gr_screen.res][SCROLL_LIST_UP].button.set_hotkey(KEY_PAGEUP);
	Buttons[gr_screen.res][SCROLL_LIST_DOWN].button.set_hotkey(KEY_PAGEDOWN);

	// init help overlay states
	Techroom_overlay_id = help_overlay_get_index(TECH_ROOM_OVERLAY);
	help_overlay_set_state(Techroom_overlay_id, gr_screen.res, 0);

	// setup slider
	Tech_slider.create(&Ui_window, Tech_slider_coords[gr_screen.res][SHIP_X_COORD], Tech_slider_coords[gr_screen.res][SHIP_Y_COORD], Tech_slider_coords[gr_screen.res][SHIP_W_COORD], Tech_slider_coords[gr_screen.res][SHIP_H_COORD], Ship_info.size(), Tech_slider_filename[gr_screen.res], &tech_scroll_list_up, &tech_scroll_list_down, &tech_ship_scroll_capture);

	// zero intel anim/bitmap stuff
	for(idx=0; idx<MAX_INTEL_ENTRIES; idx++){
		Intel_list[idx].animation.num_frames = 0;
		Intel_list[idx].bitmap = -1;
	}

	mprintf(("Techroom successfully initialized, now changing tab...\n"));
	techroom_change_tab(Tab);
}
// init
void fiction_viewer_init()
{
	if (Fiction_viewer_inited)
		return;

	// no fiction viewer?
	if (!mission_has_fiction())
		return;

	// music
	common_music_init(SCORE_FICTION_VIEWER);

	// see if we have a background bitmap, and if so, which one
	// currently, we prioritize the UI that comes latest in the array;
	// in the future we might specify this in the mission or in a tbl
	for (Fiction_viewer_ui = NUM_FVW_SETTINGS - 1; Fiction_viewer_ui >= 0; Fiction_viewer_ui--)
	{
		// load the first available background bitmap
		Fiction_viewer_bitmap = bm_load(Fiction_viewer_screen_filename[Fiction_viewer_ui][gr_screen.res]);
		if (Fiction_viewer_bitmap >= 0)
			break;
	}
	
	// no ui is valid?
	if (Fiction_viewer_ui < 0)
	{
		Warning(LOCATION, "No fiction viewer graphics -- cannot display fiction viewer!");
		return;
	}

	// set up fiction viewer font
	use_fv_font();

	// calculate text area lines from font
	Fiction_viewer_text_max_lines = Fiction_viewer_text_coordinates[Fiction_viewer_ui][gr_screen.res][3] / gr_get_font_height();

	// window
	Fiction_viewer_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0, Fiction_viewer_fontnum);
	Fiction_viewer_window.set_mask_bmap(Fiction_viewer_screen_mask[Fiction_viewer_ui][gr_screen.res]);	

	// add the buttons
	for (int i = 0; i < NUM_FVW_BUTTONS; i++)
	{
		int repeat = (i == FVW_BUTTON_SCROLL_UP || i == FVW_BUTTON_SCROLL_DOWN);
		ui_button_info *b = &Fiction_viewer_buttons[Fiction_viewer_ui][gr_screen.res][i];

		b->button.create(&Fiction_viewer_window, "", b->x, b->y, b->xt, b->yt, repeat, 1);		
		b->button.set_highlight_action(common_play_highlight_sound);
		b->button.set_bmaps(b->filename);
		b->button.link_hotspot(b->hotspot);
	}

	// set up hotkeys for buttons
	Fiction_viewer_buttons[Fiction_viewer_ui][gr_screen.res][FVW_BUTTON_ACCEPT].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
	Fiction_viewer_buttons[Fiction_viewer_ui][gr_screen.res][FVW_BUTTON_SCROLL_UP].button.set_hotkey(KEY_UP);
	Fiction_viewer_buttons[Fiction_viewer_ui][gr_screen.res][FVW_BUTTON_SCROLL_DOWN].button.set_hotkey(KEY_DOWN);

	// init brief text
	brief_color_text_init(Fiction_viewer_text, Fiction_viewer_text_coordinates[Fiction_viewer_ui][gr_screen.res][2], default_fiction_viewer_color, 0, 0);

	// if the story is going to overflow the screen, add a slider
	if (Num_brief_text_lines[0] > Fiction_viewer_text_max_lines)
	{
		Fiction_viewer_slider.create(&Fiction_viewer_window,
			Fiction_viewer_slider_coordinates[Fiction_viewer_ui][gr_screen.res][0],
			Fiction_viewer_slider_coordinates[Fiction_viewer_ui][gr_screen.res][1],
			Fiction_viewer_slider_coordinates[Fiction_viewer_ui][gr_screen.res][2],
			Fiction_viewer_slider_coordinates[Fiction_viewer_ui][gr_screen.res][3],
			Num_brief_text_lines[0] - Fiction_viewer_text_max_lines,
			Fiction_viewer_slider_filename[Fiction_viewer_ui][gr_screen.res],
			&fiction_viewer_scroll_up,
			&fiction_viewer_scroll_down,
			&fiction_viewer_scroll_capture);
	}

	if (Fiction_viewer_voice >= 0)
	{
		audiostream_play(Fiction_viewer_voice, Master_voice_volume, 0);
	}
	
	Fiction_viewer_inited = 1;
}
// init the Popup window
int popup_init(popup_info *pi, int flags)
{
	int					i;
	UI_BUTTON			*b;
	popup_background	*pbg;
	char					*fname;

	if(pi->nchoices == 0){
		pbg = &Popup_background[gr_screen.res][0];
	} else {
		pbg = &Popup_background[gr_screen.res][pi->nchoices-1];
	}

	// anytime in single player, and multiplayer, not in mission, go ahead and stop time
	if ( (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && !(Game_mode & GM_IN_MISSION)) ){
		game_stop_time();
	}

	// create base window
	Popup_window.create(pbg->coords[0], pbg->coords[1], Popup_text_coords[gr_screen.res][2]+100, Popup_text_coords[gr_screen.res][3]+50, 0);
	Popup_window.set_foreground_bmap(pbg->filename);

	// create buttons
	for (i=0; i<pi->nchoices; i++) {
		b = &Popup_buttons[i];
		// accommodate single-choice positive icon being positioned differently
		if ( (pi->nchoices == 1) && (flags&PF_USE_AFFIRMATIVE_ICON) ) {
			b->create(&Popup_window, "", Button_coords[gr_screen.res][i+1][0], Button_coords[gr_screen.res][i+1][1], 30, 25, 0, 1);
		} else {
			b->create(&Popup_window, "", Button_coords[gr_screen.res][i][0], Button_coords[gr_screen.res][i][1], 30, 25, 0, 1);
		}

		fname = popup_get_button_filename(pi, i, flags);
		b->set_bmaps(fname, 3, 0);
		b->set_highlight_action(common_play_highlight_sound);
		if ( pi->keypress[i] >= 0 ) {
			b->set_hotkey(pi->keypress[i]);
		}

		// create invisible buttons to detect mouse presses... can't use mask since button region is dynamically sized
		int lx, w, h;

		gr_get_string_size(&w, &h, pi->button_text[i]);
		lx = Button_regions[gr_screen.res][i][0] - w;
		b = &Popup_button_regions[i];	

		// accommodate single-choice positive icon being positioned differently
		if ( (pi->nchoices == 1) && (flags&PF_USE_AFFIRMATIVE_ICON) ) {
			b->create(&Popup_window, "", lx, Button_regions[gr_screen.res][i+1][1], Button_regions[gr_screen.res][i+1][2]-lx, Button_regions[gr_screen.res][i+1][3]-Button_regions[gr_screen.res][i+1][1], 0, 1);
		} else {
			b->create(&Popup_window, "", lx, Button_regions[gr_screen.res][i][1], Button_regions[gr_screen.res][i][2]-lx, Button_regions[gr_screen.res][i][3]-Button_regions[gr_screen.res][i][1], 0, 1);
		}

		b->hide();
	}

	// webcursor setup
	if (Web_cursor_bitmap >= 0) {
		if (flags & PF_WEB_CURSOR_1) {
			Popup_buttons[1].set_custom_cursor_bmap(Web_cursor_bitmap);
		}
		if (flags & PF_WEB_CURSOR_2) {
			Popup_buttons[2].set_custom_cursor_bmap(Web_cursor_bitmap);
		}
	}

	// if this is an input popup, create and center the popup
	if(flags & PF_INPUT){
		Popup_input.create(&Popup_window, Popup_text_coords[gr_screen.res][0], pbg->coords[1] + Popup_input_y_offset[gr_screen.res], Popup_text_coords[gr_screen.res][2], pi->max_input_text_len, "", UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_TEXT_CEN);
		Popup_input.set_focus();
	}	
	
	Popup_default_choice=0;
	Popup_should_die = 0;

	if (flags & PF_RUN_STATE) {
		Popup_running_state = 1;
	} else {
		Popup_running_state = 0;
	}

	popup_split_lines(pi, flags);

	// create the popup slider (which we may not need to use
	Popup_slider.create(&Popup_window, Popup_slider_coords[gr_screen.res][0], Popup_slider_coords[gr_screen.res][1], Popup_slider_coords[gr_screen.res][2], Popup_slider_coords[gr_screen.res][3], pi->nlines > Popup_max_display[gr_screen.res] ? pi->nlines - Popup_max_display[gr_screen.res] : 0,
								Popup_slider_name[gr_screen.res], popup_slider_bogus, popup_slider_bogus, NULL);

	return 0;
}
Beispiel #10
0
// init the Popup window
int popup_init(popup_info *pi, int flags)
{
	int					i;
	UI_BUTTON			*b;
	popup_background	*pbg;
	char					*fname;
	int state, choice;
	
	// to have those cool holo projection popups we need to find what
	// state the game is then load the appropiate popup graphic for
	// display
	state = gameseq_get_state();

	choice = pi->nchoices - 2;
			if (choice < 0)
				choice = 0;
	//pbg = &Popup_background[gr_screen.res][0][POPUP_DEFAULT];


	switch (state)
	{
	case GS_STATE_INITIAL_PLAYER_SELECT:
		pbg = &Popup_background[gr_screen.res][choice][POPUP_REGDESK];
			
		break;
	case GS_STATE_MAIN_MENU:
		pbg = &Popup_background[gr_screen.res][choice][POPUP_CONCOURSE];

		break;
	case GS_STATE_SIMULATOR_ROOM:
		pbg = &Popup_background[gr_screen.res][choice][POPUP_LOADMISSION];

		break;
	case GS_STATE_PILOT_MANAGE:
		pbg = &Popup_background[gr_screen.res][choice][POPUP_PILOTMANAGE];

		break;

	case GS_STATE_VIEW_CUTSCENES:
		pbg = &Popup_background[gr_screen.res][choice][POPUP_FILMROOM];

		break;

	case GS_STATE_GAME_PLAY:
		pbg = &Popup_background[gr_screen.res][choice][POPUP_FLY];

		break;

	/*case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
	case GS_STATE_MULTI_JOIN_GAME:
	case GS_STATE_DEBRIEF:
		pbg = &Popup_background[gr_screen.res][choice][POPUP_DEFAULT];

		break;*/
	
	default:
			pbg = &Popup_background[gr_screen.res][choice][POPUP_DEFAULT];

	}
		// anytime in single player, and multiplayer, not in mission, go ahead and stop time
	if ( (Game_mode & GM_NORMAL) || ((Game_mode && GM_MULTIPLAYER) && !(Game_mode & GM_IN_MISSION)) ){
		game_stop_time();
	}
	
	// create base window
	Popup_window.create(pbg->coords[0], pbg->coords[1], Popup_text_coords[gr_screen.res][2]+100, Popup_text_coords[gr_screen.res][3]+50, 0);
	Popup_window.set_foreground_bmap(pbg->filename);

	// create buttons
	for (i=0; i<pi->nchoices; i++) {
		b = &Popup_buttons[i];
		// accommodate single-choice positive icon being positioned differently
		if ( (pi->nchoices == 1) && (flags&PF_USE_AFFIRMATIVE_ICON) ) {
			b->create(&Popup_window, "", Button_coords[gr_screen.res][i+1][0], Button_coords[gr_screen.res][i+1][1], 30, 25, 0, 1);
		} else {
			b->create(&Popup_window, "", Button_coords[gr_screen.res][i][0], Button_coords[gr_screen.res][i][1], 30, 25, 0, 1);
		}

		fname = popup_get_button_filename(pi, i, flags);
		b->set_bmaps(fname, 3, 0);
		b->set_highlight_action(common_play_highlight_sound);
		if ( pi->keypress[i] >= 0 ) {
			b->set_hotkey(pi->keypress[i]);
		}

		// create invisible buttons to detect mouse presses... can't use mask since button region is dynamically sized
		int lx, w, h;

		gr_get_string_size(&w, &h, pi->button_text[i]);
		lx = Button_regions[gr_screen.res][i][0] - w;
		b = &Popup_button_regions[i];	

		// accommodate single-choice positive icon being positioned differently
		if ( (pi->nchoices == 1) && (flags&PF_USE_AFFIRMATIVE_ICON) ) {
			b->create(&Popup_window, "", lx, Button_regions[gr_screen.res][i+1][1], Button_regions[gr_screen.res][i+1][2]-lx, Button_regions[gr_screen.res][i+1][3]-Button_regions[gr_screen.res][i+1][1], 0, 1);
		} else {
			b->create(&Popup_window, "", lx, Button_regions[gr_screen.res][i][1], Button_regions[gr_screen.res][i][2]-lx, Button_regions[gr_screen.res][i][3]-Button_regions[gr_screen.res][i][1], 0, 1);
		}

		b->hide();
	}

	// webcursor setup
	if (Web_cursor_bitmap >= 0) {
		if (flags & PF_WEB_CURSOR_1) {
			Popup_buttons[1].set_custom_cursor_bmap(Web_cursor_bitmap);
		}
		if (flags & PF_WEB_CURSOR_2) {
			Popup_buttons[2].set_custom_cursor_bmap(Web_cursor_bitmap);
		}
	}

	// if this is an input popup, create and center the popup
	if(flags & PF_INPUT){
		Popup_input.create(&Popup_window, Popup_text_coords[gr_screen.res][0], pbg->coords[1] + Popup_input_y_offset[gr_screen.res], Popup_text_coords[gr_screen.res][2], pi->max_input_text_len, "", UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_ESC_CLR | UI_INPUTBOX_FLAG_ESC_FOC | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_TEXT_CEN);
		Popup_input.set_focus();
	}	
	
	Popup_default_choice=0;
	Popup_should_die = 0;

	if (flags & PF_RUN_STATE) {
		Popup_running_state = 1;
	} else {
		Popup_running_state = 0;
	}

	popup_split_lines(pi, flags);

	// create the popup slider (which we may not need to use
	Popup_slider.create(&Popup_window, Popup_slider_coords[gr_screen.res][0], Popup_slider_coords[gr_screen.res][1], Popup_slider_coords[gr_screen.res][2], Popup_slider_coords[gr_screen.res][3], pi->nlines > Popup_max_display[gr_screen.res] ? pi->nlines - Popup_max_display[gr_screen.res] : 0,
								Popup_slider_name[gr_screen.res], popup_slider_bogus, popup_slider_bogus, NULL);

	return 0;
}