diff options
Diffstat (limited to 'tools/editor/property_selector.cpp')
| -rw-r--r-- | tools/editor/property_selector.cpp | 598 | 
1 files changed, 598 insertions, 0 deletions
diff --git a/tools/editor/property_selector.cpp b/tools/editor/property_selector.cpp new file mode 100644 index 0000000000..20b72240d9 --- /dev/null +++ b/tools/editor/property_selector.cpp @@ -0,0 +1,598 @@ +#include "property_selector.h" +#include "editor_scale.h" + +#include "os/keyboard.h" + +void PropertySelector::_text_changed(const String& p_newtext) { + +	_update_search(); +} + +void PropertySelector::_sbox_input(const InputEvent& p_ie) { + +	if (p_ie.type==InputEvent::KEY) { + +		switch(p_ie.key.scancode) { +			case KEY_UP: +			case KEY_DOWN: +			case KEY_PAGEUP: +			case KEY_PAGEDOWN: { + +				search_options->call("_input_event", p_ie); +				search_box->accept_event(); + +				TreeItem *root = search_options->get_root(); +				if (!root->get_children()) +					break; + +				TreeItem *current = search_options->get_selected(); + +				TreeItem *item = search_options->get_next_selected(root); +				while (item) { +					item->deselect(0); +					item = search_options->get_next_selected(item); +				} + +				current->select(0); + +			} break; +		} +	} +} + + +void PropertySelector::_update_search() { + + +	if (properties) +		set_title(TTR("Select Property")); +	else +		set_title(TTR("Select Method")); + +	search_options->clear(); +	help_bit->set_text(""); + + +	TreeItem *root = search_options->create_item(); + + +	if (properties) { + +		List<PropertyInfo> props; + +		if (instance) { +			instance->get_property_list(&props,true); +		} else if (type!=Variant::NIL) { +			Variant v; +			if (type==Variant::INPUT_EVENT) { +				InputEvent ie; +				ie.type=event_type; +				v=ie; +			} else { +				Variant::CallError ce; +				v=Variant::construct(type,NULL,0,ce); +			} + +			v.get_property_list(&props); +		} else { + + +			Object *obj = ObjectDB::get_instance(script); +			if (obj && obj->cast_to<Script>()) { + +				props.push_back(PropertyInfo(Variant::NIL,"Script Variables",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_CATEGORY)); +				obj->cast_to<Script>()->get_script_property_list(&props); +			} + +			StringName base=base_type; +			while(base) { +				props.push_back(PropertyInfo(Variant::NIL,base,PROPERTY_HINT_NONE,"",PROPERTY_USAGE_CATEGORY)); +				ObjectTypeDB::get_property_list(base,&props,true); +				base=ObjectTypeDB::type_inherits_from(base); +			} + +		} + +		TreeItem *category=NULL; + +		bool found=false; + +		Ref<Texture> type_icons[Variant::VARIANT_MAX]={ +			Control::get_icon("MiniVariant","EditorIcons"), +			Control::get_icon("MiniBoolean","EditorIcons"), +			Control::get_icon("MiniInteger","EditorIcons"), +			Control::get_icon("MiniFloat","EditorIcons"), +			Control::get_icon("MiniString","EditorIcons"), +			Control::get_icon("MiniVector2","EditorIcons"), +			Control::get_icon("MiniRect2","EditorIcons"), +			Control::get_icon("MiniVector3","EditorIcons"), +			Control::get_icon("MiniMatrix2","EditorIcons"), +			Control::get_icon("MiniPlane","EditorIcons"), +			Control::get_icon("MiniQuat","EditorIcons"), +			Control::get_icon("MiniAabb","EditorIcons"), +			Control::get_icon("MiniMatrix3","EditorIcons"), +			Control::get_icon("MiniTransform","EditorIcons"), +			Control::get_icon("MiniColor","EditorIcons"), +			Control::get_icon("MiniImage","EditorIcons"), +			Control::get_icon("MiniPath","EditorIcons"), +			Control::get_icon("MiniRid","EditorIcons"), +			Control::get_icon("MiniObject","EditorIcons"), +			Control::get_icon("MiniInput","EditorIcons"), +			Control::get_icon("MiniDictionary","EditorIcons"), +			Control::get_icon("MiniArray","EditorIcons"), +			Control::get_icon("MiniRawArray","EditorIcons"), +			Control::get_icon("MiniIntArray","EditorIcons"), +			Control::get_icon("MiniFloatArray","EditorIcons"), +			Control::get_icon("MiniStringArray","EditorIcons"), +			Control::get_icon("MiniVector2Array","EditorIcons"), +			Control::get_icon("MiniVector3Array","EditorIcons"), +			Control::get_icon("MiniColorArray","EditorIcons") +		}; + + +		for (List<PropertyInfo>::Element *E=props.front();E;E=E->next()) { +			if (E->get().usage==PROPERTY_USAGE_CATEGORY) { +				if (category && category->get_children()==NULL) { +					memdelete(category); //old category was unused +				} +				category = search_options->create_item(root); +				category->set_text(0,E->get().name); +				category->set_selectable(0,false); + +				Ref<Texture> icon; +				if (E->get().name=="Script Variables") { +					icon=get_icon("Script","EditorIcons"); +				} else if (has_icon(E->get().name,"EditorIcons")) { +					icon=get_icon(E->get().name,"EditorIcons"); +				} else { +					icon=get_icon("Object","EditorIcons"); +				} +				category->set_icon(0,icon); +				continue; +			} + +			if (!(E->get().usage&PROPERTY_USAGE_EDITOR)) +				continue; + +			if (search_box->get_text()!=String() && E->get().name.find(search_box->get_text())==-1) +				continue; +			TreeItem *item = search_options->create_item(category?category:root); +			item->set_text(0,E->get().name); +			item->set_metadata(0,E->get().name); +			item->set_icon(0,type_icons[E->get().type]); + +			if (!found && search_box->get_text()!=String() && E->get().name.find(search_box->get_text())!=-1) { +				item->select(0); +				found=true; +			} + +			item->set_selectable(0,true); +		} + +		if (category && category->get_children()==NULL) { +			memdelete(category); //old category was unused +		} +	} else { + +		List<MethodInfo> methods; + +		if (type!=Variant::NIL) { +			Variant v; +			Variant::CallError ce; +			v=Variant::construct(type,NULL,0,ce); +			v.get_method_list(&methods); +		} else { + + +			Object *obj = ObjectDB::get_instance(script); +			if (obj && obj->cast_to<Script>()) { + +				methods.push_back(MethodInfo("*Script Methods")); +				obj->cast_to<Script>()->get_script_method_list(&methods); +			} + +			StringName base=base_type; +			while(base) { +				methods.push_back(MethodInfo("*"+String(base))); +				ObjectTypeDB::get_method_list(base,&methods,true); +				base=ObjectTypeDB::type_inherits_from(base); +			} + +		} + +		TreeItem *category=NULL; + +		bool found=false; +		bool script_methods=false; + +		for (List<MethodInfo>::Element *E=methods.front();E;E=E->next()) { +			if (E->get().name.begins_with("*")) { +				if (category && category->get_children()==NULL) { +					memdelete(category); //old category was unused +				} +				category = search_options->create_item(root); +				category->set_text(0,E->get().name.replace_first("*","")); +				category->set_selectable(0,false); + +				Ref<Texture> icon; +				script_methods=false; +				if (E->get().name=="*Script Methods") { +					icon=get_icon("Script","EditorIcons"); +					script_methods=true; +				} else if (has_icon(E->get().name,"EditorIcons")) { +					icon=get_icon(E->get().name,"EditorIcons"); +				} else { +					icon=get_icon("Object","EditorIcons"); +				} +				category->set_icon(0,icon); + +				continue; +			} + +			String name = E->get().name.get_slice(":",0); +			if (!script_methods && name.begins_with("_") && !(E->get().flags&METHOD_FLAG_VIRTUAL)) +				continue; + +			if (search_box->get_text()!=String() && name.find(search_box->get_text())==-1) +				continue; + +			TreeItem *item = search_options->create_item(category?category:root); + +			MethodInfo mi=E->get(); + +			String desc; +			if (mi.name.find(":")!=-1) { +				desc=mi.name.get_slice(":",1)+" "; +				mi.name=mi.name.get_slice(":",0); +			} else if (mi.return_val.type!=Variant::NIL) +				desc=Variant::get_type_name(mi.return_val.type); +			else +				desc="void "; + + + +			desc+=" "+mi.name+" ( "; + +			for(int i=0;i<mi.arguments.size();i++) { + +				if (i>0) +					desc+=", "; + +				if (mi.arguments[i].type==Variant::NIL) +					desc+="var "; +				else if (mi.arguments[i].name.find(":")!=-1) { +					desc+=mi.arguments[i].name.get_slice(":",1)+" "; +					mi.arguments[i].name=mi.arguments[i].name.get_slice(":",0); +				} else +					desc+=Variant::get_type_name(mi.arguments[i].type)+" "; + +				desc+=mi.arguments[i].name; + +			} + +			desc+=" )"; + +			item->set_text(0,desc); +			item->set_metadata(0,name); +			item->set_selectable(0,true); + +			if (!found && search_box->get_text()!=String() && name.find(search_box->get_text())!=-1) { +				item->select(0); +				found=true; +			} + +		} + +		if (category && category->get_children()==NULL) { +			memdelete(category); //old category was unused +		} + +	} + +	get_ok()->set_disabled(root->get_children()==NULL); + +} + + + +void PropertySelector::_confirmed() { + +	TreeItem *ti = search_options->get_selected(); +	if (!ti) +		return; +	emit_signal("selected",ti->get_metadata(0)); +	hide(); +} + +void PropertySelector::_item_selected() { + +	help_bit->set_text(""); + +	TreeItem *item=search_options->get_selected(); +	if (!item) +		return; +	String name = item->get_metadata(0); + +	String class_type; +	if (properties && type==Variant::INPUT_EVENT) { + +		switch(event_type) { +			case InputEvent::NONE:  class_type="InputEvent"; break; +			case InputEvent::KEY:  class_type="InputEventKey"; break; +			case InputEvent::MOUSE_MOTION:  class_type="InputEventMouseMotion"; break; +			case InputEvent::MOUSE_BUTTON:  class_type="InputEventMouseButton"; break; +			case InputEvent::JOYSTICK_MOTION:  class_type="InputEventJoystickMotion"; break; +			case InputEvent::JOYSTICK_BUTTON:  class_type="InputEventJoystickButton"; break; +			case InputEvent::SCREEN_TOUCH:  class_type="InputEventScreenTouch"; break; +			case InputEvent::SCREEN_DRAG:  class_type="InputEventScreenDrag"; break; +			case InputEvent::ACTION:  class_type="InputEventAction"; break; +			default: {} +		} + +	} else if (type) { +		class_type=Variant::get_type_name(type); + +	} else { +		class_type=base_type; +	} + +	DocData *dd=EditorHelp::get_doc_data(); +	String text; + + +	if (properties) { + +		String at_class=class_type; + + + +		while(at_class!=String()) { + + +			Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(at_class); +			if (E) { +				for(int i=0;i<E->get().properties.size();i++) { +					if (E->get().properties[i].name==name) { +						text=E->get().properties[i].description; +					} +				} +			} + +			at_class=ObjectTypeDB::type_inherits_from(at_class); +		} + +		if (text==String()) { + +			StringName setter; +			StringName type; +			if (ObjectTypeDB::get_setter_and_type_for_property(class_type,name,type,setter)) { +				Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(type); +				if (E) { +					for(int i=0;i<E->get().methods.size();i++) { +						if (E->get().methods[i].name==setter.operator String()) { +							text=E->get().methods[i].description; +						} +					} +				} + + +			} +		} + +	} else { + + +		String at_class=class_type; + +		while(at_class!=String()) { + +			Map<String,DocData::ClassDoc>::Element *E=dd->class_list.find(at_class); +			if (E) { +				for(int i=0;i<E->get().methods.size();i++) { +					if (E->get().methods[i].name==name) { +						text=E->get().methods[i].description; +					} +				} +			} + +			at_class=ObjectTypeDB::type_inherits_from(at_class); +		} +	} + + +	if (text==String()) +		return; + +	help_bit->set_text(text); + +} + + +void PropertySelector::_notification(int p_what) { + +	if (p_what==NOTIFICATION_ENTER_TREE) { + +		connect("confirmed",this,"_confirmed"); + +	} +} + + + +void PropertySelector::select_method_from_base_type(const String& p_base,const String& p_current) { + +	base_type=p_base; +	selected=p_current; +	type=Variant::NIL; +	script=0; +	properties=false; +	instance=NULL; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); +} + +void PropertySelector::select_method_from_script(const Ref<Script>& p_script,const String& p_current){ + +	ERR_FAIL_COND( p_script.is_null() ); +	base_type=p_script->get_instance_base_type(); +	selected=p_current; +	type=Variant::NIL; +	script=p_script->get_instance_ID(); +	properties=false; +	instance=NULL; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); + +} +void PropertySelector::select_method_from_basic_type(Variant::Type p_type, const String &p_current){ + +	ERR_FAIL_COND(p_type==Variant::NIL); +	base_type=""; +	selected=p_current; +	type=p_type; +	script=0; +	properties=false; +	instance=NULL; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); + +} + +void PropertySelector::select_method_from_instance(Object* p_instance, const String &p_current){ + + +	base_type=p_instance->get_type(); +	selected=p_current; +	type=Variant::NIL; +	script=0; +	{ +		Ref<Script> scr = p_instance->get_script(); +		if (scr.is_valid()) +			script=scr->get_instance_ID(); +	} +	properties=false; +	instance=NULL; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); + +} + + +void PropertySelector::select_property_from_base_type(const String& p_base,const String& p_current) { + +	base_type=p_base; +	selected=p_current; +	type=Variant::NIL; +	script=0; +	properties=true; +	instance=NULL; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); +} + +void PropertySelector::select_property_from_script(const Ref<Script>& p_script,const String& p_current){ + +	ERR_FAIL_COND( p_script.is_null() ); + +	base_type=p_script->get_instance_base_type(); +	selected=p_current; +	type=Variant::NIL; +	script=p_script->get_instance_ID(); +	properties=true; +	instance=NULL; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); + +} +void PropertySelector::select_property_from_basic_type(Variant::Type p_type, InputEvent::Type p_event_type, const String &p_current){ + +	ERR_FAIL_COND(p_type==Variant::NIL); +	base_type=""; +	selected=p_current; +	type=p_type; +	event_type=p_event_type; +	script=0; +	properties=true; +	instance=NULL; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); + +} + +void PropertySelector::select_property_from_instance(Object* p_instance, const String &p_current){ + + +	base_type=""; +	selected=p_current; +	type=Variant::NIL; +	script=0; +	properties=true; +	instance=p_instance; + +	popup_centered_ratio(0.6); +	search_box->set_text(""); +	search_box->grab_focus(); +	_update_search(); + +} + +void PropertySelector::_bind_methods() { + +	ObjectTypeDB::bind_method(_MD("_text_changed"),&PropertySelector::_text_changed); +	ObjectTypeDB::bind_method(_MD("_confirmed"),&PropertySelector::_confirmed); +	ObjectTypeDB::bind_method(_MD("_sbox_input"),&PropertySelector::_sbox_input); +	ObjectTypeDB::bind_method(_MD("_item_selected"),&PropertySelector::_item_selected); + +	ADD_SIGNAL(MethodInfo("selected",PropertyInfo(Variant::STRING,"name"))); + +} + + +PropertySelector::PropertySelector() { + + +	VBoxContainer *vbc = memnew( VBoxContainer ); +	add_child(vbc); +	set_child_rect(vbc); +	search_box = memnew( LineEdit ); +	vbc->add_margin_child(TTR("Search:"),search_box); +	search_box->connect("text_changed",this,"_text_changed"); +	search_box->connect("input_event",this,"_sbox_input"); +	search_options = memnew( Tree ); +	vbc->add_margin_child(TTR("Matches:"),search_options,true); +	get_ok()->set_text(TTR("Open")); +	get_ok()->set_disabled(true); +	register_text_enter(search_box); +	set_hide_on_ok(false); +	search_options->connect("item_activated",this,"_confirmed"); +	search_options->connect("cell_selected",this,"_item_selected"); +	search_options->set_hide_root(true); +	search_options->set_hide_folding(true); + +	help_bit = memnew( EditorHelpBit ); +	vbc->add_margin_child(TTR("Description:"),help_bit); +	help_bit->connect("request_hide",this,"_closed"); + + +}  |