feat: realtime editing
This commit is contained in:
parent
cd4f619a20
commit
fc6034242e
5 changed files with 146 additions and 12 deletions
|
|
@ -10,12 +10,17 @@ void Terrain::ready() {
|
|||
}
|
||||
|
||||
void Terrain::update_modifier_list() {
|
||||
bool editor{ Engine::get_singleton()->is_editor_hint() };
|
||||
this->modifiers.clear();
|
||||
for (Variant var : get_children()) {
|
||||
if (TerrainModifier * mod{ cast_to<TerrainModifier>(var) }) {
|
||||
if (editor && !mod->is_connected(TerrainModifier::sig_changed, callable_mp(this, &self_type::on_terrain_changed))) {
|
||||
mod->connect(TerrainModifier::sig_changed, callable_mp(this, &self_type::on_terrain_changed));
|
||||
}
|
||||
this->modifiers.push_back(mod);
|
||||
}
|
||||
}
|
||||
on_terrain_changed();
|
||||
}
|
||||
|
||||
void Terrain::child_entered(Node *node) {
|
||||
|
|
@ -27,9 +32,21 @@ void Terrain::child_entered(Node *node) {
|
|||
void Terrain::child_exiting(Node *node) {
|
||||
if (TerrainModifier * mod{ cast_to<TerrainModifier>(node) }) {
|
||||
this->modifiers.erase(mod);
|
||||
if (Engine::get_singleton()->is_editor_hint() && !is_queued_for_deletion()) {
|
||||
mod->disconnect(TerrainModifier::sig_changed, callable_mp(this, &self_type::on_terrain_changed));
|
||||
}
|
||||
|
||||
on_terrain_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::on_terrain_changed() {
|
||||
if (is_queued_for_deletion() || !is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
generate_meshes();
|
||||
}
|
||||
|
||||
void Terrain::_notification(int what) {
|
||||
switch (what) {
|
||||
default:
|
||||
|
|
@ -41,7 +58,6 @@ void Terrain::_notification(int what) {
|
|||
connect("child_order_changed", callable_mp(this, &self_type::update_modifier_list));
|
||||
}
|
||||
return;
|
||||
return;
|
||||
case NOTIFICATION_READY:
|
||||
ready();
|
||||
return;
|
||||
|
|
@ -67,6 +83,9 @@ void Terrain::construct_chunk_grid() {
|
|||
|
||||
void Terrain::generate_meshes() {
|
||||
for (TerrainChunkMesh *mesh : this->meshes) {
|
||||
if (!mesh->is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
mesh->update_mesh();
|
||||
}
|
||||
}
|
||||
|
|
@ -74,7 +93,42 @@ void Terrain::generate_meshes() {
|
|||
float Terrain::height_at(Vector2 world_coordinate) {
|
||||
float height{ 0 };
|
||||
for (TerrainModifier *mod : this->modifiers) {
|
||||
if (!mod->is_inside_tree()) {
|
||||
return height;
|
||||
}
|
||||
height = mod->evaluate_at(world_coordinate, height);
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
void Terrain::set_side_length(size_t length) {
|
||||
this->side_length = length;
|
||||
if (is_inside_tree()) {
|
||||
construct_chunk_grid();
|
||||
generate_meshes();
|
||||
}
|
||||
}
|
||||
|
||||
size_t Terrain::get_side_length() const {
|
||||
return this->side_length;
|
||||
}
|
||||
|
||||
void Terrain::set_chunk_size(size_t size) {
|
||||
this->chunk_size = size;
|
||||
if (is_inside_tree()) {
|
||||
construct_chunk_grid();
|
||||
generate_meshes();
|
||||
}
|
||||
}
|
||||
|
||||
void Terrain::set_detail(size_t detail) {
|
||||
this->detail = detail;
|
||||
if (is_inside_tree()) {
|
||||
construct_chunk_grid();
|
||||
generate_meshes();
|
||||
}
|
||||
}
|
||||
|
||||
size_t Terrain::get_detail() const {
|
||||
return this->detail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ class Terrain : public Node {
|
|||
void child_entered(Node *node);
|
||||
void child_exiting(Node *node);
|
||||
|
||||
void on_terrain_changed();
|
||||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
|
||||
|
|
@ -31,9 +33,12 @@ private:
|
|||
size_t detail{ 1 };
|
||||
|
||||
public:
|
||||
GET_SET_FNS(size_t, side_length);
|
||||
GET_SET_FNS(size_t, chunk_size);
|
||||
GET_SET_FNS(size_t, detail);
|
||||
void set_side_length(size_t length);
|
||||
size_t get_side_length() const;
|
||||
void set_chunk_size(size_t size);
|
||||
size_t get_chunk_size() const;
|
||||
void set_detail(size_t detail);
|
||||
size_t get_detail() const;
|
||||
|
||||
private:
|
||||
Vector<TerrainChunkMesh *> meshes;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "terrain_modifier.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "macros.h"
|
||||
#include <algorithm>
|
||||
|
|
@ -6,6 +7,7 @@
|
|||
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));
|
||||
}
|
||||
|
||||
float TerrainModifier::blend(float under, float over) {
|
||||
|
|
@ -36,12 +38,48 @@ float TerrainModifier::blend(float under, float over) {
|
|||
}
|
||||
}
|
||||
|
||||
void TerrainModifier::_notification(int what) {
|
||||
switch (what) {
|
||||
default:
|
||||
return;
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
set_notify_transform(true);
|
||||
}
|
||||
case NOTIFICATION_TRANSFORM_CHANGED:
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
float TerrainModifier::evaluate_at(Vector2 world_coordinate, float before) {
|
||||
Vector3 const global_position{ get_global_position() };
|
||||
world_coordinate -= { global_position.x, global_position.z };
|
||||
return blend(before, 0.0);
|
||||
}
|
||||
|
||||
void TerrainModifier::set_blend_distance(float value) {
|
||||
this->blend_distance = value;
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
|
||||
float TerrainModifier::get_blend_distance() const {
|
||||
return this->blend_distance;
|
||||
}
|
||||
|
||||
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 TerrainModifierDistance::_bind_methods() {
|
||||
BIND_HPROPERTY(Variant::OBJECT, distance_weight_curve, PROPERTY_HINT_RESOURCE_TYPE, "Curve");
|
||||
BIND_HPROPERTY(Variant::OBJECT, distance_height_curve, PROPERTY_HINT_RESOURCE_TYPE, "Curve");
|
||||
|
|
@ -77,3 +115,23 @@ PackedStringArray TerrainModifierDistance::get_configuration_warnings() const {
|
|||
}
|
||||
return warnings;
|
||||
}
|
||||
|
||||
void TerrainModifierDistance::set_distance_weight_curve(Ref<Curve> curve) {
|
||||
this->distance_weight_curve = curve;
|
||||
update_configuration_warnings();
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
|
||||
Ref<Curve> TerrainModifierDistance::get_distance_weight_curve() const {
|
||||
return this->distance_weight_curve;
|
||||
}
|
||||
|
||||
void TerrainModifierDistance::set_distance_height_curve(Ref<Curve> curve) {
|
||||
this->distance_height_curve = curve;
|
||||
update_configuration_warnings();
|
||||
emit_signal(sig_changed);
|
||||
}
|
||||
|
||||
Ref<Curve> TerrainModifierDistance::get_distance_height_curve() const {
|
||||
return this->distance_height_curve;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ public:
|
|||
GDENUM(BlendMode, Add, Subtract, Override);
|
||||
|
||||
protected:
|
||||
void _notification(int what);
|
||||
float blend(float under, float over);
|
||||
|
||||
public:
|
||||
|
|
@ -24,8 +25,12 @@ private:
|
|||
BlendMode blend_mode{ Add };
|
||||
|
||||
public:
|
||||
GET_SET_FNS(float, blend_distance);
|
||||
GET_SET_FNS(BlendMode, blend_mode);
|
||||
void set_blend_distance(float value);
|
||||
float get_blend_distance() const;
|
||||
void set_blend_mode(BlendMode mode);
|
||||
BlendMode get_blend_mode() const;
|
||||
|
||||
static String const sig_changed;
|
||||
};
|
||||
|
||||
MAKE_TYPE_INFO(TerrainModifier::BlendMode, Variant::INT);
|
||||
|
|
@ -46,6 +51,8 @@ private:
|
|||
Ref<Curve> distance_height_curve{};
|
||||
|
||||
public:
|
||||
GET_SET_FNS_EX(Ref<Curve>, distance_weight_curve, update_configuration_warnings());
|
||||
GET_SET_FNS_EX(Ref<Curve>, distance_height_curve, update_configuration_warnings());
|
||||
void set_distance_weight_curve(Ref<Curve> curve);
|
||||
Ref<Curve> get_distance_weight_curve() const;
|
||||
void set_distance_height_curve(Ref<Curve> curve);
|
||||
Ref<Curve> get_distance_height_curve() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,16 @@ _limits = [-30.0, 0.0, 0.0, 60.0]
|
|||
_data = [Vector2(0, -0.02282238), 0.0, -0.0014457313, 0, 0, Vector2(60, -30), -1.1081353, 0.0, 0, 0]
|
||||
point_count = 2
|
||||
|
||||
[sub_resource type="Curve" id="Curve_chm2y"]
|
||||
_limits = [0.0, 1.0, 0.0, 40.0]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(40, 0), 0.00012987918, -0.05797184, 0, 0]
|
||||
point_count = 2
|
||||
|
||||
[sub_resource type="Curve" id="Curve_o3i6r"]
|
||||
_limits = [-30.0, 0.0, 0.0, 60.0]
|
||||
_data = [Vector2(0, -0.02282238), 0.0, -1.6655813, 0, 0, Vector2(60, -30), -0.088242374, 0.0, 0, 0]
|
||||
point_count = 2
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_kbmr5"]
|
||||
|
||||
[node name="Node3D" type="Node3D" unique_id=289500437]
|
||||
|
|
@ -37,11 +47,11 @@ blend_distance = 4.0
|
|||
distance_weight_curve = SubResource("Curve_kbmr5")
|
||||
distance_height_curve = SubResource("Curve_w3uoq")
|
||||
|
||||
[node name="TerrainModifierDistance2" type="TerrainModifierDistance" parent="Terrain" unique_id=826291582]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -13.987091, 6.4899416, -20.878822)
|
||||
[node name="TerrainModifierDistance3" type="TerrainModifierDistance" parent="Terrain" unique_id=1846439541]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15.406048, 36.456497, -40.285374)
|
||||
blend_distance = 4.0
|
||||
distance_weight_curve = SubResource("Curve_kbmr5")
|
||||
distance_height_curve = SubResource("Curve_w3uoq")
|
||||
distance_weight_curve = SubResource("Curve_chm2y")
|
||||
distance_height_curve = SubResource("Curve_o3i6r")
|
||||
|
||||
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1089775425]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 11.772341, 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue