diff options
Diffstat (limited to 'editor/plugins')
51 files changed, 1182 insertions, 1207 deletions
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index df01ecd1be..36a814c30a 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -261,7 +261,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); Vector2 gpoint = mb->get_position(); - Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); + Vector2 cpoint = _get_node()->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mode == MODE_EDIT || (_is_line() && mode == MODE_CREATE)) { if (mb->get_button_index() == MOUSE_BUTTON_LEFT) { @@ -367,7 +367,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) edge_point = PosVertex(); return true; } else { - const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + const real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(xform.xform(cpoint)) < grab_threshold) { //wip closed @@ -396,7 +396,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) Vector2 gpoint = mm->get_position(); if (edited_point.valid() && (wip_active || (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT))) { - Vector2 cpoint = _get_node()->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); + Vector2 cpoint = _get_node()->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint))); //Move the point in a single axis. Should only work when editing a polygon and while holding shift. if (mode == MODE_EDIT && mm->is_shift_pressed()) { @@ -502,7 +502,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl offset = _get_offset(j); } - if (!wip_active && j == edited_point.polygon && EDITOR_GET("editors/poly_editor/show_previous_outline")) { + if (!wip_active && j == edited_point.polygon && EDITOR_GET("editors/polygon_editor/show_previous_outline")) { const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color(); const int n = pre_move_edit.size(); for (int i = 0; i < n - (is_closed ? 0 : 1); i++) { @@ -625,7 +625,7 @@ AbstractPolygon2DEditor::Vertex AbstractPolygon2DEditor::get_active_point() cons } AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const Vector2 &p_pos) const { - const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + const real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); const int n_polygons = _get_polygon_count(); const Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); @@ -653,7 +653,7 @@ AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const } AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(const Vector2 &p_pos) const { - const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + const real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); const real_t eps = grab_threshold * 2; const real_t eps2 = eps * eps; diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index 24c950fdee..fe98a91ab3 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -92,7 +92,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { PopupMenu *animations_menu; Vector<String> animations_to_add; float add_point_pos; - Vector<float> points; + Vector<real_t> points; bool dragging_selected_attempt; bool dragging_selected; diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index 69206daea8..030d90eeca 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -126,6 +126,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { graph->add_child(node); Ref<AnimationNode> agnode = blend_tree->get_node(E); + ERR_CONTINUE(!agnode.is_valid()); node->set_position_offset(blend_tree->get_node_position(E) * EDSCALE); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 681c3e7195..830b010d01 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -345,7 +345,7 @@ void AnimationPlayerEditor::_animation_rename() { void AnimationPlayerEditor::_animation_load() { ERR_FAIL_COND(!player); - file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE); + file->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILES); file->clear_filters(); List<String> extensions; @@ -355,7 +355,6 @@ void AnimationPlayerEditor::_animation_load() { } file->popup_file_dialog(); - current_option = RESOURCE_LOAD; } void AnimationPlayerEditor::_animation_save_in_path(const Ref<Resource> &p_resource, const String &p_path) { @@ -416,7 +415,6 @@ void AnimationPlayerEditor::_animation_save_as(const Ref<Resource> &p_resource) file->set_current_path(path); file->set_title(TTR("Save Resource As...")); file->popup_file_dialog(); - current_option = RESOURCE_SAVE; } void AnimationPlayerEditor::_animation_remove() { @@ -718,44 +716,48 @@ void AnimationPlayerEditor::_animation_edit() { } } -void AnimationPlayerEditor::_dialog_action(String p_path) { - switch (current_option) { - case RESOURCE_LOAD: { - ERR_FAIL_COND(!player); +void AnimationPlayerEditor::_save_animation(String p_file) { + String current = animation->get_item_text(animation->get_selected()); + if (current != "") { + Ref<Animation> anim = player->get_animation(current); - Ref<Resource> res = ResourceLoader::load(p_path, "Animation"); - ERR_FAIL_COND_MSG(res.is_null(), "Cannot load Animation from file '" + p_path + "'."); - ERR_FAIL_COND_MSG(!res->is_class("Animation"), "Loaded resource from file '" + p_path + "' is not Animation."); + ERR_FAIL_COND(!Object::cast_to<Resource>(*anim)); - String anim_name = p_path.get_file(); - int ext_pos = anim_name.rfind("."); - if (ext_pos != -1) { - anim_name = anim_name.substr(0, ext_pos); - } + RES current_res = RES(Object::cast_to<Resource>(*anim)); - undo_redo->create_action(TTR("Load Animation")); - undo_redo->add_do_method(player, "add_animation", anim_name, res); - undo_redo->add_undo_method(player, "remove_animation", anim_name); - if (player->has_animation(anim_name)) { - undo_redo->add_undo_method(player, "add_animation", anim_name, player->get_animation(anim_name)); - } - undo_redo->add_do_method(this, "_animation_player_changed", player); - undo_redo->add_undo_method(this, "_animation_player_changed", player); - undo_redo->commit_action(); - break; - } - case RESOURCE_SAVE: { - String current = animation->get_item_text(animation->get_selected()); - if (current != "") { - Ref<Animation> anim = player->get_animation(current); + _animation_save_in_path(current_res, p_file); + } +} - ERR_FAIL_COND(!Object::cast_to<Resource>(*anim)); +void AnimationPlayerEditor::_load_animations(Vector<String> p_files) { + ERR_FAIL_COND(!player); - RES current_res = RES(Object::cast_to<Resource>(*anim)); + for (int i = 0; i < p_files.size(); i++) { + String file = p_files[i]; - _animation_save_in_path(current_res, p_path); - } + Ref<Resource> res = ResourceLoader::load(file, "Animation"); + ERR_FAIL_COND_MSG(res.is_null(), "Cannot load Animation from file '" + file + "'."); + ERR_FAIL_COND_MSG(!res->is_class("Animation"), "Loaded resource from file '" + file + "' is not Animation."); + if (file.rfind("/") != -1) { + file = file.substr(file.rfind("/") + 1, file.length()); + } + if (file.rfind("\\") != -1) { + file = file.substr(file.rfind("\\") + 1, file.length()); } + + if (file.find(".") != -1) { + file = file.substr(0, file.find(".")); + } + + undo_redo->create_action(TTR("Load Animation")); + undo_redo->add_do_method(player, "add_animation", file, res); + undo_redo->add_undo_method(player, "remove_animation", file); + if (player->has_animation(file)) { + undo_redo->add_undo_method(player, "add_animation", file, player->get_animation(file)); + } + undo_redo->add_do_method(this, "_animation_player_changed", player); + undo_redo->add_undo_method(this, "_animation_player_changed", player); + undo_redo->commit_action(); } } @@ -1220,7 +1222,7 @@ void AnimationPlayerEditor::_onion_skinning_menu(int p_option) { } } -void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { +void AnimationPlayerEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) { ERR_FAIL_COND(p_ev.is_null()); Ref<InputEventKey> k = p_ev; @@ -1246,6 +1248,8 @@ void AnimationPlayerEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { } accept_event(); } break; + default: + break; } } } @@ -1495,7 +1499,6 @@ void AnimationPlayerEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_animation_player_changed"), &AnimationPlayerEditor::_animation_player_changed); ClassDB::bind_method(D_METHOD("_list_changed"), &AnimationPlayerEditor::_list_changed); ClassDB::bind_method(D_METHOD("_animation_duplicate"), &AnimationPlayerEditor::_animation_duplicate); - ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &AnimationPlayerEditor::_unhandled_key_input); ClassDB::bind_method(D_METHOD("_prepare_onion_layers_1"), &AnimationPlayerEditor::_prepare_onion_layers_1); ClassDB::bind_method(D_METHOD("_prepare_onion_layers_2"), &AnimationPlayerEditor::_prepare_onion_layers_2); @@ -1694,7 +1697,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay animation->connect("item_selected", callable_mp(this, &AnimationPlayerEditor::_animation_selected)); - file->connect("file_selected", callable_mp(this, &AnimationPlayerEditor::_dialog_action)); + file->connect("file_selected", callable_mp(this, &AnimationPlayerEditor::_save_animation)); + file->connect("files_selected", callable_mp(this, &AnimationPlayerEditor::_load_animations)); frame->connect("value_changed", callable_mp(this, &AnimationPlayerEditor::_seek_value_changed), make_binds(true, false)); scale->connect("text_submitted", callable_mp(this, &AnimationPlayerEditor::_scale_changed)); @@ -1734,6 +1738,8 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay onion.capture.shader = Ref<Shader>(memnew(Shader)); onion.capture.shader->set_code(R"( +// Animation editor onion skinning shader. + shader_type canvas_item; uniform vec4 bkg_color; diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index 5c2348f86b..be80b7f4e3 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -112,7 +112,6 @@ class AnimationPlayerEditor : public VBoxContainer { EditorFileDialog *file; ConfirmationDialog *delete_dialog; - int current_option; struct BlendEditor { AcceptDialog *dialog = nullptr; @@ -185,7 +184,8 @@ class AnimationPlayerEditor : public VBoxContainer { void _animation_duplicate(); void _animation_resource_edit(); void _scale_changed(const String &p_scale); - void _dialog_action(String p_file); + void _save_animation(String p_file); + void _load_animations(Vector<String> p_files); void _seek_frame_changed(const String &p_frame); void _seek_value_changed(float p_value, bool p_set = false, bool p_timeline_only = false); void _blend_editor_next_changed(const int p_idx); @@ -200,7 +200,7 @@ class AnimationPlayerEditor : public VBoxContainer { void _animation_key_editor_seek(float p_pos, bool p_drag, bool p_timeline_only = false); void _animation_key_editor_anim_len_changed(float p_len); - void _unhandled_key_input(const Ref<InputEvent> &p_ev); + virtual void unhandled_key_input(const Ref<InputEvent> &p_ev) override; void _animation_tool_menu(int p_option); void _onion_skinning_menu(int p_option); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 785bab42cf..5405723d10 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -614,7 +614,7 @@ void EditorAssetLibrary::_update_repository_options() { } } -void EditorAssetLibrary::_unhandled_key_input(const Ref<InputEvent> &p_event) { +void EditorAssetLibrary::unhandled_key_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); const Ref<InputEventKey> key = p_event; @@ -1322,8 +1322,6 @@ void EditorAssetLibrary::disable_community_support() { } void EditorAssetLibrary::_bind_methods() { - ClassDB::bind_method("_unhandled_key_input", &EditorAssetLibrary::_unhandled_key_input); - ADD_SIGNAL(MethodInfo("install_asset", PropertyInfo(Variant::STRING, "zip_path"), PropertyInfo(Variant::STRING, "name"))); } diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index c6ca1ecd4f..286546f962 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -299,7 +299,7 @@ class EditorAssetLibrary : public PanelContainer { protected: static void _bind_methods(); void _notification(int p_what); - void _unhandled_key_input(const Ref<InputEvent> &p_event); + virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; public: void disable_community_support(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index c440064898..d96cc1cd18 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -41,6 +41,7 @@ #include "editor/editor_settings.h" #include "editor/plugins/animation_player_editor_plugin.h" #include "editor/plugins/script_editor_plugin.h" +#include "scene/2d/cpu_particles_2d.h" #include "scene/2d/gpu_particles_2d.h" #include "scene/2d/light_2d.h" #include "scene/2d/polygon_2d.h" @@ -471,7 +472,7 @@ real_t CanvasItemEditor::snap_angle(real_t p_target, real_t p_start) const { } } -void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) { +void CanvasItemEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) { ERR_FAIL_COND(p_ev.is_null()); Ref<InputEventKey> k = p_ev; @@ -589,7 +590,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no return; } - const real_t grab_distance = EDITOR_GET("editors/poly_editor/point_grab_radius"); + const real_t grab_distance = EDITOR_GET("editors/polygon_editor/point_grab_radius"); CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); for (int i = p_node->get_child_count() - 1; i >= 0; i--) { @@ -3908,6 +3909,11 @@ void CanvasItemEditor::_notification(int p_what) { anchors_popup->add_icon_item(get_theme_icon(SNAME("ControlAlignWide"), SNAME("EditorIcons")), TTR("Full Rect"), ANCHORS_PRESET_WIDE); anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons"))); + + info_overlay->get_theme()->set_stylebox("normal", "Label", get_theme_stylebox(SNAME("CanvasItemInfoOverlay"), SNAME("EditorStyles"))); + warning_child_of_container->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); + warning_child_of_container->add_theme_font_override("font", get_theme_font(SNAME("main"), SNAME("EditorFonts"))); + warning_child_of_container->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"))); } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { @@ -4073,7 +4079,7 @@ void CanvasItemEditor::_popup_warning_depop(Control *p_control) { info_overlay->set_offset(SIDE_LEFT, (show_rulers ? RULER_WIDTH : 0) + 10); } -void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const float p_duration) { +void CanvasItemEditor::_popup_warning_temporarily(Control *p_control, const double p_duration) { Timer *timer; if (!popup_temporarily_timers.has(p_control)) { timer = memnew(Timer); @@ -4189,6 +4195,7 @@ void CanvasItemEditor::_zoom_on_position(real_t p_zoom, Point2 p_position) { p_zoom = CLAMP(p_zoom, MIN_ZOOM, MAX_ZOOM); if (p_zoom == zoom) { + zoom_widget->set_zoom(p_zoom); return; } @@ -4912,7 +4919,7 @@ void CanvasItemEditor::_focus_selection(int p_op) { void CanvasItemEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button); ClassDB::bind_method("_get_editor_data", &CanvasItemEditor::_get_editor_data); - ClassDB::bind_method("_unhandled_key_input", &CanvasItemEditor::_unhandled_key_input); + ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state); ClassDB::bind_method(D_METHOD("update_viewport"), &CanvasItemEditor::update_viewport); ClassDB::bind_method(D_METHOD("_zoom_on_position"), &CanvasItemEditor::_zoom_on_position); @@ -5279,21 +5286,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { info_overlay->add_theme_constant_override("separation", 10); viewport_scrollable->add_child(info_overlay); + // Make sure all labels inside of the container are styled the same. Theme *info_overlay_theme = memnew(Theme); - info_overlay_theme->copy_default_theme(); info_overlay->set_theme(info_overlay_theme); - StyleBoxFlat *info_overlay_label_stylebox = memnew(StyleBoxFlat); - info_overlay_label_stylebox->set_bg_color(Color(0.0, 0.0, 0.0, 0.2)); - info_overlay_label_stylebox->set_expand_margin_size_all(4); - info_overlay_theme->set_stylebox("normal", "Label", info_overlay_label_stylebox); - warning_child_of_container = memnew(Label); warning_child_of_container->hide(); warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent.")); - warning_child_of_container->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color(SNAME("warning_color"), SNAME("Editor"))); - warning_child_of_container->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font(SNAME("main"), SNAME("EditorFonts"))); - warning_child_of_container->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size(SNAME("main_size"), SNAME("EditorFonts"))); add_control_to_info_overlay(warning_child_of_container); h_scroll = memnew(HScrollBar); @@ -5740,7 +5739,7 @@ void CanvasItemEditorViewport::_on_change_type_confirmed() { } CheckBox *check = Object::cast_to<CheckBox>(button_group->get_pressed_button()); - default_type = check->get_text(); + default_texture_node_type = check->get_text(); _perform_drop_data(); selector->hide(); } @@ -5832,14 +5831,13 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & child->set_name(name); Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(ResourceCache::get(path))); - Size2 texture_size = texture->get_size(); if (parent) { editor_data->get_undo_redo().add_do_method(parent, "add_child", child); editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene()); editor_data->get_undo_redo().add_do_reference(child); editor_data->get_undo_redo().add_undo_method(parent, "remove_child", child); - } else { // if we haven't parent, lets try to make a child as a parent. + } else { // If no parent is selected, set as root node of the scene. editor_data->get_undo_redo().add_do_method(editor, "set_edited_scene", child); editor_data->get_undo_redo().add_do_method(child, "set_owner", editor->get_edited_scene()); editor_data->get_undo_redo().add_do_reference(child); @@ -5853,28 +5851,23 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(editor->get_edited_scene()->get_path_to(parent)) + "/" + new_name)); } - // handle with different property for texture - String property = "texture"; - List<PropertyInfo> props; - child->get_property_list(&props); - for (const PropertyInfo &E : props) { - if (E.name == "config/texture") { // Particles2D - property = "config/texture"; - break; - } else if (E.name == "texture/texture") { // Polygon2D - property = "texture/texture"; - break; - } else if (E.name == "normal") { // TouchScreenButton - property = "normal"; - break; - } + String node_class = child->get_class(); + if (node_class == "Polygon2D") { + editor_data->get_undo_redo().add_do_property(child, "texture/texture", texture); + } else if (node_class == "TouchScreenButton") { + editor_data->get_undo_redo().add_do_property(child, "normal", texture); + } else if (node_class == "TextureButton") { + editor_data->get_undo_redo().add_do_property(child, "texture_button", texture); + } else { + editor_data->get_undo_redo().add_do_property(child, "texture", texture); } - editor_data->get_undo_redo().add_do_property(child, property, texture); // make visible for certain node type - if (default_type == "NinePatchRect") { - editor_data->get_undo_redo().add_do_property(child, "rect/size", texture_size); - } else if (default_type == "Polygon2D") { + if (ClassDB::is_parent_class(node_class, "Control")) { + Size2 texture_size = texture->get_size(); + editor_data->get_undo_redo().add_do_property(child, "rect_size", texture_size); + } else if (node_class == "Polygon2D") { + Size2 texture_size = texture->get_size(); Vector<Vector2> list; list.push_back(Vector2(0, 0)); list.push_back(Vector2(texture_size.width, 0)); @@ -5975,23 +5968,7 @@ void CanvasItemEditorViewport::_perform_drop_data() { } else { Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(*res)); if (texture != nullptr && texture.is_valid()) { - Node *child; - if (default_type == "Light2D") { - child = memnew(Light2D); - } else if (default_type == "GPUParticles2D") { - child = memnew(GPUParticles2D); - } else if (default_type == "Polygon2D") { - child = memnew(Polygon2D); - } else if (default_type == "TouchScreenButton") { - child = memnew(TouchScreenButton); - } else if (default_type == "TextureRect") { - child = memnew(TextureRect); - } else if (default_type == "NinePatchRect") { - child = memnew(NinePatchRect); - } else { - child = memnew(Sprite2D); // default - } - + Node *child = _make_texture_node_type(default_texture_node_type); _create_nodes(target_node, child, path, drop_pos); } } @@ -6029,13 +6006,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian continue; } memdelete(instantiated_scene); - } else if (type == "Texture2D" || - type == "ImageTexture" || - type == "ViewportTexture" || - type == "CurveTexture" || - type == "GradientTexture" || - type == "StreamTexture2D" || - type == "AtlasTexture") { + } else if (ClassDB::is_parent_class(type, "Texture2D")) { Ref<Texture2D> texture = Ref<Texture2D>(Object::cast_to<Texture2D>(*res)); if (!texture.is_valid()) { continue; @@ -6052,7 +6023,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian } Transform2D trans = canvas_item_editor->get_canvas_transform(); preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x); - label->set_text(vformat(TTR("Adding %s..."), default_type)); + label->set_text(vformat(TTR("Adding %s..."), default_texture_node_type)); } return can_instantiate; } @@ -6068,9 +6039,9 @@ void CanvasItemEditorViewport::_show_resource_type_selector() { for (int i = 0; i < btn_list.size(); i++) { CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]); - check->set_pressed(check->get_text() == default_type); + check->set_pressed(check->get_text() == default_texture_node_type); } - selector->set_title(vformat(TTR("Add %s"), default_type)); + selector->set_title(vformat(TTR("Add %s"), default_texture_node_type)); selector->popup_centered(); } @@ -6126,6 +6097,30 @@ void CanvasItemEditorViewport::drop_data(const Point2 &p_point, const Variant &p } } +Node *CanvasItemEditorViewport::_make_texture_node_type(String texture_node_type) { + Node *node = nullptr; + if (texture_node_type == "Sprite2D") { + node = memnew(Sprite2D); + } else if (texture_node_type == "PointLight2D") { + node = memnew(PointLight2D); + } else if (texture_node_type == "CPUParticles2D") { + node = memnew(CPUParticles2D); + } else if (texture_node_type == "GPUParticles2D") { + node = memnew(GPUParticles2D); + } else if (texture_node_type == "Polygon2D") { + node = memnew(Polygon2D); + } else if (texture_node_type == "TouchScreenButton") { + node = memnew(TouchScreenButton); + } else if (texture_node_type == "TextureRect") { + node = memnew(TextureRect); + } else if (texture_node_type == "TextureButton") { + node = memnew(TextureButton); + } else if (texture_node_type == "NinePatchRect") { + node = memnew(NinePatchRect); + } + return node; +} + void CanvasItemEditorViewport::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -6145,22 +6140,24 @@ void CanvasItemEditorViewport::_bind_methods() { } CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor) { - default_type = "Sprite2D"; + default_texture_node_type = "Sprite2D"; // Node2D - types.push_back("Sprite2D"); - types.push_back("Light2D"); - types.push_back("GPUParticles2D"); - types.push_back("Polygon2D"); - types.push_back("TouchScreenButton"); + texture_node_types.push_back("Sprite2D"); + texture_node_types.push_back("PointLight2D"); + texture_node_types.push_back("CPUParticles2D"); + texture_node_types.push_back("GPUParticles2D"); + texture_node_types.push_back("Polygon2D"); + texture_node_types.push_back("TouchScreenButton"); // Control - types.push_back("TextureRect"); - types.push_back("NinePatchRect"); + texture_node_types.push_back("TextureRect"); + texture_node_types.push_back("TextureButton"); + texture_node_types.push_back("NinePatchRect"); target_node = nullptr; editor = p_node; editor_data = editor->get_scene_tree_dock()->get_editor_data(); canvas_item_editor = p_canvas_item_editor; - preview_node = memnew(Node2D); + preview_node = memnew(Control); accept = memnew(AcceptDialog); editor->get_gui_base()->add_child(accept); @@ -6182,10 +6179,10 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte btn_group->set_h_size_flags(0); button_group.instantiate(); - for (int i = 0; i < types.size(); i++) { + for (int i = 0; i < texture_node_types.size(); i++) { CheckBox *check = memnew(CheckBox); btn_group->add_child(check); - check->set_text(types[i]); + check->set_text(texture_node_types[i]); check->connect("button_down", callable_mp(this, &CanvasItemEditorViewport::_on_select_type), varray(check)); check->set_button_group(button_group); } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 1f59dfbc49..1965efbf30 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -56,7 +56,7 @@ public: Transform2D pre_drag_xform; Rect2 pre_drag_rect; - List<float> pre_drag_bones_length; + List<real_t> pre_drag_bones_length; List<Dictionary> pre_drag_bones_undo_state; Dictionary undo_state; @@ -455,7 +455,7 @@ private: void _keying_changed(); - void _unhandled_key_input(const Ref<InputEvent> &p_ev); + virtual void unhandled_key_input(const Ref<InputEvent> &p_ev) override; void _draw_text_at_position(Point2 p_position, String p_string, Side p_side); void _draw_margin_at_position(int p_value, Point2 p_position, Side p_side); @@ -540,7 +540,7 @@ private: VSplitContainer *bottom_split; void _update_context_menu_stylebox(); - void _popup_warning_temporarily(Control *p_control, const float p_duration); + void _popup_warning_temporarily(Control *p_control, const double p_duration); void _popup_warning_depop(Control *p_control); void _set_owner_for_node_and_children(Node *p_node, Node *p_owner); @@ -639,8 +639,10 @@ public: class CanvasItemEditorViewport : public Control { GDCLASS(CanvasItemEditorViewport, Control); - String default_type; - Vector<String> types; + // The type of node that will be created when dropping texture into the viewport. + String default_texture_node_type; + // Node types that are available to select from when dropping texture into viewport. + Vector<String> texture_node_types; Vector<String> selected_files; Node *target_node; @@ -649,7 +651,7 @@ class CanvasItemEditorViewport : public Control { EditorNode *editor; EditorData *editor_data; CanvasItemEditor *canvas_item_editor; - Node2D *preview_node; + Control *preview_node; AcceptDialog *accept; AcceptDialog *selector; Label *selector_label; @@ -662,6 +664,7 @@ class CanvasItemEditorViewport : public Control { void _on_select_type(Object *selected); void _on_change_type_confirmed(); void _on_change_type_closed(); + Node *_make_texture_node_type(String texture_node_type); void _create_preview(const Vector<String> &files) const; void _remove_preview(); diff --git a/editor/plugins/collision_polygon_3d_editor_plugin.cpp b/editor/plugins/collision_polygon_3d_editor_plugin.cpp index 5d5f78e0dc..8b354c33a1 100644 --- a/editor/plugins/collision_polygon_3d_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_3d_editor_plugin.cpp @@ -138,7 +138,7 @@ bool CollisionPolygon3DEditor::forward_spatial_gui_input(Camera3D *p_camera, con Vector<Vector2> poly = node->call("get_polygon"); //first check if a point is to be added (segment split) - real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); switch (mode) { case MODE_CREATE: { diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index 2c2adc2672..bfcc293625 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -36,10 +36,10 @@ #include "scene/resources/circle_shape_2d.h" #include "scene/resources/concave_polygon_shape_2d.h" #include "scene/resources/convex_polygon_shape_2d.h" -#include "scene/resources/line_shape_2d.h" -#include "scene/resources/ray_shape_2d.h" #include "scene/resources/rectangle_shape_2d.h" #include "scene/resources/segment_shape_2d.h" +#include "scene/resources/separation_ray_shape_2d.h" +#include "scene/resources/world_margin_shape_2d.h" void CollisionShape2DEditor::_node_removed(Node *p_node) { if (p_node == node) { @@ -51,12 +51,7 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const { switch (shape_type) { case CAPSULE_SHAPE: { Ref<CapsuleShape2D> capsule = node->get_shape(); - - if (idx == 0) { - return capsule->get_radius(); - } else if (idx == 1) { - return capsule->get_height(); - } + return Vector2(capsule->get_radius(), capsule->get_height()); } break; @@ -75,8 +70,8 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const { case CONVEX_POLYGON_SHAPE: { } break; - case LINE_SHAPE: { - Ref<LineShape2D> line = node->get_shape(); + case WORLD_MARGIN_SHAPE: { + Ref<WorldMarginShape2D> line = node->get_shape(); if (idx == 0) { return line->get_distance(); @@ -86,8 +81,8 @@ Variant CollisionShape2DEditor::get_handle_value(int idx) const { } break; - case RAY_SHAPE: { - Ref<RayShape2D> ray = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref<SeparationRayShape2D> ray = node->get_shape(); if (idx == 0) { return ray->get_length(); @@ -130,7 +125,7 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { if (idx == 0) { capsule->set_radius(parameter); } else if (idx == 1) { - capsule->set_height(parameter * 2 - capsule->get_radius() * 2); + capsule->set_height(parameter * 2); } canvas_item_editor->update_viewport(); @@ -152,9 +147,9 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { case CONVEX_POLYGON_SHAPE: { } break; - case LINE_SHAPE: { + case WORLD_MARGIN_SHAPE: { if (idx < 2) { - Ref<LineShape2D> line = node->get_shape(); + Ref<WorldMarginShape2D> line = node->get_shape(); if (idx == 0) { line->set_distance(p_point.length()); @@ -167,8 +162,8 @@ void CollisionShape2DEditor::set_handle(int idx, Point2 &p_point) { } break; - case RAY_SHAPE: { - Ref<RayShape2D> ray = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref<SeparationRayShape2D> ray = node->get_shape(); ray->set_length(Math::abs(p_point.y)); @@ -228,17 +223,17 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { case CAPSULE_SHAPE: { Ref<CapsuleShape2D> capsule = node->get_shape(); + Vector2 values = p_org; + if (idx == 0) { undo_redo->add_do_method(capsule.ptr(), "set_radius", capsule->get_radius()); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(capsule.ptr(), "set_radius", p_org); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); } else if (idx == 1) { undo_redo->add_do_method(capsule.ptr(), "set_height", capsule->get_height()); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(capsule.ptr(), "set_height", p_org); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(capsule.ptr(), "set_radius", values[0]); + undo_redo->add_undo_method(capsule.ptr(), "set_height", values[1]); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); } break; @@ -260,8 +255,8 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { // Cannot be edited directly, use CollisionPolygon2D instead. } break; - case LINE_SHAPE: { - Ref<LineShape2D> line = node->get_shape(); + case WORLD_MARGIN_SHAPE: { + Ref<WorldMarginShape2D> line = node->get_shape(); if (idx == 0) { undo_redo->add_do_method(line.ptr(), "set_distance", line->get_distance()); @@ -277,8 +272,8 @@ void CollisionShape2DEditor::commit_handle(int idx, Variant &p_org) { } break; - case RAY_SHAPE: { - Ref<RayShape2D> ray = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref<SeparationRayShape2D> ray = node->get_shape(); undo_redo->add_do_method(ray.ptr(), "set_length", ray->get_length()); undo_redo->add_do_method(canvas_item_editor, "update_viewport"); @@ -426,10 +421,10 @@ void CollisionShape2DEditor::_get_current_shape_type() { shape_type = CONCAVE_POLYGON_SHAPE; } else if (Object::cast_to<ConvexPolygonShape2D>(*s)) { shape_type = CONVEX_POLYGON_SHAPE; - } else if (Object::cast_to<LineShape2D>(*s)) { - shape_type = LINE_SHAPE; - } else if (Object::cast_to<RayShape2D>(*s)) { - shape_type = RAY_SHAPE; + } else if (Object::cast_to<WorldMarginShape2D>(*s)) { + shape_type = WORLD_MARGIN_SHAPE; + } else if (Object::cast_to<SeparationRayShape2D>(*s)) { + shape_type = SEPARATION_RAY_SHAPE; } else if (Object::cast_to<RectangleShape2D>(*s)) { shape_type = RECTANGLE_SHAPE; } else if (Object::cast_to<SegmentShape2D>(*s)) { @@ -471,8 +466,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla float radius = shape->get_radius(); float height = shape->get_height() / 2; - handles.write[0] = Point2(radius, height); - handles.write[1] = Point2(0, height + radius); + handles.write[0] = Point2(radius, 0); + handles.write[1] = Point2(0, height); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); @@ -495,8 +490,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla case CONVEX_POLYGON_SHAPE: { } break; - case LINE_SHAPE: { - Ref<LineShape2D> shape = node->get_shape(); + case WORLD_MARGIN_SHAPE: { + Ref<WorldMarginShape2D> shape = node->get_shape(); handles.resize(2); handles.write[0] = shape->get_normal() * shape->get_distance(); @@ -507,8 +502,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla } break; - case RAY_SHAPE: { - Ref<RayShape2D> shape = node->get_shape(); + case SEPARATION_RAY_SHAPE: { + Ref<SeparationRayShape2D> shape = node->get_shape(); handles.resize(1); handles.write[0] = Point2(0, shape->get_length()); diff --git a/editor/plugins/collision_shape_2d_editor_plugin.h b/editor/plugins/collision_shape_2d_editor_plugin.h index 7db6bd22aa..421e674df8 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.h +++ b/editor/plugins/collision_shape_2d_editor_plugin.h @@ -46,8 +46,8 @@ class CollisionShape2DEditor : public Control { CIRCLE_SHAPE, CONCAVE_POLYGON_SHAPE, CONVEX_POLYGON_SHAPE, - LINE_SHAPE, - RAY_SHAPE, + WORLD_MARGIN_SHAPE, + SEPARATION_RAY_SHAPE, RECTANGLE_SHAPE, SEGMENT_SHAPE }; diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 07ff0eb346..4a22dc5b62 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -101,7 +101,7 @@ void CurveEditor::_notification(int p_what) { } } -void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { +void CurveEditor::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb_ref = p_event; if (mb_ref.is_valid()) { const InputEventMouseButton &mb = **mb_ref; @@ -757,10 +757,6 @@ void CurveEditor::_draw() { } } -void CurveEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &CurveEditor::on_gui_input); -} - //--------------- bool EditorInspectorPluginCurve::can_handle(Object *p_object) { diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h index 2e8dd43d7e..c351f6ebe9 100644 --- a/editor/plugins/curve_editor_plugin.h +++ b/editor/plugins/curve_editor_plugin.h @@ -74,10 +74,8 @@ public: protected: void _notification(int p_what); - static void _bind_methods(); - private: - void on_gui_input(const Ref<InputEvent> &p_event); + virtual void gui_input(const Ref<InputEvent> &p_event) override; void on_preset_item_selected(int preset_id); void _curve_changed(); void on_context_menu_item_selected(int action_id); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index d7618b973e..415832ab3b 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -386,7 +386,7 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() { Vector<Vector3> vertices; Vector<Vector3> normals; Vector<Vector2> uvs; - Vector<float> tangents; + Vector<real_t> tangents; Basis tt = Basis(Vector3(0, 1, 0), Math_PI * 0.5); for (int i = 1; i <= lats; i++) { @@ -505,12 +505,12 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const RES &p_from, const Size int thumbnail_size = MAX(p_size.x, p_size.y); img->create(thumbnail_size, thumbnail_size, false, Image::FORMAT_RGBA8); - Color bg_color = EditorSettings::get_singleton()->get("text_editor/highlighting/background_color"); - Color keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/keyword_color"); - Color control_flow_keyword_color = EditorSettings::get_singleton()->get("text_editor/highlighting/control_flow_keyword_color"); - Color text_color = EditorSettings::get_singleton()->get("text_editor/highlighting/text_color"); - Color symbol_color = EditorSettings::get_singleton()->get("text_editor/highlighting/symbol_color"); - Color comment_color = EditorSettings::get_singleton()->get("text_editor/highlighting/comment_color"); + Color bg_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/background_color"); + Color keyword_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/keyword_color"); + Color control_flow_keyword_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/control_flow_keyword_color"); + Color text_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/text_color"); + Color symbol_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/symbol_color"); + Color comment_color = EditorSettings::get_singleton()->get("text_editor/theme/highlighting/comment_color"); if (bg_color.a == 0) { bg_color = Color(0, 0, 0, 0); @@ -635,7 +635,7 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const Ref<AudioStreamPlayback> playback = stream->instance_playback(); ERR_FAIL_COND_V(playback.is_null(), Ref<Texture2D>()); - float len_s = stream->get_length(); + real_t len_s = stream->get_length(); if (len_s == 0) { len_s = 60; //one minute audio if no length specified } @@ -649,8 +649,8 @@ Ref<Texture2D> EditorAudioStreamPreviewPlugin::generate(const RES &p_from, const playback->stop(); for (int i = 0; i < w; i++) { - float max = -1000; - float min = 1000; + real_t max = -1000; + real_t min = 1000; int from = uint64_t(i) * frame_length / w; int to = (uint64_t(i) + 1) * frame_length / w; to = MIN(to, frame_length); @@ -826,55 +826,6 @@ bool EditorFontPreviewPlugin::handles(const String &p_type) const { return ClassDB::is_parent_class(p_type, "FontData") || ClassDB::is_parent_class(p_type, "Font"); } -struct FSample { - String script; - String sample; -}; - -static FSample _samples[] = { - { "hani", U"漢字" }, - { "armn", U"Աբ" }, - { "copt", U"Αα" }, - { "cyrl", U"Аб" }, - { "grek", U"Αα" }, - { "hebr", U"אב" }, - { "arab", U"اب" }, - { "syrc", U"ܐܒ" }, - { "thaa", U"ހށ" }, - { "deva", U"आ" }, - { "beng", U"আ" }, - { "guru", U"ਆ" }, - { "gujr", U"આ" }, - { "orya", U"ଆ" }, - { "taml", U"ஆ" }, - { "telu", U"ఆ" }, - { "knda", U"ಆ" }, - { "mylm", U"ആ" }, - { "sinh", U"ආ" }, - { "thai", U"กิ" }, - { "laoo", U"ກິ" }, - { "tibt", U"ༀ" }, - { "mymr", U"က" }, - { "geor", U"Ⴀა" }, - { "hang", U"한글" }, - { "ethi", U"ሀ" }, - { "cher", U"Ꭳ" }, - { "cans", U"ᐁ" }, - { "ogam", U"ᚁ" }, - { "runr", U"ᚠ" }, - { "tglg", U"ᜀ" }, - { "hano", U"ᜠ" }, - { "buhd", U"ᝀ" }, - { "tagb", U"ᝠ" }, - { "khmr", U"ក" }, - { "mong", U"ᠠ" }, - { "limb", U"ᤁ" }, - { "tale", U"ᥐ" }, - { "latn", U"Ab" }, - { "zyyy", U"😀" }, - { "", U"" } -}; - Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size) const { RES res = ResourceLoader::load(p_path); Ref<Font> sampled_font; @@ -886,15 +837,15 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, } String sample; - for (int j = 0; j < sampled_font->get_data_count(); j++) { - for (int i = 0; _samples[i].script != String(); i++) { - if (sampled_font->get_data(j)->is_script_supported(_samples[i].script)) { - if (sampled_font->get_data(j)->has_char(_samples[i].sample[0])) { - sample += _samples[i].sample; - } - } + static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ሀᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀"; + for (int i = 0; i < sample_base.length(); i++) { + if (sampled_font->has_char(sample_base[i])) { + sample += sample_base[i]; } } + if (sample.is_empty()) { + sample = sampled_font->get_supported_chars().substr(0, 6); + } Vector2 size = sampled_font->get_string_size(sample, 50); Vector2 pos; diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp index 22c9cc9ab1..52fb5b69ea 100644 --- a/editor/plugins/font_editor_plugin.cpp +++ b/editor/plugins/font_editor_plugin.cpp @@ -50,70 +50,24 @@ Size2 FontDataPreview::get_minimum_size() const { return Vector2(64, 64) * EDSCALE; } -struct FSample { - String script; - String sample; -}; - -static FSample _samples[] = { - { "hani", U"漢字" }, - { "armn", U"Աբ" }, - { "copt", U"Αα" }, - { "cyrl", U"Аб" }, - { "grek", U"Αα" }, - { "hebr", U"אב" }, - { "arab", U"اب" }, - { "syrc", U"ܐܒ" }, - { "thaa", U"ހށ" }, - { "deva", U"आ" }, - { "beng", U"আ" }, - { "guru", U"ਆ" }, - { "gujr", U"આ" }, - { "orya", U"ଆ" }, - { "taml", U"ஆ" }, - { "telu", U"ఆ" }, - { "knda", U"ಆ" }, - { "mylm", U"ആ" }, - { "sinh", U"ආ" }, - { "thai", U"กิ" }, - { "laoo", U"ກິ" }, - { "tibt", U"ༀ" }, - { "mymr", U"က" }, - { "geor", U"Ⴀა" }, - { "hang", U"한글" }, - { "ethi", U"ሀ" }, - { "cher", U"Ꭳ" }, - { "cans", U"ᐁ" }, - { "ogam", U"ᚁ" }, - { "runr", U"ᚠ" }, - { "tglg", U"ᜀ" }, - { "hano", U"ᜠ" }, - { "buhd", U"ᝀ" }, - { "tagb", U"ᝠ" }, - { "khmr", U"ក" }, - { "mong", U"ᠠ" }, - { "limb", U"ᤁ" }, - { "tale", U"ᥐ" }, - { "latn", U"Ab" }, - { "zyyy", U"😀" }, - { "", U"" } -}; - void FontDataPreview::set_data(const Ref<FontData> &p_data) { Ref<Font> f = memnew(Font); f->add_data(p_data); line->clear(); - - String sample; - for (int i = 0; _samples[i].script != String(); i++) { - if (p_data->is_script_supported(_samples[i].script)) { - if (p_data->has_char(_samples[i].sample[0])) { - sample += _samples[i].sample; + if (p_data.is_valid()) { + String sample; + static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ሀᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀"; + for (int i = 0; i < sample_base.length(); i++) { + if (p_data->has_char(sample_base[i])) { + sample += sample_base[i]; } } + if (sample.is_empty()) { + sample = p_data->get_supported_chars().substr(0, 6); + } + line->add_string(sample, f, 72); } - line->add_string(sample, f, 72); update(); } @@ -124,159 +78,6 @@ FontDataPreview::FontDataPreview() { /*************************************************************************/ -void FontDataEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_SORT_CHILDREN) { - int split_width = get_name_split_ratio() * get_size().width; - button->set_size(Size2(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))->get_width(), get_size().height)); - if (is_layout_rtl()) { - if (le != nullptr) { - fit_child_in_rect(le, Rect2(Vector2(split_width, 0), Size2(split_width, get_size().height))); - } - fit_child_in_rect(chk, Rect2(Vector2(split_width - chk->get_size().x, 0), Size2(chk->get_size().x, get_size().height))); - fit_child_in_rect(button, Rect2(Vector2(0, 0), Size2(button->get_size().width, get_size().height))); - } else { - if (le != nullptr) { - fit_child_in_rect(le, Rect2(Vector2(0, 0), Size2(split_width, get_size().height))); - } - fit_child_in_rect(chk, Rect2(Vector2(split_width, 0), Size2(chk->get_size().x, get_size().height))); - fit_child_in_rect(button, Rect2(Vector2(get_size().width - button->get_size().width, 0), Size2(button->get_size().width, get_size().height))); - } - update(); - } - if (p_what == NOTIFICATION_DRAW) { - int split_width = get_name_split_ratio() * get_size().width; - Color dark_color = get_theme_color(SNAME("dark_color_2"), SNAME("Editor")); - if (is_layout_rtl()) { - draw_rect(Rect2(Vector2(0, 0), Size2(split_width, get_size().height)), dark_color); - } else { - draw_rect(Rect2(Vector2(split_width, 0), Size2(split_width, get_size().height)), dark_color); - } - } - if (p_what == NOTIFICATION_THEME_CHANGED) { - if (le != nullptr) { - button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - } else { - button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - } - queue_sort(); - } - if (p_what == NOTIFICATION_RESIZED) { - queue_sort(); - } -} - -void FontDataEditor::update_property() { - if (le == nullptr) { - bool c = get_edited_object()->get(get_edited_property()); - chk->set_pressed(c); - chk->set_disabled(is_read_only()); - } -} - -Size2 FontDataEditor::get_minimum_size() const { - return Size2(0, 60); -} - -void FontDataEditor::_bind_methods() { -} - -void FontDataEditor::init_lang_add() { - le = memnew(LineEdit); - le->set_placeholder("Language code"); - le->set_custom_minimum_size(Size2(get_size().width / 2, 0)); - le->set_editable(true); - add_child(le); - - button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - button->connect("pressed", callable_mp(this, &FontDataEditor::add_lang)); -} - -void FontDataEditor::init_lang_edit() { - button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - button->connect("pressed", callable_mp(this, &FontDataEditor::remove_lang)); - chk->connect("toggled", callable_mp(this, &FontDataEditor::toggle_lang)); -} - -void FontDataEditor::init_script_add() { - le = memnew(LineEdit); - le->set_placeholder("Script code"); - le->set_custom_minimum_size(Size2(get_size().width / 2, 0)); - le->set_editable(true); - add_child(le); - - button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - button->connect("pressed", callable_mp(this, &FontDataEditor::add_script)); -} - -void FontDataEditor::init_script_edit() { - button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - button->connect("pressed", callable_mp(this, &FontDataEditor::remove_script)); - chk->connect("toggled", callable_mp(this, &FontDataEditor::toggle_script)); -} - -void FontDataEditor::add_lang() { - FontData *fd = Object::cast_to<FontData>(get_edited_object()); - if (fd != nullptr && !le->get_text().is_empty()) { - fd->set_language_support_override(le->get_text(), chk->is_pressed()); - le->set_text(""); - chk->set_pressed(false); - } -} - -void FontDataEditor::add_script() { - FontData *fd = Object::cast_to<FontData>(get_edited_object()); - if (fd != nullptr && le->get_text().length() == 4) { - fd->set_script_support_override(le->get_text(), chk->is_pressed()); - le->set_text(""); - chk->set_pressed(false); - } -} - -void FontDataEditor::toggle_lang(bool p_pressed) { - FontData *fd = Object::cast_to<FontData>(get_edited_object()); - if (fd != nullptr) { - String lang = String(get_edited_property()).replace("language_support_override/", ""); - fd->set_language_support_override(lang, p_pressed); - } -} - -void FontDataEditor::toggle_script(bool p_pressed) { - FontData *fd = Object::cast_to<FontData>(get_edited_object()); - if (fd != nullptr) { - String script = String(get_edited_property()).replace("script_support_override/", ""); - fd->set_script_support_override(script, p_pressed); - } -} - -void FontDataEditor::remove_lang() { - FontData *fd = Object::cast_to<FontData>(get_edited_object()); - if (fd != nullptr) { - String lang = String(get_edited_property()).replace("language_support_override/", ""); - fd->remove_language_support_override(lang); - } -} - -void FontDataEditor::remove_script() { - FontData *fd = Object::cast_to<FontData>(get_edited_object()); - if (fd != nullptr) { - String script = String(get_edited_property()).replace("script_support_override/", ""); - fd->remove_script_support_override(script); - } -} - -FontDataEditor::FontDataEditor() { - chk = memnew(CheckBox); - chk->set_text(TTR("On")); - chk->set_flat(true); - add_child(chk); - - button = memnew(Button); - button->set_flat(true); - add_child(button); -} - -/*************************************************************************/ - bool EditorInspectorPluginFont::can_handle(Object *p_object) { return Object::cast_to<FontData>(p_object) != nullptr; } @@ -291,34 +92,6 @@ void EditorInspectorPluginFont::parse_begin(Object *p_object) { } bool EditorInspectorPluginFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { - if (p_path.begins_with("language_support_override/") && p_object->is_class("FontData")) { - String lang = p_path.replace("language_support_override/", ""); - - FontDataEditor *editor = memnew(FontDataEditor); - if (lang != "_new") { - editor->init_lang_edit(); - } else { - editor->init_lang_add(); - } - add_property_editor(p_path, editor); - - return true; - } - - if (p_path.begins_with("script_support_override/") && p_object->is_class("FontData")) { - String script = p_path.replace("script_support_override/", ""); - - FontDataEditor *editor = memnew(FontDataEditor); - if (script != "_new") { - editor->init_script_edit(); - } else { - editor->init_script_add(); - } - add_property_editor(p_path, editor); - - return true; - } - return false; } diff --git a/editor/plugins/font_editor_plugin.h b/editor/plugins/font_editor_plugin.h index 71464003a0..3530815872 100644 --- a/editor/plugins/font_editor_plugin.h +++ b/editor/plugins/font_editor_plugin.h @@ -55,39 +55,6 @@ public: /*************************************************************************/ -class FontDataEditor : public EditorProperty { - GDCLASS(FontDataEditor, EditorProperty); - - LineEdit *le = nullptr; - CheckBox *chk = nullptr; - Button *button = nullptr; - - void toggle_lang(bool p_pressed); - void toggle_script(bool p_pressed); - void add_lang(); - void add_script(); - void remove_lang(); - void remove_script(); - -protected: - void _notification(int p_what); - - static void _bind_methods(); - -public: - virtual Size2 get_minimum_size() const override; - virtual void update_property() override; - - void init_lang_add(); - void init_lang_edit(); - void init_script_add(); - void init_script_edit(); - - FontDataEditor(); -}; - -/*************************************************************************/ - class EditorInspectorPluginFont : public EditorInspectorPlugin { GDCLASS(EditorInspectorPluginFont, EditorInspectorPlugin); diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp index 5184e837ce..dd91df747a 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp @@ -60,13 +60,16 @@ void GPUParticles2DEditorPlugin::_file_selected(const String &p_file) { void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) { switch (p_idx) { case MENU_GENERATE_VISIBILITY_RECT: { - float gen_time = particles->get_lifetime(); - if (gen_time < 1.0) { - generate_seconds->set_value(1.0); + // Add one second to the default generation lifetime, since the progress is updated every second. + generate_seconds->set_value(MAX(1.0, trunc(particles->get_lifetime()) + 1.0)); + + if (generate_seconds->get_value() >= 11.0 + CMP_EPSILON) { + // Only pop up the time dialog if the particle's lifetime is long enough to warrant shortening it. + generate_visibility_rect->popup_centered(); } else { - generate_seconds->set_value(trunc(gen_time) + 1.0); + // Generate the visibility rect immediately. + _generate_visibility_rect(); } - generate_visibility_rect->popup_centered(); } break; case MENU_LOAD_EMISSION_MASK: { file->popup_file_dialog(); @@ -100,11 +103,11 @@ void GPUParticles2DEditorPlugin::_menu_callback(int p_idx) { } void GPUParticles2DEditorPlugin::_generate_visibility_rect() { - float time = generate_seconds->get_value(); + double time = generate_seconds->get_value(); float running = 0.0; - EditorProgress ep("gen_vrect", TTR("Generating Visibility Rect"), int(time)); + EditorProgress ep("gen_vrect", TTR("Generating Visibility Rect (Waiting for Particle Simulation)"), int(time)); bool was_emitting = particles->is_emitting(); if (!was_emitting) { diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp index 8576082597..903a3689b0 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp @@ -238,14 +238,16 @@ void GPUParticles3DEditor::_notification(int p_notification) { void GPUParticles3DEditor::_menu_option(int p_option) { switch (p_option) { case MENU_OPTION_GENERATE_AABB: { - float gen_time = node->get_lifetime(); + // Add one second to the default generation lifetime, since the progress is updated every second. + generate_seconds->set_value(MAX(1.0, trunc(node->get_lifetime()) + 1.0)); - if (gen_time < 1.0) { - generate_seconds->set_value(1.0); + if (generate_seconds->get_value() >= 11.0 + CMP_EPSILON) { + // Only pop up the time dialog if the particle's lifetime is long enough to warrant shortening it. + generate_aabb->popup_centered(); } else { - generate_seconds->set_value(trunc(gen_time) + 1.0); + // Generate the visibility AABB immediately. + _generate_aabb(); } - generate_aabb->popup_centered(); } break; case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { Ref<ParticlesMaterial> material = node->get_process_material(); @@ -282,11 +284,11 @@ void GPUParticles3DEditor::_menu_option(int p_option) { } void GPUParticles3DEditor::_generate_aabb() { - float time = generate_seconds->get_value(); + double time = generate_seconds->get_value(); - float running = 0.0; + double running = 0.0; - EditorProgress ep("gen_aabb", TTR("Generating AABB"), int(time)); + EditorProgress ep("gen_aabb", TTR("Generating Visibility AABB (Waiting for Particle Simulation)"), int(time)); bool was_emitting = node->is_emitting(); if (!was_emitting) { diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 39ab3215ff..768f29e15a 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -32,7 +32,7 @@ #include "editor/editor_scale.h" -void MeshEditor::_gui_input(Ref<InputEvent> p_event) { +void MeshEditor::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventMouseMotion> mm = p_event; @@ -103,10 +103,6 @@ void MeshEditor::_button_pressed(Node *p_button) { } } -void MeshEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &MeshEditor::_gui_input); -} - MeshEditor::MeshEditor() { viewport = memnew(SubViewport); Ref<World3D> world_3d; diff --git a/editor/plugins/mesh_editor_plugin.h b/editor/plugins/mesh_editor_plugin.h index 455fcb5fe9..1e88b70202 100644 --- a/editor/plugins/mesh_editor_plugin.h +++ b/editor/plugins/mesh_editor_plugin.h @@ -64,8 +64,7 @@ class MeshEditor : public SubViewportContainer { protected: void _notification(int p_what); - void _gui_input(Ref<InputEvent> p_event); - static void _bind_methods(); + void gui_input(const Ref<InputEvent> &p_event) override; public: void edit(Ref<Mesh> p_mesh); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index b8cbaaf7c1..d04e88e915 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -66,7 +66,7 @@ #include "scene/resources/cylinder_shape_3d.h" #include "scene/resources/height_map_shape_3d.h" #include "scene/resources/primitive_meshes.h" -#include "scene/resources/ray_shape_3d.h" +#include "scene/resources/separation_ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/surface_tool.h" #include "scene/resources/world_margin_shape_3d.h" @@ -106,9 +106,7 @@ void EditorNode3DGizmo::clear() { } void EditorNode3DGizmo::redraw() { - if (get_script_instance() && get_script_instance()->has_method("_redraw")) { - get_script_instance()->call("_redraw"); - } else { + if (!GDVIRTUAL_CALL(_redraw)) { ERR_FAIL_COND(!gizmo_plugin); gizmo_plugin->redraw(this); } @@ -119,8 +117,9 @@ void EditorNode3DGizmo::redraw() { } String EditorNode3DGizmo::get_handle_name(int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_get_handle_name")) { - return get_script_instance()->call("_get_handle_name", p_id); + String ret; + if (GDVIRTUAL_CALL(_get_handle_name, p_id, ret)) { + return ret; } ERR_FAIL_COND_V(!gizmo_plugin, ""); @@ -128,8 +127,9 @@ String EditorNode3DGizmo::get_handle_name(int p_id) const { } bool EditorNode3DGizmo::is_handle_highlighted(int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_is_handle_highlighted")) { - return get_script_instance()->call("_is_handle_highlighted", p_id); + bool success; + if (GDVIRTUAL_CALL(_is_handle_highlighted, p_id, success)) { + return success; } ERR_FAIL_COND_V(!gizmo_plugin, false); @@ -137,8 +137,9 @@ bool EditorNode3DGizmo::is_handle_highlighted(int p_id) const { } Variant EditorNode3DGizmo::get_handle_value(int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_get_handle_value")) { - return get_script_instance()->call("_get_handle_value", p_id); + Variant value; + if (GDVIRTUAL_CALL(_get_handle_value, p_id, value)) { + return value; } ERR_FAIL_COND_V(!gizmo_plugin, Variant()); @@ -146,8 +147,7 @@ Variant EditorNode3DGizmo::get_handle_value(int p_id) const { } void EditorNode3DGizmo::set_handle(int p_id, Camera3D *p_camera, const Point2 &p_point) { - if (get_script_instance() && get_script_instance()->has_method("_set_handle")) { - get_script_instance()->call("_set_handle", p_id, p_camera, p_point); + if (GDVIRTUAL_CALL(_set_handle, p_id, p_camera, p_point)) { return; } @@ -156,8 +156,7 @@ void EditorNode3DGizmo::set_handle(int p_id, Camera3D *p_camera, const Point2 &p } void EditorNode3DGizmo::commit_handle(int p_id, const Variant &p_restore, bool p_cancel) { - if (get_script_instance() && get_script_instance()->has_method("_commit_handle")) { - get_script_instance()->call("_commit_handle", p_id, p_restore, p_cancel); + if (GDVIRTUAL_CALL(_commit_handle, p_id, p_restore, p_cancel)) { return; } @@ -166,8 +165,9 @@ void EditorNode3DGizmo::commit_handle(int p_id, const Variant &p_restore, bool p } int EditorNode3DGizmo::subgizmos_intersect_ray(Camera3D *p_camera, const Vector2 &p_point) const { - if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_ray")) { - return get_script_instance()->call("_subgizmos_intersect_ray", p_camera, p_point); + int id; + if (GDVIRTUAL_CALL(_subgizmos_intersect_ray, p_camera, p_point, id)) { + return id; } ERR_FAIL_COND_V(!gizmo_plugin, -1); @@ -175,12 +175,14 @@ int EditorNode3DGizmo::subgizmos_intersect_ray(Camera3D *p_camera, const Vector2 } Vector<int> EditorNode3DGizmo::subgizmos_intersect_frustum(const Camera3D *p_camera, const Vector<Plane> &p_frustum) const { - if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_frustum")) { - Array frustum; - for (int i = 0; i < p_frustum.size(); i++) { - frustum[i] = p_frustum[i]; - } - return get_script_instance()->call("_subgizmos_intersect_frustum", p_camera, frustum); + TypedArray<Plane> frustum; + frustum.resize(p_frustum.size()); + for (int i = 0; i < p_frustum.size(); i++) { + frustum[i] = p_frustum[i]; + } + Vector<int> ret; + if (GDVIRTUAL_CALL(_subgizmos_intersect_frustum, p_camera, frustum, ret)) { + return ret; } ERR_FAIL_COND_V(!gizmo_plugin, Vector<int>()); @@ -188,8 +190,9 @@ Vector<int> EditorNode3DGizmo::subgizmos_intersect_frustum(const Camera3D *p_cam } Transform3D EditorNode3DGizmo::get_subgizmo_transform(int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_get_subgizmo_transform")) { - return get_script_instance()->call("_get_subgizmo_transform", p_id); + Transform3D ret; + if (GDVIRTUAL_CALL(_get_subgizmo_transform, p_id, ret)) { + return ret; } ERR_FAIL_COND_V(!gizmo_plugin, Transform3D()); @@ -197,8 +200,7 @@ Transform3D EditorNode3DGizmo::get_subgizmo_transform(int p_id) const { } void EditorNode3DGizmo::set_subgizmo_transform(int p_id, Transform3D p_transform) { - if (get_script_instance() && get_script_instance()->has_method("_set_subgizmo_transform")) { - get_script_instance()->call("_set_subgizmo_transform", p_id, p_transform); + if (GDVIRTUAL_CALL(_set_subgizmo_transform, p_id, p_transform)) { return; } @@ -207,18 +209,13 @@ void EditorNode3DGizmo::set_subgizmo_transform(int p_id, Transform3D p_transform } void EditorNode3DGizmo::commit_subgizmos(const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) { - if (get_script_instance() && get_script_instance()->has_method("_commit_subgizmos")) { - Array ids; - for (int i = 0; i < p_ids.size(); i++) { - ids[i] = p_ids[i]; - } - - Array restore; - for (int i = 0; i < p_restore.size(); i++) { - restore[i] = p_restore[i]; - } + TypedArray<Transform3D> restore; + restore.resize(p_restore.size()); + for (int i = 0; i < p_restore.size(); i++) { + restore[i] = p_restore[i]; + } - get_script_instance()->call("_commit_subgizmos", ids, restore, p_cancel); + if (GDVIRTUAL_CALL(_commit_subgizmos, p_ids, restore, p_cancel)) { return; } @@ -838,26 +835,19 @@ void EditorNode3DGizmo::_bind_methods() { ClassDB::bind_method(D_METHOD("is_subgizmo_selected"), &EditorNode3DGizmo::is_subgizmo_selected); ClassDB::bind_method(D_METHOD("get_subgizmo_selection"), &EditorNode3DGizmo::get_subgizmo_selection); - BIND_VMETHOD(MethodInfo("_redraw")); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", PropertyInfo(Variant::INT, "id"))); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", PropertyInfo(Variant::INT, "id"))); + GDVIRTUAL_BIND(_redraw); + GDVIRTUAL_BIND(_get_handle_name, "id"); + GDVIRTUAL_BIND(_is_handle_highlighted, "id"); - MethodInfo hvget(Variant::NIL, "_get_handle_value", PropertyInfo(Variant::INT, "id")); - hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - BIND_VMETHOD(hvget); + GDVIRTUAL_BIND(_get_handle_value, "id"); + GDVIRTUAL_BIND(_set_handle, "id", "camera", "point"); + GDVIRTUAL_BIND(_commit_handle, "id", "restore", "cancel"); - BIND_VMETHOD(MethodInfo("_set_handle", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point"))); - MethodInfo cm = MethodInfo("_commit_handle", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); - cm.default_arguments.push_back(false); - BIND_VMETHOD(cm); - - BIND_VMETHOD(MethodInfo(Variant::INT, "_subgizmos_intersect_ray", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point"))); - BIND_VMETHOD(MethodInfo(Variant::PACKED_INT32_ARRAY, "_subgizmos_intersect_frustum", PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::ARRAY, "frustum"))); - BIND_VMETHOD(MethodInfo(Variant::TRANSFORM3D, "_get_subgizmo_transform", PropertyInfo(Variant::INT, "id"))); - BIND_VMETHOD(MethodInfo("_set_subgizmo_transform", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM3D, "transform"))); - MethodInfo cs = MethodInfo("_commit_subgizmos", PropertyInfo(Variant::PACKED_INT32_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel")); - cs.default_arguments.push_back(false); - BIND_VMETHOD(cs); + GDVIRTUAL_BIND(_subgizmos_intersect_ray, "camera", "point"); + GDVIRTUAL_BIND(_subgizmos_intersect_frustum, "camera", "frustum"); + GDVIRTUAL_BIND(_set_subgizmo_transform, "id", "transform"); + GDVIRTUAL_BIND(_get_subgizmo_transform, "id"); + GDVIRTUAL_BIND(_commit_subgizmos, "ids", "restores", "cancel"); } EditorNode3DGizmo::EditorNode3DGizmo() { @@ -1043,11 +1033,6 @@ Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::get_gizmo(Node3D *p_spatial) { } void EditorNode3DGizmoPlugin::_bind_methods() { -#define GIZMO_REF PropertyInfo(Variant::OBJECT, "gizmo", PROPERTY_HINT_RESOURCE_TYPE, "EditorNode3DGizmo") - - BIND_VMETHOD(MethodInfo(Variant::BOOL, "_has_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); - BIND_VMETHOD(MethodInfo(GIZMO_REF, "_create_gizmo", PropertyInfo(Variant::OBJECT, "spatial", PROPERTY_HINT_RESOURCE_TYPE, "Node3D"))); - ClassDB::bind_method(D_METHOD("create_material", "name", "color", "billboard", "on_top", "use_vertex_color"), &EditorNode3DGizmoPlugin::create_material, DEFVAL(false), DEFVAL(false), DEFVAL(false)); ClassDB::bind_method(D_METHOD("create_icon_material", "name", "texture", "on_top", "color"), &EditorNode3DGizmoPlugin::create_icon_material, DEFVAL(false), DEFVAL(Color(1, 1, 1, 1))); ClassDB::bind_method(D_METHOD("create_handle_material", "name", "billboard", "texture"), &EditorNode3DGizmoPlugin::create_handle_material, DEFVAL(false), DEFVAL(Variant())); @@ -1055,45 +1040,42 @@ void EditorNode3DGizmoPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_material", "name", "gizmo"), &EditorNode3DGizmoPlugin::get_material, DEFVAL(Ref<EditorNode3DGizmo>())); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_gizmo_name")); - BIND_VMETHOD(MethodInfo(Variant::INT, "_get_priority")); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "_can_be_hidden")); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_selectable_when_hidden")); + GDVIRTUAL_BIND(_has_gizmo, "for_node_3d"); + GDVIRTUAL_BIND(_create_gizmo, "for_node_3d"); - BIND_VMETHOD(MethodInfo("_redraw", GIZMO_REF)); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_handle_name", GIZMO_REF, PropertyInfo(Variant::INT, "id"))); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_handle_highlighted", GIZMO_REF, PropertyInfo(Variant::INT, "id"))); + GDVIRTUAL_BIND(_get_gizmo_name); + GDVIRTUAL_BIND(_get_priority); + GDVIRTUAL_BIND(_can_be_hidden); + GDVIRTUAL_BIND(_is_selectable_when_hidden); - MethodInfo hvget(Variant::NIL, "_get_handle_value", GIZMO_REF, PropertyInfo(Variant::INT, "id")); - hvget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - BIND_VMETHOD(hvget); + GDVIRTUAL_BIND(_redraw, "gizmo"); + GDVIRTUAL_BIND(_get_handle_name, "gizmo", "handle_id"); + GDVIRTUAL_BIND(_is_handle_highlighted, "gizmo", "handle_id"); + GDVIRTUAL_BIND(_get_handle_value, "gizmo", "handle_id"); - BIND_VMETHOD(MethodInfo("_set_handle", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point"))); - MethodInfo cm = MethodInfo("_commit_handle", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::NIL, "restore"), PropertyInfo(Variant::BOOL, "cancel")); - cm.default_arguments.push_back(false); - BIND_VMETHOD(cm); + GDVIRTUAL_BIND(_set_handle, "gizmo", "handle_id", "camera", "screen_pos"); + GDVIRTUAL_BIND(_commit_handle, "gizmo", "handle_id", "restore", "cancel"); - BIND_VMETHOD(MethodInfo(Variant::INT, "_subgizmos_intersect_ray", GIZMO_REF, PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::VECTOR2, "point"))); - BIND_VMETHOD(MethodInfo(Variant::PACKED_INT32_ARRAY, "_subgizmos_intersect_frustum", GIZMO_REF, PropertyInfo(Variant::OBJECT, "camera", PROPERTY_HINT_RESOURCE_TYPE, "Camera3D"), PropertyInfo(Variant::ARRAY, "frustum"))); - BIND_VMETHOD(MethodInfo(Variant::TRANSFORM3D, "_get_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id"))); - BIND_VMETHOD(MethodInfo("_set_subgizmo_transform", GIZMO_REF, PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::TRANSFORM3D, "transform"))); - MethodInfo cs = MethodInfo("_commit_subgizmos", GIZMO_REF, PropertyInfo(Variant::PACKED_INT32_ARRAY, "ids"), PropertyInfo(Variant::ARRAY, "restore"), PropertyInfo(Variant::BOOL, "cancel")); - cs.default_arguments.push_back(false); - BIND_VMETHOD(cs); - -#undef GIZMO_REF + GDVIRTUAL_BIND(_subgizmos_intersect_ray, "gizmo", "camera", "screen_pos"); + GDVIRTUAL_BIND(_subgizmos_intersect_frustum, "gizmo", "camera", "frustum_planes"); + GDVIRTUAL_BIND(_get_subgizmo_transform, "gizmo", "subgizmo_id"); + GDVIRTUAL_BIND(_set_subgizmo_transform, "gizmo", "subgizmo_id", "transform"); + GDVIRTUAL_BIND(_commit_subgizmos, "gizmo", "ids", "restores", "cancel"); + ; } bool EditorNode3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { - if (get_script_instance() && get_script_instance()->has_method("_has_gizmo")) { - return get_script_instance()->call("_has_gizmo", p_spatial); + bool success; + if (GDVIRTUAL_CALL(_has_gizmo, p_spatial, success)) { + return success; } return false; } Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) { - if (get_script_instance() && get_script_instance()->has_method("_create_gizmo")) { - return get_script_instance()->call("_create_gizmo", p_spatial); + Ref<EditorNode3DGizmo> ret; + if (GDVIRTUAL_CALL(_create_gizmo, p_spatial, ret)) { + return ret; } Ref<EditorNode3DGizmo> ref; @@ -1104,106 +1086,100 @@ Ref<EditorNode3DGizmo> EditorNode3DGizmoPlugin::create_gizmo(Node3D *p_spatial) } bool EditorNode3DGizmoPlugin::can_be_hidden() const { - if (get_script_instance() && get_script_instance()->has_method("_can_be_hidden")) { - return get_script_instance()->call("_can_be_hidden"); + bool ret; + if (GDVIRTUAL_CALL(_can_be_hidden, ret)) { + return ret; } return true; } bool EditorNode3DGizmoPlugin::is_selectable_when_hidden() const { - if (get_script_instance() && get_script_instance()->has_method("_is_selectable_when_hidden")) { - return get_script_instance()->call("_is_selectable_when_hidden"); + bool ret; + if (GDVIRTUAL_CALL(_is_selectable_when_hidden, ret)) { + return ret; } return false; } void EditorNode3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - if (get_script_instance() && get_script_instance()->has_method("_redraw")) { - Ref<EditorNode3DGizmo> ref(p_gizmo); - get_script_instance()->call("_redraw", ref); - } + GDVIRTUAL_CALL(_redraw, p_gizmo); } bool EditorNode3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_is_handle_highlighted")) { - return get_script_instance()->call("_is_handle_highlighted", p_gizmo, p_id); + bool ret; + if (GDVIRTUAL_CALL(_is_handle_highlighted, Ref<EditorNode3DGizmo>(p_gizmo), p_id, ret)) { + return ret; } return false; } String EditorNode3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_get_handle_name")) { - return get_script_instance()->call("_get_handle_name", p_gizmo, p_id); + String ret; + if (GDVIRTUAL_CALL(_get_handle_name, Ref<EditorNode3DGizmo>(p_gizmo), p_id, ret)) { + return ret; } return ""; } Variant EditorNode3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_get_handle_value")) { - return get_script_instance()->call("_get_handle_value", p_gizmo, p_id); + Variant ret; + if (GDVIRTUAL_CALL(_get_handle_value, Ref<EditorNode3DGizmo>(p_gizmo), p_id, ret)) { + return ret; } return Variant(); } void EditorNode3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, Camera3D *p_camera, const Point2 &p_point) { - if (get_script_instance() && get_script_instance()->has_method("_set_handle")) { - get_script_instance()->call("_set_handle", p_gizmo, p_id, p_camera, p_point); - } + GDVIRTUAL_CALL(_set_handle, Ref<EditorNode3DGizmo>(p_gizmo), p_id, p_camera, p_point); } void EditorNode3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, const Variant &p_restore, bool p_cancel) { - if (get_script_instance() && get_script_instance()->has_method("_commit_handle")) { - get_script_instance()->call("_commit_handle", p_gizmo, p_id, p_restore, p_cancel); - } + GDVIRTUAL_CALL(_commit_handle, Ref<EditorNode3DGizmo>(p_gizmo), p_id, p_restore, p_cancel); } int EditorNode3DGizmoPlugin::subgizmos_intersect_ray(const EditorNode3DGizmo *p_gizmo, Camera3D *p_camera, const Vector2 &p_point) const { - if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_ray")) { - return get_script_instance()->call("_subgizmos_intersect_ray", p_camera, p_point); + int ret; + if (GDVIRTUAL_CALL(_subgizmos_intersect_ray, Ref<EditorNode3DGizmo>(p_gizmo), p_camera, p_point, ret)) { + return ret; } return -1; } Vector<int> EditorNode3DGizmoPlugin::subgizmos_intersect_frustum(const EditorNode3DGizmo *p_gizmo, const Camera3D *p_camera, const Vector<Plane> &p_frustum) const { - if (get_script_instance() && get_script_instance()->has_method("_subgizmos_intersect_frustum")) { - Array frustum; - for (int i = 0; i < p_frustum.size(); i++) { - frustum[i] = p_frustum[i]; - } - return get_script_instance()->call("_subgizmos_intersect_frustum", p_camera, frustum); + TypedArray<Transform3D> frustum; + frustum.resize(p_frustum.size()); + for (int i = 0; i < p_frustum.size(); i++) { + frustum[i] = p_frustum[i]; + } + Vector<int> ret; + if (GDVIRTUAL_CALL(_subgizmos_intersect_frustum, Ref<EditorNode3DGizmo>(p_gizmo), p_camera, frustum, ret)) { + return ret; } return Vector<int>(); } Transform3D EditorNode3DGizmoPlugin::get_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id) const { - if (get_script_instance() && get_script_instance()->has_method("_get_subgizmo_transform")) { - return get_script_instance()->call("_get_subgizmo_transform", p_id); + Transform3D ret; + if (GDVIRTUAL_CALL(_get_subgizmo_transform, Ref<EditorNode3DGizmo>(p_gizmo), p_id, ret)) { + return ret; } return Transform3D(); } void EditorNode3DGizmoPlugin::set_subgizmo_transform(const EditorNode3DGizmo *p_gizmo, int p_id, Transform3D p_transform) { - if (get_script_instance() && get_script_instance()->has_method("_set_subgizmo_transform")) { - get_script_instance()->call("_set_subgizmo_transform", p_id, p_transform); - } + GDVIRTUAL_CALL(_set_subgizmo_transform, Ref<EditorNode3DGizmo>(p_gizmo), p_id, p_transform); } void EditorNode3DGizmoPlugin::commit_subgizmos(const EditorNode3DGizmo *p_gizmo, const Vector<int> &p_ids, const Vector<Transform3D> &p_restore, bool p_cancel) { - if (get_script_instance() && get_script_instance()->has_method("_commit_subgizmos")) { - Array ids; - for (int i = 0; i < p_ids.size(); i++) { - ids[i] = p_ids[i]; - } - - Array restore; - for (int i = 0; i < p_restore.size(); i++) { - restore[i] = p_restore[i]; - } - - get_script_instance()->call("_commit_subgizmos", ids, restore, p_cancel); + TypedArray<Transform3D> restore; + restore.resize(p_restore.size()); + for (int i = 0; i < p_restore.size(); i++) { + restore[i] = p_restore[i]; } + + GDVIRTUAL_CALL(_commit_subgizmos, Ref<EditorNode3DGizmo>(p_gizmo), p_ids, restore, p_cancel); } void EditorNode3DGizmoPlugin::set_state(int p_state) { @@ -2101,64 +2077,76 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->begin(Mesh::PRIMITIVE_LINES); surface_tool->set_material(material); - Vector<Transform3D> grests; + LocalVector<Transform3D> grests; grests.resize(skel->get_bone_count()); - Vector<int> bones; - Vector<float> weights; + LocalVector<int> bones; + LocalVector<float> weights; bones.resize(4); weights.resize(4); for (int i = 0; i < 4; i++) { - bones.write[i] = 0; - weights.write[i] = 0; + bones[i] = 0; + weights[i] = 0; } - weights.write[0] = 1; + weights[0] = 1; AABB aabb; Color bonecolor = Color(1.0, 0.4, 0.4, 0.3); Color rootcolor = Color(0.4, 1.0, 0.4, 0.1); - for (int i_bone = 0; i_bone < skel->get_bone_count(); i_bone++) { - int i = skel->get_process_order(i_bone); + //LocalVector<int> bones_to_process = skel->get_parentless_bones(); + LocalVector<int> bones_to_process; + bones_to_process = skel->get_parentless_bones(); - int parent = skel->get_bone_parent(i); + while (bones_to_process.size() > 0) { + int current_bone_idx = bones_to_process[0]; + bones_to_process.erase(current_bone_idx); - if (parent >= 0) { - grests.write[i] = grests[parent] * skel->get_bone_rest(i); + LocalVector<int> child_bones_vector; + child_bones_vector = skel->get_bone_children(current_bone_idx); + int child_bones_size = child_bones_vector.size(); - Vector3 v0 = grests[parent].origin; - Vector3 v1 = grests[i].origin; - Vector3 d = (v1 - v0).normalized(); - float dist = v0.distance_to(v1); + // You have children but no parent, then you must be a root/parentless bone. + if (child_bones_size >= 0 && skel->get_bone_parent(current_bone_idx) <= 0) { + grests[current_bone_idx] = skel->global_pose_to_local_pose(current_bone_idx, skel->get_bone_global_pose(current_bone_idx)); + } - //find closest axis - int closest = -1; - float closest_d = 0.0; + for (int i = 0; i < child_bones_size; i++) { + int child_bone_idx = child_bones_vector[i]; + + grests[child_bone_idx] = skel->global_pose_to_local_pose(child_bone_idx, skel->get_bone_global_pose(child_bone_idx)); + Vector3 v0 = grests[current_bone_idx].origin; + Vector3 v1 = grests[child_bone_idx].origin; + Vector3 d = skel->get_bone_rest(child_bone_idx).origin.normalized(); + real_t dist = skel->get_bone_rest(child_bone_idx).origin.length(); + // Find closest axis. + int closest = -1; + real_t closest_d = 0.0; for (int j = 0; j < 3; j++) { - float dp = Math::abs(grests[parent].basis[j].normalized().dot(d)); + real_t dp = Math::abs(grests[current_bone_idx].basis[j].normalized().dot(d)); if (j == 0 || dp > closest_d) { closest = j; } } - //find closest other + // Find closest other. Vector3 first; Vector3 points[4]; - int pointidx = 0; + int point_idx = 0; for (int j = 0; j < 3; j++) { - bones.write[0] = parent; + bones[0] = current_bone_idx; surface_tool->set_bones(bones); surface_tool->set_weights(weights); surface_tool->set_color(rootcolor); - surface_tool->add_vertex(v0 - grests[parent].basis[j].normalized() * dist * 0.05); + surface_tool->add_vertex(v0 - grests[current_bone_idx].basis[j].normalized() * dist * 0.05); surface_tool->set_bones(bones); surface_tool->set_weights(weights); surface_tool->set_color(rootcolor); - surface_tool->add_vertex(v0 + grests[parent].basis[j].normalized() * dist * 0.05); + surface_tool->add_vertex(v0 + grests[current_bone_idx].basis[j].normalized() * dist * 0.05); if (j == closest) { continue; @@ -2166,7 +2154,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3 axis; if (first == Vector3()) { - axis = d.cross(d.cross(grests[parent].basis[j])).normalized(); + axis = d.cross(d.cross(grests[current_bone_idx].basis[j])).normalized(); first = axis; } else { axis = d.cross(first).normalized(); @@ -2179,7 +2167,7 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3 point = v0 + d * dist * 0.2; point += axis * dist * 0.1; - bones.write[0] = parent; + bones[0] = current_bone_idx; surface_tool->set_bones(bones); surface_tool->set_weights(weights); surface_tool->set_color(bonecolor); @@ -2189,23 +2177,22 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->set_color(bonecolor); surface_tool->add_vertex(point); - bones.write[0] = parent; + bones[0] = current_bone_idx; surface_tool->set_bones(bones); surface_tool->set_weights(weights); surface_tool->set_color(bonecolor); surface_tool->add_vertex(point); - bones.write[0] = i; + bones[0] = child_bone_idx; surface_tool->set_bones(bones); surface_tool->set_weights(weights); surface_tool->set_color(bonecolor); surface_tool->add_vertex(v1); - points[pointidx++] = point; + points[point_idx++] = point; } } - SWAP(points[1], points[2]); for (int j = 0; j < 4; j++) { - bones.write[0] = parent; + bones[0] = current_bone_idx; surface_tool->set_bones(bones); surface_tool->set_weights(weights); surface_tool->set_color(bonecolor); @@ -2215,9 +2202,9 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { surface_tool->set_color(bonecolor); surface_tool->add_vertex(points[(j + 1) % 4]); } - } else { - grests.write[i] = skel->get_bone_rest(i); - bones.write[0] = i; + + // Add the bone's children to the list of bones to be processed. + bones_to_process.push_back(child_bones_vector[i]); } } @@ -4081,7 +4068,7 @@ String CollisionShape3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_g return p_id == 0 ? "Radius" : "Height"; } - if (Object::cast_to<RayShape3D>(*s)) { + if (Object::cast_to<SeparationRayShape3D>(*s)) { return "Length"; } @@ -4108,7 +4095,7 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p if (Object::cast_to<CapsuleShape3D>(*s)) { Ref<CapsuleShape3D> cs2 = s; - return p_id == 0 ? cs2->get_radius() : cs2->get_height(); + return Vector2(cs2->get_radius(), cs2->get_height()); } if (Object::cast_to<CylinderShape3D>(*s)) { @@ -4116,8 +4103,8 @@ Variant CollisionShape3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p return p_id == 0 ? cs2->get_radius() : cs2->get_height(); } - if (Object::cast_to<RayShape3D>(*s)) { - Ref<RayShape3D> cs2 = s; + if (Object::cast_to<SeparationRayShape3D>(*s)) { + Ref<SeparationRayShape3D> cs2 = s; return cs2->get_length(); } @@ -4156,8 +4143,8 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i ss->set_radius(d); } - if (Object::cast_to<RayShape3D>(*s)) { - Ref<RayShape3D> rs = s; + if (Object::cast_to<SeparationRayShape3D>(*s)) { + Ref<SeparationRayShape3D> rs = s; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), Vector3(0, 0, 4096), sg[0], sg[1], ra, rb); float d = ra.z; @@ -4194,14 +4181,11 @@ void CollisionShape3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, i if (Object::cast_to<CapsuleShape3D>(*s)) { Vector3 axis; - axis[p_id == 0 ? 0 : 2] = 1.0; + axis[p_id == 0 ? 0 : 1] = 1.0; Ref<CapsuleShape3D> cs2 = s; Vector3 ra, rb; Geometry3D::get_closest_points_between_segments(Vector3(), axis * 4096, sg[0], sg[1], ra, rb); float d = axis.dot(ra); - if (p_id == 1) { - d -= cs2->get_radius(); - } if (Node3DEditor::get_singleton()->is_snap_enabled()) { d = Math::snapped(d, Node3DEditor::get_singleton()->get_translate_snap()); @@ -4279,12 +4263,11 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo if (Object::cast_to<CapsuleShape3D>(*s)) { Ref<CapsuleShape3D> ss = s; + Vector2 values = p_restore; + if (p_cancel) { - if (p_id == 0) { - ss->set_radius(p_restore); - } else { - ss->set_height(p_restore); - } + ss->set_radius(values[0]); + ss->set_height(values[1]); return; } @@ -4292,12 +4275,12 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo if (p_id == 0) { ur->create_action(TTR("Change Capsule Shape Radius")); ur->add_do_method(ss.ptr(), "set_radius", ss->get_radius()); - ur->add_undo_method(ss.ptr(), "set_radius", p_restore); } else { ur->create_action(TTR("Change Capsule Shape Height")); ur->add_do_method(ss.ptr(), "set_height", ss->get_height()); - ur->add_undo_method(ss.ptr(), "set_height", p_restore); } + ur->add_undo_method(ss.ptr(), "set_radius", values[0]); + ur->add_undo_method(ss.ptr(), "set_height", values[1]); ur->commit_action(); } @@ -4331,15 +4314,15 @@ void CollisionShape3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo ur->commit_action(); } - if (Object::cast_to<RayShape3D>(*s)) { - Ref<RayShape3D> ss = s; + if (Object::cast_to<SeparationRayShape3D>(*s)) { + Ref<SeparationRayShape3D> ss = s; if (p_cancel) { ss->set_length(p_restore); return; } UndoRedo *ur = Node3DEditor::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Ray Shape Length")); + ur->create_action(TTR("Change Separation Ray Shape Length")); ur->add_do_method(ss.ptr(), "set_length", ss->get_length()); ur->add_undo_method(ss.ptr(), "set_length", p_restore); ur->commit_action(); @@ -4437,7 +4420,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> points; - Vector3 d(0, height * 0.5, 0); + Vector3 d(0, height * 0.5 - radius, 0); for (int i = 0; i < 360; i++) { float ra = Math::deg2rad((float)i); float rb = Math::deg2rad((float)i + 1); @@ -4496,7 +4479,7 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> handles; handles.push_back(Vector3(cs2->get_radius(), 0, 0)); - handles.push_back(Vector3(0, cs2->get_height() * 0.5 + cs2->get_radius(), 0)); + handles.push_back(Vector3(0, cs2->get_height() * 0.5, 0)); p_gizmo->add_handles(handles, handles_material); } @@ -4614,8 +4597,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_collision_segments(cs2->get_debug_mesh_lines()); } - if (Object::cast_to<RayShape3D>(*s)) { - Ref<RayShape3D> rs = s; + if (Object::cast_to<SeparationRayShape3D>(*s)) { + Ref<SeparationRayShape3D> rs = s; Vector<Vector3> points; points.push_back(Vector3()); diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index 53f602460c..415ed5da5c 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -31,11 +31,12 @@ #ifndef NODE_3D_EDITOR_GIZMOS_H #define NODE_3D_EDITOR_GIZMOS_H +#include "core/templates/local_vector.h" #include "core/templates/ordered_hash_map.h" +#include "scene/3d/camera_3d.h" #include "scene/3d/node_3d.h" #include "scene/3d/skeleton_3d.h" -class Camera3D; class Timer; class EditorNode3DGizmoPlugin; @@ -63,7 +64,7 @@ class EditorNode3DGizmo : public Node3DGizmo { Vector<Vector3> secondary_handles; Vector<int> secondary_handle_ids; - float selectable_icon_size; + real_t selectable_icon_size; bool billboard_handle; bool valid; @@ -78,6 +79,19 @@ protected: EditorNode3DGizmoPlugin *gizmo_plugin; + GDVIRTUAL0(_redraw) + GDVIRTUAL1RC(String, _get_handle_name, int) + GDVIRTUAL1RC(bool, _is_handle_highlighted, int) + + GDVIRTUAL1RC(Variant, _get_handle_value, int) + GDVIRTUAL3(_set_handle, int, const Camera3D *, Vector2) + GDVIRTUAL3(_commit_handle, int, Variant, bool) + + GDVIRTUAL2RC(int, _subgizmos_intersect_ray, const Camera3D *, Vector2) + GDVIRTUAL2RC(Vector<int>, _subgizmos_intersect_frustum, const Camera3D *, TypedArray<Plane>) + GDVIRTUAL1RC(Transform3D, _get_subgizmo_transform, int) + GDVIRTUAL2(_set_subgizmo_transform, int, Transform3D) + GDVIRTUAL3(_commit_subgizmos, Vector<int>, TypedArray<Transform3D>, bool) public: void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1)); void add_vertices(const Vector<Vector3> &p_vertices, const Ref<Material> &p_material, Mesh::PrimitiveType p_primitive_type, bool p_billboard = false, const Color &p_modulate = Color(1, 1, 1)); @@ -144,6 +158,28 @@ protected: virtual bool has_gizmo(Node3D *p_spatial); virtual Ref<EditorNode3DGizmo> create_gizmo(Node3D *p_spatial); + GDVIRTUAL1RC(bool, _has_gizmo, Node3D *) + GDVIRTUAL1RC(Ref<EditorNode3DGizmo>, _create_gizmo, Node3D *) + + GDVIRTUAL0RC(String, _get_gizmo_name) + GDVIRTUAL0RC(int, _get_priority) + GDVIRTUAL0RC(bool, _can_be_hidden) + GDVIRTUAL0RC(bool, _is_selectable_when_hidden) + + GDVIRTUAL1(_redraw, Ref<EditorNode3DGizmo>) + GDVIRTUAL2RC(String, _get_handle_name, Ref<EditorNode3DGizmo>, int) + GDVIRTUAL2RC(bool, _is_handle_highlighted, Ref<EditorNode3DGizmo>, int) + GDVIRTUAL2RC(Variant, _get_handle_value, Ref<EditorNode3DGizmo>, int) + + GDVIRTUAL4(_set_handle, Ref<EditorNode3DGizmo>, int, const Camera3D *, Vector2) + GDVIRTUAL4(_commit_handle, Ref<EditorNode3DGizmo>, int, Variant, bool) + + GDVIRTUAL3RC(int, _subgizmos_intersect_ray, Ref<EditorNode3DGizmo>, const Camera3D *, Vector2) + GDVIRTUAL3RC(Vector<int>, _subgizmos_intersect_frustum, Ref<EditorNode3DGizmo>, const Camera3D *, TypedArray<Plane>) + GDVIRTUAL2RC(Transform3D, _get_subgizmo_transform, Ref<EditorNode3DGizmo>, int) + GDVIRTUAL3(_set_subgizmo_transform, Ref<EditorNode3DGizmo>, int, Transform3D) + GDVIRTUAL4(_commit_subgizmos, Ref<EditorNode3DGizmo>, Vector<int>, TypedArray<Transform3D>, bool) + public: void create_material(const String &p_name, const Color &p_color, bool p_billboard = false, bool p_on_top = false, bool p_use_vertex_color = false); void create_icon_material(const String &p_name, const Ref<Texture2D> &p_texture, bool p_on_top = false, const Color &p_albedo = Color(1, 1, 1, 1)); diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 5ed8205475..291cafab2b 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -122,31 +122,28 @@ void ViewportRotationControl::_draw() { } void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) { - bool focused = focused_axis == p_axis.axis; - bool positive = p_axis.axis < 3; - bool front = (Math::abs(p_axis.z_axis) <= 0.001 && positive) || p_axis.z_axis > 0.001; - int direction = p_axis.axis % 3; + const bool focused = focused_axis == p_axis.axis; + const bool positive = p_axis.axis < 3; + const int direction = p_axis.axis % 3; - Color axis_color = axis_colors[direction]; - - if (!front) { - axis_color = axis_color.darkened(0.4); - } - Color c = focused ? Color(0.9, 0.9, 0.9) : axis_color; + const Color axis_color = axis_colors[direction]; + const double alpha = focused ? 1.0 : ((p_axis.z_axis + 1.0) / 2.0) * 0.5 + 0.5; + const Color c = focused ? Color(0.9, 0.9, 0.9) : Color(axis_color.r, axis_color.g, axis_color.b, alpha); if (positive) { - Vector2i center = get_size() / 2.0; + // Draw axis lines for the positive axes. + const Vector2i center = get_size() / 2.0; draw_line(center, p_axis.screen_point, c, 1.5 * EDSCALE); - } - if (front) { draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c); - if (positive) { - String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z"); - draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0)); - } + + // Draw the axis letter for the positive axes. + const String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z"); + draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha)); } else { - draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS * (0.55 + (0.2 * (1.0 + p_axis.z_axis))), c); + // Draw an outline around the negative axes. + draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c); + draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS * 0.8, c.darkened(0.4)); } } @@ -184,7 +181,7 @@ void ViewportRotationControl::_get_sorted_axis(Vector<Axis2D> &r_axis) { r_axis.sort_custom<Axis2DCompare>(); } -void ViewportRotationControl::_gui_input(Ref<InputEvent> p_event) { +void ViewportRotationControl::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); const Ref<InputEventMouseButton> mb = p_event; @@ -255,10 +252,6 @@ void ViewportRotationControl::set_viewport(Node3DEditorViewport *p_viewport) { viewport = p_viewport; } -void ViewportRotationControl::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &ViewportRotationControl::_gui_input); -} - void Node3DEditorViewport::_update_camera(real_t p_interp_delta) { bool is_orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL; @@ -693,53 +686,55 @@ void Node3DEditorViewport::_select_region() { Node3D *single_selected = spatial_editor->get_single_selected_node(); Node3DEditorSelectedItem *se = editor_selection->get_node_editor_data<Node3DEditorSelectedItem>(single_selected); - Ref<EditorNode3DGizmo> old_gizmo; - if (!clicked_wants_append) { - se->subgizmos.clear(); - old_gizmo = se->gizmo; - se->gizmo.unref(); - } - - bool found_subgizmos = false; - Vector<Ref<Node3DGizmo>> gizmos = single_selected->get_gizmos(); - for (int j = 0; j < gizmos.size(); j++) { - Ref<EditorNode3DGizmo> seg = gizmos[j]; - if (!seg.is_valid()) { - continue; + if (se) { + Ref<EditorNode3DGizmo> old_gizmo; + if (!clicked_wants_append) { + se->subgizmos.clear(); + old_gizmo = se->gizmo; + se->gizmo.unref(); } - if (se->gizmo.is_valid() && se->gizmo != seg) { - continue; - } + bool found_subgizmos = false; + Vector<Ref<Node3DGizmo>> gizmos = single_selected->get_gizmos(); + for (int j = 0; j < gizmos.size(); j++) { + Ref<EditorNode3DGizmo> seg = gizmos[j]; + if (!seg.is_valid()) { + continue; + } - Vector<int> subgizmos = seg->subgizmos_intersect_frustum(camera, frustum); - if (!subgizmos.is_empty()) { - se->gizmo = seg; - for (int i = 0; i < subgizmos.size(); i++) { - int subgizmo_id = subgizmos[i]; - if (!se->subgizmos.has(subgizmo_id)) { - se->subgizmos.insert(subgizmo_id, se->gizmo->get_subgizmo_transform(subgizmo_id)); + if (se->gizmo.is_valid() && se->gizmo != seg) { + continue; + } + + Vector<int> subgizmos = seg->subgizmos_intersect_frustum(camera, frustum); + if (!subgizmos.is_empty()) { + se->gizmo = seg; + for (int i = 0; i < subgizmos.size(); i++) { + int subgizmo_id = subgizmos[i]; + if (!se->subgizmos.has(subgizmo_id)) { + se->subgizmos.insert(subgizmo_id, se->gizmo->get_subgizmo_transform(subgizmo_id)); + } } + found_subgizmos = true; + break; } - found_subgizmos = true; - break; } - } - if (!clicked_wants_append || found_subgizmos) { - if (se->gizmo.is_valid()) { - se->gizmo->redraw(); - } + if (!clicked_wants_append || found_subgizmos) { + if (se->gizmo.is_valid()) { + se->gizmo->redraw(); + } - if (old_gizmo != se->gizmo && old_gizmo.is_valid()) { - old_gizmo->redraw(); - } + if (old_gizmo != se->gizmo && old_gizmo.is_valid()) { + old_gizmo->redraw(); + } - spatial_editor->update_transform_gizmo(); - } + spatial_editor->update_transform_gizmo(); + } - if (found_subgizmos) { - return; + if (found_subgizmos) { + return; + } } } @@ -812,18 +807,66 @@ void Node3DEditorViewport::_select_region() { } void Node3DEditorViewport::_update_name() { - String view_mode = orthogonal ? TTR("Orthogonal") : TTR("Perspective"); + String name; - if (auto_orthogonal) { - view_mode += " [auto]"; + switch (view_type) { + case VIEW_TYPE_USER: { + if (orthogonal) { + name = TTR("Orthogonal"); + } else { + name = TTR("Perspective"); + } + } break; + case VIEW_TYPE_TOP: { + if (orthogonal) { + name = TTR("Top Orthogonal"); + } else { + name = TTR("Top Perspective"); + } + } break; + case VIEW_TYPE_BOTTOM: { + if (orthogonal) { + name = TTR("Bottom Orthogonal"); + } else { + name = TTR("Bottom Perspective"); + } + } break; + case VIEW_TYPE_LEFT: { + if (orthogonal) { + name = TTR("Left Orthogonal"); + } else { + name = TTR("Right Perspective"); + } + } break; + case VIEW_TYPE_RIGHT: { + if (orthogonal) { + name = TTR("Right Orthogonal"); + } else { + name = TTR("Right Perspective"); + } + } break; + case VIEW_TYPE_FRONT: { + if (orthogonal) { + name = TTR("Front Orthogonal"); + } else { + name = TTR("Front Perspective"); + } + } break; + case VIEW_TYPE_REAR: { + if (orthogonal) { + name = TTR("Rear Orthogonal"); + } else { + name = TTR("Rear Perspective"); + } + } break; } - if (name != "") { - view_menu->set_text(name + " " + view_mode); - } else { - view_menu->set_text(view_mode); + if (auto_orthogonal) { + // TRANSLATORS: This will be appended to the view name when Auto Orthogonal is enabled. + name += TTR(" [auto]"); } + view_menu->set_text(name); view_menu->set_size(Vector2(0, 0)); // resets the button size } @@ -1387,7 +1430,7 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { case TRANSFORM_VIEW: { _edit.plane = TRANSFORM_X_AXIS; set_message(TTR("X-Axis Transform."), 2); - name = ""; + view_type = VIEW_TYPE_USER; _update_name(); } break; case TRANSFORM_X_AXIS: { @@ -2328,7 +2371,7 @@ void Node3DEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, cons } else { cursor.y_rot += p_relative.x * radians_per_pixel; } - name = ""; + view_type = VIEW_TYPE_USER; _update_name(); } @@ -2366,7 +2409,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const Vector3 diff = prev_pos - pos; cursor.pos += diff; - name = ""; + view_type = VIEW_TYPE_USER; _update_name(); } @@ -2460,7 +2503,7 @@ static bool is_shortcut_pressed(const String &p_path) { return false; } const Input &input = *Input::get_singleton(); - int keycode = k->get_keycode(); + Key keycode = k->get_keycode(); return input.is_key_pressed(keycode); } @@ -2738,7 +2781,7 @@ void Node3DEditorViewport::_notification(int p_what) { if (show_fps) { cpu_time_history[cpu_time_history_index] = RS::get_singleton()->viewport_get_measured_render_time_cpu(viewport->get_viewport_rid()); cpu_time_history_index = (cpu_time_history_index + 1) % FRAME_TIME_HISTORY; - float cpu_time = 0.0; + double cpu_time = 0.0; for (int i = 0; i < FRAME_TIME_HISTORY; i++) { cpu_time += cpu_time_history[i]; } @@ -2748,7 +2791,7 @@ void Node3DEditorViewport::_notification(int p_what) { gpu_time_history[gpu_time_history_index] = RS::get_singleton()->viewport_get_measured_render_time_gpu(viewport->get_viewport_rid()); gpu_time_history_index = (gpu_time_history_index + 1) % FRAME_TIME_HISTORY; - float gpu_time = 0.0; + double gpu_time = 0.0; for (int i = 0; i < FRAME_TIME_HISTORY; i++) { gpu_time += gpu_time_history[i]; } @@ -2772,7 +2815,7 @@ void Node3DEditorViewport::_notification(int p_what) { frame_time_gradient->get_color_at_offset( Math::range_lerp(gpu_time, 0, 30, 0, 1))); - const float fps = 1000.0 / gpu_time; + const double fps = 1000.0 / gpu_time; fps_label->set_text(vformat(TTR("FPS: %d"), fps)); // Middle point is at 60 FPS. fps_label->add_theme_color_override( @@ -3011,7 +3054,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { cursor.y_rot = 0; cursor.x_rot = Math_PI / 2.0; set_message(TTR("Top View."), 2); - name = TTR("Top"); + view_type = VIEW_TYPE_TOP; _set_auto_orthogonal(); _update_name(); @@ -3020,7 +3063,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { cursor.y_rot = 0; cursor.x_rot = -Math_PI / 2.0; set_message(TTR("Bottom View."), 2); - name = TTR("Bottom"); + view_type = VIEW_TYPE_BOTTOM; _set_auto_orthogonal(); _update_name(); @@ -3029,7 +3072,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { cursor.x_rot = 0; cursor.y_rot = Math_PI / 2.0; set_message(TTR("Left View."), 2); - name = TTR("Left"); + view_type = VIEW_TYPE_LEFT; _set_auto_orthogonal(); _update_name(); @@ -3038,7 +3081,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { cursor.x_rot = 0; cursor.y_rot = -Math_PI / 2.0; set_message(TTR("Right View."), 2); - name = TTR("Right"); + view_type = VIEW_TYPE_RIGHT; _set_auto_orthogonal(); _update_name(); @@ -3047,7 +3090,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { cursor.x_rot = 0; cursor.y_rot = Math_PI; set_message(TTR("Front View."), 2); - name = TTR("Front"); + view_type = VIEW_TYPE_FRONT; _set_auto_orthogonal(); _update_name(); @@ -3056,7 +3099,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { cursor.x_rot = 0; cursor.y_rot = 0; set_message(TTR("Rear View."), 2); - name = TTR("Rear"); + view_type = VIEW_TYPE_REAR; _set_auto_orthogonal(); _update_name(); @@ -3190,7 +3233,7 @@ void Node3DEditorViewport::_menu_option(int p_option) { int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER); bool current = view_menu->get_popup()->is_item_checked(idx); current = !current; - viewport->set_as_audio_listener(current); + viewport->set_as_audio_listener_3d(current); view_menu->get_popup()->set_item_checked(idx, current); } break; @@ -3600,8 +3643,8 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) { _menu_option(VIEW_PERSPECTIVE); } } - if (p_state.has("view_name")) { - name = p_state["view_name"]; + if (p_state.has("view_type")) { + view_type = ViewType(p_state["view_type"].operator int()); _update_name(); } if (p_state.has("auto_orthogonal")) { @@ -3637,7 +3680,7 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) { bool listener = p_state["listener"]; int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER); - viewport->set_as_audio_listener(listener); + viewport->set_as_audio_listener_3d(listener); view_menu->get_popup()->set_item_checked(idx, listener); } if (p_state.has("doppler")) { @@ -3709,7 +3752,7 @@ Dictionary Node3DEditorViewport::get_state() const { d["distance"] = cursor.distance; d["use_environment"] = camera->get_environment().is_valid(); d["use_orthogonal"] = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL; - d["view_name"] = name; + d["view_type"] = view_type; d["auto_orthogonal"] = auto_orthogonal; d["auto_orthogonal_enabled"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUTO_ORTHOGONAL)); if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_NORMAL))) { @@ -3721,7 +3764,7 @@ Dictionary Node3DEditorViewport::get_state() const { } else if (view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_DISPLAY_SHADELESS))) { d["display_mode"] = VIEW_DISPLAY_SHADELESS; } - d["listener"] = viewport->is_audio_listener(); + d["listener"] = viewport->is_audio_listener_3d(); d["doppler"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_DOPPLER)); d["gizmos"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_GIZMOS)); d["information"] = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(VIEW_INFORMATION)); @@ -3754,7 +3797,7 @@ void Node3DEditorViewport::reset() { message_time = 0; message = ""; last_message = ""; - name = ""; + view_type = VIEW_TYPE_USER; cursor = Cursor(); _update_name(); @@ -4033,7 +4076,7 @@ bool Node3DEditorViewport::can_drop_data_fw(const Point2 &p_point, const Variant continue; } memdelete(instantiated_scene); - } else if (type == "Mesh" || type == "ArrayMesh" || type == "PrimitiveMesh") { + } else if (ClassDB::is_parent_class(type, "Mesh")) { Ref<Mesh> mesh = ResourceLoader::load(files[i]); if (!mesh.is_valid()) { continue; @@ -4366,10 +4409,10 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, Edito if (p_index == 0) { view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER), true); - viewport->set_as_audio_listener(true); + viewport->set_as_audio_listener_3d(true); } - name = ""; + view_type = VIEW_TYPE_USER; _update_name(); EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &Node3DEditorViewport::update_transform_gizmo_view)); @@ -4381,7 +4424,7 @@ Node3DEditorViewport::~Node3DEditorViewport() { ////////////////////////////////////////////////////////////// -void Node3DEditorViewportContainer::_gui_input(const Ref<InputEvent> &p_event) { +void Node3DEditorViewportContainer::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventMouseButton> mb = p_event; @@ -4673,10 +4716,6 @@ Node3DEditorViewportContainer::View Node3DEditorViewportContainer::get_view() { return view; } -void Node3DEditorViewportContainer::_bind_methods() { - ClassDB::bind_method("_gui_input", &Node3DEditorViewportContainer::_gui_input); -} - Node3DEditorViewportContainer::Node3DEditorViewportContainer() { set_clip_contents(true); view = VIEW_USE_1_VIEWPORT; @@ -4779,13 +4818,13 @@ void _update_all_gizmos(Node *p_node) { } void Node3DEditor::update_all_gizmos(Node *p_node) { + if (!p_node && get_tree()) { + p_node = get_tree()->get_edited_scene_root(); + } + if (!p_node) { - if (SceneTree::get_singleton()) { - p_node = SceneTree::get_singleton()->get_root(); - } else { - // No scene tree, so nothing to update. - return; - } + // No edited scene, so nothing to update. + return; } _update_all_gizmos(p_node); } @@ -5511,6 +5550,12 @@ void Node3DEditor::_init_indicators() { Vector<Color> origin_colors; Vector<Vector3> origin_points; + const int count_of_elements = 3 * 6; + origin_colors.resize(count_of_elements); + origin_points.resize(count_of_elements); + + int x = 0; + for (int i = 0; i < 3; i++) { Vector3 axis; axis[i] = 1; @@ -5533,25 +5578,28 @@ void Node3DEditor::_init_indicators() { grid_enable[i] = false; grid_visible[i] = false; - origin_colors.push_back(origin_color); - origin_colors.push_back(origin_color); - origin_colors.push_back(origin_color); - origin_colors.push_back(origin_color); - origin_colors.push_back(origin_color); - origin_colors.push_back(origin_color); + origin_colors.set(x, origin_color); + origin_colors.set(x + 1, origin_color); + origin_colors.set(x + 2, origin_color); + origin_colors.set(x + 3, origin_color); + origin_colors.set(x + 4, origin_color); + origin_colors.set(x + 5, origin_color); // To both allow having a large origin size and avoid jitter // at small scales, we should segment the line into pieces. // 3 pieces seems to do the trick, and let's use powers of 2. - origin_points.push_back(axis * 1048576); - origin_points.push_back(axis * 1024); - origin_points.push_back(axis * 1024); - origin_points.push_back(axis * -1024); - origin_points.push_back(axis * -1024); - origin_points.push_back(axis * -1048576); + origin_points.set(x, axis * 1048576); + origin_points.set(x + 1, axis * 1024); + origin_points.set(x + 2, axis * 1024); + origin_points.set(x + 3, axis * -1024); + origin_points.set(x + 4, axis * -1024); + origin_points.set(x + 5, axis * -1048576); + x += 6; } Ref<Shader> grid_shader = memnew(Shader); grid_shader->set_code(R"( +// 3D editor grid shader. + shader_type spatial; render_mode unshaded; @@ -5793,6 +5841,8 @@ void fragment() { Ref<Shader> rotate_shader = memnew(Shader); rotate_shader->set_code(R"( +// 3D editor rotation manipulator gizmo shader. + shader_type spatial; render_mode unshaded, depth_test_disabled; @@ -5841,6 +5891,8 @@ void fragment() { Ref<Shader> border_shader = memnew(Shader); border_shader->set_code(R"( +// 3D editor rotation manipulator gizmo shader (white outline). + shader_type spatial; render_mode unshaded, depth_test_disabled; @@ -6124,6 +6176,32 @@ void Node3DEditor::_init_grid() { grid_mat[c]->set_shader_param("grid_size", grid_fade_size); grid_mat[c]->set_shader_param("orthogonal", orthogonal); + // Cache these so we don't have to re-access memory. + Vector<Vector3> &ref_grid = grid_points[c]; + Vector<Vector3> &ref_grid_normals = grid_normals[c]; + Vector<Color> &ref_grid_colors = grid_colors[c]; + + // Count our elements same as code below it. + int expected_size = 0; + for (int i = -grid_size; i <= grid_size; i++) { + const real_t position_a = center_a + i * small_step_size; + const real_t position_b = center_b + i * small_step_size; + + // Don't draw lines over the origin if it's enabled. + if (!(origin_enabled && Math::is_zero_approx(position_a))) { + expected_size += 2; + } + + if (!(origin_enabled && Math::is_zero_approx(position_b))) { + expected_size += 2; + } + } + + int idx = 0; + ref_grid.resize(expected_size); + ref_grid_normals.resize(expected_size); + ref_grid_colors.resize(expected_size); + // In each iteration of this loop, draw one line in each direction (so two lines per loop, in each if statement). for (int i = -grid_size; i <= grid_size; i++) { Color line_color; @@ -6146,12 +6224,13 @@ void Node3DEditor::_init_grid() { line_end[a] = position_a; line_bgn[b] = bgn_b; line_end[b] = end_b; - grid_points[c].push_back(line_bgn); - grid_points[c].push_back(line_end); - grid_colors[c].push_back(line_color); - grid_colors[c].push_back(line_color); - grid_normals[c].push_back(normal); - grid_normals[c].push_back(normal); + ref_grid.set(idx, line_bgn); + ref_grid.set(idx + 1, line_end); + ref_grid_colors.set(idx, line_color); + ref_grid_colors.set(idx + 1, line_color); + ref_grid_normals.set(idx, normal); + ref_grid_normals.set(idx + 1, normal); + idx += 2; } if (!(origin_enabled && Math::is_zero_approx(position_b))) { @@ -6161,12 +6240,13 @@ void Node3DEditor::_init_grid() { line_end[b] = position_b; line_bgn[a] = bgn_a; line_end[a] = end_a; - grid_points[c].push_back(line_bgn); - grid_points[c].push_back(line_end); - grid_colors[c].push_back(line_color); - grid_colors[c].push_back(line_color); - grid_normals[c].push_back(normal); - grid_normals[c].push_back(normal); + ref_grid.set(idx, line_bgn); + ref_grid.set(idx + 1, line_end); + ref_grid_colors.set(idx, line_color); + ref_grid_colors.set(idx + 1, line_color); + ref_grid_normals.set(idx, normal); + ref_grid_normals.set(idx + 1, normal); + idx += 2; } } @@ -6204,8 +6284,22 @@ void Node3DEditor::_finish_grid() { } void Node3DEditor::update_grid() { - _finish_grid(); - _init_grid(); + const Camera3D::Projection current_projection = viewports[0]->camera->get_projection(); + + if (current_projection != grid_camera_last_update_perspective) { + grid_init_draw = false; // redraw + grid_camera_last_update_perspective = current_projection; + } + + // Gets a orthogonal or perspective position correctly (for the grid comparison) + const Vector3 camera_position = get_editor_viewport(0)->camera->get_position(); + + if (!grid_init_draw || (camera_position - grid_camera_last_update_position).length() >= 10.0f) { + _finish_grid(); + _init_grid(); + grid_init_draw = true; + grid_camera_last_update_position = camera_position; + } } void Node3DEditor::_selection_changed() { @@ -6416,7 +6510,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() { } } -void Node3DEditor::_unhandled_key_input(Ref<InputEvent> p_event) { +void Node3DEditor::unhandled_key_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); if (!is_visible_in_tree()) { @@ -6545,6 +6639,7 @@ void Node3DEditor::_notification(int p_what) { _register_all_gizmos(); _update_gizmos_menu(); _init_indicators(); + update_all_gizmos(); } break; case NOTIFICATION_EXIT_TREE: { _finish_indicators(); @@ -6793,7 +6888,6 @@ void Node3DEditor::_register_all_gizmos() { } void Node3DEditor::_bind_methods() { - ClassDB::bind_method("_unhandled_key_input", &Node3DEditor::_unhandled_key_input); ClassDB::bind_method("_get_editor_data", &Node3DEditor::_get_editor_data); ClassDB::bind_method("_request_gizmo", &Node3DEditor::_request_gizmo); ClassDB::bind_method("_clear_subgizmo_selection", &Node3DEditor::_clear_subgizmo_selection); @@ -6823,7 +6917,7 @@ void Node3DEditor::clear() { for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) { viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(Node3DEditorViewport::VIEW_AUDIO_LISTENER), i == 0); - viewports[i]->viewport->set_as_audio_listener(i == 0); + viewports[i]->viewport->set_as_audio_listener_3d(i == 0); } view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true); @@ -7418,6 +7512,8 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { sun_direction_shader.instantiate(); sun_direction_shader->set_code(R"( +// 3D editor Preview Sun direction shader. + shader_type canvas_item; uniform vec3 sun_direction; @@ -7678,7 +7774,6 @@ void Node3DEditor::add_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin) { gizmo_plugins_by_name.sort_custom<_GizmoPluginNameComparator>(); _update_gizmos_menu(); - Node3DEditor::get_singleton()->update_all_gizmos(); } void Node3DEditor::remove_gizmo_plugin(Ref<EditorNode3DGizmoPlugin> p_plugin) { diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index cb2edbcbc1..59f3ec6fcd 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -35,6 +35,7 @@ #include "editor/editor_plugin.h" #include "editor/editor_scale.h" #include "editor/plugins/node_3d_editor_gizmos.h" +#include "scene/3d/camera_3d.h" #include "scene/3d/light_3d.h" #include "scene/3d/visual_instance_3d.h" #include "scene/3d/world_environment.h" @@ -42,7 +43,6 @@ #include "scene/resources/environment.h" #include "scene/resources/sky_material.h" -class Camera3D; class Node3DEditor; class Node3DEditorViewport; class SubViewportContainer; @@ -74,9 +74,8 @@ class ViewportRotationControl : public Control { const float AXIS_CIRCLE_RADIUS = 8.0f * EDSCALE; protected: - static void _bind_methods(); void _notification(int p_what); - void _gui_input(Ref<InputEvent> p_event); + virtual void gui_input(const Ref<InputEvent> &p_event) override; void _draw(); void _draw_axis(const Axis2D &p_axis); void _get_sorted_axis(Vector<Axis2D> &r_axis); @@ -143,6 +142,16 @@ class Node3DEditorViewport : public Control { VIEW_MAX }; + enum ViewType { + VIEW_TYPE_USER, + VIEW_TYPE_TOP, + VIEW_TYPE_BOTTOM, + VIEW_TYPE_LEFT, + VIEW_TYPE_RIGHT, + VIEW_TYPE_FRONT, + VIEW_TYPE_REAR, + }; + public: enum { GIZMO_BASE_LAYER = 27, @@ -166,13 +175,13 @@ public: }; private: - float cpu_time_history[FRAME_TIME_HISTORY]; + double cpu_time_history[FRAME_TIME_HISTORY]; int cpu_time_history_index; - float gpu_time_history[FRAME_TIME_HISTORY]; + double gpu_time_history[FRAME_TIME_HISTORY]; int gpu_time_history_index; int index; - String name; + ViewType view_type; void _menu_option(int p_option); void _set_auto_orthogonal(); Node3D *preview_node; @@ -336,7 +345,7 @@ private: String last_message; String message; - float message_time; + double message_time; void set_message(String p_message, float p_time = 5); @@ -460,11 +469,10 @@ private: Vector2 drag_begin_pos; Vector2 drag_begin_ratio; - void _gui_input(const Ref<InputEvent> &p_event); + virtual void gui_input(const Ref<InputEvent> &p_event) override; protected: void _notification(int p_what); - static void _bind_methods(); public: void set_view(View p_view); @@ -521,6 +529,9 @@ private: bool grid_visible[3]; //currently visible bool grid_enable[3]; //should be always visible if true bool grid_enabled; + bool grid_init_draw = false; + Camera3D::Projection grid_camera_last_update_perspective = Camera3D::PROJECTION_PERSPECTIVE; + Vector3 grid_camera_last_update_position = Vector3(); Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[4], scale_gizmo[3], scale_plane_gizmo[3]; Ref<StandardMaterial3D> gizmo_color[3]; @@ -622,7 +633,6 @@ private: void _menu_gizmo_toggled(int p_option); void _update_camera_override_button(bool p_game_running); void _update_camera_override_viewport(Object *p_viewport); - HBoxContainer *hbc_menu; // Used for secondary menu items which are displayed depending on the currently selected node // (such as MeshInstance's "Mesh" menu). @@ -732,7 +742,7 @@ private: protected: void _notification(int p_what); //void _gui_input(InputEvent p_event); - void _unhandled_key_input(Ref<InputEvent> p_event); + virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; static void _bind_methods(); diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 8866e8c53e..119ecddf63 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -70,14 +70,14 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { return false; } - real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); Vector2 gpoint = mb->get_position(); - Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); + Vector2 cpoint = node->to_local(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); if (mb->is_pressed() && action == ACTION_NONE) { Ref<Curve2D> curve = node->get_curve(); diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 9377395418..782152b002 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -1041,7 +1041,7 @@ void Polygon2DEditor::_uv_draw() { for (int i = 0; i < uvs.size(); i++) { int next = uv_draw_max > 0 ? (i + 1) % uv_draw_max : 0; - if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { + if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_DEF("editors/polygon_editor/show_previous_outline", true)) { uv_edit_draw->draw_line(mtx.xform(points_prev[i]), mtx.xform(points_prev[next]), prev_color, Math::round(EDSCALE)); } diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index cbea2405b8..eae6916a92 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -35,9 +35,6 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" -void ResourcePreloaderEditor::_gui_input(Ref<InputEvent> p_event) { -} - void ResourcePreloaderEditor::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { load->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); @@ -335,7 +332,6 @@ void ResourcePreloaderEditor::drop_data_fw(const Point2 &p_point, const Variant } void ResourcePreloaderEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &ResourcePreloaderEditor::_gui_input); ClassDB::bind_method(D_METHOD("_update_library"), &ResourcePreloaderEditor::_update_library); ClassDB::bind_method(D_METHOD("_remove_resource", "to_remove"), &ResourcePreloaderEditor::_remove_resource); diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h index bc10b48a16..04ab458eb5 100644 --- a/editor/plugins/resource_preloader_editor_plugin.h +++ b/editor/plugins/resource_preloader_editor_plugin.h @@ -75,7 +75,7 @@ class ResourcePreloaderEditor : public PanelContainer { protected: void _notification(int p_what); - void _gui_input(Ref<InputEvent> p_event); + static void _bind_methods(); public: diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 668a15da37..a24249b95b 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -54,17 +54,17 @@ /*** SYNTAX HIGHLIGHTER ****/ String EditorSyntaxHighlighter::_get_name() const { - ScriptInstance *si = get_script_instance(); - if (si && si->has_method("_get_name")) { - return si->call("_get_name"); + String ret; + if (GDVIRTUAL_CALL(_get_name, ret)) { + return ret; } return "Unnamed"; } Array EditorSyntaxHighlighter::_get_supported_languages() const { - ScriptInstance *si = get_script_instance(); - if (si && si->has_method("_get_supported_languages")) { - return si->call("_get_supported_languages"); + Array ret; + if (GDVIRTUAL_CALL(_get_supported_languages, ret)) { + return ret; } return Array(); } @@ -81,9 +81,8 @@ Ref<EditorSyntaxHighlighter> EditorSyntaxHighlighter::_create() const { void EditorSyntaxHighlighter::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_edited_resource"), &EditorSyntaxHighlighter::_get_edited_resource); - BIND_VMETHOD(MethodInfo(Variant::STRING, "_get_name")); - BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_supported_languages")); - BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_get_supported_extentions")); + GDVIRTUAL_BIND(_get_name) + GDVIRTUAL_BIND(_get_supported_languages) } //// @@ -94,25 +93,21 @@ void EditorStandardSyntaxHighlighter::_update_cache() { highlighter->clear_member_keyword_colors(); highlighter->clear_color_regions(); - highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color")); - highlighter->set_function_color(EDITOR_GET("text_editor/highlighting/function_color")); - highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color")); - highlighter->set_member_variable_color(EDITOR_GET("text_editor/highlighting/member_variable_color")); + highlighter->set_symbol_color(EDITOR_GET("text_editor/theme/highlighting/symbol_color")); + highlighter->set_function_color(EDITOR_GET("text_editor/theme/highlighting/function_color")); + highlighter->set_number_color(EDITOR_GET("text_editor/theme/highlighting/number_color")); + highlighter->set_member_variable_color(EDITOR_GET("text_editor/theme/highlighting/member_variable_color")); /* Engine types. */ - const Color type_color = EDITOR_GET("text_editor/highlighting/engine_type_color"); + const Color type_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color"); List<StringName> types; ClassDB::get_class_list(&types); for (const StringName &E : types) { - String n = E; - if (n.begins_with("_")) { - n = n.substr(1, n.length()); - } - highlighter->add_keyword_color(n, type_color); + highlighter->add_keyword_color(E, type_color); } /* User types. */ - const Color usertype_color = EDITOR_GET("text_editor/highlighting/user_type_color"); + const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color"); List<StringName> global_classes; ScriptServer::get_global_class_list(&global_classes); for (const StringName &E : global_classes) { @@ -120,9 +115,9 @@ void EditorStandardSyntaxHighlighter::_update_cache() { } /* Autoloads. */ - Map<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); - for (Map<StringName, ProjectSettings::AutoloadInfo>::Element *E = autoloads.front(); E; E = E->next()) { - const ProjectSettings::AutoloadInfo &info = E->value(); + OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list(); + for (OrderedHashMap<StringName, ProjectSettings::AutoloadInfo>::Element E = autoloads.front(); E; E = E.next()) { + const ProjectSettings::AutoloadInfo &info = E.value(); if (info.is_singleton) { highlighter->add_keyword_color(info.name, usertype_color); } @@ -131,7 +126,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() { const Ref<Script> script = _get_edited_resource(); if (script.is_valid()) { /* Core types. */ - const Color basetype_color = EDITOR_GET("text_editor/highlighting/base_type_color"); + const Color basetype_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color"); List<String> core_types; script->get_language()->get_core_type_words(&core_types); for (const String &E : core_types) { @@ -139,8 +134,8 @@ void EditorStandardSyntaxHighlighter::_update_cache() { } /* Reserved words. */ - const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color"); + const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color"); + const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color"); List<String> keywords; script->get_language()->get_reserved_words(&keywords); for (const String &E : keywords) { @@ -152,7 +147,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() { } /* Member types. */ - const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); StringName instance_base = script->get_instance_base_type(); if (instance_base != StringName()) { List<PropertyInfo> plist; @@ -176,7 +171,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() { } /* Comments */ - const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); + const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color"); List<String> comments; script->get_language()->get_comment_delimiters(&comments); for (const String &comment : comments) { @@ -186,7 +181,7 @@ void EditorStandardSyntaxHighlighter::_update_cache() { } /* Strings */ - const Color string_color = EDITOR_GET("text_editor/highlighting/string_color"); + const Color string_color = EDITOR_GET("text_editor/theme/highlighting/string_color"); List<String> strings; script->get_language()->get_string_delimiters(&strings); for (const String &string : strings) { @@ -227,8 +222,6 @@ void ScriptEditorBase::_bind_methods() { // TODO: This signal is no use for VisualScript. ADD_SIGNAL(MethodInfo("search_in_files_requested", PropertyInfo(Variant::STRING, "text"))); ADD_SIGNAL(MethodInfo("replace_in_files_requested", PropertyInfo(Variant::STRING, "text"))); - - BIND_VMETHOD(MethodInfo("_add_syntax_highlighter", PropertyInfo(Variant::OBJECT, "highlighter"))); } static bool _is_built_in_script(Script *p_script) { @@ -323,7 +316,7 @@ void ScriptEditorQuickOpen::_sbox_input(const Ref<InputEvent> &p_ie) { k->get_keycode() == KEY_DOWN || k->get_keycode() == KEY_PAGEUP || k->get_keycode() == KEY_PAGEDOWN)) { - search_options->call("_gui_input", k); + search_options->gui_input(k); search_box->accept_event(); } } @@ -942,7 +935,10 @@ void ScriptEditor::_res_saved_callback(const Ref<Resource> &p_res) { } _update_script_names(); + _trigger_live_script_reload(); +} +void ScriptEditor::_trigger_live_script_reload() { if (!pending_auto_reload && auto_reload_running_scripts) { call_deferred(SNAME("_live_auto_reload_running_scripts")); pending_auto_reload = true; @@ -961,7 +957,7 @@ bool ScriptEditor::_test_script_times_on_disk(RES p_for_script) { bool need_ask = false; bool need_reload = false; - bool use_autoreload = bool(EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change", false)); + bool use_autoreload = bool(EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", false)); for (int i = 0; i < tab_container->get_child_count(); i++) { ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); @@ -1712,7 +1708,7 @@ void ScriptEditor::_update_members_overview_visibility() { } void ScriptEditor::_toggle_members_overview_alpha_sort(bool p_alphabetic_sort) { - EditorSettings::get_singleton()->set("text_editor/tools/sort_members_outline_alphabetically", p_alphabetic_sort); + EditorSettings::get_singleton()->set("text_editor/script_list/sort_members_outline_alphabetically", p_alphabetic_sort); _update_members_overview(); } @@ -1725,7 +1721,7 @@ void ScriptEditor::_update_members_overview() { } Vector<String> functions = se->get_functions(); - if (EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically")) { + if (EditorSettings::get_singleton()->get("text_editor/script_list/sort_members_outline_alphabetically")) { functions.sort(); } @@ -2104,7 +2100,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra const bool use_external_editor = EditorSettings::get_singleton()->get("text_editor/external/use_external_editor") || (script.is_valid() && script->get_language()->overrides_external_editor()); - const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change"); + const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/behavior/files/open_dominant_script_on_scene_change"); const bool should_open = (open_dominant && !use_external_editor) || !EditorNode::get_singleton()->is_changing_scene(); @@ -2469,9 +2465,9 @@ void ScriptEditor::_save_layout() { } void ScriptEditor::_editor_settings_changed() { - trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/files/trim_trailing_whitespace_on_save"); - convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/indent/convert_indent_on_save"); - use_space_indentation = EditorSettings::get_singleton()->get("text_editor/indent/type"); + trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/trim_trailing_whitespace_on_save"); + convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/convert_indent_on_save"); + use_space_indentation = EditorSettings::get_singleton()->get("text_editor/behavior/indent/type"); members_overview_enabled = EditorSettings::get_singleton()->get("text_editor/script_list/show_members_overview"); help_overview_enabled = EditorSettings::get_singleton()->get("text_editor/help/show_help_index"); @@ -2498,7 +2494,7 @@ void ScriptEditor::_editor_settings_changed() { _update_script_colors(); _update_script_names(); - ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save", true)); + ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save", true)); } void ScriptEditor::_filesystem_changed() { @@ -2537,7 +2533,7 @@ void ScriptEditor::_update_autosave_timer() { return; } - float autosave_time = EditorSettings::get_singleton()->get("text_editor/files/autosave_interval_secs"); + float autosave_time = EditorSettings::get_singleton()->get("text_editor/behavior/files/autosave_interval_secs"); if (autosave_time > 0) { autosave_timer->set_wait_time(autosave_time); autosave_timer->start(); @@ -2732,7 +2728,7 @@ void ScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Co } } -void ScriptEditor::_unhandled_key_input(const Ref<InputEvent> &p_event) { +void ScriptEditor::unhandled_key_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); if (!is_visible_in_tree() || !p_event->is_pressed() || p_event->is_echo()) { @@ -2827,7 +2823,7 @@ void ScriptEditor::_make_script_list_context_menu() { } void ScriptEditor::set_window_layout(Ref<ConfigFile> p_layout) { - if (!bool(EDITOR_DEF("text_editor/files/restore_scripts_on_load", true))) { + if (!bool(EDITOR_DEF("text_editor/behavior/files/restore_scripts_on_load", true))) { return; } @@ -3120,7 +3116,7 @@ void ScriptEditor::set_scene_root_script(Ref<Script> p_script) { const bool use_external_editor = EditorSettings::get_singleton()->get("text_editor/external/use_external_editor") || (p_script.is_valid() && p_script->get_language()->overrides_external_editor()); - const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change"); + const bool open_dominant = EditorSettings::get_singleton()->get("text_editor/behavior/files/open_dominant_script_on_scene_change"); if (open_dominant && !use_external_editor && p_script.is_valid()) { edit(p_script); @@ -3276,7 +3272,7 @@ void ScriptEditor::_bind_methods() { ClassDB::bind_method("_update_script_connections", &ScriptEditor::_update_script_connections); ClassDB::bind_method("_help_class_open", &ScriptEditor::_help_class_open); ClassDB::bind_method("_live_auto_reload_running_scripts", &ScriptEditor::_live_auto_reload_running_scripts); - ClassDB::bind_method("_unhandled_key_input", &ScriptEditor::_unhandled_key_input); + ClassDB::bind_method("_update_members_overview", &ScriptEditor::_update_members_overview); ClassDB::bind_method("_update_recent_scripts", &ScriptEditor::_update_recent_scripts); @@ -3367,7 +3363,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { members_overview_alphabeta_sort_button->set_flat(true); members_overview_alphabeta_sort_button->set_tooltip(TTR("Toggle alphabetical sorting of the method list.")); members_overview_alphabeta_sort_button->set_toggle_mode(true); - members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically")); + members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/script_list/sort_members_outline_alphabetically")); members_overview_alphabeta_sort_button->connect("toggled", callable_mp(this, &ScriptEditor::_toggle_members_overview_alpha_sort)); buttons_hbox->add_child(members_overview_alphabeta_sort_button); @@ -3409,8 +3405,8 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { ED_SHORTCUT("script_editor/window_sort", TTR("Sort")); ED_SHORTCUT("script_editor/window_move_up", TTR("Move Up"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_UP); ED_SHORTCUT("script_editor/window_move_down", TTR("Move Down"), KEY_MASK_SHIFT | KEY_MASK_ALT | KEY_DOWN); - ED_SHORTCUT("script_editor/next_script", TTR("Next script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_PERIOD); // these should be KEY_GREATER and KEY_LESS but those don't work - ED_SHORTCUT("script_editor/prev_script", TTR("Previous script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_COMMA); + ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_PERIOD); // these should be KEY_GREATER and KEY_LESS but those don't work + ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_COMMA); set_process_unhandled_key_input(true); file_menu = memnew(MenuButton); @@ -3604,9 +3600,9 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { history_pos = -1; edit_pass = 0; - trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/files/trim_trailing_whitespace_on_save"); - convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/indent/convert_indent_on_save"); - use_space_indentation = EditorSettings::get_singleton()->get("text_editor/indent/type"); + trim_trailing_whitespace_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/trim_trailing_whitespace_on_save"); + convert_indent_on_save = EditorSettings::get_singleton()->get("text_editor/behavior/files/convert_indent_on_save"); + use_space_indentation = EditorSettings::get_singleton()->get("text_editor/behavior/indent/type"); ScriptServer::edit_request_func = _open_script_request; @@ -3703,9 +3699,9 @@ ScriptEditorPlugin::ScriptEditorPlugin(EditorNode *p_node) { script_editor->hide(); - EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change", true); - ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/files/auto_reload_and_parse_scripts_on_save", true)); - EDITOR_DEF("text_editor/files/open_dominant_script_on_scene_change", true); + EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", true); + ScriptServer::set_reload_scripts_on_save(EDITOR_DEF("text_editor/behavior/files/auto_reload_and_parse_scripts_on_save", true)); + EDITOR_DEF("text_editor/behavior/files/open_dominant_script_on_scene_change", true); EDITOR_DEF("text_editor/external/use_external_editor", false); EDITOR_DEF("text_editor/external/exec_path", ""); EDITOR_DEF("text_editor/script_list/script_temperature_enabled", true); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 72a649ffbf..a57aeea5c0 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -56,6 +56,9 @@ private: protected: static void _bind_methods(); + GDVIRTUAL0RC(String, _get_name) + GDVIRTUAL0RC(Array, _get_supported_languages) + public: virtual String _get_name() const; virtual Array _get_supported_languages() const; @@ -74,7 +77,7 @@ private: public: virtual void _update_cache() override; - virtual Dictionary _get_line_syntax_highlighting(int p_line) override { return highlighter->get_line_syntax_highlighting(p_line); } + virtual Dictionary _get_line_syntax_highlighting_impl(int p_line) override { return highlighter->get_line_syntax_highlighting(p_line); } virtual String _get_name() const override { return TTR("Standard"); } @@ -344,6 +347,7 @@ class ScriptEditor : public PanelContainer { bool pending_auto_reload; bool auto_reload_running_scripts; + void _trigger_live_script_reload(); void _live_auto_reload_running_scripts(); void _update_selected_editor_menu(); @@ -407,7 +411,7 @@ class ScriptEditor : public PanelContainer { bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); - void _unhandled_key_input(const Ref<InputEvent> &p_event); + virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; void _script_list_gui_input(const Ref<InputEvent> &ev); void _make_script_list_context_menu(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 5bbe56a800..b7d5403919 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -33,6 +33,7 @@ #include "core/math/expression.h" #include "core/os/keyboard.h" #include "editor/debugger/editor_debugger_node.h" +#include "editor/editor_command_palette.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" @@ -165,8 +166,8 @@ void ScriptTextEditor::enable_editor() { void ScriptTextEditor::_load_theme_settings() { CodeEdit *text_edit = code_editor->get_text_editor(); - Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color"); - Color updated_safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color"); + Color updated_marked_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color"); + Color updated_safe_line_number_color = EDITOR_GET("text_editor/theme/highlighting/safe_line_number_color"); bool safe_line_number_color_updated = updated_safe_line_number_color != safe_line_number_color; bool marked_line_color_updated = updated_marked_line_color != marked_line_color; @@ -240,14 +241,14 @@ void ScriptTextEditor::_warning_clicked(Variant p_line) { goto_line_centered(p_line.operator int64_t()); } else if (p_line.get_type() == Variant::DICTIONARY) { Dictionary meta = p_line.operator Dictionary(); - code_editor->get_text_editor()->insert_at("# warning-ignore:" + meta["code"].operator String(), meta["line"].operator int64_t() - 1); + code_editor->get_text_editor()->insert_line_at(meta["line"].operator int64_t() - 1, "# warning-ignore:" + meta["code"].operator String()); _validate_script(); } } void ScriptTextEditor::_error_clicked(Variant p_line) { if (p_line.get_type() == Variant::INT) { - code_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t()); + code_editor->get_text_editor()->set_caret_line(p_line.operator int64_t()); } } @@ -255,14 +256,14 @@ void ScriptTextEditor::reload_text() { ERR_FAIL_COND(script.is_null()); CodeEdit *te = code_editor->get_text_editor(); - int column = te->cursor_get_column(); - int row = te->cursor_get_line(); + int column = te->get_caret_column(); + int row = te->get_caret_line(); int h = te->get_h_scroll(); int v = te->get_v_scroll(); te->set_text(script->get_source_code()); - te->cursor_set_line(row); - te->cursor_set_column(column); + te->set_caret_line(row); + te->set_caret_column(column); te->set_h_scroll(h); te->set_v_scroll(v); @@ -280,12 +281,12 @@ void ScriptTextEditor::add_callback(const String &p_function, PackedStringArray pos = code_editor->get_text_editor()->get_line_count() + 2; String func = script->get_language()->make_function("", p_function, p_args); //code=code+func; - code_editor->get_text_editor()->cursor_set_line(pos + 1); - code_editor->get_text_editor()->cursor_set_column(1000000); //none shall be that big - code_editor->get_text_editor()->insert_text_at_cursor("\n\n" + func); + code_editor->get_text_editor()->set_caret_line(pos + 1); + code_editor->get_text_editor()->set_caret_column(1000000); //none shall be that big + code_editor->get_text_editor()->insert_text_at_caret("\n\n" + func); } - code_editor->get_text_editor()->cursor_set_line(pos); - code_editor->get_text_editor()->cursor_set_column(1); + code_editor->get_text_editor()->set_caret_line(pos); + code_editor->get_text_editor()->set_caret_column(1); } bool ScriptTextEditor::show_members_overview() { @@ -293,7 +294,7 @@ bool ScriptTextEditor::show_members_overview() { } void ScriptTextEditor::update_settings() { - code_editor->get_text_editor()->set_gutter_draw(connection_gutter, EditorSettings::get_singleton()->get("text_editor/appearance/show_info_gutter")); + code_editor->get_text_editor()->set_gutter_draw(connection_gutter, EditorSettings::get_singleton()->get("text_editor/appearance/gutters/show_info_gutter")); code_editor->update_editor_settings(); } @@ -505,7 +506,7 @@ void ScriptTextEditor::_validate_script() { } errors_panel->pop(); // Table - bool highlight_safe = EDITOR_DEF("text_editor/highlighting/highlight_type_safe_lines", true); + bool highlight_safe = EDITOR_DEF("text_editor/appearance/gutters/highlight_type_safe_lines", true); bool last_is_safe = false; for (int i = 0; i < te->get_line_count(); i++) { if (errors.is_empty()) { @@ -665,6 +666,8 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo script->set_source_code(rel_script->get_source_code()); script->set_last_modified_time(rel_script->get_last_modified_time()); script->update_exports(); + + _trigger_live_script_reload(); } } } @@ -725,7 +728,7 @@ void ScriptTextEditor::_breakpoint_item_pressed(int p_idx) { _edit_option(breakpoints_menu->get_item_id(p_idx)); } else { code_editor->goto_line(breakpoints_menu->get_item_metadata(p_idx)); - code_editor->get_text_editor()->call_deferred(SNAME("center_viewport_to_cursor")); //Need to be deferred, because goto uses call_deferred(). + code_editor->get_text_editor()->call_deferred(SNAME("center_viewport_to_caret")); //Need to be deferred, because goto uses call_deferred(). } } @@ -755,8 +758,6 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c } else if (script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_symbol_lookup(), p_symbol, script->get_path(), base, result) == OK) { _goto_line(p_row); - result.class_name = result.class_name.trim_prefix("_"); - switch (result.type) { case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: { if (result.script.is_valid()) { @@ -830,7 +831,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c if (info.is_singleton) { EditorNode::get_singleton()->load_scene(info.path); } - } else if (p_symbol.is_rel_path()) { + } else if (p_symbol.is_relative_path()) { // Every symbol other than absolute path is relative path so keep this condition at last. String path = _get_absolute_path(p_symbol); if (FileAccess::exists(path)) { @@ -857,7 +858,7 @@ void ScriptTextEditor::_validate_symbol(const String &p_symbol) { ScriptLanguage::LookupResult result; if (ScriptServer::is_global_class(p_symbol) || p_symbol.is_resource_file() || script->get_language()->lookup_code(code_editor->get_text_editor()->get_text_for_symbol_lookup(), p_symbol, script->get_path(), base, result) == OK || (ProjectSettings::get_singleton()->has_autoload(p_symbol) && ProjectSettings::get_singleton()->get_autoload(p_symbol).is_singleton)) { text_edit->set_symbol_lookup_word_as_valid(true); - } else if (p_symbol.is_rel_path()) { + } else if (p_symbol.is_relative_path()) { String path = _get_absolute_path(p_symbol); if (FileAccess::exists(path)) { text_edit->set_symbol_lookup_word_as_valid(true); @@ -883,7 +884,7 @@ void ScriptTextEditor::update_toggle_scripts_button() { void ScriptTextEditor::_update_connected_methods() { CodeEdit *text_edit = code_editor->get_text_editor(); - text_edit->set_gutter_width(connection_gutter, text_edit->get_row_height()); + text_edit->set_gutter_width(connection_gutter, text_edit->get_line_height()); for (int i = 0; i < text_edit->get_line_count(); i++) { if (text_edit->get_line_gutter_metadata(i, connection_gutter) == "") { continue; @@ -1053,7 +1054,7 @@ void ScriptTextEditor::_edit_option(int p_op) { code_editor->duplicate_selection(); } break; case EDIT_TOGGLE_FOLD_LINE: { - tx->toggle_foldable_line(tx->cursor_get_line()); + tx->toggle_foldable_line(tx->get_caret_line()); tx->update(); } break; case EDIT_FOLD_ALL_LINES: { @@ -1061,7 +1062,7 @@ void ScriptTextEditor::_edit_option(int p_op) { tx->update(); } break; case EDIT_UNFOLD_ALL_LINES: { - tx->unhide_all_lines(); + tx->unfold_all_lines(); tx->update(); } break; case EDIT_TOGGLE_COMMENT: { @@ -1079,7 +1080,7 @@ void ScriptTextEditor::_edit_option(int p_op) { tx->begin_complex_operation(); int begin, end; - if (tx->is_selection_active()) { + if (tx->has_selection()) { begin = tx->get_selection_from_line(); end = tx->get_selection_to_line(); // ignore if the cursor is not past the first column @@ -1121,7 +1122,7 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case EDIT_EVALUATE: { Expression expression; - Vector<String> lines = code_editor->get_text_editor()->get_selection_text().split("\n"); + Vector<String> lines = code_editor->get_text_editor()->get_selected_text().split("\n"); PackedStringArray results; for (int i = 0; i < lines.size(); i++) { @@ -1141,7 +1142,7 @@ void ScriptTextEditor::_edit_option(int p_op) { } code_editor->get_text_editor()->begin_complex_operation(); //prevents creating a two-step undo - code_editor->get_text_editor()->insert_text_at_cursor(String("\n").join(results)); + code_editor->get_text_editor()->insert_text_at_caret(String("\n").join(results)); code_editor->get_text_editor()->end_complex_operation(); } break; case SEARCH_FIND: { @@ -1157,14 +1158,14 @@ void ScriptTextEditor::_edit_option(int p_op) { code_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_IN_FILES: { - String selected_text = code_editor->get_text_editor()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selected_text(); // Yep, because it doesn't make sense to instance this dialog for every single script open... // So this will be delegated to the ScriptEditor. emit_signal(SNAME("search_in_files_requested"), selected_text); } break; case REPLACE_IN_FILES: { - String selected_text = code_editor->get_text_editor()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selected_text(); emit_signal(SNAME("replace_in_files_requested"), selected_text); } break; @@ -1188,7 +1189,7 @@ void ScriptTextEditor::_edit_option(int p_op) { code_editor->remove_all_bookmarks(); } break; case DEBUG_TOGGLE_BREAKPOINT: { - int line = tx->cursor_get_line(); + int line = tx->get_caret_line(); bool dobreak = !tx->is_line_breakpointed(line); tx->set_line_as_breakpoint(line, dobreak); EditorDebuggerNode::get_singleton()->set_breakpoint(script->get_path(), line + 1, dobreak); @@ -1209,20 +1210,20 @@ void ScriptTextEditor::_edit_option(int p_op) { return; } - int line = tx->cursor_get_line(); + int line = tx->get_caret_line(); // wrap around if (line >= (int)bpoints[bpoints.size() - 1]) { tx->unfold_line(bpoints[0]); - tx->cursor_set_line(bpoints[0]); - tx->center_viewport_to_cursor(); + tx->set_caret_line(bpoints[0]); + tx->center_viewport_to_caret(); } else { for (int i = 0; i < bpoints.size(); i++) { int bline = bpoints[i]; if (bline > line) { tx->unfold_line(bline); - tx->cursor_set_line(bline); - tx->center_viewport_to_cursor(); + tx->set_caret_line(bline); + tx->center_viewport_to_caret(); return; } } @@ -1235,19 +1236,19 @@ void ScriptTextEditor::_edit_option(int p_op) { return; } - int line = tx->cursor_get_line(); + int line = tx->get_caret_line(); // wrap around if (line <= (int)bpoints[0]) { tx->unfold_line(bpoints[bpoints.size() - 1]); - tx->cursor_set_line(bpoints[bpoints.size() - 1]); - tx->center_viewport_to_cursor(); + tx->set_caret_line(bpoints[bpoints.size() - 1]); + tx->center_viewport_to_caret(); } else { for (int i = bpoints.size(); i >= 0; i--) { int bline = bpoints[i]; if (bline < line) { tx->unfold_line(bline); - tx->cursor_set_line(bline); - tx->center_viewport_to_cursor(); + tx->set_caret_line(bline); + tx->center_viewport_to_caret(); return; } } @@ -1255,21 +1256,21 @@ void ScriptTextEditor::_edit_option(int p_op) { } break; case HELP_CONTEXTUAL: { - String text = tx->get_selection_text(); + String text = tx->get_selected_text(); if (text == "") { - text = tx->get_word_under_cursor(); + text = tx->get_word_under_caret(); } if (text != "") { emit_signal(SNAME("request_help"), text); } } break; case LOOKUP_SYMBOL: { - String text = tx->get_word_under_cursor(); + String text = tx->get_word_under_caret(); if (text == "") { - text = tx->get_selection_text(); + text = tx->get_selected_text(); } if (text != "") { - _lookup_symbol(text, tx->cursor_get_line(), tx->cursor_get_column()); + _lookup_symbol(text, tx->get_caret_line(), tx->get_caret_column()); } } break; } @@ -1324,7 +1325,7 @@ void ScriptTextEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_ENTER_TREE: { - code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_row_height()); + code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_line_height()); } break; default: break; @@ -1389,6 +1390,7 @@ bool ScriptTextEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_ if (d.has("type") && (String(d["type"]) == "resource" || String(d["type"]) == "files" || String(d["type"]) == "nodes" || + String(d["type"]) == "obj_property" || String(d["type"]) == "files_and_dirs")) { return true; } @@ -1418,11 +1420,14 @@ static Node *_find_script_node(Node *p_edited_scene, Node *p_current_node, const } void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; + Dictionary d = p_data; CodeEdit *te = code_editor->get_text_editor(); - int row, col; - te->_get_mouse_pos(p_point, row, col); + Point2i pos = te->get_line_column_at_pos(p_point); + int row = pos.y; + int col = pos.x; if (d.has("type") && String(d["type"]) == "resource") { Ref<Resource> res = d["resource"]; @@ -1435,13 +1440,12 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data return; } - te->cursor_set_line(row); - te->cursor_set_column(col); - te->insert_text_at_cursor(res->get_path()); + te->set_caret_line(row); + te->set_caret_column(col); + te->insert_text_at_caret(res->get_path()); } if (d.has("type") && (String(d["type"]) == "files" || String(d["type"]) == "files_and_dirs")) { - const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\""; Array files = d["files"]; String text_to_drop; @@ -1458,9 +1462,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data } } - te->cursor_set_line(row); - te->cursor_set_column(col); - te->insert_text_at_cursor(text_to_drop); + te->set_caret_line(row); + te->set_caret_column(col); + te->insert_text_at_caret(text_to_drop); } if (d.has("type") && String(d["type"]) == "nodes") { @@ -1485,12 +1489,20 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data } String path = sn->get_path_to(node); - text_to_drop += "\"" + path.c_escape() + "\""; + text_to_drop += path.c_escape().quote(quote_style); } - te->cursor_set_line(row); - te->cursor_set_column(col); - te->insert_text_at_cursor(text_to_drop); + te->set_caret_line(row); + te->set_caret_column(col); + te->insert_text_at_caret(text_to_drop); + } + + if (d.has("type") && String(d["type"]) == "obj_property") { + const String text_to_drop = String(d["property"]).c_escape().quote(quote_style); + + te->set_caret_line(row); + te->set_caret_column(col); + te->insert_text_at_caret(text_to_drop); } } @@ -1504,18 +1516,20 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid() && mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { local_pos = mb->get_global_position() - tx->get_global_position(); create_menu = true; - } else if (k.is_valid() && k->get_keycode() == KEY_MENU) { - local_pos = tx->_get_cursor_pixel_pos(); + } else if (k.is_valid() && k->is_action("ui_menu", true)) { + tx->adjust_viewport_to_caret(); + local_pos = tx->get_caret_draw_pos(); create_menu = true; } if (create_menu) { - int col, row; - tx->_get_mouse_pos(local_pos, row, col); + Point2i pos = tx->get_line_column_at_pos(local_pos); + int row = pos.y; + int col = pos.x; - tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); - if (tx->is_right_click_moving_caret()) { - if (tx->is_selection_active()) { + tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/move_caret_on_right_click")); + if (tx->is_move_caret_on_right_click_enabled()) { + if (tx->has_selection()) { int from_line = tx->get_selection_from_line(); int to_line = tx->get_selection_to_line(); int from_column = tx->get_selection_from_column(); @@ -1526,18 +1540,18 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { tx->deselect(); } } - if (!tx->is_selection_active()) { - tx->cursor_set_line(row, true, false); - tx->cursor_set_column(col); + if (!tx->has_selection()) { + tx->set_caret_line(row, false, false); + tx->set_caret_column(col); } } String word_at_pos = tx->get_word_at_pos(local_pos); if (word_at_pos == "") { - word_at_pos = tx->get_word_under_cursor(); + word_at_pos = tx->get_word_under_caret(); } if (word_at_pos == "") { - word_at_pos = tx->get_selection_text(); + word_at_pos = tx->get_selected_text(); } bool has_color = (word_at_pos == "Color"); @@ -1589,7 +1603,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { has_color = false; } } - _make_context_menu(tx->is_selection_active(), has_color, foldable, open_docs, goto_definition, local_pos); + _make_context_menu(tx->has_selection(), has_color, foldable, open_docs, goto_definition, local_pos); } } @@ -1614,6 +1628,13 @@ void ScriptTextEditor::_color_changed(const Color &p_color) { code_editor->get_text_editor()->update(); } +void ScriptTextEditor::_prepare_edit_menu() { + const CodeEdit *tx = code_editor->get_text_editor(); + PopupMenu *popup = edit_menu->get_popup(); + popup->set_item_disabled(popup->get_item_index(EDIT_UNDO), !tx->has_undo()); + popup->set_item_disabled(popup->get_item_index(EDIT_REDO), !tx->has_redo()); +} + void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos) { context_menu->clear(); context_menu->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO); @@ -1653,6 +1674,10 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p } } + const CodeEdit *tx = code_editor->get_text_editor(); + context_menu->set_item_disabled(context_menu->get_item_index(EDIT_UNDO), !tx->has_undo()); + context_menu->set_item_disabled(context_menu->get_item_index(EDIT_REDO), !tx->has_redo()); + context_menu->set_position(get_global_transform().xform(p_pos)); context_menu->set_size(Vector2(1, 1)); context_menu->popup(); @@ -1738,6 +1763,7 @@ void ScriptTextEditor::_enable_code_editor() { search_menu->get_popup()->connect("id_pressed", callable_mp(this, &ScriptTextEditor::_edit_option)); edit_hb->add_child(edit_menu); + edit_menu->connect("about_to_popup", callable_mp(this, &ScriptTextEditor::_prepare_edit_menu)); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_redo"), EDIT_REDO); edit_menu->get_popup()->add_separator(); @@ -1924,12 +1950,12 @@ void ScriptTextEditor::register_editor() { // Leave these at zero, same can be accomplished with tab/shift-tab, including selection. // The next/previous in history shortcut in this case makes a lot more sense. - ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), 0); - ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), 0); + ED_SHORTCUT("script_text_editor/indent_left", TTR("Indent Left"), KEY_NONE); + ED_SHORTCUT("script_text_editor/indent_right", TTR("Indent Right"), KEY_NONE); ED_SHORTCUT("script_text_editor/toggle_comment", TTR("Toggle Comment"), KEY_MASK_CMD | KEY_K); ED_SHORTCUT("script_text_editor/toggle_fold_line", TTR("Fold/Unfold Line"), KEY_MASK_ALT | KEY_F); - ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), 0); - ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), 0); + ED_SHORTCUT("script_text_editor/fold_all_lines", TTR("Fold All Lines"), KEY_NONE); + ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), KEY_NONE); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C); #else @@ -1941,15 +1967,15 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/convert_indent_to_tabs", TTR("Convert Indent to Tabs"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_I); ED_SHORTCUT("script_text_editor/auto_indent", TTR("Auto Indent"), KEY_MASK_CMD | KEY_I); - ED_SHORTCUT("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); + ED_SHORTCUT_AND_COMMAND("script_text_editor/find", TTR("Find..."), KEY_MASK_CMD | KEY_F); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_MASK_CMD | KEY_G); ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G); - ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); + ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KEY_MASK_ALT | KEY_MASK_CMD | KEY_F); #else ED_SHORTCUT("script_text_editor/find_next", TTR("Find Next"), KEY_F3); ED_SHORTCUT("script_text_editor/find_previous", TTR("Find Previous"), KEY_MASK_SHIFT | KEY_F3); - ED_SHORTCUT("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R); + ED_SHORTCUT_AND_COMMAND("script_text_editor/replace", TTR("Replace..."), KEY_MASK_CMD | KEY_R); #endif ED_SHORTCUT("script_text_editor/find_in_files", TTR("Find in Files..."), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_F); @@ -1964,7 +1990,7 @@ void ScriptTextEditor::register_editor() { ED_SHORTCUT("script_text_editor/toggle_bookmark", TTR("Toggle Bookmark"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_B); ED_SHORTCUT("script_text_editor/goto_next_bookmark", TTR("Go to Next Bookmark"), KEY_MASK_CMD | KEY_B); ED_SHORTCUT("script_text_editor/goto_previous_bookmark", TTR("Go to Previous Bookmark"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B); - ED_SHORTCUT("script_text_editor/remove_all_bookmarks", TTR("Remove All Bookmarks"), 0); + ED_SHORTCUT("script_text_editor/remove_all_bookmarks", TTR("Remove All Bookmarks"), KEY_NONE); #ifdef OSX_ENABLED ED_SHORTCUT("script_text_editor/goto_function", TTR("Go to Function..."), KEY_MASK_CTRL | KEY_MASK_CMD | KEY_J); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index e4a13951e4..1ca6f56ea1 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -178,6 +178,7 @@ protected: void _make_context_menu(bool p_selection, bool p_color, bool p_foldable, bool p_open_docs, bool p_goto_definition, Vector2 p_pos); void _text_edit_gui_input(const Ref<InputEvent> &ev); void _color_changed(const Color &p_color); + void _prepare_edit_menu(); void _goto_line(int p_line) { goto_line(p_line); } void _lookup_symbol(const String &p_symbol, int p_row, int p_column); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 95973f9dfd..22ca5592bd 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -74,14 +74,14 @@ void ShaderTextEditor::reload_text() { ERR_FAIL_COND(shader.is_null()); CodeEdit *te = get_text_editor(); - int column = te->cursor_get_column(); - int row = te->cursor_get_line(); + int column = te->get_caret_column(); + int row = te->get_caret_line(); int h = te->get_h_scroll(); int v = te->get_v_scroll(); te->set_text(shader->get_code()); - te->cursor_set_line(row); - te->cursor_set_column(column); + te->set_caret_line(row); + te->set_caret_column(column); te->set_h_scroll(h); te->set_v_scroll(v); @@ -96,7 +96,7 @@ void ShaderTextEditor::set_warnings_panel(RichTextLabel *p_warnings_panel) { void ShaderTextEditor::_load_theme_settings() { CodeEdit *text_editor = get_text_editor(); - Color updated_marked_line_color = EDITOR_GET("text_editor/highlighting/mark_color"); + Color updated_marked_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color"); if (updated_marked_line_color != marked_line_color) { for (int i = 0; i < text_editor->get_line_count(); i++) { if (text_editor->get_line_background_color(i) == marked_line_color) { @@ -106,17 +106,17 @@ void ShaderTextEditor::_load_theme_settings() { marked_line_color = updated_marked_line_color; } - syntax_highlighter->set_number_color(EDITOR_GET("text_editor/highlighting/number_color")); - syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/highlighting/symbol_color")); - syntax_highlighter->set_function_color(EDITOR_GET("text_editor/highlighting/function_color")); - syntax_highlighter->set_member_variable_color(EDITOR_GET("text_editor/highlighting/member_variable_color")); + syntax_highlighter->set_number_color(EDITOR_GET("text_editor/theme/highlighting/number_color")); + syntax_highlighter->set_symbol_color(EDITOR_GET("text_editor/theme/highlighting/symbol_color")); + syntax_highlighter->set_function_color(EDITOR_GET("text_editor/theme/highlighting/function_color")); + syntax_highlighter->set_member_variable_color(EDITOR_GET("text_editor/theme/highlighting/member_variable_color")); syntax_highlighter->clear_keyword_colors(); List<String> keywords; ShaderLanguage::get_keyword_list(&keywords); - const Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - const Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color"); + const Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color"); + const Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color"); for (const String &E : keywords) { if (ShaderLanguage::is_control_flow_keyword(E)) { @@ -142,14 +142,14 @@ void ShaderTextEditor::_load_theme_settings() { } } - const Color member_variable_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + const Color member_variable_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); for (const String &E : built_ins) { syntax_highlighter->add_keyword_color(E, member_variable_color); } // Colorize comments. - const Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); + const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color"); syntax_highlighter->clear_color_regions(); syntax_highlighter->add_color_region("/*", "*/", comment_color, false); syntax_highlighter->add_color_region("//", "", comment_color, true); @@ -397,7 +397,7 @@ void ShaderEditor::_notification(int p_what) { void ShaderEditor::_editor_settings_changed() { shader_editor->update_editor_settings(); - shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/theme/line_spacing")); + shader_editor->get_text_editor()->add_theme_constant_override("line_spacing", EditorSettings::get_singleton()->get("text_editor/appearance/whitespace/line_spacing")); shader_editor->get_text_editor()->set_draw_breakpoints_gutter(false); shader_editor->get_text_editor()->set_draw_executing_lines_gutter(false); } @@ -408,7 +408,7 @@ void ShaderEditor::_show_warnings_panel(bool p_show) { void ShaderEditor::_warning_clicked(Variant p_line) { if (p_line.get_type() == Variant::INT) { - shader_editor->get_text_editor()->cursor_set_line(p_line.operator int64_t()); + shader_editor->get_text_editor()->set_caret_line(p_line.operator int64_t()); } } @@ -483,7 +483,7 @@ void ShaderEditor::_check_for_external_edit() { return; } - bool use_autoreload = bool(EDITOR_DEF("text_editor/files/auto_reload_scripts_on_external_change", false)); + bool use_autoreload = bool(EDITOR_DEF("text_editor/behavior/files/auto_reload_scripts_on_external_change", false)); if (shader->get_last_modified_time() != FileAccess::get_modified_time(shader->get_path())) { if (use_autoreload) { _reload_shader_from_disk(); @@ -550,13 +550,15 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && mb->is_pressed()) { - int col, row; CodeEdit *tx = shader_editor->get_text_editor(); - tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); - tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); - if (tx->is_right_click_moving_caret()) { - if (tx->is_selection_active()) { + Point2i pos = tx->get_line_column_at_pos(mb->get_global_position() - tx->get_global_position()); + int row = pos.y; + int col = pos.x; + tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/move_caret_on_right_click")); + + if (tx->is_move_caret_on_right_click_enabled()) { + if (tx->has_selection()) { int from_line = tx->get_selection_from_line(); int to_line = tx->get_selection_to_line(); int from_column = tx->get_selection_from_column(); @@ -567,19 +569,20 @@ void ShaderEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { tx->deselect(); } } - if (!tx->is_selection_active()) { - tx->cursor_set_line(row, true, false); - tx->cursor_set_column(col); + if (!tx->has_selection()) { + tx->set_caret_line(row, true, false); + tx->set_caret_column(col); } } - _make_context_menu(tx->is_selection_active(), get_local_mouse_position()); + _make_context_menu(tx->has_selection(), get_local_mouse_position()); } } Ref<InputEventKey> k = ev; - if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) { + if (k.is_valid() && k->is_pressed() && k->is_action("ui_menu", true)) { CodeEdit *tx = shader_editor->get_text_editor(); - _make_context_menu(tx->is_selection_active(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); + tx->adjust_viewport_to_caret(); + _make_context_menu(tx->has_selection(), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->get_caret_draw_pos())); context_menu->grab_focus(); } } diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index 4202d8b611..309821b3dc 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -386,7 +386,7 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi const real_t radius(half_height * 0.2); CapsuleShape3D *bone_shape_capsule = memnew(CapsuleShape3D); - bone_shape_capsule->set_height((half_height - radius) * 2); + bone_shape_capsule->set_height(half_height * 2); bone_shape_capsule->set_radius(radius); CollisionShape3D *bone_shape = memnew(CollisionShape3D); @@ -397,7 +397,7 @@ PhysicalBone3D *Skeleton3DEditor::create_physical_bone(int bone_id, int bone_chi bone_shape->set_transform(capsule_transform); Transform3D body_transform; - body_transform.set_look_at(Vector3(0, 0, 0), child_rest.origin); + body_transform.basis = Basis::looking_at(child_rest.origin); body_transform.origin = body_transform.basis.xform(Vector3(0, 0, -half_height)); Transform3D joint_transform; @@ -551,22 +551,30 @@ void Skeleton3DEditor::update_joint_tree() { items.insert(-1, root); - const Vector<int> &joint_porder = skeleton->get_bone_process_orders(); Ref<Texture> bone_icon = get_theme_icon(SNAME("BoneAttachment3D"), SNAME("EditorIcons")); - for (int i = 0; i < joint_porder.size(); ++i) { - const int b_idx = joint_porder[i]; + Vector<int> bones_to_process = skeleton->get_parentless_bones(); + while (bones_to_process.size() > 0) { + int current_bone_idx = bones_to_process[0]; + bones_to_process.erase(current_bone_idx); - const int p_idx = skeleton->get_bone_parent(b_idx); - TreeItem *p_item = items.find(p_idx)->get(); + const int parent_idx = skeleton->get_bone_parent(current_bone_idx); + TreeItem *parent_item = items.find(parent_idx)->get(); - TreeItem *joint_item = joint_tree->create_item(p_item); - items.insert(b_idx, joint_item); + TreeItem *joint_item = joint_tree->create_item(parent_item); + items.insert(current_bone_idx, joint_item); - joint_item->set_text(0, skeleton->get_bone_name(b_idx)); + joint_item->set_text(0, skeleton->get_bone_name(current_bone_idx)); joint_item->set_icon(0, bone_icon); joint_item->set_selectable(0, true); - joint_item->set_metadata(0, "bones/" + itos(b_idx)); + joint_item->set_metadata(0, "bones/" + itos(current_bone_idx)); + + // Add the bone's children to the list of bones to be processed + Vector<int> current_bone_child_bones = skeleton->get_bone_children(current_bone_idx); + int child_bone_size = current_bone_child_bones.size(); + for (int i = 0; i < child_bone_size; i++) { + bones_to_process.push_back(current_bone_child_bones[i]); + } } } diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 42f7d23da2..400f9f560f 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -40,7 +40,7 @@ #include "scene/gui/margin_container.h" #include "scene/gui/panel_container.h" -void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) { +void SpriteFramesEditor::gui_input(const Ref<InputEvent> &p_event) { } void SpriteFramesEditor::_open_sprite_sheet() { @@ -200,34 +200,36 @@ void SpriteFramesEditor::_sheet_scroll_input(const Ref<InputEvent> &p_event) { void SpriteFramesEditor::_sheet_add_frames() { Size2i size = split_sheet_preview->get_texture()->get_size(); - int h = split_sheet_h->get_value(); - int v = split_sheet_v->get_value(); + int frame_count_x = split_sheet_h->get_value(); + int frame_count_y = split_sheet_v->get_value(); + Size2 frame_size(size.width / frame_count_x, size.height / frame_count_y); undo_redo->create_action(TTR("Add Frame")); int fc = frames->get_frame_count(edited_anim); - AtlasTexture *atlas_source = Object::cast_to<AtlasTexture>(*split_sheet_preview->get_texture()); - - Rect2 region_rect = Rect2(); + Point2 src_origin; + Rect2 src_region(Point2(), size); - if (atlas_source && atlas_source->get_atlas().is_valid()) { - region_rect = atlas_source->get_region(); + AtlasTexture *src_atlas = Object::cast_to<AtlasTexture>(*split_sheet_preview->get_texture()); + if (src_atlas && src_atlas->get_atlas().is_valid()) { + src_origin = src_atlas->get_region().position - src_atlas->get_margin().position; + src_region = src_atlas->get_region(); } for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) { int idx = E->get(); - int width = size.width / h; - int height = size.height / v; - int xp = idx % h; - int yp = (idx - xp) / h; - int x = (xp * width) + region_rect.position.x; - int y = (yp * height) + region_rect.position.y; + Point2 frame_coords(idx % frame_count_x, idx / frame_count_x); + + Rect2 frame(frame_coords * frame_size + src_origin, frame_size); + Rect2 region = frame.intersection(src_region); + Rect2 margin(region == Rect2() ? Point2() : region.position - frame.position, frame.size - region.size); Ref<AtlasTexture> at; at.instantiate(); at->set_atlas(split_sheet_preview->get_texture()); - at->set_region(Rect2(x, y, width, height)); + at->set_region(region); + at->set_margin(margin); undo_redo->add_do_method(frames, "add_frame", edited_anim, at, -1); undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index e6c59e3533..17e30f0cab 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -147,7 +147,7 @@ class SpriteFramesEditor : public HSplitContainer { protected: void _notification(int p_what); - void _gui_input(Ref<InputEvent> p_event); + virtual void gui_input(const Ref<InputEvent> &p_event) override; static void _bind_methods(); public: diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index faf287b9bd..32bcc1a4e6 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -132,14 +132,14 @@ void TextEditor::reload_text() { ERR_FAIL_COND(text_file.is_null()); CodeEdit *te = code_editor->get_text_editor(); - int column = te->cursor_get_column(); - int row = te->cursor_get_line(); + int column = te->get_caret_column(); + int row = te->get_caret_line(); int h = te->get_h_scroll(); int v = te->get_v_scroll(); te->set_text(text_file->get_text()); - te->cursor_set_line(row); - te->cursor_set_column(column); + te->set_caret_line(row); + te->set_caret_column(column); te->set_h_scroll(h); te->set_v_scroll(v); @@ -332,7 +332,7 @@ void TextEditor::_edit_option(int p_op) { code_editor->duplicate_selection(); } break; case EDIT_TOGGLE_FOLD_LINE: { - tx->toggle_foldable_line(tx->cursor_get_line()); + tx->toggle_foldable_line(tx->get_caret_line()); tx->update(); } break; case EDIT_FOLD_ALL_LINES: { @@ -340,7 +340,7 @@ void TextEditor::_edit_option(int p_op) { tx->update(); } break; case EDIT_UNFOLD_ALL_LINES: { - tx->unhide_all_lines(); + tx->unfold_all_lines(); tx->update(); } break; case EDIT_TRIM_TRAILING_WHITESAPCE: { @@ -374,14 +374,14 @@ void TextEditor::_edit_option(int p_op) { code_editor->get_find_replace_bar()->popup_replace(); } break; case SEARCH_IN_FILES: { - String selected_text = code_editor->get_text_editor()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selected_text(); // Yep, because it doesn't make sense to instance this dialog for every single script open... // So this will be delegated to the ScriptEditor. emit_signal(SNAME("search_in_files_requested"), selected_text); } break; case REPLACE_IN_FILES: { - String selected_text = code_editor->get_text_editor()->get_selection_text(); + String selected_text = code_editor->get_text_editor()->get_selected_text(); emit_signal(SNAME("replace_in_files_requested"), selected_text); } break; @@ -427,16 +427,18 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { if (mb.is_valid()) { if (mb->get_button_index() == MOUSE_BUTTON_RIGHT) { - int col, row; CodeEdit *tx = code_editor->get_text_editor(); - tx->_get_mouse_pos(mb->get_global_position() - tx->get_global_position(), row, col); - tx->set_right_click_moves_caret(EditorSettings::get_singleton()->get("text_editor/cursor/right_click_moves_caret")); + Point2i pos = tx->get_line_column_at_pos(mb->get_global_position() - tx->get_global_position()); + int row = pos.y; + int col = pos.x; + + tx->set_move_caret_on_right_click_enabled(EditorSettings::get_singleton()->get("text_editor/behavior/navigation/move_caret_on_right_click")); bool can_fold = tx->can_fold_line(row); bool is_folded = tx->is_line_folded(row); - if (tx->is_right_click_moving_caret()) { - if (tx->is_selection_active()) { + if (tx->is_move_caret_on_right_click_enabled()) { + if (tx->has_selection()) { int from_line = tx->get_selection_from_line(); int to_line = tx->get_selection_to_line(); int from_column = tx->get_selection_from_column(); @@ -447,27 +449,35 @@ void TextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) { tx->deselect(); } } - if (!tx->is_selection_active()) { - tx->cursor_set_line(row, true, false); - tx->cursor_set_column(col); + if (!tx->has_selection()) { + tx->set_caret_line(row, true, false); + tx->set_caret_column(col); } } if (!mb->is_pressed()) { - _make_context_menu(tx->is_selection_active(), can_fold, is_folded, get_local_mouse_position()); + _make_context_menu(tx->has_selection(), can_fold, is_folded, get_local_mouse_position()); } } } Ref<InputEventKey> k = ev; - if (k.is_valid() && k->is_pressed() && k->get_keycode() == KEY_MENU) { + if (k.is_valid() && k->is_pressed() && k->is_action("ui_menu", true)) { CodeEdit *tx = code_editor->get_text_editor(); - int line = tx->cursor_get_line(); - _make_context_menu(tx->is_selection_active(), tx->can_fold_line(line), tx->is_line_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->_get_cursor_pixel_pos())); + int line = tx->get_caret_line(); + tx->adjust_viewport_to_caret(); + _make_context_menu(tx->has_selection(), tx->can_fold_line(line), tx->is_line_folded(line), (get_global_transform().inverse() * tx->get_global_transform()).xform(tx->get_caret_draw_pos())); context_menu->grab_focus(); } } +void TextEditor::_prepare_edit_menu() { + const CodeEdit *tx = code_editor->get_text_editor(); + PopupMenu *popup = edit_menu->get_popup(); + popup->set_item_disabled(popup->get_item_index(EDIT_UNDO), !tx->has_undo()); + popup->set_item_disabled(popup->get_item_index(EDIT_REDO), !tx->has_redo()); +} + void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position) { context_menu->clear(); if (p_selection) { @@ -494,6 +504,10 @@ void TextEditor::_make_context_menu(bool p_selection, bool p_can_fold, bool p_is context_menu->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_fold_line"), EDIT_TOGGLE_FOLD_LINE); } + const CodeEdit *tx = code_editor->get_text_editor(); + context_menu->set_item_disabled(context_menu->get_item_index(EDIT_UNDO), !tx->has_undo()); + context_menu->set_item_disabled(context_menu->get_item_index(EDIT_REDO), !tx->has_redo()); + context_menu->set_position(get_global_transform().xform(p_position)); context_menu->set_size(Vector2(1, 1)); context_menu->popup(); @@ -539,6 +553,7 @@ TextEditor::TextEditor() { edit_hb->add_child(edit_menu); edit_menu->set_text(TTR("Edit")); edit_menu->set_switch_on_hover(true); + edit_menu->connect("about_to_popup", callable_mp(this, &TextEditor::_prepare_edit_menu)); edit_menu->get_popup()->connect("id_pressed", callable_mp(this, &TextEditor::_edit_option)); edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_undo"), EDIT_UNDO); diff --git a/editor/plugins/text_editor.h b/editor/plugins/text_editor.h index 86a4910ac0..839e1c5f7a 100644 --- a/editor/plugins/text_editor.h +++ b/editor/plugins/text_editor.h @@ -92,6 +92,7 @@ protected: void _edit_option(int p_op); void _make_context_menu(bool p_selection, bool p_can_fold, bool p_is_folded, Vector2 p_position); void _text_edit_gui_input(const Ref<InputEvent> &ev); + void _prepare_edit_menu(); Map<String, Ref<EditorSyntaxHighlighter>> highlighters; void _change_syntax_highlighter(int p_idx); diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp index 3987cdd6a0..bd1923f4ab 100644 --- a/editor/plugins/texture_3d_editor_plugin.cpp +++ b/editor/plugins/texture_3d_editor_plugin.cpp @@ -34,9 +34,6 @@ #include "core/io/resource_loader.h" #include "editor/editor_settings.h" -void Texture3DEditor::_gui_input(Ref<InputEvent> p_event) { -} - void Texture3DEditor::_texture_rect_draw() { texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1)); } @@ -79,6 +76,8 @@ void Texture3DEditor::_update_material() { void Texture3DEditor::_make_shaders() { shader.instantiate(); shader->set_code(R"( +// Texture3DEditor preview shader. + shader_type canvas_item; uniform sampler3D tex; @@ -145,7 +144,6 @@ void Texture3DEditor::edit(Ref<Texture3D> p_texture) { } void Texture3DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &Texture3DEditor::_gui_input); ClassDB::bind_method(D_METHOD("_layer_changed"), &Texture3DEditor::_layer_changed); } diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h index 9d90d3653f..855194e644 100644 --- a/editor/plugins/texture_3d_editor_plugin.h +++ b/editor/plugins/texture_3d_editor_plugin.h @@ -65,7 +65,6 @@ class Texture3DEditor : public Control { protected: void _notification(int p_what); - void _gui_input(Ref<InputEvent> p_event); static void _bind_methods(); diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp index 80359452ac..424e018a47 100644 --- a/editor/plugins/texture_layered_editor_plugin.cpp +++ b/editor/plugins/texture_layered_editor_plugin.cpp @@ -34,7 +34,7 @@ #include "core/io/resource_loader.h" #include "editor/editor_settings.h" -void TextureLayeredEditor::_gui_input(Ref<InputEvent> p_event) { +void TextureLayeredEditor::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventMouseMotion> mm = p_event; @@ -106,6 +106,8 @@ void TextureLayeredEditor::_update_material() { void TextureLayeredEditor::_make_shaders() { shaders[0].instantiate(); shaders[0]->set_code(R"( +// TextureLayeredEditor preview shader (2D array). + shader_type canvas_item; uniform sampler2DArray tex; @@ -118,6 +120,8 @@ void fragment() { shaders[1].instantiate(); shaders[1]->set_code(R"( +// TextureLayeredEditor preview shader (cubemap). + shader_type canvas_item; uniform samplerCube tex; @@ -132,6 +136,8 @@ void fragment() { shaders[2].instantiate(); shaders[2]->set_code(R"( +// TextureLayeredEditor preview shader (cubemap array). + shader_type canvas_item; uniform samplerCubeArray tex; @@ -214,7 +220,6 @@ void TextureLayeredEditor::edit(Ref<TextureLayered> p_texture) { } void TextureLayeredEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_gui_input"), &TextureLayeredEditor::_gui_input); ClassDB::bind_method(D_METHOD("_layer_changed"), &TextureLayeredEditor::_layer_changed); } diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h index c4ced62fb9..a7fe4b94e9 100644 --- a/editor/plugins/texture_layered_editor_plugin.h +++ b/editor/plugins/texture_layered_editor_plugin.h @@ -67,7 +67,7 @@ class TextureLayeredEditor : public Control { protected: void _notification(int p_what); - void _gui_input(Ref<InputEvent> p_event); + virtual void gui_input(const Ref<InputEvent> &p_event) override; static void _bind_methods(); public: diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index b277f2ab42..1a6eb7b63b 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -330,7 +330,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { for (const Rect2 &E : autoslice_cache) { if (E.has_point(point)) { rect = E; - if (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !(Input::get_singleton()->is_key_pressed(KEY_SHIFT | KEY_ALT))) { + if (Input::get_singleton()->is_key_pressed(KEY_CTRL) && !(Input::get_singleton()->is_key_pressed(Key(KEY_SHIFT | KEY_ALT)))) { Rect2 r; if (node_sprite) { r = node_sprite->get_region_rect(); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 7ea3deedb9..165a381407 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -1721,6 +1721,8 @@ void ThemeItemEditorDialog::_edit_theme_item_gui_input(const Ref<InputEvent> &p_ edit_theme_item_dialog->hide(); edit_theme_item_dialog->set_input_as_handled(); } break; + default: + break; } } } diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 13f04cb804..0add83f64d 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -41,7 +41,7 @@ #include "editor/editor_scale.h" #include "editor/editor_settings.h" -void TileAtlasView::_gui_input(const Ref<InputEvent> &p_event) { +void TileAtlasView::gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { drag_type = DRAG_TYPE_NONE; @@ -548,8 +548,6 @@ void TileAtlasView::_notification(int p_what) { } void TileAtlasView::_bind_methods() { - ClassDB::bind_method("_gui_input", &TileAtlasView::_gui_input); - ADD_SIGNAL(MethodInfo("transform_changed", PropertyInfo(Variant::FLOAT, "zoom"), PropertyInfo(Variant::VECTOR2, "scroll"))); } @@ -582,7 +580,7 @@ TileAtlasView::TileAtlasView() { center_container = memnew(CenterContainer); center_container->set_mouse_filter(Control::MOUSE_FILTER_IGNORE); center_container->set_anchors_preset(Control::PRESET_CENTER); - center_container->connect("gui_input", callable_mp(this, &TileAtlasView::_gui_input)); + center_container->connect("gui_input", callable_mp(this, &TileAtlasView::gui_input)); panel->add_child(center_container); missing_source_label = memnew(Label); diff --git a/editor/plugins/tiles/tile_atlas_view.h b/editor/plugins/tiles/tile_atlas_view.h index b2046f4322..5b0df366ae 100644 --- a/editor/plugins/tiles/tile_atlas_view.h +++ b/editor/plugins/tiles/tile_atlas_view.h @@ -62,7 +62,7 @@ private: void _update_zoom_and_panning(bool p_zoom_on_mouse_pos = false); void _zoom_widget_changed(); void _center_view(); - void _gui_input(const Ref<InputEvent> &p_event); + virtual void gui_input(const Ref<InputEvent> &p_event) override; Map<Vector2, Map<int, Rect2i>> alternative_tiles_rect_cache; void _update_alternative_tiles_rect_cache(); diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index bab55df65a..d406c2514c 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -110,7 +110,7 @@ void DummyObject::clear_dummy_properties() { void GenericTilePolygonEditor::_base_control_draw() { ERR_FAIL_COND(!tile_set.is_valid()); - real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); Color grid_color = EditorSettings::get_singleton()->get("editors/tiles_editor/grid_color"); const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorPathSharpHandle"), SNAME("EditorIcons")); @@ -262,7 +262,7 @@ void GenericTilePolygonEditor::_advanced_menu_item_pressed(int p_item_pressed) { } void GenericTilePolygonEditor::_grab_polygon_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_point_index) { - const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + const real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); r_polygon_index = -1; r_point_index = -1; float closest_distance = grab_threshold + 1.0; @@ -280,7 +280,7 @@ void GenericTilePolygonEditor::_grab_polygon_point(Vector2 p_pos, const Transfor } void GenericTilePolygonEditor::_grab_polygon_segment_point(Vector2 p_pos, const Transform2D &p_polygon_xform, int &r_polygon_index, int &r_segment_index, Vector2 &r_point) { - const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + const real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); Point2 point = p_polygon_xform.affine_inverse().xform(p_pos); r_polygon_index = -1; @@ -340,7 +340,7 @@ void GenericTilePolygonEditor::_snap_to_half_pixel(Point2 &r_point) { } void GenericTilePolygonEditor::_base_control_gui_input(Ref<InputEvent> p_event) { - real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + real_t grab_threshold = EDITOR_GET("editors/polygon_editor/point_grab_radius"); hovered_polygon_index = -1; hovered_point_index = -1; diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index a9a36427db..aaa29bcb7a 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -484,7 +484,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { commit_message->set_h_grow_direction(Control::GrowDirection::GROW_DIRECTION_BEGIN); commit_message->set_v_grow_direction(Control::GrowDirection::GROW_DIRECTION_END); commit_message->set_custom_minimum_size(Size2(200, 100)); - commit_message->set_wrap_enabled(true); + commit_message->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY); commit_message->connect("text_changed", callable_mp(this, &VersionControlEditorPlugin::_update_commit_button)); commit_message->connect("gui_input", callable_mp(this, &VersionControlEditorPlugin::_commit_message_gui_input)); commit_box_vbc->add_child(commit_message); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 452ad126b3..50808a25af 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -70,14 +70,15 @@ const int MAX_FLOAT_CONST_DEFS = sizeof(float_constant_defs) / sizeof(FloatConst /////////////////// Control *VisualShaderNodePlugin::create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node) { - if (get_script_instance()) { - return get_script_instance()->call("_create_editor", p_parent_resource, p_node); + Object *ret; + if (GDVIRTUAL_CALL(_create_editor, p_parent_resource, p_node, ret)) { + return Object::cast_to<Control>(ret); } return nullptr; } void VisualShaderNodePlugin::_bind_methods() { - BIND_VMETHOD(MethodInfo(Variant::OBJECT, "_create_editor", PropertyInfo(Variant::OBJECT, "parent_resource", PROPERTY_HINT_RESOURCE_TYPE, "Resource"), PropertyInfo(Variant::OBJECT, "for_node", PROPERTY_HINT_RESOURCE_TYPE, "VisualShaderNode"))); + GDVIRTUAL_BIND(_create_editor, "parent_resource", "visual_shader_node"); } /////////////////// @@ -110,7 +111,6 @@ void VisualShaderGraphPlugin::_bind_methods() { ClassDB::bind_method("set_expression", &VisualShaderGraphPlugin::set_expression); ClassDB::bind_method("update_curve", &VisualShaderGraphPlugin::update_curve); ClassDB::bind_method("update_curve_xyz", &VisualShaderGraphPlugin::update_curve_xyz); - ClassDB::bind_method("update_constant", &VisualShaderGraphPlugin::update_constant); } void VisualShaderGraphPlugin::register_shader(VisualShader *p_shader) { @@ -237,18 +237,6 @@ int VisualShaderGraphPlugin::get_constant_index(float p_constant) const { return 0; } -void VisualShaderGraphPlugin::update_constant(VisualShader::Type p_type, int p_node_id) { - if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id) || !links[p_node_id].const_op) { - return; - } - VisualShaderNodeFloatConstant *float_const = Object::cast_to<VisualShaderNodeFloatConstant>(links[p_node_id].visual_node); - if (!float_const) { - return; - } - links[p_node_id].const_op->select(get_constant_index(float_const->get_constant())); - links[p_node_id].graph_node->set_size(Size2(-1, -1)); -} - void VisualShaderGraphPlugin::set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression) { if (p_type != visual_shader->get_shader_type() || !links.has(p_node_id) || !links[p_node_id].expression_edit) { return; @@ -267,10 +255,6 @@ void VisualShaderGraphPlugin::register_default_input_button(int p_node_id, int p links[p_node_id].input_ports.insert(p_port_id, { p_button }); } -void VisualShaderGraphPlugin::register_constant_option_btn(int p_node_id, OptionButton *p_button) { - links[p_node_id].const_op = p_button; -} - void VisualShaderGraphPlugin::register_expression_edit(int p_node_id, CodeEdit *p_expression_edit) { links[p_node_id].expression_edit = p_expression_edit; } @@ -322,7 +306,7 @@ void VisualShaderGraphPlugin::make_dirty(bool p_enabled) { } void VisualShaderGraphPlugin::register_link(VisualShader::Type p_type, int p_id, VisualShaderNode *p_visual_node, GraphNode *p_graph_node) { - links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } }); + links.insert(p_id, { p_type, p_visual_node, p_graph_node, p_visual_node->get_output_port_for_preview() != -1, -1, Map<int, InputPort>(), Map<int, Port>(), nullptr, nullptr, nullptr, { nullptr, nullptr, nullptr } }); } void VisualShaderGraphPlugin::register_output_port(int p_node_id, int p_port, TextureButton *p_button) { @@ -408,10 +392,14 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { node->connect("dragged", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_node_dragged), varray(p_id)); Control *custom_editor = nullptr; - int port_offset = 0; + int port_offset = 1; + + Control *content_offset = memnew(Control); + content_offset->set_custom_minimum_size(Size2(0, 5 * EDSCALE)); + node->add_child(content_offset); if (is_group) { - port_offset += 2; + port_offset += 1; } if (is_resizable) { @@ -448,7 +436,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { if (vsnode->get_input_port_count() == 0 && vsnode->get_output_port_count() == 1 && vsnode->get_output_port_name(0) == "") { //shortcut VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); - node->set_slot(0, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); + node->set_slot(1, false, VisualShaderNode::PORT_TYPE_SCALAR, Color(), true, port_right, type_color[port_right]); if (!vsnode->is_use_prop_slots()) { return; } @@ -494,23 +482,6 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { custom_editor = hbox; } - Ref<VisualShaderNodeFloatConstant> float_const = vsnode; - if (float_const.is_valid()) { - HBoxContainer *hbox = memnew(HBoxContainer); - - hbox->add_child(custom_editor); - OptionButton *btn = memnew(OptionButton); - hbox->add_child(btn); - register_constant_option_btn(p_id, btn); - btn->add_item(""); - for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) { - btn->add_item(float_constant_defs[i].name); - } - btn->select(get_constant_index(float_const->get_constant())); - btn->connect("item_selected", callable_mp(VisualShaderEditor::get_singleton(), &VisualShaderEditor::_float_constant_selected), varray(p_id)); - custom_editor = hbox; - } - if (custom_editor && !vsnode->is_use_prop_slots() && vsnode->get_output_port_count() > 0 && vsnode->get_output_port_name(0) == "" && (vsnode->get_input_port_count() == 0 || vsnode->get_input_port_name(0) == "")) { //will be embedded in first port } else if (custom_editor) { @@ -582,22 +553,26 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { if (is_curve) { VisualShaderNode::PortType port_left = vsnode->get_input_port_type(0); VisualShaderNode::PortType port_right = vsnode->get_output_port_type(0); - node->set_slot(0, true, port_left, type_color[port_left], true, port_right, type_color[port_right]); + node->set_slot(1, true, port_left, type_color[port_left], true, port_right, type_color[port_right]); VisualShaderEditor::get_singleton()->call_deferred(SNAME("_set_node_size"), (int)p_type, p_id, size); } if (vsnode->is_use_prop_slots()) { + String error = vsnode->get_warning(visual_shader->get_mode(), p_type); + if (error != String()) { + Label *error_label = memnew(Label); + error_label->add_theme_color_override("font_color", VisualShaderEditor::get_singleton()->get_theme_color(SNAME("error_color"), SNAME("Editor"))); + error_label->set_text(error); + node->add_child(error_label); + } + return; } custom_editor = nullptr; } if (is_group) { - offset = memnew(Control); - offset->set_custom_minimum_size(Size2(0, 6 * EDSCALE)); - node->add_child(offset); - if (group_node->is_editable()) { HBoxContainer *hb2 = memnew(HBoxContainer); @@ -885,15 +860,15 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { node->add_child(expression_box); register_expression_edit(p_id, expression_box); - Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); - Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); - Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color"); - Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); - Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); - Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); - Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color"); + Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color"); + Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color"); + Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color"); + Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color"); + Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color"); + Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color"); + Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color"); + Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); expression_box->set_syntax_highlighter(expression_syntax_highlighter); expression_box->add_theme_color_override("background_color", background_color); @@ -1007,6 +982,7 @@ void VisualShaderEditor::edit(VisualShader *p_visual_shader) { const Dictionary vs_version = visual_shader->get_engine_version(); if (!vs_version.has_all(components)) { visual_shader->update_engine_version(engine_version); + print_line(vformat(TTR("The shader (\"%s\") has been updated to correspond Godot %s.%s version."), visual_shader->get_path(), engine_version["major"], engine_version["minor"])); } else { for (int i = 0; i < components.size(); i++) { if (vs_version[components[i]] != engine_version[components[i]]) { @@ -1244,8 +1220,88 @@ void VisualShaderEditor::_update_options_menu() { Vector<AddOption> custom_options; Vector<AddOption> embedded_options; + static Vector<String> type_filter_exceptions; + if (type_filter_exceptions.is_empty()) { + type_filter_exceptions.append("VisualShaderNodeExpression"); + } + for (int i = 0; i < add_options.size(); i++) { if (!use_filter || add_options[i].name.findn(filter) != -1) { + // port type filtering + if (members_output_port_type != VisualShaderNode::PORT_TYPE_MAX || members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) { + Ref<VisualShaderNode> vsn; + int check_result = 0; + + if (!add_options[i].is_custom) { + vsn = Ref<VisualShaderNode>(Object::cast_to<VisualShaderNode>(ClassDB::instantiate(add_options[i].type))); + if (!vsn.is_valid()) { + continue; + } + + if (type_filter_exceptions.has(add_options[i].type)) { + check_result = 1; + } + + Ref<VisualShaderNodeInput> input = Object::cast_to<VisualShaderNodeInput>(vsn.ptr()); + if (input.is_valid()) { + input->set_shader_mode(visual_shader->get_mode()); + input->set_shader_type(visual_shader->get_shader_type()); + input->set_input_name(add_options[i].sub_func_str); + } + + Ref<VisualShaderNodeExpression> expression = Object::cast_to<VisualShaderNodeExpression>(vsn.ptr()); + if (expression.is_valid()) { + if (members_input_port_type == VisualShaderNode::PORT_TYPE_SAMPLER) { + check_result = -1; // expressions creates a port with required type automatically (except for sampler output) + } + } + + Ref<VisualShaderNodeUniformRef> uniform_ref = Object::cast_to<VisualShaderNodeUniformRef>(vsn.ptr()); + if (uniform_ref.is_valid()) { + check_result = -1; + + if (members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) { + for (int j = 0; j < uniform_ref->get_uniforms_count(); j++) { + if (visual_shader->is_port_types_compatible(uniform_ref->get_port_type_by_index(j), members_input_port_type)) { + check_result = 1; + break; + } + } + } + } + } else { + check_result = 1; + } + + if (members_output_port_type != VisualShaderNode::PORT_TYPE_MAX) { + if (check_result == 0) { + for (int j = 0; j < vsn->get_input_port_count(); j++) { + if (visual_shader->is_port_types_compatible(vsn->get_input_port_type(j), members_output_port_type)) { + check_result = 1; + break; + } + } + } + + if (check_result != 1) { + continue; + } + } + if (members_input_port_type != VisualShaderNode::PORT_TYPE_MAX) { + if (check_result == 0) { + for (int j = 0; j < vsn->get_output_port_count(); j++) { + if (visual_shader->is_port_types_compatible(vsn->get_output_port_type(j), members_input_port_type)) { + check_result = 1; + break; + } + } + } + + if (check_result != 1) { + continue; + } + } + } if ((add_options[i].func != current_func && add_options[i].func != -1) || !_is_available(add_options[i].mode)) { continue; } @@ -2028,6 +2084,8 @@ void VisualShaderEditor::_uniform_line_edit_changed(const String &p_text, int p_ undo_redo->add_undo_method(node.ptr(), "set_uniform_name", node->get_uniform_name()); undo_redo->add_do_method(graph_plugin.ptr(), "set_uniform_name", type, p_node_id, validated_name); undo_redo->add_undo_method(graph_plugin.ptr(), "set_uniform_name", type, p_node_id, node->get_uniform_name()); + undo_redo->add_do_method(graph_plugin.ptr(), "update_node_deferred", type, p_node_id); + undo_redo->add_undo_method(graph_plugin.ptr(), "update_node_deferred", type, p_node_id); undo_redo->add_do_method(this, "_update_uniforms", true); undo_redo->add_undo_method(this, "_update_uniforms", true); @@ -2171,6 +2229,16 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) { } } + // TRANSFORM_OP + { + VisualShaderNodeTransformOp *matOp = Object::cast_to<VisualShaderNodeTransformOp>(p_node); + + if (matOp) { + matOp->set_operator((VisualShaderNodeTransformOp::Operator)p_op_idx); + return; + } + } + // TRANSFORM_FUNC { VisualShaderNodeTransformFunc *matFunc = Object::cast_to<VisualShaderNodeTransformFunc>(p_node); @@ -2360,6 +2428,7 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa position += graph->get_size() * 0.5; position /= EDSCALE; } + position /= graph->get_zoom(); saved_node_pos_dirty = false; int id_to_use = visual_shader->get_valid_node_id(type); @@ -2478,6 +2547,7 @@ void VisualShaderEditor::_add_node(int p_idx, int p_op_idx, String p_resource_pa } } } + _member_cancel(); VisualShaderNodeUniform *uniform = Object::cast_to<VisualShaderNodeUniform>(vsnode.ptr()); if (uniform) { @@ -2600,13 +2670,25 @@ void VisualShaderEditor::_disconnection_request(const String &p_from, int p_from void VisualShaderEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) { from_node = p_from.to_int(); from_slot = p_from_slot; - _show_members_dialog(true); + VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX; + VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX; + Ref<VisualShaderNode> node = visual_shader->get_node(get_current_shader_type(), from_node); + if (node.is_valid()) { + output_port_type = node->get_output_port_type(from_slot); + } + _show_members_dialog(true, input_port_type, output_port_type); } void VisualShaderEditor::_connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position) { to_node = p_to.to_int(); to_slot = p_to_slot; - _show_members_dialog(true); + VisualShaderNode::PortType input_port_type = VisualShaderNode::PORT_TYPE_MAX; + VisualShaderNode::PortType output_port_type = VisualShaderNode::PORT_TYPE_MAX; + Ref<VisualShaderNode> node = visual_shader->get_node(get_current_shader_type(), to_node); + if (node.is_valid()) { + input_port_type = node->get_input_port_type(to_slot); + } + _show_members_dialog(true, input_port_type, output_port_type); } void VisualShaderEditor::_delete_nodes(int p_type, const List<int> &p_nodes) { @@ -2932,6 +3014,7 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { selected_constants.clear(); selected_uniforms.clear(); selected_comment = -1; + selected_float_constant = -1; List<int> to_change; for (int i = 0; i < graph->get_child_count(); i++) { @@ -2951,6 +3034,10 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { if (constant_node != nullptr) { selected_constants.insert(id); } + VisualShaderNodeFloatConstant *float_constant_node = Object::cast_to<VisualShaderNodeFloatConstant>(node.ptr()); + if (float_constant_node != nullptr) { + selected_float_constant = id; + } VisualShaderNodeUniform *uniform_node = Object::cast_to<VisualShaderNodeUniform>(node.ptr()); if (uniform_node != nullptr && uniform_node->is_convertible_to_constant()) { selected_uniforms.insert(id); @@ -2961,6 +3048,7 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { if (to_change.size() > 1) { selected_comment = -1; + selected_float_constant = -1; } if (to_change.is_empty() && copy_nodes_buffer.is_empty()) { @@ -2975,6 +3063,10 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { if (temp != -1) { popup_menu->remove_item(temp); } + temp = popup_menu->get_item_index(NodeMenuOptions::FLOAT_CONSTANTS); + if (temp != -1) { + popup_menu->remove_item(temp); + } temp = popup_menu->get_item_index(NodeMenuOptions::CONVERT_CONSTANTS_TO_UNIFORMS); if (temp != -1) { popup_menu->remove_item(temp); @@ -2996,14 +3088,23 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { popup_menu->remove_item(temp); } - if (selected_comment != -1) { + if (selected_constants.size() > 0 || selected_uniforms.size() > 0) { popup_menu->add_separator("", NodeMenuOptions::SEPARATOR2); - popup_menu->add_item(TTR("Set Comment Title"), NodeMenuOptions::SET_COMMENT_TITLE); - popup_menu->add_item(TTR("Set Comment Description"), NodeMenuOptions::SET_COMMENT_DESCRIPTION); - } - if (selected_constants.size() > 0 || selected_uniforms.size() > 0) { - popup_menu->add_separator("", NodeMenuOptions::SEPARATOR3); + if (selected_float_constant != -1) { + popup_menu->add_submenu_item(TTR("Float Constants"), "FloatConstants", int(NodeMenuOptions::FLOAT_CONSTANTS)); + + if (!constants_submenu) { + constants_submenu = memnew(PopupMenu); + constants_submenu->set_name("FloatConstants"); + + for (int i = 0; i < MAX_FLOAT_CONST_DEFS; i++) { + constants_submenu->add_item(float_constant_defs[i].name, i); + } + popup_menu->add_child(constants_submenu); + constants_submenu->connect("index_pressed", callable_mp(this, &VisualShaderEditor::_float_constant_selected)); + } + } if (selected_constants.size() > 0) { popup_menu->add_item(TTR("Convert Constant(s) to Uniform(s)"), NodeMenuOptions::CONVERT_CONSTANTS_TO_UNIFORMS); @@ -3014,6 +3115,12 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { } } + if (selected_comment != -1) { + popup_menu->add_separator("", NodeMenuOptions::SEPARATOR3); + popup_menu->add_item(TTR("Set Comment Title"), NodeMenuOptions::SET_COMMENT_TITLE); + popup_menu->add_item(TTR("Set Comment Description"), NodeMenuOptions::SET_COMMENT_DESCRIPTION); + } + menu_point = graph->get_local_mouse_position(); Point2 gpos = Input::get_singleton()->get_mouse_position(); popup_menu->set_position(gpos); @@ -3023,7 +3130,13 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { } } -void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) { +void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos, VisualShaderNode::PortType p_input_port_type, VisualShaderNode::PortType p_output_port_type) { + if (members_input_port_type != p_input_port_type || members_output_port_type != p_output_port_type) { + members_input_port_type = p_input_port_type; + members_output_port_type = p_output_port_type; + _update_options_menu(); + } + if (at_mouse_pos) { saved_node_pos_dirty = true; saved_node_pos = graph->get_local_mouse_position(); @@ -3059,7 +3172,7 @@ void VisualShaderEditor::_sbox_input(const Ref<InputEvent> &p_ie) { ie->get_keycode() == KEY_DOWN || ie->get_keycode() == KEY_ENTER || ie->get_keycode() == KEY_KP_ENTER)) { - members->call("_gui_input", ie); + members->gui_input(ie); node_filter->accept_event(); } } @@ -3099,15 +3212,15 @@ void VisualShaderEditor::_notification(int p_what) { preview_shader->set_icon(Control::get_theme_icon(SNAME("Shader"), SNAME("EditorIcons"))); { - Color background_color = EDITOR_GET("text_editor/highlighting/background_color"); - Color text_color = EDITOR_GET("text_editor/highlighting/text_color"); - Color keyword_color = EDITOR_GET("text_editor/highlighting/keyword_color"); - Color control_flow_keyword_color = EDITOR_GET("text_editor/highlighting/control_flow_keyword_color"); - Color comment_color = EDITOR_GET("text_editor/highlighting/comment_color"); - Color symbol_color = EDITOR_GET("text_editor/highlighting/symbol_color"); - Color function_color = EDITOR_GET("text_editor/highlighting/function_color"); - Color number_color = EDITOR_GET("text_editor/highlighting/number_color"); - Color members_color = EDITOR_GET("text_editor/highlighting/member_variable_color"); + Color background_color = EDITOR_GET("text_editor/theme/highlighting/background_color"); + Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color"); + Color keyword_color = EDITOR_GET("text_editor/theme/highlighting/keyword_color"); + Color control_flow_keyword_color = EDITOR_GET("text_editor/theme/highlighting/control_flow_keyword_color"); + Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color"); + Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color"); + Color function_color = EDITOR_GET("text_editor/theme/highlighting/function_color"); + Color number_color = EDITOR_GET("text_editor/theme/highlighting/number_color"); + Color members_color = EDITOR_GET("text_editor/theme/highlighting/member_variable_color"); preview_text->add_theme_color_override("background_color", background_color); @@ -3483,27 +3596,20 @@ void VisualShaderEditor::_uniform_select_item(Ref<VisualShaderNodeUniformRef> p_ undo_redo->commit_action(); } -void VisualShaderEditor::_float_constant_selected(int p_index, int p_node) { - if (p_index == 0) { - graph_plugin->update_node_size(p_node); - return; - } - - --p_index; - - ERR_FAIL_INDEX(p_index, MAX_FLOAT_CONST_DEFS); +void VisualShaderEditor::_float_constant_selected(int p_which) { + ERR_FAIL_INDEX(p_which, MAX_FLOAT_CONST_DEFS); VisualShader::Type type = get_current_shader_type(); - Ref<VisualShaderNodeFloatConstant> node = visual_shader->get_node(type, p_node); - if (!node.is_valid()) { - return; + Ref<VisualShaderNodeFloatConstant> node = visual_shader->get_node(type, selected_float_constant); + ERR_FAIL_COND(!node.is_valid()); + + if (Math::is_equal_approx(node->get_constant(), float_constant_defs[p_which].value)) { + return; // same } - undo_redo->create_action(TTR("Set constant")); - undo_redo->add_do_method(node.ptr(), "set_constant", float_constant_defs[p_index].value); + undo_redo->create_action(vformat(TTR("Set Constant: %s"), float_constant_defs[p_which].name)); + undo_redo->add_do_method(node.ptr(), "set_constant", float_constant_defs[p_which].value); undo_redo->add_undo_method(node.ptr(), "set_constant", node->get_constant()); - undo_redo->add_do_method(graph_plugin.ptr(), "update_constant", type, p_node); - undo_redo->add_undo_method(graph_plugin.ptr(), "update_constant", type, p_node); undo_redo->commit_action(); } @@ -3780,7 +3886,7 @@ void VisualShaderEditor::_update_preview() { preview_text->set_line_background_color(i, Color(0, 0, 0, 0)); } if (err != OK) { - Color error_line_color = EDITOR_GET("text_editor/highlighting/mark_color"); + Color error_line_color = EDITOR_GET("text_editor/theme/highlighting/mark_color"); preview_text->set_line_background_color(sl.get_error_line() - 1, error_line_color); error_panel->show(); @@ -3966,7 +4072,7 @@ VisualShaderEditor::VisualShaderEditor() { preview_text->set_v_size_flags(Control::SIZE_EXPAND_FILL); preview_text->set_syntax_highlighter(syntax_highlighter); preview_text->set_draw_line_numbers(true); - preview_text->set_readonly(true); + preview_text->set_editable(false); error_panel = memnew(PanelContainer); preview_vbox->add_child(error_panel); @@ -4448,6 +4554,7 @@ VisualShaderEditor::VisualShaderEditor() { // TRANSFORM add_options.push_back(AddOption("TransformFunc", "Transform", "Common", "VisualShaderNodeTransformFunc", TTR("Transform function."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("TransformOp", "Transform", "Common", "VisualShaderNodeTransformOp", TTR("Transform operator."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); add_options.push_back(AddOption("OuterProduct", "Transform", "Composition", "VisualShaderNodeOuterProduct", TTR("Calculate the outer product of a pair of vectors.\n\nOuterProduct treats the first parameter 'c' as a column vector (matrix with one column) and the second parameter 'r' as a row vector (matrix with one row) and does a linear algebraic matrix multiply 'c * r', yielding a matrix whose number of rows is the number of components in 'c' and whose number of columns is the number of components in 'r'."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); add_options.push_back(AddOption("TransformCompose", "Transform", "Composition", "VisualShaderNodeTransformCompose", TTR("Composes transform from four vectors."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); @@ -4458,7 +4565,11 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Inverse", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the inverse of a transform."), VisualShaderNodeTransformFunc::FUNC_INVERSE, VisualShaderNode::PORT_TYPE_TRANSFORM)); add_options.push_back(AddOption("Transpose", "Transform", "Functions", "VisualShaderNodeTransformFunc", TTR("Calculates the transpose of a transform."), VisualShaderNodeTransformFunc::FUNC_TRANSPOSE, VisualShaderNode::PORT_TYPE_TRANSFORM)); - add_options.push_back(AddOption("TransformMult", "Transform", "Operators", "VisualShaderNodeTransformMult", TTR("Multiplies transform by transform."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("Add", "Transform", "Operators", "VisualShaderNodeTransformOp", TTR("Sums two transforms."), VisualShaderNodeTransformOp::OP_ADD, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("Divide", "Transform", "Operators", "VisualShaderNodeTransformOp", TTR("Divides two transforms."), VisualShaderNodeTransformOp::OP_A_DIV_B, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("Multiply", "Transform", "Operators", "VisualShaderNodeTransformOp", TTR("Multiplies two transforms."), VisualShaderNodeTransformOp::OP_AxB, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("MultiplyComp", "Transform", "Operators", "VisualShaderNodeTransformOp", TTR("Performs per-component multiplication of two transforms."), VisualShaderNodeTransformOp::OP_AxB_COMP, VisualShaderNode::PORT_TYPE_TRANSFORM)); + add_options.push_back(AddOption("Subtract", "Transform", "Operators", "VisualShaderNodeTransformOp", TTR("Subtracts two transforms."), VisualShaderNodeTransformOp::OP_A_MINUS_B, VisualShaderNode::PORT_TYPE_TRANSFORM)); add_options.push_back(AddOption("TransformVectorMult", "Transform", "Operators", "VisualShaderNodeTransformVecMult", TTR("Multiplies vector by transform."), -1, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("TransformConstant", "Transform", "Variables", "VisualShaderNodeTransformConstant", TTR("Transform constant."), -1, VisualShaderNode::PORT_TYPE_TRANSFORM)); @@ -4741,9 +4852,6 @@ public: if (p_property != "constant") { undo_redo->add_do_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_node_deferred", shader_type, node_id); undo_redo->add_undo_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_node_deferred", shader_type, node_id); - } else { - undo_redo->add_do_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_constant", shader_type, node_id); - undo_redo->add_undo_method(VisualShaderEditor::get_singleton()->get_graph_plugin(), "update_constant", shader_type, node_id); } undo_redo->commit_action(); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index f53726edb9..9f24c5af72 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -47,6 +47,8 @@ class VisualShaderNodePlugin : public RefCounted { protected: static void _bind_methods(); + GDVIRTUAL2RC(Object *, _create_editor, RES, Ref<VisualShaderNode>) + public: virtual Control *create_editor(const Ref<Resource> &p_parent_resource, const Ref<VisualShaderNode> &p_node); }; @@ -73,7 +75,6 @@ private: Map<int, Port> output_ports; VBoxContainer *preview_box = nullptr; LineEdit *uniform_name = nullptr; - OptionButton *const_op = nullptr; CodeEdit *expression_edit = nullptr; CurveEditor *curve_editors[3] = { nullptr, nullptr, nullptr }; }; @@ -95,7 +96,6 @@ public: void register_output_port(int p_id, int p_port, TextureButton *p_button); void register_uniform_name(int p_id, LineEdit *p_uniform_name); void register_default_input_button(int p_node_id, int p_port_id, Button *p_button); - void register_constant_option_btn(int p_node_id, OptionButton *p_button); void register_expression_edit(int p_node_id, CodeEdit *p_expression_edit); void register_curve_editor(int p_node_id, int p_index, CurveEditor *p_curve_editor); void clear_links(); @@ -118,7 +118,6 @@ public: void set_uniform_name(VisualShader::Type p_type, int p_node_id, const String &p_name); void update_curve(int p_node_id); void update_curve_xyz(int p_node_id); - void update_constant(VisualShader::Type p_type, int p_node_id); void set_expression(VisualShader::Type p_type, int p_node_id, const String &p_expression); int get_constant_index(float p_constant) const; void update_node_size(int p_node_id); @@ -163,7 +162,10 @@ class VisualShaderEditor : public VBoxContainer { bool saved_node_pos_dirty; ConfirmationDialog *members_dialog; + VisualShaderNode::PortType members_input_port_type = VisualShaderNode::PORT_TYPE_MAX; + VisualShaderNode::PortType members_output_port_type = VisualShaderNode::PORT_TYPE_MAX; PopupMenu *popup_menu; + PopupMenu *constants_submenu = nullptr; MenuButton *tools; PopupPanel *comment_title_change_popup = nullptr; @@ -214,6 +216,7 @@ class VisualShaderEditor : public VBoxContainer { DELETE, DUPLICATE, SEPARATOR2, // ignore + FLOAT_CONSTANTS, CONVERT_CONSTANTS_TO_UNIFORMS, CONVERT_UNIFORMS_TO_CONSTANTS, SEPARATOR3, // ignore @@ -228,7 +231,7 @@ class VisualShaderEditor : public VBoxContainer { Label *highend_label; void _tools_menu_option(int p_idx); - void _show_members_dialog(bool at_mouse_pos); + void _show_members_dialog(bool at_mouse_pos, VisualShaderNode::PortType p_input_port_type = VisualShaderNode::PORT_TYPE_MAX, VisualShaderNode::PortType p_output_port_type = VisualShaderNode::PORT_TYPE_MAX); void _update_graph(); @@ -347,6 +350,7 @@ class VisualShaderEditor : public VBoxContainer { Set<int> selected_constants; Set<int> selected_uniforms; int selected_comment = -1; + int selected_float_constant = -1; void _convert_constants_to_uniforms(bool p_vice_versa); void _replace_node(VisualShader::Type p_type_id, int p_node_id, const StringName &p_from, const StringName &p_to); @@ -396,7 +400,7 @@ class VisualShaderEditor : public VBoxContainer { void _input_select_item(Ref<VisualShaderNodeInput> input, String name); void _uniform_select_item(Ref<VisualShaderNodeUniformRef> p_uniform, String p_name); - void _float_constant_selected(int p_index, int p_node); + void _float_constant_selected(int p_which); VisualShader::Type get_current_shader_type() const; |