diff --git a/client/api.lua b/client/api.lua index b397568..851b376 100644 --- a/client/api.lua +++ b/client/api.lua @@ -12,6 +12,9 @@ buildat.safe.disconnect = __buildat_disconnect buildat.safe.get_time_us = __buildat_get_time_us buildat.safe.profiler_block_begin = __buildat_profiler_block_begin buildat.safe.profiler_block_end = __buildat_profiler_block_end +buildat.safe.VoxelName = __buildat_VoxelName +buildat.safe.AtlasSegmentDefinition = __buildat_AtlasSegmentDefinition +buildat.safe.VoxelDefinition = __buildat_VoxelDefinition buildat.safe.createVoxelRegistry = __buildat_createVoxelRegistry buildat.safe.createAtlasRegistry = __buildat_createAtlasRegistry diff --git a/doc/client_api.txt b/doc/client_api.txt index 916d720..2cd8015 100644 --- a/doc/client_api.txt +++ b/doc/client_api.txt @@ -222,3 +222,37 @@ SubscribeToEvent(object, event_name, callback) - Return value: Name of the generated global callback which can be unusbscbribed from Urho3D via UnsubscribeFromEvent(event_name, callback_name). + +Miscellaneous +============= + +You can create a client-side voxel registry like this: + +local voxel_reg = buildat.createVoxelRegistry() +local atlas_reg = buildat.createAtlasRegistry() +do + local vdef = buildat.VoxelDefinition() + vdef.name.block_name = "rock" + vdef.name.segment_x = 0 + vdef.name.segment_y = 0 + vdef.name.segment_z = 0 + vdef.name.rotation_primary = 0 + vdef.name.rotation_secondary = 0 + vdef.handler_module = "" + local textures = {} + for i = 1, 6 do + local seg = buildat.AtlasSegmentDefinition() + seg.resource_name = "main/rock.png" + seg.total_segments = magic.IntVector2(1, 1) + seg.select_segment = magic.IntVector2(0, 0) + table.insert(textures, seg) + end + vdef.textures = textures + vdef.edge_material_id = buildat.VoxelDefinition.EDGEMATERIALID_GROUND + vdef.physically_solid = true + voxel_reg:add_voxel(vdef) + voxel_reg:add_voxel(vdef) + voxel_reg:add_voxel(vdef) + voxel_reg:add_voxel(vdef) +end + diff --git a/src/interface/voxel.h b/src/interface/voxel.h index 6508f2c..1696c34 100644 --- a/src/interface/voxel.h +++ b/src/interface/voxel.h @@ -38,6 +38,7 @@ namespace interface typedef uint8_t EdgeMaterialId; static constexpr EdgeMaterialId EDGEMATERIALID_EMPTY = 0; static constexpr EdgeMaterialId EDGEMATERIALID_GROUND = 1; + // Values at and above 10 are freely usable. struct VoxelDefinition { diff --git a/src/lua_bindings/luabind_util.h b/src/lua_bindings/luabind_util.h new file mode 100644 index 0000000..1466546 --- /dev/null +++ b/src/lua_bindings/luabind_util.h @@ -0,0 +1,27 @@ +// http://www.apache.org/licenses/LICENSE-2.0 +// Copyright 2014 Perttu Ahola +#pragma once +#include "core/types.h" +#include + +#define LUABIND_ENUM_CLASS(X) \ + namespace luabind { \ + template<> struct default_converter: \ + native_converter_base \ + { \ + static int compute_score(lua_State* L, int index){ \ + return lua_type(L, index) == LUA_TNUMBER ? 0 : -1; \ + } \ + X to_cpp_deferred(lua_State* L, int index){ \ + return X(lua_tonumber(L, index)); \ + } \ + void to_lua_deferred(lua_State* L, X const& x){ \ + lua_pushinteger(L, (int)x); \ + } \ + }; \ + template<> struct default_converter: \ + default_converter \ + {}; \ + } \ + +// vim: set noet ts=4 sw=4: diff --git a/src/lua_bindings/voxel.cpp b/src/lua_bindings/voxel.cpp index 87e0fba..6f5ff6e 100644 --- a/src/lua_bindings/voxel.cpp +++ b/src/lua_bindings/voxel.cpp @@ -1,16 +1,110 @@ // http://www.apache.org/licenses/LICENSE-2.0 // Copyright 2014 Perttu Ahola -#include "lua_bindings/util.h" #include "core/log.h" #include "interface/voxel.h" +#include "lua_bindings/util.h" +#include "lua_bindings/luabind_util.h" #include +#include +#include +#include +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#include +#pragma GCC diagnostic pop #define MODULE "lua_bindings" -using interface::VoxelInstance; -using interface::VoxelRegistry; +#define GET_TOLUA_STUFF(result_name, index, type){ \ + tolua_Error tolua_err; \ + if(!tolua_isusertype(L, index, #type, 0, &tolua_err)){ \ + tolua_error(L, __PRETTY_FUNCTION__, &tolua_err); \ + throw Exception("Expected \"" #type "\""); \ + } \ +} \ + type *result_name = (type*)tolua_tousertype(L, index, 0); + +using namespace interface; +using Urho3D::IntVector2; + +LUABIND_ENUM_CLASS(FaceDrawType); namespace lua_bindings { +luabind::object asd_get_total_segments( + const AtlasSegmentDefinition &def, lua_State *L) +{ + // TODO + return luabind::object(); +} + +void asd_set_total_segments( + AtlasSegmentDefinition &def, luabind::object value_safe, lua_State *L) +{ + // This won't work + /*luabind::object value_meta = luabind::getmetatable(value_safe); + if(luabind::object_cast(value_meta["type_name"]) != "IntVector2") + throw Exception("Value is not a sandboxed IntVector2"); + luabind::object value = value_meta["unsafe"]; + value.push(L); + int top_L = lua_gettop(L); + GET_TOLUA_STUFF(v, top_L, IntVector2);*/ + + // This works + lua_getmetatable(L, 2); + lua_getfield(L, -1, "type_name"); + if(ss_(lua_tostring(L, -1)) != "IntVector2"){ + lua_pop(L, 2); // type_name, metatable + throw Exception("Value is not a sandboxed IntVector2"); + } + lua_pop(L, 1); // type_name + lua_getfield(L, -1, "unsafe"); + int top_L = lua_gettop(L); + GET_TOLUA_STUFF(v, top_L, IntVector2); + def.total_segments = *v; + lua_pop(L, 2); // unsafe, metatable +} + +luabind::object asd_get_select_segment( + const AtlasSegmentDefinition &def, lua_State *L) +{ + // TODO + return luabind::object(); +} + +void asd_set_select_segment( + AtlasSegmentDefinition &def, luabind::object value, lua_State *L) +{ + lua_getmetatable(L, 2); + lua_getfield(L, -1, "type_name"); + if(ss_(lua_tostring(L, -1)) != "IntVector2"){ + lua_pop(L, 2); // type_name, metatable + throw Exception("Value is not a sandboxed IntVector2"); + } + lua_pop(L, 1); // type_name + lua_getfield(L, -1, "unsafe"); + int top_L = lua_gettop(L); + GET_TOLUA_STUFF(v, top_L, IntVector2); + def.select_segment = *v; + lua_pop(L, 2); // unsafe, metatable +} + +luabind::object vdef_get_textures(const VoxelDefinition &def, lua_State *L) +{ + luabind::object result = luabind::newtable(L); + for(size_t i = 0; i < 6; i++){ + result[i+1] = luabind::object(L, def.textures[i]); + } + return result; +} + +void vdef_set_textures(VoxelDefinition &def, luabind::object value, lua_State *L) +{ + for(size_t i = 0; i < 6; i++){ + def.textures[i] = luabind::object_cast( + value[i+1]); + } +} + sp_ createVoxelRegistry(lua_State *L) { return sp_( @@ -22,11 +116,57 @@ void init_voxel(lua_State *L) using namespace luabind; module(L)[ + class_, sp_>("__buildat_VoxelName") + .def(constructor<>()) + .def_readwrite("block_name", &VoxelName::block_name) + .def_readwrite("segment_x", &VoxelName::segment_x) + .def_readwrite("segment_y", &VoxelName::segment_y) + .def_readwrite("segment_z", &VoxelName::segment_z) + .def_readwrite("rotation_primary", &VoxelName::rotation_primary) + .def_readwrite("rotation_secondary", &VoxelName::rotation_secondary) + , + class_, sp_>( + "__buildat_AtlasSegmentDefinition") + .def(constructor<>()) + .def_readwrite("resource_name", + &AtlasSegmentDefinition::resource_name) + .property("total_segments", + &asd_get_total_segments, &asd_set_total_segments) + .property("select_segment", + &asd_get_select_segment, &asd_set_select_segment) + .def_readwrite("lod_simulation", + &AtlasSegmentDefinition::lod_simulation) + , + class_, sp_>( + "__buildat_VoxelDefinition") + .def(constructor<>()) + .def_readwrite("name", &VoxelDefinition::name) + .def_readwrite("id", &VoxelDefinition::id) + .property("textures", &vdef_get_textures, &vdef_set_textures) + .def_readwrite("face_draw_type", &VoxelDefinition::face_draw_type) + .def_readwrite("edge_material_id", &VoxelDefinition::edge_material_id) + .def_readwrite("physically_solid", &VoxelDefinition::physically_solid) + .enum_("FaceDrawType")[ + value("FACEDRAWTYPE_NEVER", (int)FaceDrawType::NEVER), + value("FACEDRAWTYPE_ALWAYS", (int)FaceDrawType::ALWAYS), + value("FACEDRAWTYPE_ON_EDGE", (int)FaceDrawType::ON_EDGE) + ] + .enum_("EdgeMaterialId")[ + value("EDGEMATERIALID_EMPTY", EDGEMATERIALID_EMPTY), + value("EDGEMATERIALID_GROUND", EDGEMATERIALID_GROUND) + ] + , class_, sp_>("VoxelRegistry") + .def("add_voxel", &VoxelRegistry::add_voxel) + .def("get_by_id", (const VoxelDefinition*(VoxelRegistry::*) + (const VoxelTypeId&)) &VoxelRegistry::get) + .def("get_by_name", (const VoxelDefinition*(VoxelRegistry::*) + (const VoxelName&)) &VoxelRegistry::get) .def("serialize", (ss_(VoxelRegistry::*) ()) &VoxelRegistry::serialize) .def("deserialize", (void(VoxelRegistry::*) (const ss_ &)) - &VoxelRegistry::deserialize), + &VoxelRegistry::deserialize) + , def("__buildat_createVoxelRegistry", &createVoxelRegistry) ]; }