From c4dd3ffaf63bcd2a751b69db9e51df845232ac43 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Fri, 3 Mar 2017 19:37:19 +0100 Subject: [PATCH 1/6] Config: Use set for preloadScripts Would probably make sense for all other string vectors too. --- binding-mri/binding-mri.cpp | 5 +++-- src/config.cpp | 8 +++++++- src/config.h | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index 5cb518e..c28cdaa 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -452,8 +452,9 @@ static void runRMXPScripts(BacktraceData &btData) } /* Execute preloaded scripts */ - for (size_t i = 0; i < conf.preloadScripts.size(); ++i) - runCustomScript(conf.preloadScripts[i]); + for (std::set::iterator i = conf.preloadScripts.begin(); + i != conf.preloadScripts.end(); ++i) + runCustomScript(*i); VALUE exc = rb_gv_get("$!"); if (exc != Qnil) diff --git a/src/config.cpp b/src/config.cpp index 9173acc..a58ddab 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -134,6 +134,12 @@ static std::string prefPath(const char *org, const char *app) return str; } +template +std::set setFromVec(const std::vector &vec) +{ + return std::set(vec.begin(), vec.end()); +} + typedef std::vector StringVec; namespace po = boost::program_options; @@ -226,7 +232,7 @@ void Config::read(int argc, char *argv[]) PO_DESC_ALL; - GUARD_ALL( preloadScripts = vm["preloadScript"].as(); ); + GUARD_ALL( preloadScripts = setFromVec(vm["preloadScript"].as()); ); GUARD_ALL( rtps = vm["RTP"].as(); ); diff --git a/src/config.h b/src/config.h index fc9bbda..d82698d 100644 --- a/src/config.h +++ b/src/config.h @@ -24,6 +24,7 @@ #include #include +#include struct Config { @@ -77,7 +78,7 @@ struct Config bool useScriptNames; std::string customScript; - std::vector preloadScripts; + std::set preloadScripts; std::vector rtps; std::vector fontSubs; From 6349146e0198c995cadb923a7991576064df7e90 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sat, 4 Mar 2017 11:04:02 +0100 Subject: [PATCH 2/6] main: Only set window icon on Linux OSX carries high-resolution icons in its bundles, and windows uses windres to embed .ico files, so don't interfere with those. --- src/main.cpp | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index eb07970..4b5e234 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -166,6 +166,24 @@ static void showInitError(const std::string &msg) SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "mkxp", msg.c_str(), 0); } +static void setupWindowIcon(const Config &conf, SDL_Window *win) +{ + SDL_RWops *iconSrc; + + if (conf.iconPath.empty()) + iconSrc = SDL_RWFromConstMem(assets_icon_png, assets_icon_png_len); + else + iconSrc = SDL_RWFromFile(conf.iconPath.c_str(), "rb"); + + SDL_Surface *iconImg = IMG_Load_RW(iconSrc, SDL_TRUE); + + if (iconImg) + { + SDL_SetWindowIcon(win, iconImg); + SDL_FreeSurface(iconImg); + } +} + int main(int argc, char *argv[]) { SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); @@ -239,16 +257,6 @@ int main(int argc, char *argv[]) return 0; } - /* Setup application icon */ - SDL_RWops *iconSrc; - - if (conf.iconPath.empty()) - iconSrc = SDL_RWFromConstMem(assets_icon_png, assets_icon_png_len); - else - iconSrc = SDL_RWFromFile(conf.iconPath.c_str(), "rb"); - - SDL_Surface *iconImg = IMG_Load_RW(iconSrc, SDL_TRUE); - SDL_Window *win; Uint32 winFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_INPUT_FOCUS; @@ -267,11 +275,13 @@ int main(int argc, char *argv[]) return 0; } - if (iconImg) - { - SDL_SetWindowIcon(win, iconImg); - SDL_FreeSurface(iconImg); - } + /* OSX and Windows have their own native ways of + * dealing with icons; don't interfere with them */ +#ifdef __LINUX__ + setupWindowIcon(conf, win); +#else + (void) setupWindowIcon; +#endif ALCdevice *alcDev = alcOpenDevice(0); From 0f9b5f274a9a2d9decff69c963b40ce37365d2a9 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Wed, 8 Mar 2017 16:30:07 +0100 Subject: [PATCH 3/6] Filesystem: Search for "Fonts/" with case-insensitivity --- src/filesystem.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/filesystem.cpp b/src/filesystem.cpp index fe5d403..d7fd36b 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -458,7 +458,7 @@ struct FontSetsCBData SharedFontState *sfs; }; -static void fontSetEnumCB(void *data, const char *, +static void fontSetEnumCB(void *data, const char *dir, const char *fname) { FontSetsCBData *d = static_cast(data); @@ -480,7 +480,7 @@ static void fontSetEnumCB(void *data, const char *, return; char filename[512]; - snprintf(filename, sizeof(filename), "Fonts/%s", fname); + snprintf(filename, sizeof(filename), "%s/%s", dir, fname); PHYSFS_File *handle = PHYSFS_openRead(filename); @@ -495,11 +495,29 @@ static void fontSetEnumCB(void *data, const char *, SDL_RWclose(&ops); } +/* Basically just a case-insensitive search + * for the folder "Fonts"... */ +static void findFontsFolderCB(void *data, const char *, + const char *fname) +{ + size_t i = 0; + char buffer[512]; + const char *s = fname; + + while (s && i < sizeof(buffer)) + buffer[i++] = tolower(*s++); + + buffer[i] = '\0'; + + if (strcmp(buffer, "fonts") == 0) + PHYSFS_enumerateFilesCallback(fname, fontSetEnumCB, data); +} + void FileSystem::initFontSets(SharedFontState &sfs) { FontSetsCBData d = { p, &sfs }; - PHYSFS_enumerateFilesCallback("Fonts", fontSetEnumCB, &d); + PHYSFS_enumerateFilesCallback(".", findFontsFolderCB, &d); } struct OpenReadEnumData From 60e967e3b781ce170b30ffd744e132145ef37bd7 Mon Sep 17 00:00:00 2001 From: Marty Plummer Date: Fri, 3 Mar 2017 22:45:31 -0600 Subject: [PATCH 4/6] Add icon and resource files for windows Signed-off-by: Marty Plummer --- assets/icon.ico | Bin 0 -> 16958 bytes assets/resource.h | 1 + assets/resource.rc | 4 ++++ src/main.cpp | 4 ++++ 4 files changed, 9 insertions(+) create mode 100644 assets/icon.ico create mode 100644 assets/resource.h create mode 100644 assets/resource.rc diff --git a/assets/icon.ico b/assets/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2a10780dd1c609077bcc4a2cbd42ddfe422d5aac GIT binary patch literal 16958 zcmd^{ONbps6ozXaVaUc1L_sBw8zhY4!hj?y!W~2iJ_AwQh>Ju>LUx}W{;KYJ zoT`a2bNaWkV)VP)EI(_^{l=JOv69THm~=-gyJ~*VD#6_G*ublSbY!GWxpEiSCW0m!^WP`l%XtjI$dMu7t*r(I?;^{)25CTUKS7F-m}o&?8kqVW36fn z@;|y^>}%f``{<$4_XAt7X&Tg(k{jX-_PKdupEzplhrf@Gxu{(}_|4eI-!OJ=E~~q5 z3pQcfBKBD=?(e&Q!%AAT;`2H1v;w z?TyFo+xF}&WB0w8Yy)f`h4_|2zcZg5`l>y+J$@fP|Cz={jl;3ciZ>k(x~iKQ>)MRn zx4|pt2k?UdEOm&vG&9HX&U+ng5BDD%Xalg+Ss$>T2=7rxV_loR_p0{CR&0(jC=RA! zi1lQs%N*B+alQ(3J|CO0J;tJV)moYTL}op|k@I^VQ{885&*2AK*`A3#Rj9+duCC6q z@~8hW_VCxn@_jD9XzYXgdQ6-&@|e%dWYowi;&pg6DtggOP`QulO z-T7qUx;wWf`tosX zrYoKE8{%Zk;%NmGIf%=RGN&7grHwC`+AS6Ea7655N@5Qyk2m@Ugml*7!~RHhimz zcm7Aoe#9%P5mJY`!ER(X9S^_+wn!eBA$;s%oxf+LdEYZ$Nmk6*zeU`XsGDg6bkunt zkJ!bzRJxryuVHQUDYy#jPNa>qv_m;PgSyF_UAGot?8W4 z{GOA|H#{yvR*;XbVf!U62ew#_;{Hr3qz~hxj%5;OU6=DoGKLQ`)~VP~gsdFUs|ACz~ zKp4Lot$*aRn)>=jI#c6YSz5vR=TwZp@%mRjt5}ZWlUx5vR~gQtyu|t!?Cb%8?d%bX z>X)T&;{8u%|J%{IK^e}nyteOu!4~zk-~TGf-7#}{_*t5sceL660j8W^%KJaSpYeZj z-=?ge%ktXl{{oY6#vJ>R@bBS!@SG#9#ws8D;K2aKCQcXVTMXBi^;d-N35*558S4D-zm``*qwgn}*%v(80L7 zWB(od`&hspyY8Zr{&eck&{v{P3c&czhB+^?I4{iEnOcy6HI!2p&f zbWD}Pcfg#?{kl=?n`B+E=jJ+W2g4|IUX?=|5Xbl4ru%Sw?}>LFo3VXVT9knH-hb9O zpBU@FKCb)Ev>$CS@E**_{de$t;#|ejWIw^4D(syV4{eZ-m! z=`Q*EN5Kn({{X)NzLjv7Q1QaHsF{aMWTOLJZ6^GQ_!sf94$K!y8@5fTiwtDN_Z9WH zX~^F(^LLH>ofCiefb)0a{w#8;fB$Z+U0>3VwR*kI5XvpNjc`q0HX-e-;9tV7wYLa& zxni#18qX@YN;uamP6Zwn^3saVxatz%s!M5o y$LT}g4nFkl +#include "resource.h" + +IDI_APPICON ICON "icon.ico" diff --git a/src/main.cpp b/src/main.cpp index 4b5e234..1ad3ee2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,7 +40,11 @@ #include "binding.h" +#ifdef __WINDOWS__ +#include "resource.h" +#elif __LINUX__ #include "icon.png.xxd" +#endif static void rgssThreadError(RGSSThreadData *rtData, const std::string &msg) From 3ea24bd7578ccefbef6d50397d9fd80fba6de253 Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sat, 8 Apr 2017 16:16:36 +0200 Subject: [PATCH 5/6] EventThread: Make system cursor visible over black aspect ratio bars Should be less confusing for the player. --- src/eventthread.cpp | 48 ++++++++++++++++++++++++++++++++++++--------- src/eventthread.h | 6 +++++- src/graphics.cpp | 3 +++ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 00c1b3e..42dab49 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -83,6 +83,7 @@ enum REQUEST_SETCURSORVISIBLE, UPDATE_FPS, + UPDATE_SCREEN_RECT, EVENT_COUNT }; @@ -131,6 +132,8 @@ void EventThread::process(RGSSThreadData &rtData) bool displayingFPS = false; bool cursorInWindow = false; + /* Will be updated eventually */ + SDL_Rect gameScreen = { 0, 0, 0, 0 }; /* SDL doesn't send an initial FOCUS_GAINED event */ bool windowFocused = true; @@ -170,7 +173,7 @@ void EventThread::process(RGSSThreadData &rtData) delete sMenu; sMenu = 0; - updateCursorState(cursorInWindow && windowFocused); + updateCursorState(cursorInWindow && windowFocused, gameScreen); } continue; @@ -211,14 +214,14 @@ void EventThread::process(RGSSThreadData &rtData) case SDL_WINDOWEVENT_ENTER : cursorInWindow = true; mouseState.inWindow = true; - updateCursorState(cursorInWindow && windowFocused && !sMenu); + updateCursorState(cursorInWindow && windowFocused && !sMenu, gameScreen); break; case SDL_WINDOWEVENT_LEAVE : cursorInWindow = false; mouseState.inWindow = false; - updateCursorState(cursorInWindow && windowFocused && !sMenu); + updateCursorState(cursorInWindow && windowFocused && !sMenu, gameScreen); break; @@ -229,13 +232,13 @@ void EventThread::process(RGSSThreadData &rtData) case SDL_WINDOWEVENT_FOCUS_GAINED : windowFocused = true; - updateCursorState(cursorInWindow && windowFocused && !sMenu); + updateCursorState(cursorInWindow && windowFocused && !sMenu, gameScreen); break; case SDL_WINDOWEVENT_FOCUS_LOST : windowFocused = false; - updateCursorState(cursorInWindow && windowFocused && !sMenu); + updateCursorState(cursorInWindow && windowFocused && !sMenu, gameScreen); resetInputStates(); break; @@ -268,7 +271,7 @@ void EventThread::process(RGSSThreadData &rtData) if (!sMenu) { sMenu = new SettingsMenu(rtData); - updateCursorState(false); + updateCursorState(false, gameScreen); } sMenu->raise(); @@ -374,6 +377,7 @@ void EventThread::process(RGSSThreadData &rtData) case SDL_MOUSEMOTION : mouseState.x = event.motion.x; mouseState.y = event.motion.y; + updateCursorState(cursorInWindow, gameScreen); break; case SDL_FINGERDOWN : @@ -413,7 +417,7 @@ void EventThread::process(RGSSThreadData &rtData) case REQUEST_SETCURSORVISIBLE : showCursor = event.user.code; - updateCursorState(cursorInWindow); + updateCursorState(cursorInWindow, gameScreen); break; case UPDATE_FPS : @@ -438,6 +442,15 @@ void EventThread::process(RGSSThreadData &rtData) SDL_SetWindowTitle(win, buffer); break; + + case UPDATE_SCREEN_RECT : + gameScreen.x = event.user.windowID; + gameScreen.y = event.user.code; + gameScreen.w = reinterpret_cast(event.user.data1); + gameScreen.h = reinterpret_cast(event.user.data2); + updateCursorState(cursorInWindow, gameScreen); + + break; } } @@ -532,9 +545,13 @@ void EventThread::setFullscreen(SDL_Window *win, bool mode) fullscreen = mode; } -void EventThread::updateCursorState(bool inWindow) +void EventThread::updateCursorState(bool inWindow, + const SDL_Rect &screen) { - if (inWindow) + SDL_Point pos = { mouseState.x, mouseState.y }; + bool inScreen = inWindow && SDL_PointInRect(&pos, &screen); + + if (inScreen) SDL_ShowCursor(showCursor ? SDL_TRUE : SDL_FALSE); else SDL_ShowCursor(SDL_TRUE); @@ -640,6 +657,19 @@ void EventThread::notifyFrame() SDL_PushEvent(&event); } +void EventThread::notifyGameScreenChange(const SDL_Rect &screen) +{ + /* We have to get a bit hacky here to fit the rectangle + * data into the user event struct */ + SDL_Event event; + event.type = usrIdStart + UPDATE_SCREEN_RECT; + event.user.windowID = screen.x; + event.user.code = screen.y; + event.user.data1 = reinterpret_cast(screen.w); + event.user.data2 = reinterpret_cast(screen.h); + SDL_PushEvent(&event); +} + void SyncPoint::haltThreads() { if (mainSync.locked) diff --git a/src/eventthread.h b/src/eventthread.h index 46051f1..02a9ea1 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -98,12 +98,16 @@ public: /* RGSS thread calls this once per frame */ void notifyFrame(); + /* Called on game screen (size / offset) changes */ + void notifyGameScreenChange(const SDL_Rect &screen); + private: static int eventFilter(void *, SDL_Event*); void resetInputStates(); void setFullscreen(SDL_Window *, bool mode); - void updateCursorState(bool inWindow); + void updateCursorState(bool inWindow, + const SDL_Rect &screen); bool fullscreen; bool showCursor; diff --git a/src/graphics.cpp b/src/graphics.cpp index fe51f74..d205697 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -566,6 +566,9 @@ struct GraphicsPrivate glState.viewport.refresh(); recalculateScreenSize(threadData); updateScreenResoRatio(threadData); + + SDL_Rect screen = { scOffset.x, scOffset.y, scSize.x, scSize.y }; + threadData->ethread->notifyGameScreenChange(screen); } } From 0481f920b08fae7d5002842166b5e84341a1000d Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sat, 8 Apr 2017 18:41:56 +0200 Subject: [PATCH 6/6] Input: Remove ugly [-20,-20] mouse position hack This was supposed to disappear shortly after To the Moon's release, but it unfortunately survived a bit longer :) The status of the mouse cursor being inside / outside the game window is now properly exposed (in MRI) via MKXP.mouse_in_window. --- binding-mri/binding-mri.cpp | 9 +++++++++ src/input.cpp | 6 ------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index c28cdaa..f0a4bb4 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -80,6 +80,7 @@ RB_METHOD(mriP); RB_METHOD(mkxpDataDirectory); RB_METHOD(mkxpPuts); RB_METHOD(mkxpRawKeyStates); +RB_METHOD(mkxpMouseInWindow); RB_METHOD(mriRgssMain); RB_METHOD(mriRgssStop); @@ -144,6 +145,7 @@ static void mriBindingInit() _rb_define_module_function(mod, "data_directory", mkxpDataDirectory); _rb_define_module_function(mod, "puts", mkxpPuts); _rb_define_module_function(mod, "raw_key_states", mkxpRawKeyStates); + _rb_define_module_function(mod, "mouse_in_window", mkxpMouseInWindow); rb_gv_set("MKXP", Qtrue); } @@ -222,6 +224,13 @@ RB_METHOD(mkxpRawKeyStates) return str; } +RB_METHOD(mkxpMouseInWindow) +{ + RB_UNUSED_PARAM; + + return rb_bool_new(EventThread::mouseState.inWindow); +} + static VALUE rgssMainCb(VALUE block) { rb_funcall2(block, rb_intern("call"), 0, 0); diff --git a/src/input.cpp b/src/input.cpp index d7978bd..22dab5d 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -665,9 +665,6 @@ int Input::mouseX() { RGSSThreadData &rtData = shState->rtData(); - if (!EventThread::mouseState.inWindow) - return -20; - return (EventThread::mouseState.x - rtData.screenOffset.x) * rtData.sizeResoRatio.x; } @@ -675,9 +672,6 @@ int Input::mouseY() { RGSSThreadData &rtData = shState->rtData(); - if (!EventThread::mouseState.inWindow) - return -20; - return (EventThread::mouseState.y - rtData.screenOffset.y) * rtData.sizeResoRatio.y; }