From aabfe40b007acfae67bf9022ae4fa973f4418f52 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Fri, 5 Jun 2015 19:42:45 -0400 Subject: [PATCH] Scenarios can now be opened in the editor by double-clicking them. - Character editor also supports dropping saved games on the app icon --- src/BoE.xcodeproj/project.pbxproj | 4 ++ src/pcedit/pc.appleevents.mm | 52 ++++++++++++++++--------- src/scenedit/scen.appleevents.mm | 64 +++++++++++++++++++++++++++++++ src/scenedit/scen.main.cpp | 18 ++++++--- 4 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 src/scenedit/scen.appleevents.mm diff --git a/src/BoE.xcodeproj/project.pbxproj b/src/BoE.xcodeproj/project.pbxproj index 7bedd24e..adc4bf8b 100755 --- a/src/BoE.xcodeproj/project.pbxproj +++ b/src/BoE.xcodeproj/project.pbxproj @@ -60,6 +60,7 @@ 2BF04B2E0BF51924006C0831 /* boe.town.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BF04B090BF51924006C0831 /* boe.town.cpp */; }; 91034D1D1B21DAC5008F01C1 /* undo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 912283C80FD0E16C00B21642 /* undo.cpp */; }; 91034D1F1B21DAC6008F01C1 /* undo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 912283C80FD0E16C00B21642 /* undo.cpp */; }; + 91034D211B225E4A008F01C1 /* scen.appleevents.mm in Sources */ = {isa = PBXBuildFile; fileRef = 91034D201B225E49008F01C1 /* scen.appleevents.mm */; }; 9107074C18F1D18400F7BD7F /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9191460018E63D8E005CF3A4 /* scrollbar.cpp */; }; 9107074D18F1D18400F7BD7F /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9191460018E63D8E005CF3A4 /* scrollbar.cpp */; }; 9107074E18F1D18500F7BD7F /* scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9191460018E63D8E005CF3A4 /* scrollbar.cpp */; }; @@ -546,6 +547,7 @@ 2BF04B080BF51924006C0831 /* boe.text.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = boe.text.h; sourceTree = ""; }; 2BF04B090BF51924006C0831 /* boe.town.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = boe.town.cpp; sourceTree = ""; wrapsLines = 1; }; 2BF04B0A0BF51924006C0831 /* boe.town.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = boe.town.h; sourceTree = ""; }; + 91034D201B225E49008F01C1 /* scen.appleevents.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = scen.appleevents.mm; sourceTree = ""; }; 910BBA170FB8BECA001E34EA /* dialog.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = dialog.hpp; sourceTree = ""; }; 910BBA180FB8BECA001E34EA /* dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dialog.cpp; sourceTree = ""; }; 910BBA270FB8C459001E34EA /* ticpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ticpp.cpp; sourceTree = ""; }; @@ -1071,6 +1073,7 @@ isa = PBXGroup; children = ( 91B3EEF10F969BA700BF5B67 /* scen.actions.cpp */, + 91034D201B225E49008F01C1 /* scen.appleevents.mm */, 91B3EEF50F969BA700BF5B67 /* scen.btnmg.cpp */, 91B3EEEF0F969BA700BF5B67 /* scen.core.cpp */, 91B3EEF20F969BA700BF5B67 /* scen.fileio.cpp */, @@ -1655,6 +1658,7 @@ 91FDB57C1A4E77CA00DE5983 /* shop.cpp in Sources */, 919086E01A65CA300071F7A0 /* tinyprint.cpp in Sources */, 91E30F301A7481C50057C54A /* fileio.cpp in Sources */, + 91034D211B225E4A008F01C1 /* scen.appleevents.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/pcedit/pc.appleevents.mm b/src/pcedit/pc.appleevents.mm index c3a6dc8d..a8d17095 100644 --- a/src/pcedit/pc.appleevents.mm +++ b/src/pcedit/pc.appleevents.mm @@ -6,39 +6,55 @@ // // +#include "universe.h" // Include before Cocoa because the Cocoa header defines things that cause compilation errors in here #include #include +#include "fileio.hpp" +#include "pc.menus.h" +#include "pc.fileio.h" extern bool verify_restore_quit(std::string dlog); -extern bool All_Done; +extern bool All_Done, party_in_scen, scen_items_loaded; +extern cUniverse univ; +extern fs::path file_in_mem; -typedef NSAppleEventDescriptor AEDescr; - -@interface AppleEventHandler : NSObject --(void)handleOpenDoc:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply; --(void)handleQuit:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply; +@interface AppleEventHandler : NSObject +-(BOOL)application:(NSApplication*) app openFile:(NSString*) file; +-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*) sender; @end void set_up_apple_events(); // Suppress "no prototype" warning void set_up_apple_events() { AppleEventHandler* aeHandler = [[AppleEventHandler alloc] init]; - NSAppleEventManager* AEmgr = [NSAppleEventManager sharedAppleEventManager]; - [AEmgr setEventHandler: aeHandler andSelector: @selector(handleOpenDoc:withReply:) - forEventClass: kCoreEventClass andEventID: kAEOpenDocuments]; - [AEmgr setEventHandler: aeHandler andSelector: @selector(handleQuit:withReply:) - forEventClass: kCoreEventClass andEventID: kAEQuitApplication]; + [[NSApplication sharedApplication] setDelegate: aeHandler]; } @implementation AppleEventHandler --(void)handleOpenDoc:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply { - (void) theAppleEvent; // Suppress "unused parameter" warning - (void) reply; - // TODO: Handle this +-(BOOL)application:(NSApplication*) app openFile:(NSString*) file { + (void) app; // Suppress "unused parameter" warning + + unsigned long len = [file length], sz = len + 1; + auto msg = std::shared_ptr(new unichar[sz], std::default_delete()); + std::fill(msg.get(), msg.get() + sz, 0); + [file getCharacters: msg.get() range: (NSRange){0, len}]; + std::string fileName; + std::copy(msg.get(), msg.get() + len, std::inserter(fileName, fileName.begin())); + + if(load_party(fileName, univ)) { + file_in_mem = fileName; + party_in_scen = !univ.party.scen_name.empty(); + if(!party_in_scen) load_base_item_defs(); + scen_items_loaded = true; + update_item_menu(); + menu_activate(); + } + return TRUE; } --(void)handleQuit:(AEDescr*)theAppleEvent withReply: (AEDescr*)reply { - (void) theAppleEvent; // Suppress "unused parameter" warning - (void) reply; + +-(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication*)sender { + (void) sender; // Suppress "unused parameter" warning All_Done = verify_restore_quit("save-quit"); + return All_Done; } @end diff --git a/src/scenedit/scen.appleevents.mm b/src/scenedit/scen.appleevents.mm new file mode 100644 index 00000000..68ead086 --- /dev/null +++ b/src/scenedit/scen.appleevents.mm @@ -0,0 +1,64 @@ +// +// boe.appleevents.mm +// BoE +// +// Created by Celtic Minstrel on 14-03-26. +// +// + +#include "scenario.h" // Include before Cocoa because the Cocoa header defines things that cause compilation errors in here +#include +#include +#include +#include +#include "fileio.hpp" +#include "scen.actions.h" + +//extern bool ae_loading, startup_loaded, All_Done, party_in_memory, finished_init; +extern cScenario scenario; +extern cTown* town; +extern cOutdoors* current_terrain; +extern short cur_town; +extern location cur_out; +extern bool change_made, ae_loading; + +@interface AppleEventHandler : NSObject +-(BOOL)application:(NSApplication*) app openFile:(NSString*) file; +-(NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*) sender; +@end + +void set_up_apple_events(); // Suppress "no prototype" warning +void set_up_apple_events() { + AppleEventHandler* aeHandler = [[AppleEventHandler alloc] init]; + [[NSApplication sharedApplication] setDelegate: aeHandler]; +} + +// TODO: What if they're already in a scenario? It should ask for confirmation, right? +// (Need to figure out cChoiceDlog bug first, though, as it would crash here just like it does on the quit event.) +@implementation AppleEventHandler +-(BOOL)application:(NSApplication*) app openFile:(NSString*) file { + (void) app; // Suppress "unused parameter" warning + if(file == nil) { + std::cerr << "Error: filename was nil" << std::endl; + return FALSE; + } + + unsigned long len = [file length], sz = len + 1; + auto msg = std::shared_ptr(new unichar[sz], std::default_delete()); + std::fill(msg.get(), msg.get() + sz, 0); + [file getCharacters: msg.get() range: (NSRange){0, len}]; + std::string fileName; + std::copy(msg.get(), msg.get() + len, std::inserter(fileName, fileName.begin())); + + if(load_scenario(fileName, scenario)) { + cur_town = scenario.last_town_edited; + town = scenario.towns[cur_town]; + cur_out = scenario.last_out_edited; + current_terrain = scenario.outdoors[cur_out.x][cur_out.y]; + change_made = false; + ae_loading = true; + set_up_main_screen(); + } + return TRUE; +} +@end diff --git a/src/scenedit/scen.main.cpp b/src/scenedit/scen.main.cpp index 6394f2d2..43209323 100644 --- a/src/scenedit/scen.main.cpp +++ b/src/scenedit/scen.main.cpp @@ -35,7 +35,7 @@ short mode_count = 0; cOutdoors* current_terrain; short pixel_depth,old_depth = 8; -bool change_made = false; +bool change_made = false, ae_loading = false; // Numbers of current areas being edited short cur_town; @@ -54,6 +54,8 @@ cScenario scenario; rectangle right_sbar_rect; extern rectangle terrain_buttons_rect; +extern void set_up_apple_events(); + //Changed to ISO C specified argument and return type. int main(int, char* argv[]) { try { @@ -72,6 +74,9 @@ int main(int, char* argv[]) { cDialog::doAnimations = true; init_graph_tool(); + check_for_intel(); + set_up_apple_events(); + cen_x = 18; cen_y = 18; @@ -84,11 +89,13 @@ int main(int, char* argv[]) { Set_up_win(); init_screen_locs(); - shut_down_menus(0); + if(ae_loading) + set_up_main_screen(); + else { + shut_down_menus(0); + set_up_start_screen(); + } - set_up_start_screen(); - - check_for_intel(); redraw_screen(); while(!All_Done) @@ -149,6 +156,7 @@ void Initialize(void) { } void Handle_One_Event() { + ae_loading = false; Handle_Update(); if(!mainPtr.waitEvent(event)) return;