// Copyright (C) 2012-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. #include "nv/lua/lua_map_area.hh" #include "nv/stl/flags.hh" #include "nv/lua/lua_area.hh" #include "nv/lua/lua_math.hh" #include "nv/lua/lua_values.hh" #include "nv/lua/lua_raw.hh" static const char* NLUA_MAP_AREA_METATABLE = "map_area"; typedef nv::flags<512> cell_set; static nv::uint32 nlua_to_cell_id( lua_State* L, int index, nv::map_area* map ) { if ( lua_type( L, index ) == LUA_TSTRING ) return map->string_to_id( lua_tostring( L, index ) ); else return nlua_tounsigned( L, index ); } // static cell_set nlua_to_cell_set( lua_State* L, int index, nv::map_area* map ) // { // cell_set result; // switch ( lua_type( L, index ) ) // { // case LUA_TTABLE : // { // lua_pushnil( L ); // while ( lua_next( L, index ) != 0 ) // { // if ( lua_type( L, -1 ) == LUA_TSTRING ) // result.set( map->string_to_id( lua_tostring( L, -1 ) ), true ); // else // result.set( lua_tounsigned( L, -1 ), true ); // lua_pop( L, 1 ); // } // } break; // case LUA_TSTRING : result.set( map->string_to_id( lua_tostring( L, index ) ), true ); break; // case LUA_TNUMBER : result.set( lua_tounsigned( L, index ), true ); break; // } // return result; // } bool nv::lua::detail::is_map_area( lua_State* L, int index ) { return nlua_testudata( L, index, NLUA_MAP_AREA_METATABLE ) != 0; } nv::map_area* nv::lua::detail::to_map_area( lua_State* L, int index ) { nv::map_area* o = nullptr; if ( lua_istable( L , index ) ) { lua_pushliteral( L, "__map_area_ptr" ); lua_rawget( L, index ); if ( lua_isuserdata( L, -1 ) ) { o = static_cast( lua_touserdata( L, -1 ) ); } lua_pop( L, 1 ); } else { return *reinterpret_cast( luaL_checkudata( L, index, NLUA_MAP_AREA_METATABLE ) ); } return o; } using nv::lua::detail::is_map_area; using nv::lua::detail::to_map_area; using nv::lua::detail::push_map_area; using nv::lua::detail::is_coord; using nv::lua::detail::to_coord; using nv::lua::detail::to_pcoord; using nv::lua::detail::push_coord; using nv::lua::detail::is_area; using nv::lua::detail::to_area; using nv::lua::detail::to_parea; using nv::lua::detail::push_area; void nv::lua::detail::push_map_area( lua_State* L, nv::map_area* c ) { nv::map_area** pm = reinterpret_cast( lua_newuserdata(L, sizeof(nv::map_area*) ) ); *pm = c; luaL_getmetatable( L, NLUA_MAP_AREA_METATABLE ); lua_setmetatable( L, -2 ); } static int nlua_map_area_tostring( lua_State* L ) { lua_pushliteral ( L, "map_area" ); return 1; } static int nlua_map_area_gc( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); if ( ma != nullptr ) { delete ma; } return 0; } static int nlua_map_area_get_area( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); nv::rectangle r = ma->get_rectangle(); r.lr.x -= 1; r.lr.y -= 1; push_area( L, r ); return 1; } static int nlua_map_area_get_shift( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); push_coord( L, ma->get_shift() ); return 1; } static int nlua_map_area_get_size( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); push_coord( L, ma->get_size() ); return 1; } static int nlua_map_area_get_cell( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); nlua_pushstringview( L, ma->id_to_string( ma->get_cell( to_coord( L, 2 ) ) ) ); return 1; } static int nlua_map_area_set_cell( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); ma->set_cell( to_coord( L, 2 ), nlua_to_cell_id( L, 3, ma ) ); return 0; } static int nlua_map_area_raw_get_cell( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); nlua_pushunsigned( L, ma->get_cell( to_coord( L, 2 ) ) ); return 1; } static int nlua_map_area_raw_set_cell( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); ma->set_cell( to_coord( L, 2 ), nlua_tounsigned( L, 3 ) ); return 0; } static int nlua_map_area_index( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); if ( lua_type( L, 1 ) == LUA_TSTRING ) { luaL_getmetafield( L, 1, "__functions" ); lua_pushvalue( L, 2 ); lua_rawget( L, -2 ); } else { nlua_pushunsigned( L, ma->get_cell( to_coord( L, 2 ) ) ); } return 1; } static int nlua_map_area_newindex( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); ma->set_cell( to_coord( L, 2 ), nlua_tounsigned( L, 3 ) ); return 0; } static int nlua_map_area_new_sub_area( lua_State* L ) { nv::map_area* ma = to_map_area( L, 1 ); push_map_area( L, ma->create_sub_area( to_area( L, 2 ) ) ); return 1; } static const luaL_Reg nlua_map_area_f[] = { { "get_area", nlua_map_area_get_area }, { "get_shift", nlua_map_area_get_shift }, { "get_size", nlua_map_area_get_size }, { "get_cell", nlua_map_area_get_cell }, { "set_cell", nlua_map_area_set_cell }, { "raw_get_cell", nlua_map_area_raw_get_cell }, { "raw_set_cell", nlua_map_area_raw_set_cell }, { "new_sub_area", nlua_map_area_new_sub_area }, {NULL, NULL} }; static const luaL_Reg nlua_map_area_mt[] = { { "__newindex", nlua_map_area_newindex }, { "__index", nlua_map_area_index }, { "__tostring", nlua_map_area_tostring }, { "__gc", nlua_map_area_gc }, {NULL, NULL} }; static int luaopen_map_area( lua_State * L ) { luaL_newmetatable( L, NLUA_MAP_AREA_METATABLE ); nlua_register( L, nlua_map_area_mt, -1 ); lua_createtable( L, 0, 0 ); nlua_register( L, nlua_map_area_f, -1 ); lua_setfield(L, -2, "__functions" ); lua_pop( L, 1 ); return 0; } void nv::lua::register_map_area_interface( lua_State* L, int index ) { nlua_register( L, nlua_map_area_f, index ); } void nv::lua::register_map_area( lua_State* L ) { luaopen_map_area(L); } void nv::lua::register_map_area_instance( lua_State* L, ref object_index, map_area* area ) { lua_rawgeti( L, LUA_REGISTRYINDEX, object_index.get() ); lua_pushliteral( L, "__map_area_ptr" ); lua_pushlightuserdata( L, area ); lua_rawset( L, -3 ); lua_pop( L, 1 ); }