From 6e176a454c6001eb727a53034f13b441c7986aae Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Tue, 7 Jul 2015 15:56:21 +0200 Subject: [PATCH 01/23] Constify --- src/graphics.cpp | 10 +++++----- src/scene.h | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/graphics.cpp b/src/graphics.cpp index 4d7eb59..5730cfb 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -169,15 +169,15 @@ public: } } - void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t) + void requestViewportRender(const Vec4 &c, const Vec4 &f, const Vec4 &t) { const IntRect &viewpRect = glState.scissorBox.get(); const IntRect &screenRect = geometry.rect; - bool toneRGBEffect = t.xyzHasEffect(); - bool toneGrayEffect = t.w != 0; - bool colorEffect = c.w > 0; - bool flashEffect = f.w > 0; + const bool toneRGBEffect = t.xyzHasEffect(); + const bool toneGrayEffect = t.w != 0; + const bool colorEffect = c.w > 0; + const bool flashEffect = f.w > 0; if (toneGrayEffect) { diff --git a/src/scene.h b/src/scene.h index edee331..7685407 100644 --- a/src/scene.h +++ b/src/scene.h @@ -55,7 +55,9 @@ public: virtual ~Scene(); virtual void composite(); - virtual void requestViewportRender(Vec4& /*color*/, Vec4& /*flash*/, Vec4& /*tone*/) {} + virtual void requestViewportRender(const Vec4& /* color */, + const Vec4& /* flash */, + const Vec4& /* tone */) {} const Geometry &getGeometry() const { return geometry; } From 9acdd206f65a70e590705aceca4b251535aed380 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Tue, 7 Jul 2015 15:59:10 +0200 Subject: [PATCH 02/23] Vec4: Rename 'xyzHasEffect()' to something that makes sense --- src/etc-internal.h | 2 +- src/graphics.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/etc-internal.h b/src/etc-internal.h index c9bd520..9bab3a8 100644 --- a/src/etc-internal.h +++ b/src/etc-internal.h @@ -61,7 +61,7 @@ struct Vec4 return (x == other.x && y == other.y && z == other.z && w == other.w); } - bool xyzHasEffect() const + bool xyzNotNull() const { return (x != 0.0 || y != 0.0 || z != 0.0); } diff --git a/src/graphics.cpp b/src/graphics.cpp index 5730cfb..74e97a3 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -174,7 +174,7 @@ public: const IntRect &viewpRect = glState.scissorBox.get(); const IntRect &screenRect = geometry.rect; - const bool toneRGBEffect = t.xyzHasEffect(); + const bool toneRGBEffect = t.xyzNotNull(); const bool toneGrayEffect = t.w != 0; const bool colorEffect = c.w > 0; const bool flashEffect = f.w > 0; @@ -240,7 +240,7 @@ public: /* Then apply them using hardware blending */ gl.BlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ONE); - if (add.xyzHasEffect()) + if (add.xyzNotNull()) { gl.BlendEquation(GL_FUNC_ADD); shader.setColor(add); @@ -248,7 +248,7 @@ public: screenQuad.draw(); } - if (sub.xyzHasEffect()) + if (sub.xyzNotNull()) { gl.BlendEquation(GL_FUNC_REVERSE_SUBTRACT); shader.setColor(sub); From 1e9e24e45c80af732559cdfd55590e06efe37f26 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 9 Jul 2015 12:33:55 +0200 Subject: [PATCH 03/23] README: Add note about RGSS version support --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index fede712..d9f9c09 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ Matz's Ruby Interpreter, also called CRuby, is the most widely deployed version For a list of differences, see: http://stackoverflow.com/questions/21574/what-is-the-difference-between-ruby-1-8-and-ruby-1-9 +This binding supports RGSS1, RGSS2 and RGSS3. + ### mruby (Lightweight Ruby) Website: https://github.com/mruby/mruby @@ -29,6 +31,8 @@ Due to heavy differences between mruby and MRI as well as lacking modules, runni Some extensions to the standard classes/modules are provided, taking the RPG Maker XP helpfile as a quasi "reference". These include Marshal, File, FileTest and Time. +This binding only supports RGSS1. + **Important:** If you decide to use [mattn's oniguruma regexp gem](https://github.com/mattn/mruby-onig-regexp), don't forget to add `-lonig` to the linker flags to avoid ugly symbol overlaps with libc. ### null From 5382cc11a38d7dead059df3de367c0dcf59df1fa Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 9 Jul 2015 12:38:04 +0200 Subject: [PATCH 04/23] MidiSource: Close source SDL_RWops before throwing error --- src/midisource.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/midisource.cpp b/src/midisource.cpp index fdca2e4..9cd3a44 100644 --- a/src/midisource.cpp +++ b/src/midisource.cpp @@ -626,9 +626,20 @@ struct MidiSource : ALDataSource, MidiReadHandler std::vector<uint8_t> data(dataLen); if (SDL_RWread(&ops, &data[0], 1, dataLen) < dataLen) + { + SDL_RWclose(&ops); throw Exception(Exception::MKXPError, "Reading midi data failed"); + } - readMidi(this, data); + try + { + readMidi(this, data); + } + catch (const Exception &) + { + SDL_RWclose(&ops); + throw; + } synth = shState->midiState().allocateSynth(); From e4558c9dfbcf342b2d5591753fc7e1bedff41349 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 9 Jul 2015 12:58:01 +0200 Subject: [PATCH 05/23] Use FS::openReadRaw() where ext supplementing makes no sense Specifically, in places where the full filename is always supplied, eg. when reading .rxdata type files. --- binding-mri/filesystem-binding.cpp | 2 +- binding-mruby/binding-mruby.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/binding-mri/filesystem-binding.cpp b/binding-mri/filesystem-binding.cpp index 17cf50d..4bc5e03 100644 --- a/binding-mri/filesystem-binding.cpp +++ b/binding-mri/filesystem-binding.cpp @@ -46,7 +46,7 @@ fileIntForPath(const char *path, bool rubyExc) try { - shState->fileSystem().openRead(*ops, path); + shState->fileSystem().openReadRaw(*ops, path); } catch (const Exception &e) { diff --git a/binding-mruby/binding-mruby.cpp b/binding-mruby/binding-mruby.cpp index f895de3..867d2d6 100644 --- a/binding-mruby/binding-mruby.cpp +++ b/binding-mruby/binding-mruby.cpp @@ -266,7 +266,7 @@ runRMXPScripts(mrb_state *mrb, mrbc_context *ctx) mrb_state *scriptMrb = mrb_open(); SDL_RWops ops; - shState->fileSystem().openRead(ops, scriptPack.c_str()); + shState->fileSystem().openReadRaw(ops, scriptPack.c_str()); mrb_value scriptArray = mrb_nil_value(); std::string readError; From 533e69275abd9d30674da7f42ab506cc449d7b93 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 9 Jul 2015 14:53:59 +0200 Subject: [PATCH 06/23] Constify --- src/rgssad.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rgssad.cpp b/src/rgssad.cpp index e8606b9..17e8417 100644 --- a/src/rgssad.cpp +++ b/src/rgssad.cpp @@ -34,7 +34,7 @@ struct RGSS_entryData struct RGSS_entryHandle { - RGSS_entryData data; + const RGSS_entryData data; uint32_t currentMagic; uint64_t currentOffset; PHYSFS_Io *io; @@ -229,7 +229,7 @@ RGSS_ioSeek(PHYSFS_Io *self, PHYSFS_uint64 offset) static PHYSFS_sint64 RGSS_ioTell(PHYSFS_Io *self) { - RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque); + const RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque); return entry->currentOffset; } @@ -237,7 +237,7 @@ RGSS_ioTell(PHYSFS_Io *self) static PHYSFS_sint64 RGSS_ioLength(PHYSFS_Io *self) { - RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque); + const RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque); return entry->data.size; } @@ -245,7 +245,7 @@ RGSS_ioLength(PHYSFS_Io *self) static PHYSFS_Io* RGSS_ioDuplicate(PHYSFS_Io *self) { - RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque); + const RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque); RGSS_entryHandle *entryDup = new RGSS_entryHandle(*entry); PHYSFS_Io *dup = PHYSFS_ALLOC(PHYSFS_Io); @@ -448,7 +448,7 @@ RGSS_stat(void *opaque, const char *filename, PHYSFS_Stat *stat) if (hasFile) { - RGSS_entryData &entry = data->entryHash[filename]; + const RGSS_entryData &entry = data->entryHash[filename]; stat->filesize = entry.size; stat->filetype = PHYSFS_FILETYPE_REGULAR; From 54c1107f19c6aecde16bfe4eeb843112cc9a916a Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 9 Jul 2015 13:00:56 +0200 Subject: [PATCH 07/23] FileSystem: Fix file lookup if unrelated files with same name exist Before, even though we did match all possible extensions, we only took the first match and tried opening it. If we were looking for a .png image, but there was an unrelated .txt file with the same name (as it actually happens in RTPs), we would potentially see the .txt first, try opening it, and fail alltogether, even though the image file existed. Now we try opening all matching files until we find one that we can parse. This fixes #101. --- src/alstream.cpp | 92 +++++--- src/bitmap.cpp | 23 +- src/filesystem.cpp | 518 +++++++++++++++++++++---------------------- src/filesystem.h | 21 +- src/soundemitter.cpp | 70 +++--- 5 files changed, 399 insertions(+), 325 deletions(-) diff --git a/src/alstream.cpp b/src/alstream.cpp index 18799ff..2f1e39f 100644 --- a/src/alstream.cpp +++ b/src/alstream.cpp @@ -199,43 +199,73 @@ void ALStream::closeSource() delete source; } +struct ALStreamOpenHandler : FileSystem::OpenHandler +{ + SDL_RWops *srcOps; + bool looped; + ALDataSource *source; + std::string errorMsg; + + ALStreamOpenHandler(SDL_RWops &srcOps, bool looped) + : srcOps(&srcOps), looped(looped), source(0) + {} + + bool tryRead(SDL_RWops &ops, const char *ext) + { + /* Copy this because we need to keep it around, + * as we will continue reading data from it later */ + *srcOps = ops; + + /* Try to read ogg file signature */ + char sig[5] = { 0 }; + SDL_RWread(srcOps, sig, 1, 4); + SDL_RWseek(srcOps, 0, RW_SEEK_SET); + + try + { + if (!strcmp(sig, "OggS")) + { + source = createVorbisSource(*srcOps, looped); + return true; + } + + if (!strcmp(sig, "MThd")) + { + shState->midiState().initIfNeeded(shState->config()); + + if (HAVE_FLUID) + { + source = createMidiSource(*srcOps, looped); + return true; + } + } + + source = createSDLSource(*srcOps, ext, STREAM_BUF_SIZE, looped); + } + catch (const Exception &e) + { + /* All source constructors will close the passed ops + * before throwing errors */ + errorMsg = e.msg; + return false; + } + + return true; + } +}; + void ALStream::openSource(const std::string &filename) { - char ext[8]; - shState->fileSystem().openRead(srcOps, filename.c_str(), false, ext, sizeof(ext)); + ALStreamOpenHandler handler(srcOps, looped); + shState->fileSystem().openRead(handler, filename.c_str()); + source = handler.source; needsRewind.clear(); - /* Try to read ogg file signature */ - char sig[5] = { 0 }; - SDL_RWread(&srcOps, sig, 1, 4); - SDL_RWseek(&srcOps, 0, RW_SEEK_SET); - - try - { - if (!strcmp(sig, "OggS")) - { - source = createVorbisSource(srcOps, looped); - return; - } - - if (!strcmp(sig, "MThd")) - { - shState->midiState().initIfNeeded(shState->config()); - - if (HAVE_FLUID) - { - source = createMidiSource(srcOps, looped); - return; - } - } - - source = createSDLSource(srcOps, ext, STREAM_BUF_SIZE, looped); - } - catch (const Exception &e) + if (!source) { char buf[512]; - snprintf(buf, sizeof(buf), "Unable to decode audio stream: %s.%s: %s", - filename.c_str(), ext, e.msg.c_str()); + snprintf(buf, sizeof(buf), "Unable to decode audio stream: %s: %s", + filename.c_str(), handler.errorMsg.c_str()); Debug() << buf; } diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 2a51d6f..37b1af1 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -233,13 +233,26 @@ struct BitmapPrivate } }; +struct BitmapOpenHandler : FileSystem::OpenHandler +{ + SDL_Surface *surf; + + BitmapOpenHandler() + : surf(0) + {} + + bool tryRead(SDL_RWops &ops, const char *ext) + { + surf = IMG_LoadTyped_RW(&ops, 1, ext); + return surf != 0; + } +}; + Bitmap::Bitmap(const char *filename) { - SDL_RWops ops; - char ext[8]; - - shState->fileSystem().openRead(ops, filename, false, ext, sizeof(ext)); - SDL_Surface *imgSurf = IMG_LoadTyped_RW(&ops, 1, ext); + BitmapOpenHandler handler; + shState->fileSystem().openRead(handler, filename); + SDL_Surface *imgSurf = handler.surf; if (!imgSurf) throw Exception(Exception::SDLError, "Error loading image '%s': %s", diff --git a/src/filesystem.cpp b/src/filesystem.cpp index 6642d3b..fe5d403 100644 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -37,6 +37,7 @@ #include <string.h> #include <algorithm> #include <vector> +#include <stack> #ifdef __APPLE__ #include <iconv.h> @@ -249,201 +250,65 @@ strcpySafe(char *dst, const char *src, return cpyMax; } +/* Attempt to locate an extension string in a filename. + * Either a pointer into the input string pointing at the + * extension, or null is returned */ +static const char * +findExt(const char *filename) +{ + size_t len; + + for (len = strlen(filename); len > 0; --len) + { + if (filename[len] == '/') + return 0; + + if (filename[len] == '.') + return &filename[len+1]; + } + + return 0; +} + +static void +initReadOps(PHYSFS_File *handle, + SDL_RWops &ops, + bool freeOnClose) +{ + ops.size = SDL_RWopsSize; + ops.seek = SDL_RWopsSeek; + ops.read = SDL_RWopsRead; + ops.write = SDL_RWopsWrite; + + if (freeOnClose) + ops.close = SDL_RWopsCloseFree; + else + ops.close = SDL_RWopsClose; + + ops.type = SDL_RWOPS_PHYSFS; + ops.hidden.unknown.data1 = handle; +} + +static void strTolower(std::string &str) +{ + for (size_t i = 0; i < str.size(); ++i) + str[i] = tolower(str[i]); +} + const Uint32 SDL_RWOPS_PHYSFS = SDL_RWOPS_UNKNOWN+10; struct FileSystemPrivate { - /* Maps: lower case filepath without extension, - * To: mixed case full filepath - * This is for compatibility with games that take Windows' - * case insensitivity for granted */ + /* Maps: lower case full filepath, + * To: mixed case full filepath */ BoostHash<std::string, std::string> pathCache; + /* Maps: lower case directory path, + * To: list of lower case filenames */ + BoostHash<std::string, std::vector<std::string> > fileLists; + + /* This is for compatibility with games that take Windows' + * case insensitivity for granted */ bool havePathCache; - - /* Attempt to locate an extension string in a filename. - * Either a pointer into the input string pointing at the - * extension, or null is returned */ - const char *findExt(const char *filename) - { - size_t len; - - for (len = strlen(filename); len > 0; --len) - { - if (filename[len] == '/') - return 0; - - if (filename[len] == '.') - return &filename[len+1]; - } - - return 0; - } - - struct CompleteFilenameData - { - bool found; - /* Contains the incomplete filename we're looking for; - * when found, we write the complete filename into this - * same buffer */ - char *outBuf; - /* Length of incomplete file name */ - size_t filenameLen; - /* Maximum we can write into outBuf */ - size_t outBufN; - }; - - static void completeFilenameRegCB(void *data, const char *, - const char *fname) - { - CompleteFilenameData &d = *static_cast<CompleteFilenameData*>(data); - - if (d.found) - return; - - if (strncmp(d.outBuf, fname, d.filenameLen) != 0) - return; - - /* If fname matches up to a following '.' (meaning the rest is part - * of the extension), or up to a following '\0' (full match), we've - * found our file */ - switch (fname[d.filenameLen]) - { - case '.' : - /* Overwrite the incomplete file name we looked for with - * the full version containing any extensions */ - strcpySafe(d.outBuf, fname, d.outBufN, -1); - case '\0' : - d.found = true; - } - } - - bool completeFilenameReg(const char *filepath, - char *outBuffer, - size_t outN) - { - strcpySafe(outBuffer, filepath, outN, -1); - - size_t len = strlen(outBuffer); - char *delim; - - /* Find the deliminator separating directory and file name */ - for (delim = outBuffer + len; delim > outBuffer; --delim) - if (*delim == '/') - break; - - bool root = (delim == outBuffer); - CompleteFilenameData d; - - if (!root) - { - /* If we have such a deliminator, we set it to '\0' so we - * can pass the first half to PhysFS as the directory name, - * and compare all filenames against the second half */ - d.outBuf = delim+1; - d.filenameLen = len - (delim - outBuffer + 1); - - *delim = '\0'; - } - else - { - /* Otherwise the file is in the root directory */ - d.outBuf = outBuffer; - d.filenameLen = len - (delim - outBuffer); - } - - d.found = false; - d.outBufN = outN - (d.outBuf - outBuffer); - - PHYSFS_enumerateFilesCallback(root ? "" : outBuffer, completeFilenameRegCB, &d); - - if (!d.found) - return false; - - /* Now we put the deliminator back in to form the completed - * file path (if required) */ - if (delim != outBuffer) - *delim = '/'; - - return true; - } - - bool completeFilenamePC(const char *filepath, - char *outBuffer, - size_t outN) - { - std::string lowCase(filepath); - - for (size_t i = 0; i < lowCase.size(); ++i) - lowCase[i] = tolower(lowCase[i]); - - if (!pathCache.contains(lowCase)) - return false; - - const std::string &fullPath = pathCache[lowCase]; - strcpySafe(outBuffer, fullPath.c_str(), outN, fullPath.size()); - - return true; - } - - bool completeFilename(const char *filepath, - char *outBuffer, - size_t outN) - { - if (havePathCache) - return completeFilenamePC(filepath, outBuffer, outN); - else - return completeFilenameReg(filepath, outBuffer, outN); - } - - PHYSFS_File *openReadHandle(const char *filename, - char *extBuf, - size_t extBufN) - { - char found[512]; - - if (!completeFilename(filename, found, sizeof(found))) - throw Exception(Exception::NoFileError, "%s", filename); - - PHYSFS_File *handle = PHYSFS_openRead(found); - - if (!handle) - throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError()); - - if (!extBuf) - return handle; - - for (char *q = found+strlen(found); q > found; --q) - { - if (*q == '/') - break; - - if (*q != '.') - continue; - - strcpySafe(extBuf, q+1, extBufN, -1); - break; - } - - return handle; - } - - void initReadOps(PHYSFS_File *handle, - SDL_RWops &ops, - bool freeOnClose) - { - ops.size = SDL_RWopsSize; - ops.seek = SDL_RWopsSeek; - ops.read = SDL_RWopsRead; - ops.write = SDL_RWopsWrite; - - if (freeOnClose) - ops.close = SDL_RWopsCloseFree; - else - ops.close = SDL_RWopsClose; - - ops.type = SDL_RWOPS_PHYSFS; - ops.hidden.unknown.data1 = handle; - } }; FileSystem::FileSystem(const char *argv0, @@ -484,99 +349,105 @@ void FileSystem::addPath(const char *path) } } -#ifdef __APPLE__ -struct CacheEnumCBData +struct CacheEnumData { FileSystemPrivate *p; + std::stack<std::vector<std::string>*> fileLists; + +#ifdef __APPLE__ iconv_t nfd2nfc; + char buf[512]; +#endif - CacheEnumCBData(FileSystemPrivate *fsp) + CacheEnumData(FileSystemPrivate *p) + : p(p) { - p = fsp; +#ifdef __APPLE__ nfd2nfc = iconv_open("utf-8", "utf-8-mac"); +#endif } - ~CacheEnumCBData() + ~CacheEnumData() { +#ifdef __APPLE__ iconv_close(nfd2nfc); +#endif } - void nfcFromNfd(char *dst, const char *src, size_t dstSize) + /* Converts in-place */ + void toNFC(char *inout) { - size_t srcSize = strlen(src); +#ifdef __APPLE__ + size_t srcSize = strlen(inout); + size_t bufSize = sizeof(buf); + char *bufPtr = buf; + char *inoutPtr = inout; + /* Reserve room for null terminator */ - --dstSize; - /* iconv takes a char** instead of a const char**, even though - * the string data isn't written to. */ + --bufSize; + iconv(nfd2nfc, - const_cast<char**>(&src), &srcSize, - &dst, &dstSize); + &inoutPtr, &srcSize, + &bufPtr, &bufSize); /* Null-terminate */ - *dst = 0; + *bufPtr = 0; + strcpy(inout, buf); +#else + (void) inout; +#endif } }; -#endif static void cacheEnumCB(void *d, const char *origdir, const char *fname) { -#ifdef __APPLE__ - CacheEnumCBData *data = static_cast<CacheEnumCBData*>(d); - FileSystemPrivate *p = data->p; -#else - FileSystemPrivate *p = static_cast<FileSystemPrivate*>(d); -#endif + CacheEnumData &data = *static_cast<CacheEnumData*>(d); + char fullPath[512]; - char buf[512]; - - if (*origdir == '\0') - strncpy(buf, fname, sizeof(buf)); + if (!*origdir) + snprintf(fullPath, sizeof(fullPath), "%s", fname); else - snprintf(buf, sizeof(buf), "%s/%s", origdir, fname); + snprintf(fullPath, sizeof(fullPath), "%s/%s", origdir, fname); -#ifdef __APPLE__ - char bufNfc[sizeof(buf)]; - data->nfcFromNfd(bufNfc, buf, sizeof(bufNfc)); -#else - char *const bufNfc = buf; -#endif + /* Deal with OSX' weird UTF-8 standards */ + data.toNFC(fullPath); - char *ptr = bufNfc; + std::string mixedCase(fullPath); + std::string lowerCase = mixedCase; + strTolower(lowerCase); - /* Trim leading slash */ - if (*ptr == '/') - ++ptr; + PHYSFS_Stat stat; + PHYSFS_stat(fullPath, &stat); - std::string mixedCase(ptr); - - for (char *q = bufNfc; *q; ++q) - *q = tolower(*q); - - p->pathCache.insert(std::string(ptr), mixedCase); - - for (char *q = ptr+strlen(ptr); q > ptr; --q) + if (stat.filetype == PHYSFS_FILETYPE_DIRECTORY) { - if (*q == '/') - break; + /* Create a new list for this directory */ + std::vector<std::string> &list = data.p->fileLists[lowerCase]; - if (*q != '.') - continue; - - *q = '\0'; - p->pathCache.insert(std::string(ptr), mixedCase); + /* Iterate over its contents */ + data.fileLists.push(&list); + PHYSFS_enumerateFilesCallback(fullPath, cacheEnumCB, d); + data.fileLists.pop(); } + else + { + /* Get the file list for the directory we're currently + * traversing and append this filename to it */ + std::vector<std::string> &list = *data.fileLists.top(); + std::string lowerFilename(fname); + strTolower(lowerFilename); + list.push_back(lowerFilename); - PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, d); + /* Add the lower -> mixed mapping of the file's full path */ + data.p->pathCache.insert(lowerCase, mixedCase); + } } void FileSystem::createPathCache() { -#ifdef __APPLE__ - CacheEnumCBData data(p); + CacheEnumData data(p); + data.fileLists.push(&p->fileLists[""]); PHYSFS_enumerateFilesCallback("", cacheEnumCB, &data); -#else - PHYSFS_enumerateFilesCallback("", cacheEnumCB, p); -#endif p->havePathCache = true; } @@ -591,10 +462,9 @@ static void fontSetEnumCB(void *data, const char *, const char *fname) { FontSetsCBData *d = static_cast<FontSetsCBData*>(data); - FileSystemPrivate *p = d->p; /* Only consider filenames with font extensions */ - const char *ext = p->findExt(fname); + const char *ext = findExt(fname); if (!ext) return; @@ -618,7 +488,7 @@ static void fontSetEnumCB(void *data, const char *, return; SDL_RWops ops; - p->initReadOps(handle, ops, false); + initReadOps(handle, ops, false); d->sfs->initFontSetCB(ops, filename); @@ -632,15 +502,147 @@ void FileSystem::initFontSets(SharedFontState &sfs) PHYSFS_enumerateFilesCallback("Fonts", fontSetEnumCB, &d); } -void FileSystem::openRead(SDL_RWops &ops, - const char *filename, - bool freeOnClose, - char *extBuf, - size_t extBufN) +struct OpenReadEnumData { - PHYSFS_File *handle = p->openReadHandle(filename, extBuf, extBufN); + FileSystem::OpenHandler &handler; + SDL_RWops ops; - p->initReadOps(handle, ops, freeOnClose); + /* The filename (without directory) we're looking for */ + const char *filename; + size_t filenameN; + + /* Optional hash to translate full filepaths + * (used with path cache) */ + BoostHash<std::string, std::string> *pathTrans; + + /* Number of files we've attempted to read and parse */ + size_t matchCount; + bool stopSearching; + + /* In case of a PhysFS error, save it here so it + * doesn't get changed before we get back into our code */ + const char *physfsError; + + OpenReadEnumData(FileSystem::OpenHandler &handler, + const char *filename, size_t filenameN, + BoostHash<std::string, std::string> *pathTrans) + : handler(handler), filename(filename), filenameN(filenameN), + pathTrans(pathTrans), matchCount(0), stopSearching(false), + physfsError(0) + {} +}; + +static void openReadEnumCB(void *d, const char *dirpath, + const char *filename) +{ + OpenReadEnumData &data = *static_cast<OpenReadEnumData*>(d); + char buffer[512]; + const char *fullPath; + + if (data.stopSearching) + return; + + /* If there's not even a partial match, continue searching */ + if (strncmp(filename, data.filename, data.filenameN) != 0) + return; + + if (!*dirpath) + { + fullPath = filename; + } + else + { + snprintf(buffer, sizeof(buffer), "%s/%s", dirpath, filename); + fullPath = buffer; + } + + char last = filename[data.filenameN]; + + /* If fname matches up to a following '.' (meaning the rest is part + * of the extension), or up to a following '\0' (full match), we've + * found our file */ + if (last != '.' && last != '\0') + return; + + /* If the path cache is active, translate from lower case + * to mixed case path */ + if (data.pathTrans) + fullPath = (*data.pathTrans)[fullPath].c_str(); + + PHYSFS_File *phys = PHYSFS_openRead(fullPath); + + if (!phys) + { + /* Failing to open this file here means there must + * be a deeper rooted problem somewhere within PhysFS. + * Just abort alltogether. */ + data.stopSearching = true; + data.physfsError = PHYSFS_getLastError(); + + return; + } + + initReadOps(phys, data.ops, false); + + const char *ext = findExt(filename); + + if (data.handler.tryRead(data.ops, ext)) + data.stopSearching = true; + + ++data.matchCount; +} + +void FileSystem::openRead(OpenHandler &handler, const char *filename) +{ + char buffer[512]; + size_t len = strcpySafe(buffer, filename, sizeof(buffer), -1); + char *delim; + + if (p->havePathCache) + for (size_t i = 0; i < len; ++i) + buffer[i] = tolower(buffer[i]); + + /* Find the deliminator separating directory and file name */ + for (delim = buffer + len; delim > buffer; --delim) + if (*delim == '/') + break; + + const bool root = (delim == buffer); + + const char *file = buffer; + const char *dir = ""; + + if (!root) + { + /* Cut the buffer in half so we can use it + * for both filename and directory path */ + *delim = '\0'; + file = delim+1; + dir = buffer; + } + + OpenReadEnumData data(handler, file, len + buffer - delim - !root, + p->havePathCache ? &p->pathCache : 0); + + if (p->havePathCache) + { + /* Get the list of files contained in this directory + * and manually iterate over them */ + const std::vector<std::string> &fileList = p->fileLists[dir]; + + for (size_t i = 0; i < fileList.size(); ++i) + openReadEnumCB(&data, dir, fileList[i].c_str()); + } + else + { + PHYSFS_enumerateFilesCallback(dir, openReadEnumCB, &data); + } + + if (data.physfsError) + throw Exception(Exception::PHYSFSError, "PhysFS: %s", data.physfsError); + + if (data.matchCount == 0) + throw Exception(Exception::NoFileError, "%s", filename); } void FileSystem::openReadRaw(SDL_RWops &ops, @@ -650,12 +652,10 @@ void FileSystem::openReadRaw(SDL_RWops &ops, PHYSFS_File *handle = PHYSFS_openRead(filename); assert(handle); - p->initReadOps(handle, ops, freeOnClose); + initReadOps(handle, ops, freeOnClose); } bool FileSystem::exists(const char *filename) { - char found[512]; - - return p->completeFilename(filename, found, sizeof(found)); + return PHYSFS_exists(filename); } diff --git a/src/filesystem.h b/src/filesystem.h index a98d96d..1f9f79f 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -43,17 +43,28 @@ public: * available font assets */ void initFontSets(SharedFontState &sfs); - void openRead(SDL_RWops &ops, - const char *filename, - bool freeOnClose = false, - char *extBuf = 0, - size_t extBufN = 0); + struct OpenHandler + { + /* Try to read and interpret data provided from ops. + * If data cannot be parsed, return false, otherwise true. + * Can be called multiple times until a parseable file is found. + * It's the handler's responsibility to close every passed + * ops structure, even when data could not be parsed. + * After this function returns, ops becomes invalid, so don't take + * references to it. Instead, copy the structure without closing + * if you need to further read from it later. */ + virtual bool tryRead(SDL_RWops &ops, const char *ext) = 0; + }; + + void openRead(OpenHandler &handler, + const char *filename); /* Circumvents extension supplementing */ void openReadRaw(SDL_RWops &ops, const char *filename, bool freeOnClose = false); + /* Does not perform extension supplementing */ bool exists(const char *filename); private: diff --git a/src/soundemitter.cpp b/src/soundemitter.cpp index 3850c0b..b064fd1 100644 --- a/src/soundemitter.cpp +++ b/src/soundemitter.cpp @@ -184,6 +184,44 @@ void SoundEmitter::stop() AL::Source::stop(alSrcs[i]); } +struct SoundOpenHandler : FileSystem::OpenHandler +{ + SoundBuffer *buffer; + + SoundOpenHandler() + : buffer(0) + {} + + bool tryRead(SDL_RWops &ops, const char *ext) + { + Sound_Sample *sample = Sound_NewSample(&ops, ext, 0, STREAM_BUF_SIZE); + + if (!sample) + { + SDL_RWclose(&ops); + return false; + } + + /* Do all of the decoding in the handler so we don't have + * to keep the source ops around */ + uint32_t decBytes = Sound_DecodeAll(sample); + uint8_t sampleSize = formatSampleSize(sample->actual.format); + uint32_t sampleCount = decBytes / sampleSize; + + buffer = new SoundBuffer; + buffer->bytes = sampleSize * sampleCount; + + ALenum alFormat = chooseALFormat(sampleSize, sample->actual.channels); + + AL::Buffer::uploadData(buffer->alBuffer, alFormat, sample->buffer, + buffer->bytes, sample->actual.rate); + + Sound_FreeSample(sample); + + return true; + } +}; + SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename) { SoundBuffer *buffer = bufferHash.value(filename, 0); @@ -199,40 +237,22 @@ SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename) } else { - /* Buffer not in cashe, needs to be loaded */ - SDL_RWops dataSource; - char ext[8]; + /* Buffer not in cache, needs to be loaded */ + SoundOpenHandler handler; + shState->fileSystem().openRead(handler, filename.c_str()); + buffer = handler.buffer; - shState->fileSystem().openRead(dataSource, filename.c_str(), - false, ext, sizeof(ext)); - - Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, ext, 0, STREAM_BUF_SIZE); - - if (!sampleHandle) + if (!buffer) { char buf[512]; - snprintf(buf, sizeof(buf), "Unable to decode sound: %s.%s: %s", - filename.c_str(), ext, Sound_GetError()); + snprintf(buf, sizeof(buf), "Unable to decode sound: %s: %s", + filename.c_str(), Sound_GetError()); Debug() << buf; return 0; } - uint32_t decBytes = Sound_DecodeAll(sampleHandle); - uint8_t sampleSize = formatSampleSize(sampleHandle->actual.format); - uint32_t sampleCount = decBytes / sampleSize; - - buffer = new SoundBuffer; buffer->key = filename; - buffer->bytes = sampleSize * sampleCount; - - ALenum alFormat = chooseALFormat(sampleSize, sampleHandle->actual.channels); - - AL::Buffer::uploadData(buffer->alBuffer, alFormat, sampleHandle->buffer, - buffer->bytes, sampleHandle->actual.rate); - - Sound_FreeSample(sampleHandle); - uint32_t wouldBeBytes = bufferBytes + buffer->bytes; /* If memory limit is reached, delete lowest priority buffer From fe709b6010fe128e3756648e3af14db7ecae5b86 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Fri, 10 Jul 2015 04:51:29 +0200 Subject: [PATCH 08/23] Use vector math --- src/tilemapvx.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index 6291fd9..039bd2c 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -181,8 +181,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader void updatePosition() { - dispPos.x = -(offset.x - mapViewp.x * 32) + sceneOffset.x; - dispPos.y = -(offset.y - mapViewp.y * 32) + sceneOffset.y; + dispPos = -(offset - mapViewp.pos() * 32) + sceneOffset; } void updateMapViewport() From fe6799d00bae75c6d2ef9f9a6911f49acd983e0b Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Fri, 10 Jul 2015 04:58:28 +0200 Subject: [PATCH 09/23] TilemapVX: Fix map viewport calculation --- src/tilemapvx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index 039bd2c..57abe26 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -188,7 +188,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader { int tileOX, tileOY; - Vec2i offs(offset.x-sceneOffset.x, offset.y-sceneOffset.y); + Vec2i offs = offset + sceneGeo.orig; if (offs.x >= 0) tileOX = offs.x / 32; From 861d261af24540b4280acef4fbdffd47c0ea927e Mon Sep 17 00:00:00 2001 From: cremno <cremno@mail.ru> Date: Tue, 21 Jul 2015 07:27:53 +0200 Subject: [PATCH 10/23] add Sprite#{bush_opacity,bush_opacity=} --- binding-mri/sprite-binding.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/binding-mri/sprite-binding.cpp b/binding-mri/sprite-binding.cpp index 2404e4a..dc7f902 100644 --- a/binding-mri/sprite-binding.cpp +++ b/binding-mri/sprite-binding.cpp @@ -56,6 +56,7 @@ DEF_PROP_I(Sprite, Y) DEF_PROP_I(Sprite, OX) DEF_PROP_I(Sprite, OY) DEF_PROP_I(Sprite, BushDepth) +DEF_PROP_I(Sprite, BushOpacity) DEF_PROP_I(Sprite, Opacity) DEF_PROP_I(Sprite, BlendType) DEF_PROP_I(Sprite, WaveAmp) @@ -126,6 +127,8 @@ spriteBindingInit() _rb_define_method(klass, "width", spriteWidth); _rb_define_method(klass, "height", spriteHeight); + INIT_PROP_BIND( Sprite, BushOpacity, "bush_opacity" ); + INIT_PROP_BIND( Sprite, WaveAmp, "wave_amp" ); INIT_PROP_BIND( Sprite, WaveLength, "wave_length" ); INIT_PROP_BIND( Sprite, WaveSpeed, "wave_speed" ); From d1ee507ec46cc28597717175cd43d32f98fac577 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Sun, 12 Jul 2015 10:30:36 +0200 Subject: [PATCH 11/23] Vec2i, IntRect: Add unequal operator --- src/etc-internal.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/etc-internal.h b/src/etc-internal.h index 9bab3a8..6c66239 100644 --- a/src/etc-internal.h +++ b/src/etc-internal.h @@ -88,6 +88,11 @@ struct Vec2i return x == other.x && y == other.y; } + bool operator!=(const Vec2i &other) const + { + return !(*this == other); + } + Vec2i &operator+=(const Vec2i &value) { x += value.x; @@ -176,6 +181,11 @@ struct IntRect : SDL_Rect w == other.w && h == other.h); } + bool operator!=(const IntRect &other) const + { + return !(*this == other); + } + Vec2i pos() const { return Vec2i(x, y); From 384249c31afd14b7ab83bd846180b65a0240611d Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Tue, 14 Jul 2015 18:20:31 +0200 Subject: [PATCH 12/23] Unify float literals to use f suffix and avoid double promotions I might have missed some. --- src/al-util.h | 2 +- src/alstream.cpp | 8 ++++---- src/audio.cpp | 6 +++--- src/audiostream.cpp | 22 +++++++++++----------- src/bitmap.cpp | 24 ++++++++++++------------ src/etc-internal.h | 6 +++--- src/font.cpp | 2 +- src/graphics.cpp | 12 ++++++------ src/midisource.cpp | 6 +++--- src/plane.cpp | 4 ++-- src/settingsmenu.cpp | 6 +++--- src/sharedmidistate.h | 2 +- src/soundemitter.cpp | 4 ++-- src/sprite.cpp | 8 ++++---- src/tileatlasvx.cpp | 16 ++++++++-------- src/tilemap.cpp | 2 +- src/transform.h | 2 +- src/window.cpp | 4 ++-- src/windowvx.cpp | 6 +++--- 19 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/al-util.h b/src/al-util.h index 78ae615..51801e7 100644 --- a/src/al-util.h +++ b/src/al-util.h @@ -238,6 +238,6 @@ inline ALenum chooseALFormat(int sampleSize, int channelCount) #define AUDIO_SLEEP 10 #define STREAM_BUF_SIZE 32768 -#define GLOBAL_VOLUME 0.8 +#define GLOBAL_VOLUME 0.8f #endif // ALUTIL_H diff --git a/src/alstream.cpp b/src/alstream.cpp index 2f1e39f..487f09f 100644 --- a/src/alstream.cpp +++ b/src/alstream.cpp @@ -42,12 +42,12 @@ ALStream::ALStream(LoopMode loopMode, source(0), thread(0), preemptPause(false), - pitch(1.0) + pitch(1.0f) { alSrc = AL::Source::gen(); - AL::Source::setVolume(alSrc, 1.0); - AL::Source::setPitch(alSrc, 1.0); + AL::Source::setVolume(alSrc, 1.0f); + AL::Source::setPitch(alSrc, 1.0f); AL::Source::detachBuffer(alSrc); for (int i = 0; i < STREAM_BUFS; ++i) @@ -172,7 +172,7 @@ void ALStream::setPitch(float value) /* If the source supports setting pitch natively, * we don't have to do it via OpenAL */ if (source && source->setPitch(value)) - AL::Source::setPitch(alSrc, 1.0); + AL::Source::setPitch(alSrc, 1.0f); else AL::Source::setPitch(alSrc, value); } diff --git a/src/audio.cpp b/src/audio.cpp index 945aed0..d536c70 100644 --- a/src/audio.cpp +++ b/src/audio.cpp @@ -170,7 +170,7 @@ struct AudioPrivate else { /* BGM is stopped. -> MeNotPlaying */ - bgm.setVolume(AudioStream::External, 1.0); + bgm.setVolume(AudioStream::External, 1.0f); if (!bgm.noResumeStop) bgm.stream.play(); @@ -193,7 +193,7 @@ struct AudioPrivate if (bgm.stream.queryState() == ALStream::Stopped) { /* BGM stopped midway fade in. -> MeNotPlaying */ - bgm.setVolume(AudioStream::External, 1.0); + bgm.setVolume(AudioStream::External, 1.0f); meWatch.state = MeNotPlaying; bgm.unlockStream(); @@ -219,7 +219,7 @@ struct AudioPrivate if (vol >= 1) { /* BGM fully faded in. -> MeNotPlaying */ - vol = 1.0; + vol = 1.0f; meWatch.state = MeNotPlaying; } diff --git a/src/audiostream.cpp b/src/audiostream.cpp index ae572ef..1d96553 100644 --- a/src/audiostream.cpp +++ b/src/audiostream.cpp @@ -34,11 +34,11 @@ AudioStream::AudioStream(ALStream::LoopMode loopMode, noResumeStop(false), stream(loopMode, threadId) { - current.volume = 1.0; - current.pitch = 1.0; + current.volume = 1.0f; + current.pitch = 1.0f; for (size_t i = 0; i < VolumeTypeCount; ++i) - volumes[i] = 1.0; + volumes[i] = 1.0f; fade.thread = 0; fade.threadName = std::string("audio_fadeout (") + threadId + ")"; @@ -82,8 +82,8 @@ void AudioStream::play(const std::string &filename, lockStream(); - float _volume = clamp<int>(volume, 0, 100) / 100.f; - float _pitch = clamp<int>(pitch, 50, 150) / 100.f; + float _volume = clamp<int>(volume, 0, 100) / 100.0f; + float _pitch = clamp<int>(pitch, 50, 150) / 100.0f; ALStream::State sState = stream.queryState(); @@ -211,7 +211,7 @@ void AudioStream::fadeOut(int duration) } fade.active.set(); - fade.msStep = (1.0) / duration; + fade.msStep = 1.0f / duration; fade.reqFini.clear(); fade.reqTerm.clear(); fade.startTicks = SDL_GetTicks(); @@ -302,7 +302,7 @@ void AudioStream::fadeOutThread() lockStream(); uint32_t curDur = SDL_GetTicks() - fade.startTicks; - float resVol = 1.0 - (curDur*fade.msStep); + float resVol = 1.0f - (curDur*fade.msStep); ALStream::State state = stream.queryState(); @@ -313,7 +313,7 @@ void AudioStream::fadeOutThread() if (state != ALStream::Paused) stream.stop(); - setVolume(FadeOut, 1.0); + setVolume(FadeOut, 1.0f); unlockStream(); break; @@ -340,15 +340,15 @@ void AudioStream::fadeInThread() /* Fade in duration is always 1 second */ uint32_t cur = SDL_GetTicks() - fadeIn.startTicks; - float prog = cur / 1000.0; + float prog = cur / 1000.0f; ALStream::State state = stream.queryState(); if (state != ALStream::Playing - || prog >= 1.0 + || prog >= 1.0f || fadeIn.rqFini) { - setVolume(FadeIn, 1.0); + setVolume(FadeIn, 1.0f); unlockStream(); break; diff --git a/src/bitmap.cpp b/src/bitmap.cpp index 37b1af1..24fb70f 100644 --- a/src/bitmap.cpp +++ b/src/bitmap.cpp @@ -890,9 +890,9 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C SDL_Surface *out = SDL_CreateRGBSurface (0, in->w+1, in->h+1, fm.BitsPerPixel, fm.Rmask, fm.Gmask, fm.Bmask, fm.Amask); - float fr = c.r / 255.0; - float fg = c.g / 255.0; - float fb = c.b / 255.0; + float fr = c.r / 255.0f; + float fg = c.g / 255.0f; + float fb = c.b / 255.0f; /* We allocate an output surface one pixel wider and higher than the input, * (implicitly) blit a copy of the input with RGB values set to black into @@ -946,11 +946,11 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C continue; } - float fSrcA = srcA / 255.0; - float fShdA = shdA / 255.0; + float fSrcA = srcA / 255.0f; + float fShdA = shdA / 255.0f; /* Because opacity == 1, co1 == fSrcA */ - float co2 = fShdA * (1.0 - fSrcA); + float co2 = fShdA * (1.0f - fSrcA); /* Result alpha */ float fa = fSrcA + co2; /* Temp value to simplify arithmetic below */ @@ -959,10 +959,10 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C /* Result colors */ uint8_t r, g, b, a; - r = clamp<float>(fr * co3, 0, 1) * 255; - g = clamp<float>(fg * co3, 0, 1) * 255; - b = clamp<float>(fb * co3, 0, 1) * 255; - a = clamp<float>(fa, 0, 1) * 255; + r = clamp<float>(fr * co3, 0, 1) * 255.0f; + g = clamp<float>(fg * co3, 0, 1) * 255.0f; + b = clamp<float>(fb * co3, 0, 1) * 255.0f; + a = clamp<float>(fa, 0, 1) * 255.0f; *outP = SDL_MapRGBA(&fm, r, g, b, a); } @@ -1067,11 +1067,11 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align) Vec2i gpTexSize; shState->ensureTexSize(txtSurf->w, txtSurf->h, gpTexSize); - bool fastBlit = !p->touchesTaintedArea(posRect) && txtAlpha == 1.0; + bool fastBlit = !p->touchesTaintedArea(posRect) && txtAlpha == 1.0f; if (fastBlit) { - if (squeeze == 1.0 && !shState->config().subImageFix) + if (squeeze == 1.0f && !shState->config().subImageFix) { /* Even faster: upload directly to bitmap texture. * We have to make sure the posRect lies within the texture diff --git a/src/etc-internal.h b/src/etc-internal.h index 6c66239..6b010b3 100644 --- a/src/etc-internal.h +++ b/src/etc-internal.h @@ -63,7 +63,7 @@ struct Vec4 bool xyzNotNull() const { - return (x != 0.0 || y != 0.0 || z != 0.0); + return (x != 0.0f || y != 0.0f || z != 0.0f); } }; @@ -269,13 +269,13 @@ struct NormValue NormValue(int unNorm) : unNorm(unNorm), - norm(unNorm / 255.0) + norm(unNorm / 255.0f) {} void operator =(int value) { unNorm = clamp(value, 0, 255); - norm = unNorm / 255.0; + norm = unNorm / 255.0f; } bool operator ==(int value) const diff --git a/src/font.cpp b/src/font.cpp index 058dd21..560010c 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -174,7 +174,7 @@ _TTF_Font *SharedFontState::getFont(std::string family, // FIXME 0.9 is guesswork at this point // float gamma = (96.0/45.0)*(5.0/14.0)*(size-5); // font = TTF_OpenFontRW(ops, 1, gamma /** .90*/); - font = TTF_OpenFontRW(ops, 1, size* .90); + font = TTF_OpenFontRW(ops, 1, size* 0.90f); if (!font) throw Exception(Exception::SDLError, "%s", SDL_GetError()); diff --git a/src/graphics.cpp b/src/graphics.cpp index 74e97a3..956c4d9 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -281,9 +281,9 @@ public: void setBrightness(float norm) { - brightnessQuad.setColor(Vec4(0, 0, 0, 1.0 - norm)); + brightnessQuad.setColor(Vec4(0, 0, 0, 1.0f - norm)); - brightEffect = norm < 1.0; + brightEffect = norm < 1.0f; } void updateReso(int width, int height) @@ -736,7 +736,7 @@ void Graphics::transition(int duration, shader.setFrozenScene(p->frozenScene.tex); shader.setCurrentScene(p->currentScene.tex); shader.setTransMap(transMap->getGLTypes().tex); - shader.setVague(vague / 256.0); + shader.setVague(vague / 256.0f); shader.setTexSize(p->scRes); } else @@ -774,7 +774,7 @@ void Graphics::transition(int duration, p->checkSyncLock(); - const float prog = i * (1.0 / duration); + const float prog = i * (1.0f / duration); if (transMap) { @@ -852,7 +852,7 @@ void Graphics::fadeout(int duration) FBO::unbind(); float curr = p->brightness; - float diff = 255.0 - curr; + float diff = 255.0f - curr; for (int i = duration-1; i > -1; --i) { @@ -882,7 +882,7 @@ void Graphics::fadein(int duration) FBO::unbind(); float curr = p->brightness; - float diff = 255.0 - curr; + float diff = 255.0f - curr; for (int i = 1; i <= duration; ++i) { diff --git a/src/midisource.cpp b/src/midisource.cpp index 9cd3a44..3d569a7 100644 --- a/src/midisource.cpp +++ b/src/midisource.cpp @@ -320,7 +320,7 @@ readEvent(MidiReadHandler *handler, MemChunk &chunk, | (data[2] << 0x00); e.type = Tempo; - e.e.tempo.bpm = 60000000.0 / mpqn; + e.e.tempo.bpm = 60000000 / mpqn; } else if (metaType == 0x2F) { @@ -699,7 +699,7 @@ struct MidiSource : ALDataSource, MidiReadHandler void updatePlaybackSpeed(uint32_t bpm) { - float deltaLength = 60.0 / (dpb * bpm); + float deltaLength = 60.0f / (dpb * bpm); playbackSpeed = TICK_FRAMES / (deltaLength * freq); } @@ -910,7 +910,7 @@ struct MidiSource : ALDataSource, MidiReadHandler bool setPitch(float value) { // not completely correct, but close - pitchShift = round((value > 1.0 ? 14 : 24) * (value - 1.0)); + pitchShift = round((value > 1.0f ? 14 : 24) * (value - 1.0f)); return true; } diff --git a/src/plane.cpp b/src/plane.cpp index f275e85..e3de3a0 100644 --- a/src/plane.cpp +++ b/src/plane.cpp @@ -105,8 +105,8 @@ struct PlanePrivate return; /* Scaled (zoomed) bitmap dimensions */ - double sw = bitmap->width() * zoomX; - double sh = bitmap->height() * zoomY; + float sw = bitmap->width() * zoomX; + float sh = bitmap->height() * zoomY; /* Plane offset wrapped by scaled bitmap dims */ float wox = fwrap(ox, sw); diff --git a/src/settingsmenu.cpp b/src/settingsmenu.cpp index a14b488..6518d7f 100644 --- a/src/settingsmenu.cpp +++ b/src/settingsmenu.cpp @@ -764,13 +764,13 @@ void Widget::click(int x, int y, uint8_t button) } /* Ratio of cell area to total widget width */ -#define BW_CELL_R 0.75 +#define BW_CELL_R 0.75f void BindingWidget::drawHandler(SDL_Surface *surf) { const int cellW = (rect.w*BW_CELL_R) / 2; const int cellH = rect.h / 2; - const int cellOffX = (1.0-BW_CELL_R) * rect.w; + const int cellOffX = (1.0f-BW_CELL_R) * rect.w; const int cellOff[] = { @@ -860,7 +860,7 @@ int BindingWidget::cellIndex(int x, int y) const { const int cellW = (rect.w*BW_CELL_R) / 2; const int cellH = rect.h / 2; - const int cellOff = (1.0-BW_CELL_R) * rect.w; + const int cellOff = (1.0f-BW_CELL_R) * rect.w; if (x < cellOff) return -1; diff --git a/src/sharedmidistate.h b/src/sharedmidistate.h index 00de6dc..1692848 100644 --- a/src/sharedmidistate.h +++ b/src/sharedmidistate.h @@ -80,7 +80,7 @@ struct SharedMidiState return; flSettings = fluid.new_settings(); - fluid.settings_setnum(flSettings, "synth.gain", 1.0); + fluid.settings_setnum(flSettings, "synth.gain", 1.0f); fluid.settings_setnum(flSettings, "synth.sample-rate", SYNTH_SAMPLERATE); fluid.settings_setstr(flSettings, "synth.chorus.active", conf.midi.chorus ? "yes" : "no"); fluid.settings_setstr(flSettings, "synth.reverb.active", conf.midi.reverb ? "yes" : "no"); diff --git a/src/soundemitter.cpp b/src/soundemitter.cpp index b064fd1..74eaf03 100644 --- a/src/soundemitter.cpp +++ b/src/soundemitter.cpp @@ -123,8 +123,8 @@ void SoundEmitter::play(const std::string &filename, int volume, int pitch) { - float _volume = clamp<int>(volume, 0, 100) / 100.f; - float _pitch = clamp<int>(pitch, 50, 150) / 100.f; + float _volume = clamp<int>(volume, 0, 100) / 100.0f; + float _pitch = clamp<int>(pitch, 50, 150) / 100.0f; SoundBuffer *buffer = allocateBuffer(filename); diff --git a/src/sprite.cpp b/src/sprite.cpp index 0313444..760bb0b 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -109,7 +109,7 @@ struct SpritePrivate wave.amp = 0; wave.length = 180; wave.speed = 360; - wave.phase = 0.0; + wave.phase = 0.0f; wave.dirty = false; } @@ -129,7 +129,7 @@ struct SpritePrivate (srcRect->y + srcRect->height) + bitmap->height(); - efBushDepth = 1.0 - texBushDepth / bitmap->height(); + efBushDepth = 1.0f - texBushDepth / bitmap->height(); } void onSrcRectChange() @@ -194,7 +194,7 @@ struct SpritePrivate void emitWaveChunk(SVertex *&vert, float phase, int width, float zoomY, int chunkY, int chunkLength) { - float wavePos = phase + (chunkY / (float) wave.length) * M_PI * 2; + float wavePos = phase + (chunkY / (float) wave.length) * (float) (M_PI * 2); float chunkX = sin(wavePos) * wave.amp; FloatRect tex(0, chunkY / zoomY, width, chunkLength / zoomY); @@ -261,7 +261,7 @@ struct SpritePrivate wave.qArray.resize(!!firstLength + chunks + !!lastLength); SVertex *vert = &wave.qArray.vertices[0]; - float phase = (wave.phase * M_PI) / 180.f; + float phase = (wave.phase * (float) M_PI) / 180.0f; if (firstLength > 0) emitWaveChunk(vert, phase, width, zoomY, 0, firstLength); diff --git a/src/tileatlasvx.cpp b/src/tileatlasvx.cpp index 8f3ec47..2e1c176 100644 --- a/src/tileatlasvx.cpp +++ b/src/tileatlasvx.cpp @@ -51,14 +51,14 @@ extern const int autotileVXRectsBN; /* Waterfall (C) autotile patterns */ static const StaticRect autotileVXRectsC[] = { - { 32.5, 0.5, 15, 31 }, - { 16.5, 0.5, 15, 31 }, - { 0.0, 0.5, 15, 31 }, - { 16.5, 0.5, 15, 31 }, - { 32.5, 0.5, 15, 31 }, - { 48.5, 0.5, 15, 31 }, - { 0.0, 0.5, 15, 31 }, - { 48.5, 0.5, 15, 31 } + { 32.5f, 0.5f, 15.0f, 31.0f }, + { 16.5f, 0.5f, 15.0f, 31.0f }, + { 0.0f, 0.5f, 15.0f, 31.0f }, + { 16.5f, 0.5f, 15.0f, 31.0f }, + { 32.5f, 0.5f, 15.0f, 31.0f }, + { 48.5f, 0.5f, 15.0f, 31.0f }, + { 0.0f, 0.5f, 15.0f, 31.0f }, + { 48.5f, 0.5f, 15.0f, 31.0f } }; static elementsN(autotileVXRectsC); diff --git a/src/tilemap.cpp b/src/tilemap.cpp index d3cf437..f721e03 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -698,7 +698,7 @@ struct TilemapPrivate int tileY = tsInd / 8; Vec2i texPos = TileAtlas::tileToAtlasCoor(tileX, tileY, atlas.efTilesetH, atlas.size.y); - FloatRect texRect((float) texPos.x+.5, (float) texPos.y+.5, 31, 31); + FloatRect texRect((float) texPos.x+0.5f, (float) texPos.y+0.5f, 31, 31); FloatRect posRect(x*32, y*32, 32, 32); SVertex v[4]; diff --git a/src/transform.h b/src/transform.h index cefd09f..7a129f9 100644 --- a/src/transform.h +++ b/src/transform.h @@ -130,7 +130,7 @@ private: if (rotation < 0) rotation += 360; - float angle = rotation * 3.141592654f / 180.f; + float angle = rotation * 3.141592654f / 180.0f; float cosine = (float) cos(angle); float sine = (float) sin(angle); float sxc = scale.x * cosine; diff --git a/src/window.cpp b/src/window.cpp index a32481d..71a8cc9 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -642,7 +642,7 @@ struct WindowPrivate if (active && cursorVert.vert) { - float alpha = cursorAniAlpha[cursorAniAlphaIdx] / 255.0; + float alpha = cursorAniAlpha[cursorAniAlphaIdx] / 255.0f; cursorVert.setAlpha(alpha); @@ -651,7 +651,7 @@ struct WindowPrivate if (pause && pauseAniVert.vert) { - float alpha = pauseAniAlpha[pauseAniAlphaIdx] / 255.0; + float alpha = pauseAniAlpha[pauseAniAlphaIdx] / 255.0f; FloatRect frameRect = pauseAniSrc[pauseAniQuad[pauseAniQuadIdx]]; pauseAniVert.setAlpha(alpha); diff --git a/src/windowvx.cpp b/src/windowvx.cpp index 0bafb5b..02a70d9 100644 --- a/src/windowvx.cpp +++ b/src/windowvx.cpp @@ -482,7 +482,7 @@ struct WindowVXPrivate void updateBaseQuad() { const FloatRect tex(0, 0, geo.w, geo.h); - const FloatRect pos(0, (geo.h / 2.0) * (1 - openness.norm), + const FloatRect pos(0, (geo.h / 2.0f) * (1.0f - openness.norm), geo.w, geo.h * openness.norm); base.quad.setTexPosRect(tex, pos); @@ -633,7 +633,7 @@ struct WindowVXPrivate Quad::setTexRect(pauseVert, pauseSrc[pauseQuad[pauseQuadIdx]]); /* Set opacity */ - Quad::setColor(pauseVert, Vec4(1, 1, 1, pauseAlpha[pauseAlphaIdx] / 255.0)); + Quad::setColor(pauseVert, Vec4(1, 1, 1, pauseAlpha[pauseAlphaIdx] / 255.0f)); ctrlVertArrayDirty = true; } @@ -643,7 +643,7 @@ struct WindowVXPrivate if (cursorVert.count() == 0) return; - Vec4 color(1, 1, 1, cursorAlpha[cursorAlphaIdx] / 255.0); + Vec4 color(1, 1, 1, cursorAlpha[cursorAlphaIdx] / 255.0f); for (size_t i = 0; i < cursorVert.count(); ++i) Quad::setColor(&cursorVert.vertices[i*4], color); From 9a3dd2d554df7255b592bba00d5cfea065af475b Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 16 Jul 2015 18:41:48 +0200 Subject: [PATCH 13/23] Config: Enable smoothScaling by default There's really no reason not to. --- mkxp.conf.sample | 4 ++-- src/config.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mkxp.conf.sample b/mkxp.conf.sample index e128755..b88f216 100644 --- a/mkxp.conf.sample +++ b/mkxp.conf.sample @@ -57,9 +57,9 @@ # Apply linear interpolation when game screen # is upscaled -# (default: disabled) +# (default: enabled) # -# smoothScaling=false +# smoothScaling=true # Sync screen redraws to the monitor refresh rate diff --git a/src/config.cpp b/src/config.cpp index cbbbe99..9173acc 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -151,7 +151,7 @@ void Config::read(int argc, char *argv[]) PO_DESC(winResizable, bool, false) \ PO_DESC(fullscreen, bool, false) \ PO_DESC(fixedAspectRatio, bool, true) \ - PO_DESC(smoothScaling, bool, false) \ + PO_DESC(smoothScaling, bool, true) \ PO_DESC(vsync, bool, false) \ PO_DESC(defScreenW, int, 0) \ PO_DESC(defScreenH, int, 0) \ From 5aaeb0206ce512e0415afc23b6754285ce5726af Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 16 Jul 2015 18:44:03 +0200 Subject: [PATCH 14/23] Remove some stuff that was accidentally committed --- src/config.h | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/config.h b/src/config.h index eeaf46b..fc9bbda 100644 --- a/src/config.h +++ b/src/config.h @@ -25,49 +25,6 @@ #include <string> #include <vector> -struct TouchOverlay -{ - std::string image; - - struct Button - { - enum Shape - { - Rectangle, - Circle, - Triangle - }; - - std::string id; - std::string target; - Shape shape; - - int x; - int y; - - union - { - struct - { - int width; - int height; - } r; - - struct - { - int radius; - } c; - struct - { - int x1, y1; - int x2, y2; - } t; - } u; - }; - - std::vector<Button> buttons; -}; - struct Config { int rgssVersion; From dd7545fcf28a3b83ee1139762cb38f0c23d8729f Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Thu, 16 Jul 2015 19:05:15 +0200 Subject: [PATCH 15/23] TilemapVX: Clean up the horrible map viewport calculation code Also rename "offset" to "origin" which makes a lot more sense for ox/oy attributes. --- src/etc-internal.h | 5 ++++ src/tilemap-common.h | 7 +++++ src/tilemapvx.cpp | 71 +++++++++++++++----------------------------- 3 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/etc-internal.h b/src/etc-internal.h index 6b010b3..4cbc704 100644 --- a/src/etc-internal.h +++ b/src/etc-internal.h @@ -136,6 +136,11 @@ struct Vec2i return Vec2i(x % value, y % value); } + Vec2i operator&(unsigned value) const + { + return Vec2i(x & value, y & value); + } + Vec2i operator-() const { return Vec2i(-x, -y); diff --git a/src/tilemap-common.h b/src/tilemap-common.h index 45ee91c..76dcf15 100644 --- a/src/tilemap-common.h +++ b/src/tilemap-common.h @@ -46,6 +46,13 @@ wrap(int value, int range) return res < 0 ? res + range : res; } +static inline Vec2i +wrap(const Vec2i &value, int range) +{ + return Vec2i(wrap(value.x, range), + wrap(value.y, range)); +} + static inline int16_t tableGetWrapped(const Table &t, int x, int y, int z = 0) { diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index 57abe26..5773110 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -57,12 +57,12 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader Table *mapData; Table *flags; - Vec2i offset; + Vec2i origin; - Vec2i dispPos; - /* Map viewport position */ + /* Subregion of the map that is drawn to screen (map viewport) */ IntRect mapViewp; - Vec2i sceneOffset; + /* Position on screen the map subregion is drawn at */ + Vec2i dispPos; Scene::Geometry sceneGeo; std::vector<SVertex> groundVert; @@ -179,48 +179,29 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader TileAtlasVX::build(atlas, bitmaps); } - void updatePosition() - { - dispPos = -(offset - mapViewp.pos() * 32) + sceneOffset; - } - void updateMapViewport() { - int tileOX, tileOY; + IntRect newMvp; - Vec2i offs = offset + sceneGeo.orig; + const Vec2i combOrigin = origin + sceneGeo.orig; + const Vec2i geoSize = sceneGeo.rect.size(); - if (offs.x >= 0) - tileOX = offs.x / 32; - else - tileOX = -(-(offs.x-31) / 32); + /* Round the combined origin (which is in pixels) down to the nearest + * top left tile boundary, by masking off the lower 5 bits (2^5 = 32) */ + newMvp.setPos((combOrigin & ~(32-1)) / 32); - if (offs.y >= 0) - tileOY = offs.y / 32; - else - tileOY = -(-(offs.y-31) / 32); + /* Ensure that the size is big enough to cover the whole viewport, + * and add one tile row/column as a buffer for scrolling */ + newMvp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1)); - bool dirty = false; - - if (tileOX < mapViewp.x || tileOX > mapViewp.x) - { - mapViewp.x = tileOX; - dirty = true; - } - - if (tileOY < mapViewp.y || tileOY > mapViewp.y) - { - mapViewp.y = tileOY; - dirty = true; - } - - if (dirty) + if (newMvp != mapViewp) { + mapViewp = newMvp; + flashMap.setViewport(newMvp); buffersDirty = true; } - updatePosition(); - flashMap.setViewport(mapViewp); + dispPos = sceneGeo.rect.pos() - wrap(combOrigin, 32); } static size_t quadBytes(size_t quads) @@ -365,10 +346,6 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader void onGeometryChange(const Scene::Geometry &geo) { - const Vec2i geoSize = geo.rect.size(); - mapViewp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1)); - - sceneOffset = geo.offset(); sceneGeo = geo; buffersDirty = true; @@ -379,7 +356,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader /* TileAtlasVX::Reader */ void onQuads(const FloatRect *t, const FloatRect *p, - size_t n, bool overPlayer) + size_t n, bool overPlayer) { SVertex *vert = allocVert(overPlayer ? aboveVert : groundVert, n*4); @@ -466,8 +443,8 @@ TilemapVX::BitmapArray &TilemapVX::getBitmapArray() DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData) DEF_ATTR_RD_SIMPLE(TilemapVX, FlashData, Table*, p->flashMap.getData()) DEF_ATTR_RD_SIMPLE(TilemapVX, Flags, Table*, p->flags) -DEF_ATTR_RD_SIMPLE(TilemapVX, OX, int, p->offset.x) -DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->offset.y) +DEF_ATTR_RD_SIMPLE(TilemapVX, OX, int, p->origin.x) +DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->origin.y) Viewport *TilemapVX::getViewport() const { @@ -540,10 +517,10 @@ void TilemapVX::setOX(int value) { guardDisposed(); - if (p->offset.x == value) + if (p->origin.x == value) return; - p->offset.x = value; + p->origin.x = value; p->mapViewportDirty = true; } @@ -551,10 +528,10 @@ void TilemapVX::setOY(int value) { guardDisposed(); - if (p->offset.y == value) + if (p->origin.y == value) return; - p->offset.y = value; + p->origin.y = value; p->mapViewportDirty = true; } From 30465691ae3e9070880d780679b3fc15ab40e4ac Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Sun, 19 Jul 2015 17:30:25 +0200 Subject: [PATCH 16/23] Tilemap: Fix map viewport calculation Calculation was completely off as it didn't take into account the imposed viewport origin. All in all, similar fixes as the previous ones to TilemapVX. --- src/tilemap-common.h | 10 +++++++ src/tilemap.cpp | 62 ++++++++++++-------------------------------- src/tilemapvx.cpp | 4 +-- 3 files changed, 27 insertions(+), 49 deletions(-) diff --git a/src/tilemap-common.h b/src/tilemap-common.h index 76dcf15..028dfd7 100644 --- a/src/tilemap-common.h +++ b/src/tilemap-common.h @@ -61,6 +61,16 @@ tableGetWrapped(const Table &t, int x, int y, int z = 0) z); } +/* Calculate the tile x/y on which this pixel x/y lies */ +static inline Vec2i +getTilePos(const Vec2i &pixelPos) +{ + /* Round the pixel position down to the nearest top left + * tile boundary, by masking off the lower 5 bits (2^5 = 32). + * Then divide by 32 to convert into tile units. */ + return (pixelPos & ~(32-1)) / 32; +} + enum AtSubPos { TopLeft = 0, diff --git a/src/tilemap.cpp b/src/tilemap.cpp index f721e03..8b61ea7 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -236,7 +236,7 @@ struct TilemapPrivate Table *mapData; Table *priorities; bool visible; - Vec2i offset; + Vec2i origin; Vec2i dispPos; @@ -294,7 +294,6 @@ struct TilemapPrivate /* Used layers out of 'zlayers' (rest is hidden) */ size_t activeLayers; Scene::Geometry sceneGeo; - Vec2i sceneOffset; } elem; /* Affected by: autotiles, tileset */ @@ -394,7 +393,7 @@ struct TilemapPrivate void updateFlashMapViewport() { - flashMap.setViewport(IntRect(viewpPos.x, viewpPos.y, viewpW, viewpH)); + flashMap.setViewport(IntRect(viewpPos, Vec2i(viewpW, viewpH))); } void updateAtlasInfo() @@ -442,13 +441,8 @@ struct TilemapPrivate void updateSceneGeometry(const Scene::Geometry &geo) { - elem.sceneOffset = geo.offset(); elem.sceneGeo = geo; - } - - void updatePosition() - { - dispPos = -(offset - viewpPos * 32) + elem.sceneOffset; + mapViewportDirty = true; } void invalidateAtlasSize() @@ -898,38 +892,17 @@ struct TilemapPrivate void updateMapViewport() { - int tileOX, tileOY; + const Vec2i combOrigin = origin + elem.sceneGeo.orig; + const Vec2i mvpPos = getTilePos(combOrigin); - if (offset.x >= 0) - tileOX = offset.x / 32; - else - tileOX = -(-(offset.x-31) / 32); - - if (offset.y >= 0) - tileOY = offset.y / 32; - else - tileOY = -(-(offset.y-31) / 32); - - bool dirty = false; - - if (tileOX < viewpPos.x || tileOX + 21 > viewpPos.x + viewpW) - { - viewpPos.x = tileOX; - dirty = true; - } - - if (tileOY < viewpPos.y || tileOY + 16 > viewpPos.y + viewpH) - { - viewpPos.y = tileOY; - dirty = true; - } - - if (dirty) + if (mvpPos != viewpPos) { + viewpPos = mvpPos; buffersDirty = true; updateFlashMapViewport(); - updatePosition(); } + + dispPos = elem.sceneGeo.rect.pos() - wrap(combOrigin, 32); } void prepare() @@ -1024,7 +997,6 @@ void GroundLayer::drawInt() void GroundLayer::onGeometryChange(const Scene::Geometry &geo) { p->updateSceneGeometry(geo); - p->updatePosition(); } ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport) @@ -1072,7 +1044,7 @@ void ZLayer::drawInt() int ZLayer::calculateZ(TilemapPrivate *p, int index) { - return 32 * (index + p->viewpPos.y + 1) - p->offset.y; + return 32 * (index + p->viewpPos.y + 1) - p->origin.y; } void ZLayer::initUpdateZ() @@ -1172,8 +1144,8 @@ DEF_ATTR_RD_SIMPLE(Tilemap, MapData, Table*, p->mapData) DEF_ATTR_RD_SIMPLE(Tilemap, FlashData, Table*, p->flashMap.getData()) DEF_ATTR_RD_SIMPLE(Tilemap, Priorities, Table*, p->priorities) DEF_ATTR_RD_SIMPLE(Tilemap, Visible, bool, p->visible) -DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->offset.x) -DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->offset.y) +DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->origin.x) +DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->origin.y) void Tilemap::setTileset(Bitmap *value) { @@ -1259,11 +1231,10 @@ void Tilemap::setOX(int value) { guardDisposed(); - if (p->offset.x == value) + if (p->origin.x == value) return; - p->offset.x = value; - p->updatePosition(); + p->origin.x = value; p->mapViewportDirty = true; } @@ -1271,11 +1242,10 @@ void Tilemap::setOY(int value) { guardDisposed(); - if (p->offset.y == value) + if (p->origin.y == value) return; - p->offset.y = value; - p->updatePosition(); + p->origin.y = value; p->zOrderDirty = true; p->mapViewportDirty = true; } diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index 5773110..cd91c66 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -186,9 +186,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader const Vec2i combOrigin = origin + sceneGeo.orig; const Vec2i geoSize = sceneGeo.rect.size(); - /* Round the combined origin (which is in pixels) down to the nearest - * top left tile boundary, by masking off the lower 5 bits (2^5 = 32) */ - newMvp.setPos((combOrigin & ~(32-1)) / 32); + newMvp.setPos(getTilePos(combOrigin)); /* Ensure that the size is big enough to cover the whole viewport, * and add one tile row/column as a buffer for scrolling */ From 7017ca1c538ff7514c8ad62aa7bc3ccd3daf5243 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Sun, 19 Jul 2015 17:32:13 +0200 Subject: [PATCH 17/23] Use static lifetime for constant array --- src/tileatlasvx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tileatlasvx.cpp b/src/tileatlasvx.cpp index 2e1c176..663eca3 100644 --- a/src/tileatlasvx.cpp +++ b/src/tileatlasvx.cpp @@ -500,7 +500,7 @@ onTileA4(Reader &reader, int16_t tileID, Vec2i orig = blitsA4[0].dst; tileID -= 0x1700; - const int offY[] = { 0, 3, 5, 8, 10, 13 }; + static const int offY[] = { 0, 3, 5, 8, 10, 13 }; int patternID = tileID % 0x30; int autotileID = tileID / 0x30; From 4d97a17c44391a1eec40237f923866705471757d Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Sun, 19 Jul 2015 22:32:59 +0200 Subject: [PATCH 18/23] TilemapVX: Ensure legs of out-of-view table tiles are drawn --- src/tilemapvx.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index cd91c66..50d8df0 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -181,16 +181,20 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader void updateMapViewport() { + /* Note: We include one extra row at the top above + * the normal map viewport to ensure the legs of table + * tiles off screen are properly drawn */ + IntRect newMvp; const Vec2i combOrigin = origin + sceneGeo.orig; const Vec2i geoSize = sceneGeo.rect.size(); - newMvp.setPos(getTilePos(combOrigin)); + newMvp.setPos(getTilePos(combOrigin) - Vec2i(0, 1)); /* Ensure that the size is big enough to cover the whole viewport, * and add one tile row/column as a buffer for scrolling */ - newMvp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1)); + newMvp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1, 2)); if (newMvp != mapViewp) { @@ -199,7 +203,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader buffersDirty = true; } - dispPos = sceneGeo.rect.pos() - wrap(combOrigin, 32); + dispPos = sceneGeo.rect.pos() - wrap(combOrigin, 32) - Vec2i(0, 32); } static size_t quadBytes(size_t quads) From 7bf6eca3625cfbfe5db1350727c4e7dfa1bbd2ec Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Sun, 26 Jul 2015 23:56:50 +0200 Subject: [PATCH 19/23] EventThread: Comment out unneeded SDL2 constants --- src/eventthread.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/eventthread.cpp b/src/eventthread.cpp index df381e8..e3bf194 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -490,13 +490,13 @@ int EventThread::eventFilter(void *data, SDL_Event *event) Debug() << "SDL_APP_LOWMEMORY"; return 0; - case SDL_RENDER_TARGETS_RESET : - Debug() << "****** SDL_RENDER_TARGETS_RESET"; - return 0; +// case SDL_RENDER_TARGETS_RESET : +// Debug() << "****** SDL_RENDER_TARGETS_RESET"; +// return 0; - case SDL_RENDER_DEVICE_RESET : - Debug() << "****** SDL_RENDER_DEVICE_RESET"; - return 0; +// case SDL_RENDER_DEVICE_RESET : +// Debug() << "****** SDL_RENDER_DEVICE_RESET"; +// return 0; } return 1; From 8e411cbcfe4be1075798fe33f3ad2a789f06d165 Mon Sep 17 00:00:00 2001 From: Mook <mook@users.noreply.github.com> Date: Fri, 30 Oct 2015 08:01:36 -0700 Subject: [PATCH 20/23] Graphics: Stub out play_movie Some people are using it to detect the RGSS version. --- binding-mri/graphics-binding.cpp | 17 +++++++++++++++++ src/graphics.cpp | 5 +++++ src/graphics.h | 1 + 3 files changed, 23 insertions(+) diff --git a/binding-mri/graphics-binding.cpp b/binding-mri/graphics-binding.cpp index a585e17..6b39697 100644 --- a/binding-mri/graphics-binding.cpp +++ b/binding-mri/graphics-binding.cpp @@ -183,6 +183,18 @@ RB_METHOD(graphicsReset) return Qnil; } +RB_METHOD(graphicsPlayMovie) +{ + RB_UNUSED_PARAM; + + const char *filename; + rb_get_args(argc, argv, "z", &filename RB_ARG_END); + + shState->graphics().playMovie(filename); + + return Qnil; +} + DEF_GRA_PROP_I(FrameRate) DEF_GRA_PROP_I(FrameCount) DEF_GRA_PROP_I(Brightness) @@ -223,6 +235,11 @@ void graphicsBindingInit() INIT_GRA_PROP_BIND( Brightness, "brightness" ); } + if (rgssVer >= 3) + { + _rb_define_module_function(module, "play_movie", graphicsPlayMovie); + } + INIT_GRA_PROP_BIND( Fullscreen, "fullscreen" ); INIT_GRA_PROP_BIND( ShowCursor, "show_cursor" ); } diff --git a/src/graphics.cpp b/src/graphics.cpp index 956c4d9..fe51f74 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -957,6 +957,11 @@ void Graphics::resizeScreen(int width, int height) shState->eThread().requestWindowResize(width, height); } +void Graphics::playMovie(const char *filename) +{ + Debug() << "Graphics.playMovie(" << filename << ") not implemented"; +} + DEF_ATTR_RD_SIMPLE(Graphics, Brightness, int, p->brightness) void Graphics::setBrightness(int value) diff --git a/src/graphics.h b/src/graphics.h index e914178..aa30189 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -54,6 +54,7 @@ public: int width() const; int height() const; void resizeScreen(int width, int height); + void playMovie(const char *filename); void reset(); From 5d776319b56473f564c1230116b096b01699c260 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Tue, 5 Jan 2016 08:41:47 +0100 Subject: [PATCH 21/23] Font/MRI: Improve handling of (default_)name attributes More accurate behavior, such as Font objects properly inheriting their name attributes, and centralization of code for picking the first existing name from a passed string array. Also centralizes initial default_name population in core. Note: This currently breaks the mruby binding build. --- binding-mri/font-binding.cpp | 147 ++++++++++++++++++----------------- src/font.cpp | 86 ++++++++++++++------ src/font.h | 69 ++++++++-------- src/sharedstate.cpp | 2 +- 4 files changed, 175 insertions(+), 129 deletions(-) diff --git a/binding-mri/font-binding.cpp b/binding-mri/font-binding.cpp index 2a8856a..9a6e264 100644 --- a/binding-mri/font-binding.cpp +++ b/binding-mri/font-binding.cpp @@ -27,6 +27,29 @@ #include <string.h> + +static void +collectStrings(VALUE obj, std::vector<std::string> &out) +{ + if (RB_TYPE_P(obj, RUBY_T_STRING)) + { + out.push_back(RSTRING_PTR(obj)); + } + else if (RB_TYPE_P(obj, RUBY_T_ARRAY)) + { + for (long i = 0; i < RARRAY_LEN(obj); ++i) + { + VALUE str = rb_ary_entry(obj, i); + + /* Non-string objects are tolerated (ignored) */ + if (!RB_TYPE_P(str, RUBY_T_STRING)) + continue; + + out.push_back(RSTRING_PTR(str)); + } + } +} + DEF_TYPE(Font); RB_METHOD(fontDoesExist) @@ -48,12 +71,30 @@ RB_METHOD(FontSetName); RB_METHOD(fontInitialize) { - VALUE name = Qnil; + VALUE namesObj = Qnil; int size = 0; - rb_get_args(argc, argv, "|oi", &name, &size RB_ARG_END); + rb_get_args(argc, argv, "|oi", &namesObj, &size RB_ARG_END); - Font *f = new Font(0, size); + Font *f; + + if (NIL_P(namesObj)) + { + namesObj = rb_iv_get(rb_obj_class(self), "default_name"); + f = new Font(0, size); + } + else + { + std::vector<std::string> names; + collectStrings(namesObj, names); + + f = new Font(&names, size); + } + + /* This is semantically wrong; the new Font object should take + * a dup'ed object here in case of an array. Ditto for the setters. + * However the same bug/behavior exists in all RM versions. */ + rb_iv_set(self, "name", namesObj); setPrivateData(self, f); @@ -65,13 +106,6 @@ RB_METHOD(fontInitialize) if (rgssVer >= 3) wrapProperty(self, &f->getOutColor(), "out_color", ColorType); - if (NIL_P(name)) - name = rb_iv_get(rb_obj_class(self), "default_name"); - - /* Going over the 'name=' function automatically causes - * a possbile name array to be re-verified for existing fonts */ - FontSetName(1, &name, self); - return self; } @@ -105,57 +139,17 @@ RB_METHOD(FontGetName) return rb_iv_get(self, "name"); } -static void -fontSetNameHelper(VALUE self, int argc, VALUE *argv, - const char *nameIv, char *outBuf, size_t outLen) -{ - rb_check_argc(argc, 1); - - VALUE arg = argv[0]; - - // Fixme: in RGSS3, specifying "" (and only that) as font name results in - // no text being drawn (everything else is substituted with Arial I think) - strncpy(outBuf, "", outLen); - - if (RB_TYPE_P(arg, RUBY_T_STRING)) - { - strncpy(outBuf, RSTRING_PTR(arg), outLen); - } - else if (RB_TYPE_P(arg, RUBY_T_ARRAY)) - { - for (long i = 0; i < RARRAY_LEN(arg); ++i) - { - VALUE str = rb_ary_entry(arg, i); - - /* Non-string objects are tolerated (ignored) */ - if (!RB_TYPE_P(str, RUBY_T_STRING)) - continue; - - const char *family = RSTRING_PTR(str); - - /* We only set the core Font object's name attribute - * to the actually existing font name */ - if (!shState->fontState().fontPresent(family)) - continue; - - strncpy(outBuf, family, outLen); - } - } - - /* RMXP doesn't even care if the argument type is - * something other than string/array. Whatever... */ - rb_iv_set(self, nameIv, arg); -} - RB_METHOD(FontSetName) { Font *f = getPrivateData<Font>(self); - char result[256]; - fontSetNameHelper(self, argc, argv, "name", - result, sizeof(result)); + rb_check_argc(argc, 1); - f->setName(result); + std::vector<std::string> namesObj; + collectStrings(argv[0], namesObj); + + f->setName(namesObj); + rb_iv_set(self, "name", argv[0]); return argv[0]; } @@ -223,11 +217,15 @@ RB_METHOD(FontGetDefaultName) RB_METHOD(FontSetDefaultName) { - char result[256]; - fontSetNameHelper(self, argc, argv, "default_name", - result, sizeof(result)); + RB_UNUSED_PARAM; - Font::setDefaultName(result); + rb_check_argc(argc, 1); + + std::vector<std::string> namesObj; + collectStrings(argv[0], namesObj); + + Font::setDefaultName(namesObj, shState->fontState()); + rb_iv_set(self, "default_name", argv[0]); return argv[0]; } @@ -267,7 +265,24 @@ fontBindingInit() Font::initDefaultDynAttribs(); wrapProperty(klass, &Font::getDefaultColor(), "default_color", ColorType); - rb_iv_set(klass, "default_name", rb_str_new_cstr(Font::getDefaultName())); + + /* Initialize default names */ + const std::vector<std::string> &defNames = Font::getInitialDefaultNames(); + VALUE defNamesObj; + + if (defNames.size() == 1) + { + defNamesObj = rb_str_new_cstr(defNames[0].c_str()); + } + else + { + defNamesObj = rb_ary_new2(defNames.size()); + + for (size_t i = 0; i < defNames.size(); ++i) + rb_ary_push(defNamesObj, rb_str_new_cstr(defNames[i].c_str())); + } + + rb_iv_set(klass, "default_name", defNamesObj); if (rgssVer >= 3) wrapProperty(klass, &Font::getDefaultOutColor(), "default_out_color", ColorType); @@ -310,14 +325,4 @@ fontBindingInit() INIT_PROP_BIND(Font, Outline, "outline"); INIT_PROP_BIND(Font, OutColor, "out_color"); } - - if (rgssVer >= 2) - { - VALUE defNames = rb_ary_new2(3); - rb_ary_push(defNames, rb_str_new2("Verdana")); - rb_ary_push(defNames, rb_str_new2("Arial")); - rb_ary_push(defNames, rb_str_new2("Courier New")); - - FontSetDefaultName(1, &defNames, klass); - } } diff --git a/src/font.cpp b/src/font.cpp index 560010c..62ab3e8 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -184,7 +184,7 @@ _TTF_Font *SharedFontState::getFont(std::string family, return font; } -bool SharedFontState::fontPresent(std::string family) +bool SharedFontState::fontPresent(std::string family) const { /* Check for substitutions */ if (p->subs.contains(family)) @@ -202,6 +202,26 @@ _TTF_Font *SharedFontState::openBundled(int size) return TTF_OpenFontRW(ops, 1, size); } +void pickExistingFontName(const std::vector<std::string> &names, + std::string &out, + const SharedFontState &sfs) +{ + /* Note: In RMXP, a names array with no existing entry + * results in no text being drawn at all (same for "" and []); + * we can't replicate this in mkxp due to the default substitute. */ + + for (size_t i = 0; i < names.size(); ++i) + { + if (sfs.fontPresent(names[i])) + { + out = names[i]; + return; + } + } + + out = ""; +} + struct FontPrivate { @@ -229,15 +249,15 @@ struct FontPrivate static Color defaultColorTmp; static Color defaultOutColorTmp; + static std::vector<std::string> initialDefaultNames; + /* The actual font is opened as late as possible * (when it is queried by a Bitmap), prior it is * set to null */ TTF_Font *sdlFont; - FontPrivate(const char *name = 0, - int size = 0) - : name(name ? std::string(name) : defaultName), - size(size ? size : defaultSize), + FontPrivate(int size) + : size(size), bold(defaultBold), italic(defaultItalic), outline(defaultOutline), @@ -290,6 +310,8 @@ Color *FontPrivate::defaultOutColor = &FontPrivate::defaultOutColorTmp; Color FontPrivate::defaultColorTmp(255, 255, 255, 255); Color FontPrivate::defaultOutColorTmp(0, 0, 0, 128); +std::vector<std::string> FontPrivate::initialDefaultNames; + bool Font::doesExist(const char *name) { if (!name) @@ -298,10 +320,15 @@ bool Font::doesExist(const char *name) return shState->fontState().fontPresent(name); } -Font::Font(const char *name, +Font::Font(const std::vector<std::string> *names, int size) { - p = new FontPrivate(name, size); + p = new FontPrivate(size ? size : FontPrivate::defaultSize); + + if (names) + setName(*names); + else + p->name = FontPrivate::defaultName; } Font::Font(const Font &other) @@ -321,17 +348,9 @@ const Font &Font::operator=(const Font &o) return o; } -const char *Font::getName() const +void Font::setName(const std::vector<std::string> &names) { - return p->name.c_str(); -} - -void Font::setName(const char *value) -{ - if (p->name == value) - return; - - p->name = value; + pickExistingFontName(names, p->name, shState->fontState()); p->sdlFont = 0; } @@ -367,14 +386,15 @@ DEF_ATTR_SIMPLE_STATIC(Font, DefaultOutline, bool, FontPrivate::defaultOutli DEF_ATTR_SIMPLE_STATIC(Font, DefaultColor, Color&, *FontPrivate::defaultColor) DEF_ATTR_SIMPLE_STATIC(Font, DefaultOutColor, Color&, *FontPrivate::defaultOutColor) -const char *Font::getDefaultName() +void Font::setDefaultName(const std::vector<std::string> &names, + const SharedFontState &sfs) { - return FontPrivate::defaultName.c_str(); + pickExistingFontName(names, FontPrivate::defaultName, sfs); } -void Font::setDefaultName(const char *value) +const std::vector<std::string> &Font::getInitialDefaultNames() { - FontPrivate::defaultName = value; + return FontPrivate::initialDefaultNames; } void Font::initDynAttribs() @@ -393,8 +413,30 @@ void Font::initDefaultDynAttribs() FontPrivate::defaultOutColor = new Color(FontPrivate::defaultOutColorTmp); } -void Font::initDefaults() +void Font::initDefaults(const SharedFontState &sfs) { + std::vector<std::string> &names = FontPrivate::initialDefaultNames; + + switch (rgssVer) + { + case 1 : + // FIXME: Japanese version has "MS PGothic" instead + names.push_back("Arial"); + break; + + case 2 : + names.push_back("UmePlus Gothic"); + names.push_back("MS Gothic"); + names.push_back("Courier New"); + break; + + default: + case 3 : + names.push_back("VL Gothic"); + } + + setDefaultName(names, sfs); + FontPrivate::defaultOutline = (rgssVer >= 3 ? true : false); FontPrivate::defaultShadow = (rgssVer == 2 ? true : false); } diff --git a/src/font.h b/src/font.h index 73bb83f..6024007 100644 --- a/src/font.h +++ b/src/font.h @@ -25,6 +25,9 @@ #include "etc.h" #include "util.h" +#include <vector> +#include <string> + struct SDL_RWops; struct _TTF_Font; struct Config; @@ -47,7 +50,7 @@ public: _TTF_Font *getFont(std::string family, int size); - bool fontPresent(std::string family); + bool fontPresent(std::string family) const; static _TTF_Font *openBundled(int size); @@ -55,22 +58,6 @@ private: SharedFontStatePrivate *p; }; -/* Concerning Font::name/defaultName : - * In RGSS, this is not actually a string; any type of - * object is accepted, however anything but strings and - * arrays is ignored (and text drawing turns blank). - * Single strings are interpreted as font family names, - * and directly passed to the underlying C++ object; - * arrays however are searched for the first string - * object corresponding to a valid font family name, - * and rendering is done with that. In mkxp, we pass - * this first valid font family as the 'name' attribute - * back to the C++ object on assignment and object - * creation (in case Font.default_name is also an array). - * Invalid parameters (things other than strings or - * arrays not containing any valid family name) are - * passed back as "". */ - struct FontPrivate; class Font @@ -78,31 +65,43 @@ class Font public: static bool doesExist(const char *name); - Font(const char *name = 0, + Font(const std::vector<std::string> *names = 0, int size = 0); + /* Clone constructor */ Font(const Font &other); + ~Font(); const Font &operator=(const Font &o); - DECL_ATTR( Name, const char * ) - DECL_ATTR( Size, int ) - DECL_ATTR( Bold, bool ) - DECL_ATTR( Italic, bool ) - DECL_ATTR( Color, Color& ) - DECL_ATTR( Shadow, bool ) - DECL_ATTR( Outline, bool ) - DECL_ATTR( OutColor, Color& ) + DECL_ATTR( Size, int ) + DECL_ATTR( Bold, bool ) + DECL_ATTR( Italic, bool ) + DECL_ATTR( Color, Color& ) + DECL_ATTR( Shadow, bool ) + DECL_ATTR( Outline, bool ) + DECL_ATTR( OutColor, Color& ) - DECL_ATTR_STATIC( DefaultName, const char* ) - DECL_ATTR_STATIC( DefaultSize, int ) - DECL_ATTR_STATIC( DefaultBold, bool ) - DECL_ATTR_STATIC( DefaultItalic, bool ) - DECL_ATTR_STATIC( DefaultColor, Color& ) - DECL_ATTR_STATIC( DefaultShadow, bool ) - DECL_ATTR_STATIC( DefaultOutline, bool ) - DECL_ATTR_STATIC( DefaultOutColor, Color& ) + DECL_ATTR_STATIC( DefaultSize, int ) + DECL_ATTR_STATIC( DefaultBold, bool ) + DECL_ATTR_STATIC( DefaultItalic, bool ) + DECL_ATTR_STATIC( DefaultColor, Color& ) + DECL_ATTR_STATIC( DefaultShadow, bool ) + DECL_ATTR_STATIC( DefaultOutline, bool ) + DECL_ATTR_STATIC( DefaultOutColor, Color& ) + + /* There is no point in providing getters for these, + * as the bindings will always return the stored native + * string/array object anyway. It's impossible to mirror + * in the C++ core. + * The core object picks the first existing name from the + * passed array and stores it internally (same for default). */ + void setName(const std::vector<std::string> &names); + static void setDefaultName(const std::vector<std::string> &names, + const SharedFontState &sfs); + + static const std::vector<std::string> &getInitialDefaultNames(); /* Assigns heap allocated objects to object properties; * using this in pure C++ will cause memory leaks @@ -110,7 +109,7 @@ public: void initDynAttribs(); static void initDefaultDynAttribs(); - static void initDefaults(); + static void initDefaults(const SharedFontState &sfs); /* internal */ _TTF_Font *getSdlFont(); diff --git a/src/sharedstate.cpp b/src/sharedstate.cpp index 023ff6b..9872af7 100644 --- a/src/sharedstate.cpp +++ b/src/sharedstate.cpp @@ -172,7 +172,6 @@ void SharedState::initInstance(RGSSThreadData *threadData) * Font depends on SharedState existing */ rgssVersion = threadData->config.rgssVersion; - Font::initDefaults(); _globalIBO = new GlobalIBO(); _globalIBO->ensureSize(1); @@ -183,6 +182,7 @@ void SharedState::initInstance(RGSSThreadData *threadData) try { SharedState::instance = new SharedState(threadData); + Font::initDefaults(instance->p->fontState); defaultFont = new Font(); } catch (const Exception &exc) From de74fc1bc3bfc1b63bedf3f9c5dc0f2872cf09d1 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Wed, 24 Feb 2016 17:44:42 +0100 Subject: [PATCH 22/23] EventThread: Fix mouse cursor not being hidden --- src/eventthread.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/eventthread.cpp b/src/eventthread.cpp index e3bf194..9217a4a 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -127,7 +127,9 @@ void EventThread::process(RGSSThreadData &rtData) bool displayingFPS = false; bool cursorInWindow = false; - bool windowFocused = false; + + /* SDL doesn't send an initial FOCUS_GAINED event */ + bool windowFocused = true; bool terminate = false; From 47ef36ca190a8be7449aae4717af9e70a74cbf19 Mon Sep 17 00:00:00 2001 From: Jonas Kulla <Nyocurio@gmail.com> Date: Wed, 24 Feb 2016 17:55:28 +0100 Subject: [PATCH 23/23] EventThread: ifdef out broken SDL function on OSX --- src/eventthread.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 9217a4a..00c1b3e 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -111,7 +111,11 @@ void EventThread::process(RGSSThreadData &rtData) UnidirMessage<Vec2i> &windowSizeMsg = rtData.windowSizeMsg; initALCFunctions(rtData.alcDev); + + // XXX this function breaks input focus on OSX +#ifndef __MACOSX__ SDL_SetEventFilter(eventFilter, &rtData); +#endif fullscreen = rtData.config.fullscreen; int toggleFSMod = rtData.config.anyAltToggleFS ? KMOD_ALT : KMOD_LALT;