Explorar o código

merges from okam repo

Juan Linietsky %!s(int64=10) %!d(string=hai) anos
pai
achega
4d2198110b

+ 4 - 0
SConstruct

@@ -67,12 +67,16 @@ env_base.android_source_modules=[]
 env_base.android_source_files=[]
 env_base.android_module_libraries=[]
 env_base.android_manifest_chunk=""
+env_base.android_permission_chunk=""
+env_base.android_appattributes_chunk=""
 env_base.disabled_modules=[]
 
 env_base.__class__.android_module_source = methods.android_module_source
 env_base.__class__.android_module_library = methods.android_module_library
 env_base.__class__.android_module_file = methods.android_module_file
 env_base.__class__.android_module_manifest = methods.android_module_manifest
+env_base.__class__.android_module_permission = methods.android_module_permission
+env_base.__class__.android_module_attribute = methods.android_module_attribute
 env_base.__class__.disable_module = methods.disable_module
 
 env_base.__class__.add_source_files = methods.add_source_files

+ 8 - 0
core/object.cpp

@@ -1033,6 +1033,13 @@ void Object::add_user_signal(const MethodInfo& p_signal) {
 	signal_map[p_signal.name]=s;
 }
 
+bool Object::_has_user_signal(const StringName& p_name) const {
+
+	if (!signal_map.has(p_name))
+		return false;
+	return signal_map[p_name].user.name.length()>0;
+}
+
 struct _ObjectSignalDisconnectData {
 
 	StringName signal;
@@ -1431,6 +1438,7 @@ void Object::_bind_methods() {
 //	ObjectTypeDB::bind_method(_MD("call_deferred","method","arg1","arg2","arg3","arg4"),&Object::_call_deferred_bind,DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()),DEFVAL(Variant()));
 
 	ObjectTypeDB::bind_method(_MD("add_user_signal","signal","arguments"),&Object::_add_user_signal,DEFVAL(Array()));
+	ObjectTypeDB::bind_method(_MD("has_user_signal","signal"),&Object::_has_user_signal);
 //	ObjectTypeDB::bind_method(_MD("emit_signal","signal","arguments"),&Object::_emit_signal,DEFVAL(Array()));
 
 

+ 1 - 0
core/object.h

@@ -386,6 +386,7 @@ friend void postinitialize_handler(Object*);
 	Dictionary metadata;
 
 	void _add_user_signal(const String& p_name, const Array& p_pargs=Array());
+	bool _has_user_signal(const StringName& p_name) const;
 	Variant _emit_signal(const Variant** p_args, int p_argcount, Variant::CallError& r_error);
 	Array _get_signal_list() const;
 	Array _get_signal_connection_list(const String& p_signal) const;

+ 2 - 1
doc/base/classes.xml

@@ -18902,7 +18902,8 @@
 			collider_id: collider id of the object agaisnt which the ray was stopped[br]
 			collider: collider object agaisnt which the ray was stopped[br]
 			rid:  [RID] of the object agaisnt which the ray was stopped[br]
-			If the ray did not intersect anything, then null is returned instead of a [Dictionary].
+			If the ray did not intersect anything, then an empty
+			dictionary (dir.empty()==true) is returned instead.
 			</description>
 		</method>
 		<method name="intersect_shape"  >

+ 18 - 6
drivers/gles2/rasterizer_gles2.cpp

@@ -4954,12 +4954,26 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_
 		Material::UniformData ud;
 
 		bool keep=true; //keep material value
-		bool has_old = old_mparams.has(E->key());
+
+		Map<StringName,Material::UniformData>::Element *OLD=old_mparams.find(E->key());
+		bool has_old = OLD;
 		bool old_inuse=has_old && old_mparams[E->key()].inuse;
 
-		if (!has_old || !old_inuse)
+		ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP);
+
+		if (!has_old || !old_inuse) {
 			keep=false;
-		else if (old_mparams[E->key()].value.get_type()!=E->value().default_value.get_type()) {
+		}
+		else if (OLD->get().value.get_type()!=E->value().default_value.get_type()) {
+
+			if (OLD->get().value.get_type()==Variant::INT && E->get().type==ShaderLanguage::TYPE_FLOAT) {
+				//handle common mistake using shaders (feeding ints instead of float)
+				OLD->get().value=float(OLD->get().value);
+				keep=true;
+			} else if (!ud.istexture && E->value().default_value.get_type()!=Variant::NIL) {
+
+				keep=false;
+			}
 			//type changed between old and new
 			/*	if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) {
 				if (E->value().default_value.get_type()!=Variant::_RID) //hackfor textures
@@ -4968,11 +4982,9 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_
 				keep=false;*/
 
 			//value is invalid because type differs and default is not null
-			if (E->value().default_value.get_type()!=Variant::NIL)
-				keep=false;
+			;
 		}
 
-		ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP);
 
 		if (keep) {
 			ud.value=old_mparams[E->key()].value;

+ 8 - 0
methods.py

@@ -1291,6 +1291,14 @@ def android_module_manifest(self,file):
 	base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
 	f = open(base_path,"rb")
 	self.android_manifest_chunk+=f.read()
+def android_module_permission(self,file):
+	base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
+	f = open(base_path,"rb")
+	self.android_permission_chunk+=f.read()
+def android_module_attribute(self,file):
+	base_path = self.Dir(".").abspath+"/modules/"+self.current_module+"/"+file
+	f = open(base_path,"rb")
+	self.android_appattributes_chunk+=f.read()
 
 def disable_module(self):
 	self.disabled_modules.append(self.current_module)

+ 3 - 1
modules/gdscript/gd_tokenizer.cpp

@@ -538,9 +538,11 @@ void GDTokenizerText::_advance() {
 				is_node_path=true;
 				
 			case '\'':
-				string_mode=STRING_SINGLE_QUOTE;
 			case '"': {
 
+				if (GETCHAR(0)=='\'')
+					string_mode=STRING_SINGLE_QUOTE;
+
 				int i=1;
 				if (string_mode==STRING_DOUBLE_QUOTE && GETCHAR(i)=='"' && GETCHAR(i+1)=='"') {
 					i+=2;

+ 2 - 1
modules/gridmap/grid_map.cpp

@@ -122,7 +122,7 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) {
 				Octant &g = *octant_map[ok];
 
 				g.baked=b;
-				g.bake_instance=VS::get_singleton()->instance_create();;
+				g.bake_instance=VS::get_singleton()->instance_create();;				
 				VS::get_singleton()->instance_set_base(g.bake_instance,g.baked->get_rid());
 				VS::get_singleton()->instance_geometry_set_baked_light(g.bake_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID());
 			}
@@ -418,6 +418,7 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){
 		Octant *g = memnew( Octant );
 		g->dirty=true;
 		g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC);
+		PhysicsServer::get_singleton()->body_attach_object_instance_ID(g->static_body,get_instance_ID());
 		if (is_inside_world())
 			PhysicsServer::get_singleton()->body_set_space(g->static_body,get_world()->get_space());
 

+ 2 - 1
platform/android/AndroidManifest.xml.template

@@ -10,7 +10,7 @@
                       android:largeScreens="true"
                       android:xlargeScreens="true"/>
 
-    <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false">
+    <application android:label="@string/godot_project_name_string" android:icon="@drawable/icon" android:allowBackup="false" $$ADD_APPATTRIBUTE_CHUNKS$$ >
         <activity android:name="com.android.godot.Godot"
                   android:label="@string/godot_project_name_string"
                   android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
@@ -33,6 +33,7 @@ $$ADD_APPLICATION_CHUNKS$$
     </application>
     <uses-feature android:glEsVersion="0x00020000"/>
 
+$$ADD_PERMISSION_CHUNKS$$
 <uses-permission android:name="godot.ACCESS_CHECKIN_PROPERTIES"/>
 <uses-permission android:name="godot.ACCESS_COARSE_LOCATION"/>
 <uses-permission android:name="godot.ACCESS_FINE_LOCATION"/>

+ 2 - 0
platform/android/SCsub

@@ -56,6 +56,8 @@ pp_basein = open(abspath+"/AndroidManifest.xml.template","rb")
 pp_baseout = open(abspath+"/java/AndroidManifest.xml","wb")
 manifest = pp_basein.read()
 manifest = manifest.replace("$$ADD_APPLICATION_CHUNKS$$",env.android_manifest_chunk)
+manifest = manifest.replace("$$ADD_PERMISSION_CHUNKS$$",env.android_permission_chunk)
+manifest = manifest.replace("$$ADD_APPATTRIBUTE_CHUNKS$$",env.android_appattributes_chunk)
 pp_baseout.write( manifest )
 
 

+ 88 - 25
platform/android/java_glue.cpp

@@ -45,9 +45,18 @@ static JavaClassWrapper *java_class_wrapper=NULL;
 static OS_Android *os_android=NULL;
 
 
-jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) {
+struct jvalret {
 
-	jvalue v;
+	jobject obj;
+	jvalue val;
+	jvalret() { obj=NULL; }
+
+
+};
+
+jvalret _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_arg, bool force_jobject = false) {
+
+	jvalret v;
 
 	switch(p_type) {
 
@@ -59,9 +68,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 				jvalue val;
 				val.z = (bool)(*p_arg);
 				jobject obj = env->NewObjectA(bclass, ctor, &val);
-				v.l = obj;
+				v.val.l = obj;
+				v.obj=obj;
+				env->DeleteLocalRef(bclass);
 			} else {
-				v.z=*p_arg;
+				v.val.z=*p_arg;
+
 			};
 		} break;
 		case Variant::INT: {
@@ -73,10 +85,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 				jvalue val;
 				val.i = (int)(*p_arg);
 				jobject obj = env->NewObjectA(bclass, ctor, &val);
-				v.l = obj;
+				v.val.l = obj;
+				v.obj=obj;
+				env->DeleteLocalRef(bclass);
 
 			} else {
-				v.i=*p_arg;
+				v.val.i=*p_arg;
+
 			};
 		} break;
 		case Variant::REAL: {
@@ -88,17 +103,20 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 				jvalue val;
 				val.d = (double)(*p_arg);
 				jobject obj = env->NewObjectA(bclass, ctor, &val);
-				v.l = obj;
+				v.val.l = obj;
+				v.obj=obj;
+				env->DeleteLocalRef(bclass);
 
 			} else {
-				v.f=*p_arg;
+				v.val.f=*p_arg;
 			};
 		} break;
 		case Variant::STRING: {
 
 			String s = *p_arg;
 			jstring jStr = env->NewStringUTF(s.utf8().get_data());
-			v.l=jStr;
+			v.val.l=jStr;
+			v.obj=jStr;
 		} break;
 		case Variant::STRING_ARRAY: {
 
@@ -107,9 +125,12 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 
 			for(int j=0;j<sarray.size();j++) {
 
-				env->SetObjectArrayElement(arr,j,env->NewStringUTF( sarray[j].utf8().get_data() ));
+				jstring str = env->NewStringUTF( sarray[j].utf8().get_data() );
+				env->SetObjectArrayElement(arr,j,str);
+				env->DeleteLocalRef(str);
 			}
-			v.l=arr;
+			v.val.l=arr;
+			v.obj=arr;
 
 		} break;
 
@@ -124,27 +145,36 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 
 			jobjectArray jkeys = env->NewObjectArray(keys.size(), env->FindClass("java/lang/String"), env->NewStringUTF(""));
 			for (int j=0; j<keys.size(); j++) {
-				env->SetObjectArrayElement(jkeys, j, env->NewStringUTF(String(keys[j]).utf8().get_data()));
+				jstring str = env->NewStringUTF(String(keys[j]).utf8().get_data());
+				env->SetObjectArrayElement(jkeys, j, str);
+				env->DeleteLocalRef(str);
 			};
 
 			jmethodID set_keys = env->GetMethodID(dclass, "set_keys", "([Ljava/lang/String;)V");
 			jvalue val;
 			val.l = jkeys;
 			env->CallVoidMethodA(jdict, set_keys, &val);
+			env->DeleteLocalRef(jkeys);
 
 			jobjectArray jvalues = env->NewObjectArray(keys.size(), env->FindClass("java/lang/Object"), NULL);
 
 			for (int j=0; j<keys.size(); j++) {
 				Variant var = dict[keys[j]];
-				val = _variant_to_jvalue(env, var.get_type(), &var, true);
-				env->SetObjectArrayElement(jvalues, j, val.l);
+				jvalret v = _variant_to_jvalue(env, var.get_type(), &var, true);
+				env->SetObjectArrayElement(jvalues, j, v.val.l);
+				if (v.obj) {
+					env->DeleteLocalRef(v.obj);
+				}
 			};
 
 			jmethodID set_values = env->GetMethodID(dclass, "set_values", "([Ljava/lang/Object;)V");
 			val.l = jvalues;
 			env->CallVoidMethodA(jdict, set_values, &val);
+			env->DeleteLocalRef(jvalues);
+			env->DeleteLocalRef(dclass);
 
