diff options
Diffstat (limited to 'editor')
22 files changed, 206 insertions, 165 deletions
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 081f0ac868..7e59fc31c4 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -235,19 +235,19 @@ void CreateDialog::_add_type(const String &p_type, const TypeCategory p_type_cat } } else { if (ScriptServer::is_global_class(p_type)) { - inherits = EditorNode::get_editor_data().script_class_get_base(p_type); - if (inherits.is_empty()) { - Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_type); - ERR_FAIL_COND(script.is_null()); + Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(p_type); + ERR_FAIL_COND(script.is_null()); - Ref<Script> base = script->get_base_script(); - if (base.is_null()) { - String extends; - script->get_language()->get_global_class_name(script->get_path(), &extends); + Ref<Script> base = script->get_base_script(); + if (base.is_null()) { + String extends; + script->get_language()->get_global_class_name(script->get_path(), &extends); - inherits = extends; - inherited_type = TypeCategory::CPP_TYPE; - } else { + inherits = extends; + inherited_type = TypeCategory::CPP_TYPE; + } else { + inherits = script->get_language()->get_global_class_name(base->get_path()); + if (inherits.is_empty()) { inherits = base->get_path(); inherited_type = TypeCategory::PATH_TYPE; } diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index 250182b8fc..a9d18e9dcc 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -1468,7 +1468,8 @@ Error DocTools::save_classes(const String &p_default_path, const Map<String, Str Error DocTools::load_compressed(const uint8_t *p_data, int p_compressed_size, int p_uncompressed_size) { Vector<uint8_t> data; data.resize(p_uncompressed_size); - Compression::decompress(data.ptrw(), p_uncompressed_size, p_data, p_compressed_size, Compression::MODE_DEFLATE); + int ret = Compression::decompress(data.ptrw(), p_uncompressed_size, p_data, p_compressed_size, Compression::MODE_DEFLATE); + ERR_FAIL_COND_V_MSG(ret == -1, ERR_FILE_CORRUPT, "Compressed file is corrupt."); class_list.clear(); Ref<XMLParser> parser = memnew(XMLParser); diff --git a/editor/editor_atlas_packer.cpp b/editor/editor_atlas_packer.cpp index aad32968de..9c6bcd769a 100644 --- a/editor/editor_atlas_packer.cpp +++ b/editor/editor_atlas_packer.cpp @@ -30,60 +30,10 @@ #include "editor_atlas_packer.h" +#include "core/math/geometry_2d.h" #include "core/math/vector2.h" #include "core/math/vector2i.h" -void EditorAtlasPacker::_plot_triangle(Ref<BitMap> p_bitmap, Vector2i *vertices) { - int width = p_bitmap->get_size().width; - int height = p_bitmap->get_size().height; - int x[3]; - int y[3]; - - for (int j = 0; j < 3; j++) { - x[j] = vertices[j].x; - y[j] = vertices[j].y; - } - - // sort the points vertically - if (y[1] > y[2]) { - SWAP(x[1], x[2]); - SWAP(y[1], y[2]); - } - if (y[0] > y[1]) { - SWAP(x[0], x[1]); - SWAP(y[0], y[1]); - } - if (y[1] > y[2]) { - SWAP(x[1], x[2]); - SWAP(y[1], y[2]); - } - - double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1); - double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1); - double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1); - double xf = x[0]; - double xt = x[0] + dx_upper; // if y[0] == y[1], special case - for (int yi = y[0]; yi <= (y[2] > height - 1 ? height - 1 : y[2]); yi++) { - if (yi >= 0) { - for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < width ? xt : width - 1); xi++) { - //pixels[int(x + y * width)] = color; - - p_bitmap->set_bit(Point2(xi, yi), true); - } - - for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) { - p_bitmap->set_bit(Point2(xi, yi), true); - } - } - xf += dx_far; - if (yi < y[1]) { - xt += dx_upper; - } else { - xt += dx_low; - } - } -} - void EditorAtlasPacker::chart_pack(Vector<Chart> &charts, int &r_width, int &r_height, int p_atlas_max_size, int p_cell_resolution) { int divide_by = MIN(64, p_cell_resolution); Vector<PlottedBitmap> bitmaps; @@ -122,10 +72,18 @@ void EditorAtlasPacker::chart_pack(Vector<Chart> &charts, int &r_width, int &r_h Vector2 vtx = chart.vertices[chart.faces[j].vertex[k]]; vtx -= aabb.position; vtx /= divide_by; + vtx.x = MIN(vtx.x, w - 1); + vtx.y = MIN(vtx.y, h - 1); v[k] = vtx; } - _plot_triangle(src_bitmap, v); + for (int k = 0; k < 3; k++) { + int l = k == 0 ? 2 : k - 1; + Vector<Point2i> points = Geometry2D::bresenham_line(v[k], v[l]); + for (Point2i point : points) { + src_bitmap->set_bit(point, true); + } + } } //src_bitmap->convert_to_image()->save_png("bitmap" + itos(i) + ".png"); diff --git a/editor/editor_atlas_packer.h b/editor/editor_atlas_packer.h index 169a6bead8..7b7692011f 100644 --- a/editor/editor_atlas_packer.h +++ b/editor/editor_atlas_packer.h @@ -67,8 +67,6 @@ private: } }; - static void _plot_triangle(Ref<BitMap> p_bitmap, Vector2i *vertices); - public: static void chart_pack(Vector<Chart> &charts, int &r_width, int &r_height, int p_atlas_max_size = 2048, int p_cell_resolution = 4); }; diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp index 6a5ab91ba0..18324f9971 100644 --- a/editor/editor_settings_dialog.cpp +++ b/editor/editor_settings_dialog.cpp @@ -369,6 +369,11 @@ void EditorSettingsDialog::_update_shortcuts() { Array events; // Need to get the list of events into an array so it can be set as metadata on the item. Vector<String> event_strings; + // Skip non-builtin actions. + if (!InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().has(action_name)) { + continue; + } + List<Ref<InputEvent>> all_default_events = InputMap::get_singleton()->get_builtins_with_feature_overrides_applied().find(action_name).value(); List<Ref<InputEventKey>> key_default_events; // Remove all non-key events from the defaults. Only check keys, since we are in the editor. diff --git a/editor/editor_translation.cpp b/editor/editor_translation.cpp index 98248f3a87..f64adcf0a1 100644 --- a/editor/editor_translation.cpp +++ b/editor/editor_translation.cpp @@ -56,7 +56,8 @@ void load_editor_translations(const String &p_locale) { if (etl->lang == p_locale) { Vector<uint8_t> data; data.resize(etl->uncomp_size); - Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE); + int ret = Compression::decompress(data.ptrw(), etl->uncomp_size, etl->data, etl->comp_size, Compression::MODE_DEFLATE); + ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt."); FileAccessMemory *fa = memnew(FileAccessMemory); fa->open_custom(data.ptr(), data.size()); @@ -80,7 +81,8 @@ void load_doc_translations(const String &p_locale) { if (dtl->lang == p_locale) { Vector<uint8_t> data; data.resize(dtl->uncomp_size); - Compression::decompress(data.ptrw(), dtl->uncomp_size, dtl->data, dtl->comp_size, Compression::MODE_DEFLATE); + int ret = Compression::decompress(data.ptrw(), dtl->uncomp_size, dtl->data, dtl->comp_size, Compression::MODE_DEFLATE); + ERR_FAIL_COND_MSG(ret == -1, "Compressed file is corrupt."); FileAccessMemory *fa = memnew(FileAccessMemory); fa->open_custom(data.ptr(), data.size()); diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 8486d170a7..ebfb0b32fb 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -560,7 +560,7 @@ void DynamicFontImportSettings::_variation_changed(const String &p_edited_proper void DynamicFontImportSettings::_variations_validate() { String warn; if (!vars_list_root->get_first_child()) { - warn = TTR("Warinig: There are no configurations specified, no glyphs will be pre-rendered."); + warn = TTR("Warning: There are no configurations specified, no glyphs will be pre-rendered."); } for (TreeItem *vars_item_a = vars_list_root->get_first_child(); vars_item_a; vars_item_a = vars_item_a->get_next()) { Ref<DynamicFontImportSettingsData> import_variation_data_a = vars_item_a->get_metadata(0); @@ -575,7 +575,7 @@ void DynamicFontImportSettings::_variations_validate() { match = match && (import_variation_data_b->settings[E->key()] == E->get()); } if (match) { - warn = TTR("Warinig: Multiple configurations have identical settings. Duplicates will be ignored."); + warn = TTR("Warning: Multiple configurations have identical settings. Duplicates will be ignored."); break; } } diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index c1ae5be0bb..3b5a82b2c3 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -1535,7 +1535,7 @@ void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) { bool has_rotation = false; bool has_scale = false; - for (int i = 0; cn->xform_list.size(); i++) { + for (int i = 0; i < cn->xform_list.size(); i++) { switch (cn->xform_list[i].op) { case Collada::Node::XForm::OP_ROTATE: { has_rotation = true; diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 3eb12353b5..e7c605aaf0 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -1649,14 +1649,6 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } } - if (generate_lods) { - src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle); - } - - if (create_shadow_meshes) { - src_mesh_node->get_mesh()->create_shadow_mesh(); - } - if (bake_lightmaps) { Transform3D xf; Node3D *n = src_mesh_node; @@ -1689,6 +1681,14 @@ void ResourceImporterScene::_generate_meshes(Node *p_node, const Dictionary &p_m } } + if (generate_lods) { + src_mesh_node->get_mesh()->generate_lods(merge_angle, split_angle); + } + + if (create_shadow_meshes) { + src_mesh_node->get_mesh()->create_shadow_mesh(); + } + if (!save_to_file.is_empty()) { Ref<Mesh> existing = Ref<Resource>(ResourceCache::get(save_to_file)); if (existing.is_valid()) { diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index d2a9fe2538..cd481e009e 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -75,6 +75,7 @@ void ResourceImporterTextureAtlas::get_import_options(const String &p_path, List r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "atlas_file", PROPERTY_HINT_SAVE_FILE, "*.png"), "")); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "import_mode", PROPERTY_HINT_ENUM, "Region,Mesh2D"), 0)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "crop_to_region"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "trim_alpha_border_from_region"), true)); } String ResourceImporterTextureAtlas::get_option_group_file() const { @@ -210,14 +211,18 @@ Error ResourceImporterTextureAtlas::import_group_file(const String &p_group_file pack_data.is_cropped = options["crop_to_region"]; int mode = options["import_mode"]; + bool trim_alpha_border_from_region = options["trim_alpha_border_from_region"]; if (mode == IMPORT_MODE_REGION) { pack_data.is_mesh = false; EditorAtlasPacker::Chart chart; - //clip a region from the image - Rect2 used_rect = image->get_used_rect(); + Rect2 used_rect = Rect2(Vector2(), image->get_size()); + if (trim_alpha_border_from_region) { + // Clip a region from the image. + used_rect = image->get_used_rect(); + } pack_data.region = used_rect; chart.vertices.push_back(used_rect.position); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 76558eb946..e43d1feb08 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1163,25 +1163,25 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo if (k.is_valid()) { if (k->is_pressed()) { if (ED_GET_SHORTCUT("canvas_item_editor/zoom_3.125_percent")->matches_event(p_event)) { - _update_zoom((1.0 / 32.0) * MAX(1, EDSCALE)); + _shortcut_zoom_set(1.0 / 32.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_6.25_percent")->matches_event(p_event)) { - _update_zoom((1.0 / 16.0) * MAX(1, EDSCALE)); + _shortcut_zoom_set(1.0 / 16.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_12.5_percent")->matches_event(p_event)) { - _update_zoom((1.0 / 8.0) * MAX(1, EDSCALE)); + _shortcut_zoom_set(1.0 / 8.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_25_percent")->matches_event(p_event)) { - _update_zoom((1.0 / 4.0) * MAX(1, EDSCALE)); + _shortcut_zoom_set(1.0 / 4.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_50_percent")->matches_event(p_event)) { - _update_zoom((1.0 / 2.0) * MAX(1, EDSCALE)); + _shortcut_zoom_set(1.0 / 2.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_100_percent")->matches_event(p_event)) { - _update_zoom(1.0 * MAX(1, EDSCALE)); + _shortcut_zoom_set(1.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_200_percent")->matches_event(p_event)) { - _update_zoom(2.0 * MAX(1, EDSCALE)); + _shortcut_zoom_set(2.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_400_percent")->matches_event(p_event)) { - _update_zoom(4.0 * MAX(1, EDSCALE)); + _shortcut_zoom_set(4.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_800_percent")->matches_event(p_event)) { - _update_zoom(8.0 * MAX(1, EDSCALE)); + _shortcut_zoom_set(8.0); } else if (ED_GET_SHORTCUT("canvas_item_editor/zoom_1600_percent")->matches_event(p_event)) { - _update_zoom(16.0 * MAX(1, EDSCALE)); + _shortcut_zoom_set(16.0); } } } @@ -3510,7 +3510,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans return; } CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); - if (canvas_item && !canvas_item->is_visible()) { + if (canvas_item && !canvas_item->is_visible_in_tree()) { return; } @@ -4010,6 +4010,10 @@ void CanvasItemEditor::_update_zoom(real_t p_zoom) { _zoom_on_position(p_zoom, viewport_scrollable->get_size() / 2.0); } +void CanvasItemEditor::_shortcut_zoom_set(real_t p_zoom) { + _zoom_on_position(p_zoom * MAX(1, EDSCALE), viewport->get_local_mouse_position()); +} + void CanvasItemEditor::_button_toggle_smart_snap(bool p_status) { smart_snap_active = p_status; viewport->update(); @@ -5500,16 +5504,18 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons editor_data->get_undo_redo().add_do_method(ed, "live_debug_instance_node", edited_scene->get_path_to(parent), path, new_name); editor_data->get_undo_redo().add_undo_method(ed, "live_debug_remove_node", NodePath(String(edited_scene->get_path_to(parent)) + "/" + new_name)); - CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent); - if (parent_ci) { + CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instantiated_scene); + if (instance_ci) { Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point); target_pos = canvas_item_editor->snap_point(target_pos); - target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); - // Preserve instance position of the original scene. - CanvasItem *instance_ci = Object::cast_to<CanvasItem>(instantiated_scene); - if (instance_ci) { - target_pos += instance_ci->_edit_get_position(); + + CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent); + if (parent_ci) { + target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); } + // Preserve instance position of the original scene. + target_pos += instance_ci->_edit_get_position(); + editor_data->get_undo_redo().add_do_method(instantiated_scene, "set_position", target_pos); } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 57760475a1..e7c265ee02 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -470,6 +470,7 @@ private: VBoxContainer *controls_vb; EditorZoomWidget *zoom_widget; void _update_zoom(real_t p_zoom); + void _shortcut_zoom_set(real_t p_zoom); void _zoom_on_position(real_t p_zoom, Point2 p_position = Point2()); void _button_toggle_smart_snap(bool p_status); void _button_toggle_grid_snap(bool p_status); diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index e6f267673c..7b85fea1e9 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -358,8 +358,12 @@ void EditorPropertySizeFlags::setup(const Vector<String> &p_options, bool p_vert Control *gui_base = EditorNode::get_singleton()->get_gui_base(); String wide_preset_icon = SNAME("ControlAlignHCenterWide"); + String begin_preset_icon = SNAME("ControlAlignCenterLeft"); + String end_preset_icon = SNAME("ControlAlignCenterRight"); if (vertical) { wide_preset_icon = SNAME("ControlAlignVCenterWide"); + begin_preset_icon = SNAME("ControlAlignCenterTop"); + end_preset_icon = SNAME("ControlAlignCenterBottom"); } flag_presets->clear(); @@ -367,12 +371,12 @@ void EditorPropertySizeFlags::setup(const Vector<String> &p_options, bool p_vert flag_presets->add_icon_item(gui_base->get_theme_icon(wide_preset_icon, SNAME("EditorIcons")), TTR("Fill"), SIZE_FLAGS_PRESET_FILL); } // Shrink Begin is the same as no flags at all, as such it cannot be disabled. - flag_presets->add_icon_item(gui_base->get_theme_icon(SNAME("ControlAlignCenterLeft"), SNAME("EditorIcons")), TTR("Shrink Begin"), SIZE_FLAGS_PRESET_SHRINK_BEGIN); + flag_presets->add_icon_item(gui_base->get_theme_icon(begin_preset_icon, SNAME("EditorIcons")), TTR("Shrink Begin"), SIZE_FLAGS_PRESET_SHRINK_BEGIN); if (flags.has(SIZE_SHRINK_CENTER)) { flag_presets->add_icon_item(gui_base->get_theme_icon(SNAME("ControlAlignCenter"), SNAME("EditorIcons")), TTR("Shrink Center"), SIZE_FLAGS_PRESET_SHRINK_CENTER); } if (flags.has(SIZE_SHRINK_END)) { - flag_presets->add_icon_item(gui_base->get_theme_icon(SNAME("ControlAlignCenterRight"), SNAME("EditorIcons")), TTR("Shrink End"), SIZE_FLAGS_PRESET_SHRINK_END); + flag_presets->add_icon_item(gui_base->get_theme_icon(end_preset_icon, SNAME("EditorIcons")), TTR("Shrink End"), SIZE_FLAGS_PRESET_SHRINK_END); } flag_presets->add_separator(); flag_presets->add_item(TTR("Custom"), SIZE_FLAGS_PRESET_CUSTOM); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 46b33f62fe..23f3087553 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -3669,13 +3669,8 @@ void VoxelGIGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { continue; } - Vector2 dir; - dir[j] = 1.0; - Vector2 ta, tb; int j_n1 = (j + 1) % 3; int j_n2 = (j + 2) % 3; - ta[j_n1] = 1.0; - tb[j_n2] = 1.0; for (int k = 0; k < 4; k++) { Vector3 from = aabb.position, to = aabb.position; diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 3d3738ad47..002c879cdc 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/input/input.h" +#include "core/input/input_map.h" #include "core/math/camera_matrix.h" #include "core/math/math_funcs.h" #include "core/os/keyboard.h" @@ -2291,26 +2292,6 @@ Point2i Node3DEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouse return relative; } -static bool is_shortcut_pressed(const String &p_path) { - Ref<Shortcut> shortcut = ED_GET_SHORTCUT(p_path); - if (shortcut.is_null()) { - return false; - } - - const Array shortcuts = shortcut->get_events(); - Ref<InputEventKey> k; - if (shortcuts.size() > 0) { - k = shortcuts.front(); - } - - if (k.is_null()) { - return false; - } - const Input &input = *Input::get_singleton(); - Key keycode = k->get_keycode(); - return input.is_key_pressed(keycode); -} - void Node3DEditorViewport::_update_freelook(real_t delta) { if (!is_freelook_active()) { return; @@ -2340,31 +2321,34 @@ void Node3DEditorViewport::_update_freelook(real_t delta) { Vector3 direction; - if (is_shortcut_pressed("spatial_editor/freelook_left")) { + // Use actions from the inputmap, as this is the only way to reliably detect input in this method. + // See #54469 for more discussion and explanation. + Input *inp = Input::get_singleton(); + if (inp->is_action_pressed("spatial_editor/freelook_left")) { direction -= right; } - if (is_shortcut_pressed("spatial_editor/freelook_right")) { + if (inp->is_action_pressed("spatial_editor/freelook_right")) { direction += right; } - if (is_shortcut_pressed("spatial_editor/freelook_forward")) { + if (inp->is_action_pressed("spatial_editor/freelook_forward")) { direction += forward; } - if (is_shortcut_pressed("spatial_editor/freelook_backwards")) { + if (inp->is_action_pressed("spatial_editor/freelook_backwards")) { direction -= forward; } - if (is_shortcut_pressed("spatial_editor/freelook_up")) { + if (inp->is_action_pressed("spatial_editor/freelook_up")) { direction += up; } - if (is_shortcut_pressed("spatial_editor/freelook_down")) { + if (inp->is_action_pressed("spatial_editor/freelook_down")) { direction -= up; } real_t speed = freelook_speed; - if (is_shortcut_pressed("spatial_editor/freelook_speed_modifier")) { + if (inp->is_action_pressed("spatial_editor/freelook_speed_modifier")) { speed *= 3.0; } - if (is_shortcut_pressed("spatial_editor/freelook_slow_modifier")) { + if (inp->is_action_pressed("spatial_editor/freelook_slow_modifier")) { speed *= 0.333333; } @@ -4427,6 +4411,28 @@ void Node3DEditorViewport::finish_transform() { surface->update(); } +// Register a shortcut and also add it as an input action with the same events. +void Node3DEditorViewport::register_shortcut_action(const String &p_path, const String &p_name, Key p_keycode) { + Ref<Shortcut> sc = ED_SHORTCUT(p_path, p_name, p_keycode); + shortcut_changed_callback(sc, p_path); + // Connect to the change event on the shortcut so the input binding can be updated. + sc->connect("changed", callable_mp(this, &Node3DEditorViewport::shortcut_changed_callback), varray(sc, p_path)); +} + +// Update the action in the InputMap to the provided shortcut events. +void Node3DEditorViewport::shortcut_changed_callback(const Ref<Shortcut> p_shortcut, const String &p_shortcut_path) { + InputMap *im = InputMap::get_singleton(); + if (im->has_action(p_shortcut_path)) { + im->action_erase_events(p_shortcut_path); + } else { + im->add_action(p_shortcut_path); + } + + for (int i = 0; i < p_shortcut->get_events().size(); i++) { + im->action_add_event(p_shortcut_path, p_shortcut->get_events()[i]); + } +} + Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p_index) { cpu_time_history_index = 0; gpu_time_history_index = 0; @@ -4586,14 +4592,15 @@ Node3DEditorViewport::Node3DEditorViewport(Node3DEditor *p_spatial_editor, int p view_menu->get_popup()->set_item_tooltip(shadeless_idx, unsupported_tooltip); } - ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), Key::A); - ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), Key::D); - ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), Key::W); - ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), Key::S); - ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), Key::E); - ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), Key::Q); - ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), Key::SHIFT); - ED_SHORTCUT("spatial_editor/freelook_slow_modifier", TTR("Freelook Slow Modifier"), Key::ALT); + register_shortcut_action("spatial_editor/freelook_left", TTR("Freelook Left"), Key::A); + register_shortcut_action("spatial_editor/freelook_right", TTR("Freelook Right"), Key::D); + register_shortcut_action("spatial_editor/freelook_forward", TTR("Freelook Forward"), Key::W); + register_shortcut_action("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), Key::S); + register_shortcut_action("spatial_editor/freelook_up", TTR("Freelook Up"), Key::E); + register_shortcut_action("spatial_editor/freelook_down", TTR("Freelook Down"), Key::Q); + register_shortcut_action("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), Key::SHIFT); + register_shortcut_action("spatial_editor/freelook_slow_modifier", TTR("Freelook Slow Modifier"), Key::ALT); + ED_SHORTCUT("spatial_editor/lock_transform_x", TTR("Lock Transformation to X axis"), Key::X); ED_SHORTCUT("spatial_editor/lock_transform_y", TTR("Lock Transformation to Y axis"), Key::Y); ED_SHORTCUT("spatial_editor/lock_transform_z", TTR("Lock Transformation to Z axis"), Key::Z); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 9e92a1e9b3..5c0bfab34e 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -378,7 +378,7 @@ private: Node3DEditor *spatial_editor; Camera3D *previewing; - Camera3D *preview; + Camera3D *preview = nullptr; bool previewing_cinema; bool _is_node_locked(const Node *p_node); @@ -415,6 +415,9 @@ private: void update_transform(Point2 p_mousepos, bool p_shift); void finish_transform(); + void register_shortcut_action(const String &p_path, const String &p_name, Key p_keycode); + void shortcut_changed_callback(const Ref<Shortcut> p_shortcut, const String &p_shortcut_path); + protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index bd4064708b..30c2b12519 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -762,7 +762,7 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save, bool p_history_back) { if (p_save && file.is_valid()) { // Do not try to save internal scripts, but prompt to save in-memory // scripts which are not saved to disk yet (have empty path). - if (file->is_built_in()) { + if (!file->is_built_in()) { save_current_script(); } } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 95cd5683a6..4a0fc0b29f 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -1347,7 +1347,12 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } if (picked_source >= 0) { - sources_list->set_current(picked_source); + for (int i = 0; i < sources_list->get_item_count(); i++) { + if (int(sources_list->get_item_metadata(i)) == picked_source) { + sources_list->set_current(i); + break; + } + } sources_list->ensure_current_is_visible(); TilesEditorPlugin::get_singleton()->set_sources_lists_current(picked_source); } @@ -4019,7 +4024,7 @@ TileMapEditor::TileMapEditor() { // Layer selector. layers_selection_popup = memnew(PopupMenu); layers_selection_popup->connect("id_pressed", callable_mp(this, &TileMapEditor::_layers_selection_id_pressed)); - layers_selection_popup->set_close_on_parent_focus(false); + layers_selection_popup->set_flag(Window::FLAG_POPUP, false); layers_selection_button = memnew(Button); layers_selection_button->set_toggle_mode(true); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index ade591cde6..0c78a0f1c0 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -108,7 +108,7 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_bind_methods() { ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::set_id); ClassDB::bind_method(D_METHOD("get_id"), &TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id); - ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "id", PROPERTY_HINT_RANGE, "0," + itos(INT_MAX) + ",1"), "set_id", "get_id"); ADD_SIGNAL(MethodInfo("changed", PropertyInfo(Variant::STRING, "what"))); } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 446ad12104..a821faf6b3 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -4458,8 +4458,8 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("ColorOp", "Color", "Common", "VisualShaderNodeColorOp", TTR("Color operator."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Grayscale", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), { VisualShaderNodeColorFunc::FUNC_GRAYSCALE }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); - add_options.push_back(AddOption("HSV2RGB", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeVectorFunc::FUNC_HSV2RGB }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); - add_options.push_back(AddOption("RGB2HSV", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeVectorFunc::FUNC_RGB2HSV }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("HSV2RGB", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeVectorFunc::FUNC_HSV2RGB, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("RGB2HSV", "Color", "Functions", "VisualShaderNodeVectorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeVectorFunc::FUNC_RGB2HSV, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Sepia", "Color", "Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), { VisualShaderNodeColorFunc::FUNC_SEPIA }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Burn", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), { VisualShaderNodeColorOp::OP_BURN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 4a6c014942..bf43e11cdb 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -37,9 +37,73 @@ #include "editor/create_dialog.h" #include "editor/editor_file_dialog.h" #include "editor/editor_file_system.h" +#include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +static String _get_parent_class_of_script(String p_path) { + if (!ResourceLoader::exists(p_path, "Script")) { + return "Object"; // A script eventually inherits from Object. + } + + Ref<Script> script = ResourceLoader::load(p_path, "Script"); + ERR_FAIL_COND_V(script.is_null(), "Object"); + + String class_name; + Ref<Script> base = script->get_base_script(); + + // Inherits from a built-in class. + if (base.is_null()) { + script->get_language()->get_global_class_name(script->get_path(), &class_name); + return class_name; + } + + // Inherits from a script that has class_name. + class_name = script->get_language()->get_global_class_name(base->get_path()); + if (!class_name.is_empty()) { + return class_name; + } + + // Inherits from a plain script. + return _get_parent_class_of_script(base->get_path()); +} + +static Vector<String> _get_hierarchy(String p_class_name) { + Vector<String> hierarchy; + + String class_name = p_class_name; + while (true) { + // A registered class. + if (ClassDB::class_exists(class_name)) { + hierarchy.push_back(class_name); + + class_name = ClassDB::get_parent_class(class_name); + continue; + } + + // A class defined in script with class_name. + if (ScriptServer::is_global_class(class_name)) { + hierarchy.push_back(class_name); + + Ref<Script> script = EditorNode::get_editor_data().script_class_load_script(class_name); + ERR_BREAK(script.is_null()); + class_name = _get_parent_class_of_script(script->get_path()); + continue; + } + + break; + } + + if (hierarchy.is_empty()) { + if (p_class_name.is_valid_identifier()) { + hierarchy.push_back(p_class_name); + } + hierarchy.push_back("Object"); + } + + return hierarchy; +} + void ScriptCreateDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: @@ -353,18 +417,6 @@ void ScriptCreateDialog::_load_exist() { hide(); } -Vector<String> ScriptCreateDialog::get_hierarchy(String p_object) const { - Vector<String> hierarchy; - hierarchy.append(p_object); - - String parent_class = ClassDB::get_parent_class(p_object); - while (parent_class.is_valid_identifier()) { - hierarchy.append(parent_class); - parent_class = ClassDB::get_parent_class(parent_class); - } - return hierarchy; -} - void ScriptCreateDialog::_language_changed(int l) { language = ScriptServer::get_language(l); @@ -553,14 +605,14 @@ void ScriptCreateDialog::_update_template_menu() { } String inherits_base_type = parent_name->get_text(); - // If it inherits from a script, select Object instead. + // If it inherits from a script, get its parent class first. if (inherits_base_type[0] == '"') { - inherits_base_type = "Object"; + inherits_base_type = _get_parent_class_of_script(inherits_base_type.unquote()); } // Get all ancestor node for selected base node. // There templates will also fit the base node. - Vector<String> hierarchy = get_hierarchy(inherits_base_type); + Vector<String> hierarchy = _get_hierarchy(inherits_base_type); int last_used_template = -1; int preselected_template = -1; int previous_ancestor_level = -1; diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index aea9649abc..5c0f51812f 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -115,7 +115,6 @@ class ScriptCreateDialog : public ConfirmationDialog { virtual void ok_pressed() override; void _create_new(); void _load_exist(); - Vector<String> get_hierarchy(String p_object) const; void _msg_script_valid(bool valid, const String &p_msg = String()); void _msg_path_valid(bool valid, const String &p_msg = String()); void _update_template_menu(); |