Browse Source

CollisionPolygon (3D)
Workaround for round() on PC.

Juan Linietsky 11 years ago
parent
commit
f00f4b9296

+ 3 - 3
demos/3d/platformer/follow_camera.gd

@@ -45,13 +45,13 @@ func _fixed_process(dt):
 	var col = ds.intersect_ray(target,target,collision_exception)
 	var col_right = ds.intersect_ray(target,target+Matrix3(up,deg2rad(-autoturn_ray_aperture)).xform(delta),collision_exception)
 	
-	if (col!=null):
+	if (!col.empty()):
 		#if main ray was occluded, get camera closer, this is the worst case scenario
 		delta = col.position - target	
-	elif (col_left!=null and col_right==null):
+	elif (!col_left.empty() and col_right.empty()):
 		#if only left ray is occluded, turn the camera around to the right
 		delta = Matrix3(up,deg2rad(-dt*autoturn_speed)).xform(delta)
-	elif (col_left==null and col_right!=null):
+	elif (col_left.empty() and !col_right.empty()):
 		#if only right ray is occluded, turn the camera around to the left
 		delta = Matrix3(up,deg2rad(dt*autoturn_speed)).xform(delta)
 	else:

+ 4 - 0
drivers/gles2/shader_compiler_gles2.cpp

@@ -611,7 +611,11 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() {
 	replace_table["sign"]=  "sign";
 	replace_table["floor"]= "floor";
 	replace_table["trunc"]= "trunc";
+#ifdef GLEW_ENABLED
+	replace_table["round"]= "roundfix";
+#else
 	replace_table["round"]= "round";
+#endif
 	replace_table["ceil" ]= "ceil";
 	replace_table["fract"]= "fract";
 	replace_table["mod"  ]= "mod";

+ 2 - 0
drivers/gles2/shaders/material.glsl

@@ -4,6 +4,7 @@
 #ifdef USE_GLES_OVER_GL
 #define mediump
 #define highp
+#define roundfix( m_val ) floor( (m_val) + 0.5 )
 #else
 precision mediump float;
 precision mediump int;
@@ -470,6 +471,7 @@ VERTEX_SHADER_CODE
 #ifdef USE_GLES_OVER_GL
 #define mediump
 #define highp
+#define roundfix( m_val ) floor( (m_val) + 0.5 )
 #else
 
 precision mediump float;

+ 2 - 1
scene/2d/collision_polygon_2d.cpp

@@ -153,6 +153,7 @@ void CollisionPolygon2D::set_build_mode(BuildMode p_mode) {
 
 	ERR_FAIL_INDEX(p_mode,2);
 	build_mode=p_mode;
+	_update_parent();
 }
 
 CollisionPolygon2D::BuildMode CollisionPolygon2D::get_build_mode() const{
@@ -174,7 +175,7 @@ void CollisionPolygon2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon2D::set_build_mode);
 	ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon2D::get_build_mode);
 
-	ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Automatic,Segments,Solids"),_SCS("set_build_mode"),_SCS("get_build_mode"));
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Segments"),_SCS("set_build_mode"),_SCS("get_build_mode"));
 	ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
 }
 

+ 206 - 0
scene/3d/collision_polygon.cpp

@@ -0,0 +1,206 @@
+#include "collision_polygon.h"
+
+#include "collision_object.h"
+#include "scene/resources/concave_polygon_shape.h"
+#include "scene/resources/convex_polygon_shape.h"
+
+void CollisionPolygon::_add_to_collision_object(Object *p_obj) {
+
+
+	CollisionObject *co = p_obj->cast_to<CollisionObject>();
+	ERR_FAIL_COND(!co);
+
+	if (polygon.size()==0)
+		return;
+
+	bool solids=build_mode==BUILD_SOLIDS;
+
+	Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
+	if (decomp.size()==0)
+		return;
+
+	if (true || solids) {
+
+		//here comes the sun, lalalala
+		//decompose concave into multiple convex polygons and add them
+		for(int i=0;i<decomp.size();i++) {
+			Ref<ConvexPolygonShape> convex = memnew( ConvexPolygonShape );
+			DVector<Vector3> cp;
+			int cs = decomp[i].size();
+			cp.resize(cs*2);
+			{
+				DVector<Vector3>::Write w = cp.write();
+				int idx=0;
+				for(int j=0;j<cs;j++) {
+
+					Vector2 d = decomp[i][j];
+					w[idx++]=Vector3(d.x,d.y,depth*0.5);
+					w[idx++]=Vector3(d.x,d.y,-depth*0.5);
+				}
+			}
+
+			convex->set_points(cp);
+			co->add_shape(convex,get_transform());
+
+		}
+
+	} else {
+#if 0
+		Ref<ConcavePolygonShape> concave = memnew( ConcavePolygonShape );
+
+		DVector<Vector2> segments;
+		segments.resize(polygon.size()*2);
+		DVector<Vector2>::Write w=segments.write();
+
+		for(int i=0;i<polygon.size();i++) {
+			w[(i<<1)+0]=polygon[i];
+			w[(i<<1)+1]=polygon[(i+1)%polygon.size()];
+		}
+
+		w=DVector<Vector2>::Write();
+		concave->set_segments(segments);
+
+		co->add_shape(concave,get_transform());
+#endif
+	}
+
+
+	//co->add_shape(shape,get_transform());
+
+}
+
+void CollisionPolygon::_update_parent() {
+
+	Node *parent = get_parent();
+	if (!parent)
+		return;
+	CollisionObject *co = parent->cast_to<CollisionObject>();
+	if (!co)
+		return;
+	co->_update_shapes_from_children();
+}
+
+void CollisionPolygon::_notification(int p_what) {
+
+
+	switch(p_what) {
+		case NOTIFICATION_TRANSFORM_CHANGED: {
+
+			if (!is_inside_scene())
+				break;
+			_update_parent();
+
+		} break;
+#if 0
+		case NOTIFICATION_DRAW: {
+			for(int i=0;i<polygon.size();i++) {
+
+				Vector2 p = polygon[i];
+				Vector2 n = polygon[(i+1)%polygon.size()];
+				draw_line(p,n,Color(0,0.6,0.7,0.5),3);
+			}
+
+			Vector< Vector<Vector2> > decomp = Geometry::decompose_polygon(polygon);
+#define DEBUG_DECOMPOSE
+#ifdef DEBUG_DECOMPOSE
+			Color c(0.4,0.9,0.1);
+			for(int i=0;i<decomp.size();i++) {
+
+				c.set_hsv( Math::fmod(c.get_h() + 0.738,1),c.get_s(),c.get_v(),0.5);
+				draw_colored_polygon(decomp[i],c);
+			}
+#endif
+
+		} break;
+#endif
+	}
+}
+
+void CollisionPolygon::set_polygon(const Vector<Point2>& p_polygon) {
+
+	polygon=p_polygon;
+
+	for(int i=0;i<polygon.size();i++) {
+
+		Vector3 p1(polygon[i].x,polygon[i].y,depth*0.5);
+
+		if (i==0)
+			aabb=AABB(p1,Vector3());
+		else
+			aabb.expand_to(p1);
+
+		Vector3 p2(polygon[i].x,polygon[i].y,-depth*0.5);
+		aabb.expand_to(p2);
+
+
+	}
+	if (aabb==AABB()) {
+
+		aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
+	} else {
+		aabb.pos-=aabb.size*0.3;
+		aabb.size+=aabb.size*0.6;
+	}
+	_update_parent();
+	update_gizmo();
+}
+
+Vector<Point2> CollisionPolygon::get_polygon() const {
+
+	return polygon;
+}
+
+void CollisionPolygon::set_build_mode(BuildMode p_mode) {
+
+	ERR_FAIL_INDEX(p_mode,2);
+	build_mode=p_mode;
+	_update_parent();
+}
+
+CollisionPolygon::BuildMode CollisionPolygon::get_build_mode() const{
+
+	return build_mode;
+}
+
+AABB CollisionPolygon::get_item_rect() const {
+
+	return aabb;
+}
+
+void CollisionPolygon::set_depth(float p_depth) {
+
+	depth=p_depth;
+	_update_parent();
+	update_gizmo();
+}
+
+float CollisionPolygon::get_depth() const {
+
+	return depth;
+}
+
+
+void CollisionPolygon::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("_add_to_collision_object"),&CollisionPolygon::_add_to_collision_object);
+	ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&CollisionPolygon::set_polygon);
+	ObjectTypeDB::bind_method(_MD("get_polygon"),&CollisionPolygon::get_polygon);
+
+	ObjectTypeDB::bind_method(_MD("set_depth","depth"),&CollisionPolygon::set_depth);
+	ObjectTypeDB::bind_method(_MD("get_depth"),&CollisionPolygon::get_depth);
+
+	ObjectTypeDB::bind_method(_MD("set_build_mode"),&CollisionPolygon::set_build_mode);
+	ObjectTypeDB::bind_method(_MD("get_build_mode"),&CollisionPolygon::get_build_mode);
+
+	ADD_PROPERTY( PropertyInfo(Variant::INT,"build_mode",PROPERTY_HINT_ENUM,"Solids,Triangles"),_SCS("set_build_mode"),_SCS("get_build_mode"));
+	ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon"));
+	ADD_PROPERTY( PropertyInfo(Variant::REAL,"depth"),_SCS("set_depth"),_SCS("get_depth"));
+}
+
+CollisionPolygon::CollisionPolygon() {
+
+	aabb=AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
+	build_mode=BUILD_SOLIDS;
+	depth=1.0;
+
+}

+ 50 - 0
scene/3d/collision_polygon.h

