Added stack type enums to love.graphics.push (resolves issue #906.) Current enums are "transform" and "all". "transform" is the default (for compatibility.) When love.graphics.push("all") is used, love.graphics.pop() will restore all love.graphics module state to what it was when push was called.

Updated the graphics code to use a custom matrix stack rather than OpenGL1's APIs.
This commit is contained in:
Alex Szpakowski
2014-08-06 22:25:29 -03:00
parent 028108ea64
commit afc505e183
18 changed files with 726 additions and 415 deletions
+14
View File
@@ -194,5 +194,19 @@ void Matrix::transform(Vertex *dst, const Vertex *src, int size) const
}
}
Matrix Matrix::ortho(float left, float right, float bottom, float top)
{
Matrix m;
m.e[0] = 2.0f / (right - left);
m.e[5] = 2.0f / (top - bottom);
m.e[10] = -1.0;
m.e[12] = -(right + left) / (right - left);
m.e[13] = -(top + bottom) / (top - bottom);
return m;
}
} // love
+6
View File
@@ -150,6 +150,12 @@ public:
**/
void transform(Vertex *dst, const Vertex *src, int size) const;
/**
* Creates a new orthographic projection matrix with depth in the range of
* [-1, 1].
**/
static Matrix ortho(float left, float right, float bottom, float top);
private:
/**
+18
View File
@@ -109,6 +109,16 @@ bool Graphics::getConstant(SystemLimit in, const char *&out)
return systemLimits.find(in, out);
}
bool Graphics::getConstant(const char *in, StackType &out)
{
return stackTypes.find(in, out);
}
bool Graphics::getConstant(StackType in, const char *&out)
{
return stackTypes.find(in, out);
}
StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM>::Entry Graphics::drawModeEntries[] =
{
{ "line", Graphics::DRAW_LINE },
@@ -192,5 +202,13 @@ StringMap<Graphics::SystemLimit, Graphics::LIMIT_MAX_ENUM>::Entry Graphics::syst
StringMap<Graphics::SystemLimit, Graphics::LIMIT_MAX_ENUM> Graphics::systemLimits(Graphics::systemLimitEntries, sizeof(Graphics::systemLimitEntries));
StringMap<Graphics::StackType, Graphics::STACK_MAX_ENUM>::Entry Graphics::stackTypeEntries[] =
{
{"all", Graphics::STACK_ALL},
{"transform", Graphics::STACK_TRANSFORM},
};
StringMap<Graphics::StackType, Graphics::STACK_MAX_ENUM> Graphics::stackTypes(Graphics::stackTypeEntries, sizeof(Graphics::stackTypeEntries));
} // graphics
} // love
+13
View File
@@ -112,6 +112,13 @@ public:
LIMIT_MAX_ENUM
};
enum StackType
{
STACK_ALL,
STACK_TRANSFORM,
STACK_MAX_ENUM
};
struct RendererInfo
{
std::string name;
@@ -167,6 +174,9 @@ public:
static bool getConstant(const char *in, SystemLimit &out);
static bool getConstant(SystemLimit in, const char *&out);
static bool getConstant(const char *in, StackType &out);
static bool getConstant(StackType in, const char *&out);
private:
static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[];
@@ -193,6 +203,9 @@ private:
static StringMap<SystemLimit, LIMIT_MAX_ENUM>::Entry systemLimitEntries[];
static StringMap<SystemLimit, LIMIT_MAX_ENUM> systemLimits;
static StringMap<StackType, STACK_MAX_ENUM>::Entry stackTypeEntries[];
static StringMap<StackType, STACK_MAX_ENUM> stackTypes;
}; // Graphics
} // graphics
+7 -35
View File
@@ -594,16 +594,13 @@ void Canvas::unloadVolatile()
fbo = depth_stencil = texture = 0;
resolve_fbo = msaa_buffer = 0;
for (size_t i = 0; i < attachedCanvases.size(); i++)
attachedCanvases[i]->release();
attachedCanvases.clear();
}
void Canvas::drawv(const Matrix &t, const Vertex *v)
{
glPushMatrix();
glMultMatrixf((const GLfloat *)t.getElements());
OpenGL::TempTransform transform(gl);
transform.get() *= t;
predraw();
@@ -620,8 +617,6 @@ void Canvas::drawv(const Matrix &t, const Vertex *v)
glDisableClientState(GL_VERTEX_ARRAY);
postdraw();
glPopMatrix();
}
void Canvas::draw(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
@@ -691,16 +686,8 @@ void Canvas::setupGrab()
strategy->bindFBO(fbo);
gl.setViewport(OpenGL::Viewport(0, 0, width, height));
// Reset the projection matrix
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// Set up orthographic view (no depth)
glOrtho(0.0, width, 0.0, height, -1.0, 1.0);
// Switch back to modelview matrix
glMatrixMode(GL_MODELVIEW);
// Set up the projection matrix
gl.matrices.projection.push_back(Matrix::ortho(0.0, width, 0.0, height));
// Make sure the correct sRGB setting is used when drawing to the canvas.
if (format == FORMAT_SRGB)
@@ -754,11 +741,8 @@ void Canvas::startGrab(const std::vector<Canvas *> &canvases)
// Attach the canvas textures to the active FBO and set up MRTs.
strategy->setAttachments(canvases);
for (size_t i = 0; i < canvases.size(); i++)
canvases[i]->retain();
for (size_t i = 0; i < attachedCanvases.size(); i++)
attachedCanvases[i]->release();
// We want to avoid reference cycles, so we don't retain the attached
// Canvases here. The code in Graphics::setCanvas retains them.
attachedCanvases = canvases;
}
@@ -773,10 +757,6 @@ void Canvas::startGrab()
// make sure the FBO is only using a single canvas
strategy->setAttachments();
// release any previously attached canvases
for (size_t i = 0; i < attachedCanvases.size(); i++)
attachedCanvases[i]->release();
attachedCanvases.clear();
}
@@ -786,9 +766,7 @@ void Canvas::stopGrab(bool switchingToOtherCanvas)
if (current != this)
return;
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
gl.matrices.projection.pop_back();
if (switchingToOtherCanvas)
{
@@ -1123,12 +1101,6 @@ bool Canvas::isFormatSupported(Canvas::Format format)
return supported;
}
void Canvas::bindDefaultCanvas()
{
if (current != nullptr)
current->stopGrab();
}
bool Canvas::getConstant(const char *in, Format &out)
{
return formats.find(in, out);
-1
View File
@@ -120,7 +120,6 @@ public:
static bool isFormatSupported(Format format);
static Canvas *current;
static void bindDefaultCanvas();
// The viewport dimensions of the system (default) framebuffer.
static OpenGL::Viewport systemViewport;
+3 -5
View File
@@ -368,11 +368,11 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing,
// second (using the struct's < operator).
std::sort(glyphinfolist.begin(), glyphinfolist.end());
glPushMatrix();
Matrix t;
t.setTransformation(ceilf(x), ceilf(y), angle, sx, sy, ox, oy, kx, ky);
glMultMatrixf((const GLfloat *)t.getElements());
OpenGL::TempTransform transform(gl);
transform.get() *= t;
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -393,8 +393,6 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing,
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
}
int Font::getWidth(const std::string &str)
File diff suppressed because it is too large Load Diff
+59 -56
View File
@@ -57,48 +57,7 @@ namespace opengl
// During display mode changing, certain
// variables about the OpenGL context are
// lost.
struct DisplayState
{
// Colors.
Color color;
Color backgroundColor;
// Blend mode.
Graphics::BlendMode blendMode;
// Line.
Graphics::LineStyle lineStyle;
Graphics::LineJoin lineJoin;
// Point.
float pointSize;
Graphics::PointStyle pointStyle;
// Scissor.
bool scissor;
OpenGL::Viewport scissorBox;
// Color mask.
bool colorMask[4];
bool wireframe;
// Default values.
DisplayState()
{
color.set(255,255,255,255);
backgroundColor.set(0, 0, 0, 255);
blendMode = Graphics::BLEND_ALPHA;
lineStyle = Graphics::LINE_SMOOTH;
lineJoin = Graphics::LINE_JOIN_MITER;
pointSize = 1.0f;
pointStyle = Graphics::POINT_SMOOTH;
scissor = false;
colorMask[0] = colorMask[1] = colorMask[2] = colorMask[3] = true;
wireframe = false;
}
};
class Graphics : public love::graphics::Graphics
{
@@ -110,10 +69,6 @@ public:
// Implements Module.
const char *getName() const;
DisplayState saveState();
void restoreState(const DisplayState &s);
virtual void setViewportSize(int width, int height);
virtual bool setMode(int width, int height, bool &sRGB);
virtual void unSetMode();
@@ -246,10 +201,21 @@ public:
**/
Font *getFont() const;
void setShader(Shader *shader);
void setShader();
Shader *getShader() const;
void setCanvas(Canvas *canvas);
void setCanvas(const std::vector<Canvas *> &canvases);
void setCanvas();
std::vector<Canvas *> getCanvas() const;
/**
* Sets the enabled color components when rendering.
**/
void setColorMask(bool r, bool g, bool b, bool a);
void setColorMask(const bool mask[4]);
/**
* Gets the current color mask.
@@ -460,8 +426,9 @@ public:
**/
bool isSupported(Support feature) const;
void push();
void push(StackType type = STACK_TRANSFORM);
void pop();
void rotate(float r);
void scale(float x, float y = 1.0f);
void translate(float x, float y);
@@ -470,17 +437,50 @@ public:
private:
Font *currentFont;
struct DisplayState
{
// Colors.
Color color;
Color backgroundColor;
// Blend mode.
BlendMode blendMode;
// Line.
float lineWidth;
LineStyle lineStyle;
LineJoin lineJoin;
// Point.
float pointSize;
PointStyle pointStyle;
// Scissor.
bool scissor;
OpenGL::Viewport scissorBox;
Font *font;
Shader *shader;
std::vector<Canvas *> canvases;
// Color mask.
bool colorMask[4];
bool wireframe;
DisplayState();
DisplayState(const DisplayState &other);
~DisplayState();
DisplayState &operator = (const DisplayState &other);
};
void restoreState(const DisplayState &s);
void restoreStateChecked(const DisplayState &s);
love::window::Window *currentWindow;
std::vector<double> pixel_size_stack; // stores current size of a pixel (needed for line drawing)
LineStyle lineStyle;
LineJoin lineJoin;
float lineWidth;
GLint matrixLimit;
GLint userMatrices;
bool colorMask[4];
bool wireframe;
int width;
int height;
@@ -488,7 +488,10 @@ private:
bool activeStencil;
DisplayState savedState;
std::vector<DisplayState> states;
std::vector<StackType> stackTypes; // Keeps track of the pushed stack types.
static const size_t MAX_USER_STACK_DEPTH = 64;
}; // Graphics
+3 -6
View File
@@ -526,12 +526,11 @@ void Image::uploadDefaultTexture()
void Image::drawv(const Matrix &t, const Vertex *v)
{
OpenGL::TempTransform transform(gl);
transform.get() *= t;
predraw();
glPushMatrix();
glMultMatrixf((const GLfloat *)t.getElements());
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -544,8 +543,6 @@ void Image::drawv(const Matrix &t, const Vertex *v)
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
postdraw();
}
+2 -4
View File
@@ -342,8 +342,8 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
Matrix m;
m.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
glPushMatrix();
glMultMatrixf(m.getElements());
OpenGL::TempTransform transform(gl);
transform.get() *= m;
VertexBuffer::Bind vbo_bind(*vbo);
@@ -412,8 +412,6 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
gl.setColor(gl.getColor());
}
glPopMatrix();
if (texture)
texture->postdraw();
}
+60 -3
View File
@@ -28,6 +28,7 @@
// C++
#include <algorithm>
#include <limits>
// C
#include <cstring>
@@ -47,6 +48,8 @@ OpenGL::OpenGL()
, vendor(VENDOR_UNKNOWN)
, state()
{
matrices.transform.reserve(10);
matrices.projection.reserve(2);
}
void OpenGL::initContext()
@@ -56,6 +59,7 @@ void OpenGL::initContext()
initOpenGLFunctions();
initVendor();
initMatrices();
// Store the current color so we don't have to get it through GL later.
GLfloat glcolor[4];
@@ -119,6 +123,13 @@ void OpenGL::initContext()
state.lastPseudoInstanceID = -1;
// Invalidate the cached matrices by setting some elements to NaN.
float nan = std::numeric_limits<float>::quiet_NaN();
state.lastProjectionMatrix.setTranslation(nan, nan);
state.lastTransformMatrix.setTranslation(nan, nan);
glMatrixMode(GL_MODELVIEW);
contextInitialized = true;
}
@@ -209,6 +220,15 @@ void OpenGL::initMaxValues()
maxRenderTargets = 0;
}
void OpenGL::initMatrices()
{
matrices.transform.clear();
matrices.projection.clear();
matrices.transform.push_back(Matrix());
matrices.projection.push_back(Matrix());
}
void OpenGL::createDefaultTexture()
{
// Set the 'default' texture (id 0) as a repeating white pixel. Otherwise,
@@ -231,6 +251,21 @@ void OpenGL::createDefaultTexture()
bindTexture(curtexture);
}
void OpenGL::pushTransform()
{
matrices.transform.push_back(matrices.transform.back());
}
void OpenGL::popTransform()
{
matrices.transform.pop_back();
}
Matrix &OpenGL::getTransform()
{
return matrices.transform.back();
}
void OpenGL::prepareDraw()
{
Shader *shader = Shader::current;
@@ -251,15 +286,37 @@ void OpenGL::prepareDraw()
// We need to make sure antialiased Canvases are properly resolved
// before sampling from their textures in a shader.
// This is kind of a big hack. :(
const std::map<std::string, Object *> &r = shader->getBoundRetainables();
for (auto it = r.begin(); it != r.end(); ++it)
for (auto &r : shader->getBoundRetainables())
{
// Even bigger hack! D:
Canvas *canvas = dynamic_cast<Canvas *>(it->second);
Canvas *canvas = dynamic_cast<Canvas *>(r.second);
if (canvas != nullptr)
canvas->resolveMSAA();
}
}
const float *curproj = matrices.projection.back().getElements();
const float *lastproj = state.lastProjectionMatrix.getElements();
// We only need to re-upload the projection matrix if it's changed.
if (memcmp(curproj, lastproj, sizeof(float) * 16) != 0)
{
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(curproj);
glMatrixMode(GL_MODELVIEW);
state.lastProjectionMatrix = matrices.projection.back();
}
const float *curxform = matrices.transform.back().getElements();
const float *lastxform = state.lastTransformMatrix.getElements();
// Same with the transform matrix.
if (memcmp(curxform, lastxform, sizeof(float) * 16) != 0)
{
glLoadMatrixf(curxform);
state.lastTransformMatrix = matrices.transform.back();
}
}
void OpenGL::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+40
View File
@@ -26,9 +26,11 @@
// LOVE
#include "graphics/Color.h"
#include "graphics/Texture.h"
#include "common/Matrix.h"
// C++
#include <vector>
#include <stack>
// The last argument to AttribPointer takes a buffer offset casted to a pointer.
#define BUFFER_OFFSET(i) ((char *) NULL + (i))
@@ -101,6 +103,36 @@ public:
GLenum func;
};
struct
{
std::vector<Matrix> transform;
std::vector<Matrix> projection;
} matrices;
class TempTransform
{
public:
TempTransform(OpenGL &gl)
: gl(gl)
{
gl.pushTransform();
}
~TempTransform()
{
gl.popTransform();
}
Matrix &get()
{
return gl.getTransform();
}
private:
OpenGL &gl;
};
OpenGL();
/**
@@ -116,6 +148,10 @@ public:
**/
void deInitContext();
void pushTransform();
void popTransform();
Matrix &getTransform();
/**
* Set up necessary state (LOVE-provided shader uniforms, etc.) for drawing.
* This *MUST* be called directly before OpenGL drawing functions.
@@ -258,6 +294,7 @@ private:
void initVendor();
void initOpenGLFunctions();
void initMaxValues();
void initMatrices();
void createDefaultTexture();
bool contextInitialized;
@@ -290,6 +327,9 @@ private:
// The last ID value used for pseudo-instancing.
int lastPseudoInstanceID;
Matrix lastProjectionMatrix;
Matrix lastTransformMatrix;
} state;
}; // OpenGL
@@ -843,11 +843,11 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
Color curcolor = gl.getColor();
glPushMatrix();
static Matrix t;
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
glMultMatrixf((const GLfloat *)t.getElements());
OpenGL::TempTransform transform(gl);
transform.get() *= t;
const Vertex *textureVerts = texture->getVertices();
Vertex *pVerts = particleVerts;
@@ -901,8 +901,6 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
texture->postdraw();
glPopMatrix();
gl.setColor(curcolor);
}
+12 -19
View File
@@ -97,8 +97,8 @@ Shader::~Shader()
if (current == this)
detach();
for (auto it = boundRetainables.begin(); it != boundRetainables.end(); ++it)
it->second->release();
for (const auto &retainable : boundRetainables)
retainable.second->release();
boundRetainables.clear();
@@ -178,9 +178,8 @@ void Shader::createProgram(const std::vector<GLuint> &shaderids)
if (program == 0)
throw love::Exception("Cannot create shader program object.");
std::vector<GLuint>::const_iterator it;
for (it = shaderids.begin(); it != shaderids.end(); ++it)
glAttachShader(program, *it);
for (GLuint id : shaderids)
glAttachShader(program, id);
// Bind generic vertex attribute indices to names in the shader.
for (int i = 0; i < int(OpenGL::ATTRIB_MAX_ENUM); i++)
@@ -201,8 +200,8 @@ void Shader::createProgram(const std::vector<GLuint> &shaderids)
glLinkProgram(program);
// flag shaders for auto-deletion when the program object is deleted.
for (it = shaderids.begin(); it != shaderids.end(); ++it)
glDeleteShader(*it);
for (GLuint id : shaderids)
glDeleteShader(id);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
@@ -275,10 +274,9 @@ bool Shader::loadVolatile()
std::vector<GLuint> shaderids;
ShaderSources::const_iterator source;
for (source = shaderSources.begin(); source != shaderSources.end(); ++source)
for (const auto &source : shaderSources)
{
GLuint shaderid = compileCode(source->first, source->second);
GLuint shaderid = compileCode(source.first, source.second);
shaderids.push_back(shaderid);
}
@@ -364,11 +362,10 @@ std::string Shader::getWarnings() const
const char *typestr;
// Get the individual shader stage warnings
std::map<ShaderType, std::string>::const_iterator it;
for (it = shaderWarnings.begin(); it != shaderWarnings.end(); ++it)
for (const auto &warning : shaderWarnings)
{
if (typeNames.find(it->first, typestr))
warnings += std::string(typestr) + std::string(" shader:\n") + it->second;
if (typeNames.find(warning.first, typestr))
warnings += std::string(typestr) + std::string(" shader:\n") + warning.second;
}
warnings += getProgramWarnings();
@@ -380,13 +377,9 @@ void Shader::attach(bool temporary)
{
if (current != this)
{
if (current != nullptr)
current->release();
glUseProgram(program);
current = this;
current->retain();
// retain/release happens in Graphics::setShader.
}
if (!temporary)
+3 -6
View File
@@ -271,11 +271,10 @@ void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float
return;
static Matrix t;
glPushMatrix();
t.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
glMultMatrixf((const GLfloat *)t.getElements());
OpenGL::TempTransform transform(gl);
transform.get() *= t;
texture->predraw();
@@ -314,8 +313,6 @@ void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float
}
texture->postdraw();
glPopMatrix();
}
void SpriteBatch::addv(const Vertex *v, int index)
+18 -9
View File
@@ -19,6 +19,7 @@
**/
#include "wrap_Canvas.h"
#include "Graphics.h"
namespace love
{
@@ -37,18 +38,26 @@ int w_Canvas_renderTo(lua_State *L)
Canvas *canvas = luax_checkcanvas(L, 1);
luaL_checktype(L, 2, LUA_TFUNCTION);
// Save the current Canvas so we can restore it when we're done.
Canvas *oldcanvas = Canvas::current;
Graphics *graphics = Module::getInstance<Graphics>(Module::M_GRAPHICS);
luax_catchexcept(L, [&](){ canvas->startGrab(); });
if (graphics)
{
// Save the current Canvas so we can restore it when we're done.
std::vector<Canvas *> oldcanvases = graphics->getCanvas();
lua_settop(L, 2); // make sure the function is on top of the stack
lua_call(L, 0, 0);
for (Canvas *c : oldcanvases)
c->retain();
if (oldcanvas != nullptr)
oldcanvas->startGrab(oldcanvas->getAttachedCanvases());
else
Canvas::bindDefaultCanvas();
luax_catchexcept(L, [&](){ graphics->setCanvas(canvas); });
lua_settop(L, 2); // make sure the function is on top of the stack
lua_call(L, 0, 0);
graphics->setCanvas(oldcanvases);
for (Canvas *c : oldcanvases)
c->release();
}
return 0;
}
+29 -34
View File
@@ -651,8 +651,7 @@ int w_setColorMask(lua_State *L)
mask[i] = luax_toboolean(L, i + 1);
}
// r, g, b, a
instance()->setColorMask(mask[0], mask[1], mask[2], mask[3]);
instance()->setColorMask(mask);
return 0;
}
@@ -893,43 +892,35 @@ int w_setCanvas(lua_State *L)
instance()->discardStencil();
// called with none -> reset to default buffer
if (lua_isnoneornil(L,1))
if (lua_isnoneornil(L, 1))
{
Canvas::bindDefaultCanvas();
instance()->setCanvas();
return 0;
}
bool is_table = lua_istable(L, 1);
std::vector<Canvas *> attachments;
Canvas *canvas = 0;
std::vector<Canvas *> canvases;
if (is_table)
{
// grab the first canvas in the array and attach the rest
lua_rawgeti(L, 1, 1);
canvas = luax_checkcanvas(L, -1);
lua_pop(L, 1);
for (size_t i = 2; i <= lua_objlen(L, 1); i++)
for (size_t i = 1; i <= lua_objlen(L, 1); i++)
{
lua_rawgeti(L, 1, i);
attachments.push_back(luax_checkcanvas(L, -1));
canvases.push_back(luax_checkcanvas(L, -1));
lua_pop(L, 1);
}
}
else
{
canvas = luax_checkcanvas(L, 1);
for (int i = 2; i <= lua_gettop(L); i++)
attachments.push_back(luax_checkcanvas(L, i));
for (int i = 1; i <= lua_gettop(L); i++)
canvases.push_back(luax_checkcanvas(L, i));
}
luax_catchexcept(L, [&]() {
if (attachments.size() > 0)
canvas->startGrab(attachments);
if (canvases.size() > 0)
instance()->setCanvas(canvases);
else
canvas->startGrab();
instance()->setCanvas();
});
return 0;
@@ -937,24 +928,23 @@ int w_setCanvas(lua_State *L)
int w_getCanvas(lua_State *L)
{
Canvas *canvas = Canvas::current;
int n = 1;
const std::vector<Canvas *> canvases = instance()->getCanvas();
int n = 0;
if (canvas)
if (!canvases.empty())
{
canvas->retain();
luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, canvas);
const std::vector<Canvas *> &attachments = canvas->getAttachedCanvases();
for (size_t i = 0; i < attachments.size(); i++)
for (Canvas *c : canvases)
{
attachments[i]->retain();
luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, attachments[i]);
c->retain();
luax_pushtype(L, "Canvas", GRAPHICS_CANVAS_T, c);
n++;
}
}
else
{
lua_pushnil(L);
n = 1;
}
return n;
}
@@ -963,18 +953,18 @@ int w_setShader(lua_State *L)
{
if (lua_isnoneornil(L,1))
{
Shader::detach();
instance()->setShader();
return 0;
}
Shader *shader = luax_checkshader(L, 1);
shader->attach();
instance()->setShader(shader);
return 0;
}
int w_getShader(lua_State *L)
{
Shader *shader = Shader::current;
Shader *shader = instance()->getShader();
if (shader)
{
shader->retain();
@@ -1323,7 +1313,12 @@ int w_polygon(lua_State *L)
int w_push(lua_State *L)
{
luax_catchexcept(L, [&](){ instance()->push(); });
Graphics::StackType stype = Graphics::STACK_TRANSFORM;
const char *sname = lua_isnoneornil(L, 1) ? nullptr : luaL_checkstring(L, 1);
if (sname && !Graphics::getConstant(sname, stype))
return luaL_error(L, "Invalid graphics stack type: %s", sname);
luax_catchexcept(L, [&](){ instance()->push(stype); });
return 0;
}