Add viewport override to 2D editor

This commit is contained in:
kobewi 2023-03-02 02:31:27 +01:00
parent 0a4aedb360
commit 712b223616
2 changed files with 161 additions and 21 deletions

View File

@ -58,6 +58,7 @@
#include "scene/gui/separator.h"
#include "scene/gui/split_container.h"
#include "scene/gui/subviewport_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/view_panner.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
@ -606,11 +607,26 @@ Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) {
return rect;
}
Vector2 CanvasItemEditor::_get_screen_size() const {
if (!_is_viewport_overriden()) {
return Vector2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"));
}
SubViewport *svp = Object::cast_to<SubViewport>(current_viewport);
if (svp) {
return svp->get_size();
}
Window *w = Object::cast_to<Window>(current_viewport);
if (w) {
return w->get_size();
}
return Vector2();
}
void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node) {
return;
}
if (Object::cast_to<Viewport>(p_node)) {
if (Object::cast_to<Viewport>(p_node) && p_node != current_viewport) {
return;
}
@ -630,6 +646,10 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
}
}
if (_is_viewport_overriden() && p_node->get_viewport() != current_viewport) {
return;
}
if (ci && ci->is_visible_in_tree()) {
Transform2D xform = p_canvas_xform;
if (!ci->is_set_as_top_level()) {
@ -786,7 +806,7 @@ List<CanvasItem *> CanvasItemEditor::_get_edited_canvas_items(bool p_retrieve_lo
for (const KeyValue<Node *, Object *> &E : editor_selection->get_selection()) {
CanvasItem *ci = Object::cast_to<CanvasItem>(E.key);
if (ci) {
if (ci->is_visible_in_tree() && ci->get_viewport() == EditorNode::get_singleton()->get_scene_root() && (p_retrieve_locked || !_is_node_locked(ci))) {
if (ci->is_visible_in_tree() && ci->get_viewport() == current_viewport && (p_retrieve_locked || !_is_node_locked(ci))) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(ci);
if (se) {
selection.push_back(ci);
@ -1046,6 +1066,43 @@ void CanvasItemEditor::_on_grid_menu_id_pressed(int p_id) {
viewport->queue_redraw();
}
void CanvasItemEditor::_set_viewport_override(Viewport *p_viewport) {
if (p_viewport && p_viewport == current_viewport) {
return;
}
const Callable update_size = callable_mp(this, &CanvasItemEditor::_update_viewport_size);
const Callable redraw = callable_mp((CanvasItem *)viewport, &CanvasItem::queue_redraw);
if (current_viewport && _is_viewport_overriden()) {
current_viewport->disconnect("size_changed", update_size);
current_viewport->disconnect("size_changed", redraw);
}
if (p_viewport) {
p_viewport->connect("size_changed", update_size);
p_viewport->connect("size_changed", redraw);
scene_view_display->set_global_canvas_transform(EditorNode::get_singleton()->get_scene_root()->get_global_canvas_transform());
} else {
p_viewport = EditorNode::get_singleton()->get_scene_root();
p_viewport->set_global_canvas_transform(scene_view_display->get_global_canvas_transform());
scene_view_display->set_global_canvas_transform(Transform2D());
}
current_viewport = p_viewport;
scene_view->set_texture(p_viewport->get_texture());
_update_viewport_size();
viewport->queue_redraw();
}
void CanvasItemEditor::_update_viewport_size() {
EditorNode::get_singleton()->get_scene_root()->set_size(scene_tree->get_size());
}
bool CanvasItemEditor::_is_viewport_overriden() const {
return current_viewport != EditorNode::get_singleton()->get_scene_root();
}
void CanvasItemEditor::_switch_theme_preview(int p_mode) {
view_menu->get_popup()->hide();
@ -3724,13 +3781,13 @@ void CanvasItemEditor::_draw_axis() {
Color area_axis_color = EDITOR_GET("editors/2d/viewport_border_color");
Size2 screen_size = Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"));
Size2 viewport_size = _get_screen_size();
Vector2 screen_endpoints[4] = {
transform.xform(Vector2(0, 0)),
transform.xform(Vector2(screen_size.width, 0)),
transform.xform(Vector2(screen_size.width, screen_size.height)),
transform.xform(Vector2(0, screen_size.height))
transform.xform(Vector2(viewport_size.width, 0)),
transform.xform(Vector2(viewport_size.width, viewport_size.height)),
transform.xform(Vector2(0, viewport_size.height))
};
for (int i = 0; i < 4; i++) {
@ -3919,7 +3976,11 @@ void CanvasItemEditor::_draw_viewport() {
transform = Transform2D();
transform.scale_basis(Size2(zoom, zoom));
transform.columns[2] = -view_offset * zoom;
EditorNode::get_singleton()->get_scene_root()->set_global_canvas_transform(transform);
if (_is_viewport_overriden()) {
scene_view_display->set_global_canvas_transform(transform);
} else {
current_viewport->set_global_canvas_transform(transform);
}
_draw_grid();
_draw_ruler_tool();
@ -3976,6 +4037,7 @@ void CanvasItemEditor::_update_editor_settings() {
snap_config_menu->set_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
skeleton_menu->set_icon(get_editor_theme_icon(SNAME("Bone")));
override_camera_button->set_icon(get_editor_theme_icon(SNAME("Camera2D")));
override_viewport_button->set_icon(get_editor_theme_icon(SNAME("Viewport")));
pan_button->set_icon(get_editor_theme_icon(SNAME("ToolPan")));
ruler_button->set_icon(get_editor_theme_icon(SNAME("Ruler")));
pivot_button->set_icon(get_editor_theme_icon(SNAME("EditPivot")));
@ -4006,7 +4068,7 @@ void CanvasItemEditor::_update_editor_settings() {
}
void CanvasItemEditor::_project_settings_changed() {
EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
current_viewport->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
}
void CanvasItemEditor::_notification(int p_what) {
@ -4157,6 +4219,10 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
}
}
void CanvasItemEditor::edit_viewport(Viewport *p_viewport) {
_update_override_viewport_button(p_viewport);
}
void CanvasItemEditor::_update_scrollbars() {
updating_scroll = true;
@ -4169,7 +4235,7 @@ void CanvasItemEditor::_update_scrollbars() {
Size2 vmin = v_scroll->get_minimum_size();
// Get the visible frame.
Size2 screen_rect = Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"));
Size2 screen_rect = _get_screen_size();
Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
// Calculate scrollable area.
@ -4290,6 +4356,17 @@ void CanvasItemEditor::_button_override_camera(bool p_pressed) {
}
}
void CanvasItemEditor::_button_override_viewport(bool p_pressed) {
if (p_pressed) {
Viewport *vp = Object::cast_to<Viewport>(override_viewport_button->get_meta("viewport"));
_set_viewport_override(vp);
override_viewport_button->set_tooltip_text(TTR("Editor Viewport Override\nEditor viewport is overriden. Press to disable override."));
} else {
_set_viewport_override(nullptr);
override_viewport_button->set_tooltip_text(TTR("Editor Viewport Override\nMakes editor use selected SubViewport instead of the main viewport, allowing to edit nodes inside it."));
}
}
void CanvasItemEditor::_button_tool_select(int p_index) {
Button *tb[TOOL_MAX] = { select_button, list_select_button, move_button, scale_button, rotate_button, pivot_button, pan_button, ruler_button };
for (int i = 0; i < TOOL_MAX; i++) {
@ -4327,7 +4404,7 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -4407,6 +4484,32 @@ void CanvasItemEditor::_update_override_camera_button(bool p_game_running) {
}
}
void CanvasItemEditor::_update_override_viewport_button(Viewport *p_viewport) {
if (p_viewport) {
override_viewport_button->set_disabled(false);
if (p_viewport == current_viewport) {
override_viewport_button->set_pressed_no_signal(true);
override_viewport_button->set_tooltip_text(TTR("Editor Viewport Override\nEditor viewport is overriden. Press to disable override."));
} else {
override_viewport_button->set_pressed_no_signal(false);
override_viewport_button->set_meta(SNAME("viewport"), p_viewport);
override_viewport_button->set_tooltip_text(TTR("Editor Viewport Override\nMakes editor use selected SubViewport instead of the main viewport, allowing to edit nodes inside it."));
}
} else {
if (_is_viewport_overriden()) {
override_viewport_button->set_disabled(false);
override_viewport_button->set_pressed_no_signal(true);
override_viewport_button->set_tooltip_text(TTR("Editor Viewport Override\nEditor viewport is overriden. Press to disable override."));
} else {
override_viewport_button->set_disabled(true);
override_viewport_button->set_pressed_no_signal(false);
override_viewport_button->set_tooltip_text(TTR("Editor Viewport Override\nNo SubViewport node selected. Select one to allow overriding editor viewport."));
}
override_viewport_button->set_meta(SNAME("viewport"), Variant());
}
}
void CanvasItemEditor::_popup_callback(int p_op) {
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
last_option = MenuOption(p_op);
@ -4544,7 +4647,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (!ci || !ci->is_inside_tree()) {
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -4566,7 +4669,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (!ci || !ci->is_inside_tree()) {
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -4588,7 +4691,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (!ci || !ci->is_inside_tree()) {
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -4610,7 +4713,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
if (!ci || !ci->is_inside_tree()) {
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -4651,7 +4754,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -4697,7 +4800,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -4820,7 +4923,7 @@ void CanvasItemEditor::_focus_selection(int p_op) {
if (!ci) {
continue;
}
if (ci->get_viewport() != EditorNode::get_singleton()->get_scene_root()) {
if (ci->get_viewport() != current_viewport) {
continue;
}
@ -5118,6 +5221,8 @@ void CanvasItemEditor::clear() {
snap_rotation_step = EditorSettings::get_singleton()->get_project_metadata("2d_editor", "snap_rotation_step", Math::deg_to_rad(15.0));
snap_rotation_offset = EditorSettings::get_singleton()->get_project_metadata("2d_editor", "snap_rotation_offset", 0.0);
snap_scale_step = EditorSettings::get_singleton()->get_project_metadata("2d_editor", "snap_scale_step", 0.1);
edit_viewport(nullptr);
}
void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) {
@ -5197,7 +5302,7 @@ void CanvasItemEditor::focus_selection() {
}
void CanvasItemEditor::center_at(const Point2 &p_pos) {
Vector2 offset = viewport->get_size() / 2 - EditorNode::get_singleton()->get_scene_root()->get_global_canvas_transform().xform(p_pos);
Vector2 offset = viewport->get_size() / 2 - current_viewport->get_global_canvas_transform().xform(p_pos);
view_offset -= (offset / zoom).round();
update_viewport();
}
@ -5251,11 +5356,19 @@ CanvasItemEditor::CanvasItemEditor() {
viewport_scrollable->set_h_size_flags(Control::SIZE_EXPAND_FILL);
viewport_scrollable->connect(SceneStringName(draw), callable_mp(this, &CanvasItemEditor::_update_scrollbars));
SubViewportContainer *scene_tree = memnew(SubViewportContainer);
scene_tree = memnew(SubViewportContainer);
viewport_scrollable->add_child(scene_tree);
scene_tree->set_stretch(true);
scene_tree->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT);
scene_tree->add_child(EditorNode::get_singleton()->get_scene_root());
scene_tree->connect("item_rect_changed", callable_mp(this, &CanvasItemEditor::_update_viewport_size));
scene_view_display = memnew(SubViewport);
scene_tree->add_child(scene_view_display);
scene_view = memnew(TextureRect);
scene_view_display->add_child(scene_view);
scene_view->set_clip_contents(true);
scene_view->add_child(EditorNode::get_singleton()->get_scene_root());
controls_vb = memnew(VBoxContainer);
controls_vb->set_begin(Point2(5, 5));
@ -5321,6 +5434,7 @@ CanvasItemEditor::CanvasItemEditor() {
viewport->connect(SceneStringName(draw), callable_mp(this, &CanvasItemEditor::_draw_viewport));
viewport->connect(SceneStringName(gui_input), callable_mp(this, &CanvasItemEditor::_gui_input_viewport));
viewport->connect(SceneStringName(focus_exited), callable_mp(panner.ptr(), &ViewPanner::release_pan_key));
_set_viewport_override(nullptr);
h_scroll = memnew(HScrollBar);
viewport->add_child(h_scroll);
@ -5520,6 +5634,14 @@ CanvasItemEditor::CanvasItemEditor() {
override_camera_button->set_disabled(true);
_update_override_camera_button(false);
override_viewport_button = memnew(Button);
override_viewport_button->set_theme_type_variation("FlatButton");
override_viewport_button->set_toggle_mode(true);
override_viewport_button->set_disabled(true);
main_menu_hbox->add_child(override_viewport_button);
override_viewport_button->connect(SceneStringName(toggled), callable_mp(this, &CanvasItemEditor::_button_override_viewport));
_update_override_viewport_button(nullptr);
main_menu_hbox->add_child(memnew(VSeparator));
view_menu = memnew(MenuButton);
@ -5693,10 +5815,11 @@ CanvasItemEditor *CanvasItemEditor::singleton = nullptr;
void CanvasItemEditorPlugin::edit(Object *p_object) {
canvas_item_editor->edit(Object::cast_to<CanvasItem>(p_object));
canvas_item_editor->edit_viewport(Object::cast_to<Viewport>(p_object));
}
bool CanvasItemEditorPlugin::handles(Object *p_object) const {
return p_object->is_class("CanvasItem");
return Object::cast_to<CanvasItem>(p_object) || Object::cast_to<SubViewport>(p_object) || Object::cast_to<Window>(p_object);
}
void CanvasItemEditorPlugin::make_visible(bool p_visible) {

View File

@ -47,7 +47,11 @@ class HSplitContainer;
class MenuButton;
class PanelContainer;
class StyleBoxTexture;
class SubViewport;
class SubViewportContainer;
class TextureRect;
class ViewPanner;
class Viewport;
class VScrollBar;
class VSeparator;
class VSplitContainer;
@ -195,6 +199,10 @@ private:
Tool tool = TOOL_SELECT;
Control *viewport = nullptr;
Control *viewport_scrollable = nullptr;
SubViewportContainer *scene_tree = nullptr;
SubViewport *scene_view_display = nullptr;
TextureRect *scene_view = nullptr;
Viewport *current_viewport = nullptr;
HScrollBar *h_scroll = nullptr;
VScrollBar *v_scroll = nullptr;
@ -336,6 +344,7 @@ private:
Button *ungroup_button = nullptr;
Button *override_camera_button = nullptr;
Button *override_viewport_button = nullptr;
MenuButton *view_menu = nullptr;
PopupMenu *grid_menu = nullptr;
PopupMenu *theme_menu = nullptr;
@ -419,6 +428,11 @@ private:
void _prepare_grid_menu();
void _on_grid_menu_id_pressed(int p_id);
void _set_viewport_override(Viewport *p_viewport);
void _update_viewport_size();
bool _is_viewport_overriden() const;
Vector2 _get_screen_size() const;
public:
enum ThemePreviewMode {
THEME_PREVIEW_PROJECT,
@ -519,9 +533,11 @@ private:
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_override_viewport(bool p_pressed);
void _button_tool_select(int p_index);
void _update_override_camera_button(bool p_game_running);
void _update_override_viewport_button(Viewport *p_viewport);
HSplitContainer *left_panel_split = nullptr;
HSplitContainer *right_panel_split = nullptr;
@ -585,6 +601,7 @@ public:
void set_current_tool(Tool p_tool);
void edit(CanvasItem *p_canvas_item);
void edit_viewport(Viewport *p_viewport);
void focus_selection();
void center_at(const Point2 &p_pos);