1 #include "core/instance.hpp"
2 #include "lua/internal.hpp"
3 #include "library/framebuffer.hpp"
4 #include "library/lua-framebuffer.hpp"
5 #include "library/minmax.hpp"
9 const int _dx
[8] = {-1,-1, 0, 1, 1, 1, 0,-1};
10 const int _dy
[8] = { 0, 1, 1, 1, 0,-1,-1,-1};
11 const int _dxn
[8] = { 0, 0, 1, 1, 0, 0,-1,-1};
12 const int _dyn
[8] = { 1, 1, 0, 0,-1,-1, 0, 0};
13 const int _dxp
[8] = { 0, 1, 1, 0, 0,-1,-1, 0};
14 const int _dyp
[8] = { 1, 0, 0,-1,-1, 0, 0, 1};
15 struct render_object_arrow
: public framebuffer::object
17 render_object_arrow(int32_t _x
, int32_t _y
, uint32_t _length
, uint32_t _width
,
18 uint32_t _headwidth
, uint32_t _headthickness
, int _direction
, bool _fill
,
19 framebuffer::color _color
) throw()
20 : x(_x
), y(_y
), length(_length
), width(_width
), headwidth(_headwidth
),
21 headthickness(_headthickness
), direction(_direction
), fill(_fill
), color(_color
) {}
22 ~render_object_arrow() throw() {}
23 template<bool X
> void op(struct framebuffer::fb
<X
>& scr
) throw()
25 uint32_t originx
= scr
.get_origin_x();
26 uint32_t originy
= scr
.get_origin_y();
27 auto orange
= offsetrange();
28 for(int32_t o
= orange
.first
; o
< orange
.second
; o
++) {
30 bpx
= x
+ originx
+ ((o
< 0) ? _dxn
[direction
& 7] : _dxp
[direction
& 7]) * o
;
31 bpy
= y
+ originy
+ ((o
< 0) ? _dyn
[direction
& 7] : _dyp
[direction
& 7]) * o
;
32 int dx
= _dx
[direction
& 7];
33 int dy
= _dy
[direction
& 7];
34 auto drange
= drawrange(o
);
35 for(signed d
= drange
.first
; d
< drange
.second
; d
++) {
36 int32_t xc
= bpx
+ dx
* d
;
37 int32_t yc
= bpy
+ dy
* d
;
38 if(xc
< 0 || xc
>= (ssize_t
)scr
.get_width())
40 if(yc
< 0 || yc
>= (ssize_t
)scr
.get_height())
42 color
.apply(scr
.rowptr(yc
)[xc
]);
46 void operator()(struct framebuffer::fb
<true>& scr
) throw() { op(scr
); }
47 void operator()(struct framebuffer::fb
<false>& scr
) throw() { op(scr
); }
48 void clone(framebuffer::queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
50 std::pair
<int32_t, int32_t> offsetrange()
52 int32_t cmin
= -static_cast<int32_t>(width
/ 2);
53 int32_t cmax
= static_cast<int32_t>((width
+ 1) / 2);
54 int32_t hmin
= -static_cast<int32_t>(headwidth
/ 2);
55 int32_t hmax
= static_cast<int32_t>((headwidth
+ 1) / 2);
56 return std::make_pair(min(cmin
, hmin
), max(cmax
, hmax
));
58 std::pair
<int32_t, int32_t> drawrange(int32_t offset
)
60 int32_t cmin
= -static_cast<int32_t>(width
/ 2);
61 int32_t cmax
= static_cast<int32_t>((width
+ 1) / 2);
62 int32_t hmin
= -static_cast<int32_t>(headwidth
/ 2);
63 int32_t hmax
= static_cast<int32_t>((headwidth
+ 1) / 2);
64 bool in_center
= (offset
>= cmin
&& offset
< cmax
);
65 bool in_head
= (offset
>= hmin
&& offset
< hmax
);
66 int32_t minc
= std::abs(offset
); //Works for head&tail.
68 if(in_center
) maxc
= max(maxc
, static_cast<int32_t>(length
));
72 int32_t fedge
= hmax
- minc
;
73 maxc
= max(maxc
, minc
+ fedge
/ 2 + 1);
75 maxc
= max(maxc
, hmax
);
77 maxc
= max(maxc
, static_cast<int32_t>(minc
+ headthickness
));
79 return std::make_pair(minc
, maxc
);
86 uint32_t headthickness
;
89 framebuffer::color color
;
92 int arrow(lua::state
& L
, lua::parameters
& P
)
96 uint32_t length
, headwidth
, width
, headthickness
;
99 framebuffer::color color
;
101 if(!core
.lua2
->render_ctx
) return 0;
103 P(x
, y
, length
, headwidth
, direction
, P
.optional(fill
, false), P
.optional(color
, 0xFFFFFF),
104 P
.optional(width
, 1), P
.optional2(headthickness
, width
));
106 core
.lua2
->render_ctx
->queue
->create_add
<render_object_arrow
>(x
, y
, length
, width
, headwidth
,
107 headthickness
, direction
, fill
, color
);
111 lua::functions
LUA_arrow_fns(lua_func_misc
, "gui", {