-			v.l = jdict;
+			v.val.l = jdict;
+			v.obj=jdict;
 		} break;
 
 		case Variant::INT_ARRAY: {
@@ -153,7 +183,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 			jintArray arr = env->NewIntArray(array.size());
 			DVector<int>::Read r = array.read();
 			env->SetIntArrayRegion(arr,0,array.size(),r.ptr());
-			v.l=arr;
+			v.val.l=arr;
+			v.obj=arr;
 
 		} break;
 		case Variant::RAW_ARRAY: {
@@ -161,7 +192,8 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 			jbyteArray arr = env->NewByteArray(array.size());
 			DVector<uint8_t>::Read r = array.read();
 			env->SetByteArrayRegion(arr,0,array.size(),reinterpret_cast<const signed char*>(r.ptr()));
-			v.l=arr;
+			v.val.l=arr;
+			v.obj=arr;
 
 		} break;
 		case Variant::REAL_ARRAY: {
@@ -170,12 +202,13 @@ jvalue _variant_to_jvalue(JNIEnv *env, Variant::Type p_type, const Variant* p_ar
 			jfloatArray arr = env->NewFloatArray(array.size());
 			DVector<float>::Read r = array.read();
 			env->SetFloatArrayRegion(arr,0,array.size(),r.ptr());
-			v.l=arr;
+			v.val.l=arr;
+			v.obj=arr;
 
 		} break;
 		default: {
 
-			v.i = 0;
+			v.val.i = 0;
 		} break;
 
 	}
@@ -193,8 +226,11 @@ String _get_class_name(JNIEnv * env, jclass cls, bool* array) {
 		jboolean isarr = env->CallBooleanMethod(cls, isArray);
 		(*array) = isarr ? true : false;
 	}
+	String name = env->GetStringUTFChars( clsName, NULL );
+	env->DeleteLocalRef(clsName);
+
+	return name;
 
-	return env->GetStringUTFChars( clsName, NULL );
 };
 
 
@@ -223,6 +259,8 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
 			jstring string = (jstring) env->GetObjectArrayElement(arr, i);
 			const char *rawString = env->GetStringUTFChars(string, 0);
 			sarr.push_back(String(rawString));
+			env->DeleteLocalRef(string);
+
 		}
 
 		return sarr;
@@ -321,30 +359,34 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
 
 		jobjectArray arr = (jobjectArray)obj;
 		int objCount = env->GetArrayLength(arr);
-		Array varr;
+		Array varr(true);
 
 		for (int i=0; i<objCount; i++) {
 			jobject jobj = env->GetObjectArrayElement(arr, i);
 			Variant v = _jobject_to_variant(env, jobj);
 			varr.push_back(v);
+			env->DeleteLocalRef(jobj);
+
 		}
 
 		return varr;
 	};
 
-	if (name == "com.android.godot.Dictionary") {
+    if (name == "java.util.HashMap" || name == "com.android.godot.Dictionary") {
 
-		Dictionary ret;
+		Dictionary ret(true);
 		jclass oclass = c;
 		jmethodID get_keys = env->GetMethodID(oclass, "get_keys", "()[Ljava/lang/String;");
 		jobjectArray arr = (jobjectArray)env->CallObjectMethod(obj, get_keys);
 
 		StringArray keys = _jobject_to_variant(env, arr);
+		env->DeleteLocalRef(arr);
 
 		jmethodID get_values = env->GetMethodID(oclass, "get_values", "()[Ljava/lang/Object;");
 		arr = (jobjectArray)env->CallObjectMethod(obj, get_values);
 
 		Array vals = _jobject_to_variant(env, arr);
+		env->DeleteLocalRef(arr);
 
 		//print_line("adding " + String::num(keys.size()) + " to Dictionary!");
 		for (int i=0; i<keys.size(); i++) {
@@ -352,9 +394,12 @@ Variant _jobject_to_variant(JNIEnv * env, jobject obj) {
 			ret[keys[i]] = vals[i];
 		};
 
+
 		return ret;
 	};
 
+	env->DeleteLocalRef(c);
+
 	return Variant();
 };
 
@@ -432,9 +477,13 @@ public:
 		JNIEnv *env = ThreadAndroid::get_env();
 
 		//print_line("argcount "+String::num(p_argcount));
+		List<jobject> to_erase;
 		for(int i=0;i<p_argcount;i++) {
 
-			v[i] = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]);
+			jvalret vr = _variant_to_jvalue(env, E->get().argtypes[i], p_args[i]);
+			v[i] = vr.val;
+			if (vr.obj)
+				to_erase.push_back(vr.obj);
 		}
 
 		//print_line("calling method!!");
@@ -468,6 +517,7 @@ public:
 				jobject o = env->CallObjectMethodA(instance,E->get().method,v);
 				String str = env->GetStringUTFChars((jstring)o, NULL );
 				ret=str;
+				env->DeleteLocalRef(o);
 			} break;
 			case Variant::STRING_ARRAY: {
 
@@ -475,6 +525,7 @@ public:
 
 				ret = _jobject_to_variant(env, arr);
 
+				env->DeleteLocalRef(arr);
 			} break;
 			case Variant::INT_ARRAY: {
 
@@ -488,6 +539,7 @@ public:
 				env->GetIntArrayRegion(arr,0,fCount,w.ptr());
 				w = DVector<int>::Write();
 				ret=sarr;
+				env->DeleteLocalRef(arr);
 			} break;
 			case Variant::REAL_ARRAY: {
 
@@ -501,6 +553,7 @@ public:
 				env->GetFloatArrayRegion(arr,0,fCount,w.ptr());
 				w = DVector<float>::Write();
 				ret=sarr;
+				env->DeleteLocalRef(arr);
 			} break;
 
 			case Variant::DICTIONARY: {
@@ -508,6 +561,7 @@ public:
 				//print_line("call dictionary");
 				jobject obj = env->CallObjectMethodA(instance, E->get().method, v);
 				ret = _jobject_to_variant(env, obj);
+				env->DeleteLocalRef(obj);
 
 			} break;
 			default: {
@@ -518,6 +572,10 @@ public:
 			} break;
 		}
 
+		while (to_erase.size()) {
+			env->DeleteLocalRef(to_erase.front()->get());
+			to_erase.pop_front();
+		}
 		//print_line("success");
 
 		return ret;
