Files
Mike Nelson 36d05ba9d8 Implement Photo Mode (#7287)
* Implement Photo Mode

* fix gr string errors

* return raw char array

* control conflict groups and better photo param defines

* better param identification in real time

* make photo mode hude dynamically sized

* fix xstrs after all changes

* missed a few

* use modern loop
2026-04-08 10:33:51 -04:00

368 lines
8.7 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 "controlconfig/controlsconfig.h"
#include "freespace.h"
#include "camera/photomode.h"
#include "gamesequence/gamesequence.h"
#include "globalincs/alphacolors.h"
#include "graphics/font.h"
#include "hud/hud.h"
#include "hud/hudmessage.h"
#include "io/key.h"
#include "mission/missionmessage.h"
#include "missionui/missionpause.h"
#include "network/multi_pause.h"
#include "object/object.h"
#include "popup/popup.h"
#include "sound/audiostr.h"
#include "ui/ui.h"
#include "weapon/weapon.h"
// ----------------------------------------------------------------------------------------------------------------
// PAUSE DEFINES/VARS
//
// pause bitmap name
const char *Pause_bmp_name[GR_NUM_RESOLUTIONS] = {
"PleaseWait",
"2_PleaseWait"
};
// pause bitmap display stuff
int Please_wait_coords[GR_NUM_RESOLUTIONS][4] = {
{ // GR_640
152, 217, 316, 26
},
{ // GR_1024
247, 346, 510, 36
}
};
// pause window objects
UI_WINDOW Pause_win;
UI_CHECKBOX Pause_single_step;
UI_CHECKBOX Pause_physics;
UI_CHECKBOX Pause_ai;
UI_CHECKBOX Pause_ai_render;
UI_CHECKBOX Pause_firing;
UI_CHECKBOX Pause_external_view_mode_check;
UI_BUTTON Pause_continue;
int Pause_type = PAUSE_TYPE_NORMAL;
// if we're already paused
bool Paused = false;
// background screen (for the chatbox)
int Pause_background_bitmap = -1;
// saved background screen
int Pause_saved_screen = -1;
// if we're in external vie wmode
int Pause_external_view_mode = 0;
// externs
extern int Ai_render_debug_flag;
extern int Ai_firing_enabled;
extern int physics_paused;
extern int ai_paused;
extern int last_single_step;
extern int game_single_step;
// ----------------------------------------------------------------------------------------------------------------
// PAUSE FUNCTIONS
//
int pause_get_type()
{
return Pause_type;
}
void pause_set_type(int type)
{
Pause_type = type;
}
// initialize the pause screen
void pause_init()
{
// if we're already paused. do nothing
if ( Paused ) {
return;
}
Assert( !(Game_mode & GM_MULTIPLAYER) );
// pause all weapon sounds
weapon_pause_sounds();
if (Pause_type == PAUSE_TYPE_NORMAL) {
Pause_saved_screen = gr_save_screen();
}
// pause all game music
audiostream_pause_all();
// pause voices
message_pause_all();
Pause_win.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
Pause_background_bitmap = bm_load(Pause_bmp_name[gr_screen.res]);
io::mouse::CursorManager::get()->pushStatus();
io::mouse::CursorManager::get()->showCursor(true);
Paused = true;
}
extern int button_function_demo_valid(int n);
extern int button_function(int n);
// pause do frame - will handle running multiplayer operations if necessary
void pause_do()
{
int k;
const char *pause_str = XSTR("Paused", 767);
int str_w, str_h;
// next two are for view resetting
static int previous_Viewer_mode = -1;
static int previous_hud_state = -1;
Assert( !(Game_mode & GM_MULTIPLAYER) );
// RENDER A GAME FRAME HERE AS THE BACKGROUND (if normal pause)
if(Pause_type == PAUSE_TYPE_NORMAL) {
// Fall back to viewer just incase saved screen is invalid
if(Pause_saved_screen == -1){
Pause_type = PAUSE_TYPE_VIEWER;
}
else if(Pause_type == PAUSE_TYPE_NORMAL) {
gr_restore_screen(Pause_saved_screen);
}
}
if(Pause_type == PAUSE_TYPE_NORMAL){
if (Pause_background_bitmap >= 0) {
gr_set_bitmap(Pause_background_bitmap);
// draw the bitmap
gr_bitmap(Please_wait_coords[gr_screen.res][0], Please_wait_coords[gr_screen.res][1], GR_RESIZE_MENU);
// draw "Paused" on it
gr_set_color_fast(&Color_normal);
font::set_font(font::FONT2);
gr_get_string_size(&str_w, &str_h, pause_str);
gr_string((gr_screen.max_w_unscaled - str_w) / 2, (gr_screen.max_h_unscaled - str_h) / 2, pause_str, GR_RESIZE_MENU);
font::set_font(font::FONT1);
}
}
if (Pause_type == PAUSE_TYPE_VIEWER) {
if (previous_Viewer_mode < 0)
previous_Viewer_mode = Viewer_mode;
if (previous_hud_state < 0)
previous_hud_state = hud_disabled();
}
// process the ui window here
k = Pause_win.process() & ~KEY_DEBUGGED;
switch (k)
{
case KEY_TAB:
hud_toggle_draw();
break;
// view from outside of the ship
case KEY_ENTER:
if (Pause_type == PAUSE_TYPE_VIEWER) {
button_function_demo_valid(VIEW_EXTERNAL);
}
break;
// view from target
case KEY_PADDIVIDE:
if (Pause_type == PAUSE_TYPE_VIEWER) {
button_function_demo_valid(VIEW_OTHER_SHIP);
}
break;
// change target
case KEY_PADMULTIPLY:
if (Pause_type == PAUSE_TYPE_VIEWER) {
button_function(TARGET_NEXT);
}
break;
case KEY_ESC:
case KEY_ALTED + KEY_PAUSE:
case KEY_PAUSE:
// reset previous view if we happened to be playing around with it during pause
if (Pause_type == PAUSE_TYPE_VIEWER) {
if (previous_Viewer_mode >= 0) {
Viewer_mode = previous_Viewer_mode;
}
// NOTE remember that hud state is reversed here (0 == on, 1 == off)
if ( (previous_hud_state >= 0) && (hud_disabled() != previous_hud_state) ) {
hud_set_draw( !previous_hud_state );
}
}
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
break;
} // end switch
// draw the background window
Pause_win.draw();
// a very unique case where we shouldn't be doing the page flip because we're inside of popup code
if(!popup_active()){
if(Pause_type == PAUSE_TYPE_NORMAL) {
gr_flip();
}
} else {
// this should only be happening in a very unique multiplayer case
Int3();
}
}
// close the pause screen
void pause_close()
{
// if we're not paused - do nothing
if ( !Paused ) {
return;
}
Assert( !(Game_mode & GM_MULTIPLAYER) );
// unpause all weapon sounds
weapon_unpause_sounds();
// unpause voices unless Photo Mode is keeping playback paused
if (!game_is_photo_mode_active()) {
message_resume_all();
}
// deinit stuff
if(Pause_saved_screen != -1) {
gr_free_screen(Pause_saved_screen);
Pause_saved_screen = -1;
}
if (Pause_background_bitmap != -1){
bm_release(Pause_background_bitmap);
Pause_background_bitmap = -1;
}
Pause_win.destroy();
game_flush();
io::mouse::CursorManager::get()->popStatus();
// unpause all the music unless Photo Mode is keeping playback paused
if (!game_is_photo_mode_active()) {
audiostream_unpause_all();
}
Paused = false;
}
// debug pause init
void pause_debug_init()
{
Pause_win.create( 100,100,400,300, WIN_DIALOG );
Pause_physics.create( &Pause_win, NOX("Physics Pause <P>"), 200, 150, physics_paused );
Pause_ai.create( &Pause_win, NOX("AI Pause <A>"), 200, 175, ai_paused );
#ifndef NDEBUG
Pause_ai_render.create( &Pause_win, NOX("AI Render Stuff <R>"), 200, 200, Ai_render_debug_flag);
#endif
Pause_firing.create( &Pause_win, NOX("AI firing <F>"), 200, 225, Ai_firing_enabled);
Pause_external_view_mode_check.create( &Pause_win, NOX("External View <E>"), 200, 250, Pause_external_view_mode);
Pause_single_step.create( &Pause_win, NOX("Single Step <S>"), 200, 290, game_single_step );
Pause_continue.create( &Pause_win, NOX("Leave Pause"), 200, 350, 200, 40 );
Pause_single_step.set_hotkey( KEY_S );
Pause_physics.set_hotkey( KEY_P );
Pause_ai.set_hotkey( KEY_A );
Pause_ai_render.set_hotkey( KEY_R );
Pause_firing.set_hotkey( KEY_F );
Pause_external_view_mode_check.set_hotkey( KEY_E );
Pause_continue.set_hotkey( KEY_ESC );
Pause_continue.set_focus();
}
// debug pause do frame
void pause_debug_do()
{
int key;
key = Pause_win.process();
if ( Pause_single_step.changed()) {
game_single_step = Pause_single_step.checked();
}
if ( Pause_physics.changed()) {
physics_paused = Pause_physics.checked();
}
if ( Pause_ai.changed()) {
ai_paused = Pause_ai.checked();
if (ai_paused){
obj_init_all_ships_physics();
}
}
if ( Pause_ai_render.changed()) {
Ai_render_debug_flag = Pause_ai_render.checked();
}
if ( Pause_firing.changed()) {
Ai_firing_enabled = Pause_firing.checked();
}
if ( Pause_external_view_mode_check.changed()) {
Pause_external_view_mode = Pause_external_view_mode_check.checked();
if (Pause_external_view_mode){
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR( "External view of player ship.", 182));
} else {
HUD_sourced_printf(HUD_SOURCE_HIDDEN, "%s", XSTR( "View from inside player ship.", 183));
}
}
if ( Pause_continue.pressed() || (key == KEY_PAUSE) ) { // Changed, MK, 11/9/97, only Pause break pause.
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
}
gr_clear();
Pause_win.draw();
gr_flip();
}
// debug pause close
void pause_debug_close()
{
last_single_step = 0; // Make so single step waits a frame before stepping
Pause_win.destroy();
game_flush();
}