mirror of
https://github.com/love2d/love.git
synced 2026-08-20 04:30:09 +02:00
Replaced the old stencil API with love.graphics.drawStencil(stencilfunc), love.graphics.setStencilTest(enable, invert), and love.graphics.getStencilTest.
Draw to the stencil buffer (rather than the color buffer) using love.graphics.drawStencil with a function which draws geometry. Once the stencil buffer has been drawn to, use love.graphics.setStencilTest before drawing to let drawn geometry be affected by it.
love.graphics.clear (and Canvas:clear) will clear both the color and stencil buffers by default. love.graphics.clear("stencil") will clear only the stencil buffer.
--HG--
branch : stencil-functions
This commit is contained in:
@@ -109,6 +109,16 @@ bool Graphics::getConstant(StackType in, const char *&out)
|
|||||||
return stackTypes.find(in, out);
|
return stackTypes.find(in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Graphics::getConstant(const char *in, ClearType &out)
|
||||||
|
{
|
||||||
|
return clearTypes.find(in, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Graphics::getConstant(ClearType in, const char *&out)
|
||||||
|
{
|
||||||
|
return clearTypes.find(in, out);
|
||||||
|
}
|
||||||
|
|
||||||
StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM>::Entry Graphics::drawModeEntries[] =
|
StringMap<Graphics::DrawMode, Graphics::DRAW_MAX_ENUM>::Entry Graphics::drawModeEntries[] =
|
||||||
{
|
{
|
||||||
{ "line", Graphics::DRAW_LINE },
|
{ "line", Graphics::DRAW_LINE },
|
||||||
@@ -183,5 +193,13 @@ StringMap<Graphics::StackType, Graphics::STACK_MAX_ENUM>::Entry Graphics::stackT
|
|||||||
|
|
||||||
StringMap<Graphics::StackType, Graphics::STACK_MAX_ENUM> Graphics::stackTypes(Graphics::stackTypeEntries, sizeof(Graphics::stackTypeEntries));
|
StringMap<Graphics::StackType, Graphics::STACK_MAX_ENUM> Graphics::stackTypes(Graphics::stackTypeEntries, sizeof(Graphics::stackTypeEntries));
|
||||||
|
|
||||||
|
StringMap<Graphics::ClearType, Graphics::CLEAR_MAX_ENUM>::Entry Graphics::clearTypeEntries[] =
|
||||||
|
{
|
||||||
|
{"all", Graphics::CLEAR_ALL},
|
||||||
|
{"stencil", Graphics::CLEAR_STENCIL},
|
||||||
|
};
|
||||||
|
|
||||||
|
StringMap<Graphics::ClearType, Graphics::CLEAR_MAX_ENUM> Graphics::clearTypes(Graphics::clearTypeEntries, sizeof(Graphics::clearTypeEntries));
|
||||||
|
|
||||||
} // graphics
|
} // graphics
|
||||||
} // love
|
} // love
|
||||||
|
|||||||
@@ -103,6 +103,13 @@ public:
|
|||||||
STACK_MAX_ENUM
|
STACK_MAX_ENUM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ClearType
|
||||||
|
{
|
||||||
|
CLEAR_ALL,
|
||||||
|
CLEAR_STENCIL,
|
||||||
|
CLEAR_MAX_ENUM
|
||||||
|
};
|
||||||
|
|
||||||
struct RendererInfo
|
struct RendererInfo
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -158,6 +165,9 @@ public:
|
|||||||
static bool getConstant(const char *in, StackType &out);
|
static bool getConstant(const char *in, StackType &out);
|
||||||
static bool getConstant(StackType in, const char *&out);
|
static bool getConstant(StackType in, const char *&out);
|
||||||
|
|
||||||
|
static bool getConstant(const char *in, ClearType &out);
|
||||||
|
static bool getConstant(ClearType in, const char *&out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[];
|
static StringMap<DrawMode, DRAW_MAX_ENUM>::Entry drawModeEntries[];
|
||||||
@@ -184,6 +194,9 @@ private:
|
|||||||
static StringMap<StackType, STACK_MAX_ENUM>::Entry stackTypeEntries[];
|
static StringMap<StackType, STACK_MAX_ENUM>::Entry stackTypeEntries[];
|
||||||
static StringMap<StackType, STACK_MAX_ENUM> stackTypes;
|
static StringMap<StackType, STACK_MAX_ENUM> stackTypes;
|
||||||
|
|
||||||
|
static StringMap<ClearType, CLEAR_MAX_ENUM>::Entry clearTypeEntries[];
|
||||||
|
static StringMap<ClearType, CLEAR_MAX_ENUM> clearTypes;
|
||||||
|
|
||||||
}; // Graphics
|
}; // Graphics
|
||||||
|
|
||||||
} // graphics
|
} // graphics
|
||||||
|
|||||||
@@ -823,7 +823,7 @@ void Canvas::clear(Color c)
|
|||||||
// Don't use the state-shadowed gl.setClearColor because we want to save
|
// Don't use the state-shadowed gl.setClearColor because we want to save
|
||||||
// the previous clear color.
|
// the previous clear color.
|
||||||
glClearColor(glcolor[0], glcolor[1], glcolor[2], glcolor[3]);
|
glClearColor(glcolor[0], glcolor[1], glcolor[2], glcolor[3]);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
if (attachedCanvases.size() > 0)
|
if (attachedCanvases.size() > 0)
|
||||||
strategy->setAttachments(attachedCanvases);
|
strategy->setAttachments(attachedCanvases);
|
||||||
@@ -850,6 +850,12 @@ bool Canvas::checkCreateStencil()
|
|||||||
|
|
||||||
bool success = strategy->createStencil(width, height, msaa_samples, depth_stencil);
|
bool success = strategy->createStencil(width, height, msaa_samples, depth_stencil);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
// We don't want the stencil buffer filled with garbage.
|
||||||
|
glClear(GL_STENCIL_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
if (current && current != this)
|
if (current && current != this)
|
||||||
strategy->bindFBO(current->fbo);
|
strategy->bindFBO(current->fbo);
|
||||||
else if (!current)
|
else if (!current)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Graphics::Graphics()
|
|||||||
: width(0)
|
: width(0)
|
||||||
, height(0)
|
, height(0)
|
||||||
, created(false)
|
, created(false)
|
||||||
, activeStencil(false)
|
, writingToStencil(false)
|
||||||
, displayedMinReqWarning(false)
|
, displayedMinReqWarning(false)
|
||||||
{
|
{
|
||||||
states.reserve(10);
|
states.reserve(10);
|
||||||
@@ -95,6 +95,8 @@ void Graphics::restoreState(const DisplayState &s)
|
|||||||
else
|
else
|
||||||
setScissor();
|
setScissor();
|
||||||
|
|
||||||
|
setStencilTest(s.stencilTest, s.stencilInvert);
|
||||||
|
|
||||||
setFont(s.font.get());
|
setFont(s.font.get());
|
||||||
setShader(s.shader.get());
|
setShader(s.shader.get());
|
||||||
setCanvas(s.canvases);
|
setCanvas(s.canvases);
|
||||||
@@ -132,6 +134,9 @@ void Graphics::restoreStateChecked(const DisplayState &s)
|
|||||||
setScissor();
|
setScissor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s.stencilTest != cur.stencilTest || s.stencilInvert != cur.stencilInvert)
|
||||||
|
setStencilTest(s.stencilTest, s.stencilInvert);
|
||||||
|
|
||||||
setFont(s.font.get());
|
setFont(s.font.get());
|
||||||
setShader(s.shader.get());
|
setShader(s.shader.get());
|
||||||
|
|
||||||
@@ -350,14 +355,27 @@ void Graphics::setDebug(bool enable)
|
|||||||
void Graphics::reset()
|
void Graphics::reset()
|
||||||
{
|
{
|
||||||
DisplayState s;
|
DisplayState s;
|
||||||
discardStencil();
|
drawToStencilBuffer(false);
|
||||||
origin();
|
|
||||||
restoreState(s);
|
restoreState(s);
|
||||||
|
origin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::clear()
|
void Graphics::clear(ClearType type)
|
||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
GLbitfield mask = 0;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case CLEAR_ALL:
|
||||||
|
default:
|
||||||
|
mask = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
||||||
|
break;
|
||||||
|
case CLEAR_STENCIL:
|
||||||
|
mask = GL_STENCIL_BUFFER_BIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glClear(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::present()
|
void Graphics::present()
|
||||||
@@ -409,38 +427,68 @@ bool Graphics::getScissor(int &x, int &y, int &width, int &height) const
|
|||||||
return states.back().scissor;
|
return states.back().scissor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::defineStencil()
|
void Graphics::drawToStencilBuffer(bool enable)
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure the active canvas has a stencil buffer.
|
// Make sure the active canvas has a stencil buffer.
|
||||||
if (Canvas::current)
|
if (Canvas::current)
|
||||||
Canvas::current->checkCreateStencil();
|
Canvas::current->checkCreateStencil();
|
||||||
|
|
||||||
// Disable color writes but don't save the mask values.
|
// Disable color writes but don't save the state for it.
|
||||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
|
||||||
glClear(GL_STENCIL_BUFFER_BIT);
|
// The stencil test must be enabled in order to write to the stencil buffer.
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
|
||||||
glStencilFunc(GL_ALWAYS, 1, 1);
|
glStencilFunc(GL_ALWAYS, 1, 1);
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||||
|
|
||||||
activeStencil = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::useStencil(bool invert)
|
void Graphics::setStencilTest(bool enable, bool invert)
|
||||||
{
|
{
|
||||||
glStencilFunc(GL_EQUAL, (GLint)(!invert), 1); // invert ? 0 : 1
|
DisplayState &state = states.back();
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
state.stencilTest = enable;
|
||||||
setColorMask(states.back().colorMask);
|
state.stencilInvert = invert;
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::discardStencil()
|
if (writingToStencil)
|
||||||
{
|
|
||||||
if (!activeStencil)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setColorMask(states.back().colorMask);
|
if (!enable)
|
||||||
glDisable(GL_STENCIL_TEST);
|
{
|
||||||
activeStencil = false;
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the active canvas has a stencil buffer.
|
||||||
|
if (Canvas::current)
|
||||||
|
Canvas::current->checkCreateStencil();
|
||||||
|
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
glStencilFunc(GL_EQUAL, invert ? 0 : 1, 1);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graphics::getStencilTest(bool &enable, bool &invert)
|
||||||
|
{
|
||||||
|
const DisplayState &state = states.back();
|
||||||
|
enable = state.stencilTest;
|
||||||
|
invert = state.stencilInvert;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *Graphics::newImage(love::image::ImageData *data, const Image::Flags &flags)
|
Image *Graphics::newImage(love::image::ImageData *data, const Image::Flags &flags)
|
||||||
@@ -1279,6 +1327,8 @@ Graphics::DisplayState::DisplayState()
|
|||||||
, pointSize(1.0f)
|
, pointSize(1.0f)
|
||||||
, scissor(false)
|
, scissor(false)
|
||||||
, scissorBox()
|
, scissorBox()
|
||||||
|
, stencilTest(false)
|
||||||
|
, stencilInvert(false)
|
||||||
, font(nullptr)
|
, font(nullptr)
|
||||||
, shader(nullptr)
|
, shader(nullptr)
|
||||||
, wireframe(false)
|
, wireframe(false)
|
||||||
@@ -1298,6 +1348,8 @@ Graphics::DisplayState::DisplayState(const DisplayState &other)
|
|||||||
, pointSize(other.pointSize)
|
, pointSize(other.pointSize)
|
||||||
, scissor(other.scissor)
|
, scissor(other.scissor)
|
||||||
, scissorBox(other.scissorBox)
|
, scissorBox(other.scissorBox)
|
||||||
|
, stencilTest(other.stencilTest)
|
||||||
|
, stencilInvert(other.stencilInvert)
|
||||||
, font(other.font)
|
, font(other.font)
|
||||||
, shader(other.shader)
|
, shader(other.shader)
|
||||||
, canvases(other.canvases)
|
, canvases(other.canvases)
|
||||||
@@ -1322,6 +1374,8 @@ Graphics::DisplayState &Graphics::DisplayState::operator = (const DisplayState &
|
|||||||
pointSize = other.pointSize;
|
pointSize = other.pointSize;
|
||||||
scissor = other.scissor;
|
scissor = other.scissor;
|
||||||
scissorBox = other.scissorBox;
|
scissorBox = other.scissorBox;
|
||||||
|
stencilTest = other.stencilTest;
|
||||||
|
stencilInvert = other.stencilInvert;
|
||||||
|
|
||||||
font = other.font;
|
font = other.font;
|
||||||
shader = other.shader;
|
shader = other.shader;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Clears the screen.
|
* Clears the screen.
|
||||||
**/
|
**/
|
||||||
void clear();
|
void clear(ClearType type = CLEAR_ALL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flips buffers. (Rendered geometry is presented on screen).
|
* Flips buffers. (Rendered geometry is presented on screen).
|
||||||
@@ -124,22 +124,16 @@ public:
|
|||||||
bool getScissor(int &x, int &y, int &width, int &height) const;
|
bool getScissor(int &x, int &y, int &width, int &height) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the stencil buffer and set stencil function to fill it
|
* Enables or disables drawing to the stencil buffer. When enabled, the
|
||||||
*/
|
* color buffer is disabled.
|
||||||
void defineStencil();
|
**/
|
||||||
|
void drawToStencilBuffer(bool enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set stencil function to mask the following drawing calls using
|
* Sets whether stencil testing is enabled.
|
||||||
* the current stencil buffer
|
**/
|
||||||
* @param invert Invert the mask, i.e. draw everywhere expect where
|
void setStencilTest(bool enable, bool invert);
|
||||||
* the mask is defined.
|
void getStencilTest(bool &enable, bool &invert);
|
||||||
*/
|
|
||||||
void useStencil(bool invert = false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables the stencil buffer
|
|
||||||
*/
|
|
||||||
void discardStencil();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Image object with padding and/or optimization.
|
* Creates an Image object with padding and/or optimization.
|
||||||
@@ -443,6 +437,10 @@ private:
|
|||||||
bool scissor;
|
bool scissor;
|
||||||
OpenGL::Viewport scissorBox;
|
OpenGL::Viewport scissorBox;
|
||||||
|
|
||||||
|
// Stencil.
|
||||||
|
bool stencilTest;
|
||||||
|
bool stencilInvert;
|
||||||
|
|
||||||
Object::StrongRef<Font> font;
|
Object::StrongRef<Font> font;
|
||||||
Object::StrongRef<Shader> shader;
|
Object::StrongRef<Shader> shader;
|
||||||
|
|
||||||
@@ -471,7 +469,7 @@ private:
|
|||||||
int height;
|
int height;
|
||||||
bool created;
|
bool created;
|
||||||
|
|
||||||
bool activeStencil;
|
bool writingToStencil;
|
||||||
|
|
||||||
std::vector<DisplayState> states;
|
std::vector<DisplayState> states;
|
||||||
std::vector<StackType> stackTypes; // Keeps track of the pushed stack types.
|
std::vector<StackType> stackTypes; // Keeps track of the pushed stack types.
|
||||||
|
|||||||
@@ -44,9 +44,15 @@ int w_reset(lua_State *)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_clear(lua_State *)
|
int w_clear(lua_State *L)
|
||||||
{
|
{
|
||||||
instance()->clear();
|
Graphics::ClearType type = Graphics::CLEAR_ALL;
|
||||||
|
|
||||||
|
const char *tname = lua_isnoneornil(L, 1) ? nullptr : luaL_checkstring(L, 1);
|
||||||
|
if (tname && !Graphics::getConstant(tname, type))
|
||||||
|
return luaL_error(L, "Invalid graphics clear type: %s", tname);
|
||||||
|
|
||||||
|
instance()->clear(type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,32 +124,35 @@ int w_getScissor(lua_State *L)
|
|||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setStencil(lua_State *L, bool invert)
|
int w_drawStencil(lua_State *L)
|
||||||
{
|
{
|
||||||
// no argument -> clear stencil
|
|
||||||
if (lua_isnoneornil(L, 1))
|
|
||||||
{
|
|
||||||
instance()->discardStencil();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||||
|
|
||||||
instance()->defineStencil();
|
instance()->drawToStencilBuffer(true);
|
||||||
lua_call(L, lua_gettop(L) - 1, 0); // call stencil(...)
|
|
||||||
instance()->useStencil(invert);
|
// Call stencilfunc(...)
|
||||||
|
lua_call(L, lua_gettop(L) - 1, 0);
|
||||||
|
|
||||||
|
instance()->drawToStencilBuffer(false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_setStencil(lua_State *L)
|
int w_setStencilTest(lua_State *L)
|
||||||
{
|
{
|
||||||
return setStencil(L, false);
|
bool enable = luax_toboolean(L, 1);
|
||||||
|
bool invert = luax_toboolean(L, 2);
|
||||||
|
instance()->setStencilTest(enable, invert);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int w_setInvertedStencil(lua_State *L)
|
int w_getStencilTest(lua_State *L)
|
||||||
{
|
{
|
||||||
return setStencil(L, true);
|
bool enabled, inverted;
|
||||||
|
instance()->getStencilTest(enabled, inverted);
|
||||||
|
luax_pushboolean(L, enabled);
|
||||||
|
luax_pushboolean(L, inverted);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *imageFlagName(Image::FlagType flagtype)
|
static const char *imageFlagName(Image::FlagType flagtype)
|
||||||
@@ -860,8 +869,8 @@ int w_newScreenshot(lua_State *L)
|
|||||||
|
|
||||||
int w_setCanvas(lua_State *L)
|
int w_setCanvas(lua_State *L)
|
||||||
{
|
{
|
||||||
// discard stencil testing
|
// Disable stencil writes.
|
||||||
instance()->discardStencil();
|
instance()->drawToStencilBuffer(false);
|
||||||
|
|
||||||
// called with none -> reset to default buffer
|
// called with none -> reset to default buffer
|
||||||
if (lua_isnoneornil(L, 1))
|
if (lua_isnoneornil(L, 1))
|
||||||
@@ -1411,8 +1420,9 @@ static const luaL_Reg functions[] =
|
|||||||
{ "setScissor", w_setScissor },
|
{ "setScissor", w_setScissor },
|
||||||
{ "getScissor", w_getScissor },
|
{ "getScissor", w_getScissor },
|
||||||
|
|
||||||
{ "setStencil", w_setStencil },
|
{ "drawStencil", w_drawStencil },
|
||||||
{ "setInvertedStencil", w_setInvertedStencil },
|
{ "setStencilTest", w_setStencilTest },
|
||||||
|
{ "getStencilTest", w_getStencilTest },
|
||||||
|
|
||||||
{ "point", w_point },
|
{ "point", w_point },
|
||||||
{ "line", w_line },
|
{ "line", w_line },
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ int w_getHeight(lua_State *L);
|
|||||||
int w_getDimensions(lua_State *L);
|
int w_getDimensions(lua_State *L);
|
||||||
int w_setScissor(lua_State *L);
|
int w_setScissor(lua_State *L);
|
||||||
int w_getScissor(lua_State *L);
|
int w_getScissor(lua_State *L);
|
||||||
int w_setStencil(lua_State *L);
|
int w_drawStencil(lua_State *L);
|
||||||
int w_setInvertedStencil(lua_State *L);
|
int w_setStencilTest(lua_State *L);
|
||||||
|
int w_getStencilTest(lua_State *L);
|
||||||
int w_newImage(lua_State *L);
|
int w_newImage(lua_State *L);
|
||||||
int w_newQuad(lua_State *L);
|
int w_newQuad(lua_State *L);
|
||||||
int w_newFont(lua_State *L);
|
int w_newFont(lua_State *L);
|
||||||
|
|||||||
Reference in New Issue
Block a user