@@ -0,0 +1,50 @@
+#ifndef COLLISION_POLYGON_H
+#define COLLISION_POLYGON_H
+
+#include "scene/3d/spatial.h"
+#include "scene/resources/shape.h"
+
+
+
+class CollisionPolygon : public Spatial {
+
+	OBJ_TYPE(CollisionPolygon,Spatial);
+public:
+
+	enum BuildMode {
+		BUILD_SOLIDS,
+		BUILD_TRIANGLES,
+	};
+
+protected:
+
+
+	float depth;
+	AABB aabb;
+	BuildMode build_mode;
+	Vector<Point2> polygon;
+
+	void _add_to_collision_object(Object *p_obj);
+	void _update_parent();
+
+protected:
+
+	void _notification(int p_what);
+	static void _bind_methods();
+public:
+
+	void set_build_mode(BuildMode p_mode);
+	BuildMode get_build_mode() const;
+
+	void set_depth(float p_depth);
+	float get_depth() const;
+
+	void set_polygon(const Vector<Point2>& p_polygon);
+	Vector<Point2> get_polygon() const;
+
+	virtual AABB get_item_rect() const;
+	CollisionPolygon();
+};
+
+VARIANT_ENUM_CAST( CollisionPolygon::BuildMode );
+#endif // COLLISION_POLYGON_H

+ 1 - 0
scene/main/viewport.cpp

@@ -1252,6 +1252,7 @@ void Viewport::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_use_own_world","enable"), &Viewport::set_use_own_world);
 	ObjectTypeDB::bind_method(_MD("is_using_own_world"), &Viewport::is_using_own_world);
 
+	ObjectTypeDB::bind_method(_MD("get_camera:Camera"), &Viewport::get_camera);
 
 	ObjectTypeDB::bind_method(_MD("set_as_audio_listener","enable"), &Viewport::set_as_audio_listener);
 	ObjectTypeDB::bind_method(_MD("is_audio_listener","enable"), &Viewport::is_audio_listener);

+ 2 - 1
scene/register_scene_types.cpp

@@ -199,7 +199,7 @@
 #include "scene/3d/proximity_group.h"
 #include "scene/3d/navigation_mesh.h"
 #include "scene/3d/navigation.h"
-
+#include "scene/3d/collision_polygon.h"
 #endif
 
 #include "scene/scene_binds.h"
@@ -409,6 +409,7 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<Area>();
 	ObjectTypeDB::register_type<ProximityGroup>();
 	ObjectTypeDB::register_type<CollisionShape>();
+	ObjectTypeDB::register_type<CollisionPolygon>();
 	ObjectTypeDB::register_type<RayCast>();
 	ObjectTypeDB::register_virtual_type<EditableShape>();
 	ObjectTypeDB::register_type<EditableSphere>();

+ 2 - 0
tools/editor/editor_node.cpp

@@ -79,6 +79,7 @@
 #include "plugins/path_editor_plugin.h"
 #include "plugins/rich_text_editor_plugin.h"
 #include "plugins/collision_polygon_editor_plugin.h"
+#include "plugins/collision_polygon_2d_editor_plugin.h"
 #include "plugins/script_editor_plugin.h"
 #include "plugins/path_2d_editor_plugin.h"
 #include "plugins/particles_editor_plugin.h"
@@ -4086,6 +4087,7 @@ EditorNode::EditorNode() {
 	add_editor_plugin( memnew( ItemListEditorPlugin(this) ) );
 	add_editor_plugin( memnew( RichTextEditorPlugin(this) ) );
 	add_editor_plugin( memnew( CollisionPolygonEditorPlugin(this) ) );
+	add_editor_plugin( memnew( CollisionPolygon2DEditorPlugin(this) ) );
 	add_editor_plugin( memnew( TileSetEditorPlugin(this) ) );
 	add_editor_plugin( memnew( TileMapEditorPlugin(this) ) );
 	add_editor_plugin( memnew( SpriteFramesEditorPlugin(this) ) );

+ 457 - 0
tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp

@@ -0,0 +1,457 @@
+#include "collision_polygon_2d_editor_plugin.h"
+
+#include "canvas_item_editor_plugin.h"
+#include "os/file_access.h"
+#include "tools/editor/editor_settings.h"
+
+void CollisionPolygon2DEditor::_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);
+
+
+		} break;
+		case NOTIFICATION_FIXED_PROCESS: {
+
+
+		} break;
+	}
+
+}
+void CollisionPolygon2DEditor::_node_removed(Node *p_node) {
+
+	if(p_node==node) {
+		node=NULL;
+		hide();
+	}
+
+}
+
+
+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) {
+
+		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 CollisionPolygon2DEditor::_wip_close() {
+
+	undo_redo->create_action("Create Poly");
+	undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
+	undo_redo->add_do_method(node,"set_polygon",wip);
+	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 CollisionPolygon2DEditor::forward_input_event(const InputEvent& p_event) {
+
+
+	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 = node->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();
+
+								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();
+					}
+
+
+
+				} 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,"set_polygon",poly);
+									poly.push_back(cpoint);
+									undo_redo->add_do_method(node,"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->set_polygon(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,"set_polygon",poly);
+								undo_redo->add_undo_method(node,"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,"set_polygon",poly);
+							poly.remove(closest_idx);
+							undo_redo->add_do_method(node,"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 CollisionPolygon2DEditor::_canvas_draw() {
+
+	if (!node)
+		return;
+
+	Control *vpc = canvas_item_editor->get_viewport_control();
+
+	Vector<Vector2> poly;
+
+	if (wip_active)
+		poly=wip;
+	else
+		poly=node->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);
+		vpc->draw_line(point,next_point,col,2);
+		vpc->draw_texture(handle,point-handle->get_size()*0.5);
+	}
+}
+
+
+
+void CollisionPolygon2DEditor::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<CollisionPolygon2D>();
+		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;
+
+	} 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 CollisionPolygon2DEditor::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("_menu_option"),&CollisionPolygon2DEditor::_menu_option);
+	ObjectTypeDB::bind_method(_MD("_canvas_draw"),&CollisionPolygon2DEditor::_canvas_draw);
+
+}
+
+CollisionPolygon2DEditor::CollisionPolygon2DEditor(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_edit = memnew( ToolButton );
+	add_child(button_edit);
+	button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
+	button_edit->set_toggle_mode(true);
+
+	//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 CollisionPolygon2DEditorPlugin::edit(Object *p_object) {
+
+	collision_polygon_editor->edit(p_object->cast_to<Node>());
+}
+
+bool CollisionPolygon2DEditorPlugin::handles(Object *p_object) const {
+
+	return p_object->is_type("CollisionPolygon2D");
+}
+
+void CollisionPolygon2DEditorPlugin::make_visible(bool p_visible) {
+
+	if (p_visible) {
+		collision_polygon_editor->show();
+	} else {
+
+		collision_polygon_editor->hide();
+		collision_polygon_editor->edit(NULL);
+	}
+
+}
+
+CollisionPolygon2DEditorPlugin::CollisionPolygon2DEditorPlugin(EditorNode *p_node) {
+
+	editor=p_node;
+	collision_polygon_editor = memnew( CollisionPolygon2DEditor(p_node) );
+	CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+
+	collision_polygon_editor->hide();
+
+
+
+}
+
+
+CollisionPolygon2DEditorPlugin::~CollisionPolygon2DEditorPlugin()
+{
+}
+

