1+ #include " lua_buffers.h"
2+
3+ #include " SFML\Graphics.hpp"
4+
5+ #include " lua.hpp"
6+ #include " lualib.h"
7+ #include " lauxlib.h"
8+
9+ #include < unordered_map>
10+ enum class buffer_type {
11+ vector_u8x4,
12+ vector_float,
13+ };
14+ struct u8x4 {
15+ uint8_t r, g, b, a;
16+ };
17+ struct buffer_entry
18+ {
19+ int w;
20+ buffer_type t;
21+ };
22+ std::unordered_map<void *, buffer_entry> buffer_registry;
23+
24+ void get_current_size (lua_State* L, int & x, int & y)
25+ {
26+ lua_getglobal (L, " STATE" );
27+ lua_getfield (L, -1 , " size" );
28+
29+ lua_rawgeti (L, -1 , 1 );
30+ x=lua_tointeger (L, -1 );
31+ lua_pop (L, 1 );
32+
33+ lua_rawgeti (L, -1 , 2 );
34+ y = lua_tointeger (L, -1 );
35+ lua_pop (L, 1 );
36+
37+ lua_pop (L, 2 );
38+ }
39+
40+
41+
42+ template <typename T>
43+ struct buffer_value_access {
44+ static constexpr char * name ();
45+ static int push (lua_State* L, const T& v);
46+ static T to_element (lua_State* L, int id);
47+ static std::vector<T>* check (lua_State* L, int id) { return *reinterpret_cast <std::vector<T>**>(luaL_checkudata (L, id, name ())); }
48+ static int get_buffer (lua_State* L)
49+ {
50+ auto ptr = buffer_value_access<T>::check (L, 1 );
51+ int x = luaL_checkinteger (L, 2 );
52+ int y = luaL_checkinteger (L, 3 );
53+ auto e = buffer_registry[ptr];
54+ auto & v = ptr->at (x*e.w + y); \
55+ return buffer_value_access<T>::push (L, v);
56+ }
57+ static int set_buffer (lua_State* L) {
58+ auto ptr = buffer_value_access<T>::check (L, 1 );
59+ int x = luaL_checkinteger (L, 2 );
60+ int y = luaL_checkinteger (L, 3 );
61+ auto new_value = buffer_value_access<T>::to_element (L, 4 );
62+ auto e = buffer_registry[ptr];
63+ ptr->at (x*e.w + y) = new_value;
64+ return 0 ;
65+ }
66+ static int del_buffer (lua_State* L) {
67+ auto ptr= check (L, 1 );
68+ buffer_registry.erase (ptr); delete ptr;
69+ return 0 ;
70+ }
71+ static int len_buffer (lua_State* L) {
72+ auto ptr = check (L, 1 );
73+ lua_pushnumber (L, ptr->size ());
74+ return 1 ;
75+ }
76+ static int index_buffer (lua_State* L) {
77+ auto ptr = check (L, 1 );
78+ int id = luaL_checkinteger (L, 2 );
79+ auto & v = ptr->at (id);
80+ return push (L, v);
81+ }
82+ static int newindex_buffer (lua_State* L){
83+ auto ptr = check (L, 1 );
84+ int id = luaL_checkinteger (L, 2 );
85+ auto new_value = to_element (L, 3 );
86+ ptr->at (id) = new_value;
87+ return 0 ;
88+ }
89+ static void resize_buffer (void * d, int w, int h){
90+ auto p = reinterpret_cast <std::vector<T>*>(d);
91+ p->resize (w*h);
92+ buffer_registry[d].w = w;
93+ }
94+ static int make_buffer (lua_State* L, int w, int h){
95+ auto ret = new std::vector<T>(w*h);
96+ buffer_registry[ret].w = w;
97+ auto np=lua_newuserdata (L,sizeof (ret));
98+ *reinterpret_cast <std::vector<T>**>(np)=ret;
99+ if (luaL_newmetatable (L, name ()))
100+ {
101+ lua_pushcfunction (L, del_buffer);
102+ lua_setfield (L, -2 , " __gc" );
103+ lua_pushcfunction (L, len_buffer);
104+ lua_setfield (L, -2 , " __len" );
105+
106+ lua_pushcfunction (L, get_buffer);
107+ lua_setfield (L, -2 , " get" );
108+ lua_pushcfunction (L, set_buffer);
109+ lua_setfield (L, -2 , " set" );
110+ lua_pushvalue (L, -1 );
111+ lua_setfield (L, -2 , " __index" );
112+ }
113+ lua_setmetatable (L, -2 );
114+ return 1 ;
115+ }
116+ };
117+
118+ static int make_lua_auto_buffer (lua_State* L)
119+ {
120+ const char * buf_type = luaL_checkstring (L, 1 );
121+ int x, y;
122+ get_current_size (L, x, y);
123+
124+ if (strcmp (buf_type, " color" )==0 )
125+ {
126+ return buffer_value_access<u8x4>::make_buffer (L,x,y);
127+ } else if (strcmp (buf_type, " float" ) == 0 )
128+ {
129+ return buffer_value_access<float >::make_buffer (L, x, y);
130+ }
131+ }
132+ static int present_buffer (lua_State* L)
133+ {
134+ auto ptr= buffer_value_access<u8x4>::check (L, 1 );
135+ lua_getglobal (L, " STATE" );
136+ lua_getfield (L, -1 , " texture" );
137+
138+ auto tex=reinterpret_cast <sf::Texture*>(lua_touserdata (L, -1 ));
139+ lua_pop (L, 2 );
140+ tex->update (reinterpret_cast <const sf::Uint8*>(ptr->data ()));
141+ return 0 ;
142+ }
143+ static const luaL_Reg lua_buffers_lib[] = {
144+ { " Make" ,make_lua_auto_buffer },
145+ { " Present" ,present_buffer},
146+ { NULL , NULL }
147+ };
148+
149+ int lua_open_buffers (lua_State * L)
150+ {
151+ luaL_newlib (L, lua_buffers_lib);
152+
153+ lua_setglobal (L, " buffers" );
154+
155+ return 1 ;
156+ }
157+
158+ void resize_lua_buffers (int w, int h)
159+ {
160+ for (auto & v : buffer_registry)
161+ {
162+ switch (v.second .t )
163+ {
164+ #define DO_BUFFER_RESIZE (tname,name ) case buffer_type::vector_##tname: buffer_value_access<tname>::resize_buffer(v.first,w,h);break
165+ DO_BUFFER_RESIZE (u8x4, color);
166+ DO_BUFFER_RESIZE (float , float );
167+ default :
168+ break ;
169+ }
170+ }
171+ }
172+ #undef DO_BUFFER_RESIZE
173+
174+ template <>
175+ static constexpr char * buffer_value_access<u8x4>::name()
176+ {
177+ return " color_buffer" ;
178+ }
179+
180+ template <>
181+ static int buffer_value_access<u8x4>::push(lua_State * L, const u8x4& v)
182+ {
183+ lua_newtable (L);
184+
185+ lua_pushinteger (L, v.r );
186+ lua_rawseti (L, -2 , 1 );
187+
188+ lua_pushinteger (L, v.g );
189+ lua_rawseti (L, -2 , 2 );
190+
191+ lua_pushinteger (L, v.b );
192+ lua_rawseti (L, -2 , 3 );
193+
194+ lua_pushinteger (L, v.a );
195+ lua_rawseti (L, -2 , 4 );
196+
197+ return 1 ;
198+ }
199+
200+ template <>
201+ static u8x4 buffer_value_access<u8x4>::to_element(lua_State * L, int id)
202+ {
203+ u8x4 ret;
204+ luaL_checktype (L, id, LUA_TTABLE);
205+ lua_rawgeti (L, id, 1 ); ret.r = lua_tointeger (L, -1 ); lua_pop (L, 1 );
206+ lua_rawgeti (L, id, 2 ); ret.g = lua_tointeger (L, -1 ); lua_pop (L, 1 );
207+ lua_rawgeti (L, id, 3 ); ret.b = lua_tointeger (L, -1 ); lua_pop (L, 1 );
208+ lua_rawgeti (L, id, 4 ); ret.a = lua_tointeger (L, -1 ); lua_pop (L, 1 );
209+ return ret;
210+ }
211+
212+ template <>
213+ static constexpr char * buffer_value_access<float >::name()
214+ {
215+ return " float_buffer" ;
216+ }
217+
218+ template <>
219+ static int buffer_value_access<float >::push(lua_State * L, const float & v)
220+ {
221+ lua_pushnumber (L, v);
222+ return 1 ;
223+ }
224+
225+ template <>
226+ static float buffer_value_access<float >::to_element(lua_State * L, int id)
227+ {
228+ return luaL_checknumber (L, id);
229+ }
0 commit comments