Browse Source

Merge branch 'master' of https://github.com/godotengine/godot

Juan Linietsky 9 years ago
parent
commit
990690f9f5

+ 4 - 0
core/object.cpp

@@ -1405,6 +1405,10 @@ bool Object::is_connected(const StringName& p_signal, Object *p_to_object, const
 		bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
 		bool signal_is_valid = ObjectTypeDB::has_signal(get_type_name(),p_signal);
 		if (signal_is_valid)
 		if (signal_is_valid)
 			return false;
 			return false;
+
+		if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal))
+			return false;
+
 		ERR_EXPLAIN("Nonexistent signal: "+p_signal);
 		ERR_EXPLAIN("Nonexistent signal: "+p_signal);
 		ERR_FAIL_COND_V(!s,false);
 		ERR_FAIL_COND_V(!s,false);
 	}
 	}

+ 33 - 30
drivers/SCsub

@@ -61,39 +61,42 @@ import string
 if env['vsproj']=="yes":
 if env['vsproj']=="yes":
 	env.AddToVSProject(env.drivers_sources)
 	env.AddToVSProject(env.drivers_sources)
 
 
-for f in env.drivers_sources:
-	fname = ""
-	if type(f) == type(""):
-		fname = env.File(f).path
-	else:
-		fname = env.File(f)[0].path
-	fname = fname.replace("\\", "/")
-	base = string.join(fname.split("/")[:2], "/")
-	if base != cur_base and len(list) > max_src:
-		if num > 0:
-			lib = env.Library("drivers"+str(num), list)
-			lib_list.append(lib)
-			list = []
-		num = num+1
-	cur_base = base
-	list.append(f)
+if (False): #split drivers, this used to be needed for windows until separate builders for windows were created
 
 
-lib = env.Library("drivers"+str(num), list)
-lib_list.append(lib)
+	for f in env.drivers_sources:
+		fname = ""
+		if type(f) == type(""):
+			fname = env.File(f).path
+		else:
+			fname = env.File(f)[0].path
+		fname = fname.replace("\\", "/")
+		base = string.join(fname.split("/")[:2], "/")
+		if base != cur_base and len(list) > max_src:
+			if num > 0:
+				lib = env.Library("drivers"+str(num), list)
+				lib_list.append(lib)
+				list = []
+			num = num+1
+		cur_base = base
+		list.append(f)
 
 
-if len(lib_list) > 0:
-	import os, sys
-	if os.name=='posix' and sys.platform=='msys':
-		env.Replace(ARFLAGS=['rcsT'])
+	lib = env.Library("drivers"+str(num), list)
+	lib_list.append(lib)
 
 
-		lib = env.Library("drivers_collated", lib_list)
-		lib_list = [lib]
+	if len(lib_list) > 0:
+		import os, sys
+		if os.name=='posix' and sys.platform=='msys':
+			env.Replace(ARFLAGS=['rcsT'])
 
 
-drivers_base=[]
-env.add_source_files(drivers_base,"*.cpp")
-lib_list.insert(0, env.Library("drivers", drivers_base))
+			lib = env.Library("drivers_collated", lib_list)
+			lib_list = [lib]
 
 
-env.Prepend(LIBS=lib_list)
+	drivers_base=[]
+	env.add_source_files(drivers_base,"*.cpp")
+	lib_list.insert(0, env.Library("drivers", drivers_base))
 
 
-#lib = env.Library("drivers",env.drivers_sources)
-#env.Prepend(LIBS=[lib])
+	env.Prepend(LIBS=lib_list)
+else:
+	env.add_source_files(env.drivers_sources,"*.cpp")
+	lib = env.Library("drivers",env.drivers_sources)
+	env.Prepend(LIBS=[lib])

+ 2 - 0
scene/2d/canvas_item.cpp

