Merge pull request #1367 from not-surt/snapping2

Better 2D Snapping
This commit is contained in:
Juan Linietsky 2015-03-23 11:02:45 -03:00
commit 393e5605c9
15 changed files with 293 additions and 339 deletions

View file

@ -39,6 +39,7 @@
#include "scene/resources/packed_scene.h"
#include "os/os.h"
#include "tools/editor/editor_node.h"
#include <iostream>
struct ColladaImport {

View file

@ -36,6 +36,110 @@
#include "globals.h"
#include "os/input.h"
#include "tools/editor/editor_settings.h"
#include "scene/gui/grid_container.h"
class SnapDialog : public ConfirmationDialog {
OBJ_TYPE(SnapDialog,ConfirmationDialog);
protected:
friend class CanvasItemEditor;
SpinBox *grid_offset_x;
SpinBox *grid_offset_y;
SpinBox *grid_step_x;
SpinBox *grid_step_y;
SpinBox *rotation_offset;
SpinBox *rotation_step;
public:
SnapDialog() : ConfirmationDialog() {
const int SPIN_BOX_GRID_RANGE = 256;
const int SPIN_BOX_ROTATION_RANGE = 360;
Label *label;
VBoxContainer *container;
GridContainer *child_container;
set_title("Configure Snap");
get_ok()->set_text("Close");
container = memnew(VBoxContainer);
add_child(container);
child_container = memnew(GridContainer);
child_container->set_columns(3);
container->add_child(child_container);
label = memnew(Label);
label->set_text("Grid Offset:");
child_container->add_child(label);
grid_offset_x=memnew(SpinBox);
grid_offset_x->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_x->set_max(SPIN_BOX_GRID_RANGE);
grid_offset_x->set_suffix("px");
child_container->add_child(grid_offset_x);
grid_offset_y=memnew(SpinBox);
grid_offset_y->set_min(-SPIN_BOX_GRID_RANGE);
grid_offset_y->set_max(SPIN_BOX_GRID_RANGE);
grid_offset_y->set_suffix("px");
child_container->add_child(grid_offset_y);
label = memnew(Label);
label->set_text("Grid Step:");
child_container->add_child(label);
grid_step_x=memnew(SpinBox);
grid_step_x->set_min(-SPIN_BOX_GRID_RANGE);
grid_step_x->set_max(SPIN_BOX_GRID_RANGE);
grid_step_x->set_suffix("px");
child_container->add_child(grid_step_x);
grid_step_y=memnew(SpinBox);
grid_step_y->set_min(-SPIN_BOX_GRID_RANGE);
grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
grid_step_y->set_suffix("px");
child_container->add_child(grid_step_y);
container->add_child(memnew(HSeparator));
child_container = memnew(GridContainer);
child_container->set_columns(2);
container->add_child(child_container);
label = memnew(Label);
label->set_text("Rotation Offset:");
child_container->add_child(label);
rotation_offset=memnew(SpinBox);
rotation_offset->set_min(-SPIN_BOX_ROTATION_RANGE);
rotation_offset->set_max(SPIN_BOX_ROTATION_RANGE);
rotation_offset->set_suffix("deg");
child_container->add_child(rotation_offset);
label = memnew(Label);
label->set_text("Rotation Step:");
child_container->add_child(label);
rotation_step=memnew(SpinBox);
rotation_step->set_min(-SPIN_BOX_ROTATION_RANGE);
rotation_step->set_max(SPIN_BOX_ROTATION_RANGE);
rotation_step->set_suffix("deg");
child_container->add_child(rotation_step);
}
void set_fields(const Point2 p_grid_offset, const Size2 p_grid_step, const float p_rotation_offset, const float p_rotation_step) {
grid_offset_x->set_val(p_grid_offset.x);
grid_offset_y->set_val(p_grid_offset.y);
grid_step_x->set_val(p_grid_step.x);
grid_step_y->set_val(p_grid_step.y);
rotation_offset->set_val(p_rotation_offset * (180 / Math_PI));
rotation_step->set_val(p_rotation_step * (180 / Math_PI));
}
void get_fields(Point2 &p_grid_offset, Size2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
p_grid_offset.x = grid_offset_x->get_val();
p_grid_offset.y = grid_offset_y->get_val();
p_grid_step.x = grid_step_x->get_val();
p_grid_step.y = grid_step_y->get_val();
p_rotation_offset = rotation_offset->get_val() / (180 / Math_PI);
p_rotation_step = rotation_step->get_val() / (180 / Math_PI);
}
};
void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) {
if (!is_visible())
@ -75,9 +179,24 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
return memnew( CanvasItemEditorSelectedItem );
}
bool CanvasItemEditor::is_snap_active() const {
inline float _snap_scalar(float p_offset, float p_step, bool p_snap_relative, float p_target, float p_start) {
float offset = p_snap_relative ? p_start : p_offset;
return p_step != 0 ? Math::stepify(p_target - offset, p_step) + offset : p_target;
}
return edit_menu->get_popup()->is_item_checked(edit_menu->get_popup()->get_item_index(SNAP_USE));
Vector2 CanvasItemEditor::snap_point(Vector2 p_target, Vector2 p_start) const {
if (snap_grid) {
p_target.x = _snap_scalar(snap_offset.x, snap_step.x, snap_relative, p_target.x, p_start.x);
p_target.y = _snap_scalar(snap_offset.y, snap_step.y, snap_relative, p_target.y, p_start.y);
}
if (snap_pixel)
p_target = p_target.snapped(Size2(1, 1));
return p_target;
}
float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
return snap_rotation ? _snap_scalar(snap_rotation_offset, snap_rotation_step, snap_relative, p_target, p_start) : p_target;
}
Dictionary CanvasItemEditor::get_state() const {
@ -86,9 +205,15 @@ Dictionary CanvasItemEditor::get_state() const {
state["zoom"]=zoom;
state["ofs"]=Point2(h_scroll->get_val(),v_scroll->get_val());
// state["ofs"]=-transform.get_origin();
state["use_snap"]=is_snap_active();
state["snap_vec"]=Vector2(get_snap());
state["pixel_snap"]=pixel_snap;
state["snap_offset"]=snap_offset;
state["snap_step"]=snap_step;
state["snap_rotation_offset"]=snap_rotation_offset;
state["snap_rotation_step"]=snap_rotation_step;
state["snap_grid"]=snap_grid;
state["snap_show_grid"]=snap_show_grid;
state["snap_rotation"]=snap_rotation;
state["snap_relative"]=snap_relative;
state["snap_pixel"]=snap_pixel;
return state;
}
void CanvasItemEditor::set_state(const Dictionary& p_state){
@ -105,27 +230,50 @@ void CanvasItemEditor::set_state(const Dictionary& p_state){
v_scroll->set_val(ofs.y);
}
if (state.has("use_snap")) {
if (state.has("snap_step")) {
snap_step=state["snap_step"];
}
if (state.has("snap_offset")) {
snap_offset=state["snap_offset"];
}
if (state.has("snap_rotation_step")) {
snap_rotation_step=state["snap_rotation_step"];
}
if (state.has("snap_rotation_offset")) {
snap_rotation_offset=state["snap_rotation_offset"];
}
if (state.has("snap_grid")) {
snap_grid=state["snap_grid"];
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
edit_menu->get_popup()->set_item_checked(idx,state["use_snap"]);
edit_menu->get_popup()->set_item_checked(idx,snap_grid);
}
if (state.has("snap")) {
snap_x->set_val(state["snap"]);
snap_y->set_val(state["snap"]);
if (state.has("snap_show_grid")) {
snap_show_grid=state["snap_show_grid"];
int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
}
if (state.has("snap_vec")) {
Vector2 sv = state["snap_vec"];
snap_x->set_val(sv.x);
snap_y->set_val(sv.y);
viewport->update();
if (state.has("snap_rotation")) {
snap_rotation=state["snap_rotation"];
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
}
if (state.has("pixel_snap")) {
pixel_snap=state["pixel_snap"];
if (state.has("snap_relative")) {
snap_relative=state["snap_relative"];
int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
edit_menu->get_popup()->set_item_checked(idx,snap_relative);
}
if (state.has("snap_pixel")) {
snap_pixel=state["snap_pixel"];
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
edit_menu->get_popup()->set_item_checked(idx,pixel_snap);
edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
}
}
@ -294,9 +442,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@ -308,7 +454,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE
Vector2 drag = p_dir;
if (p_snap)
drag*=get_snap();
drag*=snap_step;
undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state());
@ -355,9 +501,7 @@ Point2 CanvasItemEditor::_find_topleftmost_point() {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
@ -385,9 +529,7 @@ int CanvasItemEditor::get_item_count() {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
ic++;
@ -406,9 +548,7 @@ CanvasItem *CanvasItemEditor::get_single_item() {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
if (single_item)
@ -562,13 +702,11 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *c) {
}
void CanvasItemEditor::_snap_changed(double) {
void CanvasItemEditor::_snap_changed() {
((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
viewport->update();
}
void CanvasItemEditor::_dialog_value_changed(double) {
if (updating_value_dialog)
@ -576,11 +714,6 @@ void CanvasItemEditor::_dialog_value_changed(double) {
switch(last_option) {
case SNAP_CONFIGURE: {
// snap=dialog_val->get_val();
viewport->update();
} break;
case ZOOM_SET: {
zoom=dialog_val->get_val()/100.0;
@ -676,9 +809,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
@ -750,9 +881,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@ -958,9 +1087,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@ -1083,9 +1210,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@ -1141,9 +1266,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@ -1168,39 +1291,21 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
if (drag==DRAG_ROTATE) {
Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
Matrix32 rot;
rot.elements[1] = (dfrom - center).normalized();
rot.elements[0] = rot.elements[1].tangent();
float ang = rot.xform_inv(dto-center).atan2();
canvas_item->edit_rotate(ang);
display_rotate_to = dto;
display_rotate_from = center;
if (Node2D *node = canvas_item->cast_to<Node2D>()) {
Matrix32 rot;
rot.elements[1] = (dfrom - center).normalized();
rot.elements[0] = rot.elements[1].tangent();
node->set_rot(snap_angle(rot.xform_inv(dto-center).atan2(), node->get_rot()));
display_rotate_to = dto;
display_rotate_from = center;
viewport->update();
}
continue;
}
if (pixel_snap || (is_snap_active() && get_snap().x>0 && get_snap().y>0)) {
if (drag!=DRAG_ALL) {
dfrom=drag_point_from;
dto=snapify(dto);
} else {
Vector2 newpos = drag_point_from + (dto-dfrom);
Vector2 disp;
if (!is_snap_active() || get_snap().x<1 || get_snap().y<1) {
disp.x = Math::fposmod(newpos.x,1);
disp.y = Math::fposmod(newpos.y,1);
} else {
disp.x = Math::fposmod(newpos.x,get_snap().x);
disp.y = Math::fposmod(newpos.y,get_snap().y);
}
dto-=disp;
}
}
dfrom = drag_point_from;
dto = snap_point(dto - (drag == DRAG_ALL ? drag_from - drag_point_from : Vector2(0, 0)), drag_point_from);
Vector2 drag_vector =
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
@ -1308,8 +1413,6 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) {
if (!dragging_bone) {
local_rect.pos=begin;
@ -1492,32 +1595,32 @@ void CanvasItemEditor::_viewport_draw() {
_update_scrollbars();
RID ci=viewport->get_canvas_item();
if (get_snap().x>0 && get_snap().y>0 && is_snap_active() && true ) {
if (snap_show_grid) {
Size2 s = viewport->get_size();
int last_cell;
Matrix32 xform = transform.affine_inverse();
for(int i=0;i<s.width;i++) {
int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(i,0)).x/get_snap().x));
if (i==0)
if (snap_step.x!=0) {
for(int i=0;i<s.width;i++) {
int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x));
if (i==0)
last_cell=cell;
if (last_cell!=cell)
viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
last_cell=cell;
if (last_cell!=cell)
viewport->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3));
last_cell=cell;
}
}
for(int i=0;i<s.height;i++) {
int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(0,i)).y/get_snap().y));
if (i==0)
if (snap_step.y!=0) {
for(int i=0;i<s.height;i++) {
int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y));
if (i==0)
last_cell=cell;
if (last_cell!=cell)
viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
last_cell=cell;
if (last_cell!=cell)
viewport->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3));
last_cell=cell;
}
}
}
if (viewport->has_focus()) {
@ -1545,9 +1648,7 @@ void CanvasItemEditor::_viewport_draw() {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
if (!se)
@ -1764,9 +1865,7 @@ void CanvasItemEditor::_notification(int p_what) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
@ -1824,8 +1923,6 @@ void CanvasItemEditor::_notification(int p_what) {
group_button->set_icon(get_icon("Group","EditorIcons"));
ungroup_button->set_icon(get_icon("Ungroup","EditorIcons"));
key_insert_button->set_icon(get_icon("Key","EditorIcons"));
snap_x->connect("value_changed",this,"_snap_changed");
snap_y->connect("value_changed",this,"_snap_changed");
}
@ -2013,90 +2110,40 @@ void CanvasItemEditor::_update_scroll(float) {
}
Point2 CanvasItemEditor::snapify(const Point2& p_pos) const {
bool active=is_snap_active();
Vector2 pos = p_pos;
if (!active || get_snap().x<1 || get_snap().y<1) {
if (pixel_snap) {
pos.x=Math::stepify(pos.x,1);
pos.y=Math::stepify(pos.y,1);
}
return pos;
}
pos.x=Math::stepify(pos.x,get_snap().x);
pos.y=Math::stepify(pos.y,get_snap().y);
return pos;
}
void CanvasItemEditor::_popup_callback(int p_op) {
last_option=MenuOption(p_op);
switch(p_op) {
case SNAP_USE: {
snap_grid = !snap_grid;
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
edit_menu->get_popup()->set_item_checked( idx,!edit_menu->get_popup()->is_item_checked(0));
edit_menu->get_popup()->set_item_checked(idx,snap_grid);
} break;
case SNAP_SHOW_GRID: {
snap_show_grid = !snap_show_grid;
int idx = edit_menu->get_popup()->get_item_index(SNAP_SHOW_GRID);
edit_menu->get_popup()->set_item_checked(idx,snap_show_grid);
viewport->update();
} break;
case SNAP_USE_PIXEL: {
pixel_snap = ! pixel_snap;
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
edit_menu->get_popup()->set_item_checked(idx,pixel_snap);
case SNAP_USE_ROTATION: {
snap_rotation = !snap_rotation;
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
edit_menu->get_popup()->set_item_checked(idx,snap_rotation);
} break;
case SNAP_OBJECT_CENTERS: {
List<Node*> &selection = editor_selection->get_selected_node_list();
undo_redo->create_action("Snap Object Centers");
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
continue;
Node2D* node = canvas_item->cast_to<Node2D>();
if (!node)
continue;
Matrix32 gtrans = node->get_global_transform();
gtrans.elements[2]=snapify(gtrans.elements[2]);
undo_redo->add_do_method(node,"set_global_transform",gtrans);
undo_redo->add_undo_method(node,"set_global_transform",node->get_global_transform());
}
undo_redo->add_do_method(viewport,"update");
undo_redo->add_undo_method(viewport,"update");
undo_redo->commit_action();
case SNAP_RELATIVE: {
snap_relative = !snap_relative;
int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
edit_menu->get_popup()->set_item_checked(idx,snap_relative);
} break;
case SNAP_USE_PIXEL: {
snap_pixel = !snap_pixel;
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
edit_menu->get_popup()->set_item_checked(idx,snap_pixel);
} break;
case SNAP_CONFIGURE: {
updating_value_dialog=true;
snap_dialog->popup_centered_minsize();
/*
dialog_label->set_text("Snap (Pixels):");
dialog_val->set_min(1);
dialog_val->set_step(1);
dialog_val->set_max(4096);
dialog_val->set_val(snap);
value_dialog->popup_centered(Size2(200,85));
*/
updating_value_dialog=false;
((SnapDialog *)snap_dialog)->set_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
snap_dialog->popup_centered(Size2(200,160));
} break;
case ZOOM_IN: {
zoom=zoom*(1.0/0.5);
@ -2140,9 +2187,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
canvas_item->set_meta("_edit_lock_",true);
@ -2157,9 +2202,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
@ -2177,9 +2220,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
canvas_item->set_meta("_edit_group_",true);
@ -2194,9 +2235,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
canvas_item->set_meta("_edit_group_",Variant());
@ -2214,9 +2253,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
@ -2284,9 +2321,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
if (canvas_item->cast_to<Node2D>()) {
@ -2396,9 +2431,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
@ -2448,9 +2481,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(Map<Node*,Object*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->key()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
if (canvas_item->cast_to<Node2D>()) {
@ -2576,9 +2607,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
for(List<Node*>::Element *E=selection.front();E;E=E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
if (!canvas_item)
continue;
if (!canvas_item->is_visible())
if (!canvas_item || !canvas_item->is_visible())
continue;
@ -2858,10 +2887,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
PopupMenu *p;
p = edit_menu->get_popup();
p->add_check_item("Use Snap",SNAP_USE);
p->add_check_item("Show Grid",SNAP_SHOW_GRID);
p->add_check_item("Use Rotation Snap",SNAP_USE_ROTATION);
p->add_check_item("Snap Relative",SNAP_RELATIVE);
p->add_item("Configure Snap..",SNAP_CONFIGURE);
p->add_separator();
p->add_check_item("Use Pixel Snap",SNAP_USE_PIXEL);
p->add_item("Snap Selected Object Centers",SNAP_OBJECT_CENTERS);
p->add_separator();
p->add_item("Expand to Parent",EXPAND_TO_PARENT,KEY_MASK_CMD|KEY_P);
p->add_separator();
@ -2949,6 +2980,10 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
p->add_item("Paste Pose",ANIM_PASTE_POSE);
p->add_item("Clear Pose",ANIM_CLEAR_POSE,KEY_MASK_SHIFT|KEY_K);
snap_dialog = memnew(SnapDialog);
snap_dialog->connect("confirmed",this,"_snap_changed");
add_child(snap_dialog);
value_dialog = memnew( AcceptDialog );
value_dialog->set_title("Set a Value");
value_dialog->get_ok()->set_text("Close");
@ -2968,33 +3003,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
dialog_val->connect("value_changed",this,"_dialog_value_changed");
select_sb = Ref<StyleBoxTexture>( memnew( StyleBoxTexture) );
snap_dialog = memnew( AcceptDialog );
VBoxContainer *snap_vb = memnew( VBoxContainer );
snap_dialog->add_child(snap_vb);
snap_dialog->set_child_rect(snap_vb);
snap_dialog->set_title("Snap Configuration");
snap_x = memnew( SpinBox );
snap_x->set_custom_minimum_size(Size2(250,0));
snap_y = memnew( SpinBox );
snap_x->set_min(1);
snap_x->set_max(4096);
snap_x->set_step(1);
snap_x->set_val(10);
snap_y->set_min(1);
snap_y->set_max(4096);
snap_y->set_step(1);
snap_y->set_val(10);
snap_vb->add_margin_child("Snap X",snap_x);
snap_vb->add_margin_child("Snap Y",snap_y);
add_child(snap_dialog);
key_pos=true;
key_rot=true;
key_scale=false;
zoom=1;
//snap=10;
snap_offset=Vector2(0, 0);
snap_step=Vector2(10, 10);
snap_rotation_offset=0;
snap_rotation_step=15 / (180 / Math_PI);
snap_grid=false;
snap_show_grid=false;
snap_rotation=false;
snap_pixel=false;
updating_value_dialog=false;
box_selecting=false;
//zoom=0.5;
@ -3002,7 +3023,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
editor->get_animation_editor()->connect("keying_changed",this,"_keying_changed");
set_process_unhandled_key_input(true);
can_move_pivot=false;
pixel_snap=false;
drag=DRAG_NONE;
}

View file

@ -75,9 +75,11 @@ class CanvasItemEditor : public VBoxContainer {
enum MenuOption {
SNAP_USE,
SNAP_SHOW_GRID,
SNAP_USE_ROTATION,
SNAP_RELATIVE,
SNAP_CONFIGURE,
SNAP_USE_PIXEL,
SNAP_OBJECT_CENTERS,
ZOOM_IN,
ZOOM_OUT,
ZOOM_RESET,
@ -144,7 +146,15 @@ class CanvasItemEditor : public VBoxContainer {
Matrix32 transform;
float zoom;
bool pixel_snap;
Vector2 snap_offset;
Vector2 snap_step;
float snap_rotation_step;
float snap_rotation_offset;
bool snap_grid;
bool snap_show_grid;
bool snap_rotation;
bool snap_relative;
bool snap_pixel;
bool box_selecting;
Point2 box_selecting_to;
bool key_pos;
@ -247,14 +257,12 @@ class CanvasItemEditor : public VBoxContainer {
CanvasItem* _select_canvas_item_at_pos(const Point2 &p_pos,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform);
void _find_canvas_items_at_rect(const Rect2& p_rect,Node* p_node,const Matrix32& p_parent_xform,const Matrix32& p_canvas_xform,List<CanvasItem*> *r_items);
ConfirmationDialog *snap_dialog;
AcceptDialog *value_dialog;
Label *dialog_label;
SpinBox *dialog_val;
AcceptDialog *snap_dialog;
SpinBox *snap_x;
SpinBox *snap_y;
CanvasItem *ref_item;
void _add_canvas_item(CanvasItem *p_canvas_item);
@ -265,7 +273,6 @@ class CanvasItemEditor : public VBoxContainer {
DragType _find_drag_type(const Matrix32& p_xform, const Rect2& p_local_rect, const Point2& p_click, Vector2& r_point);
Point2 snapify(const Point2& p_pos) const;
void _popup_callback(int p_op);
bool updating_scroll;
void _update_scroll(float);
@ -275,6 +282,7 @@ class CanvasItemEditor : public VBoxContainer {
void _append_canvas_item(CanvasItem *p_item);
void _dialog_value_changed(double);
void _snap_changed();
UndoRedo *undo_redo;
Point2 _find_topleftmost_point();
@ -293,7 +301,6 @@ class CanvasItemEditor : public VBoxContainer {
void _viewport_input_event(const InputEvent& p_event);
void _viewport_draw();
void _snap_changed(double);
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
@ -339,8 +346,8 @@ protected:
static CanvasItemEditor *singleton;
public:
bool is_snap_active() const;
Size2i get_snap() const { return Size2i(snap_x->get_val(),snap_y->get_val()); }
Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
float snap_angle(float p_target, float p_start = 0) const;
Matrix32 get_canvas_transform() const { return transform; }

View file

@ -35,17 +35,6 @@ void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
}
Vector2 CollisionPolygon2DEditor::snap_point(const Vector2& p_point) const {
if (canvas_item_editor->is_snap_active()) {
return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
} else {
return p_point;
}
}
void CollisionPolygon2DEditor::_menu_option(int p_option) {
switch(p_option) {
@ -99,7 +88,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
Vector<Vector2> poly = node->get_polygon();
@ -302,7 +291,7 @@ bool CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();

View file

@ -53,7 +53,6 @@ protected:
static void _bind_methods();
public:
Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_collision_polygon);
CollisionPolygon2DEditor(EditorNode *p_editor);

View file

@ -70,19 +70,6 @@ void CollisionPolygonEditor::_node_removed(Node *p_node) {
}
Vector2 CollisionPolygonEditor::snap_point(const Vector2& p_point) const {
return p_point;
if (CanvasItemEditor::get_singleton()->is_snap_active()) {
return p_point.snapped(Vector2(1,1)*CanvasItemEditor::get_singleton()->get_snap());
} else {
return p_point;
}
}
void CollisionPolygonEditor::_menu_option(int p_option) {
switch(p_option) {
@ -150,7 +137,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const
Vector2 cpoint(spoint.x,spoint.y);
cpoint=snap_point(cpoint);
cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
Vector<Vector2> poly = node->get_polygon();
@ -364,7 +351,7 @@ bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const
Vector2 cpoint(spoint.x,spoint.y);
cpoint=snap_point(cpoint);
cpoint=CanvasItemEditor::get_singleton()->snap_point(cpoint);
edited_point_pos = cpoint;
_polygon_draw();

View file

@ -90,7 +90,6 @@ protected:
static void _bind_methods();
public:
Vector2 snap_point(const Vector2& p_point) const;
virtual bool forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event);
void edit(Node *p_collision_polygon);
CollisionPolygonEditor(EditorNode *p_editor);

View file

@ -35,17 +35,6 @@ void LightOccluder2DEditor::_node_removed(Node *p_node) {
}
Vector2 LightOccluder2DEditor::snap_point(const Vector2& p_point) const {
if (canvas_item_editor->is_snap_active()) {
return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
} else {
return p_point;
}
}
void LightOccluder2DEditor::_menu_option(int p_option) {
switch(p_option) {
@ -109,7 +98,7 @@ bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon());
@ -317,7 +306,7 @@ bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();

View file

@ -45,17 +45,6 @@ void NavigationPolygonEditor::_create_nav() {
undo_redo->commit_action();
}
Vector2 NavigationPolygonEditor::snap_point(const Vector2& p_point) const {
if (canvas_item_editor->is_snap_active()) {
return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
} else {
return p_point;
}
}
void NavigationPolygonEditor::_menu_option(int p_option) {
switch(p_option) {
@ -125,7 +114,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
@ -373,7 +362,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();

View file

@ -59,7 +59,6 @@ protected:
static void _bind_methods();
public:
Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_collision_polygon);
NavigationPolygonEditor(EditorNode *p_editor);

View file

@ -62,17 +62,6 @@ void Path2DEditor::_node_removed(Node *p_node) {
}
Vector2 Path2DEditor::snap_point(const Vector2& p_point) const {
if (canvas_item_editor->is_snap_active()) {
return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
} else {
return p_point;
}
}
bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
if (!node)
@ -93,8 +82,8 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = !mb.mod.alt? snap_point(xform.affine_inverse().xform(gpoint))
: node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
Vector2 cpoint = !mb.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
: node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
//first check if a point is to be added (segment split)
real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8);
@ -250,9 +239,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
if (!wip_active) {
wip.clear();
wip.push_back( snap_point(cpoint) );
wip.push_back( canvas_item_editor->snap_point(cpoint) );
wip_active=true;
edited_point_pos=snap_point(cpoint);
edited_point_pos=canvas_item_editor->snap_point(cpoint);
canvas_item_editor->update();
edited_point=1;
return true;
@ -265,7 +254,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
return true;
} else {
wip.push_back( snap_point(cpoint) );
wip.push_back( canvas_item_editor->snap_point(cpoint) );
edited_point=wip.size();
canvas_item_editor->update();
return true;
@ -327,9 +316,9 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
if (closest_idx>=0) {
pre_move_edit=poly;
poly.insert(closest_idx+1,snap_point(xform.affine_inverse().xform(closest_pos)));
poly.insert(closest_idx+1,canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos)));
edited_point=closest_idx+1;
edited_point_pos=snap_point(xform.affine_inverse().xform(closest_pos));
edited_point_pos=canvas_item_editor->snap_point(xform.affine_inverse().xform(closest_pos));
node->set_polygon(poly);
canvas_item_editor->update();
return true;
@ -434,8 +423,8 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = !mm.mod.alt? snap_point(xform.affine_inverse().xform(gpoint))
: node->get_global_transform().affine_inverse().xform( snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
Vector2 cpoint = !mm.mod.alt? canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint))
: node->get_global_transform().affine_inverse().xform( canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint)) );
Ref<Curve2D> curve = node->get_curve();
@ -471,7 +460,7 @@ bool Path2DEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
Vector2 gpoint = Point2(mm.x,mm.y);
edited_point_pos = snap_point(xform.affine_inverse().xform(gpoint));
edited_point_pos = canvas_item_editor->snap_point(xform.affine_inverse().xform(gpoint));
canvas_item_editor->update();
}

View file

@ -94,7 +94,6 @@ protected:
static void _bind_methods();
public:
Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_path2d);
Path2DEditor(EditorNode *p_editor);

View file

@ -69,17 +69,6 @@ void Polygon2DEditor::_node_removed(Node *p_node) {
}
Vector2 Polygon2DEditor::snap_point(const Vector2& p_point) const {
if (canvas_item_editor->is_snap_active()) {
return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
} else {
return p_point;
}
}
void Polygon2DEditor::_menu_option(int p_option) {
switch(p_option) {
@ -201,7 +190,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mb.x,mb.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
cpoint = node->get_global_transform().affine_inverse().xform(cpoint);
@ -405,7 +394,7 @@ bool Polygon2DEditor::forward_input_event(const InputEvent& p_event) {
Vector2 gpoint = Point2(mm.x,mm.y);
Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint);
cpoint=snap_point(cpoint);
cpoint=canvas_item_editor->snap_point(cpoint);
edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint);
canvas_item_editor->get_viewport_control()->update();

View file

@ -92,7 +92,6 @@ protected:
static void _bind_methods();
public:
Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_collision_polygon);
Polygon2DEditor(EditorNode *p_editor);

View file

@ -116,7 +116,6 @@ protected:
public:
HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; }
Vector2 snap_point(const Vector2& p_point) const;
bool forward_input_event(const InputEvent& p_event);
void edit(Node *p_tile_map);
TileMapEditor(EditorNode *p_editor);