mirror of
https://github.com/Relintai/terraman.git
synced 2025-04-23 21:43:23 +02:00
Fix more issues when allocating and deleting chunks really fast. (Flying around in the editor at max speed.)
This commit is contained in:
parent
bc6aec520c
commit
0845d92e65
@ -732,7 +732,10 @@ void TerrainChunkDefault::_visibility_changed(bool visible) {
|
|||||||
void TerrainChunkDefault::_exit_tree() {
|
void TerrainChunkDefault::_exit_tree() {
|
||||||
TerrainChunk::_exit_tree();
|
TerrainChunk::_exit_tree();
|
||||||
|
|
||||||
|
if (!_is_generating) {
|
||||||
rids_free();
|
rids_free();
|
||||||
|
rids_clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainChunkDefault::_world_transform_changed() {
|
void TerrainChunkDefault::_world_transform_changed() {
|
||||||
@ -874,6 +877,9 @@ TerrainChunkDefault::~TerrainChunkDefault() {
|
|||||||
_lights.clear();
|
_lights.clear();
|
||||||
|
|
||||||
debug_mesh_free();
|
debug_mesh_free();
|
||||||
|
|
||||||
|
rids_free();
|
||||||
|
rids_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainChunkDefault::_channel_setup() {
|
void TerrainChunkDefault::_channel_setup() {
|
||||||
|
@ -28,6 +28,7 @@ SOFTWARE.
|
|||||||
|
|
||||||
#include "../defines.h"
|
#include "../defines.h"
|
||||||
|
|
||||||
|
#include "core/message_queue.h"
|
||||||
#include "jobs/terrain_job.h"
|
#include "jobs/terrain_job.h"
|
||||||
#include "terrain_structure.h"
|
#include "terrain_structure.h"
|
||||||
|
|
||||||
@ -65,6 +66,10 @@ _FORCE_INLINE_ void TerrainChunk::set_is_generating(const bool value) {
|
|||||||
_is_generating = value;
|
_is_generating = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TerrainChunk::is_build_aborted() const {
|
||||||
|
return _abort_build;
|
||||||
|
}
|
||||||
|
|
||||||
bool TerrainChunk::is_in_tree() const {
|
bool TerrainChunk::is_in_tree() const {
|
||||||
return _is_in_tree;
|
return _is_in_tree;
|
||||||
}
|
}
|
||||||
@ -268,6 +273,12 @@ int TerrainChunk::job_get_current_index() {
|
|||||||
return _current_job;
|
return _current_job;
|
||||||
}
|
}
|
||||||
void TerrainChunk::job_next() {
|
void TerrainChunk::job_next() {
|
||||||
|
if (_abort_build) {
|
||||||
|
_is_generating = false;
|
||||||
|
_current_job = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
++_current_job;
|
++_current_job;
|
||||||
@ -676,6 +687,22 @@ void TerrainChunk::finalize_build() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerrainChunk::cancel_build() {
|
||||||
|
_queued_generation = false;
|
||||||
|
|
||||||
|
_abort_build = true;
|
||||||
|
|
||||||
|
#if THREAD_POOL_PRESENT
|
||||||
|
if (_is_generating) {
|
||||||
|
Ref<TerrainJob> job = job_get_current();
|
||||||
|
|
||||||
|
if (job.is_valid()) {
|
||||||
|
ThreadPool::get_singleton()->cancel_job(job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void TerrainChunk::bake_lights() {
|
void TerrainChunk::bake_lights() {
|
||||||
if (has_method("_bake_lights"))
|
if (has_method("_bake_lights"))
|
||||||
call("_bake_lights");
|
call("_bake_lights");
|
||||||
@ -966,12 +993,6 @@ void TerrainChunk::enter_tree() {
|
|||||||
void TerrainChunk::exit_tree() {
|
void TerrainChunk::exit_tree() {
|
||||||
_is_in_tree = false;
|
_is_in_tree = false;
|
||||||
|
|
||||||
if (_library.is_valid() && _library->supports_caching()) {
|
|
||||||
if (material_cache_key_has()) {
|
|
||||||
_library->material_cache_unref(material_cache_key_get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_method("_exit_tree"))
|
if (has_method("_exit_tree"))
|
||||||
call("_exit_tree");
|
call("_exit_tree");
|
||||||
}
|
}
|
||||||
@ -1026,6 +1047,24 @@ Vector3 TerrainChunk::to_global(Vector3 p_local) const {
|
|||||||
return get_global_transform().xform(p_local);
|
return get_global_transform().xform(p_local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TerrainChunk::is_safe_to_delete() {
|
||||||
|
#if THREAD_POOL_PRESENT
|
||||||
|
if (!_is_generating) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<TerrainJob> job = job_get_current();
|
||||||
|
|
||||||
|
if (!job.is_valid()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !ThreadPool::get_singleton()->has_job(job);
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
TerrainChunk::TerrainChunk() {
|
TerrainChunk::TerrainChunk() {
|
||||||
_is_processing = false;
|
_is_processing = false;
|
||||||
_is_phisics_processing = false;
|
_is_phisics_processing = false;
|
||||||
@ -1110,7 +1149,9 @@ void TerrainChunk::_enter_tree() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TerrainChunk::_exit_tree() {
|
void TerrainChunk::_exit_tree() {
|
||||||
_abort_build = true;
|
if (_is_generating) {
|
||||||
|
cancel_build();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _jobs.size(); ++i) {
|
for (int i = 0; i < _jobs.size(); ++i) {
|
||||||
Ref<TerrainJob> j = _jobs[i];
|
Ref<TerrainJob> j = _jobs[i];
|
||||||
@ -1119,9 +1160,19 @@ void TerrainChunk::_exit_tree() {
|
|||||||
j->chunk_exit_tree();
|
j->chunk_exit_tree();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_library.is_valid() && _library->supports_caching()) {
|
||||||
|
if (material_cache_key_has()) {
|
||||||
|
_library->material_cache_unref(material_cache_key_get());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainChunk::_generation_process(const float delta) {
|
void TerrainChunk::_generation_process(const float delta) {
|
||||||
|
if (_abort_build) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
if (_current_job < 0 || _current_job >= _jobs.size())
|
if (_current_job < 0 || _current_job >= _jobs.size())
|
||||||
@ -1147,6 +1198,10 @@ void TerrainChunk::_generation_process(const float delta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void TerrainChunk::_generation_physics_process(const float delta) {
|
void TerrainChunk::_generation_physics_process(const float delta) {
|
||||||
|
if (_abort_build) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
if (_current_job < 0 || _current_job >= _jobs.size())
|
if (_current_job < 0 || _current_job >= _jobs.size())
|
||||||
@ -1270,6 +1325,8 @@ void TerrainChunk::_bind_methods() {
|
|||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("finalize_build"), &TerrainChunk::finalize_build);
|
ClassDB::bind_method(D_METHOD("finalize_build"), &TerrainChunk::finalize_build);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("cancel_build"), &TerrainChunk::cancel_build);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_process"), &TerrainChunk::get_process);
|
ClassDB::bind_method(D_METHOD("get_process"), &TerrainChunk::get_process);
|
||||||
ClassDB::bind_method(D_METHOD("set_process", "value"), &TerrainChunk::set_process);
|
ClassDB::bind_method(D_METHOD("set_process", "value"), &TerrainChunk::set_process);
|
||||||
|
|
||||||
@ -1290,6 +1347,8 @@ void TerrainChunk::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("set_is_generating", "value"), &TerrainChunk::set_is_generating);
|
ClassDB::bind_method(D_METHOD("set_is_generating", "value"), &TerrainChunk::set_is_generating);
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_generating", PROPERTY_HINT_NONE, "", 0), "set_is_generating", "get_is_generating");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "is_generating", PROPERTY_HINT_NONE, "", 0), "set_is_generating", "get_is_generating");
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("is_build_aborted"), &TerrainChunk::is_build_aborted);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_dirty"), &TerrainChunk::get_dirty);
|
ClassDB::bind_method(D_METHOD("get_dirty"), &TerrainChunk::get_dirty);
|
||||||
ClassDB::bind_method(D_METHOD("set_dirty", "value"), &TerrainChunk::set_dirty);
|
ClassDB::bind_method(D_METHOD("set_dirty", "value"), &TerrainChunk::set_dirty);
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dirty", PROPERTY_HINT_NONE, "", 0), "set_dirty", "get_dirty");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "dirty", PROPERTY_HINT_NONE, "", 0), "set_dirty", "get_dirty");
|
||||||
@ -1498,4 +1557,6 @@ void TerrainChunk::_bind_methods() {
|
|||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_generation_process"), &TerrainChunk::_generation_process);
|
ClassDB::bind_method(D_METHOD("_generation_process"), &TerrainChunk::_generation_process);
|
||||||
ClassDB::bind_method(D_METHOD("_generation_physics_process"), &TerrainChunk::_generation_physics_process);
|
ClassDB::bind_method(D_METHOD("_generation_physics_process"), &TerrainChunk::_generation_physics_process);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("is_safe_to_delete"), &TerrainChunk::is_safe_to_delete);
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,8 @@ public:
|
|||||||
bool get_is_generating() const;
|
bool get_is_generating() const;
|
||||||
void set_is_generating(const bool value);
|
void set_is_generating(const bool value);
|
||||||
|
|
||||||
|
bool is_build_aborted() const;
|
||||||
|
|
||||||
bool is_in_tree() const;
|
bool is_in_tree() const;
|
||||||
|
|
||||||
bool get_dirty() const;
|
bool get_dirty() const;
|
||||||
@ -222,6 +224,7 @@ public:
|
|||||||
void build();
|
void build();
|
||||||
void clear();
|
void clear();
|
||||||
void finalize_build();
|
void finalize_build();
|
||||||
|
void cancel_build();
|
||||||
|
|
||||||
void _build();
|
void _build();
|
||||||
|
|
||||||
@ -304,6 +307,8 @@ public:
|
|||||||
Vector3 to_local(Vector3 p_global) const;
|
Vector3 to_local(Vector3 p_global) const;
|
||||||
Vector3 to_global(Vector3 p_local) const;
|
Vector3 to_global(Vector3 p_local) const;
|
||||||
|
|
||||||
|
bool is_safe_to_delete();
|
||||||
|
|
||||||
TerrainChunk();
|
TerrainChunk();
|
||||||
~TerrainChunk();
|
~TerrainChunk();
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ SOFTWARE.
|
|||||||
|
|
||||||
#include "core/version.h"
|
#include "core/version.h"
|
||||||
|
|
||||||
|
#include "core/message_queue.h"
|
||||||
#include "terrain_chunk.h"
|
#include "terrain_chunk.h"
|
||||||
#include "terrain_structure.h"
|
#include "terrain_structure.h"
|
||||||
|
|
||||||
@ -291,11 +292,14 @@ Ref<TerrainChunk> TerrainWorld::chunk_get(const int x, const int z) {
|
|||||||
Ref<TerrainChunk> TerrainWorld::chunk_remove(const int x, const int z) {
|
Ref<TerrainChunk> TerrainWorld::chunk_remove(const int x, const int z) {
|
||||||
IntPos pos(x, z);
|
IntPos pos(x, z);
|
||||||
|
|
||||||
if (!_chunks.has(pos))
|
if (!_chunks.has(pos)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Ref<TerrainChunk> chunk = _chunks.get(pos);
|
Ref<TerrainChunk> chunk = _chunks.get(pos);
|
||||||
|
|
||||||
|
chunk->exit_tree();
|
||||||
|
|
||||||
for (int i = 0; i < _chunks_vector.size(); ++i) {
|
for (int i = 0; i < _chunks_vector.size(); ++i) {
|
||||||
if (_chunks_vector.get(i) == chunk) {
|
if (_chunks_vector.get(i) == chunk) {
|
||||||
_chunks_vector.VREMOVE(i);
|
_chunks_vector.VREMOVE(i);
|
||||||
@ -303,7 +307,14 @@ Ref<TerrainChunk> TerrainWorld::chunk_remove(const int x, const int z) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk->exit_tree();
|
_generation_queue.erase(chunk);
|
||||||
|
|
||||||
|
if (chunk->get_is_generating()) {
|
||||||
|
chunk->cancel_build();
|
||||||
|
}
|
||||||
|
|
||||||
|
//never remove from this here
|
||||||
|
//_generating.erase(chunk);
|
||||||
|
|
||||||
_chunks.erase(pos);
|
_chunks.erase(pos);
|
||||||
|
|
||||||
@ -315,9 +326,18 @@ Ref<TerrainChunk> TerrainWorld::chunk_remove_index(const int index) {
|
|||||||
ERR_FAIL_INDEX_V(index, _chunks_vector.size(), NULL);
|
ERR_FAIL_INDEX_V(index, _chunks_vector.size(), NULL);
|
||||||
|
|
||||||
Ref<TerrainChunk> chunk = _chunks_vector.get(index);
|
Ref<TerrainChunk> chunk = _chunks_vector.get(index);
|
||||||
|
chunk->exit_tree();
|
||||||
|
|
||||||
_chunks_vector.VREMOVE(index);
|
_chunks_vector.VREMOVE(index);
|
||||||
_chunks.erase(IntPos(chunk->get_position_x(), chunk->get_position_z()));
|
_chunks.erase(IntPos(chunk->get_position_x(), chunk->get_position_z()));
|
||||||
chunk->exit_tree();
|
_generation_queue.erase(chunk);
|
||||||
|
|
||||||
|
if (chunk->get_is_generating()) {
|
||||||
|
chunk->cancel_build();
|
||||||
|
}
|
||||||
|
|
||||||
|
//never remove from this here
|
||||||
|
//_generating.erase(chunk);
|
||||||
|
|
||||||
emit_signal("chunk_removed", chunk);
|
emit_signal("chunk_removed", chunk);
|
||||||
|
|
||||||
@ -343,11 +363,19 @@ void TerrainWorld::chunks_clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_chunks_vector.clear();
|
_chunks_vector.clear();
|
||||||
|
|
||||||
_chunks.clear();
|
_chunks.clear();
|
||||||
|
|
||||||
_generation_queue.clear();
|
_generation_queue.clear();
|
||||||
_generating.clear();
|
|
||||||
|
for (int i = 0; i < _generating.size(); ++i) {
|
||||||
|
Ref<TerrainChunk> chunk = _generating[i];
|
||||||
|
|
||||||
|
if (chunk->get_is_generating()) {
|
||||||
|
chunk->cancel_build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//never remove from this here
|
||||||
|
//_generating.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<TerrainChunk> TerrainWorld::chunk_get_or_create(int x, int z) {
|
Ref<TerrainChunk> TerrainWorld::chunk_get_or_create(int x, int z) {
|
||||||
@ -433,7 +461,16 @@ void TerrainWorld::chunks_set(const Vector<Variant> &chunks) {
|
|||||||
if (chunks.find(chunk) == -1) {
|
if (chunks.find(chunk) == -1) {
|
||||||
chunk_remove_index(i);
|
chunk_remove_index(i);
|
||||||
_generation_queue.erase(chunk);
|
_generation_queue.erase(chunk);
|
||||||
_generating.erase(chunk);
|
|
||||||
|
chunk->exit_tree();
|
||||||
|
|
||||||
|
if (chunk->get_is_generating()) {
|
||||||
|
chunk->cancel_build();
|
||||||
|
}
|
||||||
|
|
||||||
|
//never remove from this here
|
||||||
|
//_generating.erase(chunk);
|
||||||
|
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -963,7 +1000,19 @@ void TerrainWorld::_notification(int p_what) {
|
|||||||
for (int i = 0; i < _generating.size(); ++i) {
|
for (int i = 0; i < _generating.size(); ++i) {
|
||||||
Ref<TerrainChunk> chunk = _generating.get(i);
|
Ref<TerrainChunk> chunk = _generating.get(i);
|
||||||
|
|
||||||
if (!chunk.is_valid() || !chunk->get_is_generating()) {
|
if (!chunk.is_valid()) {
|
||||||
|
_generating.VREMOVE(i);
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chunk->get_is_generating()) {
|
||||||
|
_generating.VREMOVE(i);
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunk->is_build_aborted() && chunk->is_safe_to_delete()) {
|
||||||
_generating.VREMOVE(i);
|
_generating.VREMOVE(i);
|
||||||
--i;
|
--i;
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user