Script-based generators and streams have their own class, should fix C# API
parent
18e7792bd5
commit
10d6e5bd8a
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -17,6 +17,9 @@ Semver is not yet in place, so each version can have breaking changes, although
|
||||||
- Voxel nodes can be moved, scaled and rotated
|
- Voxel nodes can be moved, scaled and rotated
|
||||||
- Voxel nodes can be limited to specific bounds, rather than being infinitely paging volumes (multiples of block size)
|
- Voxel nodes can be limited to specific bounds, rather than being infinitely paging volumes (multiples of block size)
|
||||||
|
|
||||||
|
- Smooth voxels
|
||||||
|
- Shaders now have access to the transform of each block, useful for triplanar mapping on moving volumes
|
||||||
|
|
||||||
- Blocky voxels
|
- Blocky voxels
|
||||||
- Introduced a second blocky mesher dedicated to colored cubes, with greedy meshing and palette support
|
- Introduced a second blocky mesher dedicated to colored cubes, with greedy meshing and palette support
|
||||||
- Replaced `transparent` property with `transparency_index` for more control on the culling of transparent faces
|
- Replaced `transparent` property with `transparency_index` for more control on the culling of transparent faces
|
||||||
|
@ -24,9 +27,14 @@ Semver is not yet in place, so each version can have breaking changes, although
|
||||||
- Breaking changes
|
- Breaking changes
|
||||||
- `VoxelViewer` now replaces the `viewer_path` property on `VoxelTerrain`, and allows multiple loading points
|
- `VoxelViewer` now replaces the `viewer_path` property on `VoxelTerrain`, and allows multiple loading points
|
||||||
- Defined `COLOR` channel in `VoxelBuffer`, previously known as `DATA3`
|
- Defined `COLOR` channel in `VoxelBuffer`, previously known as `DATA3`
|
||||||
|
- `VoxelGenerator` is no longer the base for script-based generators, use `VoxelGeneratorScript` instead
|
||||||
|
- `VoxelStream` is no longer the base for script-based streams, use `VoxelStreamScript` instead
|
||||||
|
|
||||||
|
- Fixes
|
||||||
|
- C# should be able to properly implement generator/stream functions
|
||||||
|
|
||||||
- Known issues
|
- Known issues
|
||||||
- `VoxelLodTerrain` does not support `VoxelViewer`, but a refactoring pass is planned for it.
|
- `VoxelLodTerrain` does not entirely support `VoxelViewer`, but a refactoring pass is planned for it.
|
||||||
|
|
||||||
|
|
||||||
`godot3.2.3` - 08/09/2020
|
`godot3.2.3` - 08/09/2020
|
||||||
|
|
|
@ -25,6 +25,7 @@ def get_doc_classes():
|
||||||
"VoxelViewer",
|
"VoxelViewer",
|
||||||
|
|
||||||
"VoxelStream",
|
"VoxelStream",
|
||||||
|
"VoxelStreamScript",
|
||||||
"VoxelStreamFile",
|
"VoxelStreamFile",
|
||||||
"VoxelStreamBlockFiles",
|
"VoxelStreamBlockFiles",
|
||||||
"VoxelStreamRegionFiles",
|
"VoxelStreamRegionFiles",
|
||||||
|
@ -36,6 +37,7 @@ def get_doc_classes():
|
||||||
"VoxelGeneratorNoise2D",
|
"VoxelGeneratorNoise2D",
|
||||||
"VoxelGeneratorTest",
|
"VoxelGeneratorTest",
|
||||||
"VoxelGeneratorGraph",
|
"VoxelGeneratorGraph",
|
||||||
|
"VoxelGeneratorScript",
|
||||||
|
|
||||||
"VoxelBoxMover",
|
"VoxelBoxMover",
|
||||||
"VoxelTool",
|
"VoxelTool",
|
||||||
|
|
|
@ -6,8 +6,6 @@ VoxelGenerator::VoxelGenerator() {
|
||||||
|
|
||||||
void VoxelGenerator::generate_block(VoxelBlockRequest &input) {
|
void VoxelGenerator::generate_block(VoxelBlockRequest &input) {
|
||||||
ERR_FAIL_COND(input.voxel_buffer.is_null());
|
ERR_FAIL_COND(input.voxel_buffer.is_null());
|
||||||
try_call_script(this, VoxelStringNames::get_singleton()->generate_block,
|
|
||||||
input.voxel_buffer, input.origin_in_voxels.to_vec3(), input.lod, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool VoxelGenerator::is_thread_safe() const {
|
//bool VoxelGenerator::is_thread_safe() const {
|
||||||
|
@ -30,7 +28,6 @@ void VoxelGenerator::_b_generate_block(Ref<VoxelBuffer> out_buffer, Vector3 orig
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelGenerator::_bind_methods() {
|
void VoxelGenerator::_bind_methods() {
|
||||||
// Note: C++ inheriting classes don't need to re-bind these, because they are bindings that call the actual virtual methods
|
ClassDB::bind_method(D_METHOD("generate_block", "out_buffer", "origin_in_voxels", "lod"),
|
||||||
|
&VoxelGenerator::_b_generate_block);
|
||||||
ClassDB::bind_method(D_METHOD("generate_block", "out_buffer", "origin_in_voxels", "lod"), &VoxelGenerator::_b_generate_block);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "voxel_generator_script.h"
|
||||||
|
#include "../voxel_string_names.h"
|
||||||
|
|
||||||
|
VoxelGeneratorScript::VoxelGeneratorScript() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorScript::generate_block(VoxelBlockRequest &input) {
|
||||||
|
ERR_FAIL_COND(input.voxel_buffer.is_null());
|
||||||
|
try_call_script(this, VoxelStringNames::get_singleton()->_generate_block,
|
||||||
|
input.voxel_buffer, input.origin_in_voxels.to_vec3(), input.lod, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VoxelGeneratorScript::get_used_channels_mask() const {
|
||||||
|
Variant ret;
|
||||||
|
if (try_call_script(this, VoxelStringNames::get_singleton()->_get_used_channels_mask, nullptr, 0, &ret)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelGeneratorScript::_bind_methods() {
|
||||||
|
BIND_VMETHOD(MethodInfo("_generate_block",
|
||||||
|
PropertyInfo(Variant::OBJECT, "out_buffer", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "VoxelBuffer"),
|
||||||
|
PropertyInfo(Variant::VECTOR3, "origin_in_voxels"),
|
||||||
|
PropertyInfo(Variant::INT, "lod")));
|
||||||
|
|
||||||
|
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_used_channels_mask"));
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef VOXEL_GENERATOR_SCRIPT_H
|
||||||
|
#define VOXEL_GENERATOR_SCRIPT_H
|
||||||
|
|
||||||
|
#include "voxel_generator.h"
|
||||||
|
|
||||||
|
// Generator based on a script, like GDScript, C# or NativeScript
|
||||||
|
class VoxelGeneratorScript : public VoxelGenerator {
|
||||||
|
GDCLASS(VoxelGeneratorScript, VoxelGenerator)
|
||||||
|
public:
|
||||||
|
VoxelGeneratorScript();
|
||||||
|
|
||||||
|
void generate_block(VoxelBlockRequest &input) override;
|
||||||
|
int get_used_channels_mask() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void _bind_methods();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VOXEL_GENERATOR_SCRIPT_H
|
|
@ -11,6 +11,7 @@
|
||||||
#include "generators/voxel_generator_image.h"
|
#include "generators/voxel_generator_image.h"
|
||||||
#include "generators/voxel_generator_noise.h"
|
#include "generators/voxel_generator_noise.h"
|
||||||
#include "generators/voxel_generator_noise_2d.h"
|
#include "generators/voxel_generator_noise_2d.h"
|
||||||
|
#include "generators/voxel_generator_script.h"
|
||||||
#include "generators/voxel_generator_waves.h"
|
#include "generators/voxel_generator_waves.h"
|
||||||
#include "meshers/blocky/voxel_library.h"
|
#include "meshers/blocky/voxel_library.h"
|
||||||
#include "meshers/blocky/voxel_mesher_blocky.h"
|
#include "meshers/blocky/voxel_mesher_blocky.h"
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
#include "streams/voxel_stream_block_files.h"
|
#include "streams/voxel_stream_block_files.h"
|
||||||
#include "streams/voxel_stream_file.h"
|
#include "streams/voxel_stream_file.h"
|
||||||
#include "streams/voxel_stream_region_files.h"
|
#include "streams/voxel_stream_region_files.h"
|
||||||
|
#include "streams/voxel_stream_script.h"
|
||||||
#include "terrain/voxel_box_mover.h"
|
#include "terrain/voxel_box_mover.h"
|
||||||
#include "terrain/voxel_lod_terrain.h"
|
#include "terrain/voxel_lod_terrain.h"
|
||||||
#include "terrain/voxel_map.h"
|
#include "terrain/voxel_map.h"
|
||||||
|
@ -65,6 +67,7 @@ void register_voxel_types() {
|
||||||
ClassDB::register_class<VoxelStreamFile>();
|
ClassDB::register_class<VoxelStreamFile>();
|
||||||
ClassDB::register_class<VoxelStreamBlockFiles>();
|
ClassDB::register_class<VoxelStreamBlockFiles>();
|
||||||
ClassDB::register_class<VoxelStreamRegionFiles>();
|
ClassDB::register_class<VoxelStreamRegionFiles>();
|
||||||
|
ClassDB::register_class<VoxelStreamScript>();
|
||||||
|
|
||||||
// Generators
|
// Generators
|
||||||
ClassDB::register_class<VoxelGenerator>();
|
ClassDB::register_class<VoxelGenerator>();
|
||||||
|
@ -75,6 +78,7 @@ void register_voxel_types() {
|
||||||
ClassDB::register_class<VoxelGeneratorNoise2D>();
|
ClassDB::register_class<VoxelGeneratorNoise2D>();
|
||||||
ClassDB::register_class<VoxelGeneratorNoise>();
|
ClassDB::register_class<VoxelGeneratorNoise>();
|
||||||
ClassDB::register_class<VoxelGeneratorGraph>();
|
ClassDB::register_class<VoxelGeneratorGraph>();
|
||||||
|
ClassDB::register_class<VoxelGeneratorScript>();
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
ClassDB::register_class<VoxelBoxMover>();
|
ClassDB::register_class<VoxelBoxMover>();
|
||||||
|
|
|
@ -7,12 +7,10 @@ VoxelStream::VoxelStream() {
|
||||||
|
|
||||||
void VoxelStream::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) {
|
void VoxelStream::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) {
|
||||||
ERR_FAIL_COND(out_buffer.is_null());
|
ERR_FAIL_COND(out_buffer.is_null());
|
||||||
try_call_script(this, VoxelStringNames::get_singleton()->emerge_block, out_buffer, origin_in_voxels.to_vec3(), lod, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelStream::immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod) {
|
void VoxelStream::immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod) {
|
||||||
ERR_FAIL_COND(buffer.is_null());
|
ERR_FAIL_COND(buffer.is_null());
|
||||||
try_call_script(this, VoxelStringNames::get_singleton()->immerge_block, buffer, origin_in_voxels.to_vec3(), lod, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelStream::emerge_blocks(Vector<VoxelBlockRequest> &p_blocks) {
|
void VoxelStream::emerge_blocks(Vector<VoxelBlockRequest> &p_blocks) {
|
||||||
|
@ -49,10 +47,6 @@ void VoxelStream::_immerge_block(Ref<VoxelBuffer> buffer, Vector3 origin_in_voxe
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelStream::get_used_channels_mask() const {
|
int VoxelStream::get_used_channels_mask() const {
|
||||||
Variant ret;
|
|
||||||
if (try_call_script(this, VoxelStringNames::get_singleton()->get_used_channels_mask, nullptr, 0, &ret)) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +64,6 @@ bool VoxelStream::has_script() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelStream::_bind_methods() {
|
void VoxelStream::_bind_methods() {
|
||||||
// TODO Make these proper virtual, it confuses C# bindings
|
|
||||||
// Note: C++ inheriting classes don't need to re-bind these, because they are bindings that call the actual virtual methods
|
|
||||||
ClassDB::bind_method(D_METHOD("emerge_block", "out_buffer", "origin_in_voxels", "lod"), &VoxelStream::_emerge_block);
|
ClassDB::bind_method(D_METHOD("emerge_block", "out_buffer", "origin_in_voxels", "lod"), &VoxelStream::_emerge_block);
|
||||||
ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "origin_in_voxels", "lod"), &VoxelStream::_immerge_block);
|
ClassDB::bind_method(D_METHOD("immerge_block", "buffer", "origin_in_voxels", "lod"), &VoxelStream::_immerge_block);
|
||||||
ClassDB::bind_method(D_METHOD("get_used_channels_mask"), &VoxelStream::_get_used_channels_mask);
|
ClassDB::bind_method(D_METHOD("get_used_channels_mask"), &VoxelStream::_get_used_channels_mask);
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "voxel_stream_script.h"
|
||||||
|
#include "../voxel_string_names.h"
|
||||||
|
|
||||||
|
void VoxelStreamScript::emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) {
|
||||||
|
ERR_FAIL_COND(out_buffer.is_null());
|
||||||
|
try_call_script(this, VoxelStringNames::get_singleton()->_emerge_block,
|
||||||
|
out_buffer, origin_in_voxels.to_vec3(), lod, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelStreamScript::immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod) {
|
||||||
|
ERR_FAIL_COND(buffer.is_null());
|
||||||
|
try_call_script(this, VoxelStringNames::get_singleton()->_immerge_block,
|
||||||
|
buffer, origin_in_voxels.to_vec3(), lod, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VoxelStreamScript::get_used_channels_mask() const {
|
||||||
|
Variant ret;
|
||||||
|
if (try_call_script(this, VoxelStringNames::get_singleton()->_get_used_channels_mask, nullptr, 0, &ret)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelStreamScript::_bind_methods() {
|
||||||
|
BIND_VMETHOD(MethodInfo("_emerge_block",
|
||||||
|
PropertyInfo(Variant::OBJECT, "out_buffer", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "VoxelBuffer"),
|
||||||
|
PropertyInfo(Variant::VECTOR3, "origin_in_voxels"),
|
||||||
|
PropertyInfo(Variant::INT, "lod")));
|
||||||
|
|
||||||
|
BIND_VMETHOD(MethodInfo("_immerge_block",
|
||||||
|
PropertyInfo(Variant::OBJECT, "buffer", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT, "VoxelBuffer"),
|
||||||
|
PropertyInfo(Variant::VECTOR3, "origin_in_voxels"),
|
||||||
|
PropertyInfo(Variant::INT, "lod")));
|
||||||
|
|
||||||
|
BIND_VMETHOD(MethodInfo(Variant::INT, "_get_used_channels_mask"));
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef VOXEL_STREAM_SCRIPT_H
|
||||||
|
#define VOXEL_STREAM_SCRIPT_H
|
||||||
|
|
||||||
|
#include "voxel_stream.h"
|
||||||
|
|
||||||
|
// Provides access to a source of paged voxel data, which may load and save.
|
||||||
|
// Must be implemented in a multi-thread-safe way.
|
||||||
|
// If you are looking for a more specialized API to generate voxels, use VoxelGenerator.
|
||||||
|
class VoxelStreamScript : public VoxelStream {
|
||||||
|
GDCLASS(VoxelStreamScript, VoxelStream)
|
||||||
|
public:
|
||||||
|
void emerge_block(Ref<VoxelBuffer> out_buffer, Vector3i origin_in_voxels, int lod) override;
|
||||||
|
void immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod) override;
|
||||||
|
|
||||||
|
int get_used_channels_mask() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VOXEL_STREAM_SCRIPT_H
|
|
@ -26,6 +26,7 @@ bool is_mesh_empty(Ref<Mesh> mesh_ref) {
|
||||||
|
|
||||||
bool try_call_script(const Object *obj, StringName method_name, const Variant **args, unsigned int argc, Variant *out_ret) {
|
bool try_call_script(const Object *obj, StringName method_name, const Variant **args, unsigned int argc, Variant *out_ret) {
|
||||||
ScriptInstance *script = obj->get_script_instance();
|
ScriptInstance *script = obj->get_script_instance();
|
||||||
|
// TODO Is has_method() needed? I've seen `call()` being called anyways in ButtonBase
|
||||||
if (script == nullptr || !script->has_method(method_name)) {
|
if (script == nullptr || !script->has_method(method_name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,11 @@ void VoxelStringNames::destroy_singleton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
VoxelStringNames::VoxelStringNames() {
|
VoxelStringNames::VoxelStringNames() {
|
||||||
emerge_block = StaticCString::create("emerge_block");
|
_emerge_block = StaticCString::create("_emerge_block");
|
||||||
immerge_block = StaticCString::create("immerge_block");
|
_immerge_block = StaticCString::create("_immerge_block");
|
||||||
generate_block = StaticCString::create("generate_block");
|
_generate_block = StaticCString::create("_generate_block");
|
||||||
get_used_channels_mask = StaticCString::create("get_used_channels_mask");
|
_get_used_channels_mask = StaticCString::create("_get_used_channels_mask");
|
||||||
|
|
||||||
block_loaded = StaticCString::create("block_loaded");
|
block_loaded = StaticCString::create("block_loaded");
|
||||||
block_unloaded = StaticCString::create("block_unloaded");
|
block_unloaded = StaticCString::create("block_unloaded");
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,11 @@ public:
|
||||||
|
|
||||||
VoxelStringNames();
|
VoxelStringNames();
|
||||||
|
|
||||||
StringName emerge_block;
|
StringName _emerge_block;
|
||||||
StringName immerge_block;
|
StringName _immerge_block;
|
||||||
StringName generate_block;
|
StringName _generate_block;
|
||||||
StringName get_used_channels_mask;
|
StringName _get_used_channels_mask;
|
||||||
|
|
||||||
StringName block_loaded;
|
StringName block_loaded;
|
||||||
StringName block_unloaded;
|
StringName block_unloaded;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue