summaryrefslogtreecommitdiff
path: root/editor/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'editor/plugins')
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp7
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp14
-rw-r--r--editor/plugins/asset_library_editor_plugin.h1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp442
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h32
-rw-r--r--editor/plugins/navigation_mesh_generator.cpp34
-rw-r--r--editor/plugins/path_editor_plugin.cpp11
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp510
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h31
-rw-r--r--editor/plugins/script_text_editor.cpp6
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp2
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp26
-rw-r--r--editor/plugins/theme_editor_plugin.cpp56
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp15
-rw-r--r--editor/plugins/tile_map_editor_plugin.h19
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp7
16 files changed, 863 insertions, 350 deletions
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index 220003eb73..b387972558 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -459,6 +459,12 @@ void AnimationPlayerEditor::_animation_remove_confirmed() {
Ref<Animation> anim = player->get_animation(current);
undo_redo->create_action(TTR("Remove Animation"));
+ if (player->get_autoplay() == current) {
+ undo_redo->add_do_method(player, "set_autoplay", "");
+ undo_redo->add_undo_method(player, "set_autoplay", current);
+ // Avoid having the autoplay icon linger around if there is only one animation in the player
+ undo_redo->add_do_method(this, "_animation_player_changed", player);
+ }
undo_redo->add_do_method(player, "remove_animation", current);
undo_redo->add_undo_method(player, "add_animation", current, anim);
undo_redo->add_do_method(this, "_animation_player_changed", player);
@@ -822,6 +828,7 @@ void AnimationPlayerEditor::_update_player() {
save_anim->set_disabled(animlist.size() == 0);
tool_anim->set_disabled(player == NULL);
onion_skinning->set_disabled(player == NULL);
+ pin->set_disabled(player == NULL);
int active_idx = -1;
for (List<StringName>::Element *E = animlist.front(); E; E = E->next()) {
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 23cdde299c..05833704d1 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -639,7 +639,7 @@ const char *EditorAssetLibrary::support_key[SUPPORT_MAX] = {
void EditorAssetLibrary::_select_author(int p_id) {
- //opemn author window
+ // Open author window
}
void EditorAssetLibrary::_select_category(int p_id) {
@@ -659,16 +659,6 @@ void EditorAssetLibrary::_select_category(int p_id) {
void EditorAssetLibrary::_select_asset(int p_id) {
_api_request("asset/" + itos(p_id), REQUESTING_ASSET);
-
- /*
- if (description) {
- memdelete(description);
- }
-
-
- description = memnew( EditorAssetLibraryItemDescription );
- add_child(description);
- description->popup_centered_minsize();*/
}
void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByteArray &p_data, int p_queue_id) {
@@ -774,7 +764,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons
_image_update(p_code == HTTPClient::RESPONSE_NOT_MODIFIED, true, p_data, p_queue_id);
} else {
- WARN_PRINTS("Error getting PNG file for asset id " + itos(image_queue[p_queue_id].asset_id));
+ WARN_PRINTS("Error getting PNG file from URL: " + image_queue[p_queue_id].image_url);
Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target);
if (obj) {
obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("ErrorSign", "EditorIcons"));
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 89b79d7cfb..69a65dd3dc 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -241,7 +241,6 @@ class EditorAssetLibrary : public PanelContainer {
bool active;
int queue_id;
- int asset_id;
ImageType image_type;
int image_index;
String image_url;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index cd8723930c..93aeca6632 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -44,6 +44,7 @@
#include "scene/2d/particles_2d.h"
#include "scene/2d/polygon_2d.h"
#include "scene/2d/screen_button.h"
+#include "scene/2d/skeleton_2d.h"
#include "scene/2d/sprite.h"
#include "scene/gui/grid_container.h"
#include "scene/gui/nine_patch_rect.h"
@@ -457,7 +458,7 @@ Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) {
return rect;
}
-void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int limit, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
+void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int p_limit, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node)
return;
if (Object::cast_to<Viewport>(p_node))
@@ -466,21 +467,18 @@ 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);
- 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;
+ 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, p_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, p_limit, Transform2D(), cl ? cl->get_transform() : p_canvas_xform);
}
+ if (p_limit != 0 && r_items.size() >= p_limit)
+ return;
}
- if (canvas_item && canvas_item->is_visible_in_tree() && (canvas_item->get_owner() != editor->get_edited_scene() || !canvas_item->has_meta("_edit_lock_"))) {
+ if (canvas_item && canvas_item->is_visible_in_tree()) {
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)) {
@@ -497,6 +495,41 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
return;
}
+void CanvasItemEditor::_get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, int p_limit) {
+
+ Node *scene = editor->get_edited_scene();
+
+ _find_canvas_items_at_pos(p_pos, scene, r_items, p_limit);
+
+ //Remove invalid results
+ for (int i = 0; i < r_items.size(); i++) {
+ Node *node = r_items[i].item;
+
+ // Make sure the selected node is in the current scene, or editable
+ while (node && node != get_tree()->get_edited_scene_root() && node->get_owner() != scene && !scene->is_editable_instance(node->get_owner())) {
+ node = node->get_parent();
+ };
+
+ // Replace the node by the group if grouped
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(node);
+ while (node && node != scene->get_parent()) {
+ CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node);
+ if (canvas_item_tmp && node->has_meta("_edit_group_")) {
+ canvas_item = canvas_item_tmp;
+ }
+ node = node->get_parent();
+ }
+
+ //Remove the item if invalid
+ if (!canvas_item || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner())) || (canvas_item->has_meta("_edit_lock_") && canvas_item->get_meta("_edit_lock_"))) {
+ r_items.remove(i);
+ i--;
+ } else {
+ r_items[i].item = canvas_item;
+ }
+ }
+}
+
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;
@@ -504,13 +537,13 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n
return;
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
+ Node *scene = editor->get_edited_scene();
- 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 = p_node == scene || p_node->get_owner() == scene || scene->is_editable_instance(p_node->get_owner());
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 && !locked && editable) {
+ 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()) {
_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
@@ -521,7 +554,7 @@ void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_n
}
}
- if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) {
+ if (canvas_item && canvas_item->is_visible_in_tree() && !locked && editable) {
Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
if (canvas_item->_edit_use_rect()) {
@@ -628,7 +661,7 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items
if (bone && bone->has_meta("_edit_bone_")) {
// Check if we have an IK chain
List<Node2D *> bone_ik_list;
- bool ik_found;
+ bool ik_found = false;
bone = Object::cast_to<Node2D>(bone->get_parent());
while (bone) {
bone_ik_list.push_back(bone);
@@ -896,7 +929,7 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
- if (b->get_button_index() == BUTTON_WHEEL_DOWN) {
+ if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_DOWN) {
// Scroll or pan down
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
view_offset.y += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
@@ -908,7 +941,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
return true;
}
- if (b->get_button_index() == BUTTON_WHEEL_UP) {
+ if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_UP) {
// Scroll or pan up
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
view_offset.y -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
@@ -920,7 +953,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
return true;
}
- if (b->get_button_index() == BUTTON_WHEEL_LEFT) {
+ if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_LEFT) {
// Pan left
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
view_offset.x -= int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
@@ -930,7 +963,7 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
}
}
- if (b->get_button_index() == BUTTON_WHEEL_RIGHT) {
+ if (b->is_pressed() && b->get_button_index() == BUTTON_WHEEL_RIGHT) {
// Pan right
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
view_offset.x += int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor();
@@ -939,28 +972,57 @@ bool CanvasItemEditor::_gui_input_zoom_or_pan(const Ref<InputEvent> &p_event) {
return true;
}
}
- }
- Ref<InputEventMouseMotion> m = p_event;
- if (m.is_valid()) {
if (drag_type == DRAG_NONE) {
- if (((m->get_button_mask() & BUTTON_MASK_LEFT) && tool == TOOL_PAN) ||
- (m->get_button_mask() & BUTTON_MASK_MIDDLE) ||
- ((m->get_button_mask() & BUTTON_MASK_LEFT) && Input::get_singleton()->is_key_pressed(KEY_SPACE)) ||
- (EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
+ if (b->is_pressed() &&
+ (b->get_button_index() == BUTTON_MIDDLE ||
+ (b->get_button_index() == BUTTON_LEFT && tool == TOOL_PAN) ||
+ (b->get_button_index() == BUTTON_LEFT && !EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) {
// Pan the viewport
- Point2i relative;
- if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
- relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
- } else {
- relative = m->get_relative();
+ drag_type = DRAG_PAN;
+ }
+ }
+
+ if (drag_type == DRAG_PAN) {
+ if (!b->is_pressed()) {
+ // Stop panning the viewport (for any mouse button press)
+ drag_type = DRAG_NONE;
+ }
+ }
+ }
+
+ Ref<InputEventKey> k = p_event;
+ if (k.is_valid()) {
+ if (k->get_scancode() == KEY_SPACE && EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning")) {
+ if (drag_type == DRAG_NONE) {
+ if (k->is_pressed() && !k->is_echo()) {
+ //Pan the viewport
+ drag_type = DRAG_PAN;
}
- view_offset.x -= relative.x / zoom;
- view_offset.y -= relative.y / zoom;
- _update_scrollbars();
- viewport->update();
- return true;
+ } else if (drag_type == DRAG_PAN) {
+ if (!k->is_pressed()) {
+ // Stop panning the viewport (for any mouse button press)
+ drag_type = DRAG_NONE;
+ }
+ }
+ }
+ }
+
+ Ref<InputEventMouseMotion> m = p_event;
+ if (m.is_valid()) {
+ if (drag_type == DRAG_PAN) {
+ // Pan the viewport
+ Point2i relative;
+ if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
+ relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
+ } else {
+ relative = m->get_relative();
}
+ view_offset.x -= relative.x / zoom;
+ view_offset.y -= relative.y / zoom;
+ _update_scrollbars();
+ viewport->update();
+ return true;
}
}
@@ -1675,17 +1737,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
// Popup the selection menu list
Point2 click = transform.affine_inverse().xform(b->get_position());
- Node *scene = editor->get_edited_scene();
-
- _find_canvas_items_at_pos(click, scene, selection_results);
- for (int i = 0; i < selection_results.size(); i++) {
- CanvasItem *item = selection_results[i].item;
- if (item != scene && item->get_owner() != scene && !scene->is_editable_instance(item->get_owner())) {
- //invalid result
- selection_results.remove(i);
- i--;
- }
- }
+ _get_canvas_items_at_pos(click, selection_results);
if (selection_results.size() == 1) {
CanvasItem *item = selection_results[0].item;
@@ -1735,7 +1787,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
// Find the item to select
CanvasItem *canvas_item = NULL;
Vector<_SelectResult> selection;
- _find_canvas_items_at_pos(click, scene, selection, editor_selection->get_selection().empty() ? 1 : 0);
+ _get_canvas_items_at_pos(click, selection, editor_selection->get_selection().empty() ? 1 : 0);
for (int i = 0; i < selection.size(); i++) {
if (editor_selection->is_selected(selection[i].item)) {
@@ -1754,23 +1806,6 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
if (!selection.empty())
canvas_item = selection[0].item;
- // Check if the canvas item is in a group, and select the group instead if it is the case
- 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;
- }
- node = node->get_parent();
- }
-
- // Make sure the selected node is in the current scene
- node = canvas_item;
- while (node && ((node != scene && node->get_owner() != scene) || !node->is_class("CanvasItem"))) {
- node = node->get_parent();
- };
- canvas_item = Object::cast_to<CanvasItem>(node);
-
if (!canvas_item) {
// Start a box selection
if (!b->get_shift()) {
@@ -1855,11 +1890,10 @@ bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &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);
+ _get_canvas_items_at_pos(click, hovering_results_tmp);
hovering_results_tmp.sort();
bool changed = false;
if (hovering_results.size() == hovering_results_tmp.size()) {
@@ -1903,10 +1937,10 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
//printf("Rotate\n");
} else if ((accepted = _gui_input_move(p_event))) {
//printf("Move\n");
- } else if ((accepted = _gui_input_select(p_event))) {
- //printf("Selection\n");
} else if ((accepted = _gui_input_zoom_or_pan(p_event))) {
//printf("Zoom or pan\n");
+ } else if ((accepted = _gui_input_select(p_event))) {
+ //printf("Selection\n");
}
if (accepted)
@@ -1919,22 +1953,18 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
CursorShape c = CURSOR_ARROW;
switch (drag_type) {
case DRAG_NONE:
- if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_MIDDLE) || Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
- c = CURSOR_DRAG;
- } else {
- switch (tool) {
- case TOOL_MOVE:
- c = CURSOR_MOVE;
- break;
- case TOOL_EDIT_PIVOT:
- c = CURSOR_CROSS;
- break;
- case TOOL_PAN:
- c = CURSOR_DRAG;
- break;
- default:
- break;
- }
+ switch (tool) {
+ case TOOL_MOVE:
+ c = CURSOR_MOVE;
+ break;
+ case TOOL_EDIT_PIVOT:
+ c = CURSOR_CROSS;
+ break;
+ case TOOL_PAN:
+ c = CURSOR_DRAG;
+ break;
+ default:
+ break;
}
break;
case DRAG_LEFT:
@@ -1956,6 +1986,8 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
case DRAG_ALL:
c = CURSOR_MOVE;
break;
+ case DRAG_PAN:
+ c = CURSOR_DRAG;
default:
break;
}
@@ -2551,43 +2583,52 @@ void CanvasItemEditor::_draw_bones() {
Color bone_color1 = EditorSettings::get_singleton()->get("editors/2d/bone_color1");
Color bone_color2 = EditorSettings::get_singleton()->get("editors/2d/bone_color2");
Color bone_ik_color = EditorSettings::get_singleton()->get("editors/2d/bone_ik_color");
+ Color bone_outline_color = EditorSettings::get_singleton()->get("editors/2d/bone_outline_color");
Color bone_selected_color = EditorSettings::get_singleton()->get("editors/2d/bone_selected_color");
+ int bone_outline_size = EditorSettings::get_singleton()->get("editors/2d/bone_outline_size");
- for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+ for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- E->get().from = Vector2();
- E->get().to = Vector2();
+ Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from));
+ Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().to));
- Node2D *n2d = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key()));
- if (!n2d)
+ if (!from_node->is_inside_tree())
+ continue; //may have been removed
+ if (!from_node)
continue;
- if (!n2d->get_parent())
+ if (!to_node && E->get().length == 0)
continue;
- CanvasItem *pi = n2d->get_parent_item();
+ Vector2 from = transform.xform(from_node->get_global_position());
+ Vector2 to;
- Node2D *pn2d = Object::cast_to<Node2D>(n2d->get_parent());
-
- if (!pn2d)
- continue;
-
- Vector2 from = transform.xform(pn2d->get_global_position());
- Vector2 to = transform.xform(n2d->get_global_position());
-
- E->get().from = from;
- E->get().to = to;
+ if (to_node)
+ to = transform.xform(to_node->get_global_position());
+ else
+ to = transform.xform(from_node->get_global_transform().xform(Vector2(E->get().length, 0)));
Vector2 rel = to - from;
Vector2 relt = rel.tangent().normalized() * bone_width;
+ Vector2 reln = rel.normalized();
+ Vector2 reltn = relt.normalized();
Vector<Vector2> bone_shape;
bone_shape.push_back(from);
bone_shape.push_back(from + rel * 0.2 + relt);
bone_shape.push_back(to);
bone_shape.push_back(from + rel * 0.2 - relt);
+
+ Vector<Vector2> bone_shape_outline;
+ bone_shape_outline.push_back(from + (-reln - reltn) * bone_outline_size);
+ bone_shape_outline.push_back(from + (-reln + reltn) * bone_outline_size);
+ bone_shape_outline.push_back(from + rel * 0.2 + relt + reltn * bone_outline_size);
+ bone_shape_outline.push_back(to + (reln + reltn) * bone_outline_size);
+ bone_shape_outline.push_back(to + (reln - reltn) * bone_outline_size);
+ bone_shape_outline.push_back(from + rel * 0.2 - relt - reltn * bone_outline_size);
+
Vector<Color> colors;
- if (pi->has_meta("_edit_ik_")) {
+ if (from_node->has_meta("_edit_ik_")) {
colors.push_back(bone_ik_color);
colors.push_back(bone_ik_color);
@@ -2600,14 +2641,26 @@ void CanvasItemEditor::_draw_bones() {
colors.push_back(bone_color2);
}
- VisualServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector<Vector2>(), RID());
-
- if (editor_selection->is_selected(pi)) {
- for (int i = 0; i < bone_shape.size(); i++) {
+ Vector<Color> outline_colors;
- VisualServer::get_singleton()->canvas_item_add_line(ci, bone_shape[i], bone_shape[(i + 1) % bone_shape.size()], bone_selected_color, 2);
- }
+ if (editor_selection->is_selected(from_node)) {
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ outline_colors.push_back(bone_selected_color);
+ } else {
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
+ outline_colors.push_back(bone_outline_color);
}
+
+ VisualServer::get_singleton()->canvas_item_add_polygon(ci, bone_shape_outline, outline_colors);
+ VisualServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector<Vector2>(), RID());
}
}
}
@@ -2616,7 +2669,7 @@ void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Trans
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))
+ 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())
@@ -2731,26 +2784,70 @@ void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p
}
}
-void CanvasItemEditor::_build_bones_list(Node *p_node) {
- ERR_FAIL_COND(!p_node);
+bool CanvasItemEditor::_build_bones_list(Node *p_node) {
+ ERR_FAIL_COND_V(!p_node, false);
+
+ bool has_child_bones = false;
for (int i = 0; i < p_node->get_child_count(); i++) {
- _build_bones_list(p_node->get_child(i));
+ if (_build_bones_list(p_node->get_child(i))) {
+ has_child_bones = true;
+ }
+ }
+
+ CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
+ Node *scene = editor->get_edited_scene();
+ if (!canvas_item || !canvas_item->is_visible() || (canvas_item != scene && canvas_item->get_owner() != scene && !scene->is_editable_instance(canvas_item->get_owner()))) {
+ return false;
}
- CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
- if (c && c->is_visible_in_tree()) {
- if (c->has_meta("_edit_bone_")) {
+ Node *parent = canvas_item->get_parent();
- ObjectID id = c->get_instance_id();
- if (!bone_list.has(id)) {
- BoneList bone;
- bone_list[id] = bone;
+ if (Object::cast_to<Bone2D>(canvas_item)) {
+ if (Object::cast_to<Bone2D>(parent)) {
+ // Add as bone->parent relationship
+ BoneKey bk;
+ bk.from = parent->get_instance_id();
+ bk.to = canvas_item->get_instance_id();
+ if (!bone_list.has(bk)) {
+ BoneList b;
+ b.length = 0;
+ bone_list[bk] = b;
}
- bone_list[id].last_pass = bone_last_frame;
+ bone_list[bk].last_pass = bone_last_frame;
}
+
+ if (!has_child_bones) {
+ // Add a last bone if the Bone2D has no Bone2D child
+ BoneKey bk;
+ bk.from = canvas_item->get_instance_id();
+ bk.to = 0;
+ if (!bone_list.has(bk)) {
+ BoneList b;
+ b.length = 0;
+ bone_list[bk] = b;
+ }
+ bone_list[bk].last_pass = bone_last_frame;
+ }
+
+ return true;
}
+
+ if (canvas_item->has_meta("_edit_bone_")) {
+ // Add a "custom bone"
+ BoneKey bk;
+ bk.from = parent->get_instance_id();
+ bk.to = canvas_item->get_instance_id();
+ if (!bone_list.has(bk)) {
+ BoneList b;
+ b.length = 0;
+ bone_list[bk] = b;
+ }
+ bone_list[bk].last_pass = bone_last_frame;
+ }
+
+ return false;
}
void CanvasItemEditor::_draw_viewport() {
@@ -2826,6 +2923,7 @@ void CanvasItemEditor::_notification(int p_what) {
int nb_control = 0;
int nb_having_pivot = 0;
+ // Update the viewport if the canvas_item changes
List<CanvasItem *> selection = _get_edited_canvas_items();
for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
@@ -2871,15 +2969,17 @@ void CanvasItemEditor::_notification(int p_what) {
nb_having_pivot++;
}
}
+
// Activate / Deactivate the pivot tool
pivot_button->set_disabled(nb_having_pivot == 0);
// Show / Hide the layout button
presets_menu->set_visible(nb_control > 0 && nb_control == selection.size());
- for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+ // Update the viewport if bones changes
+ for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- Object *b = ObjectDB::get_instance(E->key());
+ Object *b = ObjectDB::get_instance(E->key().from);
if (!b) {
viewport->update();
@@ -2887,13 +2987,22 @@ void CanvasItemEditor::_notification(int p_what) {
}
Node2D *b2 = Object::cast_to<Node2D>(b);
- if (!b2) {
+ if (!b2 || !b2->is_inside_tree()) {
continue;
}
- if (b2->get_global_transform() != E->get().xform) {
+ Transform2D global_xform = b2->get_global_transform();
+
+ if (global_xform != E->get().xform) {
+
+ E->get().xform = global_xform;
+ viewport->update();
+ }
+
+ Bone2D *bone = Object::cast_to<Bone2D>(b);
+ if (bone && bone->get_default_length() != E->get().length) {
- E->get().xform = b2->get_global_transform();
+ E->get().length = bone->get_default_length();
viewport->update();
}
}
@@ -2909,12 +3018,19 @@ void CanvasItemEditor::_notification(int p_what) {
AnimationPlayerEditor::singleton->get_key_editor()->connect("visibility_changed", this, "_keying_changed");
_keying_changed();
+ get_tree()->connect("node_added", this, "_tree_changed", varray());
+ get_tree()->connect("node_removed", this, "_tree_changed", varray());
} else if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
select_sb->set_texture(get_icon("EditorRect2D", "EditorIcons"));
}
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+ get_tree()->disconnect("node_added", this, "_tree_changed");
+ get_tree()->disconnect("node_removed", this, "_tree_changed");
+ }
+
if (p_what == NOTIFICATION_ENTER_TREE || p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) {
select_button->set_icon(get_icon("ToolSelect", "EditorIcons"));
list_select_button->set_icon(get_icon("ListSelect", "EditorIcons"));
@@ -2999,6 +3115,47 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
editor_selection->add_node(p_canvas_item);
}
+void CanvasItemEditor::_queue_update_bone_list() {
+
+ if (bone_list_dirty)
+ return;
+
+ call_deferred("_update_bone_list");
+ bone_list_dirty = true;
+}
+
+void CanvasItemEditor::_update_bone_list() {
+
+ bone_last_frame++;
+
+ if (editor->get_edited_scene()) {
+ _build_bones_list(editor->get_edited_scene());
+ }
+
+ List<Map<BoneKey, BoneList>::Element *> bone_to_erase;
+ for (Map<BoneKey, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
+ if (E->get().last_pass != bone_last_frame) {
+ bone_to_erase.push_back(E);
+ continue;
+ }
+
+ Node *node = Object::cast_to<Node>(ObjectDB::get_instance(E->key().from));
+ if (!node || !node->is_inside_tree() || (node != get_tree()->get_edited_scene_root() && !get_tree()->get_edited_scene_root()->is_a_parent_of(node))) {
+ bone_to_erase.push_back(E);
+ continue;
+ }
+ }
+ while (bone_to_erase.size()) {
+ bone_list.erase(bone_to_erase.front()->get());
+ bone_to_erase.pop_front();
+ }
+ bone_list_dirty = false;
+}
+
+void CanvasItemEditor::_tree_changed(Node *) {
+ _queue_update_bone_list();
+}
+
void CanvasItemEditor::_update_scrollbars() {
updating_scroll = true;
@@ -3023,22 +3180,7 @@ void CanvasItemEditor::_update_scrollbars() {
Size2 screen_rect = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
Rect2 local_rect = Rect2(Point2(), viewport->get_size() - Size2(vmin.width, hmin.height));
- bone_last_frame++;
-
- if (editor->get_edited_scene()) {
- _build_bones_list(editor->get_edited_scene());
- }
-
- List<Map<ObjectID, BoneList>::Element *> bone_to_erase;
- for (Map<ObjectID, BoneList>::Element *E = bone_list.front(); E; E = E->next()) {
- if (E->get().last_pass != bone_last_frame) {
- bone_to_erase.push_back(E);
- }
- }
- while (bone_to_erase.size()) {
- bone_list.erase(bone_to_erase.front()->get());
- bone_to_erase.pop_front();
- }
+ _queue_update_bone_list();
// Calculate scrollable area
Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
@@ -3802,6 +3944,9 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_draw_viewport", &CanvasItemEditor::_draw_viewport);
ClassDB::bind_method("_gui_input_viewport", &CanvasItemEditor::_gui_input_viewport);
ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed);
+ ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list);
+ ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed);
+
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state);
@@ -4005,6 +4150,7 @@ void CanvasItemEditor::focus_selection() {
CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
+ bone_list_dirty = false;
tool = TOOL_SELECT;
undo_redo = p_editor->get_undo_redo();
editor = p_editor;
@@ -4189,13 +4335,13 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p = skeleton_menu->get_popup();
p->set_hide_on_checkable_item_selection(false);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
- p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES);
- p->add_separator();
p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
p->add_separator();
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
+ p->add_separator();
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Custom Bone(s) from Node(s)"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Custom Bones")), SKELETON_CLEAR_BONES);
p->connect("id_pressed", this, "_popup_callback");
hb->add_child(memnew(VSeparator));
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 5ca8a37610..a1957b892e 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -194,7 +194,8 @@ class CanvasItemEditor : public VBoxContainer {
DRAG_V_GUIDE,
DRAG_H_GUIDE,
DRAG_DOUBLE_GUIDE,
- DRAG_KEY_MOVE
+ DRAG_KEY_MOVE,
+ DRAG_PAN
};
EditorSelection *editor_selection;
@@ -263,12 +264,24 @@ class CanvasItemEditor : public VBoxContainer {
struct BoneList {
Transform2D xform;
- Vector2 from;
- Vector2 to;
+ float length;
uint64_t last_pass;
};
+
uint64_t bone_last_frame;
- Map<ObjectID, BoneList> bone_list;
+
+ struct BoneKey {
+ ObjectID from;
+ ObjectID to;
+ _FORCE_INLINE_ bool operator<(const BoneKey &p_key) const {
+ if (from == p_key.from)
+ return to < p_key.to;
+ else
+ return from < p_key.from;
+ }
+ };
+
+ Map<BoneKey, BoneList> bone_list;
struct PoseClipboard {
Vector2 pos;
@@ -336,7 +349,9 @@ class CanvasItemEditor : public VBoxContainer {
Ref<ShortCut> multiply_grid_step_shortcut;
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_pos(const Point2 &p_pos, Node *p_node, Vector<_SelectResult> &r_items, int p_limit = 0, const Transform2D &p_parent_xform = Transform2D(), const Transform2D &p_canvas_xform = Transform2D());
+ void _get_canvas_items_at_pos(const Point2 &p_pos, Vector<_SelectResult> &r_items, int p_limit = 0);
+
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);
@@ -363,7 +378,7 @@ class CanvasItemEditor : public VBoxContainer {
void _selection_menu_hide();
UndoRedo *undo_redo;
- void _build_bones_list(Node *p_node);
+ bool _build_bones_list(Node *p_node);
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);
@@ -430,6 +445,11 @@ class CanvasItemEditor : public VBoxContainer {
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
+ bool bone_list_dirty;
+ void _queue_update_bone_list();
+ void _update_bone_list();
+ void _tree_changed(Node *);
+
friend class CanvasItemEditorPlugin;
protected:
diff --git a/editor/plugins/navigation_mesh_generator.cpp b/editor/plugins/navigation_mesh_generator.cpp
index 5d4e5520f4..0537c5c31f 100644
--- a/editor/plugins/navigation_mesh_generator.cpp
+++ b/editor/plugins/navigation_mesh_generator.cpp
@@ -280,26 +280,20 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
_build_recast_navigation_mesh(p_nav_mesh, &ep, hf, chf, cset, poly_mesh, detail_mesh, vertices, indices);
- if (hf) {
- rcFreeHeightField(hf);
- hf = 0;
- }
- if (chf) {
- rcFreeCompactHeightfield(chf);
- chf = 0;
- }
- if (cset) {
- rcFreeContourSet(cset);
- cset = 0;
- }
- if (poly_mesh) {
- rcFreePolyMesh(poly_mesh);
- poly_mesh = 0;
- }
- if (detail_mesh) {
- rcFreePolyMeshDetail(detail_mesh);
- detail_mesh = 0;
- }
+ rcFreeHeightField(hf);
+ hf = 0;
+
+ rcFreeCompactHeightfield(chf);
+ chf = 0;
+
+ rcFreeContourSet(cset);
+ cset = 0;
+
+ rcFreePolyMesh(poly_mesh);
+ poly_mesh = 0;
+
+ rcFreePolyMeshDetail(detail_mesh);
+ detail_mesh = 0;
}
ep.step(TTR("Done!"), 11);
}
diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp
index 056219a575..6dde639c54 100644
--- a/editor/plugins/path_editor_plugin.cpp
+++ b/editor/plugins/path_editor_plugin.cpp
@@ -167,18 +167,12 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p
Vector3 ofs;
- if (p_cancel) {
-
- return;
- }
-
if (t == 0) {
-
if (p_cancel) {
-
c->set_point_in(p_idx, p_restore);
return;
}
+
ur->create_action(TTR("Set Curve In Position"));
ur->add_do_method(c.ptr(), "set_point_in", idx, c->get_point_in(idx));
ur->add_undo_method(c.ptr(), "set_point_in", idx, p_restore);
@@ -186,10 +180,11 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p
} else {
if (p_cancel) {
-
c->set_point_out(idx, p_restore);
+
return;
}
+
ur->create_action(TTR("Set Curve Out Position"));
ur->add_do_method(c.ptr(), "set_point_out", idx, c->get_point_out(idx));
ur->add_undo_method(c.ptr(), "set_point_out", idx, p_restore);
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 3a169bd780..f04e0a801c 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -35,7 +35,7 @@
#include "os/file_access.h"
#include "os/input.h"
#include "os/keyboard.h"
-
+#include "scene/2d/skeleton_2d.h"
Node2D *Polygon2DEditor::_get_node() const {
return node;
@@ -66,6 +66,8 @@ void Polygon2DEditor::_notification(int p_what) {
uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons"));
uv_button[UV_MODE_ADD_SPLIT]->set_icon(get_icon("AddSplit", "EditorIcons"));
uv_button[UV_MODE_REMOVE_SPLIT]->set_icon(get_icon("DeleteSplit", "EditorIcons"));
+ uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_icon("PaintVertex", "EditorIcons"));
+ uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_icon("UnpaintVertex", "EditorIcons"));
b_snap_grid->set_icon(get_icon("Grid", "EditorIcons"));
b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons"));
@@ -78,31 +80,167 @@ void Polygon2DEditor::_notification(int p_what) {
}
}
+void Polygon2DEditor::_sync_bones() {
+
+ print_line("syncinc");
+ if (!node->has_node(node->get_skeleton())) {
+ error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node"));
+ error->popup_centered_minsize();
+ return;
+ }
+
+ Node *sn = node->get_node(node->get_skeleton());
+ Skeleton2D *skeleton = Object::cast_to<Skeleton2D>(sn);
+
+ if (!skeleton) {
+ error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node"));
+ error->popup_centered_minsize();
+ return;
+ }
+
+ Array prev_bones = node->call("_get_bones");
+ node->clear_bones();
+
+ print_line("bones in skeleton: " + itos(skeleton->get_bone_count()));
+
+ for (int i = 0; i < skeleton->get_bone_count(); i++) {
+ NodePath path = skeleton->get_path_to(skeleton->get_bone(i));
+ PoolVector<float> weights;
+ int wc = node->get_polygon().size();
+
+ for (int j = 0; j < prev_bones.size(); j += 2) {
+ NodePath pvp = prev_bones[j];
+ PoolVector<float> pv = prev_bones[j + 1];
+ if (pvp == path && pv.size() == wc) {
+ weights = pv;
+ }
+ }
+
+ if (weights.size() == 0) { //create them
+ weights.resize(node->get_polygon().size());
+ PoolVector<float>::Write w = weights.write();
+ for (int j = 0; j < wc; j++) {
+ w[j] = 0.0;
+ }
+ }
+
+ node->add_bone(path, weights);
+ }
+ Array new_bones = node->call("_get_bones");
+
+ undo_redo->create_action(TTR("Sync bones"));
+ undo_redo->add_do_method(node, "_set_bones", new_bones);
+ undo_redo->add_undo_method(node, "_set_bones", prev_bones);
+ undo_redo->add_do_method(uv_edit_draw, "update");
+ undo_redo->add_undo_method(uv_edit_draw, "update");
+ undo_redo->add_do_method(this, "_update_bone_list");
+ undo_redo->add_undo_method(this, "_update_bone_list");
+ undo_redo->commit_action();
+}
+
+void Polygon2DEditor::_update_bone_list() {
+
+ NodePath selected;
+ while (bone_scroll_vb->get_child_count()) {
+ CheckBox *cb = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(0));
+ if (cb && cb->is_pressed()) {
+ selected = cb->get_meta("bone_path");
+ }
+ memdelete(bone_scroll_vb->get_child(0));
+ }
+
+ Ref<ButtonGroup> bg;
+ bg.instance();
+ for (int i = 0; i < node->get_bone_count(); i++) {
+ CheckBox *cb = memnew(CheckBox);
+ NodePath np = node->get_bone_path(i);
+ String name;
+ if (np.get_name_count()) {
+ name = np.get_name(np.get_name_count() - 1);
+ }
+ if (name == String()) {
+ name = "Bone " + itos(i);
+ }
+ cb->set_text(name);
+ cb->set_button_group(bg);
+ cb->set_meta("bone_path", np);
+ bone_scroll_vb->add_child(cb);
+
+ if (np == selected)
+ cb->set_pressed(true);
+
+ cb->connect("pressed", this, "_bone_paint_selected", varray(i));
+ }
+
+ uv_edit_draw->update();
+}
+
+void Polygon2DEditor::_bone_paint_selected(int p_index) {
+ uv_edit_draw->update();
+}
+
void Polygon2DEditor::_uv_edit_mode_select(int p_mode) {
- if (p_mode == 0) {
+ if (p_mode == 0) { //uv
uv_button[UV_MODE_CREATE]->hide();
for (int i = UV_MODE_MOVE; i <= UV_MODE_SCALE; i++) {
uv_button[i]->show();
}
uv_button[UV_MODE_ADD_SPLIT]->hide();
uv_button[UV_MODE_REMOVE_SPLIT]->hide();
+ uv_button[UV_MODE_PAINT_WEIGHT]->hide();
+ uv_button[UV_MODE_CLEAR_WEIGHT]->hide();
_uv_mode(UV_MODE_EDIT_POINT);
- } else if (p_mode == 1) {
+ bone_scroll_main_vb->hide();
+ bone_paint_strength->hide();
+ bone_paint_radius->hide();
+ bone_paint_radius_label->hide();
+
+ } else if (p_mode == 1) { //poly
for (int i = 0; i <= UV_MODE_SCALE; i++) {
uv_button[i]->show();
}
uv_button[UV_MODE_ADD_SPLIT]->hide();
uv_button[UV_MODE_REMOVE_SPLIT]->hide();
+ uv_button[UV_MODE_PAINT_WEIGHT]->hide();
+ uv_button[UV_MODE_CLEAR_WEIGHT]->hide();
_uv_mode(UV_MODE_EDIT_POINT);
- } else {
+
+ bone_scroll_main_vb->hide();
+ bone_paint_strength->hide();
+ bone_paint_radius->hide();
+ bone_paint_radius_label->hide();
+
+ } else if (p_mode == 2) { //splits
for (int i = 0; i <= UV_MODE_SCALE; i++) {
uv_button[i]->hide();
}
uv_button[UV_MODE_ADD_SPLIT]->show();
uv_button[UV_MODE_REMOVE_SPLIT]->show();
+ uv_button[UV_MODE_PAINT_WEIGHT]->hide();
+ uv_button[UV_MODE_CLEAR_WEIGHT]->hide();
_uv_mode(UV_MODE_ADD_SPLIT);
+
+ bone_scroll_main_vb->hide();
+ bone_paint_strength->hide();
+ bone_paint_radius->hide();
+ bone_paint_radius_label->hide();
+
+ } else if (p_mode == 3) { //bones´
+ for (int i = 0; i <= UV_MODE_REMOVE_SPLIT; i++) {
+ uv_button[i]->hide();
+ }
+ uv_button[UV_MODE_PAINT_WEIGHT]->show();
+ uv_button[UV_MODE_CLEAR_WEIGHT]->show();
+ _uv_mode(UV_MODE_PAINT_WEIGHT);
+
+ bone_scroll_main_vb->show();
+ bone_paint_strength->show();
+ bone_paint_radius->show();
+ bone_paint_radius_label->show();
+ _update_bone_list();
+ bone_paint_pos = Vector2(-100000, -100000); //send brush away when switching
}
uv_edit_draw->update();
@@ -176,6 +314,9 @@ void Polygon2DEditor::_menu_option(int p_option) {
undo_redo->commit_action();
} break;
+ case UVEDIT_GRID_SETTINGS: {
+ grid_settings->popup_centered_minsize();
+ } break;
default: {
AbstractPolygon2DEditor::_menu_option(p_option);
} break;
@@ -239,41 +380,44 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
uv_drag_from = Vector2(mb->get_position().x, mb->get_position().y);
uv_drag = true;
- uv_prev = node->get_uv();
+ points_prev = node->get_uv();
if (uv_edit_mode[0]->is_pressed()) { //edit uv
- uv_prev = node->get_uv();
+ points_prev = node->get_uv();
} else { //edit polygon
- uv_prev = node->get_polygon();
+ points_prev = node->get_polygon();
}
uv_move_current = uv_mode;
if (uv_move_current == UV_MODE_CREATE) {
if (!uv_create) {
- uv_prev.resize(0);
+ points_prev.resize(0);
Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y));
- uv_prev.push_back(tuv);
+ points_prev.push_back(tuv);
uv_create_to = tuv;
- uv_drag_index = 0;
+ point_drag_index = 0;
uv_drag_from = tuv;
uv_drag = true;
uv_create = true;
uv_create_uv_prev = node->get_uv();
uv_create_poly_prev = node->get_polygon();
+ uv_create_bones_prev = node->call("_get_bones");
splits_prev = node->get_splits();
- node->set_polygon(uv_prev);
- node->set_uv(uv_prev);
+ node->set_polygon(points_prev);
+ node->set_uv(points_prev);
} else {
Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y));
- if (uv_prev.size() > 3 && tuv.distance_to(uv_prev[0]) < 8) {
+ if (points_prev.size() > 3 && tuv.distance_to(points_prev[0]) < 8) {
undo_redo->create_action(TTR("Create Polygon & UV"));
undo_redo->add_do_method(node, "set_uv", node->get_uv());
- undo_redo->add_undo_method(node, "set_uv", uv_prev);
+ undo_redo->add_undo_method(node, "set_uv", points_prev);
undo_redo->add_do_method(node, "set_polygon", node->get_polygon());
- undo_redo->add_undo_method(node, "set_polygon", uv_prev);
+ undo_redo->add_undo_method(node, "set_polygon", points_prev);
+ undo_redo->add_do_method(node, "clear_bones");
+ undo_redo->add_undo_method(node, "_set_bones", node->call("_get_bones"));
undo_redo->add_do_method(uv_edit_draw, "update");
undo_redo->add_undo_method(uv_edit_draw, "update");
undo_redo->commit_action();
@@ -281,12 +425,12 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
uv_create = false;
_uv_mode(UV_MODE_EDIT_POINT);
} else {
- uv_prev.push_back(tuv);
- uv_drag_index = uv_prev.size() - 1;
+ points_prev.push_back(tuv);
+ point_drag_index = points_prev.size() - 1;
uv_drag_from = tuv;
}
- node->set_polygon(uv_prev);
- node->set_uv(uv_prev);
+ node->set_polygon(points_prev);
+ node->set_uv(points_prev);
}
}
@@ -302,34 +446,34 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
if (uv_move_current == UV_MODE_EDIT_POINT) {
- uv_drag_index = -1;
- for (int i = 0; i < uv_prev.size(); i++) {
+ point_drag_index = -1;
+ for (int i = 0; i < points_prev.size(); i++) {
- Vector2 tuv = mtx.xform(uv_prev[i]);
+ Vector2 tuv = mtx.xform(points_prev[i]);
if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) {
uv_drag_from = tuv;
- uv_drag_index = i;
+ point_drag_index = i;
}
}
- if (uv_drag_index == -1) {
+ if (point_drag_index == -1) {
uv_drag = false;
}
}
if (uv_move_current == UV_MODE_ADD_SPLIT) {
- int drag_index = -1;
- drag_index = -1;
- for (int i = 0; i < uv_prev.size(); i++) {
+ int split_to_index = -1;
+ split_to_index = -1;
+ for (int i = 0; i < points_prev.size(); i++) {
- Vector2 tuv = mtx.xform(uv_prev[i]);
+ Vector2 tuv = mtx.xform(points_prev[i]);
if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) {
- drag_index = i;
+ split_to_index = i;
}
}
- if (drag_index == -1) {
+ if (split_to_index == -1) {
split_create = false;
return;
}
@@ -337,41 +481,65 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
if (split_create) {
split_create = false;
- if (drag_index < uv_drag_index) {
- SWAP(drag_index, uv_drag_index);
+ if (split_to_index < point_drag_index) {
+ SWAP(split_to_index, point_drag_index);
}
bool valid = true;
- if (drag_index == uv_drag_index) {
+ String split_error;
+ if (split_to_index == point_drag_index) {
+ split_error = TTR("Split point with itself.");
valid = false;
}
- if (drag_index + 1 == uv_drag_index) {
+ if (split_to_index + 1 == point_drag_index) {
//not a split,goes along the edge
+ split_error = TTR("Split can't form an existing edge.");
valid = false;
}
- if (drag_index == uv_prev.size() - 1 && uv_drag_index == 0) {
+ if (split_to_index == points_prev.size() - 1 && point_drag_index == 0) {
//not a split,goes along the edge
+ split_error = TTR("Split can't form an existing edge.");
valid = false;
}
+
for (int i = 0; i < splits_prev.size(); i += 2) {
- if (splits_prev[i] == uv_drag_index && splits_prev[i + 1] == drag_index) {
+
+ if (splits_prev[i] == point_drag_index && splits_prev[i + 1] == split_to_index) {
//already exists
+ split_error = TTR("Split already exists.");
valid = false;
+ break;
}
- if (splits_prev[i] > uv_drag_index && splits_prev[i + 1] > drag_index) {
- //crossing
- valid = false;
+
+ int a_state; //-1, outside split, 0 split point, +1, inside split
+ if (point_drag_index == splits_prev[i] || point_drag_index == splits_prev[i + 1]) {
+ a_state = 0;
+ } else if (point_drag_index < splits_prev[i] || point_drag_index > splits_prev[i + 1]) {
+ a_state = -1;
+ } else {
+ a_state = 1;
}
- if (splits_prev[i] < uv_drag_index && splits_prev[i + 1] < drag_index) {
- //crossing opposite direction
+ int b_state; //-1, outside split, 0 split point, +1, inside split
+ if (split_to_index == splits_prev[i] || split_to_index == splits_prev[i + 1]) {
+ b_state = 0;
+ } else if (split_to_index < splits_prev[i] || split_to_index > splits_prev[i + 1]) {
+ b_state = -1;
+ } else {
+ b_state = 1;
+ }
+
+ if (b_state * a_state < 0) {
+ //crossing
+ split_error = "Split crosses another split.";
valid = false;
+ break;
}
}
if (valid) {
- splits_prev.push_back(uv_drag_index);
- splits_prev.push_back(drag_index);
+ splits_prev.push_back(point_drag_index);
+ splits_prev.push_back(split_to_index);
undo_redo->create_action(TTR("Add Split"));
@@ -381,13 +549,14 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
undo_redo->add_undo_method(uv_edit_draw, "update");
undo_redo->commit_action();
} else {
- error->set_text(TTR("Invalid Split"));
+ error->set_text(TTR("Invalid Split: ") + split_error);
error->popup_centered_minsize();
}
} else {
- uv_drag_index = drag_index;
+ point_drag_index = split_to_index;
split_create = true;
+ splits_prev = node->get_splits();
uv_create_to = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y));
}
}
@@ -395,11 +564,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
if (uv_move_current == UV_MODE_REMOVE_SPLIT) {
for (int i = 0; i < splits_prev.size(); i += 2) {
- if (splits_prev[i] < 0 || splits_prev[i] >= uv_prev.size())
+ if (splits_prev[i] < 0 || splits_prev[i] >= points_prev.size())
continue;
- if (splits_prev[i + 1] < 0 || splits_prev[i] >= uv_prev.size())
+ if (splits_prev[i + 1] < 0 || splits_prev[i] >= points_prev.size())
continue;
- Vector2 e[2] = { mtx.xform(uv_prev[splits_prev[i]]), mtx.xform(uv_prev[splits_prev[i + 1]]) };
+ Vector2 e[2] = { mtx.xform(points_prev[splits_prev[i]]), mtx.xform(points_prev[splits_prev[i + 1]]) };
Vector2 mp = Vector2(mb->get_position().x, mb->get_position().y);
Vector2 cp = Geometry::get_closest_point_to_segment_2d(mp, e);
if (cp.distance_to(mp) < 8) {
@@ -419,22 +588,50 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
}
}
+ if (uv_move_current == UV_MODE_PAINT_WEIGHT || uv_move_current == UV_MODE_CLEAR_WEIGHT) {
+
+ int bone_selected = -1;
+ for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) {
+ CheckBox *c = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(i));
+ if (c && c->is_pressed()) {
+ bone_selected = i;
+ break;
+ }
+ }
+
+ if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == points_prev.size()) {
+
+ prev_weights = node->get_bone_weights(bone_selected);
+ bone_painting = true;
+ bone_painting_bone = bone_selected;
+ }
+ }
+
} else if (uv_drag && !uv_create) {
undo_redo->create_action(TTR("Transform UV Map"));
if (uv_edit_mode[0]->is_pressed()) { //edit uv
undo_redo->add_do_method(node, "set_uv", node->get_uv());
- undo_redo->add_undo_method(node, "set_uv", uv_prev);
+ undo_redo->add_undo_method(node, "set_uv", points_prev);
} else if (uv_edit_mode[1]->is_pressed()) { //edit polygon
undo_redo->add_do_method(node, "set_polygon", node->get_polygon());
- undo_redo->add_undo_method(node, "set_polygon", uv_prev);
+ undo_redo->add_undo_method(node, "set_polygon", points_prev);
}
undo_redo->add_do_method(uv_edit_draw, "update");
undo_redo->add_undo_method(uv_edit_draw, "update");
undo_redo->commit_action();
uv_drag = false;
+ } else if (bone_painting) {
+
+ undo_redo->create_action(TTR("Paint bone weights"));
+ undo_redo->add_do_method(node, "set_bone_weights", bone_painting_bone, node->get_bone_weights(bone_painting_bone));
+ undo_redo->add_undo_method(node, "set_bone_weights", bone_painting_bone, prev_weights);
+ undo_redo->add_do_method(uv_edit_draw, "update");
+ undo_redo->add_undo_method(uv_edit_draw, "update");
+ undo_redo->commit_action();
+ bone_painting = false;
}
} else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) {
@@ -445,20 +642,23 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
uv_create = false;
node->set_uv(uv_create_uv_prev);
node->set_polygon(uv_create_poly_prev);
+ node->call("_set_bones", uv_create_bones_prev);
node->set_splits(splits_prev);
uv_edit_draw->update();
} else if (uv_drag) {
uv_drag = false;
if (uv_edit_mode[0]->is_pressed()) { //edit uv
- node->set_uv(uv_prev);
+ node->set_uv(points_prev);
} else if (uv_edit_mode[1]->is_pressed()) { //edit polygon
- node->set_polygon(uv_prev);
+ node->set_polygon(points_prev);
}
uv_edit_draw->update();
} else if (split_create) {
split_create = false;
uv_edit_draw->update();
+ } else if (bone_painting) {
+ node->set_bone_weights(bone_painting_bone, prev_weights);
}
} else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
@@ -494,8 +694,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
} break;
case UV_MODE_EDIT_POINT: {
- PoolVector<Vector2> uv_new = uv_prev;
- uv_new.set(uv_drag_index, uv_new[uv_drag_index] + drag);
+ PoolVector<Vector2> uv_new = points_prev;
+ uv_new.set(point_drag_index, uv_new[point_drag_index] + drag);
if (uv_edit_mode[0]->is_pressed()) { //edit uv
node->set_uv(uv_new);
@@ -505,7 +705,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
} break;
case UV_MODE_MOVE: {
- PoolVector<Vector2> uv_new = uv_prev;
+ PoolVector<Vector2> uv_new = points_prev;
for (int i = 0; i < uv_new.size(); i++)
uv_new.set(i, uv_new[i] + drag);
@@ -519,16 +719,16 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
case UV_MODE_ROTATE: {
Vector2 center;
- PoolVector<Vector2> uv_new = uv_prev;
+ PoolVector<Vector2> uv_new = points_prev;
for (int i = 0; i < uv_new.size(); i++)
- center += uv_prev[i];
+ center += points_prev[i];
center /= uv_new.size();
float angle = (uv_drag_from - mtx.xform(center)).normalized().angle_to((uv_drag_to - mtx.xform(center)).normalized());
for (int i = 0; i < uv_new.size(); i++) {
- Vector2 rel = uv_prev[i] - center;
+ Vector2 rel = points_prev[i] - center;
rel = rel.rotated(angle);
uv_new.set(i, center + rel);
}
@@ -543,10 +743,10 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
case UV_MODE_SCALE: {
Vector2 center;
- PoolVector<Vector2> uv_new = uv_prev;
+ PoolVector<Vector2> uv_new = points_prev;
for (int i = 0; i < uv_new.size(); i++)
- center += uv_prev[i];
+ center += points_prev[i];
center /= uv_new.size();
float from_dist = uv_drag_from.distance_to(mtx.xform(center));
@@ -557,7 +757,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
float scale = to_dist / from_dist;
for (int i = 0; i < uv_new.size(); i++) {
- Vector2 rel = uv_prev[i] - center;
+ Vector2 rel = points_prev[i] - center;
rel = rel * scale;
uv_new.set(i, center + rel);
}
@@ -569,10 +769,40 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
}
} break;
}
+
+ if (bone_painting) {
+ bone_paint_pos = Vector2(mm->get_position().x, mm->get_position().y);
+ PoolVector<float> painted_weights = node->get_bone_weights(bone_painting_bone);
+
+ {
+ int pc = painted_weights.size();
+ float amount = bone_paint_strength->get_value();
+ float radius = bone_paint_radius->get_value() * EDSCALE;
+
+ if (uv_mode == UV_MODE_CLEAR_WEIGHT) {
+ amount = -amount;
+ }
+
+ PoolVector<float>::Write w = painted_weights.write();
+ PoolVector<float>::Read r = prev_weights.read();
+ PoolVector<Vector2>::Read rv = points_prev.read();
+
+ for (int i = 0; i < pc; i++) {
+ if (mtx.xform(rv[i]).distance_to(bone_paint_pos) < radius) {
+ w[i] = CLAMP(r[i] + amount, 0, 1);
+ }
+ }
+ }
+
+ node->set_bone_weights(bone_painting_bone, painted_weights);
+ }
uv_edit_draw->update();
} else if (split_create) {
uv_create_to = mtx.affine_inverse().xform(Vector2(mm->get_position().x, mm->get_position().y));
uv_edit_draw->update();
+ } else if (uv_mode == UV_MODE_PAINT_WEIGHT || uv_mode == UV_MODE_CLEAR_WEIGHT) {
+ bone_paint_pos = Vector2(mm->get_position().x, mm->get_position().y);
+ uv_edit_draw->update();
}
}
@@ -607,6 +837,8 @@ void Polygon2DEditor::_uv_draw() {
if (base_tex.is_null())
return;
+ String warning;
+
Transform2D mtx;
mtx.elements[2] = -uv_draw_ofs;
mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
@@ -649,6 +881,24 @@ void Polygon2DEditor::_uv_draw() {
uvs = node->get_polygon();
}
+ PoolVector<float>::Read weight_r;
+
+ if (uv_edit_mode[3]->is_pressed()) {
+ int bone_selected = -1;
+ for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) {
+ CheckBox *c = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(i));
+ if (c && c->is_pressed()) {
+ bone_selected = i;
+ break;
+ }
+ }
+
+ if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == uvs.size()) {
+
+ weight_r = node->get_bone_weights(bone_selected).read();
+ }
+ }
+
Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons");
Rect2 rect(Point2(), mtx.basis_xform(base_tex->get_size()));
@@ -662,12 +912,19 @@ void Polygon2DEditor::_uv_draw() {
next_point = uv_create_to;
}
uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), Color(0.9, 0.5, 0.5), 2);
- uv_edit_draw->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5);
+ if (weight_r.ptr()) {
+
+ Vector2 draw_pos = mtx.xform(uvs[i]);
+ float weight = weight_r[i];
+ uv_edit_draw->draw_rect(Rect2(draw_pos - Vector2(2, 2) * EDSCALE, Vector2(5, 5) * EDSCALE), Color(weight, weight, weight, 1.0));
+ } else {
+ uv_edit_draw->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5);
+ }
rect.expand_to(mtx.basis_xform(uvs[i]));
}
if (split_create) {
- Vector2 from = uvs[uv_drag_index];
+ Vector2 from = uvs[point_drag_index];
Vector2 to = uv_create_to;
uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), Color(0.9, 0.5, 0.5), 2);
}
@@ -682,6 +939,55 @@ void Polygon2DEditor::_uv_draw() {
uv_edit_draw->draw_line(mtx.xform(uvs[idx_from]), mtx.xform(uvs[idx_to]), Color(0.9, 0.5, 0.5), 2);
}
+ if (uv_mode == UV_MODE_PAINT_WEIGHT || uv_mode == UV_MODE_CLEAR_WEIGHT) {
+
+ NodePath bone_path;
+ for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) {
+ CheckBox *c = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(i));
+ if (c && c->is_pressed()) {
+ bone_path = node->get_bone_path(i);
+ break;
+ }
+ }
+
+ //draw skeleton
+ NodePath skeleton_path = node->get_skeleton();
+ if (node->has_node(skeleton_path)) {
+ Skeleton2D *skeleton = Object::cast_to<Skeleton2D>(node->get_node(skeleton_path));
+ if (skeleton) {
+ for (int i = 0; i < skeleton->get_bone_count(); i++) {
+
+ Bone2D *bone = skeleton->get_bone(i);
+ if (bone->get_rest() == Transform2D(0, 0, 0, 0, 0, 0))
+ continue; //not set
+
+ bool current = bone_path == skeleton->get_path_to(bone);
+
+ for (int j = 0; j < bone->get_child_count(); j++) {
+
+ Node2D *n = Object::cast_to<Node2D>(bone->get_child(j));
+ if (!n)
+ continue;
+
+ bool edit_bone = n->has_meta("_edit_bone_") && n->get_meta("_edit_bone_");
+ if (edit_bone) {
+
+ Transform2D bone_xform = node->get_global_transform().affine_inverse() * (skeleton->get_global_transform() * bone->get_skeleton_rest());
+ Transform2D endpoint_xform = bone_xform * n->get_transform();
+
+ Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
+ uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), current ? 5 : 4);
+ uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, current ? 3 : 2);
+ }
+ }
+ }
+ }
+ }
+
+ //draw paint circle
+ uv_edit_draw->draw_circle(bone_paint_pos, bone_paint_radius->get_value() * EDSCALE, Color(1, 1, 1, 0.1));
+ }
+
rect = rect.grow(200);
updating_uv_scroll = true;
uv_hscroll->set_min(rect.position.x);
@@ -711,6 +1017,10 @@ void Polygon2DEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_snap_step_x"), &Polygon2DEditor::_set_snap_step_x);
ClassDB::bind_method(D_METHOD("_set_snap_step_y"), &Polygon2DEditor::_set_snap_step_y);
ClassDB::bind_method(D_METHOD("_uv_edit_mode_select"), &Polygon2DEditor::_uv_edit_mode_select);
+ ClassDB::bind_method(D_METHOD("_sync_bones"), &Polygon2DEditor::_sync_bones);
+ ClassDB::bind_method(D_METHOD("_update_bone_list"), &Polygon2DEditor::_update_bone_list);
+
+ ClassDB::bind_method(D_METHOD("_bone_paint_selected"), &Polygon2DEditor::_bone_paint_selected);
}
Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
@@ -755,19 +1065,25 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
uv_edit_mode[2] = memnew(ToolButton);
uv_mode_hb->add_child(uv_edit_mode[2]);
uv_edit_mode[2]->set_toggle_mode(true);
+ uv_edit_mode[3] = memnew(ToolButton);
+ uv_mode_hb->add_child(uv_edit_mode[3]);
+ uv_edit_mode[3]->set_toggle_mode(true);
uv_edit_mode[0]->set_text(TTR("UV"));
uv_edit_mode[0]->set_pressed(true);
uv_edit_mode[1]->set_text(TTR("Poly"));
uv_edit_mode[2]->set_text(TTR("Splits"));
+ uv_edit_mode[3]->set_text(TTR("Bones"));
uv_edit_mode[0]->set_button_group(uv_edit_group);
uv_edit_mode[1]->set_button_group(uv_edit_group);
uv_edit_mode[2]->set_button_group(uv_edit_group);
+ uv_edit_mode[3]->set_button_group(uv_edit_group);
uv_edit_mode[0]->connect("pressed", this, "_uv_edit_mode_select", varray(0));
uv_edit_mode[1]->connect("pressed", this, "_uv_edit_mode_select", varray(1));
uv_edit_mode[2]->connect("pressed", this, "_uv_edit_mode_select", varray(2));
+ uv_edit_mode[3]->connect("pressed", this, "_uv_edit_mode_select", varray(3));
uv_mode_hb->add_child(memnew(VSeparator));
@@ -788,11 +1104,38 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
uv_button[4]->set_tooltip(TTR("Scale Polygon"));
uv_button[5]->set_tooltip(TTR("Connect two points to make a split"));
uv_button[6]->set_tooltip(TTR("Select a split to erase it"));
+ uv_button[7]->set_tooltip(TTR("Paint weights with specified intensity"));
+ uv_button[8]->set_tooltip(TTR("UnPaint weights with specified intensity"));
uv_button[0]->hide();
uv_button[5]->hide();
uv_button[6]->hide();
+ uv_button[7]->hide();
+ uv_button[8]->hide();
uv_button[1]->set_pressed(true);
+
+ bone_paint_strength = memnew(HSlider);
+ uv_mode_hb->add_child(bone_paint_strength);
+ bone_paint_strength->set_custom_minimum_size(Size2(75 * EDSCALE, 0));
+ bone_paint_strength->set_v_size_flags(SIZE_SHRINK_CENTER);
+ bone_paint_strength->set_min(0);
+ bone_paint_strength->set_max(1);
+ bone_paint_strength->set_step(0.01);
+ bone_paint_strength->set_value(0.5);
+
+ bone_paint_radius_label = memnew(Label(" " + TTR("Radius:") + " "));
+ uv_mode_hb->add_child(bone_paint_radius_label);
+ bone_paint_radius = memnew(SpinBox);
+ uv_mode_hb->add_child(bone_paint_radius);
+
+ bone_paint_strength->hide();
+ bone_paint_radius->hide();
+ bone_paint_radius_label->hide();
+ bone_paint_radius->set_min(1);
+ bone_paint_radius->set_max(100);
+ bone_paint_radius->set_step(1);
+ bone_paint_radius->set_value(32);
+
HBoxContainer *uv_main_hb = memnew(HBoxContainer);
uv_main_vb->add_child(uv_main_hb);
uv_edit_draw = memnew(Control);
@@ -806,6 +1149,8 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
uv_menu->get_popup()->add_item(TTR("UV->Polygon"), UVEDIT_UV_TO_POLYGON);
uv_menu->get_popup()->add_separator();
uv_menu->get_popup()->add_item(TTR("Clear UV"), UVEDIT_UV_CLEAR);
+ uv_menu->get_popup()->add_separator();
+ uv_menu->get_popup()->add_item(TTR("Grid Settings"), UVEDIT_GRID_SETTINGS);
uv_menu->get_popup()->connect("id_pressed", this, "_menu_option");
uv_mode_hb->add_child(memnew(VSeparator));
@@ -828,8 +1173,11 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
b_snap_grid->set_tooltip(TTR("Show Grid"));
b_snap_grid->connect("toggled", this, "_set_show_grid");
- uv_mode_hb->add_child(memnew(VSeparator));
- uv_mode_hb->add_child(memnew(Label(TTR("Grid Offset:"))));
+ grid_settings = memnew(AcceptDialog);
+ grid_settings->set_title(TTR("Configure Grid:"));
+ add_child(grid_settings);
+ VBoxContainer *grid_settings_vb = memnew(VBoxContainer);
+ grid_settings->add_child(grid_settings_vb);
SpinBox *sb_off_x = memnew(SpinBox);
sb_off_x->set_min(-256);
@@ -838,7 +1186,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
sb_off_x->set_value(snap_offset.x);
sb_off_x->set_suffix("px");
sb_off_x->connect("value_changed", this, "_set_snap_off_x");
- uv_mode_hb->add_child(sb_off_x);
+ grid_settings_vb->add_margin_child(TTR("Grid Offset X:"), sb_off_x);
SpinBox *sb_off_y = memnew(SpinBox);
sb_off_y->set_min(-256);
@@ -847,10 +1195,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
sb_off_y->set_value(snap_offset.y);
sb_off_y->set_suffix("px");
sb_off_y->connect("value_changed", this, "_set_snap_off_y");
- uv_mode_hb->add_child(sb_off_y);
-
- uv_mode_hb->add_child(memnew(VSeparator));
- uv_mode_hb->add_child(memnew(Label(TTR("Grid Step:"))));
+ grid_settings_vb->add_margin_child(TTR("Grid Offset Y:"), sb_off_y);
SpinBox *sb_step_x = memnew(SpinBox);
sb_step_x->set_min(-256);
@@ -859,7 +1204,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
sb_step_x->set_value(snap_step.x);
sb_step_x->set_suffix("px");
sb_step_x->connect("value_changed", this, "_set_snap_step_x");
- uv_mode_hb->add_child(sb_step_x);
+ grid_settings_vb->add_margin_child(TTR("Grid Step X:"), sb_step_x);
SpinBox *sb_step_y = memnew(SpinBox);
sb_step_y->set_min(-256);
@@ -868,7 +1213,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
sb_step_y->set_value(snap_step.y);
sb_step_y->set_suffix("px");
sb_step_y->connect("value_changed", this, "_set_snap_step_y");
- uv_mode_hb->add_child(sb_step_y);
+ grid_settings_vb->add_margin_child(TTR("Grid Step Y:"), sb_step_y);
uv_mode_hb->add_child(memnew(VSeparator));
uv_icon_zoom = memnew(TextureRect);
@@ -878,8 +1223,10 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
uv_zoom->set_max(4);
uv_zoom->set_value(1);
uv_zoom->set_step(0.01);
+ uv_zoom->set_v_size_flags(SIZE_SHRINK_CENTER);
+
uv_mode_hb->add_child(uv_zoom);
- uv_zoom->set_custom_minimum_size(Size2(200, 0));
+ uv_zoom->set_custom_minimum_size(Size2(80 * EDSCALE, 0));
uv_zoom_value = memnew(SpinBox);
uv_zoom->share(uv_zoom_value);
uv_zoom_value->set_custom_minimum_size(Size2(50, 0));
@@ -893,14 +1240,29 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) :
uv_main_vb->add_child(uv_hscroll);
uv_hscroll->connect("value_changed", this, "_uv_scroll_changed");
+ bone_scroll_main_vb = memnew(VBoxContainer);
+ bone_scroll_main_vb->hide();
+ sync_bones = memnew(Button(TTR("Sync Bones to Polygon")));
+ bone_scroll_main_vb->add_child(sync_bones);
+ uv_main_hb->add_child(bone_scroll_main_vb);
+ bone_scroll = memnew(ScrollContainer);
+ bone_scroll->set_v_scroll(true);
+ bone_scroll->set_h_scroll(false);
+ bone_scroll_main_vb->add_child(bone_scroll);
+ bone_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
+ bone_scroll_vb = memnew(VBoxContainer);
+ bone_scroll->add_child(bone_scroll_vb);
+ sync_bones->connect("pressed", this, "_sync_bones");
+
uv_edit_draw->connect("draw", this, "_uv_draw");
uv_edit_draw->connect("gui_input", this, "_uv_input");
uv_draw_zoom = 1.0;
- uv_drag_index = -1;
+ point_drag_index = -1;
uv_drag = false;
uv_create = false;
updating_uv_scroll = false;
split_create = false;
+ bone_painting = false;
error = memnew(AcceptDialog);
add_child(error);
diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h
index 8631ffb9a7..f9b42a21c2 100644
--- a/editor/plugins/polygon_2d_editor_plugin.h
+++ b/editor/plugins/polygon_2d_editor_plugin.h
@@ -32,7 +32,7 @@
#define POLYGON_2D_EDITOR_PLUGIN_H
#include "editor/plugins/abstract_polygon_2d_editor.h"
-
+#include "scene/gui/scroll_container.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -45,7 +45,8 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
MODE_EDIT_UV = MODE_CONT,
UVEDIT_POLYGON_TO_UV,
UVEDIT_UV_TO_POLYGON,
- UVEDIT_UV_CLEAR
+ UVEDIT_UV_CLEAR,
+ UVEDIT_GRID_SETTINGS
};
@@ -57,10 +58,12 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
UV_MODE_SCALE,
UV_MODE_ADD_SPLIT,
UV_MODE_REMOVE_SPLIT,
+ UV_MODE_PAINT_WEIGHT,
+ UV_MODE_CLEAR_WEIGHT,
UV_MODE_MAX
};
- ToolButton *uv_edit_mode[3];
+ ToolButton *uv_edit_mode[4];
Ref<ButtonGroup> uv_edit_group;
Polygon2D *node;
@@ -78,15 +81,32 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
MenuButton *uv_menu;
TextureRect *uv_icon_zoom;
+ VBoxContainer *bone_scroll_main_vb;
+ ScrollContainer *bone_scroll;
+ VBoxContainer *bone_scroll_vb;
+ Button *sync_bones;
+ HSlider *bone_paint_strength;
+ SpinBox *bone_paint_radius;
+ Label *bone_paint_radius_label;
+ bool bone_painting;
+ int bone_painting_bone;
+ PoolVector<float> prev_weights;
+ Vector2 bone_paint_pos;
+ AcceptDialog *grid_settings;
+
+ void _sync_bones();
+ void _update_bone_list();
+
Vector2 uv_draw_ofs;
float uv_draw_zoom;
- PoolVector<Vector2> uv_prev;
+ PoolVector<Vector2> points_prev;
PoolVector<Vector2> uv_create_uv_prev;
PoolVector<Vector2> uv_create_poly_prev;
+ Array uv_create_bones_prev;
PoolVector<int> splits_prev;
Vector2 uv_create_to;
- int uv_drag_index;
+ int point_drag_index;
bool uv_drag;
bool uv_create;
bool split_create;
@@ -118,6 +138,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor {
void _set_snap_step_y(float p_val);
void _uv_edit_mode_select(int p_mode);
+ void _bone_paint_selected(int p_index);
protected:
virtual Node2D *_get_node() const;
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index c872a6f28b..45f5e667fa 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -746,6 +746,8 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
_goto_line(p_row);
+ result.class_name = result.class_name.trim_prefix("_");
+
switch (result.type) {
case ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION: {
@@ -1007,6 +1009,10 @@ void ScriptTextEditor::_edit_option(int p_op) {
}
int next_line = to_line + 1;
+ if (to_line >= tx->get_line_count() - 1) {
+ tx->set_line(to_line, tx->get_line(to_line) + "\n");
+ }
+
tx->begin_complex_operation();
for (int i = from_line; i <= to_line; i++) {
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 9543b4125e..bd0406a3cb 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -5083,8 +5083,6 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) {
ED_SHORTCUT("spatial_editor/tool_rotate", TTR("Tool Rotate"), KEY_E);
ED_SHORTCUT("spatial_editor/tool_scale", TTR("Tool Scale"), KEY_R);
- ED_SHORTCUT("spatial_editor/display_wireframe", TTR("Display Wireframe"), KEY_Z);
-
ED_SHORTCUT("spatial_editor/freelook_toggle", TTR("Toggle Freelook"), KEY_MASK_SHIFT + KEY_F);
PopupMenu *p;
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 71a3c90795..a9afc7a670 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -45,6 +45,12 @@ void SpriteFramesEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
load->set_icon(get_icon("Load", "EditorIcons"));
+ copy->set_icon(get_icon("ActionCopy", "EditorIcons"));
+ paste->set_icon(get_icon("ActionPaste", "EditorIcons"));
+ empty->set_icon(get_icon("InsertBefore", "EditorIcons"));
+ empty2->set_icon(get_icon("InsertAfter", "EditorIcons"));
+ move_up->set_icon(get_icon("MoveLeft", "EditorIcons"));
+ move_down->set_icon(get_icon("MoveRight", "EditorIcons"));
_delete->set_icon(get_icon("Remove", "EditorIcons"));
new_anim->set_icon(get_icon("New", "EditorIcons"));
remove_anim->set_icon(get_icon("Remove", "EditorIcons"));
@@ -736,27 +742,35 @@ SpriteFramesEditor::SpriteFramesEditor() {
hbc->add_child(load);
copy = memnew(Button);
- copy->set_text(TTR("Copy"));
+ copy->set_flat(true);
+ copy->set_tooltip(TTR("Copy"));
hbc->add_child(copy);
paste = memnew(Button);
- paste->set_text(TTR("Paste"));
+ paste->set_flat(true);
+ paste->set_tooltip(TTR("Paste"));
hbc->add_child(paste);
empty = memnew(Button);
- empty->set_text(TTR("Insert Empty (Before)"));
+ empty->set_flat(true);
+ empty->set_tooltip(TTR("Insert Empty (Before)"));
hbc->add_child(empty);
empty2 = memnew(Button);
- empty2->set_text(TTR("Insert Empty (After)"));
+ empty2->set_flat(true);
+ empty2->set_tooltip(TTR("Insert Empty (After)"));
hbc->add_child(empty2);
+ hbc->add_spacer(false);
+
move_up = memnew(Button);
- move_up->set_text(TTR("Move (Before)"));
+ move_up->set_flat(true);
+ move_up->set_tooltip(TTR("Move (Before)"));
hbc->add_child(move_up);
move_down = memnew(Button);
- move_down->set_text(TTR("Move (After)"));
+ move_down->set_flat(true);
+ move_down->set_tooltip(TTR("Move (After)"));
hbc->add_child(move_down);
_delete = memnew(Button);
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 2427cd966b..92b95963f9 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -744,7 +744,7 @@ ThemeEditor::ThemeEditor() {
item = test_tree->create_item(test_tree->get_root());
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
item->set_editable(0, true);
- item->set_text(0, "check");
+ item->set_text(0, "Check");
item = test_tree->create_item(test_tree->get_root());
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0, true);
@@ -753,7 +753,7 @@ ThemeEditor::ThemeEditor() {
item = test_tree->create_item(test_tree->get_root());
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
item->set_editable(0, true);
- item->set_text(0, TTR("Have,Many,Several,Options!"));
+ item->set_text(0, TTR("Has,Many,Options"));
item->set_range(0, 2);
VBoxContainer *third_vb = memnew(VBoxContainer);
@@ -784,58 +784,6 @@ ThemeEditor::ThemeEditor() {
main_hb->add_constant_override("separation", 20 * EDSCALE);
- /*
- test_h_scroll = memnew( HScrollBar );
- test_h_scroll->set_position( Point2( 25, 225 ) );
- test_h_scroll->set_size( Point2( 150, 5 ) );
- panel->add_child(test_h_scroll);
-
- line_edit = memnew( LineEdit );
- line_edit->set_position( Point2( 25, 275 ) );
- line_edit->set_size( Point2( 150, 5 ) );
- line_edit->set_text("Line Edit");
- panel->add_child(line_edit);
-
- test_v_scroll = memnew( VScrollBar );
- test_v_scroll->set_position( Point2( 200, 25 ) );
- test_v_scroll->set_size( Point2( 5, 150 ) );
- panel->add_child(test_v_scroll);
-
- test_tree = memnew(Tree);
- test_tree->set_position( Point2( 300, 25 ) );
- test_tree->set_size( Point2( 200, 200 ) );
- panel->add_child(test_tree);
-
-
- TreeItem *item = test_tree->create_item();
- item->set_editable(0,true);
- item->set_text(0,"root");
- item = test_tree->create_item( test_tree->get_root() );
- item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
- item->set_editable(0,true);
- item->set_text(0,"check");
- item = test_tree->create_item( test_tree->get_root() );
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0,true);
- item->set_range_config(0,0,20,0.1);
- item->set_range(0,2);
- item = test_tree->create_item( test_tree->get_root() );
- item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
- item->set_editable(0,true);
- item->set_text(0,"Have,Many,Several,Options!"));
- item->set_range(0,2);
-
- Button *fd_button= memnew( Button );
- fd_button->set_position(Point2(300,275));
- fd_button->set_text("Open File Dialog");
- panel->add_child(fd_button);
-
- test_file_dialog = memnew( EditorFileDialog );
- panel->add_child(test_file_dialog);
-
- fd_button->connect("pressed", this,"_open_file_dialog");
-*/
-
add_del_dialog = memnew(ConfirmationDialog);
add_del_dialog->hide();
add_child(add_del_dialog);
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 14c584fa35..72b3af5a09 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -724,7 +724,11 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_shift()) {
+#ifdef APPLE_STYLE_KEYS
+ if (mb->get_command())
+#else
if (mb->get_control())
+#endif
tool = TOOL_RECTANGLE_PAINT;
else
tool = TOOL_LINE_PAINT;
@@ -734,9 +738,11 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
}
-
+#ifdef APPLE_STYLE_KEYS
+ if (mb->get_command()) {
+#else
if (mb->get_control()) {
-
+#endif
tool = TOOL_PICKING;
_pick_tile(over_tile);
@@ -940,8 +946,11 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
undo_redo->add_undo_method(node, "set", "tile_data", node->get("tile_data"));
if (mb->get_shift()) {
-
+#ifdef APPLE_STYLE_KEYS
+ if (mb->get_command())
+#else
if (mb->get_control())
+#endif
tool = TOOL_RECTANGLE_ERASE;
else
tool = TOOL_LINE_ERASE;
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index 3257901c88..642870aec0 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -125,12 +125,11 @@ class TileMapEditor : public VBoxContainer {
bool yf;
bool tr;
- CellOp() {
- idx = -1;
- xf = false;
- yf = false;
- tr = false;
- }
+ CellOp() :
+ idx(TileMap::INVALID_CELL),
+ xf(false),
+ yf(false),
+ tr(false) {}
};
Map<Point2i, CellOp> paint_undo;
@@ -141,8 +140,12 @@ class TileMapEditor : public VBoxContainer {
bool flip_h;
bool flip_v;
bool transpose;
- int auto_x;
- int auto_y;
+
+ TileData() :
+ cell(TileMap::INVALID_CELL),
+ flip_h(false),
+ flip_v(false),
+ transpose(false) {}
};
List<TileData> copydata;
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 41692e805f..385fa24ad8 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -149,6 +149,7 @@ void TileSetEditor::_import_node(Node *p_node, Ref<TileSet> p_library) {
p_library->tile_set_light_occluder(id, occluder);
p_library->tile_set_occluder_offset(id, -phys_offset);
p_library->tile_set_navigation_polygon_offset(id, -phys_offset);
+ p_library->tile_set_z_index(id, mi->get_z_index());
}
}
@@ -805,7 +806,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
Vector2 coord((int)(mb->get_position().x / (spacing + size.x)), (int)(mb->get_position().y / (spacing + size.y)));
Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y));
pos = mb->get_position() - pos;
- uint16_t bit;
+ uint16_t bit = 0;
if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) {
if (pos.x < size.x / 2) {
if (pos.y < size.y / 2) {
@@ -868,7 +869,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
Vector2 coord((int)(mm->get_position().x / (spacing + size.x)), (int)(mm->get_position().y / (spacing + size.y)));
Vector2 pos(coord.x * (spacing + size.x), coord.y * (spacing + size.y));
pos = mm->get_position() - pos;
- uint16_t bit;
+ uint16_t bit = 0;
if (tileset->autotile_get_bitmask_mode(get_current_tile()) == TileSet::BITMASK_2X2) {
if (pos.x < size.x / 2) {
if (pos.y < size.y / 2) {
@@ -1146,7 +1147,7 @@ void TileSetEditor::_on_tool_clicked(int p_tool) {
case EDITMODE_COLLISION: {
if (!edited_collision_shape.is_null()) {
Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(get_current_tile());
- int index;
+ int index = -1;
for (int i = 0; i < sd.size(); i++) {
if (sd[i].shape == edited_collision_shape) {
index = i;