Jelajahi Sumber

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

Juan Linietsky 10 tahun lalu
induk
melakukan
ddf7457894

+ 0 - 20
SConstruct

@@ -170,26 +170,6 @@ if selected_platform in platform_list:
 	else:
 		env = env_base.Clone()
 
-	# Workaround for MinGW. See:
-	# http://www.scons.org/wiki/LongCmdLinesOnWin32
-	if (os.name=="nt"):
-		import subprocess
-		def mySpawn(sh, escape, cmd, args, env):
-				newargs = ' '.join(args[1:])
-				cmdline = cmd + " " + newargs
-				startupinfo = subprocess.STARTUPINFO()
-				startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
-				proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
-					stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
-				data, err = proc.communicate()
-				rv = proc.wait()
-				if rv:
-					print "====="
-					print err
-					print "====="
-				return rv
-		env['SPAWN'] = mySpawn
-
 	env.extra_suffix=""
 
 	CCFLAGS = env.get('CCFLAGS', '')

+ 1 - 0
bin/tests/test_math.cpp

@@ -80,6 +80,7 @@ MainLoop* test() {
 
 	{
 
+
 	//	print_line("NUM: "+itos(237641278346127));
 		print_line("NUM: "+itos(-128));
 		return NULL;

+ 1 - 1
core/io/json.cpp

@@ -250,7 +250,7 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke
 				if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) {
 					//a number
 					const CharType *rptr;
-					double number = String::to_double(&p_str[idx],-1,&rptr);
+					double number = String::to_double(&p_str[idx],&rptr);
 					idx+=(rptr - &p_str[idx]);
 					r_token.type=TK_NUMBER;
 					r_token.value=number;

+ 25 - 0
core/os/input.cpp

@@ -29,6 +29,7 @@
 #include "input.h"
 #include "input_map.h"
 #include "os/os.h"
+#include "globals.h"
 Input *Input::singleton=NULL;
 
 Input *Input::get_singleton() {
@@ -69,6 +70,30 @@ void Input::_bind_methods() {
 	ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) );
 }
 
+void Input::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const {
+#ifdef TOOLS_ENABLED
+
+	String pf=p_function;
+	if (p_idx==0 && (pf=="is_action_pressed" || pf=="action_press" || pf=="action_release")) {
+
+		List<PropertyInfo> pinfo;
+		Globals::get_singleton()->get_property_list(&pinfo);
+
+		for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+			const PropertyInfo &pi=E->get();
+
+			if (!pi.name.begins_with("input/"))
+				continue;
+
+			String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
+			r_options->push_back("\""+name+"\"");
+
+		}
+	}
+#endif
+
+}
+
 Input::Input() {
 
 	singleton=this;

+ 2 - 0
core/os/input.h

@@ -76,6 +76,8 @@ public:
 	virtual void action_press(const StringName& p_action)=0;
 	virtual void action_release(const StringName& p_action)=0;
 
+	void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const;
+
 
 	Input();
 };

+ 9 - 5
core/ustring.cpp

@@ -626,7 +626,7 @@ Vector<float> String::split_floats(const String &p_splitter,bool p_allow_empty)
 		if (end<0)
 			end=len;
 		if (p_allow_empty || (end>from))
-			ret.push_back(String::to_double(&c_str()[from],end-from));
+			ret.push_back(String::to_double(&c_str()[from]));
 
 		if (end==len)
 			break;
@@ -654,8 +654,9 @@ Vector<float> String::split_floats_mk(const Vector<String> &p_splitters,bool p_a
 			spl_len=p_splitters[idx].length();
 		}
 
-		if (p_allow_empty || (end>from))
-			ret.push_back(String::to_double(&c_str()[from],end-from));
+		if (p_allow_empty || (end>from)) {
+			ret.push_back(String::to_double(&c_str()[from]));
+		}
 
 		if (end==len)
 			break;
@@ -1959,8 +1960,10 @@ float String::to_float() const {
 	return to_double();
 }
 
