Added Transform objects to love.math (resolves issue #1228).

- Added love.math.newTransform.
- Added love.graphics.applyTransform and love.graphics.replaceTransform.
- love.graphics.draw/print/printf, Text:add/addf, and SpriteBatch:add can accept a Transform argument.
- love.graphics.push can accept an optional Transform as a second argument, which will apply the Transform after pushing the matrix stack,
- Shader:send can accept Transform objects when sending to a mat4 uniform variable.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2016-11-24 21:30:45 -04:00
parent 9d2ee6d909
commit 14aa6965b3
19 changed files with 820 additions and 94 deletions
+4
View File
@@ -655,6 +655,8 @@ set(LOVE_SRC_MODULE_MATH
src/modules/math/MathModule.h
src/modules/math/RandomGenerator.cpp
src/modules/math/RandomGenerator.h
src/modules/math/Transform.cpp
src/modules/math/Transform.h
src/modules/math/wrap_BezierCurve.cpp
src/modules/math/wrap_BezierCurve.h
src/modules/math/wrap_CompressedData.cpp
@@ -663,6 +665,8 @@ set(LOVE_SRC_MODULE_MATH
src/modules/math/wrap_Math.h
src/modules/math/wrap_RandomGenerator.cpp
src/modules/math/wrap_RandomGenerator.h
src/modules/math/wrap_Transform.cpp
src/modules/math/wrap_Transform.h
)
source_group("modules\\math" FILES ${LOVE_SRC_MODULE_MATH})
@@ -895,6 +895,12 @@
FA4F2BB31DE1E4B800CA37D7 /* RecordingDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2BA21DE1E36400CA37D7 /* RecordingDevice.cpp */; };
FA4F2BB41DE1E4BD00CA37D7 /* RecordingDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2BAA1DE1E37000CA37D7 /* RecordingDevice.cpp */; };
FA4F2BB51DE1E4C300CA37D7 /* wrap_RecordingDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2BA41DE1E36400CA37D7 /* wrap_RecordingDevice.cpp */; };
FA4F2BE31DE6650600CA37D7 /* Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2BDF1DE6650600CA37D7 /* Transform.cpp */; };
FA4F2BE41DE6650600CA37D7 /* Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = FA4F2BE01DE6650600CA37D7 /* Transform.h */; };
FA4F2BE51DE6650600CA37D7 /* wrap_Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2BE11DE6650600CA37D7 /* wrap_Transform.cpp */; };
FA4F2BE61DE6650600CA37D7 /* wrap_Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = FA4F2BE21DE6650600CA37D7 /* wrap_Transform.h */; };
FA4F2BE71DE6650D00CA37D7 /* Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2BDF1DE6650600CA37D7 /* Transform.cpp */; };
FA4F2BE81DE6651000CA37D7 /* wrap_Transform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2BE11DE6650600CA37D7 /* wrap_Transform.cpp */; };
FA56D9BC1C208A0200D8D3C7 /* libmodplug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA56D9BA1C2089EE00D8D3C7 /* libmodplug.a */; };
FA577AB016C7507900860150 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A7916C71A1700860150 /* Cocoa.framework */; };
FA577AC216C7512D00860150 /* FreeType.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A6716C719D900860150 /* FreeType.framework */; };
@@ -1600,6 +1606,10 @@
FA4F2BAB1DE1E37000CA37D7 /* RecordingDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordingDevice.h; sourceTree = "<group>"; };
FA4F2BAE1DE1E37B00CA37D7 /* RecordingDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RecordingDevice.cpp; sourceTree = "<group>"; };
FA4F2BAF1DE1E37B00CA37D7 /* RecordingDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordingDevice.h; sourceTree = "<group>"; };
FA4F2BDF1DE6650600CA37D7 /* Transform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Transform.cpp; sourceTree = "<group>"; };
FA4F2BE01DE6650600CA37D7 /* Transform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Transform.h; sourceTree = "<group>"; };
FA4F2BE11DE6650600CA37D7 /* wrap_Transform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Transform.cpp; sourceTree = "<group>"; };
FA4F2BE21DE6650600CA37D7 /* wrap_Transform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Transform.h; sourceTree = "<group>"; };
FA56D9BA1C2089EE00D8D3C7 /* libmodplug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libmodplug.a; sourceTree = "<group>"; };
FA577A6716C719D900860150 /* FreeType.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FreeType.framework; path = /Library/Frameworks/FreeType.framework; sourceTree = "<absolute>"; };
FA577A6D16C719EA00860150 /* Lua.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Lua.framework; path = /Library/Frameworks/Lua.framework; sourceTree = "<absolute>"; };
@@ -2559,6 +2569,8 @@
FA0B7C041A95902C000E1D17 /* MathModule.h */,
FA0B7C051A95902C000E1D17 /* RandomGenerator.cpp */,
FA0B7C061A95902C000E1D17 /* RandomGenerator.h */,
FA4F2BDF1DE6650600CA37D7 /* Transform.cpp */,
FA4F2BE01DE6650600CA37D7 /* Transform.h */,
FA0B7C071A95902C000E1D17 /* wrap_BezierCurve.cpp */,
FA0B7C081A95902C000E1D17 /* wrap_BezierCurve.h */,
FAB17BEE1ABFB37500F9BA27 /* wrap_CompressedData.cpp */,
@@ -2569,6 +2581,8 @@
FA0B7C0B1A95902C000E1D17 /* wrap_RandomGenerator.cpp */,
FA0B7C0C1A95902C000E1D17 /* wrap_RandomGenerator.h */,
FA2E9BFE1C19E00C0004A1EE /* wrap_RandomGenerator.lua */,
FA4F2BE11DE6650600CA37D7 /* wrap_Transform.cpp */,
FA4F2BE21DE6650600CA37D7 /* wrap_Transform.h */,
);
path = math;
sourceTree = "<group>";
@@ -3191,6 +3205,7 @@
FA0B7E6B1A95902C000E1D17 /* wrap_PulleyJoint.h in Headers */,
FA0B7E051A95902C000E1D17 /* Contact.h in Headers */,
FA0B7A691A958EA3000E1D17 /* b2Island.h in Headers */,
FA4F2BE41DE6650600CA37D7 /* Transform.h in Headers */,
FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */,
FA0B7A401A958EA3000E1D17 /* b2ChainShape.h in Headers */,
217DFBE81D9F6D490055D849 /* inet.h in Headers */,
@@ -3266,6 +3281,7 @@
217DFBF71D9F6D490055D849 /* options.h in Headers */,
FA0B7E3B1A95902C000E1D17 /* World.h in Headers */,
FA0B7DC31A95902C000E1D17 /* wrap_Joystick.h in Headers */,
FA4F2BE61DE6650600CA37D7 /* wrap_Transform.h in Headers */,
FA0B7EE71A95902D000E1D17 /* Window.h in Headers */,
FA0B7E651A95902C000E1D17 /* wrap_PolygonShape.h in Headers */,
FA0B7AC91A958EA3000E1D17 /* win32.h in Headers */,
@@ -3501,6 +3517,7 @@
FA0B7AAB1A958EA3000E1D17 /* b2WeldJoint.cpp in Sources */,
FA0B7EC21A95902C000E1D17 /* threads.cpp in Sources */,
FA0B79371A958E3B000E1D17 /* macosx.mm in Sources */,
FA4F2BE81DE6651000CA37D7 /* wrap_Transform.cpp in Sources */,
FA0B7D011A95902C000E1D17 /* Filesystem.cpp in Sources */,
FA0B7ED91A95902D000E1D17 /* wrap_Timer.cpp in Sources */,
FA0B7DD11A95902C000E1D17 /* love.cpp in Sources */,
@@ -3583,6 +3600,7 @@
FA0B7D681A95902C000E1D17 /* wrap_ParticleSystem.cpp in Sources */,
FA0B7AD51A958EA3000E1D17 /* unix.c in Sources */,
FAB17BE71ABFAA9000F9BA27 /* lz4.c in Sources */,
FA4F2BE71DE6650D00CA37D7 /* Transform.cpp in Sources */,
FA0B7D651A95902C000E1D17 /* wrap_Mesh.cpp in Sources */,
FA0B7A531A958EA3000E1D17 /* b2Math.cpp in Sources */,
FA0B7CDA1A95902C000E1D17 /* Pool.cpp in Sources */,
@@ -3861,6 +3879,7 @@
FA0B7EDF1A95902D000E1D17 /* wrap_Touch.cpp in Sources */,
FA0B794A1A958E3B000E1D17 /* wrap_Data.cpp in Sources */,
217DFBFB1D9F6D490055D849 /* serial.c in Sources */,
FA4F2BE51DE6650600CA37D7 /* wrap_Transform.cpp in Sources */,
217DFC0D1D9F6D490055D849 /* unixudp.c in Sources */,
FA0B7CDC1A95902C000E1D17 /* Source.cpp in Sources */,
FA0B7DC41A95902C000E1D17 /* wrap_JoystickModule.cpp in Sources */,
@@ -4045,6 +4064,7 @@
FA0B7CDF1A95902C000E1D17 /* Source.cpp in Sources */,
FA0B7ECE1A95902C000E1D17 /* wrap_LuaThread.cpp in Sources */,
FA0B79431A958E3B000E1D17 /* Variant.cpp in Sources */,
FA4F2BE31DE6650600CA37D7 /* Transform.cpp in Sources */,
FA0B7EA01A95902C000E1D17 /* Sound.cpp in Sources */,
FA0B7DE51A95902C000E1D17 /* Cursor.cpp in Sources */,
FA0B7EDB1A95902D000E1D17 /* Touch.cpp in Sources */,
+6
View File
@@ -73,6 +73,12 @@ Matrix4::Matrix4()
{
setIdentity();
}
Matrix4::Matrix4(const float elements[16])
{
memcpy(e, elements, sizeof(float) * 16);
}
Matrix4::Matrix4(float t00, float t10, float t01, float t11, float x, float y)
{
+9
View File
@@ -52,6 +52,12 @@ public:
**/
Matrix4(float t00, float t10, float t01, float t11, float x, float y);
/**
* Creates a new matrix from the specified elements. Be sure to pass
* exactly 16 elements in!
**/
Matrix4(const float elements[16]);
/**
* Creates a new matrix set to a transformation.
**/
@@ -182,6 +188,9 @@ public:
template <typename V>
void transform(V *dst, const V *src, int size) const;
/**
* Computes and returns the inverse of the matrix.
**/
Matrix4 inverse() const;
/**
+2 -1
View File
@@ -68,7 +68,8 @@ static const TypeBits *createTypeFlags()
// Math.
b[MATH_RANDOM_GENERATOR_ID] = (one << MATH_RANDOM_GENERATOR_ID) | b[OBJECT_ID];
b[MATH_BEZIER_CURVE_ID] = (one << MATH_BEZIER_CURVE_ID) | b[OBJECT_ID];
b[MATH_COMPRESSED_DATA_ID] = (one <<MATH_COMPRESSED_DATA_ID) | b[DATA_ID];
b[MATH_COMPRESSED_DATA_ID] = (one << MATH_COMPRESSED_DATA_ID) | b[DATA_ID];
b[MATH_TRANSFORM_ID] = (one << MATH_TRANSFORM_ID) | b[OBJECT_ID];
// Audio.
b[AUDIO_SOURCE_ID] = (one << AUDIO_SOURCE_ID) | b[OBJECT_ID];
+1
View File
@@ -70,6 +70,7 @@ enum Type
MATH_RANDOM_GENERATOR_ID,
MATH_BEZIER_CURVE_ID,
MATH_COMPRESSED_DATA_ID,
MATH_TRANSFORM_ID,
// Audio
AUDIO_SOURCE_ID,
+10
View File
@@ -2092,6 +2092,16 @@ void Graphics::origin()
pixelSizeStack.back() = 1;
}
void Graphics::applyTransform(love::math::Transform *transform)
{
gl.getTransform() *= transform->getMatrix();
}
void Graphics::replaceTransform(love::math::Transform *transform)
{
gl.getTransform() = transform->getMatrix();
}
Vector Graphics::transformPoint(Vector point)
{
Vector p;
+6
View File
@@ -38,6 +38,8 @@
#include "video/VideoStream.h"
#include "math/Transform.h"
#include "Font.h"
#include "Image.h"
#include "graphics/Quad.h"
@@ -488,6 +490,10 @@ public:
void translate(float x, float y);
void shear(float kx, float ky);
void origin();
void applyTransform(love::math::Transform *transform);
void replaceTransform(love::math::Transform *transform);
Vector transformPoint(Vector point);
Vector inverseTransformPoint(Vector point);
+81 -51
View File
@@ -1667,24 +1667,37 @@ int w_draw(lua_State *L)
startidx = 2;
}
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);
if (luax_istype(L, startidx, MATH_TRANSFORM_ID))
{
math::Transform *tf = luax_totype<math::Transform>(L, startidx, MATH_TRANSFORM_ID);
luax_catchexcept(L, [&]() {
if (texture && quad)
instance()->drawq(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);
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&]() {
if (texture && quad)
instance()->drawq(texture, quad, m);
else if (drawable)
instance()->draw(drawable, m);
});
luax_catchexcept(L, [&]() {
if (texture && quad)
instance()->drawq(texture, quad, m);
else if (drawable)
instance()->draw(drawable, m);
});
}
return 0;
}
@@ -1694,19 +1707,27 @@ int w_print(lua_State *L)
std::vector<Font::ColoredString> str;
luax_checkcoloredstring(L, 1, str);
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);
if (luax_istype(L, 2, MATH_TRANSFORM_ID))
{
math::Transform *tf = luax_totype<math::Transform>(L, 2, MATH_TRANSFORM_ID);
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);
Matrix4 m(x, y, angle, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&](){ instance()->print(str, m); });
luax_catchexcept(L, [&](){ instance()->print(str, m); });
}
return 0;
}
@@ -1715,36 +1736,38 @@ int w_printf(lua_State *L)
std::vector<Font::ColoredString> str;
luax_checkcoloredstring(L, 1, str);
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
float wrap = (float)luaL_checknumber(L, 4);
float angle = 0.0f;
float sx = 1.0f, sy = 1.0f;
float ox = 0.0f, oy = 0.0f;
float kx = 0.0f, ky = 0.0f;
Font::AlignMode align = Font::ALIGN_LEFT;
Matrix4 m;
if (lua_gettop(L) >= 5)
int formatidx = 4;
if (luax_istype(L, 2, MATH_TRANSFORM_ID))
{
if (!lua_isnil(L, 5))
{
const char *str = luaL_checkstring(L, 5);
if (!Font::getConstant(str, align))
return luaL_error(L, "Incorrect alignment: %s", str);
}
math::Transform *tf = luax_totype<math::Transform>(L, 2, MATH_TRANSFORM_ID);
m = tf->getMatrix();
formatidx = 3;
}
else
{
float x = (float)luaL_checknumber(L, 2);
float y = (float)luaL_checknumber(L, 3);
angle = (float) luaL_optnumber(L, 6, 0.0f);
sx = (float) luaL_optnumber(L, 7, 1.0f);
sy = (float) luaL_optnumber(L, 8, sx);
ox = (float) luaL_optnumber(L, 9, 0.0f);
oy = (float) luaL_optnumber(L, 10, 0.0f);
kx = (float) luaL_optnumber(L, 11, 0.0f);
ky = (float) luaL_optnumber(L, 12, 0.0f);
float angle = (float) luaL_optnumber(L, 6, 0.0f);
float sx = (float) luaL_optnumber(L, 7, 1.0f);
float sy = (float) luaL_optnumber(L, 8, sx);
float ox = (float) luaL_optnumber(L, 9, 0.0f);
float oy = (float) luaL_optnumber(L, 10, 0.0f);
float kx = (float) luaL_optnumber(L, 11, 0.0f);
float ky = (float) luaL_optnumber(L, 12, 0.0f);
m = Matrix4(x, y, angle, sx, sy, ox, oy, kx, ky);
}
Matrix4 m(x, y, angle, sx, sy, ox, oy, kx, ky);
float wrap = (float)luaL_checknumber(L, formatidx);
const char *astr = lua_isnoneornil(L, formatidx + 1) ? nullptr : luaL_checkstring(L, formatidx + 1);
if (astr != nullptr && !Font::getConstant(astr, align))
return luaL_error(L, "Incorrect alignment: %s", astr);
luax_catchexcept(L, [&](){ instance()->printf(str, wrap, align, m); });
return 0;
@@ -2048,6 +2071,13 @@ int w_push(lua_State *L)
return luaL_error(L, "Invalid graphics stack type: %s", sname);
luax_catchexcept(L, [&](){ instance()->push(stype); });
if (luax_istype(L, 2, MATH_TRANSFORM_ID))
{
math::Transform *t = luax_totype<math::Transform>(L, 2, MATH_TRANSFORM_ID);
instance()->applyTransform(t);
}
return 0;
}
@@ -21,6 +21,7 @@
#include "wrap_Shader.h"
#include "graphics/wrap_Texture.h"
#include "math/MathModule.h"
#include "math/Transform.h"
#include <string>
#include <algorithm>
@@ -164,6 +165,13 @@ int w_Shader_sendMatrices(lua_State *L, int startidx, Shader *shader, const Shad
for (int i = 0; i < count; i++)
{
if (columns == 4 && rows == 4 && luax_istype(L, startidx + i, MATH_TRANSFORM_ID))
{
math::Transform *t = luax_totype<math::Transform>(L, startidx + i, MATH_TRANSFORM_ID);
memcpy(&values[i * 16], t->getMatrix().getElements(), sizeof(float) * 16);
continue;
}
luaL_checktype(L, startidx + i, LUA_TTABLE);
lua_rawgeti(L, startidx + i, 1);
@@ -23,6 +23,7 @@
#include "Image.h"
#include "Canvas.h"
#include "graphics/wrap_Texture.h"
#include "math/wrap_Transform.h"
// C++
#include <typeinfo>
@@ -51,24 +52,37 @@ 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");
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);
if (luax_istype(L, startidx, MATH_TRANSFORM_ID))
{
math::Transform *tf = luax_totype<math::Transform>(L, startidx, MATH_TRANSFORM_ID);
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);
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&]() {
if (quad)
index = t->addq(quad, m, index);
else
index = t->add(m, index);
});
luax_catchexcept(L, [&]() {
if (quad)
index = t->addq(quad, m, index);
else
index = t->add(m, index);
});
}
return index;
}
+45 -26
View File
@@ -19,6 +19,7 @@
**/
#include "wrap_Text.h"
#include "math/wrap_Transform.h"
namespace love
{
@@ -126,24 +127,33 @@ int w_Text_add(lua_State *L)
{
Text *t = luax_checktext(L, 1);
int index = 0;
std::vector<Font::ColoredString> text;
luax_checkcoloredstring(L, 2, text);
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);
if (luax_istype(L, 3, MATH_TRANSFORM_ID))
{
math::Transform *tf = luax_totype<math::Transform>(L, 3, MATH_TRANSFORM_ID);
luax_catchexcept(L, [&](){ index = t->add(text, tf->getMatrix()); });
}
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, [&](){ index = t->add(text, m); });
}
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
int index = 0;
luax_catchexcept(L, [&](){ index = t->add(text, m); });
lua_pushnumber(L, index + 1);
return 1;
}
@@ -151,6 +161,8 @@ int w_Text_addf(lua_State *L)
{
Text *t = luax_checktext(L, 1);
int index = 0;
std::vector<Font::ColoredString> text;
luax_checkcoloredstring(L, 2, text);
@@ -162,21 +174,28 @@ int w_Text_addf(lua_State *L)
if (!Font::getConstant(alignstr, align))
return luaL_error(L, "Invalid align mode: %s", alignstr);
float x = (float) luaL_optnumber(L, 5, 0.0);
float y = (float) luaL_optnumber(L, 6, 0.0);
float a = (float) luaL_optnumber(L, 7, 0.0);
float sx = (float) luaL_optnumber(L, 8, 1.0);
float sy = (float) luaL_optnumber(L, 9, sx);
float ox = (float) luaL_optnumber(L, 10, 0.0);
float oy = (float) luaL_optnumber(L, 11, 0.0);
float kx = (float) luaL_optnumber(L, 12, 0.0);
float ky = (float) luaL_optnumber(L, 13, 0.0);
if (luax_istype(L, 5, MATH_TRANSFORM_ID))
{
math::Transform *tf = luax_totype<math::Transform>(L, 5, MATH_TRANSFORM_ID);
luax_catchexcept(L, [&](){ index = t->addf(text, wrap, align, tf->getMatrix()); });
}
else
{
float x = (float) luaL_optnumber(L, 5, 0.0);
float y = (float) luaL_optnumber(L, 6, 0.0);
float a = (float) luaL_optnumber(L, 7, 0.0);
float sx = (float) luaL_optnumber(L, 8, 1.0);
float sy = (float) luaL_optnumber(L, 9, sx);
float ox = (float) luaL_optnumber(L, 10, 0.0);
float oy = (float) luaL_optnumber(L, 11, 0.0);
float kx = (float) luaL_optnumber(L, 12, 0.0);
float ky = (float) luaL_optnumber(L, 13, 0.0);
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
luax_catchexcept(L, [&](){ index = t->addf(text, wrap, align, m); });
}
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
int index = 0;
luax_catchexcept(L, [&](){ index = t->addf(text, wrap, align, m); });
lua_pushnumber(L, index + 1);
return 1;
}
+11
View File
@@ -25,6 +25,7 @@
#include "common/int.h"
#include "common/StringMap.h"
#include "BezierCurve.h"
#include "Transform.h"
// STL
#include <cmath>
@@ -374,6 +375,16 @@ BezierCurve *Math::newBezierCurve(const std::vector<Vector> &points)
return new BezierCurve(points);
}
Transform *Math::newTransform()
{
return new Transform();
}
Transform *Math::newTransform(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
{
return new Transform(x, y, a, sx, sy, ox, oy, kx, ky);
}
std::string hash(HashFunction::Function function, Data *input)
{
return hash(function, (const char*) input->getData(), input->getSize());
+4
View File
@@ -45,6 +45,7 @@ namespace math
{
class BezierCurve;
class Transform;
struct Triangle
{
@@ -176,6 +177,9 @@ public:
**/
BezierCurve *newBezierCurve(const std::vector<Vector> &points);
Transform *newTransform();
Transform *newTransform(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky);
// Implements Module.
virtual ModuleType getModuleType() const
{
+131
View File
@@ -0,0 +1,131 @@
/**
* Copyright (c) 2006-2016 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "Transform.h"
namespace love
{
namespace math
{
Transform::Transform()
: matrix()
, inverseDirty(true)
, inverseMatrix()
{
}
Transform::Transform(const Matrix4 &m)
: matrix(m)
, inverseDirty(true)
, inverseMatrix()
{
}
Transform::Transform(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
: matrix(x, y, a, sx, sy, ox, oy, kx, ky)
, inverseDirty(true)
, inverseMatrix()
{
}
Transform::~Transform()
{
}
Transform *Transform::clone()
{
return new Transform(*this);
}
Transform *Transform::inverse()
{
return new Transform(getInverseMatrix());
}
void Transform::apply(Transform *other)
{
matrix *= other->getMatrix();
inverseDirty = true;
}
void Transform::translate(float x, float y)
{
matrix.translate(x, y);
inverseDirty = true;
}
void Transform::rotate(float angle)
{
matrix.rotate(angle);
inverseDirty = true;
}
void Transform::scale(float x, float y)
{
matrix.scale(x, y);
inverseDirty = true;
}
void Transform::shear(float x, float y)
{
matrix.shear(x, y);
inverseDirty = true;
}
void Transform::reset()
{
matrix.setIdentity();
inverseDirty = true;
}
void Transform::setTransformation(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky)
{
matrix.setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
inverseDirty = true;
}
love::Vector Transform::transformPoint(love::Vector p) const
{
love::Vector result;
matrix.transform(&result, &p, 1);
return result;
}
love::Vector Transform::inverseTransformPoint(love::Vector p)
{
love::Vector result;
getInverseMatrix().transform(&result, &p, 1);
return result;
}
const Matrix4 &Transform::getMatrix() const
{
return matrix;
}
void Transform::setMatrix(const Matrix4 &m)
{
matrix = m;
inverseDirty = true;
}
} // math
} // love
+83
View File
@@ -0,0 +1,83 @@
/**
* Copyright (c) 2006-2016 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#pragma once
// LOVE
#include "common/Object.h"
#include "common/Matrix.h"
#include "common/Vector.h"
namespace love
{
namespace math
{
class Transform : public Object
{
public:
Transform();
Transform(const Matrix4 &m);
Transform(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky);
virtual ~Transform();
Transform *clone();
Transform *inverse();
void apply(Transform *other);
void translate(float x, float y);
void rotate(float angle);
void scale(float x, float y);
void shear(float x, float y);
void reset();
void setTransformation(float x, float y, float a, float sx, float sy, float ox, float oy, float kx, float ky);
love::Vector transformPoint(love::Vector p) const;
love::Vector inverseTransformPoint(love::Vector p);
const Matrix4 &getMatrix() const;
void setMatrix(const Matrix4 &m);
private:
inline const Matrix4 &getInverseMatrix()
{
if (inverseDirty)
{
inverseDirty = false;
inverseMatrix = matrix.inverse();
}
return inverseMatrix;
}
Matrix4 matrix;
bool inverseDirty;
Matrix4 inverseMatrix;
}; // Transform
} // math
} // love
+29
View File
@@ -22,8 +22,10 @@
#include "wrap_RandomGenerator.h"
#include "wrap_BezierCurve.h"
#include "wrap_CompressedData.h"
#include "wrap_Transform.h"
#include "MathModule.h"
#include "BezierCurve.h"
#include "Transform.h"
#include "common/b64.h"
#include <cmath>
@@ -118,6 +120,31 @@ int w_newBezierCurve(lua_State *L)
return 1;
}
int w_newTransform(lua_State *L)
{
Transform *t = nullptr;
if (lua_isnoneornil(L, 1))
t = Math::instance.newTransform();
else
{
float x = (float) luaL_checknumber(L, 1);
float y = (float) luaL_checknumber(L, 2);
float a = (float) luaL_optnumber(L, 3, 0.0);
float sx = (float) luaL_optnumber(L, 4, 1.0);
float sy = (float) luaL_optnumber(L, 5, sx);
float ox = (float) luaL_optnumber(L, 6, 0.0);
float oy = (float) luaL_optnumber(L, 7, 0.0);
float kx = (float) luaL_optnumber(L, 8, 0.0);
float ky = (float) luaL_optnumber(L, 9, 0.0);
t = Math::instance.newTransform(x, y, a, sx, sy, ox, oy, kx, ky);
}
luax_pushtype(L, MATH_TRANSFORM_ID, t);
t->release();
return 1;
}
int w_triangulate(lua_State *L)
{
std::vector<love::Vector> vertices;
@@ -507,6 +534,7 @@ static const luaL_Reg functions[] =
{ "_getRandomGenerator", w__getRandomGenerator },
{ "newRandomGenerator", w_newRandomGenerator },
{ "newBezierCurve", w_newBezierCurve },
{ "newTransform", w_newTransform },
{ "triangulate", w_triangulate },
{ "isConvex", w_isConvex },
{ "gammaToLinear", w_gammaToLinear },
@@ -525,6 +553,7 @@ static const lua_CFunction types[] =
luaopen_randomgenerator,
luaopen_beziercurve,
luaopen_compresseddata,
luaopen_transform,
0
};
+305
View File
@@ -0,0 +1,305 @@
/**
* Copyright (c) 2006-2016 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#include "wrap_Transform.h"
namespace love
{
namespace math
{
Transform *luax_checktransform(lua_State *L, int idx)
{
return luax_checktype<Transform>(L, idx, MATH_TRANSFORM_ID);
}
int w_Transform_clone(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
Transform *newtransform = t->clone();
luax_pushtype(L, MATH_TRANSFORM_ID, newtransform);
newtransform->release();
return 1;
}
int w_Transform_inverse(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
Transform *inverse = t->inverse();
luax_pushtype(L, MATH_TRANSFORM_ID, inverse);
inverse->release();
return 1;
}
int w_Transform_apply(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
Transform *other = luax_checktransform(L, 2);
t->apply(other);
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_translate(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
float x = (float) luaL_checknumber(L, 2);
float y = (float) luaL_checknumber(L, 3);
t->translate(x, y);
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_rotate(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
float angle = (float) luaL_checknumber(L, 2);
t->rotate(angle);
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_scale(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
float sx = (float) luaL_checknumber(L, 2);
float sy = (float) luaL_optnumber(L, 3, sx);
t->scale(sx, sy);
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_shear(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
float kx = (float) luaL_checknumber(L, 2);
float ky = (float) luaL_checknumber(L, 3);
t->shear(kx, ky);
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_reset(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
t->reset();
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_setTransformation(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
float x = (float) luaL_optnumber(L, 2, 0.0);
float y = (float) luaL_optnumber(L, 3, 0.0);
float a = (float) luaL_optnumber(L, 4, 0.0);
float sx = (float) luaL_optnumber(L, 5, 1.0);
float sy = (float) luaL_optnumber(L, 6, sx);
float ox = (float) luaL_optnumber(L, 7, 0.0);
float oy = (float) luaL_optnumber(L, 8, 0.0);
float kx = (float) luaL_optnumber(L, 9, 0.0);
float ky = (float) luaL_optnumber(L, 10, 0.0);
t->setTransformation(x, y, a, sx, sy, ox, oy, kx, ky);
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_setMatrix(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
bool columnmajor = false;
int idx = 2;
if (lua_isboolean(L, idx))
{
columnmajor = lua_toboolean(L, idx);
idx++;
}
float elements[16];
if (lua_istable(L, idx))
{
lua_rawgeti(L, idx, 1);
bool tableoftables = lua_istable(L, -1);
lua_pop(L, 1);
if (tableoftables)
{
if (columnmajor)
{
for (int column = 0; column < 4; column++)
{
lua_rawgeti(L, idx, column + 1);
for (int row = 0; row < 4; row++)
{
lua_rawgeti(L, -(row + 1), row + 1);
elements[column * 4 + row] = (float) luaL_checknumber(L, -1);
}
lua_pop(L, 4 + 1);
}
}
else
{
for (int row = 0; row < 4; row++)
{
lua_rawgeti(L, idx, row + 1);
for (int column = 0; column < 4; column++)
{
// The table has the matrix elements laid out in row-major
// order, but we need to store them column-major in memory.
lua_rawgeti(L, -(column + 1), column + 1);
elements[column * 4 + row] = (float) luaL_checknumber(L, -1);
}
lua_pop(L, 4 + 1);
}
}
}
else
{
if (columnmajor)
{
for (int column = 0; column < 4; column++)
{
for (int row = 0; row < 4; row++)
{
lua_rawgeti(L, idx, column * 4 + row + 1);
elements[column * 4 + row] = (float) luaL_checknumber(L, -1);
}
}
}
else
{
for (int column = 0; column < 4; column++)
{
for (int row = 0; row < 4; row++)
{
// The table has the matrix elements laid out in row-major
// order, but we need to store them column-major in memory.
lua_rawgeti(L, idx, row * 4 + column + 1);
elements[column * 4 + row] = (float) luaL_checknumber(L, -1);
}
}
}
lua_pop(L, 16);
}
}
else
{
if (columnmajor)
{
for (int i = 0; i < 16; i++)
elements[i] = (float) luaL_checknumber(L, idx + i);
}
else
{
for (int column = 0; column < 4; column++)
{
for (int row = 0; row < 4; row++)
elements[column * 4 + row] = (float) luaL_checknumber(L, row * 4 + column + idx);
}
}
}
t->setMatrix(Matrix4(elements));
lua_pushvalue(L, 1);
return 1;
}
int w_Transform_getMatrix(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
const float *elements = t->getMatrix().getElements();
// We want to push elements in row-major order, but they're stored column-
// major.
for (int row = 0; row < 4; row++)
{
for (int column = 0; column < 4; column++)
lua_pushnumber(L, elements[column * 4 + row]);
}
return 16;
}
int w_Transform_transformPoint(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
love::Vector p;
p.x = (float) luaL_checknumber(L, 2);
p.y = (float) luaL_checknumber(L, 3);
p = t->transformPoint(p);
lua_pushnumber(L, p.x);
lua_pushnumber(L, p.y);
return 2;
}
int w_Transform_inverseTransformPoint(lua_State *L)
{
Transform *t = luax_checktransform(L, 1);
love::Vector p;
p.x = (float) luaL_checknumber(L, 2);
p.y = (float) luaL_checknumber(L, 3);
p = t->inverseTransformPoint(p);
lua_pushnumber(L, p.x);
lua_pushnumber(L, p.y);
return 2;
}
int w_Transform__mul(lua_State *L)
{
Transform *t1 = luax_checktransform(L, 1);
Transform *t2 = luax_checktransform(L, 2);
Transform *t3 = new Transform(t1->getMatrix() * t2->getMatrix());
luax_pushtype(L, MATH_TRANSFORM_ID, t3);
t3->release();
return 1;
}
static const luaL_Reg functions[] =
{
{ "clone", w_Transform_clone },
{ "inverse", w_Transform_inverse },
{ "apply", w_Transform_apply },
{ "translate", w_Transform_translate },
{ "rotate", w_Transform_rotate },
{ "scale", w_Transform_scale },
{ "shear", w_Transform_shear },
{ "reset", w_Transform_reset },
{ "setTransformation", w_Transform_setTransformation },
{ "transformPoint", w_Transform_transformPoint },
{ "inverseTransformPoint", w_Transform_inverseTransformPoint },
{ "__mul", w_Transform__mul },
{ 0, 0 }
};
extern "C" int luaopen_transform(lua_State *L)
{
return luax_register_type(L, MATH_TRANSFORM_ID, "Transform", functions, nullptr);
}
} // math
} // love
+35
View File
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2006-2016 LOVE Development Team
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
#pragma once
// LOVE
#include "Transform.h"
#include "common/runtime.h"
namespace love
{
namespace math
{
extern "C" int luaopen_transform(lua_State *L);
} // math
} // love