source: trunk/src/lua/lua_glm.cc @ 172

Last change on this file since 172 was 172, checked in by epyon, 12 years ago
  • sdl - missing 2.0 sdl_functions
  • lua - compat implementation of lua_upvalueindex
  • position - rectangle single argument constructor made explicit
  • gl_window - fix for SDL 2.0 ascii code of key press
  • lua/glm - coord as a separate class (behaves like ivec2)
File size: 10.6 KB
Line 
1// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6
7#include "nv/lua/lua_glm.hh"
8
9#include "nv/lua/lua_raw.hh"
10#include "nv/string.hh"
11
12static size_t nlua_swizzel_lookup[256];
13
14inline bool nlua_is_swizzel( const unsigned char* str, size_t max )
15{
16        while (*str)
17        {
18                if (nlua_swizzel_lookup[*str] > max) return false;
19                str++;
20        }
21        return true;
22}
23
24template < typename T, size_t k >
25struct nlua_vec_constructor {
26        static inline T construct( lua_State*, int ) {
27                return T();
28        }
29};
30
31template < typename T > struct nlua_vec_constructor< T, 1 > {
32        static inline T construct( lua_State* L, int index ) {
33                return T( lua_tonumber( L, index ) );
34        }
35};
36
37template < typename T > struct nlua_vec_constructor< T, 2 > {
38        static inline T construct( lua_State* L, int index ) {
39                if ( lua_type( L, index ) == LUA_TUSERDATA )
40                        return nlua_to_vec<T>( L, index );
41                else
42                        return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ) );
43        }
44};
45
46template < typename T > struct nlua_vec_constructor< T, 3 > {
47        static inline T construct( lua_State* L, int index ) {
48                typedef glm::detail::tvec2<typename T::value_type> vec2;
49                if ( lua_type( L, index ) == LUA_TUSERDATA )
50                {
51                        if ( nlua_is_vec<T>( L, index ) )
52                                return nlua_to_vec<T>( L, index );
53                        else
54                                return T( nlua_to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ) );
55                }
56                else
57                {
58                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
59                                return T( lua_tonumber( L, index ), nlua_to_vec<vec2>( L, index+1 ) );
60                        else
61                                return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
62                }
63        }
64};
65
66template < typename T > struct nlua_vec_constructor< T, 4 > {
67        static inline T construct( lua_State* L, int index ) {
68                typedef glm::detail::tvec2<typename T::value_type> vec2;
69                typedef glm::detail::tvec3<typename T::value_type> vec3;
70                if ( lua_type( L, index ) == LUA_TUSERDATA )
71                {
72                        if ( nlua_is_vec<T>( L, index ) )
73                                return nlua_to_vec<T>( L, index );
74                        else
75                        {
76                                if ( nlua_is_vec<vec3>( L, index ) )
77                                        return T( nlua_to_vec<vec3>( L, index ), lua_tonumber( L, index + 1 ) );
78                                else
79                                {
80                                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
81                                                return T( nlua_to_vec<vec2>( L, index ), nlua_to_vec<vec2>( L, index + 1 ) );
82                                        else
83                                                return T( nlua_to_vec<vec2>( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ) );
84                                }
85                        }
86                }
87                else
88                {
89                        if ( lua_type( L, index+1 ) == LUA_TUSERDATA )
90                        {
91                                if ( nlua_is_vec<vec3>( L, index+1 ) )
92                                        return T( lua_tonumber( L, index ), nlua_to_vec<vec3>( L, index+1 ) );
93                                else
94                                        return T( lua_tonumber( L, index ), nlua_to_vec<vec2>( L, index+1 ), lua_tonumber( L, index + 2 ) );
95                        }
96                        else
97                        {
98                                if ( lua_type( L, index+2 ) == LUA_TUSERDATA )
99                                        return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), nlua_to_vec<vec2>( L, index+2 ) );
100                                else
101                                        return T( lua_tonumber( L, index ), lua_tonumber( L, index + 1 ), lua_tonumber( L, index + 2 ), lua_tonumber( L, index + 3 ) );
102                        }
103                }
104        }
105};
106
107template< typename T >
108int nlua_vec_new( lua_State* L )
109{
110        nlua_push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 1 ) );
111        return 1;
112}
113
114template< typename T >
115int nlua_vec_call( lua_State* L )
116{
117        nlua_push_vec( L, nlua_vec_constructor<T,sizeof( T ) / sizeof( typename T::value_type )>::construct( L, 2 ) );
118        return 1;
119}
120
121template< typename T >
122static int nlua_vec_unm( lua_State* L )
123{
124        nlua_push_vec<T>( L, -nlua_to_vec<T>( L, 1 ) );
125        return 1;
126}
127
128template< typename T >
129int nlua_vec_add( lua_State* L )
130{
131        if ( lua_type( L, 1 ) == LUA_TNUMBER )
132                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) + nlua_to_vec<T>( L, 2 ) );
133        else
134                if ( lua_type( L, 2 ) == LUA_TNUMBER )
135                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + (typename T::value_type)(lua_tonumber( L, 2 )) );
136                else
137                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) + nlua_to_vec<T>( L, 2 ) );
138        return 1;
139}
140
141template< typename T >
142int nlua_vec_sub( lua_State* L )
143{
144        if ( lua_type( L, 1 ) == LUA_TNUMBER )
145                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) - nlua_to_vec<T>( L, 2 ) );
146        else
147                if ( lua_type( L, 2 ) == LUA_TNUMBER )
148                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - (typename T::value_type)(lua_tonumber( L, 2 )) );
149                else
150                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) - nlua_to_vec<T>( L, 2 ) );
151        return 1;
152}
153
154template< typename T >
155int nlua_vec_mul( lua_State* L )
156{
157        if ( lua_type( L, 1 ) == LUA_TNUMBER )
158                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) * nlua_to_vec<T>( L, 2 ) );
159        else
160                if ( lua_type( L, 2 ) == LUA_TNUMBER )
161                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * (typename T::value_type)(lua_tonumber( L, 2 )) );
162                else
163                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) * nlua_to_vec<T>( L, 2 ) );
164        return 1;
165}
166
167template< typename T >
168int nlua_vec_div( lua_State* L )
169{
170        if ( lua_type( L, 1 ) == LUA_TNUMBER )
171                nlua_push_vec<T>( L, (typename T::value_type)(lua_tonumber( L, 1 )) / nlua_to_vec<T>( L, 2 ) );
172        else
173                if ( lua_type( L, 2 ) == LUA_TNUMBER )
174                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / (typename T::value_type)(lua_tonumber( L, 2 )) );
175                else
176                        nlua_push_vec<T>( L, nlua_to_vec<T>( L, 1 ) / nlua_to_vec<T>( L, 2 ) );
177        return 1;
178}
179
180template< typename T >
181int nlua_vec_eq( lua_State* L )
182{
183        lua_pushboolean( L, nlua_to_vec<T>( L, 1 ) == nlua_to_vec<T>( L, 2 ) );
184        return 1;
185}
186
187template< typename T >
188int nlua_vec_get( lua_State* L )
189{
190        T v = nlua_to_vec<T>( L, 1 );
191        for ( size_t i = 0; i < v.length(); ++i )
192        {
193                lua_pushnumber( L, v[i] );
194        }
195        return v.length();
196}
197
198template< typename T >
199int nlua_vec_index( lua_State* L )
200{
201        T* v = nlua_to_pvec<T>( L, 1 );
202        size_t len  = 0;
203        size_t vlen = v->length();
204        const unsigned char * key = (const unsigned char *)( lua_tolstring( L, 2, &len ) );
205        size_t idx = 255;
206
207        if ( len == 1 )
208        {
209                idx = nlua_swizzel_lookup[ key[ 0 ] ];
210                if ( idx < vlen )
211                {
212                        lua_pushnumber( L, (*v)[idx] );
213                        return 1;
214                }
215        }
216        else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
217        {
218                switch (len) {
219                case 2 : nlua_push_vec( L, glm::detail::tvec2<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]] ) ); return 1;
220                case 3 : nlua_push_vec( L, glm::detail::tvec3<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]] ) ); return 1;
221                case 4 : nlua_push_vec( L, glm::detail::tvec4<typename T::value_type>( (*v)[nlua_swizzel_lookup[key[0]]], (*v)[nlua_swizzel_lookup[key[1]]], (*v)[nlua_swizzel_lookup[key[2]]], (*v)[nlua_swizzel_lookup[key[3]]] ) ); return 1;
222                default: break;
223                }
224        }
225
226        luaL_getmetafield( L, 1, "__base" );
227        lua_pushvalue( L, 2 );
228        lua_rawget( L, -2 );
229        return 1;
230}
231
232template< typename T >
233int nlua_vec_newindex( lua_State* L )
234{
235        typedef glm::detail::tvec2<typename T::value_type> vec2;
236        typedef glm::detail::tvec3<typename T::value_type> vec3;
237        typedef glm::detail::tvec4<typename T::value_type> vec4;
238
239        T* v = nlua_to_pvec<T>( L, 1 );
240        size_t len  = 0;
241        size_t vlen = v->length();
242        const unsigned char * key = (const unsigned char *)( lua_tolstring( L, 2, &len ) );
243        size_t idx = 255;
244        if( len == 1 )
245        {
246                idx = nlua_swizzel_lookup[ key[ 0 ] ];
247                if ( idx < vlen )
248                {
249                        (*v)[idx] = (typename T::value_type)luaL_checknumber( L, 3 );
250                        return 0;
251                }
252        }
253        else if ( len < 4 && nlua_is_swizzel(key,vlen-1) )
254        {
255                switch (len) {
256                case 2 : { vec2 v2 = nlua_to_vec<vec2>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v2[i]; } return 0;
257                case 3 : { vec3 v3 = nlua_to_vec<vec3>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v3[i]; } return 0;
258                case 4 : { vec4 v4 = nlua_to_vec<vec4>(L,3); for (size_t i = 0; i<len; ++i) (*v)[nlua_swizzel_lookup[key[i]]] = v4[i]; } return 0;
259                default: break;
260                }
261        }
262        return 0;
263}
264
265template< typename T >
266static int nlua_vec_tostring( lua_State* L )
267{
268        T v = nlua_to_vec<T>( L, 1 );
269        std::string s = "(";
270        for ( size_t i = 0; i < v.length(); ++i )
271        {
272                if (i > 0) s += ",";
273                s += nv::to_string(v[i]);
274        }
275        s+=")";
276        lua_pushstring( L, s.c_str() );
277        return 1;
278}
279
280template< typename T >
281int luaopen_vec( lua_State * L )
282{
283        static const struct luaL_Reg nlua_vec_f [] = {
284                { "new",            nlua_vec_new<T> },
285                { "get",            nlua_vec_get<T> },
286                {NULL, NULL}
287        };
288
289        static const struct luaL_Reg nlua_vec_fm [] = {
290                { "__call",         nlua_vec_call<T> },
291                {NULL, NULL}
292        };
293
294        static const struct luaL_Reg nlua_vec_m [] = {
295                { "__add",      nlua_vec_add<T> },
296                { "__sub",      nlua_vec_sub<T> },
297                { "__unm",      nlua_vec_unm<T> },
298                { "__mul",      nlua_vec_mul<T> },
299                { "__div",      nlua_vec_div<T> },
300                { "__eq",       nlua_vec_eq<T> },
301                { "__index",    nlua_vec_index<T> },
302                { "__newindex", nlua_vec_newindex<T> },
303                { "__tostring", nlua_vec_tostring<T> },
304                {NULL, NULL}
305        };
306
307        luaL_newmetatable( L, nlua_metatable_name<T>() );
308        nlua_register( L, nlua_vec_m, -1 );
309        lua_createtable( L, 0, 0 );
310        nlua_register( L, nlua_vec_f, -1 );
311        lua_pushvalue(L, -1);
312        lua_setfield(L, -3, "__base" );
313        lua_replace(L, -2);
314        lua_createtable( L, 0, 0 );
315        nlua_register( L, nlua_vec_fm, -1 );
316        lua_setmetatable( L, -2 );
317        return 1;
318}
319
320void nlua_register_glm( lua_State* L )
321{
322        for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255;
323        using nv::char8;
324        nlua_swizzel_lookup[char8( 'x' )] = 0;
325        nlua_swizzel_lookup[char8( 'r' )] = 0;
326        nlua_swizzel_lookup[char8( 's' )] = 0;
327        nlua_swizzel_lookup[char8( '0' )] = 0;
328        nlua_swizzel_lookup[char8( 'y' )] = 1;
329        nlua_swizzel_lookup[char8( 'g' )] = 1;
330        nlua_swizzel_lookup[char8( 't' )] = 0;
331        nlua_swizzel_lookup[char8( '1' )] = 1;
332        nlua_swizzel_lookup[char8( 'z' )] = 2;
333        nlua_swizzel_lookup[char8( 'b' )] = 2;
334        nlua_swizzel_lookup[char8( 'u' )] = 0;
335        nlua_swizzel_lookup[char8( '2' )] = 2;
336        nlua_swizzel_lookup[char8( 'w' )] = 3;
337        nlua_swizzel_lookup[char8( 'a' )] = 3;
338        nlua_swizzel_lookup[char8( 'v' )] = 0;
339        nlua_swizzel_lookup[char8( '3' )] = 3;
340        int stack = lua_gettop( L );
341
342        luaL_requiref(L, "coord", luaopen_vec<nv::ivec2>, 1);
343        luaL_requiref(L, "ivec2", luaopen_vec<nv::ivec2>, 1);
344        luaL_requiref(L, "ivec3", luaopen_vec<nv::ivec3>, 1);
345        luaL_requiref(L, "ivec4", luaopen_vec<nv::ivec4>, 1);
346        luaL_requiref(L, "vec2", luaopen_vec<nv::vec2>, 1);
347        luaL_requiref(L, "vec3", luaopen_vec<nv::vec3>, 1);
348        luaL_requiref(L, "vec4", luaopen_vec<nv::vec4>, 1);
349        lua_settop( L, stack );
350}
351
Note: See TracBrowser for help on using the repository browser.