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

- Also disable edit menus when no party loaded and fix item menus not being populated if the party is in a scenario
This commit is contained in:
2015-01-05 17:17:34 -05:00
parent dfe54fd0a2
commit 04b9aec921
7 changed files with 148 additions and 159 deletions

View File

@@ -74,12 +74,8 @@ void Handle_One_Event();
void Handle_Activate();
void Handle_Update();
void Mouse_Pressed();
void handle_help_menu(int item_hit);
void handle_file_menu(int item_hit);
void handle_edit_menus(int item_hit);
bool verify_restore_quit(bool mode);
void set_up_apple_events();
void handle_item_menu(int item_hit);
//item_record_type convert_item (short_item_record_type s_item);
extern bool cur_scen_is_mac;
extern fs::path progDir;
@@ -192,33 +188,28 @@ void Mouse_Pressed() {
All_Done = verify_restore_quit(false);
}
void handle_help_menu(int item_hit) {
//char desk_acc_name[256];
//short desk_acc_num;
switch(item_hit) {
case 1:
cChoiceDlog("about-pced").show();
break;
default:
//GetItem (apple_menu,item_hit,desk_acc_name);
//desk_acc_num = OpenDeskAcc(desk_acc_name);
break;
}
static void display_strings(short nstr, pic_num_t pic) {
cStrDlog display_strings(get_str("pcedit", nstr), "", "Editing party", pic, PIC_DLOG);
display_strings.setSound(57);
display_strings.show();
}
void handle_file_menu(int item_hit) {
void handle_menu_choice(eMenu item_hit) {
int i,j,k;
fs::path file;
switch(item_hit) {
case 1://save
case eMenu::NONE: break;
case eMenu::ABOUT:
cChoiceDlog("about-pced").show();
break;
case eMenu::FILE_SAVE:
save_party(file_in_mem, univ);
break;
case 2://save as
case eMenu::FILE_SAVE_AS:
file = nav_put_party();
if(!file.empty()) save_party(file, univ);
break;
case 3://open
case eMenu::FILE_OPEN:
if(verify_restore_quit(true)){
file = nav_get_party();
if(!file.empty()) {
@@ -226,45 +217,24 @@ void handle_file_menu(int item_hit) {
file_in_mem = file;
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();
}
break;
// TODO: Implement these two
case 4: //close
break;
case 5: //revert;
break;
case 7://quit
case eMenu::QUIT:
All_Done = verify_restore_quit(false);
break;
}
}
static void display_strings(short nstr, pic_num_t pic) {
cStrDlog display_strings(get_str("pcedit", nstr), "", "Editing party", pic, PIC_DLOG);
display_strings.setSound(57);
display_strings.show();
}
void handle_edit_menus(int item_hit) {
short i,j,k;
if(file_in_mem.empty()) {
display_strings(5, 7);
return;
}
switch(item_hit) {
case 1:
case eMenu::EDIT_GOLD:
edit_gold_or_food(0);
break;
case 2:
case eMenu::EDIT_FOOD:
edit_gold_or_food(1);
break;
case 103:
case eMenu::LEAVE_TOWN:
if(univ.party.is_split() > 0) {
cChoiceDlog("reunite-first").show();
break;
@@ -273,7 +243,7 @@ void handle_edit_menus(int item_hit) {
leave_town();
break;
case 16:
case eMenu::REUNITE_PARTY:
if(univ.party.is_split() == 0) {
cChoiceDlog("not-split").show();
break;
@@ -286,29 +256,29 @@ void handle_edit_menus(int item_hit) {
break;
case 104:
case eMenu::RESET_TOWNS:
display_strings(20,7);
for(i = 0; i < 4; i++)
univ.party.creature_save[i].which_town = 200;
break;
case 5: // damage
case eMenu::HEAL_DAMAGE:
display_strings(1,15);
for(i = 0; i < 6; i++)
univ.party[i].cur_health = univ.party[i].max_health;
break;
case 6: // spell pts
case eMenu::RESTORE_MANA:
display_strings(2,15);
for(i = 0; i < 6; i++)
univ.party[i].cur_sp = univ.party[i].max_sp;
break;
case 7: // raise dead
case eMenu::RAISE_DEAD:
display_strings(3,15);
for(i = 0; i < 6; i++)
if(univ.party[i].main_status == eMainStatus::DEAD || univ.party[i].main_status == eMainStatus::DUST ||
univ.party[i].main_status == eMainStatus::STONE)
univ.party[i].main_status = eMainStatus::ALIVE;
break;
case 8: // conditions
case eMenu::CURE_CONDITIONS:
display_strings(4,15);
for(i = 0; i < 6; i++) {
univ.party[i].status[eStatus::POISON] = 0;
@@ -323,7 +293,7 @@ void handle_edit_menus(int item_hit) {
}
break;
case 108:
case eMenu::LEAVE_SCENARIO:
if(!party_in_scen) {
display_strings(25,15);
break;
@@ -332,20 +302,20 @@ void handle_edit_menus(int item_hit) {
break;
remove_party_from_scen();
break;
case 3:
case eMenu::EDIT_ALCHEMY:
display_alchemy(true);
break;
case 17: // all property
case eMenu::OWN_VEHICLES:
display_strings(6,7);
for(i = 0; i < 30; i++) {
univ.party.boats[i].property = false;
univ.party.horses[i].property = false;
}
break;
case 101: // edit day
case eMenu::EDIT_DAY:
edit_day();
break;
case 105: // out maps
case eMenu::ADD_OUT_MAPS:
if(!party_in_scen) {
display_strings(25,15);
break;
@@ -356,7 +326,7 @@ void handle_edit_menus(int item_hit) {
for(k = 0; k < 48; k++)
univ.out_maps[i][j][k] = 255;
break;
case 106: // town maps
case eMenu::ADD_TOWN_MAPS:
if(!party_in_scen) {
display_strings(25,15);
break;
@@ -367,24 +337,21 @@ void handle_edit_menus(int item_hit) {
for(k = 0; k < 64; k++)
univ.town_maps[i][j][k] = 255;
break;
case 10:
case eMenu::EDIT_MAGE:
display_pc(current_active_pc,0,0);
break;
case 11:
case eMenu::EDIT_PRIEST:
display_pc(current_active_pc,1,0);
break;
case 12:
case eMenu::EDIT_TRAITS:
pick_race_abil(&univ.party[current_active_pc],0);
break;
case 13:
case eMenu::EDIT_SKILLS:
spend_xp(current_active_pc,1,0);
break;
case 14:
case eMenu::EDIT_XP:
edit_xp(&univ.party[current_active_pc]);
break;
case 109:
// TODO: Implement "Set SDF"
break;;
}
}
@@ -443,11 +410,6 @@ void handle_edit_menus(int item_hit) {
// TODO: Let this take the item directly instead of the index
void handle_item_menu(int item_hit) {
cItemRec store_i;
if(file_in_mem.empty()) {
display_strings(5,7);
return;
}
store_i = univ.scenario.scen_items[item_hit];
store_i.ident = true;
give_to_pc(current_active_pc,store_i,false);

View File

@@ -13,4 +13,19 @@ void init_menubar();
void update_item_menu();
void menu_activate();
enum class eMenu {
NONE, ABOUT, QUIT,
FILE_OPEN, FILE_CLOSE, FILE_SAVE, FILE_SAVE_AS, FILE_REVERT, HELP_INDEX,
// Edit Party menu
EDIT_GOLD, EDIT_FOOD, EDIT_ALCHEMY,
HEAL_DAMAGE, RESTORE_MANA, RAISE_DEAD, CURE_CONDITIONS,
EDIT_MAGE, EDIT_PRIEST, EDIT_TRAITS, EDIT_SKILLS, EDIT_XP,
REUNITE_PARTY, OWN_VEHICLES,
// Scenario Edit menu
EDIT_DAY, LEAVE_TOWN, RESET_TOWNS, ADD_OUT_MAPS, ADD_TOWN_MAPS, LEAVE_SCENARIO, SET_SDF,
};
void handle_item_menu(int item_hit);
void handle_menu_choice(eMenu item_hit);
#endif

View File

@@ -17,11 +17,6 @@
using MenuHandle = NSMenu*;
extern void handle_help_menu(int item_hit);
extern void handle_file_menu(int item_hit);
extern void handle_edit_menus(int item_hit);
extern void handle_item_menu(int item_hit);
extern cUniverse univ;
extern fs::path file_in_mem;
extern bool scen_items_loaded;
@@ -29,10 +24,8 @@ MenuHandle menu_bar_handle;
MenuHandle apple_menu, file_menu, reg_menu, extra_menu, items_menu[4];
@interface MenuHandler : NSObject
-(void) fileMenu:(id) sender;
-(void) editMenu:(id) sender;
-(void) itemMenu:(id) sender;
-(void) helpMenu:(id) sender;
-(void) menuChoice:(id) sender;
@end
@interface ItemWrapper : NSObject
@@ -65,31 +58,50 @@ void init_menubar() {
items_menu[2] = [[menu_bar_handle itemWithTitle: @"Items 3"] submenu];
items_menu[3] = [[menu_bar_handle itemWithTitle: @"Items 4"] submenu];
MenuHandler* handler = [[[MenuHandler alloc] init] retain];
setMenuCallback([apple_menu itemWithTitle: @"About BoE Character Editor"], handler, @selector(helpMenu:), 1);
setMenuCallback([apple_menu itemWithTitle: @"Quit BoE Character Editor"], handler, @selector(fileMenu:), 7);
// TODO: Organize the file menu handling function
setMenuCallback([file_menu itemWithTitle: @"Save"], handler, @selector(fileMenu:), 1);
setMenuCallback([file_menu itemWithTitle: @"Save As…"], handler, @selector(fileMenu:), 2);
setMenuCallback([file_menu itemWithTitle: @"Open…"], handler, @selector(fileMenu:), 3);
setMenuCallback([file_menu itemWithTitle: @"Close"], handler, @selector(fileMenu:), 4);
setMenuCallback([file_menu itemWithTitle: @"Revert to Saved"], handler, @selector(fileMenu:), 5);
static const eMenu file_choices[] = {
eMenu::FILE_OPEN, eMenu::FILE_CLOSE, eMenu::NONE, eMenu::FILE_SAVE, eMenu::FILE_SAVE_AS, eMenu::FILE_REVERT,
};
static const eMenu party_choices[] = {
eMenu::EDIT_GOLD, eMenu::EDIT_FOOD, eMenu::EDIT_ALCHEMY, eMenu::NONE,
eMenu::HEAL_DAMAGE, eMenu::RESTORE_MANA, eMenu::RAISE_DEAD, eMenu::CURE_CONDITIONS, eMenu::NONE,
eMenu::EDIT_MAGE, eMenu::EDIT_PRIEST, eMenu::EDIT_TRAITS, eMenu::EDIT_SKILLS, eMenu::EDIT_XP, eMenu::NONE,
eMenu::REUNITE_PARTY, eMenu::OWN_VEHICLES,
};
static const eMenu scen_choices[] = {
eMenu::EDIT_DAY, eMenu::NONE, eMenu::LEAVE_TOWN, eMenu::RESET_TOWNS, eMenu::ADD_OUT_MAPS, eMenu::ADD_TOWN_MAPS,
eMenu::NONE, eMenu::LEAVE_SCENARIO, eMenu::SET_SDF,
};
for(int i = 0; i < [reg_menu numberOfItems]; i++)
setMenuCallback([reg_menu itemAtIndex: i], handler, @selector(editMenu:), i + 1);
for(int i = 0; i < [extra_menu numberOfItems]; i++)
setMenuCallback([extra_menu itemAtIndex: i], handler, @selector(editMenu:), i + 101);
MenuHandler* handler = [[[MenuHandler alloc] init] retain];
setMenuCallback([apple_menu itemWithTitle: @"About BoE Character Editor"], handler, @selector(menuChoice:), int(eMenu::ABOUT));
setMenuCallback([apple_menu itemWithTitle: @"Quit BoE Character 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 : party_choices)
setMenuCallback([reg_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
i = 0;
for(eMenu opt : scen_choices)
setMenuCallback([extra_menu itemAtIndex: i++], handler, @selector(menuChoice:), int(opt));
update_item_menu();
menu_activate();
}
void menu_activate() {
if(file_in_mem.empty())
if(file_in_mem.empty()) {
for(int i = 3; i < [file_menu numberOfItems]; i++)
[[file_menu itemAtIndex: i] setEnabled: NO];
else for(int i = 3; i < [file_menu numberOfItems]; i++)
[[file_menu itemAtIndex: i] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Edit Party"] setEnabled: NO];
[[menu_bar_handle itemWithTitle: @"Scenario Edit"] setEnabled: NO];
} else {
for(int i = 3; i < [file_menu numberOfItems]; i++)
[[file_menu itemAtIndex: i] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Edit Party"] setEnabled: YES];
[[menu_bar_handle itemWithTitle: @"Scenario Edit"] setEnabled: YES];
}
}
void update_item_menu() {
@@ -112,14 +124,6 @@ void update_item_menu() {
}
@implementation MenuHandler
-(void) fileMenu:(id) sender {
handle_file_menu([[sender representedObject] shortValue]);
}
-(void) editMenu:(id) sender {
handle_edit_menus([[sender representedObject] shortValue]);
}
-(void) itemMenu:(id) sender {
ItemWrapper* item = [sender representedObject];
cItemRec& theItem = [item item];
@@ -131,12 +135,10 @@ void update_item_menu() {
}
}
-(void) helpMenu:(id) sender {
int i = [[sender representedObject] intValue];
if(i == 0); // TODO: "BoE Character Editor Help"
else if(i == 1) handle_help_menu(i);
-(void) menuChoice:(id) sender {
eMenu opt = eMenu([[sender representedObject] intValue]);
handle_menu_choice(opt);
}
@end
@implementation ItemWrapper {

View File

@@ -1,5 +1,6 @@
#include "pc.menus.h"
#include <map>
#include <SFML/Graphics/RenderWindow.hpp>
#include "Resource.h"
#include "universe.h"
@@ -24,9 +25,19 @@ extern bool scen_items_loaded;
extern fs::path file_in_mem;
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(menu, i++, true, &item);
if(item.fType == MFT_SEPARATOR) return;
menuChoices[item.wID] = cmd;
}
void init_menubar() {
HWND winHandle = mainPtr.getSystemHandle();
if(winHandle == NULL) return;
@@ -42,6 +53,46 @@ 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_OPEN, eMenu::FILE_CLOSE, eMenu::NONE, eMenu::FILE_SAVE, eMenu::FILE_SAVE_AS, eMenu::FILE_REVERT, eMenu::NONE, eMenu::QUIT,
};
static const eMenu party_choices[] = {
eMenu::EDIT_GOLD, eMenu::EDIT_FOOD, eMenu::EDIT_ALCHEMY, eMenu::NONE,
eMenu::HEAL_DAMAGE, eMenu::RESTORE_MANA, eMenu::RAISE_DEAD, eMenu::CURE_CONDITIONS, eMenu::NONE,
eMenu::EDIT_MAGE, eMenu::EDIT_PRIEST, eMenu::EDIT_TRAITS, eMenu::EDIT_SKILLS, eMenu::EDIT_XP, eMenu::NONE,
eMenu::REUNITE_PARTY, eMenu::OWN_VEHICLES,
};
static const eMenu scen_choices[] = {
eMenu::EDIT_DAY, eMenu::NONE, eMenu::LEAVE_TOWN, eMenu::RESET_TOWNS, eMenu::ADD_OUT_MAPS, eMenu::ADD_TOWN_MAPS,
eMenu::NONE, eMenu::LEAVE_SCENARIO, eMenu::SET_SDF,
};
static const eMenu help_choices[] = {
eMenu::ABOUT,
};
HMENU file_menu = GetSubMenu(menuHandle, FILE_MENU_POS);
HMENU party_menu = GetSubMenu(menuHandle, PARTY_MENU_POS);
HMENU scen_menu = GetSubMenu(menuHandle, SCEN_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 : party_choices)
setMenuCommand(party_menu, i++, opt);
i = 0;
for(eMenu opt : scen_choices)
setMenuCommand(scen_menu, i++, opt);
i = 0;
for(eMenu opt : help_choices)
setMenuCommand(help_menu, i++, opt);
}
void update_item_menu() {
@@ -75,11 +126,6 @@ void menu_activate() {
DrawMenuBar(mainPtr.getSystemHandle());
}
void handle_help_menu(int item_hit);
void handle_file_menu(int item_hit);
void handle_edit_menus(int item_hit);
void handle_item_menu(int item_hit);
#include "cursors.h"
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
@@ -87,40 +133,7 @@ LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lPara
int cmd = LOWORD(wParam);
if(cmd >= 1000) { // Item menus
handle_item_menu(cmd - 1000);
} else switch(cmd) {
// File menu
case IDM_FILE_OPEN: handle_file_menu(3); break;
case IDM_FILE_CLOSE: handle_file_menu(4); break;
case IDM_FILE_SAVE: handle_file_menu(1); break;
case IDM_FILE_SAVE_AS: handle_file_menu(2); break;
case IDM_FILE_REVERT: handle_file_menu(5); break;
case IDM_FILE_QUIT: handle_file_menu(7); break;
// Edit Party menu
case IDM_PARTY_GOLD: handle_edit_menus(1); break;
case IDM_PARTY_FOOD: handle_edit_menus(2); break;
case IDM_PARTY_ALCHEMY: handle_edit_menus(3); break;
case IDM_PARTY_DAMAGE: handle_edit_menus(5); break;
case IDM_PARTY_MANA: handle_edit_menus(6); break;
case IDM_PARTY_DEAD: handle_edit_menus(7); break;
case IDM_PARTY_CONDITIONS: handle_edit_menus(8); break;
case IDM_PARTY_REUNITE: handle_edit_menus(10); break;
case IDM_PARTY_VEHICLES: handle_edit_menus(11); break;
case IDM_PARTY_MAGE: handle_edit_menus(13); break;
case IDM_PARTY_PRIEST: handle_edit_menus(14); break;
case IDM_PARTY_TRAITS: handle_edit_menus(15); break;
case IDM_PARTY_SKILLS: handle_edit_menus(16); break;
case IDM_PARTY_XP: handle_edit_menus(17); break;
// Scenario Editing menu
case IDM_SCEN_DAY: handle_edit_menus(101); break;
case IDM_SCEN_LEAVE_TOWN: handle_edit_menus(103); break;
case IDM_SCEN_TOWN_RESET: handle_edit_menus(104); break;
case IDM_SCEN_TOWN_MAP: handle_edit_menus(105); break;
case IDM_SCEN_OUT_MAP: handle_edit_menus(106); break;
case IDM_SCEN_LEAVE: handle_edit_menus(108); break;
case IDM_SCEN_SDF: handle_edit_menus(109); break;
// Help menu
case IDM_HELP: handle_help_menu(1);
}
} else handle_menu_choice(menuChoices[cmd]);
} 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

@@ -211,15 +211,6 @@ void shut_down_menus(short mode) {
DrawMenuBar(mainPtr.getSystemHandle());
}
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);
#include "cursors.h"
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {

View File

@@ -836,6 +836,12 @@ bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bo
}
if(in_scen) {
fs::path path;
path = progDir/"Blades of Exile Scenarios"/univ.party.scen_name;
if(!load_scenario(path, univ.scenario))
return false;
if(town_restore) {
// Load town data
std::istream& fin = partyIn.getFile("save/town.txt");