summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/editor_node.cpp34
-rw-r--r--editor/import/resource_importer_texture.cpp30
-rw-r--r--editor/plugins/ray_cast_2d_editor_plugin.cpp151
-rw-r--r--editor/plugins/ray_cast_2d_editor_plugin.h79
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