diff options
Diffstat (limited to 'platform')
47 files changed, 603 insertions, 320 deletions
diff --git a/platform/android/dir_access_jandroid.cpp b/platform/android/dir_access_jandroid.cpp index 69178317f7..f52b511522 100644 --- a/platform/android/dir_access_jandroid.cpp +++ b/platform/android/dir_access_jandroid.cpp @@ -110,7 +110,6 @@ String DirAccessJAndroid::get_drive(int p_drive) {  Error DirAccessJAndroid::change_dir(String p_dir) {  	JNIEnv *env = ThreadAndroid::get_env(); -	p_dir = p_dir.simplify_path();  	if (p_dir == "" || p_dir == "." || (p_dir == ".." && current_dir == ""))  		return OK; diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 9167a291f8..eb461860ed 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -30,6 +30,7 @@  #include "export.h" +#include "core/io/image_loader.h"  #include "core/io/marshalls.h"  #include "core/io/zip_io.h"  #include "core/os/dir_access.h" @@ -37,6 +38,7 @@  #include "core/os/os.h"  #include "core/project_settings.h"  #include "core/version.h" +#include "drivers/png/png_driver_common.h"  #include "editor/editor_export.h"  #include "editor/editor_log.h"  #include "editor/editor_node.h" @@ -196,16 +198,40 @@ static const char *android_perms[] = {  };  struct LauncherIcon { -	const char *option_id;  	const char *export_path; +	int dimensions;  }; -static const LauncherIcon launcher_icons[] = { -	{ "launcher_icons/xxxhdpi_192x192", "res/drawable-xxxhdpi-v4/icon.png" }, -	{ "launcher_icons/xxhdpi_144x144", "res/drawable-xxhdpi-v4/icon.png" }, -	{ "launcher_icons/xhdpi_96x96", "res/drawable-xhdpi-v4/icon.png" }, -	{ "launcher_icons/hdpi_72x72", "res/drawable-hdpi-v4/icon.png" }, -	{ "launcher_icons/mdpi_48x48", "res/drawable-mdpi-v4/icon.png" } +static const int icon_densities_count = 6; +static const char *launcher_icon_option = "launcher_icon/xxxhdpi_192x192"; +static const char *launcher_adaptive_icon_foreground_option = "launcher_adaptive_icon_foreground/xxxhdpi_432x432"; +static const char *launcher_adaptive_icon_background_option = "launcher_adaptive_icon_background/xxxhdpi_432x432"; + +static const LauncherIcon launcher_icons[icon_densities_count] = { +	{ "res/mipmap-xxxhdpi-v4/icon.png", 192 }, +	{ "res/mipmap-xxhdpi-v4/icon.png", 144 }, +	{ "res/mipmap-xhdpi-v4/icon.png", 96 }, +	{ "res/mipmap-hdpi-v4/icon.png", 72 }, +	{ "res/mipmap-mdpi-v4/icon.png", 48 }, +	{ "res/mipmap/icon.png", 192 } +}; + +static const LauncherIcon launcher_adaptive_icon_foregrounds[icon_densities_count] = { +	{ "res/mipmap-xxxhdpi-v4/icon_foreground.png", 432 }, +	{ "res/mipmap-xxhdpi-v4/icon_foreground.png", 324 }, +	{ "res/mipmap-xhdpi-v4/icon_foreground.png", 216 }, +	{ "res/mipmap-hdpi-v4/icon_foreground.png", 162 }, +	{ "res/mipmap-mdpi-v4/icon_foreground.png", 108 }, +	{ "res/mipmap/icon_foreground.png", 432 } +}; + +static const LauncherIcon launcher_adaptive_icon_backgrounds[icon_densities_count] = { +	{ "res/mipmap-xxxhdpi-v4/icon_background.png", 432 }, +	{ "res/mipmap-xxhdpi-v4/icon_background.png", 324 }, +	{ "res/mipmap-xhdpi-v4/icon_background.png", 216 }, +	{ "res/mipmap-hdpi-v4/icon_background.png", 162 }, +	{ "res/mipmap-mdpi-v4/icon_background.png", 108 }, +	{ "res/mipmap/icon_background.png", 432 }  };  class EditorExportPlatformAndroid : public EditorExportPlatform { @@ -680,7 +706,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {  		bool screen_support_large = p_preset->get("screen/support_large");  		bool screen_support_xlarge = p_preset->get("screen/support_xlarge"); -		int xr_mode_index = p_preset->get("graphics/xr_mode"); +		int xr_mode_index = p_preset->get("xr_features/xr_mode");  		Vector<String> perms; @@ -859,135 +885,174 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {  					uint32_t name = decode_uint32(&p_manifest[iofs + 12]);  					String tname = string_table[name]; -					int dof_index = p_preset->get("graphics/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof +					if (tname == "uses-feature") { +						Vector<String> feature_names; +						Vector<bool> feature_required_list; +						Vector<int> feature_versions; + +						if (xr_mode_index == 1 /* XRMode.OVR */) { +							// Check for degrees of freedom +							int dof_index = p_preset->get("xr_features/degrees_of_freedom"); // 0: none, 1: 3dof and 6dof, 2: 6dof + +							if (dof_index > 0) { +								feature_names.push_back("android.hardware.vr.headtracking"); +								feature_required_list.push_back(dof_index == 2); +								feature_versions.push_back(1); +							} + +							// Check for hand tracking +							int hand_tracking_index = p_preset->get("xr_features/hand_tracking"); // 0: none, 1: optional, 2: required +							if (hand_tracking_index > 0) { +								feature_names.push_back("oculus.software.handtracking"); +								feature_required_list.push_back(hand_tracking_index == 2); +								feature_versions.push_back(-1); // no version attribute should be added. -					if (tname == "uses-feature" && dof_index > 0) { -						if (xr_mode_index == 0) { -							WARN_PRINT("VR DOF feature setting is only valid for oculus HMDs with an XR mode set to VR"); +								if (perms.find("oculus.permission.handtracking") == -1) { +									perms.push_back("oculus.permission.handtracking"); +								} +							}  						} -						ofs += 24; // skip over end tag -						// save manifest ending so we can restore it -						Vector<uint8_t> manifest_end; -						uint32_t manifest_cur_size = p_manifest.size(); +						if (feature_names.size() > 0) { +							ofs += 24; // skip over end tag -						manifest_end.resize(p_manifest.size() - ofs); -						memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); +							// save manifest ending so we can restore it +							Vector<uint8_t> manifest_end; +							uint32_t manifest_cur_size = p_manifest.size(); -						int32_t attr_name_string = string_table.find("name"); -						ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); +							manifest_end.resize(p_manifest.size() - ofs); +							memcpy(manifest_end.ptrw(), &p_manifest[ofs], manifest_end.size()); -						int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android"); -						if (ns_android_string == -1) { -							string_table.push_back("http://schemas.android.com/apk/res/android"); -							ns_android_string = string_table.size() - 1; -						} +							int32_t attr_name_string = string_table.find("name"); +							ERR_FAIL_COND_MSG(attr_name_string == -1, "Template does not have 'name' attribute."); -						int32_t attr_uses_permission_string = string_table.find("uses-feature"); -						if (attr_uses_permission_string == -1) { -							string_table.push_back("uses-feature"); -							attr_uses_permission_string = string_table.size() - 1; -						} +							int32_t ns_android_string = string_table.find("http://schemas.android.com/apk/res/android"); +							if (ns_android_string == -1) { +								string_table.push_back("http://schemas.android.com/apk/res/android"); +								ns_android_string = string_table.size() - 1; +							} -						int32_t attr_required_string = string_table.find("required"); -						if (attr_required_string == -1) { -							string_table.push_back("required"); -							attr_required_string = string_table.size() - 1; -						} +							int32_t attr_uses_feature_string = string_table.find("uses-feature"); +							if (attr_uses_feature_string == -1) { +								string_table.push_back("uses-feature"); +								attr_uses_feature_string = string_table.size() - 1; +							} -						int32_t attr_version_string = string_table.find("version"); -						if (attr_version_string == -1) { -							string_table.push_back("version"); -							attr_version_string = string_table.size() - 1; -						} +							int32_t attr_required_string = string_table.find("required"); +							if (attr_required_string == -1) { +								string_table.push_back("required"); +								attr_required_string = string_table.size() - 1; +							} -						String required_value_string; -						if (dof_index == 1) { -							required_value_string = "false"; -						} else if (dof_index == 2) { -							required_value_string = "true"; -						} else { -							ERR_FAIL_MSG("Unknown DoF index: " + itos(dof_index) + "."); -						} -						int32_t required_value = string_table.find(required_value_string); -						if (required_value == -1) { -							string_table.push_back(required_value_string); -							required_value = string_table.size() - 1; -						} +							for (int i = 0; i < feature_names.size(); i++) { +								String feature_name = feature_names[i]; +								bool feature_required = feature_required_list[i]; +								int feature_version = feature_versions[i]; +								bool has_version_attribute = feature_version != -1; -						int32_t version_value = string_table.find("1"); -						if (version_value == -1) { -							string_table.push_back("1"); -							version_value = string_table.size() - 1; -						} +								print_line("Adding feature " + feature_name); -						int32_t feature_string = string_table.find("android.hardware.vr.headtracking"); -						if (feature_string == -1) { -							string_table.push_back("android.hardware.vr.headtracking"); -							feature_string = string_table.size() - 1; -						} +								int32_t feature_string = string_table.find(feature_name); +								if (feature_string == -1) { +									string_table.push_back(feature_name); +									feature_string = string_table.size() - 1; +								} -						{ -							manifest_cur_size += 96 + 20; // node and three attrs + end node -							p_manifest.resize(manifest_cur_size); +								String required_value_string = feature_required ? "true" : "false"; +								int32_t required_value = string_table.find(required_value_string); +								if (required_value == -1) { +									string_table.push_back(required_value_string); +									required_value = string_table.size() - 1; +								} -							// start tag -							encode_uint16(0x102, &p_manifest.write[ofs]); // type -							encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize -							encode_uint32(96, &p_manifest.write[ofs + 4]); // size -							encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno -							encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment -							encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns -							encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name -							encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start -							encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size -							encode_uint16(3, &p_manifest.write[ofs + 28]); // num_attrs -							encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index -							encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index -							encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index +								int32_t attr_version_string = -1; +								int32_t version_value = -1; +								int tag_size; +								int attr_count; +								if (has_version_attribute) { +									attr_version_string = string_table.find("version"); +									if (attr_version_string == -1) { +										string_table.push_back("version"); +										attr_version_string = string_table.size() - 1; +									} -							// android:name attribute -							encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns -							encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' -							encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value -							encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size -							p_manifest.write[ofs + 50] = 0; // typedvalue_always0 -							p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) -							encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference - -							// android:required attribute -							encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns -							encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name' -							encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value -							encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size -							p_manifest.write[ofs + 70] = 0; // typedvalue_always0 -							p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string) -							encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference - -							// android:version attribute -							encode_uint32(ns_android_string, &p_manifest.write[ofs + 76]); // ns -							encode_uint32(attr_version_string, &p_manifest.write[ofs + 80]); // 'name' -							encode_uint32(version_value, &p_manifest.write[ofs + 84]); // raw_value -							encode_uint16(8, &p_manifest.write[ofs + 88]); // typedvalue_size -							p_manifest.write[ofs + 90] = 0; // typedvalue_always0 -							p_manifest.write[ofs + 91] = 0x03; // typedvalue_type (string) -							encode_uint32(version_value, &p_manifest.write[ofs + 92]); // typedvalue reference - -							ofs += 96; +									version_value = string_table.find(itos(feature_version)); +									if (version_value == -1) { +										string_table.push_back(itos(feature_version)); +										version_value = string_table.size() - 1; +									} -							// end tag -							encode_uint16(0x103, &p_manifest.write[ofs]); // type -							encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize -							encode_uint32(24, &p_manifest.write[ofs + 4]); // size -							encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno -							encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment -							encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns -							encode_uint32(attr_uses_permission_string, &p_manifest.write[ofs + 20]); // name +									tag_size = 96; // node and three attrs + end node +									attr_count = 3; +								} else { +									tag_size = 76; // node and two attrs + end node +									attr_count = 2; +								} +								manifest_cur_size += tag_size + 24; +								p_manifest.resize(manifest_cur_size); + +								// start tag +								encode_uint16(0x102, &p_manifest.write[ofs]); // type +								encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize +								encode_uint32(tag_size, &p_manifest.write[ofs + 4]); // size +								encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno +								encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment +								encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns +								encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name +								encode_uint16(20, &p_manifest.write[ofs + 24]); // attr_start +								encode_uint16(20, &p_manifest.write[ofs + 26]); // attr_size +								encode_uint16(attr_count, &p_manifest.write[ofs + 28]); // num_attrs +								encode_uint16(0, &p_manifest.write[ofs + 30]); // id_index +								encode_uint16(0, &p_manifest.write[ofs + 32]); // class_index +								encode_uint16(0, &p_manifest.write[ofs + 34]); // style_index + +								// android:name attribute +								encode_uint32(ns_android_string, &p_manifest.write[ofs + 36]); // ns +								encode_uint32(attr_name_string, &p_manifest.write[ofs + 40]); // 'name' +								encode_uint32(feature_string, &p_manifest.write[ofs + 44]); // raw_value +								encode_uint16(8, &p_manifest.write[ofs + 48]); // typedvalue_size +								p_manifest.write[ofs + 50] = 0; // typedvalue_always0 +								p_manifest.write[ofs + 51] = 0x03; // typedvalue_type (string) +								encode_uint32(feature_string, &p_manifest.write[ofs + 52]); // typedvalue reference + +								// android:required attribute +								encode_uint32(ns_android_string, &p_manifest.write[ofs + 56]); // ns +								encode_uint32(attr_required_string, &p_manifest.write[ofs + 60]); // 'name' +								encode_uint32(required_value, &p_manifest.write[ofs + 64]); // raw_value +								encode_uint16(8, &p_manifest.write[ofs + 68]); // typedvalue_size +								p_manifest.write[ofs + 70] = 0; // typedvalue_always0 +								p_manifest.write[ofs + 71] = 0x03; // typedvalue_type (string) +								encode_uint32(required_value, &p_manifest.write[ofs + 72]); // typedvalue reference + +								ofs += 76; + +								if (has_version_attribute) { +									// android:version attribute +									encode_uint32(ns_android_string, &p_manifest.write[ofs]); // ns +									encode_uint32(attr_version_string, &p_manifest.write[ofs + 4]); // 'name' +									encode_uint32(version_value, &p_manifest.write[ofs + 8]); // raw_value +									encode_uint16(8, &p_manifest.write[ofs + 12]); // typedvalue_size +									p_manifest.write[ofs + 14] = 0; // typedvalue_always0 +									p_manifest.write[ofs + 15] = 0x03; // typedvalue_type (string) +									encode_uint32(version_value, &p_manifest.write[ofs + 16]); // typedvalue reference + +									ofs += 20; +								} -							ofs += 24; +								// end tag +								encode_uint16(0x103, &p_manifest.write[ofs]); // type +								encode_uint16(16, &p_manifest.write[ofs + 2]); // headersize +								encode_uint32(24, &p_manifest.write[ofs + 4]); // size +								encode_uint32(0, &p_manifest.write[ofs + 8]); // lineno +								encode_uint32(-1, &p_manifest.write[ofs + 12]); // comment +								encode_uint32(-1, &p_manifest.write[ofs + 16]); // ns +								encode_uint32(attr_uses_feature_string, &p_manifest.write[ofs + 20]); // name + +								ofs += 24; +							} +							memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size()); +							ofs -= 24; // go back over back end  						} -						memcpy(&p_manifest.write[ofs], manifest_end.ptr(), manifest_end.size()); -						ofs -= 24; // go back over back end  					}  					if (tname == "manifest") { @@ -1259,6 +1324,27 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {  		//printf("end\n");  	} +	void _process_launcher_icons(const String &p_processing_file_name, const Ref<Image> &p_source_image, const LauncherIcon p_icon, Vector<uint8_t> &p_data) { +		if (p_processing_file_name == p_icon.export_path) { +			Ref<Image> working_image = p_source_image; + +			if (p_source_image->get_width() != p_icon.dimensions || p_source_image->get_height() != p_icon.dimensions) { +				working_image = p_source_image->duplicate(); +				working_image->resize(p_icon.dimensions, p_icon.dimensions, Image::Interpolation::INTERPOLATE_LANCZOS); +			} + +			PoolVector<uint8_t> png_buffer; +			Error err = PNGDriverCommon::image_to_png(working_image, png_buffer); +			if (err == OK) { +				p_data.resize(png_buffer.size()); +				memcpy(p_data.ptrw(), png_buffer.read().ptr(), p_data.size()); +			} else { +				String err_str = String("Failed to convert resized icon (") + p_processing_file_name + ") to png."; +				WARN_PRINT(err_str.utf8().get_data()); +			} +		} +	} +  	static Vector<String> get_enabled_abis(const Ref<EditorExportPreset> &p_preset) {  		Vector<String> abis = get_abis();  		Vector<String> enabled_abis; @@ -1295,13 +1381,14 @@ public:  	virtual void get_export_options(List<ExportOption> *r_options) { -		r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0)); -		r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "graphics/degrees_of_freedom", PROPERTY_HINT_ENUM, "None,3DOF and 6DOF,6DOF"), 0));  		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/32_bits_framebuffer"), true)); +		r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,Oculus Mobile VR"), 0)); +		r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/degrees_of_freedom", PROPERTY_HINT_ENUM, "None,3DOF and 6DOF,6DOF"), 0)); +		r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), 0));  		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "one_click_deploy/clear_previous_install"), false)); -		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); -		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); -		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_package/use_custom_build"), false)); +		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); +		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.apk"), "")); +		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "custom_template/use_custom_build"), false));  		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));  		r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));  		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name"), "1.0")); @@ -1315,11 +1402,9 @@ public:  		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_large"), true));  		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_xlarge"), true));  		r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/opengl_debug"), false)); - -		for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) { -			r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icons[i].option_id, PROPERTY_HINT_FILE, "*.png"), "")); -		} - +		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_icon_option, PROPERTY_HINT_FILE, "*.png"), "")); +		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_foreground_option, PROPERTY_HINT_FILE, "*.png"), "")); +		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, launcher_adaptive_icon_background_option, PROPERTY_HINT_FILE, "*.png"), ""));  		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore"), ""));  		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user"), ""));  		r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password"), "")); @@ -1577,29 +1662,34 @@ public:  	virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {  		String err; +		bool valid = false; -		if (!bool(p_preset->get("custom_package/use_custom_build"))) { +		// Look for export templates (first official, and if defined custom templates). -			r_missing_templates = find_export_template("android_debug.apk") == String() || find_export_template("android_release.apk") == String(); +		if (!bool(p_preset->get("custom_template/use_custom_build"))) { +			bool dvalid = exists_export_template("android_debug.apk", &err); +			bool rvalid = exists_export_template("android_release.apk", &err); -			if (p_preset->get("custom_package/debug") != "") { -				if (FileAccess::exists(p_preset->get("custom_package/debug"))) { -					r_missing_templates = false; -				} else { +			if (p_preset->get("custom_template/debug") != "") { +				dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); +				if (!dvalid) {  					err += TTR("Custom debug template not found.") + "\n";  				}  			} - -			if (p_preset->get("custom_package/release") != "") { -				if (FileAccess::exists(p_preset->get("custom_package/release"))) { -					r_missing_templates = false; -				} else { +			if (p_preset->get("custom_template/release") != "") { +				rvalid = FileAccess::exists(p_preset->get("custom_template/release")); +				if (!rvalid) {  					err += TTR("Custom release template not found.") + "\n";  				}  			} + +			valid = dvalid || rvalid; +		} else { +			valid = exists_export_template("android_source.zip", &err);  		} +		r_missing_templates = !valid; -		bool valid = !r_missing_templates; +		// Validate the rest of the configuration.  		String adb = EditorSettings::get_singleton()->get("export/android/adb"); @@ -1628,7 +1718,7 @@ public:  			}  		} -		if (bool(p_preset->get("custom_package/use_custom_build"))) { +		if (bool(p_preset->get("custom_template/use_custom_build"))) {  			String sdk_path = EditorSettings::get_singleton()->get("export/android/custom_build_sdk_path");  			if (sdk_path == "") {  				err += TTR("Custom build requires a valid Android SDK path in Editor Settings.") + "\n"; @@ -1912,7 +2002,7 @@ public:  							}  						} else if (l.strip_edges().begins_with("<application")) { -							String last_tag = "android:icon=\"@drawable/icon\""; +							String last_tag = "android:icon=\"@mipmap/icon\"";  							int last_tag_pos = l.find(last_tag);  							if (last_tag_pos == -1) {  								ERR_PRINTS("Not adding application attributes as the expected tag was not found in '<application': " + last_tag); @@ -1949,7 +2039,7 @@ public:  		EditorProgress ep("export", "Exporting for Android", 105, true); -		if (bool(p_preset->get("custom_package/use_custom_build"))) { //custom build +		if (bool(p_preset->get("custom_template/use_custom_build"))) { //custom build  			//re-generate build.gradle and AndroidManifest.xml  			{ //test that installed build version is alright @@ -2017,9 +2107,9 @@ public:  		} else {  			if (p_debug) -				src_apk = p_preset->get("custom_package/debug"); +				src_apk = p_preset->get("custom_template/debug");  			else -				src_apk = p_preset->get("custom_package/release"); +				src_apk = p_preset->get("custom_template/release");  			src_apk = src_apk.strip_edges();  			if (src_apk == "") { @@ -2091,6 +2181,35 @@ public:  		Vector<String> enabled_abis = get_enabled_abis(p_preset); +		String project_icon_path = ProjectSettings::get_singleton()->get("application/config/icon"); + +		// Prepare images to be resized for the icons. If some image ends up being uninitialized, the default image from the export template will be used. +		Ref<Image> launcher_icon_image; +		Ref<Image> launcher_adaptive_icon_foreground_image; +		Ref<Image> launcher_adaptive_icon_background_image; + +		launcher_icon_image.instance(); +		launcher_adaptive_icon_foreground_image.instance(); +		launcher_adaptive_icon_background_image.instance(); + +		// Regular icon: user selection -> project icon -> default. +		String path = static_cast<String>(p_preset->get(launcher_icon_option)).strip_edges(); +		if (path.empty() || ImageLoader::load_image(path, launcher_icon_image) != OK) { +			ImageLoader::load_image(project_icon_path, launcher_icon_image); +		} + +		// Adaptive foreground: user selection -> regular icon (user selection -> project icon -> default). +		path = static_cast<String>(p_preset->get(launcher_adaptive_icon_foreground_option)).strip_edges(); +		if (path.empty() || ImageLoader::load_image(path, launcher_adaptive_icon_foreground_image) != OK) { +			launcher_adaptive_icon_foreground_image = launcher_icon_image; +		} + +		// Adaptive background: user selection -> default. +		path = static_cast<String>(p_preset->get(launcher_adaptive_icon_background_option)).strip_edges(); +		if (!path.empty()) { +			ImageLoader::load_image(path, launcher_adaptive_icon_background_image); +		} +  		while (ret == UNZ_OK) {  			//get filename @@ -2113,41 +2232,22 @@ public:  			//write  			if (file == "AndroidManifest.xml") { -  				_fix_manifest(p_preset, data, p_flags & (DEBUG_FLAG_DUMB_CLIENT | DEBUG_FLAG_REMOTE_DEBUG));  			}  			if (file == "resources.arsc") { -  				_fix_resources(p_preset, data);  			} -			if (file == "res/drawable-nodpi-v4/icon.png") { -				bool found = false; -				for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) { -					String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges(); -					if (icon_path != "" && icon_path.ends_with(".png")) { -						FileAccess *f = FileAccess::open(icon_path, FileAccess::READ); -						if (f) { -							data.resize(f->get_len()); -							f->get_buffer(data.ptrw(), data.size()); -							memdelete(f); -							found = true; -							break; -						} -					} +			for (int i = 0; i < icon_densities_count; ++i) { +				if (launcher_icon_image.is_valid() && !launcher_icon_image->empty()) { +					_process_launcher_icons(file, launcher_icon_image, launcher_icons[i], data);  				} -				if (!found) { - -					String appicon = ProjectSettings::get_singleton()->get("application/config/icon"); -					if (appicon != "" && appicon.ends_with(".png")) { -						FileAccess *f = FileAccess::open(appicon, FileAccess::READ); -						if (f) { -							data.resize(f->get_len()); -							f->get_buffer(data.ptrw(), data.size()); -							memdelete(f); -						} -					} +				if (launcher_adaptive_icon_foreground_image.is_valid() && !launcher_adaptive_icon_foreground_image->empty()) { +					_process_launcher_icons(file, launcher_adaptive_icon_foreground_image, launcher_adaptive_icon_foregrounds[i], data); +				} +				if (launcher_adaptive_icon_background_image.is_valid() && !launcher_adaptive_icon_background_image->empty()) { +					_process_launcher_icons(file, launcher_adaptive_icon_background_image, launcher_adaptive_icon_backgrounds[i], data);  				}  			} @@ -2246,20 +2346,7 @@ public:  			}  		} -		if (!err) { -			APKExportData ed; -			ed.ep = &ep; -			ed.apk = unaligned_apk; -			for (uint64_t i = 0; i < sizeof(launcher_icons) / sizeof(launcher_icons[0]); ++i) { -				String icon_path = String(p_preset->get(launcher_icons[i].option_id)).strip_edges(); -				if (icon_path != "" && icon_path.ends_with(".png") && FileAccess::exists(icon_path)) { -					Vector<uint8_t> data = FileAccess::get_file_as_array(icon_path); -					store_in_apk(&ed, launcher_icons[i].export_path, data); -				} -			} -		} - -		int xr_mode_index = p_preset->get("graphics/xr_mode"); +		int xr_mode_index = p_preset->get("xr_features/xr_mode");  		if (xr_mode_index == 1 /* XRMode.OVR */) {  			cl.push_back("--xr_mode_ovr");  		} else { diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml index ba01ec313b..7e9ce70d80 100644 --- a/platform/android/java/app/AndroidManifest.xml +++ b/platform/android/java/app/AndroidManifest.xml @@ -27,7 +27,7 @@      <!-- Any tag in this line after android:icon will be erased when doing custom builds. -->      <!-- If you want to add tags manually, do before it. -->      <!-- WARNING: This should stay on a single line until the parsing code is improved. See GH-32414. --> -    <application android:label="@string/godot_project_name_string" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@drawable/icon" > +    <application android:label="@string/godot_project_name_string" android:allowBackup="false" tools:ignore="GoogleAppIndexingWarning" android:icon="@mipmap/icon" >          <!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. -->          <!-- Do these changes in the export preset. Adding new ones is fine. --> diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml index 517fc403b2..b133585f99 100644 --- a/platform/android/java/lib/AndroidManifest.xml +++ b/platform/android/java/lib/AndroidManifest.xml @@ -11,7 +11,7 @@      </application>      <instrumentation -        android:icon="@drawable/icon" +        android:icon="@mipmap/icon"          android:label="@string/godot_project_name_string"          android:name=".GodotInstrumentation"          android:targetPackage="org.godotengine.godot" /> diff --git a/platform/android/java/lib/res/drawable-nodpi/icon.png b/platform/android/java/lib/res/drawable-nodpi/icon.png Binary files differdeleted file mode 100644 index 6ad9b43117..0000000000 --- a/platform/android/java/lib/res/drawable-nodpi/icon.png +++ /dev/null diff --git a/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml new file mode 100644 index 0000000000..1ed4037035 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-anydpi-v26/icon.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> +    <background android:drawable="@mipmap/icon_background"/> +    <foreground android:drawable="@mipmap/icon_foreground"/> +</adaptive-icon>
\ No newline at end of file diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon.png b/platform/android/java/lib/res/mipmap-hdpi/icon.png Binary files differnew file mode 100644 index 0000000000..cc6e113e89 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-hdpi/icon.png diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon_background.png b/platform/android/java/lib/res/mipmap-hdpi/icon_background.png Binary files differnew file mode 100644 index 0000000000..78445c0181 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-hdpi/icon_background.png diff --git a/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png Binary files differnew file mode 100644 index 0000000000..75e409ff74 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-hdpi/icon_foreground.png diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon.png b/platform/android/java/lib/res/mipmap-mdpi/icon.png Binary files differnew file mode 100644 index 0000000000..e1968fe142 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-mdpi/icon.png diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon_background.png b/platform/android/java/lib/res/mipmap-mdpi/icon_background.png Binary files differnew file mode 100644 index 0000000000..5813f751ed --- /dev/null +++ b/platform/android/java/lib/res/mipmap-mdpi/icon_background.png diff --git a/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png Binary files differnew file mode 100644 index 0000000000..982b69be1e --- /dev/null +++ b/platform/android/java/lib/res/mipmap-mdpi/icon_foreground.png diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon.png b/platform/android/java/lib/res/mipmap-xhdpi/icon.png Binary files differnew file mode 100644 index 0000000000..9281d8da48 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xhdpi/icon.png diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png Binary files differnew file mode 100644 index 0000000000..4269c822a7 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xhdpi/icon_background.png diff --git a/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png Binary files differnew file mode 100644 index 0000000000..726b267ad6 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xhdpi/icon_foreground.png diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon.png Binary files differnew file mode 100644 index 0000000000..7a6b67d273 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon.png diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png Binary files differnew file mode 100644 index 0000000000..5e8b518d17 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon_background.png diff --git a/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png Binary files differnew file mode 100644 index 0000000000..b0c727f74c --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xxhdpi/icon_foreground.png diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png Binary files differnew file mode 100644 index 0000000000..0881245802 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon.png diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png Binary files differnew file mode 100644 index 0000000000..004b6fd508 --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_background.png diff --git a/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png Binary files differnew file mode 100644 index 0000000000..72e6f92b6e --- /dev/null +++ b/platform/android/java/lib/res/mipmap-xxxhdpi/icon_foreground.png diff --git a/platform/android/java/lib/res/mipmap/icon.png b/platform/android/java/lib/res/mipmap/icon.png Binary files differnew file mode 100644 index 0000000000..0881245802 --- /dev/null +++ b/platform/android/java/lib/res/mipmap/icon.png diff --git a/platform/android/java/lib/res/mipmap/icon_background.png b/platform/android/java/lib/res/mipmap/icon_background.png Binary files differnew file mode 100644 index 0000000000..5813f751ed --- /dev/null +++ b/platform/android/java/lib/res/mipmap/icon_background.png diff --git a/platform/android/java/lib/res/mipmap/icon_foreground.png b/platform/android/java/lib/res/mipmap/icon_foreground.png Binary files differnew file mode 100644 index 0000000000..982b69be1e --- /dev/null +++ b/platform/android/java/lib/res/mipmap/icon_foreground.png diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index 8447af10e4..e0b46673ba 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -100,6 +100,16 @@ public class GodotLib {  	public static native void hover(int type, int x, int y);  	/** +	 * Forward double_tap events from the main thread to the GL thread. +	 */ +	public static native void doubletap(int x, int y); + +	/** +	 * Forward scroll events from the main thread to the GL thread. +	 */ +	public static native void scroll(int x, int y); + +	/**  	 * Forward accelerometer sensor events from the main thread to the GL thread.  	 * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)  	 */ diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java index 78f3763d84..f938583082 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotView.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotView.java @@ -32,8 +32,10 @@ package org.godotengine.godot;  import android.annotation.SuppressLint;  import android.graphics.PixelFormat;  import android.opengl.GLSurfaceView; +import android.view.GestureDetector;  import android.view.KeyEvent;  import android.view.MotionEvent; +import org.godotengine.godot.input.GodotGestureHandler;  import org.godotengine.godot.input.GodotInputHandler;  import org.godotengine.godot.utils.GLUtils;  import org.godotengine.godot.xr.XRMode; @@ -68,6 +70,7 @@ public class GodotView extends GLSurfaceView {  	private final Godot activity;  	private final GodotInputHandler inputHandler; +	private final GestureDetector detector;  	private final GodotRenderer godotRenderer;  	public GodotView(Godot activity, XRMode xrMode, boolean p_use_gl3, boolean p_use_32_bits, boolean p_use_debug_opengl) { @@ -78,6 +81,7 @@ public class GodotView extends GLSurfaceView {  		this.activity = activity;  		this.inputHandler = new GodotInputHandler(this); +		this.detector = new GestureDetector(activity, new GodotGestureHandler(this));  		this.godotRenderer = new GodotRenderer();  		init(xrMode, false, 16, 0);  	} @@ -90,6 +94,7 @@ public class GodotView extends GLSurfaceView {  	@Override  	public boolean onTouchEvent(MotionEvent event) {  		super.onTouchEvent(event); +		this.detector.onTouchEvent(event);  		return activity.gotTouchEvent(event);  	} diff --git a/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java new file mode 100644 index 0000000000..1a38a9c3d2 --- /dev/null +++ b/platform/android/java/lib/src/org/godotengine/godot/input/GodotGestureHandler.java @@ -0,0 +1,106 @@ +/*************************************************************************/ +/*  GodotGestureHandler.java                                             */ +/*************************************************************************/ +/*                       This file is part of:                           */ +/*                           GODOT ENGINE                                */ +/*                      https://godotengine.org                          */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ +/*                                                                       */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the       */ +/* "Software"), to deal in the Software without restriction, including   */ +/* without limitation the rights to use, copy, modify, merge, publish,   */ +/* distribute, sublicense, and/or sell copies of the Software, and to    */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions:                                             */ +/*                                                                       */ +/* The above copyright notice and this permission notice shall be        */ +/* included in all copies or substantial portions of the Software.       */ +/*                                                                       */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ +/*************************************************************************/ + +package org.godotengine.godot.input; + +import android.util.Log; +import android.view.GestureDetector; +import android.view.MotionEvent; +import org.godotengine.godot.GodotLib; +import org.godotengine.godot.GodotView; + +/** + * Handles gesture input related events for the {@link GodotView} view. + * https://developer.android.com/reference/android/view/GestureDetector.SimpleOnGestureListener + */ +public class GodotGestureHandler extends GestureDetector.SimpleOnGestureListener { + +	private final GodotView godotView; + +	public GodotGestureHandler(GodotView godotView) { +		this.godotView = godotView; +	} + +	private void queueEvent(Runnable task) { +		godotView.queueEvent(task); +	} + +	@Override +	public boolean onDown(MotionEvent event) { +		super.onDown(event); +		//Log.i("GodotGesture", "onDown"); +		return true; +	} + +	@Override +	public boolean onSingleTapConfirmed(MotionEvent event) { +		super.onSingleTapConfirmed(event); +		return true; +	} + +	@Override +	public void onLongPress(MotionEvent event) { +		//Log.i("GodotGesture", "onLongPress"); +	} + +	@Override +	public boolean onDoubleTap(MotionEvent event) { +		//Log.i("GodotGesture", "onDoubleTap"); +		final int x = Math.round(event.getX()); +		final int y = Math.round(event.getY()); +		queueEvent(new Runnable() { +			@Override +			public void run() { +				GodotLib.doubletap(x, y); +			} +		}); +		return true; +	} + +	@Override +	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { +		//Log.i("GodotGesture", "onScroll"); +		final int x = Math.round(distanceX); +		final int y = Math.round(distanceY); +		queueEvent(new Runnable() { +			@Override +			public void run() { +				GodotLib.scroll(x, y); +			} +		}); +		return true; +	} + +	@Override +	public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { +		//Log.i("GodotGesture", "onFling"); +		return true; +	} +} diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 0a32f4423b..858ff89cbc 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -835,6 +835,20 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jo  	os_android->process_hover(p_type, Point2(p_x, p_y));  } +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y) { +	if (step == 0) +		return; + +	os_android->process_double_tap(Point2(p_x, p_y)); +} + +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y) { +	if (step == 0) +		return; + +	os_android->process_scroll(Point2(p_x, p_y)); +} +  /*   * Android Key codes.   */ diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index 8c18c52d2b..71d4547f65 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -46,6 +46,8 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env, job  JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_back(JNIEnv *env, jobject obj);  JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_touch(JNIEnv *env, jobject obj, jint ev, jint pointer, jint count, jintArray positions);  JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hover(JNIEnv *env, jobject obj, jint p_type, jint p_x, jint p_y); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_doubletap(JNIEnv *env, jobject obj, jint p_x, jint p_y); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_scroll(JNIEnv *env, jobject obj, jint p_x, jint p_y);  JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_key(JNIEnv *env, jobject obj, jint p_scancode, jint p_unicode_char, jboolean p_pressed);  JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joybutton(JNIEnv *env, jobject obj, jint p_device, jint p_button, jboolean p_pressed);  JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_joyaxis(JNIEnv *env, jobject obj, jint p_device, jint p_axis, jfloat p_value); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 4c560273e8..bbea5e3699 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -502,6 +502,26 @@ void OS_Android::process_hover(int p_type, Point2 p_pos) {  	}  } +void OS_Android::process_double_tap(Point2 p_pos) { +	Ref<InputEventMouseButton> ev; +	ev.instance(); +	ev->set_position(p_pos); +	ev->set_global_position(p_pos); +	ev->set_pressed(true); +	ev->set_doubleclick(true); +	ev->set_button_index(1); +	input->parse_input_event(ev); +} + +void OS_Android::process_scroll(Point2 p_pos) { +	Ref<InputEventPanGesture> ev; +	ev.instance(); +	ev->set_position(p_pos); +	ev->set_delta(p_pos - scroll_prev_pos); +	input->parse_input_event(ev); +	scroll_prev_pos = p_pos; +} +  void OS_Android::process_accelerometer(const Vector3 &p_accelerometer) {  	input->set_accelerometer(p_accelerometer); diff --git a/platform/android/os_android.h b/platform/android/os_android.h index 5ac50ddef2..1cf64a2e84 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -70,6 +70,7 @@ public:  private:  	Vector<TouchPos> touch;  	Point2 hover_prev_pos; // needed to calculate the relative position on hover events +	Point2 scroll_prev_pos; // needed to calculate the relative position on scroll events  	bool use_gl2;  	bool use_apk_expansion; @@ -187,6 +188,8 @@ public:  	void process_gyroscope(const Vector3 &p_gyroscope);  	void process_touch(int p_what, int p_pointer, const Vector<TouchPos> &p_points);  	void process_hover(int p_type, Point2 p_pos); +	void process_double_tap(Point2 p_pos); +	void process_scroll(Point2 p_pos);  	void process_joy_event(JoypadEvent p_event);  	void process_event(Ref<InputEvent> p_event);  	void init_video_mode(int p_video_width, int p_video_height); diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py index 2a3e165069..dd72294816 100644 --- a/platform/haiku/detect.py +++ b/platform/haiku/detect.py @@ -95,7 +95,7 @@ def configure(env):      if not env['builtin_enet']:          env.ParseConfig('pkg-config libenet --cflags --libs') -    if not env['builtin_squish'] and env['tools']: +    if not env['builtin_squish']:          env.ParseConfig('pkg-config libsquish --cflags --libs')      if not env['builtin_zstd']: diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index c80370847d..b606d570c2 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -206,8 +206,8 @@ static const LoadingScreenInfo loading_screen_infos[] = {  void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) { -	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); -	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); +	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); +	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));  	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "")); @@ -848,9 +848,9 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p  	ERR_FAIL_COND_V_MSG(team_id.length() == 0, ERR_CANT_OPEN, "App Store Team ID not specified - cannot configure the project.");  	if (p_debug) -		src_pkg_name = p_preset->get("custom_package/debug"); +		src_pkg_name = p_preset->get("custom_template/debug");  	else -		src_pkg_name = p_preset->get("custom_package/release"); +		src_pkg_name = p_preset->get("custom_template/release");  	if (src_pkg_name == "") {  		String err; @@ -1156,25 +1156,30 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p  bool EditorExportPlatformIOS::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {  	String err; -	r_missing_templates = find_export_template("iphone.zip") == String(); +	bool valid = false; -	if (p_preset->get("custom_package/debug") != "") { -		if (FileAccess::exists(p_preset->get("custom_package/debug"))) { -			r_missing_templates = false; -		} else { +	// Look for export templates (first official, and if defined custom templates). + +	bool dvalid = exists_export_template("iphone.zip", &err); +	bool rvalid = dvalid; // Both in the same ZIP. + +	if (p_preset->get("custom_template/debug") != "") { +		dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); +		if (!dvalid) {  			err += TTR("Custom debug template not found.") + "\n";  		}  	} - -	if (p_preset->get("custom_package/release") != "") { -		if (FileAccess::exists(p_preset->get("custom_package/release"))) { -			r_missing_templates = false; -		} else { +	if (p_preset->get("custom_template/release") != "") { +		rvalid = FileAccess::exists(p_preset->get("custom_template/release")); +		if (!rvalid) {  			err += TTR("Custom release template not found.") + "\n";  		}  	} -	bool valid = !r_missing_templates; +	valid = dvalid || rvalid; +	r_missing_templates = !valid; + +	// Validate the rest of the configuration.  	String team_id = p_preset->get("application/app_store_team_id");  	if (team_id.length() == 0) { diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index bbdf6a1f57..9b93d4f140 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -87,16 +87,22 @@ public:  		String filepath = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp_js_export");  		String basereq = "/tmp_js_export"; +		String ctype = "";  		if (req[1] == basereq + ".html") {  			filepath += ".html"; +			ctype = "text/html";  		} else if (req[1] == basereq + ".js") {  			filepath += ".js"; +			ctype = "application/javascript";  		} else if (req[1] == basereq + ".pck") {  			filepath += ".pck"; +			ctype = "application/octet-stream";  		} else if (req[1] == basereq + ".png") {  			filepath += ".png"; +			ctype = "image/png";  		} else if (req[1] == basereq + ".wasm") {  			filepath += ".wasm"; +			ctype = "application/wasm";  		} else {  			String s = "HTTP/1.1 404 Not Found\r\n";  			s += "Connection: Close\r\n"; @@ -109,10 +115,14 @@ public:  		ERR_FAIL_COND(!f);  		String s = "HTTP/1.1 200 OK\r\n";  		s += "Connection: Close\r\n"; +		s += "Content-Type: " + ctype + "\r\n";  		s += "\r\n";  		CharString cs = s.utf8();  		Error err = connection->put_data((const uint8_t *)cs.get_data(), cs.size() - 1); -		ERR_FAIL_COND(err != OK); +		if (err != OK) { +			memdelete(f); +			ERR_FAIL(); +		}  		while (true) {  			uint8_t bytes[4096]; @@ -121,8 +131,12 @@ public:  				break;  			}  			err = connection->put_data(bytes, read); -			ERR_FAIL_COND(err != OK); +			if (err != OK) { +				memdelete(f); +				ERR_FAIL(); +			}  		} +		memdelete(f);  	}  	void poll() { @@ -288,32 +302,32 @@ Ref<Texture> EditorExportPlatformJavaScript::get_logo() const {  bool EditorExportPlatformJavaScript::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { -	bool valid = false;  	String err; +	bool valid = false; -	if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE) != "") -		valid = true; -	else if (find_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG) != "") -		valid = true; +	// Look for export templates (first official, and if defined custom templates). + +	bool dvalid = exists_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_DEBUG, &err); +	bool rvalid = exists_export_template(EXPORT_TEMPLATE_WEBASSEMBLY_RELEASE, &err);  	if (p_preset->get("custom_template/debug") != "") { -		if (FileAccess::exists(p_preset->get("custom_template/debug"))) { -			valid = true; -		} else { +		dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); +		if (!dvalid) {  			err += TTR("Custom debug template not found.") + "\n";  		}  	} -  	if (p_preset->get("custom_template/release") != "") { -		if (FileAccess::exists(p_preset->get("custom_template/release"))) { -			valid = true; -		} else { +		rvalid = FileAccess::exists(p_preset->get("custom_template/release")); +		if (!rvalid) {  			err += TTR("Custom release template not found.") + "\n";  		}  	} +	valid = dvalid || rvalid;  	r_missing_templates = !valid; +	// Validate the rest of the configuration. +  	if (p_preset->get("vram_texture_compression/for_mobile")) {  		String etc_error = test_etc2();  		if (etc_error != String()) { diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index dd98a98996..cf38664022 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -118,8 +118,8 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset>  void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) { -	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); -	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); +	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), "")); +	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));  	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));  	r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine")); @@ -459,9 +459,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  	EditorProgress ep("export", "Exporting for OSX", 3, true);  	if (p_debug) -		src_pkg_name = p_preset->get("custom_package/debug"); +		src_pkg_name = p_preset->get("custom_template/debug");  	else -		src_pkg_name = p_preset->get("custom_package/release"); +		src_pkg_name = p_preset->get("custom_template/release");  	if (src_pkg_name == "") {  		String err; @@ -502,6 +502,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  	else  		pkg_name = "Unnamed"; +	String pkg_name_safe = OS::get_singleton()->get_safe_dir_name(pkg_name); +  	Error err = OK;  	String tmp_app_path_name = "";  	zlib_filefunc_def io2 = io; @@ -509,12 +511,13 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  	io2.opaque = &dst_f;  	zipFile dst_pkg_zip = NULL; +	DirAccess *tmp_app_path = NULL;  	String export_format = use_dmg() && p_path.ends_with("dmg") ? "dmg" : "zip";  	if (export_format == "dmg") {  		// We're on OSX so we can export to DMG, but first we create our application bundle  		tmp_app_path_name = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".app");  		print_line("Exporting to " + tmp_app_path_name); -		DirAccess *tmp_app_path = DirAccess::create_for_path(tmp_app_path_name); +		tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);  		if (!tmp_app_path) {  			err = ERR_CANT_CREATE;  		} @@ -611,25 +614,45 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  		}  		if (data.size() > 0) { + +			if (file.find("/data.mono.osx.64.release_debug/") != -1) { +				if (!p_debug) { +					ret = unzGoToNextFile(src_pkg_zip); +					continue; //skip +				} +				file = file.replace("/data.mono.osx.64.release_debug/", "/data_" + pkg_name_safe + "/"); +			} +			if (file.find("/data.mono.osx.64.release/") != -1) { +				if (p_debug) { +					ret = unzGoToNextFile(src_pkg_zip); +					continue; //skip +				} +				file = file.replace("/data.mono.osx.64.release/", "/data_" + pkg_name_safe + "/"); +			} +  			print_line("ADDING: " + file + " size: " + itos(data.size()));  			total_size += data.size();  			if (export_format == "dmg") {  				// write it into our application bundle  				file = tmp_app_path_name.plus_file(file); - -				// write the file, need to add chmod -				FileAccess *f = FileAccess::open(file, FileAccess::WRITE); -				if (f) { -					f->store_buffer(data.ptr(), data.size()); -					f->close(); -					if (is_execute) { -						// Chmod with 0755 if the file is executable -						FileAccess::set_unix_permissions(file, 0755); +				if (err == OK) { +					err = tmp_app_path->make_dir_recursive(file.get_base_dir()); +				} +				if (err == OK) { +					// write the file, need to add chmod +					FileAccess *f = FileAccess::open(file, FileAccess::WRITE); +					if (f) { +						f->store_buffer(data.ptr(), data.size()); +						f->close(); +						if (is_execute) { +							// Chmod with 0755 if the file is executable +							FileAccess::set_unix_permissions(file, 0755); +						} +						memdelete(f); +					} else { +						err = ERR_CANT_CREATE;  					} -					memdelete(f); -				} else { -					err = ERR_CANT_CREATE;  				}  			} else {  				// add it to our zip file @@ -796,33 +819,32 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p  bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { -	bool valid = false;  	String err; +	bool valid = false; -	if (exists_export_template("osx.zip", &err)) { -		valid = true; -	} +	// Look for export templates (first official, and if defined custom templates). -	if (p_preset->get("custom_package/debug") != "") { -		if (FileAccess::exists(p_preset->get("custom_package/debug"))) { -			valid = true; -		} else { +	bool dvalid = exists_export_template("osx.zip", &err); +	bool rvalid = dvalid; // Both in the same ZIP. + +	if (p_preset->get("custom_template/debug") != "") { +		dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); +		if (!dvalid) {  			err += TTR("Custom debug template not found.") + "\n";  		}  	} - -	if (p_preset->get("custom_package/release") != "") { -		if (FileAccess::exists(p_preset->get("custom_package/release"))) { -			valid = true; -		} else { +	if (p_preset->get("custom_template/release") != "") { +		rvalid = FileAccess::exists(p_preset->get("custom_template/release")); +		if (!rvalid) {  			err += TTR("Custom release template not found.") + "\n";  		}  	} +	valid = dvalid || rvalid; +	r_missing_templates = !valid; +  	if (!err.empty())  		r_error = err; - -	r_missing_templates = !valid;  	return valid;  } diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm index 73fd4632ab..e6f8cbecf1 100644 --- a/platform/osx/godot_main_osx.mm +++ b/platform/osx/godot_main_osx.mm @@ -45,35 +45,6 @@ int main(int argc, char **argv) {  		printf("%i: %s\n", i, argv[i]);  	}; -	if (argc >= 1 && argv[0][0] == '/') { -		//potentially launched from finder -		int len = strlen(argv[0]); -		while (len--) { -			if (argv[0][len] == '/') break; -		} -		if (len >= 0) { -			char *path = (char *)malloc(len + 1); -			memcpy(path, argv[0], len); -			path[len] = 0; - -			char *pathinfo = (char *)malloc(strlen(path) + strlen("/../Info.plist") + 1); -			//in real code you would check for errors in malloc here -			strcpy(pathinfo, path); -			strcat(pathinfo, "/../Info.plist"); - -			FILE *f = fopen(pathinfo, "rb"); -			if (f) { -				//running from app bundle, as Info.plist was found -				fclose(f); -				chdir(path); -				chdir("../Resources"); //data.pck, or just the files are here -			} - -			free(path); -			free(pathinfo); -		} -	} -  #ifdef DEBUG_ENABLED  	// lets report the path we made current after all that  	char cwd[4096]; diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 44c5412a39..190dbcf662 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -76,8 +76,6 @@ public:  	List<String> args;  	MainLoop *main_loop; -	IP_Unix *ip_unix; -  #ifdef COREAUDIO_ENABLED  	AudioDriverCoreAudio audio_driver;  #endif @@ -223,6 +221,7 @@ public:  	virtual String get_config_path() const;  	virtual String get_data_path() const;  	virtual String get_cache_path() const; +	virtual String get_bundle_resource_dir() const;  	virtual String get_godot_dir_name() const;  	virtual String get_system_dir(SystemDir p_dir) const; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 95c103bd28..6a214b8669 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -479,7 +479,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };  }  - (NSRange)markedRange { -	return (markedText.length > 0) ? NSMakeRange(0, markedText.length - 1) : kEmptyRange; +	return NSMakeRange(0, markedText.length);  }  - (NSRange)selectedRange { @@ -492,6 +492,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };  	} else {  		[markedText initWithString:aString];  	} +	if (markedText.length == 0) { +		[self unmarkText]; +		return; +	}  	if (OS_OSX::singleton->im_active) {  		imeInputEventInProgress = true;  		OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]); @@ -2111,6 +2115,19 @@ String OS_OSX::get_cache_path() const {  	}  } +String OS_OSX::get_bundle_resource_dir() const { + +	NSBundle *main = [NSBundle mainBundle]; +	NSString *resourcePath = [main resourcePath]; + +	char *utfs = strdup([resourcePath UTF8String]); +	String ret; +	ret.parse_utf8(utfs); +	free(utfs); + +	return ret; +} +  // Get properly capitalized engine name for system paths  String OS_OSX::get_godot_dir_name() const { diff --git a/platform/server/detect.py b/platform/server/detect.py index b6028c20e3..d82df77957 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -162,7 +162,7 @@ def configure(env):      if not env['builtin_enet']:          env.ParseConfig('pkg-config libenet --cflags --libs') -    if not env['builtin_squish'] and env['tools']: +    if not env['builtin_squish']:          env.ParseConfig('pkg-config libsquish --cflags --libs')      if not env['builtin_zstd']: diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 0aca8049f2..46ca9cb6d1 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -58,7 +58,6 @@ class OS_Server : public OS_Unix {  	bool grab;  	virtual void delete_main_loop(); -	IP_Unix *ip_unix;  	bool force_quit; diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp index 3fa5512819..57fb9004b8 100644 --- a/platform/uwp/export/export.cpp +++ b/platform/uwp/export/export.cpp @@ -1090,15 +1090,14 @@ public:  	}  	virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { +  		String err; -		bool valid = true; -		Platform arch = (Platform)(int)(p_preset->get("architecture/target")); +		bool valid = false; -		String custom_debug_binary = p_preset->get("custom_template/debug"); -		String custom_release_binary = p_preset->get("custom_template/release"); +		// Look for export templates (first official, and if defined custom templates). +		Platform arch = (Platform)(int)(p_preset->get("architecture/target"));  		String platform_infix; -  		switch (arch) {  			case EditorExportPlatformUWP::ARM: {  				platform_infix = "arm"; @@ -1111,38 +1110,26 @@ public:  			} break;  		} -		if (!exists_export_template("uwp_" + platform_infix + "_debug.zip", &err) || !exists_export_template("uwp_" + platform_infix + "_release.zip", &err)) { -			valid = false; -			r_missing_templates = true; -		} +		bool dvalid = exists_export_template("uwp_" + platform_infix + "_debug.zip", &err); +		bool rvalid = exists_export_template("uwp_" + platform_infix + "_release.zip", &err); -		if (!valid && custom_debug_binary == "" && custom_release_binary == "") { -			if (!err.empty()) { -				r_error = err; +		if (p_preset->get("custom_template/debug") != "") { +			dvalid = FileAccess::exists(p_preset->get("custom_template/debug")); +			if (!dvalid) { +				err += TTR("Custom debug template not found.") + "\n";  			} -			return valid;  		} - -		bool dvalid = true; -		bool rvalid = true; - -		if (!FileAccess::exists(custom_debug_binary)) { -			dvalid = false; -			err += TTR("Custom debug template not found.") + "\n"; -		} - -		if (!FileAccess::exists(custom_release_binary)) { -			rvalid = false; -			err += TTR("Custom release template not found.") + "\n"; +		if (p_preset->get("custom_template/release") != "") { +			rvalid = FileAccess::exists(p_preset->get("custom_template/release")); +			if (!rvalid) { +				err += TTR("Custom release template not found.") + "\n"; +			}  		} -		if (dvalid || rvalid) -			valid = true; +		valid = dvalid || rvalid; +		r_missing_templates = !valid; -		if (!valid) { -			r_error = err; -			return valid; -		} +		// Validate the rest of the configuration.  		if (!_valid_resource_name(p_preset->get("package/short_name"))) {  			valid = false; diff --git a/platform/windows/context_gl_windows.cpp b/platform/windows/context_gl_windows.cpp index 21d954a736..ad62e3a306 100644 --- a/platform/windows/context_gl_windows.cpp +++ b/platform/windows/context_gl_windows.cpp @@ -43,6 +43,11 @@  #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126  #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#if defined(__GNUC__) +// Workaround GCC warning from -Wcast-function-type. +#define wglGetProcAddress (void *)wglGetProcAddress +#endif +  typedef HGLRC(APIENTRY *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *);  void ContextGL_Windows::release_current() { @@ -89,7 +94,7 @@ void ContextGL_Windows::swap_buffers() {  	if (use_vsync) {  		bool vsync_via_compositor_now = should_vsync_via_compositor(); -		if (vsync_via_compositor_now) { +		if (vsync_via_compositor_now && wglGetSwapIntervalEXT() == 0) {  			DwmFlush();  		} @@ -205,6 +210,7 @@ Error ContextGL_Windows::initialize() {  	}  	wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); +	wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)wglGetProcAddress("wglGetSwapIntervalEXT");  	//glWrapperInit(wrapper_get_proc_address);  	return OK; diff --git a/platform/windows/context_gl_windows.h b/platform/windows/context_gl_windows.h index 0c6a6d1814..280c5a1e3c 100644 --- a/platform/windows/context_gl_windows.h +++ b/platform/windows/context_gl_windows.h @@ -41,6 +41,7 @@  #include <windows.h>  typedef bool(APIENTRY *PFNWGLSWAPINTERVALEXTPROC)(int interval); +typedef int(APIENTRY *PFNWGLGETSWAPINTERVALEXTPROC)(void);  class ContextGL_Windows { @@ -53,6 +54,7 @@ class ContextGL_Windows {  	bool vsync_via_compositor;  	PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; +	PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;  	static bool should_vsync_via_compositor(); diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index c82a90bf7d..49432435b9 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -37,6 +37,11 @@  #define __builtin_bswap32 _byteswap_ulong  #endif +#if defined(__GNUC__) +// Workaround GCC warning from -Wcast-function-type. +#define GetProcAddress (void *)GetProcAddress +#endif +  DWORD WINAPI _xinput_get_state(DWORD dwUserIndex, XINPUT_STATE *pState) {  	return ERROR_DEVICE_NOT_CONNECTED;  } diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 3868d0bc63..a6977a7a86 100755 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -74,6 +74,11 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;  #define WM_POINTERUPDATE 0x0245  #endif +#if defined(__GNUC__) +// Workaround GCC warning from -Wcast-function-type. +#define GetProcAddress (void *)GetProcAddress +#endif +  typedef struct {  	int count;  	int screen; diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp index 3a91c62546..19c8f71d0e 100644 --- a/platform/x11/crash_handler_x11.cpp +++ b/platform/x11/crash_handler_x11.cpp @@ -107,7 +107,7 @@ static void handle_crash(int sig) {  				output.erase(output.length() - 1, 1);  			} -			fprintf(stderr, "[%ld] %s (%ls)\n", i, fname, output.c_str()); +			fprintf(stderr, "[%ld] %s (%ls)\n", (long int)i, fname, output.c_str());  		}  		free(strings); diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 5c7be34730..957779ee83 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -232,7 +232,7 @@ def configure(env):      if not env['builtin_enet']:          env.ParseConfig('pkg-config libenet --cflags --libs') -    if not env['builtin_squish'] and env['tools']: +    if not env['builtin_squish']:          env.ParseConfig('pkg-config libsquish --cflags --libs')      if not env['builtin_zstd']:  |