+ 84 - 0
tools/editor/plugins/collision_polygon_2d_editor_plugin.h

@@ -0,0 +1,84 @@
+#ifndef COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
+#define COLLISION_POLYGON_2D_EDITOR_PLUGIN_H
+
+
+#include "tools/editor/editor_plugin.h"
+#include "tools/editor/editor_node.h"
+#include "scene/2d/collision_polygon_2d.h"
+#include "scene/gui/tool_button.h"
+#include "scene/gui/button_group.h"
+
+/**
+	@author Juan Linietsky <[email protected]>
+*/
+class CanvasItemEditor;
+
+class CollisionPolygon2DEditor : public HBoxContainer {
+
+	OBJ_TYPE(CollisionPolygon2DEditor, 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;
+	CollisionPolygon2D *node;
+	MenuButton *options;
+
+	int edited_point;
+	Vector2 edited_point_pos;
+	Vector<Vector2> pre_move_edit;
+	Vector<Vector2> wip;
+	bool wip_active;
+
+
+	void _wip_close();
+	void _canvas_draw();
+	void _menu_option(int p_option);
+
+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);
+	CollisionPolygon2DEditor(EditorNode *p_editor);
+};
+
+class CollisionPolygon2DEditorPlugin : public EditorPlugin {
+
+	OBJ_TYPE( CollisionPolygon2DEditorPlugin, EditorPlugin );
+
+	CollisionPolygon2DEditor *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 "CollisionPolygon2D"; }
+	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);
+
+	CollisionPolygon2DEditorPlugin(EditorNode *p_node);
+	~CollisionPolygon2DEditorPlugin();
+
+};
+
+#endif // COLLISION_POLYGON_2D_EDITOR_PLUGIN_H

+ 223 - 58
tools/editor/plugins/collision_polygon_editor_plugin.cpp

@@ -27,10 +27,10 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 #include "collision_polygon_editor_plugin.h"
-#include "canvas_item_editor_plugin.h"
+#include "spatial_editor_plugin.h"
 #include "os/file_access.h"
 #include "tools/editor/editor_settings.h"
