1 #include "lua/internal.hpp"
2 #include "core/framebuffer.hpp"
3 #include "core/instance.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
) {
35 return lua::overcommit_std_align
+ 2 * sizeof(tilemap_entry
) * (size_t)_width
* _height
;
39 threads::alock
h(lock
);
40 CORE().fbuf
->render_kill_request(this);
42 static int create(lua::state
& L
, lua::parameters
& P
);
43 template<bool outside
> int draw(lua::state
& L
, lua::parameters
& P
);
44 int get(lua::state
& L
, lua::parameters
& P
)
50 threads::alock
h(lock
);
51 if(x
>= width
|| y
>= height
)
53 tilemap_entry
& e
= map
[y
* width
+ x
];
64 int set(lua::state
& L
, lua::parameters
& P
)
71 threads::alock
h(lock
);
72 if(x
>= width
|| y
>= height
)
74 tilemap_entry
& e
= map
[y
* width
+ x
];
75 if(P
.is
<lua_dbitmap
>(oidx
)) {
76 auto d
= P
.arg
<lua::objpin
<lua_dbitmap
>>(oidx
);
79 } else if(P
.is
<lua_bitmap
>(oidx
)) {
80 auto b
= P
.arg
<lua::objpin
<lua_bitmap
>>(oidx
);
81 auto p
= P
.arg
<lua::objpin
<lua_palette
>>(oidx
+ 1);
85 } else if(P
.is_novalue(oidx
)) {
88 P
.expected("BITMAP, DBITMAP or nil", oidx
);
91 int getsize(lua::state
& L
, lua::parameters
& P
)
97 int getcsize(lua::state
& L
, lua::parameters
& P
)
100 L
.pushnumber(cheight
);
103 size_t calcshift(size_t orig
, int32_t shift
, size_t dimension
, size_t offset
, bool circular
)
107 //Now the widow is scaled [0,dimension).
109 orig
= (orig
+ shift
) % dimension
;
112 while(orig
> dimension
) {
122 int scroll(lua::state
& L
, lua::parameters
& P
)
128 P(P
.skipped(), ox
, oy
, P
.optional(x0
, 0), P
.optional(y0
, 0), P
.optional(w
, width
),
129 P
.optional(h
, height
), P
.optional(circx
, false), P
.optional(circy
, false));
131 threads::alock
mh(lock
);
132 if(x0
> width
|| x0
+ w
> width
|| x0
+ w
< x0
|| y0
> height
|| y0
+ h
> height
||
134 throw std::runtime_error("Scroll window out of range");
135 if(!ox
&& !oy
) return 0;
136 tilemap_entry
* tmp
= tmpmap
;
137 for(size_t _y
= 0; _y
< h
; _y
++) {
139 size_t sy
= calcshift(y
, oy
, h
, y0
, circy
);
140 if(sy
< y0
|| sy
>= y0
+ h
)
142 for(size_t _x
= 0; _x
< w
; _x
++) {
144 size_t sx
= calcshift(x
, ox
, w
, x0
, circx
);
145 if(sx
< x0
|| sx
>= x0
+ w
)
148 tmp
[_y
* w
+ _x
] = map
[sy
* width
+ sx
];
151 for(size_t _y
= 0; _y
< h
; _y
++)
152 for(size_t _x
= 0; _x
< w
; _x
++)
153 map
[(_y
+ y0
) * width
+ (_x
+ x0
)] = tmp
[_y
* w
+ _x
];
158 return (stringfmt() << width
<< "*" << height
<< " (cell " << cwidth
<< "*" << cheight
166 tilemap_entry
* tmpmap
;
170 struct render_object_tilemap
: public framebuffer::object
172 render_object_tilemap(int32_t _x
, int32_t _y
, int32_t _x0
, int32_t _y0
, uint32_t _w
,
173 uint32_t _h
, bool _outside
, lua::objpin
<tilemap
>& _map
)
174 : x(_x
), y(_y
), x0(_x0
), y0(_y0
), w(_w
), h(_h
), outside(_outside
), map(_map
) {}
175 ~render_object_tilemap() throw()
178 bool kill_request(void* obj
) throw()
180 return kill_request_ifeq(map
.object(), obj
);
182 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
) throw()
184 tilemap
& _map
= *map
;
185 threads::alock
h(_map
.lock
);
186 for(size_t ty
= 0; ty
< _map
.height
; ty
++) {
187 size_t basey
= _map
.cheight
* ty
;
188 for(size_t tx
= 0; tx
< _map
.width
; tx
++) {
189 size_t basex
= _map
.cwidth
* tx
;
190 composite_op(scr
, _map
.map
[ty
* _map
.width
+ tx
], basex
, basey
);
194 template<bool T
> void composite_op(struct framebuffer::fb
<T
>& scr
, tilemap_entry
& e
, int32_t bx
,
207 uint32_t oX
= x
+ scr
.get_origin_x() - x0
;
208 uint32_t oY
= y
+ scr
.get_origin_y() - y0
;
209 range bX
= ((range::make_w(scr
.get_width()) - oX
) & range::make_s(bx
, _w
) &
210 range::make_s(x0
, w
)) - bx
;
211 range bY
= ((range::make_w(scr
.get_height()) - oY
) & range::make_s(by
, _h
) &
212 range::make_s(y0
, h
)) - by
;
213 range sX
= range::make_s(-x
- bx
+ x0
, scr
.get_last_blit_width());
214 range sY
= range::make_s(-y
- by
+ y0
, scr
.get_last_blit_height());
217 lua_bitmap_composite(scr
, oX
+ bx
, oY
+ by
, bX
, bY
, sX
, sY
, outside
,
218 lua_bitmap_holder
<T
>(*e
.b
, *e
.p
));
220 lua_bitmap_composite(scr
, oX
+ bx
, oY
+ by
, bX
, bY
, sX
, sY
, outside
,
221 lua_dbitmap_holder
<T
>(*e
.d
));
223 void operator()(struct framebuffer::fb
<false>& x
) throw() { composite_op(x
); }
224 void operator()(struct framebuffer::fb
<true>& x
) throw() { composite_op(x
); }
225 void clone(framebuffer::queue
& q
) const throw(std::bad_alloc
) { q
.clone_helper(this); }
234 lua::objpin
<tilemap
> map
;
237 template<bool outside
> int tilemap::draw(lua::state
& L
, lua::parameters
& P
)
242 lua::objpin
<tilemap
> t
;
244 if(!core
.lua2
->render_ctx
) return 0;
246 P(t
, x
, y
, P
.optional(x0
, 0), P
.optional(y0
, 0), P
.optional(w
, width
* cwidth
),
247 P
.optional(h
, height
* cheight
));
249 core
.lua2
->render_ctx
->queue
->create_add
<render_object_tilemap
>(x
, y
, x0
, y0
, w
, h
, outside
, t
);
253 int tilemap::create(lua::state
& L
, lua::parameters
& P
)
255 uint32_t w
, h
, px
, py
;
259 lua::_class
<tilemap
>::create(L
, w
, h
, px
, py
);
263 lua::_class
<tilemap
> LUA_class_tilemap(lua_class_gui
, "TILEMAP", {
264 {"new", tilemap::create
},
266 {"draw", &tilemap::draw
<false>},
267 {"draw_outside", &tilemap::draw
<true>},
268 {"set", &tilemap::set
},
269 {"get", &tilemap::get
},
270 {"scroll", &tilemap::scroll
},
271 {"getsize", &tilemap::getsize
},
272 {"getcsize", &tilemap::getcsize
},
275 tilemap::tilemap(lua::state
& L
, size_t _width
, size_t _height
, size_t _cwidth
, size_t _cheight
)
276 : width(_width
), height(_height
), cwidth(_cwidth
), cheight(_cheight
)
278 if(height
> 0 && overcommit(width
, height
, cwidth
, cheight
) / height
/ sizeof(tilemap_entry
) < width
)
279 throw std::bad_alloc();
281 map
= lua::align_overcommit
<tilemap
, tilemap_entry
>(this);
282 tmpmap
= &map
[width
* height
];
283 //Initialize the map!
284 for(size_t i
= 0; i
< 2 * width
* height
; i
++)
285 new(map
+ i
) tilemap_entry();