@@ -872,6 +930,7 @@ static void _initialize_java_modules() {
 
 	String modules = Globals::get_singleton()->get("android/modules");
 	Vector<String> mods = modules.split(",",false);
+    print_line("ANDROID MODULES : " + modules);
 	__android_log_print(ANDROID_LOG_INFO,"godot","mod count: %i",mods.size());
 
 	if (mods.size()) {
@@ -1571,6 +1630,8 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_callobject(JNIEnv * env,
 		memnew_placement(&vlist[i], Variant);
 		vlist[i] = v;
 		vptr[i] = &vlist[i];
+		env->DeleteLocalRef(obj);
+
 	};
 
 	Variant::CallError err;
@@ -1588,13 +1649,15 @@ JNIEXPORT void JNICALL Java_com_android_godot_GodotLib_calldeferred(JNIEnv * env
 	int count = env->GetArrayLength(params);
 	Variant args[VARIANT_ARG_MAX];
 
-//	print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
+    //print_line("Java->GD call: "+obj->get_type()+"::"+str_method+" argc "+itos(count));
 
 	for (int i=0; i<MIN(count,VARIANT_ARG_MAX); i++) {
 
 		jobject obj = env->GetObjectArrayElement(params, i);
 		if (obj)
 			args[i] = _jobject_to_variant(env, obj);
+		env->DeleteLocalRef(obj);
+
 //		print_line("\targ"+itos(i)+": "+Variant::get_type_name(args[i].get_type()));
 
 	};

+ 1 - 9
platform/bb10/SCsub

@@ -18,13 +18,5 @@ if env['bb10_lgles_override'] == "yes":
 
 
 prog = None
-if env["target"]=="release":
-	prog = env_bps.Program('#platform/bb10/godot_bb10_opt', bb10_lib)
-else:
-	prog = env_bps.Program('#platform/bb10/godot_bb10', bb10_lib)
-
-import os
-fname = os.path.basename(str(prog[0]))
-
-env.Command('#bin/'+fname, prog, Copy('bin/'+fname, prog[0]))
+prog = env_bps.Program('#bin/godot', bb10_lib)
 

+ 9 - 21
platform/bb10/bar/bar-descriptor.xml

@@ -1,65 +1,53 @@
-<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<?xml version='1.0' encoding='utf-8' standalone='no'?>
 <qnx xmlns="http://www.qnx.com/schemas/application/1.0">
-
-<!-- BlackBerry® 10 application descriptor file.
+    <!-- BlackBerry® 10 application descriptor file.
 
     Specifies parameters for identifying, installing, and launching native applications on BlackBerry® 10 OS.
 -->
-
     <!-- A universally unique application identifier. Must be unique across all BlackBerry applications.
          Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
     <id>com.godot.game</id>
-
     <!-- The name that is displayed in the BlackBerry application installer. 
          May have multiple values for each language. See samples or xsd schema file. Optional. -->
     <name>Godot Game</name>
-    
     <!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade. 
          Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
          An updated version of application must have a versionNumber value higher than the previous version. Required. -->
     <versionNumber>0.0.1</versionNumber>
-
     <!-- Fourth digit segment of the package version. First three segments are taken from the 
          <versionNumber> element.  Must be an integer from 0 to 2^16-1 -->
     <buildId>0</buildId>
-                 
     <!-- Description, displayed in the BlackBerry application installer.
          May have multiple values for each language. See samples or xsd schema file. Optional. -->
     <description>Game made with Godot Engine</description>
-
     <!--  Name of author which is used for signing. Must match the developer name of your development certificate. -->
     <author>You Name or Company</author>
     <authorId>authorIDherePlease</authorId>
-    
     <!--  Unique author ID assigned by signing authority. Required if using debug tokens. -->
     <!-- <authorId>ABC1234YjsnUk235h</authorId> -->
-   
     <initialWindow>
         <aspectRatio>landscape</aspectRatio>
         <autoOrients>false</autoOrients>
         <systemChrome>none</systemChrome>
         <transparent>false</transparent>
     </initialWindow>
-    
     <!--  The category where the application appears. Either core.games or core.media. -->
     <category>core.games</category>
     <permission>read_device_identifying_information</permission>
     <permission>access_internet</permission>
-    <asset path="assets">assets</asset>
+    <asset path="data.pck">data.pck</asset>
     <configuration name="Device-Debug">
-       <platformArchitecture>armle-v7</platformArchitecture>
-       <asset path="godot_bb10.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10.qnx.armle</asset>
+        <platformArchitecture>armle-v7</platformArchitecture>
+        <asset type="Qnx/Elf" path="godot.bb10.debug.qnx.armle" entry="true">godot.bb10.debug.qnx.armle</asset>
     </configuration>
     <configuration name="Device-Release">
-       <platformArchitecture>armle-v7</platformArchitecture>
-       <asset path="godot_bb10_opt.qnx.armle" entry="true" type="Qnx/Elf">godot_bb10_opt.qnx.armle</asset>
+        <platformArchitecture>armle-v7</platformArchitecture>
+        <asset type="Qnx/Elf" path="godot.bb10.opt.qnx.armle" entry="true">godot.bb10.opt.qnx.armle</asset>
     </configuration>
     <!--  The icon for the application. -->
     <icon>
-       <image>icon.png</image>
+        <image>icon.png</image>
     </icon>
-    
     <!-- Ensure that shared libraries in the package are found at run-time. -->
-    <env var="LD_LIBRARY_PATH" value="app/native/lib:/usr/lib/qt4/lib"/>
-    
+    <env value="app/native/lib:/usr/lib/qt4/lib" var="LD_LIBRARY_PATH"/>
 </qnx>

+ 0 - 2
platform/bb10/detect.py

@@ -81,8 +81,6 @@ def configure(env):
 	if (env["target"]=="release"):
 
 		env.Append(CCFLAGS=['-O3','-DRELEASE_BUILD'])
-		env['OBJSUFFIX'] = "_opt"+env['OBJSUFFIX']
-		env['LIBSUFFIX'] = "_opt"+env['LIBSUFFIX']
 
 	elif (env["target"]=="debug"):
 

+ 33 - 46
platform/bb10/export/export.cpp

@@ -321,12 +321,29 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
 	//BE SUPER CAREFUL WITH THIS PLEASE!!!
 	//BLACKBERRY THIS IS YOUR FAULT FOR NOT MAKING A BETTER WAY!!
 
-	if (bar_dir.ends_with("bb10_export")) {
-		Error err = da->erase_contents_recursive();
-		if (err!=OK) {
+	bool berr = bar_dir.ends_with("bb10_export");
+	if (berr) {
+		if (da->list_dir_begin()) {
 			EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir);
-			ERR_FAIL_COND_V(err!=OK,err);
-		}
+			ERR_FAIL_COND_V(berr,FAILED);
+		};
+
+		String f = da->get_next();
+		while (f != "") {
+
+			if (f == "." || f == "..") {
+				f = da->get_next();
+				continue;
+			};
+			Error err = da->remove(bar_dir + "/" + f);
+			if (err != OK) {
+				EditorNode::add_io_error("Can't ensure that dir is empty:\n"+bar_dir);
+				ERR_FAIL_COND_V(err!=OK,err);
+			};
+			f = da->get_next();
+		};
+
+		da->list_dir_end();
 
 	} else {
 		print_line("ARE YOU CRAZY??? THIS IS A SERIOUS BUG HERE!!!");
@@ -405,52 +422,23 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
 		ret = unzGoToNextFile(pkg);
 	}
 
-	ep.step("Finding Files..",1);
-
-	Vector<StringName> files=get_dependencies(false);
-
 	ep.step("Adding Files..",2);
 
-	da->change_dir(bar_dir);
-	da->make_dir("assets");
-	Error err = da->change_dir("assets");
-	ERR_FAIL_COND_V(err,err);
-
-	String asset_dir=da->get_current_dir();
-	if (!asset_dir.ends_with("/"))
-		asset_dir+="/";
-
-	for(int i=0;i<files.size();i++) {
-
-		String fname=files[i];
-		Vector<uint8_t> data = get_exported_file(fname);
-		/*
-		FileAccess *f=FileAccess::open(files[i],FileAccess::READ);
-		if (!f) {
-			EditorNode::add_io_error("Couldn't read: "+String(files[i]));
-		}
-		ERR_CONTINUE(!f);
-		data.resize(f->get_len());
-		f->get_buffer(data.ptr(),data.size());
-*/
-		String dst_path=fname;
-		dst_path=dst_path.replace_first("res://",asset_dir);
-
-		da->make_dir_recursive(dst_path.get_base_dir());
-
-		ep.step("Adding File: "+String(files[i]).get_file(),3+i*100/files.size());
-
-		FileAccessRef fr = FileAccess::open(dst_path,FileAccess::WRITE);
-		fr->store_buffer(data.ptr(),data.size());
+	FileAccess* dst = FileAccess::open(bar_dir+"/data.pck", FileAccess::WRITE);
+	if (!dst) {
+		EditorNode::add_io_error("Can't copy executable file to:\n "+p_path);
+		return ERR_FILE_CANT_WRITE;
 	}
-
+	save_pack(dst, false, 1024);
+	dst->close();
+	memdelete(dst);
 
 	ep.step("Creating BAR Package..",104);
 
 	String bb_packager=EditorSettings::get_singleton()->get("blackberry/host_tools");
 	bb_packager=bb_packager.plus_file("blackberry-nativepackager");
 	if (OS::get_singleton()->get_name()=="Windows")
-		bb_packager+=".exe";
+		bb_packager+=".bat";
 
 
 	if (!FileAccess::exists(bb_packager)) {
@@ -482,7 +470,7 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
 
 	int ec;
 
-	err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec);
+	Error err = OS::get_singleton()->execute(bb_packager,args,true,NULL,NULL,&ec);
 
 	if (err!=OK)
 		return err;
@@ -493,7 +481,6 @@ Error EditorExportPlatformBB10::export_project(const String& p_path, bool p_debu
 
 }
 
-
 bool EditorExportPlatformBB10::poll_devices() {
 
 	bool dc=devices_changed;
@@ -537,7 +524,7 @@ void EditorExportPlatformBB10::_device_poll_thread(void *ud) {
 		bb_deploy=bb_deploy.plus_file("blackberry-deploy");
 		bool windows = OS::get_singleton()->get_name()=="Windows";
 		if (windows)
-			bb_deploy+=".exe";
+			bb_deploy+=".bat";
 
 		if (!FileAccess::exists(bb_deploy)) {
 			OS::get_singleton()->delay_usec(3000000);
@@ -639,7 +626,7 @@ Error EditorExportPlatformBB10::run(int p_device, bool p_dumb) {
 	String bb_deploy=EditorSettings::get_singleton()->get("blackberry/host_tools");
 	bb_deploy=bb_deploy.plus_file("blackberry-deploy");
 	if (OS::get_singleton()->get_name()=="Windows")
-		bb_deploy+=".exe";
+		bb_deploy+=".bat";
 
 	if (!FileAccess::exists(bb_deploy)) {
 		EditorNode::add_io_error("Blackberry Deploy not found:\n"+bb_deploy);

+ 1 - 1
platform/bb10/os_bb10.cpp

@@ -619,7 +619,7 @@ OSBB10::OSBB10() {
 	printf("godot bb10!\n");
 	getcwd(launch_dir, sizeof(launch_dir));
 	printf("launch dir %s\n", launch_dir);
-	chdir("app/native/assets");
+	chdir("app/native");
 	launch_dir_ptr = launch_dir;
 }
 

+ 2 - 0
platform/iphone/gl_view.h

@@ -93,6 +93,8 @@
 - (BOOL)createFramebuffer;
 - (void)destroyFramebuffer;
 
+- (void)audioRouteChangeListenerCallback:(NSNotification*)notification;
+
 @property NSTimeInterval animationInterval;
 
 @end

+ 52 - 0
platform/iphone/gl_view.mm

@@ -119,6 +119,8 @@ bool _play_video(String p_path, float p_volume, String p_audio_track, String p_s
                                                name:AVPlayerItemDidPlayToEndTimeNotification
                                              object:[_instance.avPlayer currentItem]];
 
+	[_instance.avPlayer addObserver:_instance forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:0];
+
     [_instance.avPlayerLayer setFrame:_instance.bounds];
     [_instance.layer addSublayer:_instance.avPlayerLayer];
     [_instance.avPlayer play];
@@ -578,6 +580,39 @@ static void clear_touches() {
 	printf("inserting text with character %i\n", character[0]);
 };
 
+- (void)audioRouteChangeListenerCallback:(NSNotification*)notification
+{
+	printf("*********** route changed!%i\n");
+	NSDictionary *interuptionDict = notification.userInfo;
+
+	NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
+
+	switch (routeChangeReason) {
+
+		case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
+			NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
+			NSLog(@"Headphone/Line plugged in");
+			break;
+
+		case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
+			NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
+			NSLog(@"Headphone/Line was pulled. Resuming video play....");
+			if (_is_video_playing) {
+
+				dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+							[_instance.avPlayer play]; // NOTE: change this line according your current player implementation
+							NSLog(@"resumed play");
+				});
+			};
+			break;
+
+		case AVAudioSessionRouteChangeReasonCategoryChange:
+			// called at start - also when other audio wants to play
+			NSLog(@"AVAudioSessionRouteChangeReasonCategoryChange");
+			break;
+	}
+}
+
 
 // When created via code however, we get initWithFrame
 -(id)initWithFrame:(CGRect)frame
@@ -593,6 +628,11 @@ static void clear_touches() {
 	init_touches();
 	self. multipleTouchEnabled = YES;
 
+	printf("******** adding observer for sound routing changes\n");
+	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:)
+												 name:AVAudioSessionRouteChangeNotification
+											   object:nil];
+
 	//self.autoresizesSubviews = YES;
 	//[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth];
 
@@ -642,6 +682,18 @@ static void clear_touches() {
     		video_current_time = kCMTimeZero;
 		}
     }
+
+	if (object == _instance.avPlayer && [keyPath isEqualToString:@"rate"]) {
+		NSLog(@"Player playback rate changed: %.5f", _instance.avPlayer.rate);
+		if (_is_video_playing() && _instance.avPlayer.rate == 0.0 && !_instance.avPlayer.error) {
+			dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
+						[_instance.avPlayer play]; // NOTE: change this line according your current player implementation
+						NSLog(@"resumed play");
+			});
+
+			NSLog(@" . . . PAUSED (or just started)");
+		}
+	}
 }
 
 - (void)playerItemDidReachEnd:(NSNotification *)notification {

+ 11 - 0
scene/2d/camera_2d.cpp

@@ -323,6 +323,16 @@ void Camera2D::make_current() {
 	}
 }
 
+void Camera2D::clear_current() {
+
+	current=false;
+	if (is_inside_tree()) {
+		get_tree()->call_group(SceneTree::GROUP_CALL_REALTIME,group_name,"_make_current",(Object*)(NULL));
+	}
+
+}
+
+
 void Camera2D::set_limit(Margin p_margin,int p_limit) {
 
 	ERR_FAIL_INDEX(p_margin,4);
@@ -435,6 +445,7 @@ void Camera2D::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("is_rotating"),&Camera2D::is_rotating);
 
 	ObjectTypeDB::bind_method(_MD("make_current"),&Camera2D::make_current);
+	ObjectTypeDB::bind_method(_MD("clear_current"),&Camera2D::clear_current);
 	ObjectTypeDB::bind_method(_MD("_make_current"),&Camera2D::_make_current);
 
 	ObjectTypeDB::bind_method(_MD("_update_scroll"),&Camera2D::_update_scroll);

+ 95 - 94
scene/2d/camera_2d.h

@@ -26,97 +26,98 @@
 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
-#ifndef CAMERA_2D_H
-#define CAMERA_2D_H
-
-#include "scene/2d/node_2d.h"
-#include "scene/main/viewport.h"
-
-
-class Camera2D : public Node2D {
-
-	OBJ_TYPE( Camera2D, Node2D );
-
-protected:
-	Point2 camera_pos;
-	Point2 smoothed_camera_pos;
-	bool first;
-
-	Viewport *viewport;
-
-	StringName group_name;
-	StringName canvas_group_name;
-	RID canvas;
-	Vector2 offset;
-	Vector2 zoom;
-	bool centered;
-	bool rotating;
-	bool current;
-	float smoothing;
-	int limit[4];
-	float drag_margin[4];
-
-	bool h_drag_enabled;
-	bool v_drag_enabled;
-	float h_ofs;
-	float v_ofs;
-
-
-	Point2 camera_screen_center;
-	void _update_scroll();
-
-	void _make_current(Object *p_which);
-	void _set_current(bool p_current);
-protected:
-
-	virtual Matrix32 get_camera_transform();
-	void _notification(int p_what);
-	static void _bind_methods();
-public:
-
-	void set_offset(const Vector2& p_offset);
-	Vector2 get_offset() const;
-
-	void set_centered(bool p_centered);
-	bool is_centered() const;
-
-	void set_rotating(bool p_rotating);
-	bool is_rotating() const;
-
-	void set_limit(Margin p_margin,int p_limit);
-	int get_limit(Margin p_margin) const;
-
-
-	void set_h_drag_enabled(bool p_enabled);
-	bool is_h_drag_enabled() const;
-
-	void set_v_drag_enabled(bool p_enabled);
-	bool is_v_drag_enabled() const;
-
-	void set_drag_margin(Margin p_margin,float p_drag_margin);
-	float get_drag_margin(Margin p_margin) const;  
-
-	void set_v_offset(float p_offset);
-	float get_v_offset() const;
-
-	void set_h_offset(float p_offset);
-	float get_h_offset() const;
-
-	void set_follow_smoothing(float p_speed);
-	float get_follow_smoothing() const;
-
-	void make_current();
-	bool is_current() const;
-
-	void set_zoom(const Vector2& p_zoom);
-	Vector2 get_zoom() const;
-
-	Point2 get_camera_screen_center() const;
-
-	Vector2 get_camera_pos() const;
-	void force_update_scroll();
-
-	Camera2D();
-};
-
-#endif // CAMERA_2D_H
+#ifndef CAMERA_2D_H
+#define CAMERA_2D_H
+
+#include "scene/2d/node_2d.h"
+#include "scene/main/viewport.h"
+
+
+class Camera2D : public Node2D {
+
+	OBJ_TYPE( Camera2D, Node2D );
+
+protected:
+	Point2 camera_pos;
+	Point2 smoothed_camera_pos;
+	bool first;
+
+	Viewport *viewport;
+
+	StringName group_name;
+	StringName canvas_group_name;
+	RID canvas;
+	Vector2 offset;
+	Vector2 zoom;
+	bool centered;
+	bool rotating;
+	bool current;
+	float smoothing;
+	int limit[4];
+	float drag_margin[4];
+
+	bool h_drag_enabled;
+	bool v_drag_enabled;
+	float h_ofs;
+	float v_ofs;
+
+
+	Point2 camera_screen_center;
+	void _update_scroll();
+
+	void _make_current(Object *p_which);
+	void _set_current(bool p_current);
+protected:
+
+	virtual Matrix32 get_camera_transform();
+	void _notification(int p_what);
+	static void _bind_methods();
+public:
+
+	void set_offset(const Vector2& p_offset);
+	Vector2 get_offset() const;
+
+	void set_centered(bool p_centered);
+	bool is_centered() const;
+
+	void set_rotating(bool p_rotating);
+	bool is_rotating() const;
+
+	void set_limit(Margin p_margin,int p_limit);
+	int get_limit(Margin p_margin) const;
+
+
+	void set_h_drag_enabled(bool p_enabled);
+	bool is_h_drag_enabled() const;
+
+	void set_v_drag_enabled(bool p_enabled);
+	bool is_v_drag_enabled() const;
+
+	void set_drag_margin(Margin p_margin,float p_drag_margin);
+	float get_drag_margin(Margin p_margin) const;  
+
+	void set_v_offset(float p_offset);
+	float get_v_offset() const;
+
+	void set_h_offset(float p_offset);
+	float get_h_offset() const;
+
+	void set_follow_smoothing(float p_speed);
+	float get_follow_smoothing() const;
+
+	void make_current();
+	void clear_current();
+	bool is_current() const;
+
+	void set_zoom(const Vector2& p_zoom);
+	Vector2 get_zoom() const;
+
+	Point2 get_camera_screen_center() const;
+
+	Vector2 get_camera_pos() const;
+	void force_update_scroll();
+
+	Camera2D();
+};
+
+#endif // CAMERA_2D_H

+ 2 - 0
scene/resources/shader_graph.h

@@ -66,6 +66,8 @@ public:
 		NODE_VEC_TO_XFORM, // 3 vec input, 1 xform output
 		NODE_SCALAR_INTERP, // scalar interpolation (with optional curve)
 		NODE_VEC_INTERP, // vec3 interpolation  (with optional curve)
+		/*NODE_SCALAR_CURVE_REMAP,
+		NODE_VEC_CURVE_REMAP,*/
 		NODE_SCALAR_INPUT, // scalar uniform (assignable in material)
 		NODE_VEC_INPUT, // vec3 uniform (assignable in material)
 		NODE_RGB_INPUT, // color uniform (assignable in material)

+ 3 - 1
servers/visual/shader_language.cpp

@@ -2058,7 +2058,9 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
 					at+=get_datatype_name(compute_node_type(op->arguments[i]));
 
 				}
-				parser.set_error("Invalid arguments to operator "+String(token_names[op->op])+": "+at);
+				static const char *op_names[OP_MAX]={"=","+","-","*","/","+=","-=","*=","/=","-","!","==","!=","<=",">=","<",">","||","&&","call","()"};
+
+				parser.set_error("Invalid arguments to operator "+String(op_names[op->op])+": "+at);
 				return ERR_PARSE_ERROR;
 			}
 			expression.remove(next_op);