-
+#include "scene/3d/camera.h"
 void CollisionPolygonEditor::_notification(int p_what) {
 
 	switch(p_what) {
@@ -40,11 +40,16 @@ void CollisionPolygonEditor::_notification(int p_what) {
 			button_create->set_icon( get_icon("Edit","EditorIcons"));
 			button_edit->set_icon( get_icon("MovePoint","EditorIcons"));			
 			button_edit->set_pressed(true);
+			get_scene()->connect("node_removed",this,"_node_removed");
 
 
 		} break;
-		case NOTIFICATION_FIXED_PROCESS: {
+		case NOTIFICATION_PROCESS: {
 
+			if (node->get_depth() != prev_depth) {
+				_polygon_draw();
+				prev_depth=node->get_depth();
+			}
 
 		} break;
 	}
@@ -54,7 +59,10 @@ void CollisionPolygonEditor::_node_removed(Node *p_node) {
 
 	if(p_node==node) {
 		node=NULL;
+		if (imgeom->get_parent()==p_node)
+			p_node->remove_child(imgeom);
 		hide();
+		set_process(false);
 	}
 
 }
@@ -62,13 +70,15 @@ void CollisionPolygonEditor::_node_removed(Node *p_node) {
 
 Vector2 CollisionPolygonEditor::snap_point(const Vector2& p_point) const {
 
+	return p_point;
+	/*
 	if (canvas_item_editor->is_snap_active()) {
 
 		return p_point.snapped(Vector2(1,1)*canvas_item_editor->get_snap());
 
 	} else {
 		return p_point;
-	}
+	} ??? */
 }
 
 void CollisionPolygonEditor::_menu_option(int p_option) {
@@ -93,21 +103,28 @@ void CollisionPolygonEditor::_menu_option(int p_option) {
 
 void CollisionPolygonEditor::_wip_close() {
 
-	undo_redo->create_action("Create Poly");
+	undo_redo->create_action("Create Poly3D");
 	undo_redo->add_undo_method(node,"set_polygon",node->get_polygon());
 	undo_redo->add_do_method(node,"set_polygon",wip);
-	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();
+	undo_redo->add_do_method(this,"_polygon_draw");
+	undo_redo->add_undo_method(this,"_polygon_draw");
 	wip.clear();
 	wip_active=false;
 	mode=MODE_EDIT;
 	button_edit->set_pressed(true);
 	button_create->set_pressed(false);
 	edited_point=-1;
+	undo_redo->commit_action();
+
 }
 
-bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
+bool CollisionPolygonEditor::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) {
+
+
+	Transform gt = node->get_global_transform();
+	float depth = node->get_depth()*0.5;
+	Vector3 n = gt.basis.get_axis(2).normalized();
+	Plane p(gt.origin+n*depth,n);
 
 
 	switch(p_event.type) {
@@ -116,13 +133,20 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 
 			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);
+			Vector2 gpoint=Point2(mb.x,mb.y);
+			Vector3 ray_from = p_camera->project_ray_origin(gpoint);
+			Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
+
+			Vector3 spoint;
+
+			if (!p.intersects_ray(ray_from,ray_dir,&spoint))
+				break;
+
+			Vector2 cpoint(spoint.x,spoint.y);
+
+			//cpoint=snap_point(cpoint); snap?
 
 			Vector<Vector2> poly = node->get_polygon();
 
@@ -143,13 +167,13 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 							wip.push_back( cpoint );
 							wip_active=true;
 							edited_point_pos=cpoint;
-							canvas_item_editor->get_viewport_control()->update();
+							_polygon_draw();
 							edited_point=1;
 							return true;
 						} else {
 
 
-							if (wip.size()>1 && xform.xform(wip[0]).distance_to(gpoint)<grab_treshold) {
+							if (wip.size()>1 && p_camera->unproject_position(gt.xform(Vector3(wip[0].x,wip[0].y,depth))).distance_to(gpoint)<grab_treshold) {
 								//wip closed
 								_wip_close();
 
@@ -158,7 +182,7 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 
 								wip.push_back( cpoint );
 								edited_point=wip.size();
-								canvas_item_editor->get_viewport_control()->update();
+								_polygon_draw();
 								return true;
 
 								//add wip point
@@ -186,8 +210,8 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 									undo_redo->add_undo_method(node,"set_polygon",poly);
 									poly.push_back(cpoint);
 									undo_redo->add_do_method(node,"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->add_do_method(this,"_polygon_draw");
+									undo_redo->add_undo_method(this,"_polygon_draw");
 									undo_redo->commit_action();
 									return true;
 								}
@@ -198,8 +222,10 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 								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 points[2] ={
+										p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth))),
+										p_camera->unproject_position(gt.xform(Vector3(poly[(i+1)%poly.size()].x,poly[(i+1)%poly.size()].y,depth)))
+									};
 
 									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)
@@ -218,11 +244,11 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 								if (closest_idx>=0) {
 
 									pre_move_edit=poly;
-									poly.insert(closest_idx+1,xform.affine_inverse().xform(closest_pos));
+									poly.insert(closest_idx+1,cpoint);
 									edited_point=closest_idx+1;
-									edited_point_pos=xform.affine_inverse().xform(closest_pos);
+									edited_point_pos=cpoint;
 									node->set_polygon(poly);
-									canvas_item_editor->get_viewport_control()->update();
+									_polygon_draw();
 									return true;
 								}
 							} else {
@@ -234,7 +260,7 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 								real_t closest_dist=1e10;
 								for(int i=0;i<poly.size();i++) {
 
-									Vector2 cp =xform.xform(poly[i]);
+									Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth)));
 
 									real_t d = cp.distance_to(gpoint);
 									if (d<closest_dist && d<grab_treshold) {
@@ -249,8 +275,8 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 
 									pre_move_edit=poly;
 									edited_point=closest_idx;
-									edited_point_pos=xform.affine_inverse().xform(closest_pos);
-									canvas_item_editor->get_viewport_control()->update();
+									edited_point_pos=poly[closest_idx];
+									_polygon_draw();
 									return true;
 								}
 							}
@@ -265,8 +291,8 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 								undo_redo->create_action("Edit Poly");
 								undo_redo->add_do_method(node,"set_polygon",poly);
 								undo_redo->add_undo_method(node,"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->add_do_method(this,"_polygon_draw");
+								undo_redo->add_undo_method(this,"_polygon_draw");
 								undo_redo->commit_action();
 
 								edited_point=-1;
@@ -282,7 +308,7 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 						real_t closest_dist=1e10;
 						for(int i=0;i<poly.size();i++) {
 
-							Vector2 cp =xform.xform(poly[i]);
+							Vector2 cp = p_camera->unproject_position(gt.xform(Vector3(poly[i].x,poly[i].y,depth)));
 
 							real_t d = cp.distance_to(gpoint);
 							if (d<closest_dist && d<grab_treshold) {
@@ -300,8 +326,8 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 							undo_redo->add_undo_method(node,"set_polygon",poly);
 							poly.remove(closest_idx);
 							undo_redo->add_do_method(node,"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->add_do_method(this,"_polygon_draw");
+							undo_redo->add_undo_method(this,"_polygon_draw");
 							undo_redo->commit_action();
 							return true;
 						}
@@ -323,11 +349,21 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 			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();
+				Vector3 ray_from = p_camera->project_ray_origin(gpoint);
+				Vector3 ray_dir = p_camera->project_ray_normal(gpoint);
+
+				Vector3 spoint;
+
+				if (!p.intersects_ray(ray_from,ray_dir,&spoint))
+					break;
+
+				Vector2 cpoint(spoint.x,spoint.y);
+
+				//cpoint=snap_point(cpoint);
+				edited_point_pos = cpoint;
+
+				_polygon_draw();
 
 			}
 
@@ -336,13 +372,11 @@ bool CollisionPolygonEditor::forward_input_event(const InputEvent& p_event) {
 
 	return false;
 }
-void CollisionPolygonEditor::_canvas_draw() {
+void CollisionPolygonEditor::_polygon_draw() {
 
 	if (!node)
 		return;
 
-	Control *vpc = canvas_item_editor->get_viewport_control();
-
 	Vector<Vector2> poly;
 
 	if (wip_active)
@@ -351,10 +385,16 @@ void CollisionPolygonEditor::_canvas_draw() {
 		poly=node->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();
+	float depth = node->get_depth()*0.5;
+
+	imgeom->clear();
+	imgeom->set_material_override(line_material);
+	imgeom->begin(Mesh::PRIMITIVE_LINES,Ref<Texture>());
+
+
+	Rect2 rect;
 
 	for(int i=0;i<poly.size();i++) {
 
@@ -366,38 +406,127 @@ void CollisionPolygonEditor::_canvas_draw() {
 		else
 			p2 = poly[(i+1)%poly.size()];
 
-		Vector2 point = xform.xform(p);
-		Vector2 next_point = xform.xform(p2);
+		if (i==0)
+			rect.pos=p;
+		else
+			rect.expand_to(p);
+
+		Vector3 point = Vector3(p.x,p.y,depth);
+		Vector3 next_point = Vector3(p2.x,p2.y,depth);
+
+		imgeom->set_color(Color(1,0.3,0.1,0.8));
+		imgeom->add_vertex(point);
+		imgeom->set_color(Color(1,0.3,0.1,0.8));
+		imgeom->add_vertex(next_point);
 
-		Color col=Color(1,0.3,0.1,0.8);
-		vpc->draw_line(point,next_point,col,2);
-		vpc->draw_texture(handle,point-handle->get_size()*0.5);
+		//Color col=Color(1,0.3,0.1,0.8);
+		//vpc->draw_line(point,next_point,col,2);
+		//vpc->draw_texture(handle,point-handle->get_size()*0.5);
 	}
+
+	rect=rect.grow(1);
+
+	AABB r;
+	r.pos.x=rect.pos.x;
+	r.pos.y=rect.pos.y;
+	r.pos.z=depth;
+	r.size.x=rect.size.x;
+	r.size.y=rect.size.y;
+	r.size.z=0;
+
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos);
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(0.3,0,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos);
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(0.0,0.3,0));
+
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)-Vector3(0.3,0,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(r.size.x,0,0)+Vector3(0,0.3,0));
+
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)-Vector3(0,0.3,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+Vector3(0,r.size.y,0)+Vector3(0.3,0,0));
+
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+r.size);
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+r.size-Vector3(0.3,0,0));
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+r.size);
+	imgeom->set_color(Color(0.8,0.8,0.8,0.2));
+	imgeom->add_vertex(r.pos+r.size-Vector3(0.0,0.3,0));
+
+	imgeom->end();
+
+
+	while(m->get_surface_count()) {
+		m->surface_remove(0);
+	}
+
+	if (poly.size()==0)
+		return;
+
+	Array a;
+	a.resize(Mesh::ARRAY_MAX);
+	DVector<Vector3> va;
+	{
+
+		va.resize(poly.size());
+		DVector<Vector3>::Write w=va.write();
+		for(int i=0;i<poly.size();i++) {
+
+
+			Vector2 p,p2;
+			p = i==edited_point ? edited_point_pos : poly[i];
+
+			Vector3 point = Vector3(p.x,p.y,depth);
+			w[i]=point;
+		}
+	}
+	a[Mesh::ARRAY_VERTEX]=va;
+	m->add_surface(Mesh::PRIMITIVE_POINTS,a);
+	m->surface_set_material(0,handle_material);
+
 }
 
 
 
 void CollisionPolygonEditor::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<CollisionPolygon2D>();
