de-duplicate quitting logic

This commit is contained in:
2024-08-01 10:42:28 -05:00
committed by Celtic Minstrel
parent 27db98a634
commit cc5823bbcd
3 changed files with 54 additions and 73 deletions

View File

@@ -19,6 +19,7 @@
extern void finish_load_party();
extern void end_startup();
extern void post_load();
extern void queue_fake_event(const sf::Event&);
extern bool ae_loading, All_Done, party_in_memory, finished_init;
extern eGameMode overall_mode;
@@ -72,25 +73,16 @@ void set_up_apple_events() {
return TRUE;
}
// TODO: Something about the cChoiceDlog causes this to crash... AFTER returning.
-(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication*)sender {
(void) sender; // Suppress "unused parameter" warning
if(overall_mode == MODE_STARTUP && !party_in_memory) {
All_Done = true;
return NSTerminateNow;
}
if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS || (overall_mode == MODE_STARTUP && party_in_memory)) {
std::string choice = cChoiceDlog("quit-confirm-save", {"save", "quit", "cancel"}).show();
if(choice == "cancel") return NSTerminateCancel;
if(choice == "save")
save_party(univ.file, univ);
} else {
std::string choice = cChoiceDlog("quit-confirm-nosave", {"quit", "cancel"}).show();
if(choice == "cancel") return NSTerminateCancel;
}
All_Done = true;
return NSTerminateNow;
// To avoid code duplication and fix a weird crash, cancel Apple's
// termination event, but queue a fake sfml close event for
// boe.main.cpp to handle on the next frame
sf::Event event;
event.type = sf::Event::Closed;
queue_fake_event(event);
return NSTerminateCancel;
}
@end

View File

@@ -11,6 +11,7 @@
#include <iostream>
#include <ctime>
#include <sstream>
#include <deque>
#include "boe.graphics.hpp"
#include "boe.newgraph.hpp"
#include "boe.fileio.hpp"
@@ -63,6 +64,8 @@ cUniverse univ;
bool flushingInput = false, ae_loading = false;
long start_time;
std::deque<const sf::Event> fake_event_queue;
short on_spell_menu[2][62];
short on_monst_menu[256];
@@ -134,6 +137,8 @@ void handle_drop_item(short item_hit, bool& need_redraw);
void handle_drop_item(location destination, bool& need_redraw);
void handle_give_item(short item_hit, bool& did_something, bool& need_redraw);
void handle_quit_event();
#ifdef __APPLE__
eMenuChoice menuChoice=eMenuChoice::MENU_CHOICE_NONE;
short menuChoiceId=-1;
@@ -419,6 +424,11 @@ void handle_events() {
menuChoiceId=-1;
}
#endif
while(!fake_event_queue.empty()){
const sf::Event& next_event = fake_event_queue.front();
fake_event_queue.pop_front();
handle_one_event(next_event);
}
while(mainPtr.pollEvent(currentEvent)) handle_one_event(currentEvent);
// It would be nice to have minimap inside the main game window (we have lots of screen space in fullscreen mode).
@@ -448,6 +458,33 @@ void handle_events() {
}
}
void handle_quit_event() {
if(overall_mode == MODE_STARTUP) {
if(party_in_memory) {
std::string choice = cChoiceDlog("quit-confirm-save", {"save","quit","cancel"}).show();
if(choice == "cancel") return;
if(choice == "save") {
fs::path file = nav_put_or_temp_party();
if(!file.empty()) return;
save_party(file, univ);
}
}
All_Done = true;
}
if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS){
std::string choice = cChoiceDlog("quit-confirm-save", {"save", "quit", "cancel"}).show();
if(choice == "cancel")
return;
if(choice == "save")
save_party(univ.file, univ);
} else {
std::string choice = cChoiceDlog("quit-confirm-nosave", {"quit", "cancel"}).show();
if(choice == "cancel")
return;
}
All_Done = true;
}
void handle_one_event(const sf::Event& event) {
// What does this do and should it be here?
@@ -496,37 +533,17 @@ void handle_one_event(const sf::Event& event) {
break;
case sf::Event::Closed:
if(overall_mode == MODE_STARTUP) {
if(party_in_memory) {
std::string choice = cChoiceDlog("quit-confirm-save", {"save","quit","cancel"}).show();
if(choice == "cancel") break;
if(choice == "save") {
fs::path file = nav_put_or_temp_party();
if(!file.empty()) break;
save_party(file, univ);
}
}
All_Done = true;
break;
}
if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS){
std::string choice = cChoiceDlog("quit-confirm-save", {"save", "quit", "cancel"}).show();
if(choice == "cancel")
break;
if(choice == "save")
save_party(univ.file, univ);
} else {
std::string choice = cChoiceDlog("quit-confirm-nosave", {"quit", "cancel"}).show();
if(choice == "cancel")
break;
}
All_Done = true;
handle_quit_event();
break;
default:
break; // There's several events we don't need to handle at all
}
}
void queue_fake_event(const sf::Event& event) {
fake_event_queue.push_back(event);
}
void handle_one_minimap_event(const sf::Event& event) {
if(event.type == sf::Event::Closed) {
mini_map.setVisible(false);
@@ -648,36 +665,7 @@ void handle_menu_choice(eMenu item_hit) {
pick_preferences();
break;
case eMenu::QUIT:
if(overall_mode == MODE_STARTUP) {
if(party_in_memory) {
std::string choice = cChoiceDlog("quit-confirm-save", {"save","quit","cancel"}).show();
if(choice == "cancel") break;
if(choice == "save") {
fs::path file = nav_put_or_temp_party();
if(!file.empty()) break;
save_party(file, univ);
}
}
All_Done = true;
break;
}
if(overall_mode == MODE_TOWN || overall_mode == MODE_OUTDOORS) {
std::string choice = cChoiceDlog("quit-confirm-save",{"quit","save","cancel"}).show();
if(choice == "cancel")
break;
if(choice == "save") {
if(univ.file.empty()) {
univ.file = nav_put_or_temp_party();
if(univ.file.empty()) break;
}
save_party(univ.file, univ);
}
} else {
std::string choice = cChoiceDlog("quit-confirm-nosave",{"quit","cancel"}).show();
if(choice == "cancel")
return;
}
All_Done = true;
handle_quit_event();
break;
case eMenu::OPTIONS_PC_GRAPHIC:
choice = char_select_pc(1,"New graphic for who?");

View File

@@ -23,5 +23,6 @@ void update_terrain_animation();
void update_startup_animation();
void handle_events();
void handle_one_event(const sf::Event&);
void queue_fake_event(const sf::Event&);
void handle_one_minimap_event(const sf::Event &);