1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-11 13:10:58 +00:00

Merge pull request #17502 from groud/2Deditor_rect

Remove the rect surrounding 2D nodes in 2D editor when it's not pertinent
This commit is contained in:
Juan Linietsky
2018-04-13 10:21:44 -03:00
committed by GitHub
37 changed files with 791 additions and 277 deletions

View File

@@ -196,11 +196,15 @@ void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap,
Transform2D ci_transform = canvas_item->get_global_transform_with_canvas();
Transform2D to_snap_transform = p_to_snap ? p_to_snap->get_global_transform_with_canvas() : Transform2D();
if (fmod(ci_transform.get_rotation() - to_snap_transform.get_rotation(), (real_t)360.0) == 0.0) {
Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position());
Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size());
_snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation());
_snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation());
if (canvas_item->_edit_use_rect()) {
Point2 begin = ci_transform.xform(canvas_item->_edit_get_rect().get_position());
Point2 end = ci_transform.xform(canvas_item->_edit_get_rect().get_position() + canvas_item->_edit_get_rect().get_size());
_snap_if_closer_point(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation());
_snap_if_closer_point(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation());
} else {
Point2 position = ci_transform.xform(Point2());
_snap_if_closer_point(p_value, position, r_current_snap, r_snapped, ci_transform.get_rotation());
}
}
}
for (int i = 0; i < p_current->get_child_count(); i++) {
@@ -221,23 +225,23 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
// Parent sides and center
if ((is_snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) {
Point2 begin;
Point2 end;
bool can_snap = false;
if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
can_snap = true;
} else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) {
begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position());
end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size());
can_snap = true;
}
if (can_snap) {
Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
_snap_if_closer_point(p_target, begin, output, snapped, rotation);
_snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation);
_snap_if_closer_point(p_target, end, output, snapped, rotation);
} else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) {
if (parent_ci->_edit_use_rect()) {
Point2 begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position());
Point2 end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->_edit_get_rect().get_position() + parent_ci->_edit_get_rect().get_size());
_snap_if_closer_point(p_target, begin, output, snapped, rotation);
_snap_if_closer_point(p_target, (begin + end) / 2.0, output, snapped, rotation);
_snap_if_closer_point(p_target, end, output, snapped, rotation);
} else {
Point2 position = p_canvas_item->get_transform().affine_inverse().xform(Point2());
_snap_if_closer_point(p_target, position, output, snapped, rotation);
}
}
}
@@ -253,16 +257,23 @@ Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const
// Self sides
if ((is_snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) {
Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position());
Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size());
_snap_if_closer_point(p_target, begin, output, snapped, rotation);
_snap_if_closer_point(p_target, end, output, snapped, rotation);
if (p_canvas_item->_edit_use_rect()) {
Point2 begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position());
Point2 end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size());
_snap_if_closer_point(p_target, begin, output, snapped, rotation);
_snap_if_closer_point(p_target, end, output, snapped, rotation);
}
}
// Self center
if ((is_snap_active && snap_node_center && (p_modes & SNAP_NODE_CENTER)) || (p_forced_modes & SNAP_NODE_CENTER)) {
Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0);
_snap_if_closer_point(p_target, center, output, snapped, rotation);
if (p_canvas_item->_edit_use_rect()) {
Point2 center = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->_edit_get_rect().get_position() + p_canvas_item->_edit_get_rect().get_size() / 2.0);
_snap_if_closer_point(p_target, center, output, snapped, rotation);
} else {
Point2 position = p_canvas_item->get_global_transform_with_canvas().xform(Point2());
_snap_if_closer_point(p_target, position, output, snapped, rotation);
}
}
}
@@ -364,63 +375,85 @@ Rect2 CanvasItemEditor::_get_encompassing_rect_from_list(List<CanvasItem *> p_li
// Handles the first element
CanvasItem *canvas_item = p_list.front()->get();
Rect2 rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2());
Rect2 rect;
if (canvas_item->_edit_use_rect()) {
rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(canvas_item->_edit_get_rect().position + canvas_item->_edit_get_rect().size / 2), Size2());
} else {
rect = Rect2(canvas_item->get_global_transform_with_canvas().xform(Point2()), Size2());
}
// Handles the other ones
// Expand with the other ones
for (List<CanvasItem *>::Element *E = p_list.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
Rect2 current_rect = canvas_item->_edit_get_rect();
Transform2D xform = canvas_item->get_global_transform_with_canvas();
rect.expand_to(xform.xform(current_rect.position));
rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0)));
rect.expand_to(xform.xform(current_rect.position + current_rect.size));
rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y)));
if (canvas_item->_edit_use_rect()) {
Rect2 current_rect = canvas_item->_edit_get_rect();
rect.expand_to(xform.xform(current_rect.position));
rect.expand_to(xform.xform(current_rect.position + Vector2(current_rect.size.x, 0)));
rect.expand_to(xform.xform(current_rect.position + current_rect.size));
rect.expand_to(xform.xform(current_rect.position + Vector2(0, current_rect.size.y)));
} else {
rect.expand_to(xform.xform(Point2()));
}
}
return rect;
}
void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
void CanvasItemEditor::_expand_encompassing_rect_using_children(Rect2 &r_rect, const Node *p_node, bool &r_first, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node)
return;
if (Object::cast_to<Viewport>(p_node))
return;
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != "";
bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
/*bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != "";
bool editable = !inherited || EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
if (!lock_children && (!inherited || editable)) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
if (canvas_item && !canvas_item->is_set_as_toplevel()) {
_expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
} else {
CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
_expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
}
if (!lock_children && editable) {}*/
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
if (canvas_item && !canvas_item->is_set_as_toplevel()) {
_expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
} else {
const CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
_expand_encompassing_rect_using_children(r_rect, p_node->get_child(i), r_first, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
}
}
if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) {
Rect2 rect = canvas_item->_edit_get_rect();
Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
if (r_first) {
r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2());
r_first = false;
if (canvas_item->_edit_use_rect()) {
Rect2 rect = canvas_item->_edit_get_rect();
if (r_first) {
r_rect = Rect2(xform.xform(rect.position + rect.size / 2), Size2());
r_first = false;
}
if (r_rect.size != Size2()) {
r_rect.expand_to(xform.xform(rect.position));
r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
r_rect.expand_to(xform.xform(rect.position + rect.size));
}
} else {
if (r_first) {
r_rect = Rect2(xform.xform(Point2()), Size2());
r_first = false;
} else {
r_rect.expand_to(xform.xform(Point2()));
}
}
r_rect.expand_to(xform.xform(rect.position));
r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
r_rect.expand_to(xform.xform(rect.position + rect.size));
}
}
Rect2 CanvasItemEditor::_get_scene_encompassing_rect() {
Rect2 CanvasItemEditor::_get_encompassing_rect(const Node *p_node) {
Rect2 rect;
bool first = true;
_expand_encompassing_rect_using_children(rect, editor->get_edited_scene(), first);
_expand_encompassing_rect_using_children(rect, p_node, first);
return rect;
}
@@ -433,22 +466,23 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8);
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
if (canvas_item && !canvas_item->is_set_as_toplevel())
_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, 0, Transform2D(), cl ? cl->get_transform() : p_canvas_xform); //use base transform
Node *scene = editor->get_edited_scene();
if (!(p_node != scene && p_node->get_owner() != scene && (!scene->is_editable_instance(p_node) || p_node->has_meta("_edit_lock_")))) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
if (canvas_item && !canvas_item->is_set_as_toplevel()) {
_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, limit, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
} else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
_find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, limit, Transform2D(), cl ? cl->get_transform() : p_canvas_xform);
}
if (limit != 0 && r_items.size() >= limit)
return;
}
if (limit != 0 && r_items.size() >= limit)
return;
}
if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) {
if (canvas_item && canvas_item->is_visible_in_tree() && (canvas_item->get_owner() != editor->get_edited_scene() || !canvas_item->has_meta("_edit_lock_"))) {
Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse();
const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length();
if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) {
Node2D *node = Object::cast_to<Node2D>(canvas_item);
@@ -463,7 +497,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no
return;
}
void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
void CanvasItemEditor::_find_canvas_items_in_rect(const Rect2 &p_rect, Node *p_node, List<CanvasItem *> *r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
if (!p_node)
return;
if (Object::cast_to<Viewport>(p_node))
@@ -472,31 +506,37 @@ void CanvasItemEditor::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_n
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
bool inherited = p_node != get_tree()->get_edited_scene_root() && p_node->get_filename() != "";
bool editable = inherited && EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
bool editable = !inherited || EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(p_node);
bool lock_children = p_node->has_meta("_edit_group_") && p_node->get_meta("_edit_group_");
bool locked = p_node->has_meta("_edit_lock_") && p_node->get_meta("_edit_lock_");
if (!lock_children && (!inherited || editable)) {
if (!lock_children && !locked && editable) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
if (canvas_item && !canvas_item->is_set_as_toplevel()) {
_find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * canvas_item->get_transform(), p_canvas_xform);
} else {
CanvasLayer *canvas_layer = Object::cast_to<CanvasLayer>(p_node);
_find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
_find_canvas_items_in_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), canvas_layer ? canvas_layer->get_transform() : p_canvas_xform);
}
}
}
if (canvas_item && canvas_item->is_visible_in_tree() && !canvas_item->has_meta("_edit_lock_")) {
Rect2 rect = canvas_item->_edit_get_rect();
Transform2D xform = p_parent_xform * p_canvas_xform * canvas_item->get_transform();
if (p_rect.has_point(xform.xform(rect.position)) &&
p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) &&
p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) &&
p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) {
if (canvas_item->_edit_use_rect()) {
Rect2 rect = canvas_item->_edit_get_rect();
if (p_rect.has_point(xform.xform(rect.position)) &&
p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, 0))) &&
p_rect.has_point(xform.xform(rect.position + Vector2(rect.size.x, rect.size.y))) &&
p_rect.has_point(xform.xform(rect.position + Vector2(0, rect.size.y)))) {
r_items->push_back(canvas_item);
r_items->push_back(canvas_item);
}
} else {
if (p_rect.has_point(xform.xform(Point2()))) {
r_items->push_back(canvas_item);
}
}
}
}
@@ -575,8 +615,11 @@ void CanvasItemEditor::_save_canvas_item_state(List<CanvasItem *> p_canvas_items
if (se) {
se->undo_state = canvas_item->_edit_get_state();
se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
se->pre_drag_rect = canvas_item->_edit_get_rect();
if (canvas_item->_edit_use_rect()) {
se->pre_drag_rect = canvas_item->_edit_get_rect();
} else {
se->pre_drag_rect = Rect2();
}
se->pre_drag_bones_length = List<float>();
se->pre_drag_bones_undo_state = List<Dictionary>();
@@ -1290,54 +1333,55 @@ bool CanvasItemEditor::_gui_input_resize(const Ref<InputEvent> &p_event) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1) {
CanvasItem *canvas_item = selection[0];
if (canvas_item->_edit_use_rect()) {
Rect2 rect = canvas_item->_edit_get_rect();
Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
Rect2 rect = canvas_item->_edit_get_rect();
Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
Vector2 endpoints[4] = {
xform.xform(rect.position),
xform.xform(rect.position + Vector2(rect.size.x, 0)),
xform.xform(rect.position + rect.size),
xform.xform(rect.position + Vector2(0, rect.size.y))
};
Vector2 endpoints[4] = {
xform.xform(rect.position),
xform.xform(rect.position + Vector2(rect.size.x, 0)),
xform.xform(rect.position + rect.size),
xform.xform(rect.position + Vector2(0, rect.size.y))
};
DragType dragger[] = {
DRAG_TOP_LEFT,
DRAG_TOP,
DRAG_TOP_RIGHT,
DRAG_RIGHT,
DRAG_BOTTOM_RIGHT,
DRAG_BOTTOM,
DRAG_BOTTOM_LEFT,
DRAG_LEFT
};
DragType dragger[] = {
DRAG_TOP_LEFT,
DRAG_TOP,
DRAG_TOP_RIGHT,
DRAG_RIGHT,
DRAG_BOTTOM_RIGHT,
DRAG_BOTTOM,
DRAG_BOTTOM_LEFT,
DRAG_LEFT
};
DragType resize_drag = DRAG_NONE;
float radius = (select_handle->get_size().width / 2) * 1.5;
DragType resize_drag = DRAG_NONE;
float radius = (select_handle->get_size().width / 2) * 1.5;
for (int i = 0; i < 4; i++) {
int prev = (i + 3) % 4;
int next = (i + 1) % 4;
for (int i = 0; i < 4; i++) {
int prev = (i + 3) % 4;
int next = (i + 1) % 4;
Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
ofs *= (select_handle->get_size().width / 2);
ofs += endpoints[i];
if (ofs.distance_to(b->get_position()) < radius)
resize_drag = dragger[i * 2];
Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized();
ofs *= (select_handle->get_size().width / 2);
ofs += endpoints[i];
if (ofs.distance_to(b->get_position()) < radius)
resize_drag = dragger[i * 2];
ofs = (endpoints[i] + endpoints[next]) / 2;
ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
if (ofs.distance_to(b->get_position()) < radius)
resize_drag = dragger[i * 2 + 1];
}
ofs = (endpoints[i] + endpoints[next]) / 2;
ofs += (endpoints[next] - endpoints[i]).tangent().normalized() * (select_handle->get_size().width / 2);
if (ofs.distance_to(b->get_position()) < radius)
resize_drag = dragger[i * 2 + 1];
}
if (resize_drag != DRAG_NONE) {
drag_type = resize_drag;
drag_from = transform.affine_inverse().xform(b->get_position());
drag_selection = List<CanvasItem *>();
drag_selection.push_back(canvas_item);
_save_canvas_item_state(drag_selection);
return true;
if (resize_drag != DRAG_NONE) {
drag_type = resize_drag;
drag_from = transform.affine_inverse().xform(b->get_position());
drag_selection = List<CanvasItem *>();
drag_selection.push_back(canvas_item);
_save_canvas_item_state(drag_selection);
return true;
}
}
}
}
@@ -1535,61 +1579,64 @@ bool CanvasItemEditor::_gui_input_move(const Ref<InputEvent> &p_event) {
_save_canvas_item_state(drag_selection, true);
}
_restore_canvas_item_state(drag_selection, true);
if (drag_selection.size() > 0) {
bool move_local_base = k->get_alt();
bool move_local_base_rotated = k->get_control() || k->get_metakey();
_restore_canvas_item_state(drag_selection, true);
Vector2 dir;
if (k->get_scancode() == KEY_UP)
dir += Vector2(0, -1);
else if (k->get_scancode() == KEY_DOWN)
dir += Vector2(0, 1);
else if (k->get_scancode() == KEY_LEFT)
dir += Vector2(-1, 0);
else if (k->get_scancode() == KEY_RIGHT)
dir += Vector2(1, 0);
if (k->get_shift())
dir *= grid_step * Math::pow(2.0, grid_step_multiplier);
bool move_local_base = k->get_alt();
bool move_local_base_rotated = k->get_control() || k->get_metakey();
drag_to += dir;
if (k->get_shift())
drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier));
Vector2 dir;
if (k->get_scancode() == KEY_UP)
dir += Vector2(0, -1);
else if (k->get_scancode() == KEY_DOWN)
dir += Vector2(0, 1);
else if (k->get_scancode() == KEY_LEFT)
dir += Vector2(-1, 0);
else if (k->get_scancode() == KEY_RIGHT)
dir += Vector2(1, 0);
if (k->get_shift())
dir *= grid_step * Math::pow(2.0, grid_step_multiplier);
Point2 previous_pos;
if (drag_selection.size() == 1) {
Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
} else {
previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
}
drag_to += dir;
if (k->get_shift())
drag_to = drag_to.snapped(grid_step * Math::pow(2.0, grid_step_multiplier));
Point2 new_pos;
if (drag_selection.size() == 1) {
Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]);
if (node_2d && move_local_base_rotated) {
Transform2D m;
m.rotate(node_2d->get_rotation());
new_pos += m.xform(drag_to);
} else if (move_local_base) {
new_pos += drag_to;
Point2 previous_pos;
if (drag_selection.size() == 1) {
Transform2D xform = drag_selection[0]->get_global_transform_with_canvas() * drag_selection[0]->get_transform().affine_inverse();
previous_pos = xform.xform(drag_selection[0]->_edit_get_position());
} else {
previous_pos = _get_encompassing_rect_from_list(drag_selection).position;
}
Point2 new_pos;
if (drag_selection.size() == 1) {
Node2D *node_2d = Object::cast_to<Node2D>(drag_selection[0]);
if (node_2d && move_local_base_rotated) {
Transform2D m;
m.rotate(node_2d->get_rotation());
new_pos += m.xform(drag_to);
} else if (move_local_base) {
new_pos += drag_to;
} else {
new_pos = previous_pos + (drag_to - drag_from);
}
} else {
new_pos = previous_pos + (drag_to - drag_from);
}
} else {
new_pos = previous_pos + (drag_to - drag_from);
}
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
for (List<CanvasItem *>::Element *E = drag_selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
Transform2D xform = canvas_item->get_global_transform_with_canvas().affine_inverse() * canvas_item->get_transform();
Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
_solve_IK(node2d, new_pos);
} else {
canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
if (node2d && se->pre_drag_bones_undo_state.size() > 0) {
_solve_IK(node2d, new_pos);
} else {
canvas_item->_edit_set_position(canvas_item->_edit_get_position() + xform.xform(new_pos) - xform.xform(previous_pos));
}
}
}
return true;
@@ -1648,6 +1695,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
return true;
} else if (!selection_results.empty()) {
// Sorts items according the their z-index
selection_results.sort();
NodePath root_path = get_tree()->get_edited_scene_root()->get_path();
@@ -1707,16 +1755,17 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
canvas_item = selection[0].item;
// Check if the canvas item is in a group, and select the group instead if it is the case
CanvasItem *canvas_item_tmp = canvas_item;
while (canvas_item_tmp) {
if (canvas_item->has_meta("_edit_group_")) {
Node *node = canvas_item;
while (node && node != scene) {
CanvasItem *canvas_item_tmp = Object::cast_to<CanvasItem>(node);
if (canvas_item_tmp && node->has_meta("_edit_group_")) {
canvas_item = canvas_item_tmp;
}
canvas_item_tmp = canvas_item_tmp->get_parent_item();
node = node->get_parent();
}
// Make sure the selected node is in the current scene
Node *node = canvas_item;
node = canvas_item;
while (node && ((node != scene && node->get_owner() != scene) || !node->is_class("CanvasItem"))) {
node = node->get_parent();
};
@@ -1766,7 +1815,7 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
if (bsfrom.y > bsto.y)
SWAP(bsfrom.y, bsto.y);
_find_canvas_items_at_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems);
_find_canvas_items_in_rect(Rect2(bsfrom, bsto - bsfrom), scene, &selitems);
for (List<CanvasItem *>::Element *E = selitems.front(); E; E = E->next()) {
editor_selection->add_node(E->get());
}
@@ -1800,6 +1849,42 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
return false;
}
bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) {
if (drag_type == DRAG_NONE && tool == TOOL_SELECT) {
Point2 click = transform.affine_inverse().xform(m->get_position());
Node *scene = editor->get_edited_scene();
//Checks if the hovered items changed, update the viewport if so
Vector<_SelectResult> hovering_results_tmp;
_find_canvas_items_at_pos(click, scene, hovering_results_tmp);
hovering_results_tmp.sort();
bool changed = false;
if (hovering_results.size() == hovering_results_tmp.size()) {
for (int i = 0; i < hovering_results.size(); i++) {
if (hovering_results[i].item != hovering_results_tmp[i].item) {
changed = true;
break;
}
}
} else {
changed = true;
}
if (changed) {
hovering_results = hovering_results_tmp;
viewport->update();
}
return true;
}
}
return false;
}
void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
bool accepted = false;
if ((accepted = _gui_input_rulers_and_guides(p_event))) {
@@ -1827,6 +1912,9 @@ void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
if (accepted)
accept_event();
// Handles the mouse hovering
_gui_input_hover(p_event);
// Change the cursor
CursorShape c = CURSOR_ARROW;
switch (drag_type) {
@@ -2093,6 +2181,9 @@ void CanvasItemEditor::_draw_grid() {
void CanvasItemEditor::_draw_selection() {
Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons");
Ref<Texture> position_icon = get_icon("EditorPosition", "EditorIcons");
Ref<Texture> previous_position_icon = get_icon("EditorPositionPrevious", "EditorIcons");
RID ci = viewport->get_canvas_item();
List<CanvasItem *> selection = _get_edited_canvas_items(false, false);
@@ -2102,8 +2193,6 @@ void CanvasItemEditor::_draw_selection() {
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->get());
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
Rect2 rect = canvas_item->_edit_get_rect();
// Draw the previous position if we are dragging the node
if (show_helpers &&
(drag_type == DRAG_ALL || drag_type == DRAG_ROTATE ||
@@ -2112,42 +2201,52 @@ void CanvasItemEditor::_draw_selection() {
const Transform2D pre_drag_xform = transform * se->pre_drag_xform;
const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7);
Vector2 pre_drag_endpoints[4] = {
if (canvas_item->_edit_use_rect()) {
Vector2 pre_drag_endpoints[4] = {
pre_drag_xform.xform(se->pre_drag_rect.position),
pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)),
pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size),
pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y))
};
pre_drag_xform.xform(se->pre_drag_rect.position),
pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(se->pre_drag_rect.size.x, 0)),
pre_drag_xform.xform(se->pre_drag_rect.position + se->pre_drag_rect.size),
pre_drag_xform.xform(se->pre_drag_rect.position + Vector2(0, se->pre_drag_rect.size.y))
};
for (int i = 0; i < 4; i++) {
viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2);
for (int i = 0; i < 4; i++) {
viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2);
}
} else {
viewport->draw_texture(previous_position_icon, (pre_drag_xform.xform(Point2()) - (previous_position_icon->get_size() / 2)).floor());
}
}
Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform);
// Draw the selected items surrounding boxes
Vector2 endpoints[4] = {
xform.xform(rect.position),
xform.xform(rect.position + Vector2(rect.size.x, 0)),
xform.xform(rect.position + rect.size),
xform.xform(rect.position + Vector2(0, rect.size.y))
};
// Draw the selected items position / surrounding boxes
if (canvas_item->_edit_use_rect()) {
Rect2 rect = canvas_item->_edit_get_rect();
Vector2 endpoints[4] = {
xform.xform(rect.position),
xform.xform(rect.position + Vector2(rect.size.x, 0)),
xform.xform(rect.position + rect.size),
xform.xform(rect.position + Vector2(0, rect.size.y))
};
Color c = Color(1, 0.6, 0.4, 0.7);
Color c = Color(1, 0.6, 0.4, 0.7);
VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
for (int i = 0; i < 4; i++) {
viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, 2);
}
} else {
for (int i = 0; i < 4; i++) {
viewport->draw_line(endpoints[i], endpoints[(i + 1) % 4], c, 2);
Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin());
viewport->draw_set_transform_matrix(transform);
viewport->draw_texture(position_icon, -(position_icon->get_size() / 2));
viewport->draw_set_transform_matrix(Transform2D());
}
if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks
// Draw the pivot
if (canvas_item->_edit_get_pivot() != Vector2() || drag_type == DRAG_PIVOT || tool == TOOL_EDIT_PIVOT) { // This is not really clean :/
viewport->draw_texture(pivot_icon, xform.xform(canvas_item->_edit_get_pivot()) + (-pivot_icon->get_size() / 2).floor());
viewport->draw_texture(pivot_icon, (xform.xform(canvas_item->_edit_get_pivot()) - (pivot_icon->get_size() / 2)).floor());
}
Control *control = Object::cast_to<Control>(canvas_item);
@@ -2329,7 +2428,14 @@ void CanvasItemEditor::_draw_selection() {
}
}
if (tool == TOOL_SELECT) {
if (tool == TOOL_SELECT && canvas_item->_edit_use_rect()) {
Rect2 rect = canvas_item->_edit_get_rect();
Vector2 endpoints[4] = {
xform.xform(rect.position),
xform.xform(rect.position + Vector2(rect.size.x, 0)),
xform.xform(rect.position + rect.size),
xform.xform(rect.position + Vector2(0, rect.size.y))
};
for (int i = 0; i < 4; i++) {
// Draw the resize handles
int prev = (i + 3) % 4;
@@ -2506,32 +2612,121 @@ void CanvasItemEditor::_draw_bones() {
}
}
void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_xform) {
void CanvasItemEditor::_draw_invisible_nodes_positions(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
ERR_FAIL_COND(!p_node);
RID viewport_ci = viewport->get_canvas_item();
Node *scene = editor->get_edited_scene();
if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node))
return;
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
if (canvas_item && !canvas_item->is_visible())
return;
Transform2D transform_ci = p_xform;
CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
if (ci)
transform_ci = transform_ci * ci->get_transform();
Transform2D parent_xform = p_parent_xform;
Transform2D canvas_xform = p_canvas_xform;
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
_draw_locks_and_groups(p_node->get_child(i), transform_ci);
if (canvas_item && !canvas_item->is_set_as_toplevel()) {
parent_xform = parent_xform * canvas_item->get_transform();
} else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
parent_xform = Transform2D();
canvas_xform = cl ? cl->get_transform() : p_canvas_xform;
}
if (ci) {
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
_draw_invisible_nodes_positions(p_node->get_child(i), parent_xform, canvas_xform);
}
if (canvas_item && !canvas_item->_edit_use_rect() && !editor_selection->is_selected(canvas_item)) {
Transform2D xform = transform * canvas_xform * parent_xform;
// Draw the node's position
Ref<Texture> position_icon = get_icon("EditorPositionUnselected", "EditorIcons");
Transform2D transform = Transform2D(xform.get_rotation(), xform.get_origin());
viewport->draw_set_transform_matrix(transform);
viewport->draw_texture(position_icon, -position_icon->get_size() / 2, Color(1.0, 1.0, 1.0, 0.5));
viewport->draw_set_transform_matrix(Transform2D());
}
}
void CanvasItemEditor::_draw_hover() {
List<Rect2> previous_rects;
for (int i = 0; i < hovering_results.size(); i++) {
// Draw the node's name and icon
CanvasItem *canvas_item = hovering_results[i].item;
if (canvas_item->_edit_use_rect())
continue;
Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
// Get the resources
Ref<Texture> node_icon;
if (has_icon(canvas_item->get_class(), "EditorIcons"))
node_icon = get_icon(canvas_item->get_class(), "EditorIcons");
else
node_icon = get_icon("Object", "EditorIcons");
Ref<Font> font = get_font("font", "Label");
String node_name = canvas_item->get_name();
Size2 node_name_size = font->get_string_size(node_name);
Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3));
Point2 pos = xform.get_origin() - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4);
// Rectify the position to avoid overlaping items
for (List<Rect2>::Element *E = previous_rects.front(); E; E = E->next()) {
if (E->get().intersects(Rect2(pos, item_size))) {
pos.y = E->get().get_position().y - item_size.y;
}
}
previous_rects.push_back(Rect2(pos, item_size));
// Draw the node icon and name
viewport->draw_texture(node_icon, pos, Color(1.0, 1.0, 1.0, 0.5));
viewport->draw_string(font, pos + Point2(node_icon->get_size().x + 4, item_size.y - 3), node_name, Color(1.0, 1.0, 1.0, 0.5));
}
}
void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
ERR_FAIL_COND(!p_node);
Node *scene = editor->get_edited_scene();
if (p_node != scene && p_node->get_owner() != scene && !scene->is_editable_instance(p_node->get_owner()))
return;
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_node);
if (canvas_item && !canvas_item->is_visible())
return;
Transform2D parent_xform = p_parent_xform;
Transform2D canvas_xform = p_canvas_xform;
if (canvas_item && !canvas_item->is_set_as_toplevel()) {
parent_xform = parent_xform * canvas_item->get_transform();
} else {
CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
parent_xform = Transform2D();
canvas_xform = cl ? cl->get_transform() : p_canvas_xform;
}
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
_draw_locks_and_groups(p_node->get_child(i), parent_xform, canvas_xform);
}
RID viewport_canvas_item = viewport->get_canvas_item();
if (canvas_item) {
float offset = 0;
Ref<Texture> lock = get_icon("LockViewport", "EditorIcons");
if (p_node->has_meta("_edit_lock_")) {
lock->draw(viewport_ci, transform_ci.xform(Point2(0, 0)));
lock->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
offset += lock->get_size().x;
}
Ref<Texture> group = get_icon("GroupViewport", "EditorIcons");
if (ci->has_meta("_edit_group_")) {
Vector2 ofs = transform_ci.xform(Point2(0, 0));
if (ci->has_meta("_edit_lock_"))
ofs = Point2(ofs.x + lock->get_size().x, ofs.y);
group->draw(viewport_ci, ofs);
if (canvas_item->has_meta("_edit_group_")) {
group->draw(viewport_canvas_item, (transform * canvas_xform * parent_xform).xform(Point2(0, 0)) + Point2(offset, 0));
//offset += group->get_size().x;
}
}
}
@@ -2597,8 +2792,10 @@ void CanvasItemEditor::_draw_viewport() {
_draw_grid();
_draw_selection();
_draw_axis();
if (editor->get_edited_scene())
_draw_locks_and_groups(editor->get_edited_scene(), transform);
if (editor->get_edited_scene()) {
_draw_locks_and_groups(editor->get_edited_scene());
_draw_invisible_nodes_positions(editor->get_edited_scene());
}
RID ci = viewport->get_canvas_item();
VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
@@ -2618,6 +2815,7 @@ void CanvasItemEditor::_draw_viewport() {
if (show_guides)
_draw_guides();
_draw_focus();
_draw_hover();
}
void CanvasItemEditor::_notification(int p_what) {
@@ -2633,12 +2831,17 @@ void CanvasItemEditor::_notification(int p_what) {
CanvasItem *canvas_item = E->get();
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
Rect2 r = canvas_item->_edit_get_rect();
Rect2 rect;
if (canvas_item->_edit_use_rect()) {
rect = canvas_item->_edit_get_rect();
} else {
rect = Rect2();
}
Transform2D xform = canvas_item->get_transform();
if (r != se->prev_rect || xform != se->prev_xform) {
if (rect != se->prev_rect || xform != se->prev_xform) {
viewport->update();
se->prev_rect = r;
se->prev_rect = rect;
se->prev_xform = xform;
}
@@ -2840,7 +3043,7 @@ void CanvasItemEditor::_update_scrollbars() {
// Calculate scrollable area
Rect2 canvas_item_rect = Rect2(Point2(), screen_rect);
if (editor->get_edited_scene()) {
Rect2 content_rect = _get_scene_encompassing_rect();
Rect2 content_rect = _get_encompassing_rect(editor->get_edited_scene());
canvas_item_rect.expand_to(content_rect.position);
canvas_item_rect.expand_to(content_rect.position + content_rect.size);
}
@@ -3539,7 +3742,12 @@ void CanvasItemEditor::_focus_selection(int p_op) {
//if (!canvas_item->is_visible_in_tree()) continue;
++count;
Rect2 item_rect = canvas_item->_edit_get_rect();
Rect2 item_rect;
if (canvas_item->_edit_use_rect()) {
item_rect = canvas_item->_edit_get_rect();
} else {
item_rect = Rect2();
}
Vector2 pos = canvas_item->get_global_transform().get_origin();
Vector2 scale = canvas_item->get_global_transform().get_scale();