diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/editor_node.cpp | 34 | ||||
-rw-r--r-- | editor/import/resource_importer_texture.cpp | 30 | ||||
-rw-r--r-- | editor/plugins/ray_cast_2d_editor_plugin.cpp | 151 | ||||
-rw-r--r-- | editor/plugins/ray_cast_2d_editor_plugin.h | 79 |
4 files changed, 281 insertions, 13 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 6f3c45727a..db6bf4f816 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -172,6 +172,7 @@ #include "editor/plugins/physical_bone_3d_editor_plugin.h" #include "editor/plugins/polygon_2d_editor_plugin.h" #include "editor/plugins/polygon_3d_editor_plugin.h" +#include "editor/plugins/ray_cast_2d_editor_plugin.h" #include "editor/plugins/replication_editor_plugin.h" #include "editor/plugins/resource_preloader_editor_plugin.h" #include "editor/plugins/root_motion_editor_plugin.h" @@ -4095,22 +4096,28 @@ Ref<Texture2D> EditorNode::get_class_icon(const String &p_class, const String &p ERR_FAIL_COND_V_MSG(p_class.is_empty(), nullptr, "Class name cannot be empty."); if (ScriptServer::is_global_class(p_class)) { - Ref<ImageTexture> icon; - Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_class); - StringName name = p_class; - - while (script.is_valid()) { - name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); - String current_icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); - icon = _load_custom_class_icon(current_icon_path); + String class_name = p_class; + Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(class_name); + + while (true) { + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(class_name); + Ref<Texture> icon = _load_custom_class_icon(icon_path); if (icon.is_valid()) { - return icon; + return icon; // Current global class has icon. } - script = script->get_base_script(); - } - if (icon.is_null()) { - icon = gui_base->get_theme_icon(ScriptServer::get_global_class_base(name), SNAME("EditorIcons")); + // Find next global class along the inheritance chain. + do { + Ref<Script> base_script = script->get_base_script(); + if (base_script.is_null()) { + // We've reached a native class, use its icon. + String base_type; + script->get_language()->get_global_class_name(script->get_path(), &base_type); + return gui_base->get_theme_icon(base_type, "EditorIcons"); + } + script = base_script; + class_name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + } while (class_name.is_empty()); } } @@ -7068,6 +7075,7 @@ EditorNode::EditorNode() { add_editor_plugin(memnew(ControlEditorPlugin)); add_editor_plugin(memnew(GradientTexture2DEditorPlugin)); add_editor_plugin(memnew(BitMapEditorPlugin)); + add_editor_plugin(memnew(RayCast2DEditorPlugin)); for (int i = 0; i < EditorPlugins::get_plugin_count(); i++) { add_editor_plugin(EditorPlugins::create(i)); diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index de51a28c5a..8c038d0311 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -221,6 +221,7 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_as_srgb"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/hdr_clamp_exposure"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/size_limit", PROPERTY_HINT_RANGE, "0,4096,1"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "detect_3d/compress_to", PROPERTY_HINT_ENUM, "Disabled,VRAM Compressed,Basis Universal"), (p_preset == PRESET_DETECT) ? 1 : 0)); @@ -414,6 +415,7 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String const bool stream = false; const int size_limit = p_options["process/size_limit"]; const bool hdr_as_srgb = p_options["process/hdr_as_srgb"]; + const bool hdr_clamp_exposure = p_options["process/hdr_clamp_exposure"]; const int normal = p_options["compress/normal_map"]; const int hdr_compression = p_options["compress/hdr_compression"]; const int bptc_ldr = p_options["compress/bptc_ldr"]; @@ -485,6 +487,34 @@ Error ResourceImporterTexture::import(const String &p_source_file, const String } } + if (hdr_clamp_exposure) { + // Clamp HDR exposure following Filament's tonemapping formula. + // This can be used to reduce fireflies in environment maps or reduce the influence + // of the sun from an HDRI panorama on environment lighting (when a DirectionalLight3D is used instead). + const int height = image->get_height(); + const int width = image->get_width(); + + // These values are chosen arbitrarily and seem to produce good results with 4,096 samples. + const float linear = 4096.0; + const float compressed = 16384.0; + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + const Color color = image->get_pixel(i, j); + const float luma = color.get_luminance(); + + Color clamped_color; + if (luma <= linear) { + clamped_color = color; + } else { + clamped_color = (color / luma) * ((linear * linear - compressed * luma) / (2 * linear - compressed - luma)); + } + + image->set_pixel(i, j, clamped_color); + } + } + } + if (compress_mode == COMPRESS_BASIS_UNIVERSAL && image->get_format() >= Image::FORMAT_RF) { //basis universal does not support float formats, fall back compress_mode = COMPRESS_VRAM_COMPRESSED; diff --git a/editor/plugins/ray_cast_2d_editor_plugin.cpp b/editor/plugins/ray_cast_2d_editor_plugin.cpp new file mode 100644 index 0000000000..6f247a37ef --- /dev/null +++ b/editor/plugins/ray_cast_2d_editor_plugin.cpp @@ -0,0 +1,151 @@ +/*************************************************************************/ +/* ray_cast_2d_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "ray_cast_2d_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "editor/editor_node.h" + +void RayCast2DEditor::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + get_tree()->connect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + } break; + + case NOTIFICATION_EXIT_TREE: { + get_tree()->disconnect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed)); + } break; + } +} + +void RayCast2DEditor::_node_removed(Node *p_node) { + if (p_node == node) { + node = nullptr; + } +} + +bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { + if (!node || !node->is_visible_in_tree()) { + return false; + } + + Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) { + if (mb->is_pressed()) { + if (xform.xform(node->get_target_position()).distance_to(mb->get_position()) < 8) { + pressed = true; + original_target_position = node->get_target_position(); + + return true; + } else { + pressed = false; + + return false; + } + } else if (pressed) { + undo_redo->create_action(TTR("Set target_position")); + undo_redo->add_do_method(node, "set_target_position", node->get_target_position()); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(node, "set_target_position", original_target_position); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); + undo_redo->commit_action(); + + pressed = false; + + return true; + } + } + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && pressed) { + Vector2 point = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position())); + point = node->get_global_transform().affine_inverse().xform(point); + + node->set_target_position(point); + canvas_item_editor->update_viewport(); + node->notify_property_list_changed(); + + return true; + } + + return false; +} + +void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { + if (!node || !node->is_visible_in_tree()) { + return; + } + + Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons")); + p_overlay->draw_texture(handle, gt.xform(node->get_target_position()) - handle->get_size() / 2); +} + +void RayCast2DEditor::edit(Node *p_node) { + if (!canvas_item_editor) { + canvas_item_editor = CanvasItemEditor::get_singleton(); + } + + if (p_node) { + node = Object::cast_to<RayCast2D>(p_node); + } else { + node = nullptr; + } + + canvas_item_editor->update_viewport(); +} + +RayCast2DEditor::RayCast2DEditor() { + undo_redo = EditorNode::get_singleton()->get_undo_redo(); +} + +/////////////////////// + +void RayCast2DEditorPlugin::edit(Object *p_object) { + ray_cast_2d_editor->edit(Object::cast_to<RayCast2D>(p_object)); +} + +bool RayCast2DEditorPlugin::handles(Object *p_object) const { + return Object::cast_to<RayCast2D>(p_object) != nullptr; +} + +void RayCast2DEditorPlugin::make_visible(bool p_visible) { + if (!p_visible) { + edit(nullptr); + } +} + +RayCast2DEditorPlugin::RayCast2DEditorPlugin() { + ray_cast_2d_editor = memnew(RayCast2DEditor); + EditorNode::get_singleton()->get_gui_base()->add_child(ray_cast_2d_editor); +} diff --git a/editor/plugins/ray_cast_2d_editor_plugin.h b/editor/plugins/ray_cast_2d_editor_plugin.h new file mode 100644 index 0000000000..74628da0e4 --- /dev/null +++ b/editor/plugins/ray_cast_2d_editor_plugin.h @@ -0,0 +1,79 @@ +/*************************************************************************/ +/* ray_cast_2d_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RAY_CAST_2D_EDITOR_PLUGIN_H +#define RAY_CAST_2D_EDITOR_PLUGIN_H + +#include "editor/editor_plugin.h" +#include "scene/2d/ray_cast_2d.h" + +class CanvasItemEditor; + +class RayCast2DEditor : public Control { + GDCLASS(RayCast2DEditor, Control); + + UndoRedo *undo_redo = nullptr; + CanvasItemEditor *canvas_item_editor = nullptr; + RayCast2D *node; + + bool pressed = false; + Point2 original_target_position; + +protected: + void _notification(int p_what); + void _node_removed(Node *p_node); + +public: + bool forward_canvas_gui_input(const Ref<InputEvent> &p_event); + void forward_canvas_draw_over_viewport(Control *p_overlay); + void edit(Node *p_node); + + RayCast2DEditor(); +}; + +class RayCast2DEditorPlugin : public EditorPlugin { + GDCLASS(RayCast2DEditorPlugin, EditorPlugin); + + RayCast2DEditor *ray_cast_2d_editor = nullptr; + +public: + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return ray_cast_2d_editor->forward_canvas_gui_input(p_event); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { ray_cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); } + + virtual String get_name() const override { return "RayCast2D"; } + bool has_main_screen() const override { return false; } + virtual void edit(Object *p_object) override; + virtual bool handles(Object *p_object) const override; + virtual void make_visible(bool visible) override; + + RayCast2DEditorPlugin(); +}; + +#endif // RAY_CAST_2D_EDITOR_PLUGIN_H |