VOXCONVERT: added scripting support
|
@ -12,6 +12,7 @@ vengi (0.0.15.0-1) UNRELEASED; urgency=low
|
|||
* Added option to keep the input file palette and don't perform quantization
|
||||
* Allow to export the palette to png
|
||||
* Allow to generate models from heightmap images
|
||||
* Allow to run lua scripts to modify volumes
|
||||
|
||||
* Thumbnailer:
|
||||
* Try to use the built-in palette for models
|
||||
|
|
|
@ -18,6 +18,7 @@ VoxConvert:
|
|||
- Added option to keep the input file palette and don't perform quantization
|
||||
- Allow to export the palette to png
|
||||
- Allow to generate models from heightmap images
|
||||
- Allow to run lua scripts to modify volumes
|
||||
|
||||
Thumbnailer:
|
||||
|
||||
|
|
|
@ -1,11 +1,29 @@
|
|||
# Scripting api
|
||||
|
||||
There is a console command (called `xs`) in voxedit to execute lua scripts for generating voxels. This command expects the lua script filename (`.lua` can be omitted) and the additional arguments for the `main()` method.
|
||||
There is a console command (called `xs`) in [voxedit](voxedit/Index.md) and a command line parameter in [voxconvert](voxconvert/Index.md) to execute lua scripts for generating voxels. This command expects the lua script filename (`.lua` can be omitted) and the additional arguments for the `main()` method.
|
||||
|
||||
Calling `xs <script> help` will print the supported arguments for the given script.
|
||||
---
|
||||
|
||||
> **voxedit**
|
||||
>
|
||||
> Calling `xs <script> help` (in the script console) will print the supported arguments for the given script file in voxedit.
|
||||
|
||||
---
|
||||
|
||||
> **voxconvert**
|
||||
>
|
||||
> ```
|
||||
> ./vengi-voxconvert --script "<script> help" in.qb out.qb
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
By default the script files will be searched in a `scripts` folder next to where the binary is located and in the usual search paths (see [configuration](Configuration.md) for more details). You can also give the full path to the script file.
|
||||
|
||||
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)).
|
||||
|
||||
# Example without parameters
|
||||
|
||||
```lua
|
||||
|
@ -57,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.
|
||||
|
||||
# LayerManager
|
||||
# LayerManager (voxedit)
|
||||
|
||||
`layerMgr` lets you access different layers or create new ones.
|
||||
|
||||
|
@ -67,7 +85,7 @@ The functions are:
|
|||
|
||||
* `get([layerId])`: Returns the `layer` for the given `layerId` - if the `layerId` is not given, it will return the current active layer. Which by default is the layer for the volume the script is currently executed for.
|
||||
|
||||
# Layer
|
||||
# Layer (voxedit)
|
||||
|
||||
* `name()`: Returns the current name of the layer.
|
||||
|
||||
|
@ -160,7 +178,7 @@ To get a full list of commands and cvars use the console command `cmdlist` and `
|
|||
|
||||
Generates perlin noise with the frequency and amplitude as parameters with the current selected color.
|
||||
|
||||
![noise](lua-noise.png)
|
||||
![noise](img/lua-noise.png)
|
||||
|
||||
`xs noise.lua 0.3 1.0`
|
||||
|
||||
|
@ -168,7 +186,7 @@ Generates perlin noise with the frequency and amplitude as parameters with the c
|
|||
|
||||
Generates a new voxel on top of others with the current selected color and the specified height.
|
||||
|
||||
![cover](lua-cover.png)
|
||||
![cover](img/lua-cover.png)
|
||||
|
||||
`xs cover.lua 1`
|
||||
|
||||
|
@ -176,15 +194,15 @@ Generates a new voxel on top of others with the current selected color and the s
|
|||
|
||||
Generates a pyramid with the current selected color and with each level being 3 voxels high.
|
||||
|
||||
![pyramid](lua-pyramid.png)
|
||||
![pyramid](img/lua-pyramid.png)
|
||||
|
||||
`xs pyramid.lua 3`
|
||||
|
||||
## thicken.lua
|
||||
## thicken.lua (voxedit)
|
||||
|
||||
Thickens the voxel - take 1 voxel and convert to 8 voxels.
|
||||
|
||||
![thickenbefore](lua-thicken-before.png) ![thickenafter](lua-thicken-after.png)
|
||||
![thickenbefore](img/lua-thicken-before.png) ![thickenafter](img/lua-thicken-after.png)
|
||||
|
||||
`xs thicken.lua 1`
|
||||
|
||||
|
@ -192,6 +210,6 @@ Thickens the voxel - take 1 voxel and convert to 8 voxels.
|
|||
|
||||
Generate grass on top of voxels.
|
||||
|
||||
![grass](grass.png)
|
||||
![grass](img/grass.png)
|
||||
|
||||
`xs grass.lua`
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
@ -31,4 +31,4 @@ You can also use other user/password combinations by setting some cvars:
|
|||
* **db_pw**
|
||||
* **db_user**
|
||||
|
||||
See the [configuration](Configuration.md) documentation for more details.
|
||||
See the [configuration](../Configuration.md) documentation for more details.
|
||||
|
|
|
@ -8,7 +8,7 @@ You can load and save a lot of different [voxel formats](../Formats.md).
|
|||
|
||||
## Features
|
||||
|
||||
* LUA [scripting](LUAScript.md) api
|
||||
* LUA [scripting](../LUAScript.md) api
|
||||
* Layer support
|
||||
* Auto cropping volumes
|
||||
* Auto generate content like trees or noise volumes
|
||||
|
|
|
@ -24,9 +24,9 @@ nav:
|
|||
- Configuration.md
|
||||
- Formats.md
|
||||
- CHANGELOG.md
|
||||
- LUAScript.md
|
||||
- VoxEdit:
|
||||
- voxedit/Index.md
|
||||
- voxedit/LUAScript.md
|
||||
- Games:
|
||||
- OpenWorld: openworld/Index.md
|
||||
- Tools:
|
||||
|
|
|
@ -4,4 +4,4 @@ set(SRCS
|
|||
)
|
||||
|
||||
engine_add_executable(TARGET ${PROJECT_NAME} SRCS ${SRCS})
|
||||
engine_target_link_libraries(TARGET ${PROJECT_NAME} DEPENDENCIES app voxelformat)
|
||||
engine_target_link_libraries(TARGET ${PROJECT_NAME} DEPENDENCIES app voxelformat voxelgenerator)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/Color.h"
|
||||
#include "core/GameConfig.h"
|
||||
#include "core/StringUtil.h"
|
||||
#include "core/Tokenizer.h"
|
||||
#include "core/Var.h"
|
||||
#include "command/Command.h"
|
||||
#include "image/Image.h"
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include "voxel/MaterialColor.h"
|
||||
#include "voxelformat/VolumeFormat.h"
|
||||
#include "voxelformat/Format.h"
|
||||
#include "voxelgenerator/LUAGenerator.h"
|
||||
#include "voxelutil/ImageUtils.h"
|
||||
#include "voxelutil/VolumeRescaler.h"
|
||||
|
||||
|
@ -33,6 +35,7 @@ app::AppState VoxConvert::onConstruct() {
|
|||
registerArg("--scale").setShort("-s").setDescription("Scale layer to 50% of its original size");
|
||||
registerArg("--force").setShort("-f").setDescription("Overwrite existing files");
|
||||
registerArg("--export-palette").setDescription("Export the used palette data into an image. Use in combination with --src-palette");
|
||||
registerArg("--script").setDefaultValue("script.lua").setDescription("Apply the given lua script to the output volume");
|
||||
|
||||
_mergeQuads = core::Var::get(cfg::VoxformatMergequads, "true", core::CV_NOPERSIST);
|
||||
_mergeQuads->setHelp("Merge similar quads to optimize the mesh");
|
||||
|
@ -51,6 +54,10 @@ app::AppState VoxConvert::onConstruct() {
|
|||
_palette = core::Var::get("palette", voxel::getDefaultPaletteName());
|
||||
_palette->setHelp("This is the NAME part of palette-<NAME>.png or absolute png file to use (1x256)");
|
||||
|
||||
if (!filesystem()->registerPath("scripts/")) {
|
||||
Log::warn("Failed to register lua generator script path");
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -100,6 +107,11 @@ app::AppState VoxConvert::onInit() {
|
|||
}
|
||||
Log::info("* infile: - %s", infile.c_str());
|
||||
Log::info("* outfile: - %s", outfile.c_str());
|
||||
core::String scriptParameters;
|
||||
if (hasArg("--script")) {
|
||||
scriptParameters = getArgVal("--script");
|
||||
Log::info("* script: - %s", scriptParameters.c_str());
|
||||
}
|
||||
Log::info("* merge volumes: - %s", (mergeVolumes ? "true" : "false"));
|
||||
Log::info("* scale volumes: - %s", (scaleVolumes ? "true" : "false"));
|
||||
Log::info("* use source file palette: - %s", (srcPalette ? "true" : "false"));
|
||||
|
@ -204,6 +216,37 @@ app::AppState VoxConvert::onInit() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!scriptParameters.empty()) {
|
||||
voxelgenerator::LUAGenerator script;
|
||||
if (!script.init()) {
|
||||
Log::warn("Failed to initialize the script bindings");
|
||||
} else {
|
||||
core::DynamicArray<core::String> tokens;
|
||||
core::string::splitString(scriptParameters, tokens);
|
||||
const core::String &luaScript = script.load(tokens[0]);
|
||||
if (luaScript.empty()) {
|
||||
Log::error("Failed to load %s", tokens[0].c_str());
|
||||
} else {
|
||||
const voxel::Voxel voxel = voxel::createVoxel(voxel::VoxelType::Generic, 1);
|
||||
core::DynamicArray<voxelgenerator::LUAParameterDescription> argsInfo;
|
||||
if (!script.argumentInfo(luaScript, argsInfo)) {
|
||||
Log::warn("Failed to get argument details");
|
||||
}
|
||||
core::DynamicArray<core::String> args(tokens.size() - 1);
|
||||
for (size_t i = 1; i < tokens.size(); ++i) {
|
||||
args[i - 1] = tokens[i];
|
||||
}
|
||||
Log::info("Execute script %s", tokens[0].c_str());
|
||||
for (auto& v : volumes) {
|
||||
voxel::RawVolumeWrapper wrapper(v.volume);
|
||||
script.exec(luaScript, &wrapper, wrapper.region(), voxel, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
script.shutdown();
|
||||
}
|
||||
|
||||
Log::debug("Save");
|
||||
if (!voxelformat::saveFormat(outputFile, volumes)) {
|
||||
voxelformat::clearVolumes(volumes);
|
||||
|
|