1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "common/Exception.h"
22#include "wrap_BezierCurve.h"
23
24#include <cmath>
25
26namespace love
27{
28namespace math
29{
30
31BezierCurve *luax_checkbeziercurve(lua_State *L, int idx)
32{
33 return luax_checktype<BezierCurve>(L, idx);
34}
35
36int w_BezierCurve_getDegree(lua_State *L)
37{
38 BezierCurve *curve = luax_checkbeziercurve(L, 1);
39 lua_pushnumber(L, curve->getDegree());
40 return 1;
41}
42
43int w_BezierCurve_getDerivative(lua_State *L)
44{
45 BezierCurve *curve = luax_checkbeziercurve(L, 1);
46 BezierCurve *deriv = new BezierCurve(curve->getDerivative());
47 luax_pushtype(L, deriv);
48 deriv->release();
49 return 1;
50}
51
52int w_BezierCurve_getControlPoint(lua_State *L)
53{
54 BezierCurve *curve = luax_checkbeziercurve(L, 1);
55 int idx = (int) luaL_checkinteger(L, 2);
56
57 if (idx > 0) // 1-indexing
58 idx--;
59
60 luax_catchexcept(L, [&]() {
61 Vector2 v = curve->getControlPoint(idx);
62 lua_pushnumber(L, v.x);
63 lua_pushnumber(L, v.y);
64 });
65
66 return 2;
67}
68
69int w_BezierCurve_setControlPoint(lua_State *L)
70{
71 BezierCurve *curve = luax_checkbeziercurve(L, 1);
72 int idx = (int) luaL_checkinteger(L, 2);
73 float vx = (float) luaL_checknumber(L, 3);
74 float vy = (float) luaL_checknumber(L, 4);
75
76 if (idx > 0) // 1-indexing
77 idx--;
78
79 luax_catchexcept(L, [&](){ curve->setControlPoint(idx, Vector2(vx,vy)); });
80 return 0;
81}
82
83int w_BezierCurve_insertControlPoint(lua_State *L)
84{
85 BezierCurve *curve = luax_checkbeziercurve(L, 1);
86 float vx = (float) luaL_checknumber(L, 2);
87 float vy = (float) luaL_checknumber(L, 3);
88 int idx = (int) luaL_optinteger(L, 4, -1);
89
90 if (idx > 0) // 1-indexing
91 idx--;
92
93 luax_catchexcept(L, [&](){ curve->insertControlPoint(Vector2(vx,vy), idx); });
94 return 0;
95}
96
97int w_BezierCurve_removeControlPoint(lua_State *L)
98{
99 BezierCurve *curve = luax_checkbeziercurve(L, 1);
100 int idx = (int) luaL_checkinteger(L, 2);
101
102 if (idx > 0) // 1-indexing
103 idx--;
104
105 luax_catchexcept(L, [&](){ curve->removeControlPoint(idx); });
106 return 0;
107}
108
109int w_BezierCurve_getControlPointCount(lua_State *L)
110{
111 BezierCurve *curve = luax_checkbeziercurve(L, 1);
112 lua_pushinteger(L, curve->getControlPointCount());
113 return 1;
114}
115
116int w_BezierCurve_translate(lua_State *L)
117{
118 BezierCurve *curve = luax_checkbeziercurve(L, 1);
119 float dx = (float) luaL_checknumber(L, 2);
120 float dy = (float) luaL_checknumber(L, 3);
121 curve->translate(Vector2(dx,dy));
122 return 0;
123}
124
125int w_BezierCurve_rotate(lua_State *L)
126{
127 BezierCurve *curve = luax_checkbeziercurve(L, 1);
128 double phi = luaL_checknumber(L, 2);
129 float ox = (float) luaL_optnumber(L, 3, 0);
130 float oy = (float) luaL_optnumber(L, 4, 0);
131 curve->rotate(phi, Vector2(ox,oy));
132 return 0;
133}
134
135int w_BezierCurve_scale(lua_State *L)
136{
137 BezierCurve *curve = luax_checkbeziercurve(L, 1);
138 double s = luaL_checknumber(L, 2);
139 float ox = (float) luaL_optnumber(L, 3, 0);
140 float oy = (float) luaL_optnumber(L, 4, 0);
141 curve->scale(s, Vector2(ox,oy));
142 return 0;
143}
144
145int w_BezierCurve_evaluate(lua_State *L)
146{
147 BezierCurve *curve = luax_checkbeziercurve(L, 1);
148 double t = luaL_checknumber(L, 2);
149
150 luax_catchexcept(L, [&]() {
151 Vector2 v = curve->evaluate(t);
152 lua_pushnumber(L, v.x);
153 lua_pushnumber(L, v.y);
154 });
155
156 return 2;
157
158}
159
160int w_BezierCurve_getSegment(lua_State *L)
161{
162 BezierCurve *curve = luax_checkbeziercurve(L, 1);
163 double t1 = luaL_checknumber(L, 2);
164 double t2 = luaL_checknumber(L, 3);
165
166 BezierCurve *segment;
167 luax_catchexcept(L, [&](){ segment = curve->getSegment(t1, t2); });
168 luax_pushtype(L, segment);
169 segment->release();
170
171 return 1;
172}
173
174int w_BezierCurve_render(lua_State *L)
175{
176 BezierCurve *curve = luax_checkbeziercurve(L, 1);
177 int accuracy = (int) luaL_optinteger(L, 2, 5);
178
179 std::vector<Vector2> points;
180 luax_catchexcept(L, [&](){ points = curve->render(accuracy); });
181
182 lua_createtable(L, (int) points.size() * 2, 0);
183 for (int i = 0; i < (int) points.size(); ++i)
184 {
185 lua_pushnumber(L, points[i].x);
186 lua_rawseti(L, -2, 2*i+1);
187 lua_pushnumber(L, points[i].y);
188 lua_rawseti(L, -2, 2*i+2);
189 }
190
191 return 1;
192}
193
194int w_BezierCurve_renderSegment(lua_State *L)
195{
196 BezierCurve *curve = luax_checkbeziercurve(L, 1);
197 double start = luaL_checknumber(L, 2);
198 double end = luaL_checknumber(L, 3);
199 int accuracy = (int) luaL_optinteger(L, 4, 5);
200
201 std::vector<Vector2> points;
202 luax_catchexcept(L, [&](){ points = curve->renderSegment(start, end, accuracy); });
203
204 lua_createtable(L, (int) points.size() * 2, 0);
205 for (int i = 0; i < (int) points.size(); ++i)
206 {
207 lua_pushnumber(L, points[i].x);
208 lua_rawseti(L, -2, 2*i+1);
209 lua_pushnumber(L, points[i].y);
210 lua_rawseti(L, -2, 2*i+2);
211 }
212
213 return 1;
214}
215
216static const luaL_Reg w_BezierCurve_functions[] =
217{
218 {"getDegree", w_BezierCurve_getDegree},
219 {"getDerivative", w_BezierCurve_getDerivative},
220 {"getControlPoint", w_BezierCurve_getControlPoint},
221 {"setControlPoint", w_BezierCurve_setControlPoint},
222 {"insertControlPoint", w_BezierCurve_insertControlPoint},
223 {"removeControlPoint", w_BezierCurve_removeControlPoint},
224 {"getControlPointCount", w_BezierCurve_getControlPointCount},
225 {"translate", w_BezierCurve_translate},
226 {"rotate", w_BezierCurve_rotate},
227 {"scale", w_BezierCurve_scale},
228 {"evaluate", w_BezierCurve_evaluate},
229 {"getSegment", w_BezierCurve_getSegment},
230 {"render", w_BezierCurve_render},
231 {"renderSegment", w_BezierCurve_renderSegment},
232 { 0, 0 }
233};
234
235extern "C" int luaopen_beziercurve(lua_State *L)
236{
237 return luax_register_type(L, &BezierCurve::type, w_BezierCurve_functions, nullptr);
238}
239
240} // math
241} // love
242