-double String::to_double(const CharType* p_str, int p_len, const CharType **r_end)  {
+double String::to_double(const CharType* p_str, const CharType **r_end)  {
 
+	return built_in_strtod<CharType>(p_str,(CharType**)r_end);
+#if 0
 #if 0
 	//ndef NO_USE_STDLIB
 	return wcstod(p_str,p_len<0?NULL:p_str+p_len);
@@ -2053,6 +2056,7 @@ double String::to_double(const CharType* p_str, int p_len, const CharType **r_en
 
 	return sign*(integer+decimal)*Math::pow(10,exp_sign*exp);
 #endif
+#endif
 }
 
 int64_t String::to_int(const CharType* p_str,int p_len)  {
@@ -3437,7 +3441,7 @@ String String::percent_encode() const {
 		uint8_t c = cs[i];
 		if ( (c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='-' || c=='_' || c=='~' || c=='.') {
 
-			char p[2]={c,0};
+			char p[2]={(char)c,0};
 			encoded+=p;
 		} else {
 			char p[4]={'%',0,0,0};

+ 1 - 1
core/ustring.h

@@ -142,7 +142,7 @@ public:
 	int64_t to_int64() const;
 	static int to_int(const char* p_str);
 	static double to_double(const char* p_str);
-	static double to_double(const CharType* p_str, int p_len=-1, const CharType **r_end=NULL);
+	static double to_double(const CharType* p_str, const CharType **r_end=NULL);
 	static int64_t to_int(const CharType* p_str,int p_len=-1);
 	String capitalize() const;
 

+ 3 - 1
drivers/gles2/rasterizer_gles2.cpp

@@ -139,11 +139,13 @@ static _FORCE_INLINE_ uint16_t make_half_float(float f) {
     else if (exp <= 0x38000000)
     {
 
-	// store a denorm half-float value or zero
+	/*// store a denorm half-float value or zero
 	exp = (0x38000000 - exp) >> 23;
 	mantissa >>= (14 + exp);
 
 	hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa);
+	*/
+	hf=0; //denormals do not work for 3D, convert to zero
     }
     else
     {

+ 50 - 3
modules/gdscript/gd_editor.cpp

@@ -28,7 +28,7 @@
 /*************************************************************************/
 #include "gd_script.h"
 #include "gd_compiler.h"
-
+#include "globals.h"
 
 void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
 
@@ -1276,7 +1276,23 @@ static void _make_function_hint(const GDParser::FunctionNode* p_func,int p_argid
 static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const StringName& p_method,const GDCompletionIdentifier& id, int p_argidx, Set<String>& result, String& arghint) {
 
 
-	if (id.type==Variant::OBJECT && id.obj_type!=StringName()) {
+	if (id.type==Variant::INPUT_EVENT && String(p_method)=="is_action" && p_argidx==0) {
+
+		List<PropertyInfo> pinfo;
+		Globals::get_singleton()->get_property_list(&pinfo);
+
+		for(List<PropertyInfo>::Element *E=pinfo.front();E;E=E->next()) {
+			const PropertyInfo &pi=E->get();
+
+			if (!pi.name.begins_with("input/"))
+				continue;
+
+			String name = pi.name.substr(pi.name.find("/")+1,pi.name.length());
+			result.insert("\""+name+"\"");
+		}
+
+
+	} else if (id.type==Variant::OBJECT && id.obj_type!=StringName()) {
 
 
 		MethodBind *m = ObjectTypeDB::get_method(id.obj_type,p_method);
@@ -1299,7 +1315,7 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St
 				const GDParser::OperatorNode *op=static_cast<const GDParser::OperatorNode *>(p_node);
 				if (op->arguments.size()>)
 
-			}*/
+			}*/		
 		} else {
 
 			Object *obj=id.value;
@@ -1826,6 +1842,37 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base
 
 			_find_call_arguments(context,p.get_completion_node(),p.get_completion_line(),p.get_completion_argument_index(),options,r_call_hint);
 		} break;
+		case GDParser::COMPLETION_VIRTUAL_FUNC: {
+
+			GDCompletionIdentifier cid = _get_native_class(context);
+
+			if (cid.obj_type!=StringName()) {
+				List<MethodInfo> vm;
+				ObjectTypeDB::get_virtual_methods(cid.obj_type,&vm);
+				for(List<MethodInfo>::Element *E=vm.front();E;E=E->next()) {
+
+					MethodInfo &mi=E->get();
+					String m = mi.name;
+					if (m.find(":")!=-1)
+						m=m.substr(0,m.find(":"));
+					m+="(";
+
+					if (mi.arguments.size()) {
+						for(int i=0;i<mi.arguments.size();i++) {
+							if (i>0)
+								m+=", ";
+							String n =mi.arguments[i].name;
+							if (n.find(":")!=-1)
+								n=n.substr(0,n.find(":"));
+							m+=n;
+						}
+					}
+					m+="):";
+
+					options.insert(m);
+				}
+			}
+		} break;
 
 
 	}

+ 10 - 4
modules/gdscript/gd_parser.cpp

@@ -2027,14 +2027,20 @@ void GDParser::_parse_class(ClassNode *p_class) {
 				}
 
 
-				if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER) {
+				tokenizer->advance();
+				StringName name;
+
+				if (_get_completable_identifier(COMPLETION_VIRTUAL_FUNC,name)) {
+
+				}
+
+
+				if (name==StringName()) {
 
 					_set_error("Expected identifier after 'func' (syntax: 'func <identifier>([arguments]):' ).");
 					return;
 				}
 
-				StringName name = tokenizer->get_token_identifier(1);
-
 				for(int i=0;i<p_class->functions.size();i++) {
 					if (p_class->functions[i]->name==name) {
 						_set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->functions[i]->line)+").");
@@ -2045,7 +2051,7 @@ void GDParser::_parse_class(ClassNode *p_class) {
 						_set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->static_functions[i]->line)+").");
 					}
 				}
-				tokenizer->advance(2);
+
 
 				if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) {
 

+ 1 - 0
modules/gdscript/gd_parser.h

@@ -363,6 +363,7 @@ public:
 		COMPLETION_METHOD,
 		COMPLETION_CALL_ARGUMENTS,
 		COMPLETION_INDEX,
+		COMPLETION_VIRTUAL_FUNC
 	};
 
 

+ 21 - 0
platform/windows/detect.py

@@ -135,6 +135,27 @@ def configure(env):
 		env.Append(LIBPATH=[DIRECTX_PATH+"/Lib/x86"])
 		env['ENV'] = os.environ;
 	else:
+
+		# Workaround for MinGW. See:
+		# http://www.scons.org/wiki/LongCmdLinesOnWin32
+		if (os.name=="nt"):
+			import subprocess
+			def mySpawn(sh, escape, cmd, args, env):
+				newargs = ' '.join(args[1:])
+				cmdline = cmd + " " + newargs
+				startupinfo = subprocess.STARTUPINFO()
+				startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+				proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+				    stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env)
+				data, err = proc.communicate()
+				rv = proc.wait()
+				if rv:
+					print "====="
+					print err
+					print "====="
+				return rv
+			env['SPAWN'] = mySpawn
+
 		#build using mingw
 		if (os.name=="nt"):
 			env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes

+ 35 - 0
scene/3d/camera.cpp

@@ -86,6 +86,10 @@ bool Camera::_set(const StringName& p_name, const Variant& p_value) {
 		set_keep_aspect_mode(KeepAspect(int(p_value)));
 	else if (p_name=="vaspect")
 		set_keep_aspect_mode(p_value?KEEP_WIDTH:KEEP_HEIGHT);
+	else if (p_name=="h_offset")
+		h_offset=p_value;
+	else if (p_name=="v_offset")
+		v_offset=p_value;
 	else if (p_name=="current") {
 		if (p_value.operator bool()) {
 			make_current();
@@ -128,6 +132,10 @@ bool Camera::_get(const StringName& p_name,Variant &r_ret) const {
 		}
 	} else if (p_name=="visible_layers") {
 		r_ret=get_visible_layers();
+	} else if (p_name=="h_offset") {
+		r_ret=get_h_offset();
+	} else if (p_name=="v_offset") {
+		r_ret=get_v_offset();
 	} else if (p_name=="environment") {
 		r_ret=get_environment();
 	} else
@@ -170,12 +178,16 @@ void Camera::_get_property_list( List<PropertyInfo> *p_list) const {
 	p_list->push_back( PropertyInfo( Variant::BOOL, "current" ) );
 	p_list->push_back( PropertyInfo( Variant::INT, "visible_layers",PROPERTY_HINT_ALL_FLAGS ) );
 	p_list->push_back( PropertyInfo( Variant::OBJECT, "environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment" ) );
+	p_list->push_back( PropertyInfo( Variant::REAL, "h_offset" ) );
+	p_list->push_back( PropertyInfo( Variant::REAL, "v_offset" ) );
 
 }
 
 void Camera::_update_camera() {
 
 	Transform tr = get_camera_transform();
+	tr.origin+=tr.basis.get_axis(1)*v_offset;
+	tr.origin+=tr.basis.get_axis(0)*h_offset;
 	VisualServer::get_singleton()->camera_set_transform( camera, tr );
 
 // here goes listener stuff
@@ -757,6 +769,27 @@ void Camera::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, cons
 
 }
 
+void Camera::set_v_offset(float p_offset) {
+
+	v_offset=p_offset;
+	_update_camera();;
+}
+
+float Camera::get_v_offset() const {
+
+	return v_offset;
+}
+
+void Camera::set_h_offset(float p_offset) {
+	h_offset=p_offset;
+	_update_camera();
+}
+
+float Camera::get_h_offset() const {
+
+	return h_offset;
+}
+
 
 Camera::Camera() {
 
@@ -772,6 +805,8 @@ Camera::Camera() {
 	set_perspective(60.0,0.1,100.0);
 	keep_aspect=KEEP_HEIGHT;
 	layers=0xfffff;
+	v_offset=0;
+	h_offset=0;
 	VisualServer::get_singleton()->camera_set_visible_layers(camera,layers);
 	//active=false;
 }

+ 8 - 0
scene/3d/camera.h

@@ -61,6 +61,8 @@ private:
 	float fov;
 	float size;
 	float near,far;
+	float v_offset;
+	float h_offset;
 	KeepAspect keep_aspect;
 	
 	RID camera;
@@ -140,6 +142,12 @@ public:
 	void look_at(const Vector3& p_target, const Vector3& p_up_normal);
 	void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal);
 
+	void set_v_offset(float p_offset);
+	float get_v_offset() const;
+
+	void set_h_offset(float p_offset);
+	float get_h_offset() const;
+
 
 	Camera();	
 	~Camera();

+ 2 - 2
scene/gui/control.cpp

@@ -2684,8 +2684,8 @@ bool Control::is_stopping_mouse() const {
 Control *Control::get_focus_owner() const {
 
 	ERR_FAIL_COND_V(!is_inside_tree(),NULL);
-	ERR_FAIL_COND_V(!window,NULL);
-	return window->key_focus;
+	ERR_FAIL_COND_V(!data.window,NULL);
+	return data.window->window->key_focus;
 }
 
 void Control::_bind_methods() {

+ 31 - 9
scene/gui/text_edit.cpp

@@ -3274,19 +3274,41 @@ void TextEdit::_update_completion_candidates() {
 	
 	
 	String s;
-	
-	while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) {
-		s=String::chr(l[cofs-1])+s;
-		if (l[cofs-1]=='\'' || l[cofs-1]=='"')
-			break;
-		
-		cofs--;
+
+	//look for keywords first
+
+	bool pre_keyword=false;
+
+	if (cofs>0 && l[cofs-1]==' ') {
+		int kofs=cofs-1;
+		String kw;
+		while (kofs>=0 && l[kofs]==' ')
+			kofs--;
+
+		while(kofs>=0 && l[kofs]>32 && _is_completable(l[kofs])) {
+			kw=String::chr(l[kofs])+kw;
+			kofs--;
+		}
+
+		pre_keyword=keywords.has(kw);
+		print_line("KW "+kw+"? "+itos(pre_keyword));
+
+	} else {
+
+
+		while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) {
+			s=String::chr(l[cofs-1])+s;
+			if (l[cofs-1]=='\'' || l[cofs-1]=='"')
+				break;
+
+			cofs--;
+		}
 	}
-	
+
 	
 	update();
 	
-	if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) {
+	if (!pre_keyword && s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) {
 		//none to complete, cancel
 		_cancel_completion();
 		return;

+ 10 - 2
tools/editor/editor_import_export.cpp

@@ -292,7 +292,11 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const
 			_add_filter_to_list(exported,"*");
 		} else {
 			_add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported);
-			_add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter());
+			String cf = EditorImportExport::get_singleton()->get_export_custom_filter();
+			if (cf!="")
+				cf+=",";
+			cf+="*.flags";
+			_add_filter_to_list(exported,cf);
 
 		}
 
@@ -361,8 +365,12 @@ Vector<StringName> EditorExportPlatform::get_dependencies(bool p_bundles) const
 				}
 			}
 		}
+		String cf = EditorImportExport::get_singleton()->get_export_custom_filter();
+		if (cf!="")
+			cf+=",";
+		cf+="*.flags";
+		_add_filter_to_list(exported,cf);
 
-		_add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter());
 
 	}
 

