VOXELGENERATOR: moved the voxel editor sript functions into the main module

master
Martin Gerhardy 2022-03-29 22:19:52 +02:00
parent 9ed9bffb1e
commit 04455319fe
10 changed files with 170 additions and 225 deletions

View File

@ -22,8 +22,6 @@ By default the script files will be searched in a `scripts` folder next to where
There are two functions in each script. One is called `arguments` and one `main`. `arguments` returns a list of parameters for the `main` function. The default parameters for `main` are `volume`, `region` and `color`. `color` is the palette index starting from `0`. There are two functions in each script. One is called `arguments` and one `main`. `arguments` returns a list of parameters for the `main` function. The default parameters for `main` are `volume`, `region` and `color`. `color` is the palette index starting from `0`.
Those functionalities that are marked with `voxedit` are not available outside of the editor (e.g. for the command line tools like [voxconvert](voxconvert/Index.md)).
## Examples ## Examples
### Without parameters ### Without parameters
@ -77,7 +75,7 @@ A `default` value can get set, too.
The order in the arguments table defines the order in which the arguments are passed over to the script. The order in the arguments table defines the order in which the arguments are passed over to the script.
## SceneGraph (voxedit) ## SceneGraph
`scenegraph` lets you access different nodes or create new ones. `scenegraph` lets you access different nodes or create new ones.
@ -87,7 +85,7 @@ The functions are:
* `get([nodeId])`: Returns the `node` for the given `nodeId` - if the `nodeId` is not given, it will return the current active node. Which by default is the node for the volume the script is currently executed for. * `get([nodeId])`: Returns the `node` for the given `nodeId` - if the `nodeId` is not given, it will return the current active node. Which by default is the node for the volume the script is currently executed for.
## SceneGraphNode (voxedit) ## SceneGraphNode
* `name()`: Returns the current name of the node. * `name()`: Returns the current name of the node.

View File

