feat: bounds-based mesh reloading

This commit is contained in:
Sara Gerretsen 2026-02-25 22:02:02 +01:00
parent 953e4abe5b
commit 226c821454
7 changed files with 93 additions and 38 deletions

View file

@ -2,12 +2,12 @@
#include "core/config/engine.h"
#include "core/variant/variant.h"
#include "macros.h"
#include "terrain/terrain.h"
#include <algorithm>
void TerrainModifier::_bind_methods() {
BIND_HPROPERTY(Variant::INT, blend_mode, PROPERTY_HINT_ENUM, BlendMode_hint());
BIND_PROPERTY(Variant::FLOAT, blend_distance);
ADD_SIGNAL(MethodInfo(sig_changed));
}
void TerrainModifier::_notification(int what) {
@ -20,9 +20,6 @@ void TerrainModifier::_notification(int what) {
}
this->thread_safe_global_position = get_global_position();
case NOTIFICATION_TRANSFORM_CHANGED:
if (Engine::get_singleton()->is_editor_hint()) {
emit_signal(sig_changed);
}
this->thread_safe_global_position = get_global_position();
return;
}
@ -56,13 +53,10 @@ float TerrainModifier::blend(float under, float over) {
}
}
void TerrainModifier::changed() {
this->dirty = true;
emit_signal(sig_changed);
}
void TerrainModifier::changed_deferred() {
callable_mp(this, &self_type::changed).call_deferred();
void TerrainModifier::push_changed(Rect2 area) {
if (this->terrain) {
this->terrain->push_changed(area);
}
}
float TerrainModifier::evaluate_at(Vector2 world_coordinate, float before) {
@ -77,7 +71,6 @@ Vector3 TerrainModifier::get_thread_safe_global_position() const {
void TerrainModifier::set_blend_distance(float value) {
this->blend_distance = value;
emit_signal(sig_changed);
}
float TerrainModifier::get_blend_distance() const {
@ -86,15 +79,12 @@ float TerrainModifier::get_blend_distance() const {
void TerrainModifier::set_blend_mode(BlendMode mode) {
this->blend_mode = mode;
emit_signal(sig_changed);
}
TerrainModifier::BlendMode TerrainModifier::get_blend_mode() const {
return this->blend_mode;
}
String const TerrainModifier::sig_changed{ "changed" };
void SharedMutex::lock_shared() {
this->lock.lock();
this->shared_count++;
@ -127,15 +117,60 @@ void TerrainModifierDistance::_bind_methods() {
}
void TerrainModifierDistance::curves_changed() {
this->lock.lock_shared();
this->lock.lock_exclusive();
if (this->distance_height_curve.is_valid()) {
this->distance_height_curve->bake();
}
if (this->distance_weight_curve.is_valid()) {
this->distance_weight_curve->bake();
}
this->lock.unlock_exclusive();
if (!update_bounds()) {
push_changed(get_bounds());
}
}
bool TerrainModifierDistance::update_bounds() {
Rect2 const before{ get_bounds() };
Rect2 bounds{};
Vector3 position{ get_thread_safe_global_position() };
bounds.position = { position.x, position.z };
bounds.size = { 0, 0 };
this->lock.lock_shared();
if (this->distance_weight_curve.is_valid()) {
float const max_radius{ this->distance_weight_curve->get_max_domain() };
float const max_diameter{ 2.f * max_radius };
bounds.size = { max_diameter, max_diameter };
bounds.position -= { max_radius, max_radius };
}
this->lock.unlock_shared();
changed();
this->lock.lock_exclusive();
bool const changed{ before != bounds };
if (changed) {
set_bounds(bounds);
push_changed(before);
push_changed(bounds);
}
this->lock.unlock_exclusive();
return changed;
}
void TerrainModifierDistance::_notification(int what) {
switch (what) {
default:
return;
case NOTIFICATION_READY:
update_bounds();
set_notify_transform(true);
return;
case NOTIFICATION_TRANSFORM_CHANGED:
if (is_inside_tree()) {
if (!update_bounds()) {
push_changed(get_bounds());
}
}
return;
}
}
float TerrainModifierDistance::distance_at(Vector2 const &world_coordinate) {