mirror of
https://github.com/Relintai/terraman.git
synced 2025-04-25 21:45:00 +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() {
|
||||
TerrainChunk::_exit_tree();
|
||||
|
||||
rids_free();
|
||||
if (!_is_generating) {
|
||||
rids_free();
|
||||
rids_clear();
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainChunkDefault::_world_transform_changed() {
|
||||
@ -874,6 +877,9 @@ TerrainChunkDefault::~TerrainChunkDefault() {
|
||||
_lights.clear();
|
||||
|
||||
debug_mesh_free();
|
||||
|
||||
rids_free();
|
||||
rids_clear();
|
||||
}
|
||||
|
||||
void TerrainChunkDefault::_channel_setup() {
|
||||
|
@ -28,6 +28,7 @@ SOFTWARE.
|
||||
|
||||
#include "../defines.h"
|
||||
|
||||
#include "core/message_queue.h"
|
||||
#include "jobs/terrain_job.h"
|
||||
#include "terrain_structure.h"
|
||||
|
||||
@ -65,6 +66,10 @@ _FORCE_INLINE_ void TerrainChunk::set_is_generating(const bool value) {
|
||||
_is_generating = value;
|
||||
}
|
||||
|
||||
bool TerrainChunk::is_build_aborted() const {
|
||||
return _abort_build;
|
||||
}
|
||||
|
||||
bool TerrainChunk::is_in_tree() const {
|
||||
return _is_in_tree;
|
||||
}
|
||||
@ -268,6 +273,12 @@ int TerrainChunk::job_get_current_index() {
|
||||
return _current_job;
|
||||
}
|
||||
void TerrainChunk::job_next() {
|
||||
if (_abort_build) {
|
||||
_is_generating = false;
|
||||
_current_job = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
++_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() {
|
||||
if (has_method("_bake_lights"))
|
||||
call("_bake_lights");
|
||||
@ -966,12 +993,6 @@ void TerrainChunk::enter_tree() {
|
||||
void TerrainChunk::exit_tree() {
|
||||
_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"))
|
||||
call("_exit_tree");
|
||||
}
|
||||
@ -1026,6 +1047,24 @@ Vector3 TerrainChunk::to_global(Vector3 p_local) const {
|
||||
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() {
|
||||
_is_processing = false;
|
||||
_is_phisics_processing = false;
|
||||
@ -1110,7 +1149,9 @@ void TerrainChunk::_enter_tree() {
|
||||
}
|
||||
|
||||
void TerrainChunk::_exit_tree() {
|
||||
_abort_build = true;
|
||||
if (_is_generating) {
|
||||
cancel_build();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _jobs.size(); ++i) {
|
||||
Ref<TerrainJob> j = _jobs[i];
|
||||
@ -1119,9 +1160,19 @@ void TerrainChunk::_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) {
|
||||
if (_abort_build) {
|
||||
return;
|
||||
}
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
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) {
|
||||
if (_abort_build) {
|
||||
return;
|
||||
}
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
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("cancel_build"), &TerrainChunk::cancel_build);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_process"), &TerrainChunk::get_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);
|
||||
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("set_dirty", "value"), &TerrainChunk::set_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_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;
|
||||
void set_is_generating(const bool value);
|
||||
|
||||
bool is_build_aborted() const;
|
||||
|
||||
bool is_in_tree() const;
|
||||
|
||||
bool get_dirty() const;
|
||||
@ -222,6 +224,7 @@ public:
|
||||
void build();
|
||||
void clear();
|
||||
void finalize_build();
|
||||
void cancel_build();
|
||||
|
||||
void _build();
|
||||
|
||||
@ -304,6 +307,8 @@ public:
|
||||
Vector3 to_local(Vector3 p_global) const;
|
||||
Vector3 to_global(Vector3 p_local) const;
|
||||
|
||||
bool is_safe_to_delete();
|
||||
|
||||
TerrainChunk();
|
||||
~TerrainChunk();
|
||||
|
||||
|
@ -24,6 +24,7 @@ SOFTWARE.
|
||||
|
||||
#include "core/version.h"
|
||||
|
||||
#include "core/message_queue.h"
|
||||
#include "terrain_chunk.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) {
|
||||
IntPos pos(x, z);
|
||||
|
||||
if (!_chunks.has(pos))
|
||||
if (!_chunks.has(pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Ref<TerrainChunk> chunk = _chunks.get(pos);
|
||||
|
||||
chunk->exit_tree();
|
||||
|
||||
for (int i = 0; i < _chunks_vector.size(); ++i) {
|
||||
if (_chunks_vector.get(i) == chunk) {
|
||||
_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);
|
||||
|
||||
@ -315,9 +326,18 @@ Ref<TerrainChunk> TerrainWorld::chunk_remove_index(const int index) {
|
||||
ERR_FAIL_INDEX_V(index, _chunks_vector.size(), NULL);
|
||||
|
||||
Ref<TerrainChunk> chunk = _chunks_vector.get(index);
|
||||
chunk->exit_tree();
|
||||
|
||||
_chunks_vector.VREMOVE(index);
|
||||
_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);
|
||||
|
||||
@ -343,11 +363,19 @@ void TerrainWorld::chunks_clear() {
|
||||
}
|
||||
|
||||
_chunks_vector.clear();
|
||||
|
||||
_chunks.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) {
|
||||
@ -433,7 +461,16 @@ void TerrainWorld::chunks_set(const Vector<Variant> &chunks) {
|
||||
if (chunks.find(chunk) == -1) {
|
||||
chunk_remove_index(i);
|
||||
_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;
|
||||
}
|
||||
}
|
||||
@ -963,7 +1000,19 @@ void TerrainWorld::_notification(int p_what) {
|
||||
for (int i = 0; i < _generating.size(); ++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);
|
||||
--i;
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user