Skip to content

Commit 2dde3cd

Browse files
author
Semphris
committed
Refactored AnchorPoint and improved TextArea
1 parent da36f6c commit 2dde3cd

File tree

6 files changed

+180
-111
lines changed

6 files changed

+180
-111
lines changed

src/math/anchor_point.cpp

Lines changed: 44 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -23,53 +23,42 @@
2323

2424
#include "math/rectf.hpp"
2525
#include "util/log.hpp"
26+
#include "util/gettext.hpp"
27+
28+
std::vector<std::string> get_anchor_names()
29+
{
30+
// Must be dynamic because language can change at runtime (+ tinygettext must
31+
// be init'ed)
32+
return {
33+
_("Top Left"),
34+
_("Top"),
35+
_("Top Right"),
36+
_("Left"),
37+
_("Middle"),
38+
_("Right"),
39+
_("Bottom Left"),
40+
_("Bottom"),
41+
_("Bottom Right"),
42+
};
43+
}
2644

2745
std::string anchor_point_to_string(AnchorPoint point)
2846
{
29-
switch (point) {
30-
case ANCHOR_TOP_LEFT:
31-
return "topleft";
32-
case ANCHOR_TOP:
33-
return "top";
34-
case ANCHOR_TOP_RIGHT:
35-
return "topright";
36-
case ANCHOR_LEFT:
37-
return "left";
38-
case ANCHOR_MIDDLE:
39-
return "middle";
40-
case ANCHOR_RIGHT:
41-
return "right";
42-
case ANCHOR_BOTTOM_LEFT:
43-
return "bottomleft";
44-
case ANCHOR_BOTTOM:
45-
return "bottom";
46-
case ANCHOR_BOTTOM_RIGHT:
47-
return "bottomright";
48-
default:
49-
throw std::runtime_error("Invalid anchor point");
47+
try
48+
{
49+
return g_anchor_keys.at(point);
50+
}
51+
catch(const std::out_of_range&)
52+
{
53+
throw std::runtime_error("Invalid anchor point");
5054
}
5155
}
5256

5357
AnchorPoint string_to_anchor_point(const std::string& str)
5458
{
55-
if (str == "topleft")
56-
return ANCHOR_TOP_LEFT;
57-
else if (str == "top")
58-
return ANCHOR_TOP;
59-
else if (str == "topright")
60-
return ANCHOR_TOP_RIGHT;
61-
else if (str == "left")
62-
return ANCHOR_LEFT;
63-
else if (str == "middle")
64-
return ANCHOR_MIDDLE;
65-
else if (str == "right")
66-
return ANCHOR_RIGHT;
67-
else if (str == "bottomleft")
68-
return ANCHOR_BOTTOM_LEFT;
69-
else if (str == "bottom")
70-
return ANCHOR_BOTTOM;
71-
else if (str == "bottomright")
72-
return ANCHOR_BOTTOM_RIGHT;
59+
for (size_t i = 0; i < g_anchor_keys.size(); i++)
60+
if (g_anchor_keys.at(i) == str)
61+
return static_cast<AnchorPoint>(i);
7362

7463
std::ostringstream msg;
7564
msg << "Unknown anchor '" << str << "'";
@@ -80,14 +69,14 @@ Vector get_anchor_pos(const Rectf& rect, AnchorPoint point)
8069
{
8170
Vector result(0.0f, 0.0f);
8271

83-
switch (point & ANCHOR_V_MASK) {
84-
case ANCHOR_LEFT:
72+
switch (point % 3) {
73+
case 0: // left
8574
result.x = rect.get_left();
8675
break;
87-
case ANCHOR_MIDDLE:
76+
case 1: // middle
8877
result.x = rect.get_left() + (rect.get_right() - rect.get_left()) / 2.0f;
8978
break;
90-
case ANCHOR_RIGHT:
79+
case 2: // right
9180
result.x = rect.get_right();
9281
break;
9382
default:
@@ -96,14 +85,14 @@ Vector get_anchor_pos(const Rectf& rect, AnchorPoint point)
9685
break;
9786
}
9887

99-
switch (point & ANCHOR_H_MASK) {
100-
case ANCHOR_TOP:
88+
switch (point / 3) {
89+
case 0: // top
10190
result.y = rect.get_top();
10291
break;
103-
case ANCHOR_MIDDLE:
92+
case 1: // middle
10493
result.y = rect.get_top() + (rect.get_bottom() - rect.get_top()) / 2.0f;
10594
break;
106-
case ANCHOR_BOTTOM:
95+
case 2: // bottom
10796
result.y = rect.get_bottom();
10897
break;
10998
default:
@@ -120,14 +109,14 @@ Vector get_anchor_pos(const Rectf& destrect, float width, float height,
120109
{
121110
Vector result(0.0f, 0.0f);
122111

123-
switch (point & ANCHOR_V_MASK) {
124-
case ANCHOR_LEFT:
112+
switch (point % 3) {
113+
case 0: // left
125114
result.x = destrect.get_left();
126115
break;
127-
case ANCHOR_MIDDLE:
116+
case 1: // middle
128117
result.x = destrect.get_middle().x - width / 2.0f;
129118
break;
130-
case ANCHOR_RIGHT:
119+
case 2: // right
131120
result.x = destrect.get_right() - width;
132121
break;
133122
default:
@@ -136,14 +125,14 @@ Vector get_anchor_pos(const Rectf& destrect, float width, float height,
136125
break;
137126
}
138127

139-
switch (point & ANCHOR_H_MASK) {
140-
case ANCHOR_TOP:
128+
switch (point / 3) {
129+
case 0: // top
141130
result.y = destrect.get_top();
142131
break;
143-
case ANCHOR_MIDDLE:
132+
case 1: // middle
144133
result.y = destrect.get_middle().y - height / 2.0f;
145134
break;
146-
case ANCHOR_BOTTOM:
135+
case 2: // bottom
147136
result.y = destrect.get_bottom() - height;
148137
break;
149138
default:

src/math/anchor_point.hpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,31 @@
1818
#define HEADER_SUPERTUX_MATH_ANCHOR_POINT_HPP
1919

2020
#include <string>
21+
#include <vector>
2122

2223
#include "math/vector.hpp"
2324

2425
class Rectf;
2526

2627
enum AnchorPoint {
27-
ANCHOR_H_MASK = 0x00f0,
28-
ANCHOR_TOP = 0x0010,
29-
ANCHOR_BOTTOM = 0x0020,
30-
ANCHOR_V_MASK = 0x000f,
31-
ANCHOR_LEFT = 0x0001,
32-
ANCHOR_RIGHT = 0x0002,
33-
ANCHOR_MIDDLE = 0x0000,
34-
35-
ANCHOR_TOP_LEFT = ANCHOR_TOP | ANCHOR_LEFT,
36-
ANCHOR_TOP_RIGHT = ANCHOR_TOP | ANCHOR_RIGHT,
37-
ANCHOR_BOTTOM_LEFT = ANCHOR_BOTTOM | ANCHOR_LEFT,
38-
ANCHOR_BOTTOM_RIGHT = ANCHOR_BOTTOM | ANCHOR_RIGHT
28+
ANCHOR_TOP_LEFT,
29+
ANCHOR_TOP,
30+
ANCHOR_TOP_RIGHT,
31+
ANCHOR_LEFT,
32+
ANCHOR_MIDDLE,
33+
ANCHOR_RIGHT,
34+
ANCHOR_BOTTOM_LEFT,
35+
ANCHOR_BOTTOM,
36+
ANCHOR_BOTTOM_RIGHT,
37+
ANCHOR_LAST = ANCHOR_BOTTOM_RIGHT
3938
};
4039

40+
const std::vector<std::string> g_anchor_keys = {
41+
"topleft", "top", "topright", "left", "middle", "right", "bottomleft",
42+
"bottom", "bottomright"
43+
};
44+
45+
std::vector<std::string> get_anchor_names();
4146
std::string anchor_point_to_string(AnchorPoint point);
4247
AnchorPoint string_to_anchor_point(const std::string& str);
4348
Vector get_anchor_pos(const Rectf& rect, AnchorPoint point);

src/scripting/anchor_points.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@
2020
namespace scripting {
2121

2222
// TODO get these from the definitions in anchor.h (needs miniswig update)
23-
static const int ANCHOR_TOP = 0x0010;
24-
static const int ANCHOR_BOTTOM = 0x0020;
25-
static const int ANCHOR_LEFT = 0x0001;
26-
static const int ANCHOR_RIGHT = 0x0002;
27-
static const int ANCHOR_MIDDLE = 0x0000;
28-
static const int ANCHOR_TOP_LEFT = 0x0011;
29-
static const int ANCHOR_TOP_RIGHT = 0x0012;
30-
static const int ANCHOR_BOTTOM_LEFT = 0x0021;
31-
static const int ANCHOR_BOTTOM_RIGHT = 0x0022;
23+
static const int ANCHOR_TOP_LEFT = 0;
24+
static const int ANCHOR_TOP = 1;
25+
static const int ANCHOR_TOP_RIGHT = 2;
26+
static const int ANCHOR_LEFT = 3;
27+
static const int ANCHOR_MIDDLE = 4;
28+
static const int ANCHOR_RIGHT = 5;
29+
static const int ANCHOR_BOTTOM_LEFT = 6;
30+
static const int ANCHOR_BOTTOM = 7;
31+
static const int ANCHOR_BOTTOM_RIGHT = 8;
3232

3333
} // namespace scripting
3434

src/scripting/wrapper.cpp

Lines changed: 96 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11092,6 +11092,66 @@ static SQInteger WorldMap_release_hook(SQUserPointer ptr, SQInteger )
1109211092
return 0;
1109311093
}
1109411094

11095+
static SQInteger WorldMap_get_tux_x_wrapper(HSQUIRRELVM vm)
11096+
{
11097+
SQUserPointer data;
11098+
if(SQ_FAILED(sq_getinstanceup(vm, 1, &data, nullptr)) || !data) {
11099+
sq_throwerror(vm, _SC("'get_tux_x' called without instance"));
11100+
return SQ_ERROR;
11101+
}
11102+
auto _this = reinterpret_cast<scripting::WorldMap*> (data);
11103+
11104+
if (_this == nullptr) {
11105+
return SQ_ERROR;
11106+
}
11107+
11108+
11109+
try {
11110+
float return_value = _this->get_tux_x();
11111+
11112+
sq_pushfloat(vm, return_value);
11113+
return 1;
11114+
11115+
} catch(std::exception& e) {
11116+
sq_throwerror(vm, e.what());
11117+
return SQ_ERROR;
11118+
} catch(...) {
11119+
sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_tux_x'"));
11120+
return SQ_ERROR;
11121+
}
11122+
11123+
}
11124+
11125+
static SQInteger WorldMap_get_tux_y_wrapper(HSQUIRRELVM vm)
11126+
{
11127+
SQUserPointer data;
11128+
if(SQ_FAILED(sq_getinstanceup(vm, 1, &data, nullptr)) || !data) {
11129+
sq_throwerror(vm, _SC("'get_tux_y' called without instance"));
11130+
return SQ_ERROR;
11131+
}
11132+
auto _this = reinterpret_cast<scripting::WorldMap*> (data);
11133+
11134+
if (_this == nullptr) {
11135+
return SQ_ERROR;
11136+
}
11137+
11138+
11139+
try {
11140+
float return_value = _this->get_tux_y();
11141+
11142+
sq_pushfloat(vm, return_value);
11143+
return 1;
11144+
11145+
} catch(std::exception& e) {
11146+
sq_throwerror(vm, e.what());
11147+
return SQ_ERROR;
11148+
} catch(...) {
11149+
sq_throwerror(vm, _SC("Unexpected exception while executing function 'get_tux_y'"));
11150+
return SQ_ERROR;
11151+
}
11152+
11153+
}
11154+
1109511155
static SQInteger display_wrapper(HSQUIRRELVM vm)
1109611156
{
1109711157
return scripting::display(vm);
@@ -12980,56 +13040,56 @@ void register_supertux_wrapper(HSQUIRRELVM v)
1298013040
{
1298113041
using namespace wrapper;
1298213042

13043+
sq_pushstring(v, "ANCHOR_TOP_LEFT", -1);
13044+
sq_pushinteger(v, 0);
13045+
if(SQ_FAILED(sq_createslot(v, -3))) {
13046+
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_LEFT'");
13047+
}
13048+
1298313049
sq_pushstring(v, "ANCHOR_TOP", -1);
12984-
sq_pushinteger(v, 16);
13050+
sq_pushinteger(v, 1);
1298513051
if(SQ_FAILED(sq_createslot(v, -3))) {
1298613052
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP'");
1298713053
}
1298813054

12989-
sq_pushstring(v, "ANCHOR_BOTTOM", -1);
12990-
sq_pushinteger(v, 32);
13055+
sq_pushstring(v, "ANCHOR_TOP_RIGHT", -1);
13056+
sq_pushinteger(v, 2);
1299113057
if(SQ_FAILED(sq_createslot(v, -3))) {
12992-
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM'");
13058+
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_RIGHT'");
1299313059
}
1299413060

1299513061
sq_pushstring(v, "ANCHOR_LEFT", -1);
12996-
sq_pushinteger(v, 1);
13062+
sq_pushinteger(v, 3);
1299713063
if(SQ_FAILED(sq_createslot(v, -3))) {
1299813064
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_LEFT'");
1299913065
}
1300013066

13001-
sq_pushstring(v, "ANCHOR_RIGHT", -1);
13002-
sq_pushinteger(v, 2);
13003-
if(SQ_FAILED(sq_createslot(v, -3))) {
13004-
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_RIGHT'");
13005-
}
13006-
1300713067
sq_pushstring(v, "ANCHOR_MIDDLE", -1);
13008-
sq_pushinteger(v, 0);
13068+
sq_pushinteger(v, 4);
1300913069
if(SQ_FAILED(sq_createslot(v, -3))) {
1301013070
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_MIDDLE'");
1301113071
}
1301213072

13013-
sq_pushstring(v, "ANCHOR_TOP_LEFT", -1);
13014-
sq_pushinteger(v, 17);
13073+
sq_pushstring(v, "ANCHOR_RIGHT", -1);
13074+
sq_pushinteger(v, 5);
1301513075
if(SQ_FAILED(sq_createslot(v, -3))) {
13016-
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_LEFT'");
13076+
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_RIGHT'");
1301713077
}
1301813078

13019-
sq_pushstring(v, "ANCHOR_TOP_RIGHT", -1);
13020-
sq_pushinteger(v, 18);
13079+
sq_pushstring(v, "ANCHOR_BOTTOM_LEFT", -1);
13080+
sq_pushinteger(v, 6);
1302113081
if(SQ_FAILED(sq_createslot(v, -3))) {
13022-
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_TOP_RIGHT'");
13082+
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM_LEFT'");
1302313083
}
1302413084

13025-
sq_pushstring(v, "ANCHOR_BOTTOM_LEFT", -1);
13026-
sq_pushinteger(v, 33);
13085+
sq_pushstring(v, "ANCHOR_BOTTOM", -1);
13086+
sq_pushinteger(v, 7);
1302713087
if(SQ_FAILED(sq_createslot(v, -3))) {
13028-
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM_LEFT'");
13088+
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM'");
1302913089
}
1303013090

1303113091
sq_pushstring(v, "ANCHOR_BOTTOM_RIGHT", -1);
13032-
sq_pushinteger(v, 34);
13092+
sq_pushinteger(v, 8);
1303313093
if(SQ_FAILED(sq_createslot(v, -3))) {
1303413094
throw SquirrelError(v, "Couldn't register constant 'ANCHOR_BOTTOM_RIGHT'");
1303513095
}
@@ -14792,6 +14852,20 @@ void register_supertux_wrapper(HSQUIRRELVM v)
1479214852
msg << "Couldn't create new class 'WorldMap'";
1479314853
throw SquirrelError(v, msg.str());
1479414854
}
14855+
sq_pushstring(v, "get_tux_x", -1);
14856+
sq_newclosure(v, &WorldMap_get_tux_x_wrapper, 0);
14857+
sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t");
14858+
if(SQ_FAILED(sq_createslot(v, -3))) {
14859+
throw SquirrelError(v, "Couldn't register function 'get_tux_x'");
14860+
}
14861+
14862+
sq_pushstring(v, "get_tux_y", -1);
14863+
sq_newclosure(v, &WorldMap_get_tux_y_wrapper, 0);
14864+
sq_setparamscheck(v, SQ_MATCHTYPEMASKSTRING, "x|t");
14865+
if(SQ_FAILED(sq_createslot(v, -3))) {
14866+
throw SquirrelError(v, "Couldn't register function 'get_tux_y'");
14867+
}
14868+
1479514869
if(SQ_FAILED(sq_createslot(v, -3))) {
1479614870
throw SquirrelError(v, "Couldn't register class 'WorldMap'");
1479714871
}

0 commit comments

Comments
 (0)