Reform scenario editor menu -> command mapping so that the non-platform-dependent code doesn't need to know where the menuitem is

This commit is contained in:
2015-01-05 13:33:38 -05:00
parent 75e340f945
commit 584baa3f19
11 changed files with 295 additions and 287 deletions

View File

@@ -90,7 +90,6 @@ BEGIN
MENUITEM "&Scenario Details", IDM_SCEN_DETAILS
MENUITEM "Scenario Intr&o Text", IDM_SCEN_INTRO
MENUITEM "Set Starting &Location", IDM_SCEN_START
MENUITEM "Change Password", IDM_SCEN_PASSWORD
MENUITEM SEPARATOR
MENUITEM "Advanced:", IDM_SCEN_NEW_TOWN, GRAYED
MENUITEM " Edit Special &Nodes", IDM_SCEN_ADV_SPECIALS

View File

@@ -783,6 +783,7 @@ bool outdoor_move_monster(short num,location dest) {
if(!outd_is_blocked(dest) && !outd_is_special(dest) &&
(dest != univ.party.p_loc) &&
// TODO: Don't hard-code terrain types!
((univ.out[dest.x][dest.y] > 21) || (univ.out[dest.x][dest.y] < 5))) {
univ.party.out_c[num].direction =
set_direction(univ.party.out_c[num].m_loc, dest);

View File

@@ -489,12 +489,15 @@ bool handle_action(location the_point,sf::Event /*event*/) {
working_rect.bottom = spot_hit.y;
if((overall_mode == 1) || (overall_mode == MODE_FILLED_RECT)) {
change_rect_terrain(working_rect,current_terrain_type,20,0);
change_made = true;
}
else if(overall_mode == MODE_HOLLOW_RECT) {
change_rect_terrain(working_rect,current_terrain_type,20,1);
change_made = true;
}
else if(overall_mode == MODE_SET_TOWN_RECT) {
town->in_town_rect = working_rect;
change_made = true;
}
else { // MODE_ROOM_RECT
if(editing_town) {
@@ -520,6 +523,7 @@ bool handle_action(location the_point,sf::Event /*event*/) {
}
if(x < 500)
giveError("You have placed the maximum number of area rectangles (16 in town, 8 outdoors).");
else change_made = true;
}
overall_mode = MODE_DRAWING;
set_cursor(wand_curs);
@@ -895,6 +899,7 @@ bool handle_action(location the_point,sf::Event /*event*/) {
scenario.out_start = spot_hit;
set_cursor(wand_curs);
overall_mode = MODE_DRAWING;
change_made = true;
break;
case MODE_ERASE_CREATURE: //delete monst
for(x = 0; x < 60; x++)

View File

@@ -50,14 +50,6 @@ void Initialize(void);
void Handle_One_Event();
void Handle_Activate();
void Handle_Update();
void handle_file_menu(int item_hit);
void handle_edit_menu(int item_hit);
void handle_scenario_menu(int item_hit);
void handle_town_menu(int item_hit);
void handle_outdoor_menu(int item_hit);
void handle_item_menu(int item_hit);
void handle_monst_menu(int item_hit);
void handle_help_menu(int item_hit);
void Mouse_Pressed();
void close_program();
void ding();
@@ -217,10 +209,14 @@ void Handle_Update() {
restore_cursor();
}
void handle_file_menu(int item_hit) {
void handle_menu_choice(eMenu item_hit) {
bool isEdit = false, isHelp = false;
std::string helpDlog;
fs::path file_to_load;
cKey editKey = {true};
switch(item_hit) {
case 1: // open
case eMenu::NONE: return;
case eMenu::FILE_OPEN:
if(change_made && !save_check("save-before-load"))
break;
file_to_load = nav_get_scenario();
@@ -235,50 +231,50 @@ void handle_file_menu(int item_hit) {
set_up_main_screen();
}
break;
case 2: // save
case eMenu::FILE_SAVE:
town->set_up_lights();
save_scenario();
break;
case 3: // new scen
case eMenu::FILE_NEW:
if(build_scenario()) {
overall_mode = MODE_MAIN_SCREEN;
set_up_main_screen();
}
break;
case 5: // quit
case eMenu::QUIT: // quit
if(!save_check("save-before-quit"))
break;
All_Done = true;
break;
}
}
void handle_edit_menu(int item_hit) {
// Currently, this merely passes appropriate input to the frontmost dialog.
// TODO: Handle edit menu operations when no dialog is onscreen.
cKey key = {true};
switch(item_hit) {
case 1: key.k = key_undo; break;
case 2: key.k = key_redo; break;
case 4: key.k = key_cut; break;
case 5: key.k = key_copy; break;
case 6: key.k = key_paste; break;
case 7: key.k = key_del; break;
case 8: key.k = key_selectall; break;
}
if(!cDialog::sendInput(key)) {
// Handle non-dialog edit operations here.
switch(key.k) {}
}
}
void handle_scenario_menu(int item_hit) {
short i;
fs::path file;
switch(item_hit) {
case 1: // Create new town
case eMenu::EDIT_UNDO:
editKey.k = key_undo;
isEdit = true;
break;
case eMenu::EDIT_REDO:
editKey.k = key_redo;
isEdit = true;
break;
case eMenu::EDIT_CUT:
editKey.k = key_cut;
isEdit = true;
break;
case eMenu::EDIT_COPY:
editKey.k = key_copy;
isEdit = true;
break;
case eMenu::EDIT_PASTE:
editKey.k = key_paste;
isEdit = true;
break;
case eMenu::EDIT_DELETE:
editKey.k = key_del;
isEdit = true;
break;
case eMenu::EDIT_SELECT_ALL:
editKey.k = key_selectall;
isEdit = true;
break;
case eMenu::TOWN_CREATE:
if(change_made) {
giveError("You need to save the changes made to your scenario before you can add a new town.");
return;
@@ -289,36 +285,33 @@ void handle_scenario_menu(int item_hit) {
}
if(new_town(scenario.num_towns))
set_up_main_screen();
change_made = true;
break;
case 3: // Scenario Details
case eMenu::SCEN_DETAILS:
edit_scen_details();
change_made = true;
break;
case 4: // Scenario Intro Text
case eMenu::SCEN_INTRO:
edit_scen_intro();
change_made = true;
break;
case 5: // Set Starting Location
case eMenu::TOWN_START:
set_starting_loc();
change_made = true;
break;
case 6: // Change Password
// if(check_p(user_given_password)) {
// user_given_password = get_password();
// given_password = true;
// }
giveError("Passwords have been disabled; they are no longer necessary.");
break;
case 9: // Edit Special Nodes
case eMenu::SCEN_SPECIALS:
right_sbar->setPosition(0);
start_special_editing(0,0);
break;
case 10: // Edit Scenario Text
case eMenu::SCEN_TEXT:
right_sbar->setPosition(0);
start_string_editing(0,0);
break;
case 11: // Edit Journal Entries
case eMenu::SCEN_JOURNALS:
right_sbar->setPosition(0);
start_string_editing(3,0);
break;
case 12: // Import Town
case eMenu::TOWN_IMPORT:
if(change_made) {
giveError("You need to save the changes made to your scenario before you can add a new town.");
return;
@@ -330,25 +323,30 @@ void handle_scenario_menu(int item_hit) {
redraw_screen();
}
break;
case 13: // Edit Saved Item Rectangles
case eMenu::SCEN_SAVE_ITEM_RECTS:
edit_save_rects();
change_made = true;
break;
case 14: // Edit Horses
case eMenu::SCEN_HORSES:
edit_horses();
change_made = true;
break;
case 15: // Edit Boats
case eMenu::SCEN_BOATS:
edit_boats();
change_made = true;
break;
case 16: // Set Variable Town Entry
case eMenu::TOWN_VARYING:
edit_add_town();
change_made = true;
break;
case 17: // Set Scenario Event Timers
case eMenu::SCEN_TIMERS:
edit_scenario_events();
change_made = true;
break;
case 18: // Edit Item Placement Shortcuts
case eMenu::SCEN_ITEM_SHORTCUTS:
edit_item_placement();
break;
case 19: // Delete Last Town
case eMenu::TOWN_DELETE:
if(change_made) {
giveError("You need to save the changes made to your scenario before you can delete a town.");
return;
@@ -368,142 +366,146 @@ void handle_scenario_menu(int item_hit) {
if(cChoiceDlog("delete-town-confirm", {"okay", "cancel"}).show() == "okay")
delete_last_town();
break;
case 20: // Write Data to Text File
case eMenu::SCEN_DATA_DUMP:
if(cChoiceDlog("data-dump-confirm", {"okay", "cancel"}).show() == "okay")
start_data_dump();
break;
case 21: // Do Full Text Dump
case eMenu::SCEN_TEXT_DUMP:
if(cChoiceDlog("text-dump-confirm", {"okay", "cancel"}).show() == "okay")
scen_text_dump();
redraw_screen();
break;
}
if((item_hit != 18) && (item_hit != 19))
change_made = true;
}
void handle_town_menu(int item_hit) {
short i;
change_made = true;
switch(item_hit) {
case 1:
case eMenu::TOWN_DETAILS:
edit_town_details();
change_made = true;
break;
case 2:
case eMenu::TOWN_WANDERING:
edit_town_wand();
change_made = true;
break;
case 3:
case eMenu::TOWN_BOUNDARIES:
overall_mode = MODE_SET_TOWN_RECT;
mode_count = 2;
set_cursor(topleft_curs);
set_string("Set town boundary","Select upper left corner");
break;
case 4:
case eMenu::FRILL:
frill_up_terrain();
change_made = true;
break;
case 5:
case eMenu::UNFRILL:
unfrill_terrain();
change_made = true;
break;
case 6:
case eMenu::TOWN_AREAS:
edit_roomdescs(true);
change_made = true;
break;
case 8:
case eMenu::TOWN_ITEMS_RANDOM:
if(cChoiceDlog("add-random-items", {"okay", "cancel"}).show() == "cancel")
break;
place_items_in_town();
break; // add random
case 9:
for(i = 0; i < 64; i++)
change_made = true;
break;
case eMenu::TOWN_ITEMS_NOT_PROPERTY:
for(int i = 0; i < 64; i++)
town->preset_items[i].property = 0;
cChoiceDlog("set-not-owned").show();
draw_terrain();
break; // set not prop
case 10:
change_made = true;
break;
case eMenu::TOWN_ITEMS_CLEAR:
if(cChoiceDlog("clear-items-confirm", {"okay", "cancel"}).show() == "cancel")
break;
for(i = 0; i < 64; i++)
for(int i = 0; i < 64; i++)
town->preset_items[i].code = -1;
draw_terrain();
break; // clear all items
case 13:
change_made = true;
break;
case eMenu::TOWN_SPECIALS:
right_sbar->setPosition(0);
start_special_editing(2,0);
break;
case 14:
case eMenu::TOWN_TEXT:
right_sbar->setPosition(0);
start_string_editing(2,0);
break;
case 15:
case eMenu::TOWN_SIGNS:
right_sbar->setPosition(0);
start_string_editing(5,0);
break;
case 16:
case eMenu::TOWN_ADVANCED:
edit_advanced_town();
change_made = true;
break;
case 17:
case eMenu::TOWN_TIMERS:
edit_town_events();
change_made = true;
break;
}
}
void handle_outdoor_menu(int item_hit) {
change_made = true;
switch(item_hit) {
case 1:
case eMenu::OUT_DETAILS:
outdoor_details();
change_made = true;
break;
case 2:
case eMenu::OUT_WANDERING:
edit_out_wand(0);
change_made = true;
break;
case 3:
case eMenu::OUT_ENCOUNTERS:
edit_out_wand(1);
change_made = true;
break;
case 4:
frill_up_terrain();
break;
case 5:
unfrill_terrain();
break;
case 6:
case eMenu::OUT_AREAS:
edit_roomdescs(false);
change_made = true;
break;
case 8:
case eMenu::OUT_START:
overall_mode = MODE_SET_OUT_START;
set_string("Select party starting location.","");
break;
case 11:
case eMenu::OUT_SPECIALS:
right_sbar->setPosition(0);
start_special_editing(1,0);
break;
case 12:
case eMenu::OUT_TEXT:
right_sbar->setPosition(0);
start_string_editing(1,0);
break;
case 13:
case eMenu::OUT_SIGNS:
right_sbar->setPosition(0);
start_string_editing(4,0);
break;
}
}
void handle_help_menu(int item_hit) {
switch(item_hit) {
case 0:
cChoiceDlog("about-scened").show();
case eMenu::ABOUT:
helpDlog = "about-scened";
isHelp = true;
break;
case eMenu::HELP_INDEX:
launchURL("https://calref.net/~sylae/boe-doc/editor/About.html");
break;
case eMenu::HELP_START:
helpDlog = "help-editing";
isHelp = true;
break;
case eMenu::HELP_TEST:
helpDlog = "help-testing";
isHelp = true;
break;
case eMenu::HELP_DIST:
helpDlog = "help-distributing";
isHelp = true;
break;
case eMenu::HELP_CONTEST:
helpDlog = "help-contest";
isHelp = true;
break;
case 1:
cChoiceDlog("help-editing").show();
break; // started
case 2:
cChoiceDlog("help-testing").show();
break; // testing
case 3:
cChoiceDlog("help-distributing").show();
break; // distributing
case 5:
cChoiceDlog("help-contest").show();
break; // contest
}
if(isEdit) {
if(!cDialog::sendInput(editKey)) {
// Handle non-dialog edit operations here.
switch(editKey.k) {}
}
}
if(isHelp)
cChoiceDlog(helpDlog).show();
}
void handle_item_menu(int item_hit) {

View File

@@ -373,14 +373,6 @@
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="875998550">
<reference key="NSMenu" ref="399390342"/>
<string key="NSTitle">Change Password</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="229763992"/>
<reference key="NSMixedImage" ref="909111550"/>
</object>
<object class="NSMenuItem" id="1007446984">
<reference key="NSMenu" ref="399390342"/>
<bool key="NSIsDisabled">YES</bool>
@@ -1383,7 +1375,6 @@
<reference ref="174312674"/>
<reference ref="344591363"/>
<reference ref="580939217"/>
<reference ref="875998550"/>
<reference ref="949025402"/>
<reference ref="72958416"/>
</array>
@@ -1484,11 +1475,6 @@
<reference key="object" ref="799771914"/>
<reference key="parent" ref="399390342"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">808</int>
<reference key="object" ref="875998550"/>
<reference key="parent" ref="399390342"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">809</int>
<reference key="object" ref="1007446984"/>
@@ -1913,7 +1899,6 @@
<string key="805.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="806.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="807.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="808.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="809.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="81.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="811.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>

View File

@@ -13,4 +13,28 @@ void init_menubar();
void update_item_menu();
void shut_down_menus(short mode);
enum class eMenu {
NONE, ABOUT, QUIT, FRILL, UNFRILL,
FILE_NEW, FILE_OPEN, FILE_CLOSE, FILE_SAVE, FILE_REVERT,
EDIT_UNDO, EDIT_REDO, EDIT_CUT, EDIT_COPY, EDIT_PASTE, EDIT_DELETE, EDIT_SELECT_ALL,
HELP_INDEX, HELP_START, HELP_TEST, HELP_DIST, HELP_CONTEST,
// Scenario menu
TOWN_CREATE, SCEN_DETAILS, SCEN_INTRO, TOWN_START,
SCEN_SPECIALS, SCEN_TEXT, SCEN_JOURNALS, TOWN_IMPORT,
SCEN_SAVE_ITEM_RECTS, SCEN_HORSES, SCEN_BOATS,
TOWN_VARYING, SCEN_TIMERS, SCEN_ITEM_SHORTCUTS, TOWN_DELETE,
SCEN_DATA_DUMP, SCEN_TEXT_DUMP,
// Town menu
TOWN_DETAILS, TOWN_WANDERING, TOWN_BOUNDARIES, TOWN_AREAS,
TOWN_ITEMS_RANDOM, TOWN_ITEMS_NOT_PROPERTY, TOWN_ITEMS_CLEAR,
TOWN_SPECIALS, TOWN_TEXT, TOWN_SIGNS, TOWN_ADVANCED, TOWN_TIMERS,
// Outdoors menu
OUT_DETAILS, OUT_WANDERING, OUT_ENCOUNTERS, OUT_AREAS, OUT_START,
OUT_SPECIALS, OUT_TEXT, OUT_SIGNS,
};
void handle_item_menu(int item_hit);
void handle_monst_menu(int item_hit);
void handle_menu_choice(eMenu item_hit);
#endif

View File

@@ -9,6 +9,7 @@
#include "scen.menus.h"
#include <Cocoa/Cocoa.h>
#include "scenario.h"
#include "winutil.h"
using MenuHandle = NSMenu*;
MenuHandle menu_bar_handle;
@@ -18,15 +19,9 @@ MenuHandle file_menu, edit_menu, app_menu, scen_menu, town_menu, out_menu, help_
extern cScenario scenario;
@interface MenuHandler : NSObject
-(void) fileMenu:(id) sender;
-(void) editMenu:(id) sender;
-(void) scenMenu:(id) sender;
-(void) townMenu:(id) sender;
-(void) outMenu:(id) sender;
-(void) menuChoice:(id) sender;
-(void) itemMenu:(id) sender;
-(void) monstMenu:(id) sender;
-(void) helpMenu:(id) sender;
-(void) onlineHelp:(id) sender;
@end
static void setMenuCallback(NSMenuItem* item, id targ, SEL selector, int num) {
@@ -61,26 +56,55 @@ void init_menubar() {
mon_menu[2] = [[menu_bar_handle itemWithTitle: @"M3"] submenu];
mon_menu[3] = [[menu_bar_handle itemWithTitle: @"M4"] submenu];
MenuHandler* handler = [[[MenuHandler alloc] init] retain];
setMenuCallback([app_menu itemWithTitle: @"About BoE Scenario Editor"], handler, @selector(helpMenu:), 0);
setMenuCallback([app_menu itemWithTitle: @"Quit BoE Scenario Editor"], handler, @selector(fileMenu:), 5);
// TODO: Organize file menu function
setMenuCallback([file_menu itemWithTitle: @"New Scenario…"], handler, @selector(fileMenu:), 3);
setMenuCallback([file_menu itemWithTitle: @"Open…"], handler, @selector(fileMenu:), 1);
setMenuCallback([file_menu itemWithTitle: @"Save"], handler, @selector(fileMenu:), 2);
setMenuCallback([help_menu itemAtIndex: 0], handler, @selector(onlineHelp:), 0);
static const eMenu file_choices[] = {
eMenu::FILE_NEW, eMenu::FILE_OPEN, eMenu::NONE, eMenu::FILE_CLOSE, eMenu::FILE_SAVE, eMenu::FILE_REVERT,
};
static const eMenu edit_choices[] = {
eMenu::EDIT_UNDO, eMenu::EDIT_REDO, eMenu::NONE,
eMenu::EDIT_CUT, eMenu::EDIT_COPY, eMenu::EDIT_PASTE, eMenu::EDIT_DELETE, eMenu::EDIT_SELECT_ALL,
};
static const eMenu scen_choices[] = {
eMenu::TOWN_CREATE, eMenu::NONE, eMenu::SCEN_DETAILS, eMenu::SCEN_INTRO, eMenu::TOWN_START, eMenu::NONE, eMenu::NONE,
eMenu::SCEN_SPECIALS, eMenu::SCEN_TEXT, eMenu::SCEN_JOURNALS, eMenu::TOWN_IMPORT, eMenu::SCEN_SAVE_ITEM_RECTS,
eMenu::SCEN_HORSES, eMenu::SCEN_BOATS, eMenu::TOWN_VARYING, eMenu::SCEN_TIMERS, eMenu::SCEN_ITEM_SHORTCUTS,
eMenu::TOWN_DELETE, eMenu::SCEN_DATA_DUMP, eMenu::SCEN_TEXT_DUMP,
};
static const eMenu town_choices[] = {
eMenu::TOWN_DETAILS, eMenu::TOWN_WANDERING, eMenu::TOWN_BOUNDARIES, eMenu::FRILL, eMenu::UNFRILL, eMenu::TOWN_AREAS,
eMenu::NONE, eMenu::TOWN_ITEMS_RANDOM, eMenu::TOWN_ITEMS_NOT_PROPERTY, eMenu::TOWN_ITEMS_CLEAR, eMenu::NONE, eMenu::NONE,
eMenu::TOWN_SPECIALS, eMenu::TOWN_TEXT, eMenu::TOWN_SIGNS, eMenu::TOWN_ADVANCED, eMenu::TOWN_TIMERS,
};
static const eMenu out_choices[] = {
eMenu::OUT_DETAILS, eMenu::OUT_WANDERING, eMenu::OUT_ENCOUNTERS, eMenu::FRILL, eMenu::UNFRILL, eMenu::OUT_AREAS,
eMenu::NONE, eMenu::OUT_START, eMenu::NONE, eMenu::NONE,
eMenu::OUT_SPECIALS, eMenu::OUT_TEXT, eMenu::OUT_SIGNS,
};
static const eMenu help_choices[] = {
eMenu::HELP_INDEX, eMenu::NONE, eMenu::HELP_START, eMenu::HELP_TEST, eMenu::HELP_DIST, eMenu::NONE, eMenu::HELP_CONTEST,
};
for(int i = 0; i < [edit_menu numberOfItems]; i++)
setMenuCallback([edit_menu itemAtIndex: i], handler, @selector(editMenu:), i + 1);
for(int i = 0; i < [scen_menu numberOfItems]; i++)
setMenuCallback([scen_menu itemAtIndex: i], handler, @selector(scenMenu:), i + 1);
for(int i = 0; i < [town_menu numberOfItems]; i++)
setMenuCallback([town_menu itemAtIndex: i], handler, @selector(townMenu:), i + 1);
for(int i = 0; i < [out_menu numberOfItems]; i++)
setMenuCallback([out_menu itemAtIndex: i], handler, @selector(outMenu:), i + 1);
for(int i = 2; i < [help_menu numberOfItems]; i++)
setMenuCallback([help_menu itemAtIndex: i], handler, @selector(helpMenu:), i - 1);
// TODO: Item and monster menus
MenuHandler* handler = [[[MenuHandler alloc] init] retain];
setMenuCallback([app_menu itemWithTitle: @"About BoE Scenario Editor"], handler, @selector(menuChoice:), int(eMenu::ABOUT));
setMenuCallback([app_menu itemWithTitle: @"Quit BoE Scenario Editor"], handler, @selector(menuChoice:), int(eMenu::QUIT));
int i = 0;
for(eMenu opt : file_choices)
setMenuCallback([file_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : edit_choices)
setMenuCallback([edit_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : scen_choices)
setMenuCallback([scen_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : town_choices)
setMenuCallback([town_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : out_choices)
setMenuCallback([out_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : help_choices)
setMenuCallback([help_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
}
// mode 0 - initial shut down, 1 - no town, 2 - no out, 3 - no town or out 4 - all menus on
@@ -170,38 +194,9 @@ void update_item_menu() {
}
void handle_file_menu(int item_hit);
void handle_edit_menu(int item_hit);
void handle_scenario_menu(int item_hit);
void handle_town_menu(int item_hit);
void handle_outdoor_menu(int item_hit);
void handle_help_menu(int item_hit);
void handle_item_menu(int item_hit);
void handle_monst_menu(int item_hit);
@implementation MenuHandler
-(void) fileMenu:(id) sender {
handle_file_menu([[sender representedObject] intValue]);
}
// TODO: Implement edit menu (much work to be done here!)
// TODO: Fix edit menu being disabled while a modal dialog is onscreen.
// This means setting autoenable to false for the Edit menu and finding a
// way to make the menuitems work instead of just doing nothing.
-(void) editMenu:(id) sender {
handle_edit_menu([[sender representedObject] intValue]);
}
-(void) scenMenu:(id) sender {
handle_scenario_menu([[sender representedObject] intValue]);
}
-(void) townMenu:(id) sender {
handle_town_menu([[sender representedObject] intValue]);
}
-(void) outMenu:(id) sender {
handle_outdoor_menu([[sender representedObject] intValue]);
-(void) menuChoice:(id) sender {
handle_menu_choice(eMenu([[sender representedObject] intValue]));
}
// TODO: Monster and item menus
@@ -212,13 +207,4 @@ void handle_monst_menu(int item_hit);
-(void) monstMenu:(id) sender {
(void) sender; // Suppress "unused parameter" warning
}
-(void) helpMenu:(id) sender {
handle_help_menu([[sender representedObject] intValue]);
}
-(void) onlineHelp:(id) sender {
(void) sender;
[[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: @"https://calref.net/~sylae/boe-doc/editor/About.html"]];
}
@end

View File

@@ -1,5 +1,6 @@
#include "scen.menus.h"
#include <map>
#include <SFML/Graphics/RenderWindow.hpp>
#include "Resource.h"
#include "scenario.h"
@@ -25,9 +26,19 @@ extern sf::RenderWindow mainPtr;
extern cScenario scenario;
LONG_PTR mainProc;
HMENU menuHandle = NULL;
std::map<int,eMenu> menuChoices;
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam);
void setMenuCommand(HMENU& menu, int i, eMenu cmd) {
MENUITEMINFOA item;
item.cbSize = sizeof(MENUITEMINFOA);
item.fMask = MIIM_ID | MIIM_FTYPE;
GetMenuItemInfoA(file_menu, i++, true, &item);
if(info.fType == MFT_SEPARATOR) return;
menuChoices[item.wID] = cmd;
}
void init_menubar() {
HWND winHandle = mainPtr.getSystemHandle();
if(winHandle == NULL) return;
@@ -43,6 +54,64 @@ void init_menubar() {
double usableHeight = sz.y - menubarHeight;
sf::View view(sf::FloatRect(0, 0, sz.x, usableHeight));
mainPtr.setView(view);
// And now initialize the mapping from Windows menu commands to eMenu constants
static bool inited = false;
if(inited) return;
inited = true;
static const eMenu file_choices[] = {
eMenu::FILE_NEW, eMenu::FILE_OPEN, eMenu::NONE, eMenu::FILE_CLOSE, eMenu::FILE_SAVE, eMenu::FILE_REVERT, eMenu::NONE, eMenu::QUIT,
};
static const eMenu edit_choices[] = {
eMenu::EDIT_UNDO, eMenu::EDIT_REDO, eMenu::NONE,
eMenu::EDIT_CUT, eMenu::EDIT_COPY, eMenu::EDIT_PASTE, eMenu::EDIT_DELETE, eMenu::EDIT_SELECT_ALL,
};
static const eMenu scen_choices[] = {
eMenu::TOWN_CREATE, eMenu::NONE, eMenu::SCEN_DETAILS, eMenu::SCEN_INTRO, eMenu::TOWN_START, eMenu::NONE, eMenu::NONE,
eMenu::SCEN_SPECIALS, eMenu::SCEN_TEXT, eMenu::SCEN_JOURNALS, eMenu::TOWN_IMPORT, eMenu::SCEN_SAVE_ITEM_RECTS,
eMenu::SCEN_HORSES, eMenu::SCEN_BOATS, eMenu::TOWN_VARYING, eMenu::SCEN_TIMERS, eMenu::SCEN_ITEM_SHORTCUTS,
eMenu::TOWN_DELETE, eMenu::SCEN_DATA_DUMP, eMenu::SCEN_TEXT_DUMP,
};
static const eMenu town_choices[] = {
eMenu::TOWN_DETAILS, eMenu::TOWN_WANDERING, eMenu::TOWN_BOUNDARIES, eMenu::FRILL, eMenu::UNFRILL, eMenu::TOWN_AREAS,
eMenu::NONE, eMenu::TOWN_ITEMS_RANDOM, eMenu::TOWN_ITEMS_NOT_PROPERTY, eMenu::TOWN_ITEMS_CLEAR, eMenu::NONE, eMenu::NONE,
eMenu::TOWN_SPECIALS, eMenu::TOWN_TEXT, eMenu::TOWN_SIGNS, eMenu::TOWN_ADVANCED, eMenu::TOWN_TIMERS,
};
static const eMenu out_choices[] = {
eMenu::OUT_DETAILS, eMenu::OUT_WANDERING, eMenu::OUT_ENCOUNTERS, eMenu::FRILL, eMenu::UNFRILL, eMenu::OUT_AREAS,
eMenu::NONE, eMenu::OUT_START, eMenu::NONE, eMenu::NONE,
eMenu::OUT_SPECIALS, eMenu::OUT_TEXT, eMenu::OUT_SIGNS,
};
static const eMenu help_choices[] = {
eMenu::HELP_INDEX, eMenu::ABOUT, eMenu::NONE, eMenu::HELP_START, eMenu::HELP_TEST, eMenu::HELP_DIST,
};
HMENU file_menu = GetSubMenu(menuHandle, FILE_MENU_POS);
HMENU edit_menu = GetSubMenu(menuHandle, EDIT_MENU_POS);
HMENU scen_menu = GetSubMenu(menuHandle, SCEN_MENU_POS);
HMENU town_menu = GetSubMenu(menuHandle, TOWN_MENU_POS);
HMENU out_menu = GetSubMenu(menuHandle, OUT_MENU_POS);
HMENU help_menu = GetSubMenu(menuHandle, HELP_MENU_POS);
int i = 0;
for(eMenu opt : file_choices)
setMenuCommand(file_menu, i++, opt);
i = 0;
for(eMenu opt : edit_choices)
setMenuCommand(edit_menu, i++, opt);
i = 0;
for(eMenu opt : scen_choices)
setMenuCommand(scen_menu, i++, opt);
i = 0;
for(eMenu opt : town_choices)
setMenuCommand(town_menu, i++, opt);
i = 0;
for(eMenu opt : out_choices)
setMenuCommand(out_menu, i++, opt);
i = 0;
for(eMenu opt : help_choices)
setMenuCommand(help_menu, i++, opt);
}
void update_item_menu() {
@@ -158,79 +227,7 @@ LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lPara
handle_item_menu(cmd - 10000);
} else if(cmd >= 20000 && cmd < 30000) { // Monster menus
handle_monst_menu(cmd - 20000);
} else switch(cmd) {
// File menu
case IDM_FILE_NEW: handle_file_menu(3); break;
case IDM_FILE_OPEN: handle_file_menu(1); break;
case IDM_FILE_CLOSE: break;
case IDM_FILE_SAVE: handle_file_menu(2); break;
case IDM_FILE_REVERT: break;
case IDM_FILE_QUIT: handle_file_menu(5); break;
// Edit menu
case IDM_EDIT_UNDO: handle_edit_menu(1); break;
case IDM_EDIT_REDO: handle_edit_menu(2); break;
case IDM_EDIT_CUT: handle_edit_menu(4); break;
case IDM_EDIT_COPY: handle_edit_menu(5); break;
case IDM_EDIT_PASTE: handle_edit_menu(6); break;
case IDM_EDIT_DELETE: handle_edit_menu(7); break;
case IDM_EDIT_SELECT: handle_edit_menu(8); break;
// Scenario menu
case IDM_SCEN_NEW_TOWN: handle_scenario_menu(1); break;
case IDM_SCEN_DETAILS: handle_scenario_menu(3); break;
case IDM_SCEN_INTRO: handle_scenario_menu(4); break;
case IDM_SCEN_START: handle_scenario_menu(4); break;
case IDM_SCEN_PASSWORD: break;
// Scenario menu (advanced)
case IDM_SCEN_ADV_SPECIALS: handle_scenario_menu(9); break;
case IDM_SCEN_ADV_TEXT: handle_scenario_menu(10); break;
case IDM_SCEN_ADV_JOURNAL: handle_scenario_menu(11); break;
case IDM_SCEN_ADV_IMPORT_TOWN: handle_scenario_menu(12); break;
case IDM_SCEN_ADV_SAVE_RECTS: handle_scenario_menu(13); break;
case IDM_SCEN_ADV_HORSES: handle_scenario_menu(14); break;
case IDM_SCEN_ADV_BOATS: handle_scenario_menu(15); break;
case IDM_SCEN_ADV_TOWN_VARY: handle_scenario_menu(16); break;
case IDM_SCEN_ADV_EVENTS: handle_scenario_menu(17); break;
case IDM_SCEN_ADV_SHORTCUTS: handle_scenario_menu(18); break;
case IDM_SCEN_ADV_DELETE_TOWN: handle_scenario_menu(19); break;
case IDM_SCEN_ADV_DATA_DUMP: handle_scenario_menu(20); break;
case IDM_SCEN_ADV_TEXT_DUMP: handle_scenario_menu(21); break;
// Town menu
case IDM_TOWN_DETAILS: handle_town_menu(1); break;
case IDM_TOWN_WANDER: handle_town_menu(2); break;
case IDM_TOWN_BOUNDS: handle_town_menu(3); break;
case IDM_TOWN_FRILL: handle_town_menu(4); break;
case IDM_TOWN_UNFRILL: handle_town_menu(5); break;
case IDM_TOWN_AREAS: handle_town_menu(6); break;
case IDM_TOWN_RANDOM_ITEMS: handle_town_menu(8); break;
case IDM_TOWN_NOT_PROPERTY: handle_town_menu(9); break;
case IDM_TOWN_CLEAR_ITEMS: handle_town_menu(10); break;
// Town menu (advanced)
case IDM_TOWN_ADV_SPECIALS: handle_town_menu(13); break;
case IDM_TOWN_ADV_TEXT: handle_town_menu(14); break;
case IDM_TOWN_ADV_SIGNS: handle_town_menu(15); break;
case IDM_TOWN_ADV_DETAILS: handle_town_menu(16); break;
case IDM_TOWN_ADV_EVENTS: handle_town_menu(17); break;
case IDM_TOWN_ADV_REPORT: break;
// Outdoors menu
case IDM_OUT_DETAILS: handle_outdoor_menu(1); break;
case IDM_OUT_WANDER: handle_outdoor_menu(2); break;
case IDM_OUT_ENCOUNTER: handle_outdoor_menu(3); break;
case IDM_OUT_FRILL: handle_outdoor_menu(4); break;
case IDM_OUT_UNFRILL: handle_outdoor_menu(5); break;
case IDM_OUT_AREAS: handle_outdoor_menu(6); break;
case IDM_OUT_START: handle_outdoor_menu(8); break;
// Outdoors menu (advanced)
case IDM_OUT_ADV_SPECIALS: handle_outdoor_menu(11); break;
case IDM_OUT_ADV_TEXT: handle_outdoor_menu(12); break;
case IDM_OUT_ADV_SIGNS: handle_outdoor_menu(13); break;
case IDM_OUT_ADV_REPORT: break;
// Help menu
case IDM_HELP_INDEX: ShellExecuteA(NULL, "open", "https://calref.net/~sylae/boe-doc/editor/About.html", NULL, NULL, SW_SHOWNORMAL); break;
case IDM_HELP_ABOUT: handle_help_menu(0); break;
case IDM_HELP_START: handle_help_menu(1); break;
case IDM_HELP_TEST: handle_help_menu(2); break;
case IDM_HELP_DISTRIBUTE: handle_help_menu(3); break;
}
} else handle_menu_choice(menuChoices[message]);
} else if(message == WM_SETCURSOR) {
// Windows resets the cursor to an arrow whenever the mouse moves, unless we do this.
// Note: By handling this message, sf::Window::setMouseCursorVisible() will NOT work.

View File

@@ -20,6 +20,7 @@ void makeFrontWindow(sf::Window& win);
void setWindowFloating(sf::Window& win, bool floating);
void init_fileio();
void launchURL(std::string url);
fs::path nav_get_party();
fs::path nav_put_party(fs::path def = "");

View File

@@ -145,6 +145,10 @@ void beep() {
NSBeep();
}
void launchURL(std::string url) {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithCString:url.c_str() encoding:NSUTF8StringEncoding]]];
}
int getMenubarHeight() {
// Mac menubar isn't in the window, so we return 0 here.
return 0;

View File

@@ -213,6 +213,10 @@ void beep() {
MessageBeep(-1);
}
void launchURL(std::string url) {
ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
}
// TODO: Implement modal session.
// It seems that Windows doesn't have anything similar to the Mac modal session, so I might have to somehow simulate it myself.
void ModalSession::pumpEvents() {