Merge branch 'master' of /home/Ancurio/programming/C++/mkxp

This commit is contained in:
Jonas Kulla 2016-02-25 17:30:01 +01:00
commit d9f13c39e9
38 changed files with 792 additions and 686 deletions

View File

@ -20,6 +20,8 @@ Matz's Ruby Interpreter, also called CRuby, is the most widely deployed version
For a list of differences, see:
http://stackoverflow.com/questions/21574/what-is-the-difference-between-ruby-1-8-and-ruby-1-9
This binding supports RGSS1, RGSS2 and RGSS3.
### mruby (Lightweight Ruby)
Website: https://github.com/mruby/mruby
@ -29,6 +31,8 @@ Due to heavy differences between mruby and MRI as well as lacking modules, runni
Some extensions to the standard classes/modules are provided, taking the RPG Maker XP helpfile as a quasi "reference". These include Marshal, File, FileTest and Time.
This binding only supports RGSS1.
**Important:** If you decide to use [mattn's oniguruma regexp gem](https://github.com/mattn/mruby-onig-regexp), don't forget to add `-lonig` to the linker flags to avoid ugly symbol overlaps with libc.
### null

View File

@ -46,7 +46,7 @@ fileIntForPath(const char *path, bool rubyExc)
try
{
shState->fileSystem().openRead(*ops, path);
shState->fileSystem().openReadRaw(*ops, path);
}
catch (const Exception &e)
{

View File

@ -27,6 +27,29 @@
#include <string.h>
static void
collectStrings(VALUE obj, std::vector<std::string> &out)
{
if (RB_TYPE_P(obj, RUBY_T_STRING))
{
out.push_back(RSTRING_PTR(obj));
}
else if (RB_TYPE_P(obj, RUBY_T_ARRAY))
{
for (long i = 0; i < RARRAY_LEN(obj); ++i)
{
VALUE str = rb_ary_entry(obj, i);
/* Non-string objects are tolerated (ignored) */
if (!RB_TYPE_P(str, RUBY_T_STRING))
continue;
out.push_back(RSTRING_PTR(str));
}
}
}
DEF_TYPE(Font);
RB_METHOD(fontDoesExist)
@ -48,12 +71,30 @@ RB_METHOD(FontSetName);
RB_METHOD(fontInitialize)
{
VALUE name = Qnil;
VALUE namesObj = Qnil;
int size = 0;
rb_get_args(argc, argv, "|oi", &name, &size RB_ARG_END);
rb_get_args(argc, argv, "|oi", &namesObj, &size RB_ARG_END);
Font *f = new Font(0, size);
Font *f;
if (NIL_P(namesObj))
{
namesObj = rb_iv_get(rb_obj_class(self), "default_name");
f = new Font(0, size);
}
else
{
std::vector<std::string> names;
collectStrings(namesObj, names);
f = new Font(&names, size);
}
/* This is semantically wrong; the new Font object should take
* a dup'ed object here in case of an array. Ditto for the setters.
* However the same bug/behavior exists in all RM versions. */
rb_iv_set(self, "name", namesObj);
setPrivateData(self, f);
@ -65,13 +106,6 @@ RB_METHOD(fontInitialize)
if (rgssVer >= 3)
wrapProperty(self, &f->getOutColor(), "out_color", ColorType);
if (NIL_P(name))
name = rb_iv_get(rb_obj_class(self), "default_name");
/* Going over the 'name=' function automatically causes
* a possbile name array to be re-verified for existing fonts */
FontSetName(1, &name, self);
return self;
}
@ -105,57 +139,17 @@ RB_METHOD(FontGetName)
return rb_iv_get(self, "name");
}
static void
fontSetNameHelper(VALUE self, int argc, VALUE *argv,
const char *nameIv, char *outBuf, size_t outLen)
{
rb_check_argc(argc, 1);
VALUE arg = argv[0];
// Fixme: in RGSS3, specifying "" (and only that) as font name results in
// no text being drawn (everything else is substituted with Arial I think)
strncpy(outBuf, "", outLen);
if (RB_TYPE_P(arg, RUBY_T_STRING))
{
strncpy(outBuf, RSTRING_PTR(arg), outLen);
}
else if (RB_TYPE_P(arg, RUBY_T_ARRAY))
{
for (long i = 0; i < RARRAY_LEN(arg); ++i)
{
VALUE str = rb_ary_entry(arg, i);
/* Non-string objects are tolerated (ignored) */
if (!RB_TYPE_P(str, RUBY_T_STRING))
continue;
const char *family = RSTRING_PTR(str);
/* We only set the core Font object's name attribute
* to the actually existing font name */
if (!shState->fontState().fontPresent(family))
continue;
strncpy(outBuf, family, outLen);
}
}
/* RMXP doesn't even care if the argument type is
* something other than string/array. Whatever... */
rb_iv_set(self, nameIv, arg);
}
RB_METHOD(FontSetName)
{
Font *f = getPrivateData<Font>(self);
char result[256];
fontSetNameHelper(self, argc, argv, "name",
result, sizeof(result));
rb_check_argc(argc, 1);
f->setName(result);
std::vector<std::string> namesObj;
collectStrings(argv[0], namesObj);
f->setName(namesObj);
rb_iv_set(self, "name", argv[0]);
return argv[0];
}
@ -223,11 +217,15 @@ RB_METHOD(FontGetDefaultName)
RB_METHOD(FontSetDefaultName)
{
char result[256];
fontSetNameHelper(self, argc, argv, "default_name",
result, sizeof(result));
RB_UNUSED_PARAM;
Font::setDefaultName(result);
rb_check_argc(argc, 1);
std::vector<std::string> namesObj;
collectStrings(argv[0], namesObj);
Font::setDefaultName(namesObj, shState->fontState());
rb_iv_set(self, "default_name", argv[0]);
return argv[0];
}
@ -267,7 +265,24 @@ fontBindingInit()
Font::initDefaultDynAttribs();
wrapProperty(klass, &Font::getDefaultColor(), "default_color", ColorType);
rb_iv_set(klass, "default_name", rb_str_new_cstr(Font::getDefaultName()));
/* Initialize default names */
const std::vector<std::string> &defNames = Font::getInitialDefaultNames();
VALUE defNamesObj;
if (defNames.size() == 1)
{
defNamesObj = rb_str_new_cstr(defNames[0].c_str());
}
else
{
defNamesObj = rb_ary_new2(defNames.size());
for (size_t i = 0; i < defNames.size(); ++i)
rb_ary_push(defNamesObj, rb_str_new_cstr(defNames[i].c_str()));
}
rb_iv_set(klass, "default_name", defNamesObj);
if (rgssVer >= 3)
wrapProperty(klass, &Font::getDefaultOutColor(), "default_out_color", ColorType);
@ -310,14 +325,4 @@ fontBindingInit()
INIT_PROP_BIND(Font, Outline, "outline");
INIT_PROP_BIND(Font, OutColor, "out_color");
}
if (rgssVer >= 2)
{
VALUE defNames = rb_ary_new2(3);
rb_ary_push(defNames, rb_str_new2("Verdana"));
rb_ary_push(defNames, rb_str_new2("Arial"));
rb_ary_push(defNames, rb_str_new2("Courier New"));
FontSetDefaultName(1, &defNames, klass);
}
}

View File

@ -183,6 +183,18 @@ RB_METHOD(graphicsReset)
return Qnil;
}
RB_METHOD(graphicsPlayMovie)
{
RB_UNUSED_PARAM;
const char *filename;
rb_get_args(argc, argv, "z", &filename RB_ARG_END);
shState->graphics().playMovie(filename);
return Qnil;
}
DEF_GRA_PROP_I(FrameRate)
DEF_GRA_PROP_I(FrameCount)
DEF_GRA_PROP_I(Brightness)
@ -223,6 +235,11 @@ void graphicsBindingInit()
INIT_GRA_PROP_BIND( Brightness, "brightness" );
}
if (rgssVer >= 3)
{
_rb_define_module_function(module, "play_movie", graphicsPlayMovie);
}
INIT_GRA_PROP_BIND( Fullscreen, "fullscreen" );
INIT_GRA_PROP_BIND( ShowCursor, "show_cursor" );
}

View File

@ -56,6 +56,7 @@ DEF_PROP_I(Sprite, Y)
DEF_PROP_I(Sprite, OX)
DEF_PROP_I(Sprite, OY)
DEF_PROP_I(Sprite, BushDepth)
DEF_PROP_I(Sprite, BushOpacity)
DEF_PROP_I(Sprite, Opacity)
DEF_PROP_I(Sprite, BlendType)
DEF_PROP_I(Sprite, WaveAmp)
@ -126,6 +127,8 @@ spriteBindingInit()
_rb_define_method(klass, "width", spriteWidth);
_rb_define_method(klass, "height", spriteHeight);
INIT_PROP_BIND( Sprite, BushOpacity, "bush_opacity" );
INIT_PROP_BIND( Sprite, WaveAmp, "wave_amp" );
INIT_PROP_BIND( Sprite, WaveLength, "wave_length" );
INIT_PROP_BIND( Sprite, WaveSpeed, "wave_speed" );

View File

@ -266,7 +266,7 @@ runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
mrb_state *scriptMrb = mrb_open();
SDL_RWops ops;
shState->fileSystem().openRead(ops, scriptPack.c_str());
shState->fileSystem().openReadRaw(ops, scriptPack.c_str());
mrb_value scriptArray = mrb_nil_value();
std::string readError;

View File

@ -57,9 +57,9 @@
# Apply linear interpolation when game screen
# is upscaled
# (default: disabled)
# (default: enabled)
#
# smoothScaling=false
# smoothScaling=true
# Sync screen redraws to the monitor refresh rate

