Implemented Bake Props tool for TerrainWorldEditor.

This commit is contained in:
Relintai 2025-04-04 01:14:53 +02:00
parent 5d3aa83ffa
commit 474ab893d6
2 changed files with 166 additions and 0 deletions

View File

@ -65,6 +65,13 @@
#include "scene/gui/slider.h"
#include "scene/gui/spin_box.h"
#include "modules/modules_enabled.gen.h"
#ifdef MODULE_PROPS_ENABLED
#include "modules/props/prop_instance_merger.h"
#include "modules/props/props/prop_data.h"
#endif
EditorPlugin::AfterGUIInput TerrainWorldEditor::forward_spatial_input_event(Camera *p_camera, const Ref<InputEvent> &p_event) {
if (!_world || !_world->get_editable()) {
return EditorPlugin::AFTER_GUI_INPUT_PASS;
@ -1112,6 +1119,21 @@ TerrainWorldEditor::TerrainWorldEditor(EditorNode *p_editor) {
baking_tools_label->set_text(TTR("Baking Tools"));
_baking_tools_tool_container->add_child(baking_tools_label);
Label *bake_props_label = memnew(Label);
bake_props_label->set_align(Label::ALIGN_CENTER);
bake_props_label->set_text(TTR("Props"));
_baking_tools_tool_container->add_child(bake_props_label);
Button *bake_props_button = memnew(Button);
bake_props_button->set_text(TTR("Bake Props"));
bake_props_button->connect("pressed", this, "_on_bake_props_button_pressed");
_baking_tools_tool_container->add_child(bake_props_button);
Button *un_bake_props_button = memnew(Button);
un_bake_props_button->set_text(TTR("Un-Bake Props"));
un_bake_props_button->connect("pressed", this, "_on_un_bake_props_button_pressed");
_baking_tools_tool_container->add_child(un_bake_props_button);
// Surface Selector Separator
main_container->add_child(memnew(HSeparator));
@ -1384,6 +1406,113 @@ void TerrainWorldEditor::create_chunk_created_undo_point() {
_created_chunks.clear();
}
void TerrainWorldEditor::bake_props(const ObjectID p_world) {
TerrainWorld *world = ObjectDB::get_instance<TerrainWorld>(p_world);
if (!world) {
return;
}
int baked_props_count = 0;
int skipped_props_count = 0;
for (int i = 0; i < world->get_child_count(); ++i) {
PropInstanceMerger *prop_instance = Object::cast_to<PropInstanceMerger>(world->get_child(i));
if (!prop_instance) {
continue;
}
if (!prop_instance->get_script().is_null()) {
++skipped_props_count;
continue;
}
Ref<PropData> pd = prop_instance->get_prop_data();
Transform t = prop_instance->get_global_transform();
prop_instance->queue_delete();
++baked_props_count;
if (!pd.is_valid()) {
continue;
}
world->prop_add(t, pd, false);
}
String results = "Baked " + String::num_int64(baked_props_count) + " direct child props into TerrainWorld. ";
results += String::num_int64(skipped_props_count) + "were skipped (they had scripts).";
print_line(results);
}
void TerrainWorldEditor::un_bake_props(const ObjectID p_world) {
TerrainWorld *world = ObjectDB::get_instance<TerrainWorld>(p_world);
if (!world) {
return;
}
int un_baked_props_count = 0;
for (int i = 0; i < world->chunk_get_count(); ++i) {
Ref<TerrainChunk> chunk = world->chunk_get_index(i);
for (int j = 0; j < chunk->prop_get_count(); ++j) {
if (!chunk->prop_get_is_original(j)) {
continue;
}
Ref<PropData> pd = chunk->prop_get(j);
Transform t = chunk->prop_get_transform(j);
PropInstanceMerger *prop_instance = memnew(PropInstanceMerger);
prop_instance->set_global_transform(t);
prop_instance->set_prop_data(pd);
world->add_child(prop_instance);
prop_instance->set_owner(_editor->get_edited_scene());
++un_baked_props_count;
}
chunk->props_clear();
for (int j = 0; j < chunk->light_get_count(); ++j) {
Ref<TerrainLight> light = chunk->light_get_index(j);
if (light->get_owner_type() == TerrainLight::OWNER_TYPE_PROP) {
chunk->light_remove_index(j);
--j;
}
}
for (int j = 0; j < chunk->scene_get_count(); ++j) {
if (!chunk->scene_get_is_original(j)) {
chunk->scene_remove(j);
--j;
}
}
#ifdef MODULE_MESH_DATA_RESOURCE_ENABLED
for (int j = 0; j < chunk->mesh_data_resource_get_count(); ++j) {
if (!chunk->mesh_data_resource_get_is_original(j)) {
chunk->mesh_data_resource_remove(j);
--j;
}
}
#endif
chunk->build();
}
String results = "Un-Baked " + String::num_int64(un_baked_props_count) + " direct child props into TerrainWorld.";
print_line(results);
}
void TerrainWorldEditor::create_chunk_removed_undo_point() {
if (!_world) {
return;
@ -1627,6 +1756,31 @@ void TerrainWorldEditor::_on_chunk_remove_brush_size_slider_changed(float value)
}
}
void TerrainWorldEditor::_on_bake_props_button_pressed() {
if (!_world) {
return;
}
ObjectID world = _world->get_instance_id();
_undo_redo->create_action(TTR("Bake Props"));
_undo_redo->add_do_method(this, "bake_props", world);
_undo_redo->add_undo_method(this, "un_bake_props", world);
_undo_redo->commit_action();
}
void TerrainWorldEditor::_on_un_bake_props_button_pressed() {
if (!_world) {
return;
}
ObjectID world = _world->get_instance_id();
_undo_redo->create_action(TTR("Bake Props"));
_undo_redo->add_do_method(this, "un_bake_props", world);
_undo_redo->add_undo_method(this, "bake_props", world);
_undo_redo->commit_action();
}
void TerrainWorldEditor::_bind_methods() {
ClassDB::bind_method("_node_removed", &TerrainWorldEditor::_node_removed);
@ -1655,6 +1809,12 @@ void TerrainWorldEditor::_bind_methods() {
ClassDB::bind_method("undo_chunk_added_action", &TerrainWorldEditor::undo_chunk_added_action);
ClassDB::bind_method("do_chunk_removed_action", &TerrainWorldEditor::do_chunk_removed_action);
ClassDB::bind_method("undo_chunk_removed_action", &TerrainWorldEditor::undo_chunk_removed_action);
ClassDB::bind_method("_on_bake_props_button_pressed", &TerrainWorldEditor::_on_bake_props_button_pressed);
ClassDB::bind_method("_on_un_bake_props_button_pressed", &TerrainWorldEditor::_on_un_bake_props_button_pressed);
ClassDB::bind_method("bake_props", &TerrainWorldEditor::bake_props);
ClassDB::bind_method("un_bake_props", &TerrainWorldEditor::un_bake_props);
}
void TerrainWorldEditorPlugin::_notification(int p_what) {

View File

@ -99,6 +99,9 @@ protected:
HashMap<Vector2i, Ref<TerrainChunk>> _created_chunks;
HashMap<Vector2i, Ref<TerrainChunk>> _removed_chunks;
void bake_props(const ObjectID p_world);
void un_bake_props(const ObjectID p_world);
protected:
static void _bind_methods();
void _notification(int p_what);
@ -123,6 +126,9 @@ protected:
void _on_chunk_spawn_brush_size_slider_changed(float value);
void _on_chunk_remove_brush_size_slider_changed(float value);
void _on_bake_props_button_pressed();
void _on_un_bake_props_button_pressed();
private:
UndoRedo *_undo_redo;
bool _mouse_down;