Array textures can be easily drawn without a shader (resolves issue #1111).

Added love.graphics.drawLayer(texture, layerindex, …). ‘texture’ must be an array texture.
Added SpriteBatch:add/setLayer.

Added Quad:get/setLayer. This applies to array textures that are drawn without specifying an explicit layer index in the draw call.

Added love.graphics.newQuad variants which have layer arguments.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-02-26 17:11:22 -04:00
parent 9ba7234f14
commit 66b299822a
27 changed files with 559 additions and 295 deletions
+2 -2
View File
@@ -40,12 +40,12 @@ Canvas::~Canvas()
canvasCount--;
}
void Canvas::drawv(love::graphics::Graphics *gfx, const love::Matrix4 &t, const Vertex *v)
void Canvas::draw(Graphics *gfx, Quad *q, const Matrix4 &t)
{
if (gfx->isCanvasActive(this))
throw love::Exception("Cannot render a Canvas to itself!");
Texture::drawv(gfx, t, v);
Texture::draw(gfx, q, t);
}
} // graphics
+2 -4
View File
@@ -57,11 +57,9 @@ public:
virtual int getRequestedMSAA() const = 0;
virtual ptrdiff_t getMSAAHandle() const = 0;
void draw(Graphics *gfx, Quad *q, const Matrix4 &t) override;
static int canvasCount;
private:
void drawv(Graphics *gfx, const Matrix4 &t, const Vertex *v) override;
}; // Canvas
+34 -28
View File
@@ -99,8 +99,7 @@ bool isDebugEnabled()
love::Type Graphics::type("graphics", &Module::type);
Shader::ShaderSource Graphics::defaultShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
Shader::ShaderSource Graphics::defaultVideoShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
Shader::ShaderSource Graphics::defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
Graphics::Graphics()
: width(0)
@@ -130,16 +129,13 @@ Graphics::~Graphics()
defaultFont.set(nullptr);
if (Shader::defaultShader)
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++)
{
Shader::defaultShader->release();
Shader::defaultShader = nullptr;
}
if (Shader::defaultVideoShader)
{
Shader::defaultVideoShader->release();
Shader::defaultVideoShader = nullptr;
if (Shader::standardShaders[i])
{
Shader::standardShaders[i]->release();
Shader::standardShaders[i] = nullptr;
}
}
delete streamBufferState.vb[0];
@@ -390,7 +386,7 @@ void Graphics::setShader()
{
flushStreamDraws();
Shader::attachDefault();
Shader::attachDefault(Shader::STANDARD_DEFAULT);
states.back().shader.set(nullptr);
}
@@ -692,6 +688,31 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
* Drawing
**/
void Graphics::draw(Drawable *drawable, const Matrix4 &m)
{
drawable->draw(this, m);
}
void Graphics::draw(Texture *texture, Quad *quad, const Matrix4 &m)
{
texture->draw(this, quad, m);
}
void Graphics::drawLayer(Texture *texture, int layer, const Matrix4 &m)
{
texture->drawLayer(this, layer, m);
}
void Graphics::drawLayer(Texture *texture, int layer, Quad *quad, const Matrix4 &m)
{
texture->drawLayer(this, layer, quad, m);
}
void Graphics::drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount)
{
mesh->drawInstanced(this, m, instancecount);
}
void Graphics::print(const std::vector<Font::ColoredString> &str, const Matrix4 &m)
{
checkSetDefaultFont();
@@ -712,21 +733,6 @@ void Graphics::printf(const std::vector<Font::ColoredString> &str, float wrap, F
state.font->printf(this, str, wrap, align, m, state.color);
}
void Graphics::draw(Drawable *drawable, const Matrix4 &m)
{
drawable->draw(this, m);
}
void Graphics::draw(Texture *texture, Quad *quad, const Matrix4 &m)
{
texture->drawq(this, quad, m);
}
void Graphics::drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount)
{
mesh->drawInstanced(this, m, instancecount);
}
/**
* Primitives (points, shapes, lines).
**/
@@ -1165,7 +1171,7 @@ Vector Graphics::inverseTransformPoint(Vector point)
const Shader::ShaderSource &Graphics::getCurrentDefaultShaderCode() const
{
return defaultShaderCode[getShaderLanguageTarget()][isGammaCorrect() ? 1 : 0];
return defaultShaderCode[Shader::STANDARD_DEFAULT][getShaderLanguageTarget()][isGammaCorrect() ? 1 : 0];
}
/**
+3 -2
View File
@@ -585,6 +585,8 @@ public:
void draw(Drawable *drawable, const Matrix4 &m);
void draw(Texture *texture, Quad *quad, const Matrix4 &m);
void drawLayer(Texture *texture, int layer, const Matrix4 &m);
void drawLayer(Texture *texture, int layer, Quad *quad, const Matrix4 &m);
void drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount);
/**
@@ -782,8 +784,7 @@ public:
static bool getConstant(StackType in, const char *&out);
// Default shader code (a shader is always required internally.)
static Shader::ShaderSource defaultShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
static Shader::ShaderSource defaultVideoShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
static Shader::ShaderSource defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
protected:
+7 -1
View File
@@ -97,6 +97,9 @@ ParticleSystem::ParticleSystem(Graphics *gfx, Texture *texture, uint32 size)
if (size == 0 || size > MAX_PARTICLES)
throw love::Exception("Invalid ParticleSystem size.");
if (texture->getTextureType() != TEXTURE_2D)
throw love::Exception("Only 2D textures can be used with ParticleSystems.");
sizes.push_back(1.0f);
colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
@@ -434,6 +437,9 @@ ParticleSystem::Particle *ParticleSystem::removeParticle(Particle *p)
void ParticleSystem::setTexture(Texture *tex)
{
if (texture->getTextureType() != TEXTURE_2D)
throw love::Exception("Only 2D textures can be used with ParticleSystems.");
texture.set(tex);
if (defaultOffset)
@@ -958,7 +964,7 @@ bool ParticleSystem::prepareDraw(Graphics *gfx, const Matrix4 &m)
Graphics::TempTransform transform(gfx, m);
const Vertex *textureVerts = texture->getVertices();
const vertex::XYf_STf *textureVerts = texture->getQuad()->getVertices();
Vertex *pVerts = (Vertex *) buffer->map();
Particle *p = pHead;
+13 -3
View File
@@ -35,7 +35,7 @@ Quad::Quad(const Quad::Viewport &v, double sw, double sh)
: sw(sw)
, sh(sh)
{
memset(vertices, 255, sizeof(Vertex) * 4);
arrayLayer = 0;
refresh(v, sw, sh);
}
@@ -45,7 +45,7 @@ Quad::~Quad()
void Quad::refresh(const Quad::Viewport &v, double sw, double sh)
{
viewport = v;
this->viewport = v;
this->sw = sw;
this->sh = sh;
@@ -92,10 +92,20 @@ double Quad::getTextureHeight() const
return sh;
}
const Vertex *Quad::getVertices() const
const vertex::XYf_STf *Quad::getVertices() const
{
return vertices;
}
void Quad::setLayer(int layer)
{
arrayLayer = layer;
}
int Quad::getLayer() const
{
return arrayLayer;
}
} // graphics
} // love
+7 -2
View File
@@ -53,11 +53,16 @@ public:
double getTextureWidth() const;
double getTextureHeight() const;
const Vertex *getVertices() const;
const vertex::XYf_STf *getVertices() const;
void setLayer(int layer);
int getLayer() const;
private:
Vertex vertices[4];
vertex::XYf_STf vertices[4];
int arrayLayer;
Viewport viewport;
double sw;
+26 -14
View File
@@ -132,9 +132,9 @@ namespace graphics
{
love::Type Shader::type("Shader", &Object::type);
Shader *Shader::current = nullptr;
Shader *Shader::defaultShader = nullptr;
Shader *Shader::defaultVideoShader = nullptr;
Shader *Shader::standardShaders[Shader::STANDARD_MAX_ENUM] = {nullptr};
Shader::Shader(const ShaderSource &source)
: shaderSource(source)
@@ -151,27 +151,39 @@ Shader::Shader(const ShaderSource &source)
Shader::~Shader()
{
if (defaultShader == this)
defaultShader = nullptr;
if (defaultVideoShader == this)
defaultVideoShader = nullptr;
for (int i = 0; i < STANDARD_MAX_ENUM; i++)
{
if (this == standardShaders[i])
standardShaders[i] = nullptr;
}
if (current == this)
attachDefault();
attachDefault(STANDARD_DEFAULT);
}
void Shader::attachDefault()
void Shader::attachDefault(StandardShader defaultType)
{
if (defaultShader)
{
if (current != defaultShader)
defaultShader->attach();
Shader *defaultshader = standardShaders[defaultType];
if (defaultshader == nullptr)
{
current = nullptr;
return;
}
current = nullptr;
if (current != defaultshader)
defaultshader->attach();
}
bool Shader::isDefaultActive()
{
for (int i = 0; i < STANDARD_MAX_ENUM; i++)
{
if (current == standardShaders[i])
return true;
}
return false;
}
TextureType Shader::getMainTextureType() const
+16 -4
View File
@@ -95,6 +95,14 @@ public:
UNIFORM_MAX_ENUM
};
enum StandardShader
{
STANDARD_DEFAULT,
STANDARD_VIDEO,
STANDARD_ARRAY,
STANDARD_MAX_ENUM
};
struct ShaderSource
{
std::string vertex;
@@ -137,8 +145,7 @@ public:
static Shader *current;
// Pointer to the default Shader.
static Shader *defaultShader;
static Shader *defaultVideoShader;
static Shader *standardShaders[STANDARD_MAX_ENUM];
Shader(const ShaderSource &source);
virtual ~Shader();
@@ -149,9 +156,14 @@ public:
virtual void attach() = 0;
/**
* Attach the default shader.
* Attach a default shader.
**/
static void attachDefault();
static void attachDefault(StandardShader defaultType);
/**
* Gets whether any of the default shaders are currently active.
**/
static bool isDefaultActive();
/**
* Returns any warnings this Shader may have generated.
+80 -36
View File
@@ -44,7 +44,8 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usag
: texture(texture)
, size(size)
, next(0)
, color(0)
, color(255, 255, 255, 255)
, color_active(false)
, array_buf(nullptr)
, quad_indices(gfx, size)
, range_start(-1)
@@ -53,26 +54,59 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usag
if (size <= 0)
throw love::Exception("Invalid SpriteBatch size.");
size_t vertex_size = sizeof(Vertex) * 4 * size;
if (texture == nullptr)
throw love::Exception("A texture must be used when creating a SpriteBatch.");
if (texture->getTextureType() == TEXTURE_2D_ARRAY)
vertex_format = vertex::CommonFormat::XYf_STPf_RGBAub;
else
vertex_format = vertex::CommonFormat::XYf_STf_RGBAub;
format_stride = vertex::getFormatStride(vertex_format);
size_t vertex_size = format_stride * 4 * size;
array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY);
}
SpriteBatch::~SpriteBatch()
{
delete color;
delete array_buf;
}
int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
{
return add(texture->getQuad(), m, index);
}
int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
{
using namespace vertex;
if (vertex_format == CommonFormat::XYf_STPf_RGBAub)
return addLayer(quad->getLayer(), quad, m, index);
if (index < -1 || index >= size)
throw love::Exception("Invalid sprite index: %d", index + 1);
if (index == -1 && next >= size)
setBufferSize(size * 2);
addv(texture->getVertices(), m, (index == -1) ? next : index);
const XYf_STf *quadverts = quad->getVertices();
// Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
size_t offset = (index == -1 ? next : index) * format_stride * 4;
auto verts = (XYf_STf_RGBAub *) ((uint8 *) array_buf->map() + offset);
m.transform(verts, quadverts, 4);
for (int i = 0; i < 4; i++)
{
verts[i].s = quadverts[i].s;
verts[i].t = quadverts[i].t;
verts[i].color = color;
}
array_buf->setMappedRangeModified(offset, format_stride * 4);
// Increment counter.
if (index == -1)
@@ -81,15 +115,44 @@ int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
return index;
}
int SpriteBatch::addq(Quad *quad, const Matrix4 &m, int index /*= -1*/)
int SpriteBatch::addLayer(int layer, const Matrix4 &m, int index)
{
return addLayer(layer, texture->getQuad(), m, index);
}
int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index)
{
using namespace vertex;
if (vertex_format != CommonFormat::XYf_STPf_RGBAub)
throw love::Exception("addLayer can only be called on a SpriteBatch that uses an Array Texture!");
if (index < -1 || index >= size)
throw love::Exception("Invalid sprite index: %d", index + 1);
if (layer < 0 || layer >= texture->getLayerCount())
throw love::Exception("Invalid layer: %d (Texture has %d layers)", layer + 1, texture->getLayerCount());
if (index == -1 && next >= size)
setBufferSize(size * 2);
addv(quad->getVertices(), m, (index == -1) ? next : index);
const XYf_STf *quadverts = quad->getVertices();
// Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
size_t offset = (index == -1 ? next : index) * format_stride * 4;
auto verts = (XYf_STPf_RGBAub *) ((uint8 *) array_buf->map() + offset);
m.transform(verts, quadverts, 4);
for (int i = 0; i < 4; i++)
{
verts[i].s = quadverts[i].s;
verts[i].t = quadverts[i].t;
verts[i].p = (float) layer;
verts[i].color = color;
}
array_buf->setMappedRangeModified(offset, format_stride * 4);
// Increment counter.
if (index == -1)
@@ -111,6 +174,9 @@ void SpriteBatch::flush()
void SpriteBatch::setTexture(Texture *newtexture)
{
if (texture->getTextureType() != newtexture->getTextureType())
throw love::Exception("Texture must have the same texture type as the SpriteBatch's previous texture.");
texture.set(newtexture);
}
@@ -121,20 +187,19 @@ Texture *SpriteBatch::getTexture() const
void SpriteBatch::setColor(const Color &color)
{
if (!this->color)
this->color = new Color(color);
else
*(this->color) = color;
color_active = true;
this->color = color;
}
void SpriteBatch::setColor()
{
delete color;
color = nullptr;
color_active = false;
color = Color(255, 255, 255, 255);
}
const Color *SpriteBatch::getColor() const
const Color &SpriteBatch::getColor(bool &active) const
{
active = color_active;
return color;
}
@@ -151,7 +216,7 @@ void SpriteBatch::setBufferSize(int newsize)
if (newsize == size)
return;
size_t vertex_size = sizeof(Vertex) * 4 * newsize;
size_t vertex_size = format_stride * 4 * newsize;
love::graphics::Buffer *new_array_buf = nullptr;
int new_next = std::min(next, newsize);
@@ -162,7 +227,7 @@ void SpriteBatch::setBufferSize(int newsize)
new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
// Copy as much of the old data into the new GLBuffer as can fit.
size_t copy_size = sizeof(Vertex) * 4 * new_next;
size_t copy_size = format_stride * 4 * new_next;
array_buf->copyTo(0, copy_size, new_array_buf, 0);
quad_indices = QuadIndices(gfx, newsize);
@@ -233,26 +298,5 @@ bool SpriteBatch::getDrawRange(int &start, int &count) const
return true;
}
void SpriteBatch::addv(const Vertex *v, const Matrix4 &m, int index)
{
// Needed for colors.
Vertex sprite[4] = {v[0], v[1], v[2], v[3]};
const size_t sprite_size = 4 * sizeof(Vertex); // bytecount
m.transform(sprite, sprite, 4);
if (color != nullptr)
{
for (int i = 0; i < 4; i++)
sprite[i].color = *color;
}
// Always keep the VBO mapped when adding data for now (it'll be unmapped
// on draw.)
array_buf->map();
array_buf->fill(index * sprite_size, sprite_size, sprite);
}
} // graphics
} // love
+11 -7
View File
@@ -54,7 +54,10 @@ public:
virtual ~SpriteBatch();
int add(const Matrix4 &m, int index = -1);
int addq(Quad *quad, const Matrix4 &m, int index = -1);
int add(Quad *quad, const Matrix4 &m, int index = -1);
int addLayer(int layer, const Matrix4 &m, int index = -1);
int addLayer(int layer, Quad *quad, const Matrix4 &m, int index = -1);
void clear();
void flush();
@@ -78,10 +81,9 @@ public:
void setColor();
/**
* Get the current color for this SpriteBatch. Returns NULL if no color is
* set.
* Get the current color for this SpriteBatch.
**/
const Color *getColor() const;
const Color &getColor(bool &active) const;
/**
* Get the number of sprites currently in this SpriteBatch.
@@ -117,8 +119,6 @@ protected:
**/
void setBufferSize(int newsize);
void addv(const Vertex *v, const Matrix4 &m, int index);
StrongRef<Texture> texture;
// Max number of sprites in the batch.
@@ -129,7 +129,11 @@ protected:
// Current color. This color, if present, will be applied to the next
// added sprite.
Color *color;
Color color;
bool color_active;
vertex::CommonFormat vertex_format;
size_t format_stride;
love::graphics::Buffer *array_buf;
QuadIndices quad_indices;
+68 -47
View File
@@ -61,7 +61,6 @@ Texture::Texture(TextureType texType)
, filter(defaultFilter)
, wrap()
, mipmapSharpness(defaultMipmapSharpness)
, vertices()
{
}
@@ -69,32 +68,10 @@ Texture::~Texture()
{
}
void Texture::initVertices()
void Texture::initQuad()
{
for (int i = 0; i < 4; i++)
vertices[i].color = Color(255, 255, 255, 255);
// Vertices are ordered for use with triangle strips:
// 0---2
// | / |
// 1---3
vertices[0].x = 0.0f;
vertices[0].y = 0.0f;
vertices[1].x = 0.0f;
vertices[1].y = (float) height;
vertices[2].x = (float) width;
vertices[2].y = 0.0f;
vertices[3].x = (float) width;
vertices[3].y = (float) height;
vertices[0].s = 0.0f;
vertices[0].t = 0.0f;
vertices[1].s = 0.0f;
vertices[1].t = 1.0f;
vertices[2].s = 1.0f;
vertices[2].t = 0.0f;
vertices[3].s = 1.0f;
vertices[3].t = 1.0f;
Quad::Viewport v = {0, 0, (double) width, (double) height};
quad.set(new Quad(v, width, height), Acquire::NORETAIN);
}
TextureType Texture::getTextureType() const
@@ -109,37 +86,81 @@ PixelFormat Texture::getPixelFormat() const
void Texture::draw(Graphics *gfx, const Matrix4 &m)
{
drawv(gfx, m, vertices);
draw(gfx, quad, m);
}
void Texture::drawq(Graphics *gfx, Quad *quad, const Matrix4 &m)
void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform)
{
drawv(gfx, m, quad->getVertices());
}
using namespace vertex;
void Texture::drawv(Graphics *gfx, const Matrix4 &localTransform, const Vertex *v)
{
if (Shader::current)
Shader::current->checkMainTextureType(texType);
Matrix4 t(gfx->getTransform(), localTransform);
Vertex verts[4] = {v[0], v[1], v[2], v[3]};
t.transform(verts, v, 4);
if (texType == TEXTURE_2D_ARRAY)
{
drawLayer(gfx, q->getLayer(), q, localTransform);
return;
}
Color c = toColor(gfx->getColor());
for (int i = 0; i < 4; i++)
verts[i].color = c;
Graphics::StreamDrawRequest req;
req.formats[0] = vertex::CommonFormat::XYf_STf_RGBAub;
req.indexMode = vertex::TriangleIndexMode::QUADS;
req.formats[0] = CommonFormat::XYf_STf_RGBAub;
req.indexMode = TriangleIndexMode::QUADS;
req.vertexCount = 4;
req.texture = this;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
memcpy(data.stream[0], verts, sizeof(Vertex) * 4);
XYf_STf_RGBAub *verts = (XYf_STf_RGBAub *) data.stream[0];
const XYf_STf *quadverts = q->getVertices();
Matrix4 t(gfx->getTransform(), localTransform);
t.transform(verts, quadverts, 4);
for (int i = 0; i < 4; i++)
{
verts[i].s = quadverts[i].s;
verts[i].t = quadverts[i].t;
verts[i].color = c;
}
}
void Texture::drawLayer(Graphics *gfx, int layer, const Matrix4 &m)
{
drawLayer(gfx, layer, quad, m);
}
void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m)
{
using namespace vertex;
if (texType != TEXTURE_2D_ARRAY)
throw love::Exception("drawLayer can only be used with Array Textures!");
if (layer < 0 || layer >= layers)
throw love::Exception("Invalid layer: %d (Texture has %d layers)", layer + 1, layers);
Color c = toColor(gfx->getColor());
Graphics::StreamDrawRequest req;
req.formats[0] = CommonFormat::XYf_STPf_RGBAub;
req.indexMode = TriangleIndexMode::QUADS;
req.vertexCount = 4;
req.texture = this;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
XYf_STPf_RGBAub *verts = (XYf_STPf_RGBAub *) data.stream[0];
const XYf_STf *quadverts = q->getVertices();
Matrix4 t(gfx->getTransform(), m);
t.transform(verts, quadverts, 4);
for (int i = 0; i < 4; i++)
{
verts[i].s = quadverts[i].s;
verts[i].t = quadverts[i].t;
verts[i].p = (float) layer;
verts[i].color = c;
}
}
int Texture::getWidth() const
@@ -197,9 +218,9 @@ float Texture::getMipmapSharpness() const
return mipmapSharpness;
}
const Vertex *Texture::getVertices() const
Quad *Texture::getQuad() const
{
return vertices;
return quad;
}
bool Texture::validateFilter(const Filter &f, bool mipmapsAllowed)
+8 -6
View File
@@ -112,7 +112,10 @@ public:
/**
* Draws the texture using the specified transformation with a Quad applied.
**/
void drawq(Graphics *gfx, Quad *quad, const Matrix4 &m);
virtual void draw(Graphics *gfx, Quad *quad, const Matrix4 &m);
void drawLayer(Graphics *gfx, int layer, const Matrix4 &m);
virtual void drawLayer(Graphics *gfx, int layer, Quad *quad, const Matrix4 &m);
TextureType getTextureType() const;
PixelFormat getPixelFormat() const;
@@ -138,7 +141,7 @@ public:
virtual bool setMipmapSharpness(float sharpness) = 0;
float getMipmapSharpness() const;
virtual const Vertex *getVertices() const;
Quad *getQuad() const;
virtual ptrdiff_t getHandle() const = 0;
@@ -158,8 +161,7 @@ public:
protected:
void initVertices();
virtual void drawv(Graphics *gfx, const Matrix4 &localTransform, const Vertex *v);
void initQuad();
TextureType texType;
@@ -167,6 +169,7 @@ protected:
int width;
int height;
int depth;
int layers;
int mipmapCount;
@@ -174,13 +177,12 @@ protected:
int pixelWidth;
int pixelHeight;
Filter filter;
Wrap wrap;
float mipmapSharpness;
Vertex vertices[4];
StrongRef<Quad> quad;
private:
+10 -8
View File
@@ -109,16 +109,18 @@ void Video::draw(Graphics *gfx, const Matrix4 &m)
gfx->flushStreamDraws();
love::graphics::Shader *shader = Shader::current;
bool usingdefaultshader = (shader == Shader::defaultShader);
bool usingdefaultshader = Shader::isDefaultActive();
Shader *prevdefaultshader = nullptr;
// If we're using the default shader, substitute the video version.
if (usingdefaultshader)
{
// If we're using the default shader, substitute the video version.
Shader::defaultVideoShader->attach();
shader = Shader::defaultVideoShader;
prevdefaultshader = Shader::current;
Shader::standardShaders[Shader::STANDARD_VIDEO]->attach();
}
shader->setVideoTextures(images[0], images[1], images[2]);
if (Shader::current != nullptr)
Shader::current->setVideoTextures(images[0], images[1], images[2]);
Graphics::StreamDrawRequest req;
req.formats[0] = vertex::CommonFormat::XYf_STf_RGBAub;
@@ -142,8 +144,8 @@ void Video::draw(Graphics *gfx, const Matrix4 &m)
gfx->flushStreamDraws();
if (usingdefaultshader)
Shader::defaultShader->attach();
if (usingdefaultshader && prevdefaultshader != nullptr)
prevdefaultshader->attach();
}
void Video::update()
+1 -1
View File
@@ -140,7 +140,7 @@ Canvas::Canvas(const Settings &settings)
this->format = getSizedFormat(settings.format);
initVertices();
initQuad();
loadVolatile();
if (status != GL_FRAMEBUFFER_COMPLETE)
+23 -13
View File
@@ -268,25 +268,19 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
restoreState(states.back());
int gammacorrect = isGammaCorrect() ? 1 : 0;
Shader::Language target = getShaderLanguageTarget();
// We always need a default shader.
if (!Shader::defaultShader)
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++)
{
Shader::Language target = getShaderLanguageTarget();
Shader::defaultShader = newShader(defaultShaderCode[target][gammacorrect]);
}
// and a default video shader.
if (!Shader::defaultVideoShader)
{
Shader::Language target = getShaderLanguageTarget();
Shader::defaultVideoShader = newShader(defaultVideoShaderCode[target][gammacorrect]);
if (!Shader::standardShaders[i])
Shader::standardShaders[i] = newShader(defaultShaderCode[i][target][gammacorrect]);
}
// A shader should always be active, but the default shader shouldn't be
// returned by getShader(), so we don't do setShader(defaultShader).
if (!Shader::current)
Shader::defaultShader->attach();
Shader::standardShaders[Shader::STANDARD_DEFAULT]->attach();
return true;
}
@@ -343,8 +337,21 @@ void Graphics::flushStreamDraws()
if (sbstate.vertexCount == 0 && sbstate.indexCount == 0)
return;
if (Shader::current && sbstate.texture.get())
Shader::current->checkMainTextureType(sbstate.texture->getTextureType());
love::graphics::Shader *prevdefaultshader = nullptr;
if (sbstate.texture.get())
{
TextureType textype = sbstate.texture->getTextureType();
if (textype == TEXTURE_2D_ARRAY && Shader::isDefaultActive())
{
prevdefaultshader = Shader::current;
Shader::standardShaders[Shader::STANDARD_ARRAY]->attach();
}
if (Shader::current)
Shader::current->checkMainTextureType(textype);
}
OpenGL::TempDebugGroup debuggroup("Stream vertices flush and draw");
@@ -425,6 +432,9 @@ void Graphics::flushStreamDraws()
streamBufferState.vertexCount = 0;
streamBufferState.indexCount = 0;
if (prevdefaultshader != nullptr)
prevdefaultshader->attach();
}
static void APIENTRY debugCB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*len*/, const GLchar *msg, const GLvoid* /*usr*/)
+1 -1
View File
@@ -92,8 +92,8 @@ void Image::init(PixelFormat fmt, int w, int h, const Settings &settings)
if (getMipmapCount() > 1)
filter.mipmap = defaultMipmapFilter;
initQuad();
loadVolatile();
initVertices();
}
void Image::generateMipmaps()
+9
View File
@@ -650,6 +650,10 @@ void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, s)));
break;
case CommonFormat::XYf_STPf:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, s)));
break;
case CommonFormat::XYf_STf_RGBAub:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, s)));
@@ -660,6 +664,11 @@ void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, color.r)));
break;
case CommonFormat::XYf_STPf_RGBAub:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, x)));
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, color.r)));
break;
}
}
+28 -6
View File
@@ -60,8 +60,21 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
gfx->flushStreamDraws();
if (Shader::current && texture.get())
Shader::current->checkMainTextureType(texture->getTextureType());
Shader *prevdefaultshader = nullptr;
if (texture.get())
{
TextureType textype = texture->getTextureType();
if (textype == TEXTURE_2D_ARRAY && Shader::isDefaultActive())
{
prevdefaultshader = Shader::current;
Shader::standardShaders[Shader::STANDARD_ARRAY]->attach();
}
if (Shader::current)
Shader::current->checkMainTextureType(texture->getTextureType());
}
OpenGL::TempDebugGroup debuggroup("SpriteBatch draw");
@@ -72,13 +85,19 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
array_buf->unmap();
CommonFormat format = CommonFormat::XYf_STf_RGBAub;
if (color == nullptr)
format = CommonFormat::XYf_STf;
CommonFormat format = vertex_format;
if (!color_active)
{
if (format == CommonFormat::XYf_STPf_RGBAub)
format = CommonFormat::XYf_STPf;
else
format = CommonFormat::XYf_STf;
}
uint32 enabledattribs = getFormatFlags(format);
gl.setVertexPointers(format, array_buf, getFormatStride(CommonFormat::XYf_STf_RGBAub), 0);
gl.setVertexPointers(format, array_buf, format_stride, 0);
for (const auto &it : attached_attributes)
{
@@ -116,6 +135,9 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
gl.drawElements(GL_TRIANGLES, (GLsizei) quad_indices.getIndexCount(count), gltype, indices);
}
if (prevdefaultshader != nullptr)
prevdefaultshader->attach();
}
} // opengl
+8
View File
@@ -30,8 +30,10 @@ namespace vertex
static_assert(sizeof(Color) == 4, "sizeof(Color) incorrect!");
static_assert(sizeof(XYf_STf) == sizeof(float)*2 + sizeof(float)*2, "sizeof(XYf_STf) incorrect!");
static_assert(sizeof(XYf_STPf) == sizeof(float)*2 + sizeof(float)*3, "sizeof(XYf_STPf) incorrect!");
static_assert(sizeof(XYf_STf_RGBAub) == sizeof(float)*2 + sizeof(float)*2 + sizeof(Color), "sizeof(XYf_STf_RGBAub) incorrect!");
static_assert(sizeof(XYf_STus_RGBAub) == sizeof(float)*2 + sizeof(uint16)*2 + sizeof(Color), "sizeof(XYf_STus_RGBAub) incorrect!");
static_assert(sizeof(XYf_STPf_RGBAub) == sizeof(float)*2 + sizeof(float)*3 + sizeof(Color), "sizeof(XYf_STPf_RGBAub) incorrect!");
size_t getFormatStride(CommonFormat format)
{
@@ -45,10 +47,14 @@ size_t getFormatStride(CommonFormat format)
return sizeof(uint8) * 4;
case CommonFormat::XYf_STf:
return sizeof(XYf_STf);
case CommonFormat::XYf_STPf:
return sizeof(XYf_STPf);
case CommonFormat::XYf_STf_RGBAub:
return sizeof(XYf_STf_RGBAub);
case CommonFormat::XYf_STus_RGBAub:
return sizeof(XYf_STus_RGBAub);
case CommonFormat::XYf_STPf_RGBAub:
return sizeof(XYf_STPf_RGBAub);
}
}
@@ -63,9 +69,11 @@ uint32 getFormatFlags(CommonFormat format)
case CommonFormat::RGBAub:
return ATTRIBFLAG_COLOR;
case CommonFormat::XYf_STf:
case CommonFormat::XYf_STPf:
return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD;
case CommonFormat::XYf_STf_RGBAub:
case CommonFormat::XYf_STus_RGBAub:
case CommonFormat::XYf_STPf_RGBAub:
return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR;
}
+15
View File
@@ -97,8 +97,10 @@ enum class CommonFormat
XYf,
RGBAub,
XYf_STf,
XYf_STPf,
XYf_STf_RGBAub,
XYf_STus_RGBAub,
XYf_STPf_RGBAub,
};
struct XYf_STf
@@ -107,6 +109,12 @@ struct XYf_STf
float s, t;
};
struct XYf_STPf
{
float x, y;
float s, t, p;
};
struct XYf_STf_RGBAub
{
float x, y;
@@ -121,6 +129,13 @@ struct XYf_STus_RGBAub
Color color;
};
struct XYf_STPf_RGBAub
{
float x, y;
float s, t, p;
Color color;
};
size_t getFormatStride(CommonFormat format);
uint32 getFormatFlags(CommonFormat format);
size_t getIndexDataSize(IndexDataType type);
+71 -70
View File
@@ -828,6 +828,7 @@ int w_newQuad(lua_State *L)
double sw = 0.0f;
double sh = 0.0f;
int layer = 0;
if (luax_istype(L, 5, Texture::type))
{
@@ -835,6 +836,19 @@ int w_newQuad(lua_State *L)
sw = texture->getWidth();
sh = texture->getHeight();
}
else if (luax_istype(L, 6, Texture::type))
{
layer = (int) luaL_checknumber(L, 5) - 1;
Texture *texture = luax_checktexture(L, 6);
sw = texture->getWidth();
sh = texture->getHeight();
}
else if (!lua_isnoneornil(L, 7))
{
layer = (int) luaL_checknumber(L, 5) - 1;
sw = luaL_checknumber(L, 6);
sh = luaL_checknumber(L, 7);
}
else
{
sw = luaL_checknumber(L, 5);
@@ -842,6 +856,8 @@ int w_newQuad(lua_State *L)
}
Quad *quad = instance()->newQuad(v, sw, sh);
quad->setLayer(layer);
luax_pushtype(L, quad);
quad->release();
return 1;
@@ -1761,19 +1777,25 @@ int w_setDefaultShaderCode(lua_State *L)
lua_getfield(L, -1, "vertex");
lua_getfield(L, -2, "pixel");
lua_getfield(L, -3, "videopixel");
lua_getfield(L, -4, "arraypixel");
Shader::ShaderSource code;
code.vertex = luax_checkstring(L, -3);
code.pixel = luax_checkstring(L, -2);
code.vertex = luax_checkstring(L, -4);
code.pixel = luax_checkstring(L, -3);
Shader::ShaderSource videocode;
videocode.vertex = luax_checkstring(L, -3);
videocode.pixel = luax_checkstring(L, -1);
videocode.vertex = luax_checkstring(L, -4);
videocode.pixel = luax_checkstring(L, -2);
lua_pop(L, 4);
Shader::ShaderSource arraycode;
arraycode.vertex = luax_checkstring(L, -4);
arraycode.pixel = luax_checkstring(L, -1);
Graphics::defaultShaderCode[lang][i] = code;
Graphics::defaultVideoShaderCode[lang][i] = videocode;
lua_pop(L, 5);
Graphics::defaultShaderCode[Shader::STANDARD_DEFAULT][lang][i] = code;
Graphics::defaultShaderCode[Shader::STANDARD_VIDEO][lang][i] = videocode;
Graphics::defaultShaderCode[Shader::STANDARD_ARRAY][lang][i] = arraycode;
}
}
@@ -1927,37 +1949,48 @@ int w_draw(lua_State *L)
startidx = 2;
}
if (luax_istype(L, startidx, math::Transform::type))
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
{
math::Transform *tf = luax_totype<math::Transform>(L, startidx);
luax_catchexcept(L, [&]() {
if (texture && quad)
instance()->draw(texture, quad, tf->getMatrix());
else
instance()->draw(drawable, tf->getMatrix());
});
}
else
{
float x = (float) luaL_optnumber(L, startidx + 0, 0.0);
float y = (float) luaL_optnumber(L, startidx + 1, 0.0);
float a = (float) luaL_optnumber(L, startidx + 2, 0.0);
float sx = (float) luaL_optnumber(L, startidx + 3, 1.0);
float sy = (float) luaL_optnumber(L, startidx + 4, sx);
float ox = (float) luaL_optnumber(L, startidx + 5, 0.0);
float oy = (float) luaL_optnumber(L, startidx + 6, 0.0);
float kx = (float) luaL_optnumber(L, startidx + 7, 0.0);
float ky = (float) luaL_optnumber(L, startidx + 8, 0.0);
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&]() {
luax_catchexcept(L, [&]()
{
if (texture && quad)
instance()->draw(texture, quad, m);
else if (drawable)
else
instance()->draw(drawable, m);
});
});
return 0;
}
int w_drawLayer(lua_State *L)
{
Texture *texture = luax_checktexture(L, 1);
Quad *quad = nullptr;
int layer = (int) luaL_checknumber(L, 2) - 1;
int startidx = 3;
if (luax_istype(L, startidx, Quad::type))
{
texture = luax_checktexture(L, 1);
quad = luax_totype<Quad>(L, startidx);
startidx++;
}
else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1))
{
return luax_typerror(L, startidx, "Quad");
}
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
{
luax_catchexcept(L, [&]()
{
if (quad)
instance()->drawLayer(texture, layer, quad, m);
else
instance()->drawLayer(texture, layer, m);
});
});
return 0;
}
@@ -1967,27 +2000,10 @@ int w_drawInstanced(lua_State *L)
Mesh *t = luax_checkmesh(L, 1);
int instancecount = (int) luaL_checkinteger(L, 2);
if (luax_istype(L, 3, math::Transform::type))
luax_checkstandardtransform(L, 3, [&](const Matrix4 &m)
{
math::Transform *tf = luax_totype<math::Transform>(L, 3);
luax_catchexcept(L, [&]() { instance()->drawInstanced(t, tf->getMatrix(), instancecount); });
}
else
{
float x = (float) luaL_optnumber(L, 3, 0.0);
float y = (float) luaL_optnumber(L, 4, 0.0);
float a = (float) luaL_optnumber(L, 5, 0.0);
float sx = (float) luaL_optnumber(L, 6, 1.0);
float sy = (float) luaL_optnumber(L, 7, sx);
float ox = (float) luaL_optnumber(L, 8, 0.0);
float oy = (float) luaL_optnumber(L, 9, 0.0);
float kx = (float) luaL_optnumber(L, 10, 0.0);
float ky = (float) luaL_optnumber(L, 11, 0.0);
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&]() { instance()->drawInstanced(t, m, instancecount); });
}
});
return 0;
}
@@ -1997,27 +2013,11 @@ int w_print(lua_State *L)
std::vector<Font::ColoredString> str;
luax_checkcoloredstring(L, 1, str);
if (luax_istype(L, 2, math::Transform::type))
luax_checkstandardtransform(L, 2, [&](const Matrix4 &m)
{
math::Transform *tf = luax_totype<math::Transform>(L, 2);
luax_catchexcept(L, [&](){ instance()->print(str, tf->getMatrix()); });
}
else
{
float x = (float)luaL_optnumber(L, 2, 0.0);
float y = (float)luaL_optnumber(L, 3, 0.0);
float angle = (float)luaL_optnumber(L, 4, 0.0f);
float sx = (float)luaL_optnumber(L, 5, 1.0f);
float sy = (float)luaL_optnumber(L, 6, sx);
float ox = (float)luaL_optnumber(L, 7, 0.0f);
float oy = (float)luaL_optnumber(L, 8, 0.0f);
float kx = (float)luaL_optnumber(L, 9, 0.0f);
float ky = (float)luaL_optnumber(L, 10, 0.0f);
Matrix4 m(x, y, angle, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&](){ instance()->print(str, m); });
}
});
return 0;
}
@@ -2519,6 +2519,7 @@ static const luaL_Reg functions[] =
{ "captureScreenshot", w_captureScreenshot },
{ "draw", w_draw },
{ "drawLayer", w_drawLayer },
{ "drawInstanced", w_drawInstanced },
{ "print", w_print },
+6
View File
@@ -412,6 +412,11 @@ vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
videopixel = [[
vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
return VideoTexel(texcoord) * vcolor;
}]],
arraypixel = [[
uniform ArrayImage MainTex;
void effect() {
love_PixelColor = Texel(MainTex, VaryingTexCoord.xyz) * VaryingColor;
}]],
}
@@ -432,6 +437,7 @@ for lang, info in pairs(langs) do
vertex = createShaderStageCode("VERTEX", defaultcode.vertex, info.target, info.gles, false, gammacorrect),
pixel = createShaderStageCode("PIXEL", defaultcode.pixel, info.target, info.gles, false, gammacorrect, false),
videopixel = createShaderStageCode("PIXEL", defaultcode.videopixel, info.target, info.gles, false, gammacorrect, false),
arraypixel = createShaderStageCode("PIXEL", defaultcode.arraypixel, info.target, info.gles, false, gammacorrect, true),
}
end
end
+17
View File
@@ -74,11 +74,28 @@ int w_Quad_getTextureDimensions(lua_State *L)
return 2;
}
int w_Quad_setLayer(lua_State *L)
{
Quad *quad = luax_checkquad(L, 1);
int layer = (int) luaL_checknumber(L, 2) - 1;
quad->setLayer(layer);
return 0;
}
int w_Quad_getLayer(lua_State *L)
{
Quad *quad = luax_checkquad(L, 1);
lua_pushnumber(L, quad->getLayer() + 1);
return 1;
}
static const luaL_Reg w_Quad_functions[] =
{
{ "setViewport", w_Quad_setViewport },
{ "getViewport", w_Quad_getViewport },
{ "getTextureDimensions", w_Quad_getTextureDimensions },
{ "setLayer", w_Quad_setLayer },
{ "getLayer", w_Quad_getLayer },
{ 0, 0 }
};
+61 -32
View File
@@ -23,7 +23,6 @@
#include "Image.h"
#include "Canvas.h"
#include "wrap_Texture.h"
#include "math/wrap_Transform.h"
namespace love
{
@@ -47,37 +46,44 @@ static inline int w_SpriteBatch_add_or_set(lua_State *L, SpriteBatch *t, int sta
else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1))
return luax_typerror(L, startidx, "Quad");
if (luax_istype(L, startidx, math::Transform::type))
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
{
math::Transform *tf = luax_totype<math::Transform>(L, startidx);
luax_catchexcept(L, [&]() {
luax_catchexcept(L, [&]()
{
if (quad)
index = t->addq(quad, tf->getMatrix(), index);
else
index = t->add(tf->getMatrix(), index);
});
}
else
{
float x = (float) luaL_optnumber(L, startidx + 0, 0.0);
float y = (float) luaL_optnumber(L, startidx + 1, 0.0);
float a = (float) luaL_optnumber(L, startidx + 2, 0.0);
float sx = (float) luaL_optnumber(L, startidx + 3, 1.0);
float sy = (float) luaL_optnumber(L, startidx + 4, sx);
float ox = (float) luaL_optnumber(L, startidx + 5, 0.0);
float oy = (float) luaL_optnumber(L, startidx + 6, 0.0);
float kx = (float) luaL_optnumber(L, startidx + 7, 0.0);
float ky = (float) luaL_optnumber(L, startidx + 8, 0.0);
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&]() {
if (quad)
index = t->addq(quad, m, index);
index = t->add(quad, m, index);
else
index = t->add(m, index);
});
});
return index;
}
static int w_SpriteBatch_addLayer_or_setLayer(lua_State *L, SpriteBatch *t, int startidx, int index)
{
Quad *quad = nullptr;
int layer = (int) luaL_checknumber(L, startidx) - 1;
startidx++;
if (luax_istype(L, startidx, Quad::type))
{
quad = luax_totype<Quad>(L, startidx);
startidx++;
}
else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1))
return luax_typerror(L, startidx, "Quad");
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
{
luax_catchexcept(L, [&]()
{
if (quad)
index = t->addLayer(layer, quad, m, index);
else
index = t->addLayer(layer, m, index);
});
});
return index;
}
@@ -102,6 +108,26 @@ int w_SpriteBatch_set(lua_State *L)
return 0;
}
int w_SpriteBatch_addLayer(lua_State *L)
{
SpriteBatch *t = luax_checkspritebatch(L, 1);
int index = w_SpriteBatch_addLayer_or_setLayer(L, t, 2, -1);
lua_pushinteger(L, index + 1);
return 1;
}
int w_SpriteBatch_setLayer(lua_State *L)
{
SpriteBatch *t = luax_checkspritebatch(L, 1);
int index = (int) luaL_checknumber(L, 2) - 1;
w_SpriteBatch_addLayer_or_setLayer(L, t, 3, index);
return 0;
}
int w_SpriteBatch_clear(lua_State *L)
{
SpriteBatch *t = luax_checkspritebatch(L, 1);
@@ -178,16 +204,17 @@ int w_SpriteBatch_setColor(lua_State *L)
int w_SpriteBatch_getColor(lua_State *L)
{
SpriteBatch *t = luax_checkspritebatch(L, 1);
const Color *color = t->getColor();
bool active = false;
const Color &color = t->getColor(active);
// getColor returns null if no color is set.
if (!color)
if (!active)
return 0;
lua_pushnumber(L, (lua_Number) color->r / 255.0);
lua_pushnumber(L, (lua_Number) color->g / 255.0);
lua_pushnumber(L, (lua_Number) color->b / 255.0);
lua_pushnumber(L, (lua_Number) color->a / 255.0);
lua_pushnumber(L, (lua_Number) color.r / 255.0);
lua_pushnumber(L, (lua_Number) color.g / 255.0);
lua_pushnumber(L, (lua_Number) color.b / 255.0);
lua_pushnumber(L, (lua_Number) color.a / 255.0);
return 4;
}
@@ -250,6 +277,8 @@ static const luaL_Reg w_SpriteBatch_functions[] =
{
{ "add", w_SpriteBatch_add },
{ "set", w_SpriteBatch_set },
{ "addLayer", w_SpriteBatch_addLayer },
{ "setLayer", w_SpriteBatch_setLayer },
{ "clear", w_SpriteBatch_clear },
{ "flush", w_SpriteBatch_flush },
{ "setTexture", w_SpriteBatch_setTexture },
+24
View File
@@ -22,12 +22,36 @@
#include "common/runtime.h"
#include "SpriteBatch.h"
#include "math/wrap_Transform.h"
namespace love
{
namespace graphics
{
template <typename T>
static void luax_checkstandardtransform(lua_State *L, int idx, const T &func)
{
if (luax_istype(L, idx, math::Transform::type))
{
math::Transform *tf = luax_totype<math::Transform>(L, idx);
func(tf->getMatrix());
}
else
{
float x = (float) luaL_optnumber(L, idx + 0, 0.0);
float y = (float) luaL_optnumber(L, idx + 1, 0.0);
float a = (float) luaL_optnumber(L, idx + 2, 0.0);
float sx = (float) luaL_optnumber(L, idx + 3, 1.0);
float sy = (float) luaL_optnumber(L, idx + 4, sx);
float ox = (float) luaL_optnumber(L, idx + 5, 0.0);
float oy = (float) luaL_optnumber(L, idx + 6, 0.0);
float kx = (float) luaL_optnumber(L, idx + 7, 0.0);
float ky = (float) luaL_optnumber(L, idx + 8, 0.0);
func(Matrix4(x, y, a, sx, sy, ox, oy, kx, ky));
}
}
SpriteBatch *luax_checkspritebatch(lua_State *L, int idx);
extern "C" int luaopen_spritebatch(lua_State *L);