@@ -1156,6 +1156,8 @@ Matrix32 CanvasItem::get_canvas_transform() const {
 
 
 	if (canvas_layer)
 	if (canvas_layer)
 		return canvas_layer->get_transform();
 		return canvas_layer->get_transform();
+	else if (get_parent()->cast_to<CanvasItem>())
+		return get_parent()->cast_to<CanvasItem>()->get_canvas_transform();
 	else
 	else
 		return get_viewport()->get_canvas_transform();
 		return get_viewport()->get_canvas_transform();
 
 

+ 31 - 0
scene/gui/spin_box.cpp

@@ -68,6 +68,25 @@ void SpinBox::_line_edit_input(const InputEvent& p_event) {
 
 
 }
 }
 
 
+void SpinBox::_range_click_timeout() {
+
+	if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+
+		int pos_y = Input::get_singleton()->get_mouse_pos().y-get_global_pos().y;
+		bool up = pos_y < (get_size().height/2);
+		set_val( get_val() + (up?get_step():-get_step()));
+
+		if (range_click_timer->is_one_shot()) {
+			range_click_timer->set_wait_time(0.075);
+			range_click_timer->set_one_shot(false);
+			range_click_timer->start();
+		}
+
+	} else {
+		range_click_timer->stop();
+	}
+}
+
 
 
 void SpinBox::_input_event(const InputEvent& p_event) {
 void SpinBox::_input_event(const InputEvent& p_event) {
 
 
@@ -85,6 +104,10 @@ void SpinBox::_input_event(const InputEvent& p_event) {
 
 
 				set_val( get_val() + (up?get_step():-get_step()));
 				set_val( get_val() + (up?get_step():-get_step()));
 
 
+				range_click_timer->set_wait_time(0.6);
+				range_click_timer->set_one_shot(true);
+				range_click_timer->start();
+
 			} break;
 			} break;
 			case BUTTON_RIGHT: {
 			case BUTTON_RIGHT: {
 
 
@@ -112,6 +135,8 @@ void SpinBox::_input_event(const InputEvent& p_event) {
 	if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
 	if (p_event.type==InputEvent::MOUSE_BUTTON && !p_event.mouse_button.pressed && p_event.mouse_button.button_index==1) {
 
 
 		//set_default_cursor_shape(CURSOR_ARROW);
 		//set_default_cursor_shape(CURSOR_ARROW);
+		range_click_timer->stop();
+
 		if (drag.enabled) {
 		if (drag.enabled) {
 			drag.enabled=false;
 			drag.enabled=false;
 			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
 			Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
@@ -167,6 +192,7 @@ void SpinBox::_notification(int p_what) {
 		Size2i size = get_size();
 		Size2i size = get_size();
 
 
 		updown->draw(ci,Point2i(size.width-updown->get_width(),(size.height-updown->get_height())/2));
 		updown->draw(ci,Point2i(size.width-updown->get_width(),(size.height-updown->get_height())/2));
+
 	} else if (p_what==NOTIFICATION_FOCUS_EXIT) {
 	} else if (p_what==NOTIFICATION_FOCUS_EXIT) {
 
 
 
 
@@ -227,6 +253,7 @@ void SpinBox::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
 	ObjectTypeDB::bind_method(_MD("_line_edit_focus_exit"),&SpinBox::_line_edit_focus_exit);
 	ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
 	ObjectTypeDB::bind_method(_MD("get_line_edit"),&SpinBox::get_line_edit);
 	ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
 	ObjectTypeDB::bind_method(_MD("_line_edit_input"),&SpinBox::_line_edit_input);
+	ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&SpinBox::_range_click_timeout);
 
 
 
 
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"editable"),_SCS("set_editable"),_SCS("is_editable"));
@@ -248,4 +275,8 @@ SpinBox::SpinBox() {
 	line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
 	line_edit->connect("focus_exit",this,"_line_edit_focus_exit",Vector<Variant>(),CONNECT_DEFERRED);
 	line_edit->connect("input_event",this,"_line_edit_input");
 	line_edit->connect("input_event",this,"_line_edit_input");
 	drag.enabled=false;
 	drag.enabled=false;
+
+	range_click_timer = memnew( Timer );
+	range_click_timer->connect("timeout",this,"_range_click_timeout");
+	add_child(range_click_timer);
 }
 }

+ 4 - 0
scene/gui/spin_box.h

@@ -31,6 +31,7 @@
 
 
 #include "scene/gui/line_edit.h"
 #include "scene/gui/line_edit.h"
 #include "scene/gui/range.h"
 #include "scene/gui/range.h"
+#include "scene/main/timer.h"
 
 
 class SpinBox : public Range {
 class SpinBox : public Range {
 
 
@@ -39,6 +40,9 @@ class SpinBox : public Range {
 	LineEdit *line_edit;
 	LineEdit *line_edit;
 	int last_w;
 	int last_w;
 
 
+	Timer *range_click_timer;
+	void _range_click_timeout();
+
 	void _text_entered(const String& p_string);
 	void _text_entered(const String& p_string);
 	virtual void _value_changed(double);
 	virtual void _value_changed(double);
 	String prefix;
 	String prefix;

+ 38 - 3
scene/gui/text_edit.cpp

@@ -29,6 +29,7 @@
 
 
 #include "text_edit.h"
 #include "text_edit.h"
 #include "os/keyboard.h"
 #include "os/keyboard.h"
+#include "os/input.h"
 #include "os/os.h"
 #include "os/os.h"
 
 
 #include "globals.h"
 #include "globals.h"
@@ -349,6 +350,29 @@ void TextEdit::_update_scrollbars() {
 	updating_scrolls=false;
 	updating_scrolls=false;
 }
 }
 
 
+void TextEdit::_click_selection_held() {
+
+	if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode!=Selection::MODE_NONE) {
+
+		Point2 mp = Input::get_singleton()->get_mouse_pos()-get_global_pos();
+
+		int row,col;
+		_get_mouse_pos(Point2i(mp.x,mp.y), row,col);
+
+		select(selection.selecting_line,selection.selecting_column,row,col);
+
+		cursor_set_line( row );
+		cursor_set_column( col );
+		update();
+
+		click_select_held->start();
+
+	} else {
+
+		click_select_held->stop();
+	}
+}
+
 
 
 void TextEdit::_notification(int p_what) {
 void TextEdit::_notification(int p_what) {
 	
 	
@@ -1292,6 +1316,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
 					update();
 					update();
 				}
 				}
 			} else {
 			} else {
+
+				if (mb.button_index==BUTTON_LEFT)
+					click_select_held->stop();
 				
 				
 				// notify to show soft keyboard
 				// notify to show soft keyboard
 				notification(NOTIFICATION_FOCUS_ENTER);
 				notification(NOTIFICATION_FOCUS_ENTER);
@@ -1304,16 +1331,18 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
 			
 			
 			if (mm.button_mask&BUTTON_MASK_LEFT) {
 			if (mm.button_mask&BUTTON_MASK_LEFT) {
 				
 				
-				int row,col;
-				_get_mouse_pos(Point2i(mm.x,mm.y), row,col);
-				
 				if (selection.selecting_mode!=Selection::MODE_NONE) {
 				if (selection.selecting_mode!=Selection::MODE_NONE) {
+
+					int row,col;
+					_get_mouse_pos(Point2i(mm.x,mm.y), row,col);
 					
 					
 					select(selection.selecting_line,selection.selecting_column,row,col);
 					select(selection.selecting_line,selection.selecting_column,row,col);
 					
 					
 					cursor_set_line( row );
 					cursor_set_line( row );
 					cursor_set_column( col );
 					cursor_set_column( col );
 					update();
 					update();
+
+					click_select_held->start();
 					
 					
 				}
 				}
 				
 				
@@ -3697,6 +3726,7 @@ void TextEdit::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit);
 	ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit);
 	ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit);
 	ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit);
 	ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op);
 	ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op);
+	ObjectTypeDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held);
 	
 	
 	BIND_CONSTANT( SEARCH_MATCH_CASE );
 	BIND_CONSTANT( SEARCH_MATCH_CASE );
 	BIND_CONSTANT( SEARCH_WHOLE_WORDS );
 	BIND_CONSTANT( SEARCH_WHOLE_WORDS );
