Upload UI
[lsnes.git] / src / lua / gui-arrow.cpp
blobf2e78a5bb4a91de43a49ab14a95f91cefc4c3214
1 #include "lua/internal.hpp"
2 #include "library/framebuffer.hpp"
3 #include "library/minmax.hpp"
5 namespace
7 int _dx[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
8 int _dy[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
9 int _dxn[8] = { 0, 0, 1, 1, 0, 0,-1,-1};
10 int _dyn[8] = { 1, 1, 0, 0,-1,-1, 0, 0};
11 int _dxp[8] = { 0, 1, 1, 0, 0,-1,-1, 0};
12 int _dyp[8] = { 1, 0, 0,-1,-1, 0, 0, 1};
13 struct render_object_arrow : public render_object
15 render_object_arrow(int32_t _x, int32_t _y, uint32_t _length, uint32_t _width,
16 uint32_t _headwidth, uint32_t _headthickness, int _direction, bool _fill,
17 premultiplied_color _color) throw()
18 : x(_x), y(_y), length(_length), width(_width), headwidth(_headwidth),
19 headthickness(_headthickness), direction(_direction), fill(_fill), color(_color) {}
20 ~render_object_arrow() throw() {}
21 template<bool X> void op(struct framebuffer<X>& scr) throw()
23 color.set_palette(scr);
24 uint32_t originx = scr.get_origin_x();
25 uint32_t originy = scr.get_origin_y();
26 auto orange = offsetrange();
27 for(int32_t o = orange.first; o < orange.second; o++) {
28 int32_t bpx, bpy;
29 bpx = x + originx + ((o < 0) ? _dxn[direction & 7] : _dxp[direction & 7]) * o;
30 bpy = y + originy + ((o < 0) ? _dyn[direction & 7] : _dyp[direction & 7]) * o;
31 int dx = _dx[direction & 7];
32 int dy = _dy[direction & 7];
33 auto drange = drawrange(o);
34 for(unsigned d = drange.first; d < drange.second; d++) {
35 int32_t xc = bpx + dx * d;
36 int32_t yc = bpy + dy * d;
37 if(xc < 0 || xc >= scr.get_width())
38 continue;
39 if(yc < 0 || yc >= scr.get_height())
40 continue;
41 color.apply(scr.rowptr(yc)[xc]);
45 void operator()(struct framebuffer<true>& scr) throw() { op(scr); }
46 void operator()(struct framebuffer<false>& scr) throw() { op(scr); }
47 void clone(render_queue& q) const throw(std::bad_alloc) { q.clone_helper(this); }
48 private:
49 std::pair<int32_t, int32_t> offsetrange()
51 int32_t cmin = -static_cast<int32_t>(width / 2);
52 int32_t cmax = static_cast<int32_t>((width + 1) / 2);
53 int32_t hmin = -static_cast<int32_t>(headwidth / 2);
54 int32_t hmax = static_cast<int32_t>((headwidth + 1) / 2);
55 return std::make_pair(min(cmin, hmin), max(cmax, hmax));
57 std::pair<int32_t, int32_t> drawrange(int32_t offset)
59 int32_t cmin = -static_cast<int32_t>(width / 2);
60 int32_t cmax = static_cast<int32_t>((width + 1) / 2);
61 int32_t hmin = -static_cast<int32_t>(headwidth / 2);
62 int32_t hmax = static_cast<int32_t>((headwidth + 1) / 2);
63 bool in_center = (offset >= cmin && offset < cmax);
64 bool in_head = (offset >= hmin && offset < hmax);
65 int32_t minc = std::abs(offset); //Works for head&tail.
66 int32_t maxc = 0;
67 if(in_center) maxc = max(maxc, static_cast<int32_t>(length));
68 if(in_head) {
69 if(fill) {
70 if(direction & 1) {
71 int32_t fedge = hmax - minc;
72 maxc = max(maxc, minc + fedge / 2 + 1);
73 } else
74 maxc = max(maxc, hmax);
75 } else
76 maxc = max(maxc, static_cast<int32_t>(minc + headthickness));
78 return std::make_pair(minc, maxc);
80 int32_t x;
81 int32_t y;
82 uint32_t length;
83 uint32_t width;
84 uint32_t headwidth;
85 uint32_t headthickness;
86 int direction;
87 bool fill;
88 premultiplied_color color;
91 function_ptr_luafun gui_box(lua_func_misc, "gui.arrow", [](lua_state& L, const std::string& fname) -> int {
92 if(!lua_render_ctx)
93 return 0;
94 int32_t x = L.get_numeric_argument<int32_t>(1, fname.c_str());
95 int32_t y = L.get_numeric_argument<int32_t>(2, fname.c_str());
96 uint32_t length = L.get_numeric_argument<int32_t>(3, fname.c_str());
97 uint32_t headwidth = L.get_numeric_argument<int32_t>(4, fname.c_str());
98 int direction = L.get_numeric_argument<int>(5, fname.c_str());
99 int64_t color = 0xFFFFFFU;
100 bool fill = false;
101 if(L.type(6) == LUA_TBOOLEAN && L.toboolean(6))
102 fill = true;
103 L.get_numeric_argument<int64_t>(7, color, fname.c_str());
104 uint32_t width = 1;
105 L.get_numeric_argument<uint32_t>(8, width, fname.c_str());
106 uint32_t headthickness = width;
107 L.get_numeric_argument<uint32_t>(9, headthickness, fname.c_str());
108 lua_render_ctx->queue->create_add<render_object_arrow>(x, y, length, width, headwidth, headthickness,
109 direction, fill, color);
110 return 0;