VoxelServer no longer inherits Object.
The Godot-facing singleton is now a different class in gd:: namespace. Moved the updater to its own file.
This commit is contained in:
parent
d690ef0963
commit
774adfca3c
@ -10,6 +10,7 @@
|
||||
#include <scene/gui/menu_button.h>
|
||||
|
||||
using namespace zylann;
|
||||
using namespace voxel;
|
||||
|
||||
class VoxelTerrainEditorTaskIndicator : public HBoxContainer {
|
||||
GDCLASS(VoxelTerrainEditorTaskIndicator, HBoxContainer)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "meshers/cubes/voxel_mesher_cubes.h"
|
||||
#include "meshers/dmc/voxel_mesher_dmc.h"
|
||||
#include "meshers/transvoxel/voxel_mesher_transvoxel.h"
|
||||
#include "server/voxel_server_gd.h"
|
||||
#include "storage/voxel_buffer.h"
|
||||
#include "storage/voxel_memory_pool.h"
|
||||
#include "streams/region/voxel_stream_region_files.h"
|
||||
@ -69,11 +70,12 @@ void register_voxel_types() {
|
||||
VoxelStringNames::create_singleton();
|
||||
VoxelGraphNodeDB::create_singleton();
|
||||
VoxelServer::create_singleton();
|
||||
gd::VoxelServer::create_singleton();
|
||||
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("VoxelServer", VoxelServer::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("VoxelServer", gd::VoxelServer::get_singleton()));
|
||||
|
||||
// TODO Can I prevent users from instancing it? is "register_virtual_class" correct for a class that's not abstract?
|
||||
ClassDB::register_class<VoxelServer>();
|
||||
ClassDB::register_class<gd::VoxelServer>();
|
||||
|
||||
// Misc
|
||||
ClassDB::register_class<Voxel>();
|
||||
@ -181,6 +183,7 @@ void unregister_voxel_types() {
|
||||
|
||||
VoxelStringNames::destroy_singleton();
|
||||
VoxelGraphNodeDB::destroy_singleton();
|
||||
gd::VoxelServer::destroy_singleton();
|
||||
VoxelServer::destroy_singleton();
|
||||
|
||||
// Do this last as VoxelServer might still be holding some refs to voxel blocks
|
||||
|
@ -7,20 +7,17 @@
|
||||
#include "../util/profiling.h"
|
||||
#include "../util/tasks/async_dependency_tracker.h"
|
||||
|
||||
#include <core/config/project_settings.h>
|
||||
#include <core/os/memory.h>
|
||||
#include <scene/main/window.h> // Needed for doing `Node *root = SceneTree::get_root()`, Window* is forward-declared
|
||||
#include <thread>
|
||||
|
||||
using namespace zylann;
|
||||
using namespace voxel;
|
||||
namespace zylann::voxel {
|
||||
|
||||
namespace {
|
||||
VoxelServer *g_voxel_server = nullptr;
|
||||
// Could be atomics, but it's for debugging so I don't bother for now
|
||||
int g_debug_generate_tasks_count = 0;
|
||||
int g_debug_stream_tasks_count = 0;
|
||||
int g_debug_mesh_tasks_count = 0;
|
||||
} // namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -43,12 +40,6 @@ void VoxelServer::destroy_singleton() {
|
||||
VoxelServer::VoxelServer() {
|
||||
CRASH_COND(ProjectSettings::get_singleton() == nullptr);
|
||||
|
||||
#ifdef VOXEL_PROFILER_ENABLED
|
||||
CRASH_COND(RenderingServer::get_singleton() == nullptr);
|
||||
RenderingServer::get_singleton()->connect(
|
||||
SNAME("frame_post_draw"), callable_mp(this, &VoxelServer::_on_rendering_server_frame_post_draw));
|
||||
#endif
|
||||
|
||||
const int hw_threads_hint = std::thread::hardware_concurrency();
|
||||
PRINT_VERBOSE(String("Voxel: HW threads hint: {0}").format(varray(hw_threads_hint)));
|
||||
|
||||
@ -573,12 +564,6 @@ void VoxelServer::push_async_tasks(Span<zylann::IThreadedTask *> tasks) {
|
||||
_general_thread_pool.enqueue(tasks);
|
||||
}
|
||||
|
||||
void VoxelServer::_on_rendering_server_frame_post_draw() {
|
||||
#ifdef VOXEL_PROFILER_ENABLED
|
||||
VOXEL_PROFILE_MARK_FRAME();
|
||||
#endif
|
||||
}
|
||||
|
||||
void VoxelServer::process() {
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
VOXEL_PROFILE_PLOT("Static memory usage", int64_t(OS::get_singleton()->get_static_memory_usage()));
|
||||
@ -681,14 +666,6 @@ VoxelServer::Stats VoxelServer::get_stats() const {
|
||||
return s;
|
||||
}
|
||||
|
||||
Dictionary VoxelServer::_b_get_stats() {
|
||||
return get_stats().to_dict();
|
||||
}
|
||||
|
||||
void VoxelServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_stats"), &VoxelServer::_b_get_stats);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
VoxelServer::BlockDataRequest::BlockDataRequest() {
|
||||
@ -1199,53 +1176,4 @@ void VoxelServer::BlockMeshRequest::apply_result() {
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
bool g_updater_created = false;
|
||||
}
|
||||
|
||||
VoxelServerUpdater::VoxelServerUpdater() {
|
||||
PRINT_VERBOSE("Creating VoxelServerUpdater");
|
||||
set_process(true);
|
||||
g_updater_created = true;
|
||||
}
|
||||
|
||||
VoxelServerUpdater::~VoxelServerUpdater() {
|
||||
g_updater_created = false;
|
||||
}
|
||||
|
||||
void VoxelServerUpdater::ensure_existence(SceneTree *st) {
|
||||
if (st == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (g_updater_created) {
|
||||
return;
|
||||
}
|
||||
Node *root = st->get_root();
|
||||
for (int i = 0; i < root->get_child_count(); ++i) {
|
||||
VoxelServerUpdater *u = Object::cast_to<VoxelServerUpdater>(root->get_child(i));
|
||||
if (u != nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
VoxelServerUpdater *u = memnew(VoxelServerUpdater);
|
||||
u->set_name("VoxelServerUpdater_dont_touch_this");
|
||||
root->add_child(u);
|
||||
}
|
||||
|
||||
void VoxelServerUpdater::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_PROCESS:
|
||||
// To workaround the absence of API to have a custom server processing in the main loop
|
||||
VoxelServer::get_singleton()->process();
|
||||
break;
|
||||
|
||||
case NOTIFICATION_PREDELETE:
|
||||
PRINT_VERBOSE("Deleting VoxelServerUpdater");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace zylann::voxel
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include "../util/tasks/time_spread_task_runner.h"
|
||||
#include "struct_db.h"
|
||||
|
||||
#include <scene/main/node.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class VoxelNode;
|
||||
@ -20,12 +18,11 @@ namespace zylann {
|
||||
class AsyncDependencyTracker;
|
||||
}
|
||||
|
||||
// TODO Don't inherit Object. Instead have a Godot wrapper, there is very little use for Object stuff
|
||||
namespace zylann::voxel {
|
||||
|
||||
// Access point for asynchronous voxel processing APIs.
|
||||
// Functions must be used from the main thread.
|
||||
class VoxelServer : public Object {
|
||||
GDCLASS(VoxelServer, Object)
|
||||
class VoxelServer {
|
||||
public:
|
||||
struct BlockMeshOutput {
|
||||
enum Type {
|
||||
@ -40,10 +37,13 @@ public:
|
||||
};
|
||||
|
||||
struct BlockDataOutput {
|
||||
enum Type { TYPE_LOAD, TYPE_SAVE };
|
||||
enum Type { //
|
||||
TYPE_LOAD,
|
||||
TYPE_SAVE
|
||||
};
|
||||
|
||||
Type type;
|
||||
std::shared_ptr<zylann::voxel::VoxelBufferInternal> voxels;
|
||||
std::shared_ptr<VoxelBufferInternal> voxels;
|
||||
std::unique_ptr<VoxelInstanceBlockData> instances;
|
||||
Vector3i position;
|
||||
uint8_t lod;
|
||||
@ -55,9 +55,7 @@ public:
|
||||
|
||||
struct BlockMeshInput {
|
||||
// Moore area ordered by forward XYZ iteration
|
||||
zylann::FixedArray<std::shared_ptr<zylann::voxel::VoxelBufferInternal>,
|
||||
zylann::voxel::constants::MAX_BLOCK_COUNT_PER_REQUEST>
|
||||
data_blocks;
|
||||
FixedArray<std::shared_ptr<VoxelBufferInternal>, constants::MAX_BLOCK_COUNT_PER_REQUEST> data_blocks;
|
||||
unsigned int data_blocks_count = 0;
|
||||
Vector3i render_block_position;
|
||||
uint8_t lod = 0;
|
||||
@ -115,10 +113,10 @@ public:
|
||||
// TODO Add parameter to skip stream loading
|
||||
void request_block_load(uint32_t volume_id, Vector3i block_pos, int lod, bool request_instances);
|
||||
void request_block_generate(
|
||||
uint32_t volume_id, Vector3i block_pos, int lod, std::shared_ptr<zylann::AsyncDependencyTracker> tracker);
|
||||
uint32_t volume_id, Vector3i block_pos, int lod, std::shared_ptr<AsyncDependencyTracker> tracker);
|
||||
void request_all_stream_blocks(uint32_t volume_id);
|
||||
void request_voxel_block_save(uint32_t volume_id, std::shared_ptr<zylann::voxel::VoxelBufferInternal> voxels,
|
||||
Vector3i block_pos, int lod);
|
||||
void request_voxel_block_save(
|
||||
uint32_t volume_id, std::shared_ptr<VoxelBufferInternal> voxels, Vector3i block_pos, int lod);
|
||||
void request_instance_block_save(
|
||||
uint32_t volume_id, std::unique_ptr<VoxelInstanceBlockData> instances, Vector3i block_pos, int lod);
|
||||
void remove_volume(uint32_t volume_id);
|
||||
@ -141,13 +139,13 @@ public:
|
||||
_world.viewers.for_each_with_id(f);
|
||||
}
|
||||
|
||||
void push_time_spread_task(zylann::ITimeSpreadTask *task);
|
||||
void push_time_spread_task(ITimeSpreadTask *task);
|
||||
int get_main_thread_time_budget_usec() const;
|
||||
|
||||
void push_progressive_task(zylann::IProgressiveTask *task);
|
||||
void push_progressive_task(IProgressiveTask *task);
|
||||
|
||||
void push_async_task(zylann::IThreadedTask *task);
|
||||
void push_async_tasks(Span<zylann::IThreadedTask *> tasks);
|
||||
void push_async_task(IThreadedTask *task);
|
||||
void push_async_tasks(Span<IThreadedTask *> tasks);
|
||||
|
||||
// Gets by how much voxels must be padded with neighbors in order to be polygonized properly
|
||||
// void get_min_max_block_padding(
|
||||
@ -157,7 +155,7 @@ public:
|
||||
void process();
|
||||
void wait_and_clear_all_tasks(bool warn);
|
||||
|
||||
inline zylann::FileLocker &get_file_locker() {
|
||||
inline FileLocker &get_file_locker() {
|
||||
return _file_locker;
|
||||
}
|
||||
|
||||
@ -201,11 +199,6 @@ private:
|
||||
|
||||
void request_block_generate_from_data_request(BlockDataRequest &src);
|
||||
void request_block_save_from_generate_request(BlockGenerateRequest &src);
|
||||
void _on_rendering_server_frame_post_draw();
|
||||
|
||||
Dictionary _b_get_stats();
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
// Since we are going to send data to tasks running in multiple threads, a few strategies are in place:
|
||||
//
|
||||
@ -255,8 +248,8 @@ private:
|
||||
};
|
||||
|
||||
struct World {
|
||||
zylann::StructDB<Volume> volumes;
|
||||
zylann::StructDB<Viewer> viewers;
|
||||
StructDB<Volume> volumes;
|
||||
StructDB<Viewer> viewers;
|
||||
|
||||
// Must be overwritten with a new instance if count changes.
|
||||
std::shared_ptr<PriorityDependencyShared> shared_priority_dependency;
|
||||
@ -273,7 +266,7 @@ private:
|
||||
PriorityDependency &dep, Vector3i block_position, uint8_t lod, const Volume &volume, int block_size);
|
||||
static int get_priority(const PriorityDependency &dep, uint8_t lod_index, float *out_closest_distance_sq);
|
||||
|
||||
class BlockDataRequest : public zylann::IThreadedTask {
|
||||
class BlockDataRequest : public IThreadedTask {
|
||||
public:
|
||||
enum Type { //
|
||||
TYPE_LOAD = 0,
|
||||
@ -284,12 +277,12 @@ private:
|
||||
BlockDataRequest();
|
||||
~BlockDataRequest();
|
||||
|
||||
void run(zylann::ThreadedTaskContext ctx) override;
|
||||
void run(ThreadedTaskContext ctx) override;
|
||||
int get_priority() override;
|
||||
bool is_cancelled() override;
|
||||
void apply_result() override;
|
||||
|
||||
std::shared_ptr<zylann::voxel::VoxelBufferInternal> voxels;
|
||||
std::shared_ptr<VoxelBufferInternal> voxels;
|
||||
std::unique_ptr<VoxelInstanceBlockData> instances;
|
||||
Vector3i position; // In data blocks of the specified lod
|
||||
uint32_t volume_id;
|
||||
@ -306,12 +299,12 @@ private:
|
||||
// TODO Find a way to separate save, it doesnt need sorting
|
||||
};
|
||||
|
||||
class AllBlocksDataRequest : public zylann::IThreadedTask {
|
||||
class AllBlocksDataRequest : public IThreadedTask {
|
||||
public:
|
||||
AllBlocksDataRequest();
|
||||
~AllBlocksDataRequest();
|
||||
|
||||
void run(zylann::ThreadedTaskContext ctx) override;
|
||||
void run(ThreadedTaskContext ctx) override;
|
||||
int get_priority() override;
|
||||
bool is_cancelled() override;
|
||||
void apply_result() override;
|
||||
@ -321,17 +314,17 @@ private:
|
||||
std::shared_ptr<StreamingDependency> stream_dependency;
|
||||
};
|
||||
|
||||
class BlockGenerateRequest : public zylann::IThreadedTask {
|
||||
class BlockGenerateRequest : public IThreadedTask {
|
||||
public:
|
||||
BlockGenerateRequest();
|
||||
~BlockGenerateRequest();
|
||||
|
||||
void run(zylann::ThreadedTaskContext ctx) override;
|
||||
void run(ThreadedTaskContext ctx) override;
|
||||
int get_priority() override;
|
||||
bool is_cancelled() override;
|
||||
void apply_result() override;
|
||||
|
||||
std::shared_ptr<zylann::voxel::VoxelBufferInternal> voxels;
|
||||
std::shared_ptr<VoxelBufferInternal> voxels;
|
||||
Vector3i position;
|
||||
uint32_t volume_id;
|
||||
uint8_t lod;
|
||||
@ -342,22 +335,20 @@ private:
|
||||
bool drop_beyond_max_distance = true;
|
||||
PriorityDependency priority_dependency;
|
||||
std::shared_ptr<StreamingDependency> stream_dependency;
|
||||
std::shared_ptr<zylann::AsyncDependencyTracker> tracker;
|
||||
std::shared_ptr<AsyncDependencyTracker> tracker;
|
||||
};
|
||||
|
||||
class BlockMeshRequest : public zylann::IThreadedTask {
|
||||
class BlockMeshRequest : public IThreadedTask {
|
||||
public:
|
||||
BlockMeshRequest();
|
||||
~BlockMeshRequest();
|
||||
|
||||
void run(zylann::ThreadedTaskContext ctx) override;
|
||||
void run(ThreadedTaskContext ctx) override;
|
||||
int get_priority() override;
|
||||
bool is_cancelled() override;
|
||||
void apply_result() override;
|
||||
|
||||
zylann::FixedArray<std::shared_ptr<zylann::voxel::VoxelBufferInternal>,
|
||||
zylann::voxel::constants::MAX_BLOCK_COUNT_PER_REQUEST>
|
||||
blocks;
|
||||
FixedArray<std::shared_ptr<VoxelBufferInternal>, constants::MAX_BLOCK_COUNT_PER_REQUEST> blocks;
|
||||
// TODO Need to provide format
|
||||
//FixedArray<uint8_t, VoxelBufferInternal::MAX_CHANNELS> channel_depths;
|
||||
Vector3i position; // In mesh blocks of the specified lod
|
||||
@ -376,29 +367,15 @@ private:
|
||||
World _world;
|
||||
|
||||
// Pool specialized in file I/O
|
||||
zylann::ThreadedTaskRunner _streaming_thread_pool;
|
||||
ThreadedTaskRunner _streaming_thread_pool;
|
||||
// Pool for every other task
|
||||
zylann::ThreadedTaskRunner _general_thread_pool;
|
||||
ThreadedTaskRunner _general_thread_pool;
|
||||
// For tasks that can only run on the main thread and be spread out over frames
|
||||
zylann::TimeSpreadTaskRunner _time_spread_task_runner;
|
||||
TimeSpreadTaskRunner _time_spread_task_runner;
|
||||
int _main_thread_time_budget_usec = 8000;
|
||||
zylann::ProgressiveTaskRunner _progressive_task_runner;
|
||||
ProgressiveTaskRunner _progressive_task_runner;
|
||||
|
||||
zylann::FileLocker _file_locker;
|
||||
};
|
||||
|
||||
// TODO Hack to make VoxelServer update... need ways to integrate callbacks from main loop!
|
||||
class VoxelServerUpdater : public Node {
|
||||
GDCLASS(VoxelServerUpdater, Node)
|
||||
public:
|
||||
~VoxelServerUpdater();
|
||||
static void ensure_existence(SceneTree *st);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
private:
|
||||
VoxelServerUpdater();
|
||||
FileLocker _file_locker;
|
||||
};
|
||||
|
||||
struct VoxelFileLockerRead {
|
||||
@ -425,4 +402,6 @@ struct VoxelFileLockerWrite {
|
||||
String _path;
|
||||
};
|
||||
|
||||
} // namespace zylann::voxel
|
||||
|
||||
#endif // VOXEL_SERVER_H
|
||||
|
47
server/voxel_server_gd.cpp
Normal file
47
server/voxel_server_gd.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "voxel_server_gd.h"
|
||||
#include "../util/macros.h"
|
||||
#include "../util/profiling.h"
|
||||
#include "voxel_server.h"
|
||||
|
||||
namespace zylann::voxel::gd {
|
||||
VoxelServer *g_voxel_server = nullptr;
|
||||
|
||||
VoxelServer *VoxelServer::get_singleton() {
|
||||
CRASH_COND_MSG(g_voxel_server == nullptr, "Accessing singleton while it's null");
|
||||
return g_voxel_server;
|
||||
}
|
||||
|
||||
void VoxelServer::create_singleton() {
|
||||
CRASH_COND_MSG(g_voxel_server != nullptr, "Creating singleton twice");
|
||||
g_voxel_server = memnew(VoxelServer);
|
||||
}
|
||||
|
||||
void VoxelServer::destroy_singleton() {
|
||||
CRASH_COND_MSG(g_voxel_server == nullptr, "Destroying singleton twice");
|
||||
memdelete(g_voxel_server);
|
||||
g_voxel_server = nullptr;
|
||||
}
|
||||
|
||||
VoxelServer::VoxelServer() {
|
||||
#ifdef VOXEL_PROFILER_ENABLED
|
||||
CRASH_COND(RenderingServer::get_singleton() == nullptr);
|
||||
RenderingServer::get_singleton()->connect(
|
||||
SNAME("frame_post_draw"), callable_mp(this, &VoxelServer::_on_rendering_server_frame_post_draw));
|
||||
#endif
|
||||
}
|
||||
|
||||
Dictionary VoxelServer::get_stats() const {
|
||||
return zylann::voxel::VoxelServer::get_singleton()->get_stats().to_dict();
|
||||
}
|
||||
|
||||
void VoxelServer::_on_rendering_server_frame_post_draw() {
|
||||
#ifdef VOXEL_PROFILER_ENABLED
|
||||
VOXEL_PROFILE_MARK_FRAME();
|
||||
#endif
|
||||
}
|
||||
|
||||
void VoxelServer::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_stats"), &VoxelServer::get_stats);
|
||||
}
|
||||
|
||||
} // namespace zylann::voxel::gd
|
30
server/voxel_server_gd.h
Normal file
30
server/voxel_server_gd.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef VOXEL_SERVER_GD_H
|
||||
#define VOXEL_SERVER_GD_H
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include <core/object/object.h>
|
||||
|
||||
namespace zylann::voxel::gd {
|
||||
|
||||
// Godot-facing singleton class.
|
||||
// the real class is internal and does not need anything from Object.
|
||||
class VoxelServer : public Object {
|
||||
GDCLASS(VoxelServer, Object)
|
||||
public:
|
||||
Dictionary get_stats() const;
|
||||
|
||||
VoxelServer();
|
||||
|
||||
static VoxelServer *get_singleton();
|
||||
static void create_singleton();
|
||||
static void destroy_singleton();
|
||||
|
||||
private:
|
||||
void _on_rendering_server_frame_post_draw();
|
||||
|
||||
static void _bind_methods();
|
||||
};
|
||||
|
||||
} // namespace zylann::voxel::gd
|
||||
|
||||
#endif // VOXEL_SERVER_GD_H
|
55
server/voxel_server_updater.cpp
Normal file
55
server/voxel_server_updater.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "voxel_server_updater.h"
|
||||
#include "../util/macros.h"
|
||||
#include "voxel_server.h"
|
||||
|
||||
// Needed for doing `Node *root = SceneTree::get_root()`, Window* is forward-declared
|
||||
#include <scene/main/window.h>
|
||||
|
||||
namespace {
|
||||
bool g_updater_created = false;
|
||||
}
|
||||
|
||||
VoxelServerUpdater::VoxelServerUpdater() {
|
||||
PRINT_VERBOSE("Creating VoxelServerUpdater");
|
||||
set_process(true);
|
||||
g_updater_created = true;
|
||||
}
|
||||
|
||||
VoxelServerUpdater::~VoxelServerUpdater() {
|
||||
g_updater_created = false;
|
||||
}
|
||||
|
||||
void VoxelServerUpdater::ensure_existence(SceneTree *st) {
|
||||
if (st == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (g_updater_created) {
|
||||
return;
|
||||
}
|
||||
Node *root = st->get_root();
|
||||
for (int i = 0; i < root->get_child_count(); ++i) {
|
||||
VoxelServerUpdater *u = Object::cast_to<VoxelServerUpdater>(root->get_child(i));
|
||||
if (u != nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
VoxelServerUpdater *u = memnew(VoxelServerUpdater);
|
||||
u->set_name("VoxelServerUpdater_dont_touch_this");
|
||||
root->add_child(u);
|
||||
}
|
||||
|
||||
void VoxelServerUpdater::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_PROCESS:
|
||||
// To workaround the absence of API to have a custom server processing in the main loop
|
||||
zylann::voxel::VoxelServer::get_singleton()->process();
|
||||
break;
|
||||
|
||||
case NOTIFICATION_PREDELETE:
|
||||
PRINT_VERBOSE("Deleting VoxelServerUpdater");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
20
server/voxel_server_updater.h
Normal file
20
server/voxel_server_updater.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef VOXEL_SERVER_UPDATER_H
|
||||
#define VOXEL_SERVER_UPDATER_H
|
||||
|
||||
#include <scene/main/node.h>
|
||||
|
||||
// TODO Hack to make VoxelServer update... need ways to integrate callbacks from main loop!
|
||||
class VoxelServerUpdater : public Node {
|
||||
GDCLASS(VoxelServerUpdater, Node)
|
||||
public:
|
||||
~VoxelServerUpdater();
|
||||
static void ensure_existence(SceneTree *st);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
private:
|
||||
VoxelServerUpdater();
|
||||
};
|
||||
|
||||
#endif // VOXEL_SERVER_UPDATER_H
|
@ -47,7 +47,6 @@ FileResult check_magic_and_version(
|
||||
}
|
||||
|
||||
Error check_directory_created(const String &directory_path) {
|
||||
VoxelFileLockerWrite file_wlock(directory_path);
|
||||
DirAccess *d = DirAccess::create_for_path(directory_path);
|
||||
|
||||
if (d == nullptr) {
|
||||
@ -69,6 +68,13 @@ Error check_directory_created(const String &directory_path) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
namespace voxel {
|
||||
Error check_directory_created_using_file_locker(const String &directory_path) {
|
||||
VoxelFileLockerWrite file_wlock(directory_path);
|
||||
return check_directory_created(directory_path);
|
||||
}
|
||||
} // namespace voxel
|
||||
|
||||
// TODO Write tests
|
||||
|
||||
// Makes the file bigger to move the half from the current position further,
|
||||
|
@ -48,7 +48,11 @@ enum FileResult {
|
||||
const char *to_string(FileResult res);
|
||||
FileResult check_magic_and_version(
|
||||
FileAccess *f, uint8_t expected_version, const char *expected_magic, uint8_t &out_version);
|
||||
Error check_directory_created(const String &directory_path);
|
||||
|
||||
namespace voxel {
|
||||
// Specific to voxel because it uses a global lock found only in VoxelServer
|
||||
Error check_directory_created_using_file_locker(const String &directory_path);
|
||||
} // namespace voxel
|
||||
|
||||
void insert_bytes(FileAccess *f, size_t count, size_t temp_chunk_size = 512);
|
||||
|
||||
|
@ -195,7 +195,7 @@ Error RegionFile::open(const String &fpath, bool create_if_not_found) {
|
||||
CRASH_COND(f != nullptr);
|
||||
|
||||
// Checking folders, needed for region "forests"
|
||||
const Error dir_err = check_directory_created(fpath.get_base_dir());
|
||||
const Error dir_err = check_directory_created_using_file_locker(fpath.get_base_dir());
|
||||
if (dir_err != OK) {
|
||||
return ERR_CANT_CREATE;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ FileResult VoxelStreamRegionFiles::save_meta() {
|
||||
|
||||
// Make sure the directory exists
|
||||
{
|
||||
Error err = check_directory_created(_directory_path);
|
||||
Error err = check_directory_created_using_file_locker(_directory_path);
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Could not save meta");
|
||||
return FILE_CANT_OPEN;
|
||||
|
@ -127,7 +127,7 @@ void VoxelStreamBlockFiles::immerge_block(VoxelBufferInternal &buffer, Vector3i
|
||||
String file_path = get_block_file_path(block_pos, lod);
|
||||
|
||||
{
|
||||
const Error err = check_directory_created(file_path.get_base_dir());
|
||||
const Error err = check_directory_created_using_file_locker(file_path.get_base_dir());
|
||||
ERR_FAIL_COND(err != OK);
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ FileResult VoxelStreamBlockFiles::save_meta() {
|
||||
|
||||
// Make sure the directory exists
|
||||
{
|
||||
Error err = check_directory_created(_directory_path);
|
||||
Error err = check_directory_created_using_file_locker(_directory_path);
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Could not save meta");
|
||||
return FILE_CANT_OPEN;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
using namespace zylann;
|
||||
using namespace voxel;
|
||||
|
||||
VoxelInstancer::VoxelInstancer() {
|
||||
set_notify_transform(true);
|
||||
|
@ -2,7 +2,8 @@
|
||||
#include "../constants/voxel_string_names.h"
|
||||
#include "../edition/voxel_tool_lod_terrain.h"
|
||||
#include "../meshers/transvoxel/voxel_mesher_transvoxel.h"
|
||||
#include "../server/voxel_server.h"
|
||||
#include "../server/voxel_server_gd.h"
|
||||
#include "../server/voxel_server_updater.h"
|
||||
#include "../util/funcs.h"
|
||||
#include "../util/godot/funcs.h"
|
||||
#include "../util/macros.h"
|
||||
|
@ -247,8 +247,8 @@ private:
|
||||
//void process_block_loading_responses();
|
||||
void send_mesh_requests();
|
||||
|
||||
void apply_mesh_update(const VoxelServer::BlockMeshOutput &ob);
|
||||
void apply_data_block_response(VoxelServer::BlockDataOutput &ob);
|
||||
void apply_mesh_update(const zylann::voxel::VoxelServer::BlockMeshOutput &ob);
|
||||
void apply_data_block_response(zylann::voxel::VoxelServer::BlockDataOutput &ob);
|
||||
|
||||
void unload_data_block_no_lock(Vector3i block_pos, uint8_t lod_index, std::vector<BlockToSave> &blocks_to_save);
|
||||
void unload_mesh_block(Vector3i block_pos, uint8_t lod_index);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "../constants/voxel_string_names.h"
|
||||
#include "../edition/voxel_tool_terrain.h"
|
||||
#include "../server/voxel_server.h"
|
||||
#include "../server/voxel_server_updater.h"
|
||||
#include "../util/funcs.h"
|
||||
#include "../util/godot/funcs.h"
|
||||
#include "../util/macros.h"
|
||||
|
@ -121,8 +121,8 @@ private:
|
||||
void process_viewers();
|
||||
//void process_received_data_blocks();
|
||||
void process_meshing();
|
||||
void apply_mesh_update(const VoxelServer::BlockMeshOutput &ob);
|
||||
void apply_data_block_response(VoxelServer::BlockDataOutput &ob);
|
||||
void apply_mesh_update(const zylann::voxel::VoxelServer::BlockMeshOutput &ob);
|
||||
void apply_data_block_response(zylann::voxel::VoxelServer::BlockDataOutput &ob);
|
||||
|
||||
void _on_stream_params_changed();
|
||||
void _set_block_size_po2(int p_block_size_po2);
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include "../server/voxel_server.h"
|
||||
#include <core/config/engine.h>
|
||||
|
||||
using namespace zylann;
|
||||
using namespace voxel;
|
||||
|
||||
VoxelViewer::VoxelViewer() {
|
||||
set_notify_transform(!Engine::get_singleton()->is_editor_hint());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user