Initial commit
This commit is contained in:
commit
ff25887f41
|
@ -0,0 +1,7 @@
|
|||
*.o
|
||||
*.pro.*
|
||||
*.bak
|
||||
*.frag.xxd
|
||||
*.ttf.xxd
|
||||
|
||||
mkxp
|
|
@ -0,0 +1,85 @@
|
|||
# mkxp
|
||||
|
||||
mkxp is a project that seeks to provide a fully open source implementation of the RGSS (Ruby Game Scripting System) interface used in the popular game creation software "RPG Maker XP" (trademark by Enterbrain, Inc.), with focus on Linux. The goal is to be able to run games created with the above software natively without changing a single file.
|
||||
|
||||
## Bindings
|
||||
Bindings provide the interpreted language environment to run game scripts in. As of right now, they are compiled directly into the executable. Currently there are three bindings:
|
||||
|
||||
### MRI
|
||||
Website: https://www.ruby-lang.org/en/
|
||||
|
||||
Matz's Ruby Interpreter, also called CRuby, is the most widely deployed version of ruby. If you're interested in running games created with RPG Maker XP, this is the one you should go for. MRI 1.8 is what was used in RPG Maker XP, however, this binding is written against 2.0 (the latest version). For games utilizing only the default scripts provided by Enterbrain, this binding works quite well so far. Note that there are language and syntax differences between 1.8 and 2.0, so some user created scripts may not work correctly.
|
||||
|
||||
For a list of differences, see:
|
||||
http://stackoverflow.com/questions/21574/what-is-the-difference-between-ruby-1-8-and-ruby-1-9
|
||||
|
||||
To select this backend, run `qmake BINDING=BINDING_MRI`
|
||||
|
||||
### mruby (Lightweight Ruby)
|
||||
Website: https://github.com/mruby/mruby
|
||||
|
||||
mruby is a new endeavor by Matz and others to create a more lightweight, spec-adhering, embeddable Ruby implementation. You can think of it as a Ruby version of Lua.
|
||||
|
||||
Due to heavy differences between mruby and MRI as well as lacking modules, running RPG Maker games with this backend will most likely not work correctly. It is provided as experimental code. You can eg. write your own ruby scripts and run them with this backend.
|
||||
|
||||
Some extensions to the standard classes/modules are provided taking the RPG Maker XP helpfile as a quasi "standard". These include Marshal, File, FileTest and Time.
|
||||
|
||||
To select this backend, run `qmake BINDING=BINDING_MRUBY`
|
||||
|
||||
### null
|
||||
This backend only exists for testing purposes and does nothing (the engine quits immediately).
|
||||
|
||||
To select this backend, run `qmake BINDING=BINDING_NULL`
|
||||
|
||||
## Dependencies
|
||||
|
||||
* QtCore 4.8
|
||||
* libsigc++
|
||||
* PhysFS
|
||||
* glew
|
||||
* SDL2
|
||||
* SDL2_image
|
||||
* SDL2_ttf
|
||||
* sfml-system 2.0
|
||||
* sfml-audio 2.0
|
||||
|
||||
(If no version specified, assume latest)
|
||||
|
||||
### MRI binding:
|
||||
Place a recent version of ruby in the project folder and build it.
|
||||
|
||||
### mruby binding:
|
||||
Place a recent version of mruby in the project folder and build it.
|
||||
|
||||
To run mkxp, you should have a graphics card capable of at least **OpenGL 3.0**
|
||||
|
||||
## Building
|
||||
|
||||
mkxp employs Qt's qmake build system, so you'll need to install that beforehand. After cloning mkxp, run one of the above qmake calls, or simply `qmake` to select the default backend (currently MRI), then `make`.
|
||||
|
||||
## Configuration
|
||||
|
||||
mkxp reads configuration data from the file "mkxp.conf" contained in the current directory. The format is ini-style.
|
||||
|
||||
* "gameFolder": Specifies where mkxp will look for the game scripts. Default is the current directory.
|
||||
* "customScript": Specifies a raw ruby script file to be run instead of an RPG Maker game, residing in "gameFolder".
|
||||
* "RTPs": Specifies a list of space separated paths to RTPs to be used. (See next section)
|
||||
|
||||
Most other entries are self explanatory.
|
||||
|
||||
## RTPs
|
||||
|
||||
As of right now, mkxp doesn't support midi files, so to use the default RTPs provided by Enterbrain you will have to convert all midi tracks (those in BGM and ME) to ogg or wav. Make sure that the file names match up, ie. "foobar.mid" should be converted to "foobar.ogg".
|
||||
|
||||
## Fonts
|
||||
|
||||
In the RMXP version of RGSS, fonts are loaded directly from system specific search paths (meaning they must be installed to be available to games). Because this whole thing is a giant platform-dependent headache, I decided to implement the behavior Enterbrain thankfully added in VX Ace: loading fonts will automatically search a folder called "Fonts", which obeys the default searchpath behavior (ie. it can be located directly in the game folder, or an RTP).
|
||||
|
||||
If a requested font is not found, no error is generated. Instead, a built-in font is used (currently "Liberation Sans").
|
||||
|
||||
## What doesn't work
|
||||
|
||||
* Audio formats other than ogg/wav (this might change in the future)
|
||||
* Audio "pitch" parameter
|
||||
* The Win32API ruby class (for obvious reasons)
|
||||
* Loading Bitmaps with sizes greater than the OpenGL texture size limit (around 8192 on modern cards)
|
Binary file not shown.
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
** audio-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audio.h"
|
||||
#include "globalstate.h"
|
||||
#include "binding-util.h"
|
||||
#include "exception.h"
|
||||
|
||||
#define DEF_PLAY_STOP(entity) \
|
||||
RB_METHOD(audio_##entity##Play) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
const char *filename; \
|
||||
int volume = 100; \
|
||||
int pitch = 100; \
|
||||
rb_get_args(argc, argv, "z|ii", &filename, &volume, &pitch); \
|
||||
GUARD_EXC( gState->audio().entity##Play(filename, volume, pitch); ) \
|
||||
return Qnil; \
|
||||
} \
|
||||
RB_METHOD(audio_##entity##Stop) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
gState->audio().entity##Stop(); \
|
||||
return Qnil; \
|
||||
}
|
||||
|
||||
#define DEF_FADE(entity) \
|
||||
RB_METHOD(audio_##entity##Fade) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
int time; \
|
||||
rb_get_args(argc, argv, "i", &time); \
|
||||
gState->audio().bgmFade(time); \
|
||||
return Qnil; \
|
||||
}
|
||||
|
||||
#define DEF_PLAY_STOP_FADE(entity) \
|
||||
DEF_PLAY_STOP(entity) \
|
||||
DEF_FADE(entity)
|
||||
|
||||
DEF_PLAY_STOP_FADE( bgm )
|
||||
DEF_PLAY_STOP_FADE( bgs )
|
||||
DEF_PLAY_STOP_FADE( me )
|
||||
|
||||
DEF_PLAY_STOP( se )
|
||||
|
||||
|
||||
#define BIND_PLAY_STOP(entity) \
|
||||
_rb_define_module_function(module, #entity "_play", audio_##entity##Play); \
|
||||
_rb_define_module_function(module, #entity "_stop", audio_##entity##Stop);
|
||||
|
||||
#define BIND_FADE(entity) \
|
||||
_rb_define_module_function(module, #entity "_fade", audio_##entity##Fade);
|
||||
|
||||
#define BIND_PLAY_STOP_FADE(entity) \
|
||||
BIND_PLAY_STOP(entity) \
|
||||
BIND_FADE(entity)
|
||||
|
||||
|
||||
void
|
||||
audioBindingInit()
|
||||
{
|
||||
VALUE module = rb_define_module("Audio");
|
||||
|
||||
BIND_PLAY_STOP_FADE( bgm )
|
||||
BIND_PLAY_STOP_FADE( bgs )
|
||||
BIND_PLAY_STOP_FADE( me )
|
||||
|
||||
BIND_PLAY_STOP( se )
|
||||
}
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
** binding-mri.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "globalstate.h"
|
||||
#include "eventthread.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#include "./ruby/include/ruby.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
extern const char module_rpg[];
|
||||
|
||||
static void mriBindingExecute();
|
||||
static void mriBindingTerminate();
|
||||
|
||||
ScriptBinding scriptBindingImpl =
|
||||
{
|
||||
mriBindingExecute,
|
||||
mriBindingTerminate
|
||||
};
|
||||
|
||||
ScriptBinding *scriptBinding = &scriptBindingImpl;
|
||||
|
||||
void tableBindingInit();
|
||||
void etcBindingInit();
|
||||
void fontBindingInit();
|
||||
void bitmapBindingInit();
|
||||
void spriteBindingInit();
|
||||
void viewportBindingInit();
|
||||
void planeBindingInit();
|
||||
void windowBindingInit();
|
||||
void tilemapBindingInit();
|
||||
|
||||
void inputBindingInit();
|
||||
void audioBindingInit();
|
||||
void graphicsBindingInit();
|
||||
|
||||
void fileIntBindingInit();
|
||||
|
||||
static VALUE mriPrint(int, VALUE*, VALUE);
|
||||
static VALUE mriP(int, VALUE*, VALUE);
|
||||
|
||||
static void mriBindingInit()
|
||||
{
|
||||
tableBindingInit();
|
||||
etcBindingInit();
|
||||
fontBindingInit();
|
||||
bitmapBindingInit();
|
||||
spriteBindingInit();
|
||||
viewportBindingInit();
|
||||
planeBindingInit();
|
||||
windowBindingInit();
|
||||
tilemapBindingInit();
|
||||
|
||||
inputBindingInit();
|
||||
audioBindingInit();
|
||||
graphicsBindingInit();
|
||||
|
||||
fileIntBindingInit();
|
||||
|
||||
_rb_define_module_function(rb_mKernel, "print", mriPrint);
|
||||
_rb_define_module_function(rb_mKernel, "p", mriP);
|
||||
|
||||
rb_eval_string(module_rpg);
|
||||
|
||||
rb_define_global_const("MKXP", Qtrue);
|
||||
}
|
||||
|
||||
static void
|
||||
showMsg(const QByteArray &msg)
|
||||
{
|
||||
gState->eThread().showMessageBox(msg.constData());
|
||||
}
|
||||
|
||||
static void printP(int argc, VALUE *argv,
|
||||
const char *convMethod, const char *sep)
|
||||
{
|
||||
VALUE dispString = rb_str_buf_new(128);
|
||||
ID conv = rb_intern(convMethod);
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
VALUE str = rb_funcall(argv[i], conv, 0);
|
||||
rb_str_buf_append(dispString, str);
|
||||
|
||||
if (i < argc)
|
||||
rb_str_buf_cat2(dispString, sep);
|
||||
}
|
||||
|
||||
showMsg(RSTRING_PTR(dispString));
|
||||
|
||||
rb_str_free(dispString);
|
||||
}
|
||||
|
||||
RB_METHOD(mriPrint)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
printP(argc, argv, "to_s", "");
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(mriP)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
printP(argc, argv, "inspect", "\n");
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static void runCustomScript(const char *filename)
|
||||
{
|
||||
QFile scriptFile(filename);
|
||||
if (!scriptFile.open(QFile::ReadOnly))
|
||||
{
|
||||
showMsg(QByteArray("Unable to open '") + filename + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray scriptData = scriptFile.readAll();
|
||||
scriptFile.close();
|
||||
|
||||
rb_eval_string_protect(scriptData.constData(), 0);
|
||||
}
|
||||
|
||||
VALUE kernelLoadDataInt(const char *filename);
|
||||
|
||||
struct Script
|
||||
{
|
||||
QByteArray name;
|
||||
QByteArray encData;
|
||||
uint32_t unknown;
|
||||
|
||||
QByteArray decData;
|
||||
};
|
||||
|
||||
static void runRMXPScripts()
|
||||
{
|
||||
const QByteArray &scriptPack = gState->rtData().config.game.scripts;
|
||||
|
||||
if (!gState->fileSystem().exists(scriptPack.constData()))
|
||||
{
|
||||
showMsg("Unable to open '" + scriptPack + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
VALUE scriptArray = kernelLoadDataInt(scriptPack.constData());
|
||||
|
||||
if (rb_type(scriptArray) != RUBY_T_ARRAY)
|
||||
{
|
||||
showMsg("Failed to read script data");
|
||||
return;
|
||||
}
|
||||
|
||||
int scriptCount = RARRAY_LEN(scriptArray);
|
||||
|
||||
QByteArray decodeBuffer;
|
||||
decodeBuffer.resize(0x1000);
|
||||
|
||||
QVector<Script> encScripts(scriptCount);
|
||||
|
||||
for (int i = 0; i < scriptCount; ++i)
|
||||
{
|
||||
VALUE script = rb_ary_entry(scriptArray, i);
|
||||
|
||||
if (rb_type(script) != RUBY_T_ARRAY)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VALUE scriptUnknown = rb_ary_entry(script, 0);
|
||||
VALUE scriptName = rb_ary_entry(script, 1);
|
||||
VALUE scriptString = rb_ary_entry(script, 2);
|
||||
|
||||
Script &sc = encScripts[i];
|
||||
sc.name = RSTRING_PTR(scriptName);
|
||||
sc.encData = QByteArray(RSTRING_PTR(scriptString), RSTRING_LEN(scriptString));
|
||||
sc.unknown = FIX2UINT(scriptUnknown);
|
||||
}
|
||||
|
||||
for (int i = 0; i < scriptCount; ++i)
|
||||
{
|
||||
Script &sc = encScripts[i];
|
||||
|
||||
int result = Z_OK;
|
||||
ulong bufferLen;
|
||||
|
||||
while (true)
|
||||
{
|
||||
unsigned char *bufferPtr =
|
||||
reinterpret_cast<unsigned char*>(const_cast<char*>(decodeBuffer.constData()));
|
||||
const unsigned char *sourcePtr =
|
||||
reinterpret_cast<const unsigned char*>(sc.encData.constData());
|
||||
|
||||
bufferLen = decodeBuffer.length();
|
||||
|
||||
result = uncompress(bufferPtr, &bufferLen,
|
||||
sourcePtr, sc.encData.length());
|
||||
|
||||
bufferPtr[bufferLen] = '\0';
|
||||
|
||||
if (result != Z_BUF_ERROR)
|
||||
break;
|
||||
|
||||
decodeBuffer.resize(decodeBuffer.size()*2);
|
||||
}
|
||||
|
||||
if (result != Z_OK)
|
||||
{
|
||||
static char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "Error decoding script %d: '%s'",
|
||||
i, sc.name.constData());
|
||||
|
||||
showMsg(buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
// QFile file(QString("/home/Ancurio/programming/C++/mkxp/dump/%1.rb").arg(i, 3, 10, QChar('0')));
|
||||
// if (file.open(QFile::WriteOnly))
|
||||
// file.write(decodeBuffer.constData(), bufferLen);
|
||||
|
||||
sc.decData = QByteArray(decodeBuffer.constData(), bufferLen);
|
||||
|
||||
ruby_script(sc.name.constData());
|
||||
|
||||
rb_gc_start();
|
||||
|
||||
qDebug() << "Executing script:" << QString("%1").arg(i, 3, 10, QChar('0'));
|
||||
|
||||
/* Execute code */
|
||||
rb_eval_string_protect(decodeBuffer.constData(), 0);
|
||||
|
||||
VALUE exc = rb_gv_get("$!");
|
||||
if (rb_type(exc) != RUBY_T_NIL)
|
||||
break;
|
||||
}
|
||||
|
||||
// QFile file("/home/Ancurio/programming/C++/mkxp/dump/index");
|
||||
// if (file.open(QFile::WriteOnly))
|
||||
// {
|
||||
// for (int i = 0; i < encScripts.size(); ++i)
|
||||
// {
|
||||
// const Script &sc = encScripts[i];
|
||||
// file.write(sc.name);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
static void mriBindingExecute()
|
||||
{
|
||||
ruby_setup();
|
||||
|
||||
RbData rbData;
|
||||
gState->setBindingData(&rbData);
|
||||
|
||||
mriBindingInit();
|
||||
|
||||
QByteArray &customScript = gState->rtData().config.customScript;
|
||||
if (!customScript.isEmpty())
|
||||
runCustomScript(customScript.constData());
|
||||
else
|
||||
runRMXPScripts();
|
||||
|
||||
VALUE exc = rb_gv_get("$!");
|
||||
if (rb_type(exc) != RUBY_T_NIL && !rb_eql(rb_obj_class(exc), rb_eSystemExit))
|
||||
{
|
||||
qDebug() << "Had exception:" << rb_class2name(rb_obj_class(exc));
|
||||
VALUE bt = rb_funcall(exc, rb_intern("backtrace"), 0);
|
||||
rb_p(bt);
|
||||
VALUE msg = rb_funcall(exc, rb_intern("message"), 0);
|
||||
if (RSTRING_LEN(msg) < 256)
|
||||
showMsg(RSTRING_PTR(msg));
|
||||
else
|
||||
qDebug() << (RSTRING_PTR(msg));
|
||||
}
|
||||
|
||||
ruby_cleanup(0);
|
||||
|
||||
gState->rtData().rqTermAck = true;
|
||||
}
|
||||
|
||||
static void mriBindingTerminate()
|
||||
{
|
||||
rb_raise(rb_eSystemExit, " ");
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
** binding-types.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BINDINGTYPES_H
|
||||
#define BINDINGTYPES_H
|
||||
|
||||
#include "binding-util.h"
|
||||
|
||||
DECL_TYPE(Table);
|
||||
DECL_TYPE(Rect);
|
||||
DECL_TYPE(Color);
|
||||
DECL_TYPE(Tone);
|
||||
DECL_TYPE(Font);
|
||||
|
||||
DECL_TYPE(Bitmap);
|
||||
DECL_TYPE(Sprite);
|
||||
DECL_TYPE(Plane);
|
||||
DECL_TYPE(Viewport);
|
||||
DECL_TYPE(Tilemap);
|
||||
DECL_TYPE(Window);
|
||||
|
||||
#endif // BINDINGTYPES_H
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
** binding-util.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "binding-util.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "exception.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
void initType(rb_data_type_struct &type,
|
||||
const char *name,
|
||||
void (*freeInst)(void *))
|
||||
{
|
||||
type.wrap_struct_name = name;
|
||||
type.function.dmark = 0;
|
||||
type.function.dsize = 0;
|
||||
type.function.dfree = freeInst;
|
||||
type.function.reserved[0] =
|
||||
type.function.reserved[1] = 0;
|
||||
type.parent = 0;
|
||||
}
|
||||
|
||||
RbData *getRbData()
|
||||
{
|
||||
return static_cast<RbData*>(gState->bindingData());
|
||||
}
|
||||
|
||||
//enum RbException
|
||||
//{
|
||||
// RGSS = 0,
|
||||
// PHYSFS,
|
||||
// SDL,
|
||||
|
||||
// ErrnoENOENT,
|
||||
|
||||
// IOError,
|
||||
|
||||
// TypeError,
|
||||
// ArgumentError,
|
||||
|
||||
// RbExceptionsMax
|
||||
//};
|
||||
|
||||
struct
|
||||
{
|
||||
RbException id;
|
||||
const char *name;
|
||||
} static customExc[] =
|
||||
{
|
||||
{ RGSS, "RGSSError" },
|
||||
{ PHYSFS, "PHYSFSError" },
|
||||
{ SDL, "SDLError" }
|
||||
};
|
||||
|
||||
RbData::RbData()
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(customExc); ++i)
|
||||
exc[customExc[i].id] = rb_define_class(customExc[i].name, rb_eException);
|
||||
|
||||
exc[ErrnoENOENT] = rb_const_get(rb_const_get(rb_cObject, rb_intern("Errno")), rb_intern("ENOENT"));
|
||||
exc[IOError] = rb_eIOError;
|
||||
exc[TypeError] = rb_eTypeError;
|
||||
exc[ArgumentError] = rb_eArgError;
|
||||
}
|
||||
|
||||
RbData::~RbData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* Indexed with Exception::Type */
|
||||
static const RbException excToRbExc[] =
|
||||
{
|
||||
RGSS, /* RGSSError */
|
||||
ErrnoENOENT, /* NoFileError */
|
||||
IOError,
|
||||
|
||||
TypeError,
|
||||
ArgumentError,
|
||||
|
||||
PHYSFS, /* PHYSFSError */
|
||||
SDL /* SDLError */
|
||||
};
|
||||
|
||||
void raiseRbExc(const Exception &exc)
|
||||
{
|
||||
RbData *data = getRbData();
|
||||
VALUE excClass = data->exc[excToRbExc[exc.type]];
|
||||
|
||||
static char buffer[512];
|
||||
exc.snprintf(buffer, sizeof(buffer));
|
||||
rb_raise(excClass, buffer);
|
||||
}
|
||||
|
||||
int
|
||||
rb_get_args(int argc, VALUE *argv, const char *format, ...)
|
||||
{
|
||||
char c;
|
||||
VALUE *arg = argv;
|
||||
va_list ap;
|
||||
bool opt = false;
|
||||
int argI = 0;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
while ((c = *format++))
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '|' :
|
||||
break;
|
||||
default:
|
||||
// FIXME print num of needed args vs provided
|
||||
if (argc <= argI && !opt)
|
||||
rb_raise(rb_eArgError, "wrong number of arguments");
|
||||
break;
|
||||
}
|
||||
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'o' :
|
||||
{
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
VALUE *obj = va_arg(ap, VALUE*);
|
||||
|
||||
*obj = *arg++;
|
||||
++argI;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'S' :
|
||||
{
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
VALUE *str = va_arg(ap, VALUE*);
|
||||
VALUE tmp = *arg;
|
||||
|
||||
if (!rb_type(tmp) == RUBY_T_STRING)
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected string", argI);
|
||||
|
||||
*str = tmp;
|
||||
++argI;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's' :
|
||||
{
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
const char **s = va_arg(ap, const char**);
|
||||
int *len = va_arg(ap, int*);
|
||||
|
||||
VALUE tmp = *arg;
|
||||
|
||||
if (!rb_type(tmp) == RUBY_T_STRING)
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected string", argI);
|
||||
|
||||
*s = RSTRING_PTR(tmp);
|
||||
*len = RSTRING_LEN(tmp);
|
||||
++argI;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'z' :
|
||||
{
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
const char **s = va_arg(ap, const char**);
|
||||
|
||||
VALUE tmp = *arg++;
|
||||
|
||||
if (!rb_type(tmp) == RUBY_T_STRING)
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected string", argI);
|
||||
|
||||
*s = RSTRING_PTR(tmp);
|
||||
++argI;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f' :
|
||||
{
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
double *f = va_arg(ap, double*);
|
||||
VALUE fVal = *arg++;
|
||||
|
||||
switch (rb_type(fVal))
|
||||
{
|
||||
case RUBY_T_FLOAT :
|
||||
*f = rb_float_value(fVal);
|
||||
break;
|
||||
|
||||
case RUBY_T_FIXNUM :
|
||||
*f = rb_fix2int(fVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected float", argI);
|
||||
}
|
||||
|
||||
++argI;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i' :
|
||||
{
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
int *i = va_arg(ap, int*);
|
||||
VALUE iVal = *arg++;
|
||||
|
||||
switch (rb_type(iVal))
|
||||
{
|
||||
case RUBY_T_FLOAT :
|
||||
// FIXME check int range?
|
||||
*i = rb_num2long(iVal);
|
||||
break;
|
||||
|
||||
case RUBY_T_FIXNUM :
|
||||
*i = rb_fix2int(iVal);
|
||||
break;
|
||||
|
||||
default:
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected fixnum", argI);
|
||||
}
|
||||
|
||||
++argI;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'b' :
|
||||
{
|
||||
if (argI >= argc)
|
||||
break;
|
||||
|
||||
bool *b = va_arg(ap, bool*);
|
||||
VALUE bVal = *arg++;
|
||||
|
||||
switch (rb_type(bVal))
|
||||
{
|
||||
case RUBY_T_TRUE :
|
||||
*b = true;
|
||||
break;
|
||||
|
||||
case RUBY_T_FALSE :
|
||||
case RUBY_T_NIL :
|
||||
*b = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
rb_raise(rb_eTypeError, "Argument %d: Expected bool", argI);
|
||||
}
|
||||
|
||||
++argI;
|
||||
break;
|
||||
}
|
||||
|
||||
case '|' :
|
||||
opt = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
rb_raise(rb_eFatal, "invalid argument specifier %c", c);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME print num of needed args vs provided
|
||||
if (!c && argc > argI)
|
||||
rb_raise(rb_eArgError, "wrong number of arguments");
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return argI;
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
** binding-util.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BINDING_UTIL_H
|
||||
#define BINDING_UTIL_H
|
||||
|
||||
#include "./ruby/ruby.h"
|
||||
|
||||
#define PRIV_IV "priv"
|
||||
|
||||
enum RbException
|
||||
{
|
||||
RGSS = 0,
|
||||
PHYSFS,
|
||||
SDL,
|
||||
|
||||
ErrnoENOENT,
|
||||
|
||||
IOError,
|
||||
|
||||
TypeError,
|
||||
ArgumentError,
|
||||
|
||||
RbExceptionsMax
|
||||
};
|
||||
|
||||
struct RbData
|
||||
{
|
||||
VALUE exc[RbExceptionsMax];
|
||||
|
||||
RbData();
|
||||
~RbData();
|
||||
};
|
||||
|
||||
RbData *getRbData();
|
||||
|
||||
struct Exception;
|
||||
|
||||
void
|
||||
raiseRbExc(const Exception &exc);
|
||||
|
||||
#define DECL_TYPE(Klass) \
|
||||
extern rb_data_type_struct Klass##Type
|
||||
|
||||
#define DEF_TYPE(Klass) \
|
||||
rb_data_type_struct Klass##Type
|
||||
|
||||
void initType(rb_data_type_struct &type,
|
||||
const char *name,
|
||||
void (*freeInst)(void*));
|
||||
|
||||
template<class C>
|
||||
static inline void freeInstance(void *inst)
|
||||
{
|
||||
delete static_cast<C*>(inst);
|
||||
}
|
||||
|
||||
#define INIT_TYPE(Klass) initType(Klass##Type, #Klass, freeInstance<Klass>)
|
||||
|
||||
template<class C>
|
||||
static inline C *
|
||||
getPrivateData(VALUE self)
|
||||
{
|
||||
VALUE priv = rb_iv_get(self, PRIV_IV);
|
||||
return static_cast<C*>(RTYPEDDATA_DATA(priv));
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static inline C *
|
||||
getPrivateDataCheck(VALUE self, const rb_data_type_struct &type)
|
||||
{
|
||||
VALUE priv = rb_iv_get(self, PRIV_IV);
|
||||
void *obj = rb_check_typeddata(priv, &type);
|
||||
return static_cast<C*>(obj);
|
||||
}
|
||||
|
||||
static inline void
|
||||
setPrivateData(VALUE self, void *p, const rb_data_type_struct &type)
|
||||
{
|
||||
VALUE priv = rb_data_typed_object_alloc(rb_cData, p, &type);
|
||||
rb_iv_set(self, PRIV_IV, priv);
|
||||
}
|
||||
|
||||
inline VALUE
|
||||
wrapObject(void *p, const rb_data_type_struct &type)
|
||||
{
|
||||
VALUE klass = rb_const_get(rb_cObject, rb_intern(type.wrap_struct_name));
|
||||
VALUE obj = rb_obj_alloc(klass);
|
||||
|
||||
setPrivateData(obj, p, type);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline VALUE
|
||||
wrapProperty(VALUE self, void *prop, const char *iv,
|
||||
const rb_data_type_struct &type)
|
||||
{
|
||||
VALUE propObj = wrapObject(prop, type);
|
||||
|
||||
rb_iv_set(self, iv, propObj);
|
||||
|
||||
return propObj;
|
||||
}
|
||||
|
||||
inline void
|
||||
wrapNilProperty(VALUE self, const char *iv)
|
||||
{
|
||||
rb_iv_set(self, iv, Qnil);
|
||||
}
|
||||
|
||||
/* Implemented: oSszfib| */
|
||||
int
|
||||
rb_get_args(int argc, VALUE *argv, const char *format, ...);
|
||||
|
||||
typedef VALUE (*RubyMethod)(int argc, VALUE *argv, VALUE self);
|
||||
|
||||
static inline void
|
||||
_rb_define_method(VALUE klass, const char *name, RubyMethod func)
|
||||
{
|
||||
rb_define_method(klass, name, RUBY_METHOD_FUNC(func), -1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rb_define_class_method(VALUE klass, const char *name, RubyMethod func)
|
||||
{
|
||||
rb_define_singleton_method(klass, name, RUBY_METHOD_FUNC(func), -1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_rb_define_module_function(VALUE module, const char *name, RubyMethod func)
|
||||
{
|
||||
rb_define_module_function(module, name, RUBY_METHOD_FUNC(func), -1);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static inline VALUE
|
||||
objectLoad(int argc, VALUE *argv, VALUE self, rb_data_type_struct &type)
|
||||
{
|
||||
const char *data;
|
||||
int dataLen;
|
||||
rb_get_args(argc, argv, "s", &data, &dataLen);
|
||||
|
||||
VALUE obj = rb_obj_alloc(self);
|
||||
|
||||
C *c = C::deserialize(data, dataLen);
|
||||
|
||||
setPrivateData(obj, c, type);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
rb_bool_new(bool value)
|
||||
{
|
||||
return value ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
#define RB_METHOD(name) \
|
||||
static VALUE name(int argc, VALUE *argv, VALUE self)
|
||||
|
||||
#define RB_UNUSED_PARAM \
|
||||
{ (void) argc; (void) argv; (void) self; }
|
||||
|
||||
#define MARSH_LOAD_FUN(Typ) \
|
||||
RB_METHOD(Typ##Load) \
|
||||
{ \
|
||||
return objectLoad<Typ>(argc, argv, self, Typ##Type); \
|
||||
}
|
||||
|
||||
#define CLONE_FUNC(Klass) \
|
||||
static mrb_value \
|
||||
Klass##Clone(mrb_state *mrb, mrb_value self) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); \
|
||||
mrb_value dupObj = mrb_obj_clone(mrb, self); \
|
||||
Klass *dupK = new Klass(*k); \
|
||||
setPrivateData(mrb, dupObj, dupK, Klass##Type); \
|
||||
return dupObj; \
|
||||
}
|
||||
|
||||
#define CLONE_FUN(Klass) \
|
||||
RB_METHOD(Klass##Clone) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM \
|
||||
Klass *k = getPrivateData<Klass>(self); \
|
||||
VALUE dupObj = rb_obj_clone(self); \
|
||||
Klass *dupK = new Klass(*k); \
|
||||
setPrivateData(dupObj, dupK, Klass##Type); \
|
||||
return dupObj; \
|
||||
}
|
||||
|
||||
/* If we're not binding a disposable class,
|
||||
* we want to #undef DEF_PROP_CHK_DISP */
|
||||
#define DEF_PROP_CHK_DISP \
|
||||
checkDisposed(k, DISP_CLASS_NAME);
|
||||
|
||||
#define DEF_PROP_OBJ(Klass, PropKlass, PropName, prop_iv) \
|
||||
RB_METHOD(Klass##Get##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
Klass *k = getPrivateData<Klass>(self); (void) k; \
|
||||
DEF_PROP_CHK_DISP \
|
||||
return rb_iv_get(self, prop_iv); \
|
||||
} \
|
||||
RB_METHOD(Klass##Set##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(self); \
|
||||
VALUE propObj; \
|
||||
PropKlass *prop; \
|
||||
rb_get_args(argc, argv, "o", &propObj); \
|
||||
prop = getPrivateDataCheck<PropKlass>(propObj, PropKlass##Type); \
|
||||
GUARD_EXC( k->set##PropName(prop); ) \
|
||||
rb_iv_set(self, prop_iv, propObj); \
|
||||
return propObj; \
|
||||
}
|
||||
|
||||
/* Object property with allowed NIL */
|
||||
#define DEF_PROP_OBJ_NIL(Klass, PropKlass, PropName, prop_iv) \
|
||||
RB_METHOD(Klass##Get##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
Klass *k = getPrivateData<Klass>(self); (void) k; \
|
||||
DEF_PROP_CHK_DISP \
|
||||
return rb_iv_get(self, prop_iv); \
|
||||
} \
|
||||
RB_METHOD(Klass##Set##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
Klass *k = getPrivateData<Klass>(self); \
|
||||
VALUE propObj; \
|
||||
PropKlass *prop; \
|
||||
rb_get_args(argc, argv, "o", &propObj); \
|
||||
if (rb_type(propObj) == RUBY_T_NIL) \
|
||||
prop = 0; \
|
||||
else \
|
||||
prop = getPrivateDataCheck<PropKlass>(propObj, PropKlass##Type); \
|
||||
GUARD_EXC( k->set##PropName(prop); ) \
|
||||
rb_iv_set(self, prop_iv, propObj); \
|
||||
return propObj; \
|
||||
}
|
||||
|
||||
#define DEF_PROP(Klass, type, PropName, param_t_s, value_fun) \
|
||||
RB_METHOD(Klass##Get##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
Klass *k = getPrivateData<Klass>(self); \
|
||||
DEF_PROP_CHK_DISP \
|
||||
return value_fun(k->get##PropName()); \
|
||||
} \
|
||||
RB_METHOD(Klass##Set##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(self); \
|
||||
type value; \
|
||||
rb_get_args(argc, argv, param_t_s, &value); \
|
||||
GUARD_EXC( k->set##PropName(value); ) \
|
||||
return value_fun(value); \
|
||||
}
|
||||
|
||||
#define DEF_PROP_I(Klass, PropName) \
|
||||
DEF_PROP(Klass, int, PropName, "i", rb_fix_new)
|
||||
|
||||
#define DEF_PROP_F(Klass, PropName) \
|
||||
DEF_PROP(Klass, double, PropName, "f", rb_float_new)
|
||||
|
||||
#define DEF_PROP_B(Klass, PropName) \
|
||||
DEF_PROP(Klass, bool, PropName, "b", rb_bool_new)
|
||||
|
||||
#define INIT_PROP_BIND(Klass, PropName, prop_name_s) \
|
||||
{ \
|
||||
_rb_define_method(klass, prop_name_s, Klass##Get##PropName); \
|
||||
_rb_define_method(klass, prop_name_s "=", Klass##Set##PropName); \
|
||||
}
|
||||
|
||||
#define GUARD_EXC(exp) \
|
||||
{ try { exp } catch (const Exception &exc) { raiseRbExc(exc); } }
|
||||
|
||||
|
||||
#endif // BINDING_UTIL_H
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
** bitmap-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "font.h"
|
||||
#include "exception.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define DISP_CLASS_NAME "bitmap"
|
||||
|
||||
DEF_TYPE(Bitmap);
|
||||
|
||||
RB_METHOD(bitmapInitialize)
|
||||
{
|
||||
Bitmap *b = 0;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
char *filename;
|
||||
rb_get_args(argc, argv, "z", &filename);
|
||||
|
||||
GUARD_EXC( b = new Bitmap(filename); )
|
||||
}
|
||||
else
|
||||
{
|
||||
int width, height;
|
||||
rb_get_args(argc, argv, "ii", &width, &height);
|
||||
|
||||
b = new Bitmap(width, height);
|
||||
}
|
||||
|
||||
setPrivateData(self, b, BitmapType);
|
||||
|
||||
/* Wrap properties */
|
||||
Font *font = new Font();
|
||||
b->setFont(font);
|
||||
font->setColor(new Color(*font->getColor()));
|
||||
|
||||
VALUE fontProp = wrapProperty(self, font, "font", FontType);
|
||||
wrapProperty(fontProp, font->getColor(), "color", ColorType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapWidth)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
int value = 0;
|
||||
GUARD_EXC( value = b->width(); );
|
||||
|
||||
return INT2FIX(value);
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapHeight)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
int value = 0;
|
||||
GUARD_EXC( value = b->height(); );
|
||||
|
||||
return INT2FIX(value);
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapRect)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
IntRect rect;
|
||||
GUARD_EXC( rect = b->rect(); );
|
||||
|
||||
Rect *r = new Rect(rect);
|
||||
|
||||
return wrapObject(r, RectType);
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapBlt)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
int x, y;
|
||||
VALUE srcObj;
|
||||
VALUE srcRectObj;
|
||||
int opacity = 255;
|
||||
|
||||
Bitmap *src;
|
||||
Rect *srcRect;
|
||||
|
||||
rb_get_args(argc, argv, "iioo|i", &x, &y, &srcObj, &srcRectObj, &opacity);
|
||||
|
||||
src = getPrivateDataCheck<Bitmap>(srcObj, BitmapType);
|
||||
srcRect = getPrivateDataCheck<Rect>(srcRectObj, RectType);
|
||||
|
||||
GUARD_EXC( b->blt(x, y, *src, srcRect->toIntRect(), opacity); );
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapStretchBlt)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
VALUE destRectObj;
|
||||
VALUE srcObj;
|
||||
VALUE srcRectObj;
|
||||
int opacity = 255;
|
||||
|
||||
Bitmap *src;
|
||||
Rect *destRect, *srcRect;
|
||||
|
||||
rb_get_args(argc, argv, "ooo|i", &destRectObj, &srcObj, &srcRectObj);
|
||||
|
||||
src = getPrivateDataCheck<Bitmap>(srcObj, BitmapType);
|
||||
destRect = getPrivateDataCheck<Rect>(destRectObj, RectType);
|
||||
srcRect = getPrivateDataCheck<Rect>(srcRectObj, RectType);
|
||||
|
||||
GUARD_EXC( b->stretchBlt(destRect->toIntRect(), *src, srcRect->toIntRect(), opacity); );
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapFillRect)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
VALUE colorObj;
|
||||
Color *color;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
VALUE rectObj;
|
||||
Rect *rect;
|
||||
|
||||
rb_get_args(argc, argv, "oo", &rectObj, &colorObj);
|
||||
|
||||
rect = getPrivateDataCheck<Rect>(rectObj, RectType);
|
||||
color = getPrivateDataCheck<Color>(colorObj, ColorType);
|
||||
|
||||
GUARD_EXC( b->fillRect(rect->toIntRect(), color->norm); );
|
||||
}
|
||||
else
|
||||
{
|
||||
int x, y, width, height;
|
||||
|
||||
rb_get_args(argc, argv, "iiiio", &x, &y, &width, &height, &colorObj);
|
||||
|
||||
color = getPrivateDataCheck<Color>(colorObj, ColorType);
|
||||
|
||||
GUARD_EXC( b->fillRect(x, y, width, height, color->norm); );
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapClear)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
GUARD_EXC( b->clear(); )
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapGetPixel)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
int x, y;
|
||||
|
||||
rb_get_args(argc, argv, "ii", &x, &y);
|
||||
|
||||
GUARD_EXC(
|
||||
if (x < 0 || y < 0 || x >= b->width() || y >= b->height())
|
||||
return Qnil;
|
||||
)
|
||||
|
||||
Vec4 value;
|
||||
GUARD_EXC( value = b->getPixel(x, y); );
|
||||
|
||||
Color *color = new Color(value);
|
||||
|
||||
return wrapObject(color, ColorType);
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapSetPixel)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
int x, y;
|
||||
VALUE colorObj;
|
||||
|
||||
Color *color;
|
||||
|
||||
rb_get_args(argc, argv, "iio", &x, &y, &colorObj);
|
||||
|
||||
color = getPrivateDataCheck<Color>(colorObj, ColorType);
|
||||
|
||||
GUARD_EXC( b->setPixel(x, y, color->norm); );
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapHueChange)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
int hue;
|
||||
|
||||
rb_get_args(argc, argv, "i", &hue);
|
||||
|
||||
GUARD_EXC( b->hueChange(hue); );
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapDrawText)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
const char *str;
|
||||
int align = Bitmap::Left;
|
||||
|
||||
if (argc == 2 || argc == 3)
|
||||
{
|
||||
VALUE rectObj;
|
||||
Rect *rect;
|
||||
|
||||
rb_get_args(argc, argv, "oz|i", &rectObj, &str, &align);
|
||||
|
||||
rect = getPrivateDataCheck<Rect>(rectObj, RectType);
|
||||
|
||||
GUARD_EXC( b->drawText(rect->toIntRect(), str, align); );
|
||||
}
|
||||
else
|
||||
{
|
||||
int x, y, width, height;
|
||||
|
||||
rb_get_args(argc, argv, "iiiiz|i", &x, &y, &width, &height, &str, &align);
|
||||
|
||||
GUARD_EXC( b->drawText(x, y, width, height, str, align); );
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(bitmapTextSize)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(self);
|
||||
|
||||
const char *str;
|
||||
|
||||
rb_get_args(argc, argv, "z", &str);
|
||||
|
||||
IntRect value;
|
||||
GUARD_EXC( value = b->textSize(str); );
|
||||
|
||||
Rect *rect = new Rect(value);
|
||||
|
||||
return wrapObject(rect, RectType);
|
||||
}
|
||||
|
||||
DEF_PROP_OBJ(Bitmap, Font, Font, "font")
|
||||
|
||||
CLONE_FUN(Bitmap)
|
||||
|
||||
|
||||
void
|
||||
bitmapBindingInit()
|
||||
{
|
||||
INIT_TYPE(Bitmap);
|
||||
|
||||
VALUE klass = rb_define_class("Bitmap", rb_cObject);
|
||||
|
||||
disposableBindingInit<Bitmap>(klass);
|
||||
|
||||
_rb_define_method(klass, "initialize", bitmapInitialize);
|
||||
|
||||
_rb_define_method(klass, "width", bitmapWidth);
|
||||
_rb_define_method(klass, "height", bitmapHeight);
|
||||
_rb_define_method(klass, "rect", bitmapRect);
|
||||
_rb_define_method(klass, "blt", bitmapBlt);
|
||||
_rb_define_method(klass, "stretch_blt", bitmapStretchBlt);
|
||||
_rb_define_method(klass, "fill_rect", bitmapFillRect);
|
||||
_rb_define_method(klass, "clear", bitmapClear);
|
||||
_rb_define_method(klass, "get_pixel", bitmapGetPixel);
|
||||
_rb_define_method(klass, "set_pixel", bitmapSetPixel);
|
||||
_rb_define_method(klass, "hue_change", bitmapHueChange);
|
||||
_rb_define_method(klass, "draw_text", bitmapDrawText);
|
||||
_rb_define_method(klass, "text_size", bitmapTextSize);
|
||||
|
||||
INIT_PROP_BIND(Bitmap, Font, "font");
|
||||
|
||||
_rb_define_method(klass, "clone", BitmapClone);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
** disposable-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DISPOSABLEBINDING_H
|
||||
#define DISPOSABLEBINDING_H
|
||||
|
||||
#include "disposable.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(disposableDispose)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Disposable *d = getPrivateData<C>(self);
|
||||
|
||||
d->dispose();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(disposableIsDisposed)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Disposable *d = getPrivateData<C>(self);
|
||||
|
||||
return rb_bool_new(d->isDisposed());
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static void disposableBindingInit(VALUE klass)
|
||||
{
|
||||
_rb_define_method(klass, "dispose", disposableDispose<C>);
|
||||
_rb_define_method(klass, "disposed?", disposableIsDisposed<C>);
|
||||
}
|
||||
|
||||
inline void checkDisposed(Disposable *d, const char *klassName)
|
||||
{
|
||||
RbData *data = getRbData(); (void) data;
|
||||
|
||||
if (d->isDisposed())
|
||||
rb_raise(getRbData()->exc[RGSS], "disposed %s", klassName);
|
||||
}
|
||||
|
||||
#endif // DISPOSABLEBINDING_H
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
** etc-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "etc.h"
|
||||
#include "binding-util.h"
|
||||
#include "serializable-binding.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
DEF_TYPE(Color);
|
||||
DEF_TYPE(Tone);
|
||||
DEF_TYPE(Rect);
|
||||
|
||||
#define ATTR_RW(Klass, Attr, arg_type, arg_t_s, value_fun) \
|
||||
RB_METHOD(Klass##Get##Attr) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM \
|
||||
Klass *p = getPrivateData<Klass>(self); \
|
||||
return value_fun(p->get##Attr()); \
|
||||
} \
|
||||
RB_METHOD(Klass##Set##Attr) \
|
||||
{ \
|
||||
Klass *p = getPrivateData<Klass>(self); \
|
||||
arg_type arg; \
|
||||
rb_get_args(argc, argv, arg_t_s, &arg); \
|
||||
p->set##Attr(arg); \
|
||||
return *argv; \
|
||||
}
|
||||
|
||||
#define ATTR_DOUBLE_RW(Klass, Attr) ATTR_RW(Klass, Attr, double, "f", rb_float_new)
|
||||
#define ATTR_INT_RW(Klass, Attr) ATTR_RW(Klass, Attr, int, "i", rb_fix_new)
|
||||
|
||||
ATTR_DOUBLE_RW(Color, Red)
|
||||
ATTR_DOUBLE_RW(Color, Green)
|
||||
ATTR_DOUBLE_RW(Color, Blue)
|
||||
ATTR_DOUBLE_RW(Color, Alpha)
|
||||
|
||||
ATTR_DOUBLE_RW(Tone, Red)
|
||||
ATTR_DOUBLE_RW(Tone, Green)
|
||||
ATTR_DOUBLE_RW(Tone, Blue)
|
||||
ATTR_DOUBLE_RW(Tone, Gray)
|
||||
|
||||
ATTR_INT_RW(Rect, X)
|
||||
ATTR_INT_RW(Rect, Y)
|
||||
ATTR_INT_RW(Rect, Width)
|
||||
ATTR_INT_RW(Rect, Height)
|
||||
|
||||
#define EQUAL_FUN(Klass) \
|
||||
RB_METHOD(Klass##Equal) \
|
||||
{ \
|
||||
Klass *p = getPrivateData<Klass>(self); \
|
||||
VALUE otherObj; \
|
||||
Klass *other; \
|
||||
rb_get_args(argc, argv, "o", &otherObj); \
|
||||
other = getPrivateDataCheck<Klass>(otherObj, Klass##Type); \
|
||||
return rb_bool_new(*p == *other); \
|
||||
}
|
||||
|
||||
EQUAL_FUN(Color)
|
||||
EQUAL_FUN(Tone)
|
||||
EQUAL_FUN(Rect)
|
||||
|
||||
#define INIT_FUN(Klass, param_type, param_t_s, last_param_def) \
|
||||
RB_METHOD(Klass##Initialize) \
|
||||
{ \
|
||||
param_type p1, p2, p3, p4 = last_param_def; \
|
||||
rb_get_args(argc, argv, param_t_s, &p1, &p2, &p3, &p4); \
|
||||
Klass *k = new Klass(p1, p2, p3, p4); \
|
||||
setPrivateData(self, k, Klass##Type); \
|
||||
return self; \
|
||||
}
|
||||
|
||||
INIT_FUN(Color, double, "fff|f", 255)
|
||||
INIT_FUN(Tone, double, "fff|f", 0)
|
||||
INIT_FUN(Rect, int, "iiii", 0)
|
||||
|
||||
#define SET_FUN(Klass, param_type, param_t_s, last_param_def) \
|
||||
RB_METHOD(Klass##Set) \
|
||||
{ \
|
||||
param_type p1, p2, p3, p4 = last_param_def; \
|
||||
rb_get_args(argc, argv, param_t_s, &p1, &p2, &p3, &p4); \
|
||||
Klass *k = getPrivateData<Klass>(self); \
|
||||
k->set(p1, p2, p3, p4); \
|
||||
return self; \
|
||||
}
|
||||
|
||||
SET_FUN(Color, double, "fff|f", 255)
|
||||
SET_FUN(Tone, double, "fff|f", 0)
|
||||
SET_FUN(Rect, int, "iiii", 0)
|
||||
|
||||
RB_METHOD(rectEmpty)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
Rect *r = getPrivateData<Rect>(self);
|
||||
r->empty();
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(ColorStringify)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Color *c = getPrivateData<Color>(self);
|
||||
|
||||
return rb_sprintf("(%f, %f, %f, %f)",
|
||||
c->red, c->green, c->blue, c->alpha);
|
||||
}
|
||||
|
||||
RB_METHOD(ToneStringify)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Tone *t = getPrivateData<Tone>(self);
|
||||
|
||||
return rb_sprintf("(%f, %f, %f, %f)",
|
||||
t->red, t->green, t->blue, t->gray);
|
||||
}
|
||||
|
||||
RB_METHOD(RectStringify)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Rect *r = getPrivateData<Rect>(self);
|
||||
|
||||
return rb_sprintf("(%d, %d, %d, %d)",
|
||||
r->x, r->y, r->width, r->height);
|
||||
}
|
||||
|
||||
MARSH_LOAD_FUN(Color)
|
||||
MARSH_LOAD_FUN(Tone)
|
||||
MARSH_LOAD_FUN(Rect)
|
||||
|
||||
CLONE_FUN(Tone)
|
||||
CLONE_FUN(Color)
|
||||
CLONE_FUN(Rect)
|
||||
|
||||
#define INIT_BIND(Klass) \
|
||||
{ \
|
||||
INIT_TYPE(Klass); \
|
||||
klass = rb_define_class(#Klass, rb_cObject); \
|
||||
rb_define_class_method(klass, "_load", Klass##Load); \
|
||||
serializableBindingInit<Klass>(klass); \
|
||||
_rb_define_method(klass, "initialize", Klass##Initialize); \
|
||||
_rb_define_method(klass, "set", Klass##Set); \
|
||||
_rb_define_method(klass, "clone", Klass##Clone); \
|
||||
_rb_define_method(klass, "==", Klass##Equal); \
|
||||
_rb_define_method(klass, "to_s", Klass##Stringify); \
|
||||
_rb_define_method(klass, "inspect", Klass##Stringify); \
|
||||
}
|
||||
|
||||
#define MRB_ATTR_R(Class, attr) mrb_define_method(mrb, klass, #attr, Class##Get_##attr, MRB_ARGS_NONE())
|
||||
#define MRB_ATTR_W(Class, attr) mrb_define_method(mrb, klass, #attr "=", Class##Set_##attr, MRB_ARGS_REQ(1))
|
||||
#define MRB_ATTR_RW(Class, attr) { MRB_ATTR_R(Class, attr); MRB_ATTR_W(Class, attr); }
|
||||
|
||||
#define RB_ATTR_R(Klass, Attr, attr) _rb_define_method(klass, #attr, Klass##Get##Attr)
|
||||
#define RB_ATTR_W(Klass, Attr, attr) _rb_define_method(klass, #attr "=", Klass##Set##Attr)
|
||||
#define RB_ATTR_RW(Klass, Attr, attr) \
|
||||
{ RB_ATTR_R(Klass, Attr, attr); RB_ATTR_W(Klass, Attr, attr); }
|
||||
|
||||
void
|
||||
etcBindingInit()
|
||||
{
|
||||
VALUE klass;
|
||||
|
||||
INIT_BIND(Color);
|
||||
|
||||
RB_ATTR_RW(Color, Red, red);
|
||||
RB_ATTR_RW(Color, Green, green);
|
||||
RB_ATTR_RW(Color, Blue, blue);
|
||||
RB_ATTR_RW(Color, Alpha, alpha);
|
||||
|
||||
INIT_BIND(Tone);
|
||||
|
||||
RB_ATTR_RW(Tone, Red, red);
|
||||
RB_ATTR_RW(Tone, Green, green);
|
||||
RB_ATTR_RW(Tone, Blue, blue);
|
||||
RB_ATTR_RW(Tone, Gray, gray);
|
||||
|
||||
INIT_BIND(Rect);
|
||||
|
||||
RB_ATTR_RW(Rect, X, x);
|
||||
RB_ATTR_RW(Rect, Y, y);
|
||||
RB_ATTR_RW(Rect, Width, width);
|
||||
RB_ATTR_RW(Rect, Height, height);
|
||||
_rb_define_method(klass, "empty", rectEmpty);
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
** filesystem-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "binding-util.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
DEF_TYPE(FileInt);
|
||||
|
||||
static VALUE
|
||||
fileIntForPath(const char *path)
|
||||
{
|
||||
SDL_RWops *ops = SDL_AllocRW();
|
||||
gState->fileSystem().openRead(*ops, path);
|
||||
|
||||
VALUE klass = rb_const_get(rb_cObject, rb_intern("FileInt"));
|
||||
|
||||
VALUE obj = rb_obj_alloc(klass);
|
||||
|
||||
setPrivateData(obj, ops, FileIntType);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
RB_METHOD(fileIntRead)
|
||||
{
|
||||
|
||||
int length = -1;
|
||||
rb_get_args(argc, argv, "i", &length);
|
||||
|
||||
SDL_RWops *ops = getPrivateData<SDL_RWops>(self);
|
||||
|
||||
if (length == -1)
|
||||
{
|
||||
Sint64 cur = SDL_RWtell(ops);
|
||||
Sint64 end = SDL_RWseek(ops, 0, SEEK_END);
|
||||
length = end - cur;
|
||||
SDL_RWseek(ops, cur, SEEK_SET);
|
||||
}
|
||||
|
||||
if (length == 0)
|
||||
return Qnil;
|
||||
|
||||
VALUE data = rb_str_new(0, length);
|
||||
|
||||
SDL_RWread(ops, RSTRING_PTR(data), 1, length);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
RB_METHOD(fileIntClose)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
SDL_RWops *ops = getPrivateData<SDL_RWops>(self);
|
||||
SDL_RWclose(ops);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(fileIntGetByte)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
SDL_RWops *ops = getPrivateData<SDL_RWops>(self);
|
||||
|
||||
unsigned char byte;
|
||||
size_t result = SDL_RWread(ops, &byte, 1, 1);
|
||||
|
||||
return (result == 1) ? rb_fix_new(byte) : Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(fileIntBinmode)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static void
|
||||
fileIntFreeInstance(void *inst)
|
||||
{
|
||||
SDL_RWops *ops = static_cast<SDL_RWops*>(inst);
|
||||
|
||||
SDL_RWclose(ops);
|
||||
SDL_FreeRW(ops);
|
||||
}
|
||||
|
||||
VALUE
|
||||
kernelLoadDataInt(const char *filename)
|
||||
{
|
||||
rb_gc_start();
|
||||
|
||||
VALUE port = fileIntForPath(filename);
|
||||
|
||||
VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
|
||||
|
||||
VALUE result = rb_funcall(marsh, rb_intern("load"), 1, port);
|
||||
|
||||
rb_funcall(port, rb_intern("close"), 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RB_METHOD(kernelLoadData)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
const char *filename;
|
||||
rb_get_args(argc, argv, "z", &filename);
|
||||
|
||||
return kernelLoadDataInt(filename);
|
||||
}
|
||||
|
||||
RB_METHOD(kernelSaveData)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE obj;
|
||||
VALUE filename;
|
||||
|
||||
rb_get_args(argc, argv, "oS", &obj, &filename);
|
||||
|
||||
VALUE file = rb_funcall(rb_cFile, rb_intern("open"), 2, filename, rb_str_new_cstr("w"));
|
||||
|
||||
VALUE marsh = rb_const_get(rb_cObject, rb_intern("Marshal"));
|
||||
|
||||
rb_funcall(marsh, rb_intern("dump"), 2, obj, file);
|
||||
|
||||
rb_funcall(file, rb_intern("close"), 0);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
void
|
||||
fileIntBindingInit()
|
||||
{
|
||||
initType(FileIntType, "FileInt", fileIntFreeInstance);
|
||||
|
||||
VALUE klass = rb_define_class("FileInt", rb_cIO);
|
||||
|
||||
_rb_define_method(klass, "read", fileIntRead);
|
||||
// _rb_define_method(klass, "eof?", fileIntIsEof);
|
||||
// _rb_define_method(klass, "pos", fileIntGetPos);
|
||||
// _rb_define_method(klass, "pos=", fileIntSetPos);
|
||||
_rb_define_method(klass, "getbyte", fileIntGetByte);
|
||||
_rb_define_method(klass, "binmode", fileIntBinmode);
|
||||
_rb_define_method(klass, "close", fileIntClose);
|
||||
|
||||
_rb_define_module_function(rb_mKernel, "load_data", kernelLoadData);
|
||||
_rb_define_module_function(rb_mKernel, "save_data", kernelSaveData);
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
** flashable-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FLASHABLEBINDING_H
|
||||
#define FLASHABLEBINDING_H
|
||||
|
||||
#include "flashable.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(flashableFlash)
|
||||
{
|
||||
Flashable *f = getPrivateData<C>(self);
|
||||
|
||||
VALUE colorObj;
|
||||
int duration;
|
||||
|
||||
Color *color;
|
||||
|
||||
rb_get_args(argc, argv, "oi", &colorObj, &duration);
|
||||
|
||||
if (rb_type(colorObj) == RUBY_T_NIL)
|
||||
{
|
||||
f->flash(0, duration);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
color = getPrivateDataCheck<Color>(colorObj, ColorType);
|
||||
|
||||
f->flash(&color->norm, duration);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(flashableUpdate)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Flashable *f = getPrivateData<C>(self);
|
||||
|
||||
f->update();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static void flashableBindingInit(VALUE klass)
|
||||
{
|
||||
_rb_define_method(klass, "flash", flashableFlash<C>);
|
||||
_rb_define_method(klass, "update", flashableUpdate<C>);
|
||||
}
|
||||
|
||||
#endif // FLASHABLEBINDING_H
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
** font-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "font.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
#include "exception.h"
|
||||
|
||||
DEF_TYPE(Font);
|
||||
|
||||
RB_METHOD(fontDoesExist)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
const char *name;
|
||||
rb_get_args(argc, argv, "z", &name);
|
||||
|
||||
return rb_bool_new(Font::doesExist(name));
|
||||
}
|
||||
|
||||
RB_METHOD(fontInitialize)
|
||||
{
|
||||
const char *name = 0;
|
||||
int size = 0;
|
||||
|
||||
rb_get_args(argc, argv, "|zi", &name, &size);
|
||||
|
||||
Font *f = new Font(name, size);
|
||||
|
||||
setPrivateData(self, f, FontType);
|
||||
|
||||
/* Wrap property objects */
|
||||
f->setColor(new Color(*f->getColor()));
|
||||
wrapProperty(self, f->getColor(), "color", ColorType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(FontGetName)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Font *f = getPrivateData<Font>(self);
|
||||
|
||||
return rb_str_new_cstr(f->getName());
|
||||
}
|
||||
|
||||
RB_METHOD(FontSetName)
|
||||
{
|
||||
Font *f = getPrivateData<Font>(self);
|
||||
|
||||
VALUE name;
|
||||
rb_get_args(argc, argv, "S", &name);
|
||||
|
||||
f->setName(RSTRING_PTR(name));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
#undef DEF_PROP_CHK_DISP
|
||||
#define DEF_PROP_CHK_DISP
|
||||
|
||||
DEF_PROP_I(Font, Size)
|
||||
DEF_PROP_B(Font, Bold)
|
||||
DEF_PROP_B(Font, Italic)
|
||||
DEF_PROP_OBJ(Font, Color, Color, "color")
|
||||
|
||||
#define DEF_KLASS_PROP(Klass, type, PropName, param_t_s, value_fun) \
|
||||
RB_METHOD(Klass##Get##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
return value_fun(Klass::get##PropName()); \
|
||||
} \
|
||||
RB_METHOD(Klass##Set##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
type value; \
|
||||
rb_get_args(argc, argv, param_t_s, &value); \
|
||||
Klass::set##PropName(value); \
|
||||
return value_fun(value); \
|
||||
}
|
||||
|
||||
DEF_KLASS_PROP(Font, int, DefaultSize, "i", rb_fix_new)
|
||||
DEF_KLASS_PROP(Font, bool, DefaultBold, "b", rb_bool_new)
|
||||
DEF_KLASS_PROP(Font, bool, DefaultItalic, "b", rb_bool_new)
|
||||
|
||||
RB_METHOD(FontGetDefaultName)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
return rb_str_new_cstr(Font::getDefaultName());
|
||||
}
|
||||
|
||||
RB_METHOD(FontSetDefaultName)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
VALUE nameObj;
|
||||
rb_get_args(argc, argv, "S", &nameObj);
|
||||
|
||||
Font::setDefaultName(RSTRING_PTR(nameObj));
|
||||
|
||||
return nameObj;
|
||||
}
|
||||
|
||||
RB_METHOD(FontGetDefaultColor)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
return rb_iv_get(self, "default_color");
|
||||
}
|
||||
|
||||
|
||||
RB_METHOD(FontSetDefaultColor)
|
||||
{
|
||||
VALUE colorObj;
|
||||
rb_get_args(argc, argv, "o", &colorObj);
|
||||
|
||||
Color *c = getPrivateDataCheck<Color>(colorObj, ColorType);
|
||||
|
||||
Font::setDefaultColor(c);
|
||||
rb_iv_set(self, "default_color", colorObj);
|
||||
|
||||
return colorObj;
|
||||
}
|
||||
|
||||
#define INIT_KLASS_PROP_BIND(Klass, PropName, prop_name_s) \
|
||||
{ \
|
||||
rb_define_class_method(klass, prop_name_s, Klass##Get##PropName); \
|
||||
rb_define_class_method(klass, prop_name_s "=", Klass##Set##PropName); \
|
||||
}
|
||||
|
||||
void
|
||||
fontBindingInit()
|
||||
{
|
||||
INIT_TYPE(Font);
|
||||
|
||||
VALUE klass = rb_define_class("Font", rb_cObject);
|
||||
|
||||
Font::setDefaultColor(new Color(*Font::getDefaultColor()));
|
||||
wrapProperty(klass, Font::getDefaultColor(), "default_color", ColorType);
|
||||
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultName, "default_name");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultSize, "default_size");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultBold, "default_bold");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultItalic, "default_italic");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultColor, "default_color");
|
||||
|
||||
rb_define_class_method(klass, "exist?", fontDoesExist);
|
||||
|
||||
_rb_define_method(klass, "initialize", fontInitialize);
|
||||
|
||||
INIT_PROP_BIND(Font, Name, "name");
|
||||
INIT_PROP_BIND(Font, Size, "size");
|
||||
INIT_PROP_BIND(Font, Bold, "bold");
|
||||
INIT_PROP_BIND(Font, Italic, "italic");
|
||||
INIT_PROP_BIND(Font, Color, "color");
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
** graphics-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "graphics.h"
|
||||
#include "globalstate.h"
|
||||
#include "binding-util.h"
|
||||
#include "exception.h"
|
||||
|
||||
RB_METHOD(graphicsUpdate)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
gState->graphics().update();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(graphicsFreeze)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
gState->graphics().freeze();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(graphicsTransition)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
int duration = 8;
|
||||
const char *filename = 0;
|
||||
int vague = 40;
|
||||
|
||||
rb_get_args(argc, argv, "|izi", &duration, &filename, &vague);
|
||||
|
||||
GUARD_EXC( gState->graphics().transition(duration, filename, vague); )
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(graphicsFrameReset)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
gState->graphics().frameReset();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#define DEF_GRA_PROP_I(PropName) \
|
||||
RB_METHOD(graphics##Get##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
return rb_fix_new(gState->graphics().get##PropName()); \
|
||||
} \
|
||||
RB_METHOD(graphics##Set##PropName) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM; \
|
||||
int value; \
|
||||
rb_get_args(argc, argv, "i", &value); \
|
||||
gState->graphics().set##PropName(value); \
|
||||
return rb_fix_new(value); \
|
||||
}
|
||||
|
||||
DEF_GRA_PROP_I(FrameRate)
|
||||
DEF_GRA_PROP_I(FrameCount)
|
||||
|
||||
RB_METHOD(graphicsGetFullscreen)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
return rb_bool_new(gState->graphics().getFullscreen());
|
||||
}
|
||||
|
||||
RB_METHOD(graphicsSetFullscreen)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
bool mode;
|
||||
rb_get_args(argc, argv, "b", &mode);
|
||||
|
||||
gState->graphics().setFullscreen(mode);
|
||||
|
||||
return rb_bool_new(mode);
|
||||
}
|
||||
|
||||
#define INIT_GRA_PROP_BIND(PropName, prop_name_s) \
|
||||
{ \
|
||||
_rb_define_module_function(module, prop_name_s, graphics##Get##PropName); \
|
||||
_rb_define_module_function(module, prop_name_s "=", graphics##Set##PropName); \
|
||||
}
|
||||
|
||||
void graphicsBindingInit()
|
||||
{
|
||||
VALUE module = rb_define_module("Graphics");
|
||||
|
||||
_rb_define_module_function(module, "update", graphicsUpdate);
|
||||
_rb_define_module_function(module, "freeze", graphicsFreeze);
|
||||
_rb_define_module_function(module, "transition", graphicsTransition);
|
||||
_rb_define_module_function(module, "frame_reset", graphicsFrameReset);
|
||||
|
||||
INIT_GRA_PROP_BIND( FrameRate, "frame_rate" );
|
||||
INIT_GRA_PROP_BIND( FrameCount, "frame_count" );
|
||||
|
||||
INIT_GRA_PROP_BIND( Fullscreen, "fullscreen" );
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
** input-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "input.h"
|
||||
#include "globalstate.h"
|
||||
#include "exception.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
RB_METHOD(inputUpdate)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
gState->input().update();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
RB_METHOD(inputPress)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
int num;
|
||||
rb_get_args(argc, argv, "i", &num);
|
||||
|
||||
Input::ButtonCode bc = (Input::ButtonCode) num;
|
||||
|
||||
return rb_bool_new(gState->input().isPressed(bc));
|
||||
}
|
||||
|
||||
RB_METHOD(inputTrigger)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
int num;
|
||||
rb_get_args(argc, argv, "i", &num);
|
||||
|
||||
Input::ButtonCode bc = (Input::ButtonCode) num;
|
||||
|
||||
return rb_bool_new(gState->input().isTriggered(bc));
|
||||
}
|
||||
|
||||
RB_METHOD(inputRepeat)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
int num;
|
||||
rb_get_args(argc, argv, "i", &num);
|
||||
|
||||
Input::ButtonCode bc = (Input::ButtonCode) num;
|
||||
|
||||
return rb_bool_new(gState->input().isRepeated(bc));
|
||||
}
|
||||
|
||||
RB_METHOD(inputDir4)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
return rb_fix_new(gState->input().dir4Value());
|
||||
}
|
||||
|
||||
RB_METHOD(inputDir8)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
return rb_fix_new(gState->input().dir8Value());
|
||||
}
|
||||
|
||||
/* Non-standard extensions */
|
||||
RB_METHOD(inputMouseX)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
return rb_fix_new(gState->input().mouseX());
|
||||
}
|
||||
|
||||
RB_METHOD(inputMouseY)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
return rb_fix_new(gState->input().mouseY());
|
||||
}
|
||||
|
||||
#define DEF_CONST_I(name, value) \
|
||||
rb_const_set(module, rb_intern(name), rb_fix_new(value))
|
||||
|
||||
void
|
||||
inputBindingInit()
|
||||
{
|
||||
VALUE module = rb_define_module("Input");
|
||||
|
||||
_rb_define_module_function(module, "update", inputUpdate);
|
||||
_rb_define_module_function(module, "press?", inputPress);
|
||||
_rb_define_module_function(module, "trigger?", inputTrigger);
|
||||
_rb_define_module_function(module, "repeat?", inputRepeat);
|
||||
_rb_define_module_function(module, "dir4", inputDir4);
|
||||
_rb_define_module_function(module, "dir8", inputDir8);
|
||||
|
||||
DEF_CONST_I("DOWN", Input::Down );
|
||||
DEF_CONST_I("LEFT", Input::Left );
|
||||
DEF_CONST_I("RIGHT", Input::Right);
|
||||
DEF_CONST_I("UP", Input::Up );
|
||||
|
||||
DEF_CONST_I("A", Input::A );
|
||||
DEF_CONST_I("B", Input::B );
|
||||
DEF_CONST_I("C", Input::C );
|
||||
DEF_CONST_I("X", Input::X );
|
||||
DEF_CONST_I("Y", Input::Y );
|
||||
DEF_CONST_I("Z", Input::Z );
|
||||
DEF_CONST_I("L", Input::L );
|
||||
DEF_CONST_I("R", Input::R );
|
||||
|
||||
DEF_CONST_I("SHIFT", Input::Shift);
|
||||
DEF_CONST_I("CTRL", Input::Ctrl );
|
||||
DEF_CONST_I("ALT", Input::Alt );
|
||||
|
||||
DEF_CONST_I("F5", Input::F5 );
|
||||
DEF_CONST_I("F6", Input::F6 );
|
||||
DEF_CONST_I("F7", Input::F7 );
|
||||
DEF_CONST_I("F8", Input::F8 );
|
||||
DEF_CONST_I("F9", Input::F9 );
|
||||
|
||||
_rb_define_module_function(module, "mouse_x", inputMouseX);
|
||||
_rb_define_module_function(module, "mouse_y", inputMouseY);
|
||||
|
||||
DEF_CONST_I("MOUSELEFT", Input::MouseLeft );
|
||||
DEF_CONST_I("MOUSEMIDDLE", Input::MouseMiddle);
|
||||
DEF_CONST_I("MOUSERIGHT", Input::MouseRight );
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
#include "module_rpg.rb.xxd"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
** plane-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "plane.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "viewportelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
DEF_TYPE(Plane);
|
||||
|
||||
RB_METHOD(planeInitialize)
|
||||
{
|
||||
Plane *p = viewportElementInitialize<Plane>(argc, argv, self);
|
||||
|
||||
setPrivateData(self, p, PlaneType);
|
||||
|
||||
p->setColor(new Color);
|
||||
p->setTone(new Tone);
|
||||
|
||||
wrapNilProperty(self, "bitmap");
|
||||
wrapProperty(self, p->getColor(), "color", ColorType);
|
||||
wrapProperty(self, p->getTone(), "tone", ToneType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "plane"
|
||||
|
||||
DEF_PROP_OBJ(Plane, Bitmap, Bitmap, "bitmap")
|
||||
DEF_PROP_OBJ(Plane, Color, Color, "color")
|
||||
DEF_PROP_OBJ(Plane, Tone, Tone, "tone")
|
||||
|
||||
DEF_PROP_I(Plane, OX)
|
||||
DEF_PROP_I(Plane, OY)
|
||||
DEF_PROP_I(Plane, Opacity)
|
||||
DEF_PROP_I(Plane, BlendType)
|
||||
|
||||
DEF_PROP_F(Plane, ZoomX)
|
||||
DEF_PROP_F(Plane, ZoomY)
|
||||
|
||||
|
||||
void
|
||||
planeBindingInit()
|
||||
{
|
||||
INIT_TYPE(Plane);
|
||||
|
||||
VALUE klass = rb_define_class("Plane", rb_cObject);
|
||||
|
||||
disposableBindingInit<Plane> (klass);
|
||||
viewportElementBindingInit<Plane>(klass);
|
||||
|
||||
_rb_define_method(klass, "initialize", planeInitialize);
|
||||
|
||||
INIT_PROP_BIND( Plane, Bitmap, "bitmap" );
|
||||
INIT_PROP_BIND( Plane, OX, "ox" );
|
||||
INIT_PROP_BIND( Plane, OY, "oy" );
|
||||
INIT_PROP_BIND( Plane, ZoomX, "zoom_x" );
|
||||
INIT_PROP_BIND( Plane, ZoomY, "zoom_y" );
|
||||
INIT_PROP_BIND( Plane, Opacity, "opacity" );
|
||||
INIT_PROP_BIND( Plane, BlendType, "blend_type" );
|
||||
INIT_PROP_BIND( Plane, Color, "color" );
|
||||
INIT_PROP_BIND( Plane, Tone, "tone" );
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
** sceneelement-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCENEELEMENTBINDING_H
|
||||
#define SCENEELEMENTBINDING_H
|
||||
|
||||
#include "scene.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(sceneElementGetZ)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
SceneElement *se = getPrivateData<C>(self);
|
||||
|
||||
int value = 0;
|
||||
GUARD_EXC( value = se->getZ(); );
|
||||
|
||||
return rb_fix_new(value);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(sceneElementSetZ)
|
||||
{
|
||||
SceneElement *se = getPrivateData<C>(self);
|
||||
|
||||
int z;
|
||||
rb_get_args(argc, argv, "i", &z);
|
||||
|
||||
GUARD_EXC( se->setZ(z); );
|
||||
|
||||
return rb_fix_new(z);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(sceneElementGetVisible)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
SceneElement *se = getPrivateData<C>(self);
|
||||
|
||||
bool value = false;
|
||||
GUARD_EXC( value = se->getVisible(); );
|
||||
|
||||
return rb_bool_new(value);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(sceneElementSetVisible)
|
||||
{
|
||||
SceneElement *se = getPrivateData<C>(self);
|
||||
|
||||
bool visible;
|
||||
rb_get_args(argc, argv, "b", &visible);
|
||||
|
||||
GUARD_EXC( se->setVisible(visible); );
|
||||
|
||||
return rb_bool_new(visible);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void
|
||||
sceneElementBindingInit(VALUE klass)
|
||||
{
|
||||
_rb_define_method(klass, "z", sceneElementGetZ<C>);
|
||||
_rb_define_method(klass, "z=", sceneElementSetZ<C>);
|
||||
_rb_define_method(klass, "visible", sceneElementGetVisible<C>);
|
||||
_rb_define_method(klass, "visible=", sceneElementSetVisible<C>);
|
||||
}
|
||||
|
||||
#endif // SCENEELEMENTBINDING_H
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
** serializable-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SERIALIZABLEBINDING_H
|
||||
#define SERIALIZABLEBINDING_H
|
||||
|
||||
#include "serializable.h"
|
||||
#include "binding-util.h"
|
||||
#include "exception.h"
|
||||
|
||||
template<class C>
|
||||
static VALUE
|
||||
serializableDump(int, VALUE *, VALUE self)
|
||||
{
|
||||
Serializable *s = getPrivateData<C>(self);
|
||||
|
||||
int dataSize = s->serialSize();
|
||||
|
||||
VALUE data = rb_str_new(0, dataSize);
|
||||
|
||||
GUARD_EXC( s->serialize(RSTRING_PTR(data)); );
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void
|
||||
serializableBindingInit(VALUE klass)
|
||||
{
|
||||
_rb_define_method(klass, "_dump", serializableDump<C>);
|
||||
}
|
||||
|
||||
#endif // SERIALIZABLEBINDING_H
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
** sprite-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "sprite.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "flashable-binding.h"
|
||||
#include "sceneelement-binding.h"
|
||||
#include "viewportelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
DEF_TYPE(Sprite);
|
||||
|
||||
RB_METHOD(spriteInitialize)
|
||||
{
|
||||
Sprite *s = viewportElementInitialize<Sprite>(argc, argv, self);
|
||||
|
||||
setPrivateData(self, s, SpriteType);
|
||||
|
||||
/* Wrap property objects */
|
||||
s->setSrcRect(new Rect);
|
||||
s->setColor(new Color);
|
||||
s->setTone(new Tone);
|
||||
|
||||
wrapNilProperty(self, "bitmap");
|
||||
wrapProperty(self, s->getSrcRect(), "src_rect", RectType);
|
||||
wrapProperty(self, s->getColor(), "color", ColorType);
|
||||
wrapProperty(self, s->getTone(), "tone", ToneType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "sprite"
|
||||
|
||||
DEF_PROP_OBJ_NIL(Sprite, Bitmap, Bitmap, "bitmap")
|
||||
DEF_PROP_OBJ(Sprite, Rect, SrcRect, "src_rect")
|
||||
DEF_PROP_OBJ(Sprite, Color, Color, "color")
|
||||
DEF_PROP_OBJ(Sprite, Tone, Tone, "tone")
|
||||
|
||||
DEF_PROP_I(Sprite, X)
|
||||
DEF_PROP_I(Sprite, Y)
|
||||
DEF_PROP_I(Sprite, OX)
|
||||
DEF_PROP_I(Sprite, OY)
|
||||
DEF_PROP_I(Sprite, BushDepth)
|
||||
DEF_PROP_I(Sprite, Opacity)
|
||||
DEF_PROP_I(Sprite, BlendType)
|
||||
|
||||
DEF_PROP_F(Sprite, ZoomX)
|
||||
DEF_PROP_F(Sprite, ZoomY)
|
||||
DEF_PROP_F(Sprite, Angle)
|
||||
|
||||
DEF_PROP_B(Sprite, Mirror)
|
||||
|
||||
void
|
||||
spriteBindingInit()
|
||||
{
|
||||
INIT_TYPE(Sprite);
|
||||
|
||||
VALUE klass = rb_define_class("Sprite", rb_cObject);
|
||||
|
||||
disposableBindingInit <Sprite>(klass);
|
||||
flashableBindingInit <Sprite>(klass);
|
||||
viewportElementBindingInit<Sprite>(klass);
|
||||
|
||||
_rb_define_method(klass, "initialize", spriteInitialize);
|
||||
|
||||
INIT_PROP_BIND( Sprite, Bitmap, "bitmap" );
|
||||
INIT_PROP_BIND( Sprite, SrcRect, "src_rect" );
|
||||
INIT_PROP_BIND( Sprite, X, "x" );
|
||||
INIT_PROP_BIND( Sprite, Y, "y" );
|
||||
INIT_PROP_BIND( Sprite, OX, "ox" );
|
||||
INIT_PROP_BIND( Sprite, OY, "oy" );
|
||||
INIT_PROP_BIND( Sprite, ZoomX, "zoom_x" );
|
||||
INIT_PROP_BIND( Sprite, ZoomY, "zoom_y" );
|
||||
INIT_PROP_BIND( Sprite, Angle, "angle" );
|
||||
INIT_PROP_BIND( Sprite, Mirror, "mirror" );
|
||||
INIT_PROP_BIND( Sprite, BushDepth, "bush_depth" );
|
||||
INIT_PROP_BIND( Sprite, Opacity, "opacity" );
|
||||
INIT_PROP_BIND( Sprite, BlendType, "blend_type" );
|
||||
INIT_PROP_BIND( Sprite, Color, "color" );
|
||||
INIT_PROP_BIND( Sprite, Tone, "tone" );
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
** table-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "table.h"
|
||||
#include "binding-util.h"
|
||||
#include "serializable-binding.h"
|
||||
|
||||
DEF_TYPE(Table);
|
||||
|
||||
RB_METHOD(tableInitialize)
|
||||
{
|
||||
int x, y, z;
|
||||
x = y = z = 1;
|
||||
|
||||
rb_get_args(argc, argv, "i|ii", &x, &y, &z);
|
||||
|
||||
Table *t = new Table(x, y, z);
|
||||
|
||||
setPrivateData(self, t, TableType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(tableResize)
|
||||
{
|
||||
Table *t = getPrivateData<Table>(self);
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
default:
|
||||
case 1:
|
||||
t->resize(rb_fix2int(argv[0]));
|
||||
return Qnil;
|
||||
|
||||
case 2:
|
||||
t->resize(rb_fix2int(argv[0]),
|
||||
rb_fix2int(argv[1]));
|
||||
return Qnil;
|
||||
|
||||
case 3:
|
||||
t->resize(rb_fix2int(argv[0]),
|
||||
rb_fix2int(argv[1]),
|
||||
rb_fix2int(argv[2]));
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
#define TABLE_SIZE(d, D) \
|
||||
RB_METHOD(table##D##Size) \
|
||||
{ \
|
||||
RB_UNUSED_PARAM \
|
||||
Table *t = getPrivateData<Table>(self); \
|
||||
return rb_int2inum(t->d##Size()); \
|
||||
}
|
||||
|
||||
TABLE_SIZE(x, X)
|
||||
TABLE_SIZE(y, Y)
|
||||
TABLE_SIZE(z, Z)
|
||||
|
||||
RB_METHOD(tableGetAt)
|
||||
{
|
||||
Table *t = getPrivateData<Table>(self);
|
||||
|
||||
int x, y, z;
|
||||
x = y = z = 0;
|
||||
|
||||
x = rb_num2int(argv[0]);
|
||||
if (argc > 1)
|
||||
y = rb_num2int(argv[1]);
|
||||
if (argc > 2)
|
||||
z = rb_num2int(argv[2]);
|
||||
|
||||
if (argc > 3)
|
||||
rb_raise(rb_eArgError, "wrong number of arguments");
|
||||
|
||||
if (x < 0 || x >= t->xSize()
|
||||
|| y < 0 || y >= t->ySize()
|
||||
|| z < 0 || z >= t->zSize())
|
||||
{
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
int result = t->get(x, y, z);
|
||||
|
||||
return rb_int2inum(result);
|
||||
}
|
||||
|
||||
RB_METHOD(tableSetAt)
|
||||
{
|
||||
Table *t = getPrivateData<Table>(self);
|
||||
|
||||
int x, y, z, value;
|
||||
x = y = z = 0;
|
||||
|
||||
if (argc < 2)
|
||||
rb_raise(rb_eArgError, "wrong number of arguments");
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
default:
|
||||
case 2 :
|
||||
x = rb_fix2int(argv[0]);
|
||||
value = rb_fix2int(argv[1]);
|
||||
break;
|
||||
case 3 :
|
||||
x = rb_fix2int(argv[0]);
|
||||
y = rb_fix2int(argv[1]);
|
||||
value = rb_fix2int(argv[2]);
|
||||
break;
|
||||
case 4 :
|
||||
x = rb_fix2int(argv[0]);
|
||||
y = rb_fix2int(argv[1]);
|
||||
z = rb_fix2int(argv[2]);
|
||||
value = rb_fix2int(argv[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
t->set(value, x, y, z);
|
||||
|
||||
return rb_int2inum(value);
|
||||
}
|
||||
|
||||
MARSH_LOAD_FUN(Table)
|
||||
|
||||
void
|
||||
tableBindingInit()
|
||||
{
|
||||
INIT_TYPE(Table);
|
||||
|
||||
VALUE klass = rb_define_class("Table", rb_cObject);
|
||||
|
||||
serializableBindingInit<Table>(klass);
|
||||
|
||||
rb_define_class_method(klass, "_load", TableLoad);
|
||||
|
||||
_rb_define_method(klass, "initialize", tableInitialize);
|
||||
_rb_define_method(klass, "resize", tableResize);
|
||||
_rb_define_method(klass, "xsize", tableXSize);
|
||||
_rb_define_method(klass, "ysize", tableYSize);
|
||||
_rb_define_method(klass, "zsize", tableZSize);
|
||||
_rb_define_method(klass, "[]", tableGetAt);
|
||||
_rb_define_method(klass, "[]=", tableSetAt);
|
||||
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
** tilemap-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tilemap.h"
|
||||
#include "viewport.h"
|
||||
#include "bitmap.h"
|
||||
#include "table.h"
|
||||
|
||||
#include "disposable-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
static rb_data_type_struct TilemapAutotilesType;
|
||||
|
||||
RB_METHOD(tilemapAutotilesSet)
|
||||
{
|
||||
Tilemap::Autotiles *a = getPrivateData<Tilemap::Autotiles>(self);
|
||||
|
||||
int i;
|
||||
VALUE bitmapObj;
|
||||
|
||||
rb_get_args(argc, argv, "io", &i, &bitmapObj);
|
||||
|
||||
Bitmap *bitmap = getPrivateDataCheck<Bitmap>(bitmapObj, BitmapType);
|
||||
|
||||
a->set(i, bitmap);
|
||||
|
||||
VALUE ary = rb_iv_get(self, "array");
|
||||
rb_ary_store(ary, i, bitmapObj);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(tilemapAutotilesGet)
|
||||
{
|
||||
int i;
|
||||
rb_get_args (argc, argv, "i", &i);
|
||||
|
||||
if (i < 0 || i > 6)
|
||||
return Qnil;
|
||||
|
||||
VALUE ary = rb_iv_get(self, "array");
|
||||
|
||||
return rb_ary_entry(ary, i);
|
||||
}
|
||||
|
||||
DEF_TYPE(Tilemap);
|
||||
|
||||
RB_METHOD(tilemapInitialize)
|
||||
{
|
||||
Tilemap *t;
|
||||
|
||||
/* Get parameters */
|
||||
VALUE viewportObj = Qnil;
|
||||
Viewport *viewport = 0;
|
||||
|
||||
rb_get_args(argc, argv, "|o", &viewportObj);
|
||||
|
||||
if (rb_type(viewportObj) != RUBY_T_NIL)
|
||||
viewport = getPrivateDataCheck<Viewport>(viewportObj, ViewportType);
|
||||
|
||||
/* Construct object */
|
||||
t = new Tilemap(viewport);
|
||||
|
||||
setPrivateData(self, t, TilemapType);
|
||||
|
||||
rb_iv_set(self, "viewport", viewportObj);
|
||||
|
||||
wrapProperty(self, &t->getAutotiles(), "autotiles", TilemapAutotilesType);
|
||||
|
||||
VALUE autotilesObj = rb_iv_get(self, "autotiles");
|
||||
|
||||
VALUE ary = rb_ary_new2(7);
|
||||
for (int i = 0; i < 7; ++i)
|
||||
rb_ary_push(ary, Qnil);
|
||||
|
||||
rb_iv_set(autotilesObj, "array", ary);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(tilemapGetAutotiles)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
return rb_iv_get(self, "autotiles");
|
||||
}
|
||||
|
||||
RB_METHOD(tilemapUpdate)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Tilemap *t = getPrivateData<Tilemap>(self);
|
||||
|
||||
t->update();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "tilemap"
|
||||
|
||||
DEF_PROP_OBJ(Tilemap, Viewport, Viewport, "viewport")
|
||||
DEF_PROP_OBJ(Tilemap, Bitmap, Tileset, "tileset")
|
||||
DEF_PROP_OBJ(Tilemap, Table, MapData, "map_data")
|
||||
DEF_PROP_OBJ(Tilemap, Table, FlashData, "flash_data")
|
||||
DEF_PROP_OBJ(Tilemap, Table, Priorities, "priorities")
|
||||
|
||||
DEF_PROP_B(Tilemap, Visible)
|
||||
|
||||
DEF_PROP_I(Tilemap, OX)
|
||||
DEF_PROP_I(Tilemap, OY)
|
||||
|
||||
void
|
||||
tilemapBindingInit()
|
||||
{
|
||||
initType(TilemapAutotilesType, "TilemapAutotiles", 0);
|
||||
|
||||
VALUE klass = rb_define_class("TilemapAutotiles", rb_cObject);
|
||||
|
||||
_rb_define_method(klass, "[]=", tilemapAutotilesSet);
|
||||
_rb_define_method(klass, "[]", tilemapAutotilesGet);
|
||||
|
||||
INIT_TYPE(Tilemap);
|
||||
|
||||
klass = rb_define_class("Tilemap", rb_cObject);
|
||||
|
||||
disposableBindingInit<Tilemap>(klass);
|
||||
|
||||
_rb_define_method(klass, "initialize", tilemapInitialize);
|
||||
_rb_define_method(klass, "autotiles", tilemapGetAutotiles);
|
||||
_rb_define_method(klass, "update", tilemapUpdate);
|
||||
|
||||
INIT_PROP_BIND( Tilemap, Viewport, "viewport" );
|
||||
INIT_PROP_BIND( Tilemap, Tileset, "tileset" );
|
||||
INIT_PROP_BIND( Tilemap, MapData, "map_data" );
|
||||
INIT_PROP_BIND( Tilemap, FlashData, "flash_data" );
|
||||
INIT_PROP_BIND( Tilemap, Priorities, "priorities" );
|
||||
INIT_PROP_BIND( Tilemap, Visible, "visible" );
|
||||
INIT_PROP_BIND( Tilemap, OX, "ox" );
|
||||
INIT_PROP_BIND( Tilemap, OY, "oy" );
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
** viewport-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "viewport.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "flashable-binding.h"
|
||||
#include "sceneelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
DEF_TYPE(Viewport);
|
||||
|
||||
RB_METHOD(viewportInitialize)
|
||||
{
|
||||
Viewport *v;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
/* The rect arg is only used to init the viewport,
|
||||
* and does NOT replace its 'rect' property */
|
||||
VALUE rectObj;
|
||||
Rect *rect;
|
||||
|
||||
rb_get_args(argc, argv, "o", &rectObj);
|
||||
|
||||
rect = getPrivateDataCheck<Rect>(rectObj, RectType);
|
||||
|
||||
v = new Viewport(rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x, y, width, height;
|
||||
|
||||
rb_get_args(argc, argv, "iiii", &x, &y, &width, &height);
|
||||
|
||||
v = new Viewport(x, y, width, height);
|
||||
}
|
||||
|
||||
setPrivateData(self, v, ViewportType);
|
||||
|
||||
/* Wrap property objects */
|
||||
v->setRect(new Rect(*v->getRect()));
|
||||
v->setColor(new Color);
|
||||
v->setTone(new Tone);
|
||||
|
||||
wrapProperty(self, v->getRect(), "rect", RectType);
|
||||
wrapProperty(self, v->getColor(), "color", ColorType);
|
||||
wrapProperty(self, v->getTone(), "tone", ToneType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "viewport"
|
||||
|
||||
DEF_PROP_OBJ(Viewport, Rect, Rect, "rect")
|
||||
DEF_PROP_OBJ(Viewport, Color, Color, "color")
|
||||
DEF_PROP_OBJ(Viewport, Tone, Tone, "tone")
|
||||
|
||||
DEF_PROP_I(Viewport, OX)
|
||||
DEF_PROP_I(Viewport, OY)
|
||||
|
||||
|
||||
void
|
||||
viewportBindingInit()
|
||||
{
|
||||
INIT_TYPE(Viewport);
|
||||
|
||||
VALUE klass = rb_define_class("Viewport", rb_cObject);
|
||||
|
||||
disposableBindingInit <Viewport>(klass);
|
||||
flashableBindingInit <Viewport>(klass);
|
||||
sceneElementBindingInit<Viewport>(klass);
|
||||
|
||||
_rb_define_method(klass, "initialize", viewportInitialize);
|
||||
|
||||
INIT_PROP_BIND( Viewport, Rect, "rect" );
|
||||
INIT_PROP_BIND( Viewport, OX, "ox" );
|
||||
INIT_PROP_BIND( Viewport, OY, "oy" );
|
||||
INIT_PROP_BIND( Viewport, Color, "color" );
|
||||
INIT_PROP_BIND( Viewport, Tone, "tone" );
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
** viewportelement-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VIEWPORTELEMENTBINDING_H
|
||||
#define VIEWPORTELEMENTBINDING_H
|
||||
|
||||
#include "viewport.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
#include "sceneelement-binding.h"
|
||||
|
||||
template<class C>
|
||||
RB_METHOD(viewportElementGetViewport)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
ViewportElement *ve = getPrivateData<C>(self);
|
||||
|
||||
GUARD_EXC( ve->aboutToAccess(); );
|
||||
|
||||
return rb_iv_get(self, "viewport");
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static C *
|
||||
viewportElementInitialize(int argc, VALUE *argv, VALUE self)
|
||||
{
|
||||
/* Get parameters */
|
||||
VALUE viewportObj = Qnil;
|
||||
Viewport *viewport = 0;
|
||||
|
||||
rb_get_args(argc, argv, "|o", &viewportObj);
|
||||
|
||||
if (rb_type(viewportObj) != RUBY_T_NIL)
|
||||
viewport = getPrivateDataCheck<Viewport>(viewportObj, ViewportType);
|
||||
|
||||
/* Construct object */
|
||||
C *ve = new C(viewport);
|
||||
|
||||
/* Set property objects */
|
||||
rb_iv_set(self, "viewport", viewportObj);
|
||||
|
||||
return ve;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void
|
||||
viewportElementBindingInit(VALUE klass)
|
||||
{
|
||||
sceneElementBindingInit<C>(klass);
|
||||
|
||||
_rb_define_method(klass, "viewport", viewportElementGetViewport<C>);
|
||||
}
|
||||
|
||||
#endif // VIEWPORTELEMENTBINDING_H
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
** window-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "window.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "viewportelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
DEF_TYPE(Window);
|
||||
|
||||
RB_METHOD(windowInitialize)
|
||||
{
|
||||
Window *w = viewportElementInitialize<Window>(argc, argv, self);
|
||||
|
||||
setPrivateData(self, w, WindowType);
|
||||
|
||||
w->setCursorRect(new Rect);
|
||||
wrapNilProperty(self, "windowskin");
|
||||
wrapNilProperty(self, "contents");
|
||||
wrapProperty(self, w->getCursorRect(), "cursor_rect", RectType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
RB_METHOD(windowUpdate)
|
||||
{
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
Window *w = getPrivateData<Window>(self);
|
||||
|
||||
w->update();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "window"
|
||||
|
||||
DEF_PROP_OBJ_NIL(Window, Bitmap, Windowskin, "windowskin")
|
||||
DEF_PROP_OBJ_NIL(Window, Bitmap, Contents, "contents")
|
||||
DEF_PROP_OBJ(Window, Rect, CursorRect, "cursor_rect")
|
||||
|
||||
DEF_PROP_B(Window, Stretch)
|
||||
DEF_PROP_B(Window, Active)
|
||||
DEF_PROP_B(Window, Pause)
|
||||
|
||||
DEF_PROP_I(Window, X)
|
||||
DEF_PROP_I(Window, Y)
|
||||
DEF_PROP_I(Window, Width)
|
||||
DEF_PROP_I(Window, Height)
|
||||
DEF_PROP_I(Window, OX)
|
||||
DEF_PROP_I(Window, OY)
|
||||
DEF_PROP_I(Window, Opacity)
|
||||
DEF_PROP_I(Window, BackOpacity)
|
||||
DEF_PROP_I(Window, ContentsOpacity)
|
||||
|
||||
|
||||
void
|
||||
windowBindingInit()
|
||||
{
|
||||
INIT_TYPE(Window);
|
||||
|
||||
VALUE klass = rb_define_class("Window", rb_cObject);
|
||||
|
||||
disposableBindingInit <Window>(klass);
|
||||
viewportElementBindingInit<Window>(klass);
|
||||
|
||||
_rb_define_method(klass, "initialize", windowInitialize);
|
||||
_rb_define_method(klass, "update", windowUpdate);
|
||||
|
||||
INIT_PROP_BIND( Window, Windowskin, "windowskin" );
|
||||
INIT_PROP_BIND( Window, Contents, "contents" );
|
||||
INIT_PROP_BIND( Window, Stretch, "stretch" );
|
||||
INIT_PROP_BIND( Window, CursorRect, "cursor_rect" );
|
||||
INIT_PROP_BIND( Window, Active, "active" );
|
||||
INIT_PROP_BIND( Window, Pause, "pause" );
|
||||
INIT_PROP_BIND( Window, X, "x" );
|
||||
INIT_PROP_BIND( Window, Y, "y" );
|
||||
INIT_PROP_BIND( Window, Width, "width" );
|
||||
INIT_PROP_BIND( Window, Height, "height" );
|
||||
INIT_PROP_BIND( Window, OX, "ox" );
|
||||
INIT_PROP_BIND( Window, OY, "oy" );
|
||||
INIT_PROP_BIND( Window, Opacity, "opacity" );
|
||||
INIT_PROP_BIND( Window, BackOpacity, "back_opacity" );
|
||||
INIT_PROP_BIND( Window, ContentsOpacity, "contents_opacity" );
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
** audio-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audio.h"
|
||||
#include "globalstate.h"
|
||||
#include "binding-util.h"
|
||||
#include "exception.h"
|
||||
|
||||
#define DEF_PLAY_STOP(entity) \
|
||||
MRB_METHOD(audio_##entity##Play) \
|
||||
{ \
|
||||
MRB_UNUSED_PARAM; \
|
||||
char *filename; \
|
||||
mrb_int volume = 100; \
|
||||
mrb_int pitch = 100; \
|
||||
mrb_get_args(mrb, "z|ii", &filename, &volume, &pitch); \
|
||||
GUARD_EXC( gState->audio().entity##Play(filename, volume, pitch); ) \
|
||||
return mrb_nil_value(); \
|
||||
} \
|
||||
MRB_METHOD(audio_##entity##Stop) \
|
||||
{ \
|
||||
MRB_UNUSED_PARAM; \
|
||||
gState->audio().entity##Stop(); \
|
||||
return mrb_nil_value(); \
|
||||
}
|
||||
|
||||
#define DEF_FADE(entity) \
|
||||
MRB_METHOD(audio_##entity##Fade) \
|
||||
{ \
|
||||
MRB_UNUSED_PARAM; \
|
||||
mrb_int time; \
|
||||
mrb_get_args(mrb, "i", &time); \
|
||||
gState->audio().entity##Fade(time); \
|
||||
return mrb_nil_value(); \
|
||||
}
|
||||
|
||||
#define DEF_PLAY_STOP_FADE(entity) \
|
||||
DEF_PLAY_STOP(entity) \
|
||||
DEF_FADE(entity)
|
||||
|
||||
DEF_PLAY_STOP_FADE( bgm )
|
||||
DEF_PLAY_STOP_FADE( bgs )
|
||||
DEF_PLAY_STOP_FADE( me )
|
||||
|
||||
DEF_PLAY_STOP( se )
|
||||
|
||||
|
||||
#define BIND_PLAY_STOP(entity) \
|
||||
mrb_define_module_function(mrb, module, #entity "_play", audio_##entity##Play, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(2)); \
|
||||
mrb_define_module_function(mrb, module, #entity "_stop", audio_##entity##Stop, MRB_ARGS_NONE());
|
||||
|
||||
#define BIND_FADE(entity) \
|
||||
mrb_define_module_function(mrb, module, #entity "_fade", audio_##entity##Fade, MRB_ARGS_REQ(1));
|
||||
|
||||
#define BIND_PLAY_STOP_FADE(entity) \
|
||||
BIND_PLAY_STOP(entity) \
|
||||
BIND_FADE(entity)
|
||||
|
||||
|
||||
void
|
||||
audioBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *module = mrb_define_module(mrb, "Audio");
|
||||
|
||||
BIND_PLAY_STOP_FADE( bgm )
|
||||
BIND_PLAY_STOP_FADE( bgs )
|
||||
BIND_PLAY_STOP_FADE( me )
|
||||
|
||||
BIND_PLAY_STOP( se )
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
** binding-mruby.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "binding.h"
|
||||
|
||||
#include "mruby.h"
|
||||
#include "mruby/string.h"
|
||||
#include "mruby/array.h"
|
||||
#include "mruby/class.h"
|
||||
#include "mruby/irep.h"
|
||||
#include "mruby/compile.h"
|
||||
#include "mruby/proc.h"
|
||||
|
||||
#include "binding-util.h"
|
||||
|
||||
#include "stdio.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include "SDL2/SDL_messagebox.h"
|
||||
#include "SDL2/SDL_rwops.h"
|
||||
#include "SDL2/SDL_timer.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "texpool.h"
|
||||
#include "eventthread.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#include "binding-types.h"
|
||||
#include "mrb-ext/marshal.h"
|
||||
|
||||
void mrbBindingExecute();
|
||||
void mrbBindingTerminate();
|
||||
|
||||
ScriptBinding scriptBindingImpl =
|
||||
{
|
||||
mrbBindingExecute,
|
||||
mrbBindingTerminate
|
||||
};
|
||||
|
||||
ScriptBinding *scriptBinding = &scriptBindingImpl;
|
||||
|
||||
|
||||
void fileBindingInit(mrb_state *);
|
||||
void timeBindingInit(mrb_state *);
|
||||
void marshalBindingInit(mrb_state *);
|
||||
void kernelBindingInit(mrb_state *);
|
||||
|
||||
void tableBindingInit(mrb_state *);
|
||||
void etcBindingInit(mrb_state *);
|
||||
void fontBindingInit(mrb_state *);
|
||||
void bitmapBindingInit(mrb_state *);
|
||||
void spriteBindingInit(mrb_state *);
|
||||
void planeBindingInit(mrb_state *);
|
||||
void viewportBindingInit(mrb_state *);
|
||||
void windowBindingInit(mrb_state *);
|
||||
void tilemapBindingInit(mrb_state *);
|
||||
|
||||
void inputBindingInit(mrb_state *);
|
||||
void audioBindingInit(mrb_state *);
|
||||
void graphicsBindingInit(mrb_state *);
|
||||
|
||||
/* From module_rpg.c */
|
||||
extern const uint8_t mrbModuleRPG[];
|
||||
|
||||
static void mrbBindingInit(mrb_state *mrb)
|
||||
{
|
||||
int arena = mrb_gc_arena_save(mrb);
|
||||
|
||||
/* Init standard classes */
|
||||
fileBindingInit(mrb);
|
||||
timeBindingInit(mrb);
|
||||
marshalBindingInit(mrb);
|
||||
kernelBindingInit(mrb);
|
||||
|
||||
/* Init RGSS classes */
|
||||
tableBindingInit(mrb);
|
||||
etcBindingInit(mrb);
|
||||
fontBindingInit(mrb);
|
||||
bitmapBindingInit(mrb);
|
||||
spriteBindingInit(mrb);
|
||||
planeBindingInit(mrb);
|
||||
viewportBindingInit(mrb);
|
||||
windowBindingInit(mrb);
|
||||
tilemapBindingInit(mrb);
|
||||
|
||||
/* Init RGSS modules */
|
||||
inputBindingInit(mrb);
|
||||
audioBindingInit(mrb);
|
||||
graphicsBindingInit(mrb);
|
||||
|
||||
/* Load RPG module */
|
||||
mrb_load_irep(mrb, mrbModuleRPG);
|
||||
|
||||
mrb_define_global_const(mrb, "MKXP", mrb_true_value());
|
||||
|
||||
mrb_gc_arena_restore(mrb, arena);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mkxpTimeOp(mrb_state *mrb, mrb_value)
|
||||
{
|
||||
const char *opName;
|
||||
mrb_value block;
|
||||
|
||||
mrb_get_args(mrb, "z&", &opName, &block);
|
||||
|
||||
Uint64 start = SDL_GetPerformanceCounter();
|
||||
|
||||
mrb_yield(mrb, block, mrb_nil_value());
|
||||
|
||||
Uint64 diff = SDL_GetPerformanceCounter() - start;
|
||||
double sec = (double) diff / SDL_GetPerformanceFrequency();
|
||||
float ms = sec * 1000;
|
||||
|
||||
printf("<%s> [%f ms]\n", opName, ms);
|
||||
fflush(stdout);
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mkxpEvalBlock(mrb_state *mrb, mrb_value)
|
||||
{
|
||||
mrb_value block;
|
||||
mrb_get_args(mrb, "&", &block);
|
||||
|
||||
// mrb_yield_argv(mrb, block, 0, 0);
|
||||
|
||||
mrb_run(mrb, mrb_proc_ptr(block), mrb_obj_value(mrb->top_self));
|
||||
|
||||
if (mrb->exc)
|
||||
{
|
||||
qDebug() << "Got exc!" << mrb_class_name(mrb, mrb_class(mrb, mrb_obj_value(mrb->exc)));
|
||||
}
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static const char *
|
||||
mrbValueString(mrb_value value)
|
||||
{
|
||||
return mrb_string_p(value) ? RSTRING_PTR(value) : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
showExcMessageBox(mrb_state *mrb, mrb_value exc)
|
||||
{
|
||||
/* Display actual exception in a message box */
|
||||
mrb_value mesg = mrb_funcall(mrb, exc, "message", 0);
|
||||
mrb_value line = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "line", 4));
|
||||
mrb_value file = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "file", 4));
|
||||
const char *excClass = mrb_class_name(mrb, mrb_class(mrb, exc));
|
||||
|
||||
char msgBoxText[512];
|
||||
snprintf(msgBoxText, 512, "Script '%s' line %d: %s occured.\n\n%s",
|
||||
mrbValueString(file), mrb_fixnum(line), excClass, mrbValueString(mesg));
|
||||
|
||||
gState->eThread().showMessageBox(msgBoxText, SDL_MESSAGEBOX_ERROR);
|
||||
}
|
||||
|
||||
static void
|
||||
checkException(mrb_state *mrb)
|
||||
{
|
||||
if (!mrb->exc)
|
||||
return;
|
||||
|
||||
mrb_value exc = mrb_obj_value(mrb->exc);
|
||||
MrbData &mrbData = *getMrbData(mrb);
|
||||
|
||||
/* Check if an actual exception occured, or just a shutdown was called */
|
||||
if (mrb_obj_class(mrb, exc) != mrbData.exc[Shutdown])
|
||||
showExcMessageBox(mrb, exc);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
showError(const QByteArray &msg)
|
||||
{
|
||||
gState->eThread().showMessageBox(msg.constData());
|
||||
}
|
||||
|
||||
static void
|
||||
runCustomScript(mrb_state *mrb, mrbc_context *ctx, const char *filename)
|
||||
{
|
||||
/* Execute custom script */
|
||||
FILE *f = fopen(filename, "r");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
static char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "Unable to open script '%s'", filename);
|
||||
showError(buffer);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->filename = strdup(filename);
|
||||
ctx->lineno = 1;
|
||||
|
||||
/* Run code */
|
||||
mrb_load_file_cxt(mrb, f, ctx);
|
||||
|
||||
free(ctx->filename);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void
|
||||
runRMXPScripts(mrb_state *mrb, mrbc_context *ctx)
|
||||
{
|
||||
const QByteArray &scriptLoc = gState->rtData().config.game.scripts;
|
||||
|
||||
if (!gState->fileSystem().exists(scriptLoc.constData()))
|
||||
{
|
||||
showError("Unable to open '" + scriptLoc + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
/* We use a secondary util state to unmarshal the scripts */
|
||||
mrb_state *scriptMrb = mrb_open();
|
||||
SDL_RWops ops;
|
||||
|
||||
gState->fileSystem().openRead(ops, scriptLoc.constData());
|
||||
|
||||
mrb_value scriptArray = marshalLoadInt(scriptMrb, &ops);
|
||||
SDL_RWclose(&ops);
|
||||
|
||||
if (!mrb_array_p(scriptArray))
|
||||
{
|
||||
showError("Failed to read script data");
|
||||
mrb_close(scriptMrb);
|
||||
return;
|
||||
}
|
||||
|
||||
int scriptCount = mrb_ary_len(scriptMrb, scriptArray);
|
||||
|
||||
QByteArray decodeBuffer;
|
||||
decodeBuffer.resize(0x1000);
|
||||
|
||||
for (int i = 0; i < scriptCount; ++i)
|
||||
{
|
||||
mrb_value script = mrb_ary_entry(scriptArray, i);
|
||||
|
||||
mrb_value scriptChksum = mrb_ary_entry(script, 0);
|
||||
mrb_value scriptName = mrb_ary_entry(script, 1);
|
||||
mrb_value scriptString = mrb_ary_entry(script, 2);
|
||||
|
||||
(void) scriptChksum;
|
||||
|
||||
int result = Z_OK;
|
||||
ulong bufferLen;
|
||||
|
||||
while (true)
|
||||
{
|
||||
unsigned char *bufferPtr =
|
||||
reinterpret_cast<unsigned char*>(const_cast<char*>(decodeBuffer.constData()));
|
||||
unsigned char *sourcePtr =
|
||||
reinterpret_cast<unsigned char*>(RSTRING_PTR(scriptString));
|
||||
|
||||
bufferLen = decodeBuffer.length();
|
||||
|
||||
result = uncompress(bufferPtr, &bufferLen,
|
||||
sourcePtr, RSTRING_LEN(scriptString));
|
||||
|
||||
bufferPtr[bufferLen] = '\0';
|
||||
|
||||
if (result != Z_BUF_ERROR)
|
||||
break;
|
||||
|
||||
decodeBuffer.resize(decodeBuffer.size()*2);
|
||||
}
|
||||
|
||||
if (result != Z_OK)
|
||||
{
|
||||
static char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "Error decoding script %d: '%s'",
|
||||
i, RSTRING_PTR(scriptName));
|
||||
|
||||
showError(buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->filename = RSTRING_PTR(scriptName);
|
||||
ctx->lineno = 1;
|
||||
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
/* Execute code */
|
||||
mrb_load_nstring_cxt(mrb, decodeBuffer.constData(), bufferLen, ctx);
|
||||
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
|
||||
if (mrb->exc)
|
||||
break;
|
||||
}
|
||||
|
||||
mrb_close(scriptMrb);
|
||||
}
|
||||
|
||||
void mrbBindingExecute()
|
||||
{
|
||||
mrb_state *mrb = mrb_open();
|
||||
|
||||
gState->setBindingData(mrb);
|
||||
|
||||
MrbData mrbData(mrb);
|
||||
mrb->ud = &mrbData;
|
||||
|
||||
RClass *mkxpMod = mrb_define_module(mrb, "MKXP");
|
||||
mrb_define_module_function(mrb, mkxpMod, "time_op", mkxpTimeOp, MRB_ARGS_REQ(1) | MRB_ARGS_BLOCK());
|
||||
mrb_define_module_function(mrb, mkxpMod, "eval_block", mkxpEvalBlock, MRB_ARGS_BLOCK());
|
||||
|
||||
mrbBindingInit(mrb);
|
||||
|
||||
mrbc_context *ctx = mrbc_context_new(mrb);
|
||||
ctx->capture_errors = 1;
|
||||
|
||||
QByteArray &customScript = gState->rtData().config.customScript;
|
||||
if (!customScript.isEmpty())
|
||||
runCustomScript(mrb, ctx, customScript.constData());
|
||||
else
|
||||
runRMXPScripts(mrb, ctx);
|
||||
|
||||
checkException(mrb);
|
||||
|
||||
gState->rtData().rqTermAck = true;
|
||||
gState->texPool().disable();
|
||||
|
||||
mrbc_context_free(mrb, ctx);
|
||||
mrb_close(mrb);
|
||||
}
|
||||
|
||||
void mrbBindingTerminate()
|
||||
{
|
||||
mrb_state *mrb = static_cast<mrb_state*>(gState->bindingData());
|
||||
MrbData *data = static_cast<MrbData*>(mrb->ud);
|
||||
|
||||
mrb_raise(mrb, data->exc[Shutdown], "");
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
** binding-types.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BINDINGTYPES_H
|
||||
#define BINDINGTYPES_H
|
||||
|
||||
#include "binding-util.h"
|
||||
|
||||
DECL_TYPE(Table);
|
||||
DECL_TYPE(Rect);
|
||||
DECL_TYPE(Color);
|
||||
DECL_TYPE(Tone);
|
||||
DECL_TYPE(Font);
|
||||
|
||||
DECL_TYPE(Bitmap);
|
||||
DECL_TYPE(Sprite);
|
||||
DECL_TYPE(Plane);
|
||||
DECL_TYPE(Viewport);
|
||||
DECL_TYPE(Tilemap);
|
||||
DECL_TYPE(Window);
|
||||
|
||||
#endif // BINDINGTYPES_H
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
** binding-util.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "binding-util.h"
|
||||
#include "util.h"
|
||||
#include "exception.h"
|
||||
|
||||
#define SYMD(symbol) { CS##symbol, #symbol }
|
||||
|
||||
struct
|
||||
{
|
||||
CommonSymbol ind;
|
||||
const char *str;
|
||||
} static const symData[] =
|
||||
{
|
||||
SYMD(priv_iv),
|
||||
SYMD(font),
|
||||
SYMD(viewport),
|
||||
SYMD(bitmap),
|
||||
SYMD(color),
|
||||
SYMD(tone),
|
||||
SYMD(rect),
|
||||
SYMD(src_rect),
|
||||
SYMD(tileset),
|
||||
SYMD(autotiles),
|
||||
SYMD(map_data),
|
||||
SYMD(flash_data),
|
||||
SYMD(priorities),
|
||||
SYMD(windowskin),
|
||||
SYMD(contents),
|
||||
SYMD(cursor_rect),
|
||||
SYMD(path),
|
||||
SYMD(array),
|
||||
SYMD(default_color)
|
||||
};
|
||||
|
||||
static elementsN(symData);
|
||||
|
||||
struct MrbExcData
|
||||
{
|
||||
MrbException ind;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
static const MrbExcData excData[] =
|
||||
{
|
||||
{ Shutdown, "SystemExit" },
|
||||
{ RGSS, "RGSSError" },
|
||||
{ PHYSFS, "PHYSFSError" },
|
||||
{ SDL, "SDLError" },
|
||||
{ IO, "IOError" }
|
||||
};
|
||||
|
||||
static elementsN(excData);
|
||||
|
||||
#define ENO(id) { Errno##id, #id }
|
||||
|
||||
static const MrbExcData enoExcData[] =
|
||||
{
|
||||
ENO(E2BIG),
|
||||
ENO(EACCES),
|
||||
ENO(EAGAIN),
|
||||
ENO(EBADF),
|
||||
ENO(ECHILD),
|
||||
ENO(EDEADLOCK),
|
||||
ENO(EDOM),
|
||||
ENO(EEXIST),
|
||||
ENO(EINVAL),
|
||||
ENO(EMFILE),
|
||||
ENO(ENOENT),
|
||||
ENO(ENOEXEC),
|
||||
ENO(ENOMEM),
|
||||
ENO(ENOSPC),
|
||||
ENO(ERANGE),
|
||||
ENO(EXDEV)
|
||||
};
|
||||
|
||||
static elementsN(enoExcData);
|
||||
|
||||
MrbData::MrbData(mrb_state *mrb)
|
||||
{
|
||||
int arena = mrb_gc_arena_save(mrb);
|
||||
|
||||
for (int i = 0; i < excDataN; ++i)
|
||||
exc[excData[i].ind] = mrb_define_class(mrb, excData[i].str, mrb->eException_class);
|
||||
|
||||
RClass *errnoMod = mrb_define_module(mrb, "Errno");
|
||||
|
||||
for (int i = 0; i < enoExcDataN; ++i)
|
||||
exc[enoExcData[i].ind] =
|
||||
mrb_define_class_under(mrb, errnoMod, enoExcData[i].str, mrb->eStandardError_class);
|
||||
|
||||
exc[TypeError] = mrb_class_get(mrb, "TypeError");
|
||||
exc[ArgumentError] = mrb_class_get(mrb, "ArgumentError");
|
||||
|
||||
for (int i = 0; i < symDataN; ++i)
|
||||
symbols[symData[i].ind] = mrb_intern(mrb, symData[i].str);
|
||||
|
||||
mrb_gc_arena_restore(mrb, arena);
|
||||
}
|
||||
|
||||
//enum Type
|
||||
//{
|
||||
// RGSSError,
|
||||
// NoFileError,
|
||||
// IOError,
|
||||
|
||||
// /* Already defined by ruby */
|
||||
// TypeError,
|
||||
// ArgumentError,
|
||||
|
||||
// /* New types introduced in mkxp */
|
||||
// PHYSFSError,
|
||||
// SDLError
|
||||
//};
|
||||
|
||||
/* Indexed with Exception::Type */
|
||||
static const MrbException excToMrbExc[] =
|
||||
{
|
||||
RGSS, /* RGSSError */
|
||||
ErrnoENOENT, /* NoFileError */
|
||||
IO,
|
||||
|
||||
TypeError,
|
||||
ArgumentError,
|
||||
|
||||
PHYSFS, /* PHYSFSError */
|
||||
SDL, /* SDLError */
|
||||
};
|
||||
|
||||
void raiseMrbExc(mrb_state *mrb, const Exception &exc)
|
||||
{
|
||||
MrbData *data = getMrbData(mrb);
|
||||
RClass *excClass = data->exc[excToMrbExc[exc.type]];
|
||||
|
||||
static char buffer[512];
|
||||
exc.snprintf(buffer, sizeof(buffer));
|
||||
mrb_raise(mrb, excClass, buffer);
|
||||
}
|
||||
|
||||
MRB_METHOD_PUB(inspectObject)
|
||||
{
|
||||
mrb_value priv = mrb_obj_iv_get(mrb, mrb_obj_ptr(self), getSym(mrb, CSpriv_iv));
|
||||
|
||||
static char buffer[64];
|
||||
sprintf(buffer, "#<%s:%p>", DATA_TYPE(priv)->struct_name, DATA_PTR(priv));
|
||||
|
||||
return mrb_str_new_cstr(mrb, buffer);
|
||||
}
|
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
** binding-util.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BINDINGUTIL_H
|
||||
#define BINDINGUTIL_H
|
||||
|
||||
#include "mruby.h"
|
||||
#include "mruby/data.h"
|
||||
#include "mruby/variable.h"
|
||||
#include "mruby/class.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
enum CommonSymbol
|
||||
{
|
||||
CSpriv_iv = 0, /* private data */
|
||||
|
||||
/* From here on out all symbols
|
||||
* have implicit '@' prefix */
|
||||
CSfont,
|
||||
CSviewport,
|
||||
CSbitmap,
|
||||
CScolor,
|
||||
CStone,
|
||||
CSrect,
|
||||
CSsrc_rect,
|
||||
CStileset,
|
||||
CSautotiles,
|
||||
CSmap_data,
|
||||
CSflash_data,
|
||||
CSpriorities,
|
||||
CSwindowskin,
|
||||
CScontents,
|
||||
CScursor_rect,
|
||||
CSpath,
|
||||
CSarray,
|
||||
CSdefault_color,
|
||||
|
||||
CommonSymbolsMax
|
||||
};
|
||||
|
||||
enum MrbException
|
||||
{
|
||||
Shutdown = 0,
|
||||
RGSS,
|
||||
PHYSFS,
|
||||
SDL,
|
||||
|
||||
ErrnoE2BIG,
|
||||
ErrnoEACCES,
|
||||
ErrnoEAGAIN,
|
||||
ErrnoEBADF,
|
||||
ErrnoECHILD,
|
||||
ErrnoEDEADLOCK,
|
||||
ErrnoEDOM,
|
||||
ErrnoEEXIST,
|
||||
ErrnoEINVAL,
|
||||
ErrnoEMFILE,
|
||||
ErrnoENOENT,
|
||||
ErrnoENOEXEC,
|
||||
ErrnoENOMEM,
|
||||
ErrnoENOSPC,
|
||||
ErrnoERANGE,
|
||||
ErrnoEXDEV,
|
||||
|
||||
IO,
|
||||
|
||||
TypeError,
|
||||
ArgumentError,
|
||||
|
||||
MrbExceptionsMax
|
||||
};
|
||||
|
||||
struct MrbData
|
||||
{
|
||||
RClass *exc[MrbExceptionsMax];
|
||||
/* I'll leave the usage of these syms to later,
|
||||
* so I can measure how much of a speed difference they make */
|
||||
mrb_sym symbols[CommonSymbolsMax];
|
||||
|
||||
MrbData(mrb_state *mrb);
|
||||
};
|
||||
|
||||
struct Exception;
|
||||
|
||||
void
|
||||
raiseMrbExc(mrb_state *mrb, const Exception &exc);
|
||||
|
||||
inline MrbData*
|
||||
getMrbData(mrb_state *mrb)
|
||||
{
|
||||
return static_cast<MrbData*>(mrb->ud);
|
||||
}
|
||||
|
||||
#define GUARD_EXC(exp) \
|
||||
{ try { exp } catch (Exception &exc) { raiseMrbExc(mrb, exc); } }
|
||||
|
||||
#define DECL_TYPE(_Type) \
|
||||
extern const mrb_data_type _Type##Type
|
||||
|
||||
#define DEF_TYPE(_Type) \
|
||||
extern const mrb_data_type _Type##Type = \
|
||||
{ \
|
||||
#_Type, \
|
||||
freeInstance<_Type> \
|
||||
}
|
||||
|
||||
#define MRB_METHOD_PUB(name) \
|
||||
mrb_value name(mrb_state *mrb, mrb_value self)
|
||||
|
||||
#define MRB_METHOD(name) static MRB_METHOD_PUB(name)
|
||||
|
||||
#define MRB_UNUSED_PARAM \
|
||||
{ (void) mrb; (void) self; }
|
||||
|
||||
/* If we're not binding a disposable class,
|
||||
* we want to #undef DEF_PROP_CHK_DISP */
|
||||
#define DEF_PROP_CHK_DISP \
|
||||
checkDisposed(mrb, k, DISP_CLASS_NAME);
|
||||
|
||||
#define DEF_PROP_OBJ(Klass, PropKlass, PropName, prop_iv) \
|
||||
MRB_METHOD(Klass##Get##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); (void) k; \
|
||||
DEF_PROP_CHK_DISP \
|
||||
return getProperty(mrb, self, prop_iv); \
|
||||
} \
|
||||
MRB_METHOD(Klass##Set##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); \
|
||||
mrb_value propObj; \
|
||||
PropKlass *prop; \
|
||||
mrb_get_args(mrb, "o", &propObj); \
|
||||
prop = getPrivateDataCheck<PropKlass>(mrb, propObj, PropKlass##Type); \
|
||||
GUARD_EXC( k->set##PropName(prop); ) \
|
||||
setProperty(mrb, self, prop_iv, propObj); \
|
||||
return propObj; \
|
||||
}
|
||||
|
||||
/* Object property with allowed NIL */
|
||||
#define DEF_PROP_OBJ_NIL(Klass, PropKlass, PropName, prop_iv) \
|
||||
MRB_METHOD(Klass##Get##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); (void) k; \
|
||||
DEF_PROP_CHK_DISP \
|
||||
return getProperty(mrb, self, prop_iv); \
|
||||
} \
|
||||
MRB_METHOD(Klass##Set##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); \
|
||||
mrb_value propObj; \
|
||||
PropKlass *prop; \
|
||||
mrb_get_args(mrb, "o", &propObj); \
|
||||
if (mrb_nil_p(propObj)) \
|
||||
prop = 0; \
|
||||
else \
|
||||
prop = getPrivateDataCheck<PropKlass>(mrb, propObj, PropKlass##Type); \
|
||||
GUARD_EXC( k->set##PropName(prop); ) \
|
||||
setProperty(mrb, self, prop_iv, propObj); \
|
||||
return mrb_nil_value(); \
|
||||
}
|
||||
|
||||
#define DEF_PROP(Klass, mrb_type, PropName, arg_type, conv_t) \
|
||||
MRB_METHOD(Klass##Get##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); \
|
||||
DEF_PROP_CHK_DISP \
|
||||
return mrb_##conv_t##_value(k->get##PropName()); \
|
||||
} \
|
||||
MRB_METHOD(Klass##Set##PropName) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); \
|
||||
mrb_type value; \
|
||||
mrb_get_args(mrb, arg_type, &value); \
|
||||
GUARD_EXC( k->set##PropName(value); ) \
|
||||
return mrb_##conv_t##_value(value); \
|
||||
}
|
||||
|
||||
#define DEF_PROP_I(Klass, PropName) \
|
||||
DEF_PROP(Klass, mrb_int, PropName, "i", fixnum)
|
||||
|
||||
#define DEF_PROP_F(Klass, PropName) \
|
||||
DEF_PROP(Klass, mrb_float, PropName, "f", _float)
|
||||
|
||||
#define DEF_PROP_B(Klass, PropName) \
|
||||
DEF_PROP(Klass, mrb_bool, PropName, "b", bool)
|
||||
|
||||
#define CLONE_FUN(Klass) \
|
||||
MRB_METHOD(Klass##Clone) \
|
||||
{ \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); \
|
||||
mrb_value dupObj = mrb_obj_clone(mrb, self); \
|
||||
Klass *dupK = new Klass(*k); \
|
||||
setPrivateData(mrb, dupObj, dupK, Klass##Type); \
|
||||
return dupObj; \
|
||||
}
|
||||
|
||||
#define MARSH_LOAD_FUN(Klass) \
|
||||
MRB_METHOD(Klass##Load) \
|
||||
{ \
|
||||
return objectLoad<Klass>(mrb, self, Klass##Type); \
|
||||
}
|
||||
|
||||
#define INIT_PROP_BIND(Klass, PropName, prop_name_s) \
|
||||
{ \
|
||||
mrb_define_method(mrb, klass, prop_name_s, Klass##Get##PropName, MRB_ARGS_NONE()); \
|
||||
mrb_define_method(mrb, klass, prop_name_s "=", Klass##Set##PropName, MRB_ARGS_REQ(1)); \
|
||||
}
|
||||
|
||||
static inline mrb_value
|
||||
mrb__float_value(mrb_float f)
|
||||
{
|
||||
mrb_value v;
|
||||
|
||||
MRB_SET_VALUE(v, MRB_TT_FLOAT, value.f, f);
|
||||
return v;
|
||||
}
|
||||
|
||||
inline mrb_sym
|
||||
getSym(mrb_state *mrb, CommonSymbol sym)
|
||||
{
|
||||
return getMrbData(mrb)->symbols[sym];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T *
|
||||
getPrivateData(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
mrb_value priv = mrb_obj_iv_get(mrb,
|
||||
mrb_obj_ptr(self),
|
||||
getSym(mrb, CSpriv_iv));
|
||||
|
||||
return static_cast<T*>(DATA_PTR(priv));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T *
|
||||
getPrivateDataCheck(mrb_state *mrb, mrb_value obj, const mrb_data_type &type)
|
||||
{
|
||||
static const char mesg[] = "wrong argument type %S (expected %S)";
|
||||
|
||||
if (mrb_type(obj) != MRB_TT_OBJECT)
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, mesg,
|
||||
mrb_str_new_cstr(mrb, (mrb_class_name(mrb, mrb_class(mrb, obj)))),
|
||||
mrb_str_new_cstr(mrb, type.struct_name));
|
||||
|
||||
RObject *objP = mrb_obj_ptr(obj);
|
||||
|
||||
if (!mrb_obj_iv_defined(mrb, objP, getSym(mrb, CSpriv_iv)))
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, mesg,
|
||||
mrb_str_new_cstr(mrb, (mrb_class_name(mrb, mrb_class(mrb, obj)))),
|
||||
mrb_str_new_cstr(mrb, type.struct_name));
|
||||
|
||||
mrb_value priv = mrb_obj_iv_get(mrb, objP, getSym(mrb, CSpriv_iv));
|
||||
|
||||
void *p = mrb_check_datatype(mrb, priv, &type);
|
||||
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
|
||||
inline void
|
||||
setPrivateData(mrb_state *mrb, mrb_value self, void *p, const mrb_data_type &type)
|
||||
{
|
||||
RData *data =
|
||||
mrb_data_object_alloc(mrb,
|
||||
mrb_obj_class(mrb, self),
|
||||
p,
|
||||
&type);
|
||||
|
||||
mrb_obj_iv_set(mrb,
|
||||
mrb_obj_ptr(self),
|
||||
getSym(mrb, CSpriv_iv),
|
||||
mrb_obj_value(data));
|
||||
}
|
||||
|
||||
|
||||
inline mrb_value
|
||||
wrapObject(mrb_state *mrb, void *p, const mrb_data_type &type)
|
||||
{
|
||||
RClass *c = mrb_class_get(mrb, type.struct_name);
|
||||
RObject *o = (RObject*) mrb_obj_alloc(mrb, MRB_TT_OBJECT, c);
|
||||
mrb_value obj = mrb_obj_value(o);
|
||||
|
||||
setPrivateData(mrb, obj, p, type);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline void
|
||||
wrapProperty(mrb_state *mrb, mrb_value self,
|
||||
void *prop, CommonSymbol iv, const mrb_data_type &type)
|
||||
{
|
||||
mrb_value propObj = wrapObject(mrb, prop, type);
|
||||
|
||||
mrb_obj_iv_set(mrb,
|
||||
mrb_obj_ptr(self),
|
||||
getSym(mrb, iv),
|
||||
propObj);
|
||||
}
|
||||
|
||||
inline void
|
||||
wrapNilProperty(mrb_state *mrb, mrb_value self, CommonSymbol iv)
|
||||
{
|
||||
mrb_obj_iv_set(mrb,
|
||||
mrb_obj_ptr(self),
|
||||
getSym(mrb, iv),
|
||||
mrb_nil_value());
|
||||
}
|
||||
|
||||
inline mrb_value
|
||||
getProperty(mrb_state *mrb, mrb_value self, CommonSymbol iv)
|
||||
{
|
||||
return mrb_obj_iv_get(mrb,
|
||||
mrb_obj_ptr(self),
|
||||
getSym(mrb, iv));
|
||||
}
|
||||
|
||||
inline void
|
||||
setProperty(mrb_state *mrb, mrb_value self,
|
||||
CommonSymbol iv, mrb_value propObject)
|
||||
{
|
||||
mrb_obj_iv_set(mrb,
|
||||
mrb_obj_ptr(self),
|
||||
getSym(mrb, iv),
|
||||
propObject);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
freeInstance(mrb_state *, void *instance)
|
||||
{
|
||||
delete static_cast<T*>(instance);
|
||||
}
|
||||
|
||||
inline mrb_value
|
||||
mrb_bool_value(bool value)
|
||||
{
|
||||
return value ? mrb_true_value() : mrb_false_value();
|
||||
}
|
||||
|
||||
inline bool
|
||||
_mrb_bool(mrb_value o)
|
||||
{
|
||||
return mrb_test(o);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
inline mrb_value
|
||||
objectLoad(mrb_state *mrb, mrb_value self, const mrb_data_type &type)
|
||||
{
|
||||
RClass *klass = mrb_class_ptr(self);
|
||||
char *data;
|
||||
int data_len;
|
||||
mrb_get_args(mrb, "s", &data, &data_len);
|
||||
|
||||
RObject *obj = (RObject*) mrb_obj_alloc(mrb, MRB_TT_OBJECT, klass);
|
||||
mrb_value obj_value = mrb_obj_value(obj);
|
||||
|
||||
C *c = C::deserialize(data, data_len);
|
||||
|
||||
setPrivateData(mrb, obj_value, c, type);
|
||||
|
||||
return obj_value;
|
||||
}
|
||||
|
||||
MRB_METHOD_PUB(inspectObject);
|
||||
|
||||
#endif // BINDINGUTIL_H
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
** bitmap-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "font.h"
|
||||
#include "exception.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define DISP_CLASS_NAME "bitmap"
|
||||
|
||||
DEF_TYPE(Bitmap);
|
||||
|
||||
MRB_METHOD(bitmapInitialize)
|
||||
{
|
||||
Bitmap *b = 0;
|
||||
|
||||
if (mrb->c->ci->argc == 1)
|
||||
{
|
||||
char *filename;
|
||||
mrb_get_args(mrb, "z", &filename);
|
||||
|
||||
GUARD_EXC( b = new Bitmap(filename); )
|
||||
}
|
||||
else
|
||||
{
|
||||
mrb_int width, height;
|
||||
mrb_get_args(mrb, "ii", &width, &height);
|
||||
|
||||
b = new Bitmap(width, height);
|
||||
}
|
||||
|
||||
setPrivateData(mrb, self, b, BitmapType);
|
||||
|
||||
/* Wrap properties */
|
||||
Font *font = new Font();
|
||||
b->setFont(font);
|
||||
font->setColor(new Color(*font->getColor()));
|
||||
|
||||
wrapProperty(mrb, self, font, CSfont, FontType);
|
||||
wrapProperty(mrb, getProperty(mrb, self, CSfont), font->getColor(), CScolor, ColorType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapWidth)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_int value = 0;
|
||||
GUARD_EXC( value = b->width(); )
|
||||
|
||||
return mrb_fixnum_value(value);
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapHeight)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_int value = 0;
|
||||
GUARD_EXC( value = b->height(); )
|
||||
|
||||
return mrb_fixnum_value(value);
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapRect)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
IntRect rect;
|
||||
GUARD_EXC( rect = b->rect(); )
|
||||
|
||||
Rect *r = new Rect(rect);
|
||||
|
||||
return wrapObject(mrb, r, RectType);
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapBlt)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_int x, y;
|
||||
mrb_value srcObj;
|
||||
mrb_value srcRectObj;
|
||||
mrb_int opacity = 255;
|
||||
|
||||
Bitmap *src;
|
||||
Rect *srcRect;
|
||||
|
||||
mrb_get_args(mrb, "iioo|i", &x, &y, &srcObj, &srcRectObj, &opacity);
|
||||
|
||||
src = getPrivateDataCheck<Bitmap>(mrb, srcObj, BitmapType);
|
||||
srcRect = getPrivateDataCheck<Rect>(mrb, srcRectObj, RectType);
|
||||
|
||||
GUARD_EXC( b->blt(x, y, *src, srcRect->toIntRect(), opacity); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapStretchBlt)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_value destRectObj;
|
||||
mrb_value srcObj;
|
||||
mrb_value srcRectObj;
|
||||
mrb_int opacity = 255;
|
||||
|
||||
Bitmap *src;
|
||||
Rect *destRect, *srcRect;
|
||||
|
||||
mrb_get_args(mrb, "ooo|i", &destRectObj, &srcObj, &srcRectObj);
|
||||
|
||||
src = getPrivateDataCheck<Bitmap>(mrb, srcObj, BitmapType);
|
||||
destRect = getPrivateDataCheck<Rect>(mrb, destRectObj, RectType);
|
||||
srcRect = getPrivateDataCheck<Rect>(mrb, srcRectObj, RectType);
|
||||
|
||||
GUARD_EXC( b->stretchBlt(destRect->toIntRect(), *src, srcRect->toIntRect(), opacity); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapFillRect)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_value colorObj;
|
||||
Color *color;
|
||||
|
||||
if (mrb->c->ci->argc == 2)
|
||||
{
|
||||
mrb_value rectObj;
|
||||
Rect *rect;
|
||||
|
||||
mrb_get_args(mrb, "oo", &rectObj, &colorObj);
|
||||
|
||||
rect = getPrivateDataCheck<Rect>(mrb, rectObj, RectType);
|
||||
color = getPrivateDataCheck<Color>(mrb, colorObj, ColorType);
|
||||
|
||||
GUARD_EXC( b->fillRect(rect->toIntRect(), color->norm); )
|
||||
}
|
||||
else
|
||||
{
|
||||
mrb_int x, y, width, height;
|
||||
|
||||
mrb_get_args(mrb, "iiiio", &x, &y, &width, &height, &colorObj);
|
||||
|
||||
color = getPrivateDataCheck<Color>(mrb, colorObj, ColorType);
|
||||
|
||||
GUARD_EXC( b->fillRect(x, y, width, height, color->norm); )
|
||||
}
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapClear)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
GUARD_EXC( b->clear(); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapGetPixel)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_int x, y;
|
||||
|
||||
mrb_get_args(mrb, "ii", &x, &y);
|
||||
|
||||
GUARD_EXC(
|
||||
if (x < 0 || y < 0 || x >= b->width() || y >= b->height())
|
||||
return mrb_nil_value();
|
||||
)
|
||||
|
||||
Vec4 value;
|
||||
GUARD_EXC( value = b->getPixel(x, y); )
|
||||
|
||||
Color *color = new Color(value);
|
||||
|
||||
return wrapObject(mrb, color, ColorType);
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapSetPixel)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_int x, y;
|
||||
mrb_value colorObj;
|
||||
|
||||
Color *color;
|
||||
|
||||
mrb_get_args(mrb, "iio", &x, &y, &colorObj);
|
||||
|
||||
color = getPrivateDataCheck<Color>(mrb, colorObj, ColorType);
|
||||
|
||||
GUARD_EXC( b->setPixel(x, y, color->norm); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapHueChange)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_int hue;
|
||||
|
||||
mrb_get_args(mrb, "i", &hue);
|
||||
|
||||
GUARD_EXC( b->hueChange(hue); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapDrawText)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
char *str;
|
||||
mrb_int align = Bitmap::Left;
|
||||
|
||||
int argc = mrb->c->ci->argc;
|
||||
if (argc == 2 || argc == 3)
|
||||
{
|
||||
mrb_value rectObj;
|
||||
Rect *rect;
|
||||
|
||||
mrb_get_args(mrb, "oz|i", &rectObj, &str, &align);
|
||||
|
||||
rect = getPrivateDataCheck<Rect>(mrb, rectObj, RectType);
|
||||
|
||||
GUARD_EXC( b->drawText(rect->toIntRect(), str, align); )
|
||||
}
|
||||
else
|
||||
{
|
||||
mrb_int x, y, width, height;
|
||||
|
||||
mrb_get_args(mrb, "iiiiz|i", &x, &y, &width, &height, &str, &align);
|
||||
|
||||
GUARD_EXC( b->drawText(x, y, width, height, str, align); )
|
||||
}
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapTextSize)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
char *str;
|
||||
|
||||
mrb_get_args(mrb, "z", &str);
|
||||
|
||||
IntRect value;
|
||||
GUARD_EXC( value = b->textSize(str); )
|
||||
|
||||
Rect *rect = new Rect(value);
|
||||
|
||||
return wrapObject(mrb, rect, RectType);
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapGetFont)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
checkDisposed(mrb, b, "bitmap");
|
||||
|
||||
return getProperty(mrb, self, CSfont);
|
||||
}
|
||||
|
||||
MRB_METHOD(bitmapSetFont)
|
||||
{
|
||||
Bitmap *b = getPrivateData<Bitmap>(mrb, self);
|
||||
|
||||
mrb_value fontObj;
|
||||
Font *font;
|
||||
|
||||
mrb_get_args(mrb, "o", &fontObj);
|
||||
|
||||
font = getPrivateDataCheck<Font>(mrb, fontObj, FontType);
|
||||
|
||||
GUARD_EXC( b->setFont(font); )
|
||||
setProperty(mrb, self, CSfont, fontObj);
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
CLONE_FUN(Bitmap)
|
||||
|
||||
|
||||
void
|
||||
bitmapBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "Bitmap", 0);
|
||||
|
||||
disposableBindingInit<Bitmap>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", bitmapInitialize, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
|
||||
|
||||
mrb_define_method(mrb, klass, "width", bitmapWidth, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "height", bitmapHeight, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "rect", bitmapRect, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "blt", bitmapBlt, MRB_ARGS_REQ(4) | MRB_ARGS_OPT(1));
|
||||
mrb_define_method(mrb, klass, "stretch_blt", bitmapStretchBlt, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1));
|
||||
mrb_define_method(mrb, klass, "fill_rect", bitmapFillRect, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(2));
|
||||
mrb_define_method(mrb, klass, "clear", bitmapClear, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "get_pixel", bitmapGetPixel, MRB_ARGS_REQ(2));
|
||||
mrb_define_method(mrb, klass, "set_pixel", bitmapSetPixel, MRB_ARGS_REQ(3));
|
||||
mrb_define_method(mrb, klass, "hue_change", bitmapHueChange, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, klass, "draw_text", bitmapDrawText, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(4));
|
||||
mrb_define_method(mrb, klass, "text_size", bitmapTextSize, MRB_ARGS_REQ(1));
|
||||
|
||||
mrb_define_method(mrb, klass, "font", bitmapGetFont, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "font=", bitmapSetFont, MRB_ARGS_REQ(1));
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "clone", BitmapClone, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
** disposable-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DISPOSABLEBINDING_H
|
||||
#define DISPOSABLEBINDING_H
|
||||
|
||||
#include "disposable.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(disposableDispose)
|
||||
{
|
||||
Disposable *d = getPrivateData<C>(mrb, self);
|
||||
|
||||
d->dispose();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(disposableDisposed)
|
||||
{
|
||||
Disposable *d = getPrivateData<C>(mrb, self);
|
||||
|
||||
return mrb_bool_value(d->isDisposed());
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static void disposableBindingInit(mrb_state *mrb, RClass *klass)
|
||||
{
|
||||
mrb_define_method(mrb, klass, "dispose", disposableDispose<C>, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "disposed?", disposableDisposed<C>, MRB_ARGS_NONE());
|
||||
}
|
||||
|
||||
inline void checkDisposed(mrb_state *mrb, Disposable *d, const char *klassName)
|
||||
{
|
||||
MrbData *data = getMrbData(mrb);
|
||||
|
||||
if (d->isDisposed())
|
||||
mrb_raisef(mrb, data->exc[RGSS], "disposed %S",
|
||||
mrb_str_new_static(mrb, klassName, strlen(klassName)));
|
||||
}
|
||||
|
||||
#endif // DISPOSABLEBINDING_H
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
** etc-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "etc.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
#include "serializable-binding.h"
|
||||
#include "mruby/class.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define ATTR_RW(Type, attr, arg_type, mrb_val, arg_t_s) \
|
||||
MRB_METHOD(Type##Get_##attr) \
|
||||
{ \
|
||||
Type *p = getPrivateData<Type>(mrb, self); \
|
||||
\
|
||||
return mrb_##mrb_val##_value(p->attr); \
|
||||
} \
|
||||
\
|
||||
MRB_METHOD(Type##Set_##attr) \
|
||||
{ \
|
||||
Type *p = getPrivateData<Type>(mrb, self); \
|
||||
\
|
||||
arg_type arg; \
|
||||
mrb_get_args(mrb, arg_t_s, &arg); \
|
||||
\
|
||||
p->attr = arg; \
|
||||
UPDATE_F \
|
||||
\
|
||||
return mrb_##mrb_val##_value(arg); \
|
||||
}
|
||||
|
||||
#define EQUAL_FUN(Typ) \
|
||||
MRB_METHOD(Typ##Equal) \
|
||||
{ \
|
||||
Typ *p = getPrivateData<Typ>(mrb, self); \
|
||||
mrb_value otherObj; \
|
||||
Typ *other; \
|
||||
mrb_get_args(mrb, "o", &otherObj); \
|
||||
RClass *klass = mrb_obj_class(mrb, self); \
|
||||
RClass *otherKlass = mrb_obj_class(mrb, otherObj); \
|
||||
if (klass != otherKlass) \
|
||||
return mrb_false_value(); \
|
||||
other = getPrivateDataCheck<Typ>(mrb, otherObj, Typ##Type); \
|
||||
return mrb_bool_value(*p == *other); \
|
||||
}
|
||||
|
||||
#define ATTR_FLOAT_RW(Type, attr) ATTR_RW(Type, attr, mrb_float, _float, "f")
|
||||
#define ATTR_INT_RW(Type, attr) ATTR_RW(Type, attr, mrb_int, fixnum, "i")
|
||||
|
||||
#define UPDATE_F p->updateInternal();
|
||||
ATTR_FLOAT_RW(Color, red)
|
||||
ATTR_FLOAT_RW(Color, green)
|
||||
ATTR_FLOAT_RW(Color, blue)
|
||||
ATTR_FLOAT_RW(Color, alpha)
|
||||
|
||||
ATTR_FLOAT_RW(Tone, red)
|
||||
ATTR_FLOAT_RW(Tone, green)
|
||||
ATTR_FLOAT_RW(Tone, blue)
|
||||
ATTR_FLOAT_RW(Tone, gray)
|
||||
|
||||
#undef UPDATE_F
|
||||
#define UPDATE_F
|
||||
ATTR_INT_RW(Rect, x)
|
||||
ATTR_INT_RW(Rect, y)
|
||||
ATTR_INT_RW(Rect, width)
|
||||
ATTR_INT_RW(Rect, height)
|
||||
|
||||
EQUAL_FUN(Color)
|
||||
EQUAL_FUN(Tone)
|
||||
EQUAL_FUN(Rect)
|
||||
|
||||
DEF_TYPE(Color);
|
||||
DEF_TYPE(Tone);
|
||||
DEF_TYPE(Rect);
|
||||
|
||||
#define INIT_FUN(Klass, param_type, param_t_s, last_param_def) \
|
||||
MRB_METHOD(Klass##Initialize) \
|
||||
{ \
|
||||
param_type p1, p2, p3, p4 = last_param_def; \
|
||||
mrb_get_args(mrb, param_t_s, &p1, &p2, &p3, &p4); \
|
||||
Klass *k = new Klass(p1, p2, p3, p4); \
|
||||
setPrivateData(mrb, self, k, Klass##Type); \
|
||||
return self; \
|
||||
}
|
||||
|
||||
INIT_FUN(Color, mrb_float, "fff|f", 255)
|
||||
INIT_FUN(Tone, mrb_float, "fff|f", 0)
|
||||
INIT_FUN(Rect, mrb_int, "iiii", 0)
|
||||
|
||||
#define SET_FUN(Klass, param_type, param_t_s, last_param_def) \
|
||||
MRB_METHOD(Klass##Set) \
|
||||
{ \
|
||||
param_type p1, p2, p3, p4 = last_param_def; \
|
||||
mrb_get_args(mrb, param_t_s, &p1, &p2, &p3, &p4); \
|
||||
Klass *k = getPrivateData<Klass>(mrb, self); \
|
||||
k->set(p1, p2, p3, p4); \
|
||||
return self; \
|
||||
}
|
||||
|
||||
SET_FUN(Color, mrb_float, "fff|f", 255)
|
||||
SET_FUN(Tone, mrb_float, "fff|f", 0)
|
||||
SET_FUN(Rect, mrb_int, "iiii", 0)
|
||||
|
||||
MRB_METHOD(RectEmpty)
|
||||
{
|
||||
Rect *r = getPrivateData<Rect>(mrb, self);
|
||||
|
||||
r->empty();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static char buffer[64];
|
||||
|
||||
MRB_METHOD(ColorStringify)
|
||||
{
|
||||
Color *c = getPrivateData<Color>(mrb, self);
|
||||
|
||||
sprintf(buffer, "(%f, %f, %f, %f)", c->red, c->green, c->blue, c->alpha);
|
||||
|
||||
return mrb_str_new_cstr(mrb, buffer);
|
||||
}
|
||||
|
||||
MRB_METHOD(ToneStringify)
|
||||
{
|
||||
Tone *t = getPrivateData<Tone>(mrb, self);
|
||||
|
||||
sprintf(buffer, "(%f, %f, %f, %f)", t->red, t->green, t->blue, t->gray);
|
||||
|
||||
return mrb_str_new_cstr(mrb, buffer);
|
||||
}
|
||||
|
||||
MRB_METHOD(RectStringify)
|
||||
{
|
||||
Rect *r = getPrivateData<Rect>(mrb, self);
|
||||
|
||||
sprintf(buffer, "(%d, %d, %d, %d)", r->x, r->y, r->width, r->height);
|
||||
|
||||
return mrb_str_new_cstr(mrb, buffer);
|
||||
}
|
||||
|
||||
MARSH_LOAD_FUN(Color)
|
||||
MARSH_LOAD_FUN(Tone)
|
||||
MARSH_LOAD_FUN(Rect)
|
||||
|
||||
CLONE_FUN(Tone)
|
||||
CLONE_FUN(Color)
|
||||
CLONE_FUN(Rect)
|
||||
|
||||
#define MRB_ATTR_R(Class, attr) mrb_define_method(mrb, klass, #attr, Class##Get_##attr, MRB_ARGS_NONE())
|
||||
#define MRB_ATTR_W(Class, attr) mrb_define_method(mrb, klass, #attr "=", Class##Set_##attr, MRB_ARGS_REQ(1))
|
||||
#define MRB_ATTR_RW(Class, attr) { MRB_ATTR_R(Class, attr); MRB_ATTR_W(Class, attr); }
|
||||
|
||||
#define MRB_ATTR_RW_A(Class, attr, alias) \
|
||||
{ \
|
||||
mrb_define_method(mrb, klass, #alias, Class##Get_##attr, MRB_ARGS_NONE()); \
|
||||
mrb_define_method(mrb, klass, #alias "=", Class##Set_##attr, MRB_ARGS_REQ(1)); \
|
||||
}
|
||||
|
||||
#define INIT_BIND(Klass) \
|
||||
{ \
|
||||
klass = mrb_define_class(mrb, #Klass, 0); \
|
||||
mrb_define_class_method(mrb, klass, "_load", Klass##Load, MRB_ARGS_REQ(1)); \
|
||||
serializableBindingInit<Klass>(mrb, klass); \
|
||||
mrb_define_method(mrb, klass, "initialize", Klass##Initialize, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1)); \
|
||||
mrb_define_method(mrb, klass, "set", Klass##Set, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1)); \
|
||||
mrb_define_method(mrb, klass, "clone", Klass##Clone, MRB_ARGS_NONE()); \
|
||||
mrb_define_method(mrb, klass, "==", Klass##Equal, MRB_ARGS_REQ(1)); \
|
||||
mrb_define_method(mrb, klass, "to_s", Klass##Stringify, MRB_ARGS_NONE()); \
|
||||
mrb_define_method(mrb, klass, "inspect", Klass##Stringify, MRB_ARGS_NONE()); \
|
||||
}
|
||||
|
||||
void etcBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass;
|
||||
|
||||
INIT_BIND(Color);
|
||||
MRB_ATTR_RW(Color, red);
|
||||
MRB_ATTR_RW(Color, green);
|
||||
MRB_ATTR_RW(Color, blue);
|
||||
MRB_ATTR_RW(Color, alpha);
|
||||
|
||||
INIT_BIND(Tone);
|
||||
MRB_ATTR_RW(Tone, red);
|
||||
MRB_ATTR_RW(Tone, green);
|
||||
MRB_ATTR_RW(Tone, blue);
|
||||
MRB_ATTR_RW(Tone, gray);
|
||||
|
||||
INIT_BIND(Rect);
|
||||
MRB_ATTR_RW(Rect, x);
|
||||
MRB_ATTR_RW(Rect, y);
|
||||
MRB_ATTR_RW(Rect, width);
|
||||
MRB_ATTR_RW(Rect, height);
|
||||
mrb_define_method(mrb, klass, "empty", RectEmpty, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
** flashable-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FLASHABLEBINDING_H
|
||||
#define FLASHABLEBINDING_H
|
||||
|
||||
#include "flashable.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(flashableFlash)
|
||||
{
|
||||
Flashable *f = getPrivateData<C>(mrb, self);
|
||||
|
||||
mrb_value colorObj;
|
||||
mrb_int duration;
|
||||
|
||||
Color *color;
|
||||
|
||||
mrb_get_args(mrb, "oi", &colorObj, &duration);
|
||||
|
||||
if (mrb_nil_p(colorObj))
|
||||
{
|
||||
f->flash(0, duration);
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
color = getPrivateDataCheck<Color>(mrb, colorObj, ColorType);
|
||||
|
||||
f->flash(&color->norm, duration);
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(flashableUpdate)
|
||||
{
|
||||
Flashable *f = getPrivateData<C>(mrb, self);
|
||||
|
||||
f->update();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static void flashableBindingInit(mrb_state *mrb, RClass *klass)
|
||||
{
|
||||
mrb_define_method(mrb, klass, "flash", flashableFlash<C>, MRB_ARGS_REQ(2));
|
||||
mrb_define_method(mrb, klass, "update", flashableUpdate<C>, MRB_ARGS_NONE());
|
||||
}
|
||||
|
||||
#endif // FLASHABLEBINDING_H
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
** font-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "font.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include "mruby/string.h"
|
||||
|
||||
DEF_TYPE(Font);
|
||||
|
||||
MRB_METHOD(fontDoesExist)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
const char *name;
|
||||
mrb_get_args(mrb, "z", &name);
|
||||
|
||||
return mrb_bool_value(Font::doesExist(name));
|
||||
}
|
||||
|
||||
MRB_METHOD(fontInitialize)
|
||||
{
|
||||
char *name = 0;
|
||||
mrb_int size = 0;
|
||||
|
||||
mrb_get_args(mrb, "|zi", &name, &size);
|
||||
|
||||
Font *f = new Font(name, size);
|
||||
|
||||
setPrivateData(mrb, self, f, FontType);
|
||||
|
||||
/* Wrap property objects */
|
||||
f->setColor(new Color(*f->getColor()));
|
||||
wrapProperty(mrb, self, f->getColor(), CScolor, ColorType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
MRB_METHOD(FontGetName)
|
||||
{
|
||||
Font *f = getPrivateData<Font>(mrb, self);
|
||||
|
||||
return mrb_str_new_cstr(mrb, f->getName());
|
||||
}
|
||||
|
||||
MRB_METHOD(FontSetName)
|
||||
{
|
||||
Font *f = getPrivateData<Font>(mrb, self);
|
||||
|
||||
mrb_value name;
|
||||
mrb_get_args(mrb, "S", &name);
|
||||
|
||||
f->setName(RSTRING_PTR(name));
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
#undef DEF_PROP_CHK_DISP
|
||||
#define DEF_PROP_CHK_DISP
|
||||
|
||||
DEF_PROP_I(Font, Size)
|
||||
DEF_PROP_B(Font, Bold)
|
||||
DEF_PROP_B(Font, Italic)
|
||||
DEF_PROP_OBJ(Font, Color, Color, CScolor)
|
||||
|
||||
#define DEF_KLASS_PROP(Klass, mrb_type, PropName, arg_type, conv_t) \
|
||||
static mrb_value \
|
||||
Klass##Get##PropName(mrb_state *, mrb_value) \
|
||||
{ \
|
||||
return mrb_##conv_t##_value(Klass::get##PropName()); \
|
||||
} \
|
||||
static mrb_value \
|
||||
Klass##Set##PropName(mrb_state *mrb, mrb_value) \
|
||||
{ \
|
||||
mrb_type value; \
|
||||
mrb_get_args(mrb, arg_type, &value); \
|
||||
Klass::set##PropName(value); \
|
||||
return mrb_##conv_t##_value(value); \
|
||||
}
|
||||
|
||||
DEF_KLASS_PROP(Font, mrb_int, DefaultSize, "i", fixnum)
|
||||
DEF_KLASS_PROP(Font, mrb_bool, DefaultBold, "b", bool)
|
||||
DEF_KLASS_PROP(Font, mrb_bool, DefaultItalic, "b", bool)
|
||||
|
||||
MRB_METHOD(FontGetDefaultName)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
return mrb_str_new_cstr(mrb, Font::getDefaultName());
|
||||
}
|
||||
|
||||
MRB_METHOD(FontSetDefaultName)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
mrb_value nameObj;
|
||||
mrb_get_args(mrb, "S", &nameObj);
|
||||
|
||||
Font::setDefaultName(RSTRING_PTR(nameObj));
|
||||
|
||||
return nameObj;
|
||||
}
|
||||
|
||||
MRB_METHOD(FontGetDefaultColor)
|
||||
{
|
||||
return getProperty(mrb, self, CSdefault_color);
|
||||
}
|
||||
|
||||
MRB_METHOD(FontSetDefaultColor)
|
||||
{
|
||||
mrb_value colorObj;
|
||||
mrb_get_args(mrb, "o", &colorObj);
|
||||
|
||||
Color *c = getPrivateDataCheck<Color>(mrb, colorObj, ColorType);
|
||||
|
||||
Font::setDefaultColor(c);
|
||||
setProperty(mrb, self, CSdefault_color, colorObj);
|
||||
|
||||
return colorObj;
|
||||
}
|
||||
|
||||
#define INIT_KLASS_PROP_BIND(Klass, PropName, prop_name_s) \
|
||||
{ \
|
||||
mrb_define_class_method(mrb, klass, prop_name_s, Klass##Get##PropName, MRB_ARGS_NONE()); \
|
||||
mrb_define_class_method(mrb, klass, prop_name_s "=", Klass##Set##PropName, MRB_ARGS_REQ(1)); \
|
||||
}
|
||||
|
||||
void
|
||||
fontBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "Font", 0);
|
||||
|
||||
Font::setDefaultColor(new Color(*Font::getDefaultColor()));
|
||||
wrapProperty(mrb, mrb_obj_value(klass), Font::getDefaultColor(), CSdefault_color, ColorType);
|
||||
|
||||
mrb_define_class_method(mrb, klass, "exist?", fontDoesExist, MRB_ARGS_REQ(1));
|
||||
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultName, "default_name");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultSize, "default_size");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultBold, "default_bold");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultItalic, "default_italic");
|
||||
INIT_KLASS_PROP_BIND(Font, DefaultColor, "default_color");
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", fontInitialize, MRB_ARGS_OPT(2));
|
||||
|
||||
INIT_PROP_BIND(Font, Name, "name");
|
||||
INIT_PROP_BIND(Font, Size, "size");
|
||||
INIT_PROP_BIND(Font, Bold, "bold");
|
||||
INIT_PROP_BIND(Font, Italic, "italic");
|
||||
INIT_PROP_BIND(Font, Color, "color");
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
** graphics-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "graphics.h"
|
||||
#include "globalstate.h"
|
||||
#include "mruby.h"
|
||||
#include "binding-util.h"
|
||||
#include "exception.h"
|
||||
|
||||
MRB_METHOD(graphicsUpdate)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
gState->graphics().update();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(graphicsFreeze)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
gState->graphics().freeze();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(graphicsTransition)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
mrb_int duration = 8;
|
||||
const char *filename = 0;
|
||||
mrb_int vague = 40;
|
||||
|
||||
mrb_get_args(mrb, "|izi", &duration, &filename, &vague);
|
||||
|
||||
GUARD_EXC( gState->graphics().transition(duration, filename, vague); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(graphicsFrameReset)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
gState->graphics().frameReset();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
#define DEF_GRA_PROP_I(PropName) \
|
||||
MRB_METHOD(graphics##Get##PropName) \
|
||||
{ \
|
||||
MRB_UNUSED_PARAM; \
|
||||
return mrb_fixnum_value(gState->graphics().get##PropName()); \
|
||||
} \
|
||||
MRB_METHOD(graphics##Set##PropName) \
|
||||
{ \
|
||||
MRB_UNUSED_PARAM; \
|
||||
mrb_int value; \
|
||||
mrb_get_args(mrb, "i", &value); \
|
||||
gState->graphics().set##PropName(value); \
|
||||
return mrb_nil_value(); \
|
||||
}
|
||||
|
||||
DEF_GRA_PROP_I(FrameRate)
|
||||
DEF_GRA_PROP_I(FrameCount)
|
||||
|
||||
MRB_METHOD(graphicsGetFullscreen)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
return mrb_bool_value(gState->graphics().getFullscreen());
|
||||
}
|
||||
|
||||
MRB_METHOD(graphicsSetFullscreen)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
mrb_bool mode;
|
||||
mrb_get_args(mrb, "b", &mode);
|
||||
|
||||
gState->graphics().setFullscreen(mode);
|
||||
|
||||
return mrb_bool_value(mode);
|
||||
}
|
||||
|
||||
#define INIT_GRA_PROP_BIND(PropName, prop_name_s) \
|
||||
{ \
|
||||
mrb_define_module_function(mrb, module, prop_name_s, graphics##Get##PropName, MRB_ARGS_NONE()); \
|
||||
mrb_define_module_function(mrb, module, prop_name_s "=", graphics##Set##PropName, MRB_ARGS_REQ(1)); \
|
||||
}
|
||||
|
||||
void graphicsBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *module = mrb_define_module(mrb, "Graphics");
|
||||
|
||||
mrb_define_module_function(mrb, module, "update", graphicsUpdate, MRB_ARGS_NONE());
|
||||
mrb_define_module_function(mrb, module, "freeze", graphicsFreeze, MRB_ARGS_NONE());
|
||||
mrb_define_module_function(mrb, module, "transition", graphicsTransition, MRB_ARGS_OPT(3));
|
||||
mrb_define_module_function(mrb, module, "frame_reset", graphicsFrameReset, MRB_ARGS_NONE());
|
||||
|
||||
INIT_GRA_PROP_BIND( FrameRate, "frame_rate" );
|
||||
INIT_GRA_PROP_BIND( FrameCount, "frame_count" );
|
||||
|
||||
INIT_GRA_PROP_BIND( Fullscreen, "fullscreen" );
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
** input-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "input.h"
|
||||
#include "globalstate.h"
|
||||
#include "exception.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
MRB_METHOD(inputUpdate)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
gState->input().update();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
MRB_METHOD(inputPress)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
mrb_int num;
|
||||
mrb_get_args(mrb, "i", &num);
|
||||
|
||||
Input::ButtonCode bc = (Input::ButtonCode) num;
|
||||
|
||||
return mrb_bool_value(gState->input().isPressed(bc));
|
||||
}
|
||||
|
||||
MRB_METHOD(inputTrigger)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
mrb_int num;
|
||||
mrb_get_args(mrb, "i", &num);
|
||||
|
||||
Input::ButtonCode bc = (Input::ButtonCode) num;
|
||||
|
||||
return mrb_bool_value(gState->input().isTriggered(bc));
|
||||
}
|
||||
|
||||
MRB_METHOD(inputRepeat)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
mrb_int num;
|
||||
mrb_get_args(mrb, "i", &num);
|
||||
|
||||
Input::ButtonCode bc = (Input::ButtonCode) num;
|
||||
|
||||
return mrb_bool_value(gState->input().isRepeated(bc));
|
||||
}
|
||||
|
||||
MRB_METHOD(inputDir4)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
return mrb_fixnum_value(gState->input().dir4Value());
|
||||
}
|
||||
|
||||
MRB_METHOD(inputDir8)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
return mrb_fixnum_value(gState->input().dir8Value());
|
||||
}
|
||||
|
||||
/* Non-standard extensions */
|
||||
MRB_METHOD(inputMouseX)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
return mrb_fixnum_value(gState->input().mouseX());
|
||||
}
|
||||
|
||||
MRB_METHOD(inputMouseY)
|
||||
{
|
||||
MRB_UNUSED_PARAM;
|
||||
|
||||
return mrb_fixnum_value(gState->input().mouseY());
|
||||
}
|
||||
|
||||
#define DEF_CONST_I(name, value) \
|
||||
mrb_const_set(mrb, mrb_obj_value(module), mrb_intern(mrb, name), mrb_fixnum_value(value))
|
||||
|
||||
void
|
||||
inputBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *module = mrb_define_module(mrb, "Input");
|
||||
|
||||
mrb_define_module_function(mrb, module, "update", inputUpdate, MRB_ARGS_NONE());
|
||||
mrb_define_module_function(mrb, module, "press?", inputPress, MRB_ARGS_REQ(1));
|
||||
mrb_define_module_function(mrb, module, "trigger?", inputTrigger, MRB_ARGS_REQ(1));
|
||||
mrb_define_module_function(mrb, module, "repeat?", inputRepeat, MRB_ARGS_REQ(1));
|
||||
mrb_define_module_function(mrb, module, "dir4", inputDir4, MRB_ARGS_NONE());
|
||||
mrb_define_module_function(mrb, module, "dir8", inputDir8, MRB_ARGS_NONE());
|
||||
|
||||
DEF_CONST_I("DOWN", Input::Down );
|
||||
DEF_CONST_I("LEFT", Input::Left );
|
||||
DEF_CONST_I("RIGHT", Input::Right);
|
||||
DEF_CONST_I("UP", Input::Up );
|
||||
|
||||
DEF_CONST_I("A", Input::A );
|
||||
DEF_CONST_I("B", Input::B );
|
||||
DEF_CONST_I("C", Input::C );
|
||||
DEF_CONST_I("X", Input::X );
|
||||
DEF_CONST_I("Y", Input::Y );
|
||||
DEF_CONST_I("Z", Input::Z );
|
||||
DEF_CONST_I("L", Input::L );
|
||||
DEF_CONST_I("R", Input::R );
|
||||
|
||||
DEF_CONST_I("SHIFT", Input::Shift);
|
||||
DEF_CONST_I("CTRL", Input::Ctrl );
|
||||
DEF_CONST_I("ALT", Input::Alt );
|
||||
|
||||
DEF_CONST_I("F5", Input::F5 );
|
||||
DEF_CONST_I("F6", Input::F6 );
|
||||
DEF_CONST_I("F7", Input::F7 );
|
||||
DEF_CONST_I("F8", Input::F8 );
|
||||
DEF_CONST_I("F9", Input::F9 );
|
||||
|
||||
mrb_define_module_function(mrb, module, "mouse_x", inputMouseX, MRB_ARGS_NONE());
|
||||
mrb_define_module_function(mrb, module, "mouse_y", inputMouseY, MRB_ARGS_NONE());
|
||||
|
||||
DEF_CONST_I("MOUSELEFT", Input::MouseLeft );
|
||||
DEF_CONST_I("MOUSEMIDDLE", Input::MouseMiddle);
|
||||
DEF_CONST_I("MOUSERIGHT", Input::MouseRight );
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
** plane-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "plane.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "viewportelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
DEF_TYPE(Plane);
|
||||
|
||||
MRB_METHOD(planeInitialize)
|
||||
{
|
||||
Plane *p = viewportElementInitialize<Plane>(mrb, self);
|
||||
|
||||
setPrivateData(mrb, self, p, PlaneType);
|
||||
|
||||
p->setColor(new Color);
|
||||
p->setTone(new Tone);
|
||||
|
||||
wrapNilProperty(mrb, self, CSbitmap);
|
||||
wrapProperty(mrb, self, p->getColor(), CScolor, ColorType);
|
||||
wrapProperty(mrb, self, p->getTone(), CStone, ToneType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "plane"
|
||||
|
||||
DEF_PROP_OBJ(Plane, Bitmap, Bitmap, CSbitmap)
|
||||
DEF_PROP_OBJ(Plane, Color, Color, CScolor)
|
||||
DEF_PROP_OBJ(Plane, Tone, Tone, CStone)
|
||||
|
||||
DEF_PROP_I(Plane, OX)
|
||||
DEF_PROP_I(Plane, OY)
|
||||
DEF_PROP_I(Plane, Opacity)
|
||||
DEF_PROP_I(Plane, BlendType)
|
||||
|
||||
DEF_PROP_F(Plane, ZoomX)
|
||||
DEF_PROP_F(Plane, ZoomY)
|
||||
|
||||
|
||||
void
|
||||
planeBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "Plane", 0);
|
||||
|
||||
disposableBindingInit<Plane> (mrb, klass);
|
||||
viewportElementBindingInit<Plane>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", planeInitialize, MRB_ARGS_OPT(1));
|
||||
|
||||
INIT_PROP_BIND( Plane, Bitmap, "bitmap" );
|
||||
INIT_PROP_BIND( Plane, OX, "ox" );
|
||||
INIT_PROP_BIND( Plane, OY, "oy" );
|
||||
INIT_PROP_BIND( Plane, ZoomX, "zoom_x" );
|
||||
INIT_PROP_BIND( Plane, ZoomY, "zoom_y" );
|
||||
INIT_PROP_BIND( Plane, Opacity, "opacity" );
|
||||
INIT_PROP_BIND( Plane, BlendType, "blend_type" );
|
||||
INIT_PROP_BIND( Plane, Color, "color" );
|
||||
INIT_PROP_BIND( Plane, Tone, "tone" );
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
** sceneelement-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCENEELEMENTBINDING_H
|
||||
#define SCENEELEMENTBINDING_H
|
||||
|
||||
#include "scene.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(sceneElementGetZ)
|
||||
{
|
||||
SceneElement *se = getPrivateData<C>(mrb, self);
|
||||
|
||||
mrb_int value = 0;
|
||||
GUARD_EXC( value = se->getZ(); )
|
||||
|
||||
return mrb_fixnum_value(value);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(sceneElementSetZ)
|
||||
{
|
||||
SceneElement *se = getPrivateData<C>(mrb, self);
|
||||
|
||||
mrb_int z;
|
||||
mrb_get_args(mrb, "i", &z);
|
||||
|
||||
GUARD_EXC( se->setZ(z); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(sceneElementGetVisible)
|
||||
{
|
||||
SceneElement *se = getPrivateData<C>(mrb, self);
|
||||
|
||||
bool value = false;
|
||||
GUARD_EXC( value = se->getVisible(); )
|
||||
|
||||
return mrb_bool_value(value);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(sceneElementSetVisible)
|
||||
{
|
||||
SceneElement *se = getPrivateData<C>(mrb, self);
|
||||
|
||||
mrb_value visibleObj;
|
||||
bool visible;
|
||||
|
||||
mrb_get_args(mrb, "o", &visibleObj);
|
||||
|
||||
visible = mrb_test(visibleObj);
|
||||
|
||||
GUARD_EXC( se->setVisible(visible); )
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void
|
||||
sceneElementBindingInit(mrb_state *mrb, RClass *klass)
|
||||
{
|
||||
mrb_define_method(mrb, klass, "z", sceneElementGetZ<C>, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "z=", sceneElementSetZ<C>, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, klass, "visible", sceneElementGetVisible<C>, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "visible=", sceneElementSetVisible<C>, MRB_ARGS_REQ(1));
|
||||
}
|
||||
|
||||
#endif // SCENEELEMENTBINDING_H
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
** serializable-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SERIALIZABLEBINDING_H
|
||||
#define SERIALIZABLEBINDING_H
|
||||
|
||||
#include "serializable.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
#include "mruby/string.h"
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(serializableDump)
|
||||
{
|
||||
Serializable *s = getPrivateData<C>(mrb, self);
|
||||
|
||||
int dataSize = s->serialSize();
|
||||
|
||||
mrb_value data = mrb_str_new(mrb, 0, dataSize);
|
||||
|
||||
s->serialize(RSTRING_PTR(data));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void
|
||||
serializableBindingInit(mrb_state *mrb, RClass *klass)
|
||||
{
|
||||
mrb_define_method(mrb, klass, "_dump", serializableDump<C>, MRB_ARGS_NONE());
|
||||
}
|
||||
|
||||
#endif // SERIALIZABLEBINDING_H
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
** sprite-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "sprite.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "flashable-binding.h"
|
||||
#include "sceneelement-binding.h"
|
||||
#include "viewportelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
DEF_TYPE(Sprite);
|
||||
|
||||
MRB_METHOD(spriteInitialize)
|
||||
{
|
||||
Sprite *s = viewportElementInitialize<Sprite>(mrb, self);
|
||||
|
||||
setPrivateData(mrb, self, s, SpriteType);
|
||||
|
||||
/* Wrap property objects */
|
||||
s->setSrcRect(new Rect);
|
||||
s->setColor(new Color);
|
||||
s->setTone(new Tone);
|
||||
|
||||
wrapNilProperty(mrb, self, CSbitmap);
|
||||
wrapProperty(mrb, self, s->getSrcRect(), CSsrc_rect, RectType);
|
||||
wrapProperty(mrb, self, s->getColor(), CScolor, ColorType);
|
||||
wrapProperty(mrb, self, s->getTone(), CStone, ToneType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "sprite"
|
||||
|
||||
DEF_PROP_OBJ_NIL(Sprite, Bitmap, Bitmap, CSbitmap)
|
||||
DEF_PROP_OBJ(Sprite, Rect, SrcRect, CSsrc_rect)
|
||||
DEF_PROP_OBJ(Sprite, Color, Color, CScolor)
|
||||
DEF_PROP_OBJ(Sprite, Tone, Tone, CStone)
|
||||
|
||||
DEF_PROP_I(Sprite, X)
|
||||
DEF_PROP_I(Sprite, Y)
|
||||
DEF_PROP_I(Sprite, OX)
|
||||
DEF_PROP_I(Sprite, OY)
|
||||
DEF_PROP_I(Sprite, BushDepth)
|
||||
DEF_PROP_I(Sprite, Opacity)
|
||||
DEF_PROP_I(Sprite, BlendType)
|
||||
|
||||
DEF_PROP_F(Sprite, ZoomX)
|
||||
DEF_PROP_F(Sprite, ZoomY)
|
||||
DEF_PROP_F(Sprite, Angle)
|
||||
|
||||
DEF_PROP_B(Sprite, Mirror)
|
||||
|
||||
void
|
||||
spriteBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "Sprite", 0);
|
||||
|
||||
disposableBindingInit <Sprite>(mrb, klass);
|
||||
flashableBindingInit <Sprite>(mrb, klass);
|
||||
viewportElementBindingInit<Sprite>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", spriteInitialize, MRB_ARGS_OPT(1));
|
||||
|
||||
INIT_PROP_BIND( Sprite, Bitmap, "bitmap" );
|
||||
INIT_PROP_BIND( Sprite, SrcRect, "src_rect" );
|
||||
INIT_PROP_BIND( Sprite, X, "x" );
|
||||
INIT_PROP_BIND( Sprite, Y, "y" );
|
||||
INIT_PROP_BIND( Sprite, OX, "ox" );
|
||||
INIT_PROP_BIND( Sprite, OY, "oy" );
|
||||
INIT_PROP_BIND( Sprite, ZoomX, "zoom_x" );
|
||||
INIT_PROP_BIND( Sprite, ZoomY, "zoom_y" );
|
||||
INIT_PROP_BIND( Sprite, Angle, "angle" );
|
||||
INIT_PROP_BIND( Sprite, Mirror, "mirror" );
|
||||
INIT_PROP_BIND( Sprite, BushDepth, "bush_depth" );
|
||||
INIT_PROP_BIND( Sprite, Opacity, "opacity" );
|
||||
INIT_PROP_BIND( Sprite, BlendType, "blend_type" );
|
||||
INIT_PROP_BIND( Sprite, Color, "color" );
|
||||
INIT_PROP_BIND( Sprite, Tone, "tone" );
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
** table-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "table.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
#include "serializable-binding.h"
|
||||
|
||||
#include "mruby.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
DEF_TYPE(Table);
|
||||
|
||||
MRB_METHOD(tableInitialize)
|
||||
{
|
||||
mrb_int x, y, z;
|
||||
x = y = z = 1;
|
||||
|
||||
mrb_get_args(mrb, "i|ii", &x, &y, &z);
|
||||
|
||||
Table *t = new Table(x, y, z);
|
||||
|
||||
setPrivateData(mrb, self, t, TableType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define TABLE_SIZE(d, D) \
|
||||
MRB_METHOD(table##D##Size) \
|
||||
{ \
|
||||
Table *t = getPrivateData<Table>(mrb, self); \
|
||||
return mrb_fixnum_value((mrb_int)t->d##Size()); \
|
||||
}
|
||||
|
||||
TABLE_SIZE(x, X)
|
||||
TABLE_SIZE(y, Y)
|
||||
TABLE_SIZE(z, Z)
|
||||
|
||||
MRB_METHOD(tableResize)
|
||||
{
|
||||
Table *t = getPrivateData<Table>(mrb, self);
|
||||
|
||||
mrb_int x, y, z;
|
||||
mrb_get_args(mrb, "i|ii", &x, &y, &z);
|
||||
|
||||
switch (mrb->c->ci->argc)
|
||||
{
|
||||
default:
|
||||
case 1:
|
||||
t->resize(x);
|
||||
return mrb_nil_value();
|
||||
|
||||
case 2:
|
||||
t->resize(x, y);
|
||||
return mrb_nil_value();
|
||||
|
||||
case 3:
|
||||
t->resize(x, y, z);
|
||||
return mrb_nil_value();
|
||||
}
|
||||
}
|
||||
|
||||
MRB_METHOD(tableGetAt)
|
||||
{
|
||||
Table *t = getPrivateData<Table>(mrb, self);
|
||||
|
||||
mrb_int x, y, z;
|
||||
x = y = z = 0;
|
||||
|
||||
mrb_get_args(mrb, "i|ii", &x, &y, &z);
|
||||
|
||||
if (x < 0 || x >= t->xSize()
|
||||
|| y < 0 || y >= t->ySize()
|
||||
|| z < 0 || z >= t->zSize())
|
||||
{
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
mrb_int result = t->get(x, y, z);
|
||||
|
||||
return mrb_fixnum_value(result);
|
||||
}
|
||||
|
||||
#define fix(x) mrb_fixnum(x)
|
||||
|
||||
MRB_METHOD(tableSetAt)
|
||||
{
|
||||
Table *t = getPrivateData<Table>(mrb, self);
|
||||
|
||||
int argc;
|
||||
mrb_value* argv;
|
||||
mrb_int x, y, z, value;
|
||||
x = y = z = 0;
|
||||
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
|
||||
if (argc < 2)
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
default:
|
||||
case 2 :
|
||||
x = fix(argv[0]);
|
||||
value = fix(argv[1]);
|
||||
break;
|
||||
case 3 :
|
||||
x = fix(argv[0]);
|
||||
y = fix(argv[1]);
|
||||
value = fix(argv[2]);
|
||||
break;
|
||||
case 4 :
|
||||
x = fix(argv[0]);
|
||||
y = fix(argv[1]);
|
||||
z = fix(argv[2]);
|
||||
value = fix(argv[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
t->set(value, x, y, z);
|
||||
|
||||
return mrb_fixnum_value(value);
|
||||
}
|
||||
|
||||
MARSH_LOAD_FUN(Table)
|
||||
|
||||
void
|
||||
tableBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "Table", 0);
|
||||
|
||||
mrb_define_class_method(mrb, klass, "_load", TableLoad, MRB_ARGS_REQ(1));
|
||||
serializableBindingInit<Table>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", tableInitialize, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(2));
|
||||
mrb_define_method(mrb, klass, "resize", tableResize, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(2));
|
||||
mrb_define_method(mrb, klass, "xsize", tableXSize, MRB_ARGS_NONE() );
|
||||
mrb_define_method(mrb, klass, "ysize", tableYSize, MRB_ARGS_NONE() );
|
||||
mrb_define_method(mrb, klass, "zsize", tableZSize, MRB_ARGS_NONE() );
|
||||
mrb_define_method(mrb, klass, "[]", tableGetAt, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(2));
|
||||
mrb_define_method(mrb, klass, "[]=", tableSetAt, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(2));
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
** tilemap-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tilemap.h"
|
||||
#include "viewport.h"
|
||||
#include "bitmap.h"
|
||||
#include "table.h"
|
||||
|
||||
#include "disposable-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
#include "mruby/array.h"
|
||||
|
||||
static const mrb_data_type TilemapAutotilesType =
|
||||
{
|
||||
"TilemapAutotiles",
|
||||
0
|
||||
};
|
||||
|
||||
MRB_METHOD(tilemapAutotilesSet)
|
||||
{
|
||||
Tilemap::Autotiles *a = getPrivateData<Tilemap::Autotiles>(mrb, self);
|
||||
|
||||
mrb_int i;
|
||||
mrb_value bitmapObj;
|
||||
|
||||
mrb_get_args(mrb, "io", &i, &bitmapObj);
|
||||
|
||||
Bitmap *bitmap = getPrivateDataCheck<Bitmap>(mrb, bitmapObj, BitmapType);
|
||||
|
||||
a->set(i, bitmap);
|
||||
|
||||
mrb_value ary = mrb_iv_get(mrb, self, getMrbData(mrb)->symbols[CSarray]);
|
||||
mrb_ary_set(mrb, ary, i, bitmapObj);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
MRB_METHOD(tilemapAutotilesGet)
|
||||
{
|
||||
mrb_int i;
|
||||
|
||||
mrb_get_args (mrb, "i", &i);
|
||||
|
||||
if (i < 0 || i > 6)
|
||||
return mrb_nil_value();
|
||||
|
||||
mrb_value ary = mrb_iv_get(mrb, self, getMrbData(mrb)->symbols[CSarray]);
|
||||
|
||||
return mrb_ary_entry(ary, i);
|
||||
}
|
||||
|
||||
DEF_TYPE(Tilemap);
|
||||
|
||||
MRB_METHOD(tilemapInitialize)
|
||||
{
|
||||
Tilemap *t;
|
||||
|
||||
/* Get parameters */
|
||||
mrb_value viewportObj = mrb_nil_value();
|
||||
Viewport *viewport = 0;
|
||||
|
||||
mrb_get_args(mrb, "|o", &viewportObj);
|
||||
|
||||
if (!mrb_nil_p(viewportObj))
|
||||
viewport = getPrivateDataCheck<Viewport>(mrb, viewportObj, ViewportType);
|
||||
|
||||
/* Construct object */
|
||||
t = new Tilemap(viewport);
|
||||
|
||||
setPrivateData(mrb, self, t, TilemapType);
|
||||
|
||||
setProperty(mrb, self, CSviewport, viewportObj);
|
||||
|
||||
wrapProperty(mrb, self, &t->getAutotiles(), CSautotiles, TilemapAutotilesType);
|
||||
|
||||
mrb_value autotilesObj = mrb_iv_get(mrb, self, getMrbData(mrb)->symbols[CSautotiles]);
|
||||
|
||||
mrb_value ary = mrb_ary_new_capa(mrb, 7);
|
||||
for (int i = 0; i < 7; ++i)
|
||||
mrb_ary_push(mrb, ary, mrb_nil_value());
|
||||
|
||||
mrb_iv_set(mrb, autotilesObj, getMrbData(mrb)->symbols[CSarray], ary);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
MRB_METHOD(tilemapGetAutotiles)
|
||||
{
|
||||
return getProperty(mrb, self, CSautotiles);
|
||||
}
|
||||
|
||||
MRB_METHOD(tilemapUpdate)
|
||||
{
|
||||
Tilemap *t = getPrivateData<Tilemap>(mrb, self);
|
||||
|
||||
t->update();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "tilemap"
|
||||
|
||||
DEF_PROP_OBJ(Tilemap, Viewport, Viewport, CSviewport)
|
||||
DEF_PROP_OBJ(Tilemap, Bitmap, Tileset, CStileset)
|
||||
DEF_PROP_OBJ(Tilemap, Table, MapData, CSmap_data)
|
||||
DEF_PROP_OBJ(Tilemap, Table, FlashData, CSflash_data)
|
||||
DEF_PROP_OBJ(Tilemap, Table, Priorities, CSpriorities)
|
||||
|
||||
DEF_PROP_B(Tilemap, Visible)
|
||||
|
||||
DEF_PROP_I(Tilemap, OX)
|
||||
DEF_PROP_I(Tilemap, OY)
|
||||
|
||||
void
|
||||
tilemapBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "TilemapAutotiles", 0);
|
||||
|
||||
mrb_define_method(mrb, klass, "[]=", tilemapAutotilesSet, MRB_ARGS_REQ(2));
|
||||
mrb_define_method(mrb, klass, "[]", tilemapAutotilesGet, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
|
||||
klass = mrb_define_class(mrb, "Tilemap", 0);
|
||||
|
||||
disposableBindingInit<Tilemap>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", tilemapInitialize, MRB_ARGS_OPT(1));
|
||||
mrb_define_method(mrb, klass, "autotiles", tilemapGetAutotiles, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, klass, "update", tilemapUpdate, MRB_ARGS_NONE());
|
||||
|
||||
INIT_PROP_BIND( Tilemap, Viewport, "viewport" );
|
||||
INIT_PROP_BIND( Tilemap, Tileset, "tileset" );
|
||||
INIT_PROP_BIND( Tilemap, MapData, "map_data" );
|
||||
INIT_PROP_BIND( Tilemap, FlashData, "flash_data" );
|
||||
INIT_PROP_BIND( Tilemap, Priorities, "priorities" );
|
||||
INIT_PROP_BIND( Tilemap, Visible, "visible" );
|
||||
INIT_PROP_BIND( Tilemap, OX, "ox" );
|
||||
INIT_PROP_BIND( Tilemap, OY, "oy" );
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
** viewport-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "viewport.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "flashable-binding.h"
|
||||
#include "sceneelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
DEF_TYPE(Viewport);
|
||||
|
||||
MRB_METHOD(viewportInitialize)
|
||||
{
|
||||
Viewport *v;
|
||||
|
||||
if (mrb->c->ci->argc == 1)
|
||||
{
|
||||
/* The rect arg is only used to init the viewport,
|
||||
* and does NOT replace its 'rect' property */
|
||||
mrb_value rectObj;
|
||||
Rect *rect;
|
||||
|
||||
mrb_get_args(mrb, "o", &rectObj);
|
||||
|
||||
rect = getPrivateDataCheck<Rect>(mrb, rectObj, RectType);
|
||||
|
||||
v = new Viewport(rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
mrb_int x, y, width, height;
|
||||
|
||||
mrb_get_args(mrb, "iiii", &x, &y, &width, &height);
|
||||
|
||||
v = new Viewport(x, y, width, height);
|
||||
}
|
||||
|
||||
setPrivateData(mrb, self, v, ViewportType);
|
||||
|
||||
/* Wrap property objects */
|
||||
v->setRect(new Rect(*v->getRect()));
|
||||
v->setColor(new Color);
|
||||
v->setTone(new Tone);
|
||||
|
||||
wrapProperty(mrb, self, v->getRect(), CSrect, RectType);
|
||||
wrapProperty(mrb, self, v->getColor(), CScolor, ColorType);
|
||||
wrapProperty(mrb, self, v->getTone(), CStone, ToneType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "viewport"
|
||||
|
||||
DEF_PROP_OBJ(Viewport, Rect, Rect, CSrect)
|
||||
DEF_PROP_OBJ(Viewport, Color, Color, CScolor)
|
||||
DEF_PROP_OBJ(Viewport, Tone, Tone, CStone)
|
||||
|
||||
DEF_PROP_I(Viewport, OX)
|
||||
DEF_PROP_I(Viewport, OY)
|
||||
|
||||
|
||||
void
|
||||
viewportBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "Viewport", 0);
|
||||
|
||||
disposableBindingInit <Viewport>(mrb, klass);
|
||||
flashableBindingInit <Viewport>(mrb, klass);
|
||||
sceneElementBindingInit<Viewport>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", viewportInitialize, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(3));
|
||||
|
||||
INIT_PROP_BIND( Viewport, Rect, "rect" );
|
||||
INIT_PROP_BIND( Viewport, OX, "ox" );
|
||||
INIT_PROP_BIND( Viewport, OY, "oy" );
|
||||
INIT_PROP_BIND( Viewport, Color, "color" );
|
||||
INIT_PROP_BIND( Viewport, Tone, "tone" );
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
** viewportelement-binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VIEWPORTELEMENTBINDING_H
|
||||
#define VIEWPORTELEMENTBINDING_H
|
||||
|
||||
#include "viewport.h"
|
||||
#include "binding-util.h"
|
||||
#include "binding-types.h"
|
||||
|
||||
#include "sceneelement-binding.h"
|
||||
|
||||
template<class C>
|
||||
MRB_METHOD(viewportElementGetViewport)
|
||||
{
|
||||
ViewportElement *ve = getPrivateData<C>(mrb, self);
|
||||
|
||||
GUARD_EXC( ve->aboutToAccess(); )
|
||||
|
||||
return getProperty(mrb, self, CSviewport);
|
||||
}
|
||||
|
||||
template<class C>
|
||||
static C *
|
||||
viewportElementInitialize(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
/* Get parameters */
|
||||
mrb_value viewportObj = mrb_nil_value();
|
||||
Viewport *viewport = 0;
|
||||
|
||||
mrb_get_args(mrb, "|o", &viewportObj);
|
||||
|
||||
if (!mrb_nil_p(viewportObj))
|
||||
viewport = getPrivateDataCheck<Viewport>(mrb, viewportObj, ViewportType);
|
||||
|
||||
/* Construct object */
|
||||
C *ve = new C(viewport);
|
||||
|
||||
/* Set property objects */
|
||||
setProperty(mrb, self, CSviewport, viewportObj);
|
||||
|
||||
return ve;
|
||||
}
|
||||
|
||||
template<class C>
|
||||
void
|
||||
viewportElementBindingInit(mrb_state *mrb, RClass *klass)
|
||||
{
|
||||
sceneElementBindingInit<C>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "viewport", viewportElementGetViewport<C>, MRB_ARGS_NONE());
|
||||
}
|
||||
|
||||
#endif // VIEWPORTELEMENTBINDING_H
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
** window-binding.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "window.h"
|
||||
#include "disposable-binding.h"
|
||||
#include "viewportelement-binding.h"
|
||||
#include "binding-util.h"
|
||||
|
||||
DEF_TYPE(Window);
|
||||
|
||||
MRB_METHOD(windowInitialize)
|
||||
{
|
||||
Window *w = viewportElementInitialize<Window>(mrb, self);
|
||||
|
||||
setPrivateData(mrb, self, w, WindowType);
|
||||
|
||||
w->setCursorRect(new Rect);
|
||||
wrapNilProperty(mrb, self, CSwindowskin);
|
||||
wrapNilProperty(mrb, self, CScontents);
|
||||
wrapProperty(mrb, self, w->getCursorRect(), CScursor_rect, RectType);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
MRB_METHOD(windowUpdate)
|
||||
{
|
||||
Window *w = getPrivateData<Window>(mrb, self);
|
||||
|
||||
w->update();
|
||||
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "window"
|
||||
|
||||
DEF_PROP_OBJ_NIL(Window, Bitmap, Windowskin, CSwindowskin)
|
||||
DEF_PROP_OBJ_NIL(Window, Bitmap, Contents, CScontents)
|
||||
DEF_PROP_OBJ(Window, Rect, CursorRect, CScursor_rect)
|
||||
|
||||
DEF_PROP_B(Window, Stretch)
|
||||
DEF_PROP_B(Window, Active)
|
||||
DEF_PROP_B(Window, Pause)
|
||||
|
||||
DEF_PROP_I(Window, X)
|
||||
DEF_PROP_I(Window, Y)
|
||||
DEF_PROP_I(Window, Width)
|
||||
DEF_PROP_I(Window, Height)
|
||||
DEF_PROP_I(Window, OX)
|
||||
DEF_PROP_I(Window, OY)
|
||||
DEF_PROP_I(Window, Opacity)
|
||||
DEF_PROP_I(Window, BackOpacity)
|
||||
DEF_PROP_I(Window, ContentsOpacity)
|
||||
|
||||
|
||||
void
|
||||
windowBindingInit(mrb_state *mrb)
|
||||
{
|
||||
RClass *klass = mrb_define_class(mrb, "Window", 0);
|
||||
|
||||
disposableBindingInit <Window>(mrb, klass);
|
||||
viewportElementBindingInit<Window>(mrb, klass);
|
||||
|
||||
mrb_define_method(mrb, klass, "initialize", windowInitialize, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, klass, "update", windowUpdate, MRB_ARGS_NONE());
|
||||
|
||||
INIT_PROP_BIND( Window, Windowskin, "windowskin" );
|
||||
INIT_PROP_BIND( Window, Contents, "contents" );
|
||||
INIT_PROP_BIND( Window, Stretch, "stretch" );
|
||||
INIT_PROP_BIND( Window, CursorRect, "cursor_rect" );
|
||||
INIT_PROP_BIND( Window, Active, "active" );
|
||||
INIT_PROP_BIND( Window, Pause, "pause" );
|
||||
INIT_PROP_BIND( Window, X, "x" );
|
||||
INIT_PROP_BIND( Window, Y, "y" );
|
||||
INIT_PROP_BIND( Window, Width, "width" );
|
||||
INIT_PROP_BIND( Window, Height, "height" );
|
||||
INIT_PROP_BIND( Window, OX, "ox" );
|
||||
INIT_PROP_BIND( Window, OY, "oy" );
|
||||
INIT_PROP_BIND( Window, Opacity, "opacity" );
|
||||
INIT_PROP_BIND( Window, BackOpacity, "back_opacity" );
|
||||
INIT_PROP_BIND( Window, ContentsOpacity, "contents_opacity" );
|
||||
|
||||
mrb_define_method(mrb, klass, "inspect", inspectObject, MRB_ARGS_NONE());
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
** binding-null.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "binding.h"
|
||||
#include "globalstate.h"
|
||||
#include "eventthread.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
static void nullBindingExecute()
|
||||
{
|
||||
qDebug() << "The null binding doesn't do anything, so we're done!";
|
||||
gState->rtData().rqTermAck = true;
|
||||
}
|
||||
|
||||
static void nullBindingTerminate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ScriptBinding scriptBindingImpl =
|
||||
{
|
||||
nullBindingExecute,
|
||||
nullBindingTerminate
|
||||
};
|
||||
|
||||
ScriptBinding *scriptBinding = &scriptBindingImpl;
|
|
@ -0,0 +1,11 @@
|
|||
[General]
|
||||
debugMode=true
|
||||
winResizable=true
|
||||
fullscreen=false
|
||||
vsync=true
|
||||
defScreenW=640
|
||||
defScreenH=480
|
||||
solidFonts=false
|
||||
gameFolder=.
|
||||
customScript=
|
||||
RTPs=/home/Ancurio/Public/RGSS-RTP
|
|
@ -0,0 +1,192 @@
|
|||
|
||||
|
||||
TEMPLATE = app
|
||||
QT = core
|
||||
TARGET = mkxp
|
||||
DEPENDPATH += src shader assets
|
||||
INCLUDEPATH += . src SFML/include libsigc++
|
||||
|
||||
isEmpty(BINDING) {
|
||||
BINDING = BINDING_MRI
|
||||
}
|
||||
|
||||
CONFIG += $$BINDING
|
||||
|
||||
unix {
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += sigc++-2.0 sdl2 SDL2_image SDL2_ttf sfml-audio
|
||||
LIBS += -lGLEW -lphysfs -lz
|
||||
}
|
||||
|
||||
# 'slots' keyword fucks with libsigc++
|
||||
DEFINES += QT_NO_KEYWORDS
|
||||
|
||||
# Input
|
||||
HEADERS += \
|
||||
src/quadarray.h \
|
||||
src/audio.h \
|
||||
src/binding.h \
|
||||
src/bitmap.h \
|
||||
src/disposable.h \
|
||||
src/etc.h \
|
||||
src/etc-internal.h \
|
||||
src/eventthread.h \
|
||||
src/flashable.h \
|
||||
src/font.h \
|
||||
src/globalstate.h \
|
||||
src/input.h \
|
||||
src/plane.h \
|
||||
src/scene.h \
|
||||
src/sprite.h \
|
||||
src/table.h \
|
||||
src/texpool.h \
|
||||
src/tilequad.h \
|
||||
src/transform.h \
|
||||
src/viewport.h \
|
||||
src/window.h \
|
||||
src/serializable.h \
|
||||
src/shader.h \
|
||||
src/glstate.h \
|
||||
src/quad.h \
|
||||
src/tilemap.h \
|
||||
src/graphics.h \
|
||||
src/debuglogger.h \
|
||||
src/global-ibo.h \
|
||||
src/exception.h \
|
||||
src/filesystem.h \
|
||||
src/serial-util.h \
|
||||
src/intrulist.h \
|
||||
src/binding.h \
|
||||
src/gl-util.h \
|
||||
src/util.h \
|
||||
src/config.h
|
||||
|
||||
SOURCES += \
|
||||
src/main.cpp \
|
||||
src/audio.cpp \
|
||||
src/bitmap.cpp \
|
||||
src/eventthread.cpp \
|
||||
src/filesystem.cpp \
|
||||
src/font.cpp \
|
||||
src/globalstate.cpp \
|
||||
src/input.cpp \
|
||||
src/plane.cpp \
|
||||
src/scene.cpp \
|
||||
src/sprite.cpp \
|
||||
src/table.cpp \
|
||||
src/tilequad.cpp \
|
||||
src/viewport.cpp \
|
||||
src/window.cpp \
|
||||
src/texpool.cpp \
|
||||
src/shader.cpp \
|
||||
src/glstate.cpp \
|
||||
src/tilemap.cpp \
|
||||
src/autotiles.cpp \
|
||||
src/graphics.cpp \
|
||||
src/debuglogger.cpp \
|
||||
src/etc.cpp \
|
||||
src/config.cpp
|
||||
|
||||
EMBED = shader/transSimple.frag \
|
||||
shader/trans.frag \
|
||||
shader/hue.frag \
|
||||
shader/sprite.frag \
|
||||
shader/bitmapBlit.frag \
|
||||
assets/liberation.ttf
|
||||
|
||||
# xxd
|
||||
xxd.output = ${QMAKE_FILE_NAME}.xxd
|
||||
xxd.commands = xxd -i ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
|
||||
xxd.depends = $$EMBED
|
||||
xxd.input = EMBED
|
||||
xxd.variable_out = HEADERS
|
||||
|
||||
QMAKE_EXTRA_COMPILERS += xxd
|
||||
|
||||
|
||||
BINDING_NULL {
|
||||
SOURCES += binding-null/binding-null.cpp
|
||||
}
|
||||
|
||||
BINDING_MRUBY {
|
||||
LIBS += mruby/build/host/lib/libmruby.a
|
||||
INCLUDEPATH += mruby/include
|
||||
DEPENDPATH += mruby/include
|
||||
DEFINES += BINDING_MRUBY
|
||||
|
||||
HEADERS += \
|
||||
binding-mruby/binding-util.h \
|
||||
binding-mruby/disposable-binding.h \
|
||||
binding-mruby/flashable-binding.h \
|
||||
binding-mruby/binding-types.h \
|
||||
binding-mruby/sceneelement-binding.h \
|
||||
binding-mruby/viewportelement-binding.h \
|
||||
binding-mruby/serializable-binding.h \
|
||||
binding-mruby/mrb-ext/file.h \
|
||||
binding-mruby/mrb-ext/rwmem.h \
|
||||
binding-mruby/mrb-ext/marshal.h
|
||||
|
||||
SOURCES += \
|
||||
binding-mruby/binding-mruby.cpp \
|
||||
binding-mruby/binding-util.cpp \
|
||||
binding-mruby/window-binding.cpp \
|
||||
binding-mruby/bitmap-binding.cpp \
|
||||
binding-mruby/sprite-binding.cpp \
|
||||
binding-mruby/font-binding.cpp \
|
||||
binding-mruby/viewport-binding.cpp \
|
||||
binding-mruby/plane-binding.cpp \
|
||||
binding-mruby/audio-binding.cpp \
|
||||
binding-mruby/tilemap-binding.cpp \
|
||||
binding-mruby/etc-binding.cpp \
|
||||
binding-mruby/graphics-binding.cpp \
|
||||
binding-mruby/input-binding.cpp \
|
||||
binding-mruby/table-binding.cpp \
|
||||
binding-mruby/module_rpg.c \
|
||||
binding-mruby/mrb-ext/file.cpp \
|
||||
binding-mruby/mrb-ext/marshal.cpp \
|
||||
binding-mruby/mrb-ext/rwmem.cpp \
|
||||
binding-mruby/mrb-ext/kernel.cpp \
|
||||
binding-mruby/mrb-ext/time.cpp
|
||||
}
|
||||
|
||||
BINDING_MRI {
|
||||
LIBS += ./ruby/libruby.so
|
||||
INCLUDEPATH += ruby/include
|
||||
DEPENDPATH += ruby/include
|
||||
DEFINES += BINDING_MRI
|
||||
|
||||
EMBED2 = binding-mri/module_rpg.rb
|
||||
xxdp.output = ${QMAKE_FILE_NAME}.xxd
|
||||
xxdp.commands = xxd+/xxd+ ${QMAKE_FILE_NAME} -o ${QMAKE_FILE_OUT} --string
|
||||
xxdp.depends = $$EMBED2
|
||||
xxdp.input = EMBED2
|
||||
xxdp.variable_out = HEADERS
|
||||
QMAKE_EXTRA_COMPILERS += xxdp
|
||||
|
||||
HEADERS += \
|
||||
binding-mri/binding-util.h \
|
||||
binding-mri/binding-types.h \
|
||||
binding-mri/serializable-binding.h \
|
||||
binding-mri/disposable-binding.h \
|
||||
binding-mri/sceneelement-binding.h \
|
||||
binding-mri/viewportelement-binding.h \
|
||||
binding-mri/flashable-binding.h
|
||||
|
||||
SOURCES += \
|
||||
binding-mri/binding-mri.cpp \
|
||||
binding-mri/binding-util.cpp \
|
||||
binding-mri/table-binding.cpp \
|
||||
binding-mri/etc-binding.cpp \
|
||||
binding-mri/bitmap-binding.cpp \
|
||||
binding-mri/font-binding.cpp \
|
||||
binding-mri/graphics-binding.cpp \
|
||||
binding-mri/input-binding.cpp \
|
||||
binding-mri/sprite-binding.cpp \
|
||||
binding-mri/viewport-binding.cpp \
|
||||
binding-mri/plane-binding.cpp \
|
||||
binding-mri/window-binding.cpp \
|
||||
binding-mri/tilemap-binding.cpp \
|
||||
binding-mri/audio-binding.cpp \
|
||||
binding-mri/module_rpg.cpp \
|
||||
binding-mri/filesystem-binding.cpp
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
uniform sampler2D source;
|
||||
uniform sampler2D destination;
|
||||
|
||||
uniform vec4 subRect;
|
||||
|
||||
uniform float opacity;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 coor = gl_TexCoord[0].xy;
|
||||
vec2 dstCoor = (coor - subRect.xy) * subRect.zw;
|
||||
|
||||
vec4 srcFrag = texture2D(source, coor);
|
||||
vec4 dstFrag = texture2D(destination, dstCoor);
|
||||
|
||||
vec4 resFrag;
|
||||
|
||||
float ab = opacity;
|
||||
const float as = srcFrag.a;
|
||||
const float ad = dstFrag.a;
|
||||
|
||||
const float at = ab*as;
|
||||
resFrag.a = at + ad - ad*at;
|
||||
|
||||
resFrag.rgb = mix(dstFrag.rgb, srcFrag.rgb, ab*as);
|
||||
// resFrag.rgb /= (resFrag.a);
|
||||
resFrag.rgb = mix(srcFrag.rgb, resFrag.rgb, ad*resFrag.a);
|
||||
|
||||
gl_FragColor = resFrag;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
uniform sampler2D inputTexture;
|
||||
uniform float hueAdjust;
|
||||
void main ()
|
||||
{
|
||||
const vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
|
||||
const vec4 kRGBToI = vec4 (0.596, -0.275, -0.321, 0.0);
|
||||
const vec4 kRGBToQ = vec4 (0.212, -0.523, 0.311, 0.0);
|
||||
|
||||
const vec4 kYIQToR = vec4 (1.0, 0.956, 0.621, 0.0);
|
||||
const vec4 kYIQToG = vec4 (1.0, -0.272, -0.647, 0.0);
|
||||
const vec4 kYIQToB = vec4 (1.0, -1.107, 1.704, 0.0);
|
||||
|
||||
// Sample the input pixel
|
||||
vec4 color = texture2D (inputTexture, gl_TexCoord [ 0 ].xy);
|
||||
|
||||
// Convert to YIQ
|
||||
float YPrime = dot (color, kRGBToYPrime);
|
||||
float I = dot (color, kRGBToI);
|
||||
float Q = dot (color, kRGBToQ);
|
||||
|
||||
// Calculate the hue and chroma
|
||||
float hue = atan (Q, I);
|
||||
float chroma = sqrt (I * I + Q * Q);
|
||||
|
||||
// Make the user's adjustments
|
||||
hue += hueAdjust;
|
||||
|
||||
// Convert back to YIQ
|
||||
Q = chroma * sin (hue);
|
||||
I = chroma * cos (hue);
|
||||
|
||||
// Convert back to RGB
|
||||
vec4 yIQ = vec4 (YPrime, I, Q, 0.0);
|
||||
color.r = dot (yIQ, kYIQToR);
|
||||
color.g = dot (yIQ, kYIQToG);
|
||||
color.b = dot (yIQ, kYIQToB);
|
||||
|
||||
// Save the result
|
||||
gl_FragColor = color;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
uniform sampler2D texture;
|
||||
|
||||
uniform vec4 tone;
|
||||
|
||||
uniform float opacity;
|
||||
uniform vec4 color;
|
||||
uniform vec4 flash;
|
||||
|
||||
uniform float bushDepth;
|
||||
uniform float bushOpacity;
|
||||
|
||||
const vec3 lumaF = { .299, .587, .114 };
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 coor = gl_TexCoord[0].xy;
|
||||
|
||||
/* Sample source color */
|
||||
vec4 frag = texture2D(texture, coor);
|
||||
|
||||
/* Apply gray */
|
||||
const float luma = dot(frag.rgb, lumaF);
|
||||
frag.rgb = mix(frag.rgb, vec3(luma), tone.w);
|
||||
|
||||
/* Apply tone */
|
||||
frag.rgb += tone.rgb;
|
||||
|
||||
/* Apply opacity */
|
||||
frag.a *= opacity;
|
||||
|
||||
/* Apply color */
|
||||
frag.rgb = mix(frag.rgb, color.rgb, color.a);
|
||||
|
||||
/* Apply flash */
|
||||
frag.rgb = mix(frag.rgb, flash.rgb, flash.a);
|
||||
|
||||
/* Apply bush alpha by mathematical if */
|
||||
float underBush = float(coor.y < bushDepth);
|
||||
frag.a *= clamp(bushOpacity + underBush, 0, 1);
|
||||
|
||||
gl_FragColor = frag;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
/* Fragment shader dealing with transitions */
|
||||
|
||||
uniform sampler2D currentScene;
|
||||
uniform sampler2D frozenScene;
|
||||
uniform sampler2D transMap;
|
||||
/* Normalized */
|
||||
uniform float prog;
|
||||
/* Vague [0, 512] normalized */
|
||||
uniform float vague;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texCoor = gl_TexCoord[0].st;
|
||||
float transV = texture2D(transMap, texCoor).r;
|
||||
float cTransV = clamp(transV, prog, prog+vague);
|
||||
float alpha = (cTransV - prog) / vague;
|
||||
|
||||
vec4 newFrag = texture2D(currentScene, texCoor);
|
||||
vec4 oldFrag = texture2D(frozenScene, texCoor);
|
||||
|
||||
gl_FragColor = mix(newFrag, oldFrag, alpha);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
uniform sampler2D frozenScene;
|
||||
uniform sampler2D currentScene;
|
||||
uniform float prog;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texCoor = gl_TexCoord[0].st;
|
||||
vec4 newPixel = texture2D(currentScene, texCoor);
|
||||
vec4 oldPixel = texture2D(frozenScene, texCoor);
|
||||
|
||||
gl_FragColor = mix(oldPixel, newPixel, prog);
|
||||
}
|
|
@ -0,0 +1,668 @@
|
|||
/*
|
||||
** audio.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "util.h"
|
||||
#include "intrulist.h"
|
||||
#include "filesystem.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include <SFML/Audio/Music.hpp>
|
||||
#include <SFML/Audio/Sound.hpp>
|
||||
#include <SFML/Audio/SoundBuffer.hpp>
|
||||
#include <SFML/System/Thread.hpp>
|
||||
#include <SFML/System/Clock.hpp>
|
||||
#include <SFML/System/Sleep.hpp>
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
|
||||
#include "SDL2/SDL_thread.h"
|
||||
|
||||
//#include "SDL2/SDL_mixer.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define FADE_SLEEP 10
|
||||
#define SOUND_MAG_SIZE 10
|
||||
#define SOUND_MAX_MEM (50*1000*1000) // 5 MB
|
||||
|
||||
struct MusicEntity
|
||||
{
|
||||
sf::Music music;
|
||||
QByteArray filename;
|
||||
FileStream currentData;
|
||||
SDL_mutex *mutex;
|
||||
|
||||
int pitch;
|
||||
|
||||
volatile bool fading;
|
||||
struct
|
||||
{
|
||||
unsigned int duration;
|
||||
float msStep;
|
||||
volatile bool terminate;
|
||||
sf::Thread *thread;
|
||||
} fadeData;
|
||||
|
||||
/* normalized */
|
||||
float intVolume;
|
||||
float extVolume;
|
||||
|
||||
bool extPaused;
|
||||
bool noFadeInFlag;
|
||||
|
||||
MusicEntity()
|
||||
: currentData(0),
|
||||
pitch(100),
|
||||
fading(false),
|
||||
intVolume(1),
|
||||
extVolume(1),
|
||||
extPaused(false),
|
||||
noFadeInFlag(false)
|
||||
{
|
||||
music.setLoop(true);
|
||||
fadeData.thread = 0;
|
||||
mutex = SDL_CreateMutex();
|
||||
}
|
||||
|
||||
~MusicEntity()
|
||||
{
|
||||
SDL_DestroyMutex(mutex);
|
||||
}
|
||||
|
||||
void play(const QByteArray &filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
{
|
||||
terminateFade();
|
||||
|
||||
volume = bound<int>(volume, 0, 100);
|
||||
pitch = bound<int>(pitch, 50, 150);
|
||||
|
||||
if (filename == this->filename
|
||||
&& volume == (int)music.getVolume()
|
||||
// && pitch == music.getPitch()
|
||||
&& music.getStatus() == sf::Music::Playing)
|
||||
return;
|
||||
|
||||
if (filename == this->filename
|
||||
&& music.getStatus() == sf::Music::Playing)
|
||||
// && pitch == music.getPitch())
|
||||
{
|
||||
intVolume = (float) volume / 100;
|
||||
updateVolumeSync();
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
this->music.stop();
|
||||
|
||||
this->filename = filename;
|
||||
|
||||
currentData.close();
|
||||
|
||||
currentData =
|
||||
gState->fileSystem().openRead(filename.constData(), FileSystem::Audio);
|
||||
|
||||
if (!this->music.openFromStream(currentData))
|
||||
return;
|
||||
|
||||
intVolume = (float) volume / 100;
|
||||
updateVolume();
|
||||
// this->music.setPitch((float) pitch / 100);
|
||||
|
||||
if (!extPaused)
|
||||
this->music.play();
|
||||
else
|
||||
noFadeInFlag = true;
|
||||
|
||||
SDL_UnlockMutex(mutex);
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
terminateFade();
|
||||
|
||||
stopPriv();
|
||||
}
|
||||
|
||||
void fade(unsigned int ms)
|
||||
{
|
||||
if (music.getStatus() != sf::Music::Playing)
|
||||
return;
|
||||
|
||||
if (fading)
|
||||
return;
|
||||
|
||||
delete fadeData.thread;
|
||||
fadeData.thread = new sf::Thread(&MusicEntity::processFade, this);
|
||||
fadeData.duration = ms;
|
||||
fadeData.terminate = false;
|
||||
|
||||
fading = true;
|
||||
fadeData.thread->launch();
|
||||
}
|
||||
|
||||
void updateVolume()
|
||||
{
|
||||
music.setVolume(intVolume * extVolume * 100);
|
||||
}
|
||||
|
||||
void updateVolumeSync()
|
||||
{
|
||||
SDL_LockMutex(mutex);
|
||||
updateVolume();
|
||||
SDL_UnlockMutex(mutex);
|
||||
}
|
||||
|
||||
private:
|
||||
void terminateFade()
|
||||
{
|
||||
if (!fading)
|
||||
return;
|
||||
|
||||
/* Tell our thread to wrap up and wait for it */
|
||||
fadeData.terminate = true;
|
||||
fadeData.thread->wait();
|
||||
|
||||
fading = false;
|
||||
}
|
||||
|
||||
void stopPriv()
|
||||
{
|
||||
SDL_LockMutex(mutex);
|
||||
music.stop();
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
filename = QByteArray();
|
||||
}
|
||||
|
||||
void processFade()
|
||||
{
|
||||
float msStep = music.getVolume() / fadeData.duration;
|
||||
sf::Clock timer;
|
||||
sf::Time sleepTime = sf::milliseconds(FADE_SLEEP);
|
||||
unsigned int currentDur = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int elapsed = timer.getElapsedTime().asMilliseconds();
|
||||
timer.restart();
|
||||
currentDur += elapsed;
|
||||
|
||||
if (music.getStatus() != sf::Music::Playing)
|
||||
break;
|
||||
|
||||
if (fadeData.terminate)
|
||||
break;
|
||||
|
||||
if (currentDur >= fadeData.duration)
|
||||
break;
|
||||
|
||||
intVolume = (float) (music.getVolume() - (elapsed * msStep)) / 100;
|
||||
updateVolumeSync();
|
||||
|
||||
sf::sleep(sleepTime);
|
||||
}
|
||||
|
||||
stopPriv();
|
||||
fading = false;
|
||||
}
|
||||
};
|
||||
|
||||
//struct SoundBuffer
|
||||
//{
|
||||
// Mix_Chunk *sdlBuffer;
|
||||
// QByteArray filename;
|
||||
// IntruListLink<SoundBuffer> link;
|
||||
|
||||
// SoundBuffer()
|
||||
// : link(this)
|
||||
// {}
|
||||
//};
|
||||
|
||||
//struct SoundEntity
|
||||
//{
|
||||
// IntruList<SoundBuffer> buffers;
|
||||
// QHash<QByteArray, SoundBuffer*> bufferHash;
|
||||
// uint cacheSize; // in chunks, for now
|
||||
// int channelIndex;
|
||||
|
||||
// SoundEntity()
|
||||
// : cacheSize(0),
|
||||
// channelIndex(0)
|
||||
// {
|
||||
// Mix_AllocateChannels(SOUND_MAG_SIZE);
|
||||
// }
|
||||
|
||||
// ~SoundEntity()
|
||||
// {
|
||||
// IntruListLink<SoundBuffer> *iter = buffers.iterStart();
|
||||
// iter = iter->next;
|
||||
|
||||
// for (int i = 0; i < buffers.getSize(); ++i)
|
||||
// {
|
||||
// SoundBuffer *buffer = iter->data;
|
||||
// iter = iter->next;
|
||||
// delete buffer;
|
||||
// }
|
||||
// }
|
||||
|
||||
// void play(const char *filename,
|
||||
// int volume,
|
||||
// int pitch)
|
||||
// {
|
||||
// (void) pitch;
|
||||
|
||||
// volume = bound(volume, 0, 100);
|
||||
|
||||
// Mix_Chunk *buffer = requestBuffer(filename);
|
||||
|
||||
// int nextChIdx = channelIndex++;
|
||||
// if (channelIndex > SOUND_MAG_SIZE-1)
|
||||
// channelIndex = 0;
|
||||
|
||||
// Mix_HaltChannel(nextChIdx);
|
||||
// Mix_Volume(nextChIdx, ((float) MIX_MAX_VOLUME / 100) * volume);
|
||||
// Mix_PlayChannelTimed(nextChIdx, buffer, 0, -1);
|
||||
// }
|
||||
|
||||
// void stop()
|
||||
// {
|
||||
// /* Stop all channels */
|
||||
// Mix_HaltChannel(-1);
|
||||
// }
|
||||
|
||||
//private:
|
||||
// Mix_Chunk *requestBuffer(const char *filename)
|
||||
// {
|
||||
// SoundBuffer *buffer = bufferHash.value(filename, 0);
|
||||
|
||||
// if (buffer)
|
||||
// {
|
||||
// /* Buffer still in cashe.
|
||||
// * Move to front of priority list */
|
||||
// buffers.remove(buffer->link);
|
||||
// buffers.append(buffer->link);
|
||||
|
||||
// return buffer->sdlBuffer;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// /* Buffer not in cashe, needs to be loaded */
|
||||
// SDL_RWops ops;
|
||||
// gState->fileSystem().openRead(ops, filename, FileSystem::Audio);
|
||||
|
||||
// Mix_Chunk *sdlBuffer = Mix_LoadWAV_RW(&ops, 1);
|
||||
|
||||
// if (!sdlBuffer)
|
||||
// {
|
||||
// SDL_RWclose(&ops);
|
||||
// throw Exception(Exception::RGSSError, "Unable to read sound file");
|
||||
// }
|
||||
|
||||
// buffer = new SoundBuffer;
|
||||
// buffer->sdlBuffer = sdlBuffer;
|
||||
// buffer->filename = filename;
|
||||
|
||||
// ++cacheSize;
|
||||
|
||||
// bufferHash.insert(filename, buffer);
|
||||
// buffers.prepend(buffer->link);
|
||||
|
||||
// if (cacheSize > 20)
|
||||
// {
|
||||
// SoundBuffer *last = buffers.tail();
|
||||
// bufferHash.remove(last->filename);
|
||||
// buffers.remove(last->link);
|
||||
// --cacheSize;
|
||||
|
||||
// qDebug() << "Deleted buffer" << last->filename;
|
||||
|
||||
// delete last;
|
||||
// }
|
||||
|
||||
// return buffer->sdlBuffer;
|
||||
// }
|
||||
// }
|
||||
//};
|
||||
|
||||
struct SoundBuffer
|
||||
{
|
||||
sf::SoundBuffer sfBuffer;
|
||||
QByteArray filename;
|
||||
IntruListLink<SoundBuffer> link;
|
||||
|
||||
SoundBuffer()
|
||||
: link(this)
|
||||
{}
|
||||
};
|
||||
|
||||
struct SoundEntity
|
||||
{
|
||||
IntruList<SoundBuffer> buffers;
|
||||
QHash<QByteArray, SoundBuffer*> bufferHash;
|
||||
unsigned int bufferSamples;
|
||||
|
||||
sf::Sound soundMag[SOUND_MAG_SIZE];
|
||||
int magIndex;
|
||||
|
||||
SoundEntity()
|
||||
: bufferSamples(0),
|
||||
magIndex(0)
|
||||
{}
|
||||
|
||||
~SoundEntity()
|
||||
{
|
||||
QHash<QByteArray, SoundBuffer*>::iterator iter;
|
||||
for (iter = bufferHash.begin(); iter != bufferHash.end(); ++iter)
|
||||
delete iter.value();
|
||||
}
|
||||
|
||||
void play(const char *filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
{
|
||||
(void) pitch;
|
||||
|
||||
volume = bound<int>(volume, 0, 100);
|
||||
|
||||
sf::SoundBuffer &buffer = allocateBuffer(filename);
|
||||
|
||||
int soundIndex = magIndex++;
|
||||
if (magIndex > SOUND_MAG_SIZE-1)
|
||||
magIndex = 0;
|
||||
|
||||
sf::Sound &sound = soundMag[soundIndex];
|
||||
sound.stop();
|
||||
sound.setBuffer(buffer);
|
||||
sound.setVolume(volume);
|
||||
|
||||
sound.play();
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
for (int i = 0; i < SOUND_MAG_SIZE; i++)
|
||||
soundMag[i].stop();
|
||||
}
|
||||
|
||||
private:
|
||||
sf::SoundBuffer &allocateBuffer(const char *filename)
|
||||
{
|
||||
SoundBuffer *buffer = bufferHash.value(filename, 0);
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
/* Buffer still in cashe.
|
||||
* Move to front of priority list */
|
||||
|
||||
buffers.remove(buffer->link);
|
||||
buffers.append(buffer->link);
|
||||
|
||||
return buffer->sfBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Buffer not in cashe, needs to be loaded */
|
||||
|
||||
FileStream data =
|
||||
gState->fileSystem().openRead(filename, FileSystem::Audio);
|
||||
|
||||
buffer = new SoundBuffer;
|
||||
buffer->sfBuffer.loadFromStream(data);
|
||||
bufferSamples += buffer->sfBuffer.getSampleCount();
|
||||
|
||||
data.close();
|
||||
|
||||
// qDebug() << "SoundCache: Current memory consumption:" << bufferSamples/2;
|
||||
|
||||
buffer->filename = filename;
|
||||
|
||||
bufferHash.insert(filename, buffer);
|
||||
buffers.prepend(buffer->link);
|
||||
|
||||
// FIXME this part would look better if it actually looped until enough memory is freed
|
||||
/* If memory limit is reached, delete lowest priority buffer.
|
||||
* Samples are 2 bytes big */
|
||||
if ((bufferSamples/2) > SOUND_MAX_MEM && !buffers.isEmpty())
|
||||
{
|
||||
SoundBuffer *last = buffers.tail();
|
||||
bufferHash.remove(last->filename);
|
||||
buffers.remove(last->link);
|
||||
bufferSamples -= last->sfBuffer.getSampleCount();
|
||||
|
||||
qDebug() << "Deleted buffer" << last->filename;
|
||||
|
||||
delete last;
|
||||
}
|
||||
|
||||
return buffer->sfBuffer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct AudioPrivate
|
||||
{
|
||||
MusicEntity bgm;
|
||||
MusicEntity bgs;
|
||||
MusicEntity me;
|
||||
|
||||
SoundEntity se;
|
||||
|
||||
sf::Thread *meWatchThread;
|
||||
bool meWatchRunning;
|
||||
bool meWatchThreadTerm;
|
||||
|
||||
AudioPrivate()
|
||||
: meWatchThread(0),
|
||||
meWatchRunning(false),
|
||||
meWatchThreadTerm(false)
|
||||
{
|
||||
me.music.setLoop(false);
|
||||
}
|
||||
|
||||
~AudioPrivate()
|
||||
{
|
||||
if (meWatchThread)
|
||||
{
|
||||
meWatchThreadTerm = true;
|
||||
meWatchThread->wait();
|
||||
delete meWatchThread;
|
||||
}
|
||||
|
||||
bgm.stop();
|
||||
bgs.stop();
|
||||
me.stop();
|
||||
se.stop();
|
||||
}
|
||||
|
||||
void scheduleMeWatch()
|
||||
{
|
||||
if (meWatchRunning)
|
||||
return;
|
||||
|
||||
meWatchRunning = true;
|
||||
|
||||
if (meWatchThread)
|
||||
meWatchThread->wait();
|
||||
|
||||
bgm.extPaused = true;
|
||||
|
||||
delete meWatchThread;
|
||||
meWatchThread = new sf::Thread(&AudioPrivate::meWatchFunc, this);
|
||||
meWatchThread->launch();
|
||||
}
|
||||
|
||||
void meWatchFunc()
|
||||
{
|
||||
// FIXME Need to catch the case where an ME is started while
|
||||
// the BGM is still being faded in from this function
|
||||
sf::Time sleepTime = sf::milliseconds(FADE_SLEEP);
|
||||
const int bgmFadeOutSteps = 20;
|
||||
const int bgmFadeInSteps = 100;
|
||||
|
||||
/* Fade out BGM */
|
||||
for (int i = bgmFadeOutSteps; i > 0; --i)
|
||||
{
|
||||
if (meWatchThreadTerm)
|
||||
return;
|
||||
|
||||
if (bgm.music.getStatus() != sf::Music::Playing)
|
||||
{
|
||||
bgm.extVolume = 0;
|
||||
bgm.updateVolumeSync();
|
||||
break;
|
||||
}
|
||||
|
||||
bgm.extVolume = (1.0 / bgmFadeOutSteps) * (i-1);
|
||||
bgm.updateVolumeSync();
|
||||
sf::sleep(sleepTime);
|
||||
}
|
||||
|
||||
SDL_LockMutex(bgm.mutex);
|
||||
if (bgm.music.getStatus() == sf::Music::Playing)
|
||||
bgm.music.pause();
|
||||
SDL_UnlockMutex(bgm.mutex);
|
||||
|
||||
/* Linger while ME plays */
|
||||
while (me.music.getStatus() == sf::Music::Playing)
|
||||
{
|
||||
if (meWatchThreadTerm)
|
||||
return;
|
||||
|
||||
sf::sleep(sleepTime);
|
||||
}
|
||||
|
||||
SDL_LockMutex(bgm.mutex);
|
||||
bgm.extPaused = false;
|
||||
|
||||
if (bgm.music.getStatus() == sf::Music::Paused)
|
||||
bgm.music.play();
|
||||
SDL_UnlockMutex(bgm.mutex);
|
||||
|
||||
/* Fade in BGM again */
|
||||
for (int i = 0; i < bgmFadeInSteps; ++i)
|
||||
{
|
||||
if (meWatchThreadTerm)
|
||||
return;
|
||||
|
||||
SDL_LockMutex(bgm.mutex);
|
||||
|
||||
if (bgm.music.getStatus() != sf::Music::Playing || bgm.noFadeInFlag)
|
||||
{
|
||||
bgm.noFadeInFlag = false;
|
||||
bgm.extVolume = 1;
|
||||
bgm.updateVolume();
|
||||
bgm.music.play();
|
||||
SDL_UnlockMutex(bgm.mutex);
|
||||
break;
|
||||
}
|
||||
|
||||
bgm.extVolume = (1.0 / bgmFadeInSteps) * (i+1);
|
||||
bgm.updateVolume();
|
||||
|
||||
SDL_UnlockMutex(bgm.mutex);
|
||||
|
||||
sf::sleep(sleepTime);
|
||||
}
|
||||
|
||||
meWatchRunning = false;
|
||||
}
|
||||
};
|
||||
|
||||
Audio::Audio()
|
||||
: p(new AudioPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Audio::bgmPlay(const char *filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
{
|
||||
p->bgm.play(filename, volume, pitch);
|
||||
}
|
||||
|
||||
void Audio::bgmStop()
|
||||
{
|
||||
p->bgm.stop();
|
||||
}
|
||||
|
||||
void Audio::bgmFade(int time)
|
||||
{
|
||||
p->bgm.fade(time);
|
||||
}
|
||||
|
||||
|
||||
void Audio::bgsPlay(const char *filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
{
|
||||
p->bgs.play(filename, volume, pitch);
|
||||
}
|
||||
|
||||
void Audio::bgsStop()
|
||||
{
|
||||
p->bgs.stop();
|
||||
}
|
||||
|
||||
void Audio::bgsFade(int time)
|
||||
{
|
||||
p->bgs.fade(time);
|
||||
}
|
||||
|
||||
|
||||
void Audio::mePlay(const char *filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
{
|
||||
p->me.play(filename, volume, pitch);
|
||||
p->scheduleMeWatch();
|
||||
}
|
||||
|
||||
void Audio::meStop()
|
||||
{
|
||||
p->me.stop();
|
||||
}
|
||||
|
||||
void Audio::meFade(int time)
|
||||
{
|
||||
p->me.fade(time);
|
||||
}
|
||||
|
||||
|
||||
void Audio::sePlay(const char *filename,
|
||||
int volume,
|
||||
int pitch)
|
||||
{
|
||||
p->se.play(filename, volume, pitch);
|
||||
}
|
||||
|
||||
void Audio::seStop()
|
||||
{
|
||||
p->se.stop();
|
||||
}
|
||||
|
||||
Audio::~Audio() { delete p; }
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
** audio.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
struct AudioPrivate;
|
||||
|
||||
class Audio
|
||||
{
|
||||
public:
|
||||
Audio();
|
||||
~Audio();
|
||||
|
||||
void bgmPlay(const char *filename, int volume = 100, int pitch = 100);
|
||||
void bgmStop();
|
||||
void bgmFade(int time);
|
||||
|
||||
void bgsPlay(const char *filename, int volume = 100, int pitch = 100);
|
||||
void bgsStop();
|
||||
void bgsFade(int time);
|
||||
|
||||
void mePlay(const char *filename, int volume = 100, int pitch = 100);
|
||||
void meStop();
|
||||
void meFade(int time);
|
||||
|
||||
void sePlay(const char *filename, int volume = 100, int pitch = 100);
|
||||
void seStop();
|
||||
|
||||
private:
|
||||
AudioPrivate *p;
|
||||
};
|
||||
|
||||
#endif // AUDIO_H
|
|
@ -0,0 +1,199 @@
|
|||
struct StaticRect { float x, y, w, h; };
|
||||
|
||||
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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 32.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 80.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 80.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 64.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 64.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 },
|
||||
{ 0.5, 64.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 16.5, 80.5, 15, 15 },
|
||||
{ 0.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 },
|
||||
{ 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, 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 },
|
||||
{ 80.5, 16.5, 15, 15 },
|
||||
{ 32.5, 48.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 },
|
||||
{ 64.5, 64.5, 15, 15 },
|
||||
{ 80.5, 64.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 64.5, 15, 15 },
|
||||
{ 80.5, 80.5, 15, 15 },
|
||||
{ 64.5, 16.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 48.5, 96.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.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 },
|
||||
{ 64.5, 0.5, 15, 15 },
|
||||
{ 80.5, 0.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.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 },
|
||||
{ 32.5, 32.5, 15, 15 },
|
||||
{ 48.5, 32.5, 15, 15 },
|
||||
{ 48.5, 112.5, 15, 15 },
|
||||
{ 32.5, 112.5, 15, 15 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 16.5, 32.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 },
|
||||
{ 64.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 64.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 },
|
||||
{ 64.5, 96.5, 15, 15 },
|
||||
{ 80.5, 96.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 64.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 },
|
||||
{ 0.5, 96.5, 15, 15 },
|
||||
{ 16.5, 96.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 0.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 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 80.5, 48.5, 15, 15 },
|
||||
{ 0.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 },
|
||||
{ 0.5, 96.5, 15, 15 },
|
||||
{ 80.5, 96.5, 15, 15 },
|
||||
{ 80.5, 112.5, 15, 15 },
|
||||
{ 0.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 },
|
||||
{ 0.5, 32.5, 15, 15 },
|
||||
{ 80.5, 32.5, 15, 15 },
|
||||
{ 16.5, 112.5, 15, 15 },
|
||||
{ 64.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 }
|
||||
};
|
||||
|
||||
extern const int autotileRectsN = sizeof(autotileRects) / sizeof(autotileRects[0]);
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
** binding.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BINDING_H
|
||||
#define BINDING_H
|
||||
|
||||
struct ScriptBinding
|
||||
{
|
||||
/* Starts the part where the binding takes over,
|
||||
* loading the compressed scripts and executing them.
|
||||
* This function returns as soon as the scripts finish
|
||||
* execution or an error is encountered */
|
||||
void (*execute) (void);
|
||||
|
||||
/* Instructs the binding
|
||||
* to immediately terminate script execution. This
|
||||
* function will perform a longjmp instead of returning,
|
||||
* so be careful about any variables with local storage */
|
||||
void (*terminate) (void);
|
||||
};
|
||||
|
||||
/* VTable defined in the binding source */
|
||||
extern ScriptBinding *scriptBinding;
|
||||
|
||||
#endif // BINDING_H
|
|
@ -0,0 +1,573 @@
|
|||
/*
|
||||
** bitmap.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bitmap.h"
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_image.h"
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
#include "gl-util.h"
|
||||
#include "quad.h"
|
||||
#include "quadarray.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "glstate.h"
|
||||
#include "texpool.h"
|
||||
#include "shader.h"
|
||||
#include "filesystem.h"
|
||||
#include "font.h"
|
||||
#include "eventthread.h"
|
||||
|
||||
#define DISP_CLASS_NAME "bitmap"
|
||||
|
||||
struct BitmapPrivate
|
||||
{
|
||||
TexFBO tex;
|
||||
|
||||
/* 'setPixel()' calls are cached and executed
|
||||
* in batches on 'flush()' */
|
||||
PointArray pointArray;
|
||||
|
||||
Font *font;
|
||||
|
||||
BitmapPrivate()
|
||||
{
|
||||
font = &gState->defaultFont();
|
||||
}
|
||||
|
||||
void bindTextureWithMatrix()
|
||||
{
|
||||
Tex::bind(tex.tex);
|
||||
Tex::bindMatrix(tex.width, tex.height);
|
||||
}
|
||||
|
||||
void bindFBO()
|
||||
{
|
||||
FBO::bind(tex.fbo);
|
||||
}
|
||||
|
||||
void pushSetViewport() const
|
||||
{
|
||||
glState.pushSetViewport(tex.width, tex.height);
|
||||
}
|
||||
|
||||
void popViewport() const
|
||||
{
|
||||
glState.popViewport();
|
||||
}
|
||||
|
||||
void blitQuad(Quad &quad)
|
||||
{
|
||||
glState.blendMode.pushSet(BlendNone);
|
||||
quad.draw();
|
||||
glState.blendMode.pop();
|
||||
}
|
||||
|
||||
void flushPoints()
|
||||
{
|
||||
if (pointArray.count() == 0)
|
||||
return;
|
||||
|
||||
Tex::unbind();
|
||||
bindFBO();
|
||||
pushSetViewport();
|
||||
glState.blendMode.pushSet(BlendNone);
|
||||
|
||||
pointArray.commit();
|
||||
pointArray.draw();
|
||||
pointArray.reset();
|
||||
|
||||
glState.blendMode.pop();
|
||||
popViewport();
|
||||
}
|
||||
|
||||
void fillRect(const IntRect &rect,
|
||||
const Vec4 &color)
|
||||
{
|
||||
flushPoints();
|
||||
|
||||
bindFBO();
|
||||
|
||||
glState.scissorTest.pushSet(true);
|
||||
glState.scissorBox.pushSet(rect);
|
||||
glState.clearColor.pushSet(color);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glState.clearColor.pop();
|
||||
glState.scissorBox.pop();
|
||||
glState.scissorTest.pop();
|
||||
}
|
||||
|
||||
static void ensureFormat(SDL_Surface *&surf, Uint32 format)
|
||||
{
|
||||
if (surf->format->format == format)
|
||||
return;
|
||||
|
||||
SDL_Surface *surfConv = SDL_ConvertSurfaceFormat(surf, format, 0);
|
||||
SDL_FreeSurface(surf);
|
||||
surf = surfConv;
|
||||
}
|
||||
};
|
||||
|
||||
Bitmap::Bitmap(const char *filename)
|
||||
{
|
||||
SDL_RWops ops;
|
||||
gState->fileSystem().openRead(ops, filename, FileSystem::Image);
|
||||
SDL_Surface *imgSurf = IMG_Load_RW(&ops, 1);
|
||||
|
||||
if (!imgSurf)
|
||||
throw Exception(Exception::SDLError, "SDL: %s", SDL_GetError());
|
||||
|
||||
p = new BitmapPrivate;
|
||||
|
||||
p->ensureFormat(imgSurf, SDL_PIXELFORMAT_ABGR8888);
|
||||
|
||||
p->tex = gState->texPool().request(imgSurf->w, imgSurf->h);
|
||||
|
||||
Tex::bind(p->tex.tex);
|
||||
Tex::uploadImage(p->tex.width, p->tex.height, imgSurf->pixels, GL_RGBA);
|
||||
|
||||
SDL_FreeSurface(imgSurf);
|
||||
}
|
||||
|
||||
Bitmap::Bitmap(int width, int height)
|
||||
{
|
||||
p = new BitmapPrivate;
|
||||
|
||||
p->tex = gState->texPool().request(width, height);
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
Bitmap::Bitmap(const Bitmap &other)
|
||||
{
|
||||
p = new BitmapPrivate;
|
||||
|
||||
p->tex = gState->texPool().request(other.width(), other.height());
|
||||
|
||||
other.flush();
|
||||
blt(0, 0, other, rect());
|
||||
}
|
||||
|
||||
Bitmap::~Bitmap()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
int Bitmap::width() const
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
return p->tex.width;
|
||||
}
|
||||
|
||||
int Bitmap::height() const
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
return p->tex.height;
|
||||
}
|
||||
|
||||
IntRect Bitmap::rect() const
|
||||
{
|
||||
return IntRect(0, 0, width(), height());
|
||||
}
|
||||
|
||||
void Bitmap::blt(int x, int y,
|
||||
const Bitmap &source, const IntRect &rect,
|
||||
int opacity)
|
||||
{
|
||||
stretchBlt(IntRect(x, y, rect.w, rect.h),
|
||||
source, rect, opacity);
|
||||
}
|
||||
|
||||
void Bitmap::stretchBlt(const IntRect &destRect,
|
||||
const Bitmap &source, const IntRect &sourceRect,
|
||||
int opacity)
|
||||
{
|
||||
GUARD_DISPOSED;
|
||||
|
||||
opacity = bound(opacity, 0, 255);
|
||||
|
||||
if (opacity == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// else if (opacity == 255) /* Fast blit */
|
||||
// {
|
||||
// flush();
|
||||
|
||||
// FBO::bind(source.p->tex.fbo, FBO::Read);
|
||||
// FBO::bind(p->tex.fbo, FBO::Draw);
|
||||
|
||||
// FBO::blit(sourceRect.x, sourceRect.y, sourceRect.w, sourceRect.h,
|
||||
// destRect.x, destRect.y, destRect.w, destRect.h);
|
||||
// }
|
||||
else /* Fragment pipeline */
|
||||
{
|
||||
flush();
|
||||
|
||||
float normOpacity = (float) opacity / 255.0f;
|
||||
|
||||
TexFBO &gpTex = gState->gpTexFBO(destRect.w, destRect.h);
|
||||
|
||||
FBO::bind(gpTex.fbo, FBO::Draw);
|
||||
FBO::bind(p->tex.fbo, FBO::Read);
|
||||
FBO::blit(destRect.x, destRect.y, 0, 0, destRect.w, destRect.h);
|
||||
|
||||
FloatRect bltSubRect((float) sourceRect.x / source.width(),
|
||||
(float) sourceRect.y / source.height(),
|
||||
((float) source.width() / sourceRect.w) * ((float) destRect.w / gpTex.width),
|
||||
((float) source.height() / sourceRect.h) * ((float) destRect.h / gpTex.height));
|
||||
|
||||
BltShader &shader = gState->bltShader();
|
||||
shader.bind();
|
||||
shader.setDestination(gpTex.tex);
|
||||
shader.setSubRect(bltSubRect);
|
||||
shader.setOpacity(normOpacity);
|
||||
|
||||
Quad quad;
|
||||
quad.setTexPosRect(sourceRect, destRect);
|
||||
quad.setColor(Vec4(1, 1, 1, normOpacity));
|
||||
|
||||
source.p->bindTextureWithMatrix();
|
||||
p->bindFBO();
|
||||
p->pushSetViewport();
|
||||
|
||||
p->blitQuad(quad);
|
||||
|
||||
p->popViewport();
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
void Bitmap::fillRect(int x, int y,
|
||||
int width, int height,
|
||||
const Vec4 &color)
|
||||
{
|
||||
fillRect(IntRect(x, y, width, height), color);
|
||||
}
|
||||
|
||||
void Bitmap::fillRect(const IntRect &rect, const Vec4 &color)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
p->fillRect(rect, color);
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
void Bitmap::gradientFillRect(int x, int y,
|
||||
int width, int height,
|
||||
const Vec4 &color1, const Vec4 &color2,
|
||||
bool vertical)
|
||||
{
|
||||
gradientFillRect(IntRect(x, y, width, height), color1, color2, vertical);
|
||||
}
|
||||
|
||||
void Bitmap::gradientFillRect(const IntRect &rect,
|
||||
const Vec4 &color1, const Vec4 &color2,
|
||||
bool vertical)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
flush();
|
||||
|
||||
Quad quad;
|
||||
|
||||
if (vertical)
|
||||
{
|
||||
quad.vert[0].color = color2;
|
||||
quad.vert[1].color = color2;
|
||||
quad.vert[2].color = color1;
|
||||
quad.vert[3].color = color1;
|
||||
}
|
||||
else
|
||||
{
|
||||
quad.vert[0].color = color1;
|
||||
quad.vert[3].color = color1;
|
||||
quad.vert[1].color = color2;
|
||||
quad.vert[2].color = color2;
|
||||
}
|
||||
|
||||
quad.setPosRect(rect);
|
||||
|
||||
Tex::unbind();
|
||||
p->bindFBO();
|
||||
p->pushSetViewport();
|
||||
|
||||
p->blitQuad(quad);
|
||||
|
||||
p->popViewport();
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
void Bitmap::clearRect(int x, int y, int width, int height)
|
||||
{
|
||||
clearRect(IntRect(x, y, width, height));
|
||||
}
|
||||
|
||||
void Bitmap::clearRect(const IntRect &rect)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
p->fillRect(rect, Vec4());
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
void Bitmap::clear()
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
/* Any queued points won't be visible after this anyway */
|
||||
p->pointArray.reset();
|
||||
|
||||
p->bindFBO();
|
||||
|
||||
glState.clearColor.pushSet(Vec4());
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glState.clearColor.pop();
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
Vec4 Bitmap::getPixel(int x, int y) const
|
||||
{
|
||||
GUARD_DISPOSED;
|
||||
|
||||
if (x < 0 || y < 0 || x >= width() || y >= height())
|
||||
return Vec4();
|
||||
|
||||
flush();
|
||||
|
||||
p->bindFBO();
|
||||
|
||||
glState.viewport.push();
|
||||
Vec4 pixel = FBO::getPixel(x, y, width(), height());
|
||||
glState.viewport.pop();
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
void Bitmap::setPixel(int x, int y, const Vec4 &color)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
p->pointArray.append(Vec2(x+.5, y+.5), color);
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
void Bitmap::hueChange(int hue)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
if ((hue % 360) == 0)
|
||||
return;
|
||||
|
||||
flush();
|
||||
|
||||
TexFBO newTex = gState->texPool().request(width(), height());
|
||||
|
||||
FloatRect texRect(rect());
|
||||
|
||||
Quad quad;
|
||||
quad.setTexPosRect(texRect, texRect);
|
||||
|
||||
/* Calculate hue parameter */
|
||||
hue = wrapRange(hue, 0, 359);
|
||||
float hueAdj = -((M_PI * 2) / 360) * hue;
|
||||
|
||||
HueShader &shader = gState->hueShader();
|
||||
shader.bind();
|
||||
shader.setHueAdjust(hueAdj);
|
||||
shader.setInputTexture(p->tex.tex);
|
||||
|
||||
FBO::bind(newTex.fbo);
|
||||
Tex::bindMatrix(width(), height());
|
||||
p->pushSetViewport();
|
||||
|
||||
p->blitQuad(quad);
|
||||
|
||||
shader.unbind();
|
||||
|
||||
p->popViewport();
|
||||
|
||||
gState->texPool().release(p->tex);
|
||||
p->tex = newTex;
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
void Bitmap::drawText(int x, int y,
|
||||
int width, int height,
|
||||
const char *str, int align)
|
||||
{
|
||||
drawText(IntRect(x, y, width, height), str, align);
|
||||
}
|
||||
|
||||
void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
if (*str == '\0')
|
||||
return;
|
||||
|
||||
flush();
|
||||
|
||||
TTF_Font *font = p->font->getSdlFont();
|
||||
|
||||
SDL_Color c;
|
||||
p->font->getColor()->toSDLColor(c);
|
||||
|
||||
SDL_Surface *txtSurf;
|
||||
|
||||
if (gState->rtData().config.solidFonts)
|
||||
txtSurf = TTF_RenderUTF8_Solid(font, str, c);
|
||||
else
|
||||
txtSurf = TTF_RenderUTF8_Blended(font, str, c);
|
||||
|
||||
p->ensureFormat(txtSurf, SDL_PIXELFORMAT_ARGB8888);
|
||||
|
||||
int alignX = rect.x;
|
||||
|
||||
switch (align)
|
||||
{
|
||||
default:
|
||||
case Left :
|
||||
break;
|
||||
|
||||
case Center :
|
||||
alignX += (rect.w - txtSurf->w) / 2;
|
||||
break;
|
||||
|
||||
case Right :
|
||||
alignX += rect.w - txtSurf->w;
|
||||
break;
|
||||
}
|
||||
|
||||
if (alignX < rect.x)
|
||||
alignX = rect.x;
|
||||
|
||||
int alignY = rect.y + (rect.h - txtSurf->h) / 2;
|
||||
|
||||
float squeeze = (float) rect.w / txtSurf->w;
|
||||
|
||||
if (squeeze > 1)
|
||||
squeeze = 1;
|
||||
|
||||
FloatRect posRect(alignX, alignY, txtSurf->w * squeeze, txtSurf->h);
|
||||
|
||||
Vec2 gpTexSize;
|
||||
gState->ensureTexSize(txtSurf->w, txtSurf->h, gpTexSize);
|
||||
|
||||
// if (str[1] != '\0')
|
||||
{
|
||||
/* Aquire a partial copy of the destination
|
||||
* buffer we're about to render to */
|
||||
TexFBO &gpTex2 = gState->gpTexFBO(posRect.w, posRect.h);
|
||||
|
||||
FBO::bind(gpTex2.fbo, FBO::Draw);
|
||||
FBO::bind(p->tex.fbo, FBO::Read);
|
||||
FBO::blit(posRect.x, posRect.y, 0, 0, posRect.w, posRect.h);
|
||||
|
||||
FloatRect bltRect(0, 0,
|
||||
gpTexSize.x / gpTex2.width,
|
||||
gpTexSize.y / gpTex2.height);
|
||||
|
||||
BltShader &shader = gState->bltShader();
|
||||
shader.bind();
|
||||
shader.setSource();
|
||||
shader.setDestination(gpTex2.tex);
|
||||
shader.setSubRect(bltRect);
|
||||
shader.setOpacity(p->font->getColor()->norm.w);
|
||||
}
|
||||
|
||||
gState->bindTex();
|
||||
Tex::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA);
|
||||
Tex::setSmooth(true);
|
||||
|
||||
Quad quad;
|
||||
quad.setTexRect(FloatRect(0, 0, txtSurf->w, txtSurf->h));
|
||||
quad.setPosRect(posRect);
|
||||
SDL_FreeSurface(txtSurf);
|
||||
|
||||
p->bindFBO();
|
||||
p->pushSetViewport();
|
||||
glState.blendMode.pushSet(BlendNone);
|
||||
|
||||
quad.draw();
|
||||
|
||||
glState.blendMode.pop();
|
||||
p->popViewport();
|
||||
|
||||
FragShader::unbind();
|
||||
|
||||
modified();
|
||||
}
|
||||
|
||||
IntRect Bitmap::textSize(const char *str)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
TTF_Font *font = p->font->getSdlFont();
|
||||
|
||||
int w, h;
|
||||
TTF_SizeUTF8(font, str, &w, &h);
|
||||
|
||||
// if (strlen(str) == 1)
|
||||
// TTF_GlyphMetrics(font, *str, 0, 0, 0, 0, &w);
|
||||
|
||||
return IntRect(0, 0, w, h);
|
||||
}
|
||||
|
||||
DEF_ATTR_SIMPLE(Bitmap, Font, Font*, p->font)
|
||||
|
||||
void Bitmap::flush() const
|
||||
{
|
||||
p->flushPoints();
|
||||
}
|
||||
|
||||
TexFBO &Bitmap::getGLTypes()
|
||||
{
|
||||
return p->tex;
|
||||
}
|
||||
|
||||
void Bitmap::bindTexWithMatrix()
|
||||
{
|
||||
p->bindTextureWithMatrix();
|
||||
}
|
||||
|
||||
|
||||
void Bitmap::releaseResources()
|
||||
{
|
||||
gState->texPool().release(p->tex);
|
||||
delete p;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
** bitmap.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
#include "disposable.h"
|
||||
#include "etc-internal.h"
|
||||
#include "etc.h"
|
||||
|
||||
#include "sigc++/signal.h"
|
||||
|
||||
class Font;
|
||||
struct TexFBO;
|
||||
|
||||
struct BitmapPrivate;
|
||||
// FIXME make this class use proper RGSS classes again
|
||||
class Bitmap : public Disposable
|
||||
{
|
||||
public:
|
||||
Bitmap(const char *filename);
|
||||
Bitmap(int width, int height);
|
||||
/* Clone constructor */
|
||||
Bitmap(const Bitmap &other);
|
||||
~Bitmap();
|
||||
|
||||
int width() const;
|
||||
int height() const;
|
||||
IntRect rect() const;
|
||||
|
||||
void blt(int x, int y,
|
||||
const Bitmap &source, const IntRect &rect,
|
||||
int opacity = 255);
|
||||
|
||||
void stretchBlt(const IntRect &destRect,
|
||||
const Bitmap &source, const IntRect &sourceRect,
|
||||
int opacity = 255);
|
||||
|
||||
void fillRect(int x, int y,
|
||||
int width, int height,
|
||||
const Vec4 &color);
|
||||
void fillRect(const IntRect &rect, const Vec4 &color);
|
||||
|
||||
/* RGSS2 */
|
||||
void gradientFillRect(int x, int y,
|
||||
int width, int height,
|
||||
const Vec4 &color1, const Vec4 &color2,
|
||||
bool vertical = false);
|
||||
void gradientFillRect(const IntRect &rect,
|
||||
const Vec4 &color1, const Vec4 &color2,
|
||||
bool vertical = false);
|
||||
|
||||
void clearRect(int x, int y,
|
||||
int width, int height);
|
||||
void clearRect(const IntRect &rect);
|
||||
|
||||
// void radialBlur(int angle, int divisions);
|
||||
// /* ----- */
|
||||
|
||||
void clear();
|
||||
|
||||
Vec4 getPixel(int x, int y) const;
|
||||
void setPixel(int x, int y, const Vec4 &color);
|
||||
|
||||
void hueChange(int hue);
|
||||
|
||||
enum TextAlign
|
||||
{
|
||||
Left = 0,
|
||||
Center = 1,
|
||||
Right = 2
|
||||
};
|
||||
|
||||
void drawText(int x, int y,
|
||||
int width, int height,
|
||||
const char *str, int align = Left);
|
||||
|
||||
void drawText(const IntRect &rect,
|
||||
const char *str, int align = Left);
|
||||
|
||||
IntRect textSize(const char *str);
|
||||
|
||||
DECL_ATTR(Font, Font*)
|
||||
|
||||
void flush() const;
|
||||
TexFBO &getGLTypes();
|
||||
void bindTexWithMatrix();
|
||||
|
||||
sigc::signal<void> modified;
|
||||
|
||||
private:
|
||||
void releaseResources();
|
||||
|
||||
BitmapPrivate *p;
|
||||
};
|
||||
|
||||
#endif // BITMAP_H
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
** config.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QFile>
|
||||
#include <QRegExp>
|
||||
|
||||
Config::Config()
|
||||
: debugMode(false),
|
||||
winResizable(false),
|
||||
fullscreen(false),
|
||||
vsync(false),
|
||||
defScreenW(640),
|
||||
defScreenH(480),
|
||||
solidFonts(false),
|
||||
gameFolder(".")
|
||||
{}
|
||||
|
||||
void Config::read()
|
||||
{
|
||||
QSettings confFile("mkxp.conf", QSettings::IniFormat);
|
||||
|
||||
#define READ_VAL(key, Type) key = confFile.value(#key, key).to##Type()
|
||||
|
||||
READ_VAL(debugMode, Bool);
|
||||
READ_VAL(winResizable, Bool);
|
||||
READ_VAL(fullscreen, Bool);
|
||||
READ_VAL(vsync, Bool);
|
||||
READ_VAL(defScreenW, Int);
|
||||
READ_VAL(defScreenH, Int);
|
||||
READ_VAL(solidFonts, Bool);
|
||||
READ_VAL(gameFolder, ByteArray);
|
||||
READ_VAL(customScript, ByteArray);
|
||||
|
||||
QStringList _rtps = confFile.value("RTPs").toStringList();
|
||||
Q_FOREACH(const QString &s, _rtps)
|
||||
rtps << s.toUtf8();
|
||||
}
|
||||
|
||||
void Config::readGameINI()
|
||||
{
|
||||
if (!customScript.isEmpty())
|
||||
{
|
||||
game.title = basename(customScript.constData());
|
||||
return;
|
||||
}
|
||||
|
||||
QSettings gameINI(gameFolder + "/Game.ini", QSettings::IniFormat);
|
||||
QFileInfo finfo(gameFolder.constData());
|
||||
game.title = gameINI.value("Game/Title", finfo.baseName()).toByteArray();
|
||||
|
||||
/* Gotta read the "Scripts" entry manually because Qt can't handle '\' */
|
||||
QFile gameINIFile(gameFolder + "/Game.ini");
|
||||
if (gameINIFile.open(QFile::ReadOnly))
|
||||
{
|
||||
QString gameINIContents = gameINIFile.readAll();
|
||||
QRegExp scriptsRE(".*Scripts=(.*)\r\nTitle=.*");
|
||||
if (scriptsRE.exactMatch(gameINIContents))
|
||||
{
|
||||
game.scripts = scriptsRE.cap(1).toUtf8();
|
||||
game.scripts.replace('\\', '/');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
** config.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
|
||||
struct Config
|
||||
{
|
||||
bool debugMode;
|
||||
|
||||
bool winResizable;
|
||||
bool fullscreen;
|
||||
bool vsync;
|
||||
|
||||
int defScreenW;
|
||||
int defScreenH;
|
||||
|
||||
bool solidFonts;
|
||||
|
||||
QByteArray gameFolder;
|
||||
|
||||
QByteArray customScript;
|
||||
QVector<QByteArray> rtps;
|
||||
|
||||
/* Game INI contents */
|
||||
struct {
|
||||
QByteArray scripts;
|
||||
QByteArray title;
|
||||
} game;
|
||||
|
||||
Config();
|
||||
|
||||
void read();
|
||||
void readGameINI();
|
||||
};
|
||||
|
||||
#endif // CONFIG_H
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
** debuglogger.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "debuglogger.h"
|
||||
|
||||
#include "GL/glew.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTime>
|
||||
#include <QTextStream>
|
||||
#include <QDebug>
|
||||
|
||||
struct DebugLoggerPrivate
|
||||
{
|
||||
QFile logFile;
|
||||
QTextStream *stream;
|
||||
|
||||
DebugLoggerPrivate(const char *logFilename)
|
||||
{
|
||||
if (logFilename)
|
||||
{
|
||||
logFile.setFileName(logFilename);
|
||||
logFile.open(QFile::WriteOnly);
|
||||
stream = new QTextStream(&logFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
stream = new QTextStream(stderr, QIODevice::WriteOnly);
|
||||
}
|
||||
}
|
||||
|
||||
~DebugLoggerPrivate()
|
||||
{
|
||||
delete stream;
|
||||
}
|
||||
|
||||
void writeTimestamp()
|
||||
{
|
||||
QTime time = QTime::currentTime();
|
||||
*stream << "[" << time.toString().toAscii() << "] ";
|
||||
}
|
||||
|
||||
void writeLine(const char *line)
|
||||
{
|
||||
*stream << line << "\n";
|
||||
stream->flush();
|
||||
}
|
||||
};
|
||||
|
||||
static void amdDebugFunc(GLuint id,
|
||||
GLenum category,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
GLvoid* userParam)
|
||||
{
|
||||
DebugLoggerPrivate *p = static_cast<DebugLoggerPrivate*>(userParam);
|
||||
|
||||
(void) id;
|
||||
(void) category;
|
||||
(void) severity;
|
||||
(void) length;
|
||||
|
||||
p->writeTimestamp();
|
||||
p->writeLine(message);
|
||||
}
|
||||
|
||||
static void arbDebugFunc(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
GLvoid* userParam)
|
||||
{
|
||||
DebugLoggerPrivate *p = static_cast<DebugLoggerPrivate*>(userParam);
|
||||
|
||||
(void) source;
|
||||
(void) type;
|
||||
(void) id;
|
||||
(void) severity;
|
||||
(void) length;
|
||||
|
||||
p->writeTimestamp();
|
||||
p->writeLine(message);
|
||||
}
|
||||
|
||||
DebugLogger::DebugLogger(const char *filename)
|
||||
{
|
||||
p = new DebugLoggerPrivate(filename);
|
||||
|
||||
if (GLEW_KHR_debug)
|
||||
glDebugMessageCallback(arbDebugFunc, p);
|
||||
else if (GLEW_ARB_debug_output)
|
||||
glDebugMessageCallbackARB(arbDebugFunc, p);
|
||||
else if (GLEW_AMD_debug_output)
|
||||
glDebugMessageCallbackAMD(amdDebugFunc, p);
|
||||
else
|
||||
qDebug() << "DebugLogger: no debug extensions found";
|
||||
}
|
||||
|
||||
DebugLogger::~DebugLogger()
|
||||
{
|
||||
delete p;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
** debuglogger.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DEBUGLOGGER_H
|
||||
#define DEBUGLOGGER_H
|
||||
|
||||
struct DebugLoggerPrivate;
|
||||
|
||||
class DebugLogger
|
||||
{
|
||||
public:
|
||||
DebugLogger(const char *filename = 0);
|
||||
~DebugLogger();
|
||||
|
||||
private:
|
||||
DebugLoggerPrivate *p;
|
||||
};
|
||||
|
||||
#endif // DEBUGLOGGER_H
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
** disposable.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DISPOSABLE_H
|
||||
#define DISPOSABLE_H
|
||||
|
||||
#include "exception.h"
|
||||
|
||||
#include "sigc++/signal.h"
|
||||
|
||||
class Disposable
|
||||
{
|
||||
public:
|
||||
Disposable()
|
||||
: disposed(false)
|
||||
{}
|
||||
|
||||
virtual ~Disposable() {}
|
||||
|
||||
void dispose()
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
releaseResources();
|
||||
disposed = true;
|
||||
wasDisposed();
|
||||
}
|
||||
|
||||
bool isDisposed() const { return disposed; }
|
||||
|
||||
sigc::signal<void> wasDisposed;
|
||||
|
||||
protected:
|
||||
virtual void releaseResources() = 0;
|
||||
|
||||
private:
|
||||
bool disposed;
|
||||
};
|
||||
|
||||
/* Every cpp needs to define DISP_CLASS_NAME for itself (lowercase) */
|
||||
#define GUARD_DISPOSED \
|
||||
{ if (isDisposed()) throw Exception(Exception::RGSSError, "disposed %S", DISP_CLASS_NAME); }
|
||||
|
||||
#endif // DISPOSABLE_H
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
** etc-internal.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ETC_TYPES_H
|
||||
#define ETC_TYPES_H
|
||||
|
||||
#include "util.h"
|
||||
|
||||
struct Vec2
|
||||
{
|
||||
float x, y;
|
||||
|
||||
Vec2()
|
||||
: x(0), y(0)
|
||||
{}
|
||||
|
||||
Vec2(float x, float y)
|
||||
: x(x), y(y)
|
||||
{}
|
||||
|
||||
bool operator==(const Vec2 &other) const
|
||||
{
|
||||
return (x == other.x && y == other.y);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vec4
|
||||
{
|
||||
float x, y, z, w;
|
||||
|
||||
Vec4()
|
||||
: x(0), y(0), z(0), w(0)
|
||||
{}
|
||||
|
||||
Vec4(float x, float y, float z, float w)
|
||||
: x(x), y(y), z(z), w(w)
|
||||
{}
|
||||
|
||||
bool operator==(const Vec4 &other) const
|
||||
{
|
||||
return (x == other.x && y == other.y && z == other.z && w == other.w);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vec2i
|
||||
{
|
||||
int x, y;
|
||||
|
||||
Vec2i()
|
||||
: x(0), y(0)
|
||||
{}
|
||||
|
||||
Vec2i(int x, int y)
|
||||
: x(x), y(y)
|
||||
{}
|
||||
|
||||
bool operator==(const Vec2i &other)
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
};
|
||||
|
||||
/* Simple Vertex */
|
||||
struct SVertex
|
||||
{
|
||||
Vec2 pos;
|
||||
Vec2 texPos;
|
||||
|
||||
static const void *posOffset()
|
||||
{
|
||||
return (const void*) 0;
|
||||
}
|
||||
|
||||
static const void *texPosOffset()
|
||||
{
|
||||
return (const void*) sizeof(Vec2);
|
||||
}
|
||||
};
|
||||
|
||||
/* Color Vertex */
|
||||
struct CVertex
|
||||
{
|
||||
Vec2 pos;
|
||||
Vec4 color;
|
||||
|
||||
CVertex()
|
||||
: color(1, 1, 1, 1)
|
||||
{}
|
||||
|
||||
static const void *posOffset()
|
||||
{
|
||||
return (const void*) 0;
|
||||
}
|
||||
|
||||
static const void *colorOffset()
|
||||
{
|
||||
return (const void*) sizeof(pos);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
Vec2 pos;
|
||||
Vec2 texPos;
|
||||
Vec4 color;
|
||||
|
||||
Vertex()
|
||||
: color(1, 1, 1, 1)
|
||||
{}
|
||||
|
||||
static const void *posOffset()
|
||||
{
|
||||
return (const void*) 0;
|
||||
}
|
||||
|
||||
static const void *texPosOffset()
|
||||
{
|
||||
return (const void*) sizeof(Vec2);
|
||||
}
|
||||
|
||||
static const void *colorOffset()
|
||||
{
|
||||
return (const void*) sizeof(SVertex);
|
||||
}
|
||||
};
|
||||
|
||||
struct IntRect
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
IntRect()
|
||||
: x(0), y(0), w(0), h(0)
|
||||
{}
|
||||
|
||||
IntRect(int x, int y, int w, int h)
|
||||
: x(x), y(y), w(w), h(h)
|
||||
{}
|
||||
|
||||
bool operator==(const IntRect &other) const
|
||||
{
|
||||
return (x == other.x && y == other.y &&
|
||||
w == other.w && h == other.h);
|
||||
}
|
||||
};
|
||||
|
||||
struct StaticRect { float x, y, w, h; };
|
||||
|
||||
struct FloatRect
|
||||
{
|
||||
float x, y, w, h;
|
||||
|
||||
FloatRect()
|
||||
: x(0), y(0), w(0), h(0)
|
||||
{}
|
||||
|
||||
FloatRect(float x, float y, float w, float h)
|
||||
: x(x), y(y), w(w), h(h)
|
||||
{}
|
||||
|
||||
FloatRect(const StaticRect &d)
|
||||
: x(d.x), y(d.y), w(d.w), h(d.h)
|
||||
{}
|
||||
|
||||
FloatRect(const IntRect &r)
|
||||
: x(r.x), y(r.y), w(r.w), h(r.h)
|
||||
{}
|
||||
|
||||
Vec2 topLeft() const { return Vec2(x, y); }
|
||||
Vec2 bottomLeft() const { return Vec2(x, y+h); }
|
||||
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
|
||||
* normalized representation */
|
||||
struct NormValue
|
||||
{
|
||||
int unNorm;
|
||||
float norm;
|
||||
|
||||
NormValue()
|
||||
: unNorm(0),
|
||||
norm(0)
|
||||
{}
|
||||
|
||||
NormValue(int unNorm)
|
||||
: unNorm(unNorm),
|
||||
norm(unNorm / 255.0)
|
||||
{}
|
||||
|
||||
void operator =(int value)
|
||||
{
|
||||
unNorm = bound(value, 0, 255);
|
||||
norm = unNorm / 255.0;
|
||||
}
|
||||
|
||||
operator int() const
|
||||
{
|
||||
return unNorm;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ETC_TYPES_H
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
** etc.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "etc.h"
|
||||
|
||||
#include "serial-util.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include "SDL2/SDL_types.h"
|
||||
#include "SDL2/SDL_pixels.h"
|
||||
|
||||
Color::Color(double red, double green, double blue, double alpha)
|
||||
: red(red), green(green), blue(blue), alpha(alpha)
|
||||
{
|
||||
updateInternal();
|
||||
}
|
||||
|
||||
Color::Color(const Vec4 &norm)
|
||||
: norm(norm)
|
||||
{
|
||||
updateExternal();
|
||||
}
|
||||
|
||||
Color::Color(const Color &o)
|
||||
: red(o.red), green(o.green), blue(o.blue), alpha(o.alpha),
|
||||
norm(o.norm)
|
||||
{}
|
||||
|
||||
bool Color::operator==(const Color &o) const
|
||||
{
|
||||
return red == o.red &&
|
||||
green == o.green &&
|
||||
blue == o.blue &&
|
||||
alpha == o.alpha;
|
||||
}
|
||||
|
||||
void Color::updateInternal()
|
||||
{
|
||||
norm.x = red / 255;
|
||||
norm.y = green / 255;
|
||||
norm.z = blue / 255;
|
||||
norm.w = alpha / 255;
|
||||
}
|
||||
|
||||
void Color::updateExternal()
|
||||
{
|
||||
red = norm.x * 255;
|
||||
green = norm.y * 255;
|
||||
blue = norm.z * 255;
|
||||
alpha = norm.w * 255;
|
||||
}
|
||||
|
||||
void Color::set(double red, double green, double blue, double alpha)
|
||||
{
|
||||
this->red = red;
|
||||
this->green = green;
|
||||
this->blue = blue;
|
||||
this->alpha = alpha;
|
||||
|
||||
updateInternal();
|
||||
}
|
||||
|
||||
void Color::setRed(double value)
|
||||
{
|
||||
red = value;
|
||||
norm.x = bound<double>(value, 0, 255) / 255;
|
||||
}
|
||||
|
||||
void Color::setGreen(double value)
|
||||
{
|
||||
green = value;
|
||||
norm.y = bound<double>(value, 0, 255) / 255;
|
||||
}
|
||||
|
||||
void Color::setBlue(double value)
|
||||
{
|
||||
blue = value;
|
||||
norm.z = bound<double>(value, 0, 255) / 255;
|
||||
}
|
||||
|
||||
void Color::setAlpha(double value)
|
||||
{
|
||||
alpha = value;
|
||||
norm.w = bound<double>(value, 0, 255) / 255;
|
||||
}
|
||||
|
||||
void Color::toSDLColor(SDL_Color &c) const
|
||||
{
|
||||
c.r = bound<double>(red, 0, 255);
|
||||
c.g = bound<double>(green, 0, 255);
|
||||
c.b = bound<double>(blue, 0, 255);
|
||||
// c.a = bound<double>(alpha, 0, 255);
|
||||
c.a = 255;
|
||||
}
|
||||
|
||||
/* Serializable */
|
||||
int Color::serialSize() const
|
||||
{
|
||||
return 4 * 8;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Color *Color::deserialize(const char *data, int len)
|
||||
{
|
||||
if (len != 32)
|
||||
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->updateInternal();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
Tone::Tone(double red, double green, double blue, double gray)
|
||||
: red(red), green(green), blue(blue), gray(gray)
|
||||
{
|
||||
updateInternal();
|
||||
}
|
||||
|
||||
Tone::Tone(const Tone &o)
|
||||
: red(o.red), green(o.green), blue(o.blue), gray(o.gray),
|
||||
norm(o.norm)
|
||||
{}
|
||||
|
||||
bool Tone::operator==(const Tone &o) const
|
||||
{
|
||||
return red == o.red &&
|
||||
green == o.green &&
|
||||
blue == o.blue &&
|
||||
gray == o.gray;
|
||||
}
|
||||
|
||||
void Tone::updateInternal()
|
||||
{
|
||||
norm.x = (float) bound<double>(red, -255, 255) / 255;
|
||||
norm.y = (float) bound<double>(green, -255, 255) / 255;
|
||||
norm.z = (float) bound<double>(blue, -255, 255) / 255;
|
||||
norm.w = (float) bound<double>(gray, 0, 255) / 255;
|
||||
}
|
||||
|
||||
void Tone::set(double red, double green, double blue, double gray)
|
||||
{
|
||||
this->red = red;
|
||||
this->green = green;
|
||||
this->blue = blue;
|
||||
this->gray = gray;
|
||||
|
||||
updateInternal();
|
||||
}
|
||||
|
||||
void Tone::setRed(double value)
|
||||
{
|
||||
red = value;
|
||||
norm.x = (float) bound<double>(value, -255, 255) / 255;
|
||||
}
|
||||
|
||||
void Tone::setGreen(double value)
|
||||
{
|
||||
green = value;
|
||||
norm.y = (float) bound<double>(value, -255, 255) / 255;
|
||||
}
|
||||
|
||||
void Tone::setBlue(double value)
|
||||
{
|
||||
blue = value;
|
||||
norm.z = (float) bound<double>(value, -255, 255) / 255;
|
||||
}
|
||||
|
||||
void Tone::setGray(double value)
|
||||
{
|
||||
gray = value;
|
||||
norm.w = (float) bound<double>(value, 0, 255) / 255;
|
||||
}
|
||||
|
||||
/* Serializable */
|
||||
int Tone::serialSize() const
|
||||
{
|
||||
return 4 * 8;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Tone *Tone::deserialize(const char *data, int len)
|
||||
{
|
||||
if (len != 32)
|
||||
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->updateInternal();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
Rect::Rect(int x, int y, int width, int height)
|
||||
: x(x), y(y), width(width), height(height)
|
||||
{}
|
||||
|
||||
Rect::Rect(const Rect &o)
|
||||
: x(o.x), y(o.y),
|
||||
width(o.width), height(o.height)
|
||||
{}
|
||||
|
||||
Rect::Rect(const IntRect &r)
|
||||
: x(r.x), y(r.y), width(r.w), height(r.h)
|
||||
{}
|
||||
|
||||
bool Rect::operator==(const Rect &o) const
|
||||
{
|
||||
return x == o.x &&
|
||||
y == o.y &&
|
||||
width == o.width &&
|
||||
height == o.height;
|
||||
}
|
||||
|
||||
void Rect::operator=(const IntRect &rect)
|
||||
{
|
||||
x = rect.x;
|
||||
y = rect.y;
|
||||
width = rect.w;
|
||||
height = rect.h;
|
||||
}
|
||||
|
||||
void Rect::set(int x, int y, int w, int h)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
width = w;
|
||||
height = h;
|
||||
valueChanged();
|
||||
}
|
||||
|
||||
void Rect::empty()
|
||||
{
|
||||
x = y = width = height = 0;
|
||||
valueChanged();
|
||||
}
|
||||
|
||||
int Rect::serialSize() const
|
||||
{
|
||||
return 4 * 4;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Rect *Rect::deserialize(const char *data, int len)
|
||||
{
|
||||
if (len != 16)
|
||||
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);
|
||||
|
||||
return r;
|
||||
}
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
** etc.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ETC_H
|
||||
#define ETC_H
|
||||
|
||||
#include "sigc++/signal.h"
|
||||
|
||||
#include "serializable.h"
|
||||
#include "etc-internal.h"
|
||||
|
||||
struct SDL_Color;
|
||||
|
||||
enum BlendType
|
||||
{
|
||||
BlendNone = -1, /* Only internal use */
|
||||
|
||||
BlendNormal = 0,
|
||||
BlendAddition = 1,
|
||||
BlendSubstraction = 2
|
||||
};
|
||||
|
||||
struct Color : public Serializable
|
||||
{
|
||||
Color()
|
||||
: red(0), green(0), blue(0), alpha(0)
|
||||
{}
|
||||
|
||||
Color(double red, double green, double blue, double alpha = 255);
|
||||
Color(const Vec4 &norm);
|
||||
Color(const Color &o);
|
||||
|
||||
bool operator==(const Color &o) const;
|
||||
|
||||
void updateInternal();
|
||||
void updateExternal();
|
||||
|
||||
void set(double red, double green, double blue, double alpha);
|
||||
void setRed(double value);
|
||||
void setGreen(double value);
|
||||
void setBlue(double value);
|
||||
void setAlpha(double value);
|
||||
|
||||
double getRed() const { return red; }
|
||||
double getGreen() const { return green; }
|
||||
double getBlue() const { return blue; }
|
||||
double getAlpha() const { return alpha; }
|
||||
|
||||
bool hasEffect()
|
||||
{
|
||||
return (alpha != 0);
|
||||
}
|
||||
|
||||
void toSDLColor(SDL_Color &c) const;
|
||||
|
||||
/* Serializable */
|
||||
int serialSize() const;
|
||||
void serialize(char *buffer) const;
|
||||
static Color *deserialize(const char *data, int len);
|
||||
|
||||
/* Range (0.0 ~ 255.0) */
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
double alpha;
|
||||
|
||||
/* Normalized (0.0 ~ 1.0) */
|
||||
Vec4 norm;
|
||||
};
|
||||
|
||||
struct Tone : public Serializable
|
||||
{
|
||||
Tone()
|
||||
: red(0), green(0), blue(0), gray(0)
|
||||
{}
|
||||
|
||||
Tone(double red, double green, double blue, double gray = 0);
|
||||
Tone(const Tone &o);
|
||||
|
||||
bool operator==(const Tone &o) const;
|
||||
|
||||
void updateInternal();
|
||||
|
||||
void set(double red, double green, double blue, double gray);
|
||||
void setRed(double value);
|
||||
void setGreen(double value);
|
||||
void setBlue(double value);
|
||||
void setGray(double value);
|
||||
|
||||
double getRed() const { return red; }
|
||||
double getGreen() const { return green; }
|
||||
double getBlue() const { return blue; }
|
||||
double getGray() const { return gray; }
|
||||
|
||||
bool hasEffect()
|
||||
{
|
||||
return ((int)red != 0 ||
|
||||
(int)green != 0 ||
|
||||
(int)blue != 0 ||
|
||||
(int)gray != 0);
|
||||
}
|
||||
|
||||
/* Serializable */
|
||||
int serialSize() const;
|
||||
void serialize(char *buffer) const;
|
||||
static Tone *deserialize(const char *data, int len);
|
||||
|
||||
/* Range (-255.0 ~ 255.0) */
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
/* Range (0.0 ~ 255.0) */
|
||||
double gray;
|
||||
|
||||
/* Normalized (-1.0 ~ 1.0) */
|
||||
Vec4 norm;
|
||||
};
|
||||
|
||||
struct Rect : public Serializable
|
||||
{
|
||||
Rect()
|
||||
: x(0), y(0), width(0), height(0)
|
||||
{}
|
||||
|
||||
Rect(int x, int y, int width, int height);
|
||||
Rect(const Rect &o);
|
||||
Rect(const IntRect &r);
|
||||
|
||||
bool operator==(const Rect &o) const;
|
||||
void operator=(const IntRect &rect);
|
||||
void set(int x, int y, int w, int h);
|
||||
|
||||
FloatRect toFloatRect() const
|
||||
{
|
||||
return FloatRect(x, y, width, height);
|
||||
}
|
||||
|
||||
IntRect toIntRect()
|
||||
{
|
||||
return IntRect(x, y, width, height);
|
||||
}
|
||||
|
||||
void empty();
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return !(x || y || width || height);
|
||||
}
|
||||
|
||||
DECL_ATTR_INLINE(X, int, x)
|
||||
DECL_ATTR_INLINE(Y, int, y)
|
||||
DECL_ATTR_INLINE(Width, int, width)
|
||||
DECL_ATTR_INLINE(Height, int, height)
|
||||
|
||||
int serialSize() const;
|
||||
void serialize(char *buffer) const;
|
||||
static Rect *deserialize(const char *data, int len);
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
sigc::signal<void> valueChanged;
|
||||
};
|
||||
|
||||
/* For internal use.
|
||||
* All drawable classes have properties of one or more of the above
|
||||
* types, which in an interpreted environment act as independent
|
||||
* objects, and rely on the GC to clean them up. When a drawable
|
||||
* class is constructed, these properties must have default objects
|
||||
* that are constructed with the class. C++ however has no GC, so
|
||||
* there is no way to clean them up when used directly with it.
|
||||
* Therefore the default objects are first created embedded in the
|
||||
* drawable class (so they get destroyed automatically from within
|
||||
* C++ if no pointers were changed), and the binding then takes
|
||||
* care of properly allocating new, independent objects and replacing
|
||||
* the defaults. Thus both C++ and the interpreted API can be used
|
||||
* without memory leakage.
|
||||
* This can be removed at a later point when no testing directly
|
||||
* from C++ is needed anymore. */
|
||||
struct EtcTemps
|
||||
{
|
||||
Color color;
|
||||
Tone tone;
|
||||
Rect rect;
|
||||
};
|
||||
|
||||
#endif // ETC_H
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
** eventthread.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "eventthread.h"
|
||||
|
||||
#include "SDL2/SDL_events.h"
|
||||
#include "SDL2/SDL_joystick.h"
|
||||
#include "SDL2/SDL_messagebox.h"
|
||||
#include "SDL2/SDL_timer.h"
|
||||
#include "SDL2/SDL_thread.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
bool EventThread::keyStates[] = { false };
|
||||
|
||||
EventThread::JoyState EventThread::joyState =
|
||||
{
|
||||
0, 0, { false }
|
||||
};
|
||||
|
||||
EventThread::MouseState EventThread::mouseState =
|
||||
{
|
||||
0, 0, { false }
|
||||
};
|
||||
|
||||
const Uint32 REQUEST_TERMINATION = SDL_USEREVENT+0;
|
||||
const Uint32 REQUEST_SETFULLSCREEN = SDL_USEREVENT+1;
|
||||
const Uint32 REQUEST_WINRESIZE = SDL_USEREVENT+2;
|
||||
const Uint32 SHOW_MESSAGEBOX = SDL_USEREVENT+3;
|
||||
|
||||
|
||||
EventThread::EventThread()
|
||||
: fullscreen(false)
|
||||
{}
|
||||
|
||||
void EventThread::process(RGSSThreadData &rtData)
|
||||
{
|
||||
SDL_Event event;
|
||||
SDL_Window *win = rtData.window;
|
||||
WindowSizeNotify &windowSizeMsg = rtData.windowSizeMsg;
|
||||
|
||||
fullscreen = rtData.config.fullscreen;
|
||||
|
||||
bool terminate = false;
|
||||
|
||||
SDL_Joystick *js = 0;
|
||||
if (SDL_NumJoysticks() > 0)
|
||||
js = SDL_JoystickOpen(0);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!SDL_WaitEvent(&event))
|
||||
{
|
||||
qDebug() << "EventThread: Event error";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_WINDOWEVENT :
|
||||
switch (event.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_RESIZED :
|
||||
windowSizeMsg.notifyChange(event.window.data1,
|
||||
event.window.data2);
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_CLOSE :
|
||||
terminate = true;
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST :
|
||||
resetInput();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_QUIT :
|
||||
case REQUEST_TERMINATION :
|
||||
terminate = true;
|
||||
qDebug() << "EventThread termination requested";
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN :
|
||||
if (event.key.keysym.scancode == SDL_SCANCODE_RETURN &&
|
||||
(event.key.keysym.mod & KMOD_LALT))
|
||||
{
|
||||
setFullscreen(win, !fullscreen);
|
||||
break;
|
||||
}
|
||||
|
||||
keyStates[event.key.keysym.scancode] = true;
|
||||
break;
|
||||
|
||||
case REQUEST_SETFULLSCREEN :
|
||||
setFullscreen(win, static_cast<bool>(event.user.code));
|
||||
break;
|
||||
|
||||
case REQUEST_WINRESIZE :
|
||||
SDL_SetWindowSize(win, event.window.data1, event.window.data2);
|
||||
break;
|
||||
|
||||
case SHOW_MESSAGEBOX :
|
||||
SDL_ShowSimpleMessageBox(event.user.code,
|
||||
rtData.config.game.title.constData(),
|
||||
(const char*) event.user.data1, win);
|
||||
free(event.user.data1);
|
||||
msgBoxDone = true;
|
||||
break;
|
||||
|
||||
case SDL_KEYUP :
|
||||
keyStates[event.key.keysym.scancode] = false;
|
||||
break;
|
||||
|
||||
case SDL_JOYBUTTONDOWN :
|
||||
joyState.buttons[event.jbutton.button] = true;
|
||||
break;
|
||||
|
||||
case SDL_JOYBUTTONUP :
|
||||
joyState.buttons[event.jbutton.button] = false;
|
||||
break;
|
||||
|
||||
case SDL_JOYAXISMOTION :
|
||||
if (event.jaxis.axis == 0)
|
||||
joyState.xAxis = event.jaxis.value;
|
||||
else
|
||||
joyState.yAxis = event.jaxis.value;
|
||||
|
||||
break;
|
||||
|
||||
case SDL_JOYDEVICEADDED :
|
||||
if (event.jdevice.which > 0)
|
||||
break;
|
||||
|
||||
js = SDL_JoystickOpen(0);
|
||||
break;
|
||||
|
||||
case SDL_JOYDEVICEREMOVED :
|
||||
resetInput();
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN :
|
||||
mouseState.buttons[event.button.button] = true;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP :
|
||||
mouseState.buttons[event.button.button] = false;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION :
|
||||
mouseState.x = event.motion.x;
|
||||
mouseState.y = event.motion.y;
|
||||
break;
|
||||
}
|
||||
|
||||
if (terminate)
|
||||
break;
|
||||
}
|
||||
|
||||
if (SDL_JoystickGetAttached(js))
|
||||
SDL_JoystickClose(js);
|
||||
}
|
||||
|
||||
void EventThread::cleanup()
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
if (event.type == SHOW_MESSAGEBOX)
|
||||
{
|
||||
free(event.user.data1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventThread::resetInput()
|
||||
{
|
||||
memset(&keyStates, 0, sizeof(keyStates));
|
||||
memset(&joyState, 0, sizeof(joyState));
|
||||
memset(&mouseState.buttons, 0, sizeof(mouseState.buttons));
|
||||
}
|
||||
|
||||
void EventThread::setFullscreen(SDL_Window *win, bool mode)
|
||||
{
|
||||
SDL_SetWindowFullscreen
|
||||
(win, mode ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||
fullscreen = mode;
|
||||
}
|
||||
|
||||
void EventThread::requestTerminate()
|
||||
{
|
||||
SDL_Event event;
|
||||
event.type = REQUEST_TERMINATION;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void EventThread::requestFullscreenMode(bool mode)
|
||||
{
|
||||
if (mode == fullscreen)
|
||||
return;
|
||||
|
||||
SDL_Event event;
|
||||
event.type = REQUEST_SETFULLSCREEN;
|
||||
event.user.code = static_cast<Sint32>(mode);
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void EventThread::requestWindowResize(int width, int height)
|
||||
{
|
||||
SDL_Event event;
|
||||
event.type = REQUEST_WINRESIZE;
|
||||
event.window.data1 = width;
|
||||
event.window.data2 = height;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
void EventThread::showMessageBox(const char *body, int flags)
|
||||
{
|
||||
msgBoxDone = false;
|
||||
|
||||
SDL_Event event;
|
||||
event.user.code = flags;
|
||||
event.user.data1 = strdup(body);
|
||||
event.type = SHOW_MESSAGEBOX;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
/* Keep repainting screen while box is open */
|
||||
gState->graphics().repaintWait(&msgBoxDone);
|
||||
/* Prevent endless loops */
|
||||
resetInput();
|
||||
}
|
||||
|
||||
bool EventThread::getFullscreen()
|
||||
{
|
||||
return fullscreen;
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
** eventthread.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EVENTTHREAD_H
|
||||
#define EVENTTHREAD_H
|
||||
|
||||
#include "config.h"
|
||||
#include "etc-internal.h"
|
||||
|
||||
#include "SDL2/SDL_scancode.h"
|
||||
#include "SDL2/SDL_joystick.h"
|
||||
#include "SDL2/SDL_mouse.h"
|
||||
|
||||
#include "SDL2/SDL_mutex.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QVector>
|
||||
|
||||
struct RGSSThreadData;
|
||||
struct SDL_Thread;
|
||||
struct SDL_Window;
|
||||
|
||||
class EventThread
|
||||
{
|
||||
public:
|
||||
static bool keyStates[SDL_NUM_SCANCODES];
|
||||
|
||||
struct JoyState
|
||||
{
|
||||
int xAxis;
|
||||
int yAxis;
|
||||
|
||||
bool buttons[16];
|
||||
};
|
||||
|
||||
static JoyState joyState;
|
||||
|
||||
struct MouseState
|
||||
{
|
||||
int x, y;
|
||||
bool buttons[SDL_BUTTON_X2+1];
|
||||
};
|
||||
|
||||
static MouseState mouseState;
|
||||
|
||||
EventThread();
|
||||
|
||||
void process(RGSSThreadData &rtData);
|
||||
void cleanup();
|
||||
|
||||
/* Called from render thread */
|
||||
void requestFullscreenMode(bool mode);
|
||||
void requestWindowResize(int width, int height);
|
||||
|
||||
void requestTerminate();
|
||||
|
||||
bool getFullscreen();
|
||||
|
||||
void showMessageBox(const char *body, int flags = 0);
|
||||
|
||||
private:
|
||||
void resetInput();
|
||||
void setFullscreen(SDL_Window *, bool mode);
|
||||
bool fullscreen;
|
||||
volatile bool msgBoxDone;
|
||||
};
|
||||
|
||||
|
||||
struct WindowSizeNotify
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
|
||||
volatile bool changedFlag;
|
||||
volatile int w, h;
|
||||
|
||||
WindowSizeNotify()
|
||||
{
|
||||
mutex = SDL_CreateMutex();
|
||||
changedFlag = false;
|
||||
w = h = 0;
|
||||
}
|
||||
|
||||
~WindowSizeNotify()
|
||||
{
|
||||
SDL_DestroyMutex(mutex);
|
||||
}
|
||||
|
||||
/* Done from the sending side */
|
||||
void notifyChange(int w, int h)
|
||||
{
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
changedFlag = true;
|
||||
|
||||
SDL_UnlockMutex(mutex);
|
||||
}
|
||||
|
||||
/* Done from the receiving side */
|
||||
bool pollChange(int *w, int *h)
|
||||
{
|
||||
if (!changedFlag)
|
||||
return false;
|
||||
|
||||
SDL_LockMutex(mutex);
|
||||
|
||||
*w = this->w;
|
||||
*h = this->h;
|
||||
changedFlag = false;
|
||||
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct RGSSThreadData
|
||||
{
|
||||
/* Main thread sets this to request render thread to terminate */
|
||||
volatile bool rqTerm;
|
||||
/* In response, render thread sets this to confirm
|
||||
* that it received the request and isn't stuck */
|
||||
volatile bool rqTermAck;
|
||||
|
||||
EventThread *ethread;
|
||||
WindowSizeNotify windowSizeMsg;
|
||||
|
||||
const char *argv0;
|
||||
|
||||
SDL_Window *window;
|
||||
|
||||
Vec2 sizeResoRatio;
|
||||
|
||||
Config config;
|
||||
|
||||
QByteArray rgssErrorMsg;
|
||||
|
||||
RGSSThreadData(EventThread *ethread,
|
||||
const char *argv0,
|
||||
SDL_Window *window)
|
||||
: rqTerm(false),
|
||||
rqTermAck(false),
|
||||
ethread(ethread),
|
||||
argv0(argv0),
|
||||
window(window),
|
||||
sizeResoRatio(1, 1)
|
||||
{}
|
||||
};
|
||||
|
||||
#endif // EVENTTHREAD_H
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
** exception.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EXCEPTION_H
|
||||
#define EXCEPTION_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <stdio.h>
|
||||
|
||||
struct Exception
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
RGSSError,
|
||||
NoFileError,
|
||||
IOError,
|
||||
|
||||
/* Already defined by ruby */
|
||||
TypeError,
|
||||
ArgumentError,
|
||||
|
||||
/* New types introduced in mkxp */
|
||||
PHYSFSError,
|
||||
SDLError,
|
||||
MKXPError
|
||||
};
|
||||
|
||||
Type type;
|
||||
QByteArray fmt;
|
||||
QByteArray arg1;
|
||||
QByteArray arg2;
|
||||
|
||||
Exception(Type type, QByteArray fmt,
|
||||
QByteArray arg1 = QByteArray(),
|
||||
QByteArray arg2 = QByteArray())
|
||||
: type(type), fmt(fmt), arg1(arg1), arg2(arg2)
|
||||
{}
|
||||
|
||||
void snprintf(char *buffer, size_t bufSize) const
|
||||
{
|
||||
::snprintf(buffer, bufSize, fmt.constData(), arg1.constData(), arg2.constData());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // EXCEPTION_H
|
|
@ -0,0 +1,735 @@
|
|||
/*
|
||||
** filesystem.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "filesystem.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
struct RGSS_entryData
|
||||
{
|
||||
qint64 offset;
|
||||
quint64 size;
|
||||
quint32 startMagic;
|
||||
};
|
||||
|
||||
struct RGSS_entryHandle
|
||||
{
|
||||
RGSS_entryData data;
|
||||
quint32 currentMagic;
|
||||
quint64 currentOffset;
|
||||
PHYSFS_Io *io;
|
||||
|
||||
RGSS_entryHandle(const RGSS_entryData &data)
|
||||
: data(data),
|
||||
currentMagic(data.startMagic),
|
||||
currentOffset(0)
|
||||
{}
|
||||
|
||||
RGSS_entryHandle(const RGSS_entryHandle &other)
|
||||
: data(other.data),
|
||||
currentMagic(other.currentMagic),
|
||||
currentOffset(other.currentOffset)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef QList<QByteArray> QByteList;
|
||||
|
||||
struct RGSS_archiveData
|
||||
{
|
||||
PHYSFS_Io *archiveIo;
|
||||
QHash<QByteArray, RGSS_entryData> entryHash;
|
||||
QHash<QByteArray, bool> dirHash;
|
||||
};
|
||||
|
||||
static bool
|
||||
readUint32(PHYSFS_Io *io, quint32 &result)
|
||||
{
|
||||
char buff[4];
|
||||
PHYSFS_sint64 count = io->read(io, buff, 4);
|
||||
|
||||
result = ((buff[0] << 0x00) & 0x000000FF) |
|
||||
((buff[1] << 0x08) & 0x0000FF00) |
|
||||
((buff[2] << 0x10) & 0x00FF0000) |
|
||||
((buff[3] << 0x18) & 0xFF000000) ;
|
||||
|
||||
return (count == 4);
|
||||
}
|
||||
|
||||
#define RGSS_HEADER_1 0x53534752
|
||||
#define RGSS_HEADER_2 0x1004441
|
||||
|
||||
#define RGSS_MAGIC 0xDEADCAFE
|
||||
|
||||
#define PHYSFS_ALLOC(type) \
|
||||
static_cast<type*>(PHYSFS_getAllocator()->Malloc(sizeof(type)))
|
||||
|
||||
static inline quint32
|
||||
advanceMagic(quint32 &magic)
|
||||
{
|
||||
quint32 old = magic;
|
||||
|
||||
magic = magic * 7 + 3;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
struct MagicState
|
||||
{
|
||||
quint32 magic;
|
||||
quint64 offset;
|
||||
|
||||
MagicState(quint64 offset = 0)
|
||||
: offset(offset)
|
||||
{
|
||||
magic = RGSS_MAGIC;
|
||||
|
||||
for (uint i = 0; i < (offset/4); ++i)
|
||||
advanceBlock();
|
||||
}
|
||||
|
||||
quint8 advancePath()
|
||||
{
|
||||
quint8 ret = magic & 0xFF;
|
||||
|
||||
offset++;
|
||||
advanceBlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
quint8 advanceData()
|
||||
{
|
||||
quint8 ret = magic & 0xFF;
|
||||
|
||||
if (offset++ % 4 == 0)
|
||||
advanceBlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
void advanceBlock()
|
||||
{
|
||||
magic = magic * 7 + 3;
|
||||
}
|
||||
};
|
||||
|
||||
static PHYSFS_sint64
|
||||
RGSS_ioRead(PHYSFS_Io *self, void *buffer, PHYSFS_uint64 len)
|
||||
{
|
||||
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
|
||||
|
||||
quint64 toRead = qMin(entry->data.size - entry->currentOffset, len);
|
||||
quint64 offs = entry->currentOffset;
|
||||
|
||||
entry->io->seek(entry->io, entry->data.offset + offs);
|
||||
|
||||
quint64 buffI = 0;
|
||||
for (quint64 o = offs; o < offs + toRead;)
|
||||
{
|
||||
quint8 bitOffset = (0x8 * (o % 4));
|
||||
quint8 magicByte = (entry->currentMagic >> bitOffset) & 0xFF;
|
||||
|
||||
quint8 byte;
|
||||
entry->io->read(entry->io, &byte, 1);
|
||||
|
||||
((quint8*) buffer)[buffI++] = byte ^ magicByte;
|
||||
|
||||
if (++o % 4 == 0)
|
||||
advanceMagic(entry->currentMagic);
|
||||
}
|
||||
|
||||
entry->currentOffset += toRead;
|
||||
|
||||
return toRead;
|
||||
}
|
||||
|
||||
static int
|
||||
RGSS_ioSeek(PHYSFS_Io *self, PHYSFS_uint64 offset)
|
||||
{
|
||||
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
|
||||
|
||||
if (offset == entry->currentOffset)
|
||||
return 1;
|
||||
|
||||
if (offset > entry->data.size-1)
|
||||
return 0;
|
||||
|
||||
/* If rewinding, we need to rewind to begining */
|
||||
if (offset < entry->currentOffset)
|
||||
{
|
||||
entry->currentOffset = 0;
|
||||
entry->currentMagic = entry->data.startMagic;
|
||||
}
|
||||
|
||||
/* For each 4 bytes sought, advance magic */
|
||||
quint64 dwordsSought = (offset - entry->currentOffset) / 4;
|
||||
for (quint64 i = 0; i < dwordsSought; ++i)
|
||||
advanceMagic(entry->currentMagic);
|
||||
|
||||
entry->currentOffset = offset;
|
||||
entry->io->seek(entry->io, entry->data.offset + entry->currentOffset);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static PHYSFS_sint64
|
||||
RGSS_ioTell(PHYSFS_Io *self)
|
||||
{
|
||||
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
|
||||
|
||||
return entry->currentOffset;
|
||||
}
|
||||
|
||||
static PHYSFS_sint64
|
||||
RGSS_ioLength(PHYSFS_Io *self)
|
||||
{
|
||||
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
|
||||
|
||||
return entry->data.size;
|
||||
}
|
||||
|
||||
static PHYSFS_Io*
|
||||
RGSS_ioDuplicate(PHYSFS_Io *self)
|
||||
{
|
||||
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
|
||||
RGSS_entryHandle *entryDup = new RGSS_entryHandle(*entry);
|
||||
|
||||
PHYSFS_Io *dup = PHYSFS_ALLOC(PHYSFS_Io);
|
||||
*dup = *self;
|
||||
dup->opaque = entryDup;
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
static void
|
||||
RGSS_ioDestroy(PHYSFS_Io *self)
|
||||
{
|
||||
RGSS_entryHandle *entry = static_cast<RGSS_entryHandle*>(self->opaque);
|
||||
|
||||
delete entry;
|
||||
|
||||
PHYSFS_getAllocator()->Free(self);
|
||||
}
|
||||
|
||||
static const PHYSFS_Io RGSS_IoTemplate =
|
||||
{
|
||||
0, /* version */
|
||||
0, /* opaque */
|
||||
RGSS_ioRead,
|
||||
0, /* write */
|
||||
RGSS_ioSeek,
|
||||
RGSS_ioTell,
|
||||
RGSS_ioLength,
|
||||
RGSS_ioDuplicate,
|
||||
0, /* flush */
|
||||
RGSS_ioDestroy
|
||||
};
|
||||
|
||||
static void*
|
||||
RGSS_openArchive(PHYSFS_Io *io, const char *, int forWrite)
|
||||
{
|
||||
if (forWrite)
|
||||
return 0;
|
||||
|
||||
/* Check header */
|
||||
quint32 header1, header2;
|
||||
readUint32(io, header1);
|
||||
readUint32(io, header2);
|
||||
|
||||
if (header1 != RGSS_HEADER_1 || header2 != RGSS_HEADER_2)
|
||||
return 0;
|
||||
|
||||
RGSS_archiveData *data = new RGSS_archiveData;
|
||||
data->archiveIo = io;
|
||||
|
||||
quint32 magic = RGSS_MAGIC;
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* Read filename length,
|
||||
* if nothing was read, no files remain */
|
||||
quint32 nameLen;
|
||||
if (!readUint32(io, nameLen))
|
||||
break;
|
||||
|
||||
nameLen ^= advanceMagic(magic);
|
||||
|
||||
static char nameBuf[512];
|
||||
uint i;
|
||||
for (i = 0; i < nameLen; ++i)
|
||||
{
|
||||
char c;
|
||||
io->read(io, &c, 1);
|
||||
nameBuf[i] = c ^ (advanceMagic(magic) & 0xFF);
|
||||
if (nameBuf[i] == '\\')
|
||||
nameBuf[i] = '/';
|
||||
}
|
||||
nameBuf[i] = 0;
|
||||
|
||||
quint32 entrySize;
|
||||
readUint32(io, entrySize);
|
||||
entrySize ^= advanceMagic(magic);
|
||||
|
||||
RGSS_entryData entry;
|
||||
entry.offset = io->tell(io);
|
||||
entry.size = entrySize;
|
||||
entry.startMagic = magic;
|
||||
|
||||
data->entryHash.insert(nameBuf, entry);
|
||||
|
||||
/* Test for new folder */
|
||||
for (i = nameLen; i > 0; i--)
|
||||
if (nameBuf[i] == '/')
|
||||
{
|
||||
nameBuf[i] = '\0';
|
||||
if (!data->dirHash.contains(nameBuf))
|
||||
data->dirHash.insert(nameBuf, true);
|
||||
}
|
||||
|
||||
io->seek(io, entry.offset + entry.size);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
RGSS_enumerateFiles(void *opaque, const char *dirname,
|
||||
PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
|
||||
|
||||
QString dirn(dirname);
|
||||
|
||||
char dirBuf[512];
|
||||
char baseBuf[512];
|
||||
QByteList keys = data->entryHash.keys();
|
||||
keys += data->dirHash.keys();
|
||||
|
||||
Q_FOREACH (const QByteArray &filename, keys)
|
||||
{
|
||||
/* Get the filename directory part */
|
||||
strcpy(dirBuf, filename.constData());
|
||||
strcpy(baseBuf, filename.constData());
|
||||
|
||||
/* Extract path and basename */
|
||||
const char *dirpath = "";
|
||||
char *basename = dirBuf;
|
||||
|
||||
for (int i = filename.size(); i >= 0; i--)
|
||||
if (dirBuf[i] == '/')
|
||||
{
|
||||
dirBuf[i] = '\0';
|
||||
dirpath = dirBuf;
|
||||
|
||||
basename = &dirBuf[i+1];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Compare to provided dirname */
|
||||
if (strcmp(dirpath, dirname) == 0)
|
||||
cb(callbackdata, origdir, basename);
|
||||
}
|
||||
}
|
||||
|
||||
static PHYSFS_Io*
|
||||
RGSS_openRead(void *opaque, const char *filename)
|
||||
{
|
||||
RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
|
||||
|
||||
if (!data->entryHash.contains(filename))
|
||||
return 0;
|
||||
|
||||
RGSS_entryHandle *entry = new RGSS_entryHandle(data->entryHash[filename]);
|
||||
entry->io = data->archiveIo->duplicate(data->archiveIo);
|
||||
|
||||
PHYSFS_Io *io = PHYSFS_ALLOC(PHYSFS_Io);
|
||||
|
||||
*io = RGSS_IoTemplate;
|
||||
io->opaque = entry;
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
static int
|
||||
RGSS_stat(void *opaque, const char *filename, PHYSFS_Stat *stat)
|
||||
{
|
||||
RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
|
||||
|
||||
bool hasFile = data->entryHash.contains(filename);
|
||||
bool hasDir = data->dirHash.contains(filename);
|
||||
|
||||
if (!hasFile && !hasDir)
|
||||
{
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stat->modtime =
|
||||
stat->createtime =
|
||||
stat->accesstime = 0;
|
||||
stat->readonly = 1;
|
||||
|
||||
if (hasFile)
|
||||
{
|
||||
RGSS_entryData &entry = data->entryHash[filename];
|
||||
|
||||
stat->filesize = entry.size;
|
||||
stat->filetype = PHYSFS_FILETYPE_REGULAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
stat->filesize = 0;
|
||||
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
RGSS_closeArchive(void *opaque)
|
||||
{
|
||||
RGSS_archiveData *data = static_cast<RGSS_archiveData*>(opaque);
|
||||
|
||||
delete data;
|
||||
}
|
||||
|
||||
static PHYSFS_Io*
|
||||
RGSS_noop1(void*, const char*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
RGSS_noop2(void*, const char*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const PHYSFS_Archiver RGSS_Archiver =
|
||||
{
|
||||
0,
|
||||
{
|
||||
"RGSSAD",
|
||||
"RGSS encrypted archive format",
|
||||
"Jonas Kulla <Nyocurio@gmail.com>",
|
||||
"http://k-du.de/rgss/rgss.html",
|
||||
0 /* symlinks not supported */
|
||||
},
|
||||
RGSS_openArchive,
|
||||
RGSS_enumerateFiles,
|
||||
RGSS_openRead,
|
||||
RGSS_noop1, /* openWrite */
|
||||
RGSS_noop1, /* openAppend */
|
||||
RGSS_noop2, /* remove */
|
||||
RGSS_noop2, /* mkdir */
|
||||
RGSS_stat,
|
||||
RGSS_closeArchive
|
||||
};
|
||||
|
||||
FileStream::FileStream(PHYSFS_File *file)
|
||||
{
|
||||
p = file;
|
||||
}
|
||||
|
||||
FileStream::~FileStream()
|
||||
{
|
||||
// if (p)
|
||||
// PHYSFS_close(p);
|
||||
}
|
||||
|
||||
void FileStream::operator=(const FileStream &o)
|
||||
{
|
||||
p = o.p;
|
||||
}
|
||||
|
||||
sf::Int64 FileStream::read(void *data, sf::Int64 size)
|
||||
{
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
return PHYSFS_readBytes(p, data, size);
|
||||
}
|
||||
|
||||
sf::Int64 FileStream::seek(sf::Int64 position)
|
||||
{
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
int success = PHYSFS_seek(p, (PHYSFS_uint64) position);
|
||||
|
||||
return success ? position : -1;
|
||||
}
|
||||
|
||||
sf::Int64 FileStream::tell()
|
||||
{
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
return PHYSFS_tell(p);
|
||||
}
|
||||
|
||||
sf::Int64 FileStream::getSize()
|
||||
{
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
return PHYSFS_fileLength(p);
|
||||
}
|
||||
|
||||
sf::Int64 FileStream::write(const void *data, sf::Int64 size)
|
||||
{
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
return PHYSFS_writeBytes(p, data, size);
|
||||
}
|
||||
|
||||
void FileStream::close()
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
PHYSFS_close(p);
|
||||
p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void enumCB(void *, const char *origdir,
|
||||
const char *fname)
|
||||
{
|
||||
qDebug() << origdir << fname;
|
||||
char buf[128];
|
||||
sprintf(buf, "%s/%s", origdir, fname);
|
||||
PHYSFS_enumerateFilesCallback(buf, enumCB, 0);
|
||||
}
|
||||
|
||||
FileSystem::FileSystem(const char *argv0)
|
||||
{
|
||||
PHYSFS_init(argv0);
|
||||
PHYSFS_registerArchiver(&RGSS_Archiver);
|
||||
}
|
||||
|
||||
FileSystem::~FileSystem()
|
||||
{
|
||||
if (PHYSFS_deinit() == 0)
|
||||
qDebug() << "PhyFS failed to deinit.";
|
||||
}
|
||||
|
||||
void FileSystem::addPath(const char *path)
|
||||
{
|
||||
PHYSFS_mount(path, 0, 1);
|
||||
}
|
||||
|
||||
static const char *imgExt[] =
|
||||
{
|
||||
"jpg",
|
||||
"png"
|
||||
};
|
||||
|
||||
static const char *audExt[] =
|
||||
{
|
||||
// "mid",
|
||||
// "midi",
|
||||
"mp3",
|
||||
"ogg",
|
||||
"wav",
|
||||
"wma" // FIXME this prolly isn't even supported lol
|
||||
};
|
||||
|
||||
static const char *fonExt[] =
|
||||
{
|
||||
"ttf"
|
||||
};
|
||||
|
||||
struct FileExtensions
|
||||
{
|
||||
const char **ext;
|
||||
int count;
|
||||
} fileExtensions[] =
|
||||
{
|
||||
{ imgExt, ARRAY_SIZE(imgExt) },
|
||||
{ audExt, ARRAY_SIZE(audExt) },
|
||||
{ fonExt, ARRAY_SIZE(fonExt) }
|
||||
};
|
||||
|
||||
static const char *completeFileName(const char *filename,
|
||||
FileSystem::FileType type)
|
||||
{
|
||||
static char buff[1024];
|
||||
|
||||
if (PHYSFS_exists(filename))
|
||||
return filename;
|
||||
|
||||
if (type != FileSystem::Undefined)
|
||||
{
|
||||
FileExtensions *extTest = &fileExtensions[type];
|
||||
for (int i = 0; i < extTest->count; ++i)
|
||||
{
|
||||
snprintf(buff, sizeof(buff), "%s.%s", filename, extTest->ext[i]);
|
||||
if (PHYSFS_exists(buff))
|
||||
return buff;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PHYSFS_File *openReadInt(const char *filename,
|
||||
FileSystem::FileType type)
|
||||
{
|
||||
const char *foundName = completeFileName(filename, type);
|
||||
|
||||
if (!foundName)
|
||||
throw Exception(Exception::NoFileError,
|
||||
"No such file or directory - %s", filename);
|
||||
|
||||
PHYSFS_File *handle = PHYSFS_openRead(foundName);
|
||||
if (!handle)
|
||||
throw Exception(Exception::PHYSFSError, "PhysFS: %s", PHYSFS_getLastError());
|
||||
|
||||
PHYSFS_fileLength(handle);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
FileStream FileSystem::openRead(const char *filename,
|
||||
FileType type)
|
||||
{
|
||||
PHYSFS_File *handle = openReadInt(filename, type);
|
||||
|
||||
return FileStream(handle);
|
||||
}
|
||||
|
||||
static inline PHYSFS_File *sdlPHYS(SDL_RWops *ops)
|
||||
{
|
||||
return static_cast<PHYSFS_File*>(ops->hidden.unknown.data1);
|
||||
}
|
||||
|
||||
static Sint64 SDL_RWopsSize(SDL_RWops *ops)
|
||||
{
|
||||
PHYSFS_File *f = sdlPHYS(ops);
|
||||
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
return PHYSFS_fileLength(f);
|
||||
}
|
||||
|
||||
static Sint64 SDL_RWopsSeek(SDL_RWops *ops, Sint64 offset, int whence)
|
||||
{
|
||||
PHYSFS_File *f = sdlPHYS(ops);
|
||||
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
Sint64 base;
|
||||
switch (whence)
|
||||
{
|
||||
default:
|
||||
case RW_SEEK_SET :
|
||||
base = 0;
|
||||
break;
|
||||
case RW_SEEK_CUR :
|
||||
base = PHYSFS_tell(f);
|
||||
break;
|
||||
case RW_SEEK_END :
|
||||
base = PHYSFS_fileLength(f);
|
||||
break;
|
||||
}
|
||||
|
||||
int result = PHYSFS_seek(f, base + offset);
|
||||
|
||||
return (result != 0) ? PHYSFS_tell(f) : -1;
|
||||
}
|
||||
|
||||
static size_t SDL_RWopsRead(SDL_RWops *ops, void *buffer, size_t size, size_t maxnum)
|
||||
{
|
||||
PHYSFS_File *f = sdlPHYS(ops);
|
||||
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
PHYSFS_sint64 result = PHYSFS_readBytes(f, buffer, size*maxnum);
|
||||
|
||||
return (result != -1) ? (result / size) : 0;
|
||||
}
|
||||
|
||||
static size_t SDL_RWopsWrite(SDL_RWops *ops, const void *buffer, size_t size, size_t num)
|
||||
{
|
||||
PHYSFS_File *f = sdlPHYS(ops);
|
||||
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
PHYSFS_sint64 result = PHYSFS_writeBytes(f, buffer, size*num);
|
||||
|
||||
return (result != -1) ? (result / size) : 0;
|
||||
}
|
||||
|
||||
static int SDL_RWopsClose(SDL_RWops *ops)
|
||||
{
|
||||
PHYSFS_File *f = sdlPHYS(ops);
|
||||
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
int result = PHYSFS_close(f);
|
||||
|
||||
return (result != 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
const Uint32 SDL_RWOPS_PHYSFS = SDL_RWOPS_UNKNOWN+10;
|
||||
|
||||
void FileSystem::openRead(SDL_RWops &ops,
|
||||
const char *filename,
|
||||
FileType type)
|
||||
{
|
||||
PHYSFS_File *handle = openReadInt(filename, type);
|
||||
|
||||
ops.size = SDL_RWopsSize;
|
||||
ops.seek = SDL_RWopsSeek;
|
||||
ops.read = SDL_RWopsRead;
|
||||
ops.write = SDL_RWopsWrite;
|
||||
ops.close = SDL_RWopsClose;
|
||||
|
||||
ops.type = SDL_RWOPS_PHYSFS;
|
||||
ops.hidden.unknown.data1 = handle;
|
||||
}
|
||||
|
||||
bool FileSystem::exists(const char *filename, FileType type)
|
||||
{
|
||||
const char *foundName = completeFileName(filename, type);
|
||||
|
||||
return (foundName != 0);
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
** filesystem.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FILESYSTEM_H
|
||||
#define FILESYSTEM_H
|
||||
|
||||
#include "SFML/System/InputStream.hpp"
|
||||
|
||||
#include "SDL2/SDL_rwops.h"
|
||||
|
||||
struct PHYSFS_File;
|
||||
|
||||
class FileStream : public sf::InputStream
|
||||
{
|
||||
public:
|
||||
FileStream(PHYSFS_File *);
|
||||
~FileStream();
|
||||
|
||||
void operator=(const FileStream &o);
|
||||
|
||||
sf::Int64 read(void *data, sf::Int64 size);
|
||||
sf::Int64 seek(sf::Int64 position);
|
||||
sf::Int64 tell();
|
||||
sf::Int64 getSize();
|
||||
|
||||
sf::Int64 write(const void *data, sf::Int64 size);
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
PHYSFS_File *p; /* NULL denotes invalid stream */
|
||||
};
|
||||
|
||||
class FileSystem
|
||||
{
|
||||
public:
|
||||
FileSystem(const char *argv0);
|
||||
~FileSystem();
|
||||
|
||||
void addPath(const char *path);
|
||||
|
||||
/* For extension supplementing */
|
||||
enum FileType
|
||||
{
|
||||
Image = 0,
|
||||
Audio,
|
||||
Font,
|
||||
Undefined
|
||||
};
|
||||
|
||||
FileStream openRead(const char *filename,
|
||||
FileType type = Undefined);
|
||||
|
||||
void openRead(SDL_RWops &ops,
|
||||
const char *filename,
|
||||
FileType type = Undefined);
|
||||
|
||||
bool exists(const char *filename,
|
||||
FileType type = Undefined);
|
||||
};
|
||||
|
||||
extern const Uint32 SDL_RWOPS_PHYSFS;
|
||||
|
||||
#endif // FILESYSTEM_H
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
** flashable.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FLASHABLE_H
|
||||
#define FLASHABLE_H
|
||||
|
||||
#include "etc.h"
|
||||
#include "etc-internal.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
class Flashable
|
||||
{
|
||||
public:
|
||||
Flashable()
|
||||
: flashColor(0, 0, 0, 0),
|
||||
flashing(false),
|
||||
emptyFlashFlag(false)
|
||||
{}
|
||||
|
||||
virtual ~Flashable() {}
|
||||
|
||||
void flash(const Vec4 *color, int duration)
|
||||
{
|
||||
if (duration < 1)
|
||||
return;
|
||||
|
||||
flashing = true;
|
||||
this->duration = duration;
|
||||
counter = 0;
|
||||
|
||||
if (!color)
|
||||
{
|
||||
emptyFlashFlag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
flashColor = *color;
|
||||
flashAlpha = flashColor.w;
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
if (!flashing)
|
||||
return;
|
||||
|
||||
if (++counter > duration)
|
||||
{
|
||||
/* Flash finished. Cleanup */
|
||||
flashColor = Vec4(0, 0, 0, 0);
|
||||
flashing = false;
|
||||
emptyFlashFlag = false;
|
||||
return;
|
||||
}
|
||||
|
||||
/* No need to update flash color on empty flash */
|
||||
if (emptyFlashFlag)
|
||||
return;
|
||||
|
||||
float prog = (float) counter / duration;
|
||||
flashColor.w = flashAlpha * (1 - prog);
|
||||
}
|
||||
|
||||
protected:
|
||||
Vec4 flashColor;
|
||||
bool flashing;
|
||||
bool emptyFlashFlag;
|
||||
private:
|
||||
float flashAlpha;
|
||||
int duration;
|
||||
int counter;
|
||||
};
|
||||
|
||||
#endif // FLASHABLE_H
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
** font.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "font.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "filesystem.h"
|
||||
#include "exception.h"
|
||||
|
||||
#include "../assets/liberation.ttf.xxd"
|
||||
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
#include <QPair>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define BUNDLED_FONT liberation
|
||||
|
||||
#define BUNDLED_FONT_D(f) assets_## f ##_ttf
|
||||
#define BUNDLED_FONT_L(f) assets_## f ##_ttf_len
|
||||
|
||||
// Go fuck yourself CPP
|
||||
#define BNDL_F_D(f) BUNDLED_FONT_D(f)
|
||||
#define BNDL_F_L(f) BUNDLED_FONT_L(f)
|
||||
|
||||
typedef QPair<QByteArray, int> FontKey;
|
||||
|
||||
struct FontPoolPrivate
|
||||
{
|
||||
QHash<FontKey, TTF_Font*> hash;
|
||||
};
|
||||
|
||||
FontPool::FontPool()
|
||||
{
|
||||
p = new FontPoolPrivate;
|
||||
}
|
||||
|
||||
FontPool::~FontPool()
|
||||
{
|
||||
QHash<FontKey, TTF_Font*>::const_iterator iter;
|
||||
for (iter = p->hash.begin(); iter != p->hash.end(); ++iter)
|
||||
TTF_CloseFont(iter.value());
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
static SDL_RWops *openBundledFont()
|
||||
{
|
||||
return SDL_RWFromConstMem(BNDL_F_D(BUNDLED_FONT), BNDL_F_L(BUNDLED_FONT));
|
||||
}
|
||||
|
||||
_TTF_Font *FontPool::request(const char *filename,
|
||||
int size)
|
||||
{
|
||||
// FIXME Find out how font path resolution is done in VX/Ace
|
||||
QByteArray nameKey = QByteArray(filename).toLower();
|
||||
nameKey.replace(' ', '_');
|
||||
|
||||
bool useBundled = false;
|
||||
QByteArray path = QByteArray("Fonts/") + nameKey;
|
||||
if (!gState->fileSystem().exists(path.constData(), FileSystem::Font))
|
||||
{
|
||||
useBundled = true;
|
||||
nameKey = " bundled";
|
||||
}
|
||||
|
||||
FontKey key(nameKey, size);
|
||||
|
||||
TTF_Font *font = p->hash.value(key, 0);
|
||||
|
||||
if (font)
|
||||
{
|
||||
// static int i=0;qDebug() << "FontPool: <?+>" << i++;
|
||||
return font;
|
||||
}
|
||||
|
||||
// qDebug() << "FontPool: <?->";
|
||||
|
||||
/* Not in hash, create */
|
||||
SDL_RWops *ops;
|
||||
|
||||
if (useBundled)
|
||||
{
|
||||
ops = openBundledFont();
|
||||
}
|
||||
else
|
||||
{
|
||||
ops = SDL_AllocRW();
|
||||
gState->fileSystem().openRead(*ops, path.constData(), FileSystem::Font);
|
||||
}
|
||||
|
||||
// FIXME 0.9 is guesswork at this point
|
||||
font = TTF_OpenFontRW(ops, 1, (float) size * .90);
|
||||
|
||||
if (!font)
|
||||
throw Exception(Exception::SDLError, "SDL: %s", SDL_GetError());
|
||||
|
||||
p->hash.insert(key, font);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
struct FontPrivate
|
||||
{
|
||||
QByteArray name;
|
||||
int size;
|
||||
bool bold;
|
||||
bool italic;
|
||||
Color *color;
|
||||
|
||||
Color colorTmp;
|
||||
|
||||
static QByteArray defaultName;
|
||||
static int defaultSize;
|
||||
static bool defaultBold;
|
||||
static bool defaultItalic;
|
||||
static Color *defaultColor;
|
||||
|
||||
static Color defaultColorTmp;
|
||||
|
||||
TTF_Font *sdlFont;
|
||||
|
||||
FontPrivate(const char *name = 0,
|
||||
int size = 0)
|
||||
: name(name ? QByteArray(name) : defaultName),
|
||||
size(size ? size : defaultSize),
|
||||
bold(defaultBold),
|
||||
italic(defaultItalic),
|
||||
color(&colorTmp),
|
||||
colorTmp(*defaultColor)
|
||||
{
|
||||
sdlFont = gState->fontPool().request(this->name.constData(),
|
||||
this->size);
|
||||
}
|
||||
};
|
||||
|
||||
QByteArray FontPrivate::defaultName = "Arial";
|
||||
int FontPrivate::defaultSize = 22;
|
||||
bool FontPrivate::defaultBold = false;
|
||||
bool FontPrivate::defaultItalic = false;
|
||||
Color *FontPrivate::defaultColor = &FontPrivate::defaultColorTmp;
|
||||
|
||||
Color FontPrivate::defaultColorTmp(255, 255, 255, 255);
|
||||
|
||||
bool Font::doesExist(const char *name)
|
||||
{
|
||||
QByteArray path = QByteArray("fonts/") + QByteArray(name);
|
||||
|
||||
return gState->fileSystem().exists(path.constData(), FileSystem::Font);
|
||||
}
|
||||
|
||||
Font::Font(const char *name,
|
||||
int size)
|
||||
{
|
||||
p = new FontPrivate(name, size);
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
const char *Font::getName() const
|
||||
{
|
||||
return p->name.constData();
|
||||
}
|
||||
|
||||
void Font::setName(const char *value)
|
||||
{
|
||||
p->name = value;
|
||||
}
|
||||
|
||||
void Font::setSize(int value)
|
||||
{
|
||||
if (p->size == value)
|
||||
return;
|
||||
|
||||
p->size = value;
|
||||
p->sdlFont = gState->fontPool().request(p->name.constData(), value);
|
||||
}
|
||||
|
||||
#undef CHK_DISP
|
||||
#define CHK_DISP
|
||||
|
||||
DEF_ATTR_RD_SIMPLE(Font, Size, int, p->size)
|
||||
DEF_ATTR_SIMPLE(Font, Bold, bool, p->bold)
|
||||
DEF_ATTR_SIMPLE(Font, Italic, bool, p->italic)
|
||||
DEF_ATTR_SIMPLE(Font, Color, Color*, p->color)
|
||||
|
||||
DEF_ATTR_SIMPLE_STATIC(Font, DefaultSize, int, FontPrivate::defaultSize)
|
||||
DEF_ATTR_SIMPLE_STATIC(Font, DefaultBold, bool, FontPrivate::defaultBold)
|
||||
DEF_ATTR_SIMPLE_STATIC(Font, DefaultItalic, bool, FontPrivate::defaultItalic)
|
||||
DEF_ATTR_SIMPLE_STATIC(Font, DefaultColor, Color*, FontPrivate::defaultColor)
|
||||
|
||||
const char *Font::getDefaultName()
|
||||
{
|
||||
return FontPrivate::defaultName.constData();
|
||||
}
|
||||
|
||||
void Font::setDefaultName(const char *value)
|
||||
{
|
||||
FontPrivate::defaultName = value;
|
||||
}
|
||||
|
||||
_TTF_Font *Font::getSdlFont()
|
||||
{
|
||||
int style = TTF_STYLE_NORMAL;
|
||||
|
||||
if (p->bold)
|
||||
style |= TTF_STYLE_BOLD;
|
||||
|
||||
if (p->italic)
|
||||
style |= TTF_STYLE_ITALIC;
|
||||
|
||||
TTF_SetFontStyle(p->sdlFont, style);
|
||||
|
||||
return p->sdlFont;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
** font.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef FONT_H
|
||||
#define FONT_H
|
||||
|
||||
#include "etc.h"
|
||||
#include "util.h"
|
||||
|
||||
struct _TTF_Font;
|
||||
struct FontPoolPrivate;
|
||||
|
||||
class FontPool
|
||||
{
|
||||
public:
|
||||
FontPool();
|
||||
~FontPool();
|
||||
|
||||
_TTF_Font *request(const char *filename,
|
||||
int size);
|
||||
|
||||
private:
|
||||
FontPoolPrivate *p;
|
||||
};
|
||||
|
||||
struct FontPrivate;
|
||||
|
||||
class Font
|
||||
{
|
||||
public:
|
||||
static bool doesExist(const char *name);
|
||||
|
||||
Font(const char *name = 0,
|
||||
int size = 0);
|
||||
~Font();
|
||||
|
||||
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_STATIC( DefaultName, const char* )
|
||||
DECL_ATTR_STATIC( DefaultSize, int )
|
||||
DECL_ATTR_STATIC( DefaultBold, bool )
|
||||
DECL_ATTR_STATIC( DefaultItalic, bool )
|
||||
DECL_ATTR_STATIC( DefaultColor, Color* )
|
||||
|
||||
/* internal */
|
||||
_TTF_Font *getSdlFont();
|
||||
|
||||
private:
|
||||
FontPrivate *p;
|
||||
};
|
||||
|
||||
#endif // FONT_H
|
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
** gl-util.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLUTIL_H
|
||||
#define GLUTIL_H
|
||||
|
||||
#include "GL/glew.h"
|
||||
|
||||
#include "etc-internal.h"
|
||||
#include <QDebug>
|
||||
|
||||
/* Struct wrapping GLuint for some light type safety */
|
||||
#define DEF_GL_ID \
|
||||
struct ID \
|
||||
{ \
|
||||
GLuint gl; \
|
||||
explicit ID(GLuint gl = 0) \
|
||||
: gl(gl) \
|
||||
{} \
|
||||
ID &operator=(const ID &o) \
|
||||
{ \
|
||||
gl = o.gl; \
|
||||
return *this; \
|
||||
} \
|
||||
bool operator==(const ID &o) const \
|
||||
{ \
|
||||
return gl == o.gl; \
|
||||
} \
|
||||
};
|
||||
|
||||
namespace Tex
|
||||
{
|
||||
DEF_GL_ID
|
||||
|
||||
inline ID gen()
|
||||
{
|
||||
ID id;
|
||||
glGenTextures(1, &id.gl);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
inline void del(ID id)
|
||||
{
|
||||
glDeleteTextures(1, &id.gl);
|
||||
}
|
||||
|
||||
inline void bind(ID id)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, id.gl);
|
||||
}
|
||||
|
||||
inline void unbind()
|
||||
{
|
||||
bind(ID(0));
|
||||
}
|
||||
|
||||
inline void bindMatrix(int width, int height, int xOffset = 0)
|
||||
{
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glScalef(1.f / width, 1.f / height, 1.f);
|
||||
glTranslatef(xOffset, 0, 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
inline void bindWithMatrix(ID id, int width, int height, int xOffset = 0)
|
||||
{
|
||||
bind(id);
|
||||
bindMatrix(width, height, xOffset);
|
||||
}
|
||||
|
||||
inline void uploadImage(GLsizei width, GLsizei height, const void *data, GLenum format)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
inline void uploadSubImage(GLint x, GLint y, GLsizei width, GLsizei height, const void *data, GLenum format)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, format, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
inline void allocEmpty(GLsizei width, GLsizei height)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
}
|
||||
|
||||
inline void setRepeat(bool mode)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
inline void setSmooth(bool mode)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mode ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mode ? GL_LINEAR : GL_NEAREST);
|
||||
}
|
||||
}
|
||||
|
||||
namespace RB
|
||||
{
|
||||
DEF_GL_ID
|
||||
|
||||
inline ID gen()
|
||||
{
|
||||
ID id;
|
||||
glGenRenderbuffers(1, &id.gl);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
inline void del(ID id)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &id.gl);
|
||||
}
|
||||
|
||||
inline void bind(ID id)
|
||||
{
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, id.gl);
|
||||
}
|
||||
|
||||
inline void unbind()
|
||||
{
|
||||
bind(ID(0));
|
||||
}
|
||||
|
||||
inline void allocEmpty(GLsizei width, GLsizei height)
|
||||
{
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
namespace FBO
|
||||
{
|
||||
DEF_GL_ID
|
||||
|
||||
enum Mode
|
||||
{
|
||||
Draw = 0,
|
||||
Read = 1,
|
||||
Default = 2
|
||||
};
|
||||
|
||||
inline ID gen()
|
||||
{
|
||||
ID id;
|
||||
glGenFramebuffers(1, &id.gl);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
inline void del(ID id)
|
||||
{
|
||||
glDeleteFramebuffers(1, &id.gl);
|
||||
}
|
||||
|
||||
inline void bind(ID id, Mode mode = Default)
|
||||
{
|
||||
static const GLenum modes[] =
|
||||
{
|
||||
GL_DRAW_FRAMEBUFFER,
|
||||
GL_READ_FRAMEBUFFER,
|
||||
GL_FRAMEBUFFER
|
||||
};
|
||||
|
||||
glBindFramebuffer(modes[mode], id.gl);
|
||||
}
|
||||
|
||||
inline void unbind(Mode mode = Default)
|
||||
{
|
||||
bind(ID(0), mode);
|
||||
}
|
||||
|
||||
inline void setTexTarget(Tex::ID texTarget, unsigned colorAttach = 0)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_TEXTURE_2D, texTarget.gl, 0);
|
||||
}
|
||||
|
||||
inline void setRBTarget(RB::ID rbTarget, unsigned colorAttach = 0)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_RENDERBUFFER, rbTarget.gl);
|
||||
}
|
||||
|
||||
inline void blit(int srcX, int srcY,
|
||||
int srcW, int srcH,
|
||||
int dstX, int dstY,
|
||||
int dstW, int dstH)
|
||||
{
|
||||
glBlitFramebuffer(srcX, srcY, srcX+srcW, srcY+srcH,
|
||||
dstX, dstY, dstX+dstW, dstY+dstH,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
}
|
||||
|
||||
inline void blit(int srcX, int srcY,
|
||||
int dstX, int dstY,
|
||||
int srcW, int srcH)
|
||||
{
|
||||
blit(srcX, srcY, srcW, srcH, dstX, dstY, srcW, srcH);
|
||||
}
|
||||
|
||||
inline Vec4 getPixel(int x, int y, int texWidth, int texHeight)
|
||||
{
|
||||
Vec4 pixel;
|
||||
|
||||
glViewport(0, 0, texWidth, texHeight);
|
||||
glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, &pixel.x);
|
||||
|
||||
return pixel;
|
||||
}
|
||||
}
|
||||
|
||||
namespace VAO
|
||||
{
|
||||
DEF_GL_ID
|
||||
|
||||
inline ID gen()
|
||||
{
|
||||
ID id;
|
||||
glGenVertexArrays(1, &id.gl);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
inline void del(ID id)
|
||||
{
|
||||
glDeleteVertexArrays(1, &id.gl);
|
||||
}
|
||||
|
||||
inline void bind(ID id)
|
||||
{
|
||||
glBindVertexArray(id.gl);
|
||||
}
|
||||
|
||||
inline void unbind()
|
||||
{
|
||||
bind(ID(0));
|
||||
}
|
||||
}
|
||||
|
||||
template<GLenum target>
|
||||
struct GenericBO
|
||||
{
|
||||
DEF_GL_ID
|
||||
|
||||
inline static ID gen()
|
||||
{
|
||||
ID id;
|
||||
glGenBuffers(1, &id.gl);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
inline static void del(ID id)
|
||||
{
|
||||
glDeleteBuffers(1, &id.gl);
|
||||
}
|
||||
|
||||
inline static void bind(ID id)
|
||||
{
|
||||
glBindBuffer(target, id.gl);
|
||||
}
|
||||
|
||||
inline static void unbind()
|
||||
{
|
||||
bind(ID(0));
|
||||
}
|
||||
|
||||
inline static void uploadData(GLsizeiptr size, const GLvoid *data, GLenum usage = GL_STATIC_DRAW)
|
||||
{
|
||||
glBufferData(target, size, data, usage);
|
||||
}
|
||||
|
||||
inline static void uploadSubData(GLintptr offset, GLsizeiptr size, const GLvoid *data)
|
||||
{
|
||||
glBufferSubData(target, offset, size, data);
|
||||
}
|
||||
|
||||
inline static void allocEmpty(GLsizeiptr size, GLenum usage = GL_STATIC_DRAW)
|
||||
{
|
||||
uploadData(size, 0, usage);
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct GenericBO<GL_ARRAY_BUFFER> VBO;
|
||||
typedef struct GenericBO<GL_ELEMENT_ARRAY_BUFFER> IBO;
|
||||
|
||||
struct TexFBO
|
||||
{
|
||||
Tex::ID tex;
|
||||
FBO::ID fbo;
|
||||
int width, height;
|
||||
|
||||
TexFBO()
|
||||
: tex(0), fbo(0), width(0), height(0)
|
||||
{}
|
||||
|
||||
bool operator==(const TexFBO &other) const
|
||||
{
|
||||
return (tex == other.tex) && (fbo == other.fbo);
|
||||
}
|
||||
|
||||
static inline void init(TexFBO &obj)
|
||||
{
|
||||
obj.tex = Tex::gen();
|
||||
obj.fbo = FBO::gen();
|
||||
Tex::bind(obj.tex);
|
||||
Tex::setRepeat(false);
|
||||
Tex::setSmooth(false);
|
||||
}
|
||||
|
||||
static inline void allocEmpty(TexFBO &obj, int width, int height)
|
||||
{
|
||||
Tex::bind(obj.tex);
|
||||
Tex::allocEmpty(width, height);
|
||||
obj.width = width;
|
||||
obj.height = height;
|
||||
}
|
||||
|
||||
static inline void linkFBO(TexFBO &obj)
|
||||
{
|
||||
FBO::bind(obj.fbo);
|
||||
FBO::setTexTarget(obj.tex);
|
||||
}
|
||||
|
||||
static inline void fini(TexFBO &obj)
|
||||
{
|
||||
FBO::del(obj.fbo);
|
||||
Tex::del(obj.tex);
|
||||
}
|
||||
};
|
||||
|
||||
struct RBFBO
|
||||
{
|
||||
RB::ID rb;
|
||||
FBO::ID fbo;
|
||||
int width, height;
|
||||
|
||||
RBFBO()
|
||||
: rb(0), fbo(0), width(0), height(0)
|
||||
{}
|
||||
|
||||
static inline void init(RBFBO &obj)
|
||||
{
|
||||
obj.rb = RB::gen();
|
||||
obj.fbo = FBO::gen();
|
||||
}
|
||||
|
||||
static inline void allocEmpty(RBFBO &obj, int width, int height)
|
||||
{
|
||||
RB::bind(obj.rb);
|
||||
RB::allocEmpty(width, height);
|
||||
obj.width = width;
|
||||
obj.height = height;
|
||||
}
|
||||
|
||||
static inline void linkFBO(RBFBO &obj)
|
||||
{
|
||||
FBO::bind(obj.fbo);
|
||||
FBO::setRBTarget(obj.rb);
|
||||
}
|
||||
|
||||
static inline void fini(RBFBO &obj)
|
||||
{
|
||||
FBO::del(obj.fbo);
|
||||
RB::del(obj.rb);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // GLUTIL_H
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
** global-ibo.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLOBALIBO_H
|
||||
#define GLOBALIBO_H
|
||||
|
||||
#include <gl-util.h>
|
||||
#include <QVector>
|
||||
|
||||
struct GlobalIBO
|
||||
{
|
||||
IBO::ID ibo;
|
||||
QVector<quint32> buffer;
|
||||
|
||||
GlobalIBO()
|
||||
{
|
||||
ibo = IBO::gen();
|
||||
}
|
||||
|
||||
~GlobalIBO()
|
||||
{
|
||||
IBO::del(ibo);
|
||||
}
|
||||
|
||||
void ensureSize(int quadCount)
|
||||
{
|
||||
if (buffer.size() >= quadCount*6)
|
||||
return;
|
||||
|
||||
int startInd = buffer.size() / 6;
|
||||
buffer.reserve(quadCount*6);
|
||||
|
||||
for (int i = startInd; i < quadCount; ++i)
|
||||
{
|
||||
static const int indTemp[] = { 0, 1, 2, 2, 3, 0 };
|
||||
|
||||
for (int j = 0; j < 6; ++j)
|
||||
buffer.append(i * 4 + indTemp[j]);
|
||||
}
|
||||
|
||||
IBO::bind(ibo);
|
||||
IBO::uploadData(buffer.count() * sizeof(int),
|
||||
buffer.constData());
|
||||
IBO::unbind();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // GLOBALIBO_H
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
** globalstate.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "globalstate.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "filesystem.h"
|
||||
#include "graphics.h"
|
||||
#include "input.h"
|
||||
#include "audio.h"
|
||||
#include "glstate.h"
|
||||
#include "shader.h"
|
||||
#include "texpool.h"
|
||||
#include "font.h"
|
||||
#include "eventthread.h"
|
||||
#include "gl-util.h"
|
||||
#include "global-ibo.h"
|
||||
#include "binding.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
GlobalState *GlobalState::instance = 0;
|
||||
static GlobalIBO *globalIBO = 0;
|
||||
|
||||
#define GAME_ARCHIVE "Game.rgssad"
|
||||
|
||||
struct GlobalStatePrivate
|
||||
{
|
||||
void *bindingData;
|
||||
SDL_Window *sdlWindow;
|
||||
Scene *screen;
|
||||
|
||||
FileSystem fileSystem;
|
||||
|
||||
EventThread &eThread;
|
||||
RGSSThreadData &rtData;
|
||||
Config &config;
|
||||
|
||||
Graphics graphics;
|
||||
Input input;
|
||||
Audio audio;
|
||||
|
||||
GLState _glState;
|
||||
|
||||
SpriteShader spriteShader;
|
||||
TransShader transShader;
|
||||
SimpleTransShader sTransShader;
|
||||
HueShader hueShader;
|
||||
BltShader bltShader;
|
||||
|
||||
TexPool texPool;
|
||||
FontPool fontPool;
|
||||
|
||||
Font *defaultFont;
|
||||
|
||||
Tex::ID globalTex;
|
||||
int globalTexW, globalTexH;
|
||||
|
||||
TexFBO gpTexFBO;
|
||||
|
||||
unsigned int stampCounter;
|
||||
|
||||
GlobalStatePrivate(RGSSThreadData *threadData)
|
||||
: bindingData(0),
|
||||
sdlWindow(threadData->window),
|
||||
fileSystem(threadData->argv0),
|
||||
eThread(*threadData->ethread),
|
||||
rtData(*threadData),
|
||||
config(threadData->config),
|
||||
graphics(threadData),
|
||||
stampCounter(0)
|
||||
{
|
||||
if (!config.gameFolder.isEmpty())
|
||||
{
|
||||
int unused = chdir(config.gameFolder.constData());
|
||||
(void) unused;
|
||||
fileSystem.addPath(config.gameFolder.constData());
|
||||
}
|
||||
|
||||
// FIXME find out correct archive filename
|
||||
QByteArray archPath = threadData->config.gameFolder + "/" GAME_ARCHIVE;
|
||||
|
||||
if (QFile::exists(archPath.constData()))
|
||||
fileSystem.addPath(archPath.constData());
|
||||
|
||||
for (int i = 0; i < config.rtps.count(); ++i)
|
||||
fileSystem.addPath(config.rtps[i].constData());
|
||||
|
||||
globalTexW = 128;
|
||||
globalTexH = 64;
|
||||
|
||||
globalTex = Tex::gen();
|
||||
Tex::bind(globalTex);
|
||||
Tex::setRepeat(false);
|
||||
Tex::setSmooth(false);
|
||||
Tex::allocEmpty(globalTexW, globalTexH);
|
||||
|
||||
TexFBO::init(gpTexFBO);
|
||||
/* Reuse starting values */
|
||||
TexFBO::allocEmpty(gpTexFBO, globalTexW, globalTexH);
|
||||
TexFBO::linkFBO(gpTexFBO);
|
||||
}
|
||||
|
||||
~GlobalStatePrivate()
|
||||
{
|
||||
Tex::del(globalTex);
|
||||
TexFBO::fini(gpTexFBO);
|
||||
}
|
||||
};
|
||||
|
||||
void GlobalState::initInstance(RGSSThreadData *threadData)
|
||||
{
|
||||
globalIBO = new GlobalIBO();
|
||||
globalIBO->ensureSize(1);
|
||||
|
||||
GlobalState *state = new GlobalState(threadData);
|
||||
|
||||
GlobalState::instance = state;
|
||||
|
||||
state->p->defaultFont = new Font();
|
||||
}
|
||||
|
||||
void GlobalState::finiInstance()
|
||||
{
|
||||
delete GlobalState::instance->p->defaultFont;
|
||||
|
||||
delete GlobalState::instance;
|
||||
|
||||
delete globalIBO;
|
||||
}
|
||||
|
||||
void GlobalState::setScreen(Scene &screen)
|
||||
{
|
||||
p->screen = &screen;
|
||||
}
|
||||
|
||||
#define GSATT(type, lower) \
|
||||
type GlobalState :: lower() \
|
||||
{ \
|
||||
return p->lower; \
|
||||
}
|
||||
|
||||
GSATT(void*, bindingData)
|
||||
GSATT(SDL_Window*, sdlWindow)
|
||||
GSATT(Scene*, screen)
|
||||
GSATT(FileSystem&, fileSystem)
|
||||
GSATT(EventThread&, eThread)
|
||||
GSATT(RGSSThreadData&, rtData)
|
||||
GSATT(Config&, config)
|
||||
GSATT(Graphics&, graphics)
|
||||
GSATT(Input&, input)
|
||||
GSATT(Audio&, audio)
|
||||
GSATT(GLState&, _glState)
|
||||
GSATT(SpriteShader&, spriteShader)
|
||||
GSATT(TransShader&, transShader)
|
||||
GSATT(SimpleTransShader&, sTransShader)
|
||||
GSATT(HueShader&, hueShader)
|
||||
GSATT(BltShader&, bltShader)
|
||||
GSATT(TexPool&, texPool)
|
||||
GSATT(FontPool&, fontPool)
|
||||
|
||||
void GlobalState::setBindingData(void *data)
|
||||
{
|
||||
p->bindingData = data;
|
||||
}
|
||||
|
||||
void GlobalState::ensureQuadIBO(int minSize)
|
||||
{
|
||||
globalIBO->ensureSize(minSize);
|
||||
}
|
||||
|
||||
void GlobalState::bindQuadIBO()
|
||||
{
|
||||
IBO::bind(globalIBO->ibo);
|
||||
}
|
||||
|
||||
void GlobalState::bindTex()
|
||||
{
|
||||
Tex::bind(p->globalTex);
|
||||
Tex::allocEmpty(p->globalTexW, p->globalTexH);
|
||||
Tex::bindMatrix(p->globalTexW, p->globalTexH);
|
||||
}
|
||||
|
||||
void GlobalState::ensureTexSize(int minW, int minH, Vec2 ¤tSizeOut)
|
||||
{
|
||||
if (minW > p->globalTexW)
|
||||
p->globalTexW = findNextPow2(minW);
|
||||
|
||||
if (minH > p->globalTexH)
|
||||
p->globalTexH = findNextPow2(minH);
|
||||
|
||||
currentSizeOut = Vec2(p->globalTexW, p->globalTexH);
|
||||
}
|
||||
|
||||
TexFBO &GlobalState::gpTexFBO(int minW, int minH)
|
||||
{
|
||||
bool needResize = false;
|
||||
|
||||
if (minW > p->gpTexFBO.width)
|
||||
{
|
||||
p->gpTexFBO.width = findNextPow2(minW);
|
||||
needResize = true;
|
||||
}
|
||||
|
||||
if (minH > p->gpTexFBO.height)
|
||||
{
|
||||
p->gpTexFBO.height = findNextPow2(minH);
|
||||
needResize = true;
|
||||
}
|
||||
|
||||
if (needResize)
|
||||
{
|
||||
Tex::bind(p->gpTexFBO.tex);
|
||||
Tex::allocEmpty(p->gpTexFBO.width, p->gpTexFBO.height);
|
||||
}
|
||||
|
||||
return p->gpTexFBO;
|
||||
}
|
||||
|
||||
void GlobalState::checkShutdown()
|
||||
{
|
||||
if (!p->rtData.rqTerm)
|
||||
return;
|
||||
|
||||
p->rtData.rqTermAck = true;
|
||||
p->texPool.disable();
|
||||
scriptBinding->terminate();
|
||||
}
|
||||
|
||||
Font &GlobalState::defaultFont()
|
||||
{
|
||||
return *p->defaultFont;
|
||||
}
|
||||
|
||||
unsigned int GlobalState::genTimeStamp()
|
||||
{
|
||||
return p->stampCounter++;
|
||||
}
|
||||
|
||||
GlobalState::GlobalState(RGSSThreadData *threadData)
|
||||
{
|
||||
p = new GlobalStatePrivate(threadData);
|
||||
p->screen = p->graphics.getScreen();
|
||||
}
|
||||
|
||||
GlobalState::~GlobalState()
|
||||
{
|
||||
delete p;
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
** globalstate.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLOBALSTATE_H
|
||||
#define GLOBALSTATE_H
|
||||
|
||||
#include "sigc++/signal.h"
|
||||
|
||||
#define gState GlobalState::instance
|
||||
#define glState gState->_glState()
|
||||
|
||||
struct GlobalStatePrivate;
|
||||
struct RGSSThreadData;
|
||||
struct GlobalIBO;
|
||||
struct mrb_state;
|
||||
struct SDL_Window;
|
||||
struct TexFBO;
|
||||
|
||||
class Scene;
|
||||
class FileSystem;
|
||||
class EventThread;
|
||||
class Graphics;
|
||||
class Input;
|
||||
class Audio;
|
||||
class GLState;
|
||||
class SpriteShader;
|
||||
class TransShader;
|
||||
class SimpleTransShader;
|
||||
class HueShader;
|
||||
class BltShader;
|
||||
class TexPool;
|
||||
class FontPool;
|
||||
class Font;
|
||||
struct GlobalIBO;
|
||||
struct Config;
|
||||
struct Vec2;
|
||||
|
||||
struct GlobalState
|
||||
{
|
||||
void *bindingData();
|
||||
void setBindingData(void *data);
|
||||
|
||||
SDL_Window *sdlWindow();
|
||||
|
||||
Scene *screen();
|
||||
void setScreen(Scene &screen);
|
||||
|
||||
FileSystem &fileSystem();
|
||||
|
||||
EventThread &eThread();
|
||||
RGSSThreadData &rtData();
|
||||
Config &config();
|
||||
|
||||
Graphics &graphics();
|
||||
Input &input();
|
||||
Audio &audio();
|
||||
|
||||
GLState &_glState();
|
||||
|
||||
SpriteShader &spriteShader();
|
||||
TransShader &transShader();
|
||||
SimpleTransShader &sTransShader();
|
||||
HueShader &hueShader();
|
||||
BltShader &bltShader();
|
||||
|
||||
TexPool &texPool();
|
||||
FontPool &fontPool();
|
||||
|
||||
Font &defaultFont();
|
||||
|
||||
sigc::signal<void> prepareDraw;
|
||||
|
||||
unsigned int genTimeStamp();
|
||||
|
||||
/* Returns global quad IBO, and ensures it has indices
|
||||
* for at least minSize quads */
|
||||
void ensureQuadIBO(int minSize);
|
||||
void bindQuadIBO();
|
||||
|
||||
/* Global general purpose texture */
|
||||
void bindTex();
|
||||
void ensureTexSize(int minW, int minH, Vec2 ¤tSizeOut);
|
||||
|
||||
TexFBO &gpTexFBO(int minW, int minH);
|
||||
|
||||
/* Checks EventThread's shutdown request flag and if set,
|
||||
* requests the binding to terminate. In this case, this
|
||||
* function will most likely not return */
|
||||
void checkShutdown();
|
||||
|
||||
static GlobalState *instance;
|
||||
static void initInstance(RGSSThreadData *threadData);
|
||||
static void finiInstance();
|
||||
|
||||
private:
|
||||
GlobalState(RGSSThreadData *threadData);
|
||||
~GlobalState();
|
||||
|
||||
GlobalStatePrivate *p;
|
||||
};
|
||||
|
||||
#endif // GLOBALSTATE_H
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
** glstate.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "glstate.h"
|
||||
#include "GL/glew.h"
|
||||
#include "SDL2/SDL_rect.h"
|
||||
#include "etc.h"
|
||||
|
||||
void GLClearColor::apply(const Vec4 &value)
|
||||
{
|
||||
glClearColor(value.x, value.y, value.z, value.w);
|
||||
}
|
||||
|
||||
void GLScissorBox::apply(const IntRect &value)
|
||||
{
|
||||
glScissor(value.x, value.y, value.w, value.h);
|
||||
}
|
||||
|
||||
void GLScissorBox::setIntersect(const IntRect &value)
|
||||
{
|
||||
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 };
|
||||
|
||||
SDL_Rect result;
|
||||
if (!SDL_IntersectRect(&r1, &r2, &result))
|
||||
result.w = result.h = 0;
|
||||
|
||||
set(IntRect(result.x, result.y, result.w, result.h));
|
||||
}
|
||||
|
||||
void GLScissorTest::apply(const bool &value)
|
||||
{
|
||||
value ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
void GLTexture2D::apply(const bool &value)
|
||||
{
|
||||
value ? glEnable(GL_TEXTURE_2D) : glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
void GLBlendMode::apply(const BlendType &value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case BlendNone :
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_ONE, GL_ZERO);
|
||||
break;
|
||||
|
||||
case BlendNormal :
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
|
||||
case BlendAddition :
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE,
|
||||
GL_ONE, GL_ONE);
|
||||
break;
|
||||
|
||||
case BlendSubstraction :
|
||||
// FIXME Alpha calculation is untested
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE,
|
||||
GL_ONE, GL_ONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GLViewport::apply(const IntRect &value)
|
||||
{
|
||||
glViewport(value.x, value.y, value.w, value.h);
|
||||
}
|
||||
|
||||
|
||||
void GLState::setViewport(int width, int height)
|
||||
{
|
||||
viewport.set(IntRect(0, 0, width, height));
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, width, 0, height, 0, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void GLState::pushSetViewport(int width, int height)
|
||||
{
|
||||
viewport.pushSet(IntRect(0, 0, width, height));
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0, width, 0, height, 0, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void GLState::popViewport()
|
||||
{
|
||||
viewport.pop();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
GLState::Caps::Caps()
|
||||
{
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
|
||||
}
|
||||
|
||||
GLState::GLState()
|
||||
{
|
||||
clearColor.init(Vec4(0, 0, 0, 1));
|
||||
blendMode.init(BlendNormal);
|
||||
scissorTest.init(false);
|
||||
scissorBox.init(IntRect(0, 0, 640, 480));
|
||||
texture2D.init(true);
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
** glstate.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLSTATE_H
|
||||
#define GLSTATE_H
|
||||
|
||||
#include "etc.h"
|
||||
#include <QStack>
|
||||
|
||||
template<typename T>
|
||||
struct GLProperty
|
||||
{
|
||||
void init(const T &value)
|
||||
{
|
||||
current = value;
|
||||
apply(value);
|
||||
}
|
||||
|
||||
void push() { stack.push(current); }
|
||||
void pop() { set(stack.pop()); }
|
||||
T &get() { return current; }
|
||||
void set(const T &value)
|
||||
{
|
||||
if (value == current)
|
||||
return;
|
||||
|
||||
init(value);
|
||||
}
|
||||
|
||||
void pushSet(const T &value)
|
||||
{
|
||||
push();
|
||||
set(value);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void apply(const T &value) = 0;
|
||||
|
||||
T current;
|
||||
QStack<T> stack;
|
||||
};
|
||||
|
||||
// Not needed
|
||||
template<typename T>
|
||||
struct GLPropSaver
|
||||
{
|
||||
GLPropSaver(GLProperty<T> &p)
|
||||
: p(p)
|
||||
{
|
||||
p.push();
|
||||
}
|
||||
|
||||
~GLPropSaver()
|
||||
{
|
||||
p.pop();
|
||||
}
|
||||
|
||||
private:
|
||||
GLProperty<T> &p;
|
||||
};
|
||||
|
||||
|
||||
class GLClearColor : public GLProperty<Vec4>
|
||||
{
|
||||
void apply(const Vec4 &);
|
||||
};
|
||||
|
||||
class GLScissorBox : public GLProperty<IntRect>
|
||||
{
|
||||
public:
|
||||
/* Sets the intersection of the current box with value */
|
||||
void setIntersect(const IntRect &value);
|
||||
|
||||
private:
|
||||
void apply(const IntRect &value);
|
||||
};
|
||||
|
||||
class GLScissorTest : public GLProperty<bool>
|
||||
{
|
||||
void apply(const bool &value);
|
||||
};
|
||||
|
||||
class GLTexture2D : public GLProperty<bool>
|
||||
{
|
||||
void apply(const bool &value);
|
||||
};
|
||||
|
||||
class GLBlendMode : public GLProperty<BlendType>
|
||||
{
|
||||
void apply(const BlendType &value);
|
||||
};
|
||||
|
||||
class GLViewport : public GLProperty<IntRect>
|
||||
{
|
||||
void apply(const IntRect &value);
|
||||
};
|
||||
|
||||
|
||||
class GLState
|
||||
{
|
||||
public:
|
||||
GLClearColor clearColor;
|
||||
GLScissorBox scissorBox;
|
||||
GLScissorTest scissorTest;
|
||||
GLTexture2D texture2D;
|
||||
GLBlendMode blendMode;
|
||||
GLViewport viewport;
|
||||
|
||||
/* These functions pushSet/pop both the viewport
|
||||
* and a glOrtho projection matrix.
|
||||
* Useful for setting up rendering to FBOs of differing sizes */
|
||||
void setViewport(int width, int height);
|
||||
void pushSetViewport(int width, int height);
|
||||
void popViewport();
|
||||
|
||||
struct Caps
|
||||
{
|
||||
int maxTexSize;
|
||||
|
||||
Caps();
|
||||
|
||||
} caps;
|
||||
|
||||
GLState();
|
||||
};
|
||||
|
||||
#endif // GLSTATE_H
|
|
@ -0,0 +1,855 @@
|
|||
/*
|
||||
** graphics.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "graphics.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "gl-util.h"
|
||||
#include "globalstate.h"
|
||||
#include "glstate.h"
|
||||
#include "shader.h"
|
||||
#include "scene.h"
|
||||
#include "quad.h"
|
||||
#include "eventthread.h"
|
||||
#include "texpool.h"
|
||||
#include "bitmap.h"
|
||||
#include "etc-internal.h"
|
||||
#include "binding.h"
|
||||
|
||||
#include "SDL2/SDL_video.h"
|
||||
#include "SDL2/SDL_timer.h"
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#include "SFML/System/Clock.hpp"
|
||||
|
||||
struct TimerQuery
|
||||
{
|
||||
GLuint query;
|
||||
static bool queryActive;
|
||||
bool thisQueryActive;
|
||||
|
||||
TimerQuery()
|
||||
: thisQueryActive(false)
|
||||
{
|
||||
glGenQueries(1, &query);
|
||||
}
|
||||
|
||||
void begin()
|
||||
{
|
||||
if (queryActive)
|
||||
return;
|
||||
|
||||
if (thisQueryActive)
|
||||
return;
|
||||
|
||||
glBeginQuery(GL_TIME_ELAPSED, query);
|
||||
queryActive = true;
|
||||
thisQueryActive = true;
|
||||
}
|
||||
|
||||
void end()
|
||||
{
|
||||
if (!thisQueryActive)
|
||||
return;
|
||||
|
||||
glEndQuery(GL_TIME_ELAPSED);
|
||||
queryActive = false;
|
||||
thisQueryActive = false;
|
||||
}
|
||||
|
||||
bool getResult(GLuint64 *result)
|
||||
{
|
||||
if (thisQueryActive)
|
||||
return false;
|
||||
|
||||
GLint isReady;
|
||||
glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &isReady);
|
||||
|
||||
if (isReady != GL_TRUE)
|
||||
{
|
||||
// qDebug() << "TimerQuery result not ready";
|
||||
return false;
|
||||
}
|
||||
|
||||
glGetQueryObjectui64v(query, GL_QUERY_RESULT, result);
|
||||
|
||||
if (glGetError() == GL_INVALID_OPERATION)
|
||||
{
|
||||
qDebug() << "Something went wrong with getting TimerQuery results";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLuint64 getResultSync()
|
||||
{
|
||||
if (thisQueryActive)
|
||||
return 0;
|
||||
|
||||
GLuint64 result;
|
||||
GLint isReady = GL_FALSE;
|
||||
|
||||
while (isReady == GL_FALSE)
|
||||
glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &isReady);
|
||||
|
||||
glGetQueryObjectui64v(query, GL_QUERY_RESULT, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
~TimerQuery()
|
||||
{
|
||||
if (thisQueryActive)
|
||||
end();
|
||||
|
||||
glDeleteQueries(1, &query);
|
||||
}
|
||||
};
|
||||
|
||||
bool TimerQuery::queryActive = false;
|
||||
|
||||
struct GPUTimer
|
||||
{
|
||||
TimerQuery queries[2];
|
||||
const int iter;
|
||||
|
||||
uchar ind;
|
||||
quint64 acc;
|
||||
qint32 counter;
|
||||
bool first;
|
||||
|
||||
GPUTimer(int iter)
|
||||
: iter(iter),
|
||||
ind(0),
|
||||
acc(0),
|
||||
counter(0),
|
||||
first(true)
|
||||
{}
|
||||
|
||||
void startTiming()
|
||||
{
|
||||
queries[ind].begin();
|
||||
}
|
||||
|
||||
void endTiming()
|
||||
{
|
||||
queries[ind].end();
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
return;
|
||||
}
|
||||
|
||||
swapInd();
|
||||
|
||||
GLuint64 result;
|
||||
if (!queries[ind].getResult(&result))
|
||||
return;
|
||||
|
||||
acc += result;
|
||||
|
||||
if (++counter < iter)
|
||||
return;
|
||||
|
||||
qDebug() << " Avg. GPU time:" << ((double) acc / (iter * 1000 * 1000)) << "ms";
|
||||
acc = counter = 0;
|
||||
}
|
||||
|
||||
void swapInd()
|
||||
{
|
||||
ind = ind ? 0 : 1;
|
||||
}
|
||||
};
|
||||
|
||||
struct CPUTimer
|
||||
{
|
||||
const int iter;
|
||||
|
||||
quint64 acc;
|
||||
qint32 counter;
|
||||
sf::Clock clock;
|
||||
|
||||
CPUTimer(int iter)
|
||||
: iter(iter),
|
||||
acc(0),
|
||||
counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
void startTiming()
|
||||
{
|
||||
clock.restart();
|
||||
}
|
||||
|
||||
void endTiming()
|
||||
{
|
||||
acc += clock.getElapsedTime().asMicroseconds();
|
||||
|
||||
if (++counter < iter)
|
||||
return;
|
||||
|
||||
qDebug() << "Avg. CPU time:" << ((double) acc / (iter * 1000)) << "ms";
|
||||
acc = counter = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct PingPong
|
||||
{
|
||||
TexFBO rt[2];
|
||||
unsigned srcInd, dstInd;
|
||||
int screenW, screenH;
|
||||
|
||||
PingPong(int screenW, int screenH)
|
||||
: srcInd(0), dstInd(1),
|
||||
screenW(screenW), screenH(screenH)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
TexFBO::init(rt[i]);
|
||||
TexFBO::allocEmpty(rt[i], screenW, screenH);
|
||||
TexFBO::linkFBO(rt[i]);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
~PingPong()
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
TexFBO::fini(rt[i]);
|
||||
}
|
||||
|
||||
/* Binds FBO of last good buffer for reading */
|
||||
void bindLastBuffer()
|
||||
{
|
||||
FBO::bind(rt[dstInd].fbo, FBO::Read);
|
||||
}
|
||||
|
||||
/* Better not call this during render cycles */
|
||||
void resize(int width, int height)
|
||||
{
|
||||
screenW = width;
|
||||
screenH = height;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
Tex::bind(rt[i].tex);
|
||||
Tex::allocEmpty(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void startRender()
|
||||
{
|
||||
bind();
|
||||
}
|
||||
|
||||
void swapRender()
|
||||
{
|
||||
swapIndices();
|
||||
|
||||
/* Discard dest buffer */
|
||||
Tex::bind(rt[dstInd].tex);
|
||||
Tex::allocEmpty(screenW, screenH);
|
||||
|
||||
bind();
|
||||
}
|
||||
|
||||
void blitFBOs()
|
||||
{
|
||||
FBO::blit(0, 0, 0, 0, screenW, screenH);
|
||||
}
|
||||
|
||||
void finishRender()
|
||||
{
|
||||
FBO::unbind(FBO::Draw);
|
||||
FBO::bind(rt[dstInd].fbo, FBO::Read);
|
||||
}
|
||||
|
||||
private:
|
||||
void bind()
|
||||
{
|
||||
Tex::bindWithMatrix(rt[srcInd].tex, screenW, screenH, true);
|
||||
FBO::bind(rt[srcInd].fbo, FBO::Read);
|
||||
FBO::bind(rt[dstInd].fbo, FBO::Draw);
|
||||
}
|
||||
|
||||
void swapIndices()
|
||||
{
|
||||
unsigned tmp = srcInd;
|
||||
srcInd = dstInd;
|
||||
dstInd = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
class ScreenScene : public Scene
|
||||
{
|
||||
public:
|
||||
ScreenScene(int width, int height)
|
||||
: pp(width, height),
|
||||
brightEffect(false),
|
||||
actW(width), actH(height)
|
||||
{
|
||||
updateReso(width, height);
|
||||
brightnessQuad.setColor(Vec4());
|
||||
}
|
||||
|
||||
void composite()
|
||||
{
|
||||
const int w = geometry.rect.w;
|
||||
const int h = geometry.rect.h;
|
||||
|
||||
gState->prepareDraw();
|
||||
|
||||
pp.startRender();
|
||||
|
||||
glState.setViewport(w, h);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
Scene::composite();
|
||||
|
||||
if (brightEffect)
|
||||
{
|
||||
glState.texture2D.pushSet(false);
|
||||
brightnessQuad.draw();
|
||||
glState.texture2D.pop();
|
||||
}
|
||||
|
||||
pp.finishRender();
|
||||
}
|
||||
|
||||
void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
|
||||
{
|
||||
pp.swapRender();
|
||||
pp.blitFBOs();
|
||||
|
||||
SpriteShader &shader = gState->spriteShader();
|
||||
shader.bind();
|
||||
shader.resetUniforms();
|
||||
shader.setColor(c);
|
||||
shader.setFlash(f);
|
||||
shader.setTone(t);
|
||||
|
||||
glState.blendMode.pushSet(BlendNone);
|
||||
|
||||
Tex::bindMatrix(geometry.rect.w, geometry.rect.h);
|
||||
screenQuad.draw();
|
||||
|
||||
glState.blendMode.pop();
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
void setBrightness(float norm)
|
||||
{
|
||||
brightnessQuad.setColor(Vec4(0, 0, 0, 1.0 - norm));
|
||||
|
||||
brightEffect = norm < 1.0;
|
||||
}
|
||||
|
||||
void updateReso(int width, int height)
|
||||
{
|
||||
geometry.rect.w = width;
|
||||
geometry.rect.h = height;
|
||||
|
||||
screenQuad.setTexPosRect(geometry.rect, geometry.rect);
|
||||
brightnessQuad.setTexPosRect(geometry.rect, geometry.rect);
|
||||
|
||||
notifyGeometryChange();
|
||||
}
|
||||
|
||||
void setResolution(int width, int height)
|
||||
{
|
||||
pp.resize(width, height);
|
||||
updateReso(width, height);
|
||||
}
|
||||
|
||||
void setScreenSize(int width, int height)
|
||||
{
|
||||
actW = width;
|
||||
actH = height;
|
||||
}
|
||||
|
||||
PingPong &getPP()
|
||||
{
|
||||
return pp;
|
||||
}
|
||||
|
||||
private:
|
||||
PingPong pp;
|
||||
Quad screenQuad;
|
||||
Quad brightnessQuad;
|
||||
bool brightEffect;
|
||||
int actW, actH;
|
||||
};
|
||||
|
||||
struct FPSLimiter
|
||||
{
|
||||
unsigned lastTickCount;
|
||||
unsigned mspf; /* ms per frame */
|
||||
|
||||
FPSLimiter(unsigned desiredFPS)
|
||||
: lastTickCount(SDL_GetTicks())
|
||||
{
|
||||
setDesiredFPS(desiredFPS);
|
||||
}
|
||||
|
||||
void setDesiredFPS(unsigned value)
|
||||
{
|
||||
mspf = 1000 / value;
|
||||
}
|
||||
|
||||
void delay()
|
||||
{
|
||||
unsigned tmpTicks = SDL_GetTicks();
|
||||
unsigned tickDelta = tmpTicks - lastTickCount;
|
||||
lastTickCount = tmpTicks;
|
||||
|
||||
int toDelay = mspf - tickDelta;
|
||||
if (toDelay < 0)
|
||||
toDelay = 0;
|
||||
|
||||
SDL_Delay(toDelay);
|
||||
lastTickCount = SDL_GetTicks();
|
||||
}
|
||||
};
|
||||
|
||||
struct Timer
|
||||
{
|
||||
uint64_t lastTicks;
|
||||
uint64_t acc;
|
||||
int counter;
|
||||
|
||||
Timer()
|
||||
: lastTicks(SDL_GetPerformanceCounter()),
|
||||
acc(0),
|
||||
counter(0)
|
||||
{}
|
||||
};
|
||||
|
||||
struct GraphicsPrivate
|
||||
{
|
||||
/* Screen resolution */
|
||||
Vec2i scRes;
|
||||
/* Actual screen size */
|
||||
Vec2i scSize;
|
||||
|
||||
ScreenScene screen;
|
||||
RGSSThreadData *threadData;
|
||||
|
||||
int frameRate;
|
||||
int frameCount;
|
||||
int brightness;
|
||||
|
||||
FPSLimiter fpsLimiter;
|
||||
|
||||
GPUTimer gpuTimer;
|
||||
CPUTimer cpuTimer;
|
||||
|
||||
bool frozen;
|
||||
TexFBO frozenScene;
|
||||
TexFBO currentScene;
|
||||
Quad screenQuad;
|
||||
RBFBO transBuffer;
|
||||
|
||||
GraphicsPrivate()
|
||||
: scRes(640, 480),
|
||||
scSize(scRes),
|
||||
screen(scRes.x, scRes.y),
|
||||
frameRate(40),
|
||||
frameCount(0),
|
||||
brightness(255),
|
||||
fpsLimiter(frameRate),
|
||||
gpuTimer(frameRate),
|
||||
cpuTimer(frameRate),
|
||||
frozen(false)
|
||||
{
|
||||
TexFBO::init(frozenScene);
|
||||
TexFBO::allocEmpty(frozenScene, scRes.x, scRes.y);
|
||||
TexFBO::linkFBO(frozenScene);
|
||||
|
||||
TexFBO::init(currentScene);
|
||||
TexFBO::allocEmpty(currentScene, scRes.x, scRes.y);
|
||||
TexFBO::linkFBO(currentScene);
|
||||
|
||||
FloatRect screenRect(0, 0, scRes.x, scRes.y);
|
||||
screenQuad.setTexPosRect(screenRect, screenRect);
|
||||
|
||||
RBFBO::init(transBuffer);
|
||||
RBFBO::allocEmpty(transBuffer, scRes.x, scRes.y);
|
||||
RBFBO::linkFBO(transBuffer);
|
||||
}
|
||||
|
||||
~GraphicsPrivate()
|
||||
{
|
||||
TexFBO::fini(frozenScene);
|
||||
TexFBO::fini(currentScene);
|
||||
|
||||
RBFBO::fini(transBuffer);
|
||||
}
|
||||
|
||||
void updateScreenResoRatio()
|
||||
{
|
||||
Vec2 &ratio = gState->rtData().sizeResoRatio;
|
||||
ratio.x = (float) scRes.x / scSize.x;
|
||||
ratio.y = (float) scRes.y / scSize.y;
|
||||
}
|
||||
|
||||
void checkResize()
|
||||
{
|
||||
if (threadData->windowSizeMsg.pollChange(&scSize.x, &scSize.y))
|
||||
{
|
||||
screen.setScreenSize(scSize.x, scSize.y);
|
||||
updateScreenResoRatio();
|
||||
}
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
threadData->rqTermAck = true;
|
||||
gState->texPool().disable();
|
||||
|
||||
scriptBinding->terminate();
|
||||
}
|
||||
|
||||
void swapGLBuffer()
|
||||
{
|
||||
SDL_GL_SwapWindow(threadData->window);
|
||||
fpsLimiter.delay();
|
||||
|
||||
++frameCount;
|
||||
}
|
||||
|
||||
void compositeToBuffer(FBO::ID fbo)
|
||||
{
|
||||
screen.composite();
|
||||
FBO::bind(fbo, FBO::Draw);
|
||||
FBO::blit(0, 0, 0, 0, scRes.x, scRes.y);
|
||||
}
|
||||
|
||||
void blitBuffer()
|
||||
{
|
||||
FBO::blit(0, 0, 0, 0, scRes.x, scRes.y);
|
||||
}
|
||||
|
||||
void blitBufferScaled()
|
||||
{
|
||||
FBO::blit(0, 0, scRes.x, scRes.y, 0, 0, scSize.x, scSize.y);
|
||||
}
|
||||
|
||||
void blitBufferFlippedScaled()
|
||||
{
|
||||
FBO::blit(0, 0, scRes.x, scRes.y, 0, scSize.y, scSize.x, -scSize.y);
|
||||
}
|
||||
|
||||
/* Blits currently bound read FBO to screen (upside-down) */
|
||||
void blitToScreen()
|
||||
{
|
||||
FBO::unbind(FBO::Draw);
|
||||
blitBufferFlippedScaled();
|
||||
}
|
||||
|
||||
void redrawScreen()
|
||||
{
|
||||
screen.composite();
|
||||
blitToScreen();
|
||||
|
||||
swapGLBuffer();
|
||||
}
|
||||
};
|
||||
|
||||
Graphics::Graphics(RGSSThreadData *data)
|
||||
{
|
||||
p = new GraphicsPrivate;
|
||||
p->threadData = data;
|
||||
}
|
||||
|
||||
Graphics::~Graphics()
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
void Graphics::update()
|
||||
{
|
||||
gState->checkShutdown();
|
||||
|
||||
// p->cpuTimer.endTiming();
|
||||
// p->gpuTimer.startTiming();
|
||||
|
||||
if (p->frozen)
|
||||
return;
|
||||
|
||||
p->checkResize();
|
||||
p->redrawScreen();
|
||||
|
||||
// p->gpuTimer.endTiming();
|
||||
// p->cpuTimer.startTiming();
|
||||
}
|
||||
|
||||
void Graphics::wait(int duration)
|
||||
{
|
||||
for (int i = 0; i < duration; ++i)
|
||||
{
|
||||
gState->checkShutdown();
|
||||
p->checkResize();
|
||||
p->redrawScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::fadeout(int duration)
|
||||
{
|
||||
if (p->frozen)
|
||||
FBO::bind(p->frozenScene.fbo, FBO::Read);
|
||||
|
||||
for (int i = duration-1; i > -1; --i)
|
||||
{
|
||||
setBrightness((255.0 / duration) * i);
|
||||
|
||||
if (p->frozen)
|
||||
{
|
||||
p->blitToScreen();
|
||||
p->swapGLBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::fadein(int duration)
|
||||
{
|
||||
if (p->frozen)
|
||||
FBO::bind(p->frozenScene.fbo, FBO::Read);
|
||||
|
||||
for (int i = 0; i < duration; ++i)
|
||||
{
|
||||
setBrightness((255.0 / duration) * i);
|
||||
|
||||
if (p->frozen)
|
||||
{
|
||||
p->blitToScreen();
|
||||
p->swapGLBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::freeze()
|
||||
{
|
||||
p->frozen = true;
|
||||
|
||||
gState->checkShutdown();
|
||||
p->checkResize();
|
||||
|
||||
/* Capture scene into frozen buffer */
|
||||
p->compositeToBuffer(p->frozenScene.fbo);
|
||||
}
|
||||
|
||||
void Graphics::transition(int duration,
|
||||
const char *filename,
|
||||
int vague)
|
||||
{
|
||||
vague = bound(vague, 0, 512);
|
||||
Bitmap *transMap = filename ? new Bitmap(filename) : 0;
|
||||
|
||||
setBrightness(255);
|
||||
|
||||
/* Capture new scene */
|
||||
p->compositeToBuffer(p->currentScene.fbo);
|
||||
|
||||
if (transMap)
|
||||
{
|
||||
TransShader &shader = gState->transShader();
|
||||
shader.bind();
|
||||
shader.setFrozenScene(p->frozenScene.tex);
|
||||
shader.setCurrentScene(p->currentScene.tex);
|
||||
shader.setTransMap(transMap->getGLTypes().tex);
|
||||
shader.setVague(vague / 512.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleTransShader &shader = gState->sTransShader();
|
||||
shader.bind();
|
||||
shader.setFrozenScene(p->frozenScene.tex);
|
||||
shader.setCurrentScene(p->currentScene.tex);
|
||||
}
|
||||
|
||||
Tex::bindMatrix(p->scRes.x, p->scRes.y);
|
||||
|
||||
glState.blendMode.pushSet(BlendNone);
|
||||
|
||||
for (int i = 0; i < duration; ++i)
|
||||
{
|
||||
if (p->threadData->rqTerm)
|
||||
{
|
||||
FragShader::unbind();
|
||||
delete transMap;
|
||||
p->shutdown();
|
||||
}
|
||||
|
||||
const float prog = i * (1.0 / duration);
|
||||
|
||||
if (transMap)
|
||||
gState->transShader().setProg(prog);
|
||||
else
|
||||
gState->sTransShader().setProg(prog);
|
||||
|
||||
FBO::bind(p->transBuffer.fbo);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
p->screenQuad.draw();
|
||||
|
||||
p->checkResize();
|
||||
|
||||
FBO::bind(p->transBuffer.fbo, FBO::Read);
|
||||
p->blitToScreen();
|
||||
|
||||
p->swapGLBuffer();
|
||||
}
|
||||
|
||||
glState.blendMode.pop();
|
||||
|
||||
FragShader::unbind();
|
||||
|
||||
delete transMap;
|
||||
|
||||
p->frozen = false;
|
||||
}
|
||||
|
||||
Bitmap *Graphics::snapToBitmap()
|
||||
{
|
||||
Bitmap *bitmap = new Bitmap(width(), height());
|
||||
|
||||
p->compositeToBuffer(bitmap->getGLTypes().fbo);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void Graphics::frameReset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Graphics::width() const
|
||||
{
|
||||
return p->scRes.x;
|
||||
}
|
||||
|
||||
int Graphics::height() const
|
||||
{
|
||||
return p->scRes.y;
|
||||
}
|
||||
|
||||
void Graphics::resizeScreen(int width, int height)
|
||||
{
|
||||
width = bound(width, 1, 640);
|
||||
height = bound(height, 1, 480);
|
||||
|
||||
Vec2i size(width, height);
|
||||
|
||||
if (p->scRes == size)
|
||||
return;
|
||||
|
||||
gState->eThread().requestWindowResize(width, height);
|
||||
|
||||
p->scRes = size;
|
||||
|
||||
p->screen.setResolution(width, height);
|
||||
|
||||
Tex::bind(p->frozenScene.tex);
|
||||
Tex::allocEmpty(width, height);
|
||||
Tex::bind(p->currentScene.tex);
|
||||
Tex::allocEmpty(width, height);
|
||||
|
||||
FloatRect screenRect(0, 0, width, height);
|
||||
p->screenQuad.setTexPosRect(screenRect, screenRect);
|
||||
|
||||
RB::bind(p->transBuffer.rb);
|
||||
RB::allocEmpty(width, height);
|
||||
|
||||
p->updateScreenResoRatio();
|
||||
}
|
||||
|
||||
#undef RET_IF_DISP
|
||||
#define RET_IF_DISP(x)
|
||||
|
||||
#undef CHK_DISP
|
||||
#define CHK_DISP
|
||||
|
||||
DEF_ATTR_RD_SIMPLE(Graphics, FrameRate, int, p->frameRate)
|
||||
DEF_ATTR_RD_SIMPLE(Graphics, Brightness, int, p->brightness)
|
||||
|
||||
DEF_ATTR_SIMPLE(Graphics, FrameCount, int, p->frameCount)
|
||||
|
||||
void Graphics::setFrameRate(int value)
|
||||
{
|
||||
p->frameRate = bound(value, 10, 120);
|
||||
p->fpsLimiter.setDesiredFPS(p->frameRate);
|
||||
}
|
||||
|
||||
void Graphics::setBrightness(int value)
|
||||
{
|
||||
value = bound(value, 0, 255);
|
||||
|
||||
if (p->brightness == value)
|
||||
return;
|
||||
|
||||
p->brightness = value;
|
||||
p->screen.setBrightness(value / 255.0);
|
||||
}
|
||||
|
||||
bool Graphics::getFullscreen() const
|
||||
{
|
||||
return p->threadData->ethread->getFullscreen();
|
||||
}
|
||||
|
||||
void Graphics::setFullscreen(bool value)
|
||||
{
|
||||
p->threadData->ethread->requestFullscreenMode(value);
|
||||
}
|
||||
|
||||
Scene *Graphics::getScreen() const
|
||||
{
|
||||
return &p->screen;
|
||||
}
|
||||
|
||||
void Graphics::repaintWait(volatile bool *exitCond)
|
||||
{
|
||||
if (*exitCond)
|
||||
return;
|
||||
|
||||
/* Repaint the screen with the last good frame we drew */
|
||||
p->screen.getPP().bindLastBuffer();
|
||||
FBO::unbind(FBO::Draw);
|
||||
|
||||
while (!*exitCond)
|
||||
{
|
||||
gState->checkShutdown();
|
||||
|
||||
p->blitBufferFlippedScaled();
|
||||
SDL_GL_SwapWindow(p->threadData->window);
|
||||
p->fpsLimiter.delay();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
** graphics.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_H
|
||||
#define GRAPHICS_H
|
||||
|
||||
#include "util.h"
|
||||
|
||||
class Scene;
|
||||
class Bitmap;
|
||||
struct RGSSThreadData;
|
||||
struct GraphicsPrivate;
|
||||
|
||||
class Graphics
|
||||
{
|
||||
public:
|
||||
Graphics(RGSSThreadData *data);
|
||||
~Graphics();
|
||||
|
||||
void update();
|
||||
void freeze();
|
||||
void transition(int duration = 8,
|
||||
const char *filename = 0,
|
||||
int vague = 40);
|
||||
|
||||
void wait(int duration);
|
||||
void fadeout(int duration);
|
||||
void fadein(int duration);
|
||||
|
||||
Bitmap *snapToBitmap();
|
||||
|
||||
void frameReset();
|
||||
|
||||
int width() const;
|
||||
int height() const;
|
||||
void resizeScreen(int width, int height);
|
||||
|
||||
DECL_ATTR( FrameRate, int )
|
||||
DECL_ATTR( FrameCount, int )
|
||||
DECL_ATTR( Brightness, int )
|
||||
|
||||
/* Non-standard extension */
|
||||
DECL_ATTR( Fullscreen, bool )
|
||||
|
||||
/* <internal> */
|
||||
Scene *getScreen() const;
|
||||
/* Repaint screen with static image until exitCond
|
||||
* turns true. Used in EThread::showMessageBox() */
|
||||
void repaintWait(volatile bool *exitCond);
|
||||
|
||||
private:
|
||||
GraphicsPrivate *p;
|
||||
};
|
||||
|
||||
#endif // GRAPHICS_H
|
|
@ -0,0 +1,669 @@
|
|||
/*
|
||||
** input.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "input.h"
|
||||
#include "globalstate.h"
|
||||
#include "eventthread.h"
|
||||
#include "exception.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "SDL2/SDL_scancode.h"
|
||||
#include "SDL2/SDL_mouse.h"
|
||||
|
||||
#include <QVector>
|
||||
#include "string.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
const int Input::buttonCodeSize = 24;
|
||||
|
||||
struct ButtonState
|
||||
{
|
||||
bool pressed;
|
||||
bool triggered;
|
||||
bool repeated;
|
||||
|
||||
ButtonState()
|
||||
: pressed(false),
|
||||
triggered(false),
|
||||
repeated(false)
|
||||
{}
|
||||
};
|
||||
|
||||
struct KbBindingData
|
||||
{
|
||||
SDL_Scancode source;
|
||||
Input::ButtonCode target;
|
||||
};
|
||||
|
||||
struct JsBindingData
|
||||
{
|
||||
unsigned int source;
|
||||
Input::ButtonCode target;
|
||||
};
|
||||
|
||||
struct Binding
|
||||
{
|
||||
Binding(Input::ButtonCode target = Input::None)
|
||||
: target(target)
|
||||
{}
|
||||
|
||||
virtual bool sourceActive() const = 0;
|
||||
virtual bool sourceRepeatable() const = 0;
|
||||
|
||||
Input::ButtonCode target;
|
||||
};
|
||||
|
||||
/* Keyboard binding */
|
||||
struct KbBinding : public Binding
|
||||
{
|
||||
KbBinding() {}
|
||||
|
||||
KbBinding(const KbBindingData &data)
|
||||
: Binding(data.target),
|
||||
source(data.source)
|
||||
{}
|
||||
|
||||
bool sourceActive() const
|
||||
{
|
||||
return EventThread::keyStates[source];
|
||||
}
|
||||
|
||||
bool sourceRepeatable() const
|
||||
{
|
||||
// return (source >= sf::Keyboard::A && source <= sf::Keyboard::Num9) ||
|
||||
// (source >= sf::Keyboard::Left && source <= sf::Keyboard::F15);
|
||||
return (source >= SDL_SCANCODE_A && source <= SDL_SCANCODE_0) ||
|
||||
(source >= SDL_SCANCODE_RIGHT && source <= SDL_SCANCODE_UP) ||
|
||||
(source >= SDL_SCANCODE_F1 && source <= SDL_SCANCODE_F12);
|
||||
}
|
||||
|
||||
SDL_Scancode source;
|
||||
};
|
||||
|
||||
/* Joystick button binding */
|
||||
struct JsButtonBinding : public Binding
|
||||
{
|
||||
JsButtonBinding() {}
|
||||
|
||||
JsButtonBinding(const JsBindingData &data)
|
||||
: Binding(data.target),
|
||||
source(data.source)
|
||||
{}
|
||||
|
||||
bool sourceActive() const
|
||||
{
|
||||
return EventThread::joyState.buttons[source];
|
||||
}
|
||||
|
||||
bool sourceRepeatable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int source;
|
||||
};
|
||||
|
||||
/* Joystick axis binding */
|
||||
struct JsAxisBinding : public Binding
|
||||
{
|
||||
JsAxisBinding() {}
|
||||
|
||||
JsAxisBinding(int *source,
|
||||
int compareValue,
|
||||
Input::ButtonCode target)
|
||||
: Binding(target),
|
||||
source(source),
|
||||
compareValue(compareValue)
|
||||
{}
|
||||
|
||||
bool sourceActive() const
|
||||
{
|
||||
return (*source == compareValue);
|
||||
}
|
||||
|
||||
bool sourceRepeatable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int *source;
|
||||
int compareValue;
|
||||
};
|
||||
|
||||
/* Mouse button binding */
|
||||
struct MsBinding : public Binding
|
||||
{
|
||||
MsBinding() {}
|
||||
|
||||
MsBinding(int buttonIndex,
|
||||
Input::ButtonCode target)
|
||||
: Binding(target),
|
||||
index(buttonIndex)
|
||||
{}
|
||||
|
||||
bool sourceActive() const
|
||||
{
|
||||
return EventThread::mouseState.buttons[index];
|
||||
}
|
||||
|
||||
bool sourceRepeatable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int index;
|
||||
};
|
||||
|
||||
/* Not rebindable */
|
||||
//static const KbBindingData staticKbBindings[] =
|
||||
//{
|
||||
// { sf::Keyboard::Left, Input::Left },
|
||||
// { sf::Keyboard::Right, Input::Right },
|
||||
// { sf::Keyboard::Up, Input::Up },
|
||||
// { sf::Keyboard::Down, Input::Down },
|
||||
// { sf::Keyboard::LShift, Input::Shift },
|
||||
// { sf::Keyboard::RShift, Input::Shift },
|
||||
// { sf::Keyboard::LControl, Input::Ctrl },
|
||||
// { sf::Keyboard::RControl, Input::Ctrl },
|
||||
// { sf::Keyboard::LAlt, Input::Alt },
|
||||
// { sf::Keyboard::RAlt, Input::Alt },
|
||||
// { sf::Keyboard::F5, Input::F5 },
|
||||
// { sf::Keyboard::F6, Input::F6 },
|
||||
// { sf::Keyboard::F7, Input::F7 },
|
||||
// { sf::Keyboard::F8, Input::F8 },
|
||||
// { sf::Keyboard::F9, Input::F9 }
|
||||
//};
|
||||
static const KbBindingData staticKbBindings[] =
|
||||
{
|
||||
{ SDL_SCANCODE_LEFT, Input::Left },
|
||||
{ SDL_SCANCODE_RIGHT, Input::Right },
|
||||
{ SDL_SCANCODE_UP, Input::Up },
|
||||
{ SDL_SCANCODE_DOWN, Input::Down },
|
||||
{ SDL_SCANCODE_LSHIFT, Input::Shift },
|
||||
{ SDL_SCANCODE_RSHIFT, Input::Shift },
|
||||
{ SDL_SCANCODE_LCTRL, Input::Ctrl },
|
||||
{ SDL_SCANCODE_RCTRL, Input::Ctrl },
|
||||
{ SDL_SCANCODE_LALT, Input::Alt },
|
||||
{ SDL_SCANCODE_RALT, Input::Alt },
|
||||
{ SDL_SCANCODE_F5, Input::F5 },
|
||||
{ SDL_SCANCODE_F6, Input::F6 },
|
||||
{ SDL_SCANCODE_F7, Input::F7 },
|
||||
{ SDL_SCANCODE_F8, Input::F8 },
|
||||
{ SDL_SCANCODE_F9, Input::F9 }
|
||||
};
|
||||
|
||||
static elementsN(staticKbBindings);
|
||||
|
||||
/* Rebindable */
|
||||
//static const KbBindingData defaultKbBindings[] =
|
||||
//{
|
||||
// { sf::Keyboard::Space, Input::C },
|
||||
// { sf::Keyboard::Return, Input::C },
|
||||
// { sf::Keyboard::Escape, Input::B },
|
||||
// { sf::Keyboard::Num0, Input::B },
|
||||
// { sf::Keyboard::LShift, Input::A },
|
||||
// { sf::Keyboard::RShift, Input::A },
|
||||
// { sf::Keyboard::Z, Input::A },
|
||||
// { sf::Keyboard::X, Input::B },
|
||||
// { sf::Keyboard::C, Input::C },
|
||||
// { sf::Keyboard::V, Input::None },
|
||||
// { sf::Keyboard::B, Input::None },
|
||||
// { sf::Keyboard::A, Input::X },
|
||||
// { sf::Keyboard::S, Input::Y },
|
||||
// { sf::Keyboard::D, Input::Z },
|
||||
// { sf::Keyboard::Q, Input::L },
|
||||
// { sf::Keyboard::W, Input::R }
|
||||
//};
|
||||
static const KbBindingData defaultKbBindings[] =
|
||||
{
|
||||
{ SDL_SCANCODE_SPACE, Input::C },
|
||||
{ SDL_SCANCODE_RETURN, Input::C },
|
||||
{ SDL_SCANCODE_ESCAPE, Input::B },
|
||||
{ SDL_SCANCODE_KP_0, Input::B },
|
||||
{ SDL_SCANCODE_LSHIFT, Input::A },
|
||||
{ SDL_SCANCODE_RSHIFT, Input::A },
|
||||
{ SDL_SCANCODE_Z, Input::A },
|
||||
{ SDL_SCANCODE_X, Input::B },
|
||||
{ SDL_SCANCODE_C, Input::C },
|
||||
{ SDL_SCANCODE_V, Input::None },
|
||||
{ SDL_SCANCODE_B, Input::None },
|
||||
{ SDL_SCANCODE_S, Input::X },
|
||||
{ SDL_SCANCODE_A, Input::Y },
|
||||
{ SDL_SCANCODE_D, Input::Z },
|
||||
{ SDL_SCANCODE_Q, Input::L },
|
||||
{ SDL_SCANCODE_W, Input::R }
|
||||
};
|
||||
|
||||
static elementsN(defaultKbBindings);
|
||||
|
||||
/* Rebindable */
|
||||
static const JsBindingData defaultJsBindings[] =
|
||||
{
|
||||
{ 0, Input::A },
|
||||
{ 1, Input::B },
|
||||
{ 2, Input::C },
|
||||
{ 3, Input::X },
|
||||
{ 4, Input::Y },
|
||||
{ 5, Input::Z },
|
||||
{ 6, Input::L },
|
||||
{ 7, Input::R },
|
||||
{ 8, Input::None },
|
||||
{ 9, Input::None }
|
||||
};
|
||||
|
||||
static elementsN(defaultJsBindings);
|
||||
|
||||
static const int mapToIndex[] =
|
||||
{
|
||||
0, 0,
|
||||
1, 0, 2, 0, 3, 0, 4, 0,
|
||||
0,
|
||||
5, 6, 7, 8, 9, 10, 11, 12,
|
||||
0, 0,
|
||||
13, 14, 15,
|
||||
0,
|
||||
16, 17, 18, 19, 20,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
21, 22, 23
|
||||
};
|
||||
|
||||
static elementsN(mapToIndex);
|
||||
|
||||
static const Input::ButtonCode dirs[] =
|
||||
{ Input::Down, Input::Left, Input::Right, Input::Up };
|
||||
|
||||
static const int dirFlags[] =
|
||||
{
|
||||
1 << Input::Down,
|
||||
1 << Input::Left,
|
||||
1 << Input::Right,
|
||||
1 << Input::Up
|
||||
};
|
||||
|
||||
/* Dir4 is always zero on these combinations */
|
||||
static const int deadDirFlags[] =
|
||||
{
|
||||
dirFlags[0] | dirFlags[3],
|
||||
dirFlags[1] | dirFlags[2]
|
||||
};
|
||||
|
||||
static const Input::ButtonCode otherDirs[4][3] =
|
||||
{
|
||||
{ Input::Left, Input::Right, Input::Up }, // Down
|
||||
{ Input::Down, Input::Up, Input::Right }, // Left
|
||||
{ Input::Down, Input::Up, Input::Left }, // Right
|
||||
{ Input::Left, Input::Right, Input::Up } // Up
|
||||
};
|
||||
|
||||
struct InputPrivate
|
||||
{
|
||||
QVector<KbBinding> kbBindings;
|
||||
QVector<JsAxisBinding> jsABindings;
|
||||
QVector<JsButtonBinding> jsBBindings;
|
||||
QVector<MsBinding> msBindings;
|
||||
|
||||
/* Collective binding array */
|
||||
QVector<Binding*> bindings;
|
||||
|
||||
ButtonState *states;
|
||||
ButtonState *statesOld;
|
||||
|
||||
Input::ButtonCode repeating;
|
||||
unsigned int repeatCount;
|
||||
|
||||
struct
|
||||
{
|
||||
int active;
|
||||
Input::ButtonCode previous;
|
||||
} dir4Data;
|
||||
|
||||
struct
|
||||
{
|
||||
int active;
|
||||
} dir8Data;
|
||||
|
||||
|
||||
InputPrivate()
|
||||
{
|
||||
initKbBindings();
|
||||
initJsBindings();
|
||||
initMsBindings();
|
||||
|
||||
states = new ButtonState[Input::buttonCodeSize];
|
||||
statesOld = new ButtonState[Input::buttonCodeSize];
|
||||
|
||||
// Clear buffers
|
||||
clearBuffer();
|
||||
swapBuffers();
|
||||
clearBuffer();
|
||||
|
||||
repeating = Input::None;
|
||||
repeatCount = 0;
|
||||
|
||||
dir4Data.active = 0;
|
||||
dir4Data.previous = Input::None;
|
||||
|
||||
dir8Data.active = 0;
|
||||
}
|
||||
|
||||
~InputPrivate()
|
||||
{
|
||||
delete states;
|
||||
delete statesOld;
|
||||
}
|
||||
|
||||
inline ButtonState &getStateCheck(int code)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (code < 0 || code > mapToIndexN-1)
|
||||
index = 0;
|
||||
else
|
||||
index = mapToIndex[code];
|
||||
|
||||
return states[index];
|
||||
}
|
||||
|
||||
inline ButtonState &getState(Input::ButtonCode code)
|
||||
{
|
||||
return states[mapToIndex[code]];
|
||||
}
|
||||
|
||||
inline ButtonState &getOldState(Input::ButtonCode code)
|
||||
{
|
||||
return statesOld[mapToIndex[code]];
|
||||
}
|
||||
|
||||
void swapBuffers()
|
||||
{
|
||||
ButtonState *tmp = states;
|
||||
states = statesOld;
|
||||
statesOld = tmp;
|
||||
}
|
||||
|
||||
void clearBuffer()
|
||||
{
|
||||
static int size = sizeof(ButtonState) * Input::buttonCodeSize;
|
||||
memset(states, 0, size);
|
||||
}
|
||||
|
||||
void initKbBindings()
|
||||
{
|
||||
kbBindings.resize(staticKbBindingsN+defaultKbBindingsN);
|
||||
|
||||
int n = 0;
|
||||
for (int i = 0; i < staticKbBindingsN; ++i)
|
||||
kbBindings[n++] = KbBinding(staticKbBindings[i]);
|
||||
|
||||
for (int i = 0; i < defaultKbBindingsN; ++i)
|
||||
kbBindings[n++] = KbBinding(defaultKbBindings[i]);
|
||||
|
||||
/* Add to binging array */
|
||||
for (int i = 0; i < kbBindings.count(); ++i)
|
||||
bindings.append(&kbBindings[i]);
|
||||
}
|
||||
|
||||
void initJsBindings()
|
||||
{
|
||||
/* Create axis bindings */
|
||||
jsABindings.resize(4);
|
||||
|
||||
int i = 0;
|
||||
jsABindings[i++] = JsAxisBinding(&EventThread::joyState.xAxis, 0x7FFF, Input::Right);
|
||||
jsABindings[i++] = JsAxisBinding(&EventThread::joyState.xAxis, -0x8000, Input::Left);
|
||||
jsABindings[i++] = JsAxisBinding(&EventThread::joyState.yAxis, 0x7FFF, Input::Down);
|
||||
jsABindings[i++] = JsAxisBinding(&EventThread::joyState.yAxis, -0x8000, Input::Up);
|
||||
|
||||
/* Create button bindings */
|
||||
jsBBindings.resize(defaultJsBindingsN);
|
||||
|
||||
for (int i = 0; i < defaultJsBindingsN; ++i)
|
||||
jsBBindings[i] = JsButtonBinding(defaultJsBindings[i]);
|
||||
|
||||
/* Add to binging array */
|
||||
for (int i = 0; i < jsABindings.count(); ++i)
|
||||
bindings.append(&jsABindings[i]);
|
||||
|
||||
for (int i = 0; i < jsBBindings.count(); ++i)
|
||||
bindings.append(&jsBBindings[i]);
|
||||
}
|
||||
|
||||
void initMsBindings()
|
||||
{
|
||||
msBindings.resize(3);
|
||||
|
||||
int i = 0;
|
||||
msBindings[i++] = MsBinding(SDL_BUTTON_LEFT, Input::MouseLeft);
|
||||
msBindings[i++] = MsBinding(SDL_BUTTON_MIDDLE, Input::MouseMiddle);
|
||||
msBindings[i++] = MsBinding(SDL_BUTTON_RIGHT, Input::MouseRight);
|
||||
|
||||
/* Add to binding array */
|
||||
for (int i = 0; i < msBindings.count(); ++i)
|
||||
bindings.append(&msBindings[i]);
|
||||
}
|
||||
|
||||
void pollBindings(Input::ButtonCode &repeatCand)
|
||||
{
|
||||
Q_FOREACH (const Binding *b, bindings)
|
||||
pollBindingPriv(*b, repeatCand);
|
||||
|
||||
updateDir4();
|
||||
updateDir8();
|
||||
}
|
||||
|
||||
void pollBindingPriv(const Binding &b,
|
||||
Input::ButtonCode &repeatCand)
|
||||
{
|
||||
if (!b.sourceActive())
|
||||
return;
|
||||
|
||||
if (b.target == Input::None)
|
||||
return;
|
||||
|
||||
ButtonState &state = getState(b.target);
|
||||
ButtonState &oldState = getOldState(b.target);
|
||||
|
||||
state.pressed = true;
|
||||
|
||||
/* Must have been released before to trigger */
|
||||
if (!oldState.pressed)
|
||||
state.triggered = true;
|
||||
|
||||
/* Unbound keys don't create/break repeat */
|
||||
if (repeatCand != Input::None)
|
||||
return;
|
||||
|
||||
if (repeating != b.target &&
|
||||
!oldState.pressed)
|
||||
{
|
||||
if (b.sourceRepeatable())
|
||||
repeatCand = b.target;
|
||||
else
|
||||
/* Unrepeatable keys still break current repeat */
|
||||
repeating = Input::None;
|
||||
}
|
||||
}
|
||||
|
||||
void updateDir4()
|
||||
{
|
||||
int dirFlag = 0;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
dirFlag |= (getState(dirs[i]).pressed ? dirFlags[i] : 0);
|
||||
|
||||
if (dirFlag == deadDirFlags[0] || dirFlag == deadDirFlags[1])
|
||||
{
|
||||
dir4Data.active = Input::None;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dir4Data.previous != Input::None)
|
||||
{
|
||||
/* Check if prev still pressed */
|
||||
if (getState(dir4Data.previous).pressed)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
Input::ButtonCode other =
|
||||
otherDirs[(dir4Data.previous/2)-1][i];
|
||||
|
||||
if (!getState(other).pressed)
|
||||
continue;
|
||||
|
||||
dir4Data.active = other;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (!getState(dirs[i]).pressed)
|
||||
continue;
|
||||
|
||||
dir4Data.active = dirs[i];
|
||||
dir4Data.previous = dirs[i];
|
||||
return;
|
||||
}
|
||||
|
||||
dir4Data.active = Input::None;
|
||||
dir4Data.previous = Input::None;
|
||||
}
|
||||
|
||||
void updateDir8()
|
||||
{
|
||||
static const int combos[4][4] =
|
||||
{
|
||||
{ 2, 1, 3, 0 },
|
||||
{ 1, 4, 0, 7 },
|
||||
{ 3, 0, 6, 9 },
|
||||
{ 0, 7, 9, 8 }
|
||||
};
|
||||
|
||||
dir8Data.active = 0;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
Input::ButtonCode one = dirs[i];
|
||||
|
||||
if (!getState(one).pressed)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
Input::ButtonCode other = otherDirs[i][j];
|
||||
|
||||
if (!getState(other).pressed)
|
||||
continue;
|
||||
|
||||
dir8Data.active = combos[(one/2)-1][(other/2)-1];
|
||||
return;
|
||||
}
|
||||
|
||||
dir8Data.active = one;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Input::Input()
|
||||
{
|
||||
p = new InputPrivate;
|
||||
}
|
||||
|
||||
void Input::update()
|
||||
{
|
||||
gState->checkShutdown();
|
||||
|
||||
p->swapBuffers();
|
||||
p->clearBuffer();
|
||||
|
||||
ButtonCode repeatCand = None;
|
||||
|
||||
/* Poll all bindings */
|
||||
p->pollBindings(repeatCand);
|
||||
|
||||
/* Check for new repeating key */
|
||||
if (repeatCand != None && repeatCand != p->repeating)
|
||||
{
|
||||
p->repeating = repeatCand;
|
||||
p->repeatCount = 0;
|
||||
p->getState(repeatCand).repeated = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if repeating key is still pressed */
|
||||
if (p->getState(p->repeating).pressed)
|
||||
{
|
||||
p->repeatCount++;
|
||||
|
||||
/* Repeatsequence is [r...............(r...)+] */
|
||||
if (p->repeatCount > 15 && ((p->repeatCount % 4) == 0))
|
||||
p->getState(p->repeating).repeated = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
p->repeating = None;
|
||||
}
|
||||
|
||||
bool Input::isPressed(int button)
|
||||
{
|
||||
return p->getStateCheck(button).pressed;
|
||||
}
|
||||
|
||||
bool Input::isTriggered(int button)
|
||||
{
|
||||
return p->getStateCheck(button).triggered;
|
||||
}
|
||||
|
||||
bool Input::isRepeated(int button)
|
||||
{
|
||||
return p->getStateCheck(button).repeated;
|
||||
}
|
||||
|
||||
int Input::dir4Value()
|
||||
{
|
||||
return p->dir4Data.active;
|
||||
}
|
||||
|
||||
int Input::dir8Value()
|
||||
{
|
||||
return p->dir8Data.active;
|
||||
}
|
||||
|
||||
int Input::mouseX()
|
||||
{
|
||||
return EventThread::mouseState.x * gState->rtData().sizeResoRatio.x;
|
||||
}
|
||||
|
||||
int Input::mouseY()
|
||||
{
|
||||
return EventThread::mouseState.y * gState->rtData().sizeResoRatio.y;
|
||||
}
|
||||
|
||||
Input::~Input()
|
||||
{
|
||||
delete p;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
** input.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
struct InputPrivate;
|
||||
|
||||
class Input
|
||||
{
|
||||
public:
|
||||
enum ButtonCode
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Down = 2, Left = 4, Right = 6, Up = 8,
|
||||
|
||||
A = 11, B = 12, C = 13,
|
||||
X = 14, Y = 15, Z = 16,
|
||||
L = 17, R = 18,
|
||||
|
||||
Shift = 21, Ctrl = 22, Alt = 23,
|
||||
|
||||
F5 = 25, F6 = 26, F7 = 27, F8 = 28, F9 = 29,
|
||||
|
||||
/* Non-standard extensions */
|
||||
MouseLeft = 38, MouseMiddle = 39, MouseRight = 40
|
||||
};
|
||||
|
||||
static const int buttonCodeSize;
|
||||
|
||||
Input();
|
||||
~Input();
|
||||
|
||||
void update();
|
||||
|
||||
bool isPressed(int button);
|
||||
bool isTriggered(int button);
|
||||
bool isRepeated(int button);
|
||||
|
||||
int dir4Value();
|
||||
int dir8Value();
|
||||
|
||||
/* Non-standard extensions */
|
||||
int mouseX();
|
||||
int mouseY();
|
||||
|
||||
private:
|
||||
InputPrivate *p;
|
||||
};
|
||||
|
||||
#endif // INPUT_H
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
** intrulist.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INTRULIST_H
|
||||
#define INTRULIST_H
|
||||
|
||||
template <typename T>
|
||||
struct IntruListLink
|
||||
{
|
||||
IntruListLink<T> *prev;
|
||||
IntruListLink<T> *next;
|
||||
T *data;
|
||||
|
||||
IntruListLink(T *data)
|
||||
: prev(0),
|
||||
next(0),
|
||||
data(data)
|
||||
{}
|
||||
|
||||
~IntruListLink()
|
||||
{
|
||||
if (prev && next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class IntruList
|
||||
{
|
||||
IntruListLink<T> root;
|
||||
int size;
|
||||
|
||||
public:
|
||||
IntruList()
|
||||
: root(0),
|
||||
size(0)
|
||||
{
|
||||
root.prev = &root;
|
||||
root.next = &root;
|
||||
}
|
||||
|
||||
void prepend(IntruListLink<T> &node)
|
||||
{
|
||||
root.next->prev = &node;
|
||||
node.prev = &root;
|
||||
node.next = root.next;
|
||||
root.next = &node;
|
||||
|
||||
size++;
|
||||
}
|
||||
|
||||
void append(IntruListLink<T> &node)
|
||||
{
|
||||
root.prev->next = &node;
|
||||
node.next = &root;
|
||||
node.prev = root.prev;
|
||||
root.prev = &node;
|
||||
|
||||
size++;
|
||||
}
|
||||
|
||||
void insertBefore(IntruListLink<T> &node,
|
||||
IntruListLink<T> &prev)
|
||||
{
|
||||
node.next = &prev;
|
||||
node.prev = prev.prev;
|
||||
prev.prev->next = &node;
|
||||
prev.prev = &node;
|
||||
|
||||
size++;
|
||||
}
|
||||
|
||||
void remove(IntruListLink<T> &node)
|
||||
{
|
||||
if (!node.next)
|
||||
return;
|
||||
|
||||
node.prev->next = node.next;
|
||||
node.next->prev = node.prev;
|
||||
|
||||
node.prev = 0;
|
||||
node.next = 0;
|
||||
|
||||
size--;
|
||||
}
|
||||
|
||||
T *tail() const
|
||||
{
|
||||
IntruListLink<T> *node = root.prev;
|
||||
if (node == &root)
|
||||
return 0;
|
||||
|
||||
return node->data;
|
||||
}
|
||||
|
||||
IntruListLink<T> *begin()
|
||||
{
|
||||
return root.next;
|
||||
}
|
||||
|
||||
IntruListLink<T> *end()
|
||||
{
|
||||
return &root;
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return root.next == &root;
|
||||
}
|
||||
|
||||
int getSize() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // INTRULIST_H
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
** main.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "GL/glew.h"
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
#include "SDL2/SDL_image.h"
|
||||
#include "SDL2/SDL_ttf.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "eventthread.h"
|
||||
#include "debuglogger.h"
|
||||
|
||||
#include "binding.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
static const char *reqExt[] =
|
||||
{
|
||||
"GL_ARB_fragment_program",
|
||||
"GL_ARB_fragment_shader",
|
||||
"GL_ARB_framebuffer_object",
|
||||
"GL_ARB_imaging",
|
||||
"GL_ARB_shader_objects",
|
||||
"GL_ARB_shading_language_100",
|
||||
"GL_ARB_texture_non_power_of_two",
|
||||
"GL_ARB_vertex_array_object",
|
||||
"GL_ARB_vertex_buffer_object",
|
||||
"GL_EXT_bgra",
|
||||
"GL_EXT_blend_func_separate",
|
||||
"GL_EXT_blend_subtract",
|
||||
"GL_EXT_framebuffer_blit",
|
||||
0
|
||||
};
|
||||
|
||||
int rgssThreadFun(void *userdata)
|
||||
{
|
||||
RGSSThreadData *threadData = static_cast<RGSSThreadData*>(userdata);
|
||||
SDL_Window *win = threadData->window;
|
||||
SDL_GLContext ctx;
|
||||
|
||||
/* Setup GL context */
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
if (threadData->config.debugMode)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
|
||||
ctx = SDL_GL_CreateContext(win);
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
threadData->rgssErrorMsg =
|
||||
QByteArray("Error creating context: ") + SDL_GetError();
|
||||
threadData->ethread->requestTerminate();
|
||||
threadData->rqTermAck = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
threadData->rgssErrorMsg = "Error initializing glew";
|
||||
SDL_GL_DeleteContext(ctx);
|
||||
threadData->ethread->requestTerminate();
|
||||
threadData->rqTermAck = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for required GL extensions */
|
||||
const char **ext = reqExt;
|
||||
for (int i = 0; ext[i]; ++i)
|
||||
{
|
||||
if (!glewIsSupported(ext[i]))
|
||||
{
|
||||
threadData->rgssErrorMsg =
|
||||
QByteArray("Required GL extension \"") + ext[i] + "\" not present";
|
||||
threadData->ethread->requestTerminate();
|
||||
threadData->rqTermAck = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GL_SetSwapInterval(threadData->config.vsync ? 1 : 0);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
DebugLogger dLogger;
|
||||
|
||||
GlobalState::initInstance(threadData);
|
||||
|
||||
/* Start script execution */
|
||||
scriptBinding->execute();
|
||||
|
||||
threadData->ethread->requestTerminate();
|
||||
|
||||
GlobalState::finiInstance();
|
||||
|
||||
SDL_GL_DeleteContext(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int, char *argv[])
|
||||
{
|
||||
Config conf;
|
||||
|
||||
conf.read();
|
||||
conf.readGameINI();
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
|
||||
{
|
||||
qDebug() << "Error initializing SDL:" << SDL_GetError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
|
||||
TTF_Init();
|
||||
|
||||
SDL_SetHint("SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS", "0");
|
||||
|
||||
SDL_Window *win;
|
||||
Uint32 winFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
|
||||
|
||||
if (conf.winResizable)
|
||||
winFlags |= SDL_WINDOW_RESIZABLE;
|
||||
if (conf.fullscreen)
|
||||
winFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
|
||||
win = SDL_CreateWindow(conf.game.title.constData(),
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
conf.defScreenW, conf.defScreenH, winFlags);
|
||||
|
||||
if (!win)
|
||||
{
|
||||
qDebug() << "Error creating window";
|
||||
return 0;
|
||||
}
|
||||
|
||||
EventThread eventThread;
|
||||
RGSSThreadData rtData(&eventThread, argv[0], win);
|
||||
rtData.config = conf;
|
||||
|
||||
/* Start RGSS thread */
|
||||
SDL_Thread *rgssThread =
|
||||
SDL_CreateThread(rgssThreadFun, "rgss", &rtData);
|
||||
|
||||
/* Start event processing */
|
||||
eventThread.process(rtData);
|
||||
|
||||
/* Request RGSS thread to stop */
|
||||
rtData.rqTerm = true;
|
||||
|
||||
/* Wait for RGSS thread response */
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
{
|
||||
/* We can stop waiting when the request was ack'd */
|
||||
if (rtData.rqTermAck)
|
||||
{
|
||||
qDebug() << "RGSS thread ack'd request after" << i*10 << "ms";
|
||||
break;
|
||||
}
|
||||
|
||||
/* Give RGSS thread some time to respond */
|
||||
SDL_Delay(10);
|
||||
}
|
||||
|
||||
/* If RGSS thread ack'd request, wait for it to shutdown,
|
||||
* otherwise abandon hope and just end the process as is. */
|
||||
if (rtData.rqTermAck)
|
||||
SDL_WaitThread(rgssThread, 0);
|
||||
else
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.constData(),
|
||||
"The RGSS script seems to be stuck and mkxp will now force quit", win);
|
||||
|
||||
if (!rtData.rgssErrorMsg.isEmpty())
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, conf.game.title.constData(),
|
||||
rtData.rgssErrorMsg.constData(), win);
|
||||
|
||||
/* Clean up any remainin events */
|
||||
eventThread.cleanup();
|
||||
|
||||
qDebug() << "Shutting down.";
|
||||
|
||||
SDL_DestroyWindow(win);
|
||||
|
||||
TTF_Quit();
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
** plane.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "plane.h"
|
||||
|
||||
#include "globalstate.h"
|
||||
#include "bitmap.h"
|
||||
#include "etc.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "gl-util.h"
|
||||
#include "quad.h"
|
||||
#include "transform.h"
|
||||
#include "etc-internal.h"
|
||||
#include "shader.h"
|
||||
#include "glstate.h"
|
||||
|
||||
struct PlanePrivate
|
||||
{
|
||||
Bitmap *bitmap;
|
||||
NormValue opacity;
|
||||
BlendType blendType;
|
||||
Color *color;
|
||||
Tone *tone;
|
||||
|
||||
int ox, oy;
|
||||
float zoomX, zoomY;
|
||||
|
||||
Scene::Geometry sceneGeo;
|
||||
|
||||
bool quadSourceDirty;
|
||||
|
||||
Quad quad;
|
||||
|
||||
EtcTemps tmp;
|
||||
|
||||
PlanePrivate()
|
||||
: bitmap(0),
|
||||
opacity(255),
|
||||
blendType(BlendNormal),
|
||||
color(&tmp.color),
|
||||
tone(&tmp.tone),
|
||||
ox(0), oy(0),
|
||||
zoomX(1), zoomY(1),
|
||||
quadSourceDirty(false)
|
||||
{}
|
||||
|
||||
void updateQuadSource()
|
||||
{
|
||||
FloatRect srcRect;
|
||||
srcRect.x = (sceneGeo.yOrigin + ox) / zoomX;
|
||||
srcRect.y = (sceneGeo.xOrigin + oy) / zoomY;
|
||||
srcRect.w = sceneGeo.rect.w / zoomX;
|
||||
srcRect.h = sceneGeo.rect.h / zoomY;
|
||||
|
||||
quad.setTexRect(srcRect);
|
||||
}
|
||||
};
|
||||
|
||||
Plane::Plane(Viewport *viewport)
|
||||
: ViewportElement(viewport)
|
||||
{
|
||||
p = new PlanePrivate();
|
||||
|
||||
onGeometryChange(scene->getGeometry());
|
||||
}
|
||||
|
||||
#define DISP_CLASS_NAME "plane"
|
||||
|
||||
DEF_ATTR_RD_SIMPLE(Plane, OX, int, p->ox)
|
||||
DEF_ATTR_RD_SIMPLE(Plane, OY, int, p->oy)
|
||||
DEF_ATTR_RD_SIMPLE(Plane, ZoomX, float, p->zoomX)
|
||||
DEF_ATTR_RD_SIMPLE(Plane, ZoomY, float, p->zoomY)
|
||||
DEF_ATTR_RD_SIMPLE(Plane, BlendType, int, p->blendType)
|
||||
|
||||
DEF_ATTR_SIMPLE(Plane, Opacity, int, p->opacity)
|
||||
DEF_ATTR_SIMPLE(Plane, Bitmap, Bitmap*, p->bitmap)
|
||||
DEF_ATTR_SIMPLE(Plane, Color, Color*, p->color)
|
||||
DEF_ATTR_SIMPLE(Plane, Tone, Tone*, p->tone)
|
||||
|
||||
Plane::~Plane()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void Plane::setOX(int value)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
p->ox = value;
|
||||
p->quadSourceDirty = true;
|
||||
}
|
||||
|
||||
void Plane::setOY(int value)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
p->oy = value;
|
||||
p->quadSourceDirty = true;
|
||||
}
|
||||
|
||||
void Plane::setZoomX(float value)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
p->zoomX = value;
|
||||
p->quadSourceDirty = true;
|
||||
}
|
||||
|
||||
void Plane::setZoomY(float value)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
p->zoomY = value;
|
||||
p->quadSourceDirty = true;
|
||||
}
|
||||
|
||||
void Plane::setBlendType(int value)
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
|
||||
switch (value)
|
||||
{
|
||||
default :
|
||||
case BlendNormal :
|
||||
p->blendType = BlendNormal;
|
||||
return;
|
||||
case BlendAddition :
|
||||
p->blendType = BlendAddition;
|
||||
return;
|
||||
case BlendSubstraction :
|
||||
p->blendType = BlendSubstraction;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Plane::draw()
|
||||
{
|
||||
if (!p->bitmap)
|
||||
return;
|
||||
|
||||
if (p->bitmap->isDisposed())
|
||||
return;
|
||||
|
||||
if (!p->opacity)
|
||||
return;
|
||||
|
||||
if (p->quadSourceDirty)
|
||||
{
|
||||
p->updateQuadSource();
|
||||
p->quadSourceDirty = false;
|
||||
}
|
||||
|
||||
if (p->color->hasEffect() || p->tone->hasEffect() || p->opacity != 255)
|
||||
{
|
||||
SpriteShader &shader = gState->spriteShader();
|
||||
|
||||
shader.bind();
|
||||
shader.setTone(p->tone->norm);
|
||||
shader.setColor(p->color->norm);
|
||||
shader.setFlash(Vec4());
|
||||
shader.setOpacity(p->opacity.norm);
|
||||
shader.setBushOpacity(1);
|
||||
shader.setBushDepth(0);
|
||||
}
|
||||
|
||||
glState.blendMode.pushSet(p->blendType);
|
||||
|
||||
p->bitmap->flush();
|
||||
p->bitmap->bindTexWithMatrix();
|
||||
Tex::setRepeat(true);
|
||||
|
||||
p->quad.draw();
|
||||
|
||||
Tex::setRepeat(false);
|
||||
FragShader::unbind();
|
||||
}
|
||||
|
||||
void Plane::onGeometryChange(const Scene::Geometry &geo)
|
||||
{
|
||||
p->quad.setPosRect(FloatRect(geo.rect));
|
||||
|
||||
p->sceneGeo = geo;
|
||||
p->quadSourceDirty = true;
|
||||
}
|
||||
|
||||
void Plane::aboutToAccess() const
|
||||
{
|
||||
GUARD_DISPOSED
|
||||
}
|
||||
|
||||
|
||||
void Plane::releaseResources()
|
||||
{
|
||||
unlink();
|
||||
|
||||
delete p;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
** plane.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PLANE_H
|
||||
#define PLANE_H
|
||||
|
||||
#include "disposable.h"
|
||||
#include "viewport.h"
|
||||
|
||||
#include "SFML/Graphics/Sprite.hpp"
|
||||
#include "SFML/Graphics/RectangleShape.hpp"
|
||||
|
||||
class Bitmap;
|
||||
struct Color;
|
||||
struct Tone;
|
||||
|
||||
struct PlanePrivate;
|
||||
|
||||
class Plane : public ViewportElement, public Disposable
|
||||
{
|
||||
public:
|
||||
Plane(Viewport *viewport = 0);
|
||||
~Plane();
|
||||
|
||||
DECL_ATTR( Bitmap, Bitmap* )
|
||||
DECL_ATTR( OX, int )
|
||||
DECL_ATTR( OY, int )
|
||||
DECL_ATTR( ZoomX, float )
|
||||
DECL_ATTR( ZoomY, float )
|
||||
DECL_ATTR( Opacity, int )
|
||||
DECL_ATTR( BlendType, int )
|
||||
DECL_ATTR( Color, Color* )
|
||||
DECL_ATTR( Tone, Tone* )
|
||||
|
||||
private:
|
||||
PlanePrivate *p;
|
||||
|
||||
void draw();
|
||||
void onGeometryChange(const Scene::Geometry &);
|
||||
void aboutToAccess() const;
|
||||
|
||||
void releaseResources();
|
||||
};
|
||||
|
||||
#endif // PLANE_H
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
** quad.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QUAD_H
|
||||
#define QUAD_H
|
||||
|
||||
#include "GL/glew.h"
|
||||
#include "etc-internal.h"
|
||||
#include "gl-util.h"
|
||||
#include "globalstate.h"
|
||||
#include "global-ibo.h"
|
||||
|
||||
struct Quad
|
||||
{
|
||||
Vertex vert[4];
|
||||
VBO::ID vbo;
|
||||
VAO::ID vao;
|
||||
bool vboDirty;
|
||||
|
||||
static void setPosRect(CVertex *vert, const FloatRect &r)
|
||||
{
|
||||
int i = 0;
|
||||
vert[i++].pos = r.topLeft();
|
||||
vert[i++].pos = r.topRight();
|
||||
vert[i++].pos = r.bottomRight();
|
||||
vert[i++].pos = r.bottomLeft();
|
||||
}
|
||||
|
||||
static void setColor(CVertex *vert, const Vec4 &c)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
vert[i].color = c;
|
||||
}
|
||||
|
||||
static void setPosRect(SVertex *vert, const FloatRect &r)
|
||||
{
|
||||
int i = 0;
|
||||
vert[i++].pos = r.topLeft();
|
||||
vert[i++].pos = r.topRight();
|
||||
vert[i++].pos = r.bottomRight();
|
||||
vert[i++].pos = r.bottomLeft();
|
||||
}
|
||||
|
||||
static void setTexRect(SVertex *vert, const FloatRect &r)
|
||||
{
|
||||
int i = 0;
|
||||
vert[i++].texPos = r.topLeft();
|
||||
vert[i++].texPos = r.topRight();
|
||||
vert[i++].texPos = r.bottomRight();
|
||||
vert[i++].texPos = r.bottomLeft();
|
||||
}
|
||||
|
||||
static void setPosRect(Vertex *vert, const FloatRect &r)
|
||||
{
|
||||
int i = 0;
|
||||
vert[i++].pos = r.topLeft();
|
||||
vert[i++].pos = r.topRight();
|
||||
vert[i++].pos = r.bottomRight();
|
||||
vert[i++].pos = r.bottomLeft();
|
||||
}
|
||||
|
||||
static void setTexRect(Vertex *vert, const FloatRect &r)
|
||||
{
|
||||
int i = 0;
|
||||
vert[i++].texPos = r.topLeft();
|
||||
vert[i++].texPos = r.topRight();
|
||||
vert[i++].texPos = r.bottomRight();
|
||||
vert[i++].texPos = r.bottomLeft();
|
||||
}
|
||||
|
||||
static int setTexPosRect(SVertex *vert, const FloatRect &tex, const FloatRect &pos)
|
||||
{
|
||||
setPosRect(vert, pos);
|
||||
setTexRect(vert, tex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setTexPosRect(Vertex *vert, const FloatRect &tex, const FloatRect &pos)
|
||||
{
|
||||
setPosRect(vert, pos);
|
||||
setTexRect(vert, tex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Quad()
|
||||
: vbo(VBO::gen()),
|
||||
vao(VAO::gen()),
|
||||
vboDirty(true)
|
||||
{
|
||||
VAO::bind(vao);
|
||||
VBO::bind(vbo);
|
||||
gState->bindQuadIBO();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glColorPointer (4, GL_FLOAT, sizeof(Vertex), Vertex::colorOffset());
|
||||
glVertexPointer (2, GL_FLOAT, sizeof(Vertex), Vertex::posOffset());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), Vertex::texPosOffset());
|
||||
|
||||
VAO::unbind();
|
||||
VBO::unbind();
|
||||
IBO::unbind();
|
||||
|
||||
setColor(Vec4(1, 1, 1, 1));
|
||||
}
|
||||
|
||||
~Quad()
|
||||
{
|
||||
VAO::del(vao);
|
||||
VBO::del(vbo);
|
||||
}
|
||||
|
||||
void updateBuffer()
|
||||
{
|
||||
VBO::bind(vbo);
|
||||
VBO::allocEmpty(sizeof(Vertex) * 4, GL_DYNAMIC_DRAW);
|
||||
VBO::uploadData(sizeof(Vertex) * 4, vert, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
void setPosRect(const FloatRect &r)
|
||||
{
|
||||
setPosRect(vert, r);
|
||||
vboDirty = true;
|
||||
}
|
||||
|
||||
void setTexRect(const FloatRect &r)
|
||||
{
|
||||
setTexRect(vert, r);
|
||||
vboDirty = true;
|
||||
}
|
||||
|
||||
void setTexPosRect(const FloatRect &tex, const FloatRect &pos)
|
||||
{
|
||||
setTexPosRect(vert, tex, pos);
|
||||
vboDirty = true;
|
||||
}
|
||||
|
||||
void setColor(const Vec4 &c)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
vert[i].color = c;
|
||||
|
||||
vboDirty = true;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (vboDirty)
|
||||
{
|
||||
updateBuffer();
|
||||
vboDirty = false;
|
||||
}
|
||||
|
||||
VAO::bind(vao);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
VAO::unbind();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // QUAD_H
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
** quadarray.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QUADARRAY_H
|
||||
#define QUADARRAY_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "gl-util.h"
|
||||
#include "globalstate.h"
|
||||
#include "global-ibo.h"
|
||||
|
||||
typedef quint32 index_t;
|
||||
#define _GL_INDEX_TYPE GL_UNSIGNED_INT
|
||||
|
||||
struct ColorQuadArray
|
||||
{
|
||||
QVector<Vertex> vertices;
|
||||
|
||||
VBO::ID vbo;
|
||||
VAO::ID vao;
|
||||
|
||||
int quadCount;
|
||||
|
||||
ColorQuadArray()
|
||||
: quadCount(0)
|
||||
{
|
||||
vbo = VBO::gen();
|
||||
vao = VAO::gen();
|
||||
|
||||
VAO::bind(vao);
|
||||
VBO::bind(vbo);
|
||||
gState->bindQuadIBO();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glVertexPointer (2, GL_FLOAT, sizeof(Vertex), Vertex::posOffset());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), Vertex::texPosOffset());
|
||||
glColorPointer (4, GL_FLOAT, sizeof(Vertex), Vertex::colorOffset());
|
||||
|
||||
VAO::unbind();
|
||||
IBO::unbind();
|
||||
VBO::unbind();
|
||||
}
|
||||
|
||||
~ColorQuadArray()
|
||||
{
|
||||
VBO::del(vbo);
|
||||
VAO::del(vao);
|
||||
}
|
||||
|
||||
void resize(int size)
|
||||
{
|
||||
vertices.resize(size * 4);
|
||||
quadCount = size;
|
||||
}
|
||||
|
||||
/* This needs to be called after the final 'append()' call
|
||||
* and previous to the first 'draw()' call. */
|
||||
void commit()
|
||||
{
|
||||
VBO::bind(vbo);
|
||||
VBO::uploadData(vertices.size() * sizeof(Vertex), vertices.constData(), GL_DYNAMIC_DRAW);
|
||||
VBO::unbind();
|
||||
|
||||
gState->ensureQuadIBO(quadCount);
|
||||
}
|
||||
|
||||
void draw(uint offset, uint count)
|
||||
{
|
||||
VAO::bind(vao);
|
||||
|
||||
const char *_offset = (const char*) 0 + offset * 6 * sizeof(index_t);
|
||||
glDrawElements(GL_TRIANGLES, count * 6, _GL_INDEX_TYPE, _offset);
|
||||
|
||||
VAO::unbind();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
draw(0, quadCount);
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
return quadCount;
|
||||
}
|
||||
};
|
||||
|
||||
struct PointArray
|
||||
{
|
||||
QVector<Vertex> vertices;
|
||||
VBO::ID vbo;
|
||||
VAO::ID vao;
|
||||
|
||||
PointArray()
|
||||
{
|
||||
vbo = VBO::gen();
|
||||
vao = VAO::gen();
|
||||
|
||||
VAO::bind(vao);
|
||||
VBO::bind(vbo);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), (const GLvoid*) 0);
|
||||
glColorPointer (4, GL_FLOAT, sizeof(Vertex), (const GLvoid*) sizeof(SVertex));
|
||||
|
||||
VAO::unbind();
|
||||
VBO::unbind();
|
||||
}
|
||||
|
||||
~PointArray()
|
||||
{
|
||||
VBO::del(vbo);
|
||||
VAO::del(vao);
|
||||
}
|
||||
|
||||
void append(const Vec2 &pos, const Vec4 &color)
|
||||
{
|
||||
Vertex vert;
|
||||
vert.pos = pos;
|
||||
vert.color = color;
|
||||
vertices.append(vert);
|
||||
}
|
||||
|
||||
void commit()
|
||||
{
|
||||
VBO::bind(vbo);
|
||||
VBO::uploadData(vertices.size() * sizeof(Vertex), vertices.constData());
|
||||
VBO::unbind();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
vertices.clear();
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
VAO::bind(vao);
|
||||
glDrawArrays(GL_POINTS, 0, count());
|
||||
VAO::unbind();
|
||||
}
|
||||
|
||||
int count()
|
||||
{
|
||||
return vertices.count();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // QUADARRAY_H
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
** scene.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "scene.h"
|
||||
#include "globalstate.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
Scene::Scene()
|
||||
{
|
||||
geometry.xOrigin = geometry.yOrigin = 0;
|
||||
geometry.rect = IntRect();
|
||||
}
|
||||
|
||||
void Scene::insert(SceneElement &element)
|
||||
{
|
||||
IntruListLink<SceneElement> *iter;
|
||||
|
||||
for (iter = elements.begin(); iter != elements.end(); iter = iter->next)
|
||||
{
|
||||
SceneElement *e = iter->data;
|
||||
|
||||
if (element.z <= e->z)
|
||||
{
|
||||
if (element.z == e->z)
|
||||
if (element.creationStamp > e->creationStamp)
|
||||
continue;
|
||||
|
||||
elements.insertBefore(element.link, *iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
elements.append(element.link);
|
||||
}
|
||||
|
||||
void Scene::reinsert(SceneElement &element)
|
||||
{
|
||||
elements.remove(element.link);
|
||||
insert(element);
|
||||
}
|
||||
|
||||
void Scene::notifyGeometryChange()
|
||||
{
|
||||
IntruListLink<SceneElement> *iter;
|
||||
|
||||
for (iter = elements.begin(); iter != elements.end(); iter = iter->next)
|
||||
{
|
||||
iter->data->onGeometryChange(geometry);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::composite()
|
||||
{
|
||||
IntruListLink<SceneElement> *iter;
|
||||
|
||||
for (iter = elements.begin(); iter != elements.end(); iter = iter->next)
|
||||
{
|
||||
SceneElement *e = iter->data;
|
||||
|
||||
if (e->visible)
|
||||
e->draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SceneElement::SceneElement(Scene &scene, int z)
|
||||
: link(this),
|
||||
creationStamp(gState->genTimeStamp()),
|
||||
z(z),
|
||||
visible(true),
|
||||
scene(&scene)
|
||||
{
|
||||
scene.insert(*this);
|
||||
}
|
||||
|
||||
SceneElement::~SceneElement()
|
||||
{
|
||||
unlink();
|
||||
}
|
||||
|
||||
void SceneElement::setScene(Scene &scene)
|
||||
{
|
||||
unlink();
|
||||
|
||||
this->scene = &scene;
|
||||
|
||||
scene.insert(*this);
|
||||
|
||||
onGeometryChange(scene.getGeometry());
|
||||
}
|
||||
|
||||
int SceneElement::getZ() const
|
||||
{
|
||||
aboutToAccess();
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
void SceneElement::setZ(int value)
|
||||
{
|
||||
aboutToAccess();
|
||||
|
||||
if (z == value)
|
||||
return;
|
||||
|
||||
z = value;
|
||||
scene->reinsert(*this);
|
||||
}
|
||||
|
||||
bool SceneElement::getVisible() const
|
||||
{
|
||||
aboutToAccess();
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
void SceneElement::setVisible(bool value)
|
||||
{
|
||||
aboutToAccess();
|
||||
|
||||
visible = value;
|
||||
}
|
||||
|
||||
void SceneElement::unlink()
|
||||
{
|
||||
scene->elements.remove(link);
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
** scene.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCENE_H
|
||||
#define SCENE_H
|
||||
|
||||
#include "util.h"
|
||||
#include "intrulist.h"
|
||||
#include "etc.h"
|
||||
#include "etc-internal.h"
|
||||
|
||||
class SceneElement;
|
||||
class Viewport;
|
||||
class Window;
|
||||
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
struct Geometry
|
||||
{
|
||||
int xOrigin, yOrigin;
|
||||
IntRect rect;
|
||||
};
|
||||
|
||||
Scene();
|
||||
virtual ~Scene() {}
|
||||
|
||||
virtual void composite();
|
||||
virtual void requestViewportRender(Vec4& /*color*/, Vec4& /*flash*/, Vec4& /*tone*/) {}
|
||||
|
||||
const Geometry &getGeometry() const { return geometry; }
|
||||
|
||||
protected:
|
||||
void insert(SceneElement &element);
|
||||
void reinsert(SceneElement &element);
|
||||
|
||||
/* Notify all elements that geometry has changed */
|
||||
void notifyGeometryChange();
|
||||
|
||||
IntruList<SceneElement> elements;
|
||||
Geometry geometry;
|
||||
|
||||
friend class SceneElement;
|
||||
friend class Window;
|
||||
};
|
||||
|
||||
class SceneElement
|
||||
{
|
||||
public:
|
||||
SceneElement(Scene &scene, int z = 0);
|
||||
virtual ~SceneElement();
|
||||
|
||||
void setScene(Scene &scene);
|
||||
|
||||
DECL_ATTR_VIRT( Z, int )
|
||||
DECL_ATTR_VIRT( Visible, bool )
|
||||
|
||||
/* Disposable classes reimplement this to
|
||||
* check if they're disposed before access */
|
||||
virtual void aboutToAccess() const {}
|
||||
|
||||
protected:
|
||||
virtual void draw() = 0;
|
||||
virtual void onGeometryChange(const Scene::Geometry &) {}
|
||||
|
||||
void unlink();
|
||||
|
||||
IntruListLink<SceneElement> link;
|
||||
const unsigned int creationStamp;
|
||||
int z;
|
||||
bool visible;
|
||||
Scene *scene;
|
||||
|
||||
friend class Scene;
|
||||
friend class Viewport;
|
||||
};
|
||||
|
||||
#endif // SCENE_H
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
** serial-util.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SERIALUTIL_H
|
||||
#define SERIALUTIL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned uint;
|
||||
|
||||
static inline int16_t
|
||||
read_int16(const char *data, uint &i)
|
||||
{
|
||||
int16_t result = (data[i] & 0x000000FF) | ((data[i+1] << 8) & 0x0000FF00);
|
||||
i += 2;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
read_int32(const char *data, uint &i)
|
||||
{
|
||||
int32_t result = ((data[i+0] << 0x00) & 0x000000FF)
|
||||
| ((data[i+1] << 0x08) & 0x0000FF00)
|
||||
| ((data[i+2] << 0x10) & 0x00FF0000)
|
||||
| ((data[i+3] << 0x18) & 0xFF000000);
|
||||
i += 4;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_int16(char **data, int16_t value)
|
||||
{
|
||||
*(*data)++ = (value >> 0) & 0xFF;
|
||||
*(*data)++ = (value >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
static inline void
|
||||
write_int32(char **data, int32_t value)
|
||||
{
|
||||
*(*data)++ = (value >> 0x00) & 0xFF;
|
||||
*(*data)++ = (value >> 0x08) & 0xFF;
|
||||
*(*data)++ = (value >> 0x10) & 0xFF;
|
||||
*(*data)++ = (value >> 0x18) & 0xFF;
|
||||
}
|
||||
|
||||
union doubleInt
|
||||
{
|
||||
double d;
|
||||
int64_t i;
|
||||
};
|
||||
|
||||
static inline void
|
||||
write_double(char **data, double value)
|
||||
{
|
||||
doubleInt di;
|
||||
di.d = value;
|
||||
|
||||
*(*data)++ = (di.i >> 0x00) & 0xFF;
|
||||
*(*data)++ = (di.i >> 0x08) & 0xFF;
|
||||
*(*data)++ = (di.i >> 0x10) & 0xFF;
|
||||
*(*data)++ = (di.i >> 0x18) & 0xFF;
|
||||
*(*data)++ = (di.i >> 0x20) & 0xFF;
|
||||
*(*data)++ = (di.i >> 0x28) & 0xFF;
|
||||
*(*data)++ = (di.i >> 0x30) & 0xFF;
|
||||
*(*data)++ = (di.i >> 0x38) & 0xFF;
|
||||
}
|
||||
|
||||
static inline double
|
||||
read_double(const char *data, uint &i)
|
||||
{
|
||||
doubleInt di;
|
||||
di.i = (((int64_t)data[i+0] << 0x00) & 0x00000000000000FF)
|
||||
| (((int64_t)data[i+1] << 0x08) & 0x000000000000FF00)
|
||||
| (((int64_t)data[i+2] << 0x10) & 0x0000000000FF0000)
|
||||
| (((int64_t)data[i+3] << 0x18) & 0x00000000FF000000)
|
||||
| (((int64_t)data[i+4] << 0x20) & 0x000000FF00000000)
|
||||
| (((int64_t)data[i+5] << 0x28) & 0x0000FF0000000000)
|
||||
| (((int64_t)data[i+6] << 0x30) & 0x00FF000000000000)
|
||||
| (((int64_t)data[i+7] << 0x38) & 0xFF00000000000000);
|
||||
i += 8;
|
||||
|
||||
return di.d;
|
||||
}
|
||||
|
||||
#endif // SERIALUTIL_H
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
** serializable.h
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SERIALIZABLE_H
|
||||
#define SERIALIZABLE_H
|
||||
|
||||
struct Serializable
|
||||
{
|
||||
virtual ~Serializable() {}
|
||||
|
||||
virtual int serialSize() const = 0;
|
||||
virtual void serialize(char *buffer) const = 0;
|
||||
};
|
||||
|
||||
template<class C>
|
||||
C *deserialize(const char *data)
|
||||
{
|
||||
return C::deserialize(data);
|
||||
}
|
||||
|
||||
#endif // SERIALIZABLE_H
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
** shader.cpp
|
||||
**
|
||||
** This file is part of mkxp.
|
||||
**
|
||||
** Copyright (C) 2013 Jonas Kulla <Nyocurio@gmail.com>
|
||||
**
|
||||
** mkxp is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 2 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** mkxp is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "shader.h"
|
||||
|
||||
#include "GL/glew.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include "../shader/sprite.frag.xxd"
|
||||
#include "../shader/hue.frag.xxd"
|
||||
#include "../shader/trans.frag.xxd"
|
||||
#include "../shader/transSimple.frag.xxd"
|
||||
#include "../shader/bitmapBlit.frag.xxd"
|
||||
|
||||
#define GET_U(name) u_##name = glGetUniformLocation(program, #name)
|
||||
|
||||
FragShader::~FragShader()
|
||||
{
|
||||
glUseProgram(0);
|
||||
glDeleteProgram(program);
|
||||
glDeleteShader(shader);
|
||||
}
|
||||
|
||||
void FragShader::bind()
|
||||
{
|
||||
glUseProgram(program);
|
||||
}
|
||||
|
||||
void FragShader::unbind()
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void FragShader::init(const unsigned char *source, int length)
|
||||
{
|
||||
GLint success;
|
||||
|
||||
shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(shader, 1, (const GLchar**) &source, (const GLint*) &length);
|
||||
glCompileShader(shader);
|
||||
|
||||
glGetObjectParameterivARB(shader, GL_COMPILE_STATUS, &success);
|
||||
Q_ASSERT(success);
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, shader);
|
||||
glLinkProgram(program);
|
||||
|
||||
glGetObjectParameterivARB(program, GL_LINK_STATUS, &success);
|
||||
Q_ASSERT(success);
|
||||
}
|
||||
|
||||
void FragShader::initFromFile(const char *filename)
|
||||
{
|
||||
QFile shaderFile(filename);
|
||||
shaderFile.open(QFile::ReadOnly);
|
||||
QByteArray contents = shaderFile.readAll();
|
||||
shaderFile.close();
|
||||
|
||||
init((const unsigned char*) contents.constData(), contents.size());
|
||||
}
|
||||
|
||||
void FragShader::setVec4Uniform(GLint location, const Vec4 &vec)
|
||||
{
|
||||
glUniform4f(location, vec.x, vec.y, vec.z, vec.w);
|
||||
}
|
||||
|
||||
void FragShader::setTexUniform(GLint location, unsigned unitIndex, Tex::ID texture)
|
||||
{
|
||||
GLenum texUnit = GL_TEXTURE0 + unitIndex;
|
||||
|
||||
glActiveTexture(texUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, texture.gl);
|
||||
glUniform1i(location, unitIndex);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
|
||||
TransShader::TransShader()
|
||||
{
|
||||
init(shader_trans_frag,
|
||||
shader_trans_frag_len);
|
||||
|
||||
GET_U(currentScene);
|
||||
GET_U(frozenScene);
|
||||
GET_U(transMap);
|
||||
GET_U(prog);
|
||||
GET_U(vague);
|
||||
}
|
||||
|
||||
void TransShader::setCurrentScene(Tex::ID tex)
|
||||
{
|
||||
setTexUniform(u_currentScene, 0, tex);
|
||||
}
|
||||
|
||||
void TransShader::setFrozenScene(Tex::ID tex)
|
||||
{
|
||||
setTexUniform(u_frozenScene, 1, tex);
|
||||
}
|
||||
|
||||
void TransShader::setTransMap(Tex::ID tex)
|
||||
{
|
||||
setTexUniform(u_transMap, 2, tex);
|
||||
}
|
||||
|
||||
void TransShader::setProg(float value)
|
||||
{
|
||||
glUniform1f(u_prog, value);
|
||||
}
|
||||
|
||||
void TransShader::setVague(float value)
|
||||
{
|
||||
glUniform1f(u_vague, value);
|
||||
}
|
||||
|
||||
|
||||
SimpleTransShader::SimpleTransShader()
|
||||
{
|
||||
init(shader_transSimple_frag,
|
||||
shader_transSimple_frag_len);
|
||||
|
||||
GET_U(currentScene);
|
||||
GET_U(frozenScene);
|
||||
GET_U(prog);
|
||||
}
|
||||
|
||||
void SimpleTransShader::setCurrentScene(Tex::ID tex)
|
||||
{
|
||||
setTexUniform(u_currentScene, 0, tex);
|
||||
}
|
||||
|
||||
void SimpleTransShader::setFrozenScene(Tex::ID tex)
|
||||
{
|
||||
setTexUniform(u_frozenScene, 1, tex);
|
||||
}
|
||||
|
||||
void SimpleTransShader::setProg(float value)
|
||||
{
|
||||
glUniform1f(u_prog, value);
|
||||
}
|
||||
|
||||
|
||||
SpriteShader::SpriteShader()
|
||||
{
|
||||
init(shader_sprite_frag,
|
||||
shader_sprite_frag_len);
|
||||
|
||||
GET_U(tone);
|
||||
GET_U(color);
|
||||
GET_U(flash);
|
||||
GET_U(opacity);
|
||||
GET_U(bushDepth);
|
||||
GET_U(bushOpacity);
|
||||
|
||||
bind();
|
||||
resetUniforms();
|
||||
unbind();
|
||||
}
|
||||
|
||||
void SpriteShader::resetUniforms()
|
||||
{
|
||||
setTone(Vec4());
|
||||
setColor(Vec4());
|
||||
setFlash(Vec4());
|
||||
setOpacity(1);
|
||||
setBushDepth(0);
|
||||
setBushOpacity(0.5);
|
||||
}
|
||||
|
||||
void SpriteShader::setTone(const Vec4 &tone)
|
||||
{
|
||||
setVec4Uniform(u_tone, tone);
|
||||
}
|
||||
|
||||
void SpriteShader::setColor(const Vec4 &color)
|
||||
{
|
||||
setVec4Uniform(u_color, color);
|
||||
}
|
||||
|
||||
void SpriteShader::setFlash(const Vec4 &flash)
|
||||
{
|
||||
setVec4Uniform(u_flash, flash);
|
||||
}
|
||||
|
||||
void SpriteShader::setOpacity(float value)
|
||||
{
|
||||
glUniform1f(u_opacity, value);
|
||||
}
|
||||
|
||||
void SpriteShader::setBushDepth(float value)
|
||||
{
|
||||
glUniform1f(u_bushDepth, value);
|
||||
}
|
||||
|
||||
void SpriteShader::setBushOpacity(float value)
|
||||
{
|
||||
glUniform1f(u_bushOpacity, value);
|
||||
}
|
||||
|
||||
|
||||
HueShader::HueShader()
|
||||
{
|
||||
init(shader_hue_frag,
|
||||
shader_hue_frag_len);
|
||||
|
||||
GET_U(hueAdjust);
|
||||
GET_U(inputTexture);
|
||||
}
|
||||
|
||||
void HueShader::setHueAdjust(float value)
|
||||
{
|
||||
glUniform1f(u_hueAdjust, value);
|
||||
}
|
||||
|
||||
void HueShader::setInputTexture(Tex::ID tex)
|
||||
{
|
||||
setTexUniform(u_inputTexture, 0, tex);
|
||||
}
|
||||
|
||||
|
||||
BltShader::BltShader()
|
||||
{
|
||||
init(shader_bitmapBlit_frag,
|
||||
shader_bitmapBlit_frag_len);
|
||||
|
||||
GET_U(source);
|
||||
GET_U(destination);
|
||||
GET_U(subRect);
|
||||
GET_U(opacity);
|
||||
}
|
||||
|
||||
void BltShader::setSource()
|
||||
{
|
||||
glUniform1i(u_source, 0);
|
||||
}
|
||||
|
||||
void BltShader::setDestination(const Tex::ID value)
|
||||
{
|
||||
setTexUniform(u_destination, 1, value);
|
||||
}
|
||||
|
||||
void BltShader::setSubRect(const FloatRect &value)
|
||||
{
|
||||
glUniform4f(u_subRect, value.x, value.y, value.w, value.h);
|
||||
}
|
||||
|
||||
void BltShader::setOpacity(float value)
|
||||
{
|
||||
glUniform1f(u_opacity, value);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue