[Export] Add readable descriptions and validation warnings to the export options.

This commit is contained in:
bruvzg 2023-03-09 10:41:52 +02:00
parent 1b4b8934e0
commit 0088981c40
No known key found for this signature in database
GPG key ID: 7960FCF39844EC38
49 changed files with 2215 additions and 391 deletions

View file

@ -1703,16 +1703,109 @@ void EditorExportPlatformAndroid::get_preset_features(const Ref<EditorExportPres
}
}
void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_options) {
String EditorExportPlatformAndroid::get_export_option_warning(const EditorExportPreset *p_preset, const StringName &p_name) const {
if (p_preset) {
if (p_name == ("apk_expansion/public_key")) {
bool apk_expansion = p_preset->get("apk_expansion/enable");
String apk_expansion_pkey = p_preset->get("apk_expansion/public_key");
if (apk_expansion && apk_expansion_pkey.is_empty()) {
return TTR("Invalid public key for APK expansion.");
}
} else if (p_name == "package/unique_name") {
String pn = p_preset->get("package/unique_name");
String pn_err;
if (!is_package_name_valid(pn, &pn_err)) {
return TTR("Invalid package name:") + " " + pn_err;
}
} else if (p_name == "gradle_build/use_gradle_build") {
bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
String enabled_plugins_names = PluginConfigAndroid::get_plugins_names(get_enabled_plugins(Ref<EditorExportPreset>(p_preset)));
if (!enabled_plugins_names.is_empty() && !gradle_build_enabled) {
return TTR("\"Use Gradle Build\" must be enabled to use the plugins.");
}
} else if (p_name == "xr_features/xr_mode") {
bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
int xr_mode_index = p_preset->get("xr_features/xr_mode");
if (xr_mode_index == XR_MODE_OPENXR && !gradle_build_enabled) {
return TTR("OpenXR requires \"Use Gradle Build\" to be enabled");
}
} else if (p_name == "xr_features/hand_tracking") {
int xr_mode_index = p_preset->get("xr_features/xr_mode");
int hand_tracking = p_preset->get("xr_features/hand_tracking");
if (xr_mode_index != XR_MODE_OPENXR) {
if (hand_tracking > XR_HAND_TRACKING_NONE) {
return TTR("\"Hand Tracking\" is only valid when \"XR Mode\" is \"OpenXR\".");
}
}
} else if (p_name == "xr_features/passthrough") {
int xr_mode_index = p_preset->get("xr_features/xr_mode");
int passthrough_mode = p_preset->get("xr_features/passthrough");
if (xr_mode_index != XR_MODE_OPENXR) {
if (passthrough_mode > XR_PASSTHROUGH_NONE) {
return TTR("\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\".");
}
}
} else if (p_name == "gradle_build/export_format") {
bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
if (int(p_preset->get("gradle_build/export_format")) == EXPORT_FORMAT_AAB && !gradle_build_enabled) {
return TTR("\"Export AAB\" is only valid when \"Use Gradle Build\" is enabled.");
}
} else if (p_name == "gradle_build/min_sdk") {
String min_sdk_str = p_preset->get("gradle_build/min_sdk");
int min_sdk_int = VULKAN_MIN_SDK_VERSION;
bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
if (!gradle_build_enabled) {
return TTR("\"Min SDK\" can only be overridden when \"Use Gradle Build\" is enabled.");
}
if (!min_sdk_str.is_valid_int()) {
return vformat(TTR("\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."), min_sdk_str);
} else {
min_sdk_int = min_sdk_str.to_int();
if (min_sdk_int < OPENGL_MIN_SDK_VERSION) {
return vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), OPENGL_MIN_SDK_VERSION);
}
}
}
} else if (p_name == "gradle_build/target_sdk") {
String target_sdk_str = p_preset->get("gradle_build/target_sdk");
int target_sdk_int = DEFAULT_TARGET_SDK_VERSION;
String min_sdk_str = p_preset->get("gradle_build/min_sdk");
int min_sdk_int = VULKAN_MIN_SDK_VERSION;
if (min_sdk_str.is_valid_int()) {
min_sdk_int = min_sdk_str.to_int();
}
bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
if (!target_sdk_str.is_empty()) { // Empty means no override, nothing to do.
if (!gradle_build_enabled) {
return TTR("\"Target SDK\" can only be overridden when \"Use Gradle Build\" is enabled.");
}
if (!target_sdk_str.is_valid_int()) {
return vformat(TTR("\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."), target_sdk_str);
} else {
target_sdk_int = target_sdk_str.to_int();
if (target_sdk_int < min_sdk_int) {
return TTR("\"Target SDK\" version must be greater or equal to \"Min SDK\" version.");
}
}
}
}
}
return String();
}
void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_options) const {
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, "gradle_build/use_gradle_build"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "gradle_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "gradle_build/use_gradle_build"), false, false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "gradle_build/export_format", PROPERTY_HINT_ENUM, "Export APK,Export AAB"), EXPORT_FORMAT_APK, false, true));
// Using String instead of int to default to an empty string (no override) with placeholder for instructions (see GH-62465).
// This implies doing validation that the string is a proper int.
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/min_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", VULKAN_MIN_SDK_VERSION)), "", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "gradle_build/target_sdk", PROPERTY_HINT_PLACEHOLDER_TEXT, vformat("%d (default)", DEFAULT_TARGET_SDK_VERSION)), "", false, true));
Vector<PluginConfigAndroid> plugins_configs = get_plugins();
for (int i = 0; i < plugins_configs.size(); i++) {
@ -1742,7 +1835,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
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"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/unique_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "ext.domain.name"), "org.godotengine.$genname", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "package/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name [default if blank]"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "package/signed"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "package/app_category", PROPERTY_HINT_ENUM, "Accessibility,Audio,Game,Image,Maps,News,Productivity,Social,Video"), APP_CATEGORY_GAME));
@ -1755,10 +1848,10 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "graphics/opengl_debug"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,OpenXR"), XR_MODE_REGULAR));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), XR_HAND_TRACKING_NONE));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,OpenXR"), XR_MODE_REGULAR, false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking", PROPERTY_HINT_ENUM, "None,Optional,Required"), XR_HAND_TRACKING_NONE, false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/hand_tracking_frequency", PROPERTY_HINT_ENUM, "Low,High"), XR_HAND_TRACKING_FREQUENCY_LOW));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/passthrough", PROPERTY_HINT_ENUM, "None,Optional,Required"), XR_PASSTHROUGH_NONE));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/passthrough", PROPERTY_HINT_ENUM, "None,Optional,Required"), XR_PASSTHROUGH_NONE, false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true));
@ -1770,9 +1863,9 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "command_line/extra_args"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "apk_expansion/enable"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "apk_expansion/enable"), false, false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "apk_expansion/SALT"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "apk_expansion/public_key", PROPERTY_HINT_MULTILINE_TEXT), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "apk_expansion/public_key", PROPERTY_HINT_MULTILINE_TEXT), "", false, true));
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "permissions/custom_permissions"), PackedStringArray()));
@ -2272,111 +2365,39 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const {
String err;
bool valid = true;
const bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build");
// Validate the project configuration.
bool apk_expansion = p_preset->get("apk_expansion/enable");
if (apk_expansion) {
String apk_expansion_pkey = p_preset->get("apk_expansion/public_key");
if (apk_expansion_pkey.is_empty()) {
valid = false;
err += TTR("Invalid public key for APK expansion.") + "\n";
List<ExportOption> options;
get_export_options(&options);
for (const EditorExportPlatform::ExportOption &E : options) {
if (get_export_option_visibility(p_preset.ptr(), E.option.name)) {
String warn = get_export_option_warning(p_preset.ptr(), E.option.name);
if (!warn.is_empty()) {
err += warn + "\n";
if (E.required) {
valid = false;
}
}
}
}
String pn = p_preset->get("package/unique_name");
String pn_err;
if (!is_package_name_valid(pn, &pn_err)) {
valid = false;
err += TTR("Invalid package name:") + " " + pn_err + "\n";
}
String etc_error = test_etc2();
if (!etc_error.is_empty()) {
valid = false;
err += etc_error;
}
// Ensure that `Use Gradle Build` is enabled if a plugin is selected.
String enabled_plugins_names = PluginConfigAndroid::get_plugins_names(get_enabled_plugins(p_preset));
if (!enabled_plugins_names.is_empty() && !gradle_build_enabled) {
valid = false;
err += TTR("\"Use Gradle Build\" must be enabled to use the plugins.");
err += "\n";
}
// Validate the Xr features are properly populated
int xr_mode_index = p_preset->get("xr_features/xr_mode");
int hand_tracking = p_preset->get("xr_features/hand_tracking");
int passthrough_mode = p_preset->get("xr_features/passthrough");
if (xr_mode_index == XR_MODE_OPENXR && !gradle_build_enabled) {
valid = false;
err += TTR("OpenXR requires \"Use Gradle Build\" to be enabled");
err += "\n";
}
if (xr_mode_index != XR_MODE_OPENXR) {
if (hand_tracking > XR_HAND_TRACKING_NONE) {
valid = false;
err += TTR("\"Hand Tracking\" is only valid when \"XR Mode\" is \"OpenXR\".");
err += "\n";
}
if (passthrough_mode > XR_PASSTHROUGH_NONE) {
valid = false;
err += TTR("\"Passthrough\" is only valid when \"XR Mode\" is \"OpenXR\".");
err += "\n";
}
}
if (int(p_preset->get("gradle_build/export_format")) == EXPORT_FORMAT_AAB &&
!gradle_build_enabled) {
valid = false;
err += TTR("\"Export AAB\" is only valid when \"Use Gradle Build\" is enabled.");
err += "\n";
}
// Check the min sdk version.
String min_sdk_str = p_preset->get("gradle_build/min_sdk");
int min_sdk_int = VULKAN_MIN_SDK_VERSION;
if (!min_sdk_str.is_empty()) { // Empty means no override, nothing to do.
if (!gradle_build_enabled) {
valid = false;
err += TTR("\"Min SDK\" can only be overridden when \"Use Gradle Build\" is enabled.");
err += "\n";
}
if (!min_sdk_str.is_valid_int()) {
valid = false;
err += vformat(TTR("\"Min SDK\" should be a valid integer, but got \"%s\" which is invalid."), min_sdk_str);
err += "\n";
} else {
if (min_sdk_str.is_valid_int()) {
min_sdk_int = min_sdk_str.to_int();
if (min_sdk_int < OPENGL_MIN_SDK_VERSION) {
valid = false;
err += vformat(TTR("\"Min SDK\" cannot be lower than %d, which is the version needed by the Godot library."), OPENGL_MIN_SDK_VERSION);
err += "\n";
}
}
}
// Check the target sdk version.
String target_sdk_str = p_preset->get("gradle_build/target_sdk");
int target_sdk_int = DEFAULT_TARGET_SDK_VERSION;
if (!target_sdk_str.is_empty()) { // Empty means no override, nothing to do.
if (!gradle_build_enabled) {
valid = false;
err += TTR("\"Target SDK\" can only be overridden when \"Use Gradle Build\" is enabled.");
err += "\n";
}
if (!target_sdk_str.is_valid_int()) {
valid = false;
err += vformat(TTR("\"Target SDK\" should be a valid integer, but got \"%s\" which is invalid."), target_sdk_str);
err += "\n";
} else {
if (target_sdk_str.is_valid_int()) {
target_sdk_int = target_sdk_str.to_int();
if (target_sdk_int > DEFAULT_TARGET_SDK_VERSION) {
// Warning only, so don't override `valid`.
@ -2386,18 +2407,13 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
}
}
if (target_sdk_int < min_sdk_int) {
valid = false;
err += TTR("\"Target SDK\" version must be greater or equal to \"Min SDK\" version.");
err += "\n";
}
String current_renderer = GLOBAL_GET("rendering/renderer/rendering_method.mobile");
if (current_renderer == "forward_plus") {
// Warning only, so don't override `valid`.
err += vformat(TTR("The \"%s\" renderer is designed for Desktop devices, and is not suitable for Android devices."), current_renderer);
err += "\n";
}
if (_uses_vulkan() && min_sdk_int < VULKAN_MIN_SDK_VERSION) {
// Warning only, so don't override `valid`.
err += vformat(TTR("\"Min SDK\" should be greater or equal to %d for the \"%s\" renderer."), VULKAN_MIN_SDK_VERSION, current_renderer);
@ -3266,23 +3282,25 @@ void EditorExportPlatformAndroid::resolve_platform_feature_priorities(const Ref<
}
EditorExportPlatformAndroid::EditorExportPlatformAndroid() {
if (EditorNode::get_singleton()) {
#ifdef MODULE_SVG_ENABLED
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
Ref<Image> img = memnew(Image);
const bool upsample = !Math::is_equal_approx(Math::round(EDSCALE), EDSCALE);
ImageLoaderSVG img_loader;
img_loader.create_image_from_string(img, _android_logo_svg, EDSCALE, upsample, false);
logo = ImageTexture::create_from_image(img);
ImageLoaderSVG img_loader;
img_loader.create_image_from_string(img, _android_logo_svg, EDSCALE, upsample, false);
logo = ImageTexture::create_from_image(img);
img_loader.create_image_from_string(img, _android_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
img_loader.create_image_from_string(img, _android_run_icon_svg, EDSCALE, upsample, false);
run_icon = ImageTexture::create_from_image(img);
#endif
devices_changed.set();
plugins_changed.set();
devices_changed.set();
plugins_changed.set();
#ifndef ANDROID_ENABLED
check_for_changes_thread.start(_check_for_changes_poll_thread, this);
check_for_changes_thread.start(_check_for_changes_poll_thread, this);
#endif
}
}
EditorExportPlatformAndroid::~EditorExportPlatformAndroid() {