Get the game to compile, at least

- Scenario and PC editors still don't link
- Copy files stage set up in the Common project
- Scenario and PC editors now placed in Scenario Editor subfolder in the output directory
- Disabled some totally useless warnings
- "About" menuitem now considered to belong to "Help" menu (even on Mac code) as far as the handlers are concerned
- Dialog string filter is now a function instead of a custom iterator
- Modal session now requires parent window as additional parameter
- Preferences and menus work! Cursors still need some work.
- Since Visual Studio has no way of showing program output that I can find, stdout and stderr are now redirected to a file.
This commit is contained in:
2014-12-30 17:20:22 -05:00
parent c0642fe993
commit 0b330432b4
39 changed files with 990 additions and 141 deletions

View File

@@ -10,6 +10,9 @@
#define BOE_CURSORS_H
#include <string>
#include <boost/filesystem/path.hpp>
namespace fs = boost::filesystem;
enum cursor_type {
wand_curs = 0,
@@ -43,7 +46,7 @@ enum cursor_type {
class Cursor {
void* ptr;
public:
Cursor(std::string imgPath, float hotSpotX, float hotSpotY);
Cursor(fs::path imgPath, float hotSpotX, float hotSpotY);
~Cursor();
void apply();
};

View File

@@ -11,23 +11,6 @@
#include <string>
#include "restypes.hpp"
cursor_type current_cursor = sword_curs;
cursor_type arrow_curs[3][3] = {
{NW_curs, N_curs, NE_curs},
{W_curs,wait_curs,E_curs},
{SW_curs, S_curs, SE_curs},
};
const std::string cursors[25] = {
"wand", "eyedropper", "brush", "spraycan",
"eraser", "topleft", "bottomright", "hand",
"NW", "N", "NE",
"W", "wait", "E",
"SW", "S", "SE",
"sword", "boot", "drop", "target",
"talk", "key", "look", "watch",
};
static NSImage* imageFromURL(CFURLRef url){
CGImageSourceRef imageSource = CGImageSourceCreateWithURL(url, NULL);
CGImageRef theImage = nil;

141
src/tools/cursors.win.cpp Normal file
View File

@@ -0,0 +1,141 @@
#include "cursors.h"
#include <Windows.h>
#include <exception>
#include <SFML/Graphics/RenderWindow.hpp>
#include "restypes.hpp"
extern cursor_type current_cursor;
extern sf::RenderWindow mainPtr;
const std::string cursors[25] = {
"wand", "eyedropper", "brush", "spraycan",
"eraser", "topleft", "bottomright", "hand",
"NW", "N", "NE",
"W", "wait", "E",
"SW", "S", "SE",
"sword", "boot", "drop", "target",
"talk", "key", "look", "watch",
};
static const COLORREF clrMagenta = RGB(255, 0, 255);
// This function adapted from <http://web.archive.org/web/20130502044728/http://marknelson.us/2002/07/01/rendering-transparent-gifs-revisited/>
// It loads an image from a file and replaces transparency with magenta.
// This is probably undesirable in the general case, but since we only expect transparent GIFs, it should work out.
HBITMAP LoadPicture(std::string filename) {
sf::Image gif;
gif.loadFromFile(filename);
HDC dc = CreateCompatibleDC(NULL);
HBITMAP bmp = CreateCompatibleBitmap(dc, gif.getSize().x, gif.getSize().y);
SelectObject(dc, &bmp);
// Not exactly efficient, but it gets the job done.
for(int x = 0; x < gif.getSize().x; x++) {
for(int y = 0; y < gif.getSize().y; y++) {
sf::Color clr = gif.getPixel(x, y);
if(clr == sf::Color::Transparent)
SetPixel(dc, x, y, clrMagenta);
else SetPixel(dc, x, y, RGB(clr.r, clr.g, clr.b));
}
}
DeleteDC(dc);
return bmp;
}
// This function taken from <http://www.codeproject.com/Articles/5220/Creating-a-color-cursor-from-a-bitmap>
void GetMaskBitmaps(HBITMAP hSourceBitmap, COLORREF clrTransparent, HBITMAP& hAndMaskBitmap, HBITMAP& hXorMaskBitmap) {
HDC hDC = GetDC(NULL);
HDC hMainDC = CreateCompatibleDC(hDC);
HDC hAndMaskDC = CreateCompatibleDC(hDC);
HDC hXorMaskDC = CreateCompatibleDC(hDC);
//Get the dimensions of the source bitmap
BITMAP bm;
GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
hAndMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight);
hXorMaskBitmap = CreateCompatibleBitmap(hDC, bm.bmWidth, bm.bmHeight);
//Select the bitmaps to DC
HBITMAP hOldMainBitmap = (HBITMAP)SelectObject(hMainDC, hSourceBitmap);
HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);
//Scan each pixel of the souce bitmap and create the masks
COLORREF MainBitPixel;
for(int x = 0; x<bm.bmWidth; ++x) {
for(int y = 0; y<bm.bmHeight; ++y) {
MainBitPixel = GetPixel(hMainDC, x, y);
if(MainBitPixel == clrTransparent) {
SetPixel(hAndMaskDC, x, y, RGB(255, 255, 255));
SetPixel(hXorMaskDC, x, y, RGB(0, 0, 0));
} else {
SetPixel(hAndMaskDC, x, y, RGB(0, 0, 0));
SetPixel(hXorMaskDC, x, y, MainBitPixel);
}
}
}
SelectObject(hMainDC, hOldMainBitmap);
SelectObject(hAndMaskDC, hOldAndMaskBitmap);
SelectObject(hXorMaskDC, hOldXorMaskBitmap);
DeleteDC(hXorMaskDC);
DeleteDC(hAndMaskDC);
DeleteDC(hMainDC);
ReleaseDC(NULL, hDC);
}
Cursor::Cursor(fs::path imgPath, float hotSpotX, float hotSpotY) {
HBITMAP cursorImage = LoadPicture(imgPath.string()), cursorAnd, cursorXor;
if(cursorImage == NULL) {
std::string error = "Error loading cursor from " + imgPath.string();
throw std::exception(error.c_str());
}
GetMaskBitmaps(cursorImage, clrMagenta, cursorAnd, cursorXor);
ICONINFO iconinfo = {0};
iconinfo.fIcon = FALSE;
iconinfo.xHotspot = hotSpotX;
iconinfo.yHotspot = hotSpotY;
iconinfo.hbmMask = cursorAnd;
iconinfo.hbmColor = cursorXor;
HCURSOR hCursor = CreateIconIndirect(&iconinfo);
ptr = &hCursor;
DeleteObject(cursorImage);
DeleteObject(cursorAnd);
DeleteObject(cursorXor);
}
Cursor::~Cursor() {
HCURSOR* curs = (HCURSOR*)ptr;
DestroyIcon(*curs);
}
void Cursor::apply() {
HCURSOR* curs = (HCURSOR*)ptr;
SetCursor(*curs);
// TODO: This ensures the cursor stays set when the mouse moves. Is it necessary, though?
SetClassLong(mainPtr.getSystemHandle(), GCL_HCURSOR, (LONG)(*curs));
}
void obscureCursor() {
SetCursor(NULL);
}
void set_cursor(cursor_type which_c) {
if(which_c != watch_curs)
current_cursor = which_c;
if(which_c == text_curs) {
SetCursor(LoadCursor(NULL, IDC_IBEAM));
} else {
Cursor& curs = *ResMgr::get<CursorRsrc>(cursors[which_c]);
curs.apply();
}
}
void restore_cursor() {
set_cursor(current_cursor);
}

View File

@@ -22,6 +22,7 @@
#include "porting.h"
#include "restypes.hpp"
#include "tarball.hpp"
#include "cursors.h"
bool cur_scen_is_mac = true, mac_is_intel;
extern sf::Texture items_gworld,tiny_obj_gworld,fields_gworld,roads_gworld,boom_gworld,missiles_gworld;
@@ -43,6 +44,14 @@ static bool load_town_talk(fs::path town_base, short which_town, cSpeech& the_ta
static bool load_party_v1(fs::path file_to_load, cUniverse& univ, bool town_restore, bool in_scen, bool maps_there, bool must_port);
static bool load_party_v2(fs::path file_to_load, cUniverse& univ, bool town_restore, bool in_scen, bool maps_there);
// Cursors included here so that they needn't be unnecessarily duplicated in platform-specific files
cursor_type current_cursor = sword_curs;
cursor_type arrow_curs[3][3] = {
{NW_curs, N_curs, NE_curs},
{W_curs, wait_curs, E_curs},
{SW_curs, S_curs, SE_curs},
};
#include <stdexcept>
void init_directories(const char* exec_path) {
@@ -54,7 +63,7 @@ void init_directories(const char* exec_path) {
#endif
progDir = progDir.parent_path();
if(progDir.filename() == "Scenario Editor") progDir = progDir.parent_path();
std::cout << progDir << '\n';
std::cout << progDir << std::endl;
// Initialize the resource manager paths
ResMgr::pushPath<ImageRsrc>(progDir/"Scenario Editor"/"graphics.exd"/"mac");
ResMgr::pushPath<CursorRsrc>(progDir/"Scenario Editor"/"graphics.exd"/"mac"/"cursors");

View File

@@ -68,7 +68,7 @@ void init_graph_tool(){
fin.read(vbuf, size);
if(!maskShader.loadFromMemory(vbuf, fbuf)) {
fprintf(stderr,"Error: Failed to load shaders from %s\nVertex:\n%s\nFragment:\n%s",shaderPath.c_str(),vbuf,fbuf);
fprintf(stderr,"Error: Failed to load shaders from %s\nVertex:\n%s\nFragment:\n%s",shaderPath.string().c_str(),vbuf,fbuf);
}
delete[] fbuf;
delete[] vbuf;

133
src/tools/prefs.win.cpp Normal file
View File

@@ -0,0 +1,133 @@
#include "prefs.hpp"
#include <map>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <boost/filesystem.hpp>
#include <boost/any.hpp>
#include <boost/lexical_cast.hpp>
namespace fs = boost::filesystem;
std::map<std::string,boost::any> prefs;
using iarray = std::vector<int>;
static bool prefsLoaded = false, prefsDirty = false;
void set_pref(std::string keypath, bool value) {
prefsDirty = true;
prefs[keypath] = value;
}
bool get_bool_pref(std::string keypath, bool fallback) {
if(prefs.find(keypath) == prefs.end()) return fallback;
if(prefs[keypath].type() == typeid(bool)) return boost::any_cast<bool>(prefs[keypath]);
return fallback;
}
void set_pref(std::string keypath, int value) {
prefsDirty = true;
prefs[keypath] = value;
}
int get_int_pref(std::string keypath, int fallback) {
if(prefs.find(keypath) == prefs.end()) return fallback;
if(prefs[keypath].type() == typeid(int)) return boost::any_cast<int>(prefs[keypath]);
return fallback;
}
void append_iarray_pref(std::string keypath, int value) {
prefsDirty = true;
if(prefs.find(keypath) == prefs.end() || prefs[keypath].type() != typeid(iarray))
prefs[keypath] = iarray{value};
else {
iarray& arr = boost::any_cast<iarray>(prefs[keypath]);
arr.push_back(value);
prefs[keypath] = arr;
}
}
std::vector<int> get_iarray_pref(std::string keypath) {
if(prefs.find(keypath) == prefs.end()) return {};
if(prefs[keypath].type() == typeid(iarray)) return boost::any_cast<iarray>(prefs[keypath]);
return {};
}
void clear_pref(std::string keypath) {
prefsDirty = true;
auto iter = prefs.find(keypath);
if(iter != prefs.end()) prefs.erase(iter);
}
static bool save_prefs(fs::path fpath) {
if(!prefsDirty) return true;
fs::create_directories(fpath.parent_path());
std::ofstream fout(fpath.string().c_str());
for(auto& kv : prefs) {
if(kv.second.type() == typeid(iarray)) {
iarray& arr = boost::any_cast<iarray>(kv.second);
fout << kv.first << " = [";
for(int i : arr) fout << i << ' ';
fout.seekp(-1,std::ios::cur); // To overwrite the final space written in the loop
fout << ']' << std::endl;
} else if(kv.second.type() == typeid(bool))
fout << kv.first << " = " << std::boolalpha << boost::any_cast<bool>(kv.second) << std::endl;
else if(kv.second.type() == typeid(int))
fout << kv.first << " = " << boost::any_cast<int>(kv.second) << std::endl;
else printf("Warning: Unknown preference value type, skipping...\n");
if(!fout) {
perror("Error writing preferences");
return false;
}
}
prefsDirty = false;
return true;
}
static bool load_prefs(fs::path fpath) {
prefsDirty = false;
std::map<std::string,boost::any> temp_prefs;
std::ifstream fin(fpath.string().c_str());
std::string line;
while(std::getline(fin, line)) {
if(!fin) {
perror("Error reading preferences");
return false;
}
if(line[0] == '#') continue;
int eq = line.find_first_of('=');
if(eq == std::string::npos) {
printf("Error reading preferences: line is not a comment and lacks an = sign:\n\t%s\n", line.c_str());
return false;
}
int key_end = line.find_last_not_of(' ', eq - 1), val_beg = line.find_first_not_of(' ', eq + 1);
if(val_beg == std::string::npos) {
printf("Error reading preferences: line is missing value:\n\t%s\n", line.c_str());
return false;
}
if(key_end == std::string::npos) {
printf("Error reading preferences: line is missing key:\n\t%s\n", line.c_str());
return false;
}
std::string key = line.substr(0, key_end + 1), val = line.substr(val_beg);
if(val == "true") temp_prefs[key] = true;
else if(val == "false") temp_prefs[key] = false;
else if(val[0] == '[') {
int arr_end = val.find_first_of(']');
std::istringstream arr_vals(val.substr(1, arr_end - 1));
int i = 0;
iarray vals;
while(arr_vals >> i) vals.push_back(i);
temp_prefs[key] = vals;
} else temp_prefs[key] = boost::lexical_cast<int>(val);
}
prefs.swap(temp_prefs);
return prefsLoaded = true;
}
extern fs::path tempDir;
bool sync_prefs() {
fs::path prefsPath = tempDir.parent_path() / "bladesprefs.ini";
if(prefsLoaded) return save_prefs(prefsPath);
else return load_prefs(prefsPath);
}

View File

@@ -59,7 +59,7 @@ namespace ResMgr {
std::stack<fs::path> tmpPaths = resPaths();
while(!tmpPaths.empty()) {
fs::path thisPath = tmpPaths.top()/path;
printf("Testing %s...\n",thisPath.c_str());
printf("Testing %s...\n",thisPath.string().c_str());
if(fs::exists(thisPath)) {
pathFound()[path] = tmpPaths.top();
return thisPath;
@@ -165,7 +165,7 @@ namespace ResMgr {
/// @tparam type The type of resource the path applies to.
/// @param path The path at which resources of this type may be found.
template<typename type> void pushPath(fs::path path) {
printf("Pushing path %s in %s...\n",path.c_str(),__FUNCTION__);
printf("Pushing path %s in %s...\n",path.string().c_str(),__FUNCTION__);
resPool<type>::resPaths().push(path);
if(resPool<type>::resPaths().empty()) printf("A problem occurred.\n");
}

View File

@@ -34,11 +34,15 @@ std::string get_clipboard();
void beep();
// Calculates how much of the window is occupied by the menubar
int getMenubarHeight();
class ModalSession {
void* session;
sf::Window& parent;
public:
void pumpEvents();
ModalSession(sf::Window& win);
ModalSession(sf::Window& win, sf::Window& parent);
~ModalSession();
};

View File

@@ -145,6 +145,11 @@ void beep() {
NSBeep();
}
int getMenubarHeight() {
// Mac menubar isn't in the window, so we return 0 here.
return 0;
}
NSOpenPanel* dlg_get_scen;
NSOpenPanel* dlg_get_game;
NSSavePanel* dlg_put_scen;

222
src/tools/winutil.win.cpp Normal file
View File

@@ -0,0 +1,222 @@
#include "winutil.h"
#include <Windows.h>
#include <SFML/Graphics/RenderWindow.hpp>
extern sf::RenderWindow mainPtr;
OPENFILENAME getParty, getScen, putParty, putScen;
// TODO: I'm sure there's a better way to do this (maybe one that's keyboard layout agnostic)
// The proper way would involve use of the TextEntered event
char keyToChar(sf::Keyboard::Key key, bool isShift) {
using kb = sf::Keyboard;
switch(key) {
case kb::A: return isShift ? 'A' : 'a';
case kb::B: return isShift ? 'B' : 'b';
case kb::C: return isShift ? 'C' : 'c';
case kb::D: return isShift ? 'D' : 'd';
case kb::E: return isShift ? 'E' : 'e';
case kb::F: return isShift ? 'F' : 'f';
case kb::G: return isShift ? 'G' : 'g';
case kb::H: return isShift ? 'H' : 'h';
case kb::I: return isShift ? 'I' : 'i';
case kb::J: return isShift ? 'J' : 'j';
case kb::K: return isShift ? 'K' : 'k';
case kb::L: return isShift ? 'L' : 'l';
case kb::M: return isShift ? 'M' : 'm';
case kb::N: return isShift ? 'N' : 'n';
case kb::O: return isShift ? 'O' : 'o';
case kb::P: return isShift ? 'P' : 'p';
case kb::Q: return isShift ? 'Q' : 'q';
case kb::R: return isShift ? 'R' : 'r';
case kb::S: return isShift ? 'S' : 's';
case kb::T: return isShift ? 'T' : 't';
case kb::U: return isShift ? 'U' : 'u';
case kb::V: return isShift ? 'V' : 'v';
case kb::W: return isShift ? 'W' : 'w';
case kb::X: return isShift ? 'X' : 'x';
case kb::Y: return isShift ? 'Y' : 'y';
case kb::Z: return isShift ? 'Z' : 'z';
case kb::Num1: return isShift ? '!' : '1';
case kb::Num2: return isShift ? '@' : '2';
case kb::Num3: return isShift ? '#' : '3';
case kb::Num4: return isShift ? '$' : '4';
case kb::Num5: return isShift ? '%' : '5';
case kb::Num6: return isShift ? '^' : '6';
case kb::Num7: return isShift ? '&' : '7';
case kb::Num8: return isShift ? '*' : '8';
case kb::Num9: return isShift ? '(' : '9';
case kb::Num0: return isShift ? ')' : '0';
case kb::Tilde: return isShift ? '~' : '`';
case kb::Dash: return isShift ? '_' : '-';
case kb::Equal: return isShift ? '+' : '=';
case kb::LBracket: return isShift ? '{' : '[';
case kb::RBracket: return isShift ? '}' : ']';
case kb::SemiColon: return isShift ? ':' : ';';
case kb::Quote: return isShift ? '"' : '\'';
case kb::Comma: return isShift ? '<' : ',';
case kb::Period: return isShift ? '>' : '.';
case kb::Slash: return isShift ? '?' : '/';
case kb::BackSlash: return isShift ? '|' : '\\';
case kb::Tab: return '\t';
case kb::Space: return ' ';
case kb::Return: return '\n';
case kb::BackSpace: return '\b';
case kb::Delete: return '\x7f';
case kb::Numpad0: return '0';
case kb::Numpad1: return '1';
case kb::Numpad2: return '2';
case kb::Numpad3: return '3';
case kb::Numpad4: return '4';
case kb::Numpad5: return '5';
case kb::Numpad6: return '6';
case kb::Numpad7: return '7';
case kb::Numpad8: return '8';
case kb::Numpad9: return '9';
// TODO: Should have Equal here, but SFML doesn't distinguish between normal and keybad equal :/
// Ditto for the decimal point.
case kb::Divide: return '/';
case kb::Multiply: return '*';
case kb::Subtract: return '-';
case kb::Add: return '+';
default: break;
}
return 0;
}
void makeFrontWindow(sf::Window& win) {
HWND win_handle = win.getSystemHandle();
BringWindowToTop(win_handle);
}
void setWindowFloating(sf::Window& win, bool floating) {
HWND win_handle = win.getSystemHandle();
UINT flags = SWP_NOMOVE | SWP_NOSIZE;
HWND newPos = floating ? HWND_TOPMOST : HWND_TOP;
// The flags param specifies that these 0's are ignored.
SetWindowPos(win_handle, newPos, 0, 0, 0, 0, flags);
}
void init_fileio() {
OPENFILENAME base_dlg;
memset(&base_dlg, 0, sizeof(OPENFILENAME));
// Common values
base_dlg.lStructSize = sizeof(OPENFILENAME);
base_dlg.hwndOwner = mainPtr.getSystemHandle();
base_dlg.nFilterIndex = 1;
base_dlg.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
getParty = getScen = putParty = putScen = base_dlg;
// Open saved game dialog
getParty.lpstrFilter = LPCTSTR("Blades of Exile Saved Games\0*.exg\0Legacy Saved Games\0*.mac;*.boe;*.SAV\0");
getParty.lpstrTitle = LPCTSTR("Load Game");
getParty.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
// Open scenario dialog
getScen.lpstrFilter = LPCTSTR("Blades of Exile Scenarios\0*.boes\0Legacy or Unpacked Scenarios\0*.exs\0");
getScen.lpstrTitle = LPCTSTR("Open Scenario");
// Save game dialog
putParty.lpstrFilter = LPCTSTR("Blades of Exile Saved Games\0*.exg\0");
putParty.lpstrTitle = LPCTSTR("Save Game");
putParty.Flags |= OFN_OVERWRITEPROMPT;
// Save scenario dialog
putScen.lpstrFilter = LPCTSTR("Blades of Exile Scenario\0*.boes\0");
putScen.lpstrTitle = LPCTSTR("Save Scenario");
}
static std::string runFileDlog(OPENFILENAME& dlg, const std::string& file, bool save) {
size_t sz = std::max<size_t>(MAX_PATH, file.length()) + 1;
char* path = new char[sz];
std::copy(file.begin(), file.end(), path);
std::fill(path + file.length(), path + sz, 0);
putParty.lpstrFile = path;
putParty.nMaxFile = sz - 1;
putParty.nFileOffset = file.find_last_of('\\');
if(putParty.nFileOffset == std::string::npos)
putParty.nFileOffset = 0;
else putParty.nFileOffset++;
putParty.nFileExtension = file.find_last_of('.');
if(putParty.nFileExtension == std::string::npos)
putParty.nFileExtension = 0;
else putParty.nFileExtension++;
if(save) GetSaveFileName(&dlg);
else GetOpenFileName(&dlg);
std::string result = putParty.lpstrFile;
putParty.lpstrFile = NULL;
putParty.nMaxFile = 0;
delete path;
putParty.Flags &= ~OFN_EXTENSIONDIFFERENT;
putParty.Flags &= ~OFN_READONLY;
return result;
}
fs::path nav_get_party() {
return runFileDlog(getParty, "Blades of Exile Save.exg", false);
}
fs::path nav_put_party(fs::path def) {
return runFileDlog(putParty, def.string(), true);
}
fs::path nav_get_scenario() {
return runFileDlog(getScen, "", false);
}
fs::path nav_put_scenario(fs::path def) {
return runFileDlog(putScen, def.string(), true);
}
void set_clipboard(std::string text) {
if(text.empty()) return;
if(!OpenClipboard(mainPtr.getSystemHandle())) return;
HGLOBAL hData = (char*) GlobalAlloc(GMEM_MOVEABLE, text.length() + 1);
char* data = (char*)GlobalLock(hData);
std::copy(text.c_str(), text.c_str() + text.length(), data);
data[text.length()] = 0;
GlobalUnlock(hData);
EmptyClipboard();
SetClipboardData(CF_TEXT, hData);
CloseClipboard();
}
std::string get_clipboard() {
if(!OpenClipboard(NULL)) return "";
HGLOBAL hData = GetClipboardData(CF_TEXT);
char* data = (char*) GlobalLock(hData);
std::string contents(data);
GlobalUnlock(hData);
CloseClipboard();
return contents;
}
void beep() {
MessageBeep(-1);
}
// 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() {
HWND win_handle = (HWND)session;
}
ModalSession::ModalSession(sf::Window& win, sf::Window& parent) : parent(parent) {
session = win.getSystemHandle();
EnableWindow(parent.getSystemHandle(), false);
}
ModalSession::~ModalSession() {
HWND win_handle = (HWND)session;
EnableWindow(parent.getSystemHandle(), true);
RedrawWindow(parent.getSystemHandle(), NULL, NULL, RDW_NOCHILDREN | RDW_UPDATENOW);
}
void set_up_apple_events() {
// TODO: Probably nothing to do here on Windows?
// Basically what might possibly happen here is to set up stuff to handle dragging a file onto the application icon.
// The Mac version also handles requests from the operating system for the application to quit.
}
int getMenubarHeight() {
return GetSystemMetrics(SM_CYMENU);
}