diff options
Diffstat (limited to 'editor')
-rw-r--r-- | editor/icons/icon_editor_position.svg | 69 | ||||
-rw-r--r-- | editor/icons/icon_editor_position_previous.svg | 62 | ||||
-rw-r--r-- | editor/icons/icon_editor_position_unselected.svg | 66 | ||||
-rw-r--r-- | editor/plugins/asset_library_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 654 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.h | 12 | ||||
-rw-r--r-- | editor/plugins/skeleton_2d_editor_plugin.cpp | 5 | ||||
-rw-r--r-- | editor/plugins/sprite_editor_plugin.cpp | 5 | ||||
-rw-r--r-- | editor/project_settings_editor.cpp | 172 | ||||
-rw-r--r-- | editor/project_settings_editor.h | 2 |
10 files changed, 751 insertions, 298 deletions
diff --git a/editor/icons/icon_editor_position.svg b/editor/icons/icon_editor_position.svg new file mode 100644 index 0000000000..7cbce07fab --- /dev/null +++ b/editor/icons/icon_editor_position.svg @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg919" + sodipodi:docname="icon_editor_position.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata925"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs923" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2550" + inkscape:window-height="1414" + id="namedview921" + showgrid="false" + inkscape:zoom="64" + inkscape:cx="13.492036" + inkscape:cy="5.8518769" + inkscape:window-x="1370" + inkscape:window-y="20" + inkscape:window-maximized="0" + inkscape:current-layer="svg919" + inkscape:snap-page="true" /> + <g + id="g6479"> + <path + id="path913" + d="M 6 0 L 6 4.4199219 A 4.2661548 4.0576186 0 0 0 4.2910156 6 L 0 6 L 0 10 L 4.2949219 10 A 4.2661548 4.0576186 0 0 0 6 11.582031 L 6 16 L 10 16 L 10 11.580078 A 4.2661548 4.0576186 0 0 0 11.708984 10 L 16 10 L 16 6 L 11.705078 6 A 4.2661548 4.0576186 0 0 0 10 4.4179688 L 10 0 L 6 0 z " + style="fill:#ffffff;fill-opacity:0.70588237" /> + <path + id="path915" + d="M 7 1 L 7 4.0605469 A 4.2661548 4.0576186 0 0 1 8 3.9414062 A 4.2661548 4.0576186 0 0 1 9 4.0605469 L 9 1 L 7 1 z M 1 7 L 1 9 L 3.8691406 9 A 4.2661548 4.0576186 0 0 1 3.734375 8 A 4.2661548 4.0576186 0 0 1 3.8710938 7 L 1 7 z M 12.130859 7 A 4.2661548 4.0576186 0 0 1 12.265625 8 A 4.2661548 4.0576186 0 0 1 12.128906 9 L 15 9 L 15 7 L 12.130859 7 z M 7 11.939453 L 7 15 L 9 15 L 9 11.939453 A 4.2661548 4.0576186 0 0 1 8 12.058594 A 4.2661548 4.0576186 0 0 1 7 11.939453 z " + style="fill:#ff8484;stroke:none;fill-opacity:1" /> + <circle + id="circle1517" + r="2.9201488" + cy="8" + cx="8" + style="fill:#ff8484;fill-opacity:1;stroke-width:0.97338283" /> + </g> +</svg> diff --git a/editor/icons/icon_editor_position_previous.svg b/editor/icons/icon_editor_position_previous.svg new file mode 100644 index 0000000000..d9eb7d7ce2 --- /dev/null +++ b/editor/icons/icon_editor_position_previous.svg @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg919" + sodipodi:docname="icon_editor_position_previous.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata925"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs923" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1356" + inkscape:window-height="742" + id="namedview921" + showgrid="false" + inkscape:zoom="11.313709" + inkscape:cx="14.523034" + inkscape:cy="-5.7323703" + inkscape:window-x="4" + inkscape:window-y="20" + inkscape:window-maximized="0" + inkscape:current-layer="svg919" + inkscape:snap-page="true" /> + <path + style="fill:#6699ff;stroke:none;fill-opacity:0.69803923" + d="M 7 1 L 7 4.0605469 A 4.2661548 4.0576186 0 0 1 8 3.9414062 A 4.2661548 4.0576186 0 0 1 9 4.0605469 L 9 1 L 7 1 z M 1 7 L 1 9 L 3.8691406 9 A 4.2661548 4.0576186 0 0 1 3.734375 8 A 4.2661548 4.0576186 0 0 1 3.8710938 7 L 1 7 z M 12.130859 7 A 4.2661548 4.0576186 0 0 1 12.265625 8 A 4.2661548 4.0576186 0 0 1 12.128906 9 L 15 9 L 15 7 L 12.130859 7 z M 7 11.939453 L 7 15 L 9 15 L 9 11.939453 A 4.2661548 4.0576186 0 0 1 8 12.058594 A 4.2661548 4.0576186 0 0 1 7 11.939453 z " + id="path915" /> + <circle + style="fill:#6699ff;fill-opacity:0.69803923;stroke-width:0.97338283" + cx="8" + cy="8" + r="2.9201488" + id="circle1517" /> +</svg> diff --git a/editor/icons/icon_editor_position_unselected.svg b/editor/icons/icon_editor_position_unselected.svg new file mode 100644 index 0000000000..8f32c89f16 --- /dev/null +++ b/editor/icons/icon_editor_position_unselected.svg @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg919" + sodipodi:docname="icon_editor_position_unselected.svg" + inkscape:version="0.92.2 5c3e80d, 2017-08-06"> + <metadata + id="metadata925"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs923" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="2550" + inkscape:window-height="1414" + id="namedview921" + showgrid="false" + inkscape:zoom="64" + inkscape:cx="13.492036" + inkscape:cy="8.3518769" + inkscape:window-x="1370" + inkscape:window-y="20" + inkscape:window-maximized="0" + inkscape:current-layer="svg919" + inkscape:snap-page="true" /> + <path + style="fill:#000000;fill-opacity:0.41077441" + d="M 6 0 L 6 4.4199219 A 4.2661548 4.0576186 0 0 0 4.2910156 6 L 0 6 L 0 10 L 4.2949219 10 A 4.2661548 4.0576186 0 0 0 6 11.582031 L 6 16 L 10 16 L 10 11.580078 A 4.2661548 4.0576186 0 0 0 11.708984 10 L 16 10 L 16 6 L 11.705078 6 A 4.2661548 4.0576186 0 0 0 10 4.4179688 L 10 0 L 6 0 z " + id="path913" /> + <path + style="fill:#d9d9d9;stroke:none;fill-opacity:1" + d="M 7 1 L 7 4.0605469 A 4.2661548 4.0576186 0 0 1 8 3.9414062 A 4.2661548 4.0576186 0 0 1 9 4.0605469 L 9 1 L 7 1 z M 1 7 L 1 9 L 3.8691406 9 A 4.2661548 4.0576186 0 0 1 3.734375 8 A 4.2661548 4.0576186 0 0 1 3.8710938 7 L 1 7 z M 12.130859 7 A 4.2661548 4.0576186 0 0 1 12.265625 8 A 4.2661548 4.0576186 0 0 1 12.128906 9 L 15 9 L 15 7 L 12.130859 7 z M 7 11.939453 L 7 15 L 9 15 L 9 11.939453 A 4.2661548 4.0576186 0 0 1 8 12.058594 A 4.2661548 4.0576186 0 0 1 7 11.939453 z " + id="path915" /> + <circle + style="fill:#d9d9d9;fill-opacity:1;stroke-width:0.97338283" + cx="8" + cy="8" + r="2.9201488" + id="circle1517" /> +</svg> diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index b72c9b25be..c203b4b81e 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -902,7 +902,7 @@ void EditorAssetLibrary::_search(int p_page) { } if (filter->get_text() != String()) { - args += "&filter=" + filter->get_text().percent_encode(); + args += "&filter=" + filter->get_text().http_escape(); } if (p_page > 0) { diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index b8d0958c99..bb94aee462 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -196,11 +196,15 @@ void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, Transform2D ci_transform = canvas_item->get_global_transform_with_canvas(); Transform2D to_snap_transform = p_to_snap ? p_to_snap->get_global_transform_with_canvas() : Transform2D(); if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), (real_t)360.0) == 0.0) { - Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position()); - Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size()); - - _snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation()); - _snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation()); + if (canvas_item->_edit_use_rect()) { + Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position()); + Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size()); + _snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation()); + _snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation()); + } else { + Point2 position = ci_transform.xform(Point2()); + _snap_if_closer_point(p_value, position, r_current_snap, r_snapped, ci_transform.get_rotation()); + } } } for (int i = 0; i < p_current->get_child_count(); i++) { @@ -221,23 +225,23 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const // Parent sides and center if ((is_snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) { - Point2 begin; - Point2 end; - bool can_snap = false; if (const Control *c = Object::cast_to<Control>(p_canvas_item)) { - begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0))); - end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1))); - can_snap = true; - } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) { - begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position()); - end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size()); - can_snap = true; - } - - if (can_snap) { + Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0))); + Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1))); _snap_if_closer_point(p_target, begin, output, snapped, rotation); _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation); _snap_if_closer_point(p_target, end, output, snapped, rotation); + } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) { + if (parent_ci->_edit_use_rect()) { + Point2 begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position()); + Point2 end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size()); + _snap_if_closer_point(p_target, begin, output, snapped, rotation); + _snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation); + _snap_if_closer_point(p_target, end, output, snapped, rotation); + } else { + Point2 position = p_canvas_item->get_transform().affine_inverse().xform(Point2()); + _snap_if_closer_point(p_target, position, output, snapped, rotation); + } } } @@ -253,16 +257,23 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const // Self sides if ((is_snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) { - Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position()); - Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size()); - _snap_if_closer_point(p_target, begin, output, snapped, rotation); - _snap_if_closer_point(p_target, end, output, snapped, rotation); + if (p_canvas_item->_edit_use_rect()) { + Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position()); + Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size()); + _snap_if_closer_point(p_target, begin, output, snapped, rotation); + _snap_if_closer_point(p_target, end, output, snapped, rotation); + } } // Self center if ((is_snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) { - Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0); - _snap_if_closer_point(p_target, center, output, snapped, rotation); + if (p_canvas_item->_edit_use_rect()) { + Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0); + _snap_if_closer_point(p_target, center, output, snapped, rotation); + } else { + Point2 position = p_canvas_item->get_global_transform_with_canvas().xform(Point2()); + _snap_if_closer_point(p_target, position, output, snapped, rotation); + } } } @@ -364,63 +375,85 @@ Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_li // Handles the first element CanvasItem *canvas_item = p_list.front()->get(); - Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2()); + Rect2 rect; + if (canvas_item->_edit_use_rect()) { + rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2()); + } else { + rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(Point2()), Size2()); + } - // Handles the other ones + // Expand with the other ones for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) { CanvasItem *canvas_item = E->get(); - Rect2 current_rect = canvas_item->_edit_get_rect(); Transform2D xform = canvas_item->get_global_transform_with_canvas(); - rect.expand_to(xform.xform(current_rect.position)); - rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0))); - rect.expand_to(xform.xform(current_rect.position + current_rect.size)); - rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y))); + if (canvas_item->_edit_use_rect()) { + Rect2 current_rect = canvas_item->_edit_get_rect(); + + rect.expand_to(xform.xform(current_rect.position)); + rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0))); + rect.expand_to(xform.xform(current_rect.position + current_rect.size)); + rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y))); + } else { + rect.expand_to(xform.xform(Point2())); + } } return rect; } -void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { +void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) return; - CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); + const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); - bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; - bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); + /*bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; + bool editable = !inherited || EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); - if (!lock_children && (!inherited || editable)) { - for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); - } else { - CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); - _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); - } + if (!lock_children && editable) {}*/ + + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + const CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); + _expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); } } if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - Rect2 rect = canvas_item->_edit_get_rect(); Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); - if (r_first) { - r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2()); - r_first = false; + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + if (r_first) { + r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2()); + r_first = false; + } + if (r_rect.size != Size2()) { + r_rect.expand_to(xform.xform(rect.position)); + r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); + r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); + r_rect.expand_to(xform.xform(rect.position + rect.size)); + } + } else { + if (r_first) { + r_rect = Rect2(xform.xform(Point2()), Size2()); + r_first = false; + } else { + r_rect.expand_to(xform.xform(Point2())); + } } - r_rect.expand_to(xform.xform(rect.position)); - r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0))); - r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y))); - r_rect.expand_to(xform.xform(rect.position + rect.size)); } } -Rect2 CanvasItemEditor::_get_scene_encompassing_rect() { +Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) { Rect2 rect; bool first = true; - _expand_encompassing_rect_using_children(rect, editor->get_edited_scene(), first); + _expand_encompassing_rect_using_children(rect, p_node, first); + return rect; } @@ -433,22 +466,23 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); - for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - if (canvas_item && !canvas_item->is_set_as_toplevel()) - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); - else { - CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); - _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); //use base transform + Node *scene = editor->get_edited_scene(); + if (!(p_node != scene && p_node->get_owner() != scene && (!scene->is_editable_instance(p_node) || p_node->has_meta("_edit_lock_")))) { + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, limit, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); + _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, limit, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); + } + if (limit != 0 && r_items.size() >= limit) + return; } - if (limit != 0 && r_items.size() >= limit) - return; } - if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - + if (canvas_item && canvas_item->is_visible_in_tree() && (canvas_item->get_owner() != editor->get_edited_scene() || !canvas_item->has_meta("_edit_lock_"))) { Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse(); const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length(); - if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) { Node2D *node = Object::cast_to<Node2D>(canvas_item); @@ -463,7 +497,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no return; } -void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { +void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { if (!p_node) return; if (Object::cast_to<Viewport>(p_node)) @@ -472,31 +506,37 @@ void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_n CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != ""; - bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); + bool editable = !inherited || EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node); bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_"); + bool locked = p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_"); - if (!lock_children && (!inherited || editable)) { + if (!lock_children && !locked && editable) { for (int i = p_node->get_child_count() - 1; i >= 0; i--) { if (canvas_item && !canvas_item->is_set_as_toplevel()) { - _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform); } else { CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node); - _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); + _find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform); } } } if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) { - - Rect2 rect = canvas_item->_edit_get_rect(); Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform(); - if (p_rect.has_point(xform.xform(rect.position)) && - p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) && - p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) && - p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) { + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + if (p_rect.has_point(xform.xform(rect.position)) && + p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) && + p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) && + p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) { - r_items->push_back(canvas_item); + r_items->push_back(canvas_item); + } + } else { + if (p_rect.has_point(xform.xform(Point2()))) { + r_items->push_back(canvas_item); + } } } } @@ -575,8 +615,11 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items if (se) { se->undo_state = canvas_item->_edit_get_state(); se->pre_drag_xform = canvas_item->get_global_transform_with_canvas(); - se->pre_drag_rect = canvas_item->_edit_get_rect(); - + if (canvas_item->_edit_use_rect()) { + se->pre_drag_rect = canvas_item->_edit_get_rect(); + } else { + se->pre_drag_rect = Rect2(); + } se->pre_drag_bones_length = List<float>(); se->pre_drag_bones_undo_state = List<Dictionary>(); @@ -1290,54 +1333,55 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) { List<CanvasItem *> selection = _get_edited_canvas_items(); if (selection.size() == 1) { CanvasItem *canvas_item = selection[0]; + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); + + Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; - Rect2 rect = canvas_item->_edit_get_rect(); - Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); - - Vector2 endpoints[4] = { - xform.xform(rect.position), - xform.xform(rect.position + Vector2(rect.size.x, 0)), - xform.xform(rect.position + rect.size), - xform.xform(rect.position + Vector2(0, rect.size.y)) - }; - - DragType dragger[] = { - DRAG_TOP_LEFT, - DRAG_TOP, - DRAG_TOP_RIGHT, - DRAG_RIGHT, - DRAG_BOTTOM_RIGHT, - DRAG_BOTTOM, - DRAG_BOTTOM_LEFT, - DRAG_LEFT - }; - - DragType resize_drag = DRAG_NONE; - float radius = (select_handle->get_size().width / 2) * 1.5; - - for (int i = 0; i < 4; i++) { - int prev = (i + 3) % 4; - int next = (i + 1) % 4; + DragType dragger[] = { + DRAG_TOP_LEFT, + DRAG_TOP, + DRAG_TOP_RIGHT, + DRAG_RIGHT, + DRAG_BOTTOM_RIGHT, + DRAG_BOTTOM, + DRAG_BOTTOM_LEFT, + DRAG_LEFT + }; - Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); - ofs *= (select_handle->get_size().width / 2); - ofs += endpoints[i]; - if (ofs.distance_to(b->get_position()) < radius) - resize_drag = dragger[i * 2]; + DragType resize_drag = DRAG_NONE; + float radius = (select_handle->get_size().width / 2) * 1.5; - ofs = (endpoints[i] + endpoints[next]) / 2; - ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2); - if (ofs.distance_to(b->get_position()) < radius) - resize_drag = dragger[i * 2 + 1]; - } + for (int i = 0; i < 4; i++) { + int prev = (i + 3) % 4; + int next = (i + 1) % 4; + + Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); + ofs *= (select_handle->get_size().width / 2); + ofs += endpoints[i]; + if (ofs.distance_to(b->get_position()) < radius) + resize_drag = dragger[i * 2]; + + ofs = (endpoints[i] + endpoints[next]) / 2; + ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2); + if (ofs.distance_to(b->get_position()) < radius) + resize_drag = dragger[i * 2 + 1]; + } - if (resize_drag != DRAG_NONE) { - drag_type = resize_drag; - drag_from = transform.affine_inverse().xform(b->get_position()); - drag_selection = List<CanvasItem *>(); - drag_selection.push_back(canvas_item); - _save_canvas_item_state(drag_selection); - return true; + if (resize_drag != DRAG_NONE) { + drag_type = resize_drag; + drag_from = transform.affine_inverse().xform(b->get_position()); + drag_selection = List<CanvasItem *>(); + drag_selection.push_back(canvas_item); + _save_canvas_item_state(drag_selection); + return true; + } } } } @@ -1535,61 +1579,64 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { _save_canvas_item_state(drag_selection, true); } - _restore_canvas_item_state(drag_selection, true); - - bool move_local_base = k->get_alt(); - bool move_local_base_rotated = k->get_control() || k->get_metakey(); - - Vector2 dir; - if (k->get_scancode() == KEY_UP) - dir += Vector2(0, -1); - else if (k->get_scancode() == KEY_DOWN) - dir += Vector2(0, 1); - else if (k->get_scancode() == KEY_LEFT) - dir += Vector2(-1, 0); - else if (k->get_scancode() == KEY_RIGHT) - dir += Vector2(1, 0); - if (k->get_shift()) - dir *= grid_step * Math::pow(2.0, grid_step_multiplier); - - drag_to += dir; - if (k->get_shift()) - drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier)); - - Point2 previous_pos; - if (drag_selection.size() == 1) { - Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); - previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); - } else { - previous_pos = _get_encompassing_rect_from_list(drag_selection).position; - } + if (drag_selection.size() > 0) { - Point2 new_pos; - if (drag_selection.size() == 1) { - Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]); - if (node_2d && move_local_base_rotated) { - Transform2D m; - m.rotate(node_2d->get_rotation()); - new_pos += m.xform(drag_to); - } else if (move_local_base) { - new_pos += drag_to; + _restore_canvas_item_state(drag_selection, true); + + bool move_local_base = k->get_alt(); + bool move_local_base_rotated = k->get_control() || k->get_metakey(); + + Vector2 dir; + if (k->get_scancode() == KEY_UP) + dir += Vector2(0, -1); + else if (k->get_scancode() == KEY_DOWN) + dir += Vector2(0, 1); + else if (k->get_scancode() == KEY_LEFT) + dir += Vector2(-1, 0); + else if (k->get_scancode() == KEY_RIGHT) + dir += Vector2(1, 0); + if (k->get_shift()) + dir *= grid_step * Math::pow(2.0, grid_step_multiplier); + + drag_to += dir; + if (k->get_shift()) + drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier)); + + Point2 previous_pos; + if (drag_selection.size() == 1) { + Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse(); + previous_pos = xform.xform(drag_selection[0]->_edit_get_position()); + } else { + previous_pos = _get_encompassing_rect_from_list(drag_selection).position; + } + + Point2 new_pos; + if (drag_selection.size() == 1) { + Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]); + if (node_2d && move_local_base_rotated) { + Transform2D m; + m.rotate(node_2d->get_rotation()); + new_pos += m.xform(drag_to); + } else if (move_local_base) { + new_pos += drag_to; + } else { + new_pos = previous_pos + (drag_to - drag_from); + } } else { new_pos = previous_pos + (drag_to - drag_from); } - } else { - new_pos = previous_pos + (drag_to - drag_from); - } - for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { - CanvasItem *canvas_item = E->get(); - CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); + for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) { + CanvasItem *canvas_item = E->get(); + CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); + Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform(); - Node2D *node2d = Object::cast_to<Node2D>(canvas_item); - if (node2d && se->pre_drag_bones_undo_state.size() > 0) { - _solve_IK(node2d, new_pos); - } else { - canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + Node2D *node2d = Object::cast_to<Node2D>(canvas_item); + if (node2d && se->pre_drag_bones_undo_state.size() > 0) { + _solve_IK(node2d, new_pos); + } else { + canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos)); + } } } return true; @@ -1648,6 +1695,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return true; } else if (!selection_results.empty()) { + // Sorts items according the their z-index selection_results.sort(); NodePath root_path = get_tree()->get_edited_scene_root()->get_path(); @@ -1707,16 +1755,17 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { canvas_item = selection[0].item; // Check if the canvas item is in a group, and select the group instead if it is the case - CanvasItem *canvas_item_tmp = canvas_item; - while (canvas_item_tmp) { - if (canvas_item->has_meta("_edit_group_")) { + Node *node = canvas_item; + while (node && node != scene) { + CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node); + if (canvas_item_tmp && node->has_meta("_edit_group_")) { canvas_item = canvas_item_tmp; } - canvas_item_tmp = canvas_item_tmp->get_parent_item(); + node = node->get_parent(); } // Make sure the selected node is in the current scene - Node *node = canvas_item; + node = canvas_item; while (node && ((node != scene && node->get_owner() != scene) || !node->is_class("CanvasItem"))) { node = node->get_parent(); }; @@ -1766,7 +1815,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { if (bsfrom.y > bsto.y) SWAP(bsfrom.y, bsto.y); - _find_canvas_items_at_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems); + _find_canvas_items_in_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems); for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) { editor_selection->add_node(E->get()); } @@ -1800,6 +1849,42 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) { return false; } +bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseMotion> m = p_event; + if (m.is_valid()) { + if (drag_type == DRAG_NONE && tool == TOOL_SELECT) { + Point2 click = transform.affine_inverse().xform(m->get_position()); + Node *scene = editor->get_edited_scene(); + + //Checks if the hovered items changed, update the viewport if so + Vector<_SelectResult> hovering_results_tmp; + _find_canvas_items_at_pos(click, scene, hovering_results_tmp); + hovering_results_tmp.sort(); + bool changed = false; + if (hovering_results.size() == hovering_results_tmp.size()) { + for (int i = 0; i < hovering_results.size(); i++) { + if (hovering_results[i].item != hovering_results_tmp[i].item) { + changed = true; + break; + } + } + } else { + changed = true; + } + + if (changed) { + hovering_results = hovering_results_tmp; + viewport->update(); + } + + return true; + } + } + + return false; +} + void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { bool accepted = false; if ((accepted = _gui_input_rulers_and_guides(p_event))) { @@ -1827,6 +1912,9 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) { if (accepted) accept_event(); + // Handles the mouse hovering + _gui_input_hover(p_event); + // Change the cursor CursorShape c = CURSOR_ARROW; switch (drag_type) { @@ -2093,6 +2181,9 @@ void CanvasItemEditor::_draw_grid() { void CanvasItemEditor::_draw_selection() { Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons"); + Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons"); + Ref<Texture> previous_position_icon = get_icon("EditorPositionPrevious", "EditorIcons"); + RID ci = viewport->get_canvas_item(); List<CanvasItem *> selection = _get_edited_canvas_items(false, false); @@ -2102,8 +2193,6 @@ void CanvasItemEditor::_draw_selection() { CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get()); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Rect2 rect = canvas_item->_edit_get_rect(); - // Draw the previous position if we are dragging the node if (show_helpers && (drag_type == DRAG_ALL || drag_type == DRAG_ROTATE || @@ -2112,42 +2201,52 @@ void CanvasItemEditor::_draw_selection() { const Transform2D pre_drag_xform = transform * se->pre_drag_xform; const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7); - Vector2 pre_drag_endpoints[4] = { + if (canvas_item->_edit_use_rect()) { + Vector2 pre_drag_endpoints[4] = { - pre_drag_xform.xform(se->pre_drag_rect.position), - pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)), - pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size), - pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y)) - }; + pre_drag_xform.xform(se->pre_drag_rect.position), + pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)), + pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size), + pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y)) + }; - for (int i = 0; i < 4; i++) { - viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2); + for (int i = 0; i < 4; i++) { + viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2); + } + } else { + viewport->draw_texture(previous_position_icon, (pre_drag_xform.xform(Point2()) - (previous_position_icon->get_size() / 2)).floor()); } } Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform); - - // Draw the selected items surrounding boxes - Vector2 endpoints[4] = { - xform.xform(rect.position), - xform.xform(rect.position + Vector2(rect.size.x, 0)), - xform.xform(rect.position + rect.size), - xform.xform(rect.position + Vector2(0, rect.size.y)) - }; - Color c = Color(1, 0.6, 0.4, 0.7); + // Draw the selected items position / surrounding boxes + if (canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; + + Color c = Color(1, 0.6, 0.4, 0.7); - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); + for (int i = 0; i < 4; i++) { + viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, 2); + } + } else { - for (int i = 0; i < 4; i++) { - viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, 2); + Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin()); + viewport->draw_set_transform_matrix(transform); + viewport->draw_texture(position_icon, -(position_icon->get_size() / 2)); + viewport->draw_set_transform_matrix(Transform2D()); } if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks // Draw the pivot if (canvas_item->_edit_get_pivot() != Vector2() || drag_type == DRAG_PIVOT || tool == TOOL_EDIT_PIVOT) { // This is not really clean :/ - viewport->draw_texture(pivot_icon, xform.xform(canvas_item->_edit_get_pivot()) + (-pivot_icon->get_size() / 2).floor()); + viewport->draw_texture(pivot_icon, (xform.xform(canvas_item->_edit_get_pivot()) - (pivot_icon->get_size() / 2)).floor()); } Control *control = Object::cast_to<Control>(canvas_item); @@ -2329,7 +2428,14 @@ void CanvasItemEditor::_draw_selection() { } } - if (tool == TOOL_SELECT) { + if (tool == TOOL_SELECT && canvas_item->_edit_use_rect()) { + Rect2 rect = canvas_item->_edit_get_rect(); + Vector2 endpoints[4] = { + xform.xform(rect.position), + xform.xform(rect.position + Vector2(rect.size.x, 0)), + xform.xform(rect.position + rect.size), + xform.xform(rect.position + Vector2(0, rect.size.y)) + }; for (int i = 0; i < 4; i++) { // Draw the resize handles int prev = (i + 3) % 4; @@ -2506,32 +2612,121 @@ void CanvasItemEditor::_draw_bones() { } } -void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_xform) { +void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { + ERR_FAIL_COND(!p_node); + + Node *scene = editor->get_edited_scene(); + if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node)) + return; + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); + if (canvas_item && !canvas_item->is_visible()) + return; + + Transform2D parent_xform = p_parent_xform; + Transform2D canvas_xform = p_canvas_xform; + + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + parent_xform = parent_xform * canvas_item->get_transform(); + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); + parent_xform = Transform2D(); + canvas_xform = cl ? cl->get_transform() : p_canvas_xform; + } + + for (int i = p_node->get_child_count() - 1; i >= 0; i--) { + _draw_invisible_nodes_positions(p_node->get_child(i), parent_xform, canvas_xform); + } + + if (canvas_item && !canvas_item->_edit_use_rect() && !editor_selection->is_selected(canvas_item)) { + Transform2D xform = transform * canvas_xform * parent_xform; + + // Draw the node's position + Ref<Texture> position_icon = get_icon("EditorPositionUnselected", "EditorIcons"); + Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin()); + viewport->draw_set_transform_matrix(transform); + viewport->draw_texture(position_icon, -position_icon->get_size() / 2, Color(1.0, 1.0, 1.0, 0.5)); + viewport->draw_set_transform_matrix(Transform2D()); + } +} + +void CanvasItemEditor::_draw_hover() { + List<Rect2> previous_rects; + + for (int i = 0; i < hovering_results.size(); i++) { + // Draw the node's name and icon + CanvasItem *canvas_item = hovering_results[i].item; + + if (canvas_item->_edit_use_rect()) + continue; + + Transform2D xform = transform * canvas_item->get_global_transform_with_canvas(); + + // Get the resources + Ref<Texture> node_icon; + if (has_icon(canvas_item->get_class(), "EditorIcons")) + node_icon = get_icon(canvas_item->get_class(), "EditorIcons"); + else + node_icon = get_icon("Object", "EditorIcons"); + Ref<Font> font = get_font("font", "Label"); + String node_name = canvas_item->get_name(); + Size2 node_name_size = font->get_string_size(node_name); + Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3)); + + Point2 pos = xform.get_origin() - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4); + // Rectify the position to avoid overlaping items + for (List<Rect2>::Element *E = previous_rects.front(); E; E = E->next()) { + if (E->get().intersects(Rect2(pos, item_size))) { + pos.y = E->get().get_position().y - item_size.y; + } + } + + previous_rects.push_back(Rect2(pos, item_size)); + + // Draw the node icon and name + viewport->draw_texture(node_icon, pos, Color(1.0, 1.0, 1.0, 0.5)); + viewport->draw_string(font, pos + Point2(node_icon->get_size().x + 4, item_size.y - 3), node_name, Color(1.0, 1.0, 1.0, 0.5)); + } +} + +void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) { ERR_FAIL_COND(!p_node); - RID viewport_ci = viewport->get_canvas_item(); + Node *scene = editor->get_edited_scene(); + if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node->get_owner())) + return; + CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node); + if (canvas_item && !canvas_item->is_visible()) + return; + + Transform2D parent_xform = p_parent_xform; + Transform2D canvas_xform = p_canvas_xform; - Transform2D transform_ci = p_xform; - CanvasItem *ci = Object::cast_to<CanvasItem>(p_node); - if (ci) - transform_ci = transform_ci * ci->get_transform(); + if (canvas_item && !canvas_item->is_set_as_toplevel()) { + parent_xform = parent_xform * canvas_item->get_transform(); + } else { + CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node); + parent_xform = Transform2D(); + canvas_xform = cl ? cl->get_transform() : p_canvas_xform; + } for (int i = p_node->get_child_count() - 1; i >= 0; i--) { - _draw_locks_and_groups(p_node->get_child(i), transform_ci); + _draw_locks_and_groups(p_node->get_child(i), parent_xform, canvas_xform); } - if (ci) { + RID viewport_canvas_item = viewport->get_canvas_item(); + if (canvas_item) { + float offset = 0; + Ref<Texture> lock = get_icon("LockViewport", "EditorIcons"); if (p_node->has_meta("_edit_lock_")) { - lock->draw(viewport_ci, transform_ci.xform(Point2(0, 0))); + lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); + offset += lock->get_size().x; } Ref<Texture> group = get_icon("GroupViewport", "EditorIcons"); - if (ci->has_meta("_edit_group_")) { - Vector2 ofs = transform_ci.xform(Point2(0, 0)); - if (ci->has_meta("_edit_lock_")) - ofs = Point2(ofs.x + lock->get_size().x, ofs.y); - group->draw(viewport_ci, ofs); + if (canvas_item->has_meta("_edit_group_")) { + group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0)); + //offset += group->get_size().x; } } } @@ -2597,8 +2792,10 @@ void CanvasItemEditor::_draw_viewport() { _draw_grid(); _draw_selection(); _draw_axis(); - if (editor->get_edited_scene()) - _draw_locks_and_groups(editor->get_edited_scene(), transform); + if (editor->get_edited_scene()) { + _draw_locks_and_groups(editor->get_edited_scene()); + _draw_invisible_nodes_positions(editor->get_edited_scene()); + } RID ci = viewport->get_canvas_item(); VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); @@ -2618,6 +2815,7 @@ void CanvasItemEditor::_draw_viewport() { if (show_guides) _draw_guides(); _draw_focus(); + _draw_hover(); } void CanvasItemEditor::_notification(int p_what) { @@ -2633,12 +2831,17 @@ void CanvasItemEditor::_notification(int p_what) { CanvasItem *canvas_item = E->get(); CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); - Rect2 r = canvas_item->_edit_get_rect(); + Rect2 rect; + if (canvas_item->_edit_use_rect()) { + rect = canvas_item->_edit_get_rect(); + } else { + rect = Rect2(); + } Transform2D xform = canvas_item->get_transform(); - if (r != se->prev_rect || xform != se->prev_xform) { + if (rect != se->prev_rect || xform != se->prev_xform) { viewport->update(); - se->prev_rect = r; + se->prev_rect = rect; se->prev_xform = xform; } @@ -2840,7 +3043,7 @@ void CanvasItemEditor::_update_scrollbars() { // Calculate scrollable area Rect2 canvas_item_rect = Rect2(Point2(), screen_rect); if (editor->get_edited_scene()) { - Rect2 content_rect = _get_scene_encompassing_rect(); + Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene()); canvas_item_rect.expand_to(content_rect.position); canvas_item_rect.expand_to(content_rect.position + content_rect.size); } @@ -3539,7 +3742,12 @@ void CanvasItemEditor::_focus_selection(int p_op) { //if (!canvas_item->is_visible_in_tree()) continue; ++count; - Rect2 item_rect = canvas_item->_edit_get_rect(); + Rect2 item_rect; + if (canvas_item->_edit_use_rect()) { + item_rect = canvas_item->_edit_get_rect(); + } else { + item_rect = Rect2(); + } Vector2 pos = canvas_item->get_global_transform().get_origin(); Vector2 scale = canvas_item->get_global_transform().get_scale(); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index da7ce9172a..5ca8a37610 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -258,6 +258,7 @@ class CanvasItemEditor : public VBoxContainer { }; Vector<_SelectResult> selection_results; + Vector<_SelectResult> hovering_results; struct BoneList { @@ -336,7 +337,7 @@ class CanvasItemEditor : public VBoxContainer { Ref<ShortCut> divide_grid_step_shortcut; void _find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int limit = 0, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); - void _find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); bool _select_click_on_item(CanvasItem *item, Point2 p_click_pos, bool p_append); ConfirmationDialog *snap_dialog; @@ -366,8 +367,8 @@ class CanvasItemEditor : public VBoxContainer { List<CanvasItem *> _get_edited_canvas_items(bool retreive_locked = false, bool remove_canvas_item_if_parent_in_selection = true); Rect2 _get_encompassing_rect_from_list(List<CanvasItem *> p_list); - void _expand_encompassing_rect_using_children(Rect2 &p_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); - Rect2 _get_scene_encompassing_rect(); + void _expand_encompassing_rect_using_children(Rect2 &p_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + Rect2 _get_encompassing_rect(const Node *p_node); Object *_get_editor_data(Object *p_what); @@ -387,7 +388,9 @@ class CanvasItemEditor : public VBoxContainer { void _draw_selection(); void _draw_axis(); void _draw_bones(); - void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform); + void _draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D()); + void _draw_hover(); void _draw_viewport(); @@ -400,6 +403,7 @@ class CanvasItemEditor : public VBoxContainer { bool _gui_input_select(const Ref<InputEvent> &p_event); bool _gui_input_zoom_or_pan(const Ref<InputEvent> &p_event); bool _gui_input_rulers_and_guides(const Ref<InputEvent> &p_event); + bool _gui_input_hover(const Ref<InputEvent> &p_event); void _gui_input_viewport(const Ref<InputEvent> &p_event); diff --git a/editor/plugins/skeleton_2d_editor_plugin.cpp b/editor/plugins/skeleton_2d_editor_plugin.cpp index 6bf94b95eb..e372f792d6 100644 --- a/editor/plugins/skeleton_2d_editor_plugin.cpp +++ b/editor/plugins/skeleton_2d_editor_plugin.cpp @@ -20,6 +20,10 @@ void Skeleton2DEditor::edit(Skeleton2D *p_sprite) { void Skeleton2DEditor::_menu_option(int p_option) { + if (!node) { + return; + } + switch (p_option) { case MENU_OPTION_MAKE_REST: { @@ -107,6 +111,7 @@ Skeleton2DEditorPlugin::Skeleton2DEditorPlugin(EditorNode *p_node) { editor = p_node; sprite_editor = memnew(Skeleton2DEditor); editor->get_viewport()->add_child(sprite_editor); + make_visible(false); //sprite_editor->options->hide(); } diff --git a/editor/plugins/sprite_editor_plugin.cpp b/editor/plugins/sprite_editor_plugin.cpp index 99aabcb3eb..49816fe2ae 100644 --- a/editor/plugins/sprite_editor_plugin.cpp +++ b/editor/plugins/sprite_editor_plugin.cpp @@ -80,6 +80,10 @@ Vector<Vector2> expand(const Vector<Vector2> &points, const Rect2i &rect, float void SpriteEditor::_menu_option(int p_option) { + if (!node) { + return; + } + switch (p_option) { case MENU_OPTION_CREATE_MESH_2D: { @@ -389,6 +393,7 @@ SpriteEditorPlugin::SpriteEditorPlugin(EditorNode *p_node) { editor = p_node; sprite_editor = memnew(SpriteEditor); editor->get_viewport()->add_child(sprite_editor); + make_visible(false); //sprite_editor->options->hide(); } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 6e3be343ba..8ae573baef 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -178,15 +178,15 @@ void ProjectSettingsEditor::_action_edited() { } int order = ProjectSettings::get_singleton()->get_order(add_at); - Array va = ProjectSettings::get_singleton()->get(add_at); + Dictionary action = ProjectSettings::get_singleton()->get(add_at); setting = true; undo_redo->create_action(TTR("Rename Input Action Event")); undo_redo->add_do_method(ProjectSettings::get_singleton(), "clear", add_at); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, va); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", action_prop, action); undo_redo->add_do_method(ProjectSettings::get_singleton(), "set_order", action_prop, order); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", action_prop); - undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, va); + undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", add_at, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set_order", add_at, order); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -203,8 +203,9 @@ void ProjectSettingsEditor::_device_input_add() { Ref<InputEvent> ie; String name = add_at; int idx = edit_idx; - Array old_val = ProjectSettings::get_singleton()->get(name); - Array arr = old_val.duplicate(); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); + Dictionary action = old_val.duplicate(); + Array events = action["events"]; switch (add_type) { @@ -215,9 +216,9 @@ void ProjectSettingsEditor::_device_input_add() { mb->set_button_index(device_index->get_selected() + 1); mb->set_device(_get_current_device()); - for (int i = 0; i < arr.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEventMouseButton> aie = arr[i]; + Ref<InputEventMouseButton> aie = events[i]; if (aie.is_null()) continue; if (aie->get_device() == mb->get_device() && aie->get_button_index() == mb->get_button_index()) { @@ -233,20 +234,26 @@ void ProjectSettingsEditor::_device_input_add() { Ref<InputEventJoypadMotion> jm; jm.instance(); jm->set_axis(device_index->get_selected() >> 1); - jm->set_axis_value(device_index->get_selected() & 1 ? 1 : -1); jm->set_device(_get_current_device()); - for (int i = 0; i < arr.size(); i++) { + bool should_update_event = true; + Variant deadzone = device_special_value->get_value(); + for (int i = 0; i < events.size(); i++) { - Ref<InputEventJoypadMotion> aie = arr[i]; + Ref<InputEventJoypadMotion> aie = events[i]; if (aie.is_null()) continue; - if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis() && aie->get_axis_value() == jm->get_axis_value()) { - return; + if (aie->get_device() == jm->get_device() && aie->get_axis() == jm->get_axis()) { + should_update_event = false; + break; } } + if (!should_update_event && deadzone == action["deadzone"]) + return; + ie = jm; + action["deadzone"] = deadzone; } break; case INPUT_JOY_BUTTON: { @@ -257,9 +264,9 @@ void ProjectSettingsEditor::_device_input_add() { jb->set_button_index(device_index->get_selected()); jb->set_device(_get_current_device()); - for (int i = 0; i < arr.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEventJoypadButton> aie = arr[i]; + Ref<InputEventJoypadButton> aie = events[i]; if (aie.is_null()) continue; if (aie->get_device() == jb->get_device() && aie->get_button_index() == jb->get_button_index()) { @@ -272,14 +279,15 @@ void ProjectSettingsEditor::_device_input_add() { default: {} } - if (idx < 0 || idx >= arr.size()) { - arr.push_back(ie); + if (idx < 0 || idx >= events.size()) { + events.push_back(ie); } else { - arr[idx] = ie; + events[idx] = ie; } + action["events"] = events; undo_redo->create_action(TTR("Add Input Action Event")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -320,12 +328,13 @@ void ProjectSettingsEditor::_press_a_key_confirm() { String name = add_at; int idx = edit_idx; - Array old_val = ProjectSettings::get_singleton()->get(name); - Array arr = old_val.duplicate(); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); + Dictionary action = old_val.duplicate(); + Array events = action["events"]; - for (int i = 0; i < arr.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEventKey> aie = arr[i]; + Ref<InputEventKey> aie = events[i]; if (aie.is_null()) continue; if (aie->get_scancode_with_modifiers() == ie->get_scancode_with_modifiers()) { @@ -333,14 +342,15 @@ void ProjectSettingsEditor::_press_a_key_confirm() { } } - if (idx < 0 || idx >= arr.size()) { - arr.push_back(ie); + if (idx < 0 || idx >= events.size()) { + events.push_back(ie); } else { - arr[idx] = ie; + events[idx] = ie; } + action["events"] = events; undo_redo->create_action(TTR("Add Input Action Event")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, arr); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -418,6 +428,9 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even last_wait_for_key = Ref<InputEvent>(); press_a_key->popup_centered(Size2(250, 80) * EDSCALE); press_a_key->grab_focus(); + + device_special_value_label->hide(); + device_special_value->hide(); } break; case INPUT_MOUSE_BUTTON: { @@ -443,6 +456,9 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even _set_current_device(0); device_input->get_ok()->set_text(TTR("Add")); } + + device_special_value_label->hide(); + device_special_value->hide(); } break; case INPUT_JOY_MOTION: { @@ -464,6 +480,15 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even _set_current_device(0); device_input->get_ok()->set_text(TTR("Add")); } + + device_special_value_label->set_text(TTR("Deadzone (global to the action):")); + device_special_value_label->show(); + device_special_value->set_min(0.0f); + device_special_value->set_max(1.0f); + device_special_value->set_step(0.01f); + Dictionary action = ProjectSettings::get_singleton()->get(add_at); + device_special_value->set_value(action.has("deadzone") ? action["deadzone"] : Variant(0.5f)); + device_special_value->show(); } break; case INPUT_JOY_BUTTON: { @@ -486,6 +511,8 @@ void ProjectSettingsEditor::_add_item(int p_item, Ref<InputEvent> p_exiting_even device_input->get_ok()->set_text(TTR("Add")); } + device_special_value_label->hide(); + device_special_value->hide(); } break; default: {} } @@ -522,18 +549,17 @@ void ProjectSettingsEditor::_action_activated() { String name = "input/" + ti->get_parent()->get_text(0); int idx = ti->get_metadata(0); - Array va = ProjectSettings::get_singleton()->get(name); - - ERR_FAIL_INDEX(idx, va.size()); - - Ref<InputEvent> ie = va[idx]; + Dictionary action = ProjectSettings::get_singleton()->get(name); + Array events = action["events"]; - if (ie.is_null()) + ERR_FAIL_INDEX(idx, events.size()); + Ref<InputEvent> event = events[idx]; + if (event.is_null()) return; add_at = name; edit_idx = idx; - _edit_item(ie); + _edit_item(event); } void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, int p_id) { @@ -543,6 +569,7 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, ERR_FAIL_COND(!ti); if (p_id == 1) { + // Add action event Point2 ofs = input_editor->get_global_position(); Rect2 ir = input_editor->get_item_rect(ti); ir.position.y -= input_editor->get_scroll().y; @@ -554,14 +581,12 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, edit_idx = -1; } else if (p_id == 2) { - //remove + // Remove if (ti->get_parent() == input_editor->get_root()) { - - //remove main thing - + // Remove action String name = "input/" + ti->get_text(0); - Variant old_val = ProjectSettings::get_singleton()->get(name); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); int order = ProjectSettings::get_singleton()->get_order(name); undo_redo->create_action(TTR("Erase Input Action")); @@ -575,24 +600,19 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, undo_redo->commit_action(); } else { - //remove action + // Remove action event String name = "input/" + ti->get_parent()->get_text(0); - Variant old_val = ProjectSettings::get_singleton()->get(name); + Dictionary old_val = ProjectSettings::get_singleton()->get(name); + Dictionary action = old_val.duplicate(); int idx = ti->get_metadata(0); - Array va = old_val; - - ERR_FAIL_INDEX(idx, va.size()); - - for (int i = idx; i < va.size() - 1; i++) { - - va[i] = va[i + 1]; - } - - va.resize(va.size() - 1); + Array events = action["events"]; + ERR_FAIL_INDEX(idx, events.size()); + events.remove(idx); + action["events"] = events; undo_redo->create_action(TTR("Erase Input Action Event")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "set", name, old_val); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -601,30 +621,31 @@ void ProjectSettingsEditor::_action_button_pressed(Object *p_obj, int p_column, undo_redo->commit_action(); } } else if (p_id == 3) { - //edit + // Edit if (ti->get_parent() == input_editor->get_root()) { - + // Edit action name ti->set_as_cursor(0); input_editor->edit_selected(); } else { - //edit action + // Edit action event String name = "input/" + ti->get_parent()->get_text(0); int idx = ti->get_metadata(0); - Array va = ProjectSettings::get_singleton()->get(name); + Dictionary action = ProjectSettings::get_singleton()->get(name); - ERR_FAIL_INDEX(idx, va.size()); + Array events = action["events"]; + ERR_FAIL_INDEX(idx, events.size()); - Ref<InputEvent> ie = va[idx]; + Ref<InputEvent> event = events[idx]; - if (ie.is_null()) + if (event.is_null()) return; ti->set_as_cursor(0); add_at = name; edit_idx = idx; - _edit_item(ie); + _edit_item(event); } } } @@ -660,17 +681,18 @@ void ProjectSettingsEditor::_update_actions() { } item->set_custom_bg_color(0, get_color("prop_subsection", "Editor")); - Array actions = ProjectSettings::get_singleton()->get(pi.name); + Dictionary action = ProjectSettings::get_singleton()->get(pi.name); + Array events = action["events"]; - for (int i = 0; i < actions.size(); i++) { + for (int i = 0; i < events.size(); i++) { - Ref<InputEvent> ie = actions[i]; - if (ie.is_null()) + Ref<InputEvent> event = events[i]; + if (event.is_null()) continue; TreeItem *action = input_editor->create_item(item); - Ref<InputEventKey> k = ie; + Ref<InputEventKey> k = event; if (k.is_valid()) { String str = keycode_get_string(k->get_scancode()).capitalize(); @@ -687,7 +709,7 @@ void ProjectSettingsEditor::_update_actions() { action->set_icon(0, get_icon("Keyboard", "EditorIcons")); } - Ref<InputEventJoypadButton> jb = ie; + Ref<InputEventJoypadButton> jb = event; if (jb.is_valid()) { @@ -701,7 +723,7 @@ void ProjectSettingsEditor::_update_actions() { action->set_icon(0, get_icon("JoyButton", "EditorIcons")); } - Ref<InputEventMouseButton> mb = ie; + Ref<InputEventMouseButton> mb = event; if (mb.is_valid()) { String str = _get_device_string(mb->get_device()) + ", "; @@ -718,7 +740,7 @@ void ProjectSettingsEditor::_update_actions() { action->set_icon(0, get_icon("Mouse", "EditorIcons")); } - Ref<InputEventJoypadMotion> jm = ie; + Ref<InputEventJoypadMotion> jm = event; if (jm.is_valid()) { @@ -732,7 +754,7 @@ void ProjectSettingsEditor::_update_actions() { action->add_button(0, get_icon("Edit", "EditorIcons"), 3, false, TTR("Edit")); action->add_button(0, get_icon("Remove", "EditorIcons"), 2, false, TTR("Remove")); action->set_metadata(0, i); - action->set_meta("__input", ie); + action->set_meta("__input", event); } } @@ -892,10 +914,12 @@ void ProjectSettingsEditor::_action_adds(String) { void ProjectSettingsEditor::_action_add() { - Array va; + Dictionary action; + action["events"] = Array(); + action["deadzone"] = 0.5f; String name = "input/" + action_name->get_text(); undo_redo->create_action(TTR("Add Input Action")); - undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, va); + undo_redo->add_do_method(ProjectSettings::get_singleton(), "set", name, action); undo_redo->add_undo_method(ProjectSettings::get_singleton(), "clear", name); undo_redo->add_do_method(this, "_update_actions"); undo_redo->add_undo_method(this, "_update_actions"); @@ -1814,6 +1838,14 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { device_index = memnew(OptionButton); vbc_right->add_child(device_index); + l = memnew(Label); + l->set_text(TTR("Special value:")); + vbc_right->add_child(l); + device_special_value_label = l; + + device_special_value = memnew(SpinBox); + vbc_right->add_child(device_special_value); + setting = false; //translations diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 0ced88d7f6..b8bfdcd876 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -83,6 +83,8 @@ class ProjectSettingsEditor : public AcceptDialog { OptionButton *device_id; OptionButton *device_index; Label *device_index_label; + SpinBox *device_special_value; + Label *device_special_value_label; MenuButton *popup_copy_to_feature; LineEdit *action_name; |