1 #include "lua/internal.hpp"
2 #include "core/framebuffer.hpp"
3 #include "library/framebuffer.hpp"
4 #include "library/png.hpp"
5 #include "library/string.hpp"
6 #include "library/threads.hpp"
7 #include "library/lua-framebuffer.hpp"
8 #include "library/zip.hpp"
9 #include "lua/bitmap.hpp"
26 lua::objpin
<lua_bitmap
> b
;
27 lua::objpin
<lua_dbitmap
> d
;
28 lua::objpin
<lua_palette
> p
;
33 tilemap(lua::state
& L
, size_t _width
, size_t _height
, size_t _cwidth
, size_t _cheight
);
34 static size_t overcommit(size_t _width
, size_t _height
, size_t _cwidth
, size_t _cheight
) { return 0; }
37 threads::alock
h(lock
);
38 render_kill_request(this);
40 static int create(lua::state
& L
, lua::parameters
& P
);
41 int draw(lua::state
& L
, lua::parameters
& P
);
42 int get(lua::state
& L
, lua::parameters
& P
)
48 threads::alock
h(lock
);
49 if(x
>= width
|| y
>= height
)
51 tilemap_entry
& e
= map
[y
* width
+ x
];
62 int set(lua::state
& L
, lua::parameters
& P
)
69 threads::alock
h(lock
);
70 if(x
>= width
|| y
>= height
)
72 tilemap_entry
& e
= map
[y
* width
+ x
];
73 if(P
.is
<lua_dbitmap
>(oidx
)) {
74 auto d
= P
.arg
<lua::objpin
<lua_dbitmap
>>(oidx
);
77 } else if(P
.is
<lua_bitmap
>(oidx
)) {
78 auto b
= P
.arg
<lua::objpin
<lua_bitmap
>>(oidx
);
79 auto p
= P
.arg
<lua::objpin
<lua_palette
>>(oidx
+ 1);
83 } else if(P
.is_novalue(oidx
)) {
86 P
.expected("BITMAP, DBITMAP or nil", oidx
);
89 int getsize(lua::state
& L
, lua::parameters
& P
)
95 int getcsize(lua::state
& L
, lua::parameters
& P
)
98 L
.pushnumber(cheight
);
101 size_t calcshift(size_t orig
, int32_t shift
, size_t dimension
, size_t offset
, bool circular
)
105 //Now the widow is scaled [0,dimension).
107 orig
= (orig
+ shift
) % dimension
;
110 while(orig
> dimension
) {
120 int scroll(lua::state
& L
, lua::parameters
& P
)
126 P(P
.skipped(), ox
, oy
, P
.optional(x0
, 0), P
.optional(y0
, 0), P
.optional(w
, width
),
127 P
.optional(h
, height
), P
.optional(circx
, false), P
.optional(circy
, false));
129 threads::alock
mh(lock
);
130 if(x0
> width
|| x0
+ w
> width
|| x0
+ w
< x0
|| y0
> height
|| y0
+ h
> height
||
132 throw std::runtime_error("Scroll window out of range");
133 if(!ox
&& !oy
) return 0;
134 std::vector
<tilemap_entry
> tmp
;
136 for(size_t _y
= 0; _y
< h
; _y
++) {
138 size_t sy
= calcshift(y
, oy
, h
, y0
, circy
);
139 if(sy
< y0
|| sy
>= y0
+ h
)
141 for(size_t _x
= 0; _x
< w
; _x
++) {
143 size_t sx
= calcshift(x
, ox
, w
, x0
, circx
);
144 if(sx
< x0
|| sx
>= x0
+ w
)
147 tmp
[_y
* w
+ _x
] = map
[sy
* width
+ sx
];
150 for(size_t _y
= 0; _y
< h
; _y
++)
151 for(size_t _x
= 0; _x
< w
; _x
++)
152 map
[(_y
+ y0
) * width
+ (_x
+ x0
)] = tmp
[_y
* w
+ _x
];
157 return (stringfmt() << width
<< "*" << height
<< " (cell " << cwidth
<< "*" << cheight
164 std::vector
<tilemap_entry
> map
;
168 struct render_object_tilemap
: public framebuffer::object
170 render_object_tilemap(int32_t _x
, int32_t _y
, int32_t _x0
, int32_t _y0
, uint32_t _w
,
171 uint32_t _h
, lua::objpin
<tilemap
> _map
)
172 : x(_x
), y(_y
), x0(_x0
), y0(_y0
), w(_w
), h(_h
), map(_map
) {}
173 ~render_object_tilemap() throw()
176 bool kill_request(void* obj
) throw()
178 return kill_request_ifeq(map
.object(), obj
);
180 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
) throw()
182 tilemap
& _map
= *map
;
183 threads::alock
h(_map
.lock
);
184 for(size_t ty
= 0; ty
< _map
.height
; ty
++) {
185 size_t basey
= _map
.cheight
* ty
;
186 for(size_t tx
= 0; tx
< _map
.width
; tx
++) {
187 size_t basex
= _map
.cwidth
* tx
;
188 composite_op(scr
, _map
.map
[ty
* _map
.width
+ tx
], basex
, basey
);
192 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
, int32_t xp
,
193 int32_t yp
, int32_t xmin
, int32_t xmax
, int32_t ymin
, int32_t ymax
, lua_dbitmap
& d
) throw()
195 if(xmin
>= xmax
|| ymin
>= ymax
) return;
197 for(int32_t r
= ymin
; r
< ymax
; r
++) {
198 typename
framebuffer::fb
<T
>::element_t
* rptr
= scr
.rowptr(yp
+ r
);
199 size_t eptr
= xp
+ xmin
;
200 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++)
201 d
.pixels
[r
* d
.width
+ c
].apply(rptr
[eptr
]);
204 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
, int32_t xp
,
205 int32_t yp
, int32_t xmin
, int32_t xmax
, int32_t ymin
, int32_t ymax
, lua_bitmap
& b
,
209 if(xmin
>= xmax
|| ymin
>= ymax
) return;
210 p
.palette_mutex
.lock();
211 framebuffer::color
* palette
= &p
.colors
[0];
212 size_t pallim
= p
.colors
.size();
214 for(int32_t r
= ymin
; r
< ymax
; r
++) {
215 typename
framebuffer::fb
<T
>::element_t
* rptr
= scr
.rowptr(yp
+ r
);
216 size_t eptr
= xp
+ xmin
;
217 for(int32_t c
= xmin
; c
< xmax
; c
++, eptr
++) {
218 uint16_t i
= b
.pixels
[r
* b
.width
+ c
];
220 palette
[i
].apply(rptr
[eptr
]);
223 p
.palette_mutex
.unlock();
225 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
, tilemap_entry
& e
, int32_t bx
,
237 //Calculate notional screen coordinates for the tile.
238 int32_t scrx
= x
+ scr
.get_origin_x() + bx
- x0
;
239 int32_t scry
= y
+ scr
.get_origin_y() + by
- y0
;
240 int32_t scrw
= scr
.get_width();
241 int32_t scrh
= scr
.get_height();
246 clip(scrx
, scrw
, x
+ scr
.get_origin_x(), w
, xmin
, xmax
);
247 clip(scry
, scrh
, y
+ scr
.get_origin_y(), h
, ymin
, ymax
);
249 composite_op(scr
, scrx
, scry
, xmin
, xmax
, ymin
, ymax
, *e
.b
, *e
.p
);
251 composite_op(scr
, scrx
, scry
, xmin
, xmax
, ymin
, ymax
, *e
.d
);
253 //scrc + cmin >= 0 and scrc + cmax <= scrd (Clip on screen).
254 //scrc + cmin >= bc and scrc + cmax <= bc + d (Clip on texture).
255 void clip(int32_t scrc
, int32_t scrd
, int32_t bc
, int32_t d
, int32_t& cmin
, int32_t& cmax
)
259 if(scrc
+ cmax
> scrd
)
263 if(scrc
+ cmax
> bc
+ d
)
264 cmax
= bc
+ d
- scrc
;
266 void operator()(struct framebuffer::fb
<false>& x
) throw() { composite_op(x
); }
267 void operator()(struct framebuffer::fb
<true>& x
) throw() { composite_op(x
); }
268 void clone(framebuffer::queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
276 lua::objpin
<tilemap
> map
;
279 int tilemap::draw(lua::state
& L
, lua::parameters
& P
)
283 lua::objpin
<tilemap
> t
;
285 if(!lua_render_ctx
) return 0;
287 P(t
, x
, y
, P
.optional(x0
, 0), P
.optional(y0
, 0), P
.optional(w
, width
* cwidth
),
288 P
.optional(h
, height
* cheight
));
290 lua_render_ctx
->queue
->create_add
<render_object_tilemap
>(x
, y
, x0
, y0
, w
, h
, t
);
294 int tilemap::create(lua::state
& L
, lua::parameters
& P
)
296 uint32_t w
, h
, px
, py
;
300 lua::_class
<tilemap
>::create(L
, w
, h
, px
, py
);
304 lua::_class
<tilemap
> class_tilemap(lua_class_gui
, "TILEMAP", {
305 {"new", tilemap::create
},
307 {"draw", &tilemap::draw
},
308 {"set", &tilemap::set
},
309 {"get", &tilemap::get
},
310 {"scroll", &tilemap::scroll
},
311 {"getsize", &tilemap::getsize
},
312 {"getcsize", &tilemap::getcsize
},
315 tilemap::tilemap(lua::state
& L
, size_t _width
, size_t _height
, size_t _cwidth
, size_t _cheight
)
316 : width(_width
), height(_height
), cwidth(_cwidth
), cheight(_cheight
)
318 if(width
* height
/ height
!= width
)
319 throw std::bad_alloc();
320 map
.resize(width
* height
);