diff --git a/modules/terraman/editor/terrain_world_editor.cpp b/modules/terraman/editor/terrain_world_editor.cpp index 9601fc6c2..d731160e3 100644 --- a/modules/terraman/editor/terrain_world_editor.cpp +++ b/modules/terraman/editor/terrain_world_editor.cpp @@ -48,6 +48,7 @@ #include "core/os/keyboard.h" +#include "../data/terrain_light.h" #include "../world/terrain_chunk.h" #include "../library/terrain_library.h" @@ -78,6 +79,10 @@ #include "modules/mesh_data_resource/nodes/mesh_data_instance.h" #endif +#ifdef MODULE_VERTEX_LIGHTS_3D_ENABLED +#include "modules/vertex_lights_3d/vertex_light_3d.h" +#endif + EditorPlugin::AfterGUIInput TerrainWorldEditor::forward_spatial_input_event(Camera *p_camera, const Ref &p_event) { if (!_world || !_world->get_editable()) { return EditorPlugin::AFTER_GUI_INPUT_PASS; @@ -1143,7 +1148,7 @@ TerrainWorldEditor::TerrainWorldEditor(EditorNode *p_editor) { un_bake_scenes_button->connect("pressed", this, "_on_un_bake_scenes_button_pressed"); _baking_tools_tool_container->add_child(un_bake_scenes_button); -// Baking Tools - MeshDataInstances + // Baking Tools - MeshDataInstances #ifdef MODULE_MESH_DATA_RESOURCE_ENABLED Label *bake_mdis_label = memnew(Label); bake_mdis_label->set_align(Label::ALIGN_CENTER); @@ -1152,7 +1157,7 @@ TerrainWorldEditor::TerrainWorldEditor(EditorNode *p_editor) { Button *bake_mdis_button = memnew(Button); bake_mdis_button->set_text(TTR("Bake Mesh Data Instances")); - bake_mdis_button->set_tooltip(TTR("Takes the current world's direct child MeshDataInstances, adds them directly as props and delets them.\nThe ones that have a script attached will be skipped. Node names will be remembered.")); + bake_mdis_button->set_tooltip(TTR("Takes the current world's direct child MeshDataInstances, adds them directly as MeshDataInstances and deletes them.\nThe ones that have a script attached will be skipped. Node names will be remembered.")); bake_mdis_button->connect("pressed", this, "_on_bake_mdis_button_pressed"); _baking_tools_tool_container->add_child(bake_mdis_button); @@ -1164,7 +1169,24 @@ TerrainWorldEditor::TerrainWorldEditor(EditorNode *p_editor) { #endif // Baking Tools - VertexLights - // TODO +#ifdef MODULE_VERTEX_LIGHTS_3D_ENABLED + Label *bake_vertex_lights_label = memnew(Label); + bake_vertex_lights_label->set_align(Label::ALIGN_CENTER); + bake_vertex_lights_label->set_text(TTR("Vertex Lights")); + _baking_tools_tool_container->add_child(bake_vertex_lights_label); + + Button *bake_vertex_lights_button = memnew(Button); + bake_vertex_lights_button->set_text(TTR("Bake Vertex Lights")); + bake_vertex_lights_button->set_tooltip(TTR("Takes the current world's direct child VertexLights, adds them as lights and deletes them.\nThe ones that have a script attached will be skipped. Node names will be remembered.")); + bake_vertex_lights_button->connect("pressed", this, "_on_bake_vertex_lights_button_pressed"); + _baking_tools_tool_container->add_child(bake_vertex_lights_button); + + Button *un_bake_vertex_lights_button = memnew(Button); + un_bake_vertex_lights_button->set_text(TTR("Un-Bake Vertex Lights")); + un_bake_vertex_lights_button->set_tooltip(TTR("Takes the owned lights stored in the current world, makes VertexLights from them, and removes them from world.")); + un_bake_vertex_lights_button->connect("pressed", this, "_on_un_bake_vertex_lights_button_pressed"); + _baking_tools_tool_container->add_child(un_bake_vertex_lights_button); +#endif // Baking Tools - Props #ifdef MODULE_PROPS_ENABLED @@ -1175,7 +1197,7 @@ TerrainWorldEditor::TerrainWorldEditor(EditorNode *p_editor) { Button *bake_props_button = memnew(Button); bake_props_button->set_text(TTR("Bake Props")); - bake_props_button->set_tooltip(TTR("Takes the current world's direct child PropInstanceMergers, adds them directly as props and delets them.\nThe ones that have a script attached will be skipped. Node names will be remembered.")); + bake_props_button->set_tooltip(TTR("Takes the current world's direct child PropInstanceMergers, adds them directly as props and deletes them.\nThe ones that have a script attached will be skipped. Node names will be remembered.")); bake_props_button->connect("pressed", this, "_on_bake_props_button_pressed"); _baking_tools_tool_container->add_child(bake_props_button); @@ -1704,6 +1726,9 @@ void TerrainWorldEditor::bake_mdis(const ObjectID p_world) { continue; } + // todo check if it has children + + // this is not needed bool editable = EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(mdi); if (editable) { @@ -1789,6 +1814,113 @@ void TerrainWorldEditor::un_bake_mdis(const ObjectID p_world) { #endif } +void TerrainWorldEditor::bake_vertex_lights(const ObjectID p_world) { +#ifdef MODULE_VERTEX_LIGHTS_3D_ENABLED + TerrainWorld *world = ObjectDB::get_instance(p_world); + + if (!world) { + return; + } + + int baked_vl_count = 0; + int skipped_vl_disabled_count = 0; + int skipped_vl_having_children_count = 0; + + for (int i = 0; i < world->get_child_count(); ++i) { + VertexLight3D *vl = Object::cast_to(world->get_child(i)); + + if (!vl) { + continue; + } + + if (vl->get_child_count() > 0) { + ++skipped_vl_having_children_count; + continue; + } + + if (!vl->get_is_enabled()) { + ++skipped_vl_disabled_count; + continue; + } + + Transform t = vl->get_global_transform(); + + Ref light; + light.instance(); + + Vector3i wdp = world->world_position_to_world_data_position_3d(t.xform(Vector3())); + light->set_world_data_position(wdp); + + light->set_name(vl->get_name()); + light->set_range(vl->get_range()); + light->set_attenuation(vl->get_attenuation()); + light->set_color(vl->get_color()); + light->set_light_mode((TerrainLight::LightMode)((int)vl->get_mode())); + light->set_item_cull_mask(vl->get_item_cull_mask()); + + vl->queue_delete(); + + ++baked_vl_count; + + world->light_add(light); + } + + String results = "Baked " + String::num_int64(baked_vl_count) + " direct child VertexLight3D into TerrainWorld.\n"; + results += String::num_int64(skipped_vl_having_children_count) + " were skipped due to them having children.\n"; + results += String::num_int64(skipped_vl_disabled_count) + " were skipped due to them not being enabled."; + + print_line(results); +#endif +} +void TerrainWorldEditor::un_bake_vertex_lights(const ObjectID p_world) { +#ifdef MODULE_VERTEX_LIGHTS_3D_ENABLED + TerrainWorld *world = ObjectDB::get_instance(p_world); + + if (!world) { + return; + } + + int un_baked_vl_count = 0; + + for (int i = 0; i < world->chunk_get_count(); ++i) { + Ref chunk = world->chunk_get_index(i); + + for (int j = 0; j < chunk->light_get_count(); ++j) { + Ref light = chunk->light_get_index(j); + + if (light->get_owner_type() != TerrainLight::OWNER_TYPE_NONE) { + continue; + } + + chunk->light_remove_index(j); + --j; + + VertexLight3D *vl = memnew(VertexLight3D); + + vl->set_name(light->get_name()); + vl->set_range(light->get_range()); + vl->set_attenuation(light->get_attenuation()); + vl->set_color(light->get_color()); + vl->set_mode((VertexLight3D::VertexLight3DMode)((int)light->get_light_mode())); + vl->set_item_cull_mask(light->get_item_cull_mask()); + + Transform t; + t.set_origin(world->world_data_position_to_world_position_3d(light->get_world_data_position())); + vl->set_transform(t); + + world->add_child(vl); + vl->set_owner(_editor->get_edited_scene()); + + ++un_baked_vl_count; + } + } + + String results = "Un-Baked " + String::num_int64(un_baked_vl_count) + " direct child VertexLight3D Instances from TerrainWorld."; + + print_line(results); +#endif +} + void TerrainWorldEditor::create_chunk_removed_undo_point() { if (!_world) { return; @@ -2107,6 +2239,31 @@ void TerrainWorldEditor::_on_un_bake_mdis_button_pressed() { _undo_redo->commit_action(); } +void TerrainWorldEditor::_on_bake_vertex_lights_button_pressed() { + if (!_world) { + return; + } + + ObjectID world = _world->get_instance_id(); + + _undo_redo->create_action(TTR("Bake Vertex Lights")); + _undo_redo->add_do_method(this, "bake_vertex_lights", world); + _undo_redo->add_undo_method(this, "un_bake_vertex_lights", world); + _undo_redo->commit_action(); +} +void TerrainWorldEditor::_on_un_bake_vertex_lights_button_pressed() { + if (!_world) { + return; + } + + ObjectID world = _world->get_instance_id(); + + _undo_redo->create_action(TTR("Bake Vertex Lights")); + _undo_redo->add_do_method(this, "un_bake_vertex_lights", world); + _undo_redo->add_undo_method(this, "bake_vertex_lights", world); + _undo_redo->commit_action(); +} + void TerrainWorldEditor::_bind_methods() { ClassDB::bind_method("_node_removed", &TerrainWorldEditor::_node_removed); @@ -2156,6 +2313,13 @@ void TerrainWorldEditor::_bind_methods() { ClassDB::bind_method("bake_mdis", &TerrainWorldEditor::bake_mdis); ClassDB::bind_method("un_bake_mdis", &TerrainWorldEditor::un_bake_mdis); + + // Vertex Lights + ClassDB::bind_method("_on_bake_vertex_lights_button_pressed", &TerrainWorldEditor::_on_bake_vertex_lights_button_pressed); + ClassDB::bind_method("_on_un_bake_vertex_lights_button_pressed", &TerrainWorldEditor::_on_un_bake_vertex_lights_button_pressed); + + ClassDB::bind_method("bake_vertex_lights", &TerrainWorldEditor::bake_vertex_lights); + ClassDB::bind_method("un_bake_vertex_lights", &TerrainWorldEditor::un_bake_vertex_lights); } void TerrainWorldEditorPlugin::_notification(int p_what) { diff --git a/modules/terraman/editor/terrain_world_editor.h b/modules/terraman/editor/terrain_world_editor.h index 401b1fdc3..f5c853a8f 100644 --- a/modules/terraman/editor/terrain_world_editor.h +++ b/modules/terraman/editor/terrain_world_editor.h @@ -108,6 +108,9 @@ protected: void bake_mdis(const ObjectID p_world); void un_bake_mdis(const ObjectID p_world); + void bake_vertex_lights(const ObjectID p_world); + void un_bake_vertex_lights(const ObjectID p_world); + protected: static void _bind_methods(); void _notification(int p_what); @@ -141,6 +144,9 @@ protected: void _on_bake_mdis_button_pressed(); void _on_un_bake_mdis_button_pressed(); + void _on_bake_vertex_lights_button_pressed(); + void _on_un_bake_vertex_lights_button_pressed(); + private: UndoRedo *_undo_redo; bool _mouse_down;