This includes the following changes (mostly related to the above): - Move loc_compare functor to location.hpp - Add reattach() function to rebind a town or outdoor section to a different scenario object. (I don't think this is strictly necessary, as the scenario reference is only used in limited situations in the game itself, not in the editor, but it's better not to keep a reference to freed memory around when importing a town or sector from another scenario, even if the reference is never accessed.) - Fix imported towns not being officially "loaded" until you explicitly use Load a New Town to reload them - Fix Choose button in Load New Sector dialog - More functions in the vector2d implementation
233 lines
8.4 KiB
C++
233 lines
8.4 KiB
C++
|
|
#include "scen.menus.hpp"
|
|
#include <map>
|
|
#include <SFML/Graphics/RenderWindow.hpp>
|
|
#include "scenresource.h"
|
|
#include "scenario.hpp"
|
|
#include "winutil.hpp"
|
|
#include "menu_accel.win.hpp"
|
|
|
|
// Include this last because some #defines in the Windows headers cause compile errors in my headers.
|
|
// Fortunately they're on symbols not used in this file, so this should work.
|
|
#include <Windows.h>
|
|
#undef HELP_INDEX // Except this one.
|
|
|
|
// This is the index of each menu on the menubar
|
|
enum {
|
|
FILE_MENU_POS = 0,
|
|
EDIT_MENU_POS = 1,
|
|
SCEN_MENU_POS = 2,
|
|
TOWN_MENU_POS = 3,
|
|
OUT_MENU_POS = 4,
|
|
HELP_MENU_POS = 6,
|
|
};
|
|
|
|
extern sf::RenderWindow mainPtr;
|
|
extern cScenario scenario;
|
|
LONG_PTR mainProc;
|
|
HMENU menuHandle = NULL;
|
|
accel_table_t accel;
|
|
std::map<int,eMenu> menuChoices;
|
|
|
|
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
void setMenuCommand(HMENU& menu, int i, eMenu cmd) {
|
|
static char title[256];
|
|
MENUITEMINFOA item;
|
|
item.cbSize = sizeof(MENUITEMINFOA);
|
|
item.cch = 255;
|
|
item.dwTypeData = title;
|
|
item.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
|
|
GetMenuItemInfoA(menu, i++, true, &item);
|
|
if(item.fType == MFT_SEPARATOR) return;
|
|
menuChoices[item.wID] = cmd;
|
|
// Now set up the accelerator, if any
|
|
std::string item_name = item.dwTypeData;
|
|
size_t pos = item_name.find_last_of('\t');
|
|
if(pos == std::string::npos) return;
|
|
pos++;
|
|
if(pos >= item_name.size()) return;
|
|
std::string key_name = item_name.substr(pos);
|
|
accel.add(item.wID, key_name);
|
|
}
|
|
|
|
void init_menubar() {
|
|
HWND winHandle = mainPtr.getSystemHandle();
|
|
if(winHandle == NULL) return;
|
|
if(menuHandle == NULL)
|
|
menuHandle = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU1));
|
|
SetMenu(winHandle, menuHandle);
|
|
// Now we have to do a little hack to handle menu messages.
|
|
// We replace SFML's window procedure with our own, which checks for menu events and then forwards to SFML's procedure.
|
|
mainProc = SetWindowLongPtr(winHandle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&menuProc));
|
|
// Fix the window's viewport so that everything is drawn correctly
|
|
sf::Vector2u sz = mainPtr.getSize();
|
|
double menubarHeight = getMenubarHeight();
|
|
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_SAVE_AS, 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::OUT_RESIZE, eMenu::NONE,
|
|
eMenu::SCEN_DETAILS, eMenu::SCEN_INTRO, eMenu::TOWN_START, eMenu::SCEN_SHEETS, eMenu::SCEN_PICS, eMenu::SCEN_SNDS, eMenu::NONE, eMenu::NONE,
|
|
eMenu::SCEN_SPECIALS, eMenu::SCEN_TEXT, eMenu::SCEN_JOURNALS, eMenu::TOWN_IMPORT, eMenu::OUT_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_TOC, 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);
|
|
|
|
accel.build();
|
|
}
|
|
|
|
void shut_down_menus(short mode) {
|
|
if(menuHandle == NULL) return;
|
|
HMENU file_menu = GetSubMenu(menuHandle, FILE_MENU_POS);
|
|
if(mode == 0) {
|
|
EnableMenuItem(file_menu, IDM_FILE_SAVE, MF_GRAYED | MF_BYCOMMAND);
|
|
EnableMenuItem(menuHandle, SCEN_MENU_POS, MF_GRAYED | MF_BYPOSITION);
|
|
EnableMenuItem(menuHandle, TOWN_MENU_POS, MF_GRAYED | MF_BYPOSITION);
|
|
EnableMenuItem(menuHandle, OUT_MENU_POS, MF_GRAYED | MF_BYPOSITION);
|
|
}
|
|
std::shared_ptr<char> buf(new char[256]);
|
|
MENUITEMINFOA info;
|
|
info.cbSize = sizeof(MENUITEMINFOA);
|
|
info.dwTypeData = buf.get();
|
|
info.fMask = MIIM_STRING | MIIM_FTYPE;
|
|
if(mode == 4) {
|
|
EnableMenuItem(file_menu, IDM_FILE_SAVE, MF_ENABLED | MF_BYCOMMAND);
|
|
EnableMenuItem(menuHandle, SCEN_MENU_POS, MF_ENABLED | MF_BYPOSITION);
|
|
EnableMenuItem(menuHandle, TOWN_MENU_POS, MF_ENABLED | MF_BYPOSITION);
|
|
EnableMenuItem(menuHandle, OUT_MENU_POS, MF_ENABLED | MF_BYPOSITION);
|
|
|
|
HMENU town_menu = GetSubMenu(menuHandle, TOWN_MENU_POS);
|
|
for(int i = 0; i < GetMenuItemCount(town_menu); i++) {
|
|
info.cch = 256;
|
|
GetMenuItemInfoA(town_menu, i, true, &info);
|
|
if(info.fType == MFT_SEPARATOR || !strcmp("Advanced", info.dwTypeData))
|
|
continue;
|
|
EnableMenuItem(town_menu, i, MF_ENABLED | MF_BYPOSITION);
|
|
}
|
|
|
|
HMENU out_menu = GetSubMenu(menuHandle, OUT_MENU_POS);
|
|
for(int i = 0; i < GetMenuItemCount(out_menu); i++) {
|
|
info.cch = 256;
|
|
GetMenuItemInfoA(out_menu, i, true, &info);
|
|
if(!strcmp("Advanced", info.dwTypeData)) continue;
|
|
EnableMenuItem(out_menu, i, MF_ENABLED | MF_BYPOSITION);
|
|
}
|
|
}
|
|
if((mode == 1) || (mode == 3)) {
|
|
HMENU town_menu = GetSubMenu(menuHandle, TOWN_MENU_POS);
|
|
for(int i = 0; i < GetMenuItemCount(town_menu); i++) {
|
|
info.cch = 256;
|
|
GetMenuItemInfoA(town_menu, i, true, &info);
|
|
if(info.fType == MFT_SEPARATOR || info.dwTypeData[0] == ' ')
|
|
continue;
|
|
EnableMenuItem(town_menu, i, MF_GRAYED | MF_BYPOSITION);
|
|
}
|
|
}
|
|
if((mode == 2) || (mode == 3)) {
|
|
HMENU out_menu = GetSubMenu(menuHandle, OUT_MENU_POS);
|
|
for(int i = 0; i < GetMenuItemCount(out_menu); i++) {
|
|
info.cch = 256;
|
|
GetMenuItemInfoA(out_menu, i, true, &info);
|
|
if(info.fType == MFT_SEPARATOR || info.dwTypeData[0] == ' ')
|
|
continue;
|
|
EnableMenuItem(out_menu, i, MF_GRAYED | MF_BYPOSITION);
|
|
}
|
|
}
|
|
DrawMenuBar(mainPtr.getSystemHandle());
|
|
}
|
|
|
|
#include "cursors.hpp"
|
|
|
|
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
|
|
MSG msg = {handle, message, wParam, lParam};
|
|
if(HIWORD(wParam) != 1 || message != WM_COMMAND) {
|
|
if(TranslateAccelerator(handle, accel.handle, &msg))
|
|
return 0;
|
|
}
|
|
if(message == WM_COMMAND) {
|
|
int cmd = LOWORD(wParam);
|
|
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.
|
|
restore_cursor();
|
|
return true;
|
|
}
|
|
return CallWindowProc(reinterpret_cast<WNDPROC>(mainProc), handle, message, wParam, lParam);
|
|
}
|
|
|
|
#include "fileio.hpp"
|
|
#include "scen.actions.hpp"
|
|
|
|
extern short cur_town;
|
|
extern location cur_out;
|
|
extern cTown* town;
|
|
extern cOutdoors* current_terrain;
|
|
extern bool change_made, ae_loading;
|
|
void set_up_apple_events(int argc, char* argv[]) {
|
|
if(argc > 1) {
|
|
if(load_scenario(argv[1], 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();
|
|
}
|
|
}
|
|
}
|