diff options
author | Anton Yabchinskiy <arn@bestmx.ru> | 2015-03-10 11:44:40 +0300 |
---|---|---|
committer | Anton Yabchinskiy <arn@bestmx.ru> | 2015-03-10 11:44:40 +0300 |
commit | 43713810deaadfec6a1656767cf5520073e58a06 (patch) | |
tree | 8b1c7e82562494e1889b1550b58b3d953f076696 /tools/editor | |
parent | 19a99afa81354ed69e1c07b6050aeb438e4ee2cb (diff) | |
parent | 91744e9ed3124ca48e0837ee72bfe7182fd31701 (diff) |
Merge branch 'master' of https://github.com/okamstudio/godot
Diffstat (limited to 'tools/editor')
25 files changed, 1035 insertions, 129 deletions
diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 6399d0f909..e6ec11e9d3 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -904,6 +904,16 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func return OK; } +static int _get_pad(int p_alignment, int p_n) { + + int rest = p_n % p_alignment; + int pad = 0; + if (rest > 0) { + pad = p_alignment - rest; + }; + + return pad; +}; Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) { @@ -930,11 +940,19 @@ Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path pd->ep->step("Storing File: "+p_path,2+p_file*100/p_total); pd->count++; pd->ftmp->store_buffer(p_data.ptr(),p_data.size()); + if (pd->alignment > 1) { + + int pad = _get_pad(pd->alignment, pd->ftmp->get_pos()); + for (int i=0; i<pad; i++) { + + pd->ftmp->store_8(0); + }; + }; return OK; } -Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) { +Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles, int p_alignment) { EditorProgress ep("savepack","Packing",102); @@ -952,7 +970,6 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) { dst->store_32(0); } - size_t fcountpos = dst->get_pos(); dst->store_32(0); @@ -961,11 +978,20 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) { pd.f=dst; pd.ftmp=tmp; pd.count=0; + pd.alignment = p_alignment; Error err = export_project_files(save_pack_file,&pd,p_make_bundles); memdelete(tmp); if (err) return err; + if (p_alignment > 1) { + int pad = _get_pad(p_alignment, dst->get_pos()); + for (int i=0; i<pad; i++) { + + dst->store_8(0); + }; + }; + size_t ofsplus = dst->get_pos(); //append file diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h index cd24fa076b..a4723f41d0 100644 --- a/tools/editor/editor_import_export.h +++ b/tools/editor/editor_import_export.h @@ -100,6 +100,7 @@ protected: Vector<TempData> file_ofs; EditorProgress *ep; int count; + int alignment; }; @@ -121,7 +122,7 @@ public: Error export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles); - Error save_pack(FileAccess *p_where, bool p_make_bundles=false); + Error save_pack(FileAccess *p_where, bool p_make_bundles=false, int p_alignment = 1); virtual String get_name() const =0; virtual ImageCompression get_image_compression() const=0; virtual Ref<Texture> get_logo() const =0; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index cc1a05f7d3..3d42867d9a 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -90,6 +90,7 @@ #include "plugins/baked_light_editor_plugin.h" #include "plugins/polygon_2d_editor_plugin.h" #include "plugins/navigation_polygon_editor_plugin.h" +#include "plugins/light_occluder_2d_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" @@ -4115,6 +4116,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( PathEditorPlugin(this) ) ); add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) ); add_editor_plugin( memnew( Polygon2DEditorPlugin(this) ) ); + add_editor_plugin( memnew( LightOccluder2DEditorPlugin(this) ) ); add_editor_plugin( memnew( NavigationPolygonEditorPlugin(this) ) ); for(int i=0;i<EditorPlugins::get_plugin_count();i++) diff --git a/tools/editor/icons/icon_canvas_item_material.png b/tools/editor/icons/icon_canvas_item_material.png Binary files differnew file mode 100644 index 0000000000..2fe8921653 --- /dev/null +++ b/tools/editor/icons/icon_canvas_item_material.png diff --git a/tools/editor/icons/icon_canvas_modulate.png b/tools/editor/icons/icon_canvas_modulate.png Binary files differnew file mode 100644 index 0000000000..2a34df7793 --- /dev/null +++ b/tools/editor/icons/icon_canvas_modulate.png diff --git a/tools/editor/icons/icon_light_occluder_2d.png b/tools/editor/icons/icon_light_occluder_2d.png Binary files differnew file mode 100644 index 0000000000..c66dd536d3 --- /dev/null +++ b/tools/editor/icons/icon_light_occluder_2d.png diff --git a/tools/editor/icons/icon_occluder_polygon_2d.png b/tools/editor/icons/icon_occluder_polygon_2d.png Binary files differnew file mode 100644 index 0000000000..705794b729 --- /dev/null +++ b/tools/editor/icons/icon_occluder_polygon_2d.png diff --git a/tools/editor/icons/icon_rotate_0.png b/tools/editor/icons/icon_rotate_0.png Binary files differnew file mode 100644 index 0000000000..85a4b4c420 --- /dev/null +++ b/tools/editor/icons/icon_rotate_0.png diff --git a/tools/editor/icons/icon_rotate_180.png b/tools/editor/icons/icon_rotate_180.png Binary files differnew file mode 100644 index 0000000000..c4c516cff5 --- /dev/null +++ b/tools/editor/icons/icon_rotate_180.png diff --git a/tools/editor/icons/icon_rotate_270.png b/tools/editor/icons/icon_rotate_270.png Binary files differnew file mode 100644 index 0000000000..6e0f2e62b8 --- /dev/null +++ b/tools/editor/icons/icon_rotate_270.png diff --git a/tools/editor/icons/icon_rotate_90.png b/tools/editor/icons/icon_rotate_90.png Binary files differnew file mode 100644 index 0000000000..f25b0e99a3 --- /dev/null +++ b/tools/editor/icons/icon_rotate_90.png diff --git a/tools/editor/icons/icon_transpose.png b/tools/editor/icons/icon_transpose.png Binary files differnew file mode 100644 index 0000000000..f9b78bc0fd --- /dev/null +++ b/tools/editor/icons/icon_transpose.png diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp index 529ed3374b..6dd46843cc 100644 --- a/tools/editor/io_plugins/editor_import_collada.cpp +++ b/tools/editor/io_plugins/editor_import_collada.cpp @@ -285,13 +285,16 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { case Collada::CameraData::MODE_ORTHOGONAL: { - if (cd.orthogonal.x_mag) { + if (cd.orthogonal.y_mag) { - camera->set_orthogonal(cd.orthogonal.x_mag,cd.z_near,cd.z_far); + camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT); + camera->set_orthogonal(cd.orthogonal.y_mag*2.0 ,cd.z_near,cd.z_far); - } else if (!cd.orthogonal.x_mag && cd.orthogonal.y_mag) { + } else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) { - camera->set_orthogonal(cd.orthogonal.y_mag * cd.aspect,cd.z_near,cd.z_far); + + camera->set_keep_aspect_mode(Camera::KEEP_WIDTH); + camera->set_orthogonal(cd.orthogonal.x_mag*2.0,cd.z_near,cd.z_far); } } break; diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp index 42a185b7c2..184f80a1b7 100644 --- a/tools/editor/plugins/baked_light_baker.cpp +++ b/tools/editor/plugins/baked_light_baker.cpp @@ -1233,7 +1233,7 @@ float BakedLightBaker::_throw_ray(ThreadStack& thread_stack,bool p_bake_direct,c if (dist<r) { //avoid accumulaiton of light on corners //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size); - skip-true; + skip=true; } else { diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 514f4b6525..fdec72332e 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -87,7 +87,7 @@ Dictionary CanvasItemEditor::get_state() const { state["ofs"]=Point2(h_scroll->get_val(),v_scroll->get_val()); // state["ofs"]=-transform.get_origin(); state["use_snap"]=is_snap_active(); - state["snap"]=snap; + state["snap_vec"]=Vector2(get_snap()); state["pixel_snap"]=pixel_snap; return state; } @@ -111,7 +111,15 @@ void CanvasItemEditor::set_state(const Dictionary& p_state){ } if (state.has("snap")) { - snap=state["snap"]; + snap_x->set_val(state["snap"]); + snap_y->set_val(state["snap"]); + } + + 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("pixel_snap")) { @@ -300,7 +308,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE Vector2 drag = p_dir; if (p_snap) - drag*=snap; + drag*=get_snap(); undo_redo->add_undo_method(canvas_item,"edit_set_state",canvas_item->edit_get_state()); @@ -554,6 +562,13 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *c) { } +void CanvasItemEditor::_snap_changed(double) { + + viewport->update(); +} + + + void CanvasItemEditor::_dialog_value_changed(double) { if (updating_value_dialog) @@ -563,7 +578,7 @@ void CanvasItemEditor::_dialog_value_changed(double) { case SNAP_CONFIGURE: { - snap=dialog_val->get_val(); + // snap=dialog_val->get_val(); viewport->update(); } break; case ZOOM_SET: { @@ -1165,7 +1180,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { continue; } - if (pixel_snap || (is_snap_active() && snap>0)) { + if (pixel_snap || (is_snap_active() && get_snap().x>0 && get_snap().y>0)) { if (drag!=DRAG_ALL) { dfrom=drag_point_from; @@ -1174,14 +1189,14 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { Vector2 newpos = drag_point_from + (dto-dfrom); Vector2 disp; - if (!is_snap_active() || snap<1) { + 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,snap); - disp.y = Math::fposmod(newpos.y,snap); + disp.x = Math::fposmod(newpos.x,get_snap().x); + disp.y = Math::fposmod(newpos.y,get_snap().y); } dto-=disp; } @@ -1477,7 +1492,7 @@ void CanvasItemEditor::_viewport_draw() { _update_scrollbars(); RID ci=viewport->get_canvas_item(); - if (snap>0 && is_snap_active() && true ) { + if (get_snap().x>0 && get_snap().y>0 && is_snap_active() && true ) { Size2 s = viewport->get_size(); @@ -1485,7 +1500,7 @@ void CanvasItemEditor::_viewport_draw() { 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/snap)); + int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(i,0)).x/get_snap().x)); if (i==0) last_cell=cell; if (last_cell!=cell) @@ -1495,7 +1510,7 @@ void CanvasItemEditor::_viewport_draw() { for(int i=0;i<s.height;i++) { - int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(0,i)).y/snap)); + int cell = Math::fast_ftoi(Math::floor(xform.xform(Vector2(0,i)).y/get_snap().y)); if (i==0) last_cell=cell; if (last_cell!=cell) @@ -1809,6 +1824,8 @@ 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"); } @@ -2002,7 +2019,7 @@ Point2 CanvasItemEditor::snapify(const Point2& p_pos) const { Vector2 pos = p_pos; - if (!active || snap<1) { + if (!active || get_snap().x<1 || get_snap().y<1) { if (pixel_snap) { @@ -2014,8 +2031,8 @@ Point2 CanvasItemEditor::snapify(const Point2& p_pos) const { } - pos.x=Math::stepify(pos.x,snap); - pos.y=Math::stepify(pos.y,snap); + pos.x=Math::stepify(pos.x,get_snap().x); + pos.y=Math::stepify(pos.y,get_snap().y); return pos; @@ -2038,15 +2055,46 @@ void CanvasItemEditor::_popup_callback(int p_op) { int idx = edit_menu->get_popup()->get_item_index(SNAP_USE_PIXEL); edit_menu->get_popup()->set_item_checked(idx,pixel_snap); } 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(); + + } 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; } break; @@ -2604,6 +2652,7 @@ void CanvasItemEditor::_bind_methods() { ObjectTypeDB::bind_method("_unhandled_key_input",&CanvasItemEditor::_unhandled_key_input); ObjectTypeDB::bind_method("_viewport_draw",&CanvasItemEditor::_viewport_draw); ObjectTypeDB::bind_method("_viewport_input_event",&CanvasItemEditor::_viewport_input_event); + ObjectTypeDB::bind_method("_snap_changed",&CanvasItemEditor::_snap_changed); ADD_SIGNAL( MethodInfo("item_lock_status_changed") ); ADD_SIGNAL( MethodInfo("item_group_status_changed") ); @@ -2812,6 +2861,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { 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(); @@ -2918,12 +2968,33 @@ 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=10; updating_value_dialog=false; box_selecting=false; //zoom=0.5; diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 6648d486e8..9160742826 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -77,6 +77,7 @@ class CanvasItemEditor : public VBoxContainer { SNAP_USE, SNAP_CONFIGURE, SNAP_USE_PIXEL, + SNAP_OBJECT_CENTERS, ZOOM_IN, ZOOM_OUT, ZOOM_RESET, @@ -143,7 +144,6 @@ class CanvasItemEditor : public VBoxContainer { Matrix32 transform; float zoom; - int snap; bool pixel_snap; bool box_selecting; Point2 box_selecting_to; @@ -250,7 +250,11 @@ class CanvasItemEditor : public VBoxContainer { 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); @@ -289,6 +293,7 @@ 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; @@ -335,7 +340,7 @@ protected: public: bool is_snap_active() const; - int get_snap() const { return snap; } + Size2i get_snap() const { return Size2i(snap_x->get_val(),snap_y->get_val()); } Matrix32 get_canvas_transform() const { return transform; } diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp index ed228e9a1c..9a0d5b4066 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -4,6 +4,7 @@ #include "os/file_access.h" #include "tools/editor/editor_settings.h" + void CollisionPolygon2DEditor::_notification(int p_what) { switch(p_what) { @@ -368,6 +369,7 @@ void CollisionPolygon2DEditor::edit(Node *p_collision_polygon) { wip.clear(); wip_active=false; edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); } else { node=NULL; diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp new file mode 100644 index 0000000000..5fa3d8ac8f --- /dev/null +++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -0,0 +1,502 @@ +#include "light_occluder_2d_editor_plugin.h" + +#include "canvas_item_editor_plugin.h" +#include "os/file_access.h" +#include "tools/editor/editor_settings.h" + +void LightOccluder2DEditor::_notification(int p_what) { + + switch(p_what) { + + case NOTIFICATION_READY: { + + button_create->set_icon( get_icon("Edit","EditorIcons")); + button_edit->set_icon( get_icon("MovePoint","EditorIcons")); + button_edit->set_pressed(true); + get_tree()->connect("node_removed",this,"_node_removed"); + create_poly->connect("confirmed",this,"_create_poly"); + + } break; + case NOTIFICATION_FIXED_PROCESS: { + + + } break; + } + +} +void LightOccluder2DEditor::_node_removed(Node *p_node) { + + if(p_node==node) { + node=NULL; + hide(); + canvas_item_editor->get_viewport_control()->update(); + } + +} + + +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) { + + case MODE_CREATE: { + + mode=MODE_CREATE; + button_create->set_pressed(true); + button_edit->set_pressed(false); + } break; + case MODE_EDIT: { + + mode=MODE_EDIT; + button_create->set_pressed(false); + button_edit->set_pressed(true); + } break; + + } +} + +void LightOccluder2DEditor::_wip_close(bool p_closed) { + + undo_redo->create_action("Create Poly"); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",node->get_occluder_polygon()->get_polygon()); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",wip); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_closed",node->get_occluder_polygon()->is_closed()); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_closed",p_closed); + + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + wip.clear(); + wip_active=false; + mode=MODE_EDIT; + button_edit->set_pressed(true); + button_create->set_pressed(false); + edited_point=-1; +} + +bool LightOccluder2DEditor::forward_input_event(const InputEvent& p_event) { + + + if (!node) + return false; + + if (node->get_occluder_polygon().is_null()) { + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + create_poly->set_text("No OccluderPolygon2D resource on this node.\nCreate and assign one?"); + create_poly->popup_centered_minsize(); + } + return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1); + } + switch(p_event.type) { + + case InputEvent::MOUSE_BUTTON: { + + const InputEventMouseButton &mb=p_event.mouse_button; + + Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + + + Vector2 gpoint = Point2(mb.x,mb.y); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint=snap_point(cpoint); + cpoint = node->get_global_transform().affine_inverse().xform(cpoint); + + Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon()); + + //first check if a point is to be added (segment split) + real_t grab_treshold=EDITOR_DEF("poly_editor/point_grab_radius",8); + + switch(mode) { + + + case MODE_CREATE: { + + if (mb.button_index==BUTTON_LEFT && mb.pressed) { + + + if (!wip_active) { + + wip.clear(); + wip.push_back( cpoint ); + wip_active=true; + edited_point_pos=cpoint; + canvas_item_editor->get_viewport_control()->update(); + edited_point=1; + return true; + } else { + + + if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) { + //wip closed + _wip_close(true); + + return true; + } else if (wip.size()>1 && xform.xform(wip[wip.size()-1]).distance_to(gpoint)<grab_treshold) { + //wip closed + _wip_close(false); + return true; + + } else { + + wip.push_back( cpoint ); + edited_point=wip.size(); + canvas_item_editor->get_viewport_control()->update(); + return true; + + //add wip point + } + } + } else if (mb.button_index==BUTTON_RIGHT && mb.pressed && wip_active) { + _wip_close(true); + } + + + + } break; + + case MODE_EDIT: { + + if (mb.button_index==BUTTON_LEFT) { + if (mb.pressed) { + + if (mb.mod.control) { + + + if (poly.size() < 3) { + + undo_redo->create_action("Edit Poly"); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + poly.push_back(cpoint); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + return true; + } + + //search edges + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + for(int i=0;i<poly.size();i++) { + + Vector2 points[2] ={ xform.xform(poly[i]), + xform.xform(poly[(i+1)%poly.size()]) }; + + Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint,points); + if (cp.distance_squared_to(points[0])<CMP_EPSILON2 || cp.distance_squared_to(points[1])<CMP_EPSILON2) + continue; //not valid to reuse point + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_idx=i; + } + + + } + + if (closest_idx>=0) { + + pre_move_edit=poly; + poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos)); + edited_point=closest_idx+1; + edited_point_pos=xform.affine_inverse().xform(closest_pos); + node->get_occluder_polygon()->set_polygon(Variant(poly)); + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } else { + + //look for points to move + + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + for(int i=0;i<poly.size();i++) { + + Vector2 cp =xform.xform(poly[i]); + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_idx=i; + } + + } + + if (closest_idx>=0) { + + pre_move_edit=poly; + edited_point=closest_idx; + edited_point_pos=xform.affine_inverse().xform(closest_pos); + canvas_item_editor->get_viewport_control()->update(); + return true; + } + } + } else { + + if (edited_point!=-1) { + + //apply + + ERR_FAIL_INDEX_V(edited_point,poly.size(),false); + poly[edited_point]=edited_point_pos; + undo_redo->create_action("Edit Poly"); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",pre_move_edit); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + + edited_point=-1; + return true; + } + } + } if (mb.button_index==BUTTON_RIGHT && mb.pressed && edited_point==-1) { + + + + int closest_idx=-1; + Vector2 closest_pos; + real_t closest_dist=1e10; + for(int i=0;i<poly.size();i++) { + + Vector2 cp =xform.xform(poly[i]); + + real_t d = cp.distance_to(gpoint); + if (d<closest_dist && d<grab_treshold) { + closest_dist=d; + closest_pos=cp; + closest_idx=i; + } + + } + + if (closest_idx>=0) { + + + undo_redo->create_action("Edit Poly (Remove Point)"); + undo_redo->add_undo_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + poly.remove(closest_idx); + undo_redo->add_do_method(node->get_occluder_polygon().ptr(),"set_polygon",poly); + undo_redo->add_do_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(),"update"); + undo_redo->commit_action(); + return true; + } + + } + + + + } break; + } + + + + } break; + case InputEvent::MOUSE_MOTION: { + + const InputEventMouseMotion &mm=p_event.mouse_motion; + + if (edited_point!=-1 && (wip_active || mm.button_mask&BUTTON_MASK_LEFT)) { + + Vector2 gpoint = Point2(mm.x,mm.y); + Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); + cpoint=snap_point(cpoint); + edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); + + canvas_item_editor->get_viewport_control()->update(); + + } + + } break; + } + + return false; +} +void LightOccluder2DEditor::_canvas_draw() { + + if (!node || !node->get_occluder_polygon().is_valid()) + return; + + Control *vpc = canvas_item_editor->get_viewport_control(); + + Vector<Vector2> poly; + + if (wip_active) + poly=wip; + else + poly=Variant(node->get_occluder_polygon()->get_polygon()); + + + Matrix32 xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + Ref<Texture> handle= get_icon("EditorHandle","EditorIcons"); + + int len = poly.size(); + + for(int i=0;i<poly.size();i++) { + + + Vector2 p,p2; + p = i==edited_point ? edited_point_pos : poly[i]; + if ((wip_active && i==poly.size()-1) || (((i+1)%poly.size())==edited_point)) + p2=edited_point_pos; + else + p2 = poly[(i+1)%poly.size()]; + + Vector2 point = xform.xform(p); + Vector2 next_point = xform.xform(p2); + + Color col=Color(1,0.3,0.1,0.8); + + if (i==poly.size()-1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) { + + } else { + vpc->draw_line(point,next_point,col,2); + } + vpc->draw_texture(handle,point-handle->get_size()*0.5); + } +} + + + +void LightOccluder2DEditor::edit(Node *p_collision_polygon) { + + if (!canvas_item_editor) { + canvas_item_editor=CanvasItemEditor::get_singleton(); + } + + if (p_collision_polygon) { + + node=p_collision_polygon->cast_to<LightOccluder2D>(); + if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw"); + wip.clear(); + wip_active=false; + edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); + } else { + node=NULL; + + if (canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw")) + canvas_item_editor->get_viewport_control()->disconnect("draw",this,"_canvas_draw"); + + } + +} + +void LightOccluder2DEditor::_create_poly() { + + if (!node) + return; + undo_redo->create_action("Create Occluder Polygon"); + undo_redo->add_do_method(node,"set_occluder_polygon",Ref<OccluderPolygon2D>(memnew( OccluderPolygon2D))); + undo_redo->add_undo_method(node,"set_occluder_polygon",Variant(REF())); + undo_redo->commit_action(); +} + +void LightOccluder2DEditor::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_menu_option"),&LightOccluder2DEditor::_menu_option); + ObjectTypeDB::bind_method(_MD("_canvas_draw"),&LightOccluder2DEditor::_canvas_draw); + ObjectTypeDB::bind_method(_MD("_node_removed"),&LightOccluder2DEditor::_node_removed); + ObjectTypeDB::bind_method(_MD("_create_poly"),&LightOccluder2DEditor::_create_poly); + +} + + +LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) { + + canvas_item_editor=NULL; + editor=p_editor; + undo_redo = editor->get_undo_redo(); + + add_child( memnew( VSeparator )); + button_create = memnew( ToolButton ); + add_child(button_create); + button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE)); + button_create->set_toggle_mode(true); + button_create->set_tooltip("Create a new polygon from scratch"); + + button_edit = memnew( ToolButton ); + add_child(button_edit); + button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT)); + button_edit->set_toggle_mode(true); + button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."); + + create_poly = memnew( ConfirmationDialog ); + add_child(create_poly); + create_poly->get_ok()->set_text("Create"); + + + //add_constant_override("separation",0); + +#if 0 + options = memnew( MenuButton ); + add_child(options); + options->set_area_as_parent_rect(); + options->set_text("Polygon"); + //options->get_popup()->add_item("Parse BBCODE",PARSE_BBCODE); + options->get_popup()->connect("item_pressed", this,"_menu_option"); +#endif + + mode = MODE_EDIT; + wip_active=false; + +} + + +void LightOccluder2DEditorPlugin::edit(Object *p_object) { + + collision_polygon_editor->edit(p_object->cast_to<Node>()); +} + +bool LightOccluder2DEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("LightOccluder2D"); +} + +void LightOccluder2DEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + collision_polygon_editor->show(); + } else { + + collision_polygon_editor->hide(); + collision_polygon_editor->edit(NULL); + } + +} + +LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) { + + editor=p_node; + collision_polygon_editor = memnew( LightOccluder2DEditor(p_node) ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor); + + collision_polygon_editor->hide(); + + + +} + + +LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin() +{ +} + diff --git a/tools/editor/plugins/light_occluder_2d_editor_plugin.h b/tools/editor/plugins/light_occluder_2d_editor_plugin.h new file mode 100644 index 0000000000..5fb5631d05 --- /dev/null +++ b/tools/editor/plugins/light_occluder_2d_editor_plugin.h @@ -0,0 +1,87 @@ +#ifndef LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H +#define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H + + + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/2d/light_occluder_2d.h" +#include "scene/gui/tool_button.h" +#include "scene/gui/button_group.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class CanvasItemEditor; + +class LightOccluder2DEditor : public HBoxContainer { + + OBJ_TYPE(LightOccluder2DEditor, HBoxContainer ); + + UndoRedo *undo_redo; + enum Mode { + + MODE_CREATE, + MODE_EDIT, + + }; + + Mode mode; + + ToolButton *button_create; + ToolButton *button_edit; + + CanvasItemEditor *canvas_item_editor; + EditorNode *editor; + Panel *panel; + LightOccluder2D *node; + MenuButton *options; + + int edited_point; + Vector2 edited_point_pos; + Vector<Vector2> pre_move_edit; + Vector<Vector2> wip; + bool wip_active; + + ConfirmationDialog *create_poly; + + void _wip_close(bool p_closed); + void _canvas_draw(); + void _menu_option(int p_option); + void _create_poly(); + +protected: + void _notification(int p_what); + void _node_removed(Node *p_node); + 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); + LightOccluder2DEditor(EditorNode *p_editor); +}; + +class LightOccluder2DEditorPlugin : public EditorPlugin { + + OBJ_TYPE( LightOccluder2DEditorPlugin, EditorPlugin ); + + LightOccluder2DEditor *collision_polygon_editor; + EditorNode *editor; + +public: + + virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); } + + virtual String get_name() const { return "LightOccluder2D"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + LightOccluder2DEditorPlugin(EditorNode *p_node); + ~LightOccluder2DEditorPlugin(); + +}; + +#endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H diff --git a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp index 599d18c8bb..163accfdd3 100644 --- a/tools/editor/plugins/navigation_polygon_editor_plugin.cpp +++ b/tools/editor/plugins/navigation_polygon_editor_plugin.cpp @@ -36,6 +36,9 @@ void NavigationPolygonEditor::_node_removed(Node *p_node) { void NavigationPolygonEditor::_create_nav() { + if (!node) + return; + undo_redo->create_action("Create Navigation Polygon"); undo_redo->add_do_method(node,"set_navigation_polygon",Ref<NavigationPolygon>(memnew( NavigationPolygon))); undo_redo->add_undo_method(node,"set_navigation_polygon",Variant(REF())); @@ -107,7 +110,7 @@ bool NavigationPolygonEditor::forward_input_event(const InputEvent& p_event) { create_nav->set_text("No NavigationPolygon resource on this node.\nCreate and assign one?"); create_nav->popup_centered_minsize(); } - return false; + return (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1);; } @@ -445,6 +448,7 @@ void NavigationPolygonEditor::edit(Node *p_collision_polygon) { wip.clear(); wip_active=false; edited_point=-1; + canvas_item_editor->get_viewport_control()->update(); } else { node=NULL; diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index ce5ea58124..79e43f9012 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -34,7 +34,7 @@ #include "os/file_access.h" #include "tools/editor/editor_settings.h" #include "os/input.h" - +#include "method_bind_ext.inc" void TileMapEditor::_notification(int p_what) { @@ -42,8 +42,13 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_READY: { + transpose->set_icon( get_icon("Transpose","EditorIcons")); mirror_x->set_icon( get_icon("MirrorX","EditorIcons")); mirror_y->set_icon( get_icon("MirrorY","EditorIcons")); + rotate_0->set_icon( get_icon("Rotate0","EditorIcons")); + rotate_90->set_icon( get_icon("Rotate90","EditorIcons")); + rotate_180->set_icon( get_icon("Rotate180","EditorIcons")); + rotate_270->set_icon( get_icon("Rotate270","EditorIcons")); } break; } @@ -85,24 +90,31 @@ void TileMapEditor::set_selected_tile(int p_tile) { } } -void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v,bool p_with_undo) { +// Wrapper to workaround five arg limit of undo/redo methods +void TileMapEditor::_set_cell_shortened(const Point2& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose) { + ERR_FAIL_COND(!node); + node->set_cell(floor(p_pos.x), floor(p_pos.y), p_value, p_flip_h, p_flip_v, p_transpose); +} + +void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bool p_flip_v, bool p_transpose,bool p_with_undo) { ERR_FAIL_COND(!node); bool prev_flip_h=node->is_cell_x_flipped(p_pos.x,p_pos.y); bool prev_flip_v=node->is_cell_y_flipped(p_pos.x,p_pos.y); + bool prev_transpose=node->is_cell_transposed(p_pos.x,p_pos.y); int prev_val=node->get_cell(p_pos.x,p_pos.y); - if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_flip_v) + if (p_value==prev_val && p_flip_h==prev_flip_h && p_flip_v==prev_flip_v && p_transpose==prev_transpose) return; //check that it's actually different if (p_with_undo) { - undo_redo->add_do_method(node,"set_cell",p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v); - undo_redo->add_undo_method(node,"set_cell",p_pos.x,p_pos.y,prev_val,prev_flip_h,prev_flip_v); + undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose); + undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose); } else { - node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v); + node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose); } @@ -168,6 +180,7 @@ struct _TileMapEditorCopyData { int cell; bool flip_h; bool flip_v; + bool transpose; }; bool TileMapEditor::forward_input_event(const InputEvent& p_event) { @@ -204,6 +217,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { tcd.cell=node->get_cell(j,i); tcd.flip_h=node->is_cell_x_flipped(j,i); tcd.flip_v=node->is_cell_y_flipped(j,i); + tcd.transpose=node->is_cell_transposed(j,i); dupdata.push_back(tcd); @@ -214,7 +228,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for (List<_TileMapEditorCopyData>::Element *E=dupdata.front();E;E=E->next()) { - _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,true); + _set_cell(E->get().pos+ofs,E->get().cell,E->get().flip_h,E->get().flip_v,E->get().transpose,true); } undo_redo->commit_action(); @@ -239,6 +253,10 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { } else if (mb.mod.control) { tool=TOOL_PICKING; set_selected_tile(node->get_cell(over_tile.x, over_tile.y)); + mirror_x->set_pressed(node->is_cell_x_flipped(over_tile.x, over_tile.y)); + mirror_y->set_pressed(node->is_cell_y_flipped(over_tile.x, over_tile.y)); + transpose->set_pressed(node->is_cell_transposed(over_tile.x, over_tile.y)); + _update_transform_buttons(); canvas_item_editor->update(); return true; } else { @@ -248,7 +266,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { Point2i local =node->world_to_map((xform_inv.xform(Point2(mb.x,mb.y)))); paint_undo.clear(); paint_undo[local]=_get_op_from_cell(local); - node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); return true; } } @@ -263,8 +281,8 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y)); - undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf); + undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); @@ -289,7 +307,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { Point2i local =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y))); paint_undo.clear(); paint_undo[local]=_get_op_from_cell(local); - //node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + //node->set_cell(local.x,local.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); //return true; _set_cell(local,TileMap::INVALID_CELL); return true; @@ -302,9 +320,9 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - //undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y)); - _set_cell(p,TileMap::INVALID_CELL,false,false,true); - undo_redo->add_undo_method(node,"set_cell",p.x,p.y,E->get().idx,E->get().xf,E->get().yf); + //undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + _set_cell(p,TileMap::INVALID_CELL,false,false,false,true); + undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); @@ -340,7 +358,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { paint_undo[over_tile]=_get_op_from_cell(over_tile); } - node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); return true; } @@ -373,13 +391,17 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { if (!paint_undo.has(over_tile)) { paint_undo[over_tile]=_get_op_from_cell(over_tile); } - //node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed()); + //node->set_cell(over_tile.x,over_tile.y,id,mirror_x->is_pressed(),mirror_y->is_pressed(),transpose->is_pressed()); _set_cell(local,TileMap::INVALID_CELL); return true; } if (tool==TOOL_PICKING) { set_selected_tile(node->get_cell(over_tile.x, over_tile.y)); + mirror_x->set_pressed(node->is_cell_x_flipped(over_tile.x, over_tile.y)); + mirror_y->set_pressed(node->is_cell_y_flipped(over_tile.x, over_tile.y)); + transpose->set_pressed(node->is_cell_transposed(over_tile.x, over_tile.y)); + _update_transform_buttons(); canvas_item_editor->update(); return true; } @@ -618,19 +640,53 @@ void TileMapEditor::_canvas_draw() { Ref<Texture> t = ts->tile_get_texture(st); if (t.is_valid()) { - Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+node->map_to_world(over_tile)+node->get_cell_draw_offset()); + Vector2 from = node->map_to_world(over_tile)+node->get_cell_draw_offset(); Rect2 r = ts->tile_get_region(st); Size2 sc = xform.get_scale(); if (mirror_x->is_pressed()) sc.x*=-1.0; if (mirror_y->is_pressed()) sc.y*=-1.0; + + Rect2 rect; if (r==Rect2()) { + rect=Rect2(from,t->get_size()); + } else { + + rect=Rect2(from,r.get_size()); + } + + + if (node->get_tile_origin()==TileMap::TILE_ORIGIN_TOP_LEFT) { + rect.pos+=ts->tile_get_texture_offset(st); + + } else if (node->get_tile_origin()==TileMap::TILE_ORIGIN_CENTER) { + rect.pos+=node->get_cell_size()/2; + Vector2 s = r.size; + + Vector2 center = (s/2) - ts->tile_get_texture_offset(st); + + + if (mirror_x->is_pressed()) + rect.pos.x-=s.x-center.x; + else + rect.pos.x-=center.x; - canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5)); + if (mirror_y->is_pressed()) + rect.pos.y-=s.y-center.y; + else + rect.pos.y-=center.y; + } + + rect.pos=xform.xform(rect.pos); + rect.size*=sc; + + if (r==Rect2()) { + + canvas_item_editor->draw_texture_rect(t,rect,false,Color(1,1,1,0.5),transpose->is_pressed()); } else { - canvas_item_editor->draw_texture_rect_region(t,Rect2(from,r.get_size()*sc),r,Color(1,1,1,0.5)); + canvas_item_editor->draw_texture_rect_region(t,rect,r,Color(1,1,1,0.5),transpose->is_pressed()); } } } @@ -697,6 +753,8 @@ void TileMapEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_canvas_mouse_enter"),&TileMapEditor::_canvas_mouse_enter); ObjectTypeDB::bind_method(_MD("_canvas_mouse_exit"),&TileMapEditor::_canvas_mouse_exit); ObjectTypeDB::bind_method(_MD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed); + ObjectTypeDB::bind_method(_MD("_update_transform_buttons"),&TileMapEditor::_update_transform_buttons); + ObjectTypeDB::bind_method(_MD("_set_cell_shortened","pos","tile","flip_x","flip_y","transpose"),&TileMapEditor::_set_cell_shortened,DEFVAL(false),DEFVAL(false),DEFVAL(false)); } @@ -709,10 +767,60 @@ TileMapEditor::CellOp TileMapEditor::_get_op_from_cell(const Point2i& p_pos) op.xf=true; if (node->is_cell_y_flipped(p_pos.x,p_pos.y)) op.yf=true; + if (node->is_cell_transposed(p_pos.x,p_pos.y)) + op.tr=true; } return op; } +void TileMapEditor::_update_transform_buttons(Object *p_button) { + //ERR_FAIL_NULL(p_button); + ToolButton *b=p_button->cast_to<ToolButton>(); + //ERR_FAIL_COND(!b); + + mirror_x->set_block_signals(true); + mirror_y->set_block_signals(true); + transpose->set_block_signals(true); + rotate_0->set_block_signals(true); + rotate_90->set_block_signals(true); + rotate_180->set_block_signals(true); + rotate_270->set_block_signals(true); + + if (b == rotate_0) { + mirror_x->set_pressed(false); + mirror_y->set_pressed(false); + transpose->set_pressed(false); + } + else if (b == rotate_90) { + mirror_x->set_pressed(true); + mirror_y->set_pressed(false); + transpose->set_pressed(true); + } + else if (b == rotate_180) { + mirror_x->set_pressed(true); + mirror_y->set_pressed(true); + transpose->set_pressed(false); + } + else if (b == rotate_270) { + mirror_x->set_pressed(false); + mirror_y->set_pressed(true); + transpose->set_pressed(true); + } + + rotate_0->set_pressed(!mirror_x->is_pressed() && !mirror_y->is_pressed() && !transpose->is_pressed()); + rotate_90->set_pressed(mirror_x->is_pressed() && !mirror_y->is_pressed() && transpose->is_pressed()); + rotate_180->set_pressed(mirror_x->is_pressed() && mirror_y->is_pressed() && !transpose->is_pressed()); + rotate_270->set_pressed(!mirror_x->is_pressed() && mirror_y->is_pressed() && transpose->is_pressed()); + + mirror_x->set_block_signals(false); + mirror_y->set_block_signals(false); + transpose->set_block_signals(false); + rotate_0->set_block_signals(false); + rotate_90->set_block_signals(false); + rotate_180->set_block_signals(false); + rotate_270->set_block_signals(false); +} + TileMapEditor::TileMapEditor(EditorNode *p_editor) { node=NULL; @@ -734,18 +842,52 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { canvas_item_editor_hb = memnew( HBoxContainer ); CanvasItemEditor::get_singleton()->add_control_to_menu_panel(canvas_item_editor_hb); canvas_item_editor_hb->add_child( memnew( VSeparator )); + transpose = memnew( ToolButton ); + transpose->set_toggle_mode(true); + transpose->set_tooltip("Transpose"); + transpose->set_focus_mode(FOCUS_NONE); + transpose->connect("pressed", this, "_update_transform_buttons", make_binds(transpose)); + canvas_item_editor_hb->add_child(transpose); mirror_x = memnew( ToolButton ); mirror_x->set_toggle_mode(true); mirror_x->set_tooltip("Mirror X (A)"); mirror_x->set_focus_mode(FOCUS_NONE); + mirror_x->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_x)); canvas_item_editor_hb->add_child(mirror_x); mirror_y = memnew( ToolButton ); mirror_y->set_toggle_mode(true); mirror_y->set_tooltip("Mirror Y (S)"); mirror_y->set_focus_mode(FOCUS_NONE); + mirror_y->connect("pressed", this, "_update_transform_buttons", make_binds(mirror_y)); canvas_item_editor_hb->add_child(mirror_y); + canvas_item_editor_hb->add_child(memnew(VSeparator)); + rotate_0 = memnew( ToolButton ); + rotate_0->set_toggle_mode(true); + rotate_0->set_tooltip("Rotate 0 degrees"); + rotate_0->set_focus_mode(FOCUS_NONE); + rotate_0->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_0)); + canvas_item_editor_hb->add_child(rotate_0); + rotate_90 = memnew( ToolButton ); + rotate_90->set_toggle_mode(true); + rotate_90->set_tooltip("Rotate 90 degrees"); + rotate_90->set_focus_mode(FOCUS_NONE); + rotate_90->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_90)); + canvas_item_editor_hb->add_child(rotate_90); + rotate_180 = memnew( ToolButton ); + rotate_180->set_toggle_mode(true); + rotate_180->set_tooltip("Rotate 180 degrees"); + rotate_180->set_focus_mode(FOCUS_NONE); + rotate_180->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_180)); + canvas_item_editor_hb->add_child(rotate_180); + rotate_270 = memnew( ToolButton ); + rotate_270->set_toggle_mode(true); + rotate_270->set_tooltip("Rotate 270 degrees"); + rotate_270->set_focus_mode(FOCUS_NONE); + rotate_270->connect("pressed", this, "_update_transform_buttons", make_binds(rotate_270)); + canvas_item_editor_hb->add_child(rotate_270); canvas_item_editor_hb->hide(); - + + rotate_0->set_pressed(true); tool=TOOL_NONE; selection_active=false; mouse_over=false; diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index f3c590e228..367e687d77 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -71,8 +71,13 @@ class TileMapEditor : public VBoxContainer { bool mouse_over; Label *mirror_label; + ToolButton *transpose; ToolButton *mirror_x; ToolButton *mirror_y; + ToolButton *rotate_0; + ToolButton *rotate_90; + ToolButton *rotate_180; + ToolButton *rotate_270; HBoxContainer *canvas_item_editor_hb; @@ -81,8 +86,8 @@ class TileMapEditor : public VBoxContainer { int idx; bool xf; bool yf; - CellOp() { idx=-1; xf=false; yf=false; } - CellOp(const CellOp& p_other) : idx(p_other.idx), xf(p_other.xf), yf(p_other.yf) {} + bool tr; + CellOp() { idx=-1; xf=false; yf=false; tr=false; } }; Map<Point2i,CellOp> paint_undo; @@ -94,7 +99,8 @@ class TileMapEditor : public VBoxContainer { void _canvas_draw(); void _menu_option(int p_option); - void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_with_undo=false); + void _set_cell(const Point2i& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_transpose=false, bool p_with_undo=false); + void _set_cell_shortened(const Point2& p_pos, int p_value, bool p_flip_h=false, bool p_flip_v=false, bool p_transpose=false); void _canvas_mouse_enter(); void _canvas_mouse_exit(); @@ -106,6 +112,7 @@ protected: void _node_removed(Node *p_node); static void _bind_methods(); CellOp _get_op_from_cell(const Point2i& p_pos); + void _update_transform_buttons(Object *p_button=0); public: HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; } diff --git a/tools/editor/plugins/tile_set_editor_plugin.cpp b/tools/editor/plugins/tile_set_editor_plugin.cpp index a51caf7d54..8ff7720934 100644 --- a/tools/editor/plugins/tile_set_editor_plugin.cpp +++ b/tools/editor/plugins/tile_set_editor_plugin.cpp @@ -37,83 +37,103 @@ void TileSetEditor::edit(const Ref<TileSet>& p_tileset) { void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_merge) { if (!p_merge) - p_library->clear(); + p_library->clear(); for(int i=0;i<scene->get_child_count();i++) { - Node *child = scene->get_child(i); + Node *child = scene->get_child(i); - if (!child->cast_to<Sprite>()) { - if (child->get_child_count()>0) { - child=child->get_child(0); - if (!child->cast_to<Sprite>()) { - continue; - } + if (!child->cast_to<Sprite>()) { + if (child->get_child_count()>0) { + child=child->get_child(0); + if (!child->cast_to<Sprite>()) { + continue; + } - } else - continue; + } else + continue; - } + } - Sprite *mi = child->cast_to<Sprite>(); - Ref<Texture> texture=mi->get_texture(); - if (texture.is_null()) + Sprite *mi = child->cast_to<Sprite>(); + Ref<Texture> texture=mi->get_texture(); + Ref<CanvasItemMaterial> material=mi->get_material(); + + if (texture.is_null()) continue; - int id = p_library->find_tile_by_name(mi->get_name()); - if (id<0) { - - id=p_library->get_last_unused_tile_id(); - p_library->create_tile(id); - p_library->tile_set_name(id,mi->get_name()); - } - - - p_library->tile_set_texture(id,texture); - Vector2 phys_offset; - - if (mi->is_centered()) { - Size2 s; - if (mi->is_region()) { - s=mi->get_region_rect().size; - } else { - s=texture->get_size(); - } - phys_offset+=-s/2; - } - if (mi->is_region()) { - p_library->tile_set_region(id,mi->get_region_rect()); - } - - Vector<Ref<Shape2D> >collisions; - - for(int j=0;j<mi->get_child_count();j++) { - - Node *child2 = mi->get_child(j); - if (!child2->cast_to<StaticBody2D>()) - continue; - StaticBody2D *sb = child2->cast_to<StaticBody2D>(); - if (sb->get_shape_count()==0) - continue; - Ref<Shape2D> collision=sb->get_shape(0); - if (collision.is_valid()) { - collisions.push_back(collision); + int id = p_library->find_tile_by_name(mi->get_name()); + if (id<0) { + + id=p_library->get_last_unused_tile_id(); + p_library->create_tile(id); + p_library->tile_set_name(id,mi->get_name()); + } + + + + p_library->tile_set_texture(id,texture); + p_library->tile_set_material(id,material); + + Vector2 phys_offset; + + if (mi->is_centered()) { + Size2 s; + if (mi->is_region()) { + s=mi->get_region_rect().size; + } else { + s=texture->get_size(); + } + phys_offset+=-s/2; + } + if (mi->is_region()) { + p_library->tile_set_region(id,mi->get_region_rect()); + } + + Vector<Ref<Shape2D> >collisions; + Ref<NavigationPolygon> nav_poly; + Ref<OccluderPolygon2D> occluder; + + for(int j=0;j<mi->get_child_count();j++) { + + Node *child2 = mi->get_child(j); + + if (child2->cast_to<NavigationPolygonInstance>()) + nav_poly=child2->cast_to<NavigationPolygonInstance>()->get_navigation_polygon(); + + if (child2->cast_to<LightOccluder2D>()) + occluder=child2->cast_to<LightOccluder2D>()->get_occluder_polygon(); + + if (!child2->cast_to<StaticBody2D>()) + continue; + StaticBody2D *sb = child2->cast_to<StaticBody2D>(); + if (sb->get_shape_count()==0) + continue; + Ref<Shape2D> collision=sb->get_shape(0); + if (collision.is_valid()) { + collisions.push_back(collision); } - } + } - if (collisions.size()) { + if (collisions.size()) { - p_library->tile_set_shapes(id,collisions); - p_library->tile_set_shape_offset(id,-phys_offset); - } else { - p_library->tile_set_shape_offset(id,Vector2()); + p_library->tile_set_shapes(id,collisions); + p_library->tile_set_shape_offset(id,-phys_offset); + } else { + p_library->tile_set_shape_offset(id,Vector2()); + + } + + p_library->tile_set_texture_offset(id,mi->get_offset()); + p_library->tile_set_navigation_polygon(id,nav_poly); + 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_texture_offset(id,mi->get_offset()); } } @@ -121,23 +141,23 @@ void TileSetEditor::_menu_confirm() { switch(option) { - case MENU_OPTION_REMOVE_ITEM: { + case MENU_OPTION_REMOVE_ITEM: { - tileset->remove_tile(to_erase); - } break; - case MENU_OPTION_MERGE_FROM_SCENE: - case MENU_OPTION_CREATE_FROM_SCENE: { + tileset->remove_tile(to_erase); + } break; + case MENU_OPTION_MERGE_FROM_SCENE: + case MENU_OPTION_CREATE_FROM_SCENE: { - EditorNode *en = editor; - Node * scene = en->get_edited_scene(); - if (!scene) - break; + EditorNode *en = editor; + Node * scene = en->get_edited_scene(); + if (!scene) + break; - _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE); + _import_scene(scene,tileset,option==MENU_OPTION_MERGE_FROM_SCENE); - } break; + } break; } } @@ -165,11 +185,11 @@ void TileSetEditor::_menu_cbk(int p_option) { cd->set_text("Create from scene?"); cd->popup_centered(Size2(300,60)); } break; - case MENU_OPTION_MERGE_FROM_SCENE: { + case MENU_OPTION_MERGE_FROM_SCENE: { - cd->set_text("Merge from scene?"); - cd->popup_centered(Size2(300,60)); - } break; + cd->set_text("Merge from scene?"); + cd->popup_centered(Size2(300,60)); + } break; } } diff --git a/tools/editor/plugins/tile_set_editor_plugin.h b/tools/editor/plugins/tile_set_editor_plugin.h index 2531ec55bf..1248b4e007 100644 --- a/tools/editor/plugins/tile_set_editor_plugin.h +++ b/tools/editor/plugins/tile_set_editor_plugin.h @@ -56,7 +56,7 @@ class TileSetEditor : public Control { int option; void _menu_cbk(int p_option); - void _menu_confirm(); + void _menu_confirm(); static void _import_scene(Node *p_scene, Ref<TileSet> p_library, bool p_merge); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index a600683097..fb4c134263 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -1857,8 +1857,33 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String& p } else { p_item->set_text(1,"<"+res->get_type()+">"); }; + + if (has_icon(res->get_type(),"EditorIcons")) { + + p_item->set_icon(0,get_icon(res->get_type(),"EditorIcons")); + } else { + + Dictionary d = p_item->get_metadata(0); + int hint=d.has("hint")?d["hint"].operator int():-1; + String hint_text=d.has("hint_text")?d["hint_text"]:""; + if (hint==PROPERTY_HINT_RESOURCE_TYPE) { + + if (has_icon(hint_text,"EditorIcons")) { + + p_item->set_icon(0,get_icon(hint_text,"EditorIcons")); + + } else { + p_item->set_icon(0,get_icon("Object","EditorIcons")); + + } + } + } + + + } + } break; default: {}; } @@ -2529,7 +2554,10 @@ void PropertyEditor::update_tree() { item->set_editable( 1, !read_only ); item->add_button(1,get_icon("EditResource","EditorIcons")); String type; + if (p.hint==PROPERTY_HINT_RESOURCE_TYPE) + type=p.hint_string; bool notnil=false; + if (obj->get( p.name ).get_type() == Variant::NIL || obj->get( p.name ).operator RefPtr().is_null()) { item->set_text(1,"<null>"); @@ -2553,12 +2581,18 @@ void PropertyEditor::update_tree() { }; notnil=true; + if (has_icon(res->get_type(),"EditorIcons")) { + type=res->get_type(); + } } - if (p.hint==PROPERTY_HINT_RESOURCE_TYPE) { + + if (type!=String()) { + if (type.find(",")!=-1) + type=type.get_slice(",",0); //printf("prop %s , type %s\n",p.name.ascii().get_data(),p.hint_string.ascii().get_data()); - if (has_icon(p.hint_string,"EditorIcons")) - item->set_icon( 0, get_icon(p.hint_string,"EditorIcons") ); + if (has_icon(type,"EditorIcons")) + item->set_icon( 0, get_icon(type,"EditorIcons") ); else item->set_icon( 0, get_icon("Object","EditorIcons") ); } |