godot_voxel/register_types.cpp

309 lines
14 KiB
C++
Raw Permalink Normal View History

#include "register_types.h"
2021-12-30 21:06:00 -08:00
#include "constants/voxel_string_names.h"
#include "edition/voxel_mesh_sdf_gd.h"
#include "edition/voxel_tool.h"
#include "edition/voxel_tool_buffer.h"
#include "edition/voxel_tool_lod_terrain.h"
#include "edition/voxel_tool_terrain.h"
2022-07-16 15:59:06 -07:00
#include "engine/voxel_engine_gd.h"
#include "generators/graph/voxel_generator_graph.h"
2020-02-23 11:08:14 -08:00
#include "generators/graph/voxel_graph_node_db.h"
#include "generators/simple/voxel_generator_flat.h"
#include "generators/simple/voxel_generator_heightmap.h"
#include "generators/simple/voxel_generator_image.h"
#include "generators/simple/voxel_generator_noise.h"
#include "generators/simple/voxel_generator_noise_2d.h"
#include "generators/simple/voxel_generator_waves.h"
#include "generators/voxel_generator_script.h"
#include "meshers/blocky/voxel_blocky_library.h"
#include "meshers/blocky/voxel_mesher_blocky.h"
#include "meshers/cubes/voxel_mesher_cubes.h"
#include "meshers/dmc/voxel_mesher_dmc.h"
#include "meshers/transvoxel/voxel_mesher_transvoxel.h"
#include "storage/modifiers_gd.h"
#include "storage/voxel_buffer_gd.h"
#include "storage/voxel_memory_pool.h"
#include "storage/voxel_metadata_variant.h"
2021-01-31 08:51:42 -08:00
#include "streams/region/voxel_stream_region_files.h"
2021-01-28 14:02:49 -08:00
#include "streams/sqlite/voxel_stream_sqlite.h"
2022-07-17 11:15:32 -07:00
#include "streams/vox/vox_loader.h"
#include "streams/voxel_block_serializer_gd.h"
#include "streams/voxel_stream_script.h"
#include "terrain/fixed_lod/voxel_box_mover.h"
#include "terrain/fixed_lod/voxel_terrain.h"
2021-12-30 21:06:00 -08:00
#include "terrain/instancing/voxel_instance_component.h"
#include "terrain/instancing/voxel_instance_library_scene_item.h"
2021-02-07 13:40:55 -08:00
#include "terrain/instancing/voxel_instancer.h"
#include "terrain/variable_lod/voxel_lod_terrain.h"
#include "terrain/voxel_mesh_block.h"
2020-09-06 11:01:12 -07:00
#include "terrain/voxel_viewer.h"
2020-08-31 13:51:30 -07:00
#include "util/macros.h"
#include "util/noise/fast_noise_lite/fast_noise_lite.h"
#include "util/noise/fast_noise_lite/fast_noise_lite_gradient.h"
2022-04-10 18:10:44 -07:00
#include "util/string_funcs.h"
#include "util/tasks/godot/threaded_task_gd.h"
2021-01-01 16:59:12 -08:00
2021-12-30 21:06:00 -08:00
#ifdef VOXEL_ENABLE_FAST_NOISE_2
#include "util/noise/fast_noise_2.h"
#endif
#include <core/config/engine.h>
#include <core/config/project_settings.h>
#ifdef TOOLS_ENABLED
#include "editor/editor_plugin.h"
#include "editor/fast_noise_lite/fast_noise_lite_editor_plugin.h"
#include "editor/graph/voxel_graph_editor_plugin.h"
#include "editor/instance_library/voxel_instance_library_editor_plugin.h"
#include "editor/instance_library/voxel_instance_library_multimesh_item_editor_plugin.h"
2021-12-30 14:20:30 -08:00
#include "editor/instancer/voxel_instancer_editor_plugin.h"
#include "editor/mesh_sdf/voxel_mesh_sdf_editor_plugin.h"
#include "editor/terrain/voxel_terrain_editor_plugin.h"
#include "editor/vox/vox_editor_plugin.h"
#include "editor/voxel_debug.h"
2021-12-30 21:06:00 -08:00
#ifdef VOXEL_ENABLE_FAST_NOISE_2
#include "editor/fast_noise_2/fast_noise_2_editor_plugin.h"
#endif
2021-12-30 21:06:00 -08:00
#endif // TOOLS_ENABLED
2021-04-03 12:40:35 -07:00
#ifdef VOXEL_RUN_TESTS
#include "tests/tests.h"
#endif
namespace zylann::voxel {
2022-07-16 15:59:06 -07:00
static VoxelEngine::ThreadsConfig get_config_from_godot(unsigned int &out_main_thread_time_budget_usec) {
CRASH_COND(ProjectSettings::get_singleton() == nullptr);
2022-07-16 15:59:06 -07:00
VoxelEngine::ThreadsConfig config;
// Compute thread count for general pool.
// Note that the I/O thread counts as one used thread and will always be present.
// "RST" means changing the property requires an editor restart (or game restart)
GLOBAL_DEF_RST("voxel/threads/count/minimum", 1);
ProjectSettings::get_singleton()->set_custom_property_info("voxel/threads/count/minimum",
PropertyInfo(Variant::INT, "voxel/threads/count/minimum", PROPERTY_HINT_RANGE, "1,64"));
GLOBAL_DEF_RST("voxel/threads/count/margin_below_max", 1);
ProjectSettings::get_singleton()->set_custom_property_info("voxel/threads/count/margin_below_max",
PropertyInfo(Variant::INT, "voxel/threads/count/margin_below_max", PROPERTY_HINT_RANGE, "1,64"));
GLOBAL_DEF_RST("voxel/threads/count/ratio_over_max", 0.5f);
ProjectSettings::get_singleton()->set_custom_property_info("voxel/threads/count/ratio_over_max",
PropertyInfo(Variant::FLOAT, "voxel/threads/count/ratio_over_max", PROPERTY_HINT_RANGE, "0,1,0.1"));
GLOBAL_DEF_RST("voxel/threads/main/time_budget_ms", 8);
ProjectSettings::get_singleton()->set_custom_property_info("voxel/threads/main/time_budget_ms",
PropertyInfo(Variant::INT, "voxel/threads/main/time_budget_ms", PROPERTY_HINT_RANGE, "0,1000"));
out_main_thread_time_budget_usec =
1000 * int(ProjectSettings::get_singleton()->get("voxel/threads/main/time_budget_ms"));
config.thread_count_minimum =
math::max(1, int(ProjectSettings::get_singleton()->get("voxel/threads/count/minimum")));
// How many threads below available count on the CPU should we set as limit
config.thread_count_margin_below_max =
math::max(1, int(ProjectSettings::get_singleton()->get("voxel/threads/count/margin_below_max")));
// Portion of available CPU threads to attempt using
config.thread_count_ratio_over_max = zylann::math::clamp(
float(ProjectSettings::get_singleton()->get("voxel/threads/count/ratio_over_max")), 0.f, 1.f);
return config;
}
} // namespace zylann::voxel
2022-05-07 14:06:32 -07:00
void initialize_voxel_module(ModuleInitializationLevel p_level) {
2022-01-03 15:20:38 -08:00
using namespace zylann;
using namespace voxel;
2022-05-07 14:06:32 -07:00
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
VoxelMemoryPool::create_singleton();
VoxelStringNames::create_singleton();
VoxelGraphNodeDB::create_singleton();
unsigned int main_thread_budget_usec;
2022-07-16 15:59:06 -07:00
const VoxelEngine::ThreadsConfig threads_config = get_config_from_godot(main_thread_budget_usec);
VoxelEngine::create_singleton(threads_config);
VoxelEngine::get_singleton().set_main_thread_time_budget_usec(main_thread_budget_usec);
// TODO Pick this from the current renderer + user option (at time of writing, Godot 4 has only one renderer and
// has not figured out how such option would be exposed).
// Could use `can_create_resources_async` but this is internal.
// AFAIK `is_low_end` will be `true` only for OpenGL backends, which are the only ones not supporting async
// resource creation.
2022-08-24 16:11:54 -07:00
VoxelEngine::get_singleton().set_threaded_graphics_resource_building_enabled(
RenderingServer::get_singleton()->is_low_end() == false);
2022-07-16 15:59:06 -07:00
gd::VoxelEngine::create_singleton();
Engine::get_singleton()->add_singleton(Engine::Singleton("VoxelEngine", gd::VoxelEngine::get_singleton()));
2022-05-07 14:06:32 -07:00
VoxelMetadataFactory::get_singleton().add_constructor_by_type<gd::VoxelMetadataVariant>(
gd::METADATA_TYPE_VARIANT);
VoxelMesherTransvoxel::load_static_resources();
2022-05-07 14:06:32 -07:00
// TODO Can I prevent users from instancing it? is "register_virtual_class" correct for a class that's not
// abstract?
2022-07-16 15:59:06 -07:00
ClassDB::register_class<gd::VoxelEngine>();
2022-05-07 14:06:32 -07:00
// Misc
ClassDB::register_class<VoxelBlockyModel>();
ClassDB::register_class<VoxelBlockyLibrary>();
ClassDB::register_class<VoxelColorPalette>();
ClassDB::register_class<VoxelInstanceLibrary>();
ClassDB::register_abstract_class<VoxelInstanceLibraryItem>();
ClassDB::register_class<VoxelInstanceLibraryMultiMeshItem>();
ClassDB::register_class<VoxelInstanceLibrarySceneItem>();
ClassDB::register_class<VoxelDataBlockEnterInfo>();
// Storage
ClassDB::register_class<gd::VoxelBuffer>();
// Nodes
ClassDB::register_abstract_class<VoxelNode>();
ClassDB::register_class<VoxelTerrain>();
ClassDB::register_class<VoxelLodTerrain>();
ClassDB::register_class<VoxelViewer>();
ClassDB::register_class<VoxelInstanceGenerator>();
ClassDB::register_class<VoxelInstancer>();
ClassDB::register_class<VoxelInstanceComponent>();
ClassDB::register_abstract_class<gd::VoxelModifier>();
ClassDB::register_class<gd::VoxelModifierSphere>();
ClassDB::register_class<gd::VoxelModifierMesh>();
2022-05-07 14:06:32 -07:00
// Streams
ClassDB::register_abstract_class<VoxelStream>();
ClassDB::register_class<VoxelStreamRegionFiles>();
ClassDB::register_class<VoxelStreamScript>();
ClassDB::register_class<VoxelStreamSQLite>();
// Generators
ClassDB::register_abstract_class<VoxelGenerator>();
ClassDB::register_class<VoxelGeneratorFlat>();
ClassDB::register_class<VoxelGeneratorWaves>();
ClassDB::register_abstract_class<VoxelGeneratorHeightmap>();
ClassDB::register_class<VoxelGeneratorImage>();
ClassDB::register_class<VoxelGeneratorNoise2D>();
ClassDB::register_class<VoxelGeneratorNoise>();
ClassDB::register_class<VoxelGeneratorGraph>();
ClassDB::register_class<VoxelGeneratorScript>();
// Utilities
ClassDB::register_class<VoxelBoxMover>();
ClassDB::register_class<VoxelRaycastResult>();
ClassDB::register_abstract_class<VoxelTool>();
ClassDB::register_abstract_class<VoxelToolTerrain>();
ClassDB::register_abstract_class<VoxelToolLodTerrain>();
// I had to bind this one despite it being useless as-is because otherwise Godot lazily initializes its class.
// And this can happen in a thread, causing crashes due to the concurrent access
ClassDB::register_abstract_class<VoxelToolBuffer>();
ClassDB::register_class<gd::VoxelBlockSerializer>();
ClassDB::register_class<VoxelVoxLoader>();
ClassDB::register_class<ZN_FastNoiseLite>();
ClassDB::register_class<ZN_FastNoiseLiteGradient>();
ClassDB::register_class<ZN_ThreadedTask>();
// See SCsub
2021-12-30 21:06:00 -08:00
#ifdef VOXEL_ENABLE_FAST_NOISE_2
2022-05-07 14:06:32 -07:00
ClassDB::register_class<FastNoise2>();
#endif
2022-05-07 14:06:32 -07:00
ClassDB::register_class<VoxelMeshSDF>();
// Meshers
ClassDB::register_abstract_class<VoxelMesher>();
ClassDB::register_class<VoxelMesherBlocky>();
ClassDB::register_class<VoxelMesherTransvoxel>();
ClassDB::register_class<VoxelMesherDMC>();
ClassDB::register_class<VoxelMesherCubes>();
// Reminder: how to create a singleton accessible from scripts:
// Engine::get_singleton()->add_singleton(Engine::Singleton("SingletonName",singleton_instance));
// Reminders
ZN_PRINT_VERBOSE(format("Size of Variant: {}", sizeof(Variant)));
ZN_PRINT_VERBOSE(format("Size of Object: {}", sizeof(Object)));
ZN_PRINT_VERBOSE(format("Size of RefCounted: {}", sizeof(RefCounted)));
ZN_PRINT_VERBOSE(format("Size of Node: {}", sizeof(Node)));
ZN_PRINT_VERBOSE(format("Size of Node3D: {}", sizeof(Node3D)));
2022-08-28 13:49:10 -07:00
ZN_PRINT_VERBOSE(format("Size of RWLock: {}", sizeof(zylann::RWLock)));
ZN_PRINT_VERBOSE(format("Size of Mutex: {}", sizeof(zylann::Mutex)));
ZN_PRINT_VERBOSE(format("Size of BinaryMutex: {}", sizeof(zylann::BinaryMutex)));
2022-05-07 14:06:32 -07:00
ZN_PRINT_VERBOSE(format("Size of gd::VoxelBuffer: {}", sizeof(gd::VoxelBuffer)));
ZN_PRINT_VERBOSE(format("Size of VoxelBufferInternal: {}", sizeof(VoxelBufferInternal)));
ZN_PRINT_VERBOSE(format("Size of VoxelMeshBlock: {}", sizeof(VoxelMeshBlock)));
ZN_PRINT_VERBOSE(format("Size of VoxelTerrain: {}", sizeof(VoxelTerrain)));
ZN_PRINT_VERBOSE(format("Size of VoxelLodTerrain: {}", sizeof(VoxelLodTerrain)));
ZN_PRINT_VERBOSE(format("Size of VoxelInstancer: {}", sizeof(VoxelInstancer)));
ZN_PRINT_VERBOSE(format("Size of VoxelDataMap: {}", sizeof(VoxelDataMap)));
ZN_PRINT_VERBOSE(format("Size of VoxelData: {}", sizeof(VoxelData)));
2022-08-06 15:15:56 -07:00
ZN_PRINT_VERBOSE(format("Size of VoxelMesher::Output: {}", sizeof(VoxelMesher::Output)));
ZN_PRINT_VERBOSE(format("Size of VoxelEngine::BlockMeshOutput: {}", sizeof(VoxelEngine::BlockMeshOutput)));
2022-08-28 13:49:10 -07:00
ZN_PRINT_VERBOSE(format("Size of VoxelModifierStack: {}", sizeof(VoxelModifierStack)));
if (RenderingDevice::get_singleton() != nullptr) {
ZN_PRINT_VERBOSE(format("TextureArray max layers: {}",
RenderingDevice::get_singleton()->limit_get(RenderingDevice::LIMIT_MAX_TEXTURE_ARRAY_LAYERS)));
}
2022-05-07 14:06:32 -07:00
#ifdef VOXEL_RUN_TESTS
zylann::voxel::tests::run_voxel_tests();
#endif
// Compatibility with older version
ClassDB::add_compatibility_class("VoxelLibrary", "VoxelBlockyLibrary");
ClassDB::add_compatibility_class("Voxel", "VoxelBlockyModel");
ClassDB::add_compatibility_class("VoxelInstanceLibraryItem", "VoxelInstanceLibraryMultiMeshItem");
// Not possible to add a compat class for this one because the new name is indistinguishable from an old one.
// However this is an abstract class so it should not be found in resources hopefully
//ClassDB::add_compatibility_class("VoxelInstanceLibraryItemBase", "VoxelInstanceLibraryItem");
}
2019-08-29 14:55:02 -07:00
#ifdef TOOLS_ENABLED
2022-05-07 14:06:32 -07:00
if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
EditorPlugins::add_by_type<VoxelGraphEditorPlugin>();
EditorPlugins::add_by_type<VoxelTerrainEditorPlugin>();
EditorPlugins::add_by_type<VoxelInstanceLibraryEditorPlugin>();
EditorPlugins::add_by_type<VoxelInstanceLibraryMultiMeshItemEditorPlugin>();
2022-05-07 14:06:32 -07:00
EditorPlugins::add_by_type<ZN_FastNoiseLiteEditorPlugin>();
EditorPlugins::add_by_type<magica::VoxEditorPlugin>();
EditorPlugins::add_by_type<VoxelInstancerEditorPlugin>();
EditorPlugins::add_by_type<VoxelMeshSDFEditorPlugin>();
2021-12-30 21:06:00 -08:00
#ifdef VOXEL_ENABLE_FAST_NOISE_2
2022-05-07 14:06:32 -07:00
EditorPlugins::add_by_type<FastNoise2EditorPlugin>();
2019-08-29 14:55:02 -07:00
#endif
2022-05-07 14:06:32 -07:00
}
2021-12-30 21:06:00 -08:00
#endif // TOOLS_ENABLED
}
2022-05-07 14:06:32 -07:00
void uninitialize_voxel_module(ModuleInitializationLevel p_level) {
2022-01-03 15:20:38 -08:00
using namespace zylann;
using namespace voxel;
2022-05-07 14:06:32 -07:00
if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) {
// At this point, the GDScript module has nullified GDScriptLanguage::singleton!!
2022-07-16 15:59:06 -07:00
// That means it's impossible to free scripts still referenced by VoxelEngine. And that can happen, because
2022-05-07 14:06:32 -07:00
// users can write custom generators, which run inside threads, and these threads are hosted in the server...
// See https://github.com/Zylann/godot_voxel/issues/189
VoxelMesherTransvoxel::free_static_resources();
2022-05-07 14:06:32 -07:00
VoxelStringNames::destroy_singleton();
VoxelGraphNodeDB::destroy_singleton();
2022-07-16 15:59:06 -07:00
gd::VoxelEngine::destroy_singleton();
VoxelEngine::destroy_singleton();
2022-05-07 14:06:32 -07:00
2022-07-16 15:59:06 -07:00
// Do this last as VoxelEngine might still be holding some refs to voxel blocks
2022-05-07 14:06:32 -07:00
VoxelMemoryPool::destroy_singleton();
// TODO No remove?
2020-01-25 17:59:53 -08:00
}
2019-08-29 14:55:02 -07:00
#ifdef TOOLS_ENABLED
2022-05-07 14:06:32 -07:00
if (p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) {
zylann::free_debug_resources();
2022-05-07 14:06:32 -07:00
// TODO Seriously, no remove?
//EditorPlugins::remove_by_type<VoxelGraphEditorPlugin>();
}
#endif // TOOLS_ENABLED
}