Merge branch 'master' of /home/Ancurio/programming/C++/mkxp
Conflicts: src/config.h
This commit is contained in:
commit
d07309c8f9
|
@ -124,9 +124,9 @@ set(MAIN_HEADERS
|
|||
src/glstate.h
|
||||
src/quad.h
|
||||
src/tilemap.h
|
||||
src/flashmap.h
|
||||
src/tilemap-common.h
|
||||
src/graphics.h
|
||||
src/debuglogger.h
|
||||
src/gl-debug.h
|
||||
src/global-ibo.h
|
||||
src/exception.h
|
||||
src/filesystem.h
|
||||
|
@ -180,7 +180,7 @@ set(MAIN_SOURCE
|
|||
src/tilemap.cpp
|
||||
src/autotiles.cpp
|
||||
src/graphics.cpp
|
||||
src/debuglogger.cpp
|
||||
src/gl-debug.cpp
|
||||
src/etc.cpp
|
||||
src/config.cpp
|
||||
src/settingsmenu.cpp
|
||||
|
@ -210,16 +210,21 @@ source_group("MKXP Source" FILES ${MAIN_SOURCE} ${MAIN_HEADERS})
|
|||
## Setup embedded source ##
|
||||
|
||||
set(EMBEDDED_INPUT
|
||||
shader/common.h
|
||||
shader/transSimple.frag
|
||||
shader/trans.frag
|
||||
shader/hue.frag
|
||||
shader/sprite.frag
|
||||
shader/plane.frag
|
||||
shader/gray.frag
|
||||
shader/bitmapBlit.frag
|
||||
shader/flatColor.frag
|
||||
shader/simple.frag
|
||||
shader/simpleColor.frag
|
||||
shader/simpleAlpha.frag
|
||||
shader/simpleAlphaUni.frag
|
||||
shader/flashMap.frag
|
||||
shader/minimal.vert
|
||||
shader/simple.vert
|
||||
shader/simpleColor.vert
|
||||
shader/sprite.vert
|
||||
|
@ -230,6 +235,7 @@ set(EMBEDDED_INPUT
|
|||
shader/blurV.vert
|
||||
shader/simpleMatrix.vert
|
||||
assets/liberation.ttf
|
||||
assets/icon.png
|
||||
)
|
||||
|
||||
if (RGSS2)
|
||||
|
|
13
README.md
13
README.md
|
@ -4,8 +4,10 @@ mkxp is a project that seeks to provide a fully open source implementation of th
|
|||
|
||||
It is licensed under the GNU General Public License v2+.
|
||||
|
||||
[**Prebuilt binaries for Linux (32/64)**](http://ancurio.bplaced.net/mkxp/generic/)
|
||||
[**Prebuilt binaries for OSX by Ali**](https://app.box.com/mkxpmacbuilds)
|
||||
## Prebuilt binaries
|
||||
[**Linux (32bit/64bit)**](http://ancurio.bplaced.net/mkxp/generic/)
|
||||
[**OSX**](https://app.box.com/mkxpmacbuilds) by Ali
|
||||
[**Windows (mingw-w64 32bit)**](http://ancurio.bplaced.net/mkxp/mingw32/)
|
||||
|
||||
## Bindings
|
||||
Bindings provide the glue code for an interpreted language environment to run game scripts in. Currently there are three bindings:
|
||||
|
@ -85,13 +87,11 @@ The syntax is: `--<option>=<value>`
|
|||
|
||||
Example: `./mkxp --gameFolder="my game" --vsync=true --fixedFramerate=60`
|
||||
|
||||
## Midi music (*ALPHA STATUS*)
|
||||
## Midi music
|
||||
|
||||
mkxp doesn't come with a soundfont by default, so you will have to supply it yourself (set its path in the config). Playback has been tested and should work reasonably well with all RTP assets.
|
||||
|
||||
Known issues with midi playback:
|
||||
|
||||
* Some songs' instruments become mute after looping
|
||||
You can use this public domain soundfont: [GMGSx.sf2](https://www.dropbox.com/s/qxdvoxxcexsvn43/GMGSx.sf2?dl=0)
|
||||
|
||||
## Fonts
|
||||
|
||||
|
@ -101,7 +101,6 @@ If a requested font is not found, no error is generated. Instead, a built-in fon
|
|||
|
||||
## What doesn't work (yet)
|
||||
|
||||
* Text outline
|
||||
* Movie playback
|
||||
* wma audio files
|
||||
* The Win32API ruby class (for obvious reasons)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="100"
|
||||
height="100"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient3821">
|
||||
<stop
|
||||
id="stop3823"
|
||||
style="stop-color:#00ff88;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop3825"
|
||||
style="stop-color:#00ff86;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-323.76562,-436.67187)"
|
||||
id="layer1">
|
||||
<path
|
||||
d="m 373.76195,439.49229 c -26.05643,0 -47.17591,21.12683 -47.17591,47.18326 0,26.05643 21.11948,47.17591 47.17591,47.17591 26.05643,0 47.18326,-21.11948 47.18326,-47.17591 0,-26.05643 -21.12683,-47.18326 -47.18326,-47.18326 z m 0,26.80867 c 11.25095,0 20.37459,9.12364 20.37459,20.37459 0,11.25094 -9.12364,20.36724 -20.37459,20.36724 -11.25094,0 -20.36724,-9.1163 -20.36724,-20.36724 0,-11.25095 9.1163,-20.37459 20.36724,-20.37459 z"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2985"
|
||||
style="fill:#00ff87;fill-opacity:1;stroke:#000000;stroke-width:5.64083672;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -25,6 +25,7 @@
|
|||
#include "eventthread.h"
|
||||
#include "filesystem.h"
|
||||
#include "util.h"
|
||||
#include "sdl-util.h"
|
||||
#include "debugwriter.h"
|
||||
#include "graphics.h"
|
||||
#include "audio.h"
|
||||
|
@ -192,8 +193,11 @@ RB_METHOD(mriP)
|
|||
RB_METHOD(mkxpDataDirectory)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
const std::string &path = shState->config().customDataPath;
|
||||
const char *s = path.empty() ? "." : path.c_str();
|
||||
|
||||
return rb_str_new_cstr(shState->config().customDataPath.c_str());
|
||||
return rb_str_new_cstr(s);
|
||||
}
|
||||
|
||||
RB_METHOD(mkxpPuts)
|
||||
|
@ -336,7 +340,7 @@ static void runCustomScript(const std::string &filename)
|
|||
{
|
||||
std::string scriptData;
|
||||
|
||||
if (!readFile(filename.c_str(), scriptData))
|
||||
if (!readFileSDL(filename.c_str(), scriptData))
|
||||
{
|
||||
showMsg(std::string("Unable to open '") + filename + "'");
|
||||
return;
|
||||
|
@ -346,7 +350,7 @@ static void runCustomScript(const std::string &filename)
|
|||
newStringUTF8(filename.c_str(), filename.size()), NULL);
|
||||
}
|
||||
|
||||
VALUE kernelLoadDataInt(const char *filename);
|
||||
VALUE kernelLoadDataInt(const char *filename, bool rubyExc);
|
||||
|
||||
struct BacktraceData
|
||||
{
|
||||
|
@ -373,7 +377,19 @@ static void runRMXPScripts(BacktraceData &btData)
|
|||
return;
|
||||
}
|
||||
|
||||
VALUE scriptArray = kernelLoadDataInt(scriptPack.c_str());
|
||||
VALUE scriptArray;
|
||||
|
||||
/* We checked if Scripts.rxdata exists, but something might
|
||||
* still go wrong */
|
||||
try
|
||||
{
|
||||
scriptArray = kernelLoadDataInt(scriptPack.c_str(), false);
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
showMsg(std::string("Failed to read script data: ") + e.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!RB_TYPE_P(scriptArray, RUBY_T_ARRAY))
|
||||
{
|
||||
|
@ -540,6 +556,13 @@ static void showExc(VALUE exc, const BacktraceData &btData)
|
|||
|
||||
static void mriBindingExecute()
|
||||
{
|
||||
/* Normally only a ruby executable would do a sysinit,
|
||||
* but not doing it will lead to crashes due to closed
|
||||
* stdio streams on some platforms (eg. Windows) */
|
||||
int argc = 0;
|
||||
char **argv = 0;
|
||||
ruby_sysinit(&argc, &argv);
|
||||
|
||||
ruby_setup();
|
||||
rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding()));
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ fileIntFreeInstance(void *inst)
|
|||
DEF_TYPE_CUSTOMFREE(FileInt, fileIntFreeInstance);
|
||||
|
||||
static VALUE
|
||||
fileIntForPath(const char *path)
|
||||
fileIntForPath(const char *path, bool rubyExc)
|
||||
{
|
||||
SDL_RWops *ops = SDL_AllocRW();
|
||||
|
||||
|
@ -51,7 +51,11 @@ fileIntForPath(const char *path)
|
|||
catch (const Exception &e)
|
||||
{
|
||||
SDL_FreeRW(ops);
|
||||
raiseRbExc(e);
|
||||
|
||||
if (rubyExc)
|
||||
raiseRbExc(e);
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
|
||||
VALUE klass = rb_const_get(rb_cObject, rb_intern("FileInt"));
|
||||
|
@ -119,11 +123,11 @@ RB_METHOD(fileIntBinmode)
|
|||
}
|
||||
|
||||
VALUE
|
||||
kernelLoadDataInt(const char *filename)
|
||||
kernelLoadDataInt(const char *filename, bool rubyExc)
|
||||
{
|
||||
rb_gc_start();
|
||||
|
||||
VALUE port = fileIntForPath(filename);
|
||||
VALUE port = fileIntForPath(filename, rubyExc);
|
||||
|
||||
VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
|
||||
|
||||
|
@ -142,7 +146,7 @@ RB_METHOD(kernelLoadData)
|
|||
const char *filename;
|
||||
rb_get_args(argc, argv, "z", &filename RB_ARG_END);
|
||||
|
||||
return kernelLoadDataInt(filename);
|
||||
return kernelLoadDataInt(filename, true);
|
||||
}
|
||||
|
||||
RB_METHOD(kernelSaveData)
|
||||
|
|
|
@ -38,17 +38,22 @@ static int getButtonArg(int argc, VALUE *argv)
|
|||
{
|
||||
int num;
|
||||
|
||||
if (rgssVer >= 3)
|
||||
{
|
||||
ID sym;
|
||||
rb_get_args(argc, argv, "n", &sym RB_ARG_END);
|
||||
rb_check_argc(argc, 1);
|
||||
|
||||
if (FIXNUM_P(argv[0]))
|
||||
{
|
||||
num = FIX2INT(argv[0]);
|
||||
}
|
||||
else if (SYMBOL_P(argv[0]) && rgssVer >= 3)
|
||||
{
|
||||
VALUE symHash = getRbData()->buttoncodeHash;
|
||||
num = FIX2INT(rb_hash_lookup2(symHash, ID2SYM(sym), INT2FIX(Input::None)));
|
||||
num = FIX2INT(rb_hash_lookup2(symHash, argv[0], INT2FIX(Input::None)));
|
||||
}
|
||||
else
|
||||
{
|
||||
rb_get_args(argc, argv, "i", &num RB_ARG_END);
|
||||
// FIXME: RMXP allows only few more types that
|
||||
// don't make sense (symbols in pre 3, floats)
|
||||
num = 0;
|
||||
}
|
||||
|
||||
return num;
|
||||
|
|
|
@ -192,7 +192,7 @@ static void
|
|||
runCustomScript(mrb_state *mrb, mrbc_context *ctx, const char *filename)
|
||||
{
|
||||
/* Execute custom script */
|
||||
FILE *f = fopen(filename, "r");
|
||||
FILE *f = fopen(filename, "rb");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
|
@ -217,7 +217,7 @@ static void
|
|||
runMrbFile(mrb_state *mrb, const char *filename)
|
||||
{
|
||||
/* Execute compiled script */
|
||||
FILE *f = fopen(filename, "r");
|
||||
FILE *f = fopen(filename, "rb");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
|
|
|
@ -40,20 +40,26 @@ MRB_FUNCTION(inputUpdate)
|
|||
static mrb_int getButtonArg(mrb_state *mrb)
|
||||
{
|
||||
mrb_int num;
|
||||
mrb_value arg;
|
||||
|
||||
if (rgssVer >= 3)
|
||||
mrb_get_args(mrb, "o", &arg);
|
||||
|
||||
if (mrb_fixnum_p(arg))
|
||||
{
|
||||
num = mrb_fixnum(arg);
|
||||
}
|
||||
else if (mrb_symbol_p(arg) && rgssVer >= 3)
|
||||
{
|
||||
mrb_sym sym;
|
||||
mrb_get_args(mrb, "n", &sym);
|
||||
|
||||
mrb_value symHash = getMrbData(mrb)->buttoncodeHash;
|
||||
mrb_value numVal = mrb_hash_fetch(mrb, symHash, mrb_symbol_value(sym),
|
||||
mrb_value numVal = mrb_hash_fetch(mrb, symHash, arg,
|
||||
mrb_fixnum_value(Input::None));
|
||||
num = mrb_fixnum(numVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
mrb_get_args(mrb, "i", &num);
|
||||
// FIXME: RMXP allows only few more types that
|
||||
// don't make sense (symbols in pre 3, floats)
|
||||
num = 0;
|
||||
}
|
||||
|
||||
return num;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,14 @@
|
|||
# Lines starting with '#' are comments
|
||||
# Lines starting with '#' are comments.
|
||||
#
|
||||
# About filesystem paths specified in this config:
|
||||
# The "gameFolder" path is resolved either relative
|
||||
# to the directory containing the mkxp executable
|
||||
# (the default behavior), or relative to the current
|
||||
# working directory (when compiled with
|
||||
# -DWORKDIR_CURRENT). All other paths are resolved
|
||||
# relative to gameFolder and ignoring both RTPs and
|
||||
# encrypted archives.
|
||||
|
||||
|
||||
# Specify the RGSS version to run under.
|
||||
# Possible values are 0, 1, 2, 3. If set to 0,
|
||||
|
@ -17,6 +27,14 @@
|
|||
# debugMode=false
|
||||
|
||||
|
||||
# Continuously print average FPS to console.
|
||||
# This setting does not affect the window title
|
||||
# FPS display toggled via F2
|
||||
# (default: disabled)
|
||||
#
|
||||
# printFPS=false
|
||||
|
||||
|
||||
# Game window is resizable
|
||||
# (default: disabled)
|
||||
#
|
||||
|
@ -80,12 +98,32 @@
|
|||
# frameSkip=true
|
||||
|
||||
|
||||
# Use a fixed framerate that is approx. equal to the
|
||||
# native screen refresh rate. This is different from
|
||||
# "fixedFramerate" because the actual frame rate is
|
||||
# reported back to the game, ensuring correct timers.
|
||||
# If the screen refresh rate cannot be determined,
|
||||
# this option is force-disabled
|
||||
# (default: disabled)
|
||||
#
|
||||
# syncToRefreshrate=false
|
||||
|
||||
|
||||
# Don't use alpha blending when rendering text
|
||||
# (default: disabled)
|
||||
#
|
||||
# solidFonts=false
|
||||
|
||||
|
||||
# Work around buggy graphics drivers which don't
|
||||
# properly synchronize texture access, most
|
||||
# apparent when text doesn't show up or the map
|
||||
# tileset doesn't render at all
|
||||
# (default: disabled)
|
||||
#
|
||||
# subImageFix=false
|
||||
|
||||
|
||||
# Set the base path of the game to '/path/to/game'
|
||||
# (default: executable directory)
|
||||
#
|
||||
|
@ -218,6 +256,19 @@
|
|||
# SE.sourceCount=6
|
||||
|
||||
|
||||
# The Windows game executable name minus ".exe". By default
|
||||
# this is "Game", but some developers manually rename it.
|
||||
# mkxp needs this name because both the .ini (game
|
||||
# configuration) and .rgssad (encrypted data archive) must
|
||||
# carry the same name minus their extension, and we cannot
|
||||
# guess the executable's name.
|
||||
# You could just as well rename them both to "Game.ini" and
|
||||
# "Game.rgssad", but specifying the executable name here
|
||||
# is a tiny bit less intrusive.
|
||||
#
|
||||
# execName=Game
|
||||
|
||||
|
||||
# Give a hint on which language the game title as
|
||||
# specified in the Game.ini is, useful if the encoding
|
||||
# is being falsely detected. Relevant only if mkxp was
|
||||
|
|
14
mkxp.pro
14
mkxp.pro
|
@ -103,9 +103,9 @@ HEADERS += \
|
|||
src/glstate.h \
|
||||
src/quad.h \
|
||||
src/tilemap.h \
|
||||
src/flashmap.h \
|
||||
src/tilemap-common.h \
|
||||
src/graphics.h \
|
||||
src/debuglogger.h \
|
||||
src/gl-debug.h \
|
||||
src/global-ibo.h \
|
||||
src/exception.h \
|
||||
src/filesystem.h \
|
||||
|
@ -158,7 +158,7 @@ SOURCES += \
|
|||
src/tilemap.cpp \
|
||||
src/autotiles.cpp \
|
||||
src/graphics.cpp \
|
||||
src/debuglogger.cpp \
|
||||
src/gl-debug.cpp \
|
||||
src/etc.cpp \
|
||||
src/config.cpp \
|
||||
src/settingsmenu.cpp \
|
||||
|
@ -183,16 +183,21 @@ SOURCES += \
|
|||
src/fluid-fun.cpp
|
||||
|
||||
EMBED = \
|
||||
shader/common.h \
|
||||
shader/transSimple.frag \
|
||||
shader/trans.frag \
|
||||
shader/hue.frag \
|
||||
shader/sprite.frag \
|
||||
shader/plane.frag \
|
||||
shader/gray.frag \
|
||||
shader/bitmapBlit.frag \
|
||||
shader/flatColor.frag \
|
||||
shader/simple.frag \
|
||||
shader/simpleColor.frag \
|
||||
shader/simpleAlpha.frag \
|
||||
shader/simpleAlphaUni.frag \
|
||||
shader/flashMap.frag \
|
||||
shader/minimal.vert \
|
||||
shader/simple.vert \
|
||||
shader/simpleColor.vert \
|
||||
shader/sprite.vert \
|
||||
|
@ -202,7 +207,8 @@ EMBED = \
|
|||
shader/blurV.vert \
|
||||
shader/simpleMatrix.vert \
|
||||
shader/tilemapvx.vert \
|
||||
assets/liberation.ttf
|
||||
assets/liberation.ttf \
|
||||
assets/icon.png
|
||||
|
||||
SHARED_FLUID {
|
||||
DEFINES += SHARED_FLUID
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
--- a/common.mk
|
||||
+++ b/common.mk
|
||||
@@ -95,6 +95,7 @@ COMMONOBJS = array.$(OBJEXT) \
|
||||
vm_trace.$(OBJEXT) \
|
||||
thread.$(OBJEXT) \
|
||||
cont.$(OBJEXT) \
|
||||
+ ext/zlib/zlib.$(OBJEXT) \
|
||||
$(BUILTIN_ENCOBJS) \
|
||||
$(BUILTIN_TRANSOBJS) \
|
||||
$(MISSING)
|
||||
diff --git a/ruby-2.1.5.orig/configure b/ruby-2.1.5/configure
|
||||
index d0f1f68..45ab642 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -2838,6 +2838,8 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
|
||||
|
||||
|
||||
|
||||
+LIBS="$LIBS -lz"
|
||||
+
|
||||
{ # environment section
|
||||
|
||||
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -31,6 +31,8 @@ rm() {
|
||||
}
|
||||
])])])
|
||||
|
||||
+LIBS="$LIBS -lz"
|
||||
+
|
||||
{ # environment section
|
||||
|
||||
AC_ARG_WITH(baseruby,
|
||||
--- a/inits.c
|
||||
+++ b/inits.c
|
||||
@@ -61,5 +61,6 @@ rb_call_inits(void)
|
||||
CALL(Complex);
|
||||
CALL(version);
|
||||
CALL(vm_trace);
|
||||
+ CALL(zlib);
|
||||
}
|
||||
#undef CALL
|
|
@ -6,7 +6,7 @@ uniform sampler2D destination;
|
|||
|
||||
uniform vec4 subRect;
|
||||
|
||||
uniform float opacity;
|
||||
uniform lowp float opacity;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ varying vec2 v_blurCoord[2];
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 frag = vec4(0, 0, 0, 0);
|
||||
lowp vec4 frag = vec4(0, 0, 0, 0);
|
||||
|
||||
frag += texture2D(texture, v_texCoord);
|
||||
frag += texture2D(texture, v_blurCoord[0]);
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#ifdef GLSLES
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
/* Only the fragment shader has no default float precision */
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* Desktop GLSL doesn't know about these */
|
||||
#define highp
|
||||
#define mediump
|
||||
#define lowp
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
uniform float alpha;
|
||||
uniform lowp float alpha;
|
||||
|
||||
varying vec4 v_color;
|
||||
varying lowp vec4 v_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
uniform lowp vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = color;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
uniform sampler2D texture;
|
||||
uniform lowp float gray;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
const vec3 lumaF = vec3(.299, .587, .114);
|
||||
|
||||
void main()
|
||||
{
|
||||
/* Sample source color */
|
||||
vec4 frag = texture2D(texture, v_texCoord);
|
||||
|
||||
/* Apply gray */
|
||||
float luma = dot(frag.rgb, lumaF);
|
||||
frag.rgb = mix(frag.rgb, vec3(luma), gray);
|
||||
|
||||
gl_FragColor = frag;
|
||||
}
|
|
@ -29,7 +29,11 @@ void main ()
|
|||
/* Make the user's adjustments */
|
||||
hue += hueAdjust;
|
||||
|
||||
// Convert back to YIQ
|
||||
/* Remember old I and color */
|
||||
float IOriginal = I;
|
||||
vec4 coOriginal = color;
|
||||
|
||||
/* Convert back to YIQ */
|
||||
Q = chroma * sin (hue);
|
||||
I = chroma * cos (hue);
|
||||
|
||||
|
@ -40,5 +44,5 @@ void main ()
|
|||
color.b = dot (yIQ, kYIQToB);
|
||||
|
||||
/* Save the result */
|
||||
gl_FragColor = color;
|
||||
gl_FragColor = (IOriginal == 0.0) ? coOriginal : color;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
uniform mat4 projMat;
|
||||
attribute vec2 position;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projMat * vec4(position, 0, 1);
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
uniform sampler2D texture;
|
||||
|
||||
uniform vec4 tone;
|
||||
uniform lowp vec4 tone;
|
||||
|
||||
uniform float opacity;
|
||||
uniform vec4 color;
|
||||
uniform vec4 flash;
|
||||
uniform lowp float opacity;
|
||||
uniform lowp vec4 color;
|
||||
uniform lowp vec4 flash;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
uniform sampler2D texture;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
varying vec4 v_color;
|
||||
varying lowp vec4 v_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
uniform sampler2D texture;
|
||||
uniform lowp float alpha;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(texture, v_texCoord);
|
||||
gl_FragColor.a *= alpha;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
varying vec4 v_color;
|
||||
varying lowp vec4 v_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
@ -6,10 +6,10 @@ uniform vec2 translation;
|
|||
|
||||
attribute vec2 position;
|
||||
attribute vec2 texCoord;
|
||||
attribute vec4 color;
|
||||
attribute lowp vec4 color;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
varying vec4 v_color;
|
||||
varying lowp vec4 v_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
@ -6,10 +6,10 @@ uniform vec2 texSizeInv;
|
|||
|
||||
attribute vec2 position;
|
||||
attribute vec2 texCoord;
|
||||
attribute vec4 color;
|
||||
attribute lowp vec4 color;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
varying vec4 v_color;
|
||||
varying lowp vec4 v_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
|
||||
uniform sampler2D texture;
|
||||
|
||||
uniform vec4 tone;
|
||||
uniform lowp vec4 tone;
|
||||
|
||||
uniform float opacity;
|
||||
uniform vec4 color;
|
||||
uniform lowp float opacity;
|
||||
uniform lowp vec4 color;
|
||||
|
||||
uniform float bushDepth;
|
||||
uniform float bushOpacity;
|
||||
uniform lowp float bushOpacity;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
|
@ -32,7 +32,7 @@ void main()
|
|||
frag.rgb = mix(frag.rgb, color.rgb, color.a);
|
||||
|
||||
/* Apply bush alpha by mathematical if */
|
||||
float underBush = float(v_texCoord.y < bushDepth);
|
||||
lowp float underBush = float(v_texCoord.y < bushDepth);
|
||||
frag.a *= clamp(bushOpacity + underBush, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = frag;
|
||||
|
|
|
@ -18,8 +18,9 @@ const float atAniOffset = 32.0*3.0;
|
|||
void main()
|
||||
{
|
||||
vec2 tex = texCoord;
|
||||
if (tex.x <= atAreaW && tex.y <= atAreaH)
|
||||
tex.x += aniIndex * atAniOffset;
|
||||
|
||||
lowp float pred = float(tex.x <= atAreaW && tex.y <= atAreaH);
|
||||
tex.x += aniIndex * atAniOffset * pred;
|
||||
|
||||
gl_Position = projMat * vec4(position + translation, 0, 1);
|
||||
|
||||
|
|
|
@ -18,14 +18,15 @@ const float atAreaCW = 4.0*32.0;
|
|||
void main()
|
||||
{
|
||||
vec2 tex = texCoord;
|
||||
lowp float pred;
|
||||
|
||||
/* Type A autotiles shift horizontally */
|
||||
if (tex.x <= atAreaA.x && tex.y <= atAreaA.y)
|
||||
tex.x += aniOffset.x;
|
||||
pred = float(tex.x <= atAreaA.x && tex.y <= atAreaA.y);
|
||||
tex.x += aniOffset.x * pred;
|
||||
|
||||
/* Type C autotiles shift vertically */
|
||||
if (tex.x >= atAreaCX && tex.x <= (atAreaCX+atAreaCW) && tex.y <= atAreaA.y)
|
||||
tex.y += aniOffset.y;
|
||||
pred = float(tex.x >= atAreaCX && tex.x <= (atAreaCX+atAreaCW) && tex.y <= atAreaA.y);
|
||||
tex.y += aniOffset.y * pred;
|
||||
|
||||
gl_Position = projMat * vec4(position + translation, 0, 1);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ void main()
|
|||
{
|
||||
float transV = texture2D(transMap, v_texCoord).r;
|
||||
float cTransV = clamp(transV, prog, prog+vague);
|
||||
float alpha = (cTransV - prog) / vague;
|
||||
lowp float alpha = (cTransV - prog) / vague;
|
||||
|
||||
vec4 newFrag = texture2D(currentScene, v_texCoord);
|
||||
vec4 oldFrag = texture2D(frozenScene, v_texCoord);
|
||||
|
|
|
@ -238,5 +238,6 @@ inline ALenum chooseALFormat(int sampleSize, int channelCount)
|
|||
|
||||
#define AUDIO_SLEEP 10
|
||||
#define STREAM_BUF_SIZE 32768
|
||||
#define GLOBAL_VOLUME 0.8
|
||||
|
||||
#endif // ALUTIL_H
|
||||
|
|
|
@ -23,10 +23,13 @@
|
|||
|
||||
#include "sharedstate.h"
|
||||
#include "sharedmidistate.h"
|
||||
#include "eventthread.h"
|
||||
#include "filesystem.h"
|
||||
#include "exception.h"
|
||||
#include "aldatasource.h"
|
||||
#include "fluid-fun.h"
|
||||
#include "sdl-util.h"
|
||||
#include "debugwriter.h"
|
||||
|
||||
#include <SDL_mutex.h>
|
||||
#include <SDL_thread.h>
|
||||
|
@ -122,6 +125,9 @@ void ALStream::stop()
|
|||
|
||||
void ALStream::play(float offset)
|
||||
{
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
checkStopped();
|
||||
|
||||
switch (state)
|
||||
|
@ -195,8 +201,8 @@ void ALStream::closeSource()
|
|||
|
||||
void ALStream::openSource(const std::string &filename)
|
||||
{
|
||||
const char *ext;
|
||||
shState->fileSystem().openRead(srcOps, filename.c_str(), FileSystem::Audio, false, &ext);
|
||||
char ext[8];
|
||||
shState->fileSystem().openRead(srcOps, filename.c_str(), false, ext, sizeof(ext));
|
||||
needsRewind.clear();
|
||||
|
||||
/* Try to read ogg file signature */
|
||||
|
@ -204,24 +210,36 @@ void ALStream::openSource(const std::string &filename)
|
|||
SDL_RWread(&srcOps, sig, 1, 4);
|
||||
SDL_RWseek(&srcOps, 0, RW_SEEK_SET);
|
||||
|
||||
if (!strcmp(sig, "OggS"))
|
||||
try
|
||||
{
|
||||
source = createVorbisSource(srcOps, looped);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(sig, "MThd"))
|
||||
{
|
||||
shState->midiState().initIfNeeded(shState->config());
|
||||
|
||||
if (HAVE_FLUID)
|
||||
if (!strcmp(sig, "OggS"))
|
||||
{
|
||||
source = createMidiSource(srcOps, looped);
|
||||
source = createVorbisSource(srcOps, looped);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
source = createSDLSource(srcOps, ext, STREAM_BUF_SIZE, looped);
|
||||
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)
|
||||
{
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "Unable to decode audio stream: %s.%s: %s",
|
||||
filename.c_str(), ext, e.msg.c_str());
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
|
||||
Debug() << buf;
|
||||
}
|
||||
}
|
||||
|
||||
void ALStream::stopStream()
|
||||
|
@ -361,6 +379,8 @@ void ALStream::streamData()
|
|||
* refill and queue them up again */
|
||||
while (true)
|
||||
{
|
||||
shState->rtData().syncPoint.passSecondarySync();
|
||||
|
||||
ALint procBufs = AL::Source::getProcBufferCount(alSrc);
|
||||
|
||||
while (procBufs--)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "soundemitter.h"
|
||||
#include "sharedstate.h"
|
||||
#include "sharedmidistate.h"
|
||||
#include "eventthread.h"
|
||||
#include "sdl-util.h"
|
||||
|
||||
#include <string>
|
||||
|
@ -40,6 +41,8 @@ struct AudioPrivate
|
|||
|
||||
SoundEmitter se;
|
||||
|
||||
SyncPoint &syncPoint;
|
||||
|
||||
/* The 'MeWatch' is responsible for detecting
|
||||
* a playing ME, quickly fading out the BGM and
|
||||
* keeping it paused/stopped while the ME plays,
|
||||
|
@ -60,11 +63,12 @@ struct AudioPrivate
|
|||
MeWatchState state;
|
||||
} meWatch;
|
||||
|
||||
AudioPrivate(const Config &conf)
|
||||
AudioPrivate(RGSSThreadData &rtData)
|
||||
: bgm(ALStream::Looped, "bgm"),
|
||||
bgs(ALStream::Looped, "bgs"),
|
||||
me(ALStream::NotLooped, "me"),
|
||||
se(conf)
|
||||
se(rtData.config),
|
||||
syncPoint(rtData.syncPoint)
|
||||
{
|
||||
meWatch.state = MeNotPlaying;
|
||||
meWatch.thread = createSDLThread
|
||||
|
@ -84,6 +88,8 @@ struct AudioPrivate
|
|||
|
||||
while (true)
|
||||
{
|
||||
syncPoint.passSecondarySync();
|
||||
|
||||
if (meWatch.termReq)
|
||||
return;
|
||||
|
||||
|
@ -231,8 +237,8 @@ struct AudioPrivate
|
|||
}
|
||||
};
|
||||
|
||||
Audio::Audio(const Config &conf)
|
||||
: p(new AudioPrivate(conf))
|
||||
Audio::Audio(RGSSThreadData &rtData)
|
||||
: p(new AudioPrivate(rtData))
|
||||
{}
|
||||
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
* quite make out their meaning yet) */
|
||||
|
||||
struct AudioPrivate;
|
||||
struct Config;
|
||||
struct RGSSThreadData;
|
||||
|
||||
class Audio
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
void reset();
|
||||
|
||||
private:
|
||||
Audio(const Config &conf);
|
||||
Audio(RGSSThreadData &rtData);
|
||||
~Audio();
|
||||
|
||||
friend struct SharedStatePrivate;
|
||||
|
|
|
@ -252,7 +252,7 @@ float AudioStream::playingOffset()
|
|||
|
||||
void AudioStream::updateVolume()
|
||||
{
|
||||
float vol = 1.0;
|
||||
float vol = GLOBAL_VOLUME;
|
||||
|
||||
for (size_t i = 0; i < VolumeTypeCount; ++i)
|
||||
vol *= volumes[i];
|
||||
|
|
|
@ -4,196 +4,196 @@ extern const StaticRect autotileRects[] =
|
|||
{
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 80.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 64.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 0.5, 64.5, 15, 15 },
|
||||
{ 16.5, 64.5, 15, 15 },
|
||||
{ 16.5, 80.5, 15, 15 },
|
||||
{ 0.5, 80.5, 15, 15 },
|
||||
{ 16.5, 80.5, 15, 15 },
|
||||
{ 0.5, 64.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 16.5, 80.5, 15, 15 },
|
||||
{ 0.5, 80.5, 15, 15 },
|
||||
{ 16.5, 80.5, 15, 15 },
|
||||
{ 0.5, 64.5, 15, 15 },
|
||||
{ 16.5, 64.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 0.5, 80.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 0.5, 64.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 0.5, 80.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 48.5, 48.5, 15, 15 },
|
||||
{ 32.5, 48.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 32.5, 48.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 48.5, 48.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 32.5, 48.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 48.5, 48.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 64.5, 15, 15 },
|
||||
{ 80.5, 64.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 80.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 64.5, 15, 15 },
|
||||
{ 80.5, 64.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 64.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 80.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 64.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 32.5, 96.5, 15, 15 },
|
||||
{ 48.5, 96.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.5, 112.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 96.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.5, 112.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.5, 96.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.5, 112.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.5, 112.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 0.5, 64.5, 15, 15 },
|
||||
{ 80.5, 64.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 0.5, 80.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.5, 112.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 16.5, 32.5, 15, 15 },
|
||||
{ 0.5, 48.5, 15, 15 },
|
||||
{ 16.5, 48.5, 15, 15 },
|
||||
{ 0.5, 48.5, 15, 15 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 16.5, 32.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 0.5, 48.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 64.5, 48.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 64.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 64.5, 16.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 64.5, 96.5, 15, 15 },
|
||||
{ 80.5, 96.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 64.5, 112.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 96.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 64.5, 112.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 0.5, 96.5, 15, 15 },
|
||||
{ 16.5, 96.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 0.5, 112.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 0.5, 96.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 0.5, 112.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 0.5, 48.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 16.5, 32.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 0.5, 112.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 0.5, 96.5, 15, 15 },
|
||||
{ 80.5, 96.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 0.5, 112.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 64.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 64.5, 112.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 0.5, 112.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 0.5, 0.5, 15, 15 },
|
||||
{ 16.5, 0.5, 15, 15 },
|
||||
{ 16.5, 16.5, 15, 15 },
|
||||
{ 0.5, 16.5, 15, 15 }
|
||||
{ 0.5, 16.5, 15, 15 },
|
||||
{ 16.5, 16.5, 15, 15 }
|
||||
};
|
||||
|
||||
extern const int autotileRectsN = sizeof(autotileRects) / sizeof(autotileRects[0]);
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
"Operation not supported for mega surfaces"); \
|
||||
}
|
||||
|
||||
#define OUTLINE_SIZE 1
|
||||
|
||||
/* Normalize (= ensure width and
|
||||
* height are positive) */
|
||||
static IntRect normalizedRect(const IntRect &rect)
|
||||
|
@ -248,9 +250,10 @@ struct BitmapPrivate
|
|||
Bitmap::Bitmap(const char *filename)
|
||||
{
|
||||
SDL_RWops ops;
|
||||
const char *extension;
|
||||
shState->fileSystem().openRead(ops, filename, FileSystem::Image, false, &extension);
|
||||
SDL_Surface *imgSurf = IMG_LoadTyped_RW(&ops, 1, extension);
|
||||
char ext[8];
|
||||
|
||||
shState->fileSystem().openRead(ops, filename, false, ext, sizeof(ext));
|
||||
SDL_Surface *imgSurf = IMG_LoadTyped_RW(&ops, 1, ext);
|
||||
|
||||
if (!imgSurf)
|
||||
throw Exception(Exception::SDLError, "Error loading image '%s': %s",
|
||||
|
@ -317,6 +320,7 @@ Bitmap::Bitmap(const char *filename)
|
|||
/* Mega surface */
|
||||
p = new BitmapPrivate(this);
|
||||
p->megaSurface = imgSurf;
|
||||
SDL_SetSurfaceBlendMode(p->megaSurface, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
else if (isCrop)
|
||||
{
|
||||
|
@ -487,14 +491,46 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
|||
if (opacity == 0)
|
||||
return;
|
||||
|
||||
if (source.megaSurface())
|
||||
SDL_Surface *srcSurf = source.megaSurface();
|
||||
|
||||
if (srcSurf && shState->config().subImageFix)
|
||||
{
|
||||
/* Blit from software surface, for broken GL drivers */
|
||||
Vec2i gpTexSize;
|
||||
shState->ensureTexSize(sourceRect.w, sourceRect.h, gpTexSize);
|
||||
shState->bindTex();
|
||||
|
||||
GLMeta::subRectImageUpload(srcSurf->w, sourceRect.x, sourceRect.y, 0, 0,
|
||||
sourceRect.w, sourceRect.h, srcSurf, GL_RGBA);
|
||||
GLMeta::subRectImageEnd();
|
||||
|
||||
SimpleShader &shader = shState->shaders().simple;
|
||||
shader.bind();
|
||||
shader.setTranslation(Vec2i());
|
||||
shader.setTexSize(gpTexSize);
|
||||
|
||||
p->pushSetViewport(shader);
|
||||
p->bindFBO();
|
||||
|
||||
Quad &quad = shState->gpQuad();
|
||||
quad.setTexRect(FloatRect(0, 0, sourceRect.w, sourceRect.h));
|
||||
quad.setPosRect(destRect);
|
||||
|
||||
p->blitQuad(quad);
|
||||
p->popViewport();
|
||||
|
||||
p->addTaintedArea(destRect);
|
||||
p->onModified();
|
||||
|
||||
return;
|
||||
}
|
||||
else if (srcSurf)
|
||||
{
|
||||
/* Blit from software surface */
|
||||
/* Don't do transparent blits for now */
|
||||
if (opacity < 255)
|
||||
source.ensureNonMega();
|
||||
|
||||
SDL_Surface *srcSurf = source.megaSurface();
|
||||
|
||||
SDL_Rect srcRect = sourceRect;
|
||||
SDL_Rect dstRect = destRect;
|
||||
SDL_Rect btmRect = { 0, 0, width(), height() };
|
||||
|
@ -510,26 +546,25 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
|||
SDL_Surface *blitTemp =
|
||||
SDL_CreateRGBSurface(0, destRect.w, destRect.h, bpp, rMask, gMask, bMask, aMask);
|
||||
|
||||
// FXIME: This is supposed to be a scaled blit, put SDL2 for some reason
|
||||
// makes the source surface unusable after BlitScaled() is called. Investigate!
|
||||
SDL_BlitSurface(srcSurf, &srcRect, blitTemp, 0);
|
||||
SDL_BlitScaled(srcSurf, &srcRect, blitTemp, 0);
|
||||
|
||||
TEX::bind(p->gl.tex);
|
||||
|
||||
if (bltRect.w == dstRect.w && bltRect.h == dstRect.h)
|
||||
{
|
||||
/* Dest rectangle lies within bounding box */
|
||||
TEX::uploadSubImage(destRect.x, destRect.y,
|
||||
destRect.w, destRect.h,
|
||||
blitTemp->pixels, GL_RGBA);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clipped blit */
|
||||
GLMeta::subRectImageUpload(blitTemp->w, bltRect.x - dstRect.x, bltRect.y - dstRect.y,
|
||||
bltRect.x, bltRect.y, bltRect.w, bltRect.h, blitTemp, GL_RGBA);
|
||||
GLMeta::subRectImageEnd();
|
||||
}
|
||||
|
||||
|
||||
SDL_FreeSurface(blitTemp);
|
||||
|
||||
p->onModified();
|
||||
|
@ -581,7 +616,6 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
|||
}
|
||||
|
||||
p->addTaintedArea(destRect);
|
||||
|
||||
p->onModified();
|
||||
}
|
||||
|
||||
|
@ -1057,6 +1091,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
|||
|
||||
TTF_Font *font = p->font->getSdlFont();
|
||||
const Color &fontColor = p->font->getColor();
|
||||
const Color &outColor = p->font->getOutColor();
|
||||
|
||||
SDL_Color c = fontColor.toSDLColor();
|
||||
c.a = 255;
|
||||
|
@ -1072,11 +1107,34 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
|||
|
||||
p->ensureFormat(txtSurf, SDL_PIXELFORMAT_ABGR8888);
|
||||
|
||||
// While real outlining is not yet here, use shadow
|
||||
// as a replacement to at least make text legible
|
||||
if (p->font->getShadow() || p->font->getOutline())
|
||||
if (p->font->getShadow())
|
||||
applyShadow(txtSurf, *p->format, c);
|
||||
|
||||
/* outline using TTF_Outline and blending it together with SDL_BlitSurface
|
||||
* FIXME: outline is forced to have the same opacity as the font color */
|
||||
if (p->font->getOutline())
|
||||
{
|
||||
SDL_Color co = outColor.toSDLColor();
|
||||
co.a = 255;
|
||||
SDL_Surface *outline;
|
||||
/* set the next font render to render the outline */
|
||||
TTF_SetFontOutline(font, OUTLINE_SIZE);
|
||||
if (shState->rtData().config.solidFonts)
|
||||
outline = TTF_RenderUTF8_Solid(font, str, co);
|
||||
else
|
||||
outline = TTF_RenderUTF8_Blended(font, str, co);
|
||||
|
||||
p->ensureFormat(outline, SDL_PIXELFORMAT_ABGR8888);
|
||||
SDL_Rect outRect = {OUTLINE_SIZE, OUTLINE_SIZE, txtSurf->w, txtSurf->h};
|
||||
|
||||
SDL_SetSurfaceBlendMode(txtSurf, SDL_BLENDMODE_BLEND);
|
||||
SDL_BlitSurface(txtSurf, NULL, outline, &outRect);
|
||||
SDL_FreeSurface(txtSurf);
|
||||
txtSurf = outline;
|
||||
/* reset outline to 0 */
|
||||
TTF_SetFontOutline(font, 0);
|
||||
}
|
||||
|
||||
int alignX = rect.x;
|
||||
|
||||
switch (align)
|
||||
|
@ -1113,7 +1171,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
|||
|
||||
if (fastBlit)
|
||||
{
|
||||
if (squeeze == 1.0)
|
||||
if (squeeze == 1.0 && !shState->config().subImageFix)
|
||||
{
|
||||
/* Even faster: upload directly to bitmap texture.
|
||||
* We have to make sure the posRect lies within the texture
|
||||
|
|
|
@ -1 +1 @@
|
|||
#include "../liberation.ttf.xxd"
|
||||
#include "liberation.ttf.xxd"
|
||||
|
|
124
src/config.cpp
124
src/config.cpp
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "debugwriter.h"
|
||||
#include "util.h"
|
||||
#include "sdl-util.h"
|
||||
|
||||
#ifdef INI_ENCODING
|
||||
extern "C" {
|
||||
|
@ -123,6 +124,10 @@ static bool validUtf8(const char *string)
|
|||
static std::string prefPath(const char *org, const char *app)
|
||||
{
|
||||
char *path = SDL_GetPrefPath(org, app);
|
||||
|
||||
if (!path)
|
||||
return std::string();
|
||||
|
||||
std::string str(path);
|
||||
SDL_free(path);
|
||||
|
||||
|
@ -135,65 +140,47 @@ namespace po = boost::program_options;
|
|||
#define CONF_FILE "mkxp.conf"
|
||||
|
||||
Config::Config()
|
||||
: rgssVersion(0),
|
||||
debugMode(false),
|
||||
winResizable(false),
|
||||
fullscreen(false),
|
||||
fixedAspectRatio(true),
|
||||
smoothScaling(false),
|
||||
vsync(false),
|
||||
defScreenW(0),
|
||||
defScreenH(0),
|
||||
fixedFramerate(0),
|
||||
frameSkip(true),
|
||||
solidFonts(false),
|
||||
gameFolder("."),
|
||||
anyAltToggleFS(false),
|
||||
enableReset(true),
|
||||
allowSymlinks(false),
|
||||
pathCache(true),
|
||||
useScriptNames(false)
|
||||
{
|
||||
midi.chorus = false;
|
||||
midi.reverb = false;
|
||||
SE.sourceCount = 6;
|
||||
}
|
||||
{}
|
||||
|
||||
void Config::read(int argc, char *argv[])
|
||||
{
|
||||
#define PO_DESC_ALL \
|
||||
PO_DESC(rgssVersion, int) \
|
||||
PO_DESC(debugMode, bool) \
|
||||
PO_DESC(winResizable, bool) \
|
||||
PO_DESC(fullscreen, bool) \
|
||||
PO_DESC(fixedAspectRatio, bool) \
|
||||
PO_DESC(smoothScaling, bool) \
|
||||
PO_DESC(vsync, bool) \
|
||||
PO_DESC(defScreenW, int) \
|
||||
PO_DESC(defScreenH, int) \
|
||||
PO_DESC(fixedFramerate, int) \
|
||||
PO_DESC(frameSkip, bool) \
|
||||
PO_DESC(solidFonts, bool) \
|
||||
PO_DESC(gameFolder, std::string) \
|
||||
PO_DESC(anyAltToggleFS, bool) \
|
||||
PO_DESC(enableReset, bool) \
|
||||
PO_DESC(allowSymlinks, bool) \
|
||||
PO_DESC(dataPathOrg, std::string) \
|
||||
PO_DESC(dataPathApp, std::string) \
|
||||
PO_DESC(iconPath, std::string) \
|
||||
PO_DESC(titleLanguage, std::string) \
|
||||
PO_DESC(midi.soundFont, std::string) \
|
||||
PO_DESC(midi.chorus, bool) \
|
||||
PO_DESC(midi.reverb, bool) \
|
||||
PO_DESC(SE.sourceCount, int) \
|
||||
PO_DESC(customScript, std::string) \
|
||||
PO_DESC(pathCache, bool) \
|
||||
PO_DESC(useScriptNames, bool)
|
||||
PO_DESC(rgssVersion, int, 0) \
|
||||
PO_DESC(debugMode, bool, false) \
|
||||
PO_DESC(printFPS, bool, false) \
|
||||
PO_DESC(winResizable, bool, false) \
|
||||
PO_DESC(fullscreen, bool, false) \
|
||||
PO_DESC(fixedAspectRatio, bool, true) \
|
||||
PO_DESC(smoothScaling, bool, false) \
|
||||
PO_DESC(vsync, bool, false) \
|
||||
PO_DESC(defScreenW, int, 0) \
|
||||
PO_DESC(defScreenH, int, 0) \
|
||||
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(gameFolder, std::string, ".") \
|
||||
PO_DESC(anyAltToggleFS, bool, false) \
|
||||
PO_DESC(enableReset, bool, true) \
|
||||
PO_DESC(allowSymlinks, bool, false) \
|
||||
PO_DESC(dataPathOrg, std::string, "") \
|
||||
PO_DESC(dataPathApp, std::string, "") \
|
||||
PO_DESC(iconPath, std::string, "") \
|
||||
PO_DESC(execName, std::string, "Game") \
|
||||
PO_DESC(titleLanguage, std::string, "") \
|
||||
PO_DESC(midi.soundFont, std::string, "") \
|
||||
PO_DESC(midi.chorus, bool, false) \
|
||||
PO_DESC(midi.reverb, bool, false) \
|
||||
PO_DESC(SE.sourceCount, int, 6) \
|
||||
PO_DESC(customScript, std::string, "") \
|
||||
PO_DESC(pathCache, bool, true) \
|
||||
PO_DESC(useScriptNames, bool, false)
|
||||
|
||||
// Not gonna take your shit boost
|
||||
#define GUARD_ALL( exp ) try { exp } catch(...) {}
|
||||
|
||||
#define PO_DESC(key, type) (#key, po::value< type >()->default_value(key))
|
||||
#define PO_DESC(key, type, def) (#key, po::value< type >()->default_value(def))
|
||||
|
||||
po::options_description podesc;
|
||||
podesc.add_options()
|
||||
|
@ -219,26 +206,23 @@ void Config::read(int argc, char *argv[])
|
|||
}
|
||||
|
||||
/* Parse configuration file */
|
||||
std::ifstream confFile;
|
||||
confFile.open(CONF_FILE);
|
||||
SDLRWStream confFile(CONF_FILE, "r");
|
||||
|
||||
if (confFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
po::store(po::parse_config_file(confFile, podesc, true), vm);
|
||||
po::store(po::parse_config_file(confFile.stream(), podesc, true), vm);
|
||||
po::notify(vm);
|
||||
}
|
||||
catch (po::error &error)
|
||||
{
|
||||
Debug() << CONF_FILE":" << error.what();
|
||||
}
|
||||
|
||||
confFile.close();
|
||||
}
|
||||
|
||||
#undef PO_DESC
|
||||
#define PO_DESC(key, type) GUARD_ALL( key = vm[#key].as< type >(); )
|
||||
#define PO_DESC(key, type, def) GUARD_ALL( key = vm[#key].as< type >(); )
|
||||
|
||||
PO_DESC_ALL;
|
||||
|
||||
|
@ -349,16 +333,26 @@ void Config::readGameINI()
|
|||
("Game.Scripts", po::value<std::string>())
|
||||
;
|
||||
|
||||
std::string iniPath = gameFolder + "/Game.ini";
|
||||
|
||||
std::ifstream iniFile;
|
||||
iniFile.open((iniPath).c_str());
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_config_file(iniFile, podesc, true), vm);
|
||||
po::notify(vm);
|
||||
std::string iniFilename = execName + ".ini";
|
||||
SDLRWStream iniFile(iniFilename.c_str(), "r");
|
||||
|
||||
iniFile.close();
|
||||
if (iniFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
po::store(po::parse_config_file(iniFile.stream(), podesc, true), vm);
|
||||
po::notify(vm);
|
||||
}
|
||||
catch (po::error &error)
|
||||
{
|
||||
Debug() << iniFilename + ":" << error.what();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug() << "FAILED to open" << iniFilename;
|
||||
}
|
||||
|
||||
GUARD_ALL( game.title = vm["Game.Title"].as<std::string>(); );
|
||||
GUARD_ALL( game.scripts = vm["Game.Scripts"].as<std::string>(); );
|
||||
|
|
48
src/config.h
48
src/config.h
|
@ -29,6 +29,49 @@ struct CropTexture
|
|||
{
|
||||
std::string filename;
|
||||
int w, h;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -36,6 +79,7 @@ struct Config
|
|||
int rgssVersion;
|
||||
|
||||
bool debugMode;
|
||||
bool printFPS;
|
||||
|
||||
bool winResizable;
|
||||
bool fullscreen;
|
||||
|
@ -48,9 +92,12 @@ struct Config
|
|||
|
||||
int fixedFramerate;
|
||||
bool frameSkip;
|
||||
bool syncToRefreshrate;
|
||||
|
||||
bool solidFonts;
|
||||
|
||||
bool subImageFix;
|
||||
|
||||
std::string gameFolder;
|
||||
bool anyAltToggleFS;
|
||||
bool enableReset;
|
||||
|
@ -61,6 +108,7 @@ struct Config
|
|||
std::string dataPathApp;
|
||||
|
||||
std::string iconPath;
|
||||
std::string execName;
|
||||
std::string titleLanguage;
|
||||
|
||||
struct
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* A cheap replacement for qDebug() */
|
||||
|
||||
class Debug
|
||||
|
@ -56,7 +61,11 @@ public:
|
|||
|
||||
~Debug()
|
||||
{
|
||||
std::clog << buf.str() << std::endl;
|
||||
#ifdef __ANDROID__
|
||||
__android_log_write(ANDROID_LOG_DEBUG, "mkxp", buf.str().c_str());
|
||||
#else
|
||||
std::cerr << buf.str() << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -60,6 +60,11 @@ struct Vec4
|
|||
{
|
||||
return (x == other.x && y == other.y && z == other.z && w == other.w);
|
||||
}
|
||||
|
||||
bool xyzHasEffect() const
|
||||
{
|
||||
return (x != 0.0 || y != 0.0 || z != 0.0);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vec2i
|
||||
|
@ -74,19 +79,68 @@ struct Vec2i
|
|||
: x(x), y(y)
|
||||
{}
|
||||
|
||||
explicit Vec2i(int xy)
|
||||
: x(xy), y(xy)
|
||||
{}
|
||||
|
||||
bool operator==(const Vec2i &other) const
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
|
||||
Vec2i &operator+=(const Vec2i &other)
|
||||
Vec2i &operator+=(const Vec2i &value)
|
||||
{
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
x += value.x;
|
||||
y += value.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vec2i &operator-=(const Vec2i &value)
|
||||
{
|
||||
x -= value.x;
|
||||
y -= value.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vec2i operator+(const Vec2i &value) const
|
||||
{
|
||||
return Vec2i(x + value.x, y + value.y);
|
||||
}
|
||||
|
||||
Vec2i operator-(const Vec2i &value) const
|
||||
{
|
||||
return Vec2i(x - value.x, y - value.y);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec2i operator*(T value) const
|
||||
{
|
||||
return Vec2i(x * value, y * value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec2i operator/(T value) const
|
||||
{
|
||||
return Vec2i(x / value, y / value);
|
||||
}
|
||||
|
||||
Vec2i operator%(int value) const
|
||||
{
|
||||
return Vec2i(x % value, y % value);
|
||||
}
|
||||
|
||||
Vec2i operator-() const
|
||||
{
|
||||
return Vec2i(-x, -y);
|
||||
}
|
||||
|
||||
Vec2i operator!() const
|
||||
{
|
||||
return Vec2i(!x, !y);
|
||||
}
|
||||
|
||||
operator Vec2() const
|
||||
{
|
||||
return Vec2(x, y);
|
||||
|
@ -108,6 +162,14 @@ struct IntRect : SDL_Rect
|
|||
this->h = h;
|
||||
}
|
||||
|
||||
IntRect(const Vec2i &pos, const Vec2i &size)
|
||||
{
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
w = size.x;
|
||||
h = size.y;
|
||||
}
|
||||
|
||||
bool operator==(const IntRect &other) const
|
||||
{
|
||||
return (x == other.x && y == other.y &&
|
||||
|
@ -124,10 +186,24 @@ struct IntRect : SDL_Rect
|
|||
return Vec2i(w, h);
|
||||
}
|
||||
|
||||
operator SDL_Rect() const
|
||||
void setPos(const Vec2i &value)
|
||||
{
|
||||
SDL_Rect r = { x, y, w, h };
|
||||
return r;
|
||||
x = value.x;
|
||||
y = value.y;
|
||||
}
|
||||
|
||||
void setSize(const Vec2i &value)
|
||||
{
|
||||
w = value.x;
|
||||
h = value.y;
|
||||
}
|
||||
|
||||
bool encloses(const IntRect &o) const
|
||||
{
|
||||
return (x <= o.x &&
|
||||
y <= o.y &&
|
||||
x+w >= o.x+o.w &&
|
||||
y+h >= o.y+o.h);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -163,35 +239,10 @@ struct FloatRect
|
|||
Vec2 topRight() const { return Vec2(x+w, y); }
|
||||
Vec2 bottomRight() const { return Vec2(x+w, y+h); }
|
||||
|
||||
void shrinkHalf()
|
||||
{
|
||||
x += 0.5;
|
||||
y += 0.5;
|
||||
w -= 1.0;
|
||||
h -= 1.0;
|
||||
}
|
||||
|
||||
FloatRect vFlipped() const
|
||||
{
|
||||
return FloatRect(x, y+h, w, -h);
|
||||
}
|
||||
|
||||
FloatRect hFlipped() const
|
||||
{
|
||||
return FloatRect(x+w, y, -w, h);
|
||||
}
|
||||
|
||||
Vec2 corner(int i) const
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0 : return topLeft();
|
||||
case 1 : return topRight();
|
||||
case 2 : return bottomRight();
|
||||
case 3 : return bottomLeft();
|
||||
default : return Vec2();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Value between 0 and 255 with internal
|
||||
|
|
57
src/etc.cpp
57
src/etc.cpp
|
@ -105,12 +105,10 @@ int Color::serialSize() const
|
|||
|
||||
void Color::serialize(char *buffer) const
|
||||
{
|
||||
char *buf = buffer;
|
||||
|
||||
write_double(&buf, red);
|
||||
write_double(&buf, green);
|
||||
write_double(&buf, blue);
|
||||
write_double(&buf, alpha);
|
||||
writeDouble(&buffer, red);
|
||||
writeDouble(&buffer, green);
|
||||
writeDouble(&buffer, blue);
|
||||
writeDouble(&buffer, alpha);
|
||||
}
|
||||
|
||||
Color *Color::deserialize(const char *data, int len)
|
||||
|
@ -119,12 +117,11 @@ Color *Color::deserialize(const char *data, int len)
|
|||
throw Exception(Exception::ArgumentError, "Color: Serialized data invalid");
|
||||
|
||||
Color *c = new Color();
|
||||
uint i = 0;
|
||||
|
||||
c->red = read_double(data, i);
|
||||
c->green = read_double(data, i);
|
||||
c->blue = read_double(data, i);
|
||||
c->alpha = read_double(data, i);
|
||||
c->red = readDouble(&data);
|
||||
c->green = readDouble(&data);
|
||||
c->blue = readDouble(&data);
|
||||
c->alpha = readDouble(&data);
|
||||
c->updateInternal();
|
||||
|
||||
return c;
|
||||
|
@ -241,12 +238,10 @@ int Tone::serialSize() const
|
|||
|
||||
void Tone::serialize(char *buffer) const
|
||||
{
|
||||
char *buf = buffer;
|
||||
|
||||
write_double(&buf, red);
|
||||
write_double(&buf, green);
|
||||
write_double(&buf, blue);
|
||||
write_double(&buf, gray);
|
||||
writeDouble(&buffer, red);
|
||||
writeDouble(&buffer, green);
|
||||
writeDouble(&buffer, blue);
|
||||
writeDouble(&buffer, gray);
|
||||
}
|
||||
|
||||
Tone *Tone::deserialize(const char *data, int len)
|
||||
|
@ -255,12 +250,11 @@ Tone *Tone::deserialize(const char *data, int len)
|
|||
throw Exception(Exception::ArgumentError, "Tone: Serialized data invalid");
|
||||
|
||||
Tone *t = new Tone();
|
||||
uint i = 0;
|
||||
|
||||
t->red = read_double(data, i);
|
||||
t->green = read_double(data, i);
|
||||
t->blue = read_double(data, i);
|
||||
t->gray = read_double(data, i);
|
||||
t->red = readDouble(&data);
|
||||
t->green = readDouble(&data);
|
||||
t->blue = readDouble(&data);
|
||||
t->gray = readDouble(&data);
|
||||
t->updateInternal();
|
||||
|
||||
return t;
|
||||
|
@ -390,12 +384,10 @@ int Rect::serialSize() const
|
|||
|
||||
void Rect::serialize(char *buffer) const
|
||||
{
|
||||
char *buf = buffer;
|
||||
|
||||
write_int32(&buf, x);
|
||||
write_int32(&buf, y);
|
||||
write_int32(&buf, width);
|
||||
write_int32(&buf, height);
|
||||
writeInt32(&buffer, x);
|
||||
writeInt32(&buffer, y);
|
||||
writeInt32(&buffer, width);
|
||||
writeInt32(&buffer, height);
|
||||
}
|
||||
|
||||
Rect *Rect::deserialize(const char *data, int len)
|
||||
|
@ -404,12 +396,11 @@ Rect *Rect::deserialize(const char *data, int len)
|
|||
throw Exception(Exception::ArgumentError, "Rect: Serialized data invalid");
|
||||
|
||||
Rect *r = new Rect();
|
||||
uint i = 0;
|
||||
|
||||
r->x = read_int32(data, i);
|
||||
r->y = read_int32(data, i);
|
||||
r->width = read_int32(data, i);
|
||||
r->height = read_int32(data, i);
|
||||
r->x = readInt32(&data);
|
||||
r->y = readInt32(&data);
|
||||
r->width = readInt32(&data);
|
||||
r->height = readInt32(&data);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -26,25 +26,51 @@
|
|||
#include <SDL_messagebox.h>
|
||||
#include <SDL_timer.h>
|
||||
#include <SDL_thread.h>
|
||||
#include <SDL_touch.h>
|
||||
|
||||
#include <alext.h>
|
||||
|
||||
#include "sharedstate.h"
|
||||
#include "graphics.h"
|
||||
#include "settingsmenu.h"
|
||||
#include "al-util.h"
|
||||
#include "debugwriter.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
uint8_t EventThread::keyStates[] = { false };
|
||||
typedef void (ALC_APIENTRY *LPALCDEVICEPAUSESOFT) (ALCdevice *device);
|
||||
typedef void (ALC_APIENTRY *LPALCDEVICERESUMESOFT) (ALCdevice *device);
|
||||
|
||||
EventThread::JoyState EventThread::joyState =
|
||||
{
|
||||
{ 0 }, { false }
|
||||
};
|
||||
#define AL_DEVICE_PAUSE_FUN \
|
||||
AL_FUN(DevicePause, LPALCDEVICEPAUSESOFT) \
|
||||
AL_FUN(DeviceResume, LPALCDEVICERESUMESOFT)
|
||||
|
||||
EventThread::MouseState EventThread::mouseState =
|
||||
struct ALCFunctions
|
||||
{
|
||||
0, 0, false, { false }
|
||||
};
|
||||
#define AL_FUN(name, type) type name;
|
||||
AL_DEVICE_PAUSE_FUN
|
||||
#undef AL_FUN
|
||||
} static alc;
|
||||
|
||||
static void
|
||||
initALCFunctions(ALCdevice *alcDev)
|
||||
{
|
||||
if (!strstr(alcGetString(alcDev, ALC_EXTENSIONS), "ALC_SOFT_pause_device"))
|
||||
return;
|
||||
|
||||
Debug() << "ALC_SOFT_pause_device present";
|
||||
|
||||
#define AL_FUN(name, type) alc. name = (type) alcGetProcAddress(alcDev, "alc" #name "SOFT");
|
||||
AL_DEVICE_PAUSE_FUN;
|
||||
#undef AL_FUN
|
||||
}
|
||||
|
||||
#define HAVE_ALC_DEVICE_PAUSE alc.DevicePause
|
||||
|
||||
uint8_t EventThread::keyStates[];
|
||||
EventThread::JoyState EventThread::joyState;
|
||||
EventThread::MouseState EventThread::mouseState;
|
||||
EventThread::TouchState EventThread::touchState;
|
||||
|
||||
/* User event codes */
|
||||
enum
|
||||
|
@ -80,19 +106,24 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
{
|
||||
SDL_Event event;
|
||||
SDL_Window *win = rtData.window;
|
||||
WindowSizeNotify &windowSizeMsg = rtData.windowSizeMsg;
|
||||
UnidirMessage<Vec2i> &windowSizeMsg = rtData.windowSizeMsg;
|
||||
|
||||
initALCFunctions(rtData.alcDev);
|
||||
SDL_SetEventFilter(eventFilter, &rtData);
|
||||
|
||||
fullscreen = rtData.config.fullscreen;
|
||||
int toggleFSMod = rtData.config.anyAltToggleFS ? KMOD_ALT : KMOD_LALT;
|
||||
|
||||
fps.lastFrame = SDL_GetPerformanceCounter();
|
||||
fps.displayCounter = 0;
|
||||
fps.displaying = false;
|
||||
fps.immInitFlag = false;
|
||||
fps.immFiniFlag = false;
|
||||
fps.acc = 0;
|
||||
fps.accDiv = 0;
|
||||
|
||||
if (rtData.config.printFPS)
|
||||
fps.sendUpdates.set();
|
||||
|
||||
bool displayingFPS = false;
|
||||
|
||||
bool cursorInWindow = false;
|
||||
bool windowFocused = false;
|
||||
|
||||
|
@ -109,6 +140,11 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
|
||||
bool resetting = false;
|
||||
|
||||
int winW, winH;
|
||||
int i;
|
||||
|
||||
SDL_GetWindowSize(win, &winW, &winH);
|
||||
|
||||
SettingsMenu *sMenu = 0;
|
||||
|
||||
while (true)
|
||||
|
@ -132,14 +168,36 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Preselect and discard unwanted events here */
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_MOUSEBUTTONDOWN :
|
||||
case SDL_MOUSEBUTTONUP :
|
||||
case SDL_MOUSEMOTION :
|
||||
if (event.button.which == SDL_TOUCH_MOUSEID)
|
||||
continue;
|
||||
break;
|
||||
|
||||
case SDL_FINGERDOWN :
|
||||
case SDL_FINGERUP :
|
||||
case SDL_FINGERMOTION :
|
||||
if (event.tfinger.fingerId >= MAX_FINGERS)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now process the rest */
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_WINDOWEVENT :
|
||||
switch (event.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED :
|
||||
windowSizeMsg.notifyChange(event.window.data1,
|
||||
event.window.data2);
|
||||
winW = event.window.data1;
|
||||
winH = event.window.data2;
|
||||
|
||||
windowSizeMsg.post(Vec2i(winW, winH));
|
||||
resetInputStates();
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_ENTER :
|
||||
|
@ -210,14 +268,18 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
|
||||
if (event.key.keysym.scancode == SDL_SCANCODE_F2)
|
||||
{
|
||||
if (!fps.displaying)
|
||||
if (!displayingFPS)
|
||||
{
|
||||
fps.immInitFlag = true;
|
||||
fps.displaying = true;
|
||||
fps.immInitFlag.set();
|
||||
fps.sendUpdates.set();
|
||||
displayingFPS = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fps.displaying = false;
|
||||
displayingFPS = false;
|
||||
|
||||
if (!rtData.config.printFPS)
|
||||
fps.sendUpdates.clear();
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
|
@ -274,8 +336,12 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
joyState.buttons[event.jbutton.button] = false;
|
||||
break;
|
||||
|
||||
case SDL_JOYHATMOTION :
|
||||
joyState.hats[event.jhat.hat] = event.jhat.value;
|
||||
break;
|
||||
|
||||
case SDL_JOYAXISMOTION :
|
||||
joyState.axis[event.jaxis.axis] = event.jaxis.value;
|
||||
joyState.axes[event.jaxis.axis] = event.jaxis.value;
|
||||
break;
|
||||
|
||||
case SDL_JOYDEVICEADDED :
|
||||
|
@ -300,7 +366,21 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
case SDL_MOUSEMOTION :
|
||||
mouseState.x = event.motion.x;
|
||||
mouseState.y = event.motion.y;
|
||||
break;
|
||||
|
||||
case SDL_FINGERDOWN :
|
||||
i = event.tfinger.fingerId;
|
||||
touchState.fingers[i].down = true;
|
||||
|
||||
case SDL_FINGERMOTION :
|
||||
i = event.tfinger.fingerId;
|
||||
touchState.fingers[i].x = event.tfinger.x * winW;
|
||||
touchState.fingers[i].y = event.tfinger.y * winH;
|
||||
break;
|
||||
|
||||
case SDL_FINGERUP :
|
||||
i = event.tfinger.fingerId;
|
||||
memset(&touchState.fingers[i], 0, sizeof(touchState.fingers[0]));
|
||||
break;
|
||||
|
||||
default :
|
||||
|
@ -329,7 +409,10 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
break;
|
||||
|
||||
case UPDATE_FPS :
|
||||
if (!fps.displaying)
|
||||
if (rtData.config.printFPS)
|
||||
Debug() << "FPS:" << event.user.code;
|
||||
|
||||
if (!fps.sendUpdates)
|
||||
break;
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%s - %d FPS",
|
||||
|
@ -354,12 +437,69 @@ void EventThread::process(RGSSThreadData &rtData)
|
|||
break;
|
||||
}
|
||||
|
||||
/* Just in case */
|
||||
rtData.syncPoint.resumeThreads();
|
||||
|
||||
if (SDL_JoystickGetAttached(js))
|
||||
SDL_JoystickClose(js);
|
||||
|
||||
delete sMenu;
|
||||
}
|
||||
|
||||
int EventThread::eventFilter(void *data, SDL_Event *event)
|
||||
{
|
||||
RGSSThreadData &rtData = *static_cast<RGSSThreadData*>(data);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_APP_WILLENTERBACKGROUND :
|
||||
Debug() << "SDL_APP_WILLENTERBACKGROUND";
|
||||
|
||||
if (HAVE_ALC_DEVICE_PAUSE)
|
||||
alc.DevicePause(rtData.alcDev);
|
||||
|
||||
rtData.syncPoint.haltThreads();
|
||||
|
||||
return 0;
|
||||
|
||||
case SDL_APP_DIDENTERBACKGROUND :
|
||||
Debug() << "SDL_APP_DIDENTERBACKGROUND";
|
||||
return 0;
|
||||
|
||||
case SDL_APP_WILLENTERFOREGROUND :
|
||||
Debug() << "SDL_APP_WILLENTERFOREGROUND";
|
||||
return 0;
|
||||
|
||||
case SDL_APP_DIDENTERFOREGROUND :
|
||||
Debug() << "SDL_APP_DIDENTERFOREGROUND";
|
||||
|
||||
if (HAVE_ALC_DEVICE_PAUSE)
|
||||
alc.DeviceResume(rtData.alcDev);
|
||||
|
||||
rtData.syncPoint.resumeThreads();
|
||||
|
||||
return 0;
|
||||
|
||||
case SDL_APP_TERMINATING :
|
||||
Debug() << "SDL_APP_TERMINATING";
|
||||
return 0;
|
||||
|
||||
case SDL_APP_LOWMEMORY :
|
||||
Debug() << "SDL_APP_LOWMEMORY";
|
||||
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;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EventThread::cleanup()
|
||||
{
|
||||
SDL_Event event;
|
||||
|
@ -374,6 +514,7 @@ void EventThread::resetInputStates()
|
|||
memset(&keyStates, 0, sizeof(keyStates));
|
||||
memset(&joyState, 0, sizeof(joyState));
|
||||
memset(&mouseState.buttons, 0, sizeof(mouseState.buttons));
|
||||
memset(&touchState, 0, sizeof(touchState));
|
||||
}
|
||||
|
||||
void EventThread::setFullscreen(SDL_Window *win, bool mode)
|
||||
|
@ -454,7 +595,7 @@ bool EventThread::getShowCursor() const
|
|||
|
||||
void EventThread::notifyFrame()
|
||||
{
|
||||
if (!fps.displaying)
|
||||
if (!fps.sendUpdates)
|
||||
return;
|
||||
|
||||
uint64_t current = SDL_GetPerformanceCounter();
|
||||
|
@ -463,8 +604,8 @@ void EventThread::notifyFrame()
|
|||
|
||||
if (fps.immInitFlag)
|
||||
{
|
||||
fps.immInitFlag = false;
|
||||
fps.immFiniFlag = true;
|
||||
fps.immInitFlag.clear();
|
||||
fps.immFiniFlag.set();
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -480,7 +621,7 @@ void EventThread::notifyFrame()
|
|||
return;
|
||||
|
||||
fps.displayCounter = 0;
|
||||
fps.immFiniFlag = false;
|
||||
fps.immFiniFlag.clear();
|
||||
|
||||
int32_t avgFPS = fps.acc / fps.accDiv;
|
||||
fps.acc = fps.accDiv = 0;
|
||||
|
@ -490,3 +631,87 @@ void EventThread::notifyFrame()
|
|||
event.user.type = usrIdStart + UPDATE_FPS;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void SyncPoint::haltThreads()
|
||||
{
|
||||
if (mainSync.locked)
|
||||
return;
|
||||
|
||||
/* Lock the reply sync first to avoid races */
|
||||
reply.lock();
|
||||
|
||||
/* Lock main sync and sleep until RGSS thread
|
||||
* reports back */
|
||||
mainSync.lock();
|
||||
reply.waitForUnlock();
|
||||
|
||||
/* Now that the RGSS thread is asleep, we can
|
||||
* safely put the other threads to sleep as well
|
||||
* without causing deadlocks */
|
||||
secondSync.lock();
|
||||
}
|
||||
|
||||
void SyncPoint::resumeThreads()
|
||||
{
|
||||
if (!mainSync.locked)
|
||||
return;
|
||||
|
||||
mainSync.unlock(false);
|
||||
secondSync.unlock(true);
|
||||
}
|
||||
|
||||
bool SyncPoint::mainSyncLocked()
|
||||
{
|
||||
return mainSync.locked;
|
||||
}
|
||||
|
||||
void SyncPoint::waitMainSync()
|
||||
{
|
||||
reply.unlock(false);
|
||||
mainSync.waitForUnlock();
|
||||
}
|
||||
|
||||
void SyncPoint::passSecondarySync()
|
||||
{
|
||||
if (!secondSync.locked)
|
||||
return;
|
||||
|
||||
secondSync.waitForUnlock();
|
||||
}
|
||||
|
||||
SyncPoint::Util::Util()
|
||||
{
|
||||
mut = SDL_CreateMutex();
|
||||
cond = SDL_CreateCond();
|
||||
}
|
||||
|
||||
SyncPoint::Util::~Util()
|
||||
{
|
||||
SDL_DestroyCond(cond);
|
||||
SDL_DestroyMutex(mut);
|
||||
}
|
||||
|
||||
void SyncPoint::Util::lock()
|
||||
{
|
||||
locked.set();
|
||||
}
|
||||
|
||||
void SyncPoint::Util::unlock(bool multi)
|
||||
{
|
||||
locked.clear();
|
||||
|
||||
if (multi)
|
||||
SDL_CondBroadcast(cond);
|
||||
else
|
||||
SDL_CondSignal(cond);
|
||||
}
|
||||
|
||||
void SyncPoint::Util::waitForUnlock()
|
||||
{
|
||||
SDL_LockMutex(mut);
|
||||
|
||||
while (locked)
|
||||
SDL_CondWait(cond, mut);
|
||||
|
||||
SDL_UnlockMutex(mut);
|
||||
}
|
||||
|
|
|
@ -37,21 +37,22 @@
|
|||
#include <stdint.h>
|
||||
|
||||
struct RGSSThreadData;
|
||||
typedef struct ALCdevice_struct ALCdevice;
|
||||
struct SDL_Window;
|
||||
union SDL_Event;
|
||||
|
||||
#define MAX_FINGERS 4
|
||||
|
||||
class EventThread
|
||||
{
|
||||
public:
|
||||
static uint8_t keyStates[SDL_NUM_SCANCODES];
|
||||
|
||||
struct JoyState
|
||||
{
|
||||
int axis[256];
|
||||
int axes[256];
|
||||
uint8_t hats[256];
|
||||
bool buttons[256];
|
||||
};
|
||||
|
||||
static JoyState joyState;
|
||||
|
||||
struct MouseState
|
||||
{
|
||||
int x, y;
|
||||
|
@ -59,7 +60,21 @@ public:
|
|||
bool buttons[32];
|
||||
};
|
||||
|
||||
struct FingerState
|
||||
{
|
||||
bool down;
|
||||
int x, y;
|
||||
};
|
||||
|
||||
struct TouchState
|
||||
{
|
||||
FingerState fingers[MAX_FINGERS];
|
||||
};
|
||||
|
||||
static uint8_t keyStates[SDL_NUM_SCANCODES];
|
||||
static JoyState joyState;
|
||||
static MouseState mouseState;
|
||||
static TouchState touchState;
|
||||
|
||||
static bool allocUserEvents();
|
||||
|
||||
|
@ -84,6 +99,8 @@ public:
|
|||
void notifyFrame();
|
||||
|
||||
private:
|
||||
static int eventFilter(void *, SDL_Event*);
|
||||
|
||||
void resetInputStates();
|
||||
void setFullscreen(SDL_Window *, bool mode);
|
||||
void updateCursorState(bool inWindow);
|
||||
|
@ -96,111 +113,101 @@ private:
|
|||
{
|
||||
uint64_t lastFrame;
|
||||
uint64_t displayCounter;
|
||||
bool displaying;
|
||||
bool immInitFlag;
|
||||
bool immFiniFlag;
|
||||
AtomicFlag sendUpdates;
|
||||
AtomicFlag immInitFlag;
|
||||
AtomicFlag immFiniFlag;
|
||||
double acc;
|
||||
uint32_t accDiv;
|
||||
} fps;
|
||||
};
|
||||
|
||||
/* Used to asynchronously inform the RGSS thread
|
||||
* about window size changes */
|
||||
struct WindowSizeNotify
|
||||
* about certain value changes */
|
||||
template<typename T>
|
||||
struct UnidirMessage
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
UnidirMessage()
|
||||
: mutex(SDL_CreateMutex()),
|
||||
current(T())
|
||||
{}
|
||||
|
||||
AtomicFlag changed;
|
||||
int w, h;
|
||||
|
||||
WindowSizeNotify()
|
||||
{
|
||||
mutex = SDL_CreateMutex();
|
||||
w = h = 0;
|
||||
}
|
||||
|
||||
~WindowSizeNotify()
|
||||
~UnidirMessage()
|
||||
{
|
||||
SDL_DestroyMutex(mutex);
|
||||
}
|
||||
|
||||
/* Done from the sending side */
|
||||
void notifyChange(int w, int h)
|
||||
void post(const T &value)
|
||||
{
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
changed.set();
|
||||
current = value;
|
||||
|
||||
SDL_UnlockMutex(mutex);
|
||||
}
|
||||
|
||||
/* Done from the receiving side */
|
||||
bool pollChange(int *w, int *h)
|
||||
bool poll(T &out) const
|
||||
{
|
||||
if (!changed)
|
||||
return false;
|
||||
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
*w = this->w;
|
||||
*h = this->h;
|
||||
out = current;
|
||||
changed.clear();
|
||||
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct BindingNotify
|
||||
{
|
||||
BindingNotify()
|
||||
/* Done from either */
|
||||
void get(T &out) const
|
||||
{
|
||||
mut = SDL_CreateMutex();
|
||||
}
|
||||
~BindingNotify()
|
||||
{
|
||||
SDL_DestroyMutex(mut);
|
||||
}
|
||||
|
||||
bool poll(BDescVec &out) const
|
||||
{
|
||||
if (!changed)
|
||||
return false;
|
||||
|
||||
SDL_LockMutex(mut);
|
||||
|
||||
out = data;
|
||||
changed.clear();
|
||||
|
||||
SDL_UnlockMutex(mut);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void get(BDescVec &out) const
|
||||
{
|
||||
SDL_LockMutex(mut);
|
||||
out = data;
|
||||
SDL_UnlockMutex(mut);
|
||||
}
|
||||
|
||||
void post(const BDescVec &d)
|
||||
{
|
||||
SDL_LockMutex(mut);
|
||||
|
||||
changed.set();
|
||||
data = d;
|
||||
|
||||
SDL_UnlockMutex(mut);
|
||||
SDL_LockMutex(mutex);
|
||||
out = current;
|
||||
SDL_UnlockMutex(mutex);
|
||||
}
|
||||
|
||||
private:
|
||||
SDL_mutex *mut;
|
||||
BDescVec data;
|
||||
SDL_mutex *mutex;
|
||||
mutable AtomicFlag changed;
|
||||
T current;
|
||||
};
|
||||
|
||||
struct SyncPoint
|
||||
{
|
||||
/* Used by eventFilter to control sleep/wakeup */
|
||||
void haltThreads();
|
||||
void resumeThreads();
|
||||
|
||||
/* Used by RGSS thread */
|
||||
bool mainSyncLocked();
|
||||
void waitMainSync();
|
||||
|
||||
/* Used by secondary (audio) threads */
|
||||
void passSecondarySync();
|
||||
|
||||
private:
|
||||
struct Util
|
||||
{
|
||||
Util();
|
||||
~Util();
|
||||
|
||||
void lock();
|
||||
void unlock(bool multi);
|
||||
void waitForUnlock();
|
||||
|
||||
AtomicFlag locked;
|
||||
SDL_mutex *mut;
|
||||
SDL_cond *cond;
|
||||
};
|
||||
|
||||
Util mainSync;
|
||||
Util reply;
|
||||
Util secondSync;
|
||||
};
|
||||
|
||||
struct RGSSThreadData
|
||||
|
@ -218,15 +225,18 @@ struct RGSSThreadData
|
|||
AtomicFlag rqResetFinish;
|
||||
|
||||
EventThread *ethread;
|
||||
WindowSizeNotify windowSizeMsg;
|
||||
BindingNotify bindingUpdateMsg;
|
||||
UnidirMessage<Vec2i> windowSizeMsg;
|
||||
UnidirMessage<BDescVec> bindingUpdateMsg;
|
||||
SyncPoint syncPoint;
|
||||
|
||||
const char *argv0;
|
||||
|
||||
SDL_Window *window;
|
||||
ALCdevice *alcDev;
|
||||
|
||||
Vec2 sizeResoRatio;
|
||||
Vec2i screenOffset;
|
||||
const int refreshRate;
|
||||
|
||||
Config config;
|
||||
|
||||
|
@ -235,11 +245,15 @@ struct RGSSThreadData
|
|||
RGSSThreadData(EventThread *ethread,
|
||||
const char *argv0,
|
||||
SDL_Window *window,
|
||||
ALCdevice *alcDev,
|
||||
int refreshRate,
|
||||
const Config& newconf)
|
||||
: ethread(ethread),
|
||||
argv0(argv0),
|
||||
window(window),
|
||||
alcDev(alcDev),
|
||||
sizeResoRatio(1, 1),
|
||||
refreshRate(refreshRate),
|
||||
config(newconf)
|
||||
{}
|
||||
};
|
||||
|
|
|
@ -42,6 +42,105 @@
|
|||
#include <iconv.h>
|
||||
#endif
|
||||
|
||||
struct SDLRWIoContext
|
||||
{
|
||||
SDL_RWops *ops;
|
||||
std::string filename;
|
||||
|
||||
SDLRWIoContext(const char *filename)
|
||||
: ops(SDL_RWFromFile(filename, "r")),
|
||||
filename(filename)
|
||||
{
|
||||
if (!ops)
|
||||
throw Exception(Exception::SDLError,
|
||||
"Failed to open file: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
~SDLRWIoContext()
|
||||
{
|
||||
SDL_RWclose(ops);
|
||||
}
|
||||
};
|
||||
|
||||
static PHYSFS_Io *createSDLRWIo(const char *filename);
|
||||
|
||||
static SDL_RWops *getSDLRWops(PHYSFS_Io *io)
|
||||
{
|
||||
return static_cast<SDLRWIoContext*>(io->opaque)->ops;
|
||||
}
|
||||
|
||||
static PHYSFS_sint64 SDLRWIoRead(struct PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
|
||||
{
|
||||
return SDL_RWread(getSDLRWops(io), buf, 1, len);
|
||||
}
|
||||
|
||||
static int SDLRWIoSeek(struct PHYSFS_Io *io, PHYSFS_uint64 offset)
|
||||
{
|
||||
return (SDL_RWseek(getSDLRWops(io), offset, RW_SEEK_SET) != -1);
|
||||
}
|
||||
|
||||
static PHYSFS_sint64 SDLRWIoTell(struct PHYSFS_Io *io)
|
||||
{
|
||||
return SDL_RWseek(getSDLRWops(io), 0, RW_SEEK_CUR);
|
||||
}
|
||||
|
||||
static PHYSFS_sint64 SDLRWIoLength(struct PHYSFS_Io *io)
|
||||
{
|
||||
return SDL_RWsize(getSDLRWops(io));
|
||||
}
|
||||
|
||||
static struct PHYSFS_Io *SDLRWIoDuplicate(struct PHYSFS_Io *io)
|
||||
{
|
||||
SDLRWIoContext *ctx = static_cast<SDLRWIoContext*>(io->opaque);
|
||||
int64_t offset = io->tell(io);
|
||||
PHYSFS_Io *dup = createSDLRWIo(ctx->filename.c_str());
|
||||
|
||||
if (dup)
|
||||
SDLRWIoSeek(dup, offset);
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
static void SDLRWIoDestroy(struct PHYSFS_Io *io)
|
||||
{
|
||||
delete static_cast<SDLRWIoContext*>(io->opaque);
|
||||
delete io;
|
||||
}
|
||||
|
||||
static PHYSFS_Io SDLRWIoTemplate =
|
||||
{
|
||||
0, 0, /* version, opaque */
|
||||
SDLRWIoRead,
|
||||
0, /* write */
|
||||
SDLRWIoSeek,
|
||||
SDLRWIoTell,
|
||||
SDLRWIoLength,
|
||||
SDLRWIoDuplicate,
|
||||
0, /* flush */
|
||||
SDLRWIoDestroy
|
||||
};
|
||||
|
||||
static PHYSFS_Io *createSDLRWIo(const char *filename)
|
||||
{
|
||||
SDLRWIoContext *ctx;
|
||||
|
||||
try
|
||||
{
|
||||
ctx = new SDLRWIoContext(filename);
|
||||
}
|
||||
catch (const Exception &e)
|
||||
{
|
||||
Debug() << "Failed mounting" << filename;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PHYSFS_Io *io = new PHYSFS_Io;
|
||||
*io = SDLRWIoTemplate;
|
||||
io->opaque = ctx;
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
static inline PHYSFS_File *sdlPHYS(SDL_RWops *ops)
|
||||
{
|
||||
return static_cast<PHYSFS_File*>(ops->hidden.unknown.data1);
|
||||
|
@ -131,18 +230,36 @@ static int SDL_RWopsCloseFree(SDL_RWops *ops)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Copies the first srcN characters from src into dst,
|
||||
* or the full string if srcN == -1. Never writes more
|
||||
* than dstMax, and guarantees dst to be null terminated.
|
||||
* Returns copied bytes (minus terminating null) */
|
||||
static size_t
|
||||
strcpySafe(char *dst, const char *src,
|
||||
size_t dstMax, int srcN)
|
||||
{
|
||||
if (srcN < 0)
|
||||
srcN = strlen(src);
|
||||
|
||||
size_t cpyMax = std::min<size_t>(dstMax-1, srcN);
|
||||
|
||||
memcpy(dst, src, cpyMax);
|
||||
dst[cpyMax] = '\0';
|
||||
|
||||
return cpyMax;
|
||||
}
|
||||
|
||||
const Uint32 SDL_RWOPS_PHYSFS = SDL_RWOPS_UNKNOWN+10;
|
||||
|
||||
struct FileSystemPrivate
|
||||
{
|
||||
/* Maps: lower case filename, To: actual (mixed case) filename.
|
||||
/* Maps: lower case filepath without extension,
|
||||
* To: mixed case full filepath
|
||||
* This is for compatibility with games that take Windows'
|
||||
* case insensitivity for granted */
|
||||
BoostHash<std::string, std::string> pathCache;
|
||||
bool havePathCache;
|
||||
|
||||
std::vector<std::string> extensions[FileSystem::Undefined+1];
|
||||
|
||||
/* Attempt to locate an extension string in a filename.
|
||||
* Either a pointer into the input string pointing at the
|
||||
* extension, or null is returned */
|
||||
|
@ -162,120 +279,129 @@ struct FileSystemPrivate
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Complete filename via regular physfs lookup */
|
||||
bool completeFilenameReg(const char *filename,
|
||||
FileSystem::FileType type,
|
||||
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,
|
||||
const char **foundExt)
|
||||
size_t outN)
|
||||
{
|
||||
/* Try supplementing extensions to find an existing path */
|
||||
const std::vector<std::string> &extList = extensions[type];
|
||||
strcpySafe(outBuffer, filepath, outN, -1);
|
||||
|
||||
for (size_t i = 0; i < extList.size(); ++i)
|
||||
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)
|
||||
{
|
||||
const char *ext = extList[i].c_str();
|
||||
/* 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);
|
||||
|
||||
snprintf(outBuffer, outN, "%s.%s", filename, ext);
|
||||
|
||||
if (PHYSFS_exists(outBuffer))
|
||||
{
|
||||
if (foundExt)
|
||||
*foundExt = ext;
|
||||
|
||||
return true;
|
||||
}
|
||||
*delim = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise the file is in the root directory */
|
||||
d.outBuf = outBuffer;
|
||||
d.filenameLen = len - (delim - outBuffer);
|
||||
}
|
||||
|
||||
/* Doing the check without supplemented extension
|
||||
* fits the usage pattern of RMXP games */
|
||||
if (PHYSFS_exists(filename))
|
||||
{
|
||||
strncpy(outBuffer, filename, outN);
|
||||
d.found = false;
|
||||
d.outBufN = outN - (d.outBuf - outBuffer);
|
||||
|
||||
if (foundExt)
|
||||
*foundExt = findExt(filename);
|
||||
PHYSFS_enumerateFilesCallback(root ? "" : outBuffer, completeFilenameRegCB, &d);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (!d.found)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
/* Now we put the deliminator back in to form the completed
|
||||
* file path (if required) */
|
||||
if (delim != outBuffer)
|
||||
*delim = '/';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Complete filename via path cache */
|
||||
bool completeFilenamePC(const char *filename,
|
||||
FileSystem::FileType type,
|
||||
bool completeFilenamePC(const char *filepath,
|
||||
char *outBuffer,
|
||||
size_t outN,
|
||||
const char **foundExt)
|
||||
size_t outN)
|
||||
{
|
||||
size_t i;
|
||||
char lowCase[512];
|
||||
std::string lowCase(filepath);
|
||||
|
||||
for (i = 0; i < sizeof(lowCase)-1 && filename[i]; ++i)
|
||||
lowCase[i] = tolower(filename[i]);
|
||||
for (size_t i = 0; i < lowCase.size(); ++i)
|
||||
lowCase[i] = tolower(lowCase[i]);
|
||||
|
||||
lowCase[i] = '\0';
|
||||
if (!pathCache.contains(lowCase))
|
||||
return false;
|
||||
|
||||
std::string key;
|
||||
const std::string &fullPath = pathCache[lowCase];
|
||||
strcpySafe(outBuffer, fullPath.c_str(), outN, fullPath.size());
|
||||
|
||||
const std::vector<std::string> &extList = extensions[type];
|
||||
|
||||
for (size_t i = 0; i < extList.size(); ++i)
|
||||
{
|
||||
const char *ext = extList[i].c_str();
|
||||
|
||||
snprintf(outBuffer, outN, "%s.%s", lowCase, ext);
|
||||
key = outBuffer;
|
||||
|
||||
if (pathCache.contains(key))
|
||||
{
|
||||
strncpy(outBuffer, pathCache[key].c_str(), outN);
|
||||
|
||||
if (foundExt)
|
||||
*foundExt = ext;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
key = lowCase;
|
||||
|
||||
if (pathCache.contains(key))
|
||||
{
|
||||
strncpy(outBuffer, pathCache[key].c_str(), outN);
|
||||
|
||||
if (foundExt)
|
||||
*foundExt = findExt(filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Try to complete 'filename' with file extensions
|
||||
* based on 'type'. If no combination could be found,
|
||||
* returns false, and 'foundExt' is untouched */
|
||||
bool completeFileName(const char *filename,
|
||||
FileSystem::FileType type,
|
||||
bool completeFilename(const char *filepath,
|
||||
char *outBuffer,
|
||||
size_t outN,
|
||||
const char **foundExt)
|
||||
size_t outN)
|
||||
{
|
||||
if (havePathCache)
|
||||
return completeFilenamePC(filename, type, outBuffer, outN, foundExt);
|
||||
return completeFilenamePC(filepath, outBuffer, outN);
|
||||
else
|
||||
return completeFilenameReg(filename, type, outBuffer, outN, foundExt);
|
||||
return completeFilenameReg(filepath, outBuffer, outN);
|
||||
}
|
||||
|
||||
PHYSFS_File *openReadHandle(const char *filename,
|
||||
FileSystem::FileType type,
|
||||
const char **foundExt)
|
||||
char *extBuf,
|
||||
size_t extBufN)
|
||||
{
|
||||
char found[512];
|
||||
|
||||
if (!completeFileName(filename, type, found, sizeof(found), foundExt))
|
||||
if (!completeFilename(filename, found, sizeof(found)))
|
||||
throw Exception(Exception::NoFileError, "%s", filename);
|
||||
|
||||
PHYSFS_File *handle = PHYSFS_openRead(found);
|
||||
|
@ -283,6 +409,21 @@ struct FileSystemPrivate
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -309,45 +450,8 @@ FileSystem::FileSystem(const char *argv0,
|
|||
bool allowSymlinks)
|
||||
{
|
||||
p = new FileSystemPrivate;
|
||||
|
||||
p->havePathCache = false;
|
||||
|
||||
/* Image extensions */
|
||||
p->extensions[Image].push_back("jpg");
|
||||
p->extensions[Image].push_back("png");
|
||||
|
||||
/* Audio extensions */
|
||||
const Sound_DecoderInfo **di;
|
||||
for (di = Sound_AvailableDecoders(); *di; ++di)
|
||||
{
|
||||
const char **ext;
|
||||
for (ext = (*di)->extensions; *ext; ++ext)
|
||||
{
|
||||
/* All reported extensions are uppercase,
|
||||
* so we need to hammer them down first */
|
||||
char buf[16];
|
||||
for (size_t i = 0; i < sizeof(buf); ++i)
|
||||
{
|
||||
buf[i] = tolower((*ext)[i]);
|
||||
|
||||
if (!buf[i])
|
||||
break;
|
||||
}
|
||||
|
||||
p->extensions[Audio].push_back(buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (rgssVer >= 2 && !contains(p->extensions[Audio], std::string("ogg")))
|
||||
p->extensions[Audio].push_back("ogg");
|
||||
|
||||
p->extensions[Audio].push_back("mid");
|
||||
p->extensions[Audio].push_back("midi");
|
||||
|
||||
/* Font extensions */
|
||||
p->extensions[Font].push_back("ttf");
|
||||
p->extensions[Font].push_back("otf");
|
||||
|
||||
PHYSFS_init(argv0);
|
||||
|
||||
PHYSFS_registerArchiver(&RGSS1_Archiver);
|
||||
|
@ -368,7 +472,16 @@ FileSystem::~FileSystem()
|
|||
|
||||
void FileSystem::addPath(const char *path)
|
||||
{
|
||||
PHYSFS_mount(path, 0, 1);
|
||||
/* Try the normal mount first */
|
||||
if (!PHYSFS_mount(path, 0, 1))
|
||||
{
|
||||
/* If it didn't work, try mounting via a wrapped
|
||||
* SDL_RWops */
|
||||
PHYSFS_Io *io = createSDLRWIo(path);
|
||||
|
||||
if (io)
|
||||
PHYSFS_mountIo(io, path, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -436,12 +549,22 @@ static void cacheEnumCB(void *d, const char *origdir,
|
|||
|
||||
std::string mixedCase(ptr);
|
||||
|
||||
for (char *p = bufNfc; *p; ++p)
|
||||
*p = tolower(*p);
|
||||
for (char *q = bufNfc; *q; ++q)
|
||||
*q = tolower(*q);
|
||||
|
||||
std::string lowerCase(ptr);
|
||||
p->pathCache.insert(std::string(ptr), mixedCase);
|
||||
|
||||
p->pathCache.insert(lowerCase, mixedCase);
|
||||
for (char *q = ptr+strlen(ptr); q > ptr; --q)
|
||||
{
|
||||
if (*q == '/')
|
||||
break;
|
||||
|
||||
if (*q != '.')
|
||||
continue;
|
||||
|
||||
*q = '\0';
|
||||
p->pathCache.insert(std::string(ptr), mixedCase);
|
||||
}
|
||||
|
||||
PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, d);
|
||||
}
|
||||
|
@ -450,7 +573,7 @@ void FileSystem::createPathCache()
|
|||
{
|
||||
#ifdef __APPLE__
|
||||
CacheEnumCBData data(p);
|
||||
PHYSFS_enumerateFilesCallback("", cacheEnumCB, &data);
|
||||
PHYSFS_enumerateFilesCallback("", cacheEnumCB2, &data);
|
||||
#else
|
||||
PHYSFS_enumerateFilesCallback("", cacheEnumCB, p);
|
||||
#endif
|
||||
|
@ -458,12 +581,6 @@ void FileSystem::createPathCache()
|
|||
p->havePathCache = true;
|
||||
}
|
||||
|
||||
static void strToLower(std::string &str)
|
||||
{
|
||||
for (size_t i = 0; i < str.size(); ++i)
|
||||
str[i] = tolower(str[i]);
|
||||
}
|
||||
|
||||
struct FontSetsCBData
|
||||
{
|
||||
FileSystemPrivate *p;
|
||||
|
@ -482,16 +599,21 @@ static void fontSetEnumCB(void *data, const char *,
|
|||
if (!ext)
|
||||
return;
|
||||
|
||||
std::string lower(ext);
|
||||
strToLower(lower);
|
||||
char lowExt[8];
|
||||
size_t i;
|
||||
|
||||
if (!contains(p->extensions[FileSystem::Font], lower))
|
||||
for (i = 0; i < sizeof(lowExt)-1 && ext[i]; ++i)
|
||||
lowExt[i] = tolower(ext[i]);
|
||||
lowExt[i] = '\0';
|
||||
|
||||
if (strcmp(lowExt, "ttf") && strcmp(lowExt, "otf"))
|
||||
return;
|
||||
|
||||
std::string filename("Fonts/");
|
||||
filename += fname;
|
||||
char filename[512];
|
||||
snprintf(filename, sizeof(filename), "Fonts/%s", fname);
|
||||
filename[sizeof(filename)-1] = '\0';
|
||||
|
||||
PHYSFS_File *handle = PHYSFS_openRead(filename.c_str());
|
||||
PHYSFS_File *handle = PHYSFS_openRead(filename);
|
||||
|
||||
if (!handle)
|
||||
return;
|
||||
|
@ -513,11 +635,11 @@ void FileSystem::initFontSets(SharedFontState &sfs)
|
|||
|
||||
void FileSystem::openRead(SDL_RWops &ops,
|
||||
const char *filename,
|
||||
FileType type,
|
||||
bool freeOnClose,
|
||||
const char **foundExt)
|
||||
char *extBuf,
|
||||
size_t extBufN)
|
||||
{
|
||||
PHYSFS_File *handle = p->openReadHandle(filename, type, foundExt);
|
||||
PHYSFS_File *handle = p->openReadHandle(filename, extBuf, extBufN);
|
||||
|
||||
p->initReadOps(handle, ops, freeOnClose);
|
||||
}
|
||||
|
@ -532,9 +654,9 @@ void FileSystem::openReadRaw(SDL_RWops &ops,
|
|||
p->initReadOps(handle, ops, freeOnClose);
|
||||
}
|
||||
|
||||
bool FileSystem::exists(const char *filename, FileType type)
|
||||
bool FileSystem::exists(const char *filename)
|
||||
{
|
||||
char found[512];
|
||||
|
||||
return p->completeFileName(filename, type, found, sizeof(found), 0);
|
||||
return p->completeFilename(filename, found, sizeof(found));
|
||||
}
|
||||
|
|
|
@ -43,28 +43,18 @@ public:
|
|||
* available font assets */
|
||||
void initFontSets(SharedFontState &sfs);
|
||||
|
||||
/* For extension supplementing */
|
||||
enum FileType
|
||||
{
|
||||
Image = 0,
|
||||
Audio,
|
||||
Font,
|
||||
Undefined
|
||||
};
|
||||
|
||||
void openRead(SDL_RWops &ops,
|
||||
const char *filename,
|
||||
FileType type = Undefined,
|
||||
bool freeOnClose = false,
|
||||
const char **foundExt = 0);
|
||||
char *extBuf = 0,
|
||||
size_t extBufN = 0);
|
||||
|
||||
/* Circumvents extension supplementing */
|
||||
void openReadRaw(SDL_RWops &ops,
|
||||
const char *filename,
|
||||
bool freeOnClose = false);
|
||||
|
||||
bool exists(const char *filename,
|
||||
FileType type = Undefined);
|
||||
bool exists(const char *filename);
|
||||
|
||||
private:
|
||||
FileSystemPrivate *p;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <fluidsynth.h>
|
||||
#endif
|
||||
|
||||
#ifdef __LINUX__
|
||||
#if __LINUX__ || __ANDROID__
|
||||
#define FLUID_LIB "libfluidsynth.so.1"
|
||||
#elif __MACOSX__
|
||||
#define FLUID_LIB "libfluidsynth.1.dylib"
|
||||
|
|
20
src/font.h
20
src/font.h
|
@ -86,16 +86,14 @@ public:
|
|||
|
||||
const Font &operator=(const Font &o);
|
||||
|
||||
const char *getName() const;
|
||||
void setName(const char *value);
|
||||
|
||||
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( 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_STATIC( DefaultName, const char* )
|
||||
DECL_ATTR_STATIC( DefaultSize, int )
|
||||
|
@ -108,7 +106,7 @@ public:
|
|||
|
||||
/* Assigns heap allocated objects to object properties;
|
||||
* using this in pure C++ will cause memory leaks
|
||||
* (ie. only to be used in GCed language bindings */
|
||||
* (ie. only to be used in GCed language bindings) */
|
||||
void initDynAttribs();
|
||||
static void initDefaultDynAttribs();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** debuglogger.cpp
|
||||
** gl-debug.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
|
@ -19,25 +19,25 @@
|
|||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "debuglogger.h"
|
||||
#include "gl-debug.h"
|
||||
#include "debugwriter.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "gl-fun.h"
|
||||
|
||||
struct DebugLoggerPrivate
|
||||
struct GLDebugLoggerPrivate
|
||||
{
|
||||
std::ostream *stream;
|
||||
|
||||
DebugLoggerPrivate(const char *logFilename)
|
||||
GLDebugLoggerPrivate(const char *logFilename)
|
||||
{
|
||||
(void) logFilename;
|
||||
|
||||
stream = &std::clog;
|
||||
}
|
||||
|
||||
~DebugLoggerPrivate()
|
||||
~GLDebugLoggerPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ static void APIENTRY arbDebugFunc(GLenum source,
|
|||
const GLchar* message,
|
||||
const void* userParam)
|
||||
{
|
||||
DebugLoggerPrivate *p =
|
||||
static_cast<DebugLoggerPrivate*>(const_cast<void*>(userParam));
|
||||
GLDebugLoggerPrivate *p =
|
||||
static_cast<GLDebugLoggerPrivate*>(const_cast<void*>(userParam));
|
||||
|
||||
(void) source;
|
||||
(void) type;
|
||||
|
@ -75,9 +75,9 @@ static void APIENTRY arbDebugFunc(GLenum source,
|
|||
p->writeLine(message);
|
||||
}
|
||||
|
||||
DebugLogger::DebugLogger(const char *filename)
|
||||
GLDebugLogger::GLDebugLogger(const char *filename)
|
||||
{
|
||||
p = new DebugLoggerPrivate(filename);
|
||||
p = new GLDebugLoggerPrivate(filename);
|
||||
|
||||
if (gl.DebugMessageCallback)
|
||||
gl.DebugMessageCallback(arbDebugFunc, p);
|
||||
|
@ -85,7 +85,7 @@ DebugLogger::DebugLogger(const char *filename)
|
|||
Debug() << "DebugLogger: no debug extensions found";
|
||||
}
|
||||
|
||||
DebugLogger::~DebugLogger()
|
||||
GLDebugLogger::~GLDebugLogger()
|
||||
{
|
||||
delete p;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** debuglogger.h
|
||||
** gl-debug.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
|
@ -22,16 +22,30 @@
|
|||
#ifndef DEBUGLOGGER_H
|
||||
#define DEBUGLOGGER_H
|
||||
|
||||
struct DebugLoggerPrivate;
|
||||
#include "gl-fun.h"
|
||||
|
||||
class DebugLogger
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
|
||||
struct GLDebugLoggerPrivate;
|
||||
|
||||
class GLDebugLogger
|
||||
{
|
||||
public:
|
||||
DebugLogger(const char *filename = 0);
|
||||
~DebugLogger();
|
||||
GLDebugLogger(const char *filename = 0);
|
||||
~GLDebugLogger();
|
||||
|
||||
private:
|
||||
DebugLoggerPrivate *p;
|
||||
GLDebugLoggerPrivate *p;
|
||||
};
|
||||
|
||||
#define GL_MARKER(format, ...) \
|
||||
if (gl.StringMarker) \
|
||||
{ \
|
||||
char buf[128]; \
|
||||
int len = snprintf(buf, sizeof(buf), format, ##__VA_ARGS__); \
|
||||
gl.StringMarker(std::min<size_t>(len, sizeof(buf)), buf); \
|
||||
}
|
||||
|
||||
|
||||
#endif // DEBUGLOGGER_H
|
|
@ -29,12 +29,12 @@
|
|||
|
||||
GLFunctions gl;
|
||||
|
||||
typedef const GLubyte* (APIENTRYP PFNGLGETSTRINGIPROC) (GLenum, GLuint);
|
||||
typedef const GLubyte* (APIENTRYP _PFNGLGETSTRINGIPROC) (GLenum, GLuint);
|
||||
|
||||
static void parseExtensionsCore(PFNGLGETINTEGERVPROC GetIntegerv, BoostSet<std::string> &out)
|
||||
static void parseExtensionsCore(_PFNGLGETINTEGERVPROC GetIntegerv, BoostSet<std::string> &out)
|
||||
{
|
||||
PFNGLGETSTRINGIPROC GetStringi =
|
||||
(PFNGLGETSTRINGIPROC) SDL_GL_GetProcAddress("glGetStringi");
|
||||
_PFNGLGETSTRINGIPROC GetStringi =
|
||||
(_PFNGLGETSTRINGIPROC) SDL_GL_GetProcAddress("glGetStringi");
|
||||
|
||||
GLint extCount = 0;
|
||||
GetIntegerv(GL_NUM_EXTENSIONS, &extCount);
|
||||
|
@ -43,7 +43,7 @@ static void parseExtensionsCore(PFNGLGETINTEGERVPROC GetIntegerv, BoostSet<std::
|
|||
out.insert((const char*) GetStringi(GL_EXTENSIONS, i));
|
||||
}
|
||||
|
||||
static void parseExtensionsCompat(PFNGLGETSTRINGPROC GetString, BoostSet<std::string> &out)
|
||||
static void parseExtensionsCompat(_PFNGLGETSTRINGPROC GetString, BoostSet<std::string> &out)
|
||||
{
|
||||
const char *ext = (const char*) GetString(GL_EXTENSIONS);
|
||||
|
||||
|
@ -82,8 +82,8 @@ void initGLFunctions()
|
|||
/* Determine GL version */
|
||||
const char *ver = (const char*) gl.GetString(GL_VERSION);
|
||||
|
||||
const char *glesPrefix = "OpenGL ES ";
|
||||
size_t glesPrefixN = strlen(glesPrefix);
|
||||
const char glesPrefix[] = "OpenGL ES ";
|
||||
const size_t glesPrefixN = sizeof(glesPrefix)-1;
|
||||
|
||||
bool gles = false;
|
||||
|
||||
|
@ -101,6 +101,11 @@ void initGLFunctions()
|
|||
if (glMajor < 2)
|
||||
throw EXC("At least OpenGL (ES) 2.0 is required");
|
||||
|
||||
if (gles)
|
||||
{
|
||||
GL_ES_FUN;
|
||||
}
|
||||
|
||||
BoostSet<std::string> ext;
|
||||
|
||||
if (glMajor >= 3)
|
||||
|
@ -172,6 +177,13 @@ void initGLFunctions()
|
|||
GL_DEBUG_KHR_FUN;
|
||||
}
|
||||
|
||||
if (HAVE_EXT(GREMEDY_string_marker))
|
||||
{
|
||||
#undef EXT_SUFFIX
|
||||
#define EXT_SUFFIX "GREMEDY"
|
||||
GL_GREMEMDY_FUN;
|
||||
}
|
||||
|
||||
/* Misc caps */
|
||||
if (!gles || glMajor >= 3 || HAVE_EXT(EXT_unpack_subimage))
|
||||
gl.unpack_subimage = true;
|
||||
|
|
249
src/gl-fun.h
249
src/gl-fun.h
|
@ -30,179 +30,194 @@
|
|||
#endif
|
||||
|
||||
/* Etc */
|
||||
typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
|
||||
typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
|
||||
typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
|
||||
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
|
||||
typedef GLenum (APIENTRYP _PFNGLGETERRORPROC) (void);
|
||||
typedef void (APIENTRYP _PFNGLCLEARCOLORPROC) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
|
||||
typedef void (APIENTRYP _PFNGLCLEARPROC) (GLbitfield mask);
|
||||
typedef const GLubyte * (APIENTRYP _PFNGLGETSTRINGPROC) (GLenum name);
|
||||
typedef void (APIENTRYP _PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
|
||||
typedef void (APIENTRYP _PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP _PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
|
||||
typedef void (APIENTRYP _PFNGLENABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP _PFNGLDISABLEPROC) (GLenum cap);
|
||||
typedef void (APIENTRYP _PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP _PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
typedef void (APIENTRYP _PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
|
||||
typedef void (APIENTRYP _PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef void (APIENTRYP _PFNGLBLENDEQUATIONPROC) (GLenum mode);
|
||||
typedef void (APIENTRYP _PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
|
||||
|
||||
/* Texture */
|
||||
typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
|
||||
typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
|
||||
typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
typedef void (APIENTRYP _PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
|
||||
typedef void (APIENTRYP _PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
|
||||
typedef void (APIENTRYP _PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
|
||||
typedef void (APIENTRYP _PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP _PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
|
||||
typedef void (APIENTRYP _PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
|
||||
typedef void (APIENTRYP _PFNGLACTIVETEXTUREPROC) (GLenum texture);
|
||||
|
||||
/* Debug callback */
|
||||
/* Debugging */
|
||||
typedef void (APIENTRY * _GLDEBUGPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void *userParam);
|
||||
typedef void (APIENTRYP _PFNGLDEBUGMESSAGECALLBACKPROC) (_GLDEBUGPROC callback, const void *userParam);
|
||||
typedef void (APIENTRYP _PFNGLSTRINGMARKERPROC) (GLsizei len, const GLvoid *string);
|
||||
|
||||
/* Buffer object */
|
||||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
|
||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
|
||||
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
|
||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
|
||||
typedef void (APIENTRYP _PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
|
||||
typedef void (APIENTRYP _PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers);
|
||||
typedef void (APIENTRYP _PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (APIENTRYP _PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
|
||||
typedef void (APIENTRYP _PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
|
||||
|
||||
/* Shader */
|
||||
typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const* strings, const GLint* lengths);
|
||||
typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param);
|
||||
typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
|
||||
typedef GLuint (APIENTRYP _PFNGLCREATESHADERPROC) (GLenum type);
|
||||
typedef void (APIENTRYP _PFNGLDELETESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP _PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const* strings, const GLint* lengths);
|
||||
typedef void (APIENTRYP _PFNGLCOMPILESHADERPROC) (GLuint shader);
|
||||
typedef void (APIENTRYP _PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
|
||||
typedef void (APIENTRYP _PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param);
|
||||
typedef void (APIENTRYP _PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
|
||||
|
||||
/* Program */
|
||||
typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param);
|
||||
typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
|
||||
typedef GLuint (APIENTRYP _PFNGLCREATEPROGRAMPROC) (void);
|
||||
typedef void (APIENTRYP _PFNGLDELETEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP _PFNGLUSEPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP _PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (APIENTRYP _PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param);
|
||||
typedef void (APIENTRYP _PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog);
|
||||
|
||||
/* Uniform */
|
||||
typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
typedef GLint (APIENTRYP _PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar* name);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
|
||||
/* Vertex attribute */
|
||||
typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
|
||||
typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint);
|
||||
typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint);
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
|
||||
typedef void (APIENTRYP _PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name);
|
||||
typedef void (APIENTRYP _PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint);
|
||||
typedef void (APIENTRYP _PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint);
|
||||
typedef void (APIENTRYP _PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer);
|
||||
|
||||
/* Framebuffer object */
|
||||
typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
|
||||
typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
|
||||
typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
|
||||
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
typedef void (APIENTRYP _PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint* framebuffers);
|
||||
typedef void (APIENTRYP _PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint* framebuffers);
|
||||
typedef void (APIENTRYP _PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
|
||||
typedef void (APIENTRYP _PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
|
||||
typedef void (APIENTRYP _PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
|
||||
|
||||
/* Vertex array object */
|
||||
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
|
||||
typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
|
||||
typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
|
||||
typedef void (APIENTRYP _PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
|
||||
typedef void (APIENTRYP _PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
|
||||
typedef void (APIENTRYP _PFNGLBINDVERTEXARRAYPROC) (GLuint array);
|
||||
|
||||
/* GLES only */
|
||||
typedef void (APIENTRYP _PFNGLRELEASESHADERCOMPILERPROC) (void);
|
||||
|
||||
#ifdef GLES2_HEADER
|
||||
#define GL_NUM_EXTENSIONS 0x821D
|
||||
#define GL_READ_FRAMEBUFFER 0x8CA8
|
||||
#define GL_DRAW_FRAMEBUFFER 0x8CA9
|
||||
#define GL_UNPACK_ROW_LENGTH 0x0CF2
|
||||
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
|
||||
#define GL_UNPACK_SKIP_ROWS 0x0CF3
|
||||
#endif
|
||||
|
||||
#define GL_20_FUN \
|
||||
/* Etc */ \
|
||||
GL_FUN(GetError, PFNGLGETERRORPROC) \
|
||||
GL_FUN(ClearColor, PFNGLCLEARCOLORPROC) \
|
||||
GL_FUN(Clear, PFNGLCLEARPROC) \
|
||||
GL_FUN(GetString, PFNGLGETSTRINGPROC) \
|
||||
GL_FUN(GetIntegerv, PFNGLGETINTEGERVPROC) \
|
||||
GL_FUN(PixelStorei, PFNGLPIXELSTOREIPROC) \
|
||||
GL_FUN(ReadPixels, PFNGLREADPIXELSPROC) \
|
||||
GL_FUN(Enable, PFNGLENABLEPROC) \
|
||||
GL_FUN(Disable, PFNGLDISABLEPROC) \
|
||||
GL_FUN(Scissor, PFNGLSCISSORPROC) \
|
||||
GL_FUN(Viewport, PFNGLVIEWPORTPROC) \
|
||||
GL_FUN(BlendFunc, PFNGLBLENDFUNCPROC) \
|
||||
GL_FUN(BlendFuncSeparate, PFNGLBLENDFUNCSEPARATEPROC) \
|
||||
GL_FUN(BlendEquation, PFNGLBLENDEQUATIONPROC) \
|
||||
GL_FUN(DrawElements, PFNGLDRAWELEMENTSPROC) \
|
||||
GL_FUN(GetError, _PFNGLGETERRORPROC) \
|
||||
GL_FUN(ClearColor, _PFNGLCLEARCOLORPROC) \
|
||||
GL_FUN(Clear, _PFNGLCLEARPROC) \
|
||||
GL_FUN(GetString, _PFNGLGETSTRINGPROC) \
|
||||
GL_FUN(GetIntegerv, _PFNGLGETINTEGERVPROC) \
|
||||
GL_FUN(PixelStorei, _PFNGLPIXELSTOREIPROC) \
|
||||
GL_FUN(ReadPixels, _PFNGLREADPIXELSPROC) \
|
||||
GL_FUN(Enable, _PFNGLENABLEPROC) \
|
||||
GL_FUN(Disable, _PFNGLDISABLEPROC) \
|
||||
GL_FUN(Scissor, _PFNGLSCISSORPROC) \
|
||||
GL_FUN(Viewport, _PFNGLVIEWPORTPROC) \
|
||||
GL_FUN(BlendFunc, _PFNGLBLENDFUNCPROC) \
|
||||
GL_FUN(BlendFuncSeparate, _PFNGLBLENDFUNCSEPARATEPROC) \
|
||||
GL_FUN(BlendEquation, _PFNGLBLENDEQUATIONPROC) \
|
||||
GL_FUN(DrawElements, _PFNGLDRAWELEMENTSPROC) \
|
||||
/* Texture */ \
|
||||
GL_FUN(GenTextures, PFNGLGENTEXTURESPROC) \
|
||||
GL_FUN(DeleteTextures, PFNGLDELETETEXTURESPROC) \
|
||||
GL_FUN(BindTexture, PFNGLBINDTEXTUREPROC) \
|
||||
GL_FUN(TexImage2D, PFNGLTEXIMAGE2DPROC) \
|
||||
GL_FUN(TexSubImage2D, PFNGLTEXSUBIMAGE2DPROC) \
|
||||
GL_FUN(TexParameteri, PFNGLTEXPARAMETERIPROC) \
|
||||
GL_FUN(ActiveTexture, PFNGLACTIVETEXTUREPROC) \
|
||||
GL_FUN(GenTextures, _PFNGLGENTEXTURESPROC) \
|
||||
GL_FUN(DeleteTextures, _PFNGLDELETETEXTURESPROC) \
|
||||
GL_FUN(BindTexture, _PFNGLBINDTEXTUREPROC) \
|
||||
GL_FUN(TexImage2D, _PFNGLTEXIMAGE2DPROC) \
|
||||
GL_FUN(TexSubImage2D, _PFNGLTEXSUBIMAGE2DPROC) \
|
||||
GL_FUN(TexParameteri, _PFNGLTEXPARAMETERIPROC) \
|
||||
GL_FUN(ActiveTexture, _PFNGLACTIVETEXTUREPROC) \
|
||||
/* Buffer object */ \
|
||||
GL_FUN(GenBuffers, PFNGLGENBUFFERSPROC) \
|
||||
GL_FUN(DeleteBuffers, PFNGLDELETEBUFFERSPROC) \
|
||||
GL_FUN(BindBuffer, PFNGLBINDBUFFERPROC) \
|
||||
GL_FUN(BufferData, PFNGLBUFFERDATAPROC) \
|
||||
GL_FUN(BufferSubData, PFNGLBUFFERSUBDATAPROC) \
|
||||
GL_FUN(GenBuffers, _PFNGLGENBUFFERSPROC) \
|
||||
GL_FUN(DeleteBuffers, _PFNGLDELETEBUFFERSPROC) \
|
||||
GL_FUN(BindBuffer, _PFNGLBINDBUFFERPROC) \
|
||||
GL_FUN(BufferData, _PFNGLBUFFERDATAPROC) \
|
||||
GL_FUN(BufferSubData, _PFNGLBUFFERSUBDATAPROC) \
|
||||
/* Shader */ \
|
||||
GL_FUN(CreateShader, PFNGLCREATESHADERPROC) \
|
||||
GL_FUN(DeleteShader, PFNGLDELETESHADERPROC) \
|
||||
GL_FUN(ShaderSource, PFNGLSHADERSOURCEPROC) \
|
||||
GL_FUN(CompileShader, PFNGLCOMPILESHADERPROC) \
|
||||
GL_FUN(AttachShader, PFNGLATTACHSHADERPROC) \
|
||||
GL_FUN(GetShaderiv, PFNGLGETSHADERIVPROC) \
|
||||
GL_FUN(GetShaderInfoLog, PFNGLGETSHADERINFOLOGPROC) \
|
||||
GL_FUN(CreateShader, _PFNGLCREATESHADERPROC) \
|
||||
GL_FUN(DeleteShader, _PFNGLDELETESHADERPROC) \
|
||||
GL_FUN(ShaderSource, _PFNGLSHADERSOURCEPROC) \
|
||||
GL_FUN(CompileShader, _PFNGLCOMPILESHADERPROC) \
|
||||
GL_FUN(AttachShader, _PFNGLATTACHSHADERPROC) \
|
||||
GL_FUN(GetShaderiv, _PFNGLGETSHADERIVPROC) \
|
||||
GL_FUN(GetShaderInfoLog, _PFNGLGETSHADERINFOLOGPROC) \
|
||||
/* Program */ \
|
||||
GL_FUN(CreateProgram, PFNGLCREATEPROGRAMPROC) \
|
||||
GL_FUN(DeleteProgram, PFNGLDELETEPROGRAMPROC) \
|
||||
GL_FUN(UseProgram, PFNGLUSEPROGRAMPROC) \
|
||||
GL_FUN(LinkProgram, PFNGLLINKPROGRAMPROC) \
|
||||
GL_FUN(GetProgramiv, PFNGLGETPROGRAMIVPROC) \
|
||||
GL_FUN(GetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC) \
|
||||
GL_FUN(CreateProgram, _PFNGLCREATEPROGRAMPROC) \
|
||||
GL_FUN(DeleteProgram, _PFNGLDELETEPROGRAMPROC) \
|
||||
GL_FUN(UseProgram, _PFNGLUSEPROGRAMPROC) \
|
||||
GL_FUN(LinkProgram, _PFNGLLINKPROGRAMPROC) \
|
||||
GL_FUN(GetProgramiv, _PFNGLGETPROGRAMIVPROC) \
|
||||
GL_FUN(GetProgramInfoLog, _PFNGLGETPROGRAMINFOLOGPROC) \
|
||||
/* Uniform */ \
|
||||
GL_FUN(GetUniformLocation, PFNGLGETUNIFORMLOCATIONPROC) \
|
||||
GL_FUN(Uniform1f, PFNGLUNIFORM1FPROC) \
|
||||
GL_FUN(Uniform2f, PFNGLUNIFORM2FPROC) \
|
||||
GL_FUN(Uniform4f, PFNGLUNIFORM4FPROC) \
|
||||
GL_FUN(Uniform1i, PFNGLUNIFORM1IPROC) \
|
||||
GL_FUN(UniformMatrix4fv, PFNGLUNIFORMMATRIX4FVPROC) \
|
||||
GL_FUN(GetUniformLocation, _PFNGLGETUNIFORMLOCATIONPROC) \
|
||||
GL_FUN(Uniform1f, _PFNGLUNIFORM1FPROC) \
|
||||
GL_FUN(Uniform2f, _PFNGLUNIFORM2FPROC) \
|
||||
GL_FUN(Uniform4f, _PFNGLUNIFORM4FPROC) \
|
||||
GL_FUN(Uniform1i, _PFNGLUNIFORM1IPROC) \
|
||||
GL_FUN(UniformMatrix4fv, _PFNGLUNIFORMMATRIX4FVPROC) \
|
||||
/* Vertex attribute */ \
|
||||
GL_FUN(BindAttribLocation, PFNGLBINDATTRIBLOCATIONPROC) \
|
||||
GL_FUN(EnableVertexAttribArray, PFNGLENABLEVERTEXATTRIBARRAYPROC) \
|
||||
GL_FUN(DisableVertexAttribArray, PFNGLDISABLEVERTEXATTRIBARRAYPROC) \
|
||||
GL_FUN(VertexAttribPointer, PFNGLVERTEXATTRIBPOINTERPROC)
|
||||
GL_FUN(BindAttribLocation, _PFNGLBINDATTRIBLOCATIONPROC) \
|
||||
GL_FUN(EnableVertexAttribArray, _PFNGLENABLEVERTEXATTRIBARRAYPROC) \
|
||||
GL_FUN(DisableVertexAttribArray, _PFNGLDISABLEVERTEXATTRIBARRAYPROC) \
|
||||
GL_FUN(VertexAttribPointer, _PFNGLVERTEXATTRIBPOINTERPROC)
|
||||
|
||||
#define GL_ES_FUN \
|
||||
GL_FUN(ReleaseShaderCompiler, _PFNGLRELEASESHADERCOMPILERPROC)
|
||||
|
||||
#define GL_FBO_FUN \
|
||||
/* Framebuffer object */ \
|
||||
GL_FUN(GenFramebuffers, PFNGLGENFRAMEBUFFERSPROC) \
|
||||
GL_FUN(DeleteFramebuffers, PFNGLDELETEFRAMEBUFFERSPROC) \
|
||||
GL_FUN(BindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \
|
||||
GL_FUN(FramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC)
|
||||
GL_FUN(GenFramebuffers, _PFNGLGENFRAMEBUFFERSPROC) \
|
||||
GL_FUN(DeleteFramebuffers, _PFNGLDELETEFRAMEBUFFERSPROC) \
|
||||
GL_FUN(BindFramebuffer, _PFNGLBINDFRAMEBUFFERPROC) \
|
||||
GL_FUN(FramebufferTexture2D, _PFNGLFRAMEBUFFERTEXTURE2DPROC)
|
||||
|
||||
#define GL_FBO_BLIT_FUN \
|
||||
GL_FUN(BlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC)
|
||||
GL_FUN(BlitFramebuffer, _PFNGLBLITFRAMEBUFFERPROC)
|
||||
|
||||
#define GL_VAO_FUN \
|
||||
/* Vertex array object */ \
|
||||
GL_FUN(GenVertexArrays, PFNGLGENVERTEXARRAYSPROC) \
|
||||
GL_FUN(DeleteVertexArrays, PFNGLDELETEVERTEXARRAYSPROC) \
|
||||
GL_FUN(BindVertexArray, PFNGLBINDVERTEXARRAYPROC)
|
||||
GL_FUN(GenVertexArrays, _PFNGLGENVERTEXARRAYSPROC) \
|
||||
GL_FUN(DeleteVertexArrays, _PFNGLDELETEVERTEXARRAYSPROC) \
|
||||
GL_FUN(BindVertexArray, _PFNGLBINDVERTEXARRAYPROC)
|
||||
|
||||
#define GL_DEBUG_KHR_FUN \
|
||||
GL_FUN(DebugMessageCallback, _PFNGLDEBUGMESSAGECALLBACKPROC)
|
||||
|
||||
#define GL_GREMEMDY_FUN \
|
||||
GL_FUN(StringMarker, _PFNGLSTRINGMARKERPROC)
|
||||
|
||||
|
||||
struct GLFunctions
|
||||
{
|
||||
#define GL_FUN(name, type) type name;
|
||||
|
||||
GL_20_FUN
|
||||
GL_ES_FUN
|
||||
GL_FBO_FUN
|
||||
GL_FBO_BLIT_FUN
|
||||
GL_VAO_FUN
|
||||
GL_DEBUG_KHR_FUN
|
||||
GL_GREMEMDY_FUN
|
||||
|
||||
bool glsles;
|
||||
bool unpack_subimage;
|
||||
|
|
|
@ -61,43 +61,43 @@ namespace TEX
|
|||
return id;
|
||||
}
|
||||
|
||||
inline void del(ID id)
|
||||
static inline void del(ID id)
|
||||
{
|
||||
gl.DeleteTextures(1, &id.gl);
|
||||
}
|
||||
|
||||
inline void bind(ID id)
|
||||
static inline void bind(ID id)
|
||||
{
|
||||
gl.BindTexture(GL_TEXTURE_2D, id.gl);
|
||||
}
|
||||
|
||||
inline void unbind()
|
||||
static inline void unbind()
|
||||
{
|
||||
bind(ID(0));
|
||||
}
|
||||
|
||||
inline void uploadImage(GLsizei width, GLsizei height, const void *data, GLenum format)
|
||||
static inline void uploadImage(GLsizei width, GLsizei height, const void *data, GLenum format)
|
||||
{
|
||||
gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
inline void uploadSubImage(GLint x, GLint y, GLsizei width, GLsizei height, const void *data, GLenum format)
|
||||
static inline void uploadSubImage(GLint x, GLint y, GLsizei width, GLsizei height, const void *data, GLenum format)
|
||||
{
|
||||
gl.TexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, format, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
inline void allocEmpty(GLsizei width, GLsizei height)
|
||||
static inline void allocEmpty(GLsizei width, GLsizei height)
|
||||
{
|
||||
gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
inline void setRepeat(bool mode)
|
||||
static inline void setRepeat(bool mode)
|
||||
{
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
inline void setSmooth(bool mode)
|
||||
static inline void setSmooth(bool mode)
|
||||
{
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode ? GL_LINEAR : GL_NEAREST);
|
||||
gl.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mode ? GL_LINEAR : GL_NEAREST);
|
||||
|
@ -117,27 +117,27 @@ namespace FBO
|
|||
return id;
|
||||
}
|
||||
|
||||
inline void del(ID id)
|
||||
static inline void del(ID id)
|
||||
{
|
||||
gl.DeleteFramebuffers(1, &id.gl);
|
||||
}
|
||||
|
||||
inline void bind(ID id)
|
||||
static inline void bind(ID id)
|
||||
{
|
||||
gl.BindFramebuffer(GL_FRAMEBUFFER, id.gl);
|
||||
}
|
||||
|
||||
inline void unbind()
|
||||
static inline void unbind()
|
||||
{
|
||||
bind(ID(0));
|
||||
}
|
||||
|
||||
inline void setTarget(TEX::ID target, unsigned colorAttach = 0)
|
||||
static inline void setTarget(TEX::ID target, unsigned colorAttach = 0)
|
||||
{
|
||||
gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_TEXTURE_2D, target.gl, 0);
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
static inline void clear()
|
||||
{
|
||||
gl.Clear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ struct GenericBO
|
|||
{
|
||||
DEF_GL_ID
|
||||
|
||||
inline static ID gen()
|
||||
static inline ID gen()
|
||||
{
|
||||
ID id;
|
||||
gl.GenBuffers(1, &id.gl);
|
||||
|
@ -156,32 +156,32 @@ struct GenericBO
|
|||
return id;
|
||||
}
|
||||
|
||||
inline static void del(ID id)
|
||||
static inline void del(ID id)
|
||||
{
|
||||
gl.DeleteBuffers(1, &id.gl);
|
||||
}
|
||||
|
||||
inline static void bind(ID id)
|
||||
static inline void bind(ID id)
|
||||
{
|
||||
gl.BindBuffer(target, id.gl);
|
||||
}
|
||||
|
||||
inline static void unbind()
|
||||
static inline void unbind()
|
||||
{
|
||||
bind(ID(0));
|
||||
}
|
||||
|
||||
inline static void uploadData(GLsizeiptr size, const GLvoid *data, GLenum usage = GL_STATIC_DRAW)
|
||||
static inline void uploadData(GLsizeiptr size, const GLvoid *data, GLenum usage = GL_STATIC_DRAW)
|
||||
{
|
||||
gl.BufferData(target, size, data, usage);
|
||||
}
|
||||
|
||||
inline static void uploadSubData(GLintptr offset, GLsizeiptr size, const GLvoid *data)
|
||||
static inline void uploadSubData(GLintptr offset, GLsizeiptr size, const GLvoid *data)
|
||||
{
|
||||
gl.BufferSubData(target, offset, size, data);
|
||||
}
|
||||
|
||||
inline static void allocEmpty(GLsizeiptr size, GLenum usage = GL_STATIC_DRAW)
|
||||
static inline void allocEmpty(GLsizeiptr size, GLenum usage = GL_STATIC_DRAW)
|
||||
{
|
||||
uploadData(size, 0, usage);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ void GLScissorBox::apply(const IntRect &value)
|
|||
|
||||
void GLScissorBox::setIntersect(const IntRect &value)
|
||||
{
|
||||
IntRect ¤t = get();
|
||||
const IntRect ¤t = get();
|
||||
|
||||
SDL_Rect r1 = { current.x, current.y, current.w, current.h };
|
||||
SDL_Rect r2 = { value.x, value.y, value.w, value.h };
|
||||
|
|
|
@ -43,7 +43,7 @@ struct GLProperty
|
|||
|
||||
void push() { stack.push(current); }
|
||||
void pop() { set(stack.top()); stack.pop(); }
|
||||
T &get() { return current; }
|
||||
const T &get() { return current; }
|
||||
void set(const T &value)
|
||||
{
|
||||
if (value == current)
|
||||
|
|
162
src/graphics.cpp
162
src/graphics.cpp
|
@ -171,36 +171,112 @@ public:
|
|||
|
||||
void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
|
||||
{
|
||||
pp.swapRender();
|
||||
const IntRect &viewpRect = glState.scissorBox.get();
|
||||
const IntRect &screenRect = geometry.rect;
|
||||
|
||||
/* Scissor test _does_ affect FBO blit operations,
|
||||
* and since we're inside the draw cycle, it will
|
||||
* be turned on, so turn it off temporarily */
|
||||
glState.scissorTest.pushSet(false);
|
||||
if (t.w != 0.0)
|
||||
{
|
||||
pp.swapRender();
|
||||
|
||||
GLMeta::blitBegin(pp.frontBuffer());
|
||||
GLMeta::blitSource(pp.backBuffer());
|
||||
GLMeta::blitRectangle(geometry.rect, Vec2i());
|
||||
GLMeta::blitEnd();
|
||||
if (!viewpRect.encloses(screenRect))
|
||||
{
|
||||
/* Scissor test _does_ affect FBO blit operations,
|
||||
* and since we're inside the draw cycle, it will
|
||||
* be turned on, so turn it off temporarily */
|
||||
glState.scissorTest.pushSet(false);
|
||||
|
||||
glState.scissorTest.pop();
|
||||
GLMeta::blitBegin(pp.frontBuffer());
|
||||
GLMeta::blitSource(pp.backBuffer());
|
||||
GLMeta::blitRectangle(geometry.rect, Vec2i());
|
||||
GLMeta::blitEnd();
|
||||
|
||||
PlaneShader &shader = shState->shaders().plane;
|
||||
glState.scissorTest.pop();
|
||||
}
|
||||
|
||||
GrayShader &shader = shState->shaders().gray;
|
||||
shader.bind();
|
||||
shader.setGray(t.w);
|
||||
shader.applyViewportProj();
|
||||
shader.setTexSize(screenRect.size());
|
||||
|
||||
TEX::bind(pp.backBuffer().tex);
|
||||
|
||||
glState.blend.pushSet(false);
|
||||
screenQuad.draw();
|
||||
glState.blend.pop();
|
||||
}
|
||||
|
||||
bool toneEffect = t.xyzHasEffect();
|
||||
bool colorEffect = c.xyzHasEffect();
|
||||
bool flashEffect = f.xyzHasEffect();
|
||||
|
||||
if (!toneEffect && !colorEffect && !flashEffect)
|
||||
return;
|
||||
|
||||
FlatColorShader &shader = shState->shaders().flatColor;
|
||||
shader.bind();
|
||||
shader.setColor(c);
|
||||
shader.setFlash(f);
|
||||
shader.setTone(t);
|
||||
shader.setOpacity(1.0);
|
||||
shader.applyViewportProj();
|
||||
shader.setTexSize(geometry.rect.size());
|
||||
|
||||
TEX::bind(pp.backBuffer().tex);
|
||||
/* Apply tone */
|
||||
if (toneEffect)
|
||||
{
|
||||
/* First split up additive / substractive components */
|
||||
Vec4 add, sub;
|
||||
|
||||
glState.blend.pushSet(false);
|
||||
if (t.x > 0)
|
||||
add.x = t.x;
|
||||
if (t.y > 0)
|
||||
add.y = t.y;
|
||||
if (t.z > 0)
|
||||
add.z = t.z;
|
||||
|
||||
screenQuad.draw();
|
||||
if (t.x < 0)
|
||||
sub.x = -t.x;
|
||||
if (t.y < 0)
|
||||
sub.y = -t.y;
|
||||
if (t.z < 0)
|
||||
sub.z = -t.z;
|
||||
|
||||
glState.blend.pop();
|
||||
/* Then apply them using hardware blending */
|
||||
gl.BlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ONE);
|
||||
|
||||
if (add.xyzHasEffect())
|
||||
{
|
||||
gl.BlendEquation(GL_FUNC_ADD);
|
||||
shader.setColor(add);
|
||||
|
||||
screenQuad.draw();
|
||||
}
|
||||
|
||||
if (sub.xyzHasEffect())
|
||||
{
|
||||
gl.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
shader.setColor(sub);
|
||||
|
||||
screenQuad.draw();
|
||||
}
|
||||
}
|
||||
|
||||
if (colorEffect || flashEffect)
|
||||
{
|
||||
gl.BlendEquation(GL_FUNC_ADD);
|
||||
gl.BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL_ZERO, GL_ONE);
|
||||
}
|
||||
|
||||
if (colorEffect)
|
||||
{
|
||||
shader.setColor(c);
|
||||
screenQuad.draw();
|
||||
}
|
||||
|
||||
if (flashEffect)
|
||||
{
|
||||
shader.setColor(f);
|
||||
screenQuad.draw();
|
||||
}
|
||||
|
||||
glState.blendMode.refresh();
|
||||
}
|
||||
|
||||
void setBrightness(float norm)
|
||||
|
@ -390,6 +466,7 @@ struct GraphicsPrivate
|
|||
|
||||
ScreenScene screen;
|
||||
RGSSThreadData *threadData;
|
||||
SDL_GLContext glCtx;
|
||||
|
||||
int frameRate;
|
||||
int frameCount;
|
||||
|
@ -413,6 +490,7 @@ struct GraphicsPrivate
|
|||
winSize(rtData->config.defScreenW, rtData->config.defScreenH),
|
||||
screen(scRes.x, scRes.y),
|
||||
threadData(rtData),
|
||||
glCtx(SDL_GL_GetCurrentContext()),
|
||||
frameRate(DEF_FRAMERATE),
|
||||
frameCount(0),
|
||||
brightness(255),
|
||||
|
@ -482,7 +560,7 @@ struct GraphicsPrivate
|
|||
|
||||
void checkResize()
|
||||
{
|
||||
if (threadData->windowSizeMsg.pollChange(&winSize.x, &winSize.y))
|
||||
if (threadData->windowSizeMsg.poll(winSize))
|
||||
{
|
||||
/* some GL drivers change the viewport on window resize */
|
||||
glState.viewport.refresh();
|
||||
|
@ -552,16 +630,40 @@ struct GraphicsPrivate
|
|||
|
||||
swapGLBuffer();
|
||||
}
|
||||
|
||||
void checkSyncLock()
|
||||
{
|
||||
if (!threadData->syncPoint.mainSyncLocked())
|
||||
return;
|
||||
|
||||
/* Releasing the GL context before sleeping and making it
|
||||
* current again on wakeup seems to avoid the context loss
|
||||
* when the app moves into the background on Android */
|
||||
SDL_GL_MakeCurrent(threadData->window, 0);
|
||||
threadData->syncPoint.waitMainSync();
|
||||
SDL_GL_MakeCurrent(threadData->window, glCtx);
|
||||
|
||||
fpsLimiter.resetFrameAdjust();
|
||||
}
|
||||
};
|
||||
|
||||
Graphics::Graphics(RGSSThreadData *data)
|
||||
{
|
||||
p = new GraphicsPrivate(data);
|
||||
|
||||
if (data->config.fixedFramerate > 0)
|
||||
p->fpsLimiter.setDesiredFPS(data->config.fixedFramerate);
|
||||
else if (data->config.fixedFramerate < 0)
|
||||
if (data->config.syncToRefreshrate)
|
||||
{
|
||||
p->frameRate = data->refreshRate;
|
||||
p->fpsLimiter.disabled = true;
|
||||
}
|
||||
else if (data->config.fixedFramerate > 0)
|
||||
{
|
||||
p->fpsLimiter.setDesiredFPS(data->config.fixedFramerate);
|
||||
}
|
||||
else if (data->config.fixedFramerate < 0)
|
||||
{
|
||||
p->fpsLimiter.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::~Graphics()
|
||||
|
@ -572,6 +674,7 @@ Graphics::~Graphics()
|
|||
void Graphics::update()
|
||||
{
|
||||
p->checkShutDownReset();
|
||||
p->checkSyncLock();
|
||||
|
||||
if (p->frozen)
|
||||
return;
|
||||
|
@ -613,10 +716,12 @@ void Graphics::transition(int duration,
|
|||
const char *filename,
|
||||
int vague)
|
||||
{
|
||||
p->checkSyncLock();
|
||||
|
||||
if (!p->frozen)
|
||||
return;
|
||||
|
||||
vague = clamp(vague, 0, 512);
|
||||
vague = clamp(vague, 1, 256);
|
||||
Bitmap *transMap = filename ? new Bitmap(filename) : 0;
|
||||
|
||||
setBrightness(255);
|
||||
|
@ -637,7 +742,7 @@ void Graphics::transition(int duration,
|
|||
shader.setFrozenScene(p->frozenScene.tex);
|
||||
shader.setCurrentScene(p->currentScene.tex);
|
||||
shader.setTransMap(transMap->getGLTypes().tex);
|
||||
shader.setVague(vague / 512.0f);
|
||||
shader.setVague(vague / 256.0);
|
||||
shader.setTexSize(p->scRes);
|
||||
}
|
||||
else
|
||||
|
@ -673,6 +778,8 @@ void Graphics::transition(int duration,
|
|||
return;
|
||||
}
|
||||
|
||||
p->checkSyncLock();
|
||||
|
||||
const float prog = i * (1.0 / duration);
|
||||
|
||||
if (transMap)
|
||||
|
@ -728,6 +835,9 @@ void Graphics::setFrameRate(int value)
|
|||
{
|
||||
p->frameRate = clamp(value, 10, 120);
|
||||
|
||||
if (p->threadData->config.syncToRefreshrate)
|
||||
return;
|
||||
|
||||
if (p->threadData->config.fixedFramerate > 0)
|
||||
return;
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ struct JsAxisBinding : public Binding
|
|||
|
||||
bool sourceActive() const
|
||||
{
|
||||
int val = EventThread::joyState.axis[source];
|
||||
int val = EventThread::joyState.axes[source];
|
||||
|
||||
if (dir == Negative)
|
||||
return val < -JAXIS_THRESHOLD;
|
||||
|
@ -150,6 +150,34 @@ struct JsAxisBinding : public Binding
|
|||
AxisDir dir;
|
||||
};
|
||||
|
||||
/* Joystick hat binding */
|
||||
struct JsHatBinding : public Binding
|
||||
{
|
||||
JsHatBinding() {}
|
||||
|
||||
JsHatBinding(uint8_t source,
|
||||
uint8_t pos,
|
||||
Input::ButtonCode target)
|
||||
: Binding(target),
|
||||
source(source),
|
||||
pos(pos)
|
||||
{}
|
||||
|
||||
bool sourceActive() const
|
||||
{
|
||||
/* For a diagonal input accept it as an input for both the axes */
|
||||
return (pos & EventThread::joyState.hats[source]) != 0;
|
||||
}
|
||||
|
||||
bool sourceRepeatable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t source;
|
||||
uint8_t pos;
|
||||
};
|
||||
|
||||
/* Mouse button binding */
|
||||
struct MsBinding : public Binding
|
||||
{
|
||||
|
@ -241,6 +269,7 @@ struct InputPrivate
|
|||
std::vector<KbBinding> kbStatBindings;
|
||||
std::vector<KbBinding> kbBindings;
|
||||
std::vector<JsAxisBinding> jsABindings;
|
||||
std::vector<JsHatBinding> jsHBindings;
|
||||
std::vector<JsButtonBinding> jsBBindings;
|
||||
std::vector<MsBinding> msBindings;
|
||||
|
||||
|
@ -348,6 +377,7 @@ struct InputPrivate
|
|||
{
|
||||
kbBindings.clear();
|
||||
jsABindings.clear();
|
||||
jsHBindings.clear();
|
||||
jsBBindings.clear();
|
||||
|
||||
for (size_t i = 0; i < d.size(); ++i)
|
||||
|
@ -381,6 +411,16 @@ struct InputPrivate
|
|||
|
||||
break;
|
||||
}
|
||||
case JHat :
|
||||
{
|
||||
JsHatBinding bind;
|
||||
bind.source = src.d.jh.hat;
|
||||
bind.pos = src.d.jh.pos;
|
||||
bind.target = desc.target;
|
||||
jsHBindings.push_back(bind);
|
||||
|
||||
break;
|
||||
}
|
||||
case JButton :
|
||||
{
|
||||
JsButtonBinding bind;
|
||||
|
@ -402,6 +442,7 @@ struct InputPrivate
|
|||
|
||||
appendBindings(kbBindings);
|
||||
appendBindings(jsABindings);
|
||||
appendBindings(jsHBindings);
|
||||
appendBindings(jsBBindings);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,6 +129,20 @@ static void addAxisBinding(BDescVec &d, uint8_t axis, AxisDir dir, Input::Button
|
|||
d.push_back(desc);
|
||||
}
|
||||
|
||||
static void addHatBinding(BDescVec &d, uint8_t hat, uint8_t pos, Input::ButtonCode target)
|
||||
{
|
||||
SourceDesc src;
|
||||
src.type = JHat;
|
||||
src.d.jh.hat = hat;
|
||||
src.d.jh.pos = pos;
|
||||
|
||||
BindingDesc desc;
|
||||
desc.src = src;
|
||||
desc.target = target;
|
||||
|
||||
d.push_back(desc);
|
||||
}
|
||||
|
||||
BDescVec genDefaultBindings(const Config &conf)
|
||||
{
|
||||
BDescVec d;
|
||||
|
@ -150,11 +164,16 @@ BDescVec genDefaultBindings(const Config &conf)
|
|||
addAxisBinding(d, 0, Positive, Input::Right);
|
||||
addAxisBinding(d, 1, Negative, Input::Up );
|
||||
addAxisBinding(d, 1, Positive, Input::Down );
|
||||
|
||||
addHatBinding(d, 0, SDL_HAT_LEFT, Input::Left );
|
||||
addHatBinding(d, 0, SDL_HAT_RIGHT, Input::Right);
|
||||
addHatBinding(d, 0, SDL_HAT_UP, Input::Up );
|
||||
addHatBinding(d, 0, SDL_HAT_DOWN, Input::Down );
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
#define FORMAT_VER 1
|
||||
#define FORMAT_VER 2
|
||||
|
||||
struct Header
|
||||
{
|
||||
|
@ -166,7 +185,7 @@ struct Header
|
|||
static void buildPath(const std::string &dir, uint32_t rgssVersion,
|
||||
char *out, size_t outSize)
|
||||
{
|
||||
snprintf(out, outSize, "%s/keybindings.mkxp%u", dir.c_str(), rgssVersion);
|
||||
snprintf(out, outSize, "%skeybindings.mkxp%u", dir.c_str(), rgssVersion);
|
||||
}
|
||||
|
||||
static bool writeBindings(const BDescVec &d, const std::string &dir,
|
||||
|
@ -178,7 +197,7 @@ static bool writeBindings(const BDescVec &d, const std::string &dir,
|
|||
char path[1024];
|
||||
buildPath(dir, rgssVersion, path, sizeof(path));
|
||||
|
||||
FILE *f = fopen(path, "w");
|
||||
FILE *f = fopen(path, "wb");
|
||||
|
||||
if (!f)
|
||||
return false;
|
||||
|
@ -247,6 +266,10 @@ static bool verifyDesc(const BindingDesc &desc)
|
|||
return src.d.scan < SDL_NUM_SCANCODES;
|
||||
case JButton:
|
||||
return true;
|
||||
case JHat:
|
||||
/* Only accept single directional binds */
|
||||
return src.d.jh.pos == SDL_HAT_LEFT || src.d.jh.pos == SDL_HAT_RIGHT ||
|
||||
src.d.jh.pos == SDL_HAT_UP || src.d.jh.pos == SDL_HAT_DOWN;
|
||||
case JAxis:
|
||||
return src.d.ja.dir == Negative || src.d.ja.dir == Positive;
|
||||
default:
|
||||
|
@ -263,7 +286,7 @@ static bool readBindings(BDescVec &out, const std::string &dir,
|
|||
char path[1024];
|
||||
buildPath(dir, rgssVersion, path, sizeof(path));
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
FILE *f = fopen(path, "rb");
|
||||
|
||||
if (!f)
|
||||
return false;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "input.h"
|
||||
|
||||
#include <SDL_scancode.h>
|
||||
#include <SDL_joystick.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
|
@ -40,7 +41,8 @@ enum SourceType
|
|||
Invalid,
|
||||
Key,
|
||||
JButton,
|
||||
JAxis
|
||||
JAxis,
|
||||
JHat
|
||||
};
|
||||
|
||||
struct SourceDesc
|
||||
|
@ -60,6 +62,13 @@ struct SourceDesc
|
|||
/* Joystick axis direction */
|
||||
AxisDir dir;
|
||||
} ja;
|
||||
struct
|
||||
{
|
||||
/* Joystick axis index */
|
||||
uint8_t hat;
|
||||
/* Joystick axis direction */
|
||||
uint8_t pos;
|
||||
} jh;
|
||||
} d;
|
||||
|
||||
bool operator==(const SourceDesc &o) const
|
||||
|
@ -77,6 +86,8 @@ struct SourceDesc
|
|||
return d.jb == o.d.jb;
|
||||
case JAxis:
|
||||
return (d.ja.axis == o.d.ja.axis) && (d.ja.dir == o.d.ja.dir);
|
||||
case JHat:
|
||||
return (d.jh.hat == o.d.jh.hat) && (d.jh.pos == o.d.jh.pos);
|
||||
default:
|
||||
assert(!"unreachable");
|
||||
return false;
|
||||
|
|
118
src/main.cpp
118
src/main.cpp
|
@ -26,20 +26,21 @@
|
|||
#include <SDL_ttf.h>
|
||||
#include <SDL_sound.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
#include "sharedstate.h"
|
||||
#include "eventthread.h"
|
||||
#include "debuglogger.h"
|
||||
#include "gl-debug.h"
|
||||
#include "debugwriter.h"
|
||||
#include "exception.h"
|
||||
#include "gl-fun.h"
|
||||
|
||||
#include "binding.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "icon.png.xxd"
|
||||
|
||||
static void
|
||||
rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
|
||||
|
@ -67,13 +68,14 @@ printGLInfo()
|
|||
int rgssThreadFun(void *userdata)
|
||||
{
|
||||
RGSSThreadData *threadData = static_cast<RGSSThreadData*>(userdata);
|
||||
const Config &conf = threadData->config;
|
||||
SDL_Window *win = threadData->window;
|
||||
SDL_GLContext glCtx;
|
||||
|
||||
/* Setup GL context */
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
if (threadData->config.debugMode)
|
||||
if (conf.debugMode)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
|
||||
glCtx = SDL_GL_CreateContext(win);
|
||||
|
@ -102,27 +104,17 @@ int rgssThreadFun(void *userdata)
|
|||
|
||||
printGLInfo();
|
||||
|
||||
SDL_GL_SetSwapInterval(threadData->config.vsync ? 1 : 0);
|
||||
bool vsync = conf.vsync || conf.syncToRefreshrate;
|
||||
SDL_GL_SetSwapInterval(vsync ? 1 : 0);
|
||||
|
||||
DebugLogger dLogger;
|
||||
GLDebugLogger dLogger;
|
||||
|
||||
/* Setup AL context */
|
||||
ALCdevice *alcDev = alcOpenDevice(0);
|
||||
|
||||
if (!alcDev)
|
||||
{
|
||||
rgssThreadError(threadData, "Error opening OpenAL device");
|
||||
SDL_GL_DeleteContext(glCtx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ALCcontext *alcCtx = alcCreateContext(alcDev, 0);
|
||||
ALCcontext *alcCtx = alcCreateContext(threadData->alcDev, 0);
|
||||
|
||||
if (!alcCtx)
|
||||
{
|
||||
rgssThreadError(threadData, "Error creating OpenAL context");
|
||||
alcCloseDevice(alcDev);
|
||||
SDL_GL_DeleteContext(glCtx);
|
||||
|
||||
return 0;
|
||||
|
@ -138,7 +130,6 @@ int rgssThreadFun(void *userdata)
|
|||
{
|
||||
rgssThreadError(threadData, exc.msg);
|
||||
alcDestroyContext(alcCtx);
|
||||
alcCloseDevice(alcDev);
|
||||
SDL_GL_DeleteContext(glCtx);
|
||||
|
||||
return 0;
|
||||
|
@ -153,8 +144,6 @@ int rgssThreadFun(void *userdata)
|
|||
SharedState::finiInstance();
|
||||
|
||||
alcDestroyContext(alcCtx);
|
||||
alcCloseDevice(alcDev);
|
||||
|
||||
SDL_GL_DeleteContext(glCtx);
|
||||
|
||||
return 0;
|
||||
|
@ -171,20 +160,27 @@ static void printRgssVersion(int ver)
|
|||
Debug() << buf;
|
||||
}
|
||||
|
||||
static void showInitError(const std::string &msg)
|
||||
{
|
||||
Debug() << msg;
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "mkxp", msg.c_str(), 0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
||||
|
||||
/* initialize SDL first */
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
|
||||
{
|
||||
Debug() << "Error initializing SDL:" << SDL_GetError();
|
||||
|
||||
showInitError(std::string("Error initializing SDL: ") + SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!EventThread::allocUserEvents())
|
||||
{
|
||||
Debug() << "Error allocating SDL user events";
|
||||
|
||||
showInitError("Error allocating SDL user events");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -201,8 +197,15 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* now we load the config */
|
||||
Config conf;
|
||||
|
||||
conf.read(argc, argv);
|
||||
|
||||
if (!conf.gameFolder.empty())
|
||||
if (chdir(conf.gameFolder.c_str()) != 0)
|
||||
{
|
||||
showInitError(std::string("Unable to switch into gameFolder ") + conf.gameFolder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
conf.readGameINI();
|
||||
|
||||
assert(conf.rgssVersion >= 1 && conf.rgssVersion <= 3);
|
||||
|
@ -211,7 +214,7 @@ int main(int argc, char *argv[])
|
|||
int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
|
||||
if (IMG_Init(imgFlags) != imgFlags)
|
||||
{
|
||||
Debug() << "Error initializing SDL_image:" << SDL_GetError();
|
||||
showInitError(std::string("Error initializing SDL_image: ") + SDL_GetError());
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
|
@ -219,7 +222,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (TTF_Init() < 0)
|
||||
{
|
||||
Debug() << "Error initializing SDL_ttf:" << SDL_GetError();
|
||||
showInitError(std::string("Error initializing SDL_ttf: ") + SDL_GetError());
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
|
||||
|
@ -228,7 +231,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (Sound_Init() == 0)
|
||||
{
|
||||
Debug() << "Error initializing SDL_sound:" << Sound_GetError();
|
||||
showInitError(std::string("Error initializing SDL_sound: ") + Sound_GetError());
|
||||
TTF_Quit();
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
|
@ -236,7 +239,15 @@ int main(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
SDL_SetHint("SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS", "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;
|
||||
|
@ -252,22 +263,43 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (!win)
|
||||
{
|
||||
Debug() << "Error creating window:" << SDL_GetError();
|
||||
showInitError(std::string("Error creating window: ") + SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!conf.iconPath.empty())
|
||||
if (iconImg)
|
||||
{
|
||||
SDL_Surface *iconImg = IMG_Load(conf.iconPath.c_str());
|
||||
if (iconImg)
|
||||
{
|
||||
SDL_SetWindowIcon(win, iconImg);
|
||||
SDL_FreeSurface(iconImg);
|
||||
}
|
||||
SDL_SetWindowIcon(win, iconImg);
|
||||
SDL_FreeSurface(iconImg);
|
||||
}
|
||||
|
||||
ALCdevice *alcDev = alcOpenDevice(0);
|
||||
|
||||
if (!alcDev)
|
||||
{
|
||||
showInitError("Error opening OpenAL device");
|
||||
SDL_DestroyWindow(win);
|
||||
TTF_Quit();
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_DisplayMode mode;
|
||||
SDL_GetDisplayMode(0, 0, &mode);
|
||||
|
||||
/* Can't sync to display refresh rate if its value is unknown */
|
||||
if (!mode.refresh_rate)
|
||||
conf.syncToRefreshrate = false;
|
||||
|
||||
EventThread eventThread;
|
||||
RGSSThreadData rtData(&eventThread, argv[0], win, conf);
|
||||
RGSSThreadData rtData(&eventThread, argv[0], win,
|
||||
alcDev, mode.refresh_rate, conf);
|
||||
|
||||
int winW, winH;
|
||||
SDL_GetWindowSize(win, &winW, &winH);
|
||||
rtData.windowSizeMsg.post(Vec2i(winW, winH));
|
||||
|
||||
/* Load and post key bindings */
|
||||
rtData.bindingUpdateMsg.post(loadBindings(conf));
|
||||
|
@ -314,13 +346,9 @@ int main(int argc, char *argv[])
|
|||
/* Clean up any remainin events */
|
||||
eventThread.cleanup();
|
||||
|
||||
/* Store key bindings */
|
||||
BDescVec keyBinds;
|
||||
rtData.bindingUpdateMsg.get(keyBinds);
|
||||
storeBindings(keyBinds, rtData.config);
|
||||
|
||||
Debug() << "Shutting down.";
|
||||
|
||||
alcCloseDevice(alcDev);
|
||||
SDL_DestroyWindow(win);
|
||||
|
||||
Sound_Quit();
|
||||
|
|
|
@ -55,7 +55,13 @@
|
|||
#define TICK_FRAMES 32
|
||||
#define BUF_TICKS (STREAM_BUF_SIZE / TICK_FRAMES)
|
||||
#define DEFAULT_BPM 120
|
||||
#define LOOP_MARKER 111
|
||||
#define MAX_CHANNELS 16
|
||||
|
||||
#define CC_CTRL_VOLUME 7
|
||||
#define CC_CTRL_EXPRESSION 11
|
||||
#define CC_CTRL_LOOP 111
|
||||
|
||||
#define CC_VAL_DEFAULT 127
|
||||
|
||||
enum MidiEventType
|
||||
{
|
||||
|
@ -522,6 +528,59 @@ struct Track
|
|||
}
|
||||
};
|
||||
|
||||
/* Some songs use CC events for effects like fade-out,
|
||||
* slowly decreasing a channel's volume to 0. The problem is that
|
||||
* for looped songs, events are continuously fed into the synth
|
||||
* without restoring those controls back to their default value.
|
||||
* We can't reset them at the very beginning of tracks because it
|
||||
* might cause audible interactions with notes which are still decaying
|
||||
* past the end of the song. Therefore, we insert a fake CC event right
|
||||
* after the first NoteOn event for each channel which resets the
|
||||
* control to its default state while avoiding audible glitches.
|
||||
* If there is already a CC event for this control before the first
|
||||
* NoteOn event, we don't clobber it by not inserting our fake event. */
|
||||
template<uint8_t ctrl>
|
||||
struct CCResetter
|
||||
{
|
||||
bool chanHandled[MAX_CHANNELS];
|
||||
|
||||
CCResetter()
|
||||
{
|
||||
memset(&chanHandled, 0, sizeof(chanHandled));
|
||||
}
|
||||
|
||||
void handleEvent(const MidiEvent &e, Track &track)
|
||||
{
|
||||
if (e.type != NoteOn && e.type != CC)
|
||||
return;
|
||||
|
||||
uint8_t chan = e.e.chan.chan;
|
||||
|
||||
if (chanHandled[chan])
|
||||
return;
|
||||
|
||||
if (e.type == CC && e.e.cc.ctrl == ctrl)
|
||||
{
|
||||
/* Don't clobber the existing CC value */
|
||||
chanHandled[chan] = true;
|
||||
return;
|
||||
}
|
||||
else if (e.type == NoteOn)
|
||||
{
|
||||
chanHandled[chan] = true;
|
||||
|
||||
MidiEvent re;
|
||||
re.delta = 0;
|
||||
re.type = CC;
|
||||
re.e.cc.chan = chan;
|
||||
re.e.cc.ctrl = ctrl;
|
||||
re.e.cc.val = CC_VAL_DEFAULT;
|
||||
|
||||
track.appendEvent(re);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MidiSource : ALDataSource, MidiReadHandler
|
||||
{
|
||||
const uint16_t freq;
|
||||
|
@ -530,6 +589,8 @@ struct MidiSource : ALDataSource, MidiReadHandler
|
|||
int16_t synthBuf[BUF_TICKS*TICK_FRAMES*2];
|
||||
|
||||
std::vector<Track> tracks;
|
||||
CCResetter<CC_CTRL_VOLUME> volReset;
|
||||
CCResetter<CC_CTRL_EXPRESSION> expReset;
|
||||
|
||||
/* Index of longest track */
|
||||
uint8_t longestI;
|
||||
|
@ -631,7 +692,7 @@ struct MidiSource : ALDataSource, MidiReadHandler
|
|||
playbackSpeed = TICK_FRAMES / (deltaLength * freq);
|
||||
}
|
||||
|
||||
void activateEvent(MidiEvent &e)
|
||||
void activateEvent(const MidiEvent &e)
|
||||
{
|
||||
int16_t key = e.e.note.key;
|
||||
|
||||
|
@ -705,9 +766,14 @@ struct MidiSource : ALDataSource, MidiReadHandler
|
|||
void onMidiEvent(const MidiEvent &e, uint32_t absDelta)
|
||||
{
|
||||
assert(curTrack >= 0 && curTrack < (int16_t) tracks.size());
|
||||
tracks[curTrack].appendEvent(e);
|
||||
|
||||
if (e.type == CC && e.e.cc.ctrl == LOOP_MARKER)
|
||||
Track &track = tracks[curTrack];
|
||||
|
||||
track.appendEvent(e);
|
||||
volReset.handleEvent(e, track);
|
||||
expReset.handleEvent(e, track);
|
||||
|
||||
if (e.type == CC && e.e.cc.ctrl == CC_CTRL_LOOP)
|
||||
loopDelta = absDelta;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,8 +90,8 @@ struct PlanePrivate
|
|||
if (gl.npot_repeat)
|
||||
{
|
||||
FloatRect srcRect;
|
||||
srcRect.x = (sceneGeo.xOrigin + ox) / zoomX;
|
||||
srcRect.y = (sceneGeo.yOrigin + oy) / zoomY;
|
||||
srcRect.x = (sceneGeo.orig.x + ox) / zoomX;
|
||||
srcRect.y = (sceneGeo.orig.y + oy) / zoomY;
|
||||
srcRect.w = sceneGeo.rect.w / zoomX;
|
||||
srcRect.h = sceneGeo.rect.h / zoomY;
|
||||
|
||||
|
|
|
@ -23,10 +23,7 @@
|
|||
#include "sharedstate.h"
|
||||
|
||||
Scene::Scene()
|
||||
{
|
||||
geometry.xOrigin = geometry.yOrigin = 0;
|
||||
geometry.rect = IntRect();
|
||||
}
|
||||
{}
|
||||
|
||||
Scene::~Scene()
|
||||
{
|
||||
|
|
10
src/scene.h
10
src/scene.h
|
@ -39,8 +39,16 @@ class Scene
|
|||
public:
|
||||
struct Geometry
|
||||
{
|
||||
int xOrigin, yOrigin;
|
||||
/* Position and size relative to parent */
|
||||
IntRect rect;
|
||||
|
||||
/* Origin of contents */
|
||||
Vec2i orig;
|
||||
|
||||
Vec2i offset() const
|
||||
{
|
||||
return rect.pos() - orig;
|
||||
}
|
||||
};
|
||||
|
||||
Scene();
|
||||
|
|
113
src/sdl-util.h
113
src/sdl-util.h
|
@ -3,8 +3,10 @@
|
|||
|
||||
#include <SDL_atomic.h>
|
||||
#include <SDL_thread.h>
|
||||
#include <SDL_rwops.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
struct AtomicFlag
|
||||
{
|
||||
|
@ -45,4 +47,115 @@ SDL_Thread *createSDLThread(C *obj, const std::string &name = std::string())
|
|||
return SDL_CreateThread(__sdlThreadFun<C, func>, name.c_str(), obj);
|
||||
}
|
||||
|
||||
/* On Android, SDL_RWFromFile always opens files from inside
|
||||
* the apk asset folder even when a file with same name exists
|
||||
* on the physical filesystem. This wrapper attempts to open a
|
||||
* real file first before falling back to the assets folder */
|
||||
static inline
|
||||
SDL_RWops *RWFromFile(const char *filename,
|
||||
const char *mode)
|
||||
{
|
||||
FILE *f = fopen(filename, mode);
|
||||
|
||||
if (!f)
|
||||
return SDL_RWFromFile(filename, mode);
|
||||
|
||||
return SDL_RWFromFP(f, SDL_TRUE);
|
||||
}
|
||||
|
||||
inline bool readFileSDL(const char *path,
|
||||
std::string &out)
|
||||
{
|
||||
SDL_RWops *f = RWFromFile(path, "rb");
|
||||
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
long size = SDL_RWsize(f);
|
||||
size_t back = out.size();
|
||||
|
||||
out.resize(back+size);
|
||||
size_t read = SDL_RWread(f, &out[back], 1, size);
|
||||
SDL_RWclose(f);
|
||||
|
||||
if (read != (size_t) size)
|
||||
out.resize(back+read);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<size_t bufSize = 248, size_t pbSize = 8>
|
||||
class SDLRWBuf : public std::streambuf
|
||||
{
|
||||
public:
|
||||
SDLRWBuf(SDL_RWops *ops)
|
||||
: ops(ops)
|
||||
{
|
||||
char *end = buf + bufSize + pbSize;
|
||||
setg(end, end, end);
|
||||
}
|
||||
|
||||
private:
|
||||
int_type underflow()
|
||||
{
|
||||
if (!ops)
|
||||
return traits_type::eof();
|
||||
|
||||
if (gptr() < egptr())
|
||||
return traits_type::to_int_type(*gptr());
|
||||
|
||||
char *base = buf;
|
||||
char *start = base;
|
||||
|
||||
if (eback() == base)
|
||||
{
|
||||
memmove(base, egptr() - pbSize, pbSize);
|
||||
start += pbSize;
|
||||
}
|
||||
|
||||
size_t n = SDL_RWread(ops, start, 1, bufSize - (start - base));
|
||||
if (n == 0)
|
||||
return traits_type::eof();
|
||||
|
||||
setg(base, start, start + n);
|
||||
|
||||
return underflow();
|
||||
}
|
||||
|
||||
SDL_RWops *ops;
|
||||
char buf[bufSize+pbSize];
|
||||
};
|
||||
|
||||
class SDLRWStream
|
||||
{
|
||||
public:
|
||||
SDLRWStream(const char *filename,
|
||||
const char *mode)
|
||||
: ops(RWFromFile(filename, mode)),
|
||||
buf(ops),
|
||||
s(&buf)
|
||||
{}
|
||||
|
||||
~SDLRWStream()
|
||||
{
|
||||
if (ops)
|
||||
SDL_RWclose(ops);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return ops != 0;
|
||||
}
|
||||
|
||||
std::istream &stream()
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
private:
|
||||
SDL_RWops *ops;
|
||||
SDLRWBuf<> buf;
|
||||
std::istream s;
|
||||
};
|
||||
|
||||
#endif // SDLUTIL_H
|
||||
|
|
|
@ -27,67 +27,44 @@
|
|||
|
||||
#include <SDL_endian.h>
|
||||
|
||||
typedef unsigned uint;
|
||||
|
||||
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
|
||||
#error "Non little endian systems not supported"
|
||||
#endif
|
||||
|
||||
static inline int16_t
|
||||
read_int16(const char *data, uint &i)
|
||||
{
|
||||
int16_t result;
|
||||
|
||||
memcpy(&result, &data[i], 2);
|
||||
i += 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
read_int32(const char *data, uint &i)
|
||||
readInt32(const char **dataP)
|
||||
{
|
||||
int32_t result;
|
||||
|
||||
memcpy(&result, &data[i], 4);
|
||||
i += 4;
|
||||
memcpy(&result, *dataP, 4);
|
||||
*dataP += 4;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline double
|
||||
read_double(const char *data, uint &i)
|
||||
readDouble(const char **dataP)
|
||||
{
|
||||
double result;
|
||||
|
||||
memcpy(&result, &data[i], 8);
|
||||
i += 8;
|
||||
memcpy(&result, *dataP, 8);
|
||||
*dataP += 8;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_int16(char **data, int16_t value)
|
||||
writeInt32(char **dataP, int32_t value)
|
||||
{
|
||||
memcpy(*data, &value, 2);
|
||||
|
||||
*data += 2;
|
||||
memcpy(*dataP, &value, 4);
|
||||
*dataP += 4;
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_int32(char **data, int32_t value)
|
||||
writeDouble(char **dataP, double value)
|
||||
{
|
||||
memcpy(*data, &value, 4);
|
||||
|
||||
*data += 4;
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_double(char **data, double value)
|
||||
{
|
||||
memcpy(*data, &value, 8);
|
||||
|
||||
*data += 8;
|
||||
memcpy(*dataP, &value, 8);
|
||||
*dataP += 8;
|
||||
}
|
||||
|
||||
#endif // SERIALUTIL_H
|
||||
|
|
|
@ -81,6 +81,7 @@ static elementsN(vButtons);
|
|||
std::string sourceDescString(const SourceDesc &src)
|
||||
{
|
||||
char buf[128];
|
||||
char pos;
|
||||
|
||||
switch (src.type)
|
||||
{
|
||||
|
@ -104,6 +105,32 @@ std::string sourceDescString(const SourceDesc &src)
|
|||
snprintf(buf, sizeof(buf), "JS %d", src.d.jb);
|
||||
return buf;
|
||||
|
||||
case JHat:
|
||||
switch(src.d.jh.pos)
|
||||
{
|
||||
case SDL_HAT_UP:
|
||||
pos = 'U';
|
||||
break;
|
||||
|
||||
case SDL_HAT_DOWN:
|
||||
pos = 'D';
|
||||
break;
|
||||
|
||||
case SDL_HAT_LEFT:
|
||||
pos = 'L';
|
||||
break;
|
||||
|
||||
case SDL_HAT_RIGHT:
|
||||
pos = 'R';
|
||||
break;
|
||||
|
||||
default:
|
||||
pos = '-';
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "Hat %d:%c",
|
||||
src.d.jh.hat, pos);
|
||||
return buf;
|
||||
|
||||
case JAxis:
|
||||
snprintf(buf, sizeof(buf), "Axis %d%c",
|
||||
src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+');
|
||||
|
@ -204,7 +231,8 @@ struct Label : Widget
|
|||
Label(SMP *p, const IntRect &rect,
|
||||
const char *str, uint8_t r, uint8_t g, uint8_t b)
|
||||
: Widget(p, rect),
|
||||
str(str)
|
||||
str(str),
|
||||
visible(true)
|
||||
{
|
||||
c.r = r;
|
||||
c.g = g;
|
||||
|
@ -615,6 +643,21 @@ struct SettingsMenuPrivate
|
|||
desc.d.jb = event.jbutton.button;
|
||||
break;
|
||||
|
||||
case SDL_JOYHATMOTION:
|
||||
{
|
||||
int v = event.jhat.value;
|
||||
|
||||
/* Only register if single directional input */
|
||||
if (v != SDL_HAT_LEFT && v != SDL_HAT_RIGHT &&
|
||||
v != SDL_HAT_UP && v != SDL_HAT_DOWN)
|
||||
return true;
|
||||
|
||||
desc.type = JHat;
|
||||
desc.d.jh.hat = event.jhat.hat;
|
||||
desc.d.jh.pos = v;
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_JOYAXISMOTION:
|
||||
{
|
||||
int v = event.jaxis.value;
|
||||
|
@ -677,6 +720,9 @@ struct SettingsMenuPrivate
|
|||
|
||||
rtData.bindingUpdateMsg.post(binds);
|
||||
|
||||
/* Store the key bindings to disk as well to prevent config loss */
|
||||
storeBindings(binds, rtData.config);
|
||||
|
||||
destroyReq = true;
|
||||
}
|
||||
|
||||
|
@ -1007,6 +1053,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event)
|
|||
|
||||
case SDL_JOYBUTTONDOWN :
|
||||
case SDL_JOYBUTTONUP :
|
||||
case SDL_JOYHATMOTION :
|
||||
case SDL_JOYAXISMOTION :
|
||||
if (!p->hasFocus)
|
||||
return false;
|
||||
|
@ -1083,6 +1130,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event)
|
|||
}
|
||||
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
case SDL_JOYHATMOTION:
|
||||
case SDL_JOYAXISMOTION:
|
||||
if (p->state != AwaitingInput)
|
||||
return true;
|
||||
|
|
145
src/shader.cpp
145
src/shader.cpp
|
@ -28,25 +28,30 @@
|
|||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "../sprite.frag.xxd"
|
||||
#include "../hue.frag.xxd"
|
||||
#include "../trans.frag.xxd"
|
||||
#include "../transSimple.frag.xxd"
|
||||
#include "../bitmapBlit.frag.xxd"
|
||||
#include "../plane.frag.xxd"
|
||||
#include "../simple.frag.xxd"
|
||||
#include "../simpleColor.frag.xxd"
|
||||
#include "../simpleAlpha.frag.xxd"
|
||||
#include "../flashMap.frag.xxd"
|
||||
#include "../simple.vert.xxd"
|
||||
#include "../simpleColor.vert.xxd"
|
||||
#include "../sprite.vert.xxd"
|
||||
#include "../tilemap.vert.xxd"
|
||||
#include "../blur.frag.xxd"
|
||||
#include "../simpleMatrix.vert.xxd"
|
||||
#include "../blurH.vert.xxd"
|
||||
#include "../blurV.vert.xxd"
|
||||
#include "../tilemapvx.vert.xxd"
|
||||
#include "common.h.xxd"
|
||||
#include "sprite.frag.xxd"
|
||||
#include "hue.frag.xxd"
|
||||
#include "trans.frag.xxd"
|
||||
#include "transSimple.frag.xxd"
|
||||
#include "bitmapBlit.frag.xxd"
|
||||
#include "plane.frag.xxd"
|
||||
#include "gray.frag.xxd"
|
||||
#include "flatColor.frag.xxd"
|
||||
#include "simple.frag.xxd"
|
||||
#include "simpleColor.frag.xxd"
|
||||
#include "simpleAlpha.frag.xxd"
|
||||
#include "simpleAlphaUni.frag.xxd"
|
||||
#include "flashMap.frag.xxd"
|
||||
#include "minimal.vert.xxd"
|
||||
#include "simple.vert.xxd"
|
||||
#include "simpleColor.vert.xxd"
|
||||
#include "sprite.vert.xxd"
|
||||
#include "tilemap.vert.xxd"
|
||||
#include "blur.frag.xxd"
|
||||
#include "simpleMatrix.vert.xxd"
|
||||
#include "blurH.vert.xxd"
|
||||
#include "blurV.vert.xxd"
|
||||
#include "tilemapvx.vert.xxd"
|
||||
|
||||
|
||||
#define INIT_SHADER(vert, frag, name) \
|
||||
|
@ -106,32 +111,39 @@ void Shader::unbind()
|
|||
glState.program.set(0);
|
||||
}
|
||||
|
||||
static const char *glesHeader = "precision mediump float;\n";
|
||||
static const size_t glesHeaderSize = strlen(glesHeader);
|
||||
|
||||
static void setupShaderSource(GLuint shader,
|
||||
const unsigned char *src, int srcSize)
|
||||
static void setupShaderSource(GLuint shader, GLenum type,
|
||||
const unsigned char *body, int bodySize)
|
||||
{
|
||||
GLuint shaderSrcN;
|
||||
const GLchar *shaderSrc[2];
|
||||
GLint shaderSrcSize[2];
|
||||
static const char glesDefine[] = "#define GLSLES\n";
|
||||
static const char fragDefine[] = "#define FRAGMENT_SHADER\n";
|
||||
|
||||
const GLchar *shaderSrc[4];
|
||||
GLint shaderSrcSize[4];
|
||||
size_t i = 0;
|
||||
|
||||
if (gl.glsles)
|
||||
{
|
||||
shaderSrcN = 2;
|
||||
shaderSrc[0] = glesHeader;
|
||||
shaderSrc[1] = (const GLchar*) src;
|
||||
shaderSrcSize[0] = glesHeaderSize;
|
||||
shaderSrcSize[1] = srcSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
shaderSrcN = 1;
|
||||
shaderSrc[0] = (const GLchar*) src;
|
||||
shaderSrcSize[0] = srcSize;
|
||||
shaderSrc[i] = glesDefine;
|
||||
shaderSrcSize[i] = sizeof(glesDefine)-1;
|
||||
++i;
|
||||
}
|
||||
|
||||
gl.ShaderSource(shader, shaderSrcN, shaderSrc, shaderSrcSize);
|
||||
if (type == GL_FRAGMENT_SHADER)
|
||||
{
|
||||
shaderSrc[i] = fragDefine;
|
||||
shaderSrcSize[i] = sizeof(fragDefine)-1;
|
||||
++i;
|
||||
}
|
||||
|
||||
shaderSrc[i] = (const GLchar*) shader_common_h;
|
||||
shaderSrcSize[i] = shader_common_h_len;
|
||||
++i;
|
||||
|
||||
shaderSrc[i] = (const GLchar*) body;
|
||||
shaderSrcSize[i] = bodySize;
|
||||
++i;
|
||||
|
||||
gl.ShaderSource(shader, i, shaderSrc, shaderSrcSize);
|
||||
}
|
||||
|
||||
void Shader::init(const unsigned char *vert, int vertSize,
|
||||
|
@ -142,7 +154,7 @@ void Shader::init(const unsigned char *vert, int vertSize,
|
|||
GLint success;
|
||||
|
||||
/* Compile vertex shader */
|
||||
setupShaderSource(vertShader, vert, vertSize);
|
||||
setupShaderSource(vertShader, GL_VERTEX_SHADER, vert, vertSize);
|
||||
gl.CompileShader(vertShader);
|
||||
|
||||
gl.GetShaderiv(vertShader, GL_COMPILE_STATUS, &success);
|
||||
|
@ -156,7 +168,7 @@ void Shader::init(const unsigned char *vert, int vertSize,
|
|||
}
|
||||
|
||||
/* Compile fragment shader */
|
||||
setupShaderSource(fragShader, frag, fragSize);
|
||||
setupShaderSource(fragShader, GL_FRAGMENT_SHADER, frag, fragSize);
|
||||
gl.CompileShader(fragShader);
|
||||
|
||||
gl.GetShaderiv(fragShader, GL_COMPILE_STATUS, &success);
|
||||
|
@ -260,6 +272,21 @@ void ShaderBase::setTranslation(const Vec2i &value)
|
|||
}
|
||||
|
||||
|
||||
FlatColorShader::FlatColorShader()
|
||||
{
|
||||
INIT_SHADER(minimal, flatColor, FlatColorShader);
|
||||
|
||||
ShaderBase::init();
|
||||
|
||||
GET_U(color);
|
||||
}
|
||||
|
||||
void FlatColorShader::setColor(const Vec4 &value)
|
||||
{
|
||||
setVec4Uniform(u_color, value);
|
||||
}
|
||||
|
||||
|
||||
SimpleShader::SimpleShader()
|
||||
{
|
||||
INIT_SHADER(simple, simple, SimpleShader);
|
||||
|
@ -306,6 +333,27 @@ void SimpleSpriteShader::setSpriteMat(const float value[16])
|
|||
}
|
||||
|
||||
|
||||
AlphaSpriteShader::AlphaSpriteShader()
|
||||
{
|
||||
INIT_SHADER(sprite, simpleAlphaUni, AlphaSpriteShader);
|
||||
|
||||
ShaderBase::init();
|
||||
|
||||
GET_U(spriteMat);
|
||||
GET_U(alpha);
|
||||
}
|
||||
|
||||
void AlphaSpriteShader::setSpriteMat(const float value[16])
|
||||
{
|
||||
gl.UniformMatrix4fv(u_spriteMat, 1, GL_FALSE, value);
|
||||
}
|
||||
|
||||
void AlphaSpriteShader::setAlpha(float value)
|
||||
{
|
||||
gl.Uniform1f(u_alpha, value);
|
||||
}
|
||||
|
||||
|
||||
TransShader::TransShader()
|
||||
{
|
||||
INIT_SHADER(simple, trans, TransShader);
|
||||
|
@ -450,6 +498,21 @@ void PlaneShader::setOpacity(float value)
|
|||
}
|
||||
|
||||
|
||||
GrayShader::GrayShader()
|
||||
{
|
||||
INIT_SHADER(simple, gray, GrayShader);
|
||||
|
||||
ShaderBase::init();
|
||||
|
||||
GET_U(gray);
|
||||
}
|
||||
|
||||
void GrayShader::setGray(float value)
|
||||
{
|
||||
gl.Uniform1f(u_gray, value);
|
||||
}
|
||||
|
||||
|
||||
TilemapShader::TilemapShader()
|
||||
{
|
||||
INIT_SHADER(tilemap, simple, TilemapShader);
|
||||
|
|
37
src/shader.h
37
src/shader.h
|
@ -87,6 +87,17 @@ protected:
|
|||
GLint u_texSizeInv, u_translation;
|
||||
};
|
||||
|
||||
class FlatColorShader : public ShaderBase
|
||||
{
|
||||
public:
|
||||
FlatColorShader();
|
||||
|
||||
void setColor(const Vec4 &value);
|
||||
|
||||
private:
|
||||
GLint u_color;
|
||||
};
|
||||
|
||||
class SimpleShader : public ShaderBase
|
||||
{
|
||||
public:
|
||||
|
@ -121,6 +132,18 @@ private:
|
|||
GLint u_spriteMat;
|
||||
};
|
||||
|
||||
class AlphaSpriteShader : public ShaderBase
|
||||
{
|
||||
public:
|
||||
AlphaSpriteShader();
|
||||
|
||||
void setSpriteMat(const float value[16]);
|
||||
void setAlpha(float value);
|
||||
|
||||
private:
|
||||
GLint u_spriteMat, u_alpha;
|
||||
};
|
||||
|
||||
class TransShader : public ShaderBase
|
||||
{
|
||||
public:
|
||||
|
@ -179,6 +202,17 @@ private:
|
|||
GLint u_tone, u_color, u_flash, u_opacity;
|
||||
};
|
||||
|
||||
class GrayShader : public ShaderBase
|
||||
{
|
||||
public:
|
||||
GrayShader();
|
||||
|
||||
void setGray(float value);
|
||||
|
||||
private:
|
||||
GLint u_gray;
|
||||
};
|
||||
|
||||
class TilemapShader : public ShaderBase
|
||||
{
|
||||
public:
|
||||
|
@ -273,12 +307,15 @@ private:
|
|||
/* Global object containing all available shaders */
|
||||
struct ShaderSet
|
||||
{
|
||||
FlatColorShader flatColor;
|
||||
SimpleShader simple;
|
||||
SimpleColorShader simpleColor;
|
||||
SimpleAlphaShader simpleAlpha;
|
||||
SimpleSpriteShader simpleSprite;
|
||||
AlphaSpriteShader alphaSprite;
|
||||
SpriteShader sprite;
|
||||
PlaneShader plane;
|
||||
GrayShader gray;
|
||||
TilemapShader tilemap;
|
||||
FlashMapShader flashMap;
|
||||
TransShader trans;
|
||||
|
|
|
@ -46,14 +46,14 @@ SharedState *SharedState::instance = 0;
|
|||
int SharedState::rgssVersion = 0;
|
||||
static GlobalIBO *_globalIBO = 0;
|
||||
|
||||
static const char *defGameArchive()
|
||||
static const char *gameArchExt()
|
||||
{
|
||||
if (rgssVer == 1)
|
||||
return "Game.rgssad";
|
||||
return ".rgssad";
|
||||
else if (rgssVer == 2)
|
||||
return "Game.rgss2a";
|
||||
return ".rgss2a";
|
||||
else if (rgssVer == 3)
|
||||
return "Game.rgss3a";
|
||||
return ".rgss3a";
|
||||
|
||||
assert(!"unreachable");
|
||||
return 0;
|
||||
|
@ -88,6 +88,7 @@ struct SharedStatePrivate
|
|||
|
||||
TEX::ID globalTex;
|
||||
int globalTexW, globalTexH;
|
||||
bool globalTexDirty;
|
||||
|
||||
TEXFBO gpTexFBO;
|
||||
|
||||
|
@ -107,25 +108,18 @@ struct SharedStatePrivate
|
|||
midiState(threadData->config),
|
||||
graphics(threadData),
|
||||
input(*threadData),
|
||||
audio(threadData->config),
|
||||
audio(*threadData),
|
||||
fontState(threadData->config),
|
||||
stampCounter(0)
|
||||
{
|
||||
if (!config.gameFolder.empty())
|
||||
{
|
||||
int result = chdir(config.gameFolder.c_str());
|
||||
/* Shaders have been compiled in ShaderSet's constructor */
|
||||
if (gl.ReleaseShaderCompiler)
|
||||
gl.ReleaseShaderCompiler();
|
||||
|
||||
if (result != 0)
|
||||
throw Exception(Exception::MKXPError,
|
||||
"Unable to switch into gameFolder '%s'",
|
||||
config.gameFolder.c_str());
|
||||
}
|
||||
|
||||
// FIXME find out correct archive filename
|
||||
std::string archPath = defGameArchive();
|
||||
std::string archPath = config.execName + gameArchExt();
|
||||
|
||||
/* Check if a game archive exists */
|
||||
FILE *tmp = fopen(archPath.c_str(), "r");
|
||||
FILE *tmp = fopen(archPath.c_str(), "rb");
|
||||
if (tmp)
|
||||
{
|
||||
fileSystem.addPath(archPath.c_str());
|
||||
|
@ -150,6 +144,7 @@ struct SharedStatePrivate
|
|||
TEX::setRepeat(false);
|
||||
TEX::setSmooth(false);
|
||||
TEX::allocEmpty(globalTexW, globalTexH);
|
||||
globalTexDirty = false;
|
||||
|
||||
TEXFBO::init(gpTexFBO);
|
||||
/* Reuse starting values */
|
||||
|
@ -257,16 +252,27 @@ GlobalIBO &SharedState::globalIBO()
|
|||
void SharedState::bindTex()
|
||||
{
|
||||
TEX::bind(p->globalTex);
|
||||
TEX::allocEmpty(p->globalTexW, p->globalTexH);
|
||||
|
||||
if (p->globalTexDirty)
|
||||
{
|
||||
TEX::allocEmpty(p->globalTexW, p->globalTexH);
|
||||
p->globalTexDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SharedState::ensureTexSize(int minW, int minH, Vec2i ¤tSizeOut)
|
||||
{
|
||||
if (minW > p->globalTexW)
|
||||
{
|
||||
p->globalTexDirty = true;
|
||||
p->globalTexW = findNextPow2(minW);
|
||||
}
|
||||
|
||||
if (minH > p->globalTexH)
|
||||
{
|
||||
p->globalTexDirty = true;
|
||||
p->globalTexH = findNextPow2(minH);
|
||||
}
|
||||
|
||||
currentSizeOut = Vec2i(p->globalTexW, p->globalTexH);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "exception.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
#include "debugwriter.h"
|
||||
|
||||
#include <SDL_sound.h>
|
||||
|
||||
|
@ -120,13 +121,16 @@ SoundEmitter::~SoundEmitter()
|
|||
|
||||
void SoundEmitter::play(const std::string &filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
int pitch)
|
||||
{
|
||||
float _volume = clamp<int>(volume, 0, 100) / 100.f;
|
||||
float _pitch = clamp<int>(pitch, 50, 150) / 100.f;
|
||||
|
||||
SoundBuffer *buffer = allocateBuffer(filename);
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
/* Try to find first free source */
|
||||
size_t i;
|
||||
for (i = 0; i < srcCount; ++i)
|
||||
|
@ -168,7 +172,7 @@ void SoundEmitter::play(const std::string &filename,
|
|||
if (switchBuffer)
|
||||
AL::Source::attachBuffer(src, buffer->alBuffer);
|
||||
|
||||
AL::Source::setVolume(src, _volume);
|
||||
AL::Source::setVolume(src, _volume * GLOBAL_VOLUME);
|
||||
AL::Source::setPitch(src, _pitch);
|
||||
|
||||
AL::Source::play(src);
|
||||
|
@ -197,18 +201,22 @@ SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
|
|||
{
|
||||
/* Buffer not in cashe, needs to be loaded */
|
||||
SDL_RWops dataSource;
|
||||
const char *extension;
|
||||
char ext[8];
|
||||
|
||||
shState->fileSystem().openRead(dataSource, filename.c_str(),
|
||||
FileSystem::Audio, false, &extension);
|
||||
false, ext, sizeof(ext));
|
||||
|
||||
Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, extension, 0, STREAM_BUF_SIZE);
|
||||
Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, ext, 0, STREAM_BUF_SIZE);
|
||||
|
||||
if (!sampleHandle)
|
||||
{
|
||||
SDL_RWclose(&dataSource);
|
||||
throw Exception(Exception::SDLError, "%s.%s: %s",
|
||||
filename.c_str(), extension, Sound_GetError());
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "Unable to decode sound: %s.%s: %s",
|
||||
filename.c_str(), ext, Sound_GetError());
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
Debug() << buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t decBytes = Sound_DecodeAll(sampleHandle);
|
||||
|
|
|
@ -57,7 +57,8 @@ struct SpritePrivate
|
|||
NormValue opacity;
|
||||
BlendType blendType;
|
||||
|
||||
SDL_Rect sceneRect;
|
||||
IntRect sceneRect;
|
||||
Vec2i sceneOrig;
|
||||
|
||||
/* Would this sprite be visible on
|
||||
* the screen if drawn? */
|
||||
|
@ -182,9 +183,8 @@ struct SpritePrivate
|
|||
return;
|
||||
}
|
||||
|
||||
SDL_Rect self;
|
||||
self.x = trans.getPosition().x - trans.getOrigin().x;
|
||||
self.y = trans.getPosition().y - trans.getOrigin().y;
|
||||
IntRect self;
|
||||
self.setPos(trans.getPositionI() - (trans.getOriginI() + sceneOrig));
|
||||
self.w = bitmap->width();
|
||||
self.h = bitmap->height();
|
||||
|
||||
|
@ -332,7 +332,7 @@ void Sprite::setBitmap(Bitmap *bitmap)
|
|||
|
||||
p->bitmap = bitmap;
|
||||
|
||||
if (!bitmap)
|
||||
if (nullOrDisposed(bitmap))
|
||||
return;
|
||||
|
||||
bitmap->ensureNonMega();
|
||||
|
@ -515,7 +515,6 @@ void Sprite::draw()
|
|||
|
||||
bool renderEffect = p->color->hasEffect() ||
|
||||
p->tone->hasEffect() ||
|
||||
p->opacity != 255 ||
|
||||
flashing ||
|
||||
p->bushDepth != 0;
|
||||
|
||||
|
@ -541,6 +540,16 @@ void Sprite::draw()
|
|||
|
||||
base = &shader;
|
||||
}
|
||||
else if (p->opacity != 255)
|
||||
{
|
||||
AlphaSpriteShader &shader = shState->shaders().alphaSprite;
|
||||
shader.bind();
|
||||
|
||||
shader.setSpriteMat(p->trans.getMatrix());
|
||||
shader.setAlpha(p->opacity.norm);
|
||||
shader.applyViewportProj();
|
||||
base = &shader;
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleSpriteShader &shader = shState->shaders().simpleSprite;
|
||||
|
@ -567,13 +576,10 @@ void Sprite::onGeometryChange(const Scene::Geometry &geo)
|
|||
{
|
||||
/* Offset at which the sprite will be drawn
|
||||
* relative to screen origin */
|
||||
int xOffset = geo.rect.x - geo.xOrigin;
|
||||
int yOffset = geo.rect.y - geo.yOrigin;
|
||||
p->trans.setGlobalOffset(geo.offset());
|
||||
|
||||
p->trans.setGlobalOffset(xOffset, yOffset);
|
||||
|
||||
p->sceneRect.w = geo.rect.w;
|
||||
p->sceneRect.h = geo.rect.h;
|
||||
p->sceneRect.setSize(geo.rect.size());
|
||||
p->sceneOrig = geo.orig;
|
||||
}
|
||||
|
||||
void Sprite::releaseResources()
|
||||
|
|
|
@ -30,94 +30,92 @@
|
|||
|
||||
/* Init normally */
|
||||
Table::Table(int x, int y /*= 1*/, int z /*= 1*/)
|
||||
: m_x(x), m_y(y), m_z(z),
|
||||
: xs(x), ys(y), zs(z),
|
||||
data(x*y*z)
|
||||
{}
|
||||
|
||||
Table::Table(const Table &other)
|
||||
: m_x(other.m_x), m_y(other.m_y), m_z(other.m_z),
|
||||
: xs(other.xs), ys(other.ys), zs(other.zs),
|
||||
data(other.data)
|
||||
{}
|
||||
|
||||
int16_t Table::get(int x, int y, int z) const
|
||||
{
|
||||
return data[m_x*m_y*z + m_x*y + x];
|
||||
return data[xs*ys*z + xs*y + x];
|
||||
}
|
||||
|
||||
void Table::set(int16_t value, int x, int y, int z)
|
||||
{
|
||||
if (x < 0 || x >= m_x
|
||||
|| y < 0 || y >= m_y
|
||||
|| z < 0 || z >= m_z)
|
||||
if (x < 0 || x >= xs
|
||||
|| y < 0 || y >= ys
|
||||
|| z < 0 || z >= zs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data[m_x*m_y*z + m_x*y + x] = value;
|
||||
data[xs*ys*z + xs*y + x] = value;
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
void Table::resize(int x, int y, int z)
|
||||
{
|
||||
if (x == m_x && y == m_y && z == m_z)
|
||||
if (x == xs && y == ys && z == zs)
|
||||
return;
|
||||
|
||||
std::vector<int16_t> newData(x*y*z);
|
||||
|
||||
for (int k = 0; k < std::min(z, m_z); ++k)
|
||||
for (int j = 0; j < std::min(y, m_y); ++j)
|
||||
for (int i = 0; i < std::min(x, m_x); ++i)
|
||||
for (int k = 0; k < std::min(z, zs); ++k)
|
||||
for (int j = 0; j < std::min(y, ys); ++j)
|
||||
for (int i = 0; i < std::min(x, xs); ++i)
|
||||
newData[x*y*k + x*j + i] = at(i, j, k);
|
||||
|
||||
data.swap(newData);
|
||||
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_z = z;
|
||||
xs = x;
|
||||
ys = y;
|
||||
zs = z;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Table::resize(int x, int y)
|
||||
{
|
||||
resize(x, y, m_z);
|
||||
resize(x, y, zs);
|
||||
}
|
||||
|
||||
void Table::resize(int x)
|
||||
{
|
||||
resize(x, m_y, m_z);
|
||||
resize(x, ys, zs);
|
||||
}
|
||||
|
||||
/* Serializable */
|
||||
int Table::serialSize() const
|
||||
{
|
||||
/* header + data */
|
||||
return 20 + (m_x * m_y * m_z) * 2;
|
||||
return 20 + (xs * ys * zs) * 2;
|
||||
}
|
||||
|
||||
void Table::serialize(char *buffer) const
|
||||
{
|
||||
char *buff_p = buffer;
|
||||
|
||||
/* Table dimensions: we don't care
|
||||
* about them but RMXP needs them */
|
||||
int dim = 1;
|
||||
int size = m_x * m_y * m_z;
|
||||
int size = xs * ys * zs;
|
||||
|
||||
if (m_y > 1)
|
||||
if (ys > 1)
|
||||
dim = 2;
|
||||
|
||||
if (m_z > 1)
|
||||
if (zs > 1)
|
||||
dim = 3;
|
||||
|
||||
write_int32(&buff_p, dim);
|
||||
write_int32(&buff_p, m_x);
|
||||
write_int32(&buff_p, m_y);
|
||||
write_int32(&buff_p, m_z);
|
||||
write_int32(&buff_p, size);
|
||||
writeInt32(&buffer, dim);
|
||||
writeInt32(&buffer, xs);
|
||||
writeInt32(&buffer, ys);
|
||||
writeInt32(&buffer, zs);
|
||||
writeInt32(&buffer, size);
|
||||
|
||||
memcpy(buff_p, dataPtr(data), sizeof(int16_t)*size);
|
||||
memcpy(buffer, dataPtr(data), sizeof(int16_t)*size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,13 +124,11 @@ Table *Table::deserialize(const char *data, int len)
|
|||
if (len < 20)
|
||||
throw Exception(Exception::RGSSError, "Marshal: Table: bad file format");
|
||||
|
||||
uint idx = 0;
|
||||
|
||||
read_int32(data, idx);
|
||||
int x = read_int32(data, idx);
|
||||
int y = read_int32(data, idx);
|
||||
int z = read_int32(data, idx);
|
||||
int size = read_int32(data, idx);
|
||||
readInt32(&data);
|
||||
int x = readInt32(&data);
|
||||
int y = readInt32(&data);
|
||||
int z = readInt32(&data);
|
||||
int size = readInt32(&data);
|
||||
|
||||
if (size != x*y*z)
|
||||
throw Exception(Exception::RGSSError, "Marshal: Table: bad file format");
|
||||
|
@ -141,7 +137,7 @@ Table *Table::deserialize(const char *data, int len)
|
|||
throw Exception(Exception::RGSSError, "Marshal: Table: bad file format");
|
||||
|
||||
Table *t = new Table(x, y, z);
|
||||
memcpy(dataPtr(t->data), &data[idx], sizeof(int16_t)*size);
|
||||
memcpy(dataPtr(t->data), data, sizeof(int16_t)*size);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
|
12
src/table.h
12
src/table.h
|
@ -36,9 +36,9 @@ public:
|
|||
Table(const Table &other);
|
||||
virtual ~Table() {}
|
||||
|
||||
int xSize() const { return m_x; }
|
||||
int ySize() const { return m_y; }
|
||||
int zSize() const { return m_z; }
|
||||
int xSize() const { return xs; }
|
||||
int ySize() const { return ys; }
|
||||
int zSize() const { return zs; }
|
||||
|
||||
int16_t get(int x, int y = 0, int z = 0) const;
|
||||
void set(int16_t value, int x, int y = 0, int z = 0);
|
||||
|
@ -54,18 +54,18 @@ public:
|
|||
/* <internal */
|
||||
inline int16_t &at(int x, int y = 0, int z = 0)
|
||||
{
|
||||
return data[m_x*m_y*z + m_x*y + x];
|
||||
return data[xs*ys*z + xs*y + x];
|
||||
}
|
||||
|
||||
inline const int16_t &at(int x, int y = 0, int z = 0) const
|
||||
{
|
||||
return data[m_x*m_y*z + m_x*y + x];
|
||||
return data[xs*ys*z + xs*y + x];
|
||||
}
|
||||
|
||||
sigc::signal<void> modified;
|
||||
|
||||
private:
|
||||
int m_x, m_y, m_z;
|
||||
int xs, ys, zs;
|
||||
std::vector<int16_t> data;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "tileatlasvx.h"
|
||||
|
||||
#include "tilemap-common.h"
|
||||
#include "bitmap.h"
|
||||
#include "table.h"
|
||||
#include "etc-internal.h"
|
||||
|
@ -65,21 +66,6 @@ static elementsN(autotileVXRectsC);
|
|||
namespace TileAtlasVX
|
||||
{
|
||||
|
||||
static int
|
||||
wrap(int value, int range)
|
||||
{
|
||||
int res = value % range;
|
||||
return res < 0 ? res + range : res;
|
||||
}
|
||||
|
||||
static int16_t
|
||||
tableGetWrapped(const Table &t, int x, int y, int z = 0)
|
||||
{
|
||||
return t.at(wrap(x, t.xSize()),
|
||||
wrap(y, t.ySize()),
|
||||
z);
|
||||
}
|
||||
|
||||
static int16_t
|
||||
tableGetSafe(const Table *t, int x)
|
||||
{
|
||||
|
@ -333,35 +319,6 @@ void build(TEXFBO &tf, Bitmap *bitmaps[BM_COUNT])
|
|||
#define OVER_PLAYER_FLAG (1 << 4)
|
||||
#define TABLE_FLAG (1 << 7)
|
||||
|
||||
static void
|
||||
atSelectSubPos(FloatRect &pos, int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
pos.x += 16;
|
||||
return;
|
||||
case 2:
|
||||
pos.y += 16;
|
||||
return;
|
||||
case 3:
|
||||
pos.x += 16;
|
||||
pos.y += 16;
|
||||
return;
|
||||
case 4:
|
||||
pos.y += 24;
|
||||
return;
|
||||
case 5:
|
||||
pos.x += 16;
|
||||
pos.y += 24;
|
||||
return;
|
||||
default:
|
||||
assert(!"Unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
/* Reference: http://www.tktkgame.com/tkool/memo/vx/tile_id.html */
|
||||
|
||||
static void
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** flashmap.h
|
||||
** tilemap-common.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
|
@ -19,8 +19,8 @@
|
|||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FLASHMAP_H
|
||||
#define FLASHMAP_H
|
||||
#ifndef TILEMAPCOMMON_H
|
||||
#define TILEMAPCOMMON_H
|
||||
|
||||
#include "table.h"
|
||||
#include "gl-util.h"
|
||||
|
@ -30,8 +30,11 @@
|
|||
#include "glstate.h"
|
||||
#include "shader.h"
|
||||
#include "vertex.h"
|
||||
#include "quad.h"
|
||||
#include "etc-internal.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
|
||||
#include <sigc++/connection.h>
|
||||
|
@ -44,11 +47,50 @@ wrap(int value, int range)
|
|||
}
|
||||
|
||||
static inline int16_t
|
||||
tableGetWrapped(const Table *t, int x, int y, int z = 0)
|
||||
tableGetWrapped(const Table &t, int x, int y, int z = 0)
|
||||
{
|
||||
return t->get(wrap(x, t->xSize()),
|
||||
wrap(y, t->ySize()),
|
||||
z);
|
||||
return t.get(wrap(x, t.xSize()),
|
||||
wrap(y, t.ySize()),
|
||||
z);
|
||||
}
|
||||
|
||||
enum AtSubPos
|
||||
{
|
||||
TopLeft = 0,
|
||||
TopRight = 1,
|
||||
BottomLeft = 2,
|
||||
BottomRight = 3,
|
||||
BottomLeftTable = 4,
|
||||
BottomRightTable = 5
|
||||
};
|
||||
|
||||
static inline void
|
||||
atSelectSubPos(FloatRect &pos, int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case TopLeft:
|
||||
return;
|
||||
case TopRight:
|
||||
pos.x += 16;
|
||||
return;
|
||||
case BottomLeft:
|
||||
pos.y += 16;
|
||||
return;
|
||||
case BottomRight:
|
||||
pos.x += 16;
|
||||
pos.y += 16;
|
||||
return;
|
||||
case BottomLeftTable:
|
||||
pos.y += 24;
|
||||
return;
|
||||
case BottomRightTable:
|
||||
pos.x += 16;
|
||||
pos.y += 24;
|
||||
return;
|
||||
default:
|
||||
assert(!"Unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
struct FlashMap
|
||||
|
@ -144,7 +186,7 @@ private:
|
|||
|
||||
bool sampleFlashColor(Vec4 &out, int x, int y) const
|
||||
{
|
||||
int16_t packed = tableGetWrapped(data, x, y);
|
||||
int16_t packed = tableGetWrapped(*data, x, y);
|
||||
|
||||
if (packed == 0)
|
||||
return false;
|
||||
|
@ -216,4 +258,4 @@ private:
|
|||
std::vector<CVertex> vertices;
|
||||
};
|
||||
|
||||
#endif // FLASHMAP_H
|
||||
#endif // TILEMAPCOMMON_H
|
|
@ -26,6 +26,7 @@
|
|||
#include "table.h"
|
||||
|
||||
#include "sharedstate.h"
|
||||
#include "config.h"
|
||||
#include "glstate.h"
|
||||
#include "gl-util.h"
|
||||
#include "gl-meta.h"
|
||||
|
@ -36,7 +37,7 @@
|
|||
#include "quad.h"
|
||||
#include "vertex.h"
|
||||
#include "tileatlas.h"
|
||||
#include "flashmap.h"
|
||||
#include "tilemap-common.h"
|
||||
|
||||
#include <sigc++/connection.h>
|
||||
|
||||
|
@ -441,15 +442,13 @@ struct TilemapPrivate
|
|||
|
||||
void updateSceneGeometry(const Scene::Geometry &geo)
|
||||
{
|
||||
elem.sceneOffset.x = geo.rect.x - geo.xOrigin;
|
||||
elem.sceneOffset.y = geo.rect.y - geo.yOrigin;
|
||||
elem.sceneOffset = geo.offset();
|
||||
elem.sceneGeo = geo;
|
||||
}
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
dispPos.x = -(offset.x - viewpPos.x * 32) + elem.sceneOffset.x;
|
||||
dispPos.y = -(offset.y - viewpPos.y * 32) + elem.sceneOffset.y;
|
||||
dispPos = -(offset - viewpPos * 32) + elem.sceneOffset;
|
||||
}
|
||||
|
||||
void invalidateAtlasSize()
|
||||
|
@ -542,19 +541,59 @@ struct TilemapPrivate
|
|||
if (tileset->megaSurface())
|
||||
{
|
||||
/* Mega surface tileset */
|
||||
TEX::bind(atlas.gl.tex);
|
||||
|
||||
SDL_Surface *tsSurf = tileset->megaSurface();
|
||||
|
||||
for (size_t i = 0; i < blits.size(); ++i)
|
||||
if (shState->config().subImageFix)
|
||||
{
|
||||
const TileAtlas::Blit &blitOp = blits[i];
|
||||
/* Implementation for broken GL drivers */
|
||||
FBO::bind(atlas.gl.fbo);
|
||||
glState.blend.pushSet(false);
|
||||
glState.viewport.pushSet(IntRect(0, 0, atlas.size.x, atlas.size.y));
|
||||
|
||||
GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
|
||||
blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
|
||||
SimpleShader &shader = shState->shaders().simple;
|
||||
shader.bind();
|
||||
shader.applyViewportProj();
|
||||
shader.setTranslation(Vec2i());
|
||||
|
||||
Quad &quad = shState->gpQuad();
|
||||
|
||||
for (size_t i = 0; i < blits.size(); ++i)
|
||||
{
|
||||
const TileAtlas::Blit &blitOp = blits[i];
|
||||
|
||||
Vec2i texSize;
|
||||
shState->ensureTexSize(tsLaneW, blitOp.h, texSize);
|
||||
shState->bindTex();
|
||||
GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
|
||||
0, 0, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
|
||||
|
||||
shader.setTexSize(texSize);
|
||||
quad.setTexRect(FloatRect(0, 0, tsLaneW, blitOp.h));
|
||||
quad.setPosRect(FloatRect(blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h));
|
||||
|
||||
quad.draw();
|
||||
}
|
||||
|
||||
GLMeta::subRectImageEnd();
|
||||
glState.viewport.pop();
|
||||
glState.blend.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clean implementation */
|
||||
TEX::bind(atlas.gl.tex);
|
||||
|
||||
for (size_t i = 0; i < blits.size(); ++i)
|
||||
{
|
||||
const TileAtlas::Blit &blitOp = blits[i];
|
||||
|
||||
GLMeta::subRectImageUpload(tsSurf->w, blitOp.src.x, blitOp.src.y,
|
||||
blitOp.dst.x, blitOp.dst.y, tsLaneW, blitOp.h, tsSurf, GL_RGBA);
|
||||
}
|
||||
|
||||
GLMeta::subRectImageEnd();
|
||||
}
|
||||
|
||||
GLMeta::subRectImageEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -590,21 +629,6 @@ struct TilemapPrivate
|
|||
return value;
|
||||
}
|
||||
|
||||
FloatRect getAutotilePieceRect(int x, int y, /* in pixel coords */
|
||||
int corner)
|
||||
{
|
||||
switch (corner)
|
||||
{
|
||||
case 0 : break;
|
||||
case 1 : x += 16; break;
|
||||
case 2 : x += 16; y += 16; break;
|
||||
case 3 : y += 16; break;
|
||||
default: abort();
|
||||
}
|
||||
|
||||
return FloatRect(x, y, 16, 16);
|
||||
}
|
||||
|
||||
void handleAutotile(int x, int y, int tileInd, SVVector *array)
|
||||
{
|
||||
/* Which autotile [0-7] */
|
||||
|
@ -617,7 +641,9 @@ struct TilemapPrivate
|
|||
/* Iterate over the 4 tile pieces */
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
FloatRect posRect = getAutotilePieceRect(x*32, y*32, i);
|
||||
FloatRect posRect(x*32, y*32, 16, 16);
|
||||
atSelectSubPos(posRect, i);
|
||||
|
||||
FloatRect texRect = pieceRect[i];
|
||||
|
||||
/* Adjust to atlas coordinates */
|
||||
|
@ -635,7 +661,7 @@ struct TilemapPrivate
|
|||
void handleTile(int x, int y, int z)
|
||||
{
|
||||
int tileInd =
|
||||
tableGetWrapped(mapData, x + viewpPos.x, y + viewpPos.y, z);
|
||||
tableGetWrapped(*mapData, x + viewpPos.x, y + viewpPos.y, z);
|
||||
|
||||
/* Check for empty space */
|
||||
if (tileInd < 48)
|
||||
|
@ -972,6 +998,9 @@ void GroundLayer::updateVboCount()
|
|||
|
||||
void GroundLayer::draw()
|
||||
{
|
||||
if (p->groundVert.size() == 0)
|
||||
return;
|
||||
|
||||
ShaderBase *shader;
|
||||
|
||||
p->bindShader(shader);
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include "quad.h"
|
||||
#include "quadarray.h"
|
||||
#include "shader.h"
|
||||
#include "flashmap.h"
|
||||
#include "tilemap-common.h"
|
||||
|
||||
#include <vector>
|
||||
#include <sigc++/connection.h>
|
||||
|
@ -366,11 +366,10 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
|
|||
|
||||
void onGeometryChange(const Scene::Geometry &geo)
|
||||
{
|
||||
mapViewp.w = (geo.rect.w / 32) + !!(geo.rect.w % 32) + 1;
|
||||
mapViewp.h = (geo.rect.h / 32) + !!(geo.rect.h % 32) + 1;
|
||||
const Vec2i geoSize = geo.rect.size();
|
||||
mapViewp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1));
|
||||
|
||||
sceneOffset.x = geo.rect.x - geo.xOrigin;
|
||||
sceneOffset.y = geo.rect.y - geo.yOrigin;
|
||||
sceneOffset = geo.offset();
|
||||
sceneGeo = geo;
|
||||
|
||||
buffersDirty = true;
|
||||
|
|
|
@ -58,7 +58,6 @@ public:
|
|||
Transform()
|
||||
: scale(1, 1),
|
||||
rotation(0),
|
||||
xOffset(0), yOffset(0),
|
||||
dirty(true)
|
||||
{
|
||||
memset(matrix, 0, sizeof(matrix));
|
||||
|
@ -68,38 +67,47 @@ public:
|
|||
}
|
||||
|
||||
Vec2 &getPosition() { return position; }
|
||||
Vec2 &getScale() { return scale; }
|
||||
Vec2 &getOrigin() { return origin; }
|
||||
Vec2 &getScale() { return scale; }
|
||||
float getRotation() { return rotation; }
|
||||
|
||||
Vec2i getPositionI() const
|
||||
{
|
||||
return Vec2i(position.x, position.y);
|
||||
}
|
||||
|
||||
Vec2i getOriginI() const
|
||||
{
|
||||
return Vec2i(origin.x, origin.y);
|
||||
}
|
||||
|
||||
void setPosition(const Vec2 &value)
|
||||
{
|
||||
position = value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void setScale(const Vec2 &value)
|
||||
{
|
||||
scale = value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void setOrigin(const Vec2 &value)
|
||||
{
|
||||
origin = value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void setScale(const Vec2 &value)
|
||||
{
|
||||
scale = value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void setRotation(float value)
|
||||
{
|
||||
rotation = value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void setGlobalOffset(int x, int y)
|
||||
void setGlobalOffset(const Vec2i &value)
|
||||
{
|
||||
xOffset = x;
|
||||
yOffset = y;
|
||||
offset = value;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
@ -129,8 +137,8 @@ private:
|
|||
float syc = scale.y * cosine;
|
||||
float sxs = scale.x * sine;
|
||||
float sys = scale.y * sine;
|
||||
float tx = -origin.x * sxc - origin.y * sys + position.x + xOffset;
|
||||
float ty = origin.x * sxs - origin.y * syc + position.y + yOffset;
|
||||
float tx = -origin.x * sxc - origin.y * sys + position.x + offset.x;
|
||||
float ty = origin.x * sxs - origin.y * syc + position.y + offset.y;
|
||||
|
||||
matrix[0] = sxc;
|
||||
matrix[1] = -sxs;
|
||||
|
@ -146,7 +154,7 @@ private:
|
|||
float rotation;
|
||||
|
||||
/* Silently added to position */
|
||||
int xOffset, yOffset;
|
||||
Vec2i offset;
|
||||
|
||||
float matrix[16];
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ findNextPow2(int start)
|
|||
inline bool readFile(const char *path,
|
||||
std::string &out)
|
||||
{
|
||||
FILE *f = fopen(path, "r");
|
||||
FILE *f = fopen(path, "rb");
|
||||
|
||||
if (!f)
|
||||
return false;
|
||||
|
|
|
@ -144,8 +144,8 @@ void Viewport::update()
|
|||
Flashable::update();
|
||||
}
|
||||
|
||||
DEF_ATTR_RD_SIMPLE(Viewport, OX, int, geometry.xOrigin)
|
||||
DEF_ATTR_RD_SIMPLE(Viewport, OY, int, geometry.yOrigin)
|
||||
DEF_ATTR_RD_SIMPLE(Viewport, OX, int, geometry.orig.x)
|
||||
DEF_ATTR_RD_SIMPLE(Viewport, OY, int, geometry.orig.y)
|
||||
|
||||
DEF_ATTR_SIMPLE(Viewport, Rect, Rect&, *p->rect)
|
||||
DEF_ATTR_SIMPLE(Viewport, Color, Color&, *p->color)
|
||||
|
@ -155,10 +155,10 @@ void Viewport::setOX(int value)
|
|||
{
|
||||
guardDisposed();
|
||||
|
||||
if (geometry.xOrigin == value)
|
||||
if (geometry.orig.x == value)
|
||||
return;
|
||||
|
||||
geometry.xOrigin = value;
|
||||
geometry.orig.x = value;
|
||||
notifyGeometryChange();
|
||||
}
|
||||
|
||||
|
@ -166,10 +166,10 @@ void Viewport::setOY(int value)
|
|||
{
|
||||
guardDisposed();
|
||||
|
||||
if (geometry.yOrigin == value)
|
||||
if (geometry.orig.y == value)
|
||||
return;
|
||||
|
||||
geometry.yOrigin = value;
|
||||
geometry.orig.y = value;
|
||||
notifyGeometryChange();
|
||||
}
|
||||
|
||||
|
|
|
@ -471,16 +471,15 @@ struct WindowPrivate
|
|||
i += TileQuads::buildFrame(effectRect, cursorVert.vert);
|
||||
}
|
||||
|
||||
/* Scroll arrows */
|
||||
int scrollLRY = (size.y - 16) / 2;
|
||||
int scrollTBX = (size.x - 16) / 2;
|
||||
/* Scroll arrow position: Top Bottom X, Left Right Y */
|
||||
const Vec2i scroll = (size - Vec2i(16)) / 2;
|
||||
|
||||
Sides<IntRect> scrollArrows;
|
||||
|
||||
scrollArrows.l = IntRect(4, scrollLRY, 8, 16);
|
||||
scrollArrows.r = IntRect(size.x - 12, scrollLRY, 8, 16);
|
||||
scrollArrows.t = IntRect(scrollTBX, 4, 16, 8);
|
||||
scrollArrows.b = IntRect(scrollTBX, size.y - 12, 16, 8);
|
||||
scrollArrows.l = IntRect(4, scroll.y, 8, 16);
|
||||
scrollArrows.r = IntRect(size.x - 12, scroll.y, 8, 16);
|
||||
scrollArrows.t = IntRect(scroll.x, 4, 16, 8);
|
||||
scrollArrows.b = IntRect(scroll.x, size.y - 12, 16, 8);
|
||||
|
||||
if (contents)
|
||||
{
|
||||
|
@ -557,13 +556,10 @@ struct WindowPrivate
|
|||
if (size == Vec2i(0, 0))
|
||||
return;
|
||||
|
||||
Vec2i trans(position.x + sceneOffset.x,
|
||||
position.y + sceneOffset.y);
|
||||
|
||||
SimpleAlphaShader &shader = shState->shaders().simpleAlpha;
|
||||
shader.bind();
|
||||
shader.applyViewportProj();
|
||||
shader.setTranslation(trans);
|
||||
shader.setTranslation(position + sceneOffset);
|
||||
|
||||
if (useBaseTex)
|
||||
{
|
||||
|
@ -598,12 +594,11 @@ struct WindowPrivate
|
|||
controlsVertDirty = false;
|
||||
}
|
||||
|
||||
/* Actual on screen coordinates */
|
||||
int effectX = position.x + sceneOffset.x;
|
||||
int effectY = position.y + sceneOffset.y;
|
||||
/* Effective on screen coordinates */
|
||||
const Vec2i efPos = position + sceneOffset;
|
||||
|
||||
IntRect windowRect(effectX, effectY, size.x, size.y);
|
||||
IntRect contentsRect(effectX+16, effectY+16, size.x-32, size.y-32);
|
||||
const IntRect windowRect(efPos, size);
|
||||
const IntRect contentsRect(efPos + Vec2i(16), size - Vec2i(32));
|
||||
|
||||
glState.scissorTest.pushSet(true);
|
||||
glState.scissorBox.push();
|
||||
|
@ -615,7 +610,7 @@ struct WindowPrivate
|
|||
|
||||
if (!nullOrDisposed(windowskin))
|
||||
{
|
||||
shader.setTranslation(Vec2i(effectX, effectY));
|
||||
shader.setTranslation(efPos);
|
||||
|
||||
/* Draw arrows / cursors */
|
||||
windowskin->bindTex(shader);
|
||||
|
@ -631,9 +626,7 @@ struct WindowPrivate
|
|||
/* Draw contents bitmap */
|
||||
glState.scissorBox.setIntersect(contentsRect);
|
||||
|
||||
effectX += 16-contentsOffset.x;
|
||||
effectY += 16-contentsOffset.y;
|
||||
shader.setTranslation(Vec2i(effectX, effectY));
|
||||
shader.setTranslation(efPos + (Vec2i(16) - contentsOffset));
|
||||
|
||||
contents->bindTex(shader);
|
||||
contentsQuad.draw();
|
||||
|
@ -727,7 +720,7 @@ void Window::setWindowskin(Bitmap *value)
|
|||
|
||||
p->windowskin = value;
|
||||
|
||||
if (!value)
|
||||
if (nullOrDisposed(value))
|
||||
return;
|
||||
|
||||
value->ensureNonMega();
|
||||
|
@ -743,7 +736,7 @@ void Window::setContents(Bitmap *value)
|
|||
p->contents = value;
|
||||
p->controlsVertDirty = true;
|
||||
|
||||
if (!value)
|
||||
if (nullOrDisposed(value))
|
||||
return;
|
||||
|
||||
value->ensureNonMega();
|
||||
|
@ -876,8 +869,7 @@ void Window::draw()
|
|||
|
||||
void Window::onGeometryChange(const Scene::Geometry &geo)
|
||||
{
|
||||
p->sceneOffset.x = geo.rect.x - geo.xOrigin;
|
||||
p->sceneOffset.y = geo.rect.y - geo.yOrigin;
|
||||
p->sceneOffset = geo.offset();
|
||||
}
|
||||
|
||||
void Window::setZ(int value)
|
||||
|
|
|
@ -506,15 +506,15 @@ struct WindowVXPrivate
|
|||
|
||||
void rebuildCtrlVert()
|
||||
{
|
||||
const int arrowTBX = (geo.w - 16) / 2;
|
||||
const int arrowLRY = (geo.h - 16) / 2;
|
||||
/* Scroll arrow position: Top Bottom X, Left Right Y */
|
||||
const Vec2i arrow = (geo.size() - Vec2i(16)) / 2;
|
||||
|
||||
const Sides<FloatRect> arrowPos =
|
||||
{
|
||||
FloatRect( 4, arrowLRY, 8, 16 ), /* Left */
|
||||
FloatRect( geo.w - 12, arrowLRY, 8, 16 ), /* Right */
|
||||
FloatRect( arrowTBX, 4, 16, 8 ), /* Top */
|
||||
FloatRect( arrowTBX, geo.h - 12, 16, 8 ) /* Bottom */
|
||||
FloatRect( 4, arrow.y, 8, 16 ), /* Left */
|
||||
FloatRect( geo.w - 12, arrow.y, 8, 16 ), /* Right */
|
||||
FloatRect( arrow.x, 4, 16, 8 ), /* Top */
|
||||
FloatRect( arrow.x, geo.h - 12, 16, 8 ) /* Bottom */
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
|
@ -538,7 +538,7 @@ struct WindowVXPrivate
|
|||
|
||||
if (pause)
|
||||
{
|
||||
const FloatRect pausePos(arrowTBX, geo.h - 16, 16, 16);
|
||||
const FloatRect pausePos(arrow.x, geo.h - 16, 16, 16);
|
||||
pauseVert = &vert[i*4];
|
||||
|
||||
i += Quad::setTexPosRect(&vert[i*4], pauseSrc[0], pausePos);
|
||||
|
@ -730,8 +730,7 @@ struct WindowVXPrivate
|
|||
bool windowskinValid = !nullOrDisposed(windowskin);
|
||||
bool contentsValid = !nullOrDisposed(contents);
|
||||
|
||||
Vec2i trans(geo.x + sceneOffset.x,
|
||||
geo.y + sceneOffset.y);
|
||||
Vec2i trans = geo.pos() + sceneOffset;
|
||||
|
||||
SimpleAlphaShader &shader = shState->shaders().simpleAlpha;
|
||||
shader.bind();
|
||||
|
@ -764,8 +763,7 @@ struct WindowVXPrivate
|
|||
{
|
||||
/* Translate cliprect from local into screen space */
|
||||
IntRect clip = clipRect;
|
||||
clip.x += trans.x;
|
||||
clip.y += trans.y;
|
||||
clip.setPos(clip.pos() + trans);
|
||||
|
||||
glState.scissorBox.push();
|
||||
glState.scissorTest.pushSet(true);
|
||||
|
@ -773,11 +771,10 @@ struct WindowVXPrivate
|
|||
if (rgssVer >= 3)
|
||||
glState.scissorBox.setIntersect(clip);
|
||||
else
|
||||
glState.scissorBox.setIntersect(IntRect(trans.x, trans.y, geo.w, geo.h));
|
||||
glState.scissorBox.setIntersect(IntRect(trans, geo.size()));
|
||||
|
||||
IntRect pad = padRect;
|
||||
pad.x += trans.x;
|
||||
pad.y += trans.y;
|
||||
pad.setPos(pad.pos() + trans);
|
||||
|
||||
if (drawCursor)
|
||||
{
|
||||
|
@ -786,10 +783,7 @@ struct WindowVXPrivate
|
|||
contTrans.y += cursorRect->y;
|
||||
|
||||
if (rgssVer >= 3)
|
||||
{
|
||||
contTrans.x -= contentsOff.x;
|
||||
contTrans.y -= contentsOff.y;
|
||||
}
|
||||
contTrans -= contentsOff;
|
||||
|
||||
shader.setTranslation(contTrans);
|
||||
|
||||
|
@ -804,8 +798,7 @@ struct WindowVXPrivate
|
|||
glState.scissorBox.setIntersect(clip);
|
||||
|
||||
Vec2i contTrans = pad.pos();
|
||||
contTrans.x -= contentsOff.x;
|
||||
contTrans.y -= contentsOff.y;
|
||||
contTrans -= contentsOff;
|
||||
shader.setTranslation(contTrans);
|
||||
|
||||
TEX::setSmooth(false); // XXX
|
||||
|
@ -921,6 +914,9 @@ void WindowVX::setContents(Bitmap *value)
|
|||
|
||||
p->contents = value;
|
||||
|
||||
if (nullOrDisposed(value))
|
||||
return;
|
||||
|
||||
FloatRect rect = p->contents->rect();
|
||||
p->contentsQuad.setTexPosRect(rect, rect);
|
||||
p->ctrlVertDirty = true;
|
||||
|
@ -1102,8 +1098,7 @@ void WindowVX::draw()
|
|||
|
||||
void WindowVX::onGeometryChange(const Scene::Geometry &geo)
|
||||
{
|
||||
p->sceneOffset.x = geo.rect.x - geo.xOrigin;
|
||||
p->sceneOffset.y = geo.rect.y - geo.yOrigin;
|
||||
p->sceneOffset = geo.offset();
|
||||
}
|
||||
|
||||
void WindowVX::releaseResources()
|
||||
|
|
Loading…
Reference in New Issue