mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 04:31:34 -10:00
This advances the versions for Clang to 16 and GCC to 13 along with fixing any warnings these new versions are detecting now. The new image versions also include Vulkan so the additional workflow step for installing that is not necessary anymore.
730 lines
18 KiB
C++
730 lines
18 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include "cutscene/cutscenes.h"
|
|
#include "freespace.h"
|
|
#include "gamesequence/gamesequence.h"
|
|
#include "gamesnd/gamesnd.h"
|
|
#include "globalincs/alphacolors.h"
|
|
#include "io/key.h"
|
|
#include "localization/localize.h"
|
|
#include "menuui/mainhallmenu.h"
|
|
#include "movie.h"
|
|
#include "parse/parselo.h"
|
|
#include "popup/popup.h"
|
|
#include "ui/ui.h"
|
|
|
|
|
|
extern int Cmdline_nomovies;
|
|
|
|
|
|
const char* Cutscene_bitmap_name[GR_NUM_RESOLUTIONS] = {
|
|
"ViewFootage",
|
|
"2_ViewFootage"
|
|
};
|
|
const char* Cutscene_mask_name[GR_NUM_RESOLUTIONS] = {
|
|
"ViewFootage-m",
|
|
"2_ViewFootage-m"
|
|
};
|
|
|
|
int Description_index;
|
|
SCP_vector<cutscene_info> Cutscenes;
|
|
|
|
void cutscene_close()
|
|
{
|
|
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
|
|
if (cut->description != NULL)
|
|
{
|
|
vm_free(cut->description);
|
|
cut->description = NULL;
|
|
}
|
|
}
|
|
|
|
static cutscene_info *get_cutscene_pointer(char *cutscene_filename)
|
|
{
|
|
for (int i = 0; i < (int)Cutscenes.size(); i++) {
|
|
if (!stricmp(cutscene_filename, Cutscenes[i].filename)) {
|
|
return &Cutscenes[i];
|
|
}
|
|
}
|
|
|
|
// Didn't find anything.
|
|
return NULL;
|
|
}
|
|
|
|
static void cutscene_info_init(cutscene_info *csni)
|
|
{
|
|
csni->filename[0] = '\0';
|
|
csni->name[0] = '\0';
|
|
csni->description = NULL;
|
|
csni->flags = {};
|
|
}
|
|
|
|
// initialization stuff for cutscenes
|
|
void parse_cutscene_table(const char* filename)
|
|
{
|
|
|
|
char buf[MULTITEXT_LENGTH];
|
|
cutscene_info csnt;
|
|
cutscene_info_init(&csnt);
|
|
|
|
cutscene_info *csnp;
|
|
bool create_if_not_found = true;
|
|
|
|
try
|
|
{
|
|
|
|
read_file_text(filename, CF_TYPE_TABLES);
|
|
|
|
reset_parse();
|
|
|
|
// parse in all the cutscenes
|
|
skip_to_string("#Cutscenes");
|
|
ignore_white_space();
|
|
|
|
while (required_string_either("#End", "$Filename:"))
|
|
{
|
|
bool csn_new = false;
|
|
|
|
required_string("$Filename:");
|
|
stuff_string(csnt.filename, F_PATHNAME, MAX_FILENAME_LEN);
|
|
|
|
if (optional_string("+nocreate")) {
|
|
if (!Parsing_modular_table) {
|
|
Warning(LOCATION, "+nocreate flag used for cutscene in non-modular table\n");
|
|
}
|
|
create_if_not_found = false;
|
|
}
|
|
|
|
// Does this cutscene exist already?
|
|
// If so, load this new info into it
|
|
csnp = get_cutscene_pointer(csnt.filename);
|
|
if (csnp != NULL) {
|
|
if (!Parsing_modular_table) {
|
|
error_display(1,
|
|
"Error: Cutscene %s already exists. All cutscene names must be unique.",
|
|
csnt.filename);
|
|
}
|
|
} else {
|
|
// Don't create cutscene if it has +nocreate and is in a modular table.
|
|
if (!create_if_not_found && Parsing_modular_table) {
|
|
if (!skip_to_start_of_string_either("$Filename:", "#End")) {
|
|
error_display(1, "Missing [#End] or [$Filename] after cutscene %s", csnt.filename);
|
|
}
|
|
continue;
|
|
}
|
|
Cutscenes.push_back(csnt);
|
|
csn_new = true;
|
|
csnp = &Cutscenes[Cutscenes.size() -1];
|
|
}
|
|
|
|
//If $Name is not found use the $Filename instead because this field needs data
|
|
//but only do this if if we're parsing the tbl and not a tbm
|
|
if (optional_string("$Name:")) {
|
|
stuff_string(csnp->name, F_NAME, NAME_LENGTH);
|
|
mprintf(("Adding cutscene %s\n", csnp->name));
|
|
} else if (strlen(csnp->name) == 0) {
|
|
strcpy_s(csnp->name, csnt.filename);
|
|
mprintf(("Missing $Name: in cutscene.tbl. Using filename %s instead.\n", csnt.filename));
|
|
}
|
|
|
|
//If $Description is not found we can leave it blank
|
|
if (optional_string("$Description:")) {
|
|
stuff_string(buf, F_MULTITEXT, sizeof(buf));
|
|
drop_white_space(buf);
|
|
compact_multitext_string(buf);
|
|
csnp->description = vm_strdup(buf);
|
|
}
|
|
|
|
if (optional_string("$cd:"))
|
|
{
|
|
// CD option isn't needed anymore. Consume the token and ignore it
|
|
int junk;
|
|
stuff_int(&junk);
|
|
}
|
|
|
|
if (csn_new) {
|
|
csnp->flags.reset();
|
|
}
|
|
|
|
if (Cutscenes.empty())
|
|
{
|
|
// The original code assumes the first movie is the intro, so make it viewable
|
|
csnp->flags.set(Cutscene::Cutscene_Flags::Viewable);
|
|
}
|
|
|
|
if (optional_string("$Always Viewable:"))
|
|
{
|
|
bool flag;
|
|
stuff_boolean(&flag);
|
|
if (flag)
|
|
csnp->flags.set(Cutscene::Cutscene_Flags::Always_viewable);
|
|
}
|
|
if (optional_string("$Never Viewable:"))
|
|
{
|
|
bool flag;
|
|
stuff_boolean(&flag);
|
|
if (flag)
|
|
csnp->flags.set(Cutscene::Cutscene_Flags::Never_viewable);
|
|
}
|
|
if (optional_string("$Custom data:")) {
|
|
parse_string_map(csnp->custom_data, "$end_custom_data", "+Val:");
|
|
}
|
|
|
|
}
|
|
|
|
required_string("#End");
|
|
}
|
|
catch (const parse::ParseException& e)
|
|
{
|
|
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "cutscenes.tbl", e.what()));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void cutscene_init()
|
|
{
|
|
|
|
atexit(cutscene_close);
|
|
|
|
Cutscenes.clear();
|
|
|
|
// first parse the default table
|
|
parse_cutscene_table("cutscenes.tbl");
|
|
|
|
// parse any modular tables
|
|
parse_modular_table("*-csn.tbm", parse_cutscene_table);
|
|
}
|
|
|
|
// marks a cutscene as viewable
|
|
void cutscene_mark_viewable(const char* filename)
|
|
{
|
|
char cut_file[MAX_FILENAME_LEN];
|
|
char file[MAX_FILENAME_LEN];
|
|
|
|
Assert(filename != NULL);
|
|
|
|
// strip off extension
|
|
strcpy_s(file, filename);
|
|
char* p = strchr(file, '.');
|
|
if (p)
|
|
{
|
|
*p = 0;
|
|
}
|
|
|
|
// change to lower case
|
|
strlwr(file);
|
|
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
|
|
{
|
|
// change the cutscene file name to lower case
|
|
strcpy_s(cut_file, cut->filename);
|
|
strlwr(cut_file);
|
|
|
|
// see if the stripped filename matches the cutscene filename
|
|
if (strstr(cut_file, file) != NULL)
|
|
{
|
|
cut->flags.set(Cutscene::Cutscene_Flags::Viewable);
|
|
return;
|
|
}
|
|
}
|
|
|
|
Warning(LOCATION, "Could not find cutscene '%s' in listing; cannot mark it viewable...", filename);
|
|
}
|
|
|
|
#define NUM_BUTTONS 8
|
|
|
|
#define TECH_DATABASE_BUTTON 0
|
|
#define SIMULATOR_BUTTON 1
|
|
#define CUTSCENES_BUTTON 2
|
|
#define CREDITS_BUTTON 3
|
|
|
|
#define SCROLL_UP_BUTTON 4
|
|
#define SCROLL_DOWN_BUTTON 5
|
|
#define PLAY_BUTTON 6
|
|
#define EXIT_BUTTON 7
|
|
|
|
static SCP_vector<int> Cutscene_list;
|
|
//static int Stats_scroll_offset; // not used - taylor
|
|
static int Selected_line = 0; // line that is currently selected for binding
|
|
static int Scroll_offset;
|
|
static int Background_bitmap;
|
|
static UI_BUTTON List_region;
|
|
static UI_WINDOW Ui_window;
|
|
|
|
static ui_button_info Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
|
|
{ // GR_640
|
|
ui_button_info("TDB_00", 7, 3, 37, 7, 0), // tech database 1
|
|
ui_button_info("TDB_01", 7, 18, 37, 23, 1), // tech database 2
|
|
ui_button_info("TDB_02", 7, 34, 37, 38, 2), // tech database 3
|
|
ui_button_info("TDB_03", 7, 49, 37, 54, 3), // tech database 4
|
|
|
|
ui_button_info("VFB_04", 6, 318, -1, -1, 4), // scroll up
|
|
ui_button_info("VFB_05", 36, 318, -1, -1, 5), // scroll down
|
|
ui_button_info("VFB_06", 578, 319, 587, 366, 6), // play
|
|
ui_button_info("VFB_07", 574, 431, 587, 413, 7), // exit
|
|
},
|
|
{ // GR_1024
|
|
ui_button_info("2_TDB_00", 12, 5, 59, 12, 0), // tech database 1
|
|
ui_button_info("2_TDB_01", 12, 31, 59, 37, 1), // tech database 2
|
|
ui_button_info("2_TDB_02", 12, 56, 59, 62, 2), // tech database 3
|
|
ui_button_info("2_TDB_03", 12, 81, 59, 88, 3), // tech database 4
|
|
|
|
ui_button_info("2_VFB_04", 9, 509, -1, -1, 4), // scroll up
|
|
ui_button_info("2_VFB_05", 58, 509, -1, -1, 5), // scroll down
|
|
ui_button_info("2_VFB_06", 925, 511, 940, 586, 6), // play
|
|
ui_button_info("2_VFB_07", 918, 689, 940, 661, 7), // exit
|
|
}
|
|
};
|
|
|
|
// text
|
|
#define NUM_CUTSCENE_TEXT 6
|
|
UI_XSTR Cutscene_text[GR_NUM_RESOLUTIONS][NUM_CUTSCENE_TEXT] = {
|
|
{ // GR_640
|
|
{"Technical Database", 1055, 37, 7, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][TECH_DATABASE_BUTTON].button},
|
|
{"Mission Simulator", 1056, 37, 23, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][SIMULATOR_BUTTON].button},
|
|
{"Cutscenes", 1057, 37, 38, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CUTSCENES_BUTTON].button},
|
|
{"Credits", 1058, 37, 54, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][CREDITS_BUTTON].button},
|
|
|
|
{"Play", 1335, 587, 366, UI_XSTR_COLOR_GREEN, -1, &Buttons[0][PLAY_BUTTON].button},
|
|
{"Exit", 1419, 587, 413, UI_XSTR_COLOR_PINK, -1, &Buttons[0][EXIT_BUTTON].button},
|
|
},
|
|
{ // GR_1024
|
|
{"Technical Database", 1055, 59, 12, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][TECH_DATABASE_BUTTON].button},
|
|
{"Mission Simulator", 1056, 59, 37, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][SIMULATOR_BUTTON].button},
|
|
{"Cutscenes", 1057, 59, 62, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CUTSCENES_BUTTON].button},
|
|
{"Credits", 1058, 59, 88, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][CREDITS_BUTTON].button},
|
|
|
|
{"Play", 1335, 940, 586, UI_XSTR_COLOR_GREEN, -1, &Buttons[1][PLAY_BUTTON].button},
|
|
{"Exit", 1419, 940, 661, UI_XSTR_COLOR_PINK, -1, &Buttons[1][EXIT_BUTTON].button},
|
|
}
|
|
};
|
|
|
|
int Cutscene_list_coords[GR_NUM_RESOLUTIONS][4] = {
|
|
{ // GR_640
|
|
9, 117, 621, 198
|
|
},
|
|
{ // GR_1024
|
|
14, 188, 994, 316
|
|
}
|
|
};
|
|
|
|
int Cutscene_desc_coords[GR_NUM_RESOLUTIONS][4] = {
|
|
{ // GR_640
|
|
9, 378, 484, 73
|
|
},
|
|
{ // GR_1024
|
|
14, 605, 775, 117
|
|
}
|
|
};
|
|
|
|
#define MAX_TEXT_LINES 20
|
|
int Cutscene_max_text_lines[GR_NUM_RESOLUTIONS] = {
|
|
10,
|
|
MAX_TEXT_LINES
|
|
};
|
|
#define MAX_TEXT_LINE_LEN 256
|
|
|
|
static int Text_size;
|
|
static int Text_offset = 0;
|
|
static int Text_line_size[MAX_TEXT_LINES];
|
|
static const char* Text_lines[MAX_TEXT_LINES];
|
|
|
|
|
|
void cutscenes_screen_play()
|
|
{
|
|
char name[MAX_FILENAME_LEN]; // *full_name
|
|
int which_cutscene;
|
|
|
|
Assert((Selected_line >= 0) && (Selected_line < (int) Cutscene_list.size()));
|
|
which_cutscene = Cutscene_list[Selected_line];
|
|
|
|
strcpy_s(name, Cutscenes[which_cutscene].filename);
|
|
// full_name = cf_add_ext(name, NOX(".mve"));
|
|
|
|
main_hall_stop_music(true);
|
|
main_hall_stop_ambient();
|
|
auto rval = movie::play(name);
|
|
main_hall_start_music();
|
|
|
|
if (!rval)
|
|
{
|
|
char str[256];
|
|
|
|
if (Cmdline_nomovies)
|
|
strcpy_s(str, XSTR("Movies are currently disabled.", 1574));
|
|
else
|
|
sprintf(str, XSTR("Unable to play movie %s.", 204), Cutscenes[which_cutscene].name);
|
|
|
|
popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, str);
|
|
}
|
|
|
|
}
|
|
|
|
void cutscenes_screen_scroll_line_up()
|
|
{
|
|
if (Selected_line)
|
|
{
|
|
Selected_line--;
|
|
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
|
|
|
} else
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
|
|
if (Selected_line < Scroll_offset)
|
|
Scroll_offset = Selected_line;
|
|
}
|
|
|
|
void cutscenes_screen_scroll_line_down()
|
|
{
|
|
int h;
|
|
|
|
if (Selected_line < (int) Cutscene_list.size() - 1)
|
|
{
|
|
Selected_line++;
|
|
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
|
|
|
} else
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
|
|
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
|
|
if (Selected_line >= Scroll_offset + h)
|
|
{
|
|
Scroll_offset++;
|
|
}
|
|
}
|
|
|
|
void cutscenes_screen_scroll_screen_up()
|
|
{
|
|
int h;
|
|
|
|
if (Scroll_offset)
|
|
{
|
|
Scroll_offset--;
|
|
Assert(Selected_line > Scroll_offset);
|
|
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
|
|
while (Selected_line >= Scroll_offset + h)
|
|
{
|
|
Selected_line--;
|
|
}
|
|
|
|
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
|
|
|
} else
|
|
{
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
}
|
|
}
|
|
|
|
void cutscenes_screen_scroll_screen_down()
|
|
{
|
|
int h;
|
|
|
|
h = Cutscene_list_coords[gr_screen.res][3] / gr_get_font_height();
|
|
if (Scroll_offset + h < (int) Cutscene_list.size())
|
|
{
|
|
Scroll_offset++;
|
|
if (Selected_line < Scroll_offset)
|
|
{
|
|
Selected_line = Scroll_offset;
|
|
}
|
|
|
|
gamesnd_play_iface(InterfaceSounds::SCROLL);
|
|
} else
|
|
{
|
|
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
|
|
}
|
|
}
|
|
|
|
int cutscenes_screen_button_pressed(int n)
|
|
{
|
|
switch (n)
|
|
{
|
|
case TECH_DATABASE_BUTTON:
|
|
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
|
gameseq_post_event(GS_EVENT_TECH_MENU);
|
|
return 1;
|
|
|
|
case SIMULATOR_BUTTON:
|
|
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
|
gameseq_post_event(GS_EVENT_SIMULATOR_ROOM);
|
|
return 1;
|
|
|
|
case CREDITS_BUTTON:
|
|
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
|
gameseq_post_event(GS_EVENT_CREDITS);
|
|
return 1;
|
|
|
|
case SCROLL_UP_BUTTON:
|
|
cutscenes_screen_scroll_screen_up();
|
|
break;
|
|
|
|
case SCROLL_DOWN_BUTTON:
|
|
cutscenes_screen_scroll_screen_down();
|
|
break;
|
|
|
|
case PLAY_BUTTON:
|
|
cutscenes_screen_play();
|
|
break;
|
|
|
|
case EXIT_BUTTON:
|
|
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
|
|
gameseq_post_event(GS_EVENT_MAIN_MENU);
|
|
game_flush();
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void cutscenes_screen_init()
|
|
{
|
|
int i;
|
|
ui_button_info* b;
|
|
|
|
Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
|
|
Ui_window.set_mask_bmap(Cutscene_mask_name[gr_screen.res]);
|
|
|
|
for (i = 0; i < NUM_BUTTONS; i++)
|
|
{
|
|
b = &Buttons[gr_screen.res][i];
|
|
|
|
b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1);
|
|
// set up callback for when a mouse first goes over a button
|
|
b->button.set_highlight_action(common_play_highlight_sound);
|
|
b->button.set_bmaps(b->filename);
|
|
b->button.link_hotspot(b->hotspot);
|
|
}
|
|
|
|
// add xstrs
|
|
for (i = 0; i < NUM_CUTSCENE_TEXT; i++)
|
|
{
|
|
Ui_window.add_XSTR(&Cutscene_text[gr_screen.res][i]);
|
|
}
|
|
|
|
Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
|
|
Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(KEY_PAGEUP);
|
|
Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN);
|
|
|
|
List_region.create(&Ui_window, "", Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1],
|
|
Cutscene_list_coords[gr_screen.res][2], Cutscene_list_coords[gr_screen.res][3], 0, 1);
|
|
List_region.hide();
|
|
|
|
// set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
|
|
Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(KEY_PAGEUP);
|
|
Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN);
|
|
|
|
Background_bitmap = bm_load(Cutscene_bitmap_name[gr_screen.res]);
|
|
Scroll_offset = Selected_line = 0;
|
|
Description_index = -1;
|
|
|
|
Cutscene_list.clear();
|
|
|
|
int u = 0;
|
|
for (auto cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut, ++u)
|
|
{
|
|
if (cut->flags[Cutscene::Cutscene_Flags::Viewable, Cutscene::Cutscene_Flags::Always_viewable] && !cut->flags[Cutscene::Cutscene_Flags::Never_viewable])
|
|
{
|
|
Cutscene_list.push_back(u);
|
|
}
|
|
}
|
|
}
|
|
|
|
void cutscenes_screen_close()
|
|
{
|
|
if (Background_bitmap)
|
|
bm_release(Background_bitmap);
|
|
|
|
Ui_window.destroy();
|
|
}
|
|
|
|
void cutscenes_screen_do_frame()
|
|
{
|
|
int i, k, y, z;
|
|
int font_height = gr_get_font_height();
|
|
int select_tease_line = -1;
|
|
|
|
k = Ui_window.process();
|
|
switch (k)
|
|
{
|
|
case KEY_DOWN: // select next line
|
|
cutscenes_screen_scroll_line_down();
|
|
break;
|
|
|
|
case KEY_UP: // select previous line
|
|
cutscenes_screen_scroll_line_up();
|
|
break;
|
|
|
|
case KEY_TAB:
|
|
case KEY_CTRLED | KEY_DOWN:
|
|
cutscenes_screen_button_pressed(CREDITS_BUTTON);
|
|
break;
|
|
|
|
case KEY_SHIFTED | KEY_TAB:
|
|
case KEY_CTRLED | KEY_UP:
|
|
cutscenes_screen_button_pressed(SIMULATOR_BUTTON);
|
|
break;
|
|
|
|
case KEY_ENTER:
|
|
cutscenes_screen_play();
|
|
break;
|
|
|
|
case KEY_ESC: // cancel
|
|
gameseq_post_event(GS_EVENT_MAIN_MENU);
|
|
game_flush();
|
|
break;
|
|
|
|
case KEY_F1: // show help overlay
|
|
break;
|
|
|
|
case KEY_F2: // goto options screen
|
|
gameseq_post_event(GS_EVENT_OPTIONS_MENU);
|
|
break;
|
|
|
|
// the "show-all" hotkey
|
|
case KEY_CTRLED | KEY_SHIFTED | KEY_S:
|
|
{
|
|
Cutscene_list.clear();
|
|
size_t size = Cutscenes.size();
|
|
for (size_t t = 0; t < size; t++)
|
|
{
|
|
Cutscene_list.push_back((int) t);
|
|
}
|
|
|
|
break;
|
|
}
|
|
} // end switch
|
|
|
|
for (i = 0; i < NUM_BUTTONS; i++)
|
|
{
|
|
if (Buttons[gr_screen.res][i].button.pressed())
|
|
{
|
|
if (cutscenes_screen_button_pressed(i))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (List_region.button_down())
|
|
{
|
|
List_region.get_mouse_pos(NULL, &y);
|
|
z = Scroll_offset + y / font_height;
|
|
if ((z >= 0) && (z < (int) Cutscene_list.size()))
|
|
select_tease_line = z;
|
|
}
|
|
|
|
if (List_region.pressed())
|
|
{
|
|
List_region.get_mouse_pos(NULL, &y);
|
|
z = Scroll_offset + y / font_height;
|
|
if ((z >= 0) && (z < (int) Cutscene_list.size()))
|
|
Selected_line = z;
|
|
}
|
|
|
|
GR_MAYBE_CLEAR_RES(Background_bitmap);
|
|
if (Background_bitmap >= 0)
|
|
{
|
|
gr_set_bitmap(Background_bitmap);
|
|
gr_bitmap(0, 0, GR_RESIZE_MENU);
|
|
}
|
|
|
|
Ui_window.draw();
|
|
|
|
for (i = TECH_DATABASE_BUTTON; i <= CREDITS_BUTTON; i++)
|
|
{
|
|
if (Buttons[gr_screen.res][i].button.button_down())
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i > CREDITS_BUTTON)
|
|
{
|
|
Buttons[gr_screen.res][CUTSCENES_BUTTON].button.draw_forced(2);
|
|
}
|
|
|
|
y = 0;
|
|
z = Scroll_offset;
|
|
while (y + font_height <= Cutscene_list_coords[gr_screen.res][3])
|
|
{
|
|
if (z >= (int) Cutscene_list.size())
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (z == Selected_line)
|
|
{
|
|
gr_set_color_fast(&Color_text_selected);
|
|
} else if (z == select_tease_line)
|
|
{
|
|
gr_set_color_fast(&Color_text_subselected);
|
|
} else
|
|
{
|
|
gr_set_color_fast(&Color_text_normal);
|
|
}
|
|
|
|
gr_printf_menu(Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1] + y,
|
|
"%s", Cutscenes[Cutscene_list[z]].name);
|
|
|
|
y += font_height;
|
|
z++;
|
|
}
|
|
|
|
if (Description_index != Selected_line)
|
|
{
|
|
char* src = NULL;
|
|
|
|
Description_index = Selected_line;
|
|
Text_size = 0;
|
|
if (Description_index < (int) Cutscene_list.size() &&
|
|
(int) Cutscene_list[Description_index] < (int) Cutscenes.size())
|
|
{
|
|
src = Cutscenes[Cutscene_list[Description_index]].description;
|
|
if (src)
|
|
{
|
|
Text_size = split_str(src, Cutscene_desc_coords[gr_screen.res][2], Text_line_size, Text_lines,
|
|
Cutscene_max_text_lines[gr_screen.res], MAX_TEXT_LINE_LEN);
|
|
Assert(Text_size >= 0 && Text_size < Cutscene_max_text_lines[gr_screen.res]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Description_index >= 0)
|
|
{
|
|
int len;
|
|
char line[MAX_TEXT_LINE_LEN + 1];
|
|
|
|
gr_set_color_fast(&Color_text_normal);
|
|
|
|
y = 0;
|
|
z = Text_offset;
|
|
while (y + font_height <= Cutscene_desc_coords[gr_screen.res][3])
|
|
{
|
|
if (z >= Text_size || z >= MAX_TEXT_LINES - 1)
|
|
break;
|
|
|
|
len = Text_line_size[z];
|
|
if (len > MAX_TEXT_LINE_LEN)
|
|
len = MAX_TEXT_LINE_LEN;
|
|
|
|
strncpy(line, Text_lines[z], len);
|
|
line[len] = 0;
|
|
gr_string(Cutscene_desc_coords[gr_screen.res][0], Cutscene_desc_coords[gr_screen.res][1] + y, line,
|
|
GR_RESIZE_MENU);
|
|
|
|
y += font_height;
|
|
z++;
|
|
}
|
|
}
|
|
|
|
gr_flip();
|
|
}
|