+ 1 - 0
tools/editor/editor_settings.cpp

@@ -446,6 +446,7 @@ void EditorSettings::_load_defaults() {
 	set("animation/confirm_insert_track",true);
 
 	set("property_editor/texture_preview_width",48);
+	set("property_editor/auto_refresh_interval",0.3);
 	set("help/doc_path","");
 
 	set("import/ask_save_before_reimport",false);

+ 4 - 0
tools/editor/plugins/animation_player_editor_plugin.cpp

@@ -76,6 +76,8 @@ void AnimationPlayerEditor::_notification(int p_what) {
 			seek->set_val(player->get_current_animation_pos());
 			if (edit_anim->is_pressed())
 				editor->get_animation_editor()->set_anim_pos(player->get_current_animation_pos());
+			EditorNode::get_singleton()->get_property_editor()->refresh();
+
 		} else if (last_active) {
 			//need the last frame after it stopped
 
@@ -854,6 +856,8 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos) {
 		return;
 
 	seek->set_val(p_pos);
+	EditorNode::get_singleton()->get_property_editor()->refresh();
+
 
 
 	//seekit

+ 73 - 0
tools/editor/property_editor.cpp

@@ -1880,6 +1880,14 @@ void PropertyEditor::_notification(int p_what) {
 	if (p_what==NOTIFICATION_FIXED_PROCESS) {
 		
 		
+		if (refresh_countdown>0) {
+			refresh_countdown-=get_fixed_process_delta_time();
+			if (refresh_countdown<=0) {
+				TreeItem *root = tree->get_root();
+				_refresh_item(root);
+			}
+		}
+
 		changing=true;
 		 
 		if (update_tree_pending) {
@@ -1986,7 +1994,71 @@ TreeItem *PropertyEditor::get_parent_node(String p_path,HashMap<String,TreeItem*
 }
 
 
+void PropertyEditor::_refresh_item(TreeItem *p_item) {
+
+	if (!p_item)
+		return;
+
+	String name = p_item->get_metadata(1);
+
+	if (name!=String()) {
+
+		if (get_instanced_node()) {
+
+			Dictionary d = get_instanced_node()->get_instance_state();
+			if (d.has(name)) {
+				Variant v = obj->get(name);
+				Variant vorig = d[name];
+
+				int found=-1;
+				for(int i=0;i<p_item->get_button_count(1);i++) {
+
+					if (p_item->get_button_id(1,i)==3) {
+						found=i;
+						break;
+					}
+				}
+
+				bool changed = ! (v==vorig);
+
+				if ((found!=-1)!=changed) {
+
+					if (changed) {
 
+						p_item->add_button(1,get_icon("Reload","EditorIcons"),3);
+					} else {
+
+						p_item->erase_button(1,found);
+					}
+
+				}
+
+			}
+
+		}
+
+		Dictionary d=p_item->get_metadata(0);
+		set_item_text(p_item,d["type"],d["name"],d["hint"],d["hint_text"]);
+	}
+
+	TreeItem *c=p_item->get_children();
+
+	while (c) {
+
+		_refresh_item(c);
+
+		c=c->get_next();
+	}
+
+}
+
+void PropertyEditor::refresh() {
+
+	if (refresh_countdown>0)
+		return;
+	refresh_countdown=EditorSettings::get_singleton()->get("property_editor/auto_refresh_interval");
+
+}
 
 void PropertyEditor::update_tree() {
 
@@ -3025,6 +3097,7 @@ PropertyEditor::PropertyEditor() {
 	keying=false;
 	read_only=false;
 	show_categories=false;
+	refresh_countdown=0;
 	
 }
 

+ 4 - 0
tools/editor/property_editor.h

@@ -156,6 +156,7 @@ class PropertyEditor : public Control {
 	bool keying;
 	bool read_only;
 	bool show_categories;
+	float refresh_countdown;
 
 	HashMap<String,String> pending;
 	String selected_property;
@@ -185,6 +186,7 @@ class PropertyEditor : public Control {
 	void _draw_flags(Object *ti,const Rect2& p_rect);
 
 	Node *get_instanced_node();
+	void _refresh_item(TreeItem *p_item);
 
 	UndoRedo *undo_redo;
 protected:
@@ -203,6 +205,8 @@ public:
 	void update_tree();
 	void update_property(const String& p_prop);
 
+	void refresh();
+
 	void edit(Object* p_object);
 
 	void set_keying(bool p_active);