@ -18,12 +18,31 @@
#include "io/Filesystem.h" #include "io/Filesystem.h"
#include "noise/Simplex.h" #include "noise/Simplex.h"
#include "app/App.h" #include "app/App.h"
#include "voxelformat/SceneGraphUtil.h"
#include "voxelutil/VolumeResizer.h" #include "voxelutil/VolumeResizer.h"
#include "voxelformat/SceneGraph.h"
#include "voxelformat/SceneGraphNode.h"
#define GENERATOR_LUA_SANTITY 1 #define GENERATOR_LUA_SANTITY 1
namespace voxelgenerator { namespace voxelgenerator {
static const char *luaVoxel_globalscenegraph() {
return "__global_scenegraph";
}
static const char *luaVoxel_metascenegraphnode() {
return "__meta_scenegraphnode";
}
static const char *luaVoxel_metascenegraph() {
return "__meta_scenegraph";
}
static const char *luaVoxel_metavolumewrapper_mem() {
return "__meta_volumewrappermem";
}
static const char *luaVoxel_metavolumewrapper() { static const char *luaVoxel_metavolumewrapper() {
return "__meta_volumewrapper"; return "__meta_volumewrapper";
} }
@ -36,7 +55,18 @@ static const char *luaVoxel_metanoise() {
return "__meta_noise"; return "__meta_noise";
} }
static voxelformat::SceneGraphNode* luaVoxel_toscenegraphnode(lua_State* s, int n) {
return *(voxelformat::SceneGraphNode**)clua_getudata<voxelformat::SceneGraphNode*>(s, n, luaVoxel_metascenegraphnode());
}
static int luaVoxel_pushscenegraphnode(lua_State* s, voxelformat::SceneGraphNode& node) {
return clua_pushudata(s, &node, luaVoxel_metascenegraphnode());
}
static voxel::RawVolumeWrapper* luaVoxel_tovolumewrapper(lua_State* s, int n) { static voxel::RawVolumeWrapper* luaVoxel_tovolumewrapper(lua_State* s, int n) {
if (luaL_testudata(s, n, luaVoxel_metavolumewrapper_mem())) {
return *(voxel::RawVolumeWrapper**)clua_getudata<voxel::RawVolume*>(s, n, luaVoxel_metavolumewrapper_mem());
}
return *(voxel::RawVolumeWrapper**)clua_getudata<voxel::RawVolume*>(s, n, luaVoxel_metavolumewrapper()); return *(voxel::RawVolumeWrapper**)clua_getudata<voxel::RawVolume*>(s, n, luaVoxel_metavolumewrapper());
} }
@ -47,6 +77,13 @@ static int luaVoxel_pushvolumewrapper(lua_State* s, voxel::RawVolumeWrapper* vol
return clua_pushudata(s, volume, luaVoxel_metavolumewrapper()); return clua_pushudata(s, volume, luaVoxel_metavolumewrapper());
} }
static int luaVoxel_pushvolumewrapper_mem(lua_State* s, voxel::RawVolumeWrapper* volume) {
if (volume == nullptr) {
return clua_error(s, "No volume given - can't push");
}
return clua_pushudata(s, volume, luaVoxel_metavolumewrapper_mem());
}
static int luaVoxel_volumewrapper_voxel(lua_State* s) { static int luaVoxel_volumewrapper_voxel(lua_State* s) {
const voxel::RawVolumeWrapper* volume = luaVoxel_tovolumewrapper(s, 1); const voxel::RawVolumeWrapper* volume = luaVoxel_tovolumewrapper(s, 1);
const int x = (int)luaL_checkinteger(s, 2); const int x = (int)luaL_checkinteger(s, 2);
@ -100,6 +137,12 @@ static int luaVoxel_volumewrapper_setvoxel(lua_State* s) {
return 1; return 1;
} }
static int luaVoxel_volumewrapper_gc(lua_State *s) {
voxel::RawVolumeWrapper* volume = luaVoxel_tovolumewrapper(s, 1);
delete volume;
return 0;
}
static int luaVoxel_palette_colors(lua_State* s) { static int luaVoxel_palette_colors(lua_State* s) {
const voxel::Palette &palette = voxel::getPalette(); const voxel::Palette &palette = voxel::getPalette();
lua_createtable(s, palette.colorCount, 0); lua_createtable(s, palette.colorCount, 0);
@ -364,17 +407,83 @@ static int luaVoxel_noise_worley3(lua_State* s) {
return 1; return 1;
} }
static int luaVoxel_scenegraph_new_node(lua_State* s) {
const char *name = lua_tostring(s, 1);
const bool visible = lua_toboolean(s, 2);
const voxel::Region* region = voxelgenerator::LUAGenerator::luaVoxel_toRegion(s, 3);
voxel::RawVolume *v = new voxel::RawVolume(*region);
voxelformat::SceneGraphNode node;
node.setVolume(v, true);
node.setName(name);
node.setVisible(visible);
const glm::vec3 rp = v->region().getPivot();
const glm::vec3 size = v->region().getDimensionsInVoxels();
node.setPivot(0, rp, size);
voxelformat::SceneGraph* sceneGraph = lua::LUA::globalData<voxelformat::SceneGraph>(s, luaVoxel_globalscenegraph());
const int nodeId = voxelformat::addNodeToSceneGraph(*sceneGraph, node, sceneGraph->root().id());
if (nodeId == -1) {
return clua_error(s, "Failed to add new node");
}
return luaVoxel_pushscenegraphnode(s, sceneGraph->node(nodeId));
}
static int luaVoxel_scenegraph_get_node(lua_State* s) {
int nodeId = (int)luaL_optinteger(s, 1, -1);
voxelformat::SceneGraph* sceneGraph = lua::LUA::globalData<voxelformat::SceneGraph>(s, luaVoxel_globalscenegraph());
if (nodeId == -1) {
nodeId = sceneGraph->activeNode();
}
if (!sceneGraph->hasNode(nodeId)) {
return clua_error(s, "Could not find node for id %d", nodeId);
}
voxelformat::SceneGraphNode& node = sceneGraph->node(nodeId);
if (node.type() != voxelformat::SceneGraphNodeType::Model) {
return clua_error(s, "Invalid node for id %d", nodeId);
}
return luaVoxel_pushscenegraphnode(s, node);
}
static int luaVoxel_scenegraphnode_volume(lua_State* s) {
voxelformat::SceneGraphNode* node = luaVoxel_toscenegraphnode(s, 1);
voxel::RawVolumeWrapper *wrapper = new voxel::RawVolumeWrapper(node->volume());
return luaVoxel_pushvolumewrapper_mem(s, wrapper);
}
static int luaVoxel_scenegraphnode_name(lua_State* s) {
voxelformat::SceneGraphNode* node = luaVoxel_toscenegraphnode(s, 1);
lua_pushstring(s, node->name().c_str());
return 1;
}
static int luaVoxel_scenegraphnode_setname(lua_State* s) {
voxelformat::SceneGraphNode* node = luaVoxel_toscenegraphnode(s, 1);
const char *newName = lua_tostring(s, 2);
node->setName(newName);
return 0;
}
static int luaVoxel_scenegraphnode_tostring(lua_State *s) {
voxelformat::SceneGraphNode* node = luaVoxel_toscenegraphnode(s, 1);
lua_pushfstring(s, "layer: [%d, %s]", node->id(), node->name().c_str());
return 1;
}
static void prepareState(lua_State* s) { static void prepareState(lua_State* s) {
static const luaL_Reg volumeFuncs[] = { luaL_Reg volumeFuncs[] = {
{"voxel", luaVoxel_volumewrapper_voxel}, {"voxel", luaVoxel_volumewrapper_voxel},
{"region", luaVoxel_volumewrapper_region}, {"region", luaVoxel_volumewrapper_region},
{"translate", luaVoxel_volumewrapper_translate}, {"translate", luaVoxel_volumewrapper_translate},
{"resize", luaVoxel_volumewrapper_resize}, {"resize", luaVoxel_volumewrapper_resize},
{"setVoxel", luaVoxel_volumewrapper_setvoxel}, {"setVoxel", luaVoxel_volumewrapper_setvoxel},
{nullptr, nullptr},
{nullptr, nullptr} {nullptr, nullptr}
}; };
clua_registerfuncs(s, volumeFuncs, luaVoxel_metavolumewrapper()); clua_registerfuncs(s, volumeFuncs, luaVoxel_metavolumewrapper());
volumeFuncs[lengthof(volumeFuncs) - 2] = {"__gc", luaVoxel_volumewrapper_gc};
clua_registerfuncs(s, volumeFuncs, luaVoxel_metavolumewrapper_mem());
static const luaL_Reg regionFuncs[] = { static const luaL_Reg regionFuncs[] = {
{"width", luaVoxel_region_width}, {"width", luaVoxel_region_width},
{"height", luaVoxel_region_height}, {"height", luaVoxel_region_height},
@ -392,6 +501,22 @@ static void prepareState(lua_State* s) {
}; };
clua_registerfuncs(s, regionFuncs, LUAGenerator::luaVoxel_metaregion()); clua_registerfuncs(s, regionFuncs, LUAGenerator::luaVoxel_metaregion());
static const luaL_Reg sceneGraphFuncs[] = {
{"new", luaVoxel_scenegraph_new_node},
{"get", luaVoxel_scenegraph_get_node},
{nullptr, nullptr}
};
clua_registerfuncsglobal(s, sceneGraphFuncs, luaVoxel_metascenegraph(), "scenegraph");
static const luaL_Reg sceneGraphNodeFuncs[] = {
{"name", luaVoxel_scenegraphnode_name},
{"volume", luaVoxel_scenegraphnode_volume},
{"setName", luaVoxel_scenegraphnode_setname},
{"__tostring", luaVoxel_scenegraphnode_tostring},
{nullptr, nullptr}
};
clua_registerfuncs(s, sceneGraphNodeFuncs, luaVoxel_metascenegraphnode());
static const luaL_Reg paletteFuncs[] = { static const luaL_Reg paletteFuncs[] = {
{"colors", luaVoxel_palette_colors}, {"colors", luaVoxel_palette_colors},
{"color", luaVoxel_palette_color}, {"color", luaVoxel_palette_color},
@ -615,7 +740,7 @@ core::DynamicArray<LUAScript> LUAGenerator::listScripts() const {
return scripts; return scripts;
} }
bool LUAGenerator::exec(const core::String& luaScript, voxel::RawVolumeWrapper* volume, const voxel::Region& region, const voxel::Voxel& voxel, const core::DynamicArray<core::String>& args) { bool LUAGenerator::exec(const core::String& luaScript, voxelformat::SceneGraph &sceneGraph, voxel::RawVolumeWrapper &volume, const voxel::Region& region, const voxel::Voxel& voxel, const core::DynamicArray<core::String>& args) {
core::DynamicArray<LUAParameterDescription> argsInfo; core::DynamicArray<LUAParameterDescription> argsInfo;
if (!argumentInfo(luaScript, argsInfo)) { if (!argumentInfo(luaScript, argsInfo)) {
Log::error("Failed to get argument details"); Log::error("Failed to get argument details");
@ -631,8 +756,8 @@ bool LUAGenerator::exec(const core::String& luaScript, voxel::RawVolumeWrapper*
} }
lua::LUA lua; lua::LUA lua;
lua.newGlobalData<voxelformat::SceneGraph>(luaVoxel_globalscenegraph(), &sceneGraph);
prepareState(lua); prepareState(lua);
initializeCustomState(lua);
// load and run once to initialize the global variables // load and run once to initialize the global variables
if (luaL_dostring(lua, luaScript.c_str())) { if (luaL_dostring(lua, luaScript.c_str())) {
@ -640,7 +765,7 @@ bool LUAGenerator::exec(const core::String& luaScript, voxel::RawVolumeWrapper*
return false; return false;
} }
// get main(volume, region) method // get main(volume, region, color) method
lua_getglobal(lua, "main"); lua_getglobal(lua, "main");
if (!lua_isfunction(lua, -1)) { if (!lua_isfunction(lua, -1)) {
Log::error("LUA generator: no main(volume, region, color) function found in '%s'", luaScript.c_str()); Log::error("LUA generator: no main(volume, region, color) function found in '%s'", luaScript.c_str());
@ -648,7 +773,7 @@ bool LUAGenerator::exec(const core::String& luaScript, voxel::RawVolumeWrapper*
} }
// first parameter is volume // first parameter is volume
if (luaVoxel_pushvolumewrapper(lua, volume) == 0) { if (luaVoxel_pushvolumewrapper(lua, &volume) == 0) {
Log::error("Failed to push volume"); Log::error("Failed to push volume");
return false; return false;
} }

View File

@ -12,6 +12,10 @@
struct lua_State; struct lua_State;
namespace voxelformat {
class SceneGraph;
}
namespace voxel { namespace voxel {
class Region; class Region;
class RawVolumeWrapper; class RawVolumeWrapper;
@ -61,8 +65,6 @@ struct LUAScript {
}; };
class LUAGenerator : public core::IComponent { class LUAGenerator : public core::IComponent {
protected:
virtual void initializeCustomState(lua_State* s) {}
public: public:
static inline const char *luaVoxel_metaregion() { static inline const char *luaVoxel_metaregion() {
return "__meta_region"; return "__meta_region";
@ -78,7 +80,7 @@ public:
core::String load(const core::String& scriptName) const; core::String load(const core::String& scriptName) const;
core::DynamicArray<LUAScript> listScripts() const; core::DynamicArray<LUAScript> listScripts() const;
bool argumentInfo(const core::String& luaScript, core::DynamicArray<LUAParameterDescription>& params); bool argumentInfo(const core::String& luaScript, core::DynamicArray<LUAParameterDescription>& params);
bool exec(const core::String& luaScript, voxel::RawVolumeWrapper* volume, const voxel::Region& region, const voxel::Voxel& voxel, const core::DynamicArray<core::String>& args = core::DynamicArray<core::String>()); bool exec(const core::String& luaScript, voxelformat::SceneGraph &sceneGraph, voxel::RawVolumeWrapper &volume, const voxel::Region& region, const voxel::Voxel& voxel, const core::DynamicArray<core::String>& args = core::DynamicArray<core::String>());
}; };
inline auto scriptCompleter(const io::FilesystemPtr& filesystem) { inline auto scriptCompleter(const io::FilesystemPtr& filesystem) {

View File

@ -8,6 +8,7 @@
#include "voxel/RawVolume.h" #include "voxel/RawVolume.h"
#include "voxel/RawVolumeWrapper.h" #include "voxel/RawVolumeWrapper.h"
#include "voxel/Voxel.h" #include "voxel/Voxel.h"
#include "voxelformat/SceneGraph.h"
#include "voxelgenerator/LUAGenerator.h" #include "voxelgenerator/LUAGenerator.h"
namespace voxelgenerator { namespace voxelgenerator {
@ -53,10 +54,11 @@ TEST_F(LUAGeneratorTest, testExecute) {
voxel::Region region(0, 0, 0, 7, 7, 7); voxel::Region region(0, 0, 0, 7, 7, 7);
voxel::RawVolume volume(region); voxel::RawVolume volume(region);
voxel::RawVolumeWrapper wrapper(&volume); voxel::RawVolumeWrapper wrapper(&volume);
voxelformat::SceneGraph sceneGraph;
LUAGenerator g; LUAGenerator g;
ASSERT_TRUE(g.init()); ASSERT_TRUE(g.init());
EXPECT_TRUE(g.exec(script, &wrapper, wrapper.region(), voxel::createVoxel(voxel::VoxelType::Generic, 42))); EXPECT_TRUE(g.exec(script, sceneGraph, wrapper, wrapper.region(), voxel::createVoxel(voxel::VoxelType::Generic, 42)));
EXPECT_EQ(42, volume.voxel(0, 0, 0).getColor()); EXPECT_EQ(42, volume.voxel(0, 0, 0).getColor());
EXPECT_NE(0, volume.voxel(1, 0, 0).getColor()); EXPECT_NE(0, volume.voxel(1, 0, 0).getColor());
EXPECT_TRUE(wrapper.dirtyRegion().isValid()); EXPECT_TRUE(wrapper.dirtyRegion().isValid());
@ -85,11 +87,10 @@ TEST_F(LUAGeneratorTest, testArguments) {
end end
)"; )";
ASSERT_TRUE(voxel::initDefaultPalette());
voxel::Region region(0, 0, 0, 7, 7, 7); voxel::Region region(0, 0, 0, 7, 7, 7);
voxel::RawVolume volume(region); voxel::RawVolume volume(region);
voxel::RawVolumeWrapper wrapper(&volume); voxel::RawVolumeWrapper wrapper(&volume);
voxelformat::SceneGraph sceneGraph;
LUAGenerator g; LUAGenerator g;
ASSERT_TRUE(g.init()); ASSERT_TRUE(g.init());
@ -105,7 +106,31 @@ TEST_F(LUAGeneratorTest, testArguments) {
core::DynamicArray<core::String> args; core::DynamicArray<core::String> args;
args.push_back("param1"); args.push_back("param1");
args.push_back("param2"); args.push_back("param2");
EXPECT_TRUE(g.exec(script, &wrapper, region, voxel::createVoxel(voxel::VoxelType::Generic, 42), args)); EXPECT_TRUE(g.exec(script, sceneGraph, wrapper, region, voxel::createVoxel(voxel::VoxelType::Generic, 42), args));
g.shutdown();
}
TEST_F(LUAGeneratorTest, testSceneGraph) {
const core::String script = R"(
function main(volume, region, color)
local layer = scenegraph.get()
layer:setName("foobar")
layer:volume():setVoxel(0, 0, 0, color)
end
)";
voxelformat::SceneGraph sceneGraph;
voxelformat::SceneGraphNode node;
voxel::Region region(0, 0, 0, 7, 7, 7);
voxel::RawVolume volume(region);
node.setVolume(&volume, false);
sceneGraph.emplace(core::move(node));
voxel::RawVolumeWrapper wrapper(&volume);
LUAGenerator g;
ASSERT_TRUE(g.init());
core::DynamicArray<core::String> args;
EXPECT_TRUE(g.exec(script, sceneGraph, wrapper, region, voxel::createVoxel(voxel::VoxelType::Generic, 42), args));
g.shutdown(); g.shutdown();
} }

View File

@ -568,7 +568,7 @@ void VoxConvert::script(const core::String &scriptParameters, voxelformat::Scene
Log::info("Execute script %s", tokens[0].c_str()); Log::info("Execute script %s", tokens[0].c_str());
for (voxelformat::SceneGraphNode& node : sceneGraph) { for (voxelformat::SceneGraphNode& node : sceneGraph) {
voxel::RawVolumeWrapper wrapper(node.volume()); voxel::RawVolumeWrapper wrapper(node.volume());
script.exec(luaScript, &wrapper, wrapper.region(), voxel, args); script.exec(luaScript, sceneGraph, wrapper, wrapper.region(), voxel, args);
if (wrapper.volume() != node.volume()) { if (wrapper.volume() != node.volume()) {
node.setVolume(wrapper.volume(), true); node.setVolume(wrapper.volume(), true);
} }

View File

@ -1,5 +1,4 @@
set(SRCS set(SRCS
EditorLUAGenerator.h EditorLUAGenerator.cpp
MementoHandler.h MementoHandler.cpp MementoHandler.h MementoHandler.cpp
SceneManager.h SceneManager.cpp SceneManager.h SceneManager.cpp
CustomBindingContext.h CustomBindingContext.h

View File

@ -1,188 +0,0 @@
/**
* @file
*/
#include "EditorLUAGenerator.h"
#include "commonlua/LUAFunctions.h"
#include "SceneManager.h"
#include "voxel/RawVolume.h"
#include "voxel/RawVolumeWrapper.h"
#include "voxelformat/SceneGraphNode.h"
#include "voxelgenerator/LUAGenerator.h"
namespace voxedit {
static const char *luaVoxel_metascenegraphnode() {
return "__meta_scenegraphnode";
}
static const char *luaVoxel_metavolume() {
return "__meta_volume";
}
static const char *luaVoxel_metascenegraph() {
return "__meta_scenegraph";
}
struct LUAVolume {
int nodeId;
voxel::RawVolume* volume;
voxel::Region dirtyRegion = voxel::Region::InvalidRegion;
};
static voxelformat::SceneGraphNode* luaVoxel_toSceneGraphNode(lua_State* s, int n) {
return clua_getudata<voxelformat::SceneGraphNode*>(s, n, luaVoxel_metascenegraphnode());
}
static int luaVoxel_pushscenegraphnode(lua_State* s, voxelformat::SceneGraphNode& node) {
return clua_pushudata(s, &node, luaVoxel_metascenegraphnode());
}
static int luaVoxel_pushvolume(lua_State* s, const LUAVolume& luaVolume) {
return clua_pushudata(s, luaVolume, luaVoxel_metavolume());
}
static LUAVolume* luaVoxel_tovolume(lua_State* s, int n) {
return clua_getudata<LUAVolume*>(s, n, luaVoxel_metavolume());
}
static int luaVoxel_scenegraph_new_node(lua_State* s) {
const char *name = lua_tostring(s, 1);
const bool visible = lua_toboolean(s, 2);
const voxel::Region* region = voxelgenerator::LUAGenerator::luaVoxel_toRegion(s, 3);
voxel::RawVolume *v = new voxel::RawVolume(*region);
voxelformat::SceneGraphNode node;
node.setVolume(v, true);
node.setName(name);
node.setVisible(visible);
const glm::vec3 rp = v->region().getPivot();
const glm::vec3 size = v->region().getDimensionsInVoxels();
node.setPivot(0, rp, size);
const int nodeId = sceneMgr().addNodeToSceneGraph(node);
if (nodeId == -1) {
return clua_error(s, "Failed to add new node");
}
return luaVoxel_pushscenegraphnode(s, sceneMgr().sceneGraph().node(nodeId));
}
static int luaVoxel_scenegraph_get_node(lua_State* s) {
int nodeId = (int)luaL_optinteger(s, 1, -1);
const voxelformat::SceneGraph &sceneGraph = sceneMgr().sceneGraph();
if (nodeId == -1) {
nodeId = sceneGraph.activeNode();
}
if (!sceneGraph.hasNode(nodeId)) {
return clua_error(s, "Could not find node for id %d", nodeId);
}
voxelformat::SceneGraphNode& node = sceneGraph.node(nodeId);
if (node.type() != voxelformat::SceneGraphNodeType::Model) {
return clua_error(s, "Invalid node for id %d", nodeId);
}
return luaVoxel_pushscenegraphnode(s, node);
}
static int luaVoxel_scenegraphnode_name(lua_State* s) {
voxelformat::SceneGraphNode* node = luaVoxel_toSceneGraphNode(s, 1);
lua_pushstring(s, node->name().c_str());
return 1;
}
static int luaVoxel_scenegraphnode_setname(lua_State* s) {
voxelformat::SceneGraphNode* node = luaVoxel_toSceneGraphNode(s, 1);
const char *newName = lua_tostring(s, 2);
node->setName(newName);
return 0;
}
static int luaVoxel_scenegraphnode_tostring(lua_State *s) {
voxelformat::SceneGraphNode* node = luaVoxel_toSceneGraphNode(s, 1);
lua_pushfstring(s, "layer: [%d, %s]", node->id(), node->name().c_str());
return 1;
}
static int luaVoxel_scenegraphnode_volume(lua_State* s) {
voxelformat::SceneGraphNode* node = luaVoxel_toSceneGraphNode(s, 1);
voxel::RawVolume* volume = node->volume();
if (volume == nullptr) {
return clua_error(s, "Invalid node id %d given - no volume found", node->id());
}
const LUAVolume luaVolume{node->id(), volume, voxel::Region::InvalidRegion};
return luaVoxel_pushvolume(s, luaVolume);
}
static int luaVoxel_volume_voxel(lua_State* s) {
const LUAVolume* volume = luaVoxel_tovolume(s, 1);
const int x = (int)luaL_checkinteger(s, 2);
const int y = (int)luaL_checkinteger(s, 3);
const int z = (int)luaL_checkinteger(s, 4);
const voxel::Voxel& voxel = volume->volume->voxel(x, y, z);
if (voxel::isAir(voxel.getMaterial())) {
lua_pushinteger(s, -1);
} else {
lua_pushinteger(s, voxel.getColor());
}
return 1;
}
static int luaVoxel_volume_region(lua_State* s) {
const LUAVolume* volume = luaVoxel_tovolume(s, 1);
return voxelgenerator::LUAGenerator::luaVoxel_pushregion(s, &volume->volume->region());
}
static int luaVoxel_volume_setvoxel(lua_State* s) {
LUAVolume* volume = luaVoxel_tovolume(s, 1);
voxel::RawVolumeWrapper wrapper(volume->volume);
const int x = (int)luaL_checkinteger(s, 2);
const int y = (int)luaL_checkinteger(s, 3);
const int z = (int)luaL_checkinteger(s, 4);
const int color = (int)luaL_checkinteger(s, 5);
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, color);
const bool insideRegion = wrapper.setVoxel(x, y, z, voxel);
lua_pushboolean(s, insideRegion ? 1 : 0);
if (wrapper.dirtyRegion().isValid()) {
if (volume->dirtyRegion.isValid()) {
volume->dirtyRegion.accumulate(wrapper.dirtyRegion());
} else {
volume->dirtyRegion = wrapper.dirtyRegion();
}
}
return 1;
}
static int luaVoxel_volume_gc(lua_State *s) {
LUAVolume* volume = luaVoxel_tovolume(s, 1);
if (volume->dirtyRegion.isValid()) {
sceneMgr().modified(volume->nodeId, volume->dirtyRegion);
}
return 0;
}
void EditorLUAGenerator::initializeCustomState(lua_State *s) {
static const luaL_Reg sceneGraphFuncs[] = {
{"new", luaVoxel_scenegraph_new_node},
{"get", luaVoxel_scenegraph_get_node},
{nullptr, nullptr}
};
clua_registerfuncsglobal(s, sceneGraphFuncs, luaVoxel_metascenegraph(), "scenegraph");
static const luaL_Reg sceneGraphNodeFuncs[] = {
{"volume", luaVoxel_scenegraphnode_volume},
{"name", luaVoxel_scenegraphnode_name},
{"setName", luaVoxel_scenegraphnode_setname},
{"__tostring", luaVoxel_scenegraphnode_tostring},
{nullptr, nullptr}
};
clua_registerfuncs(s, sceneGraphNodeFuncs, luaVoxel_metascenegraphnode());
static const luaL_Reg volumeFuncs[] = {
{"voxel", luaVoxel_volume_voxel},
{"region", luaVoxel_volume_region},
{"setVoxel", luaVoxel_volume_setvoxel},
{"__gc", luaVoxel_volume_gc},
{nullptr, nullptr}
};
clua_registerfuncs(s, volumeFuncs, luaVoxel_metavolume());
}
}

View File

@ -1,16 +0,0 @@
/**
* @file
*/
#pragma once
#include "voxelgenerator/LUAGenerator.h"
namespace voxedit {
class EditorLUAGenerator : public voxelgenerator::LUAGenerator {
protected:
void initializeCustomState(lua_State* s) override;
};
}

View File

@ -1762,7 +1762,7 @@ bool SceneManager::runScript(const core::String& script, const core::DynamicArra
if (selection.isValid()) { if (selection.isValid()) {
wrapper.setRegion(selection); wrapper.setRegion(selection);
} }
const bool retVal = _luaGenerator.exec(script, &wrapper, wrapper.region(), _modifier.cursorVoxel(), args); const bool retVal = _luaGenerator.exec(script, _sceneGraph, wrapper, wrapper.region(), _modifier.cursorVoxel(), args);
if (wrapper.volume() != volume) { if (wrapper.volume() != volume) {
sceneGraphNode(nodeId)->setVolume(wrapper.volume(), true); sceneGraphNode(nodeId)->setVolume(wrapper.volume(), true);
} }

View File

@ -27,7 +27,7 @@
#include "command/ActionButton.h" #include "command/ActionButton.h"
#include "math/Axis.h" #include "math/Axis.h"
#include "MementoHandler.h" #include "MementoHandler.h"
#include "EditorLUAGenerator.h" #include "voxelgenerator/LUAGenerator.h"
#include "modifier/ModifierType.h" #include "modifier/ModifierType.h"
#include "modifier/ModifierFacade.h" #include "modifier/ModifierFacade.h"
#include <functional> #include <functional>
@ -170,7 +170,7 @@ private:
// existing voxel under the cursor // existing voxel under the cursor
voxel::Voxel _hitCursorVoxel; voxel::Voxel _hitCursorVoxel;
EditorLUAGenerator _luaGenerator; voxelgenerator::LUAGenerator _luaGenerator;
voxel::RawVolume* activeVolume(); voxel::RawVolume* activeVolume();
/** /**