-		if (!canvas_item_editor->get_viewport_control()->is_connected("draw",this,"_canvas_draw"))
-			canvas_item_editor->get_viewport_control()->connect("draw",this,"_canvas_draw");
+		node=p_collision_polygon->cast_to<CollisionPolygon>();
 		wip.clear();
 		wip_active=false;
 		edited_point=-1;
+		p_collision_polygon->add_child(imgeom);
+		_polygon_draw();
+		set_process(true);
+		prev_depth=-1;
 
 	} 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");
+		if (imgeom->get_parent())
+			imgeom->get_parent()->remove_child(imgeom);
 
+		set_process(false);
 	}
 
 }
@@ -405,13 +534,14 @@ void CollisionPolygonEditor::edit(Node *p_collision_polygon) {
 void CollisionPolygonEditor::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("_menu_option"),&CollisionPolygonEditor::_menu_option);
-	ObjectTypeDB::bind_method(_MD("_canvas_draw"),&CollisionPolygonEditor::_canvas_draw);
+	ObjectTypeDB::bind_method(_MD("_polygon_draw"),&CollisionPolygonEditor::_polygon_draw);
+	ObjectTypeDB::bind_method(_MD("_node_removed"),&CollisionPolygonEditor::_node_removed);
 
 }
 
 CollisionPolygonEditor::CollisionPolygonEditor(EditorNode *p_editor) {
 
-	canvas_item_editor=NULL;
+
 	editor=p_editor;
 	undo_redo = editor->get_undo_redo();
 
@@ -439,7 +569,42 @@ CollisionPolygonEditor::CollisionPolygonEditor(EditorNode *p_editor) {
 
 	mode = MODE_EDIT;
 	wip_active=false;
+	imgeom = memnew( ImmediateGeometry );
+	imgeom->set_transform(Transform(Matrix3(),Vector3(0,0,0.00001)));
+
+
+	line_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
+	line_material->set_flag(Material::FLAG_UNSHADED, true);
+	line_material->set_line_width(3.0);
+	line_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
+	line_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, true);
+	line_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1));
+
+
+
+
+	handle_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
+	handle_material->set_flag(Material::FLAG_UNSHADED, true);
+	handle_material->set_fixed_flag(FixedMaterial::FLAG_USE_POINT_SIZE, true);
+	handle_material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1));
+	handle_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
+	handle_material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY, false);
+	Ref<Texture> handle= SpatialEditor::get_singleton()->get_icon("Editor3DHandle","EditorIcons");
+	handle_material->set_point_size(handle->get_width());
+	handle_material->set_texture(FixedMaterial::PARAM_DIFFUSE,handle);
+
+	pointsm = memnew( MeshInstance );
+	imgeom->add_child(pointsm);
+	m = Ref<Mesh>( memnew( Mesh ) );
+	pointsm->set_mesh(m);
+	pointsm->set_transform(Transform(Matrix3(),Vector3(0,0,0.00001)));
+
+
+}
+
+CollisionPolygonEditor::~CollisionPolygonEditor() {
 
+	memdelete( imgeom );
 }
 
 
