diff options
36 files changed, 330 insertions, 204 deletions
diff --git a/doc/classes/EditorInspector.xml b/doc/classes/EditorInspector.xml index 7834390247..61d240c1dc 100644 --- a/doc/classes/EditorInspector.xml +++ b/doc/classes/EditorInspector.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="EditorInspector" inherits="ScrollContainer" version="4.0"> <brief_description> + A tab used to edit properties of the selected node. </brief_description> <description> + The editor inspector is by default located on the right-hand side of the editor. It's used to edit the properties of the selected node. For example, you can select a node such as the Sprite2D then edit its transform through the inspector tool. The editor inspector is an essential tool in the game development workflow. </description> <tutorials> </tutorials> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 512401d2de..f2574360cb 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -22,6 +22,8 @@ - Ctrl + N: Like the down arrow key, move the cursor to the next line - Ctrl + D: Like the Delete key, delete the character on the right side of cursor - Ctrl + H: Like the Backspace key, delete the character on the left side of the cursor + - Ctrl + A: Like the Home key, move the cursor to the beginning of the line + - Ctrl + E: Like the End key, move the cursor to the end of the line - Command + Left arrow: Like the Home key, move the cursor to the beginning of the line - Command + Right arrow: Like the End key, move the cursor to the end of the line </description> diff --git a/doc/classes/Mesh.xml b/doc/classes/Mesh.xml index b2d979239c..67b6045152 100644 --- a/doc/classes/Mesh.xml +++ b/doc/classes/Mesh.xml @@ -161,9 +161,6 @@ <constant name="ARRAY_FORMAT_INDEX" value="256" enum="ArrayFormat"> Mesh array uses indices. </constant> - <constant name="ARRAY_COMPRESS_BASE" value="9" enum="ArrayFormat"> - Used internally to calculate other [code]ARRAY_COMPRESS_*[/code] enum values. Do not use. - </constant> <constant name="ARRAY_COMPRESS_VERTEX" value="512" enum="ArrayFormat"> Flag used to mark a compressed (half float) vertex array. </constant> diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 83259afb35..c76ff9d679 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -197,7 +197,7 @@ void GroupDialog::_add_group(String p_name) { } String name = p_name.strip_edges(); - if (name == "" || groups->search_item_text(name)) { + if (name.empty() || groups->get_item_with_text(name)) { return; } diff --git a/editor/icons/icon_godot_docs.svg b/editor/icons/icon_godot_docs.svg deleted file mode 100644 index e38885aed9..0000000000 --- a/editor/icons/icon_godot_docs.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g stroke-width=".32031" transform="matrix(.017241 0 0 .017241 -.82759 -2.7)"><path d="m0 0s-.325 1.994-.515 1.976l-36.182-3.491c-2.879-.278-5.115-2.574-5.317-5.459l-.994-14.247-27.992-1.997-1.904 12.912c-.424 2.872-2.932 5.037-5.835 5.037h-38.188c-2.902 0-5.41-2.165-5.834-5.037l-1.905-12.912-27.992 1.997-.994 14.247c-.202 2.886-2.438 5.182-5.317 5.46l-36.2 3.49c-.187.018-.324-1.978-.511-1.978l-.049-7.83 30.658-4.944 1.004-14.374c.203-2.91 2.551-5.263 5.463-5.472l38.551-2.75c.146-.01.29-.016.434-.016 2.897 0 5.401 2.166 5.825 5.038l1.959 13.286h28.005l1.959-13.286c.423-2.871 2.93-5.037 5.831-5.037.142 0 .284.005.423.015l38.556 2.75c2.911.209 5.26 2.562 5.463 5.472l1.003 14.374 30.645 4.966z" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 919.24 771.67)"/><path d="m0 0v-59.041c.108-.001.216-.005.323-.015l36.196-3.49c1.896-.183 3.382-1.709 3.514-3.609l1.116-15.978 31.574-2.253 2.175 14.747c.282 1.912 1.922 3.329 3.856 3.329h38.188c1.933 0 3.573-1.417 3.855-3.329l2.175-14.747 31.575 2.253 1.115 15.978c.133 1.9 1.618 3.425 3.514 3.609l36.182 3.49c.107.01.214.014.322.015v4.711l.015.005v54.325h.134c4.795 6.12 9.232 12.569 13.487 19.449-5.651 9.62-12.575 18.217-19.976 26.182-6.864-3.455-13.531-7.369-19.828-11.534-3.151 3.132-6.7 5.694-10.186 8.372-3.425 2.751-7.285 4.768-10.946 7.118 1.09 8.117 1.629 16.108 1.846 24.448-9.446 4.754-19.519 7.906-29.708 10.17-4.068-6.837-7.788-14.241-11.028-21.479-3.842.642-7.702.88-11.567.926v.006c-.027 0-.052-.006-.075-.006-.024 0-.049.006-.073.006v-.006c-3.872-.046-7.729-.284-11.572-.926-3.238 7.238-6.956 14.642-11.03 21.479-10.184-2.264-20.258-5.416-29.703-10.17.216-8.34.755-16.331 1.848-24.448-3.668-2.35-7.523-4.367-10.949-7.118-3.481-2.678-7.036-5.24-10.188-8.372-6.297 4.165-12.962 8.079-19.828 11.534-7.401-7.965-14.321-16.562-19.974-26.182 4.253-6.88 8.693-13.329 13.487-19.449z" fill="#478cbf" transform="matrix(4.1626 0 0 -4.1626 104.7 525.91)"/><path d="m0 0-1.121-16.063c-.135-1.936-1.675-3.477-3.611-3.616l-38.555-2.751c-.094-.007-.188-.01-.281-.01-1.916 0-3.569 1.406-3.852 3.33l-2.211 14.994h-31.459l-2.211-14.994c-.297-2.018-2.101-3.469-4.133-3.32l-38.555 2.751c-1.936.139-3.476 1.68-3.611 3.616l-1.121 16.063-32.547 3.138c.015-3.498.06-7.33.06-8.093 0-34.374 43.605-50.896 97.781-51.086h.133c54.176.19 97.766 16.712 97.766 51.086 0 .777.047 4.593.063 8.093z" fill="#478cbf" transform="matrix(4.1626 0 0 -4.1626 784.07 817.24)"/><path d="m0 0c0-12.052-9.765-21.815-21.813-21.815-12.042 0-21.81 9.763-21.81 21.815 0 12.044 9.768 21.802 21.81 21.802 12.048 0 21.813-9.758 21.813-21.802" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 389.21 625.67)"/><path d="m0 0c0-7.994-6.479-14.473-14.479-14.473-7.996 0-14.479 6.479-14.479 14.473s6.483 14.479 14.479 14.479c8 0 14.479-6.485 14.479-14.479" fill="#414042" transform="matrix(4.1626 0 0 -4.1626 367.37 631.06)"/><path d="m0 0c-3.878 0-7.021 2.858-7.021 6.381v20.081c0 3.52 3.143 6.381 7.021 6.381s7.028-2.861 7.028-6.381v-20.081c0-3.523-3.15-6.381-7.028-6.381" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 511.99 724.74)"/><path d="m0 0c0-12.052 9.765-21.815 21.815-21.815 12.041 0 21.808 9.763 21.808 21.815 0 12.044-9.767 21.802-21.808 21.802-12.05 0-21.815-9.758-21.815-21.802" fill="#fff" transform="matrix(4.1626 0 0 -4.1626 634.79 625.67)"/><path d="m0 0c0-7.994 6.477-14.473 14.471-14.473 8.002 0 14.479 6.479 14.479 14.473s-6.477 14.479-14.479 14.479c-7.994 0-14.471-6.485-14.471-14.479" fill="#414042" transform="matrix(4.1626 0 0 -4.1626 656.64 631.06)"/></g><path d="m4 5a3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3h2a3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0 -3-3 3 3 0 0 0 -2.8262 2h-2.3496a3 3 0 0 0 -2.8242-2zm0 1a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2zm8 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2-2 2 2 0 0 1 2-2z"/></svg>
\ No newline at end of file diff --git a/editor/icons/icon_particle_attractor_2d.svg b/editor/icons/icon_particle_attractor_2d.svg deleted file mode 100644 index 85f289dc4b..0000000000 --- a/editor/icons/icon_particle_attractor_2d.svg +++ /dev/null @@ -1 +0,0 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 1a3 7 0 0 0 -2.0801 1.9668 7 3 45 0 0 -2.8691.083984 7 3 45 0 0 -.080078 2.8633 7 3 0 0 0 -1.9707 2.0859 7 3 0 0 0 1.9668 2.0801 3 7 45 0 0 .083984 2.8691 3 7 45 0 0 2.8633.080078 3 7 0 0 0 2.0859 1.9707 3 7 0 0 0 2.0801-1.9668 7 3 45 0 0 2.8691-.083984 7 3 45 0 0 .080078-2.8633 7 3 0 0 0 1.9707-2.0859 7 3 0 0 0 -1.9668-2.0801 3 7 45 0 0 -.083984-2.8691 3 7 45 0 0 -2.8633-.080078 3 7 0 0 0 -2.0859-1.9707zm0 1a2 6 0 0 1 1.2598 1.3438 3 7 45 0 0 -1.2578.75977 7 3 45 0 0 -1.2637-.75781 2 6 0 0 1 1.2617-1.3457zm-3.6348 1.5293a6 2 45 0 1 1.2344.28906 3 7 0 0 0 -.35352 1.4238 7 3 0 0 0 -1.4297.35742 6 2 45 0 1 -.058594-1.8418 6 2 45 0 1 .60742-.22852zm7.0762.0039062a2 6 45 0 1 .80078.22461 2 6 45 0 1 -.060547 1.8418 7 3 0 0 0 -1.4238-.35352 3 7 0 0 0 -.35742-1.4297 2 6 45 0 1 1.041-.2832zm-4.998.70703a6 2 45 0 1 .74023.4707 3 7 45 0 0 -.41211.33984 7 3 0 0 0 -.52344.048828 2 6 0 0 1 .19531-.85938zm3.1152.0019531a2 6 0 0 1 .18945.85547 7 3 0 0 0 -.5293-.050781 7 3 45 0 0 -.4043-.33594 2 6 45 0 1 .74414-.46875zm-1.5586 1.7578a6 2 0 0 1 .82031.021484 6 2 45 0 1 .59375.56445 6 2 45 0 1 .56445.59375 2 6 0 0 1 .021484.82031 2 6 0 0 1 -.021484.82031 2 6 45 0 1 -.56445.59375 2 6 45 0 1 -.59375.56445 6 2 0 0 1 -.82031.021484 6 2 0 0 1 -.82031-.021484 6 2 45 0 1 -.59375-.56445 6 2 45 0 1 -.56445-.59375 2 6 0 0 1 -.021484-.82031 2 6 0 0 1 .021484-.82031 2 6 45 0 1 .56445-.59375 2 6 45 0 1 .59375-.56445 6 2 0 0 1 .82031-.021484zm2.9004.24805a6 2 0 0 1 .85938.19531 2 6 45 0 1 -.4707.74023 7 3 45 0 0 -.33984-.41211 3 7 0 0 0 -.048828-.52344zm-5.8027.0039062a3 7 0 0 0 -.050781.5293 3 7 45 0 0 -.33594.4043 6 2 45 0 1 -.46875-.74414 6 2 0 0 1 .85547-.18945zm7.5566.48633a6 2 0 0 1 1.3457 1.2617 6 2 0 0 1 -1.3438 1.2598 7 3 45 0 0 -.75977-1.2578 3 7 45 0 0 .75781-1.2637zm-9.3105.0019532a7 3 45 0 0 .75977 1.2578 3 7 45 0 0 -.75781 1.2637 6 2 0 0 1 -1.3457-1.2617 6 2 0 0 1 1.3438-1.2598zm4.6562.25977a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1-1 1 1 0 0 0 -1-1zm3.2891 1.8145a6 2 45 0 1 .46875.74414 6 2 0 0 1 -.85547.18945 3 7 0 0 0 .050781-.5293 3 7 45 0 0 .33594-.4043zm-6.5781.0019531a7 3 45 0 0 .33984.41211 3 7 0 0 0 .048828.52344 6 2 0 0 1 -.85938-.19531 2 6 45 0 1 .4707-.74023zm-.89258 1.584a7 3 0 0 0 1.4238.35352 3 7 0 0 0 .35742 1.4297 2 6 45 0 1 -1.8418.058594 2 6 45 0 1 .060547-1.8418zm8.3652 0a6 2 45 0 1 .058594 1.8418 6 2 45 0 1 -1.8418-.060547 3 7 0 0 0 .35352-1.4238 7 3 0 0 0 1.4297-.35742zm-2.4316.5a2 6 0 0 1 -.19531.85938 6 2 45 0 1 -.74023-.4707 3 7 45 0 0 .41211-.33984 7 3 0 0 0 .52344-.048828zm-3.5.001953a7 3 0 0 0 .5293.050781 7 3 45 0 0 .4043.33594 2 6 45 0 1 -.74414.46875 2 6 0 0 1 -.18945-.85547zm1.7461.99414a7 3 45 0 0 1.2637.75781 2 6 0 0 1 -1.2617 1.3457 2 6 0 0 1 -1.2598-1.3438 3 7 45 0 0 1.2578-.75977z" fill="#a5b7f3" fill-opacity=".98824"/></svg>
\ No newline at end of file diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index b65482cc6b..ecd1e341d1 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -337,6 +337,7 @@ void InspectorDock::_notification(int p_what) { history_menu->set_icon(get_icon("History", "EditorIcons")); object_menu->set_icon(get_icon("Tools", "EditorIcons")); warning->set_icon(get_icon("NodeWarning", "EditorIcons")); + warning->add_color_override("font_color", get_color("warning_color", "Editor")); } break; } } @@ -584,6 +585,7 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) { add_child(warning); warning->set_text(TTR("Changes may be lost!")); warning->set_icon(get_icon("NodeWarning", "EditorIcons")); + warning->add_color_override("font_color", get_color("warning_color", "Editor")); warning->set_clip_text(true); warning->hide(); warning->connect("pressed", this, "_warning_pressed"); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a0e5b1c6ea..bf21abb455 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -58,6 +58,7 @@ #define RULER_WIDTH (15 * EDSCALE) #define SCALE_HANDLE_DISTANCE 25 +#define MOVE_HANDLE_DISTANCE 25 class SnapDialog : public ConfirmationDialog { @@ -1866,14 +1867,16 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { drag_type = DRAG_SCALE_BOTH; - Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); - Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { - drag_type = DRAG_SCALE_X; - } - Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); - if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { - drag_type = DRAG_SCALE_Y; + if (show_transformation_gizmos) { + Size2 scale_factor = Size2(SCALE_HANDLE_DISTANCE, SCALE_HANDLE_DISTANCE); + Rect2 x_handle_rect = Rect2(scale_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_SCALE_X; + } + Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_SCALE_Y; + } } drag_from = transform.affine_inverse().xform(b->get_position()); @@ -1924,7 +1927,7 @@ bool CanvasItemEditor::_gui_input_scale(const Ref<InputEvent> &p_event) { scale.y = scale.x * ratio; } } else if (drag_type == DRAG_SCALE_Y) { - scale.y += scale_factor.y; + scale.y -= scale_factor.y; if (uniform) { scale.x = scale.y / ratio; } @@ -1983,6 +1986,24 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { if (selection.size() > 0) { drag_type = DRAG_MOVE; + + CanvasItem *canvas_item = drag_selection[0]; + Transform2D parent_xform = canvas_item->get_global_transform_with_canvas() * canvas_item->get_transform().affine_inverse(); + Transform2D unscaled_transform = (transform * parent_xform * canvas_item->_edit_get_transform()).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + + if (show_transformation_gizmos) { + Size2 move_factor = Size2(MOVE_HANDLE_DISTANCE, MOVE_HANDLE_DISTANCE); + Rect2 x_handle_rect = Rect2(move_factor.x * EDSCALE, -5 * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (x_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_MOVE_X; + } + Rect2 y_handle_rect = Rect2(-5 * EDSCALE, move_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + if (y_handle_rect.has_point(simple_xform.affine_inverse().xform(b->get_position()))) { + drag_type = DRAG_MOVE_Y; + } + } + drag_from = transform.affine_inverse().xform(b->get_position()); drag_selection = selection; _save_canvas_item_state(drag_selection); @@ -1992,7 +2013,7 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } } - if (drag_type == DRAG_MOVE) { + if (drag_type == DRAG_MOVE || drag_type == DRAG_MOVE_X || drag_type == DRAG_MOVE_Y) { // Move the nodes if (m.is_valid()) { @@ -2014,7 +2035,15 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) { } else { previous_pos = _get_encompassing_rect_from_list(drag_selection).position; } + Point2 new_pos = snap_point(previous_pos + (drag_to - drag_from), SNAP_GRID | SNAP_GUIDES | SNAP_PIXEL | SNAP_NODE_PARENT | SNAP_NODE_ANCHORS | SNAP_OTHER_NODES, 0, NULL, drag_selection); + + if (drag_type == DRAG_MOVE_X) { + new_pos.y = previous_pos.y; + } else if (drag_type == DRAG_MOVE_Y) { + new_pos.x = previous_pos.x; + } + bool single_axis = m->get_shift(); if (single_axis) { if (ABS(new_pos.x - previous_pos.x) > ABS(new_pos.y - previous_pos.y)) { @@ -3235,10 +3264,39 @@ void CanvasItemEditor::_draw_selection() { } } - // Draw the rescale handles + // Draw the move handles bool is_ctrl = Input::get_singleton()->is_key_pressed(KEY_CONTROL); bool is_alt = Input::get_singleton()->is_key_pressed(KEY_ALT); - if ((is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y) { + if (tool == TOOL_MOVE && show_transformation_gizmos) { + if (_is_node_movable(canvas_item)) { + Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized(); + Transform2D simple_xform = viewport->get_transform() * unscaled_transform; + + Size2 move_factor = Size2(MOVE_HANDLE_DISTANCE, MOVE_HANDLE_DISTANCE); + viewport->draw_set_transform_matrix(simple_xform); + + Vector<Point2> points; + points.push_back(Vector2(move_factor.x * EDSCALE, 5 * EDSCALE)); + points.push_back(Vector2(move_factor.x * EDSCALE, -5 * EDSCALE)); + points.push_back(Vector2((move_factor.x + 10) * EDSCALE, 0)); + + viewport->draw_colored_polygon(points, get_color("axis_x_color", "Editor")); + viewport->draw_line(Point2(), Point2(move_factor.x * EDSCALE, 0), get_color("axis_x_color", "Editor"), Math::round(EDSCALE), true); + + points.clear(); + points.push_back(Vector2(5 * EDSCALE, move_factor.y * EDSCALE)); + points.push_back(Vector2(-5 * EDSCALE, move_factor.y * EDSCALE)); + points.push_back(Vector2(0, (move_factor.y + 10) * EDSCALE)); + + viewport->draw_colored_polygon(points, get_color("axis_y_color", "Editor")); + viewport->draw_line(Point2(), Point2(0, move_factor.y * EDSCALE), get_color("axis_y_color", "Editor"), Math::round(EDSCALE), true); + + viewport->draw_set_transform_matrix(viewport->get_transform()); + } + } + + // Draw the rescale handles + if (show_transformation_gizmos && ((is_alt && is_ctrl) || tool == TOOL_SCALE || drag_type == DRAG_SCALE_X || drag_type == DRAG_SCALE_Y)) { if (_is_node_movable(canvas_item)) { Transform2D unscaled_transform = (xform * canvas_item->get_transform().affine_inverse() * canvas_item->_edit_get_transform()).orthonormalized(); Transform2D simple_xform = viewport->get_transform() * unscaled_transform; @@ -3253,9 +3311,9 @@ void CanvasItemEditor::_draw_selection() { scale_factor.y += offset.x; } } else if (drag_type == DRAG_SCALE_Y) { - scale_factor.y -= offset.y; + scale_factor.y += offset.y; if (uniform) { - scale_factor.x -= offset.y; + scale_factor.x += offset.y; } } @@ -3264,9 +3322,9 @@ void CanvasItemEditor::_draw_selection() { viewport->draw_rect(x_handle_rect, get_color("axis_x_color", "Editor")); viewport->draw_line(Point2(), Point2(scale_factor.x * EDSCALE, 0), get_color("axis_x_color", "Editor"), Math::round(EDSCALE), true); - Rect2 y_handle_rect = Rect2(-5 * EDSCALE, -(scale_factor.y + 10) * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); + Rect2 y_handle_rect = Rect2(-5 * EDSCALE, scale_factor.y * EDSCALE, 10 * EDSCALE, 10 * EDSCALE); viewport->draw_rect(y_handle_rect, get_color("axis_y_color", "Editor")); - viewport->draw_line(Point2(), Point2(0, -scale_factor.y * EDSCALE), get_color("axis_y_color", "Editor"), Math::round(EDSCALE), true); + viewport->draw_line(Point2(), Point2(0, scale_factor.y * EDSCALE), get_color("axis_y_color", "Editor"), Math::round(EDSCALE), true); viewport->draw_set_transform_matrix(viewport->get_transform()); } @@ -4381,10 +4439,8 @@ void CanvasItemEditor::_update_override_camera_button(bool p_game_running) { } void CanvasItemEditor::_popup_callback(int p_op) { - last_option = MenuOption(p_op); switch (p_op) { - case SHOW_GRID: { show_grid = !show_grid; int idx = view_menu->get_popup()->get_item_index(SHOW_GRID); @@ -4409,6 +4465,12 @@ void CanvasItemEditor::_popup_callback(int p_op) { view_menu->get_popup()->set_item_checked(idx, show_edit_locks); viewport->update(); } break; + case SHOW_TRANSFORMATION_GIZMOS: { + show_transformation_gizmos = !show_transformation_gizmos; + int idx = view_menu->get_popup()->get_item_index(SHOW_TRANSFORMATION_GIZMOS); + view_menu->get_popup()->set_item_checked(idx, show_transformation_gizmos); + viewport->update(); + } break; case SNAP_USE_NODE_PARENT: { snap_node_parent = !snap_node_parent; int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT); @@ -5035,6 +5097,7 @@ Dictionary CanvasItemEditor::get_state() const { state["show_helpers"] = show_helpers; state["show_zoom_control"] = zoom_hb->is_visible(); state["show_edit_locks"] = show_edit_locks; + state["show_transformation_gizmos"] = show_transformation_gizmos; state["snap_rotation"] = snap_rotation; state["snap_scale"] = snap_scale; state["snap_relative"] = snap_relative; @@ -5173,6 +5236,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) { view_menu->get_popup()->set_item_checked(idx, show_edit_locks); } + if (state.has("show_transformation_gizmos")) { + show_transformation_gizmos = state["show_transformation_gizmos"]; + int idx = view_menu->get_popup()->get_item_index(SHOW_TRANSFORMATION_GIZMOS); + view_menu->get_popup()->set_item_checked(idx, show_transformation_gizmos); + } + if (state.has("show_zoom_control")) { // This one is not user-controllable, but instrumentable zoom_hb->set_visible(state["show_zoom_control"]); @@ -5265,6 +5334,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { show_helpers = false; show_rulers = true; show_guides = true; + show_transformation_gizmos = true; show_edit_locks = true; zoom = 1.0 / MAX(1, EDSCALE); view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); @@ -5596,6 +5666,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_origin", TTR("Show Origin")), SHOW_ORIGIN); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_viewport", TTR("Show Viewport")), SHOW_VIEWPORT); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_edit_locks", TTR("Show Group And Lock Icons")), SHOW_EDIT_LOCKS); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_transformation_gizmos", TTR("Show Transformation Gizmos")), SHOW_TRANSFORMATION_GIZMOS); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 3291d6b9bf..37bc47ecd4 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -119,6 +119,7 @@ private: SHOW_ORIGIN, SHOW_VIEWPORT, SHOW_EDIT_LOCKS, + SHOW_TRANSFORMATION_GIZMOS, LOCK_SELECTED, UNLOCK_SELECTED, GROUP_SELECTED, @@ -189,7 +190,6 @@ private: SKELETON_SHOW_BONES, SKELETON_SET_IK_CHAIN, SKELETON_CLEAR_IK_CHAIN - }; enum DragType { @@ -209,6 +209,8 @@ private: DRAG_ANCHOR_BOTTOM_LEFT, DRAG_ANCHOR_ALL, DRAG_MOVE, + DRAG_MOVE_X, + DRAG_MOVE_Y, DRAG_SCALE_X, DRAG_SCALE_Y, DRAG_SCALE_BOTH, @@ -248,6 +250,8 @@ private: bool show_viewport; bool show_helpers; bool show_edit_locks; + bool show_transformation_gizmos; + float zoom; Point2 view_offset; Point2 previous_update_view_offset; diff --git a/editor/plugins/collision_shape_2d_editor_plugin.cpp b/editor/plugins/collision_shape_2d_editor_plugin.cpp index be9e5b0e3a..179ebca562 100644 --- a/editor/plugins/collision_shape_2d_editor_plugin.cpp +++ b/editor/plugins/collision_shape_2d_editor_plugin.cpp @@ -448,8 +448,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla float radius = shape->get_radius(); float height = shape->get_height() / 2; - handles.write[0] = Point2(radius, -height); - handles.write[1] = Point2(0, -(height + radius)); + handles.write[0] = Point2(radius, height); + handles.write[1] = Point2(0, height + radius); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); @@ -502,8 +502,8 @@ void CollisionShape2DEditor::forward_canvas_draw_over_viewport(Control *p_overla handles.resize(3); Vector2 ext = shape->get_extents(); handles.write[0] = Point2(ext.x, 0); - handles.write[1] = Point2(0, -ext.y); - handles.write[2] = Point2(ext.x, -ext.y); + handles.write[1] = Point2(0, ext.y); + handles.write[2] = Point2(ext.x, ext.y); p_overlay->draw_texture(h, gt.xform(handles[0]) - size); p_overlay->draw_texture(h, gt.xform(handles[1]) - size); diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index 8b5fe7d2c5..9101c64eab 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -103,8 +103,10 @@ void SkeletonEditor::create_physical_skeleton() { PhysicalBone *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_id, const Vector<BoneInfo> &bones_infos) { - real_t half_height(skeleton->get_bone_rest(bone_child_id).origin.length() * 0.5); - real_t radius(half_height * 0.2); + const Transform child_rest = skeleton->get_bone_rest(bone_child_id); + + const real_t half_height(child_rest.origin.length() * 0.5); + const real_t radius(half_height * 0.2); CapsuleShape *bone_shape_capsule = memnew(CapsuleShape); bone_shape_capsule->set_height((half_height - radius) * 2); @@ -114,7 +116,8 @@ PhysicalBone *SkeletonEditor::create_physical_bone(int bone_id, int bone_child_i bone_shape->set_shape(bone_shape_capsule); Transform body_transform; - body_transform.origin = Vector3(0, 0, -half_height); + body_transform.set_look_at(Vector3(0, 0, 0), child_rest.origin, Vector3(0, 1, 0)); + body_transform.origin = body_transform.basis.xform(Vector3(0, 0, -half_height)); Transform joint_transform; joint_transform.origin = Vector3(0, 0, half_height); diff --git a/editor/plugins/skeleton_ik_editor_plugin.cpp b/editor/plugins/skeleton_ik_editor_plugin.cpp index 43dc13b270..eb6ad9498d 100644 --- a/editor/plugins/skeleton_ik_editor_plugin.cpp +++ b/editor/plugins/skeleton_ik_editor_plugin.cpp @@ -41,21 +41,12 @@ void SkeletonIKEditorPlugin::_play() { return; if (play_btn->is_pressed()) { - - initial_bone_poses.resize(skeleton_ik->get_parent_skeleton()->get_bone_count()); - for (int i = 0; i < skeleton_ik->get_parent_skeleton()->get_bone_count(); ++i) { - initial_bone_poses.write[i] = skeleton_ik->get_parent_skeleton()->get_bone_pose(i); - } - skeleton_ik->start(); } else { skeleton_ik->stop(); - if (initial_bone_poses.size() != skeleton_ik->get_parent_skeleton()->get_bone_count()) - return; - for (int i = 0; i < skeleton_ik->get_parent_skeleton()->get_bone_count(); ++i) { - skeleton_ik->get_parent_skeleton()->set_bone_pose(i, initial_bone_poses[i]); + skeleton_ik->get_parent_skeleton()->set_bone_global_pose_override(i, Transform(), 0); } } } diff --git a/editor/plugins/skeleton_ik_editor_plugin.h b/editor/plugins/skeleton_ik_editor_plugin.h index 06c07031f6..814eb8ff5b 100644 --- a/editor/plugins/skeleton_ik_editor_plugin.h +++ b/editor/plugins/skeleton_ik_editor_plugin.h @@ -44,7 +44,6 @@ class SkeletonIKEditorPlugin : public EditorPlugin { Button *play_btn; EditorNode *editor; - Vector<Transform> initial_bone_poses; void _play(); diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index f889228f87..0c3e29028c 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -2026,13 +2026,13 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { toolbar->add_child(bucket_fill_button); picker_button = memnew(ToolButton); - picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_CONTROL)); + picker_button->set_shortcut(ED_SHORTCUT("tile_map_editor/pick_tile", TTR("Pick Tile"), KEY_I)); picker_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_PICKING)); picker_button->set_toggle_mode(true); toolbar->add_child(picker_button); select_button = memnew(ToolButton); - select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_MASK_CMD + KEY_B)); + select_button->set_shortcut(ED_SHORTCUT("tile_map_editor/select", TTR("Select"), KEY_M)); select_button->connect("pressed", this, "_button_tool_select", make_binds(TOOL_SELECTING)); select_button->set_toggle_mode(true); toolbar->add_child(select_button); diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index f4c0ffa6eb..a7988279c0 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -168,6 +168,7 @@ void SoftBodyBullet::set_node_position(int p_node_index, const Vector3 &p_global void SoftBodyBullet::set_node_position(int p_node_index, const btVector3 &p_global_position) { if (bt_soft_body) { + bt_soft_body->m_nodes[p_node_index].m_q = bt_soft_body->m_nodes[p_node_index].m_x; bt_soft_body->m_nodes[p_node_index].m_x = p_global_position; } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index 0462ef1125..1d1a49945f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -318,9 +318,9 @@ namespace Godot return res; } - public int ToAbgr32() + public uint ToAbgr32() { - int c = (byte)Math.Round(a * 255); + uint c = (byte)Math.Round(a * 255); c <<= 8; c |= (byte)Math.Round(b * 255); c <<= 8; @@ -331,9 +331,9 @@ namespace Godot return c; } - public long ToAbgr64() + public ulong ToAbgr64() { - long c = (ushort)Math.Round(a * 65535); + ulong c = (ushort)Math.Round(a * 65535); c <<= 16; c |= (ushort)Math.Round(b * 65535); c <<= 16; @@ -344,9 +344,9 @@ namespace Godot return c; } - public int ToArgb32() + public uint ToArgb32() { - int c = (byte)Math.Round(a * 255); + uint c = (byte)Math.Round(a * 255); c <<= 8; c |= (byte)Math.Round(r * 255); c <<= 8; @@ -357,9 +357,9 @@ namespace Godot return c; } - public long ToArgb64() + public ulong ToArgb64() { - long c = (ushort)Math.Round(a * 65535); + ulong c = (ushort)Math.Round(a * 65535); c <<= 16; c |= (ushort)Math.Round(r * 65535); c <<= 16; @@ -370,9 +370,9 @@ namespace Godot return c; } - public int ToRgba32() + public uint ToRgba32() { - int c = (byte)Math.Round(r * 255); + uint c = (byte)Math.Round(r * 255); c <<= 8; c |= (byte)Math.Round(g * 255); c <<= 8; @@ -383,9 +383,9 @@ namespace Godot return c; } - public long ToRgba64() + public ulong ToRgba64() { - long c = (ushort)Math.Round(r * 65535); + ulong c = (ushort)Math.Round(r * 65535); c <<= 16; c |= (ushort)Math.Round(g * 65535); c <<= 16; @@ -419,7 +419,7 @@ namespace Godot this.a = a; } - public Color(int rgba) + public Color(uint rgba) { a = (rgba & 0xFF) / 255.0f; rgba >>= 8; @@ -430,7 +430,7 @@ namespace Godot r = (rgba & 0xFF) / 255.0f; } - public Color(long rgba) + public Color(ulong rgba) { a = (rgba & 0xFFFF) / 65535.0f; rgba >>= 16; diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 36cafeec73..dc49ed72d0 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -1935,8 +1935,11 @@ PropertyInfo VisualScriptClassConstant::get_input_value_port_info(int p_idx) con } PropertyInfo VisualScriptClassConstant::get_output_value_port_info(int p_idx) const { - - return PropertyInfo(Variant::INT, String(base_type) + "." + String(name)); + if (name == "") { + return PropertyInfo(Variant::INT, String(base_type)); + } else { + return PropertyInfo(Variant::INT, String(base_type) + "." + String(name)); + } } String VisualScriptClassConstant::get_caption() const { @@ -1958,6 +1961,22 @@ StringName VisualScriptClassConstant::get_class_constant() { void VisualScriptClassConstant::set_base_type(const StringName &p_which) { base_type = p_which; + List<String> constants; + ClassDB::get_integer_constant_list(base_type, &constants, true); + if (constants.size() > 0) { + bool found_name = false; + for (List<String>::Element *E = constants.front(); E; E = E->next()) { + if (E->get() == name) { + found_name = true; + break; + } + } + if (!found_name) { + name = constants[0]; + } + } else { + name = ""; + } _change_notify(); ports_changed_notify(); } diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 44c5b5d6b4..e5d9bdc60c 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -507,9 +507,8 @@ void OS_Android::process_double_tap(Point2 p_pos) { ev.instance(); ev->set_position(p_pos); ev->set_global_position(p_pos); - ev->set_pressed(true); + ev->set_pressed(false); ev->set_doubleclick(true); - ev->set_button_index(1); input->parse_input_event(ev); } diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index caeae90238..a1a221b5bb 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1562,6 +1562,24 @@ void PhysicalBone::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); } +void PhysicalBone::reset_physics_simulation_state() { + if (simulate_physics) { + _start_physics_simulation(); + } else { + _stop_physics_simulation(); + } +} + +void PhysicalBone::reset_to_rest_position() { + if (parent_skeleton) { + if (-1 == bone_id) { + set_global_transform(parent_skeleton->get_global_transform() * body_offset); + } else { + set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); + } + } +} + bool PhysicalBone::PinJointData::_set(const StringName &p_name, const Variant &p_value, RID j) { if (JointData::_set(p_name, p_value, j)) { return true; @@ -2167,7 +2185,7 @@ void PhysicalBone::_notification(int p_what) { parent_skeleton = find_skeleton_parent(get_parent()); update_bone_id(); reset_to_rest_position(); - _reset_physics_simulation_state(); + reset_physics_simulation_state(); if (!joint.is_valid() && joint_data) { _reload_joint(); } @@ -2238,8 +2256,6 @@ void PhysicalBone::_bind_methods() { ClassDB::bind_method(D_METHOD("set_body_offset", "offset"), &PhysicalBone::set_body_offset); ClassDB::bind_method(D_METHOD("get_body_offset"), &PhysicalBone::get_body_offset); - ClassDB::bind_method(D_METHOD("is_static_body"), &PhysicalBone::is_static_body); - ClassDB::bind_method(D_METHOD("get_simulate_physics"), &PhysicalBone::get_simulate_physics); ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics); @@ -2508,26 +2524,13 @@ const Transform &PhysicalBone::get_joint_offset() const { return joint_offset; } -void PhysicalBone::set_static_body(bool p_static) { - - static_body = p_static; - - set_as_toplevel(!static_body); - - _reset_physics_simulation_state(); -} - -bool PhysicalBone::is_static_body() { - return static_body; -} - void PhysicalBone::set_simulate_physics(bool p_simulate) { if (simulate_physics == p_simulate) { return; } simulate_physics = p_simulate; - _reset_physics_simulation_state(); + reset_physics_simulation_state(); } bool PhysicalBone::get_simulate_physics() { @@ -2535,7 +2538,7 @@ bool PhysicalBone::get_simulate_physics() { } bool PhysicalBone::is_simulating_physics() { - return _internal_simulate_physics && !_internal_static_body; + return _internal_simulate_physics; } void PhysicalBone::set_bone_name(const String &p_name) { @@ -2618,8 +2621,6 @@ PhysicalBone::PhysicalBone() : #endif joint_data(NULL), parent_skeleton(NULL), - static_body(false), - _internal_static_body(false), simulate_physics(false), _internal_simulate_physics(false), bone_id(-1), @@ -2629,8 +2630,7 @@ PhysicalBone::PhysicalBone() : friction(1), gravity_scale(1) { - set_static_body(static_body); - _reset_physics_simulation_state(); + reset_physics_simulation_state(); } PhysicalBone::~PhysicalBone() { @@ -2657,8 +2657,7 @@ void PhysicalBone::update_bone_id() { parent_skeleton->bind_physical_bone_to_bone(bone_id, this); _fix_joint_offset(); - _internal_static_body = !static_body; // Force staticness reset - _reset_staticness_state(); + reset_physics_simulation_state(); } } @@ -2680,49 +2679,6 @@ void PhysicalBone::update_offset() { #endif } -void PhysicalBone::reset_to_rest_position() { - if (parent_skeleton) { - if (-1 == bone_id) { - set_global_transform(parent_skeleton->get_global_transform() * body_offset); - } else { - set_global_transform(parent_skeleton->get_global_transform() * parent_skeleton->get_bone_global_pose(bone_id) * body_offset); - } - } -} - -void PhysicalBone::_reset_physics_simulation_state() { - if (simulate_physics && !static_body) { - _start_physics_simulation(); - } else { - _stop_physics_simulation(); - } - - _reset_staticness_state(); -} - -void PhysicalBone::_reset_staticness_state() { - - if (parent_skeleton && -1 != bone_id) { - if (static_body && simulate_physics) { // With this check I'm sure the position of this body is updated only when it's necessary - - if (_internal_static_body) { - return; - } - - parent_skeleton->bind_child_node_to_bone(bone_id, this); - _internal_static_body = true; - } else { - - if (!_internal_static_body) { - return; - } - - parent_skeleton->unbind_child_node_from_bone(bone_id, this); - _internal_static_body = false; - } - } -} - void PhysicalBone::_start_physics_simulation() { if (_internal_simulate_physics || !parent_skeleton) { return; @@ -2732,17 +2688,27 @@ void PhysicalBone::_start_physics_simulation() { PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + set_as_toplevel(true); _internal_simulate_physics = true; } void PhysicalBone::_stop_physics_simulation() { - if (!_internal_simulate_physics || !parent_skeleton) { + if (!parent_skeleton) { return; } - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); - parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); - _internal_simulate_physics = false; + if (parent_skeleton->get_animate_physical_bones()) { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + } else { + PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); + PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); + PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); + } + if (_internal_simulate_physics) { + PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); + set_as_toplevel(false); + _internal_simulate_physics = false; + } } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 05bcbe22f0..6a1e803eaf 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -562,8 +562,6 @@ private: Skeleton *parent_skeleton; Transform body_offset; Transform body_offset_inverse; - bool static_body; - bool _internal_static_body; bool simulate_physics; bool _internal_simulate_physics; int bone_id; @@ -613,9 +611,6 @@ public: void set_body_offset(const Transform &p_offset); const Transform &get_body_offset() const; - void set_static_body(bool p_static); - bool is_static_body(); - void set_simulate_physics(bool p_simulate); bool get_simulate_physics(); bool is_simulating_physics(); @@ -641,16 +636,15 @@ public: void apply_central_impulse(const Vector3 &p_impulse); void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); + void reset_physics_simulation_state(); + void reset_to_rest_position(); + PhysicalBone(); ~PhysicalBone(); private: void update_bone_id(); void update_offset(); - void reset_to_rest_position(); - - void _reset_physics_simulation_state(); - void _reset_staticness_state(); void _start_physics_simulation(); void _stop_physics_simulation(); diff --git a/scene/3d/skeleton.cpp b/scene/3d/skeleton.cpp index 17e67c47d1..4089e0c23b 100644 --- a/scene/3d/skeleton.cpp +++ b/scene/3d/skeleton.cpp @@ -32,6 +32,7 @@ #include "core/message_queue.h" +#include "core/engine.h" #include "core/project_settings.h" #include "scene/3d/physics_body.h" #include "scene/resources/surface_tool.h" @@ -332,6 +333,27 @@ void Skeleton::_notification(int p_what) { dirty = false; } break; + +#ifndef _3D_DISABLED + case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { + // This is active only if the skeleton animates the physical bones + // and the state of the bone is not active. + if (animate_physical_bones) { + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + if (bones[i].physical_bone->is_simulating_physics() == false) { + bones[i].physical_bone->reset_to_rest_position(); + } + } + } + } + } break; + case NOTIFICATION_READY: { + if (Engine::get_singleton()->is_editor_hint()) { + set_physics_process_internal(true); + } + } break; +#endif } } @@ -584,6 +606,27 @@ void Skeleton::localize_rests() { #ifndef _3D_DISABLED +void Skeleton::set_animate_physical_bones(bool p_animate) { + animate_physical_bones = p_animate; + + if (Engine::get_singleton()->is_editor_hint() == false) { + bool sim = false; + for (int i = 0; i < bones.size(); i += 1) { + if (bones[i].physical_bone) { + bones[i].physical_bone->reset_physics_simulation_state(); + if (bones[i].physical_bone->is_simulating_physics()) { + sim = true; + } + } + } + set_physics_process_internal(sim == false && p_animate); + } +} + +bool Skeleton::get_animate_physical_bones() const { + return animate_physical_bones; +} + void Skeleton::bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone) { ERR_FAIL_INDEX(p_bone, bones.size()); ERR_FAIL_COND(bones[p_bone].physical_bone); @@ -653,12 +696,14 @@ void _pb_stop_simulation(Node *p_node) { PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); if (pb) { pb->set_simulate_physics(false); - pb->set_static_body(false); } } void Skeleton::physical_bones_stop_simulation() { _pb_stop_simulation(this); + if (Engine::get_singleton()->is_editor_hint() == false && animate_physical_bones) { + set_physics_process_internal(true); + } } void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector<int> &p_sim_bones) { @@ -669,24 +714,17 @@ void _pb_start_simulation(const Skeleton *p_skeleton, Node *p_node, const Vector PhysicalBone *pb = Object::cast_to<PhysicalBone>(p_node); if (pb) { - bool sim = false; for (int i = p_sim_bones.size() - 1; 0 <= i; --i) { if (p_sim_bones[i] == pb->get_bone_id() || p_skeleton->is_bone_parent_of(pb->get_bone_id(), p_sim_bones[i])) { - sim = true; + pb->set_simulate_physics(true); break; } } - - pb->set_simulate_physics(true); - if (sim) { - pb->set_static_body(false); - } else { - pb->set_static_body(true); - } } } void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { + set_physics_process_internal(false); Vector<int> sim_bones; if (p_bones.size() <= 0) { @@ -836,11 +874,15 @@ void Skeleton::_bind_methods() { #ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("set_animate_physical_bones"), &Skeleton::set_animate_physical_bones); + ClassDB::bind_method(D_METHOD("get_animate_physical_bones"), &Skeleton::get_animate_physical_bones); + ClassDB::bind_method(D_METHOD("physical_bones_stop_simulation"), &Skeleton::physical_bones_stop_simulation); ClassDB::bind_method(D_METHOD("physical_bones_start_simulation", "bones"), &Skeleton::physical_bones_start_simulation_on, DEFVAL(Array())); ClassDB::bind_method(D_METHOD("physical_bones_add_collision_exception", "exception"), &Skeleton::physical_bones_add_collision_exception); ClassDB::bind_method(D_METHOD("physical_bones_remove_collision_exception", "exception"), &Skeleton::physical_bones_remove_collision_exception); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "animate_physical_bones"), "set_animate_physical_bones", "get_animate_physical_bones"); #endif // _3D_DISABLED BIND_CONSTANT(NOTIFICATION_UPDATE_SKELETON); @@ -848,6 +890,7 @@ void Skeleton::_bind_methods() { Skeleton::Skeleton() { + animate_physical_bones = true; dirty = false; process_order_dirty = true; } diff --git a/scene/3d/skeleton.h b/scene/3d/skeleton.h index 056f70e22b..9599510850 100644 --- a/scene/3d/skeleton.h +++ b/scene/3d/skeleton.h @@ -115,6 +115,7 @@ private: } }; + bool animate_physical_bones; Vector<Bone> bones; Vector<int> process_order; bool process_order_dirty; @@ -199,6 +200,9 @@ public: #ifndef _3D_DISABLED // Physical bone API + void set_animate_physical_bones(bool p_animate); + bool get_animate_physical_bones() const; + void bind_physical_bone_to_bone(int p_bone, PhysicalBone *p_physical_bone); void unbind_physical_bone_from_bone(int p_bone); diff --git a/scene/3d/soft_body.cpp b/scene/3d/soft_body.cpp index ef13985bf4..435bef7247 100644 --- a/scene/3d/soft_body.cpp +++ b/scene/3d/soft_body.cpp @@ -247,7 +247,7 @@ bool SoftBody::_get_property_pinned_points(int p_item, const String &p_what, Var } void SoftBody::_changed_callback(Object *p_changed, const char *p_prop) { - update_physics_server(); + prepare_physics_server(); _reset_points_offsets(); #ifdef TOOLS_ENABLED if (p_changed == this) { @@ -267,7 +267,7 @@ void SoftBody::_notification(int p_what) { RID space = get_world()->get_space(); PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space); - update_physics_server(); + prepare_physics_server(); } break; case NOTIFICATION_READY: { if (!parent_collision_ignore.is_empty()) @@ -290,21 +290,6 @@ void SoftBody::_notification(int p_what) { set_notify_transform(true); } break; - case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - - if (!simulation_started) - return; - - _update_cache_pin_points_datas(); - // Submit bone attachment - const int pinned_points_indices_size = pinned_points.size(); - PoolVector<PinnedPoint>::Read r = pinned_points.read(); - for (int i = 0; i < pinned_points_indices_size; ++i) { - if (r[i].spatial_attachment) { - PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); - } - } - } break; case NOTIFICATION_VISIBILITY_CHANGED: { _update_pickable(); @@ -421,6 +406,21 @@ String SoftBody::get_configuration_warning() const { return warning; } +void SoftBody::_update_physics_server() { + if (!simulation_started) + return; + + _update_cache_pin_points_datas(); + // Submit bone attachment + const int pinned_points_indices_size = pinned_points.size(); + PoolVector<PinnedPoint>::Read r = pinned_points.read(); + for (int i = 0; i < pinned_points_indices_size; ++i) { + if (r[i].spatial_attachment) { + PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); + } + } +} + void SoftBody::_draw_soft_mesh() { if (get_mesh().is_null()) return; @@ -435,6 +435,8 @@ void SoftBody::_draw_soft_mesh() { call_deferred("set_transform", Transform()); } + _update_physics_server(); + visual_server_handler.open(); PhysicsServer::get_singleton()->soft_body_update_visual_server(physics_rid, &visual_server_handler); visual_server_handler.close(); @@ -442,7 +444,7 @@ void SoftBody::_draw_soft_mesh() { visual_server_handler.commit_changes(); } -void SoftBody::update_physics_server() { +void SoftBody::prepare_physics_server() { if (Engine::get_singleton()->is_editor_hint()) { @@ -706,8 +708,6 @@ SoftBody::SoftBody() : ray_pickable(true) { PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); - //set_notify_transform(true); - set_physics_process_internal(true); } SoftBody::~SoftBody() { diff --git a/scene/3d/soft_body.h b/scene/3d/soft_body.h index 629c2e42a5..800db12594 100644 --- a/scene/3d/soft_body.h +++ b/scene/3d/soft_body.h @@ -116,10 +116,11 @@ protected: virtual String get_configuration_warning() const; protected: + void _update_physics_server(); void _draw_soft_mesh(); public: - void update_physics_server(); + void prepare_physics_server(); void become_mesh_owner(); void set_collision_mask(uint32_t p_mask); diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp index 46028a9ce2..518c243dd0 100644 --- a/scene/animation/skeleton_ik.cpp +++ b/scene/animation/skeleton_ik.cpp @@ -329,17 +329,6 @@ void FabrikInverseKinematic::solve(Task *p_task, real_t blending_delta, bool ove } } -void FabrikInverseKinematic::reset(Task *p_task) { - ChainItem *ci(&p_task->chain.chain_root); - while (ci) { - p_task->skeleton->set_bone_global_pose_override(ci->bone, Transform(), 0); - if (!ci->children.empty()) - ci = &ci->children.write[0]; - else - ci = NULL; - } -} - void SkeletonIK::_validate_property(PropertyInfo &property) const { if (property.name == "root_bone" || property.name == "tip_bone") { @@ -542,8 +531,6 @@ void SkeletonIK::start(bool p_one_time) { void SkeletonIK::stop() { set_process_internal(false); - if (task) - FabrikInverseKinematic::reset(task); } Transform SkeletonIK::_get_target_transform() { diff --git a/scene/animation/skeleton_ik.h b/scene/animation/skeleton_ik.h index 8fc8a58b99..9ae010dc4e 100644 --- a/scene/animation/skeleton_ik.h +++ b/scene/animation/skeleton_ik.h @@ -139,7 +139,6 @@ public: static void set_goal(Task *p_task, const Transform &p_goal); static void make_goal(Task *p_task, const Transform &p_inverse_transf, real_t blending_delta); static void solve(Task *p_task, real_t blending_delta, bool override_tip_basis, bool p_use_magnet, const Vector3 &p_magnet_position); - static void reset(Task *p_task); }; class SkeletonIK : public Node { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 7cc47d351e..2504989d2c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -184,6 +184,12 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { case KEY_H: { remap_key = KEY_BACKSPACE; } break; + case KEY_A: { + remap_key = KEY_HOME; + } break; + case KEY_E: { + remap_key = KEY_END; + } break; } if (remap_key != KEY_UNKNOWN) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index af5d0e2f45..b19e1d8362 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -204,6 +204,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int line_ascent = cfont->get_ascent(); int line_descent = cfont->get_descent(); + int backtrack = 0; // for dynamic hidden content. + int nonblank_line_count = 0; //number of nonblank lines as counted during PROCESS_DRAW Variant meta; @@ -214,6 +216,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & { \ if (p_mode != PROCESS_CACHE) { \ line++; \ + backtrack = 0; \ if (!line_is_blank) { \ nonblank_line_count++; \ } \ @@ -263,7 +266,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & l.maximum_width = MAX(l.maximum_width, MIN(p_width, wofs + m_width)); \ l.minimum_width = MAX(l.minimum_width, m_width); \ } \ - if (wofs + m_width > p_width) { \ + if (wofs - backtrack + m_width > p_width) { \ line_wrapped = true; \ if (p_mode == PROCESS_CACHE) { \ if (spaces > 0) \ @@ -390,6 +393,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & int fw = 0; lh = 0; + if (p_mode != PROCESS_CACHE) { lh = line < l.height_caches.size() ? l.height_caches[line] : 1; line_ascent = line < l.ascent_caches.size() ? l.ascent_caches[line] : 1; @@ -432,13 +436,12 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & { - int ofs = 0; + int ofs = 0 - backtrack; for (int i = 0; i < end; i++) { int pofs = wofs + ofs; if (p_mode == PROCESS_POINTER && r_click_char && p_click_pos.y >= p_ofs.y + y && p_click_pos.y <= p_ofs.y + y + lh) { - //int o = (wofs+w)-p_click_pos.x; int cw = font->get_char_size(c[i], c[i + 1]).x; @@ -481,7 +484,10 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & bool visible = visible_characters < 0 || ((p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - line_descent - line_ascent, line_ascent + line_descent)) && faded_visibility > 0.0f); + const bool previously_visible = visible; + for (int j = 0; j < fx_stack.size(); j++) { + ItemFX *item_fx = fx_stack[j]; if (item_fx->type == ITEM_CUSTOMFX && custom_fx_ok) { @@ -575,6 +581,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & } else { cw = drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent) + fx_offset, fx_char, c[i + 1], fx_color); } + } else if (previously_visible) { + backtrack += font->get_char_size(fx_char, c[i + 1]).x; } p_char_count++; @@ -648,6 +656,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & case ITEM_NEWLINE: { lh = 0; + if (p_mode != PROCESS_CACHE) { lh = line < l.height_caches.size() ? l.height_caches[line] : 1; line_is_blank = true; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 964f376dbd..790e1d5f4f 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1121,7 +1121,7 @@ void Tree::draw_item_rect(const TreeItem::Cell &p_cell, const Rect2i &p_rect, co } rect.position.y += Math::floor((rect.size.y - font->get_height()) / 2.0) + font->get_ascent(); - font->draw(ci, rect.position, text, p_color, rect.size.x); + font->draw(ci, rect.position, text, p_color, MAX(0, rect.size.width)); } int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item) { @@ -3630,6 +3630,17 @@ TreeItem *Tree::search_item_text(const String &p_find, int *r_col, bool p_select return _search_item_text(from->get_next_visible(true), p_find, r_col, p_selectable); } +TreeItem *Tree::get_item_with_text(const String &p_find) const { + for (TreeItem *current = root; current; current = current->get_next_visible()) { + for (int i = 0; i < columns.size(); i++) { + if (current->get_text(i) == p_find) { + return current; + } + } + } + return NULL; +} + void Tree::_do_incr_search(const String &p_add) { uint64_t time = OS::get_singleton()->get_ticks_usec() / 1000; // convert to msec diff --git a/scene/gui/tree.h b/scene/gui/tree.h index d87de6e773..f3c88eb5ac 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -577,7 +577,10 @@ public: Rect2 get_item_rect(TreeItem *p_item, int p_column = -1) const; bool edit_selected(); + // First item that starts with the text, from the current focused item down and wraps around. TreeItem *search_item_text(const String &p_find, int *r_col = NULL, bool p_selectable = false); + // First item that matches the whole text, from the first item down. + TreeItem *get_item_with_text(const String &p_find) const; Point2 get_scroll() const; void scroll_to_item(TreeItem *p_item); diff --git a/scene/resources/line_shape_2d.cpp b/scene/resources/line_shape_2d.cpp index 7f39467403..84da8125ea 100644 --- a/scene/resources/line_shape_2d.cpp +++ b/scene/resources/line_shape_2d.cpp @@ -115,7 +115,7 @@ void LineShape2D::_bind_methods() { LineShape2D::LineShape2D() : Shape2D(Physics2DServer::get_singleton()->line_shape_create()) { - normal = Vector2(0, -1); + normal = Vector2(0, 1); d = 0; _update_shape(); } diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 0599920303..8f68cc5286 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -518,7 +518,6 @@ void Mesh::_bind_methods() { BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_BASE); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_VERTEX); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 412b5c259c..baeb88400e 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -316,14 +316,17 @@ void ParticlesMaterial::_update_shader() { if (flags[FLAG_DISABLE_Z]) { - code += " float angle1_rad = atan(direction.y, direction.x) + rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " angle1_rad += direction.x != 0.0 ? atan(direction.y, direction.x) : sign(direction.y) * (pi / 2.0);\n"; code += " vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);\n"; code += " VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D - code += " float angle1_rad = atan(direction.x, direction.z) + rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; - code += " float angle2_rad = atan(direction.y, abs(direction.z)) + rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;\n"; + code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; + code += " angle1_rad += direction.z != 0.0 ? atan(direction.x, direction.z) : sign(direction.x) * (pi / 2.0);\n"; + code += " angle2_rad += direction.z != 0.0 ? atan(direction.y, abs(direction.z)) : (direction.x != 0.0 ? atan(direction.y, abs(direction.x)) : sign(direction.y) * (pi / 2.0));\n"; code += " vec3 direction_xz = vec3(sin(angle1_rad), 0.0, cos(angle1_rad));\n"; code += " vec3 direction_yz = vec3(0.0, sin(angle2_rad), cos(angle2_rad));\n"; code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; diff --git a/thirdparty/README.md b/thirdparty/README.md index 9b6f670972..7c3378dec3 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -281,6 +281,7 @@ Files extracted from upstream source: - All `*.c` and `*.h` files from `miniupnpc` to `thirdparty/miniupnpc/miniupnpc` - Remove `test*`, `minihttptestserver.c` and `wingenminiupnpcstrings.c` +The patch `windows_fix.diff` is applied to `minissdpc.c` to fix an upstream issue. The only modified file is miniupnpcstrings.h, which was created for Godot (it is usually autogenerated by cmake). diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c index 29f8110155..ea9af02e1f 100644 --- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c +++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c @@ -683,11 +683,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], #endif } else { struct in_addr mc_if; -#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) - InetPtonA(AF_INET, multicastif, &mc_if); -#else mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ -#endif if(mc_if.s_addr != INADDR_NONE) { ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; diff --git a/thirdparty/miniupnpc/windows_fix.diff b/thirdparty/miniupnpc/windows_fix.diff new file mode 100644 index 0000000000..460b596888 --- /dev/null +++ b/thirdparty/miniupnpc/windows_fix.diff @@ -0,0 +1,16 @@ +diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c +index 29f8110155..ea9af02e1f 100644 +--- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c ++++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c +@@ -683,11 +683,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], + #endif + } else { + struct in_addr mc_if; +-#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) +- InetPtonA(AF_INET, multicastif, &mc_if); +-#else + mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ +-#endif + if(mc_if.s_addr != INADDR_NONE) + { + ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; |