Added the ability to use custom mipmaps in Images, via love.graphics.newImage(filename, {mipmap1, mipmap2, ...}). Resolves issue #1064.

All mipmap levels must be present if custom mipmaps are used (and their sizes must be half the size of the previous mipmap level, rounded down.)

Image:getData now returns all custom mipmaps in an Image.
This commit is contained in:
Alex Szpakowski
2015-07-30 20:48:36 -03:00
parent 6bce7c7cd0
commit 66942d5f31
14 changed files with 247 additions and 129 deletions
+5 -6
View File
@@ -44,7 +44,7 @@ namespace sdl
// we want them in pixel coordinates (may be different with high-DPI enabled.)
static void windowToPixelCoords(double *x, double *y)
{
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
if (window)
window->windowToPixelCoords(x, y);
}
@@ -52,7 +52,7 @@ static void windowToPixelCoords(double *x, double *y)
#ifndef LOVE_MACOSX
static void normalizedToPixelCoords(double *x, double *y)
{
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
int w = 1, h = 1;
if (window)
@@ -70,7 +70,7 @@ static void normalizedToPixelCoords(double *x, double *y)
// handling inside the function which triggered them on some backends.
static int SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event)
{
graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
switch (event->type)
{
@@ -152,7 +152,6 @@ Message *Event::convert(const SDL_Event &e) const
std::vector<StrongRef<Variant>> vargs;
vargs.reserve(4);
love::keyboard::Keyboard *kb = nullptr;
love::filesystem::Filesystem *filesystem = nullptr;
love::keyboard::Keyboard::Key key = love::keyboard::Keyboard::KEY_UNKNOWN;
@@ -176,7 +175,7 @@ Message *Event::convert(const SDL_Event &e) const
case SDL_KEYDOWN:
if (e.key.repeat)
{
kb = Module::getInstance<love::keyboard::Keyboard>(Module::M_KEYBOARD);
auto kb = Module::getInstance<love::keyboard::Keyboard>(Module::M_KEYBOARD);
if (kb && !kb->hasKeyRepeat())
break;
}
@@ -394,7 +393,7 @@ Message *Event::convert(const SDL_Event &e) const
Message *Event::convertJoystickEvent(const SDL_Event &e) const
{
joystick::JoystickModule *joymodule = Module::getInstance<joystick::JoystickModule>(Module::M_JOYSTICK);
auto joymodule = Module::getInstance<joystick::JoystickModule>(Module::M_JOYSTICK);
if (!joymodule)
return nullptr;
+2 -2
View File
@@ -190,8 +190,8 @@ void BMFontRasterizer::parseConfig(const std::string &configtext)
{
using namespace love::filesystem;
Filesystem *filesystem = Module::getInstance<Filesystem>(Module::M_FILESYSTEM);
image::Image *imagemodule = Module::getInstance<image::Image>(Module::M_IMAGE);
auto filesystem = Module::getInstance<Filesystem>(Module::M_FILESYSTEM);
auto imagemodule = Module::getInstance<image::Image>(Module::M_IMAGE);
if (!filesystem)
throw love::Exception("Filesystem module not loaded!");
+3 -3
View File
@@ -194,7 +194,7 @@ void Graphics::checkSetDefaultFont()
// Create a new default font if we don't have one yet.
if (!defaultFont.get())
{
font::Font *fontmodule = Module::getInstance<font::Font>(M_FONT);
auto fontmodule = Module::getInstance<font::Font>(M_FONT);
if (!fontmodule)
throw love::Exception("Font module has not been loaded.");
@@ -664,12 +664,12 @@ void Graphics::clearStencil()
glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
Image *Graphics::newImage(love::image::ImageData *data, const Image::Flags &flags)
Image *Graphics::newImage(const std::vector<love::image::ImageData *> &data, const Image::Flags &flags)
{
return new Image(data, flags);
}
Image *Graphics::newImage(love::image::CompressedImageData *cdata, const Image::Flags &flags)
Image *Graphics::newImage(const std::vector<love::image::CompressedImageData *> &cdata, const Image::Flags &flags)
{
return new Image(cdata, flags);
}
+2 -2
View File
@@ -157,8 +157,8 @@ public:
/**
* Creates an Image object with padding and/or optimization.
**/
Image *newImage(love::image::ImageData *data, const Image::Flags &flags);
Image *newImage(love::image::CompressedImageData *cdata, const Image::Flags &flags);
Image *newImage(const std::vector<love::image::ImageData *> &data, const Image::Flags &flags);
Image *newImage(const std::vector<love::image::CompressedImageData *> &cdata, const Image::Flags &flags);
Quad *newQuad(Quad::Viewport v, float sw, float sh);
+138 -70
View File
@@ -23,7 +23,6 @@
#include "common/int.h"
// STD
#include <cstring> // For memcpy
#include <algorithm> // for min/max
namespace love
@@ -40,18 +39,62 @@ float Image::maxMipmapSharpness = 0.0f;
Texture::FilterMode Image::defaultMipmapFilter = Texture::FILTER_LINEAR;
float Image::defaultMipmapSharpness = 0.0f;
Image::Image(love::image::ImageData *data, const Flags &flags)
: data(data)
, cdata(nullptr)
, texture(0)
static int getMipmapCount(int basewidth, int baseheight)
{
return (int) log2(std::max(basewidth, baseheight)) + 1;
}
template <typename T>
static bool verifyMipmapLevels(const std::vector<T> &miplevels)
{
int numlevels = (int) miplevels.size();
if (numlevels == 1)
return false;
int width = miplevels[0]->getWidth();
int height = miplevels[0]->getHeight();
int expectedlevels = getMipmapCount(width, height);
// All mip levels must be present when not using auto-generated mipmaps.
if (numlevels != expectedlevels)
throw love::Exception("Image does not have all required mipmap levels (expected %d, got %d)", expectedlevels, numlevels);
// Verify the size of each mip level.
for (int i = 1; i < numlevels; i++)
{
width = std::max(width / 2, 1);
height = std::max(height / 2, 1);
if (miplevels[i]->getWidth() != width)
throw love::Exception("Width of image mipmap level %d is incorrect (expected %d, got %d)", i+1, width, miplevels[i]->getWidth());
if (miplevels[i]->getHeight() != height)
throw love::Exception("Height of image mipmap level %d is incorrect (expected %d, got %d)", i+1, height, miplevels[i]->getHeight());
}
return true;
}
Image::Image(const std::vector<love::image::ImageData *> &imagedata, const Flags &flags)
: texture(0)
, mipmapSharpness(defaultMipmapSharpness)
, compressed(false)
, flags(flags)
, usingDefaultTexture(false)
, textureMemorySize(0)
{
width = data->getWidth();
height = data->getHeight();
if (imagedata.empty())
throw love::Exception("");
width = imagedata[0]->getWidth();
height = imagedata[0]->getHeight();
if (verifyMipmapLevels(imagedata))
this->flags.mipmaps = true;
for (const auto &id : imagedata)
data.push_back(id);
preload();
loadVolatile();
@@ -59,27 +102,29 @@ Image::Image(love::image::ImageData *data, const Flags &flags)
++imageCount;
}
Image::Image(love::image::CompressedImageData *cdata, const Flags &flags)
: data(nullptr)
, cdata(cdata)
, texture(0)
Image::Image(const std::vector<love::image::CompressedImageData *> &compresseddata, const Flags &flags)
: texture(0)
, mipmapSharpness(defaultMipmapSharpness)
, compressed(true)
, flags(flags)
, usingDefaultTexture(false)
, textureMemorySize(0)
{
this->flags.sRGB = (flags.sRGB || cdata->isSRGB());
this->flags.sRGB = (flags.sRGB || cdata[0]->isSRGB());
width = cdata->getWidth(0);
height = cdata->getHeight(0);
width = compresseddata[0]->getWidth(0);
height = compresseddata[0]->getHeight(0);
if (flags.mipmaps)
if (verifyMipmapLevels(compresseddata))
this->flags.mipmaps = true;
else if (flags.mipmaps && getMipmapCount(width, height) != compresseddata[0]->getMipmapCount())
throw love::Exception("Image cannot have mipmaps: compressed image data does not have all required mipmap levels.");
for (const auto &cd : compresseddata)
{
// The mipmap texture data comes from the CompressedImageData in this case,
// so we should make sure it has all necessary mipmap levels.
if (cdata->getMipmapCount() < (int) log2(std::max(width, height)) + 1)
throw love::Exception("Image cannot have mipmaps: compressed image data does not have all required mipmap levels.");
cdata.push_back(cd);
if (cd->getFormat() != cdata[0]->getFormat())
throw love::Exception("All image mipmap levels must have the same format.");
}
preload();
@@ -159,14 +204,25 @@ void Image::loadDefaultTexture()
void Image::loadFromCompressedData()
{
GLenum iformat = getCompressedFormat(cdata->getFormat());
int count = flags.mipmaps ? cdata->getMipmapCount() : 1;
GLenum iformat = getCompressedFormat(cdata[0]->getFormat());
int count = 1;
if (flags.mipmaps && cdata.size() > 1)
count = (int) cdata.size();
else if (flags.mipmaps)
count = cdata[0]->getMipmapCount();
for (int i = 0; i < count; i++)
{
glCompressedTexImage2D(GL_TEXTURE_2D, i, iformat,
cdata->getWidth(i), cdata->getHeight(i), 0,
(GLsizei) cdata->getSize(i), cdata->getData(i));
// Compressed image mipmaps can come from separate CompressedImageData
// objects, or all from a single object.
auto cd = cdata.size() > 1 ? cdata[i].get() : cdata[0].get();
int datamip = cdata.size() > 1 ? 0 : i;
glCompressedTexImage2D(GL_TEXTURE_2D, i, iformat, cd->getWidth(datamip),
cd->getHeight(datamip), 0,
(GLsizei) cd->getSize(datamip), cd->getData(datamip));
}
}
@@ -182,23 +238,29 @@ void Image::loadFromImageData()
iformat = format;
}
int mipcount = flags.mipmaps ? (int) data.size() : 1;
for (int i = 0; i < mipcount; i++)
{
love::thread::Lock lock(data->getMutex());
glTexImage2D(GL_TEXTURE_2D, 0, iformat, width, height, 0, format,
GL_UNSIGNED_BYTE, data->getData());
love::image::ImageData *id = data[i].get();
love::thread::Lock lock(id->getMutex());
glTexImage2D(GL_TEXTURE_2D, i, iformat, id->getWidth(), id->getHeight(),
0, format, GL_UNSIGNED_BYTE, id->getData());
}
generateMipmaps();
if (data.size() <= 1)
generateMipmaps();
}
bool Image::loadVolatile()
{
OpenGL::TempDebugGroup debuggroup("Image load");
if (isCompressed() && !hasCompressedTextureSupport(cdata->getFormat(), flags.sRGB))
if (isCompressed() && !hasCompressedTextureSupport(cdata[0]->getFormat(), flags.sRGB))
{
const char *str;
if (image::CompressedImageData::getConstant(cdata->getFormat(), str))
if (image::CompressedImageData::getConstant(cdata[0]->getFormat(), str))
{
throw love::Exception("Cannot create image: "
"%s%s compressed images are not supported on this system.", flags.sRGB ? "sRGB " : "", str);
@@ -212,7 +274,8 @@ bool Image::loadVolatile()
throw love::Exception("sRGB images are not supported on this system.");
// GL_EXT_sRGB doesn't support glGenerateMipmap for sRGB textures.
if (flags.sRGB && (GLAD_ES_VERSION_2_0 && GLAD_EXT_sRGB && !GLAD_ES_VERSION_3_0))
if (flags.sRGB && (GLAD_ES_VERSION_2_0 && GLAD_EXT_sRGB && !GLAD_ES_VERSION_3_0)
&& data.size() <= 1)
{
flags.mipmaps = false;
filter.mipmap = FILTER_NONE;
@@ -244,13 +307,10 @@ bool Image::loadVolatile()
return true;
}
if ((isCompressed() || !flags.mipmaps) && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0))
{
int count = (flags.mipmaps && isCompressed()) ? cdata->getMipmapCount() : 1;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, count - 1);
}
if (!flags.mipmaps && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0))
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
if (flags.mipmaps && !isCompressed() &&
if (flags.mipmaps && !isCompressed() && data.size() <= 1 &&
!(GLAD_ES_VERSION_2_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
{
// Auto-generate mipmaps every time the texture is modified, if
@@ -281,17 +341,12 @@ bool Image::loadVolatile()
size_t prevmemsize = textureMemorySize;
if (isCompressed())
{
textureMemorySize = 0;
for (int i = 0; i < (flags.mipmaps ? cdata->getMipmapCount() : 1); i++)
textureMemorySize += cdata->getSize(i);
}
textureMemorySize = cdata[0]->getSize();
else
{
textureMemorySize = width * height * 4;
if (flags.mipmaps)
textureMemorySize *= 1.333;
}
textureMemorySize = data[0]->getSize();
if (flags.mipmaps)
textureMemorySize *= 1.33334;
gl.updateTextureMemorySize(prevmemsize, textureMemorySize);
@@ -323,31 +378,44 @@ bool Image::refresh(int xoffset, int yoffset, int w, int h)
throw love::Exception("Invalid rectangle dimensions.");
}
OpenGL::TempDebugGroup debuggroup("Image refresh");
gl.bindTexture(texture);
if (isCompressed())
loadFromCompressedData();
else
{
const image::pixel *pdata = (const image::pixel *) data->getData();
pdata += yoffset * data->getWidth() + xoffset;
GLenum format = GL_RGBA;
// In ES2, the format parameter of TexSubImage must match the internal
// format of the texture.
if (flags.sRGB && (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0))
format = GL_SRGB_ALPHA;
{
thread::Lock lock(data->getMutex());
glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h, format,
GL_UNSIGNED_BYTE, pdata);
}
generateMipmaps();
loadFromCompressedData();
return true;
}
GLenum format = GL_RGBA;
// In ES2, the format parameter of TexSubImage must match the internal
// format of the texture.
if (flags.sRGB && (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0))
format = GL_SRGB_ALPHA;
int mipcount = flags.mipmaps ? (int) data.size() : 1;
// Reupload the sub-rectangle of each mip level (if we have custom mipmaps.)
for (int i = 0; i < mipcount; i++)
{
const image::pixel *pdata = (const image::pixel *) data[i]->getData();
pdata += yoffset * data[i]->getWidth() + xoffset;
thread::Lock lock(data[i]->getMutex());
glTexSubImage2D(GL_TEXTURE_2D, i, xoffset, yoffset, w, h, format,
GL_UNSIGNED_BYTE, pdata);
xoffset /= 2;
yoffset /= 2;
w = std::max(w / 2, 1);
h = std::max(h / 2, 1);
}
if (data.size() <= 1)
generateMipmaps();
return true;
}
@@ -388,14 +456,14 @@ const void *Image::getHandle() const
return &texture;
}
love::image::ImageData *Image::getImageData() const
const std::vector<StrongRef<love::image::ImageData>> &Image::getImageData() const
{
return data.get();
return data;
}
love::image::CompressedImageData *Image::getCompressedData() const
const std::vector<StrongRef<love::image::CompressedImageData>> &Image::getCompressedData() const
{
return cdata.get();
return cdata;
}
void Image::setFilter(const Texture::Filter &f)
+12 -9
View File
@@ -69,16 +69,18 @@ public:
* Creates a new Image. Not that anything is ready to use
* before load is called.
*
* @param data The data from which to load the image.
* @param data The data from which to load the image. Each element in the
* array is a mipmap level. If more than the base level is present, all
* mip levels must be present.
**/
Image(love::image::ImageData *data, const Flags &flags);
Image(const std::vector<love::image::ImageData *> &data, const Flags &flags);
/**
* Creates a new Image with compressed image data.
*
* @param cdata The compressed data from which to load the image.
**/
Image(love::image::CompressedImageData *cdata, const Flags &flags);
Image(const std::vector<love::image::CompressedImageData *> &cdata, const Flags &flags);
virtual ~Image();
@@ -98,8 +100,8 @@ public:
virtual const void *getHandle() const;
love::image::ImageData *getImageData() const;
love::image::CompressedImageData *getCompressedData() const;
const std::vector<StrongRef<love::image::ImageData>> &getImageData() const;
const std::vector<StrongRef<love::image::CompressedImageData>> &getCompressedData() const;
virtual void setFilter(const Texture::Filter &f);
virtual bool setWrap(const Texture::Wrap &w);
@@ -147,13 +149,14 @@ private:
GLenum getCompressedFormat(image::CompressedImageData::Format cformat) const;
// The ImageData from which the texture is created. May be null if
// The ImageData from which the texture is created. May be empty if
// Compressed image data was used to create the texture.
StrongRef<love::image::ImageData> data;
// Each element in the array is a mipmap level.
std::vector<StrongRef<love::image::ImageData>> data;
// Or the Compressed Image Data from which the texture is created. May be
// null if raw ImageData was used to create the texture.
StrongRef<love::image::CompressedImageData> cdata;
// empty if raw ImageData was used to create the texture.
std::vector<StrongRef<love::image::CompressedImageData>> cdata;
// OpenGL texture identifier.
GLuint texture;
+1 -1
View File
@@ -38,7 +38,7 @@ int w_Canvas_renderTo(lua_State *L)
Canvas *canvas = luax_checkcanvas(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);
Graphics *graphics = Module::getInstance<Graphics>(Module::M_GRAPHICS);
auto graphics = Module::getInstance<Graphics>(Module::M_GRAPHICS);
if (graphics)
{
+55 -20
View File
@@ -25,6 +25,7 @@
#include "image/Image.h"
#include "font/Rasterizer.h"
#include "filesystem/wrap_Filesystem.h"
#include "image/wrap_Image.h"
#include <cassert>
#include <cstring>
@@ -236,8 +237,8 @@ static const char *imageFlagName(Image::FlagType flagtype)
int w_newImage(lua_State *L)
{
love::image::ImageData *data = nullptr;
love::image::CompressedImageData *cdata = nullptr;
std::vector<love::image::ImageData *> data;
std::vector<love::image::CompressedImageData *> cdata;
Image::Flags flags;
if (!lua_isnoneornil(L, 2))
@@ -252,23 +253,23 @@ int w_newImage(lua_State *L)
// Convert to ImageData / CompressedImageData, if necessary.
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_ID) || luax_istype(L, 1, FILESYSTEM_FILE_DATA_ID))
{
love::image::Image *image = Module::getInstance<love::image::Image>(Module::M_IMAGE);
if (image == nullptr)
auto imagemodule = Module::getInstance<love::image::Image>(Module::M_IMAGE);
if (imagemodule == nullptr)
return luaL_error(L, "Cannot load images without the love.image module.");
love::filesystem::FileData *fdata = love::filesystem::luax_getfiledata(L, 1);
if (image->isCompressed(fdata))
if (imagemodule->isCompressed(fdata))
{
luax_catchexcept(L,
[&]() { cdata = image->newCompressedData(fdata); },
[&]() { cdata.push_back(imagemodule->newCompressedData(fdata)); },
[&](bool) { fdata->release(); }
);
}
else
{
luax_catchexcept(L,
[&]() { data = image->newImageData(fdata); },
[&]() { data.push_back(imagemodule->newImageData(fdata)); },
[&](bool) { fdata->release(); }
);
}
@@ -277,27 +278,61 @@ int w_newImage(lua_State *L)
releasedata = true;
}
else if (luax_istype(L, 1, IMAGE_COMPRESSED_IMAGE_DATA_ID))
cdata = luax_checktype<love::image::CompressedImageData>(L, 1, IMAGE_COMPRESSED_IMAGE_DATA_ID);
cdata.push_back(love::image::luax_checkcompressedimagedata(L, 1));
else
data = luax_checktype<love::image::ImageData>(L, 1, IMAGE_IMAGE_DATA_ID);
data.push_back(love::image::luax_checkimagedata(L, 1));
if (!data && !cdata)
return luaL_error(L, "Error creating image (could not load data.)");
if (lua_istable(L, 2))
{
lua_getfield(L, 2, imageFlagName(Image::FLAG_TYPE_MIPMAPS));
// Add all manually specified mipmap images to the array of imagedata.
// i.e. flags = {mipmaps = {mip1, mip2, ...}}.
if (lua_istable(L, -1))
{
for (size_t i = 1; i <= luax_objlen(L, -1); i++)
{
lua_rawgeti(L, -1, i);
if (!data.empty())
{
if (!luax_istype(L, -1, IMAGE_IMAGE_DATA_ID))
luax_convobj(L, -1, "image", "newImageData");
data.push_back(love::image::luax_checkimagedata(L, -1));
}
else if (!cdata.empty())
{
if (!luax_istype(L, -1, IMAGE_COMPRESSED_IMAGE_DATA_ID))
luax_convobj(L, -1, "image", "newCompressedData");
cdata.push_back(love::image::luax_checkcompressedimagedata(L, -1));
}
lua_pop(L, 1);
}
}
lua_pop(L, 1);
}
// Create the image.
Image *image = nullptr;
luax_catchexcept(L,
[&]() {
if (cdata)
if (!cdata.empty())
image = instance()->newImage(cdata, flags);
else if (data)
else if (!data.empty())
image = instance()->newImage(data, flags);
},
[&](bool) {
if (releasedata && data)
data->release();
else if (releasedata && cdata)
cdata->release();
if (releasedata)
{
for (auto d : data)
d->release();
for (auto d : cdata)
d->release();
}
}
);
@@ -363,10 +398,10 @@ int w_newImageFont(lua_State *L)
{
Image *i = luax_checktype<Image>(L, 1, GRAPHICS_IMAGE_ID);
filter = i->getFilter();
love::image::ImageData *id = i->getImageData();
if (!id)
const auto &idlevels = i->getImageData();
if (idlevels.empty())
return luaL_argerror(L, 1, "Image must not be compressed.");
luax_pushtype(L, IMAGE_IMAGE_DATA_ID, id);
luax_pushtype(L, IMAGE_IMAGE_DATA_ID, idlevels[0].get());
lua_replace(L, 1);
}
+16 -3
View File
@@ -92,13 +92,26 @@ int w_Image_refresh(lua_State *L)
int w_Image_getData(lua_State *L)
{
Image *i = luax_checkimage(L, 1);
int n = 0;
if (i->isCompressed())
luax_pushtype(L, IMAGE_COMPRESSED_IMAGE_DATA_ID, i->getCompressedData());
{
for (const auto &cdata : i->getCompressedData())
{
luax_pushtype(L, IMAGE_COMPRESSED_IMAGE_DATA_ID, cdata.get());
n++;
}
}
else
luax_pushtype(L, IMAGE_IMAGE_DATA_ID, i->getImageData());
{
for (const auto &data : i->getImageData())
{
luax_pushtype(L, IMAGE_IMAGE_DATA_ID, data.get());
n++;
}
}
return 1;
return n;
}
static const char *imageFlagName(Image::FlagType flagtype)
+2 -2
View File
@@ -107,12 +107,12 @@ public:
/**
* Gets the width of a sub-image at the specified mipmap level.
**/
int getWidth(int miplevel) const;
int getWidth(int miplevel = 0) const;
/**
* Gets the height of a sub-image at the specified mipmap level.
**/
int getHeight(int miplevel) const;
int getHeight(int miplevel = 0) const;
/**
* Gets the format of the compressed data.
+1 -1
View File
@@ -122,7 +122,7 @@ void Keyboard::setTextInput(bool enable, double x, double y, double w, double h)
{
// SDL_SetTextInputRect expects coordinates in window-space but setTextInput
// takes pixels, so we should convert.
window::Window *window = Module::getInstance<window::Window>(M_WINDOW);
auto window = Module::getInstance<window::Window>(M_WINDOW);
if (window)
{
window->pixelToWindowCoords(&x, &y);
+5 -5
View File
@@ -36,7 +36,7 @@ namespace sdl
// we want them in pixel coordinates (may be different with high-DPI enabled.)
static void windowToPixelCoords(double *x, double *y)
{
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
if (window)
window->windowToPixelCoords(x, y);
}
@@ -44,7 +44,7 @@ static void windowToPixelCoords(double *x, double *y)
// And vice versa for setting mouse coordinates.
static void pixelToWindowCoords(double *x, double *y)
{
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
if (window)
window->pixelToWindowCoords(x, y);
}
@@ -146,7 +146,7 @@ void Mouse::getPosition(double &x, double &y) const
void Mouse::setPosition(double x, double y)
{
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
SDL_Window *handle = nullptr;
if (window)
@@ -211,14 +211,14 @@ bool Mouse::isVisible() const
void Mouse::setGrabbed(bool grab)
{
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
if (window)
window->setMouseGrab(grab);
}
bool Mouse::isGrabbed() const
{
window::Window *window = Module::getInstance<window::Window>(Module::M_WINDOW);
auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
if (window)
return window->isMouseGrabbed();
else
+3 -3
View File
@@ -118,8 +118,8 @@ void LuaThread::onError()
if (error.empty())
return;
event::Event *event = Module::getInstance<event::Event>(Module::M_EVENT);
if (!event)
auto eventmodule = Module::getInstance<event::Event>(Module::M_EVENT);
if (!eventmodule)
return;
Proxy p;
@@ -136,7 +136,7 @@ void LuaThread::onError()
for (const StrongRef<Variant> &v : vargs)
v->release();
event->push(msg);
eventmodule->push(msg);
msg->release();
}
+2 -2
View File
@@ -466,7 +466,7 @@ bool Window::onSizeChanged(int width, int height)
SDL_GL_GetDrawableSize(window, &curMode.pixelwidth, &curMode.pixelheight);
graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
if (gfx != nullptr)
gfx->setViewportSize(curMode.pixelwidth, curMode.pixelheight);
@@ -609,7 +609,7 @@ bool Window::setFullscreen(bool fullscreen, Window::FullscreenType fstype)
updateSettings(newsettings);
// Update the viewport size now instead of waiting for event polling.
graphics::Graphics *gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
if (gfx != nullptr)
gfx->setViewportSize(curMode.pixelwidth, curMode.pixelheight);