View File

@ -238,6 +238,6 @@ inline ALenum chooseALFormat(int sampleSize, int channelCount)
#define AUDIO_SLEEP 10
#define STREAM_BUF_SIZE 32768
#define GLOBAL_VOLUME 0.8
#define GLOBAL_VOLUME 0.8f
#endif // ALUTIL_H

View File

@ -42,12 +42,12 @@ ALStream::ALStream(LoopMode loopMode,
source(0),
thread(0),
preemptPause(false),
pitch(1.0)
pitch(1.0f)
{
alSrc = AL::Source::gen();
AL::Source::setVolume(alSrc, 1.0);
AL::Source::setPitch(alSrc, 1.0);
AL::Source::setVolume(alSrc, 1.0f);
AL::Source::setPitch(alSrc, 1.0f);
AL::Source::detachBuffer(alSrc);
for (int i = 0; i < STREAM_BUFS; ++i)
@ -172,7 +172,7 @@ void ALStream::setPitch(float value)
/* If the source supports setting pitch natively,
* we don't have to do it via OpenAL */
if (source && source->setPitch(value))
AL::Source::setPitch(alSrc, 1.0);
AL::Source::setPitch(alSrc, 1.0f);
else
AL::Source::setPitch(alSrc, value);
}
@ -199,43 +199,73 @@ void ALStream::closeSource()
delete source;
}
struct ALStreamOpenHandler : FileSystem::OpenHandler
{
SDL_RWops *srcOps;
bool looped;
ALDataSource *source;
std::string errorMsg;
ALStreamOpenHandler(SDL_RWops &srcOps, bool looped)
: srcOps(&srcOps), looped(looped), source(0)
{}
bool tryRead(SDL_RWops &ops, const char *ext)
{
/* Copy this because we need to keep it around,
* as we will continue reading data from it later */
*srcOps = ops;
/* Try to read ogg file signature */
char sig[5] = { 0 };
SDL_RWread(srcOps, sig, 1, 4);
SDL_RWseek(srcOps, 0, RW_SEEK_SET);
try
{
if (!strcmp(sig, "OggS"))
{
source = createVorbisSource(*srcOps, looped);
return true;
}
if (!strcmp(sig, "MThd"))
{
shState->midiState().initIfNeeded(shState->config());
if (HAVE_FLUID)
{
source = createMidiSource(*srcOps, looped);
return true;
}
}
source = createSDLSource(*srcOps, ext, STREAM_BUF_SIZE, looped);
}
catch (const Exception &e)
{
/* All source constructors will close the passed ops
* before throwing errors */
errorMsg = e.msg;
return false;
}
return true;
}
};
void ALStream::openSource(const std::string &filename)
{
char ext[8];
shState->fileSystem().openRead(srcOps, filename.c_str(), false, ext, sizeof(ext));
ALStreamOpenHandler handler(srcOps, looped);
shState->fileSystem().openRead(handler, filename.c_str());
source = handler.source;
needsRewind.clear();
/* Try to read ogg file signature */
char sig[5] = { 0 };
SDL_RWread(&srcOps, sig, 1, 4);
SDL_RWseek(&srcOps, 0, RW_SEEK_SET);
try
{
if (!strcmp(sig, "OggS"))
{
source = createVorbisSource(srcOps, looped);
return;
}
if (!strcmp(sig, "MThd"))
{
shState->midiState().initIfNeeded(shState->config());
if (HAVE_FLUID)
{
source = createMidiSource(srcOps, looped);
return;
}
}
source = createSDLSource(srcOps, ext, STREAM_BUF_SIZE, looped);
}
catch (const Exception &e)
if (!source)
{
char buf[512];
snprintf(buf, sizeof(buf), "Unable to decode audio stream: %s.%s: %s",
filename.c_str(), ext, e.msg.c_str());
snprintf(buf, sizeof(buf), "Unable to decode audio stream: %s: %s",
filename.c_str(), handler.errorMsg.c_str());
Debug() << buf;
}

View File

@ -170,7 +170,7 @@ struct AudioPrivate
else
{
/* BGM is stopped. -> MeNotPlaying */
bgm.setVolume(AudioStream::External, 1.0);
bgm.setVolume(AudioStream::External, 1.0f);
if (!bgm.noResumeStop)
bgm.stream.play();
@ -193,7 +193,7 @@ struct AudioPrivate
if (bgm.stream.queryState() == ALStream::Stopped)
{
/* BGM stopped midway fade in. -> MeNotPlaying */
bgm.setVolume(AudioStream::External, 1.0);
bgm.setVolume(AudioStream::External, 1.0f);
meWatch.state = MeNotPlaying;
bgm.unlockStream();
@ -219,7 +219,7 @@ struct AudioPrivate
if (vol >= 1)
{
/* BGM fully faded in. -> MeNotPlaying */
vol = 1.0;
vol = 1.0f;
meWatch.state = MeNotPlaying;
}

View File

@ -34,11 +34,11 @@ AudioStream::AudioStream(ALStream::LoopMode loopMode,
noResumeStop(false),
stream(loopMode, threadId)
{
current.volume = 1.0;
current.pitch = 1.0;
current.volume = 1.0f;
current.pitch = 1.0f;
for (size_t i = 0; i < VolumeTypeCount; ++i)
volumes[i] = 1.0;
volumes[i] = 1.0f;
fade.thread = 0;
fade.threadName = std::string("audio_fadeout (") + threadId + ")";
@ -82,8 +82,8 @@ void AudioStream::play(const std::string &filename,
lockStream();
float _volume = clamp<int>(volume, 0, 100) / 100.f;
float _pitch = clamp<int>(pitch, 50, 150) / 100.f;
float _volume = clamp<int>(volume, 0, 100) / 100.0f;
float _pitch = clamp<int>(pitch, 50, 150) / 100.0f;
ALStream::State sState = stream.queryState();
@ -211,7 +211,7 @@ void AudioStream::fadeOut(int duration)
}
fade.active.set();
fade.msStep = (1.0) / duration;
fade.msStep = 1.0f / duration;
fade.reqFini.clear();
fade.reqTerm.clear();
fade.startTicks = SDL_GetTicks();
@ -302,7 +302,7 @@ void AudioStream::fadeOutThread()
lockStream();
uint32_t curDur = SDL_GetTicks() - fade.startTicks;
float resVol = 1.0 - (curDur*fade.msStep);
float resVol = 1.0f - (curDur*fade.msStep);
ALStream::State state = stream.queryState();
@ -313,7 +313,7 @@ void AudioStream::fadeOutThread()
if (state != ALStream::Paused)
stream.stop();
setVolume(FadeOut, 1.0);
setVolume(FadeOut, 1.0f);
unlockStream();
break;
@ -340,15 +340,15 @@ void AudioStream::fadeInThread()
/* Fade in duration is always 1 second */
uint32_t cur = SDL_GetTicks() - fadeIn.startTicks;
float prog = cur / 1000.0;
float prog = cur / 1000.0f;
ALStream::State state = stream.queryState();
if (state != ALStream::Playing
|| prog >= 1.0
|| prog >= 1.0f
|| fadeIn.rqFini)
{
setVolume(FadeIn, 1.0);
setVolume(FadeIn, 1.0f);
unlockStream();
break;

View File

@ -247,13 +247,26 @@ struct BitmapPrivate
}
};
struct BitmapOpenHandler : FileSystem::OpenHandler
{
SDL_Surface *surf;
BitmapOpenHandler()
: surf(0)
{}
bool tryRead(SDL_RWops &ops, const char *ext)
{
surf = IMG_LoadTyped_RW(&ops, 1, ext);
return surf != 0;
}
};
Bitmap::Bitmap(const char *filename)
{
SDL_RWops ops;
char ext[8];
shState->fileSystem().openRead(ops, filename, false, ext, sizeof(ext));
SDL_Surface *imgSurf = IMG_LoadTyped_RW(&ops, 1, ext);
BitmapOpenHandler handler;
shState->fileSystem().openRead(handler, filename);
SDL_Surface *imgSurf = handler.surf;
if (!imgSurf)
throw Exception(Exception::SDLError, "Error loading image '%s': %s",
@ -992,9 +1005,9 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C
SDL_Surface *out = SDL_CreateRGBSurface
(0, in->w+1, in->h+1, fm.BitsPerPixel, fm.Rmask, fm.Gmask, fm.Bmask, fm.Amask);
float fr = c.r / 255.0;
float fg = c.g / 255.0;
float fb = c.b / 255.0;
float fr = c.r / 255.0f;
float fg = c.g / 255.0f;
float fb = c.b / 255.0f;
/* We allocate an output surface one pixel wider and higher than the input,
* (implicitly) blit a copy of the input with RGB values set to black into
@ -1048,11 +1061,11 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C
continue;
}
float fSrcA = srcA / 255.0;
float fShdA = shdA / 255.0;
float fSrcA = srcA / 255.0f;
float fShdA = shdA / 255.0f;
/* Because opacity == 1, co1 == fSrcA */
float co2 = fShdA * (1.0 - fSrcA);
float co2 = fShdA * (1.0f - fSrcA);
/* Result alpha */
float fa = fSrcA + co2;
/* Temp value to simplify arithmetic below */
@ -1061,10 +1074,10 @@ static void applyShadow(SDL_Surface *&in, const SDL_PixelFormat &fm, const SDL_C
/* Result colors */
uint8_t r, g, b, a;
r = clamp<float>(fr * co3, 0, 1) * 255;
g = clamp<float>(fg * co3, 0, 1) * 255;
b = clamp<float>(fb * co3, 0, 1) * 255;
a = clamp<float>(fa, 0, 1) * 255;
r = clamp<float>(fr * co3, 0, 1) * 255.0f;
g = clamp<float>(fg * co3, 0, 1) * 255.0f;
b = clamp<float>(fb * co3, 0, 1) * 255.0f;
a = clamp<float>(fa, 0, 1) * 255.0f;
*outP = SDL_MapRGBA(&fm, r, g, b, a);
}
@ -1169,11 +1182,11 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
Vec2i gpTexSize;
shState->ensureTexSize(txtSurf->w, txtSurf->h, gpTexSize);
bool fastBlit = !p->touchesTaintedArea(posRect) && txtAlpha == 1.0;
bool fastBlit = !p->touchesTaintedArea(posRect) && txtAlpha == 1.0f;
if (fastBlit)
{
if (squeeze == 1.0 && !shState->config().subImageFix)
if (squeeze == 1.0f && !shState->config().subImageFix)
{
/* Even faster: upload directly to bitmap texture.
* We have to make sure the posRect lies within the texture

View File

@ -151,7 +151,7 @@ void Config::read(int argc, char *argv[])
PO_DESC(winResizable, bool, false) \
PO_DESC(fullscreen, bool, false) \
PO_DESC(fixedAspectRatio, bool, true) \
PO_DESC(smoothScaling, bool, false) \
PO_DESC(smoothScaling, bool, true) \
PO_DESC(vsync, bool, false) \
PO_DESC(defScreenW, int, 0) \
PO_DESC(defScreenH, int, 0) \

View File

@ -31,49 +31,6 @@ struct CropTexture
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
{
int rgssVersion;

View File

@ -61,9 +61,9 @@ struct Vec4
return (x == other.x && y == other.y && z == other.z && w == other.w);
}
bool xyzHasEffect() const
bool xyzNotNull() const
{
return (x != 0.0 || y != 0.0 || z != 0.0);
return (x != 0.0f || y != 0.0f || z != 0.0f);
}
};
@ -88,6 +88,11 @@ struct Vec2i
return x == other.x && y == other.y;
}
bool operator!=(const Vec2i &other) const
{
return !(*this == other);
}
Vec2i &operator+=(const Vec2i &value)
{
x += value.x;
@ -131,6 +136,11 @@ struct Vec2i
return Vec2i(x % value, y % value);
}
Vec2i operator&(unsigned value) const
{
return Vec2i(x & value, y & value);
}
Vec2i operator-() const
{
return Vec2i(-x, -y);
@ -176,6 +186,11 @@ struct IntRect : SDL_Rect
w == other.w && h == other.h);
}
bool operator!=(const IntRect &other) const
{
return !(*this == other);
}
Vec2i pos() const
{
return Vec2i(x, y);
@ -259,13 +274,13 @@ struct NormValue
NormValue(int unNorm)
: unNorm(unNorm),
norm(unNorm / 255.0)
norm(unNorm / 255.0f)
{}
void operator =(int value)
{
unNorm = clamp(value, 0, 255);
norm = unNorm / 255.0;
norm = unNorm / 255.0f;
}
bool operator ==(int value) const

View File

@ -111,7 +111,11 @@ void EventThread::process(RGSSThreadData &rtData)
UnidirMessage<Vec2i> &windowSizeMsg = rtData.windowSizeMsg;
initALCFunctions(rtData.alcDev);
// XXX this function breaks input focus on OSX
#ifndef __MACOSX__
SDL_SetEventFilter(eventFilter, &rtData);
#endif
fullscreen = rtData.config.fullscreen;
int toggleFSMod = rtData.config.anyAltToggleFS ? KMOD_ALT : KMOD_LALT;
@ -127,7 +131,9 @@ void EventThread::process(RGSSThreadData &rtData)
bool displayingFPS = false;
bool cursorInWindow = false;
bool windowFocused = false;
/* SDL doesn't send an initial FOCUS_GAINED event */
bool windowFocused = true;
bool terminate = false;
@ -490,9 +496,9 @@ int EventThread::eventFilter(void *data, SDL_Event *event)
Debug() << "SDL_APP_LOWMEMORY";
return 0;
case SDL_RENDER_TARGETS_RESET :
Debug() << "****** SDL_RENDER_TARGETS_RESET";
return 0;
// case SDL_RENDER_TARGETS_RESET :
// Debug() << "****** SDL_RENDER_TARGETS_RESET";
// return 0;
// case SDL_RENDER_DEVICE_RESET :
// Debug() << "****** SDL_RENDER_DEVICE_RESET";

View File

@ -37,6 +37,7 @@
#include <string.h>
#include <algorithm>
#include <vector>
#include <stack>
#ifdef __APPLE__
#include <iconv.h>
@ -249,201 +250,65 @@ strcpySafe(char *dst, const char *src,
return cpyMax;
}
/* Attempt to locate an extension string in a filename.
* Either a pointer into the input string pointing at the
* extension, or null is returned */
static const char *
findExt(const char *filename)
{
size_t len;
for (len = strlen(filename); len > 0; --len)
{
if (filename[len] == '/')
return 0;
if (filename[len] == '.')
return &filename[len+1];
}
return 0;
}
static void
initReadOps(PHYSFS_File *handle,
SDL_RWops &ops,
bool freeOnClose)
{
ops.size = SDL_RWopsSize;
ops.seek = SDL_RWopsSeek;
ops.read = SDL_RWopsRead;
ops.write = SDL_RWopsWrite;
if (freeOnClose)
ops.close = SDL_RWopsCloseFree;
else
ops.close = SDL_RWopsClose;
ops.type = SDL_RWOPS_PHYSFS;
ops.hidden.unknown.data1 = handle;
}
static void strTolower(std::string &str)
{
for (size_t i = 0; i < str.size(); ++i)
str[i] = tolower(str[i]);
}
const Uint32 SDL_RWOPS_PHYSFS = SDL_RWOPS_UNKNOWN+10;
struct FileSystemPrivate
{
/* Maps: lower case filepath without extension,
* To: mixed case full filepath
* This is for compatibility with games that take Windows'
* case insensitivity for granted */
/* Maps: lower case full filepath,
* To: mixed case full filepath */
BoostHash<std::string, std::string> pathCache;
/* Maps: lower case directory path,
* To: list of lower case filenames */
BoostHash<std::string, std::vector<std::string> > fileLists;
/* This is for compatibility with games that take Windows'
* case insensitivity for granted */
bool havePathCache;
/* Attempt to locate an extension string in a filename.
* Either a pointer into the input string pointing at the
* extension, or null is returned */
const char *findExt(const char *filename)
{
size_t len;
for (len = strlen(filename); len > 0; --len)
{
if (filename[len] == '/')
return 0;
if (filename[len] == '.')
return &filename[len+1];
}
return 0;
}
struct CompleteFilenameData
{
bool found;
/* Contains the incomplete filename we're looking for;
* when found, we write the complete filename into this
* same buffer */
char *outBuf;
/* Length of incomplete file name */
size_t filenameLen;
/* Maximum we can write into outBuf */
size_t outBufN;
};
static void completeFilenameRegCB(void *data, const char *,
const char *fname)
{
CompleteFilenameData &d = *static_cast<CompleteFilenameData*>(data);
if (d.found)
return;
if (strncmp(d.outBuf, fname, d.filenameLen) != 0)
return;
/* If fname matches up to a following '.' (meaning the rest is part
* of the extension), or up to a following '\0' (full match), we've
* found our file */
switch (fname[d.filenameLen])
{
case '.' :
/* Overwrite the incomplete file name we looked for with
* the full version containing any extensions */
strcpySafe(d.outBuf, fname, d.outBufN, -1);
case '\0' :
d.found = true;
}
}
bool completeFilenameReg(const char *filepath,
char *outBuffer,
size_t outN)
{
strcpySafe(outBuffer, filepath, outN, -1);
size_t len = strlen(outBuffer);
char *delim;
/* Find the deliminator separating directory and file name */
for (delim = outBuffer + len; delim > outBuffer; --delim)
if (*delim == '/')
break;
bool root = (delim == outBuffer);
CompleteFilenameData d;
if (!root)
{
/* If we have such a deliminator, we set it to '\0' so we
* can pass the first half to PhysFS as the directory name,
* and compare all filenames against the second half */
d.outBuf = delim+1;
d.filenameLen = len - (delim - outBuffer + 1);
*delim = '\0';
}
else
{
/* Otherwise the file is in the root directory */
d.outBuf = outBuffer;
d.filenameLen = len - (delim - outBuffer);
}
d.found = false;
d.outBufN = outN - (d.outBuf - outBuffer);
PHYSFS_enumerateFilesCallback(root ? "" : outBuffer, completeFilenameRegCB, &d);
if (!d.found)
return false;
/* Now we put the deliminator back in to form the completed
* file path (if required) */
if (delim != outBuffer)
*delim = '/';
return true;
}
bool completeFilenamePC(const char *filepath,
char *outBuffer,
size_t outN)
{
std::string lowCase(filepath);
for (size_t i = 0; i < lowCase.size(); ++i)
lowCase[i] = tolower(lowCase[i]);
if (!pathCache.contains(lowCase))
return false;
const std::string &fullPath = pathCache[lowCase];
strcpySafe(outBuffer, fullPath.c_str(), outN, fullPath.size());
return true;
}
bool completeFilename(const char *filepath,
char *outBuffer,
size_t outN)
{
if (havePathCache)
return completeFilenamePC(filepath, outBuffer, outN);
else
return completeFilenameReg(filepath, outBuffer, outN);
}
PHYSFS_File *openReadHandle(const char *filename,
char *extBuf,
size_t extBufN)
{
char found[512];
if (!completeFilename(filename, found, sizeof(found)))
throw Exception(Exception::NoFileError, "%s", filename);
PHYSFS_File *handle = PHYSFS_openRead(found);
if (!handle)
throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError());
if (!extBuf)
return handle;
for (char *q = found+strlen(found); q > found; --q)
{
if (*q == '/')
break;
if (*q != '.')
continue;
strcpySafe(extBuf, q+1, extBufN, -1);
break;
}
return handle;
}
void initReadOps(PHYSFS_File *handle,
SDL_RWops &ops,
bool freeOnClose)
{
ops.size = SDL_RWopsSize;
ops.seek = SDL_RWopsSeek;
ops.read = SDL_RWopsRead;
ops.write = SDL_RWopsWrite;
if (freeOnClose)
ops.close = SDL_RWopsCloseFree;
else
ops.close = SDL_RWopsClose;
ops.type = SDL_RWOPS_PHYSFS;
ops.hidden.unknown.data1 = handle;
}
};
FileSystem::FileSystem(const char *argv0,
@ -484,99 +349,105 @@ void FileSystem::addPath(const char *path)
}
}
#ifdef __APPLE__
struct CacheEnumCBData
struct CacheEnumData
{
FileSystemPrivate *p;
std::stack<std::vector<std::string>*> fileLists;
#ifdef __APPLE__
iconv_t nfd2nfc;
char buf[512];
#endif
CacheEnumCBData(FileSystemPrivate *fsp)
CacheEnumData(FileSystemPrivate *p)
: p(p)
{
p = fsp;
#ifdef __APPLE__
nfd2nfc = iconv_open("utf-8", "utf-8-mac");
#endif
}
~CacheEnumCBData()
~CacheEnumData()
{
#ifdef __APPLE__
iconv_close(nfd2nfc);
#endif
}
void nfcFromNfd(char *dst, const char *src, size_t dstSize)
/* Converts in-place */
void toNFC(char *inout)
{
size_t srcSize = strlen(src);
#ifdef __APPLE__
size_t srcSize = strlen(inout);
size_t bufSize = sizeof(buf);
char *bufPtr = buf;
char *inoutPtr = inout;
/* Reserve room for null terminator */
--dstSize;
/* iconv takes a char** instead of a const char**, even though
* the string data isn't written to. */
--bufSize;
iconv(nfd2nfc,
const_cast<char**>(&src), &srcSize,
&dst, &dstSize);
&inoutPtr, &srcSize,
&bufPtr, &bufSize);
/* Null-terminate */
*dst = 0;
*bufPtr = 0;
strcpy(inout, buf);
#else
(void) inout;
#endif
}
};
#endif
static void cacheEnumCB(void *d, const char *origdir,
const char *fname)
{
#ifdef __APPLE__
CacheEnumCBData *data = static_cast<CacheEnumCBData*>(d);
FileSystemPrivate *p = data->p;
#else
FileSystemPrivate *p = static_cast<FileSystemPrivate*>(d);
#endif
CacheEnumData &data = *static_cast<CacheEnumData*>(d);
char fullPath[512];
char buf[512];
if (*origdir == '\0')
strncpy(buf, fname, sizeof(buf));
if (!*origdir)
snprintf(fullPath, sizeof(fullPath), "%s", fname);
else
snprintf(buf, sizeof(buf), "%s/%s", origdir, fname);
snprintf(fullPath, sizeof(fullPath), "%s/%s", origdir, fname);
#ifdef __APPLE__
char bufNfc[sizeof(buf)];
data->nfcFromNfd(bufNfc, buf, sizeof(bufNfc));
#else
char *const bufNfc = buf;
#endif
/* Deal with OSX' weird UTF-8 standards */
data.toNFC(fullPath);
char *ptr = bufNfc;
std::string mixedCase(fullPath);
std::string lowerCase = mixedCase;
strTolower(lowerCase);
/* Trim leading slash */
if (*ptr == '/')
++ptr;
PHYSFS_Stat stat;
PHYSFS_stat(fullPath, &stat);
std::string mixedCase(ptr);
for (char *q = bufNfc; *q; ++q)
*q = tolower(*q);
p->pathCache.insert(std::string(ptr), mixedCase);
for (char *q = ptr+strlen(ptr); q > ptr; --q)
if (stat.filetype == PHYSFS_FILETYPE_DIRECTORY)
{
if (*q == '/')
break;
/* Create a new list for this directory */
std::vector<std::string> &list = data.p->fileLists[lowerCase];
if (*q != '.')
continue;
*q = '\0';
p->pathCache.insert(std::string(ptr), mixedCase);
/* Iterate over its contents */
data.fileLists.push(&list);
PHYSFS_enumerateFilesCallback(fullPath, cacheEnumCB, d);
data.fileLists.pop();
}
else
{
/* Get the file list for the directory we're currently
* traversing and append this filename to it */
std::vector<std::string> &list = *data.fileLists.top();
std::string lowerFilename(fname);
strTolower(lowerFilename);
list.push_back(lowerFilename);
PHYSFS_enumerateFilesCallback(mixedCase.c_str(), cacheEnumCB, d);
/* Add the lower -> mixed mapping of the file's full path */
data.p->pathCache.insert(lowerCase, mixedCase);
}
}
void FileSystem::createPathCache()
{
#ifdef __APPLE__
CacheEnumCBData data(p);
CacheEnumData data(p);
data.fileLists.push(&p->fileLists[""]);
PHYSFS_enumerateFilesCallback("", cacheEnumCB, &data);
#else
PHYSFS_enumerateFilesCallback("", cacheEnumCB, p);
#endif
p->havePathCache = true;
}
@ -591,10 +462,9 @@ static void fontSetEnumCB(void *data, const char *,
const char *fname)
{
FontSetsCBData *d = static_cast<FontSetsCBData*>(data);
FileSystemPrivate *p = d->p;
/* Only consider filenames with font extensions */
const char *ext = p->findExt(fname);
const char *ext = findExt(fname);
if (!ext)
return;
@ -618,7 +488,7 @@ static void fontSetEnumCB(void *data, const char *,
return;
SDL_RWops ops;
p->initReadOps(handle, ops, false);
initReadOps(handle, ops, false);
d->sfs->initFontSetCB(ops, filename);
@ -632,15 +502,147 @@ void FileSystem::initFontSets(SharedFontState &sfs)
PHYSFS_enumerateFilesCallback("Fonts", fontSetEnumCB, &d);
}
void FileSystem::openRead(SDL_RWops &ops,
const char *filename,
bool freeOnClose,
char *extBuf,
size_t extBufN)
struct OpenReadEnumData
{
PHYSFS_File *handle = p->openReadHandle(filename, extBuf, extBufN);
FileSystem::OpenHandler &handler;
SDL_RWops ops;
p->initReadOps(handle, ops, freeOnClose);
/* The filename (without directory) we're looking for */
const char *filename;
size_t filenameN;
/* Optional hash to translate full filepaths
* (used with path cache) */
BoostHash<std::string, std::string> *pathTrans;
/* Number of files we've attempted to read and parse */
size_t matchCount;
bool stopSearching;
/* In case of a PhysFS error, save it here so it
* doesn't get changed before we get back into our code */
const char *physfsError;
OpenReadEnumData(FileSystem::OpenHandler &handler,
const char *filename, size_t filenameN,
BoostHash<std::string, std::string> *pathTrans)
: handler(handler), filename(filename), filenameN(filenameN),
pathTrans(pathTrans), matchCount(0), stopSearching(false),
physfsError(0)
{}
};
static void openReadEnumCB(void *d, const char *dirpath,
const char *filename)
{
OpenReadEnumData &data = *static_cast<OpenReadEnumData*>(d);
char buffer[512];
const char *fullPath;
if (data.stopSearching)
return;
/* If there's not even a partial match, continue searching */
if (strncmp(filename, data.filename, data.filenameN) != 0)
return;
if (!*dirpath)
{
fullPath = filename;
}
else
{
snprintf(buffer, sizeof(buffer), "%s/%s", dirpath, filename);
fullPath = buffer;
}
char last = filename[data.filenameN];
/* If fname matches up to a following '.' (meaning the rest is part
* of the extension), or up to a following '\0' (full match), we've
* found our file */
if (last != '.' && last != '\0')
return;
/* If the path cache is active, translate from lower case
* to mixed case path */
if (data.pathTrans)
fullPath = (*data.pathTrans)[fullPath].c_str();
PHYSFS_File *phys = PHYSFS_openRead(fullPath);
if (!phys)
{
/* Failing to open this file here means there must
* be a deeper rooted problem somewhere within PhysFS.
* Just abort alltogether. */
data.stopSearching = true;
data.physfsError = PHYSFS_getLastError();
return;
}
initReadOps(phys, data.ops, false);
const char *ext = findExt(filename);
if (data.handler.tryRead(data.ops, ext))
data.stopSearching = true;
++data.matchCount;
}
void FileSystem::openRead(OpenHandler &handler, const char *filename)
{
char buffer[512];
size_t len = strcpySafe(buffer, filename, sizeof(buffer), -1);
char *delim;
if (p->havePathCache)
for (size_t i = 0; i < len; ++i)
buffer[i] = tolower(buffer[i]);
/* Find the deliminator separating directory and file name */
for (delim = buffer + len; delim > buffer; --delim)
if (*delim == '/')
break;
const bool root = (delim == buffer);
const char *file = buffer;
const char *dir = "";
if (!root)
{
/* Cut the buffer in half so we can use it
* for both filename and directory path */
*delim = '\0';
file = delim+1;
dir = buffer;
}
OpenReadEnumData data(handler, file, len + buffer - delim - !root,
p->havePathCache ? &p->pathCache : 0);
if (p->havePathCache)
{
/* Get the list of files contained in this directory
* and manually iterate over them */
const std::vector<std::string> &fileList = p->fileLists[dir];
for (size_t i = 0; i < fileList.size(); ++i)
openReadEnumCB(&data, dir, fileList[i].c_str());
}
else
{
PHYSFS_enumerateFilesCallback(dir, openReadEnumCB, &data);
}
if (data.physfsError)
throw Exception(Exception::PHYSFSError, "PhysFS: %s", data.physfsError);
if (data.matchCount == 0)
throw Exception(Exception::NoFileError, "%s", filename);
}
void FileSystem::openReadRaw(SDL_RWops &ops,
@ -650,12 +652,10 @@ void FileSystem::openReadRaw(SDL_RWops &ops,
PHYSFS_File *handle = PHYSFS_openRead(filename);
assert(handle);
p->initReadOps(handle, ops, freeOnClose);
initReadOps(handle, ops, freeOnClose);
}
bool FileSystem::exists(const char *filename)
{
char found[512];
return p->completeFilename(filename, found, sizeof(found));
return PHYSFS_exists(filename);
}

View File

@ -43,17 +43,28 @@ public:
* available font assets */
void initFontSets(SharedFontState &sfs);
void openRead(SDL_RWops &ops,
const char *filename,
bool freeOnClose = false,
char *extBuf = 0,
size_t extBufN = 0);
struct OpenHandler
{
/* Try to read and interpret data provided from ops.
* If data cannot be parsed, return false, otherwise true.
* Can be called multiple times until a parseable file is found.
* It's the handler's responsibility to close every passed
* ops structure, even when data could not be parsed.
* After this function returns, ops becomes invalid, so don't take
* references to it. Instead, copy the structure without closing
* if you need to further read from it later. */
virtual bool tryRead(SDL_RWops &ops, const char *ext) = 0;
};
void openRead(OpenHandler &handler,
const char *filename);
/* Circumvents extension supplementing */
void openReadRaw(SDL_RWops &ops,
const char *filename,
bool freeOnClose = false);
/* Does not perform extension supplementing */
bool exists(const char *filename);
private:

View File

@ -174,7 +174,7 @@ _TTF_Font *SharedFontState::getFont(std::string family,
// FIXME 0.9 is guesswork at this point
// float gamma = (96.0/45.0)*(5.0/14.0)*(size-5);
// font = TTF_OpenFontRW(ops, 1, gamma /** .90*/);
font = TTF_OpenFontRW(ops, 1, size* .90);
font = TTF_OpenFontRW(ops, 1, size* 0.90f);
if (!font)
throw Exception(Exception::SDLError, "%s", SDL_GetError());
@ -184,7 +184,7 @@ _TTF_Font *SharedFontState::getFont(std::string family,
return font;
}
bool SharedFontState::fontPresent(std::string family)
bool SharedFontState::fontPresent(std::string family) const
{
/* Check for substitutions */
if (p->subs.contains(family))
@ -202,6 +202,26 @@ _TTF_Font *SharedFontState::openBundled(int size)
return TTF_OpenFontRW(ops, 1, size);
}
void pickExistingFontName(const std::vector<std::string> &names,
std::string &out,
const SharedFontState &sfs)
{
/* Note: In RMXP, a names array with no existing entry
* results in no text being drawn at all (same for "" and []);
* we can't replicate this in mkxp due to the default substitute. */
for (size_t i = 0; i < names.size(); ++i)
{
if (sfs.fontPresent(names[i]))
{
out = names[i];
return;
}
}
out = "";
}
struct FontPrivate
{
@ -229,15 +249,15 @@ struct FontPrivate
static Color defaultColorTmp;
static Color defaultOutColorTmp;
static std::vector<std::string> initialDefaultNames;
/* The actual font is opened as late as possible
* (when it is queried by a Bitmap), prior it is
* set to null */
TTF_Font *sdlFont;
FontPrivate(const char *name = 0,
int size = 0)
: name(name ? std::string(name) : defaultName),
size(size ? size : defaultSize),
FontPrivate(int size)
: size(size),
bold(defaultBold),
italic(defaultItalic),
outline(defaultOutline),
@ -290,6 +310,8 @@ Color *FontPrivate::defaultOutColor = &FontPrivate::defaultOutColorTmp;
Color FontPrivate::defaultColorTmp(255, 255, 255, 255);
Color FontPrivate::defaultOutColorTmp(0, 0, 0, 128);
std::vector<std::string> FontPrivate::initialDefaultNames;
bool Font::doesExist(const char *name)
{
if (!name)
@ -298,10 +320,15 @@ bool Font::doesExist(const char *name)
return shState->fontState().fontPresent(name);
}
Font::Font(const char *name,
Font::Font(const std::vector<std::string> *names,
int size)
{
p = new FontPrivate(name, size);
p = new FontPrivate(size ? size : FontPrivate::defaultSize);
if (names)
setName(*names);
else
p->name = FontPrivate::defaultName;
}
Font::Font(const Font &other)
@ -321,17 +348,9 @@ const Font &Font::operator=(const Font &o)
return o;
}
const char *Font::getName() const
void Font::setName(const std::vector<std::string> &names)
{
return p->name.c_str();
}
void Font::setName(const char *value)
{
if (p->name == value)
return;
p->name = value;
pickExistingFontName(names, p->name, shState->fontState());
p->sdlFont = 0;
}
@ -367,14 +386,15 @@ DEF_ATTR_SIMPLE_STATIC(Font, DefaultOutline, bool, FontPrivate::defaultOutli
DEF_ATTR_SIMPLE_STATIC(Font, DefaultColor, Color&, *FontPrivate::defaultColor)
DEF_ATTR_SIMPLE_STATIC(Font, DefaultOutColor, Color&, *FontPrivate::defaultOutColor)
const char *Font::getDefaultName()
void Font::setDefaultName(const std::vector<std::string> &names,
const SharedFontState &sfs)
{
return FontPrivate::defaultName.c_str();
pickExistingFontName(names, FontPrivate::defaultName, sfs);
}
void Font::setDefaultName(const char *value)
const std::vector<std::string> &Font::getInitialDefaultNames()
{
FontPrivate::defaultName = value;
return FontPrivate::initialDefaultNames;
}
void Font::initDynAttribs()
@ -393,8 +413,30 @@ void Font::initDefaultDynAttribs()
FontPrivate::defaultOutColor = new Color(FontPrivate::defaultOutColorTmp);
}
void Font::initDefaults()
void Font::initDefaults(const SharedFontState &sfs)
{
std::vector<std::string> &names = FontPrivate::initialDefaultNames;
switch (rgssVer)
{
case 1 :
// FIXME: Japanese version has "MS PGothic" instead
names.push_back("Arial");
break;
case 2 :
names.push_back("UmePlus Gothic");
names.push_back("MS Gothic");
names.push_back("Courier New");
break;
default:
case 3 :
names.push_back("VL Gothic");
}
setDefaultName(names, sfs);
FontPrivate::defaultOutline = (rgssVer >= 3 ? true : false);
FontPrivate::defaultShadow = (rgssVer == 2 ? true : false);
}

View File

@ -25,6 +25,9 @@
#include "etc.h"
#include "util.h"
#include <vector>
#include <string>
struct SDL_RWops;
struct _TTF_Font;
struct Config;
@ -47,7 +50,7 @@ public:
_TTF_Font *getFont(std::string family,
int size);
bool fontPresent(std::string family);
bool fontPresent(std::string family) const;
static _TTF_Font *openBundled(int size);
@ -55,22 +58,6 @@ private:
SharedFontStatePrivate *p;
};
/* Concerning Font::name/defaultName :
* In RGSS, this is not actually a string; any type of
* object is accepted, however anything but strings and
* arrays is ignored (and text drawing turns blank).
* Single strings are interpreted as font family names,
* and directly passed to the underlying C++ object;
* arrays however are searched for the first string
* object corresponding to a valid font family name,
* and rendering is done with that. In mkxp, we pass
* this first valid font family as the 'name' attribute
* back to the C++ object on assignment and object
* creation (in case Font.default_name is also an array).
* Invalid parameters (things other than strings or
* arrays not containing any valid family name) are
* passed back as "". */
struct FontPrivate;
class Font
@ -78,31 +65,43 @@ class Font
public:
static bool doesExist(const char *name);
Font(const char *name = 0,
Font(const std::vector<std::string> *names = 0,
int size = 0);
/* Clone constructor */
Font(const Font &other);
~Font();
const Font &operator=(const Font &o);
DECL_ATTR( Name, const char * )
DECL_ATTR( Size, int )
DECL_ATTR( Bold, bool )
DECL_ATTR( Italic, bool )
DECL_ATTR( Color, Color& )
DECL_ATTR( Shadow, bool )
DECL_ATTR( Outline, bool )
DECL_ATTR( OutColor, Color& )
DECL_ATTR( Size, int )
DECL_ATTR( Bold, bool )
DECL_ATTR( Italic, bool )
DECL_ATTR( Color, Color& )
DECL_ATTR( Shadow, bool )
DECL_ATTR( Outline, bool )
DECL_ATTR( OutColor, Color& )
DECL_ATTR_STATIC( DefaultName, const char* )
DECL_ATTR_STATIC( DefaultSize, int )
DECL_ATTR_STATIC( DefaultBold, bool )
DECL_ATTR_STATIC( DefaultItalic, bool )
DECL_ATTR_STATIC( DefaultColor, Color& )
DECL_ATTR_STATIC( DefaultShadow, bool )
DECL_ATTR_STATIC( DefaultOutline, bool )
DECL_ATTR_STATIC( DefaultOutColor, Color& )
DECL_ATTR_STATIC( DefaultSize, int )
DECL_ATTR_STATIC( DefaultBold, bool )
DECL_ATTR_STATIC( DefaultItalic, bool )
DECL_ATTR_STATIC( DefaultColor, Color& )
DECL_ATTR_STATIC( DefaultShadow, bool )
DECL_ATTR_STATIC( DefaultOutline, bool )
DECL_ATTR_STATIC( DefaultOutColor, Color& )
/* There is no point in providing getters for these,
* as the bindings will always return the stored native
* string/array object anyway. It's impossible to mirror
* in the C++ core.
* The core object picks the first existing name from the
* passed array and stores it internally (same for default). */
void setName(const std::vector<std::string> &names);
static void setDefaultName(const std::vector<std::string> &names,
const SharedFontState &sfs);
static const std::vector<std::string> &getInitialDefaultNames();
/* Assigns heap allocated objects to object properties;
* using this in pure C++ will cause memory leaks
@ -110,7 +109,7 @@ public:
void initDynAttribs();
static void initDefaultDynAttribs();
static void initDefaults();
static void initDefaults(const SharedFontState &sfs);
/* internal */
_TTF_Font *getSdlFont();

View File

@ -169,15 +169,15 @@ public:
}
}
void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
void requestViewportRender(const Vec4 &c, const Vec4 &f, const Vec4 &t)
{
const IntRect &viewpRect = glState.scissorBox.get();
const IntRect &screenRect = geometry.rect;
bool toneRGBEffect = t.xyzHasEffect();
bool toneGrayEffect = t.w != 0;
bool colorEffect = c.w > 0;
bool flashEffect = f.w > 0;
const bool toneRGBEffect = t.xyzNotNull();
const bool toneGrayEffect = t.w != 0;
const bool colorEffect = c.w > 0;
const bool flashEffect = f.w > 0;
if (toneGrayEffect)
{
@ -240,7 +240,7 @@ public:
/* Then apply them using hardware blending */
gl.BlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ONE);
if (add.xyzHasEffect())
if (add.xyzNotNull())
{
gl.BlendEquation(GL_FUNC_ADD);
shader.setColor(add);
@ -248,7 +248,7 @@ public:
screenQuad.draw();
}
if (sub.xyzHasEffect())
if (sub.xyzNotNull())
{
gl.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
shader.setColor(sub);
@ -281,9 +281,9 @@ public:
void setBrightness(float norm)
{
brightnessQuad.setColor(Vec4(0, 0, 0, 1.0 - norm));
brightnessQuad.setColor(Vec4(0, 0, 0, 1.0f - norm));
brightEffect = norm < 1.0;
brightEffect = norm < 1.0f;
}
void updateReso(int width, int height)
@ -742,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 / 256.0);
shader.setVague(vague / 256.0f);
shader.setTexSize(p->scRes);
}
else
@ -780,7 +780,7 @@ void Graphics::transition(int duration,
p->checkSyncLock();
const float prog = i * (1.0 / duration);
const float prog = i * (1.0f / duration);
if (transMap)
{
@ -858,7 +858,7 @@ void Graphics::fadeout(int duration)
FBO::unbind();
float curr = p->brightness;
float diff = 255.0 - curr;
float diff = 255.0f - curr;
for (int i = duration-1; i > -1; --i)
{
@ -888,7 +888,7 @@ void Graphics::fadein(int duration)
FBO::unbind();
float curr = p->brightness;
float diff = 255.0 - curr;
float diff = 255.0f - curr;
for (int i = 1; i <= duration; ++i)
{
@ -963,6 +963,11 @@ void Graphics::resizeScreen(int width, int height)
shState->eThread().requestWindowResize(width, height);
}
void Graphics::playMovie(const char *filename)
{
Debug() << "Graphics.playMovie(" << filename << ") not implemented";
}
DEF_ATTR_RD_SIMPLE(Graphics, Brightness, int, p->brightness)
void Graphics::setBrightness(int value)

View File

@ -54,6 +54,7 @@ public:
int width() const;
int height() const;
void resizeScreen(int width, int height);
void playMovie(const char *filename);
void reset();

View File

@ -320,7 +320,7 @@ readEvent(MidiReadHandler *handler, MemChunk &chunk,
| (data[2] << 0x00);
e.type = Tempo;
e.e.tempo.bpm = 60000000.0 / mpqn;
e.e.tempo.bpm = 60000000 / mpqn;
}
else if (metaType == 0x2F)
{
@ -626,9 +626,20 @@ struct MidiSource : ALDataSource, MidiReadHandler
std::vector<uint8_t> data(dataLen);
if (SDL_RWread(&ops, &data[0], 1, dataLen) < dataLen)
{
SDL_RWclose(&ops);
throw Exception(Exception::MKXPError, "Reading midi data failed");
}
readMidi(this, data);
try
{
readMidi(this, data);
}
catch (const Exception &)
{
SDL_RWclose(&ops);
throw;
}
synth = shState->midiState().allocateSynth();
@ -688,7 +699,7 @@ struct MidiSource : ALDataSource, MidiReadHandler
void updatePlaybackSpeed(uint32_t bpm)
{
float deltaLength = 60.0 / (dpb * bpm);
float deltaLength = 60.0f / (dpb * bpm);
playbackSpeed = TICK_FRAMES / (deltaLength * freq);
}
@ -899,7 +910,7 @@ struct MidiSource : ALDataSource, MidiReadHandler
bool setPitch(float value)
{
// not completely correct, but close
pitchShift = round((value > 1.0 ? 14 : 24) * (value - 1.0));
pitchShift = round((value > 1.0f ? 14 : 24) * (value - 1.0f));
return true;
}

View File

@ -105,8 +105,8 @@ struct PlanePrivate
return;
/* Scaled (zoomed) bitmap dimensions */
double sw = bitmap->width() * zoomX;
double sh = bitmap->height() * zoomY;
float sw = bitmap->width() * zoomX;
float sh = bitmap->height() * zoomY;
/* Plane offset wrapped by scaled bitmap dims */
float wox = fwrap(ox, sw);

View File

@ -34,7 +34,7 @@ struct RGSS_entryData
struct RGSS_entryHandle
{
RGSS_entryData data;
const RGSS_entryData data;
uint32_t currentMagic;
uint64_t currentOffset;
PHYSFS_Io *io;
@ -229,7 +229,7 @@ RGSS_ioSeek(PHYSFS_Io *self, PHYSFS_uint64 offset)
static PHYSFS_sint64
RGSS_ioTell(PHYSFS_Io *self)
{
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
const RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
return entry->currentOffset;
}
@ -237,7 +237,7 @@ RGSS_ioTell(PHYSFS_Io *self)
static PHYSFS_sint64
RGSS_ioLength(PHYSFS_Io *self)
{
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
const RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
return entry->data.size;
}
@ -245,7 +245,7 @@ RGSS_ioLength(PHYSFS_Io *self)
static PHYSFS_Io*
RGSS_ioDuplicate(PHYSFS_Io *self)
{
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
const RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
RGSS_entryHandle *entryDup = new RGSS_entryHandle(*entry);
PHYSFS_Io *dup = PHYSFS_ALLOC(PHYSFS_Io);
@ -448,7 +448,7 @@ RGSS_stat(void *opaque, const char *filename, PHYSFS_Stat *stat)
if (hasFile)
{
RGSS_entryData &entry = data->entryHash[filename];
const RGSS_entryData &entry = data->entryHash[filename];
stat->filesize = entry.size;
stat->filetype = PHYSFS_FILETYPE_REGULAR;

View File

@ -55,7 +55,9 @@ public:
virtual ~Scene();
virtual void composite();
virtual void requestViewportRender(Vec4& /*color*/, Vec4& /*flash*/, Vec4& /*tone*/) {}
virtual void requestViewportRender(const Vec4& /* color */,
const Vec4& /* flash */,
const Vec4& /* tone */) {}
const Geometry &getGeometry() const { return geometry; }

View File

@ -764,13 +764,13 @@ void Widget::click(int x, int y, uint8_t button)
}
/* Ratio of cell area to total widget width */
#define BW_CELL_R 0.75
#define BW_CELL_R 0.75f
void BindingWidget::drawHandler(SDL_Surface *surf)
{
const int cellW = (rect.w*BW_CELL_R) / 2;
const int cellH = rect.h / 2;
const int cellOffX = (1.0-BW_CELL_R) * rect.w;
const int cellOffX = (1.0f-BW_CELL_R) * rect.w;
const int cellOff[] =
{
@ -860,7 +860,7 @@ int BindingWidget::cellIndex(int x, int y) const
{
const int cellW = (rect.w*BW_CELL_R) / 2;
const int cellH = rect.h / 2;
const int cellOff = (1.0-BW_CELL_R) * rect.w;
const int cellOff = (1.0f-BW_CELL_R) * rect.w;
if (x < cellOff)
return -1;

View File

@ -80,7 +80,7 @@ struct SharedMidiState
return;
flSettings = fluid.new_settings();
fluid.settings_setnum(flSettings, "synth.gain", 1.0);
fluid.settings_setnum(flSettings, "synth.gain", 1.0f);
fluid.settings_setnum(flSettings, "synth.sample-rate", SYNTH_SAMPLERATE);
fluid.settings_setstr(flSettings, "synth.chorus.active", conf.midi.chorus ? "yes" : "no");
fluid.settings_setstr(flSettings, "synth.reverb.active", conf.midi.reverb ? "yes" : "no");

View File

@ -172,7 +172,6 @@ void SharedState::initInstance(RGSSThreadData *threadData)
* Font depends on SharedState existing */
rgssVersion = threadData->config.rgssVersion;
Font::initDefaults();
_globalIBO = new GlobalIBO();
_globalIBO->ensureSize(1);
@ -183,6 +182,7 @@ void SharedState::initInstance(RGSSThreadData *threadData)
try
{
SharedState::instance = new SharedState(threadData);
Font::initDefaults(instance->p->fontState);
defaultFont = new Font();
}
catch (const Exception &exc)

View File

@ -123,8 +123,8 @@ void SoundEmitter::play(const std::string &filename,
int volume,
int pitch)
{
float _volume = clamp<int>(volume, 0, 100) / 100.f;
float _pitch = clamp<int>(pitch, 50, 150) / 100.f;
float _volume = clamp<int>(volume, 0, 100) / 100.0f;
float _pitch = clamp<int>(pitch, 50, 150) / 100.0f;
SoundBuffer *buffer = allocateBuffer(filename);
@ -184,6 +184,44 @@ void SoundEmitter::stop()
AL::Source::stop(alSrcs[i]);
}
struct SoundOpenHandler : FileSystem::OpenHandler
{
SoundBuffer *buffer;
SoundOpenHandler()
: buffer(0)
{}
bool tryRead(SDL_RWops &ops, const char *ext)
{
Sound_Sample *sample = Sound_NewSample(&ops, ext, 0, STREAM_BUF_SIZE);
if (!sample)
{
SDL_RWclose(&ops);
return false;
}
/* Do all of the decoding in the handler so we don't have
* to keep the source ops around */
uint32_t decBytes = Sound_DecodeAll(sample);
uint8_t sampleSize = formatSampleSize(sample->actual.format);
uint32_t sampleCount = decBytes / sampleSize;
buffer = new SoundBuffer;
buffer->bytes = sampleSize * sampleCount;
ALenum alFormat = chooseALFormat(sampleSize, sample->actual.channels);
AL::Buffer::uploadData(buffer->alBuffer, alFormat, sample->buffer,
buffer->bytes, sample->actual.rate);
Sound_FreeSample(sample);
return true;
}
};
SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
{
SoundBuffer *buffer = bufferHash.value(filename, 0);
@ -199,40 +237,22 @@ SoundBuffer *SoundEmitter::allocateBuffer(const std::string &filename)
}
else
{
/* Buffer not in cashe, needs to be loaded */
SDL_RWops dataSource;
char ext[8];
/* Buffer not in cache, needs to be loaded */
SoundOpenHandler handler;
shState->fileSystem().openRead(handler, filename.c_str());
buffer = handler.buffer;
shState->fileSystem().openRead(dataSource, filename.c_str(),
false, ext, sizeof(ext));
Sound_Sample *sampleHandle = Sound_NewSample(&dataSource, ext, 0, STREAM_BUF_SIZE);
if (!sampleHandle)
if (!buffer)
{
char buf[512];
snprintf(buf, sizeof(buf), "Unable to decode sound: %s.%s: %s",
filename.c_str(), ext, Sound_GetError());
snprintf(buf, sizeof(buf), "Unable to decode sound: %s: %s",
filename.c_str(), Sound_GetError());
Debug() << buf;
return 0;
}
uint32_t decBytes = Sound_DecodeAll(sampleHandle);
uint8_t sampleSize = formatSampleSize(sampleHandle->actual.format);
uint32_t sampleCount = decBytes / sampleSize;
buffer = new SoundBuffer;
buffer->key = filename;
buffer->bytes = sampleSize * sampleCount;
ALenum alFormat = chooseALFormat(sampleSize, sampleHandle->actual.channels);
AL::Buffer::uploadData(buffer->alBuffer, alFormat, sampleHandle->buffer,
buffer->bytes, sampleHandle->actual.rate);
Sound_FreeSample(sampleHandle);
uint32_t wouldBeBytes = bufferBytes + buffer->bytes;
/* If memory limit is reached, delete lowest priority buffer

View File

@ -109,7 +109,7 @@ struct SpritePrivate
wave.amp = 0;
wave.length = 180;
wave.speed = 360;
wave.phase = 0.0;
wave.phase = 0.0f;
wave.dirty = false;
}
@ -129,7 +129,7 @@ struct SpritePrivate
(srcRect->y + srcRect->height) +
bitmap->height();
efBushDepth = 1.0 - texBushDepth / bitmap->height();
efBushDepth = 1.0f - texBushDepth / bitmap->height();
}
void onSrcRectChange()
@ -194,7 +194,7 @@ struct SpritePrivate
void emitWaveChunk(SVertex *&vert, float phase, int width,
float zoomY, int chunkY, int chunkLength)
{
float wavePos = phase + (chunkY / (float) wave.length) * M_PI * 2;
float wavePos = phase + (chunkY / (float) wave.length) * (float) (M_PI * 2);
float chunkX = sin(wavePos) * wave.amp;
FloatRect tex(0, chunkY / zoomY, width, chunkLength / zoomY);
@ -261,7 +261,7 @@ struct SpritePrivate
wave.qArray.resize(!!firstLength + chunks + !!lastLength);
SVertex *vert = &wave.qArray.vertices[0];
float phase = (wave.phase * M_PI) / 180.f;
float phase = (wave.phase * (float) M_PI) / 180.0f;
if (firstLength > 0)
emitWaveChunk(vert, phase, width, zoomY, 0, firstLength);

View File

@ -51,14 +51,14 @@ extern const int autotileVXRectsBN;
/* Waterfall (C) autotile patterns */
static const StaticRect autotileVXRectsC[] =
{
{ 32.5, 0.5, 15, 31 },
{ 16.5, 0.5, 15, 31 },
{ 0.0, 0.5, 15, 31 },
{ 16.5, 0.5, 15, 31 },
{ 32.5, 0.5, 15, 31 },
{ 48.5, 0.5, 15, 31 },
{ 0.0, 0.5, 15, 31 },
{ 48.5, 0.5, 15, 31 }
{ 32.5f, 0.5f, 15.0f, 31.0f },
{ 16.5f, 0.5f, 15.0f, 31.0f },
{ 0.0f, 0.5f, 15.0f, 31.0f },
{ 16.5f, 0.5f, 15.0f, 31.0f },
{ 32.5f, 0.5f, 15.0f, 31.0f },
{ 48.5f, 0.5f, 15.0f, 31.0f },
{ 0.0f, 0.5f, 15.0f, 31.0f },
{ 48.5f, 0.5f, 15.0f, 31.0f }
};
static elementsN(autotileVXRectsC);
@ -500,7 +500,7 @@ onTileA4(Reader &reader, int16_t tileID,
Vec2i orig = blitsA4[0].dst;
tileID -= 0x1700;
const int offY[] = { 0, 3, 5, 8, 10, 13 };
static const int offY[] = { 0, 3, 5, 8, 10, 13 };
int patternID = tileID % 0x30;
int autotileID = tileID / 0x30;

View File

@ -46,6 +46,13 @@ wrap(int value, int range)
return res < 0 ? res + range : res;
}
static inline Vec2i
wrap(const Vec2i &value, int range)
{
return Vec2i(wrap(value.x, range),
wrap(value.y, range));
}
static inline int16_t
tableGetWrapped(const Table &t, int x, int y, int z = 0)
{
@ -54,6 +61,16 @@ tableGetWrapped(const Table &t, int x, int y, int z = 0)
z);
}
/* Calculate the tile x/y on which this pixel x/y lies */
static inline Vec2i
getTilePos(const Vec2i &pixelPos)
{
/* Round the pixel position down to the nearest top left
* tile boundary, by masking off the lower 5 bits (2^5 = 32).
* Then divide by 32 to convert into tile units. */
return (pixelPos & ~(32-1)) / 32;
}
enum AtSubPos
{
TopLeft = 0,

View File

@ -236,7 +236,7 @@ struct TilemapPrivate
Table *mapData;
Table *priorities;
bool visible;
Vec2i offset;
Vec2i origin;
Vec2i dispPos;
@ -294,7 +294,6 @@ struct TilemapPrivate
/* Used layers out of 'zlayers' (rest is hidden) */
size_t activeLayers;
Scene::Geometry sceneGeo;
Vec2i sceneOffset;
} elem;
/* Affected by: autotiles, tileset */
@ -394,7 +393,7 @@ struct TilemapPrivate
void updateFlashMapViewport()
{
flashMap.setViewport(IntRect(viewpPos.x, viewpPos.y, viewpW, viewpH));
flashMap.setViewport(IntRect(viewpPos, Vec2i(viewpW, viewpH)));
}
void updateAtlasInfo()
@ -442,13 +441,8 @@ struct TilemapPrivate
void updateSceneGeometry(const Scene::Geometry &geo)
{
elem.sceneOffset = geo.offset();
elem.sceneGeo = geo;
}
void updatePosition()
{
dispPos = -(offset - viewpPos * 32) + elem.sceneOffset;
mapViewportDirty = true;
}
void invalidateAtlasSize()
@ -698,7 +692,7 @@ struct TilemapPrivate
int tileY = tsInd / 8;
Vec2i texPos = TileAtlas::tileToAtlasCoor(tileX, tileY, atlas.efTilesetH, atlas.size.y);
FloatRect texRect((float) texPos.x+.5, (float) texPos.y+.5, 31, 31);
FloatRect texRect((float) texPos.x+0.5f, (float) texPos.y+0.5f, 31, 31);
FloatRect posRect(x*32, y*32, 32, 32);
SVertex v[4];
@ -898,38 +892,17 @@ struct TilemapPrivate
void updateMapViewport()
{
int tileOX, tileOY;
const Vec2i combOrigin = origin + elem.sceneGeo.orig;
const Vec2i mvpPos = getTilePos(combOrigin);
if (offset.x >= 0)
tileOX = offset.x / 32;
else
tileOX = -(-(offset.x-31) / 32);
if (offset.y >= 0)
tileOY = offset.y / 32;
else
tileOY = -(-(offset.y-31) / 32);
bool dirty = false;
if (tileOX < viewpPos.x || tileOX + 21 > viewpPos.x + viewpW)
{
viewpPos.x = tileOX;
dirty = true;
}
if (tileOY < viewpPos.y || tileOY + 16 > viewpPos.y + viewpH)
{
viewpPos.y = tileOY;
dirty = true;
}
if (dirty)
if (mvpPos != viewpPos)
{
viewpPos = mvpPos;
buffersDirty = true;
updateFlashMapViewport();
updatePosition();
}
dispPos = elem.sceneGeo.rect.pos() - wrap(combOrigin, 32);
}
void prepare()
@ -1024,7 +997,6 @@ void GroundLayer::drawInt()
void GroundLayer::onGeometryChange(const Scene::Geometry &geo)
{
p->updateSceneGeometry(geo);
p->updatePosition();
}
ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport)
@ -1072,7 +1044,7 @@ void ZLayer::drawInt()
int ZLayer::calculateZ(TilemapPrivate *p, int index)
{
return 32 * (index + p->viewpPos.y + 1) - p->offset.y;
return 32 * (index + p->viewpPos.y + 1) - p->origin.y;
}
void ZLayer::initUpdateZ()
@ -1172,8 +1144,8 @@ DEF_ATTR_RD_SIMPLE(Tilemap, MapData, Table*, p->mapData)
DEF_ATTR_RD_SIMPLE(Tilemap, FlashData, Table*, p->flashMap.getData())
DEF_ATTR_RD_SIMPLE(Tilemap, Priorities, Table*, p->priorities)
DEF_ATTR_RD_SIMPLE(Tilemap, Visible, bool, p->visible)
DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->offset.x)
DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->offset.y)
DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->origin.x)
DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->origin.y)
void Tilemap::setTileset(Bitmap *value)
{
@ -1259,11 +1231,10 @@ void Tilemap::setOX(int value)
{
guardDisposed();
if (p->offset.x == value)
if (p->origin.x == value)
return;
p->offset.x = value;
p->updatePosition();
p->origin.x = value;
p->mapViewportDirty = true;
}
@ -1271,11 +1242,10 @@ void Tilemap::setOY(int value)
{
guardDisposed();
if (p->offset.y == value)
if (p->origin.y == value)
return;
p->offset.y = value;
p->updatePosition();
p->origin.y = value;
p->zOrderDirty = true;
p->mapViewportDirty = true;
}

View File

@ -57,12 +57,12 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
Table *mapData;
Table *flags;
Vec2i offset;
Vec2i origin;
Vec2i dispPos;
/* Map viewport position */
/* Subregion of the map that is drawn to screen (map viewport) */
IntRect mapViewp;
Vec2i sceneOffset;
/* Position on screen the map subregion is drawn at */
Vec2i dispPos;
Scene::Geometry sceneGeo;
std::vector<SVertex> groundVert;
@ -179,49 +179,31 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
TileAtlasVX::build(atlas, bitmaps);
}
void updatePosition()
{
dispPos.x = -(offset.x - mapViewp.x * 32) + sceneOffset.x;
dispPos.y = -(offset.y - mapViewp.y * 32) + sceneOffset.y;
}
void updateMapViewport()
{
int tileOX, tileOY;
/* Note: We include one extra row at the top above
* the normal map viewport to ensure the legs of table
* tiles off screen are properly drawn */
Vec2i offs(offset.x-sceneOffset.x, offset.y-sceneOffset.y);
IntRect newMvp;
if (offs.x >= 0)
tileOX = offs.x / 32;
else
tileOX = -(-(offs.x-31) / 32);
const Vec2i combOrigin = origin + sceneGeo.orig;
const Vec2i geoSize = sceneGeo.rect.size();
if (offs.y >= 0)
tileOY = offs.y / 32;
else
tileOY = -(-(offs.y-31) / 32);
newMvp.setPos(getTilePos(combOrigin) - Vec2i(0, 1));
bool dirty = false;
/* Ensure that the size is big enough to cover the whole viewport,
* and add one tile row/column as a buffer for scrolling */
newMvp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1, 2));
if (tileOX < mapViewp.x || tileOX > mapViewp.x)
{
mapViewp.x = tileOX;
dirty = true;
}
if (tileOY < mapViewp.y || tileOY > mapViewp.y)
{
mapViewp.y = tileOY;
dirty = true;
}
if (dirty)
if (newMvp != mapViewp)
{
mapViewp = newMvp;
flashMap.setViewport(newMvp);
buffersDirty = true;
}
updatePosition();
flashMap.setViewport(mapViewp);
dispPos = sceneGeo.rect.pos() - wrap(combOrigin, 32) - Vec2i(0, 32);
}
static size_t quadBytes(size_t quads)
@ -366,10 +348,6 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
void onGeometryChange(const Scene::Geometry &geo)
{
const Vec2i geoSize = geo.rect.size();
mapViewp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1));
sceneOffset = geo.offset();
sceneGeo = geo;
buffersDirty = true;
@ -380,7 +358,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
/* TileAtlasVX::Reader */
void onQuads(const FloatRect *t, const FloatRect *p,
size_t n, bool overPlayer)
size_t n, bool overPlayer)
{
SVertex *vert = allocVert(overPlayer ? aboveVert : groundVert, n*4);
@ -467,8 +445,8 @@ TilemapVX::BitmapArray &TilemapVX::getBitmapArray()
DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData)
DEF_ATTR_RD_SIMPLE(TilemapVX, FlashData, Table*, p->flashMap.getData())
DEF_ATTR_RD_SIMPLE(TilemapVX, Flags, Table*, p->flags)
DEF_ATTR_RD_SIMPLE(TilemapVX, OX, int, p->offset.x)
DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->offset.y)
DEF_ATTR_RD_SIMPLE(TilemapVX, OX, int, p->origin.x)
DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->origin.y)
Viewport *TilemapVX::getViewport() const
{
@ -541,10 +519,10 @@ void TilemapVX::setOX(int value)
{
guardDisposed();
if (p->offset.x == value)
if (p->origin.x == value)
return;
p->offset.x = value;
p->origin.x = value;
p->mapViewportDirty = true;
}
@ -552,10 +530,10 @@ void TilemapVX::setOY(int value)
{
guardDisposed();
if (p->offset.y == value)
if (p->origin.y == value)
return;
p->offset.y = value;
p->origin.y = value;
p->mapViewportDirty = true;
}

View File

@ -130,7 +130,7 @@ private:
if (rotation < 0)
rotation += 360;
float angle = rotation * 3.141592654f / 180.f;
float angle = rotation * 3.141592654f / 180.0f;
float cosine = (float) cos(angle);
float sine = (float) sin(angle);
float sxc = scale.x * cosine;

View File

@ -642,7 +642,7 @@ struct WindowPrivate
if (active && cursorVert.vert)
{
float alpha = cursorAniAlpha[cursorAniAlphaIdx] / 255.0;
float alpha = cursorAniAlpha[cursorAniAlphaIdx] / 255.0f;
cursorVert.setAlpha(alpha);
@ -651,7 +651,7 @@ struct WindowPrivate
if (pause && pauseAniVert.vert)
{
float alpha = pauseAniAlpha[pauseAniAlphaIdx] / 255.0;
float alpha = pauseAniAlpha[pauseAniAlphaIdx] / 255.0f;
FloatRect frameRect = pauseAniSrc[pauseAniQuad[pauseAniQuadIdx]];
pauseAniVert.setAlpha(alpha);

View File

@ -482,7 +482,7 @@ struct WindowVXPrivate
void updateBaseQuad()
{
const FloatRect tex(0, 0, geo.w, geo.h);
const FloatRect pos(0, (geo.h / 2.0) * (1 - openness.norm),
const FloatRect pos(0, (geo.h / 2.0f) * (1.0f - openness.norm),
geo.w, geo.h * openness.norm);
base.quad.setTexPosRect(tex, pos);
@ -633,7 +633,7 @@ struct WindowVXPrivate
Quad::setTexRect(pauseVert, pauseSrc[pauseQuad[pauseQuadIdx]]);
/* Set opacity */
Quad::setColor(pauseVert, Vec4(1, 1, 1, pauseAlpha[pauseAlphaIdx] / 255.0));
Quad::setColor(pauseVert, Vec4(1, 1, 1, pauseAlpha[pauseAlphaIdx] / 255.0f));
ctrlVertArrayDirty = true;
}
@ -643,7 +643,7 @@ struct WindowVXPrivate
if (cursorVert.count() == 0)
return;
Vec4 color(1, 1, 1, cursorAlpha[cursorAlphaIdx] / 255.0);
Vec4 color(1, 1, 1, cursorAlpha[cursorAlphaIdx] / 255.0f);
for (size_t i = 0; i < cursorVert.count(); ++i)
Quad::setColor(&cursorVert.vertices[i*4], color);