mirror of
https://github.com/love2d/love-android.git
synced 2026-08-12 16:41:12 +02:00
Updated LÖVE source to changeset da332813bc05
This commit is contained in:
@@ -465,7 +465,11 @@ bool luax_istype(lua_State *L, int idx, love::Type type)
|
||||
return false;
|
||||
|
||||
Proxy *p = (Proxy *) lua_touserdata(L, idx);
|
||||
return typeFlags[p->type][type];
|
||||
|
||||
if (p->type > INVALID_ID && p->type < TYPE_MAX_ENUM)
|
||||
return typeFlags[p->type][type];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int luax_getfunction(lua_State *L, const char *mod, const char *fn)
|
||||
|
||||
@@ -32,11 +32,11 @@ namespace event
|
||||
|
||||
#define instance() (Module::getInstance<Event>(Module::M_EVENT))
|
||||
|
||||
static int poll_i(lua_State *L)
|
||||
static int w_poll_i(lua_State *L)
|
||||
{
|
||||
Message *m;
|
||||
Message *m = nullptr;
|
||||
|
||||
while (instance()->poll(m))
|
||||
if (instance()->poll(m))
|
||||
{
|
||||
int args = m->toLua(L);
|
||||
m->release();
|
||||
@@ -47,23 +47,22 @@ static int poll_i(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_poll(lua_State *L)
|
||||
{
|
||||
lua_pushcclosure(L, &w_poll_i, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_pump(lua_State *)
|
||||
{
|
||||
instance()->pump();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_poll(lua_State *L)
|
||||
{
|
||||
lua_pushcclosure(L, &poll_i, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_wait(lua_State *L)
|
||||
{
|
||||
Message *m;
|
||||
|
||||
if ((m = instance()->wait()))
|
||||
Message *m = instance()->wait();
|
||||
if (m)
|
||||
{
|
||||
int args = m->toLua(L);
|
||||
m->release();
|
||||
@@ -75,12 +74,11 @@ int w_wait(lua_State *L)
|
||||
|
||||
int w_push(lua_State *L)
|
||||
{
|
||||
Message *m;
|
||||
Message *m = Message::fromLua(L, 1);
|
||||
|
||||
bool success = (m = Message::fromLua(L, 1)) != NULL;
|
||||
luax_pushboolean(L, success);
|
||||
luax_pushboolean(L, m != nullptr);
|
||||
|
||||
if (!success)
|
||||
if (m == nullptr)
|
||||
return 1;
|
||||
|
||||
instance()->push(m);
|
||||
@@ -143,7 +141,9 @@ extern "C" int luaopen_love_event(lua_State *L)
|
||||
w.functions = functions;
|
||||
w.types = nullptr;
|
||||
|
||||
return luax_register_module(L, w);
|
||||
int ret = luax_register_module(L, w);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // event
|
||||
|
||||
@@ -156,6 +156,12 @@ public:
|
||||
**/
|
||||
virtual std::string getRealDirectory(const char *filename) const = 0;
|
||||
|
||||
/**
|
||||
* Checks if a path exists.
|
||||
* @param path The path to check.
|
||||
**/
|
||||
virtual bool exists(const char *path) const = 0;
|
||||
|
||||
/**
|
||||
* Checks if a path is a directory.
|
||||
* @param dir The directory name to check.
|
||||
@@ -168,6 +174,12 @@ public:
|
||||
**/
|
||||
virtual bool isFile(const char *file) const = 0;
|
||||
|
||||
/**
|
||||
* Gets whether a filepath is actually a symlink.
|
||||
* Always returns false if symlinks are not enabled.
|
||||
**/
|
||||
virtual bool isSymlink(const char *filename) const = 0;
|
||||
|
||||
/**
|
||||
* Creates a directory. Write dir must be set.
|
||||
* @param dir The directory to create.
|
||||
@@ -232,12 +244,6 @@ public:
|
||||
**/
|
||||
virtual bool areSymlinksEnabled() const = 0;
|
||||
|
||||
/**
|
||||
* Gets whether a filepath is actually a symlink.
|
||||
* Always returns false if symlinks are not enabled.
|
||||
**/
|
||||
virtual bool isSymlink(const char *filename) const = 0;
|
||||
|
||||
// Require path accessors
|
||||
// Not const because it's R/W
|
||||
virtual std::vector<std::string> &getRequirePath() = 0;
|
||||
|
||||
@@ -154,7 +154,11 @@ int64 File::read(void *dst, int64 size)
|
||||
if (size < 0)
|
||||
throw love::Exception("Invalid read size.");
|
||||
|
||||
#ifdef LOVE_USE_PHYSFS_2_1
|
||||
int64 read = PHYSFS_readBytes(file, dst, (PHYSFS_uint64) size);
|
||||
#else
|
||||
int64 read = (int64)PHYSFS_read(file, dst, 1, (PHYSFS_uint32) size);
|
||||
#endif
|
||||
|
||||
return read;
|
||||
}
|
||||
@@ -171,7 +175,11 @@ bool File::write(const void *data, int64 size)
|
||||
throw love::Exception("Invalid write size.");
|
||||
|
||||
// Try to write.
|
||||
#ifdef LOVE_USE_PHYSFS_2_1
|
||||
int64 written = PHYSFS_writeBytes(file, data, (PHYSFS_uint64) size);
|
||||
#else
|
||||
int64 written = (int64) PHYSFS_write(file, data, 1, (PHYSFS_uint32) size);
|
||||
#endif
|
||||
|
||||
// Check that correct amount of data was written.
|
||||
if (written != size)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define LOVE_FILESYSTEM_PHYSFS_FILE_H
|
||||
|
||||
// LOVE
|
||||
#include "common/config.h"
|
||||
#include "filesystem/File.h"
|
||||
|
||||
// PhysFS
|
||||
@@ -34,6 +35,12 @@
|
||||
// STD
|
||||
#include <string>
|
||||
|
||||
// These platforms always use PhysFS 2.1.
|
||||
#if (defined(LOVE_IOS) || defined(LOVE_ANDROID)) \
|
||||
&& (PHYSFS_VER_MAJOR == 2 && PHYSFS_VER_MINOR >= 1)
|
||||
#define LOVE_USE_PHYSFS_2_1
|
||||
#endif
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace filesystem
|
||||
|
||||
@@ -188,7 +188,13 @@ bool Filesystem::setIdentity(const char *ident, bool appendToPath)
|
||||
// We don't want old read-only save paths to accumulate when we set a new
|
||||
// identity.
|
||||
if (!old_save_path.empty())
|
||||
{
|
||||
#ifdef LOVE_USE_PHYSFS_2_1
|
||||
PHYSFS_unmount(old_save_path.c_str());
|
||||
#else
|
||||
PHYSFS_removeFromSearchPath(old_save_path.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Try to add the save directory to the search path.
|
||||
// (No error on fail, it means that the path doesn't exist).
|
||||
@@ -433,7 +439,11 @@ bool Filesystem::unmount(const char *archive)
|
||||
if (!mountPoint)
|
||||
return false;
|
||||
|
||||
#ifdef LOVE_USE_PHYSFS_2_1
|
||||
return PHYSFS_unmount(realPath.c_str()) != 0;
|
||||
#else
|
||||
return PHYSFS_removeFromSearchPath(realPath.c_str()) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
love::filesystem::File *Filesystem::newFile(const char *filename) const
|
||||
@@ -569,14 +579,40 @@ std::string Filesystem::getRealDirectory(const char *filename) const
|
||||
return std::string(dir);
|
||||
}
|
||||
|
||||
bool Filesystem::exists(const char *path) const
|
||||
{
|
||||
return PHYSFS_exists(path) != 0;
|
||||
}
|
||||
|
||||
bool Filesystem::isDirectory(const char *dir) const
|
||||
{
|
||||
#ifdef LOVE_USE_PHYSFS_2_1
|
||||
PHYSFS_Stat stat = {};
|
||||
if (PHYSFS_stat(dir, &stat))
|
||||
return stat.filetype == PHYSFS_FILETYPE_DIRECTORY;
|
||||
else
|
||||
return false;
|
||||
#else
|
||||
return PHYSFS_isDirectory(dir) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Filesystem::isFile(const char *file) const
|
||||
{
|
||||
return PHYSFS_exists(file) && !PHYSFS_isDirectory(file);
|
||||
return PHYSFS_exists(file) && !isDirectory(file);
|
||||
}
|
||||
|
||||
bool Filesystem::isSymlink(const char *filename) const
|
||||
{
|
||||
#ifdef LOVE_USE_PHYSFS_2_1
|
||||
PHYSFS_Stat stat = {};
|
||||
if (PHYSFS_stat(filename, &stat))
|
||||
return stat.filetype == PHYSFS_FILETYPE_SYMLINK;
|
||||
else
|
||||
return false;
|
||||
#else
|
||||
return PHYSFS_isSymbolicLink(filename) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Filesystem::createDirectory(const char *dir)
|
||||
@@ -643,7 +679,15 @@ void Filesystem::getDirectoryItems(const char *dir, std::vector<std::string> &it
|
||||
|
||||
int64 Filesystem::getLastModified(const char *filename) const
|
||||
{
|
||||
PHYSFS_sint64 time = PHYSFS_getLastModTime(filename);
|
||||
PHYSFS_sint64 time = -1;
|
||||
|
||||
#ifdef LOVE_USE_PHYSFS_2_1
|
||||
PHYSFS_Stat stat = {};
|
||||
if (PHYSFS_stat(filename, &stat))
|
||||
time = stat.modtime;
|
||||
#else
|
||||
time = PHYSFS_getLastModTime(filename);
|
||||
#endif
|
||||
|
||||
if (time == -1)
|
||||
throw love::Exception("Could not determine file modification date.");
|
||||
@@ -679,11 +723,6 @@ bool Filesystem::areSymlinksEnabled() const
|
||||
return PHYSFS_symbolicLinksPermitted() != 0;
|
||||
}
|
||||
|
||||
bool Filesystem::isSymlink(const char *filename) const
|
||||
{
|
||||
return PHYSFS_isSymbolicLink(filename) != 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> &Filesystem::getRequirePath()
|
||||
{
|
||||
return requirePath;
|
||||
|
||||
@@ -75,8 +75,10 @@ public:
|
||||
|
||||
std::string getRealDirectory(const char *filename) const;
|
||||
|
||||
bool exists(const char *path) const;
|
||||
bool isDirectory(const char *dir) const;
|
||||
bool isFile(const char *file) const;
|
||||
bool isSymlink(const char *filename) const;
|
||||
|
||||
bool createDirectory(const char *dir);
|
||||
|
||||
@@ -93,7 +95,6 @@ public:
|
||||
|
||||
void setSymlinksEnabled(bool enable);
|
||||
bool areSymlinksEnabled() const;
|
||||
bool isSymlink(const char *filename) const;
|
||||
|
||||
std::vector<std::string> &getRequirePath();
|
||||
|
||||
|
||||
@@ -316,6 +316,13 @@ int w_getExecutablePath(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_exists(lua_State *L)
|
||||
{
|
||||
const char *arg = luaL_checkstring(L, 1);
|
||||
luax_pushboolean(L, instance()->exists(arg));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_isDirectory(lua_State *L)
|
||||
{
|
||||
const char *arg = luaL_checkstring(L, 1);
|
||||
@@ -330,6 +337,13 @@ int w_isFile(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_isSymlink(lua_State *L)
|
||||
{
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
luax_pushboolean(L, instance()->isSymlink(filename));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_createDirectory(lua_State *L)
|
||||
{
|
||||
const char *arg = luaL_checkstring(L, 1);
|
||||
@@ -551,13 +565,6 @@ int w_areSymlinksEnabled(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_isSymlink(lua_State *L)
|
||||
{
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
luax_pushboolean(L, instance()->isSymlink(filename));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getRequirePath(lua_State *L)
|
||||
{
|
||||
std::stringstream path;
|
||||
@@ -715,8 +722,10 @@ static const luaL_Reg functions[] =
|
||||
{ "getSourceBaseDirectory", w_getSourceBaseDirectory },
|
||||
{ "getRealDirectory", w_getRealDirectory },
|
||||
{ "getExecutablePath", w_getExecutablePath },
|
||||
{ "exists", w_exists },
|
||||
{ "isDirectory", w_isDirectory },
|
||||
{ "isFile", w_isFile },
|
||||
{ "isSymlink", w_isSymlink },
|
||||
{ "createDirectory", w_createDirectory },
|
||||
{ "remove", w_remove },
|
||||
{ "read", w_read },
|
||||
@@ -729,7 +738,6 @@ static const luaL_Reg functions[] =
|
||||
{ "getSize", w_getSize },
|
||||
{ "setSymlinksEnabled", w_setSymlinksEnabled },
|
||||
{ "areSymlinksEnabled", w_areSymlinksEnabled },
|
||||
{ "isSymlink", w_isSymlink },
|
||||
{ "newFileData", w_newFileData },
|
||||
{ "getRequirePath", w_getRequirePath },
|
||||
{ "setRequirePath", w_setRequirePath },
|
||||
|
||||
@@ -82,6 +82,16 @@ bool Graphics::getConstant(BlendMode in, const char *&out)
|
||||
return blendModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, BlendAlpha &out)
|
||||
{
|
||||
return blendAlphaModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(BlendAlpha in, const char *&out)
|
||||
{
|
||||
return blendAlphaModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, LineStyle &out)
|
||||
{
|
||||
return lineStyles.find(in, out);
|
||||
@@ -102,6 +112,26 @@ bool Graphics::getConstant(LineJoin in, const char *&out)
|
||||
return lineJoins.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, StencilAction &out)
|
||||
{
|
||||
return stencilActions.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(StencilAction in, const char *&out)
|
||||
{
|
||||
return stencilActions.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, CompareMode &out)
|
||||
{
|
||||
return compareModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(CompareMode in, const char *&out)
|
||||
{
|
||||
return compareModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Graphics::getConstant(const char *in, Support &out)
|
||||
{
|
||||
return support.find(in, out);
|
||||
@@ -152,16 +182,24 @@ StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM> Graphics::drawModes(Graph
|
||||
|
||||
StringMap<Graphics::BlendMode, Graphics::BLEND_MAX_ENUM>::Entry Graphics::blendModeEntries[] =
|
||||
{
|
||||
{ "alpha", BLEND_ALPHA },
|
||||
{ "add", BLEND_ADD },
|
||||
{ "alpha", BLEND_ALPHA },
|
||||
{ "add", BLEND_ADD },
|
||||
{ "subtract", BLEND_SUBTRACT },
|
||||
{ "multiply", BLEND_MULTIPLY },
|
||||
{ "screen", BLEND_SCREEN },
|
||||
{ "replace", BLEND_REPLACE },
|
||||
{ "screen", BLEND_SCREEN },
|
||||
{ "replace", BLEND_REPLACE },
|
||||
};
|
||||
|
||||
StringMap<Graphics::BlendMode, Graphics::BLEND_MAX_ENUM> Graphics::blendModes(Graphics::blendModeEntries, sizeof(Graphics::blendModeEntries));
|
||||
|
||||
StringMap<Graphics::BlendAlpha, Graphics::BLENDALPHA_MAX_ENUM>::Entry Graphics::blendAlphaEntries[] =
|
||||
{
|
||||
{ "alphamultiply", BLENDALPHA_MULTIPLY },
|
||||
{ "premultiplied", BLENDALPHA_PREMULTIPLIED },
|
||||
};
|
||||
|
||||
StringMap<Graphics::BlendAlpha, Graphics::BLENDALPHA_MAX_ENUM> Graphics::blendAlphaModes(Graphics::blendAlphaEntries, sizeof(Graphics::blendAlphaEntries));
|
||||
|
||||
StringMap<Graphics::LineStyle, Graphics::LINE_MAX_ENUM>::Entry Graphics::lineStyleEntries[] =
|
||||
{
|
||||
{ "smooth", LINE_SMOOTH },
|
||||
@@ -179,6 +217,31 @@ StringMap<Graphics::LineJoin, Graphics::LINE_JOIN_MAX_ENUM>::Entry Graphics::lin
|
||||
|
||||
StringMap<Graphics::LineJoin, Graphics::LINE_JOIN_MAX_ENUM> Graphics::lineJoins(Graphics::lineJoinEntries, sizeof(Graphics::lineJoinEntries));
|
||||
|
||||
StringMap<Graphics::StencilAction, Graphics::STENCIL_MAX_ENUM>::Entry Graphics::stencilActionEntries[] =
|
||||
{
|
||||
{ "replace", STENCIL_REPLACE },
|
||||
{ "increment", STENCIL_INCREMENT },
|
||||
{ "decrement", STENCIL_DECREMENT },
|
||||
{ "incrementwrap", STENCIL_INCREMENT_WRAP },
|
||||
{ "decrementwrap", STENCIL_DECREMENT_WRAP },
|
||||
{ "invert", STENCIL_INVERT },
|
||||
};
|
||||
|
||||
StringMap<Graphics::StencilAction, Graphics::STENCIL_MAX_ENUM> Graphics::stencilActions(Graphics::stencilActionEntries, sizeof(Graphics::stencilActionEntries));
|
||||
|
||||
StringMap<Graphics::CompareMode, Graphics::COMPARE_MAX_ENUM>::Entry Graphics::compareModeEntries[] =
|
||||
{
|
||||
{ "less", COMPARE_LESS },
|
||||
{ "lequal", COMPARE_LEQUAL },
|
||||
{ "equal", COMPARE_EQUAL },
|
||||
{ "gequal", COMPARE_GEQUAL },
|
||||
{ "greater", COMPARE_GREATER },
|
||||
{ "notequal", COMPARE_NOTEQUAL },
|
||||
{ "always", COMPARE_ALWAYS },
|
||||
};
|
||||
|
||||
StringMap<Graphics::CompareMode, Graphics::COMPARE_MAX_ENUM> Graphics::compareModes(Graphics::compareModeEntries, sizeof(Graphics::compareModeEntries));
|
||||
|
||||
StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::supportEntries[] =
|
||||
{
|
||||
{ "multicanvasformats", SUPPORT_MULTI_CANVAS_FORMATS },
|
||||
|
||||
@@ -81,6 +81,13 @@ public:
|
||||
BLEND_MAX_ENUM
|
||||
};
|
||||
|
||||
enum BlendAlpha
|
||||
{
|
||||
BLENDALPHA_MULTIPLY,
|
||||
BLENDALPHA_PREMULTIPLIED,
|
||||
BLENDALPHA_MAX_ENUM
|
||||
};
|
||||
|
||||
enum LineStyle
|
||||
{
|
||||
LINE_ROUGH,
|
||||
@@ -96,6 +103,29 @@ public:
|
||||
LINE_JOIN_MAX_ENUM
|
||||
};
|
||||
|
||||
enum StencilAction
|
||||
{
|
||||
STENCIL_REPLACE,
|
||||
STENCIL_INCREMENT,
|
||||
STENCIL_DECREMENT,
|
||||
STENCIL_INCREMENT_WRAP,
|
||||
STENCIL_DECREMENT_WRAP,
|
||||
STENCIL_INVERT,
|
||||
STENCIL_MAX_ENUM
|
||||
};
|
||||
|
||||
enum CompareMode
|
||||
{
|
||||
COMPARE_LESS,
|
||||
COMPARE_LEQUAL,
|
||||
COMPARE_EQUAL,
|
||||
COMPARE_GEQUAL,
|
||||
COMPARE_GREATER,
|
||||
COMPARE_NOTEQUAL,
|
||||
COMPARE_ALWAYS,
|
||||
COMPARE_MAX_ENUM
|
||||
};
|
||||
|
||||
enum Support
|
||||
{
|
||||
SUPPORT_MULTI_CANVAS_FORMATS,
|
||||
@@ -232,12 +262,21 @@ public:
|
||||
static bool getConstant(const char *in, BlendMode &out);
|
||||
static bool getConstant(BlendMode in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, BlendAlpha &out);
|
||||
static bool getConstant(BlendAlpha in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, LineStyle &out);
|
||||
static bool getConstant(LineStyle in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, LineJoin &out);
|
||||
static bool getConstant(LineJoin in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, StencilAction &out);
|
||||
static bool getConstant(StencilAction in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, CompareMode &out);
|
||||
static bool getConstant(CompareMode in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, Support &out);
|
||||
static bool getConstant(Support in, const char *&out);
|
||||
|
||||
@@ -258,12 +297,21 @@ private:
|
||||
static StringMap<BlendMode, BLEND_MAX_ENUM>::Entry blendModeEntries[];
|
||||
static StringMap<BlendMode, BLEND_MAX_ENUM> blendModes;
|
||||
|
||||
static StringMap<BlendAlpha, BLENDALPHA_MAX_ENUM>::Entry blendAlphaEntries[];
|
||||
static StringMap<BlendAlpha, BLENDALPHA_MAX_ENUM> blendAlphaModes;
|
||||
|
||||
static StringMap<LineStyle, LINE_MAX_ENUM>::Entry lineStyleEntries[];
|
||||
static StringMap<LineStyle, LINE_MAX_ENUM> lineStyles;
|
||||
|
||||
static StringMap<LineJoin, LINE_JOIN_MAX_ENUM>::Entry lineJoinEntries[];
|
||||
static StringMap<LineJoin, LINE_JOIN_MAX_ENUM> lineJoins;
|
||||
|
||||
static StringMap<StencilAction, STENCIL_MAX_ENUM>::Entry stencilActionEntries[];
|
||||
static StringMap<StencilAction, STENCIL_MAX_ENUM> stencilActions;
|
||||
|
||||
static StringMap<CompareMode, COMPARE_MAX_ENUM>::Entry compareModeEntries[];
|
||||
static StringMap<CompareMode, COMPARE_MAX_ENUM> compareModes;
|
||||
|
||||
static StringMap<Support, SUPPORT_MAX_ENUM>::Entry supportEntries[];
|
||||
static StringMap<Support, SUPPORT_MAX_ENUM> support;
|
||||
|
||||
|
||||
@@ -558,7 +558,7 @@ bool Canvas::checkCreateStencil()
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object
|
||||
|| GLAD_EXT_packed_depth_stencil || GLAD_OES_packed_depth_stencil)
|
||||
{
|
||||
format = GL_DEPTH_STENCIL;
|
||||
format = GL_DEPTH24_STENCIL8;
|
||||
attachment = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||
}
|
||||
|
||||
|
||||
@@ -617,7 +617,7 @@ std::vector<Font::DrawCommand> Font::generateVerticesFormatted(const ColoredCode
|
||||
return drawcommands;
|
||||
}
|
||||
|
||||
void Font::drawVertices(const std::vector<DrawCommand> &drawcommands)
|
||||
void Font::drawVertices(const std::vector<DrawCommand> &drawcommands, bool bufferedvertices)
|
||||
{
|
||||
// Vertex attribute pointers need to be set before calling this function.
|
||||
// This assumes that the attribute pointers are constant for all vertices.
|
||||
@@ -634,7 +634,12 @@ void Font::drawVertices(const std::vector<DrawCommand> &drawcommands)
|
||||
const GLenum gltype = quadIndices.getType();
|
||||
const size_t elemsize = quadIndices.getElementSize();
|
||||
|
||||
GLBuffer::Bind bind(*quadIndices.getBuffer());
|
||||
// We only get indices from the index buffer if we're also using vertex
|
||||
// buffers, because at least one graphics driver (the one for Kepler nvidia
|
||||
// GPUs in OS X 10.11) fails to render geometry if an index buffer is used
|
||||
// with client-side vertex arrays.
|
||||
if (bufferedvertices)
|
||||
quadIndices.getBuffer()->bind();
|
||||
|
||||
// We need a separate draw call for every section of the text which uses a
|
||||
// different texture than the previous section.
|
||||
@@ -645,8 +650,15 @@ void Font::drawVertices(const std::vector<DrawCommand> &drawcommands)
|
||||
|
||||
// TODO: Use glDrawElementsBaseVertex when supported?
|
||||
gl.bindTexture(cmd.texture);
|
||||
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getPointer(offset));
|
||||
|
||||
if (bufferedvertices)
|
||||
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getPointer(offset));
|
||||
else
|
||||
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getIndices(offset));
|
||||
}
|
||||
|
||||
if (bufferedvertices)
|
||||
quadIndices.getBuffer()->unbind();
|
||||
}
|
||||
|
||||
void Font::printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices)
|
||||
@@ -665,7 +677,7 @@ void Font::printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands
|
||||
|
||||
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
|
||||
|
||||
drawVertices(drawcommands);
|
||||
drawVertices(drawcommands, false);
|
||||
}
|
||||
|
||||
void Font::print(const std::vector<ColoredString> &text, float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
|
||||
std::vector<DrawCommand> generateVerticesFormatted(const ColoredCodepoints &text, float wrap, AlignMode align, std::vector<GlyphVertex> &vertices, TextInfo *info = nullptr);
|
||||
|
||||
void drawVertices(const std::vector<DrawCommand> &drawcommands);
|
||||
void drawVertices(const std::vector<DrawCommand> &drawcommands, bool bufferedvertices);
|
||||
|
||||
static void getCodepointsFromString(const std::string &str, Codepoints &codepoints);
|
||||
static void getCodepointsFromString(const std::vector<ColoredString> &strs, ColoredCodepoints &codepoints);
|
||||
|
||||
@@ -244,7 +244,9 @@ void GLBuffer::unload()
|
||||
size_t QuadIndices::maxSize = 0;
|
||||
size_t QuadIndices::elementSize = 0;
|
||||
size_t QuadIndices::objectCount = 0;
|
||||
|
||||
GLBuffer *QuadIndices::indexBuffer = nullptr;
|
||||
char *QuadIndices::indices = nullptr;
|
||||
|
||||
QuadIndices::QuadIndices(size_t size)
|
||||
: size(size)
|
||||
@@ -259,6 +261,7 @@ QuadIndices::QuadIndices(size_t size)
|
||||
if (indexBuffer == nullptr || size > maxSize)
|
||||
{
|
||||
GLBuffer *newbuffer = nullptr;
|
||||
char *newindices = nullptr;
|
||||
|
||||
// Depending on the size, a switch to int and more memory is needed.
|
||||
GLenum targettype = getType(size);
|
||||
@@ -271,9 +274,12 @@ QuadIndices::QuadIndices(size_t size)
|
||||
try
|
||||
{
|
||||
newbuffer = new GLBuffer(buffersize, nullptr, GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW);
|
||||
newindices = new char[buffersize];
|
||||
}
|
||||
catch (std::bad_alloc &)
|
||||
{
|
||||
delete[] newbuffer;
|
||||
delete[] newindices;
|
||||
throw love::Exception("Out of memory.");
|
||||
}
|
||||
|
||||
@@ -281,6 +287,10 @@ QuadIndices::QuadIndices(size_t size)
|
||||
// The old GLBuffer can now be deleted.
|
||||
delete indexBuffer;
|
||||
indexBuffer = newbuffer;
|
||||
|
||||
delete[] indices;
|
||||
indices = newindices;
|
||||
|
||||
maxSize = size;
|
||||
elementSize = elemsize;
|
||||
|
||||
@@ -319,6 +329,9 @@ QuadIndices::~QuadIndices()
|
||||
{
|
||||
delete indexBuffer;
|
||||
indexBuffer = nullptr;
|
||||
|
||||
delete[] indices;
|
||||
indices = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,13 +368,15 @@ const void *QuadIndices::getPointer(size_t offset) const
|
||||
return indexBuffer->getPointer(offset);
|
||||
}
|
||||
|
||||
const void *QuadIndices::getIndices(size_t offset) const
|
||||
{
|
||||
return indices + offset;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void QuadIndices::fill()
|
||||
{
|
||||
GLBuffer::Bind bind(*indexBuffer);
|
||||
GLBuffer::Mapper mapper(*indexBuffer);
|
||||
|
||||
T *indices = (T *) mapper.get();
|
||||
T *inds = (T *) indices;
|
||||
|
||||
// 0----2
|
||||
// | / |
|
||||
@@ -369,14 +384,17 @@ void QuadIndices::fill()
|
||||
// 1----3
|
||||
for (size_t i = 0; i < maxSize; ++i)
|
||||
{
|
||||
indices[i*6+0] = T(i * 4 + 0);
|
||||
indices[i*6+1] = T(i * 4 + 1);
|
||||
indices[i*6+2] = T(i * 4 + 2);
|
||||
inds[i*6+0] = T(i * 4 + 0);
|
||||
inds[i*6+1] = T(i * 4 + 1);
|
||||
inds[i*6+2] = T(i * 4 + 2);
|
||||
|
||||
indices[i*6+3] = T(i * 4 + 2);
|
||||
indices[i*6+4] = T(i * 4 + 1);
|
||||
indices[i*6+5] = T(i * 4 + 3);
|
||||
inds[i*6+3] = T(i * 4 + 2);
|
||||
inds[i*6+4] = T(i * 4 + 1);
|
||||
inds[i*6+5] = T(i * 4 + 3);
|
||||
}
|
||||
|
||||
GLBuffer::Bind bind(*indexBuffer);
|
||||
indexBuffer->fill(0, indexBuffer->getSize(), indices);
|
||||
}
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -384,6 +384,20 @@ public:
|
||||
*/
|
||||
const void *getPointer(size_t offset) const;
|
||||
|
||||
/**
|
||||
* Returns a direct pointer to the index data.
|
||||
*
|
||||
* At least one graphics driver (the one for Kepler nvidia GPUs in OS X)
|
||||
* fails to render geometry if the vertex data was a direct CPU pointer but
|
||||
* the index data came from an Index Buffer.
|
||||
* So the direct pointer to the index buffer should be used instead of the
|
||||
* index buffer when rendering using client-side vertex arrays.
|
||||
*
|
||||
* @param offset An offset in bytes into the index data.
|
||||
* @return A direct pointer to the index data at the specified offset.
|
||||
**/
|
||||
const void *getIndices(size_t offset) const;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
@@ -406,6 +420,9 @@ private:
|
||||
|
||||
// The GLBuffer for the element array. Can be null.
|
||||
static GLBuffer *indexBuffer;
|
||||
|
||||
// The array of indices that will also be stored in the index buffer.
|
||||
static char *indices;
|
||||
};
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -106,7 +106,7 @@ void Graphics::restoreState(const DisplayState &s)
|
||||
setColor(s.color);
|
||||
setBackgroundColor(s.backgroundColor);
|
||||
|
||||
setBlendMode(s.blendMode, s.blendMultiplyAlpha);
|
||||
setBlendMode(s.blendMode, s.blendAlphaMode);
|
||||
|
||||
setLineWidth(s.lineWidth);
|
||||
setLineStyle(s.lineStyle);
|
||||
@@ -119,7 +119,7 @@ void Graphics::restoreState(const DisplayState &s)
|
||||
else
|
||||
setScissor();
|
||||
|
||||
setStencilTest(s.stencilTest, s.stencilInvert);
|
||||
setStencilTest(s.stencilCompare, s.stencilTestValue);
|
||||
|
||||
setFont(s.font.get());
|
||||
setShader(s.shader.get());
|
||||
@@ -141,8 +141,8 @@ void Graphics::restoreStateChecked(const DisplayState &s)
|
||||
|
||||
setBackgroundColor(s.backgroundColor);
|
||||
|
||||
if (s.blendMode != cur.blendMode || s.blendMultiplyAlpha != cur.blendMultiplyAlpha)
|
||||
setBlendMode(s.blendMode, s.blendMultiplyAlpha);
|
||||
if (s.blendMode != cur.blendMode || s.blendAlphaMode != cur.blendAlphaMode)
|
||||
setBlendMode(s.blendMode, s.blendAlphaMode);
|
||||
|
||||
// These are just simple assignments.
|
||||
setLineWidth(s.lineWidth);
|
||||
@@ -160,8 +160,8 @@ void Graphics::restoreStateChecked(const DisplayState &s)
|
||||
setScissor();
|
||||
}
|
||||
|
||||
if (s.stencilTest != cur.stencilTest || s.stencilInvert != cur.stencilInvert)
|
||||
setStencilTest(s.stencilTest, s.stencilInvert);
|
||||
if (s.stencilCompare != cur.stencilCompare || s.stencilTestValue != cur.stencilTestValue)
|
||||
setStencilTest(s.stencilCompare, s.stencilTestValue);
|
||||
|
||||
setFont(s.font.get());
|
||||
setShader(s.shader.get());
|
||||
@@ -433,7 +433,7 @@ void Graphics::setDebug(bool enable)
|
||||
void Graphics::reset()
|
||||
{
|
||||
DisplayState s;
|
||||
drawToStencilBuffer(false);
|
||||
stopDrawToStencilBuffer();
|
||||
restoreState(s);
|
||||
origin();
|
||||
}
|
||||
@@ -641,24 +641,9 @@ bool Graphics::getScissor(int &x, int &y, int &width, int &height) const
|
||||
return state.scissor;
|
||||
}
|
||||
|
||||
void Graphics::drawToStencilBuffer(bool enable)
|
||||
void Graphics::drawToStencilBuffer(StencilAction action, int value)
|
||||
{
|
||||
if (writingToStencil == enable)
|
||||
return;
|
||||
|
||||
writingToStencil = enable;
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
const DisplayState &state = states.back();
|
||||
|
||||
// Revert the color write mask.
|
||||
setColorMask(state.colorMask);
|
||||
|
||||
// Use the user-set stencil test state when writes are disabled.
|
||||
setStencilTest(state.stencilTest, state.stencilInvert);
|
||||
return;
|
||||
}
|
||||
writingToStencil = true;
|
||||
|
||||
// Make sure the active canvas has a stencil buffer.
|
||||
if (Canvas::current)
|
||||
@@ -667,23 +652,63 @@ void Graphics::drawToStencilBuffer(bool enable)
|
||||
// Disable color writes but don't save the state for it.
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
GLenum glaction = GL_REPLACE;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case STENCIL_REPLACE:
|
||||
default:
|
||||
glaction = GL_REPLACE;
|
||||
break;
|
||||
case STENCIL_INCREMENT:
|
||||
glaction = GL_INCR;
|
||||
break;
|
||||
case STENCIL_DECREMENT:
|
||||
glaction = GL_DECR;
|
||||
break;
|
||||
case STENCIL_INCREMENT_WRAP:
|
||||
glaction = GL_INCR_WRAP;
|
||||
break;
|
||||
case STENCIL_DECREMENT_WRAP:
|
||||
glaction = GL_DECR_WRAP;
|
||||
break;
|
||||
case STENCIL_INVERT:
|
||||
glaction = GL_INVERT;
|
||||
break;
|
||||
}
|
||||
|
||||
// The stencil test must be enabled in order to write to the stencil buffer.
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
glStencilFunc(GL_ALWAYS, 1, 1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
glStencilFunc(GL_ALWAYS, value, 0xFFFFFFFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, glaction);
|
||||
}
|
||||
|
||||
void Graphics::setStencilTest(bool enable, bool invert)
|
||||
void Graphics::stopDrawToStencilBuffer()
|
||||
{
|
||||
if (!writingToStencil)
|
||||
return;
|
||||
|
||||
writingToStencil = false;
|
||||
|
||||
const DisplayState &state = states.back();
|
||||
|
||||
// Revert the color write mask.
|
||||
setColorMask(state.colorMask);
|
||||
|
||||
// Use the user-set stencil test state when writes are disabled.
|
||||
setStencilTest(state.stencilCompare, state.stencilTestValue);
|
||||
}
|
||||
|
||||
void Graphics::setStencilTest(CompareMode compare, int value)
|
||||
{
|
||||
DisplayState &state = states.back();
|
||||
state.stencilTest = enable;
|
||||
state.stencilInvert = invert;
|
||||
state.stencilCompare = compare;
|
||||
state.stencilTestValue = value;
|
||||
|
||||
if (writingToStencil)
|
||||
return;
|
||||
|
||||
if (!enable)
|
||||
if (compare == COMPARE_ALWAYS)
|
||||
{
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
return;
|
||||
@@ -693,16 +718,61 @@ void Graphics::setStencilTest(bool enable, bool invert)
|
||||
if (Canvas::current)
|
||||
Canvas::current->checkCreateStencil();
|
||||
|
||||
GLenum glcompare = GL_EQUAL;
|
||||
|
||||
/**
|
||||
* Q: Why are some of the compare modes inverted (e.g. COMPARE_LESS becomes
|
||||
* GL_GREATER)?
|
||||
*
|
||||
* A: OpenGL / GPUs do the comparison in the opposite way that makes sense
|
||||
* for this API. For example, if the compare function is GL_GREATER then the
|
||||
* stencil test will pass if the reference value is greater than the value
|
||||
* in the stencil buffer. With our API it's more intuitive to assume that
|
||||
* setStencilTest(COMPARE_GREATER, 4) will make it pass if the stencil
|
||||
* buffer has a value greater than 4.
|
||||
**/
|
||||
|
||||
switch (compare)
|
||||
{
|
||||
case COMPARE_LESS:
|
||||
glcompare = GL_GREATER;
|
||||
break;
|
||||
case COMPARE_LEQUAL:
|
||||
glcompare = GL_GEQUAL;
|
||||
break;
|
||||
case COMPARE_EQUAL:
|
||||
default:
|
||||
glcompare = GL_EQUAL;
|
||||
break;
|
||||
case COMPARE_GEQUAL:
|
||||
glcompare = GL_LEQUAL;
|
||||
break;
|
||||
case COMPARE_GREATER:
|
||||
glcompare = GL_LESS;
|
||||
break;
|
||||
case COMPARE_NOTEQUAL:
|
||||
glcompare = GL_NOTEQUAL;
|
||||
break;
|
||||
case COMPARE_ALWAYS:
|
||||
glcompare = GL_ALWAYS;
|
||||
break;
|
||||
}
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_EQUAL, invert ? 0 : 1, 1);
|
||||
glStencilFunc(glcompare, value, 0xFFFFFFFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
}
|
||||
|
||||
void Graphics::getStencilTest(bool &enable, bool &invert)
|
||||
void Graphics::setStencilTest()
|
||||
{
|
||||
setStencilTest(COMPARE_ALWAYS, 0);
|
||||
}
|
||||
|
||||
void Graphics::getStencilTest(CompareMode &compare, int &value)
|
||||
{
|
||||
const DisplayState &state = states.back();
|
||||
enable = state.stencilTest;
|
||||
invert = state.stencilInvert;
|
||||
compare = state.stencilCompare;
|
||||
value = state.stencilTestValue;
|
||||
}
|
||||
|
||||
void Graphics::clearStencil()
|
||||
@@ -987,7 +1057,7 @@ Graphics::ColorMask Graphics::getColorMask() const
|
||||
return states.back().colorMask;
|
||||
}
|
||||
|
||||
void Graphics::setBlendMode(BlendMode mode, bool multiplyalpha)
|
||||
void Graphics::setBlendMode(BlendMode mode, BlendAlpha alphamode)
|
||||
{
|
||||
GLenum func = GL_FUNC_ADD;
|
||||
GLenum srcRGB = GL_ONE;
|
||||
@@ -1024,19 +1094,19 @@ void Graphics::setBlendMode(BlendMode mode, bool multiplyalpha)
|
||||
}
|
||||
|
||||
// We can only do alpha-multiplication when srcRGB would have been unmodified.
|
||||
if (srcRGB == GL_ONE && multiplyalpha)
|
||||
if (srcRGB == GL_ONE && alphamode == BLENDALPHA_MULTIPLY)
|
||||
srcRGB = GL_SRC_ALPHA;
|
||||
|
||||
glBlendEquation(func);
|
||||
glBlendFuncSeparate(srcRGB, dstRGB, srcA, dstA);
|
||||
|
||||
states.back().blendMode = mode;
|
||||
states.back().blendMultiplyAlpha = multiplyalpha;
|
||||
states.back().blendAlphaMode = alphamode;
|
||||
}
|
||||
|
||||
Graphics::BlendMode Graphics::getBlendMode(bool &multiplyalpha) const
|
||||
Graphics::BlendMode Graphics::getBlendMode(BlendAlpha &alphamode) const
|
||||
{
|
||||
multiplyalpha = states.back().blendMultiplyAlpha;
|
||||
alphamode = states.back().blendAlphaMode;
|
||||
return states.back().blendMode;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,13 +146,15 @@ public:
|
||||
* Enables or disables drawing to the stencil buffer. When enabled, the
|
||||
* color buffer is disabled.
|
||||
**/
|
||||
void drawToStencilBuffer(bool enable);
|
||||
void drawToStencilBuffer(StencilAction action, int value);
|
||||
void stopDrawToStencilBuffer();
|
||||
|
||||
/**
|
||||
* Sets whether stencil testing is enabled.
|
||||
**/
|
||||
void setStencilTest(bool enable, bool invert);
|
||||
void getStencilTest(bool &enable, bool &invert);
|
||||
void setStencilTest(CompareMode compare, int value);
|
||||
void setStencilTest();
|
||||
void getStencilTest(CompareMode &compare, int &value);
|
||||
|
||||
/**
|
||||
* Clear the stencil buffer in the active Canvas(es.)
|
||||
@@ -241,12 +243,12 @@ public:
|
||||
/**
|
||||
* Sets the current blend mode.
|
||||
**/
|
||||
void setBlendMode(BlendMode mode, bool multiplyalpha);
|
||||
void setBlendMode(BlendMode mode, BlendAlpha alphamode);
|
||||
|
||||
/**
|
||||
* Gets the current blend mode.
|
||||
**/
|
||||
BlendMode getBlendMode(bool &multiplyalpha) const;
|
||||
BlendMode getBlendMode(BlendAlpha &alphamode) const;
|
||||
|
||||
/**
|
||||
* Sets the default filter for images, canvases, and fonts.
|
||||
@@ -476,7 +478,7 @@ private:
|
||||
Colorf backgroundColor = Colorf(0.0, 0.0, 0.0, 255.0);
|
||||
|
||||
BlendMode blendMode = BLEND_ALPHA;
|
||||
bool blendMultiplyAlpha = true;
|
||||
BlendAlpha blendAlphaMode = BLENDALPHA_MULTIPLY;
|
||||
|
||||
float lineWidth = 1.0f;
|
||||
LineStyle lineStyle = LINE_SMOOTH;
|
||||
@@ -488,8 +490,8 @@ private:
|
||||
ScissorRect scissorRect = ScissorRect();
|
||||
|
||||
// Stencil.
|
||||
bool stencilTest = false;
|
||||
bool stencilInvert = false;
|
||||
CompareMode stencilCompare = COMPARE_ALWAYS;
|
||||
int stencilTestValue = 0;
|
||||
|
||||
StrongRef<Font> font;
|
||||
StrongRef<Shader> shader;
|
||||
|
||||
@@ -141,11 +141,14 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].x);
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].s);
|
||||
|
||||
{
|
||||
GLsizei count = (GLsizei) quadIndices.getIndexCount(pCount);
|
||||
GLBuffer::Bind ibo_bind(*quadIndices.getBuffer());
|
||||
gl.drawElements(GL_TRIANGLES, count, quadIndices.getType(), quadIndices.getPointer(0));
|
||||
}
|
||||
GLsizei count = (GLsizei) quadIndices.getIndexCount(pCount);
|
||||
GLenum gltype = quadIndices.getType();
|
||||
|
||||
// We use a client-side index array instead of an Index Buffers, because
|
||||
// at least one graphics driver (the one for Kepler nvidia GPUs in OS X
|
||||
// 10.11) fails to render geometry if an index buffer is used with
|
||||
// client-side vertex arrays.
|
||||
gl.drawElements(GL_TRIANGLES, count, gltype, quadIndices.getIndices(0));
|
||||
}
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -245,7 +245,7 @@ void Text::draw(float x, float y, float angle, float sx, float sy, float ox, flo
|
||||
|
||||
gl.useVertexAttribArrays(ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR);
|
||||
|
||||
font->drawVertices(draw_commands);
|
||||
font->drawVertices(draw_commands, true);
|
||||
}
|
||||
|
||||
void Text::setFont(Font *f)
|
||||
|
||||
@@ -79,23 +79,23 @@ bool Video::loadVolatile()
|
||||
// Create the textures using the initial frame data.
|
||||
auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
|
||||
|
||||
gl.bindTexture(textures[0]);
|
||||
gl.setTextureFilter(filter);
|
||||
int widths[3] = {frame->yw, frame->cw, frame->cw};
|
||||
int heights[3] = {frame->yh, frame->ch, frame->ch};
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frame->yw, frame->yh,
|
||||
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->yplane);
|
||||
const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
|
||||
|
||||
gl.bindTexture(textures[1]);
|
||||
gl.setTextureFilter(filter);
|
||||
Texture::Wrap wrap; // Clamp wrap mode.
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frame->cw, frame->ch,
|
||||
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->cbplane);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
gl.bindTexture(textures[i]);
|
||||
|
||||
gl.bindTexture(textures[2]);
|
||||
gl.setTextureFilter(filter);
|
||||
gl.setTextureFilter(filter);
|
||||
gl.setTextureWrap(wrap);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, frame->cw, frame->ch,
|
||||
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->crplane);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, widths[i], heights[i], 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, data[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -154,17 +154,17 @@ void Video::update()
|
||||
{
|
||||
auto frame = (const love::video::VideoStream::Frame*) stream->getFrontBuffer();
|
||||
|
||||
gl.bindTexture(textures[0]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame->yw, frame->yh,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->yplane);
|
||||
int widths[3] = {frame->yw, frame->cw, frame->cw};
|
||||
int heights[3] = {frame->yh, frame->ch, frame->ch};
|
||||
|
||||
gl.bindTexture(textures[1]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame->cw, frame->ch,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->cbplane);
|
||||
const unsigned char *data[3] = {frame->yplane, frame->cbplane, frame->crplane};
|
||||
|
||||
gl.bindTexture(textures[2]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame->cw, frame->ch,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->crplane);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
gl.bindTexture(textures[i]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widths[i], heights[i],
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -217,35 +217,63 @@ int w_stencil(lua_State *L)
|
||||
{
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
|
||||
// Second argument: whether to keep the contents of the stencil buffer.
|
||||
if (lua_toboolean(L, 2) == 0)
|
||||
Graphics::StencilAction action = Graphics::STENCIL_REPLACE;
|
||||
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
{
|
||||
const char *actionstr = luaL_checkstring(L, 2);
|
||||
if (!Graphics::getConstant(actionstr, action))
|
||||
return luaL_error(L, "Invalid stencil draw action: %s", actionstr);
|
||||
}
|
||||
|
||||
int stencilvalue = (int) luaL_optnumber(L, 3, 1);
|
||||
|
||||
// Fourth argument: whether to keep the contents of the stencil buffer.
|
||||
if (lua_toboolean(L, 4) == 0)
|
||||
instance()->clearStencil();
|
||||
|
||||
instance()->drawToStencilBuffer(true);
|
||||
instance()->drawToStencilBuffer(action, stencilvalue);
|
||||
|
||||
// Call stencilfunc()
|
||||
lua_pushvalue(L, 1);
|
||||
lua_call(L, 0, 0);
|
||||
|
||||
instance()->drawToStencilBuffer(false);
|
||||
|
||||
instance()->stopDrawToStencilBuffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_setStencilTest(lua_State *L)
|
||||
{
|
||||
bool enable = luax_toboolean(L, 1);
|
||||
bool invert = luax_toboolean(L, 2);
|
||||
instance()->setStencilTest(enable, invert);
|
||||
// COMPARE_ALWAYS effectively disables stencil testing.
|
||||
Graphics::CompareMode compare = Graphics::COMPARE_ALWAYS;
|
||||
int comparevalue = 0;
|
||||
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
{
|
||||
const char *comparestr = luaL_checkstring(L, 1);
|
||||
if (!Graphics::getConstant(comparestr, compare))
|
||||
return luaL_error(L, "Invalid compare mode: %s", comparestr);
|
||||
|
||||
comparevalue = (int) luaL_checknumber(L, 2);
|
||||
}
|
||||
|
||||
instance()->setStencilTest(compare, comparevalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_getStencilTest(lua_State *L)
|
||||
{
|
||||
bool enabled, inverted;
|
||||
instance()->getStencilTest(enabled, inverted);
|
||||
luax_pushboolean(L, enabled);
|
||||
luax_pushboolean(L, inverted);
|
||||
Graphics::CompareMode compare = Graphics::COMPARE_ALWAYS;
|
||||
int comparevalue = 1;
|
||||
|
||||
instance()->getStencilTest(compare, comparevalue);
|
||||
|
||||
const char *comparestr;
|
||||
if (!Graphics::getConstant(compare, comparestr))
|
||||
return luaL_error(L, "Unknown compare mode.");
|
||||
|
||||
lua_pushstring(L, comparestr);
|
||||
lua_pushnumber(L, comparevalue);
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -1014,25 +1042,34 @@ int w_setBlendMode(lua_State *L)
|
||||
if (!Graphics::getConstant(str, mode))
|
||||
return luaL_error(L, "Invalid blend mode: %s", str);
|
||||
|
||||
bool multiplyalpha = luax_optboolean(L, 2, true);
|
||||
Graphics::BlendAlpha alphamode = Graphics::BLENDALPHA_MULTIPLY;
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
{
|
||||
const char *alphastr = luaL_checkstring(L, 2);
|
||||
if (!Graphics::getConstant(alphastr, alphamode))
|
||||
return luaL_error(L, "Invalid blend alpha mode: %s", alphastr);
|
||||
}
|
||||
|
||||
luax_catchexcept(L, [&](){ instance()->setBlendMode(mode, multiplyalpha); });
|
||||
luax_catchexcept(L, [&](){ instance()->setBlendMode(mode, alphamode); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_getBlendMode(lua_State *L)
|
||||
{
|
||||
const char *str;
|
||||
Graphics::BlendMode mode;
|
||||
bool multiplyalpha = false;
|
||||
const char *alphastr;
|
||||
|
||||
luax_catchexcept(L, [&](){ mode = instance()->getBlendMode(multiplyalpha); });
|
||||
Graphics::BlendAlpha alphamode;
|
||||
Graphics::BlendMode mode = instance()->getBlendMode(alphamode);
|
||||
|
||||
if (!Graphics::getConstant(mode, str))
|
||||
return luaL_error(L, "Unknown blend mode");
|
||||
|
||||
if (!Graphics::getConstant(alphamode, alphastr))
|
||||
return luaL_error(L, "Unknown blend alpha mode");
|
||||
|
||||
lua_pushstring(L, str);
|
||||
lua_pushboolean(L, multiplyalpha);
|
||||
lua_pushstring(L, alphastr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -1201,7 +1238,7 @@ int w_newScreenshot(lua_State *L)
|
||||
int w_setCanvas(lua_State *L)
|
||||
{
|
||||
// Disable stencil writes.
|
||||
instance()->drawToStencilBuffer(false);
|
||||
instance()->stopDrawToStencilBuffer();
|
||||
|
||||
// called with none -> reset to default buffer
|
||||
if (lua_isnoneornil(L, 1))
|
||||
|
||||
@@ -366,7 +366,7 @@ function love.graphics.newVideo(file, loadaudio)
|
||||
elseif loadaudio == true then
|
||||
error("Video had no audio track", 2)
|
||||
else
|
||||
video:getStream():setSync(love.video.newRemote())
|
||||
video:getStream():setSync()
|
||||
end
|
||||
|
||||
return video
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
// C++
|
||||
#include <typeinfo>
|
||||
#include <algorithm>
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -108,12 +109,28 @@ const char *luax_readAttributeData(lua_State *L, Mesh::DataType type, int compon
|
||||
int w_Mesh_setVertices(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
size_t vertoffset = (size_t) luaL_optnumber(L, 3, 1) - 1;
|
||||
|
||||
if (vertoffset >= t->getVertexCount())
|
||||
return luaL_error(L, "Invalid vertex start index (must be between 1 and %d)", (int) t->getVertexCount());
|
||||
|
||||
size_t stride = t->getVertexStride();
|
||||
size_t byteoffset = vertoffset * stride;
|
||||
|
||||
if (luax_istype(L, 2, DATA_ID))
|
||||
{
|
||||
Data *d = luax_checktype<Data>(L, 2, DATA_ID);
|
||||
|
||||
size_t datasize = std::min(d->getSize(), (t->getVertexCount() - vertoffset) * stride);
|
||||
char *bytedata = (char *) t->mapVertexData() + byteoffset;
|
||||
|
||||
memcpy(bytedata, d->getData(), datasize);
|
||||
|
||||
t->unmapVertexData(byteoffset, datasize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
size_t nvertices = luax_objlen(L, 2);
|
||||
|
||||
if (vertoffset + nvertices > t->getVertexCount())
|
||||
@@ -125,9 +142,6 @@ int w_Mesh_setVertices(lua_State *L)
|
||||
for (const Mesh::AttribFormat &format : vertexformat)
|
||||
ncomponents += format.components;
|
||||
|
||||
size_t stride = t->getVertexStride();
|
||||
size_t byteoffset = vertoffset * stride;
|
||||
|
||||
char *data = (char *) t->mapVertexData() + byteoffset;
|
||||
|
||||
for (size_t i = 0; i < nvertices; i++)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#define LOVE_GRAPHICS_OPENGL_WRAP_MESH_H
|
||||
|
||||
// LOVE
|
||||
#include "common/config.h"
|
||||
#include "common/runtime.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
|
||||
@@ -25,20 +25,9 @@ misrepresented as being the original software.
|
||||
local Video_mt = ...
|
||||
local Video = Video_mt.__index
|
||||
|
||||
function Video:loadRemote()
|
||||
local stream = self:getStream()
|
||||
local remote = love.video.newRemote()
|
||||
stream:setSync(remote)
|
||||
return remote
|
||||
end
|
||||
|
||||
function Video:setSource(source)
|
||||
self:_setSource(source)
|
||||
if source then
|
||||
self:getStream():setSync(source)
|
||||
else
|
||||
self:getStream():setSync(love.video.newRemote())
|
||||
end
|
||||
self:getStream():setSync(source)
|
||||
end
|
||||
|
||||
function Video:play()
|
||||
|
||||
@@ -55,56 +55,9 @@ public:
|
||||
|
||||
virtual ~Math();
|
||||
|
||||
/**
|
||||
* @copydoc RandomGenerator::random()
|
||||
**/
|
||||
inline double random()
|
||||
RandomGenerator *getRandomGenerator()
|
||||
{
|
||||
return rng.random();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc RandomGenerator::random(double)
|
||||
**/
|
||||
inline double random(double max)
|
||||
{
|
||||
return rng.random(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc RandomGenerator::random(double,double)
|
||||
**/
|
||||
inline double random(double min, double max)
|
||||
{
|
||||
return rng.random(min, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc RandomGenerator::randomNormal()
|
||||
**/
|
||||
inline double randomNormal(double stddev)
|
||||
{
|
||||
return rng.randomNormal(stddev);
|
||||
}
|
||||
|
||||
inline void setRandomSeed(RandomGenerator::Seed seed)
|
||||
{
|
||||
rng.setSeed(seed);
|
||||
}
|
||||
|
||||
inline RandomGenerator::Seed getRandomSeed() const
|
||||
{
|
||||
return rng.getSeed();
|
||||
}
|
||||
|
||||
inline void setRandomState(const std::string &statestr)
|
||||
{
|
||||
rng.setState(statestr);
|
||||
}
|
||||
|
||||
inline std::string getRandomState() const
|
||||
{
|
||||
return rng.getState();
|
||||
return &rng;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,44 +39,10 @@ namespace love
|
||||
namespace math
|
||||
{
|
||||
|
||||
int w_random(lua_State *L)
|
||||
int w__getRandomGenerator(lua_State *L)
|
||||
{
|
||||
return luax_getrandom(L, 1, Math::instance.random());
|
||||
}
|
||||
|
||||
int w_randomNormal(lua_State *L)
|
||||
{
|
||||
double stddev = luaL_optnumber(L, 1, 1.0);
|
||||
double mean = luaL_optnumber(L, 2, 0.0);
|
||||
double r = Math::instance.randomNormal(stddev);
|
||||
|
||||
lua_pushnumber(L, r + mean);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_setRandomSeed(lua_State *L)
|
||||
{
|
||||
luax_catchexcept(L, [&](){ Math::instance.setRandomSeed(luax_checkrandomseed(L, 1)); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_getRandomSeed(lua_State *L)
|
||||
{
|
||||
RandomGenerator::Seed s = Math::instance.getRandomSeed();
|
||||
lua_pushnumber(L, (lua_Number) s.b32.low);
|
||||
lua_pushnumber(L, (lua_Number) s.b32.high);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_setRandomState(lua_State *L)
|
||||
{
|
||||
luax_catchexcept(L, [&](){ Math::instance.setRandomState(luax_checkstring(L, 1)); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_getRandomState(lua_State *L)
|
||||
{
|
||||
luax_pushstring(L, Math::instance.getRandomState());
|
||||
RandomGenerator *t = Math::instance.getRandomGenerator();
|
||||
luax_pushtype(L, MATH_RANDOM_GENERATOR_ID, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -463,12 +429,9 @@ static FFI_Math ffifuncs =
|
||||
// List of functions to wrap.
|
||||
static const luaL_Reg functions[] =
|
||||
{
|
||||
{ "random", w_random },
|
||||
{ "randomNormal", w_randomNormal },
|
||||
{ "setRandomSeed", w_setRandomSeed },
|
||||
{ "getRandomSeed", w_getRandomSeed },
|
||||
{ "setRandomState", w_setRandomState },
|
||||
{ "getRandomState", w_getRandomState },
|
||||
// love.math.random etc. are defined in wrap_Math.lua.
|
||||
|
||||
{ "_getRandomGenerator", w__getRandomGenerator },
|
||||
{ "newRandomGenerator", w_newRandomGenerator },
|
||||
{ "newBezierCurve", w_newBezierCurve },
|
||||
{ "triangulate", w_triangulate },
|
||||
@@ -502,7 +465,7 @@ extern "C" int luaopen_love_math(lua_State *L)
|
||||
|
||||
int n = luax_register_module(L, w);
|
||||
|
||||
// Execute wrap_Event.lua, sending the math table and ffifuncs pointer as args.
|
||||
// Execute wrap_Math.lua, sending the math table and ffifuncs pointer as args.
|
||||
luaL_loadbuffer(L, math_lua, sizeof(math_lua), "wrap_Math.lua");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_pushlightuserdata(L, &ffifuncs);
|
||||
|
||||
@@ -22,7 +22,36 @@ misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
--]]
|
||||
|
||||
local math, ffifuncspointer = ...
|
||||
local love_math, ffifuncspointer = ...
|
||||
|
||||
local type, tonumber, error = type, tonumber, error
|
||||
local floor = math.floor
|
||||
|
||||
local rng = love_math._getRandomGenerator()
|
||||
|
||||
function love_math.random(l, u)
|
||||
return rng:random(l, u)
|
||||
end
|
||||
|
||||
function love_math.randomNormal(stddev, mean)
|
||||
return rng:randomNormal(stddev, mean)
|
||||
end
|
||||
|
||||
function love_math.setRandomSeed(low, high)
|
||||
return rng:setSeed(low, high)
|
||||
end
|
||||
|
||||
function love_math.getRandomSeed()
|
||||
return rng:getSeed()
|
||||
end
|
||||
|
||||
function love_math.setRandomState(state)
|
||||
return rng:setState(state)
|
||||
end
|
||||
|
||||
function love_math.getRandomState()
|
||||
return rng:getState()
|
||||
end
|
||||
|
||||
if type(jit) ~= "table" or not jit.status() then
|
||||
-- LuaJIT's FFI is *much* slower than LOVE's regular methods when the JIT
|
||||
@@ -33,8 +62,6 @@ end
|
||||
local status, ffi = pcall(require, "ffi")
|
||||
if not status then return end
|
||||
|
||||
local type, tonumber = type, tonumber
|
||||
|
||||
-- Matches the struct declaration in wrap_Math.cpp.
|
||||
pcall(ffi.cdef, [[
|
||||
typedef struct FFI_Math
|
||||
@@ -54,7 +81,7 @@ local ffifuncs = ffi.cast("FFI_Math *", ffifuncspointer)
|
||||
|
||||
-- Overwrite some regular love.math functions with FFI implementations.
|
||||
|
||||
function math.noise(x, y, z, w)
|
||||
function love_math.noise(x, y, z, w)
|
||||
if w ~= nil then
|
||||
return tonumber(ffifuncs.noise4(x, y, z, w))
|
||||
elseif z ~= nil then
|
||||
@@ -73,7 +100,7 @@ local function gammaToLinear(c)
|
||||
return c
|
||||
end
|
||||
|
||||
function math.gammaToLinear(r, g, b, a)
|
||||
function love_math.gammaToLinear(r, g, b, a)
|
||||
if type(r) == "table" then
|
||||
local t = r
|
||||
return gammaToLinear(t[1]), gammaToLinear(t[2]), gammaToLinear(t[3]), t[4]
|
||||
@@ -88,7 +115,7 @@ local function linearToGamma(c)
|
||||
return c
|
||||
end
|
||||
|
||||
function math.linearToGamma(r, g, b, a)
|
||||
function love_math.linearToGamma(r, g, b, a)
|
||||
if type(r) == "table" then
|
||||
local t = r
|
||||
return linearToGamma(t[1]), linearToGamma(t[2]), linearToGamma(t[3]), t[4]
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
// Put the Lua code directly into a raw string literal.
|
||||
static const char randomgenerator_lua[] =
|
||||
#include "wrap_RandomGenerator.lua"
|
||||
;
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace math
|
||||
@@ -56,41 +61,16 @@ RandomGenerator::Seed luax_checkrandomseed(lua_State *L, int idx)
|
||||
return s;
|
||||
}
|
||||
|
||||
int luax_getrandom(lua_State *L, int startidx, double r)
|
||||
{
|
||||
int l, u;
|
||||
// from lua 5.1.4 source code: lmathlib.c:185 ff.
|
||||
switch (lua_gettop(L) - (startidx - 1))
|
||||
{
|
||||
case 0:
|
||||
lua_pushnumber(L, r);
|
||||
break;
|
||||
case 1:
|
||||
u = (int) luaL_checknumber(L, startidx);
|
||||
luaL_argcheck(L, 1 <= u, startidx, "interval is empty");
|
||||
lua_pushnumber(L, floor(r * u) + 1);
|
||||
break;
|
||||
case 2:
|
||||
l = (int) luaL_checknumber(L, startidx);
|
||||
u = (int) luaL_checknumber(L, startidx + 1);
|
||||
luaL_argcheck(L, l <= u, startidx + 1, "interval is empty");
|
||||
lua_pushnumber(L, floor(r * (u - l + 1)) + l);
|
||||
break;
|
||||
default:
|
||||
return luaL_error(L, "wrong number of arguments");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
RandomGenerator *luax_checkrandomgenerator(lua_State *L, int idx)
|
||||
{
|
||||
return luax_checktype<RandomGenerator>(L, idx, MATH_RANDOM_GENERATOR_ID);
|
||||
}
|
||||
|
||||
int w_RandomGenerator_random(lua_State *L)
|
||||
int w_RandomGenerator__random(lua_State *L)
|
||||
{
|
||||
RandomGenerator *rng = luax_checkrandomgenerator(L, 1);
|
||||
return luax_getrandom(L, 2, rng->random());
|
||||
lua_pushnumber(L, rng->random());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_RandomGenerator_randomNormal(lua_State *L)
|
||||
@@ -135,9 +115,28 @@ int w_RandomGenerator_getState(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// C functions in a struct, necessary for the FFI versions of RandomGenerator functions.
|
||||
struct FFI_RandomGenerator
|
||||
{
|
||||
double (*random)(Proxy *p);
|
||||
};
|
||||
|
||||
static FFI_RandomGenerator ffifuncs =
|
||||
{
|
||||
[](Proxy *p) -> double // random()
|
||||
{
|
||||
// FIXME: We need better type-checking...
|
||||
if (!typeFlags[p->type][MATH_RANDOM_GENERATOR_ID])
|
||||
return 0.0;
|
||||
|
||||
RandomGenerator *rng = (RandomGenerator *) p->object;
|
||||
return rng->random();
|
||||
}
|
||||
};
|
||||
|
||||
static const luaL_Reg w_RandomGenerator_functions[] =
|
||||
{
|
||||
{ "random", w_RandomGenerator_random },
|
||||
{ "_random", w_RandomGenerator__random }, // random() is defined in wrap_RandomGenerator.lua.
|
||||
{ "randomNormal", w_RandomGenerator_randomNormal },
|
||||
{ "setSeed", w_RandomGenerator_setSeed },
|
||||
{ "getSeed", w_RandomGenerator_getSeed },
|
||||
@@ -148,7 +147,24 @@ static const luaL_Reg w_RandomGenerator_functions[] =
|
||||
|
||||
extern "C" int luaopen_randomgenerator(lua_State *L)
|
||||
{
|
||||
return luax_register_type(L, MATH_RANDOM_GENERATOR_ID, "RandomGenerator", w_RandomGenerator_functions, nullptr);
|
||||
int n = luax_register_type(L, MATH_RANDOM_GENERATOR_ID, "RandomGenerator", w_RandomGenerator_functions, nullptr);
|
||||
|
||||
luax_gettypemetatable(L, MATH_RANDOM_GENERATOR_ID);
|
||||
|
||||
// Load and execute wrap_RandomGenerator.lua, sending the metatable and the
|
||||
// ffi functions struct pointer as arguments.
|
||||
if (lua_istable(L, -1))
|
||||
{
|
||||
luaL_loadbuffer(L, randomgenerator_lua, sizeof(randomgenerator_lua), "wrap_RandomGenerator.lua");
|
||||
lua_pushvalue(L, -2);
|
||||
lua_pushlightuserdata(L, &ffifuncs);
|
||||
lua_call(L, 2, 0);
|
||||
}
|
||||
|
||||
// Pop the metatable.
|
||||
lua_pop(L, 1);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
} // math
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace math
|
||||
|
||||
// Helper functions.
|
||||
RandomGenerator::Seed luax_checkrandomseed(lua_State *L, int idx);
|
||||
int luax_getrandom(lua_State *L, int startidx, double r);
|
||||
|
||||
RandomGenerator *luax_checkrandomgenerator(lua_State *L, int idx);
|
||||
extern "C" int luaopen_randomgenerator(lua_State *L);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
R"luastring"--(
|
||||
-- DO NOT REMOVE THE ABOVE LINE. It is used to load this file as a C++ string.
|
||||
-- There is a matching delimiter at the bottom of the file.
|
||||
|
||||
--[[
|
||||
Copyright (c) 2006-2015 LOVE Development Team
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
--]]
|
||||
|
||||
local RandomGenerator_mt, ffifuncspointer = ...
|
||||
local RandomGenerator = RandomGenerator_mt.__index
|
||||
|
||||
local type, tonumber, error = type, tonumber, error
|
||||
local floor = math.floor
|
||||
|
||||
local _random = RandomGenerator._random
|
||||
|
||||
local function getrandom(r, l, u)
|
||||
if u ~= nil then
|
||||
if type(r) ~= "number" then error("bad argument #1 to 'random' (number expected)", 2) end
|
||||
if type(l) ~= "number" then error("bad argument #2 to 'random' (number expected)", 2) end
|
||||
return floor(r * (u - l + 1)) + l
|
||||
elseif l ~= nil then
|
||||
if type(l) ~= "number" then error("bad argument #1 to 'random' (number expected)", 2) end
|
||||
return floor(r * l) + 1
|
||||
else
|
||||
return r
|
||||
end
|
||||
end
|
||||
|
||||
function RandomGenerator:random(l, u)
|
||||
local r = _random(self)
|
||||
return getrandom(r, l, u)
|
||||
end
|
||||
|
||||
if type(jit) ~= "table" or not jit.status() then
|
||||
-- LuaJIT's FFI is *much* slower than LOVE's regular methods when the JIT
|
||||
-- compiler is disabled.
|
||||
return
|
||||
end
|
||||
|
||||
local status, ffi = pcall(require, "ffi")
|
||||
if not status then return end
|
||||
|
||||
pcall(ffi.cdef, [[
|
||||
typedef struct Proxy Proxy;
|
||||
|
||||
typedef struct FFI_RandomGenerator
|
||||
{
|
||||
double (*random)(Proxy *p);
|
||||
} FFI_RandomGenerator;
|
||||
]])
|
||||
|
||||
local ffifuncs = ffi.cast("FFI_RandomGenerator *", ffifuncspointer)
|
||||
|
||||
|
||||
-- Overwrite some regular love.math functions with FFI implementations.
|
||||
|
||||
function RandomGenerator:random(l, u)
|
||||
local r = tonumber(ffifuncs.random(self))
|
||||
return getrandom(r, l, u)
|
||||
end
|
||||
|
||||
-- DO NOT REMOVE THE NEXT LINE. It is used to load this file as a C++ string.
|
||||
--)luastring"--"
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "Decoder.h"
|
||||
|
||||
// libmodplug
|
||||
#ifdef LOVE_ANDROID
|
||||
#if defined(LOVE_ANDROID) || defined(LOVE_IOS)
|
||||
#include <modplug.h>
|
||||
#else
|
||||
#include <libmodplug/modplug.h>
|
||||
|
||||
@@ -90,7 +90,7 @@ void Window::setGLFramebufferAttributes(int msaa, bool sRGB)
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (msaa > 0) ? 1 : 0);
|
||||
@@ -122,9 +122,9 @@ void Window::setGLContextAttributes(const ContextAttribs &attribs)
|
||||
int contextflags = 0;
|
||||
|
||||
if (attribs.gles)
|
||||
profilemask |= SDL_GL_CONTEXT_PROFILE_ES;
|
||||
profilemask = SDL_GL_CONTEXT_PROFILE_ES;
|
||||
else if (attribs.debug)
|
||||
profilemask |= SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
profilemask = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
|
||||
if (attribs.debug)
|
||||
contextflags |= SDL_GL_CONTEXT_DEBUG_FLAG;
|
||||
@@ -237,21 +237,24 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
|
||||
if (preferGLES)
|
||||
std::rotate(attribslist.begin(), attribslist.begin() + 1, attribslist.end());
|
||||
|
||||
if (context)
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
std::string windowerror;
|
||||
std::string contexterror;
|
||||
std::string glversion;
|
||||
|
||||
// Try each context profile in order.
|
||||
for (ContextAttribs attribs : attribslist)
|
||||
// Unfortunately some OpenGL context settings are part of the internal
|
||||
// window state in the Windows and Linux SDL backends, so we have to
|
||||
// recreate the window when we want to change those settings...
|
||||
// Also, apparently some Intel drivers on Windows give back a Microsoft
|
||||
// OpenGL 1.1 software renderer context when high MSAA values are requested!
|
||||
|
||||
const auto create = [&](ContextAttribs attribs) -> bool
|
||||
{
|
||||
// Unfortunately some OpenGL context settings are part of the internal
|
||||
// window state in the Windows and Linux SDL backends, so we have to
|
||||
// recreate the window when we want to change those settings...
|
||||
if (context)
|
||||
{
|
||||
SDL_GL_DeleteContext(context);
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
SDL_DestroyWindow(window);
|
||||
@@ -259,81 +262,18 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
|
||||
window = nullptr;
|
||||
}
|
||||
|
||||
int curMSAA = msaa;
|
||||
bool curSRGB = love::graphics::isGammaCorrect();
|
||||
|
||||
setGLFramebufferAttributes(curMSAA, curSRGB);
|
||||
setGLContextAttributes(attribs);
|
||||
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
|
||||
if (!window && curMSAA > 0)
|
||||
{
|
||||
// The MSAA setting could have caused the failure.
|
||||
setGLFramebufferAttributes(0, curSRGB);
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
if (window)
|
||||
curMSAA = 0;
|
||||
}
|
||||
|
||||
if (!window && curSRGB)
|
||||
{
|
||||
// same with sRGB.
|
||||
setGLFramebufferAttributes(curMSAA, false);
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
if (window)
|
||||
curSRGB = false;
|
||||
}
|
||||
|
||||
if (!window && curMSAA > 0 && curSRGB)
|
||||
{
|
||||
// Or both!
|
||||
setGLFramebufferAttributes(0, false);
|
||||
window = SDL_CreateWindow(title.c_str(), x, y, w, h, windowflags);
|
||||
if (window)
|
||||
{
|
||||
curMSAA = 0;
|
||||
curSRGB = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Immediately try the next context profile if window creation failed.
|
||||
if (!window)
|
||||
{
|
||||
windowerror = std::string(SDL_GetError());
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
windowerror.clear();
|
||||
|
||||
context = SDL_GL_CreateContext(window);
|
||||
|
||||
if (!context && curMSAA > 0)
|
||||
{
|
||||
// MSAA and sRGB settings can also cause CreateContext to fail, on
|
||||
// certain SDL backends.
|
||||
setGLFramebufferAttributes(0, curSRGB);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context && curSRGB)
|
||||
{
|
||||
setGLFramebufferAttributes(curMSAA, false);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context && curMSAA > 0 && curSRGB)
|
||||
{
|
||||
setGLFramebufferAttributes(0, false);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
if (!context && attribs.debug)
|
||||
{
|
||||
attribs.debug = false;
|
||||
setGLContextAttributes(attribs);
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
if (!context)
|
||||
contexterror = std::string(SDL_GetError());
|
||||
|
||||
// Make sure the context's version is at least what we requested.
|
||||
if (context && !checkGLVersion(attribs, glversion))
|
||||
@@ -342,7 +282,58 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
if (context)
|
||||
if (!context)
|
||||
{
|
||||
SDL_DestroyWindow(window);
|
||||
window = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// Try each context profile in order.
|
||||
for (ContextAttribs attribs : attribslist)
|
||||
{
|
||||
int curMSAA = msaa;
|
||||
bool curSRGB = love::graphics::isGammaCorrect();
|
||||
|
||||
setGLFramebufferAttributes(curMSAA, curSRGB);
|
||||
setGLContextAttributes(attribs);
|
||||
|
||||
windowerror.clear();
|
||||
contexterror.clear();
|
||||
|
||||
create(attribs);
|
||||
|
||||
if (!window && curMSAA > 0)
|
||||
{
|
||||
// The MSAA setting could have caused the failure.
|
||||
setGLFramebufferAttributes(0, curSRGB);
|
||||
if (create(attribs))
|
||||
curMSAA = 0;
|
||||
}
|
||||
|
||||
if (!window && curSRGB)
|
||||
{
|
||||
// same with sRGB.
|
||||
setGLFramebufferAttributes(curMSAA, false);
|
||||
if (create(attribs))
|
||||
curSRGB = false;
|
||||
}
|
||||
|
||||
if (!window && curMSAA > 0 && curSRGB)
|
||||
{
|
||||
// Or both!
|
||||
setGLFramebufferAttributes(0, false);
|
||||
if (create(attribs))
|
||||
{
|
||||
curMSAA = 0;
|
||||
curSRGB = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (window && context)
|
||||
{
|
||||
love::graphics::setGammaCorrect(curSRGB);
|
||||
break;
|
||||
@@ -370,6 +361,8 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
|
||||
std::string title = "Unable to initialize OpenGL";
|
||||
std::string message = "This program requires a graphics card and video drivers which support OpenGL 2.1 or OpenGL ES 2.";
|
||||
|
||||
if (!contexterror.empty())
|
||||
message += "\n\nOpenGL context creation error: " + contexterror;
|
||||
if (!glversion.empty())
|
||||
message += " \n\nDetected OpenGL version: " + glversion;
|
||||
|
||||
@@ -478,7 +471,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
||||
return false;
|
||||
|
||||
// Make sure the window keeps any previously set icon.
|
||||
setIcon(curMode.icon.get());
|
||||
setIcon(icon.get());
|
||||
|
||||
// Make sure the mouse keeps its previous grab setting.
|
||||
setMouseGrab(mouseGrabbed);
|
||||
@@ -497,7 +490,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
|
||||
|
||||
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
gfx->setMode(curMode.pixelwidth, curMode.pixelheight);
|
||||
gfx->setMode(pixelWidth, pixelHeight);
|
||||
|
||||
#ifdef LOVE_ANDROID
|
||||
love::android::setImmersive(f.fullscreen);
|
||||
@@ -511,14 +504,14 @@ bool Window::onSizeChanged(int width, int height)
|
||||
if (!window)
|
||||
return false;
|
||||
|
||||
curMode.width = width;
|
||||
curMode.height = height;
|
||||
windowWidth = width;
|
||||
windowHeight = height;
|
||||
|
||||
SDL_GL_GetDrawableSize(window, &curMode.pixelwidth, &curMode.pixelheight);
|
||||
SDL_GL_GetDrawableSize(window, &pixelWidth, &pixelHeight);
|
||||
|
||||
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
gfx->setViewportSize(curMode.pixelwidth, curMode.pixelheight);
|
||||
gfx->setViewportSize(pixelWidth, pixelHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -528,49 +521,43 @@ void Window::updateSettings(const WindowSettings &newsettings)
|
||||
Uint32 wflags = SDL_GetWindowFlags(window);
|
||||
|
||||
// Set the new display mode as the current display mode.
|
||||
SDL_GetWindowSize(window, &curMode.width, &curMode.height);
|
||||
SDL_GL_GetDrawableSize(window, &curMode.pixelwidth, &curMode.pixelheight);
|
||||
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
|
||||
SDL_GL_GetDrawableSize(window, &pixelWidth, &pixelHeight);
|
||||
|
||||
if ((wflags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)
|
||||
{
|
||||
curMode.settings.fullscreen = true;
|
||||
curMode.settings.fstype = FULLSCREEN_DESKTOP;
|
||||
settings.fullscreen = true;
|
||||
settings.fstype = FULLSCREEN_DESKTOP;
|
||||
}
|
||||
else if ((wflags & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN)
|
||||
{
|
||||
curMode.settings.fullscreen = true;
|
||||
curMode.settings.fstype = FULLSCREEN_EXCLUSIVE;
|
||||
settings.fullscreen = true;
|
||||
settings.fstype = FULLSCREEN_EXCLUSIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
curMode.settings.fullscreen = false;
|
||||
curMode.settings.fstype = newsettings.fstype;
|
||||
settings.fullscreen = false;
|
||||
settings.fstype = newsettings.fstype;
|
||||
}
|
||||
|
||||
#ifdef LOVE_ANDROID
|
||||
curMode.settings.fullscreen = love::android::getImmersive();
|
||||
settings.fullscreen = love::android::getImmersive();
|
||||
#endif
|
||||
|
||||
// The min width/height is set to 0 internally in SDL when in fullscreen.
|
||||
if (curMode.settings.fullscreen)
|
||||
{
|
||||
curMode.settings.minwidth = newsettings.minwidth;
|
||||
curMode.settings.minheight = newsettings.minheight;
|
||||
}
|
||||
else
|
||||
SDL_GetWindowMinimumSize(window, &curMode.settings.minwidth, &curMode.settings.minheight);
|
||||
// SDL_GetWindowMinimumSize gives back 0,0 sometimes...
|
||||
settings.minwidth = newsettings.minwidth;
|
||||
settings.minheight = newsettings.minheight;
|
||||
|
||||
curMode.settings.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0;
|
||||
curMode.settings.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0;
|
||||
curMode.settings.centered = newsettings.centered;
|
||||
settings.resizable = (wflags & SDL_WINDOW_RESIZABLE) != 0;
|
||||
settings.borderless = (wflags & SDL_WINDOW_BORDERLESS) != 0;
|
||||
settings.centered = newsettings.centered;
|
||||
|
||||
getPosition(curMode.settings.x, curMode.settings.y, curMode.settings.display);
|
||||
getPosition(settings.x, settings.y, settings.display);
|
||||
|
||||
curMode.settings.highdpi = (wflags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
settings.highdpi = (wflags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
|
||||
// Only minimize on focus loss if the window is in exclusive-fullscreen
|
||||
// mode.
|
||||
if (curMode.settings.fullscreen && curMode.settings.fstype == FULLSCREEN_EXCLUSIVE)
|
||||
// Only minimize on focus loss if the window is in exclusive-fullscreen mode
|
||||
if (settings.fullscreen && settings.fstype == FULLSCREEN_EXCLUSIVE)
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1");
|
||||
else
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||
@@ -581,25 +568,25 @@ void Window::updateSettings(const WindowSettings &newsettings)
|
||||
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &buffers);
|
||||
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
|
||||
|
||||
curMode.settings.msaa = (buffers > 0 ? samples : 0);
|
||||
curMode.settings.vsync = SDL_GL_GetSwapInterval() != 0;
|
||||
settings.msaa = (buffers > 0 ? samples : 0);
|
||||
settings.vsync = SDL_GL_GetSwapInterval() != 0;
|
||||
|
||||
SDL_DisplayMode dmode = {};
|
||||
SDL_GetCurrentDisplayMode(curMode.settings.display, &dmode);
|
||||
SDL_GetCurrentDisplayMode(settings.display, &dmode);
|
||||
|
||||
// May be 0 if the refresh rate can't be determined.
|
||||
curMode.settings.refreshrate = (double) dmode.refresh_rate;
|
||||
settings.refreshrate = (double) dmode.refresh_rate;
|
||||
}
|
||||
|
||||
void Window::getWindow(int &width, int &height, WindowSettings &settings)
|
||||
void Window::getWindow(int &width, int &height, WindowSettings &newsettings)
|
||||
{
|
||||
// The window might have been modified (moved, resized, etc.) by the user.
|
||||
if (window)
|
||||
updateSettings(curMode.settings);
|
||||
updateSettings(settings);
|
||||
|
||||
width = curMode.width;
|
||||
height = curMode.height;
|
||||
settings = curMode.settings;
|
||||
width = windowWidth;
|
||||
height = windowHeight;
|
||||
newsettings = settings;
|
||||
}
|
||||
|
||||
void Window::close()
|
||||
@@ -632,7 +619,7 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
|
||||
if (!window)
|
||||
return false;
|
||||
|
||||
WindowSettings newsettings = curMode.settings;
|
||||
WindowSettings newsettings = settings;
|
||||
newsettings.fullscreen = fullscreen;
|
||||
newsettings.fstype = fstype;
|
||||
|
||||
@@ -647,8 +634,8 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
|
||||
sdlflags = SDL_WINDOW_FULLSCREEN;
|
||||
|
||||
SDL_DisplayMode mode = {};
|
||||
mode.w = curMode.width;
|
||||
mode.h = curMode.height;
|
||||
mode.w = windowWidth;
|
||||
mode.h = windowHeight;
|
||||
|
||||
SDL_GetClosestDisplayMode(SDL_GetWindowDisplayIndex(window), &mode, &mode);
|
||||
SDL_SetWindowDisplayMode(window, &mode);
|
||||
@@ -664,10 +651,14 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
updateSettings(newsettings);
|
||||
|
||||
// Apparently this gets un-set when we exit fullscreen (at least in OS X).
|
||||
if (!fullscreen)
|
||||
SDL_SetWindowMinimumSize(window, settings.minwidth, settings.minheight);
|
||||
|
||||
// Update the viewport size now instead of waiting for event polling.
|
||||
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
|
||||
if (gfx != nullptr)
|
||||
gfx->setViewportSize(curMode.pixelwidth, curMode.pixelheight);
|
||||
gfx->setViewportSize(pixelWidth, pixelHeight);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -677,7 +668,7 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
|
||||
|
||||
bool Window::setFullscreen(bool fullscreen)
|
||||
{
|
||||
return setFullscreen(fullscreen, curMode.settings.fstype);
|
||||
return setFullscreen(fullscreen, settings.fstype);
|
||||
}
|
||||
|
||||
int Window::getDisplayCount() const
|
||||
@@ -749,7 +740,7 @@ void Window::setPosition(int x, int y, int displayindex)
|
||||
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
|
||||
curMode.settings.useposition = true;
|
||||
settings.useposition = true;
|
||||
}
|
||||
|
||||
void Window::getPosition(int &x, int &y, int &displayindex)
|
||||
@@ -801,7 +792,7 @@ bool Window::setIcon(love::image::ImageData *imgd)
|
||||
if (!imgd)
|
||||
return false;
|
||||
|
||||
curMode.icon.set(imgd);
|
||||
icon.set(imgd);
|
||||
|
||||
if (!window)
|
||||
return false;
|
||||
@@ -842,7 +833,7 @@ bool Window::setIcon(love::image::ImageData *imgd)
|
||||
|
||||
love::image::ImageData *Window::getIcon()
|
||||
{
|
||||
return curMode.icon.get();
|
||||
return icon.get();
|
||||
}
|
||||
|
||||
void Window::setDisplaySleepEnabled(bool enable)
|
||||
@@ -917,24 +908,24 @@ bool Window::isMouseGrabbed() const
|
||||
|
||||
void Window::getPixelDimensions(int &w, int &h) const
|
||||
{
|
||||
w = curMode.pixelwidth;
|
||||
h = curMode.pixelheight;
|
||||
w = pixelWidth;
|
||||
h = pixelHeight;
|
||||
}
|
||||
|
||||
void Window::windowToPixelCoords(double *x, double *y) const
|
||||
{
|
||||
if (x != nullptr)
|
||||
*x = (*x) * ((double) curMode.pixelwidth / (double) curMode.width);
|
||||
*x = (*x) * ((double) pixelWidth / (double) windowWidth);
|
||||
if (y != nullptr)
|
||||
*y = (*y) * ((double) curMode.pixelheight / (double) curMode.height);
|
||||
*y = (*y) * ((double) pixelHeight / (double) windowHeight);
|
||||
}
|
||||
|
||||
void Window::pixelToWindowCoords(double *x, double *y) const
|
||||
{
|
||||
if (x != nullptr)
|
||||
*x = (*x) * ((double) curMode.width / (double) curMode.pixelwidth);
|
||||
*x = (*x) * ((double) windowWidth / (double) pixelWidth);
|
||||
if (y != nullptr)
|
||||
*y = (*y) * ((double) curMode.height / (double) curMode.pixelheight);
|
||||
*y = (*y) * ((double) windowHeight / (double) pixelHeight);
|
||||
}
|
||||
|
||||
double Window::getPixelScale() const
|
||||
@@ -942,7 +933,7 @@ double Window::getPixelScale() const
|
||||
#ifdef LOVE_ANDROID
|
||||
return love::android::getScreenScale();
|
||||
#else
|
||||
return (double) curMode.pixelheight / (double) curMode.height;
|
||||
return (double) pixelHeight / (double) windowHeight;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -131,16 +131,12 @@ private:
|
||||
|
||||
std::string title;
|
||||
|
||||
struct _currentMode
|
||||
{
|
||||
int width = 800;
|
||||
int height = 600;
|
||||
int pixelwidth = 800;
|
||||
int pixelheight = 600;
|
||||
WindowSettings settings;
|
||||
StrongRef<love::image::ImageData> icon;
|
||||
|
||||
} curMode;
|
||||
int windowWidth = 800;
|
||||
int windowHeight = 600;
|
||||
int pixelWidth = 800;
|
||||
int pixelHeight = 600;
|
||||
WindowSettings settings;
|
||||
StrongRef<love::image::ImageData> icon;
|
||||
|
||||
bool open;
|
||||
|
||||
|
||||
@@ -386,13 +386,13 @@ function love.init()
|
||||
end
|
||||
|
||||
-- If config file exists, load it and allow it to update config table.
|
||||
if not love.conf and love.filesystem and love.filesystem.isFile("conf.lua") then
|
||||
require("conf")
|
||||
local confok, conferr
|
||||
if (not love.conf) and love.filesystem and love.filesystem.isFile("conf.lua") then
|
||||
confok, conferr = pcall(require, "conf")
|
||||
end
|
||||
|
||||
-- Yes, conf.lua might not exist, but there are other ways of making
|
||||
-- love.conf appear, so we should check for it anyway.
|
||||
local confok, conferr
|
||||
if love.conf then
|
||||
confok, conferr = pcall(love.conf, c)
|
||||
-- If love.conf errors, we'll trigger the error after loading modules so
|
||||
@@ -635,7 +635,7 @@ function love.errhand(msg)
|
||||
return
|
||||
elseif e == "keypressed" and a == "escape" then
|
||||
return
|
||||
elseif e == "touchreleased" then
|
||||
elseif e == "touchpressed" then
|
||||
local name = love.window.getTitle()
|
||||
if #name == 0 or name == "Untitled" then name = "Game" end
|
||||
local buttons = {"OK", "Cancel"}
|
||||
|
||||
@@ -708,12 +708,16 @@ const unsigned char boot_lua[] =
|
||||
0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x2c, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x69, 0x74, 0x20, 0x61,
|
||||
0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x0a,
|
||||
0x09, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65,
|
||||
0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73,
|
||||
0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c,
|
||||
0x75, 0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x22, 0x29, 0x0a,
|
||||
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e,
|
||||
0x66, 0x65, 0x72, 0x72, 0x0a,
|
||||
0x09, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73,
|
||||
0x74, 0x65, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73,
|
||||
0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x22, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x2e, 0x6c, 0x75, 0x61, 0x22, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x20,
|
||||
0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x22,
|
||||
0x63, 0x6f, 0x6e, 0x66, 0x22, 0x29, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x2d, 0x2d, 0x20, 0x59, 0x65, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x20,
|
||||
0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x2c, 0x20, 0x62,
|
||||
@@ -723,8 +727,6 @@ const unsigned char boot_lua[] =
|
||||
0x61, 0x72, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x77, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63,
|
||||
0x68, 0x65, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x77, 0x61, 0x79,
|
||||
0x2e, 0x0a,
|
||||
0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e,
|
||||
0x66, 0x65, 0x72, 0x72, 0x0a,
|
||||
0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x6f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x72, 0x72, 0x20,
|
||||
0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2c,
|
||||
@@ -1154,7 +1156,7 @@ const unsigned char boot_lua[] =
|
||||
0x20, 0x22, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x74, 0x6f,
|
||||
0x75, 0x63, 0x68, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x75, 0x63, 0x68, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x6c,
|
||||
0x6f, 0x76, 0x65, 0x2e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2e, 0x67, 0x65, 0x74, 0x54, 0x69, 0x74, 0x6c,
|
||||
0x65, 0x28, 0x29, 0x0a,
|
||||
|
||||
@@ -887,7 +887,7 @@ function love.nogame()
|
||||
function Mosaic:addGeneration()
|
||||
self.generation = self.generation + 1
|
||||
if self.generation % 5 == 0 then
|
||||
if love.math.random(0, 100) < 30 then
|
||||
if love.math.random(0, 100) < 60 then
|
||||
self.generator = self.generators[love.math.random(2, #self.generators)]
|
||||
else
|
||||
self.generator = self.generators[1]
|
||||
@@ -975,6 +975,12 @@ function love.nogame()
|
||||
g_entities.toast:center()
|
||||
end
|
||||
|
||||
function love.keypressed(key)
|
||||
if key == "escape" then
|
||||
love.event.quit()
|
||||
end
|
||||
end
|
||||
|
||||
function love.keyreleased(key)
|
||||
if key == "f" then
|
||||
local is_fs = love.window.getFullscreen()
|
||||
|
||||
@@ -3471,7 +3471,7 @@ const unsigned char nogame_lua[] =
|
||||
0x09, 0x09, 0x69, 0x66, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x25, 0x20, 0x35, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x72, 0x61,
|
||||
0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x30, 0x2c, 0x20, 0x31, 0x30, 0x30, 0x29, 0x20, 0x3c, 0x20, 0x33, 0x30, 0x20,
|
||||
0x6e, 0x64, 0x6f, 0x6d, 0x28, 0x30, 0x2c, 0x20, 0x31, 0x30, 0x30, 0x29, 0x20, 0x3c, 0x20, 0x36, 0x30, 0x20,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x09, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73,
|
||||
@@ -3649,6 +3649,14 @@ const unsigned char nogame_lua[] =
|
||||
0x3a, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x28, 0x29, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79,
|
||||
0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x28, 0x6b, 0x65, 0x79, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x65, 0x73, 0x63, 0x61, 0x70,
|
||||
0x65, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x71, 0x75, 0x69, 0x74,
|
||||
0x28, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6b, 0x65, 0x79,
|
||||
0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x28, 0x6b, 0x65, 0x79, 0x29, 0x0a,
|
||||
0x09, 0x09, 0x69, 0x66, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x66, 0x22, 0x20, 0x74, 0x68,
|
||||
0x65, 0x6e, 0x0a,
|
||||
|
||||
Reference in New Issue
Block a user