diff options
Diffstat (limited to 'editor')
29 files changed, 410 insertions, 85 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 7183d34d4f..33f833afa4 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -5818,6 +5818,7 @@ AnimationTrackEditor::AnimationTrackEditor() { info_message->set_valign(Label::VALIGN_CENTER); info_message->set_align(Label::ALIGN_CENTER); info_message->set_autowrap(true); + info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); main_panel->add_child(info_message); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 5344658223..fb7cf494cd 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -151,6 +151,10 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p if (!ClassDB::is_parent_class(p_type, base_type)) return; } else { + if (!search_loaded_scripts.has(p_type)) { + search_loaded_scripts[p_type] = ed.script_class_load_script(p_type); + } + if (!ScriptServer::is_global_class(p_type) || !ed.script_class_is_parent(p_type, base_type)) return; @@ -352,7 +356,12 @@ void CreateDialog::_update_search() { } else { bool found = false; - String type2 = I->get(); + String type2 = type; + + if (!cpp_type && !search_loaded_scripts.has(type)) { + search_loaded_scripts[type] = ed.script_class_load_script(type); + } + while (type2 != "" && (cpp_type ? ClassDB::is_parent_class(type2, base_type) : ed.script_class_is_parent(type2, base_type)) && type2 != base_type) { if (search_box->get_text().is_subsequence_ofi(type2)) { @@ -361,10 +370,15 @@ void CreateDialog::_update_search() { } type2 = cpp_type ? ClassDB::get_parent_class(type2) : ed.script_class_get_base(type2); + + if (!cpp_type && !search_loaded_scripts.has(type2)) { + search_loaded_scripts[type2] = ed.script_class_load_script(type2); + } } - if (found) - add_type(I->get(), search_options_types, root, &to_select); + if (found) { + add_type(type, search_options_types, root, &to_select); + } } if (EditorNode::get_editor_data().get_custom_types().has(type) && ClassDB::is_parent_class(type, base_type)) { @@ -470,6 +484,7 @@ void CreateDialog::_notification(int p_what) { } break; case NOTIFICATION_POPUP_HIDE: { EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "create_new_node", get_rect()); + search_loaded_scripts.clear(); } break; } } diff --git a/editor/create_dialog.h b/editor/create_dialog.h index f3ed1d7af6..1150ac60da 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -51,6 +51,7 @@ class CreateDialog : public ConfirmationDialog { LineEdit *search_box; Tree *search_options; HashMap<String, TreeItem *> search_options_types; + HashMap<String, RES> search_loaded_scripts; bool is_replace_mode; String base_type; String preferred_search_result_type; diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 8a03292708..f75d9c98e0 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -58,6 +58,7 @@ void EditorAbout::_notification(int p_what) { void EditorAbout::_license_tree_selected() { TreeItem *selected = _tpl_tree->get_selected(); + _tpl_text->scroll_to_line(0); _tpl_text->set_text(selected->get_metadata(0)); } diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index b331a39535..acfdea28e2 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -1329,7 +1329,8 @@ EditorAudioBuses::EditorAudioBuses() { add_child(top_hb); file = memnew(Label); - file->set_text(String(TTR("Layout")) + ": " + "default_bus_layout.tres"); + String layout_path = ProjectSettings::get_singleton()->get("audio/default_bus_layout"); + file->set_text(String(TTR("Layout")) + ": " + layout_path.get_file()); file->set_clip_text(true); file->set_h_size_flags(SIZE_EXPAND_FILL); top_hb->add_child(file); diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 777eda2170..1cafd1d1f4 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -820,7 +820,7 @@ void EditorData::save_edited_scene_state(EditorSelection *p_selection, EditorHis ERR_FAIL_INDEX(current_edited_scene, edited_scene.size()); EditedScene &es = edited_scene.write[current_edited_scene]; - es.selection = p_selection->get_selected_node_list(); + es.selection = p_selection->get_full_selected_node_list(); es.history_current = p_history->current; es.history_stored = p_history->history; es.editor_states = get_editor_states(); @@ -870,7 +870,7 @@ bool EditorData::script_class_is_parent(const String &p_class, const String &p_i if (!ScriptServer::is_global_class(p_class)) return false; String base = script_class_get_base(p_class); - Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class), "Script"); + Ref<Script> script = script_class_load_script(p_class); Ref<Script> base_script = script->get_base_script(); while (p_inherits != base) { @@ -889,12 +889,7 @@ bool EditorData::script_class_is_parent(const String &p_class, const String &p_i StringName EditorData::script_class_get_base(const String &p_class) const { - if (!ScriptServer::is_global_class(p_class)) - return StringName(); - - String path = ScriptServer::get_global_class_path(p_class); - - Ref<Script> script = ResourceLoader::load(path, "Script"); + Ref<Script> script = script_class_load_script(p_class); if (script.is_null()) return StringName(); @@ -910,7 +905,7 @@ Object *EditorData::script_class_instance(const String &p_class) { if (ScriptServer::is_global_class(p_class)) { Object *obj = ClassDB::instance(ScriptServer::get_global_class_native_base(p_class)); if (obj) { - RES script = ResourceLoader::load(ScriptServer::get_global_class_path(p_class)); + Ref<Script> script = script_class_load_script(p_class); if (script.is_valid()) obj->set_script(script.get_ref_ptr()); return obj; @@ -919,6 +914,15 @@ Object *EditorData::script_class_instance(const String &p_class) { return NULL; } +Ref<Script> EditorData::script_class_load_script(const String &p_class) const { + + if (!ScriptServer::is_global_class(p_class)) + return Ref<Script>(); + + String path = ScriptServer::get_global_class_path(p_class); + return ResourceLoader::load(path, "Script"); +} + void EditorData::script_class_set_icon_path(const String &p_class, const String &p_icon_path) { _script_class_icon_paths[p_class] = p_icon_path; } @@ -1142,6 +1146,16 @@ List<Node *> &EditorSelection::get_selected_node_list() { return selected_node_list; } +List<Node *> EditorSelection::get_full_selected_node_list() { + + List<Node *> node_list; + for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) { + node_list.push_back(E->key()); + } + + return node_list; +} + void EditorSelection::clear() { while (!selection.empty()) { diff --git a/editor/editor_data.h b/editor/editor_data.h index df83135942..aa3e84d5a4 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -219,6 +219,8 @@ public: StringName script_class_get_base(const String &p_class) const; Object *script_class_instance(const String &p_class); + Ref<Script> script_class_load_script(const String &p_class) const; + StringName script_class_get_name(const String &p_path) const; void script_class_set_name(const String &p_path, const StringName &p_class); @@ -273,6 +275,7 @@ public: void clear(); List<Node *> &get_selected_node_list(); + List<Node *> get_full_selected_node_list(); Map<Node *, Object *> &get_selection() { return selection; } EditorSelection(); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d42345d9a2..0e373a5deb 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -71,6 +71,7 @@ #include "editor/import/resource_importer_texture.h" #include "editor/import/resource_importer_texture_atlas.h" #include "editor/import/resource_importer_wav.h" +#include "editor/multi_node_edit.h" #include "editor/plugins/animation_blend_space_1d_editor.h" #include "editor/plugins/animation_blend_space_2d_editor.h" #include "editor/plugins/animation_blend_tree_editor_plugin.h" @@ -1065,7 +1066,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { img->crop_from_point(x, y, vp_size, vp_size); } else { int ratio = vp_size / preview_size; - int size = preview_size * (ratio / 2); + int size = preview_size * MAX(1, ratio / 2); x = (img->get_width() - size) / 2; y = (img->get_height() - size) / 2; @@ -1742,15 +1743,37 @@ void EditorNode::_edit_current() { } else { + Node *selected_node = NULL; + if (current_obj->is_class("ScriptEditorDebuggerInspectedObject")) { editable_warning = TTR("This is a remote object, so changes to it won't be kept.\nPlease read the documentation relevant to debugging to better understand this workflow."); capitalize = false; disable_folding = true; + } else if (current_obj->is_class("MultiNodeEdit")) { + Node *scene = get_edited_scene(); + if (scene) { + MultiNodeEdit *multi_node_edit = Object::cast_to<MultiNodeEdit>(current_obj); + int node_count = multi_node_edit->get_node_count(); + if (node_count > 0) { + List<Node *> multi_nodes; + for (int node_index = 0; node_index < node_count; ++node_index) { + Node *node = scene->get_node(multi_node_edit->get_node(node_index)); + if (node) { + multi_nodes.push_back(node); + } + } + if (!multi_nodes.empty()) { + // Pick the top-most node + multi_nodes.sort_custom<Node::Comparator>(); + selected_node = multi_nodes.front()->get(); + } + } + } } get_inspector()->edit(current_obj); node_dock->set_node(NULL); - scene_tree_dock->set_selected(NULL); + scene_tree_dock->set_selected(selected_node); inspector_dock->update(NULL); } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index d3d91e6e0d..e14beabfa2 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1884,6 +1884,23 @@ void EditorPropertyColor::_bind_methods() { void EditorPropertyColor::update_property() { picker->set_pick_color(get_edited_object()->get(get_edited_property())); + const Color color = picker->get_pick_color(); + + // Add a tooltip to display each channel's values without having to click the ColorPickerButton + if (picker->is_editing_alpha()) { + picker->set_tooltip(vformat( + "R: %s\nG: %s\nB: %s\nA: %s", + rtos(color.r).pad_decimals(2), + rtos(color.g).pad_decimals(2), + rtos(color.b).pad_decimals(2), + rtos(color.a).pad_decimals(2))); + } else { + picker->set_tooltip(vformat( + "R: %s\nG: %s\nB: %s", + rtos(color.r).pad_decimals(2), + rtos(color.g).pad_decimals(2), + rtos(color.b).pad_decimals(2))); + } } void EditorPropertyColor::setup(bool p_show_alpha) { diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index d80176f00d..fbc4a5ee5c 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -112,7 +112,7 @@ void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) { if (mm->get_control()) { set_value(Math::round(pre_grab_value + get_step() * grabbing_spinner_dist_cache * 10)); } else { - set_value(pre_grab_value + get_step() * grabbing_spinner_dist_cache * 10); + set_value(pre_grab_value + get_step() * grabbing_spinner_dist_cache); } } } else if (updown_offset != -1) { diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index fa171ddb0c..5409ef65ea 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -71,11 +71,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory subdirectory_item->select(0); } - if ((path.begins_with(lpath) && path != lpath)) { - subdirectory_item->set_collapsed(false); - } else { - subdirectory_item->set_collapsed(uncollapsed_paths.find(lpath) < 0); - } + subdirectory_item->set_collapsed(uncollapsed_paths.find(lpath) < 0); if (searched_string.length() > 0 && dname.to_lower().find(searched_string) >= 0) { parent_should_expand = true; } diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 4cefb53617..74d81bf561 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -529,6 +529,7 @@ GroupDialog::GroupDialog() { group_empty->set_valign(Label::VALIGN_CENTER); group_empty->set_align(Label::ALIGN_CENTER); group_empty->set_autowrap(true); + group_empty->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); nodes_to_remove->add_child(group_empty); group_empty->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index 85e47594a8..0792d5c95f 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -34,12 +34,10 @@ #include "editor_node.h" bool MultiNodeEdit::_set(const StringName &p_name, const Variant &p_value) { - return _set_impl(p_name, p_value, ""); } bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, const String &p_field) { - Node *es = EditorNode::get_singleton()->get_edited_scene(); if (!es) return false; @@ -88,7 +86,6 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, } bool MultiNodeEdit::_get(const StringName &p_name, Variant &r_ret) const { - Node *es = EditorNode::get_singleton()->get_edited_scene(); if (!es) return false; @@ -117,7 +114,6 @@ bool MultiNodeEdit::_get(const StringName &p_name, Variant &r_ret) const { } void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const { - HashMap<String, PLData> usage; Node *es = EditorNode::get_singleton()->get_edited_scene(); @@ -171,17 +167,23 @@ void MultiNodeEdit::_get_property_list(List<PropertyInfo> *p_list) const { } void MultiNodeEdit::clear_nodes() { - nodes.clear(); } void MultiNodeEdit::add_node(const NodePath &p_node) { - nodes.push_back(p_node); } -void MultiNodeEdit::set_property_field(const StringName &p_property, const Variant &p_value, const String &p_field) { +int MultiNodeEdit::get_node_count() const { + return nodes.size(); +} +NodePath MultiNodeEdit::get_node(int p_index) const { + ERR_FAIL_INDEX_V(p_index, nodes.size(), NodePath()); + return nodes[p_index]; +} + +void MultiNodeEdit::set_property_field(const StringName &p_property, const Variant &p_value, const String &p_field) { _set_impl(p_property, p_value, p_field); } diff --git a/editor/multi_node_edit.h b/editor/multi_node_edit.h index b9192b206a..33df4a2ca5 100644 --- a/editor/multi_node_edit.h +++ b/editor/multi_node_edit.h @@ -54,6 +54,9 @@ public: void clear_nodes(); void add_node(const NodePath &p_node); + int get_node_count() const; + NodePath get_node(int p_index) const; + void set_property_field(const StringName &p_property, const Variant &p_value, const String &p_field); MultiNodeEdit(); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index e5042513c8..1b263fa4f6 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -1227,8 +1227,8 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event, bo } if (panning) { - if (!b->is_pressed()) { - // Stop panning the viewport (for any mouse button press) + if (!b->is_pressed() && (pan_on_scroll || (b->get_button_index() != BUTTON_WHEEL_DOWN && b->get_button_index() != BUTTON_WHEEL_UP))) { + // Stop panning the viewport (for any mouse button press except zooming) panning = false; } } @@ -1315,6 +1315,7 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { // Start dragging if we still have nodes if (drag_selection.size() > 0) { + _save_canvas_item_state(drag_selection); drag_from = transform.affine_inverse().xform((b.is_valid()) ? b->get_position() : viewport->get_local_mouse_position()); Vector2 new_pos; if (drag_selection.size() == 1) { @@ -1328,7 +1329,6 @@ bool CanvasItemEditor::_gui_input_pivot(const Ref<InputEvent> &p_event) { } drag_type = DRAG_PIVOT; - _save_canvas_item_state(drag_selection); } return true; } @@ -3811,6 +3811,7 @@ void CanvasItemEditor::_notification(int p_what) { grid_snap_button->set_icon(get_icon("SnapGrid", "EditorIcons")); snap_config_menu->set_icon(get_icon("GuiTabMenu", "EditorIcons")); skeleton_menu->set_icon(get_icon("Bone", "EditorIcons")); + override_camera_button->set_icon(get_icon("Camera2D", "EditorIcons")); pan_button->set_icon(get_icon("ToolPan", "EditorIcons")); ruler_button->set_icon(get_icon("Ruler", "EditorIcons")); pivot_button->set_icon(get_icon("EditPivot", "EditorIcons")); @@ -3880,6 +3881,15 @@ void CanvasItemEditor::_notification(int p_what) { anchor_mode_button->set_icon(get_icon("Anchor", "EditorIcons")); } + + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (!is_visible() && override_camera_button->is_pressed()) { + ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger(); + + debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE); + override_camera_button->set_pressed(false); + } + } } void CanvasItemEditor::_selection_changed() { @@ -4221,6 +4231,15 @@ void CanvasItemEditor::_button_toggle_grid_snap(bool p_status) { grid_snap_active = p_status; viewport->update(); } +void CanvasItemEditor::_button_override_camera(bool p_pressed) { + ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger(); + + if (p_pressed) { + debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_2D); + } else { + debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE); + } +} void CanvasItemEditor::_button_tool_select(int p_index) { @@ -4318,6 +4337,17 @@ void CanvasItemEditor::_button_toggle_anchor_mode(bool p_status) { viewport->update(); } +void CanvasItemEditor::_update_override_camera_button(bool p_game_running) { + if (p_game_running) { + override_camera_button->set_disabled(false); + override_camera_button->set_tooltip(TTR("Game camera override\nOverrides game camera with editor viewport camera.")); + } else { + override_camera_button->set_disabled(true); + override_camera_button->set_pressed(false); + override_camera_button->set_tooltip(TTR("Game camera override\nNo game instance running.")); + } +} + void CanvasItemEditor::_popup_callback(int p_op) { last_option = MenuOption(p_op); @@ -4915,6 +4945,8 @@ void CanvasItemEditor::_bind_methods() { ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus); ClassDB::bind_method("_button_toggle_smart_snap", &CanvasItemEditor::_button_toggle_smart_snap); ClassDB::bind_method("_button_toggle_grid_snap", &CanvasItemEditor::_button_toggle_grid_snap); + ClassDB::bind_method(D_METHOD("_button_override_camera", "pressed"), &CanvasItemEditor::_button_override_camera); + ClassDB::bind_method(D_METHOD("_update_override_camera_button", "game_running"), &CanvasItemEditor::_update_override_camera_button); ClassDB::bind_method("_button_toggle_anchor_mode", &CanvasItemEditor::_button_toggle_anchor_mode); ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll); ClassDB::bind_method("_update_scrollbars", &CanvasItemEditor::_update_scrollbars); @@ -5247,6 +5279,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { editor_selection->connect("selection_changed", this, "update"); editor_selection->connect("selection_changed", this, "_selection_changed"); + editor->call_deferred("connect", "play_pressed", this, "_update_override_camera_button", make_binds(true)); + editor->call_deferred("connect", "stop_pressed", this, "_update_override_camera_button", make_binds(false)); + hb = memnew(HBoxContainer); add_child(hb); hb->set_anchors_and_margins_preset(Control::PRESET_WIDE); @@ -5492,6 +5527,15 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { hb->add_child(memnew(VSeparator)); + override_camera_button = memnew(ToolButton); + hb->add_child(override_camera_button); + override_camera_button->connect("toggled", this, "_button_override_camera"); + override_camera_button->set_toggle_mode(true); + override_camera_button->set_disabled(true); + _update_override_camera_button(false); + + hb->add_child(memnew(VSeparator)); + view_menu = memnew(MenuButton); view_menu->set_text(TTR("View")); hb->add_child(view_menu); @@ -5575,7 +5619,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { key_auto_insert_button->set_toggle_mode(true); key_auto_insert_button->set_focus_mode(FOCUS_NONE); //key_auto_insert_button->connect("pressed", this, "_popup_callback", varray(ANIM_INSERT_KEY)); - key_auto_insert_button->set_tooltip(TTR("Auto insert keys when objects are translated, rotated on scaled (based on mask).\nKeys are only added to existing tracks, no new tracks will be created.\nKeys must be inserted manually for the first time.")); + key_auto_insert_button->set_tooltip(TTR("Auto insert keys when objects are translated, rotated or scaled (based on mask).\nKeys are only added to existing tracks, no new tracks will be created.\nKeys must be inserted manually for the first time.")); key_auto_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_auto_insert_key", TTR("Auto Insert Key"))); animation_hb->add_child(key_auto_insert_button); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 058f9a77d3..3fdf00d611 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -364,6 +364,7 @@ private: ToolButton *ungroup_button; MenuButton *skeleton_menu; + ToolButton *override_camera_button; MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; @@ -537,8 +538,11 @@ private: void _button_zoom_plus(); void _button_toggle_smart_snap(bool p_status); void _button_toggle_grid_snap(bool p_status); + void _button_override_camera(bool p_pressed); void _button_tool_select(int p_index); + void _update_override_camera_button(bool p_game_running); + HSplitContainer *palette_split; VSplitContainer *bottom_split; diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp index 635b934333..22df8fd8f4 100644 --- a/editor/plugins/mesh_instance_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_editor_plugin.cpp @@ -180,6 +180,7 @@ void MeshInstanceEditor::_menu_option(int p_option) { CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shapes[i]); + cshape->set_transform(node->get_transform()); Node *owner = node->get_owner(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 603a2365c1..f63445dab8 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -571,6 +571,7 @@ void ScriptTextEditor::_validate_script() { String error_text = "error(" + itos(line) + "," + itos(col) + "): " + errortxt; code_editor->set_error(error_text); code_editor->set_error_pos(line - 1, col - 1); + script_is_valid = false; } else { code_editor->set_error(""); line = -1; @@ -585,6 +586,7 @@ void ScriptTextEditor::_validate_script() { functions.push_back(E->get()); } + script_is_valid = true; } _update_connected_methods(); @@ -967,7 +969,7 @@ void ScriptTextEditor::_update_connected_methods() { text_edit->clear_info_icons(); missing_connections.clear(); - if (!script->is_valid()) { + if (!script_is_valid) { return; } @@ -1000,10 +1002,18 @@ void ScriptTextEditor::_update_connected_methods() { if (!ClassDB::has_method(script->get_instance_base_type(), connection.method)) { int line = -1; - if (script->has_method(connection.method)) { - line = script->get_member_line(connection.method); - text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method); - methods_found.insert(connection.method); + + for (int j = 0; j < functions.size(); j++) { + String name = functions[j].get_slice(":", 0); + if (name == connection.method) { + line = functions[j].get_slice(":", 1).to_int(); + text_edit->set_line_info_icon(line - 1, get_parent_control()->get_icon("Slot", "EditorIcons"), connection.method); + methods_found.insert(connection.method); + break; + } + } + + if (line >= 0) { continue; } @@ -1728,6 +1738,7 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color, bool p ScriptTextEditor::ScriptTextEditor() { theme_loaded = false; + script_is_valid = false; VSplitContainer *editor_box = memnew(VSplitContainer); add_child(editor_box); diff --git a/editor/plugins/script_text_editor.h b/editor/plugins/script_text_editor.h index eba75befd4..2ba0be8feb 100644 --- a/editor/plugins/script_text_editor.h +++ b/editor/plugins/script_text_editor.h @@ -59,6 +59,7 @@ class ScriptTextEditor : public ScriptEditorBase { RichTextLabel *warnings_panel; Ref<Script> script; + bool script_is_valid; Vector<String> functions; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index eb39496106..c989613f02 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -901,6 +901,8 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { + emit_signal("clicked", this); + float zoom_factor = 1 + (ZOOM_MULTIPLIER - 1) * b->get_factor(); switch (b->get_button_index()) { @@ -2763,6 +2765,7 @@ void SpatialEditorViewport::_preview_exited_scene() { preview_camera->disconnect("toggled", this, "_toggle_camera_preview"); preview_camera->set_pressed(false); _toggle_camera_preview(false); + preview_camera->connect("toggled", this, "_toggle_camera_preview"); view_menu->show(); } @@ -3101,6 +3104,7 @@ void SpatialEditorViewport::_bind_methods() { ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpatialEditorViewport::drop_data_fw); ADD_SIGNAL(MethodInfo("toggle_maximize_view", PropertyInfo(Variant::OBJECT, "viewport"))); + ADD_SIGNAL(MethodInfo("clicked", PropertyInfo(Variant::OBJECT, "viewport"))); } void SpatialEditorViewport::reset() { @@ -3599,6 +3603,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed vbox->add_child(preview_camera); preview_camera->set_h_size_flags(0); preview_camera->hide(); + preview_camera->connect("toggled", this, "_toggle_camera_preview"); previewing = NULL; gizmo_scale = 1.0; @@ -4373,6 +4378,19 @@ void SpatialEditor::_menu_item_toggled(bool pressed, int p_option) { tool_option_button[TOOL_OPT_USE_SNAP]->set_pressed(pressed); snap_enabled = pressed; } break; + + case MENU_TOOL_OVERRIDE_CAMERA: { + ScriptEditorDebugger *const debugger = ScriptEditor::get_singleton()->get_debugger(); + + if (pressed) { + using Override = ScriptEditorDebugger::CameraOverride; + + debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id)); + } else { + debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE); + } + + } break; } } @@ -4400,6 +4418,35 @@ void SpatialEditor::_menu_gizmo_toggled(int p_option) { update_all_gizmos(); } +void SpatialEditor::_update_camera_override_button(bool p_game_running) { + Button *const button = tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]; + + if (p_game_running) { + button->set_disabled(false); + button->set_tooltip(TTR("Game camera override\nNo game instance running.")); + } else { + button->set_disabled(true); + button->set_pressed(false); + button->set_tooltip(TTR("Game camera override\nOverrides game camera with editor viewport camera.")); + } +} + +void SpatialEditor::_update_camera_override_viewport(Object *p_viewport) { + SpatialEditorViewport *current_viewport = Object::cast_to<SpatialEditorViewport>(p_viewport); + + if (!current_viewport) + return; + + ScriptEditorDebugger *const debugger = ScriptEditor::get_singleton()->get_debugger(); + + camera_override_viewport_id = current_viewport->index; + if (debugger->get_camera_override() >= ScriptEditorDebugger::OVERRIDE_3D_1) { + using Override = ScriptEditorDebugger::CameraOverride; + + debugger->set_camera_override((Override)(Override::OVERRIDE_3D_1 + camera_override_viewport_id)); + } +} + void SpatialEditor::_menu_item_pressed(int p_option) { switch (p_option) { @@ -5294,6 +5341,7 @@ void SpatialEditor::_notification(int p_what) { tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_icon("Object", "EditorIcons")); tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_icon("Snap", "EditorIcons")); + tool_option_button[SpatialEditor::TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_icon("Camera", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_icon("Panels1", "EditorIcons")); view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_icon("Panels2", "EditorIcons")); @@ -5309,6 +5357,9 @@ void SpatialEditor::_notification(int p_what) { get_tree()->connect("node_removed", this, "_node_removed"); EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor()->connect("node_changed", this, "_refresh_menu_icons"); editor_selection->connect("selection_changed", this, "_refresh_menu_icons"); + + editor->connect("stop_pressed", this, "_update_camera_override_button", make_binds(false)); + editor->connect("play_pressed", this, "_update_camera_override_button", make_binds(true)); } else if (p_what == NOTIFICATION_ENTER_TREE) { _register_all_gizmos(); @@ -5343,6 +5394,13 @@ void SpatialEditor::_notification(int p_what) { // Update grid color by rebuilding grid. _finish_grid(); _init_grid(); + } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (!is_visible() && tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->is_pressed()) { + ScriptEditorDebugger *debugger = ScriptEditor::get_singleton()->get_debugger(); + + debugger->set_camera_override(ScriptEditorDebugger::OVERRIDE_NONE); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_pressed(false); + } } } @@ -5487,6 +5545,8 @@ void SpatialEditor::_bind_methods() { ClassDB::bind_method("_request_gizmo", &SpatialEditor::_request_gizmo); ClassDB::bind_method("_toggle_maximize_view", &SpatialEditor::_toggle_maximize_view); ClassDB::bind_method("_refresh_menu_icons", &SpatialEditor::_refresh_menu_icons); + ClassDB::bind_method("_update_camera_override_button", &SpatialEditor::_update_camera_override_button); + ClassDB::bind_method("_update_camera_override_viewport", &SpatialEditor::_update_camera_override_viewport); ADD_SIGNAL(MethodInfo("transform_key_request")); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); @@ -5540,6 +5600,8 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { snap_key_enabled = false; tool_mode = TOOL_MODE_SELECT; + camera_override_viewport_id = 0; + hbc_menu = memnew(HBoxContainer); vbc->add_child(hbc_menu); @@ -5637,6 +5699,17 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { hbc_menu->add_child(memnew(VSeparator)); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA] = memnew(ToolButton); + hbc_menu->add_child(tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_toggle_mode(true); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_flat(true); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_disabled(true); + button_binds.write[0] = MENU_TOOL_OVERRIDE_CAMERA; + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->connect("toggled", this, "_menu_item_toggled", button_binds); + _update_camera_override_button(false); + + hbc_menu->add_child(memnew(VSeparator)); + // Drag and drop support; preview_node = memnew(Spatial); preview_bounds = AABB(); @@ -5725,6 +5798,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { viewports[i] = memnew(SpatialEditorViewport(this, editor, i)); viewports[i]->connect("toggle_maximize_view", this, "_toggle_maximize_view"); + viewports[i]->connect("clicked", this, "_update_camera_override_viewport"); viewports[i]->assign_pending_data_pointers(preview_node, &preview_bounds, accept); viewport_base->add_child(viewports[i]); } diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index fe91c33642..65e3c32ca8 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -494,6 +494,7 @@ public: TOOL_OPT_LOCAL_COORDS, TOOL_OPT_USE_SNAP, + TOOL_OPT_OVERRIDE_CAMERA, TOOL_OPT_MAX }; @@ -559,6 +560,7 @@ private: MENU_TOOL_LIST_SELECT, MENU_TOOL_LOCAL_COORDS, MENU_TOOL_USE_SNAP, + MENU_TOOL_OVERRIDE_CAMERA, MENU_TRANSFORM_CONFIGURE_SNAP, MENU_TRANSFORM_DIALOG, MENU_VIEW_USE_1_VIEWPORT, @@ -585,9 +587,6 @@ private: PopupMenu *gizmos_menu; MenuButton *view_menu; - ToolButton *lock_button; - ToolButton *unlock_button; - AcceptDialog *accept; ConfirmationDialog *snap_dialog; @@ -615,13 +614,16 @@ private: void _menu_item_pressed(int p_option); void _menu_item_toggled(bool pressed, int p_option); 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; void _generate_selection_box(); UndoRedo *undo_redo; - void _instance_scene(); + int camera_override_viewport_id; + void _init_indicators(); void _update_gizmos_menu(); void _update_gizmos_menu_theme(); @@ -716,7 +718,7 @@ public: void set_can_preview(Camera *p_preview); SpatialEditorViewport *get_editor_viewport(int p_idx) { - ERR_FAIL_INDEX_V(p_idx, 4, NULL); + ERR_FAIL_INDEX_V(p_idx, static_cast<int>(VIEWPORTS_COUNT), NULL); return viewports[p_idx]; } diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 2d66087699..10567557d6 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -1996,6 +1996,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { info_message->set_valign(Label::VALIGN_CENTER); info_message->set_align(Label::ALIGN_CENTER); info_message->set_autowrap(true); + info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); palette->add_child(info_message); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index d81c6d3f96..cc4c21cc04 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -584,6 +584,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { empty_message->set_valign(Label::VALIGN_CENTER); empty_message->set_align(Label::ALIGN_CENTER); empty_message->set_autowrap(true); + empty_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); empty_message->set_v_size_flags(SIZE_EXPAND_FILL); main_vb->add_child(empty_message); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index e96f2e55c2..1a74779fb5 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -2462,7 +2462,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Darken", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), VisualShaderNodeColorOp::OP_DARKEN, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Difference", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Difference operator."), VisualShaderNodeColorOp::OP_DIFFERENCE, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Dodge", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Dodge operator."), VisualShaderNodeColorOp::OP_DODGE, VisualShaderNode::PORT_TYPE_VECTOR)); - add_options.push_back(AddOption("HardLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("HardLight operator"), VisualShaderNodeColorOp::OP_HARD_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR)); + add_options.push_back(AddOption("HardLight", "Color", "Operators", "VisualShaderNodeColorOp", TTR("HardLight operator."), VisualShaderNodeColorOp::OP_HARD_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Lighten", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Lighten operator."), VisualShaderNodeColorOp::OP_LIGHTEN, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Overlay", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Overlay operator."), VisualShaderNodeColorOp::OP_OVERLAY, VisualShaderNode::PORT_TYPE_VECTOR)); add_options.push_back(AddOption("Screen", "Color", "Operators", "VisualShaderNodeColorOp", TTR("Screen operator."), VisualShaderNodeColorOp::OP_SCREEN, VisualShaderNode::PORT_TYPE_VECTOR)); @@ -2531,9 +2531,11 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Alpha", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "alpha"), "alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Binormal", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal"), "binormal", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Color", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color"), "color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("DepthTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "depth_texture"), "depth_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("FrontFacing", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "front_facing"), "front_facing", VisualShaderNode::PORT_TYPE_BOOLEAN, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Side", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "side"), "side", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Tangent", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "tangent"), "tangent", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_SPATIAL)); @@ -2567,9 +2569,12 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("FragCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("LightPass", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("NormalTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "normal_texture"), "normal_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("PointCoord", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenPixelSize", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_pixel_size"), "screen_pixel_size", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("ScreenTexture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_shader_mode, "screen_texture"), "screen_texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenUV", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Texture", "Input", "Fragment", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_FRAGMENT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("FragCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "fragcoord"), "fragcoord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("LightAlpha", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "light_alpha"), "light_alpha", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); @@ -2581,6 +2586,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("PointCoord", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "point_coord"), "point_coord", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ScreenUV", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "screen_uv"), "screen_uv", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("ShadowColor", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_light_shader_mode, "shadow_color"), "shadow_color", VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); + add_options.push_back(AddOption("Texture", "Input", "Light", "VisualShaderNodeInput", vformat(input_param_for_fragment_and_light_shader_modes, "texture"), "texture", VisualShaderNode::PORT_TYPE_SAMPLER, VisualShader::TYPE_LIGHT, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("Extra", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "extra"), "extra", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); add_options.push_back(AddOption("LightPass", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "light_pass"), "light_pass", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_CANVAS_ITEM)); @@ -2774,7 +2780,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Expression", "Special", "", "VisualShaderNodeExpression", TTR("Custom Godot Shader Language expression, with custom amount of input and output ports. This is a direct injection of code into the vertex/fragment/light function, do not use it to write the function declarations inside."))); add_options.push_back(AddOption("Fresnel", "Special", "", "VisualShaderNodeFresnel", TTR("Returns falloff based on the dot product of surface normal and view direction of camera (pass associated inputs to it)."), -1, VisualShaderNode::PORT_TYPE_SCALAR)); - add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants."))); + add_options.push_back(AddOption("GlobalExpression", "Special", "", "VisualShaderNodeGlobalExpression", TTR("Custom Godot Shader Language expression, which is placed on top of the resulted shader. You can place various function definitions inside and call it later in the Expressions. You can also declare varyings, uniforms and constants."))); add_options.push_back(AddOption("ScalarDerivativeFunc", "Special", "Common", "VisualShaderNodeScalarDerivativeFunc", TTR("(Fragment/Light mode only) Scalar derivative function."), -1, VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); add_options.push_back(AddOption("VectorDerivativeFunc", "Special", "Common", "VisualShaderNodeVectorDerivativeFunc", TTR("(Fragment/Light mode only) Vector derivative function."), -1, VisualShaderNode::PORT_TYPE_VECTOR, VisualShader::TYPE_FRAGMENT | VisualShader::TYPE_LIGHT, -1, -1, true)); @@ -2878,11 +2884,12 @@ public: void setup(const Ref<VisualShaderNodeInput> &p_input) { input = p_input; - Ref<Texture> type_icon[4] = { + Ref<Texture> type_icon[5] = { EditorNode::get_singleton()->get_gui_base()->get_icon("float", "EditorIcons"), EditorNode::get_singleton()->get_gui_base()->get_icon("Vector3", "EditorIcons"), EditorNode::get_singleton()->get_gui_base()->get_icon("bool", "EditorIcons"), EditorNode::get_singleton()->get_gui_base()->get_icon("Transform", "EditorIcons"), + EditorNode::get_singleton()->get_gui_base()->get_icon("ImageTexture", "EditorIcons"), }; add_item("[None]"); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index f56f7ef7ca..9ac775e456 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -442,15 +442,7 @@ void ProjectSettingsEditor::_wait_for_key(const Ref<InputEvent> &p_event) { if (k.is_valid() && k->is_pressed() && k->get_scancode() != 0) { last_wait_for_key = p_event; - String str = keycode_get_string(k->get_scancode()).capitalize(); - if (k->get_metakey()) - str = vformat("%s+", find_keycode_name(KEY_META)) + str; - if (k->get_shift()) - str = TTR("Shift+") + str; - if (k->get_alt()) - str = TTR("Alt+") + str; - if (k->get_control()) - str = TTR("Control+") + str; + const String str = keycode_get_string(k->get_scancode_with_modifiers()); press_a_key_label->set_text(str); press_a_key->accept_event(); @@ -740,15 +732,7 @@ void ProjectSettingsEditor::_update_actions() { Ref<InputEventKey> k = event; if (k.is_valid()) { - String str = keycode_get_string(k->get_scancode()).capitalize(); - if (k->get_metakey()) - str = vformat("%s+", find_keycode_name(KEY_META)) + str; - if (k->get_shift()) - str = TTR("Shift+") + str; - if (k->get_alt()) - str = TTR("Alt+") + str; - if (k->get_control()) - str = TTR("Control+") + str; + const String str = keycode_get_string(k->get_scancode_with_modifiers()); action2->set_text(0, str); action2->set_icon(0, get_icon("Keyboard", "EditorIcons")); @@ -1546,28 +1530,33 @@ void ProjectSettingsEditor::_update_translations() { Array l_filter = l_filter_all[1]; int s = names.size(); - if (!translation_locales_list_created) { + bool is_short_list_when_show_all_selected = filter_mode == SHOW_ALL_LOCALES && translation_filter_treeitems.size() < s; + bool is_full_list_when_show_only_selected = filter_mode == SHOW_ONLY_SELECTED_LOCALES && translation_filter_treeitems.size() == s; + bool should_recreate_locales_list = is_short_list_when_show_all_selected || is_full_list_when_show_only_selected; + + if (!translation_locales_list_created || should_recreate_locales_list) { translation_locales_list_created = true; translation_filter->clear(); root = translation_filter->create_item(NULL); translation_filter->set_hide_root(true); - translation_filter_treeitems.resize(s); - + translation_filter_treeitems.clear(); for (int i = 0; i < s; i++) { String n = names[i]; String l = langs[i]; + bool is_checked = l_filter.has(l); + if (filter_mode == SHOW_ONLY_SELECTED_LOCALES && !is_checked) continue; + TreeItem *t = translation_filter->create_item(root); t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); t->set_text(0, n); t->set_editable(0, true); t->set_tooltip(0, l); - t->set_checked(0, l_filter.has(l)); - translation_filter_treeitems.write[i] = t; + t->set_checked(0, is_checked); + translation_filter_treeitems.push_back(t); } } else { - for (int i = 0; i < s; i++) { - + for (int i = 0; i < translation_filter_treeitems.size(); i++) { TreeItem *t = translation_filter_treeitems[i]; t->set_checked(0, l_filter.has(t->get_tooltip(0))); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index beead9e7f1..71e93750f0 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2403,6 +2403,7 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } List<Node *> selection = editor_selection->get_selected_node_list(); + List<Node *> full_selection = editor_selection->get_full_selected_node_list(); // Above method only returns nodes with common parent. if (selection.size() == 0) return; @@ -2437,21 +2438,40 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { } if (profile_allow_script_editing) { + bool add_separator = false; - if (selection.size() == 1) { + if (full_selection.size() == 1) { + add_separator = true; menu->add_icon_shortcut(get_icon("ScriptCreate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/attach_script"), TOOL_ATTACH_SCRIPT); if (existing_script.is_valid()) { menu->add_icon_shortcut(get_icon("ScriptExtend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/extend_script"), TOOL_EXTEND_SCRIPT); } } - if (selection.size() > 1 || (existing_script.is_valid() && exisiting_script_removable)) { + if (existing_script.is_valid() && exisiting_script_removable) { + add_separator = true; menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); + } else if (full_selection.size() > 1) { + bool script_exists = false; + for (List<Node *>::Element *E = full_selection.front(); E; E = E->next()) { + if (!E->get()->get_script().is_null()) { + script_exists = true; + break; + } + } + + if (script_exists) { + add_separator = true; + menu->add_icon_shortcut(get_icon("ScriptRemove", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/clear_script"), TOOL_CLEAR_SCRIPT); + } + } + + if (add_separator) { + menu->add_separator(); } - menu->add_separator(); } if (profile_allow_editing) { - if (selection.size() == 1) { + if (full_selection.size() == 1) { menu->add_icon_shortcut(get_icon("Rename", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/rename"), TOOL_RENAME); } menu->add_icon_shortcut(get_icon("Reload", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/change_node_type"), TOOL_REPLACE); @@ -2463,7 +2483,9 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->add_icon_shortcut(get_icon("Duplicate", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/duplicate"), TOOL_DUPLICATE); menu->add_icon_shortcut(get_icon("Reparent", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent"), TOOL_REPARENT); menu->add_icon_shortcut(get_icon("ReparentToNewNode", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/reparent_to_new_node"), TOOL_REPARENT_TO_NEW_NODE); - menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT); + if (selection.size() == 1) { + menu->add_icon_shortcut(get_icon("NewRoot", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/make_root"), TOOL_MAKE_ROOT); + } } } if (selection.size() == 1) { @@ -2472,9 +2494,11 @@ void SceneTreeDock::_tree_rmb(const Vector2 &p_menu_pos) { menu->add_separator(); menu->add_icon_shortcut(get_icon("Blend", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/merge_from_scene"), TOOL_MERGE_FROM_SCENE); menu->add_icon_shortcut(get_icon("CreateNewSceneFrom", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/save_branch_as_scene"), TOOL_NEW_SCENE_FROM); + } + if (full_selection.size() == 1) { menu->add_separator(); + menu->add_icon_shortcut(get_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH); } - menu->add_icon_shortcut(get_icon("CopyNodePath", "EditorIcons"), ED_GET_SHORTCUT("scene_tree/copy_node_path"), TOOL_COPY_NODE_PATH); bool is_external = (selection[0]->get_filename() != ""); if (is_external) { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index c1899b2bde..afbd8832f2 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -33,6 +33,8 @@ #include "core/io/marshalls.h" #include "core/project_settings.h" #include "core/ustring.h" +#include "editor/plugins/canvas_item_editor_plugin.h" +#include "editor/plugins/spatial_editor_plugin.h" #include "editor_network_profiler.h" #include "editor_node.h" #include "editor_profiler.h" @@ -1232,6 +1234,42 @@ void ScriptEditorDebugger::_notification(int p_what) { } } } + + if (camera_override == OVERRIDE_2D) { + CanvasItemEditor *editor = CanvasItemEditor::get_singleton(); + + Dictionary state = editor->get_state(); + float zoom = state["zoom"]; + Point2 offset = state["ofs"]; + Transform2D transform; + + transform.scale_basis(Size2(zoom, zoom)); + transform.elements[2] = -offset * zoom; + + Array msg; + msg.push_back("override_camera_2D:transform"); + msg.push_back(transform); + ppeer->put_var(msg); + + } else if (camera_override >= OVERRIDE_3D_1) { + int viewport_idx = camera_override - OVERRIDE_3D_1; + SpatialEditorViewport *viewport = SpatialEditor::get_singleton()->get_editor_viewport(viewport_idx); + Camera *const cam = viewport->get_camera(); + + Array msg; + msg.push_back("override_camera_3D:transform"); + msg.push_back(cam->get_camera_transform()); + if (cam->get_projection() == Camera::PROJECTION_ORTHOGONAL) { + msg.push_back(false); + msg.push_back(cam->get_size()); + } else { + msg.push_back(true); + msg.push_back(cam->get_fov()); + } + msg.push_back(cam->get_znear()); + msg.push_back(cam->get_zfar()); + ppeer->put_var(msg); + } } if (error_count != last_error_count || warning_count != last_warning_count) { @@ -1446,6 +1484,7 @@ void ScriptEditorDebugger::start() { set_process(true); breaked = false; + camera_override = OVERRIDE_NONE; } void ScriptEditorDebugger::pause() { @@ -1890,6 +1929,45 @@ void ScriptEditorDebugger::live_debug_reparent_node(const NodePath &p_at, const } } +ScriptEditorDebugger::CameraOverride ScriptEditorDebugger::get_camera_override() const { + return camera_override; +} + +void ScriptEditorDebugger::set_camera_override(CameraOverride p_override) { + + if (p_override == OVERRIDE_2D && camera_override != OVERRIDE_2D) { + if (connection.is_valid()) { + Array msg; + msg.push_back("override_camera_2D:set"); + msg.push_back(true); + ppeer->put_var(msg); + } + } else if (p_override != OVERRIDE_2D && camera_override == OVERRIDE_2D) { + if (connection.is_valid()) { + Array msg; + msg.push_back("override_camera_2D:set"); + msg.push_back(false); + ppeer->put_var(msg); + } + } else if (p_override >= OVERRIDE_3D_1 && camera_override < OVERRIDE_3D_1) { + if (connection.is_valid()) { + Array msg; + msg.push_back("override_camera_3D:set"); + msg.push_back(true); + ppeer->put_var(msg); + } + } else if (p_override < OVERRIDE_3D_1 && camera_override >= OVERRIDE_3D_1) { + if (connection.is_valid()) { + Array msg; + msg.push_back("override_camera_3D:set"); + msg.push_back(false); + ppeer->put_var(msg); + } + } + + camera_override = p_override; +} + void ScriptEditorDebugger::set_breakpoint(const String &p_path, int p_line, bool p_enabled) { if (connection.is_valid()) { @@ -2424,6 +2502,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { info_message->set_valign(Label::VALIGN_CENTER); info_message->set_align(Label::ALIGN_CENTER); info_message->set_autowrap(true); + info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); info_message->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); perf_draw->add_child(info_message); } diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index cc284476c0..14b024d066 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -35,6 +35,7 @@ #include "core/io/tcp_server.h" #include "editor/editor_inspector.h" #include "editor/property_editor.h" +#include "scene/3d/camera.h" #include "scene/gui/box_container.h" #include "scene/gui/button.h" @@ -58,6 +59,17 @@ class ScriptEditorDebugger : public Control { GDCLASS(ScriptEditorDebugger, Control); +public: + enum CameraOverride { + OVERRIDE_NONE, + OVERRIDE_2D, + OVERRIDE_3D_1, // 3D Viewport 1 + OVERRIDE_3D_2, // 3D Viewport 2 + OVERRIDE_3D_3, // 3D Viewport 3 + OVERRIDE_3D_4 // 3D Viewport 4 + }; + +private: enum MessageType { MESSAGE_ERROR, MESSAGE_WARNING, @@ -165,6 +177,8 @@ class ScriptEditorDebugger : public Control { bool live_debug; + CameraOverride camera_override; + void _performance_draw(); void _performance_select(); void _stack_dump_frame_selected(); @@ -250,6 +264,9 @@ public: void live_debug_duplicate_node(const NodePath &p_at, const String &p_new_name); void live_debug_reparent_node(const NodePath &p_at, const NodePath &p_new_place, const String &p_new_name, int p_at_pos); + CameraOverride get_camera_override() const; + void set_camera_override(CameraOverride p_override); + void set_breakpoint(const String &p_path, int p_line, bool p_enabled); void update_live_edit_root(); diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index f8425ebe22..a38c6b98cc 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -310,15 +310,7 @@ void EditorSettingsDialog::_wait_for_key(const Ref<InputEvent> &p_event) { if (k.is_valid() && k->is_pressed() && k->get_scancode() != 0) { last_wait_for_key = k; - String str = keycode_get_string(k->get_scancode()).capitalize(); - if (k->get_metakey()) - str = vformat("%s+", find_keycode_name(KEY_META)) + str; - if (k->get_shift()) - str = TTR("Shift+") + str; - if (k->get_alt()) - str = TTR("Alt+") + str; - if (k->get_control()) - str = TTR("Control+") + str; + const String str = keycode_get_string(k->get_scancode_with_modifiers()); press_a_key_label->set_text(str); press_a_key->accept_event(); |