@@ -3811,6 +3841,11 @@ TextEdit::TextEdit()  {
 	idle_detect->set_one_shot(true);
 	idle_detect->set_one_shot(true);
 	idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3));
 	idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3));
 	idle_detect->connect("timeout", this,"_push_current_op");
 	idle_detect->connect("timeout", this,"_push_current_op");
+
+	click_select_held = memnew( Timer );
+	add_child(click_select_held);
+	click_select_held->set_wait_time(0.05);
+	click_select_held->connect("timeout", this,"_click_selection_held");
 	
 	
 #if 0
 #if 0
 	syntax_coloring=true;
 	syntax_coloring=true;

+ 2 - 0
scene/gui/text_edit.h

@@ -219,6 +219,7 @@ class TextEdit : public Control  {
 	uint64_t last_dblclk;
 	uint64_t last_dblclk;
 
 
 	Timer *idle_detect;
 	Timer *idle_detect;
+	Timer *click_select_held;
 	HScrollBar *h_scroll;
 	HScrollBar *h_scroll;
 	VScrollBar *v_scroll;
 	VScrollBar *v_scroll;
 	bool updating_scrolls;
 	bool updating_scrolls;
@@ -240,6 +241,7 @@ class TextEdit : public Control  {
 	void adjust_viewport_to_cursor();
 	void adjust_viewport_to_cursor();
 	void _scroll_moved(double);
 	void _scroll_moved(double);
 	void _update_scrollbars();
 	void _update_scrollbars();
+	void _click_selection_held();
 
 
 	void _pre_shift_selection();
 	void _pre_shift_selection();
 	void _post_shift_selection();
 	void _post_shift_selection();

+ 61 - 1
scene/gui/tree.cpp

@@ -1369,7 +1369,40 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) {
 }
 }
 
 
 
 
