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

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