source: trunk/src/lua/lua_map_tile.cc @ 440

Last change on this file since 440 was 440, checked in by epyon, 10 years ago
  • massive std::string removal
  • no header depends on std::string anymore (or any other STL header)
  • still some code files do (WIP)
  • massive refactoring where std::string was used
  • lua still messy (grep for string128 - used everywhere)
  • string_twine added
File size: 11.3 KB
RevLine 
[395]1// Copyright (C) 2012-2015 ChaosForge Ltd
[221]2// http://chaosforge.org/
3//
[395]4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
[221]6
7#include "nv/lua/lua_map_tile.hh"
8
9#include "nv/lua/lua_map_area.hh"
[368]10#include "nv/stl/flags.hh"
[374]11#include "nv/stl/numeric.hh"
12#include "nv/stl/algorithm.hh"
[319]13#include "nv/core/random.hh"
[221]14#include "nv/lua/lua_area.hh"
15#include "nv/lua/lua_glm.hh"
16#include "nv/lua/lua_values.hh"
17#include "nv/lua/lua_raw.hh"
18
[440]19// TODO: REMOVE
20#include <string>
21
[221]22static const char* NLUA_MAP_TILE_METATABLE = "map_tile";
23
24struct map_tile
25{
[369]26        nv::uint8*  data;
27        nv::uchar8* ascii;
28        nv::uint16  size_x;
29        nv::uint16  size_y;
[221]30};
31
32
[323]33// static bool nlua_is_map_tile( lua_State* L, int index )
34// {
35//      return luaL_testudata( L, index, NLUA_MAP_TILE_METATABLE ) != 0;
36// }
37//
38// static map_tile nlua_to_map_tile( lua_State* L, int index )
39// {
40//      return *(map_tile*)luaL_checkudata( L, index, NLUA_MAP_TILE_METATABLE );
41// }
[221]42
[323]43static map_tile* nlua_to_pmap_tile( lua_State* L, int index )
[221]44{
[406]45        return reinterpret_cast<map_tile*>( luaL_checkudata( L, index, NLUA_MAP_TILE_METATABLE ) );
[221]46}
47
[323]48static void nlua_push_map_tile( lua_State* L, const map_tile& tile )
[221]49{
[406]50        map_tile* result = reinterpret_cast<map_tile*>( lua_newuserdata( L, sizeof(map_tile) ) );
[221]51        *result = tile;
52        luaL_setmetatable( L, NLUA_MAP_TILE_METATABLE );
53}
54
55static int nlua_map_tile_new( lua_State* L )
56{
57        bool ascii = lua_toboolean( L, 4 ) != 0;
58        nv::map_area* map_area = nv::lua::detail::to_map_area( L, 3 );
59        lua_settop( L, 2 );
[433]60        nv::string_view lts = nv::trimmed( lua_tostring( L, 1 ) );
61        std::string code( lts.data(), lts.size() );
[378]62        std::string chars( " \r\t" );
63        code.erase( nv::remove_if( code.begin(), code.end(),
64                [&chars] ( const char& c )
65        {
66                return chars.find( c ) != std::string::npos;
67        } ), code.end() );
[221]68
69        map_tile tile;
70
[406]71        tile.size_y = nv::uint16( nv::count( code.begin(), code.end(), '\n' ) + 1 );
72        tile.size_x = nv::uint16( code.find( '\n' ) );
[221]73        if ( tile.size_x == 0 )
74        {
[406]75                tile.size_x = nv::uint16( code.length() );
[221]76        }
77        tile.data  = new nv::uint8[ tile.size_x * tile.size_y ];
[369]78        tile.ascii = ( ascii ? new nv::uchar8[ tile.size_x * tile.size_y ] : nullptr );
[221]79
80        nv::uint8 translation[256] = { 0 };
81       
82        // TODO: error reporting
83        if ( lua_istable( L, 2 ) )
84        {
85                lua_pushnil( L );
86                while ( lua_next( L, 2 ) != 0 )
87                {
88                        // uses 'key' (at index -2) and 'value' (at index -1) */
89                        if ( lua_isstring( L, -2 ) && lua_objlen( L, -2 ) == 1 )
90                        {
[406]91                                translation[ nv::uint8( lua_tostring( L, -2 )[0] ) ] = nv::uint8( map_area->string_to_id( lua_tostring( L, -1 ) ) );
[221]92                        }
93                        // removes 'value'; keeps 'key' for next iteration */
94                        lua_pop( L, 1 );
95                }
96        }
97
[323]98        for ( nv::uint16 line = 0; line < tile.size_x; line++ )
99                for ( nv::uint16 row = 0; row < tile.size_y; row++ )
[221]100                {
[406]101                        nv::uchar8 gylph = nv::uchar8( code[ row * ( tile.size_x + 1 ) + line ] );
[221]102                        // TODO: check for errors
103                        tile.data[ row * tile.size_x + line ] = translation[ gylph ];
104                        if ( ascii ) tile.ascii[row * tile.size_x + line] = gylph;
105                }
106
107        nlua_push_map_tile( L, tile );
108        return 1;
109}
110
111static int nlua_map_tile_clone( lua_State* L )
112{
113        map_tile* old_tile = nlua_to_pmap_tile( L, 1 );
[406]114        map_tile* new_tile = reinterpret_cast<map_tile*>( lua_newuserdata( L, sizeof( map_tile ) ) );
[221]115        new_tile->size_x = old_tile->size_x;
116        new_tile->size_y = old_tile->size_y;
117        nv::uint32 size  = new_tile->size_x * new_tile->size_y;
118        new_tile->data   = new nv::uint8[ size ];
119        new_tile->ascii  = nullptr;
120        if ( old_tile->ascii )
121        {
[369]122                new_tile->ascii = new nv::uchar8[ size ];
[221]123        }
[383]124        nv::raw_copy_n( old_tile->data, size, new_tile->data );
125        if ( old_tile->ascii ) nv::raw_copy_n( old_tile->ascii, size, new_tile->ascii );
[221]126
127        luaL_getmetatable( L, NLUA_MAP_TILE_METATABLE );
128        lua_setmetatable( L, -2 );
129        return 1;
130}
131
132static int nlua_map_tile_place( lua_State* L )
133{
134        map_tile* tile     = nlua_to_pmap_tile( L, 1 );
135        nv::map_area* area = nv::lua::detail::to_map_area( L, 2 );
136        nv::ivec2 coord    = nv::lua::detail::to_coord( L, 3 );
137
138        for ( nv::uint16 x = 0; x < tile->size_x; ++x )
139                for ( nv::uint16 y = 0; y < tile->size_y; ++y )
140                {
141                        nv::uint8 c = tile->data[ y * tile->size_x + x ];
[228]142                        if ( c != 0 ) area->set_cell( coord + nv::ivec2( x, y ), c );
[221]143                }
144
145        return 0;
146}
147
148static nv::uint8* nlua_map_tile_flip_x_helper( nv::uint8* src, nv::uint16 sx, nv::uint16 sy )
149{
150        if ( src == nullptr ) return nullptr;
151        nv::uint8* data = new nv::uint8[ sx * sy ];
152        for ( nv::uint16 x = 0; x < sx; ++x )
153                for ( nv::uint16 y = 0; y < sy; ++y )
154                {
155                        data[ y * sx + x ] = src[ ( y + 1 ) * sx - x - 1 ];
156                }
157        delete src;
158        return data;
159}
160
161static nv::uint8* nlua_map_tile_flip_y_helper( nv::uint8* src, nv::uint16 sx, nv::uint16 sy )
162{
163        if ( src == nullptr ) return nullptr;
164        nv::uint8* data = new nv::uint8[ sx * sy ];
165        for ( nv::uint16 x = 0; x < sx; ++x )
166                for ( nv::uint16 y = 0; y < sy; ++y )
167                {
168                        data[ y * sx + x ] = src[ ( sy - y - 1 ) * sx + x ];
169                }
170        delete src;
171        return data;
172}
173
174static nv::uint8* nlua_map_tile_flip_xy_helper( nv::uint8* src, nv::uint16 sx, nv::uint16 sy )
175{
176        if ( src == nullptr ) return nullptr;
177        nv::uint8* data = new nv::uint8[ sx * sy ];
178        for ( nv::uint16 x = 0; x < sx; ++x )
179                for ( nv::uint16 y = 0; y < sy; ++y )
180                {
181                        data[ y * sx + x ] = src[ ( sy - y ) * sx - x - 1 ];
182                }
183        delete src;
184        return data;
185}
186
187static int nlua_map_tile_flip_x( lua_State* L )
188{
189        map_tile* tile = nlua_to_pmap_tile( L, 1 );
190        tile->data     = nlua_map_tile_flip_x_helper( tile->data,  tile->size_x, tile->size_y );
191        tile->ascii    = nlua_map_tile_flip_x_helper( tile->ascii, tile->size_x, tile->size_y );
192        return 0;
193}
194
195static int nlua_map_tile_flip_y( lua_State* L )
196{
197        map_tile* tile = nlua_to_pmap_tile( L, 1 );
198        tile->data     = nlua_map_tile_flip_y_helper( tile->data,  tile->size_x, tile->size_y );
199        tile->ascii    = nlua_map_tile_flip_y_helper( tile->ascii, tile->size_x, tile->size_y );
200        return 0;
201}
202
203static int nlua_map_tile_flip_xy( lua_State* L )
204{
205        map_tile* tile = nlua_to_pmap_tile( L, 1 );
206        tile->data     = nlua_map_tile_flip_xy_helper( tile->data,  tile->size_x, tile->size_y );
207        tile->ascii    = nlua_map_tile_flip_xy_helper( tile->ascii, tile->size_x, tile->size_y );
208        return 0;
209}
210
211static int nlua_map_tile_flip_random( lua_State* L )
212{
213        switch ( nv::random::get().urand( 4 ) )
214        {
[323]215        case 1 : nlua_map_tile_flip_x( L ); break;
216        case 2 : nlua_map_tile_flip_y( L ); break;
217        case 3 : nlua_map_tile_flip_xy( L ); break;
[319]218        default:
[221]219                break;
220        }
221        return 0;
222}
223
224static int nlua_map_tile_get_size( lua_State* L )
225{
226        map_tile* tile = nlua_to_pmap_tile( L, 1 );
227        nv::lua::detail::push_coord( L, nv::ivec2( tile->size_x, tile->size_y ) );
228        return 1;
229}
230
231static int nlua_map_tile_get_area( lua_State* L )
232{
233        map_tile* tile = nlua_to_pmap_tile( L, 1 );
234        nv::lua::detail::push_area( L, nv::rectangle( nv::ivec2(1,1), nv::ivec2( tile->size_x, tile->size_y ) ) );
235        return 1;
236}
237
238static int nlua_map_tile_expand( lua_State* L )
239{
240        // TODO: lots of error checking
241        map_tile* tile = nlua_to_pmap_tile( L, 1 );
242        // assert( tile^.ascii == nullptr );
[383]243        nv::vector< nv::uint8 > sizes_x = nlua_tobytearray( L, 2 );
244        nv::vector< nv::uint8 > sizes_y;
245        if ( lua_istable( L, 3 ) )
246                sizes_y = nlua_tobytearray( L, 2 );
247        else
248                sizes_y.assign( sizes_x );
[221]249
250        nv::uint16 org_x = tile->size_x;
251        nv::uint16 org_y = tile->size_y;
[406]252        nv::uint16 new_x = nv::uint16( nv::accumulate( sizes_x.begin(), sizes_x.end(), 0 ) );
253        nv::uint16 new_y = nv::uint16( nv::accumulate( sizes_y.begin(), sizes_y.end(), 0 ) );
[221]254
255        nv::uint8* data = new nv::uint8[ new_x * new_y ];
256
257        nv::uint16 line_count = 0;
258        for ( nv::uint16 line = 0; line < org_y; ++line )
259                for ( nv::uint16 count = 0; count < sizes_y[ line ]; ++count )
260                {
261                        nv::uint16 px = 0;
262                        for ( nv::uint16 x = 0; x < org_x; ++x )
263                                for ( nv::uint16 c = 0; c < sizes_x[ x ]; ++c )
264                                {
265                                        data[ px + line_count * new_x ] = tile->data[ x + line * org_x ];
266                                        px++;
267                                }
268                        line_count++;
269                }
270
271        delete tile->data;
272        tile->size_x = new_x;
273        tile->size_y = new_y;
274        tile->data   = data;
275        return 0;
276}
277
278static int nlua_map_tile_raw_get( lua_State* L )
279{
[406]280        map_tile* tile = reinterpret_cast<map_tile*>( lua_touserdata( L, 1 ) );
[221]281        if ( lua_type( L, 2 ) == LUA_TNUMBER )
282        {
283                lua_pushinteger( L, tile->data[ ( lua_tointeger( L, 2 ) - 1 ) + ( lua_tointeger( L, 3 ) - 1 ) * tile->size_x ] );
284        }
285        else
286        {
287                nv::ivec2 coord = nv::lua::detail::to_coord( L, 2 );
288                lua_pushinteger( L, tile->data[ ( coord.x - 1 ) + ( coord.y - 1 ) * tile->size_x ] );
289        }
290        return 1;
291}
292
293static int nlua_map_tile_raw_set( lua_State* L )
294{
[406]295        map_tile* tile = reinterpret_cast<map_tile*>( lua_touserdata( L, 1 ) );
[221]296        if ( lua_type( L, 2 ) == LUA_TNUMBER )
297        {
[406]298                tile->data[ ( lua_tointeger( L, 2 ) - 1 ) + ( lua_tointeger( L, 3 ) - 1 ) * tile->size_x ] = nv::uint8( lua_tointeger( L, 3 ) );
[221]299        }
300        else
301        {
302                nv::ivec2 coord = nv::lua::detail::to_coord( L, 2 );
[406]303                tile->data[ ( coord.x - 1 ) + ( coord.y - 1 ) * tile->size_x ] = nv::uint8( lua_tointeger( L, 3 ) );
[221]304        }
305        return 0;
306}
307
308static int nlua_map_tile_ascii_get( lua_State* L )
309{
[406]310        map_tile* tile = reinterpret_cast<map_tile*>( lua_touserdata( L, 1 ) );
[221]311        if ( lua_type( L, 2 ) == LUA_TNUMBER )
312        {
313                lua_pushinteger( L, tile->ascii[ ( lua_tointeger( L, 2 ) - 1 ) + ( lua_tointeger( L, 3 ) - 1 ) * tile->size_x ] );
314        }
315        else
316        {
317                nv::ivec2 coord = nv::lua::detail::to_coord( L, 2 );
318                lua_pushinteger( L, tile->ascii[ ( coord.x - 1 ) + ( coord.y - 1 ) * tile->size_x ] );
319        }
320        return 1;
321}
322
323static int nlua_map_tile_ascii_set( lua_State* L )
324{
[406]325        map_tile* tile = reinterpret_cast<map_tile*>( lua_touserdata( L, 1 ) );
[221]326        if ( lua_type( L, 2 ) == LUA_TNUMBER )
327        {
[406]328                tile->ascii[ ( lua_tointeger( L, 2 ) - 1 ) + ( lua_tointeger( L, 3 ) - 1 ) * tile->size_x ] = nv::uint8( lua_tointeger( L, 3 ) );
[221]329        }
330        else
331        {
332                nv::ivec2 coord = nv::lua::detail::to_coord( L, 2 );
[406]333                tile->ascii[ ( coord.x - 1 ) + ( coord.y - 1 ) * tile->size_x ] = nv::uint8( lua_tointeger( L, 3 ) );
[221]334        }
335        return 0;
336}
337
338static int nlua_map_tile_gc( lua_State* L )
339{
[406]340        map_tile* tile = reinterpret_cast<map_tile*>( lua_touserdata( L, 1 ) );
[221]341        if ( tile != nullptr )
342        {
343                delete tile->data;
344                if ( tile->ascii ) delete tile->ascii;
345        }
346        return 0;
347}
348
349static const luaL_Reg nlua_map_tile_sf[] = {
350        { "new",   nlua_map_tile_new },
351        { NULL, NULL }
352};
353
354static const luaL_Reg nlua_map_tile_f[] = {
355        { "place",      nlua_map_tile_place },
356        { "clone",      nlua_map_tile_clone },
357        { "flip_x",     nlua_map_tile_flip_x },
358        { "flip_y",     nlua_map_tile_flip_y },
359        { "flip_xy",    nlua_map_tile_flip_xy },
360        { "flip_random",nlua_map_tile_flip_random },
361        { "get_size",   nlua_map_tile_get_size },
362        { "get_area",   nlua_map_tile_get_area },
363        { "expand",     nlua_map_tile_expand },
364        { "raw_get",    nlua_map_tile_raw_get },
365        { "raw_set",    nlua_map_tile_raw_set },
366        { "get_ascii",  nlua_map_tile_ascii_get },
367        { "set_ascii",  nlua_map_tile_ascii_set },
368        { "__gc",       nlua_map_tile_gc },
369        { NULL, NULL }
370};
371
372void nv::lua::register_map_tile( lua_State * L )
373{
374        // TODO: check if __gc is used!
375        luaL_newmetatable( L, NLUA_MAP_TILE_METATABLE );
376        lua_pushvalue( L, -1 );
377        lua_setfield( L, -2, "__index" );
378        nlua_register( L, nlua_map_tile_f, -1 );
379
380        lua_createtable( L, 0, 0 );
381        nlua_register( L, "map_tile", nlua_map_tile_sf );
382}
Note: See TracBrowser for help on using the repository browser.