+void Tree::_range_click_timeout() {
 
 
+	if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+
+		Point2 pos = (Input::get_singleton()->get_mouse_pos()-get_global_pos())-cache.bg->get_offset();
+		if (show_column_titles) {
+			pos.y-=_get_title_button_height();
+
+			if (pos.y<0) {
+				range_click_timer->stop();
+				return;
+			}
+		}
+
+		click_handled=false;
+		InputModifierState mod = {}; // should be irrelevant..
+
+		blocked++;
+		propagate_mouse_event(pos+cache.offset, 0, 0, false, root, BUTTON_LEFT, mod);
+		blocked--;
+
+		if (range_click_timer->is_one_shot()) {
+			range_click_timer->set_wait_time(0.05);
+			range_click_timer->set_one_shot(false);
+			range_click_timer->start();
+		}
+
+		if (!click_handled)
+			range_click_timer->stop();
+
+	} else {
+		range_click_timer->stop();
+	}
+}
 
 
 
 
 int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_doubleclick,TreeItem *p_item,int p_button,const InputModifierState& p_mod) {
 int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_doubleclick,TreeItem *p_item,int p_button,const InputModifierState& p_mod) {
@@ -1564,9 +1597,25 @@ int Tree::propagate_mouse_event(const Point2i &p_pos,int x_ofs,int y_ofs,bool p_
 						bool up=p_pos.y < (item_h /2);
 						bool up=p_pos.y < (item_h /2);
 
 
 						if (p_button==BUTTON_LEFT) {
 						if (p_button==BUTTON_LEFT) {
+
+							if (range_click_timer->get_time_left() == 0) {
+
+								range_item_last=p_item;
+								range_up_last=up;
+
+								range_click_timer->set_wait_time(0.6);
+								range_click_timer->set_one_shot(true);
+								range_click_timer->start();
+
+							} else if (up != range_up_last) {
+
+								return -1; // break. avoid changing direction on mouse held
+							}
+
 							p_item->set_range( col, c.val + (up?1.0:-1.0) * c.step );
 							p_item->set_range( col, c.val + (up?1.0:-1.0) * c.step );
 
 
 							item_edited(col,p_item);
 							item_edited(col,p_item);
+
 						} else if (p_button==BUTTON_RIGHT) {
 						} else if (p_button==BUTTON_RIGHT) {
 
 
 							p_item->set_range( col, (up?c.max:c.min) );
 							p_item->set_range( col, (up?c.max:c.min) );
@@ -2024,6 +2073,8 @@ void Tree::_input_event(InputEvent p_event) {
 				update_cache();
 				update_cache();
 			const InputEventMouseMotion& b=p_event.mouse_motion;
 			const InputEventMouseMotion& b=p_event.mouse_motion;
 
 
+			range_click_timer->stop();
+
 			Ref<StyleBox> bg = cache.bg;
 			Ref<StyleBox> bg = cache.bg;
 
 
 			Point2 pos = Point2(b.x,b.y) - bg->get_offset();
 			Point2 pos = Point2(b.x,b.y) - bg->get_offset();
@@ -2031,7 +2082,6 @@ void Tree::_input_event(InputEvent p_event) {
 			Cache::ClickType old_hover = cache.hover_type;
 			Cache::ClickType old_hover = cache.hover_type;
 			int old_index = cache.hover_index;
 			int old_index = cache.hover_index;
 
 
-
 			cache.hover_type=Cache::CLICK_NONE;
 			cache.hover_type=Cache::CLICK_NONE;
 			cache.hover_index=0;
 			cache.hover_index=0;
 			if (show_column_titles) {
 			if (show_column_titles) {
@@ -2108,6 +2158,8 @@ void Tree::_input_event(InputEvent p_event) {
 
 
 				if (b.button_index==BUTTON_LEFT) {
 				if (b.button_index==BUTTON_LEFT) {
 
 
+					range_click_timer->stop();
+
 					if (pressing_for_editor) {
 					if (pressing_for_editor) {
 
 
 						if (range_drag_enabled) {
 						if (range_drag_enabled) {
@@ -2228,10 +2280,13 @@ void Tree::_input_event(InputEvent p_event) {
 
 
 				} break;
 				} break;
 				case BUTTON_WHEEL_UP: {
 				case BUTTON_WHEEL_UP: {
+
+					range_click_timer->stop();
 					v_scroll->set_val( v_scroll->get_val()-v_scroll->get_page()/8 );
 					v_scroll->set_val( v_scroll->get_val()-v_scroll->get_page()/8 );
 				} break;
 				} break;
 				case BUTTON_WHEEL_DOWN: {
 				case BUTTON_WHEEL_DOWN: {
 
 
+					range_click_timer->stop();
 					v_scroll->set_val( v_scroll->get_val()+v_scroll->get_page()/8 );
 					v_scroll->set_val( v_scroll->get_val()+v_scroll->get_page()/8 );
 				} break;
 				} break;
 			}
 			}
@@ -3135,6 +3190,7 @@ bool Tree::is_folding_hidden() const {
 
 
 void Tree::_bind_methods() {
 void Tree::_bind_methods() {
 
 
+	ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout);
 	ObjectTypeDB::bind_method(_MD("_input_event"),&Tree::_input_event);
 	ObjectTypeDB::bind_method(_MD("_input_event"),&Tree::_input_event);
 	ObjectTypeDB::bind_method(_MD("_popup_select"),&Tree::popup_select);
 	ObjectTypeDB::bind_method(_MD("_popup_select"),&Tree::popup_select);
 	ObjectTypeDB::bind_method(_MD("_text_editor_enter"),&Tree::text_editor_enter);
 	ObjectTypeDB::bind_method(_MD("_text_editor_enter"),&Tree::text_editor_enter);
@@ -3229,6 +3285,10 @@ Tree::Tree() {
 	add_child(h_scroll);
 	add_child(h_scroll);
 	add_child(v_scroll);
 	add_child(v_scroll);
 
 
+	range_click_timer = memnew( Timer );
+	range_click_timer->connect("timeout",this,"_range_click_timeout");
+	add_child(range_click_timer);
+
 	h_scroll->connect("value_changed", this,"_scroll_moved");
 	h_scroll->connect("value_changed", this,"_scroll_moved");
 	v_scroll->connect("value_changed", this,"_scroll_moved");
 	v_scroll->connect("value_changed", this,"_scroll_moved");
 	text_editor->connect("text_entered", this,"_text_editor_enter");
 	text_editor->connect("text_entered", this,"_text_editor_enter");

+ 6 - 1
scene/gui/tree.h

@@ -127,7 +127,7 @@ friend class Tree;
 
 
 
 
 	
 	
-	TreeItem(Tree *p_tree);		
+	TreeItem(Tree *p_tree);
 		
 		
 
 
 	void _changed_notify(int p_cell);
 	void _changed_notify(int p_cell);
@@ -301,6 +301,11 @@ friend class TreeItem;
 
 
 	Vector<ColumnInfo> columns;
 	Vector<ColumnInfo> columns;
 
 
+	Timer *range_click_timer;
+	TreeItem *range_item_last;
+	bool range_up_last;
+	void _range_click_timeout();
+
 	int compute_item_height(TreeItem *p_item) const;
 	int compute_item_height(TreeItem *p_item) const;
 	int get_item_height(TreeItem *p_item) const;
 	int get_item_height(TreeItem *p_item) const;
 //	void draw_item_text(String p_text,const Ref<Texture>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color);
 //	void draw_item_text(String p_text,const Ref<Texture>& p_icon,int p_icon_max_w,bool p_tool,Rect2i p_rect,const Color& p_color);

+ 71 - 63
tools/editor/plugins/mesh_editor_plugin.cpp

@@ -1,13 +1,8 @@
 #include "mesh_editor_plugin.h"
 #include "mesh_editor_plugin.h"
 
 
-#include "tools/editor/editor_plugin.h"
-#include "tools/editor/editor_node.h"
-#include "scene/3d/mesh_instance.h"
 #include "scene/3d/physics_body.h"
 #include "scene/3d/physics_body.h"
 #include "scene/3d/body_shape.h"
 #include "scene/3d/body_shape.h"
-#include "scene/gui/spin_box.h"
 #include "scene/gui/box_container.h"
 #include "scene/gui/box_container.h"
-#include "scene/3d/mesh_instance.h"
 #include "scene/3d/navigation_mesh.h"
 #include "scene/3d/navigation_mesh.h"
 #include "spatial_editor_plugin.h"
 #include "spatial_editor_plugin.h"
 
 
@@ -38,92 +33,106 @@ void MeshInstanceEditor::_menu_option(int p_option) {
 	}
 	}
 
 
 	switch(p_option) {
 	switch(p_option) {
-		case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: {
+		case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY:
+		case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {
 
 
-			Ref<Shape> shape = mesh->create_trimesh_shape();
-			if (shape.is_null())
-				return;
-			StaticBody *body = memnew( StaticBody );
-			CollisionShape *cshape = memnew( CollisionShape );
-			cshape->set_shape(shape);
-			body->add_child(cshape);
-			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();
+			bool trimesh_shape = (p_option==MENU_OPTION_CREATE_STATIC_TRIMESH_BODY);
 
 
+			EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection();
 			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
 			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-			ur->create_action("Create Static Trimesh");
-			ur->add_do_method(node,"add_child",body);
-			ur->add_do_method(body,"set_owner",owner);
-			ur->add_do_method(cshape,"set_owner",owner);
-			ur->add_do_reference(body);
-			ur->add_undo_method(node,"remove_child",body);
-			ur->commit_action();
 
 
-		} break;
-		case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: {
+			List<Node*> selection = editor_selection->get_selected_node_list();
 
 
-			Ref<Shape> shape = mesh->create_convex_shape();
-			if (shape.is_null())
-				return;
-			StaticBody *body = memnew( StaticBody );
-			CollisionShape *cshape = memnew( CollisionShape );
-			cshape->set_shape(shape);
-			body->add_child(cshape);
-			Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();
+			if (selection.empty()) {
+				Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape();
+				if (shape.is_null())
+					return;
 
 
-			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-			ur->create_action("Create Static Trimesh");
-			ur->add_do_method(node,"add_child",body);
-			ur->add_do_method(body,"set_owner",owner);
-			ur->add_do_method(cshape,"set_owner",owner);
-			ur->add_do_reference(body);
-			ur->add_undo_method(node,"remove_child",body);
-			ur->commit_action();
+				CollisionShape *cshape = memnew( CollisionShape );
+				cshape->set_shape(shape);
+				StaticBody *body = memnew( StaticBody );
+				body->add_child(cshape);
 
 
-		} break;
-		case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: {
+				Node *owner = node==get_tree()->get_edited_scene_root() ? node : node->get_owner();
 
 
+				if (trimesh_shape)
+					ur->create_action("Create Static Trimesh Body");
+				else
+					ur->create_action("Create Static Convex Body");
 
 
-			if (node==get_tree()->get_edited_scene_root()) {
-				err_dialog->set_text("This doesn't work on scene root!");
-				err_dialog->popup_centered_minsize();
+				ur->add_do_method(node,"add_child",body);
+				ur->add_do_method(body,"set_owner",owner);
+				ur->add_do_method(cshape,"set_owner",owner);
+				ur->add_do_reference(body);
+				ur->add_undo_method(node,"remove_child",body);
+				ur->commit_action();
 				return;
 				return;
 			}
 			}
-			Ref<Shape> shape = mesh->create_trimesh_shape();
-			if (shape.is_null())
-				return;
-			CollisionShape *cshape = memnew( CollisionShape );
-			cshape->set_shape(shape);
 
 
-			Node *owner =  node->get_owner();
+			if (trimesh_shape)
+				ur->create_action("Create Static Trimesh Body");
+			else
+				ur->create_action("Create Static Convex Body");
+
+			for (List<Node*>::Element *E=selection.front();E;E=E->next()) {
+
+				MeshInstance *instance = E->get()->cast_to<MeshInstance>();
+				if (!instance)
+					continue;
+
+				Ref<Mesh> m = instance->get_mesh();
+				if (m.is_null())
+					continue;
+
+				Ref<Shape> shape = trimesh_shape ? m->create_trimesh_shape() : m->create_convex_shape();
+				if (shape.is_null())
+					continue;
+
+				CollisionShape *cshape = memnew( CollisionShape );
+				cshape->set_shape(shape);
+				StaticBody *body = memnew( StaticBody );
+				body->add_child(cshape);
+
+				Node *owner = instance==get_tree()->get_edited_scene_root() ? instance : instance->get_owner();
+
+				ur->add_do_method(instance,"add_child",body);
+				ur->add_do_method(body,"set_owner",owner);
+				ur->add_do_method(cshape,"set_owner",owner);
+				ur->add_do_reference(body);
+				ur->add_undo_method(instance,"remove_child",body);
+			}
 
 
-			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-			ur->create_action("Create Static Trimesh");
-			ur->add_do_method(node->get_parent(),"add_child",cshape);
-			ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
-			ur->add_do_method(cshape,"set_owner",owner);
-			ur->add_do_reference(cshape);
-			ur->add_undo_method(node->get_parent(),"remove_child",cshape);
 			ur->commit_action();
 			ur->commit_action();
 
 
 		} break;
 		} break;
-		case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {
 
 
+		case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE:
+		case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: {
 
 
 			if (node==get_tree()->get_edited_scene_root()) {
 			if (node==get_tree()->get_edited_scene_root()) {
 				err_dialog->set_text("This doesn't work on scene root!");
 				err_dialog->set_text("This doesn't work on scene root!");
 				err_dialog->popup_centered_minsize();
 				err_dialog->popup_centered_minsize();
 				return;
 				return;
 			}
 			}
-			Ref<Shape> shape = mesh->create_convex_shape();
+
+			bool trimesh_shape = (p_option==MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE);
+
+			Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape();
 			if (shape.is_null())
 			if (shape.is_null())
 				return;
 				return;
+
 			CollisionShape *cshape = memnew( CollisionShape );
 			CollisionShape *cshape = memnew( CollisionShape );
 			cshape->set_shape(shape);
 			cshape->set_shape(shape);
 
 
 			Node *owner =  node->get_owner();
 			Node *owner =  node->get_owner();
 
 
 			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
 			UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo();
-			ur->create_action("Create Static Trimesh");
+
+			if (trimesh_shape)
+				ur->create_action("Create Trimesh Shape");
+			else
+				ur->create_action("Create Convex Shape");
+
 			ur->add_do_method(node->get_parent(),"add_child",cshape);
 			ur->add_do_method(node->get_parent(),"add_child",cshape);
 			ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
 			ur->add_do_method(node->get_parent(),"move_child",cshape,node->get_index()+1);
 			ur->add_do_method(cshape,"set_owner",owner);
 			ur->add_do_method(cshape,"set_owner",owner);
@@ -132,10 +141,8 @@ void MeshInstanceEditor::_menu_option(int p_option) {
 			ur->commit_action();
 			ur->commit_action();
 
 
 		} break;
 		} break;
-		case MENU_OPTION_CREATE_NAVMESH: {
-
-
 
 
+		case MENU_OPTION_CREATE_NAVMESH: {
 
 
 			Ref<NavigationMesh> nmesh = memnew( NavigationMesh );
 			Ref<NavigationMesh> nmesh = memnew( NavigationMesh );
 
 
@@ -158,6 +165,7 @@ void MeshInstanceEditor::_menu_option(int p_option) {
 			ur->add_undo_method(node,"remove_child",nmi);
 			ur->add_undo_method(node,"remove_child",nmi);
 			ur->commit_action();
 			ur->commit_action();
 		} break;
 		} break;
+
 		case MENU_OPTION_CREATE_OUTLINE_MESH: {
 		case MENU_OPTION_CREATE_OUTLINE_MESH: {
 
 
 			outline_dialog->popup_centered(Vector2(200, 90));
 			outline_dialog->popup_centered(Vector2(200, 90));

+ 4 - 9
tools/editor/plugins/mesh_editor_plugin.h

@@ -23,24 +23,19 @@ class MeshInstanceEditor : public Node {
 		MENU_OPTION_CREATE_OUTLINE_MESH,
 		MENU_OPTION_CREATE_OUTLINE_MESH,
 	};
 	};
 
 
+	MeshInstance *node;
+
+	MenuButton *options;
+
 	ConfirmationDialog *outline_dialog;
 	ConfirmationDialog *outline_dialog;
 	SpinBox *outline_size;
 	SpinBox *outline_size;
 
 
 	AcceptDialog *err_dialog;
 	AcceptDialog *err_dialog;
 
 
-
-	Panel *panel;
-	MeshInstance *node;
-
-	LineEdit *surface_source;
-	LineEdit *mesh_source;
-
-
 	void _menu_option(int p_option);
 	void _menu_option(int p_option);
 	void _create_outline_mesh();
 	void _create_outline_mesh();
 
 
 friend class MeshInstanceEditorPlugin;
 friend class MeshInstanceEditorPlugin;
-	MenuButton * options;
 
 
 protected:
 protected:
 	void _node_removed(Node *p_node);
 	void _node_removed(Node *p_node);