mirror of
https://forgejo.xatacraft.ru/Sunshine/mkxp-sunshine.git
synced 2026-08-19 13:29:54 +00:00
Merge remote-tracking branch 'MKXP/master' into new-mkxp
This commit is contained in:
commit
8921e23ba5
25 changed files with 326 additions and 141 deletions
|
|
@ -205,6 +205,11 @@ set(MAIN_SOURCE
|
|||
src/fluid-fun.cpp
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND MAIN_HEADERS windows/resource.h)
|
||||
list(APPEND MAIN_SOURCE windows/resource.rc)
|
||||
endif()
|
||||
|
||||
source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
|
||||
|
||||
## Setup embedded source ##
|
||||
|
|
@ -405,6 +410,7 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE
|
|||
)
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
src
|
||||
windows
|
||||
${SIGCXX_INCLUDE_DIRS}
|
||||
${PIXMAN_INCLUDE_DIRS}
|
||||
${PHYSFS_INCLUDE_DIRS}
|
||||
|
|
|
|||
|
|
@ -115,6 +115,15 @@ DEF_PLAY_STOP( se )
|
|||
DEF_AUD_PROP_I(BGM_Volume)
|
||||
DEF_AUD_PROP_I(SFX_Volume)
|
||||
|
||||
RB_METHOD(audioSetupMidi)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
shState->audio().setupMidi();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(audioReset)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
|
@ -158,6 +167,8 @@ audioBindingInit()
|
|||
{
|
||||
BIND_POS( bgm );
|
||||
BIND_POS( bgs );
|
||||
|
||||
_rb_define_module_function(module, "setup_midi", audioSetupMidi);
|
||||
}
|
||||
|
||||
BIND_PLAY_STOP( se )
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ RB_METHOD(mriP);
|
|||
RB_METHOD(mkxpDataDirectory);
|
||||
RB_METHOD(mkxpPuts);
|
||||
RB_METHOD(mkxpRawKeyStates);
|
||||
RB_METHOD(mkxpMouseInWindow);
|
||||
|
||||
RB_METHOD(mriRgssMain);
|
||||
RB_METHOD(mriRgssStop);
|
||||
|
|
@ -140,8 +141,18 @@ 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);
|
||||
|
||||
/* Load global constants */
|
||||
rb_gv_set("MKXP", Qtrue);
|
||||
|
||||
VALUE debug = rb_bool_new(shState->config().editor.debug);
|
||||
if (rgssVer == 1)
|
||||
rb_gv_set("DEBUG", debug);
|
||||
else if (rgssVer >= 2)
|
||||
rb_gv_set("TEST", debug);
|
||||
|
||||
rb_gv_set("BTEST", rb_bool_new(shState->config().editor.battleTest));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -222,6 +233,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);
|
||||
|
|
@ -455,8 +473,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<std::string>::iterator i = conf.preloadScripts.begin();
|
||||
i != conf.preloadScripts.end(); ++i)
|
||||
runCustomScript(*i);
|
||||
|
||||
VALUE exc = rb_gv_get("$!");
|
||||
if (exc != Qnil)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ raiseRbExc(const Exception &exc);
|
|||
|
||||
/* 2.1 has added a new field (flags) to rb_data_type_t */
|
||||
#include <ruby/version.h>
|
||||
#if RUBY_API_VERSION_MINOR > 0
|
||||
#if RUBY_API_VERSION_MAJOR >= 2 && RUBY_API_VERSION_MINOR >= 1
|
||||
/* TODO: can mkxp use RUBY_TYPED_FREE_IMMEDIATELY here? */
|
||||
#define DEF_TYPE_FLAGS 0
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@
|
|||
# vsync=true
|
||||
|
||||
|
||||
# Override the game window title
|
||||
# (default: none)
|
||||
#
|
||||
# windowTitle=Custom Title
|
||||
|
||||
|
||||
# Enforce a static frame rate
|
||||
# (0 = disabled)
|
||||
#
|
||||
|
|
@ -89,6 +95,26 @@
|
|||
# subImageFix=false
|
||||
|
||||
|
||||
# Enable framebuffer blitting if the driver is
|
||||
# capable of it. Some drivers carry buggy
|
||||
# implementations of this functionality, so
|
||||
# disabling it can be used as a workaround
|
||||
# (default: enabled)
|
||||
#
|
||||
# enableBlitting=true
|
||||
|
||||
|
||||
# Limit the maximum size (width, height) of
|
||||
# most textures mkxp will create (exceptions are
|
||||
# rendering backbuffers and similar).
|
||||
# If set to 0, the hardware maximum is used.
|
||||
# This is useful for recording traces that can
|
||||
# be played back on machines with lower specs.
|
||||
# (default: 0)
|
||||
#
|
||||
# maxTextureSize=0
|
||||
|
||||
|
||||
# Set the base path of the game to '/path/to/game'
|
||||
# (default: executable directory)
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,48 +1,40 @@
|
|||
|
||||
uniform sampler2D inputTexture;
|
||||
uniform float hueAdjust;
|
||||
uniform sampler2D texture;
|
||||
uniform mediump float hueAdjust;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
/* Source: gamedev.stackexchange.com/a/59808/24839 */
|
||||
vec3 rgb2hsv(vec3 c)
|
||||
{
|
||||
const vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||
|
||||
float d = q.x - min(q.w, q.y);
|
||||
|
||||
/* Avoid divide-by-zero situations by adding a very tiny delta.
|
||||
* Since we always deal with underlying 8-Bit color values, this
|
||||
* should never mask a real value */
|
||||
const float eps = 1.0e-10;
|
||||
|
||||
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + eps)), d / (q.x + eps), q.x);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
void main ()
|
||||
{
|
||||
const vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
|
||||
const vec4 kRGBToI = vec4 (0.596, -0.275, -0.321, 0.0);
|
||||
const vec4 kRGBToQ = vec4 (0.212, -0.523, 0.311, 0.0);
|
||||
vec4 color = texture2D (texture, v_texCoord.xy);
|
||||
vec3 hsv = rgb2hsv(color.rgb);
|
||||
|
||||
const vec4 kYIQToR = vec4 (1.0, 0.956, 0.621, 0.0);
|
||||
const vec4 kYIQToG = vec4 (1.0, -0.272, -0.647, 0.0);
|
||||
const vec4 kYIQToB = vec4 (1.0, -1.107, 1.704, 0.0);
|
||||
hsv.x += hueAdjust;
|
||||
color.rgb = hsv2rgb(hsv);
|
||||
|
||||
/* Sample the input pixel */
|
||||
vec4 color = texture2D (inputTexture, v_texCoord.xy);
|
||||
|
||||
/* Convert to YIQ */
|
||||
float YPrime = dot (color, kRGBToYPrime);
|
||||
float I = dot (color, kRGBToI);
|
||||
float Q = dot (color, kRGBToQ);
|
||||
|
||||
/* Calculate the hue and chroma */
|
||||
float hue = atan (Q, I);
|
||||
float chroma = sqrt (I * I + Q * Q);
|
||||
|
||||
/* Make the user's adjustments */
|
||||
hue += hueAdjust;
|
||||
|
||||
/* Remember old I and color */
|
||||
float IOriginal = I;
|
||||
vec4 coOriginal = color;
|
||||
|
||||
/* Convert back to YIQ */
|
||||
Q = chroma * sin (hue);
|
||||
I = chroma * cos (hue);
|
||||
|
||||
/* Convert back to RGB */
|
||||
vec4 yIQ = vec4 (YPrime, I, Q, 0.0);
|
||||
color.r = dot (yIQ, kYIQToR);
|
||||
color.g = dot (yIQ, kYIQToG);
|
||||
color.b = dot (yIQ, kYIQToB);
|
||||
|
||||
/* Save the result */
|
||||
gl_FragColor = (IOriginal == 0.0) ? coOriginal : color;
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,9 +221,9 @@ struct BitmapPrivate
|
|||
surf = surfConv;
|
||||
}
|
||||
|
||||
void onModified()
|
||||
void onModified(bool freeSurface = true)
|
||||
{
|
||||
if (surface)
|
||||
if (surface && freeSurface)
|
||||
{
|
||||
SDL_FreeSurface(surface);
|
||||
surface = 0;
|
||||
|
|
@ -768,6 +768,14 @@ void Bitmap::clear()
|
|||
p->onModified();
|
||||
}
|
||||
|
||||
static uint32_t &getPixelAt(SDL_Surface *surf, SDL_PixelFormat *form, int x, int y)
|
||||
{
|
||||
size_t offset = x*form->BytesPerPixel + y*surf->pitch;
|
||||
uint8_t *bytes = (uint8_t*) surf->pixels + offset;
|
||||
|
||||
return *((uint32_t*) bytes);
|
||||
}
|
||||
|
||||
Color Bitmap::getPixel(int x, int y) const
|
||||
{
|
||||
guardDisposed();
|
||||
|
|
@ -790,9 +798,7 @@ Color Bitmap::getPixel(int x, int y) const
|
|||
glState.viewport.pop();
|
||||
}
|
||||
|
||||
size_t offset = x*p->format->BytesPerPixel + y*p->surface->pitch;
|
||||
uint8_t *bytes = (uint8_t*) p->surface->pixels + offset;
|
||||
uint32_t pixel = *((uint32_t*) bytes);
|
||||
uint32_t pixel = getPixelAt(p->surface, p->format, x, y);
|
||||
|
||||
return Color((pixel >> p->format->Rshift) & 0xFF,
|
||||
(pixel >> p->format->Gshift) & 0xFF,
|
||||
|
|
@ -819,7 +825,16 @@ void Bitmap::setPixel(int x, int y, const Color &color)
|
|||
|
||||
p->addTaintedArea(IntRect(x, y, 1, 1));
|
||||
|
||||
p->onModified();
|
||||
/* Setting just a single pixel is no reason to throw away the
|
||||
* whole cached surface; we can just apply the same change */
|
||||
|
||||
if (p->surface)
|
||||
{
|
||||
uint32_t &surfPixel = getPixelAt(p->surface, p->format, x, y);
|
||||
surfPixel = SDL_MapRGBA(p->format, pixel[0], pixel[1], pixel[2], pixel[3]);
|
||||
}
|
||||
|
||||
p->onModified(false);
|
||||
}
|
||||
|
||||
void Bitmap::hueChange(int hue)
|
||||
|
|
@ -839,13 +854,10 @@ void Bitmap::hueChange(int hue)
|
|||
quad.setTexPosRect(texRect, texRect);
|
||||
quad.setColor(Vec4(1, 1, 1, 1));
|
||||
|
||||
/* Calculate hue parameter */
|
||||
hue = wrapRange(hue, 0, 359);
|
||||
float hueAdj = -((M_PI * 2) / 360) * hue;
|
||||
|
||||
HueShader &shader = shState->shaders().hue;
|
||||
shader.bind();
|
||||
shader.setHueAdjust(hueAdj);
|
||||
/* Shader expects normalized value */
|
||||
shader.setHueAdjust(wrapRange(hue, 0, 359) / 360.0f);
|
||||
|
||||
FBO::bind(newTex.fbo);
|
||||
p->pushSetViewport(shader);
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ static std::string prefPath(const char *org, const char *app)
|
|||
return str;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::set<T> setFromVec(const std::vector<T> &vec)
|
||||
{
|
||||
return std::set<T>(vec.begin(), vec.end());
|
||||
}
|
||||
|
||||
typedef std::vector<std::string> StringVec;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
|
|
@ -66,11 +72,16 @@ void Config::read(int argc, char *argv[])
|
|||
PO_DESC(fixedAspectRatio, bool, true) \
|
||||
PO_DESC(smoothScaling, bool, true) \
|
||||
PO_DESC(vsync, bool, true) \
|
||||
PO_DESC(defScreenW, int, 0) \
|
||||
PO_DESC(defScreenH, int, 0) \
|
||||
PO_DESC(windowTitle, std::string, "") \
|
||||
PO_DESC(fixedFramerate, int, 0) \
|
||||
PO_DESC(frameSkip, bool, true) \
|
||||
PO_DESC(syncToRefreshrate, bool, false) \
|
||||
PO_DESC(solidFonts, bool, false) \
|
||||
PO_DESC(subImageFix, bool, false) \
|
||||
PO_DESC(enableBlitting, bool, true) \
|
||||
PO_DESC(maxTextureSize, int, 0) \
|
||||
PO_DESC(gameFolder, std::string, ".") \
|
||||
PO_DESC(allowSymlinks, bool, false) \
|
||||
PO_DESC(iconPath, std::string, "") \
|
||||
|
|
@ -80,6 +91,27 @@ void Config::read(int argc, char *argv[])
|
|||
// Not gonna take your shit boost
|
||||
#define GUARD_ALL( exp ) try { exp } catch(...) {}
|
||||
|
||||
editor.debug = false;
|
||||
editor.battleTest = false;
|
||||
|
||||
/* Read arguments sent from the editor */
|
||||
if (argc > 1)
|
||||
{
|
||||
std::string argv1 = argv[1];
|
||||
/* RGSS1 uses "debug", 2 and 3 use "test" */
|
||||
if (argv1 == "debug" || argv1 == "test")
|
||||
editor.debug = true;
|
||||
else if (argv1 == "btest")
|
||||
editor.battleTest = true;
|
||||
|
||||
/* Fix offset */
|
||||
if (editor.debug || editor.battleTest)
|
||||
{
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
|
||||
#define PO_DESC(key, type, def) (#key, po::value< type >()->default_value(def))
|
||||
|
||||
po::options_description podesc;
|
||||
|
|
@ -125,7 +157,7 @@ void Config::read(int argc, char *argv[])
|
|||
|
||||
PO_DESC_ALL;
|
||||
|
||||
GUARD_ALL( preloadScripts = vm["preloadScript"].as<StringVec>(); );
|
||||
GUARD_ALL( preloadScripts = setFromVec(vm["preloadScript"].as<StringVec>()); );
|
||||
|
||||
GUARD_ALL( fontSubs = vm["fontSub"].as<StringVec>(); );
|
||||
|
||||
|
|
|
|||
16
src/config.h
16
src/config.h
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
struct Config
|
||||
{
|
||||
|
|
@ -40,6 +41,7 @@ struct Config
|
|||
|
||||
int defScreenW;
|
||||
int defScreenH;
|
||||
std::string windowTitle;
|
||||
|
||||
int fixedFramerate;
|
||||
bool frameSkip;
|
||||
|
|
@ -48,6 +50,8 @@ struct Config
|
|||
bool solidFonts;
|
||||
|
||||
bool subImageFix;
|
||||
bool enableBlitting;
|
||||
int maxTextureSize;
|
||||
|
||||
std::string gameFolder;
|
||||
bool allowSymlinks;
|
||||
|
|
@ -60,12 +64,22 @@ struct Config
|
|||
int sourceCount;
|
||||
} SE;
|
||||
|
||||
std::vector<std::string> preloadScripts;
|
||||
bool useScriptNames;
|
||||
|
||||
std::string customScript;
|
||||
std::set<std::string> preloadScripts;
|
||||
std::vector<std::string> rtps;
|
||||
|
||||
std::vector<std::string> fontSubs;
|
||||
|
||||
std::vector<std::string> rubyLoadpaths;
|
||||
|
||||
/* Editor flags */
|
||||
struct {
|
||||
bool debug;
|
||||
bool battleTest;
|
||||
} editor;
|
||||
|
||||
/* Game INI contents */
|
||||
struct {
|
||||
std::string scripts;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <SDL_timer.h>
|
||||
#include <SDL_thread.h>
|
||||
#include <SDL_touch.h>
|
||||
#include <SDL_rect.h>
|
||||
|
||||
#include <al.h>
|
||||
#include <alc.h>
|
||||
|
|
@ -90,6 +91,7 @@ enum
|
|||
REQUEST_SETCURSORVISIBLE,
|
||||
|
||||
UPDATE_FPS,
|
||||
UPDATE_SCREEN_RECT,
|
||||
|
||||
EVENT_COUNT
|
||||
};
|
||||
|
|
@ -137,6 +139,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;
|
||||
|
|
@ -194,7 +198,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
delete sMenu;
|
||||
sMenu = 0;
|
||||
|
||||
updateCursorState(cursorInWindow && windowFocused);
|
||||
updateCursorState(cursorInWindow && windowFocused, gameScreen);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
|
@ -237,14 +241,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;
|
||||
|
||||
|
|
@ -259,13 +263,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;
|
||||
|
|
@ -292,7 +296,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
if (!sMenu)
|
||||
{
|
||||
sMenu = new SettingsMenu(rtData);
|
||||
updateCursorState(false);
|
||||
updateCursorState(false, gameScreen);
|
||||
}
|
||||
|
||||
sMenu->raise();
|
||||
|
|
@ -316,14 +320,14 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
if (fullscreen)
|
||||
{
|
||||
/* Prevent fullscreen flicker */
|
||||
strncpy(pendingTitle, rtData.config.game.title.c_str(),
|
||||
strncpy(pendingTitle, rtData.config.windowTitle.c_str(),
|
||||
sizeof(pendingTitle));
|
||||
havePendingTitle = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_SetWindowTitle(win, rtData.config.game.title.c_str());
|
||||
SDL_SetWindowTitle(win, rtData.config.windowTitle.c_str());
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -440,6 +444,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 :
|
||||
|
|
@ -471,7 +476,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
|
||||
case REQUEST_MESSAGEBOX :
|
||||
SDL_ShowSimpleMessageBox(event.user.code,
|
||||
rtData.config.game.title.c_str(),
|
||||
rtData.config.windowTitle.c_str(),
|
||||
(const char*) event.user.data1, win);
|
||||
free(event.user.data1);
|
||||
msgBoxDone.set();
|
||||
|
|
@ -479,7 +484,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
|
||||
case REQUEST_SETCURSORVISIBLE :
|
||||
showCursor = event.user.code;
|
||||
updateCursorState(cursorInWindow);
|
||||
updateCursorState(cursorInWindow, gameScreen);
|
||||
break;
|
||||
|
||||
case UPDATE_FPS :
|
||||
|
|
@ -490,7 +495,7 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
break;
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%s - %d FPS",
|
||||
rtData.config.game.title.c_str(), event.user.code);
|
||||
rtData.config.windowTitle.c_str(), event.user.code);
|
||||
|
||||
/* Updating the window title in fullscreen
|
||||
* mode seems to cause flickering */
|
||||
|
|
@ -504,6 +509,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<intptr_t>(event.user.data1);
|
||||
gameScreen.h = reinterpret_cast<intptr_t>(event.user.data2);
|
||||
updateCursorState(cursorInWindow, gameScreen);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -614,9 +628,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);
|
||||
|
|
@ -722,6 +740,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<void*>(screen.w);
|
||||
event.user.data2 = reinterpret_cast<void*>(screen.h);
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void SyncPoint::haltThreads()
|
||||
{
|
||||
if (mainSync.locked)
|
||||
|
|
|
|||
|
|
@ -106,12 +106,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;
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ struct FontSetsCBData
|
|||
};
|
||||
|
||||
static PHYSFS_EnumerateCallbackResult
|
||||
fontSetEnumCB(void *data, const char *, const char *fname)
|
||||
fontSetEnumCB (void *data, const char *dir, const char *fname)
|
||||
{
|
||||
FontSetsCBData *d = static_cast<FontSetsCBData*>(data);
|
||||
|
||||
|
|
@ -486,7 +486,7 @@ fontSetEnumCB(void *data, const char *, const char *fname)
|
|||
return PHYSFS_ENUM_STOP;
|
||||
|
||||
char filename[512];
|
||||
snprintf(filename, sizeof(filename), "Fonts/%s", fname);
|
||||
snprintf(filename, sizeof(filename), "%s/%s", dir, fname);
|
||||
|
||||
PHYSFS_File *handle = PHYSFS_openRead(filename);
|
||||
|
||||
|
|
@ -503,6 +503,26 @@ fontSetEnumCB(void *data, const char *, const char *fname)
|
|||
return PHYSFS_ENUM_OK;
|
||||
}
|
||||
|
||||
/* Basically just a case-insensitive search
|
||||
* for the folder "Fonts"... */
|
||||
static PHYSFS_EnumerateCallbackResult
|
||||
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_enumerate(fname, fontSetEnumCB, data);
|
||||
|
||||
return PHYSFS_ENUM_OK;
|
||||
}
|
||||
|
||||
void FileSystem::initFontSets(SharedFontState &sfs)
|
||||
{
|
||||
FontSetsCBData d = { p, &sfs };
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "shader.h"
|
||||
#include "etc.h"
|
||||
#include "gl-fun.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <SDL_rect.h>
|
||||
|
||||
|
|
@ -111,7 +112,7 @@ GLState::Caps::Caps()
|
|||
gl.GetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
|
||||
}
|
||||
|
||||
GLState::GLState()
|
||||
GLState::GLState(const Config &conf)
|
||||
{
|
||||
gl.Disable(GL_DEPTH_TEST);
|
||||
|
||||
|
|
@ -121,4 +122,7 @@ GLState::GLState()
|
|||
scissorTest.init(false);
|
||||
scissorBox.init(IntRect(0, 0, 640, 480));
|
||||
program.init(0);
|
||||
|
||||
if (conf.maxTextureSize > 0)
|
||||
caps.maxTexSize = conf.maxTextureSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <stack>
|
||||
#include <assert.h>
|
||||
|
||||
struct Config;
|
||||
|
||||
template<typename T>
|
||||
struct GLProperty
|
||||
{
|
||||
|
|
@ -130,7 +132,7 @@ public:
|
|||
|
||||
} caps;
|
||||
|
||||
GLState();
|
||||
GLState(const Config &conf);
|
||||
};
|
||||
|
||||
#endif // GLSTATE_H
|
||||
|
|
|
|||
|
|
@ -101,11 +101,9 @@ struct PingPong
|
|||
{
|
||||
screenW = width;
|
||||
screenH = height;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
TEX::bind(rt[i].tex);
|
||||
TEX::allocEmpty(width, height);
|
||||
}
|
||||
TEXFBO::allocEmpty(rt[i], width, height);
|
||||
}
|
||||
|
||||
void startRender()
|
||||
|
|
@ -486,9 +484,7 @@ struct GraphicsPrivate
|
|||
|
||||
bool frozen;
|
||||
TEXFBO frozenScene;
|
||||
TEXFBO currentScene;
|
||||
Quad screenQuad;
|
||||
TEXFBO transBuffer;
|
||||
|
||||
/* Global list of all live Disposables
|
||||
* (disposed on reset) */
|
||||
|
|
@ -516,17 +512,9 @@ struct GraphicsPrivate
|
|||
TEXFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
|
||||
TEXFBO::linkFBO(frozenScene);
|
||||
|
||||
TEXFBO::init(currentScene);
|
||||
TEXFBO::allocEmpty(currentScene, scRes.x, scRes.y);
|
||||
TEXFBO::linkFBO(currentScene);
|
||||
|
||||
FloatRect screenRect(0, 0, scRes.x, scRes.y);
|
||||
screenQuad.setTexPosRect(screenRect, screenRect);
|
||||
|
||||
TEXFBO::init(transBuffer);
|
||||
TEXFBO::allocEmpty(transBuffer, scRes.x, scRes.y);
|
||||
TEXFBO::linkFBO(transBuffer);
|
||||
|
||||
fpsLimiter.resetFrameAdjust();
|
||||
|
||||
obscuredTex = TEX::gen();
|
||||
|
|
@ -539,9 +527,6 @@ struct GraphicsPrivate
|
|||
~GraphicsPrivate()
|
||||
{
|
||||
TEXFBO::fini(frozenScene);
|
||||
TEXFBO::fini(currentScene);
|
||||
|
||||
TEXFBO::fini(transBuffer);
|
||||
}
|
||||
|
||||
void updateScreenResoRatio(RGSSThreadData *rtData)
|
||||
|
|
@ -584,6 +569,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -755,8 +743,15 @@ void Graphics::transition(int duration,
|
|||
|
||||
setBrightness(255);
|
||||
|
||||
/* The PP frontbuffer will hold the current scene after the
|
||||
* composition step. Since the backbuffer is unused during
|
||||
* the transition, we can reuse it as the target buffer for
|
||||
* the final rendered image. */
|
||||
TEXFBO ¤tScene = p->screen.getPP().frontBuffer();
|
||||
TEXFBO &transBuffer = p->screen.getPP().backBuffer();
|
||||
|
||||
/* Capture new scene */
|
||||
p->compositeToBuffer(p->currentScene);
|
||||
p->screen.composite();
|
||||
|
||||
/* If no transition bitmap is provided,
|
||||
* we can use a simplified shader */
|
||||
|
|
@ -769,7 +764,7 @@ void Graphics::transition(int duration,
|
|||
shader.bind();
|
||||
shader.applyViewportProj();
|
||||
shader.setFrozenScene(p->frozenScene.tex);
|
||||
shader.setCurrentScene(p->currentScene.tex);
|
||||
shader.setCurrentScene(currentScene.tex);
|
||||
shader.setTransMap(transMap->getGLTypes().tex);
|
||||
shader.setVague(vague / 256.0f);
|
||||
shader.setTexSize(p->scRes);
|
||||
|
|
@ -780,7 +775,7 @@ void Graphics::transition(int duration,
|
|||
shader.bind();
|
||||
shader.applyViewportProj();
|
||||
shader.setFrozenScene(p->frozenScene.tex);
|
||||
shader.setCurrentScene(p->currentScene.tex);
|
||||
shader.setCurrentScene(currentScene.tex);
|
||||
shader.setTexSize(p->scRes);
|
||||
}
|
||||
|
||||
|
|
@ -830,7 +825,7 @@ void Graphics::transition(int duration,
|
|||
|
||||
/* Draw the composed frame to a buffer first
|
||||
* (we need this because we're skipping PingPong) */
|
||||
FBO::bind(p->transBuffer.fbo);
|
||||
FBO::bind(transBuffer.fbo);
|
||||
FBO::clear();
|
||||
p->screenQuad.draw();
|
||||
|
||||
|
|
@ -841,7 +836,7 @@ void Graphics::transition(int duration,
|
|||
FBO::clear();
|
||||
|
||||
GLMeta::blitBeginScreen(Vec2i(p->winSize));
|
||||
GLMeta::blitSource(p->transBuffer);
|
||||
GLMeta::blitSource(transBuffer);
|
||||
p->metaBlitBufferFlippedScaled();
|
||||
GLMeta::blitEnd();
|
||||
|
||||
|
|
@ -984,17 +979,11 @@ void Graphics::resizeScreen(int width, int height)
|
|||
|
||||
p->screen.setResolution(width, height);
|
||||
|
||||
TEX::bind(p->frozenScene.tex);
|
||||
TEX::allocEmpty(width, height);
|
||||
TEX::bind(p->currentScene.tex);
|
||||
TEX::allocEmpty(width, height);
|
||||
TEXFBO::allocEmpty(p->frozenScene, width, height);
|
||||
|
||||
FloatRect screenRect(0, 0, width, height);
|
||||
p->screenQuad.setTexPosRect(screenRect, screenRect);
|
||||
|
||||
TEX::bind(p->transBuffer.tex);
|
||||
TEX::allocEmpty(width, height);
|
||||
|
||||
shState->eThread().requestWindowResize(width, height);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -742,9 +742,6 @@ int Input::mouseX()
|
|||
{
|
||||
RGSSThreadData &rtData = shState->rtData();
|
||||
|
||||
if (!EventThread::mouseState.inWindow)
|
||||
return -20;
|
||||
|
||||
return (EventThread::mouseState.x - rtData.screenOffset.x) * rtData.sizeResoRatio.x;
|
||||
}
|
||||
|
||||
|
|
@ -752,9 +749,6 @@ int Input::mouseY()
|
|||
{
|
||||
RGSSThreadData &rtData = shState->rtData();
|
||||
|
||||
if (!EventThread::mouseState.inWindow)
|
||||
return -20;
|
||||
|
||||
return (EventThread::mouseState.y - rtData.screenOffset.y) * rtData.sizeResoRatio.y;
|
||||
}
|
||||
|
||||
|
|
|
|||
58
src/main.cpp
58
src/main.cpp
|
|
@ -41,6 +41,10 @@
|
|||
|
||||
#include "binding.h"
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#include "resource.h"
|
||||
#endif
|
||||
|
||||
#include "icon.png.xxd"
|
||||
|
||||
#ifdef STEAM
|
||||
|
|
@ -106,6 +110,9 @@ int rgssThreadFun(void *userdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!conf.enableBlitting)
|
||||
gl.BlitFramebuffer = 0;
|
||||
|
||||
gl.ClearColor(0, 0, 0, 1);
|
||||
gl.Clear(GL_COLOR_BUFFER_BIT);
|
||||
SDL_GL_SwapWindow(win);
|
||||
|
|
@ -165,6 +172,24 @@ static void showInitError(const std::string &msg)
|
|||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "OneShot", 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");
|
||||
|
|
@ -218,7 +243,10 @@ int main(int argc, char *argv[])
|
|||
if (conf.screenMode)
|
||||
return screenMain(conf);
|
||||
|
||||
int imgFlags = IMG_INIT_PNG;
|
||||
if (conf.windowTitle.empty())
|
||||
conf.windowTitle = conf.game.title;
|
||||
|
||||
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
|
||||
if (IMG_Init(imgFlags) != imgFlags)
|
||||
{
|
||||
showInitError(std::string("Error initializing SDL_image: ") + SDL_GetError());
|
||||
|
|
@ -246,23 +274,13 @@ 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 | SDL_WINDOW_RESIZABLE; //| SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
|
||||
if (conf.fullscreen)
|
||||
winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
win = SDL_CreateWindow(conf.game.title.c_str(),
|
||||
win = SDL_CreateWindow(conf.windowTitle.c_str(),
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
conf.defScreenW, conf.defScreenH, winFlags);
|
||||
|
||||
|
|
@ -272,11 +290,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);
|
||||
|
||||
|
|
@ -345,13 +365,13 @@ int main(int argc, char *argv[])
|
|||
if (rtData.rqTermAck)
|
||||
SDL_WaitThread(rgssThread, 0);
|
||||
else
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(),
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(),
|
||||
"The RGSS script seems to be stuck and mkxp will now force quit", win);
|
||||
|
||||
if (!rtData.rgssErrorMsg.empty())
|
||||
{
|
||||
Debug() << rtData.rgssErrorMsg;
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.c_str(),
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.windowTitle.c_str(),
|
||||
rtData.rgssErrorMsg.c_str(), win);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -297,6 +297,8 @@ processDirectories(RGSS_archiveData *data, BoostSet<std::string> &topLevel,
|
|||
|
||||
if (slash)
|
||||
nameBuf[i] = '/';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for more entries */
|
||||
|
|
|
|||
|
|
@ -551,7 +551,6 @@ HueShader::HueShader()
|
|||
ShaderBase::init();
|
||||
|
||||
GET_U(hueAdjust);
|
||||
GET_U(inputTexture);
|
||||
}
|
||||
|
||||
void HueShader::setHueAdjust(float value)
|
||||
|
|
@ -559,11 +558,6 @@ void HueShader::setHueAdjust(float value)
|
|||
gl.Uniform1f(u_hueAdjust, value);
|
||||
}
|
||||
|
||||
void HueShader::setInputTexture(TEX::ID tex)
|
||||
{
|
||||
setTexUniform(u_inputTexture, 0, tex);
|
||||
}
|
||||
|
||||
|
||||
SimpleMatrixShader::SimpleMatrixShader()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -241,10 +241,9 @@ public:
|
|||
HueShader();
|
||||
|
||||
void setHueAdjust(float value);
|
||||
void setInputTexture(TEX::ID tex);
|
||||
|
||||
private:
|
||||
GLint u_hueAdjust, u_inputTexture;
|
||||
GLint u_hueAdjust;
|
||||
};
|
||||
|
||||
class SimpleMatrixShader : public ShaderBase
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ struct SharedStatePrivate
|
|||
input(*threadData),
|
||||
audio(*threadData),
|
||||
oneshot(*threadData),
|
||||
_glState(threadData->config),
|
||||
fontState(threadData->config),
|
||||
stampCounter(0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ struct SpritePrivate
|
|||
|
||||
void recomputeBushDepth()
|
||||
{
|
||||
if (!bitmap)
|
||||
if (nullOrDisposed(bitmap))
|
||||
return;
|
||||
|
||||
/* Calculate effective (normalized) bush depth */
|
||||
|
|
@ -139,12 +139,20 @@ struct SpritePrivate
|
|||
|
||||
void onSrcRectChange()
|
||||
{
|
||||
if (mirrored)
|
||||
quad.setTexRect(srcRect->toFloatRect().hFlipped());
|
||||
else
|
||||
quad.setTexRect(srcRect->toFloatRect());
|
||||
FloatRect rect = srcRect->toFloatRect();
|
||||
Vec2i bmSize;
|
||||
|
||||
quad.setPosRect(IntRect(0, 0, srcRect->width, srcRect->height));
|
||||
if (!nullOrDisposed(bitmap))
|
||||
bmSize = Vec2i(bitmap->width(), bitmap->height());
|
||||
|
||||
/* Clamp the rectangle so it doesn't reach outside
|
||||
* the bitmap bounds */
|
||||
rect.w = clamp<int>(rect.w, 0, bmSize.x-rect.x);
|
||||
rect.h = clamp<int>(rect.h, 0, bmSize.y-rect.y);
|
||||
|
||||
quad.setTexRect(mirrored ? rect.hFlipped() : rect);
|
||||
|
||||
quad.setPosRect(FloatRect(0, 0, rect.w, rect.h));
|
||||
recomputeBushDepth();
|
||||
|
||||
wave.dirty = true;
|
||||
|
|
|
|||
BIN
windows/icon.ico
Normal file
BIN
windows/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
1
windows/resource.h
Normal file
1
windows/resource.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
#define IDI_APPICON 101
|
||||
4
windows/resource.rc
Normal file
4
windows/resource.rc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
|
||||
IDI_APPICON ICON "icon.ico"
|
||||
Loading…
Reference in a new issue