+ 1 - 1
tools/collada/collada.cpp

@@ -817,7 +817,7 @@ void Collada::_parse_camera(XMLParser& parser) {
 			if (name=="perspective") {
 
 				camera.mode=CameraData::MODE_PERSPECTIVE;
-			} else if (name=="orthogonal") {
+			} else if (name=="orthographic") {
 
 				camera.mode=CameraData::MODE_ORTHOGONAL;
 			} else if (name=="xfov") {

+ 18 - 0
tools/collada/collada.h

@@ -337,6 +337,24 @@ public:
 					if(normal==p_vert.normal) {
 						if(uv==p_vert.uv) {
 							if(uv2==p_vert.uv2) {
+
+								if (!weights.empty() || !p_vert.weights.empty()) {
+
+									if (weights.size()==p_vert.weights.size()) {
+
+										for(int i=0;i<weights.size();i++) {
+											if (weights[i].bone_idx!=p_vert.weights[i].bone_idx)
+												return weights[i].bone_idx<p_vert.weights[i].bone_idx;
+
+											if (weights[i].weight!=p_vert.weights[i].weight)
+												return weights[i].weight<p_vert.weights[i].weight;
+										}
+									}  else {
+										return weights.size() < p_vert.weights.size();
+									}
+
+								}
+
 								return (color<p_vert.color);
 							} else
 								return (uv2<p_vert.uv2);

+ 28 - 2
tools/editor/editor_import_export.cpp

@@ -904,6 +904,16 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func
 	return OK;
 }
 
+static int _get_pad(int p_alignment, int p_n) {
+
+	int rest = p_n % p_alignment;
+	int pad = 0;
+	if (rest > 0) {
+		pad = p_alignment - rest;
+	};
+
+	return pad;
+};
 
 Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path, const Vector<uint8_t>& p_data,int p_file,int p_total) {
 
@@ -930,11 +940,19 @@ Error EditorExportPlatform::save_pack_file(void *p_userdata,const String& p_path
 	pd->ep->step("Storing File: "+p_path,2+p_file*100/p_total);
 	pd->count++;
 	pd->ftmp->store_buffer(p_data.ptr(),p_data.size());
+	if (pd->alignment > 1) {
+
+		int pad = _get_pad(pd->alignment, pd->ftmp->get_pos());
+		for (int i=0; i<pad; i++) {
+
+			pd->ftmp->store_8(0);
+		};
+	};
 	return OK;
 
 }
 
-Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
+Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles, int p_alignment) {
 
 	EditorProgress ep("savepack","Packing",102);
 
@@ -952,7 +970,6 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
 		dst->store_32(0);
 	}
 
-
 	size_t fcountpos = dst->get_pos();
 	dst->store_32(0);
 
@@ -961,11 +978,20 @@ Error EditorExportPlatform::save_pack(FileAccess *dst,bool p_make_bundles) {
 	pd.f=dst;
 	pd.ftmp=tmp;
 	pd.count=0;
+	pd.alignment = p_alignment;
 	Error err = export_project_files(save_pack_file,&pd,p_make_bundles);
 	memdelete(tmp);
 	if (err)
 		return err;
 
+	if (p_alignment > 1) {
+		int pad = _get_pad(p_alignment, dst->get_pos());
+		for (int i=0; i<pad; i++) {
+
+			dst->store_8(0);
+		};
+	};
+
 	size_t ofsplus = dst->get_pos();
 	//append file
 

+ 2 - 1
tools/editor/editor_import_export.h

@@ -100,6 +100,7 @@ protected:
 		Vector<TempData> file_ofs;
 		EditorProgress *ep;
 		int count;
+		int alignment;
 
 	};
 
@@ -121,7 +122,7 @@ public:
 
 	Error export_project_files(EditorExportSaveFunction p_func, void* p_udata,bool p_make_bundles);
 
-	Error save_pack(FileAccess *p_where, bool p_make_bundles=false);
+	Error save_pack(FileAccess *p_where, bool p_make_bundles=false, int p_alignment = 1);
 	virtual String get_name() const =0;
 	virtual ImageCompression get_image_compression() const=0;
 	virtual Ref<Texture> get_logo() const =0;

+ 7 - 4
tools/editor/io_plugins/editor_import_collada.cpp

@@ -285,13 +285,16 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) {
 
 					case Collada::CameraData::MODE_ORTHOGONAL: {
 
-						if (cd.orthogonal.x_mag) {
+						if (cd.orthogonal.y_mag) {
 
-							camera->set_orthogonal(cd.orthogonal.x_mag,cd.z_near,cd.z_far);
+							camera->set_keep_aspect_mode(Camera::KEEP_HEIGHT);
+							camera->set_orthogonal(cd.orthogonal.y_mag*2.0 ,cd.z_near,cd.z_far);
 
-						} else if (!cd.orthogonal.x_mag && cd.orthogonal.y_mag) {
+						} else if (!cd.orthogonal.y_mag && cd.orthogonal.x_mag) {
 
-							camera->set_orthogonal(cd.orthogonal.y_mag * cd.aspect,cd.z_near,cd.z_far);
+
+							camera->set_keep_aspect_mode(Camera::KEEP_WIDTH);
+							camera->set_orthogonal(cd.orthogonal.x_mag*2.0,cd.z_near,cd.z_far);
 						}
 
 					} break;

+ 55 - 16
tools/export/blender25/io_scene_dae/export_dae.py

@@ -94,8 +94,6 @@ def strarr(arr):
 	s+=" "
 	return s
 
-
-
 class DaeExporter:
 
 	def validate_id(self,d):
@@ -132,10 +130,10 @@ class DaeExporter:
 				tup = tup + (self.tangent.x,self.tangent.y,self.tangent.z)
 			if (self.bitangent!=None):
 				tup = tup + (self.bitangent.x,self.bitangent.y,self.bitangent.z)
-			#for t in self.bones:
-			#	tup = tup + (t)
-			#for t in self.weights:
-			#	tup = tup + (t)
+			for t in self.bones:
+				tup = tup + (float(t),)
+			for t in self.weights:
+				tup = tup + (float(t),)
 
 			return tup
 
@@ -212,8 +210,8 @@ class DaeExporter:
 		imgid = self.new_id("image")
 		
 		if (not os.path.isfile(imgpath)):
-			if img_tmp_path.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
-				imgpath="images/"+os.path.basename(img_tmp_path)
+			if imgpath.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")):
+				imgpath="images/"+os.path.basename(imgpath)
 			else:
 				imgpath="images/"+image.name+".png"
 		
@@ -512,12 +510,12 @@ class DaeExporter:
 		mat_assign=[]
 
 		uv_layer_count=len(mesh.uv_textures)
-		if (len(mesh.uv_textures)):
+		if (has_tangents and len(mesh.uv_textures)):
 			try:
 				mesh.calc_tangents()
 			except:
-				print("Warning, blender API is fucked up, not exporting UVs for this object.")
-				uv_layer_count=0
+				self.operator.report({'WARNING'},'CalcTangets failed for mesh "'+mesh.name+'", no tangets will be exported.')
+				#uv_layer_count=0
 				mesh.calc_normals_split()
 				has_tangents=False
 
@@ -591,16 +589,30 @@ class DaeExporter:
 
 				if (armature!=None):
 					wsum=0.0
+					zero_bones=[]
+
 					for vg in mv.groups:
 						if vg.group >= len(node.vertex_groups):
 							continue;
 						name = node.vertex_groups[vg.group].name
+
 						if (name in si["bone_index"]):
 							#could still put the weight as 0.0001 maybe
 							if (vg.weight>0.001): #blender has a lot of zero weight stuff
 								v.bones.append(si["bone_index"][name])
 								v.weights.append(vg.weight)
 								wsum+=vg.weight
+					if (wsum==0.0):
+						if not self.wrongvtx_report:
+							self.operator.report({'WARNING'},'Mesh for object "'+node.name+'" has unassigned weights. This may look wrong in exported model.')
+							self.wrongvtx_report=True
+
+						#blender can have bones assigned that weight zero so they remain local
+						#this is the best it can be done?
+						v.bones.append(0)
+						v.weights.append(1)
+
+
 
 
 				tup = v.get_tup()
@@ -889,6 +901,15 @@ class DaeExporter:
 		if (node.parent!=None):
 			if (node.parent.type=="ARMATURE"):
 				armature=node.parent
+			armcount=0
+			for n in node.modifiers:
+				if (n.type=="ARMATURE"):
+					armcount+=1
+			if (armcount>1):
+				self.operator.report({'WARNING'},'Object "'+node.name+'" refers to more than one armature! This is unsopported.')
+
+
+
 
 		if (node.data.shape_keys!=None):
 				sk = node.data.shape_keys
@@ -940,6 +961,12 @@ class DaeExporter:
 		boneidx = si["bone_count"]
 		si["bone_count"]+=1
 		bonesid = si["id"]+"-"+str(boneidx)
+		if (bone.name in self.used_bones):
+			if (self.config["use_anim_action_all"]):
+				self.operator.report({'WARNING'},'Bone name "'+bone.name+'" used in more than one skeleton. Actions might export wrong.')
+		else:
+			self.used_bones.append(bone.name)
+
 		si["bone_index"][bone.name]=boneidx
 		si["bone_ids"][bone]=boneid
 		si["bone_names"].append(bonesid)
@@ -1002,12 +1029,12 @@ class DaeExporter:
 			self.writel(S_CAMS,5,'<zfar> '+str(camera.clip_end)+' </zfar>')
 			self.writel(S_CAMS,4,'</perspective>')
 		else:
-			self.writel(S_CAMS,4,'<orthografic>')
-			self.writel(S_CAMS,5,'<xmag> '+str(camera.ortho_scale)+' </xmag>') # I think?
+			self.writel(S_CAMS,4,'<orthographic>')
+			self.writel(S_CAMS,5,'<xmag> '+str(camera.ortho_scale*0.5)+' </xmag>') # I think?
 			self.writel(S_CAMS,5,'<aspect_ratio> '+str(self.scene.render.resolution_x / self.scene.render.resolution_y)+' </aspect_ratio>')
 			self.writel(S_CAMS,5,'<znear> '+str(camera.clip_start)+' </znear>')
 			self.writel(S_CAMS,5,'<zfar> '+str(camera.clip_end)+' </zfar>')
-			self.writel(S_CAMS,4,'</orthografic>')
+			self.writel(S_CAMS,4,'</orthographic>')
 
 		self.writel(S_CAMS,3,'</technique_common>')
 		self.writel(S_CAMS,2,'</optics>')
@@ -1534,10 +1561,14 @@ class DaeExporter:
 				for z in tcn:
 					self.writel(S_ANIM_CLIPS,2,'<instance_animation url="#'+z+'"/>')
 				self.writel(S_ANIM_CLIPS,1,'</animation_clip>')
+				if (len(tcn)==0):
+					self.operator.report({'WARNING'},'Animation clip "'+x.name+'" contains no tracks.')
+
 
 
 			self.writel(S_ANIM_CLIPS,0,'</library_animation_clips>')
 
+
 			for i,s in enumerate(self.skeletons):
 				if (s.animation_data==None):
 					continue
@@ -1547,6 +1578,7 @@ class DaeExporter:
 					s.animation_data.action = None
 					for j,bone in enumerate(s.pose.bones):
 						bone.matrix_basis = tmp_mat[i][1][j]
+
 		else:
 			self.export_animation(self.scene.frame_start,self.scene.frame_end)
 		
@@ -1617,7 +1649,8 @@ class DaeExporter:
 		f.write(bytes('</COLLADA>\n',"UTF-8"))
 		return True
 
-	def __init__(self,path,kwargs):
+	def __init__(self,path,kwargs,operator):
+		self.operator=operator
 		self.scene=bpy.context.scene
 		self.last_id=0
 		self.scene_name=self.new_id("scene")
@@ -1631,6 +1664,10 @@ class DaeExporter:
 		self.config=kwargs
 		self.valid_nodes=[]
 		self.armature_for_morph={}
+		self.used_bones=[]
+		self.wrongvtx_report=False		
+
+
 
 
 
@@ -1642,9 +1679,11 @@ def save(operator, context,
 	**kwargs
 	):
 
-	exp = DaeExporter(filepath,kwargs)
+	exp = DaeExporter(filepath,kwargs,operator)
 	exp.export()
 
+
+
 	return {'FINISHED'}  # so the script wont run after we have batch exported.