@@ -450,7 +615,7 @@ void CollisionPolygonEditorPlugin::edit(Object *p_object) {
 
 bool CollisionPolygonEditorPlugin::handles(Object *p_object) const {
 
-	return p_object->is_type("CollisionPolygon2D");
+	return p_object->is_type("CollisionPolygon");
 }
 
 void CollisionPolygonEditorPlugin::make_visible(bool p_visible) {
@@ -469,7 +634,7 @@ CollisionPolygonEditorPlugin::CollisionPolygonEditorPlugin(EditorNode *p_node) {
 
 	editor=p_node;
 	collision_polygon_editor = memnew( CollisionPolygonEditor(p_node) );
-	CanvasItemEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
+	SpatialEditor::get_singleton()->add_control_to_menu_panel(collision_polygon_editor);
 
 	collision_polygon_editor->hide();
 

+ 17 - 6
tools/editor/plugins/collision_polygon_editor_plugin.h

@@ -31,7 +31,9 @@
 
 #include "tools/editor/editor_plugin.h"
 #include "tools/editor/editor_node.h"
-#include "scene/2d/collision_polygon_2d.h"
+#include "scene/3d/collision_polygon.h"
+#include "scene/3d/immediate_geometry.h"
+#include "scene/3d/mesh_instance.h"
 #include "scene/gui/tool_button.h"
 #include "scene/gui/button_group.h"
 
@@ -57,10 +59,17 @@ class CollisionPolygonEditor : public HBoxContainer {
 	ToolButton *button_create;
 	ToolButton *button_edit;
 
-	CanvasItemEditor *canvas_item_editor;
+
+	Ref<FixedMaterial> line_material;
+	Ref<FixedMaterial> handle_material;
+
 	EditorNode *editor;
 	Panel *panel;
-	CollisionPolygon2D *node;
+	CollisionPolygon *node;
+	ImmediateGeometry *imgeom;
+	MeshInstance *pointsm;
+	Ref<Mesh> m;
+
 	MenuButton *options;
 
 	int edited_point;
@@ -69,9 +78,10 @@ class CollisionPolygonEditor : public HBoxContainer {
 	Vector<Vector2> wip;
 	bool wip_active;
 
+	float prev_depth;
 
 	void _wip_close();
-	void _canvas_draw();
+	void _polygon_draw();
 	void _menu_option(int p_option);
 
 protected:
@@ -81,9 +91,10 @@ protected:
 public:
 
 	Vector2 snap_point(const Vector2& p_point) const;
-	bool forward_input_event(const InputEvent& p_event);
+	virtual bool forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event);
 	void edit(Node *p_collision_polygon);
 	CollisionPolygonEditor(EditorNode *p_editor);
+	~CollisionPolygonEditor();
 };
 
 class CollisionPolygonEditorPlugin : public EditorPlugin {
@@ -95,7 +106,7 @@ class CollisionPolygonEditorPlugin : public EditorPlugin {
 
 public:
 
-	virtual bool forward_input_event(const InputEvent& p_event) { return collision_polygon_editor->forward_input_event(p_event); }
+	virtual bool forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) { return collision_polygon_editor->forward_spatial_input_event(p_camera,p_event); }
 
 	virtual String get_name() const { return "CollisionPolygon"; }
 	bool has_main_screen() const { return false; }

+ 6 - 0
tools/editor/plugins/spatial_editor_plugin.cpp

@@ -690,10 +690,16 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) {
 
 				case BUTTON_WHEEL_UP: {
 
+
 					cursor.distance/=1.08;
+					if (cursor.distance<0.001)
+						cursor.distance=0.001;
+
 				} break;
 				case BUTTON_WHEEL_DOWN: {
 
+					if (cursor.distance<0.001)
+						cursor.distance=0.001;
 					cursor.distance*=1.08;
 
 				} break;

+ 39 - 0
tools/editor/spatial_editor_gizmos.cpp

@@ -2066,7 +2066,39 @@ CollisionShapeSpatialGizmo::CollisionShapeSpatialGizmo(CollisionShape* p_cs) {
 
 
 
+/////
+
+
+void CollisionPolygonSpatialGizmo::redraw() {
+
+	clear();
+
+	Vector<Vector2> points = polygon->get_polygon();
+	float depth = polygon->get_depth()*0.5;
 
+	Vector<Vector3> lines;
+	for(int i=0;i<points.size();i++) {
+
+		int n = (i+1)%points.size();
+		lines.push_back(Vector3(points[i].x,points[i].y,depth));
+		lines.push_back(Vector3(points[n].x,points[n].y,depth));
+		lines.push_back(Vector3(points[i].x,points[i].y,-depth));
+		lines.push_back(Vector3(points[n].x,points[n].y,-depth));
+		lines.push_back(Vector3(points[i].x,points[i].y,depth));
+		lines.push_back(Vector3(points[i].x,points[i].y,-depth));
+
+	}
+
+	add_lines(lines,SpatialEditorGizmos::singleton->shape_material);
+	add_collision_segments(lines);
+}
+
+CollisionPolygonSpatialGizmo::CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon){
+
+	set_spatial_node(p_polygon);
+	polygon=p_polygon;
+}
+///
 
 
 String VisibilityNotifierGizmo::get_handle_name(int p_idx) const {
@@ -2901,6 +2933,13 @@ Ref<SpatialEditorGizmo> SpatialEditorGizmos::get_gizmo(Spatial *p_spatial) {
 		return misg;
 	}
 
+	if (p_spatial->cast_to<CollisionPolygon>()) {
+
+		Ref<CollisionPolygonSpatialGizmo> misg = memnew( CollisionPolygonSpatialGizmo(p_spatial->cast_to<CollisionPolygon>()) );
+		return misg;
+	}
+
+
 	return Ref<SpatialEditorGizmo>();
 }
 

+ 16 - 0
tools/editor/spatial_editor_gizmos.h

@@ -46,6 +46,7 @@
 #include "scene/3d/navigation_mesh.h"
 #include "scene/3d/car_body.h"
 #include "scene/3d/vehicle_body.h"
+#include "scene/3d/collision_polygon.h"
 #include "scene/3d/physics_joint.h"
 
 
@@ -302,6 +303,21 @@ public:
 
 };
 
+
+class CollisionPolygonSpatialGizmo  : public SpatialGizmoTool {
+
+	OBJ_TYPE(CollisionPolygonSpatialGizmo,SpatialGizmoTool);
+
+	CollisionPolygon* polygon;
+
+public:
+
+	void redraw();
+	CollisionPolygonSpatialGizmo(CollisionPolygon* p_polygon=NULL);
+
+};
+
+
 class RayCastSpatialGizmo  : public SpatialGizmoTool {
 
 	OBJ_TYPE(RayCastSpatialGizmo,SpatialGizmoTool);