Script-based generators and streams have their own class, should fix C# API

master
Marc Gilleron 2020-10-31 22:11:25 +00:00
parent 18e7792bd5
commit 10d6e5bd8a
12 changed files with 132 additions and 22 deletions

View File

@ -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 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
- 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
@ -24,9 +27,14 @@ Semver is not yet in place, so each version can have breaking changes, although
- Breaking changes
- `VoxelViewer` now replaces the `viewer_path` property on `VoxelTerrain`, and allows multiple loading points
- 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
- `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

View File

@ -25,6 +25,7 @@ def get_doc_classes():
"VoxelViewer",
"VoxelStream",
"VoxelStreamScript",
"VoxelStreamFile",
"VoxelStreamBlockFiles",
"VoxelStreamRegionFiles",
@ -36,6 +37,7 @@ def get_doc_classes():
"VoxelGeneratorNoise2D",
"VoxelGeneratorTest",
"VoxelGeneratorGraph",
"VoxelGeneratorScript",
"VoxelBoxMover",
"VoxelTool",

View File

@ -6,8 +6,6 @@ VoxelGenerator::VoxelGenerator() {
void VoxelGenerator::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);
}
//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() {
// 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);
}

View File

@ -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"));
}

View File

@ -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

View File

@ -11,6 +11,7 @@
#include "generators/voxel_generator_image.h"
#include "generators/voxel_generator_noise.h"
#include "generators/voxel_generator_noise_2d.h"
#include "generators/voxel_generator_script.h"
#include "generators/voxel_generator_waves.h"
#include "meshers/blocky/voxel_library.h"
#include "meshers/blocky/voxel_mesher_blocky.h"
@ -23,6 +24,7 @@
#include "streams/voxel_stream_block_files.h"
#include "streams/voxel_stream_file.h"
#include "streams/voxel_stream_region_files.h"
#include "streams/voxel_stream_script.h"
#include "terrain/voxel_box_mover.h"
#include "terrain/voxel_lod_terrain.h"
#include "terrain/voxel_map.h"
@ -65,6 +67,7 @@ void register_voxel_types() {
ClassDB::register_class<VoxelStreamFile>();
ClassDB::register_class<VoxelStreamBlockFiles>();
ClassDB::register_class<VoxelStreamRegionFiles>();
ClassDB::register_class<VoxelStreamScript>();
// Generators
ClassDB::register_class<VoxelGenerator>();
@ -75,6 +78,7 @@ void register_voxel_types() {
ClassDB::register_class<VoxelGeneratorNoise2D>();
ClassDB::register_class<VoxelGeneratorNoise>();
ClassDB::register_class<VoxelGeneratorGraph>();
ClassDB::register_class<VoxelGeneratorScript>();
// Utilities
ClassDB::register_class<VoxelBoxMover>();

View File

@ -7,12 +7,10 @@ VoxelStream::VoxelStream() {
void VoxelStream::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 VoxelStream::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);
}
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 {
Variant ret;
if (try_call_script(this, VoxelStringNames::get_singleton()->get_used_channels_mask, nullptr, 0, &ret)) {
return ret;
}
return 0;
}
@ -70,8 +64,6 @@ bool VoxelStream::has_script() const {
}
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("immerge_block", "buffer", "origin_in_voxels", "lod"), &VoxelStream::_immerge_block);
ClassDB::bind_method(D_METHOD("get_used_channels_mask"), &VoxelStream::_get_used_channels_mask);

View File

@ -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"));
}

View File

@ -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

View File

@ -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) {
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)) {
return false;
}

View File

@ -14,10 +14,11 @@ void VoxelStringNames::destroy_singleton() {
}
VoxelStringNames::VoxelStringNames() {
emerge_block = StaticCString::create("emerge_block");
immerge_block = StaticCString::create("immerge_block");
generate_block = StaticCString::create("generate_block");
get_used_channels_mask = StaticCString::create("get_used_channels_mask");
_emerge_block = StaticCString::create("_emerge_block");
_immerge_block = StaticCString::create("_immerge_block");
_generate_block = StaticCString::create("_generate_block");
_get_used_channels_mask = StaticCString::create("_get_used_channels_mask");
block_loaded = StaticCString::create("block_loaded");
block_unloaded = StaticCString::create("block_unloaded");

View File

@ -17,10 +17,11 @@ public:
VoxelStringNames();
StringName emerge_block;
StringName immerge_block;
StringName generate_block;
StringName get_used_channels_mask;
StringName _emerge_block;
StringName _immerge_block;
StringName _generate_block;
StringName _get_used_channels_mask;
StringName block_loaded;
StringName block_unloaded;