diff --git a/register_types.cpp b/register_types.cpp index 3b6ab82..89514e9 100644 --- a/register_types.cpp +++ b/register_types.cpp @@ -6,6 +6,7 @@ #include "terrain/terrain_modifier.h" #include "terrain/terrain_modifier_composite.h" #include "terrain/terrain_modifier_distance.h" +#include "terrain/terrain_modifier_noise.h" #include "terrain/terrain_modifier_path.h" void initialize_terrain_module(ModuleInitializationLevel p_level) { @@ -17,6 +18,7 @@ void initialize_terrain_module(ModuleInitializationLevel p_level) { ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); } diff --git a/terrain_modifier_noise.cpp b/terrain_modifier_noise.cpp new file mode 100644 index 0000000..355f9d2 --- /dev/null +++ b/terrain_modifier_noise.cpp @@ -0,0 +1,52 @@ +#include "terrain_modifier_noise.h" +#include "core/math/math_defs.h" +#include "macros.h" + +void TerrainModifierNoise::_bind_methods() { + BIND_HPROPERTY(Variant::OBJECT, noise, PROPERTY_HINT_RESOURCE_TYPE, "Noise"); + BIND_PROPERTY(Variant::FLOAT, noise_amplitude); +} + +void TerrainModifierNoise::push_changed_all() { + push_changed(get_bounds()); +} + +void TerrainModifierNoise::noise_changed() { + { + SharedMutex::LockExclusive exclusive{ this->lock }; + this->noise_buffer = this->noise->duplicate_deep(); + } + push_changed_all(); +} + +float TerrainModifierNoise::evaluate_at(Vector2 world_coordinates, float before) { + SharedMutex::LockShared shared{ this->lock }; + if (this->noise.is_null()) { + return before; + } + return 0.5f * this->noise_amplitude * (this->noise_buffer->get_noise_2d(world_coordinates.x, world_coordinates.y) + 1.f) + before; +} + +void TerrainModifierNoise::set_noise(Ref noise) { + { + SharedMutex::LockExclusive exclusive{ this->lock }; + if (noise == this->noise) { + return; + } + if (this->noise.is_valid()) { + this->noise->disconnect_changed(callable_mp(this, &self_type::noise_changed)); + } + if (noise.is_valid()) { + noise->connect_changed(callable_mp(this, &self_type::noise_changed)); + set_bounds({ { -Math::INF, -Math::INF }, { Math::INF, Math::INF } }); + } else { + set_bounds({ { 0, 0 }, { 0, 0 } }); + } + this->noise = noise; + } + noise_changed(); +} + +Ref TerrainModifierNoise::get_noise() const { + return this->noise; +} diff --git a/terrain_modifier_noise.h b/terrain_modifier_noise.h new file mode 100644 index 0000000..752bf0a --- /dev/null +++ b/terrain_modifier_noise.h @@ -0,0 +1,27 @@ +#pragma once + +#include "macros.h" +#include "modules/noise/noise.h" +#include "terrain/shared_mutex.h" +#include "terrain/terrain_modifier.h" + +class TerrainModifierNoise : public TerrainModifier { + GDCLASS(TerrainModifierNoise, TerrainModifier); + static void _bind_methods(); + void push_changed_all(); + void noise_changed(); + +public: + float evaluate_at(Vector2 world_coordinates, float before) override; + +private: + SharedMutex lock{}; + Ref noise{}; + Ref noise_buffer{}; + float noise_amplitude{ 1.f }; + +public: + void set_noise(Ref noise); + Ref get_noise() const; + GET_SET_FNS_EX(float, noise_amplitude, push_changed_all()); +};