Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Add readable export errors. #61624

Merged
merged 1 commit into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions doc/classes/RichTextLabel.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<argument index="0" name="image" type="Texture" />
<argument index="1" name="width" type="int" default="0" />
<argument index="2" name="height" type="int" default="0" />
<argument index="3" name="align" type="int" enum="RichTextLabel.InlineAlign" default="2" />
<description>
Adds an image's opening and closing tags to the tag stack, optionally providing a [code]width[/code] and [code]height[/code] to resize the image.
If [code]width[/code] or [code]height[/code] is set to 0, the image size will be adjusted in order to keep the original aspect ratio.
Expand Down Expand Up @@ -335,6 +336,18 @@
<constant name="ALIGN_FILL" value="3" enum="Align">
Makes text fill width.
</constant>
<constant name="INLINE_ALIGN_TOP" value="0" enum="InlineAlign">
Aligns top of the inline image to the top of the text.
</constant>
<constant name="INLINE_ALIGN_CENTER" value="1" enum="InlineAlign">
Aligns center of the inline image to the center of the text.
</constant>
<constant name="INLINE_ALIGN_BASELINE" value="2" enum="InlineAlign">
Aligns bottom of the inline image to the baseline of the text.
</constant>
<constant name="INLINE_ALIGN_BOTTOM" value="3" enum="InlineAlign">
Aligns bottom of the inline image to the bottom of the text.
</constant>
<constant name="LIST_NUMBERS" value="0" enum="ListType">
Each list item has a number marker.
</constant>
Expand Down
115 changes: 95 additions & 20 deletions editor/editor_export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "editor/editor_file_system.h"
#include "editor/plugins/script_editor_plugin.h"
#include "editor_node.h"
#include "editor_scale.h"
#include "editor_settings.h"
#include "scene/resources/resource_format_text.h"

Expand Down Expand Up @@ -220,6 +221,82 @@ EditorExportPreset::EditorExportPreset() :

///////////////////////////////////

bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) {
bool has_messages = false;

int msg_count = get_message_count();

p_log->add_text(TTR("Project export for platform:") + " ");
p_log->add_image(get_logo(), 16 * EDSCALE, 16 * EDSCALE, RichTextLabel::INLINE_ALIGN_CENTER);
p_log->add_text(" ");
p_log->add_text(get_name());
p_log->add_text(" - ");
if (p_err == OK) {
if (get_worst_message_type() >= EditorExportPlatform::EXPORT_MESSAGE_WARNING) {
p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_icon("StatusWarning", "EditorIcons"), 16 * EDSCALE, 16 * EDSCALE, RichTextLabel::INLINE_ALIGN_CENTER);
p_log->add_text(" ");
p_log->add_text(TTR("Completed with errors."));
has_messages = true;
} else {
p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_icon("StatusSuccess", "EditorIcons"), 16 * EDSCALE, 16 * EDSCALE, RichTextLabel::INLINE_ALIGN_CENTER);
p_log->add_text(" ");
p_log->add_text(TTR("Completed sucessfully."));
if (msg_count > 0) {
has_messages = true;
}
}
} else {
p_log->add_image(EditorNode::get_singleton()->get_gui_base()->get_icon("StatusError", "EditorIcons"), 16 * EDSCALE, 16 * EDSCALE, RichTextLabel::INLINE_ALIGN_CENTER);
p_log->add_text(" ");
p_log->add_text(TTR("Failed."));
has_messages = true;
}

if (msg_count) {
p_log->push_table(2);
p_log->set_table_column_expand(0, false);
p_log->set_table_column_expand(1, true);
for (int m = 0; m < msg_count; m++) {
EditorExportPlatform::ExportMessage msg = get_message(m);
Color color = EditorNode::get_singleton()->get_gui_base()->get_color("font_color", "Label");
Ref<Texture> icon;

switch (msg.msg_type) {
case EditorExportPlatform::EXPORT_MESSAGE_INFO: {
color = EditorNode::get_singleton()->get_gui_base()->get_color("font_color", "Editor") * Color(1, 1, 1, 0.6);
} break;
case EditorExportPlatform::EXPORT_MESSAGE_WARNING: {
icon = EditorNode::get_singleton()->get_gui_base()->get_icon("Warning", "EditorIcons");
color = EditorNode::get_singleton()->get_gui_base()->get_color("warning_color", "Editor");
} break;
case EditorExportPlatform::EXPORT_MESSAGE_ERROR: {
icon = EditorNode::get_singleton()->get_gui_base()->get_icon("Error", "EditorIcons");
color = EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor");
} break;
default:
break;
}

p_log->push_cell();
p_log->add_text("\t");
if (icon.is_valid()) {
p_log->add_image(icon);
}
p_log->pop();

p_log->push_cell();
p_log->push_color(color);
p_log->add_text(vformat("[%s]: %s", msg.category, msg.text));
p_log->pop();
p_log->pop();
}
p_log->pop();
p_log->add_newline();
}
p_log->add_newline();
return has_messages;
}

void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags) {
String host = EditorSettings::get_singleton()->get("network/debug/remote_host");
int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port");
Expand Down Expand Up @@ -961,7 +1038,10 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c

String tmppath = EditorSettings::get_singleton()->get_cache_dir().plus_file("packtmp");
FileAccess *ftmp = FileAccess::open(tmppath, FileAccess::WRITE);
ERR_FAIL_COND_V_MSG(!ftmp, ERR_CANT_CREATE, "Cannot create file '" + tmppath + "'.");
if (!ftmp) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), vformat(TTR("Cannot create file \"%s\"."), tmppath));
return ERR_CANT_CREATE;
}

PackData pd;
pd.ep = &ep;
Expand All @@ -974,7 +1054,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c

if (err != OK) {
DirAccess::remove_file_or_error(tmppath);
ERR_PRINT("Failed to export project files");
add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), TTR("Failed to export project files."));
return err;
}

Expand Down Expand Up @@ -1066,7 +1146,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
if (!ftmp) {
memdelete(f);
DirAccess::remove_file_or_error(tmppath);
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Can't open file to read from path '" + String(tmppath) + "'.");
add_message(EXPORT_MESSAGE_ERROR, TTR("Save PCK"), vformat(TTR("Can't open file to read from path \"%s\"."), tmppath));
return ERR_CANT_CREATE;
}

const int bufsize = 16384;
Expand Down Expand Up @@ -1117,8 +1198,9 @@ Error EditorExportPlatform::save_zip(const Ref<EditorExportPreset> &p_preset, co
zd.zip = zip;

Error err = export_project_files(p_preset, _save_zip_file, &zd);
if (err != OK && err != ERR_SKIP)
ERR_PRINT("Failed to export project files");
if (err != OK && err != ERR_SKIP) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Save ZIP"), TTR("Failed to export project files."));
}

zipClose(zip, nullptr);

Expand Down Expand Up @@ -1184,6 +1266,7 @@ void EditorExportPlatform::gen_export_flags(Vector<String> &r_flags, int p_flags
r_flags.push_back("--debug-navigation");
}
}

EditorExportPlatform::EditorExportPlatform() {
}

Expand Down Expand Up @@ -1638,6 +1721,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr

Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
if (!DirAccess::exists(p_path.get_base_dir())) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("The given export path doesn't exist."));
return ERR_FILE_BAD_PATH;
}

Expand Down Expand Up @@ -1665,13 +1749,16 @@ Error EditorExportPlatformPC::prepare_template(const Ref<EditorExportPreset> &p_
}

if (template_path != String() && !FileAccess::exists(template_path)) {
EditorNode::get_singleton()->show_warning(TTR("Template file not found:") + "\n" + template_path);
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), vformat(TTR("Template file not found: \"%s\"."), template_path));
return ERR_FILE_NOT_FOUND;
}

DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
da->make_dir_recursive(p_path.get_base_dir());
Error err = da->copy(template_path, p_path, get_chmod_flags());
if (err != OK) {
add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Template"), TTR("Failed to copy export template."));
}

return err;
}
Expand All @@ -1691,14 +1778,11 @@ Error EditorExportPlatformPC::export_project_data(const Ref<EditorExportPreset>
Error err = save_pack(p_preset, pck_path, &so_files, p_preset->get("binary_format/embed_pck"), &embedded_pos, &embedded_size);
if (err == OK && p_preset->get("binary_format/embed_pck")) {
if (embedded_size >= 0x100000000 && !p_preset->get("binary_format/64_bits")) {
EditorNode::get_singleton()->show_warning(TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("On 32-bit exports the embedded PCK cannot be bigger than 4 GiB."));
return ERR_INVALID_PARAMETER;
}

FixUpEmbeddedPckFunc fixup_func = get_fixup_embedded_pck_func();
if (fixup_func) {
err = fixup_func(p_path, embedded_pos, embedded_size);
}
err = fixup_embedded_pck(p_path, embedded_pos, embedded_size);
}

if (err == OK && !so_files.empty()) {
Expand Down Expand Up @@ -1778,17 +1862,8 @@ void EditorExportPlatformPC::set_chmod_flags(int p_flags) {
chmod_flags = p_flags;
}

EditorExportPlatformPC::FixUpEmbeddedPckFunc EditorExportPlatformPC::get_fixup_embedded_pck_func() const {
return fixup_embedded_pck_func;
}

void EditorExportPlatformPC::set_fixup_embedded_pck_func(FixUpEmbeddedPckFunc p_fixup_embedded_pck_func) {
fixup_embedded_pck_func = p_fixup_embedded_pck_func;
}

EditorExportPlatformPC::EditorExportPlatformPC() {
chmod_flags = -1;
fixup_embedded_pck_func = nullptr;
}

///////////////////////
Expand Down
66 changes: 58 additions & 8 deletions editor/editor_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include "core/os/dir_access.h"
#include "core/resource.h"
#include "scene/gui/rich_text_label.h"
#include "scene/main/node.h"
#include "scene/main/timer.h"
#include "scene/resources/texture.h"
Expand Down Expand Up @@ -151,6 +152,19 @@ class EditorExportPlatform : public Reference {
typedef Error (*EditorExportSaveFunction)(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total);
typedef Error (*EditorExportSaveSharedObject)(void *p_userdata, const SharedObject &p_so);

enum ExportMessageType {
EXPORT_MESSAGE_NONE,
EXPORT_MESSAGE_INFO,
EXPORT_MESSAGE_WARNING,
EXPORT_MESSAGE_ERROR,
};

struct ExportMessage {
ExportMessageType msg_type;
String category;
String text;
};

private:
struct SavedData {
uint64_t ofs;
Expand Down Expand Up @@ -180,6 +194,8 @@ class EditorExportPlatform : public Reference {
PoolVector<String> features_pv;
};

Vector<ExportMessage> messages;

void _export_find_resources(EditorFileSystemDirectory *p_dir, Set<String> &p_paths);
void _export_find_dependencies(const String &p_path, Set<String> &p_paths);

Expand Down Expand Up @@ -220,6 +236,47 @@ class EditorExportPlatform : public Reference {

virtual Ref<EditorExportPreset> create_preset();

virtual void clear_messages() { messages.clear(); }
virtual void add_message(ExportMessageType p_type, const String &p_category, const String &p_message) {
ExportMessage msg;
msg.category = p_category;
msg.text = p_message;
msg.msg_type = p_type;
messages.push_back(msg);
switch (p_type) {
case EXPORT_MESSAGE_INFO: {
print_line(vformat("%s: %s\n", msg.category, msg.text));
} break;
case EXPORT_MESSAGE_WARNING: {
WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text));
} break;
case EXPORT_MESSAGE_ERROR: {
ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text));
} break;
default:
break;
}
}

virtual int get_message_count() const {
return messages.size();
}

virtual ExportMessage get_message(int p_index) const {
ERR_FAIL_INDEX_V(p_index, messages.size(), ExportMessage());
return messages[p_index];
}

virtual ExportMessageType get_worst_message_type() const {
ExportMessageType worst_type = EXPORT_MESSAGE_NONE;
for (int i = 0; i < messages.size(); i++) {
worst_type = MAX(worst_type, messages[i].msg_type);
}
return worst_type;
}

virtual bool fill_log_messages(RichTextLabel *p_log, Error p_err);

virtual void get_export_options(List<ExportOption> *r_options) = 0;
virtual bool should_update_export_options() { return false; }
virtual bool get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { return true; }
Expand Down Expand Up @@ -400,9 +457,6 @@ class EditorExport : public Node {
class EditorExportPlatformPC : public EditorExportPlatform {
GDCLASS(EditorExportPlatformPC, EditorExportPlatform);

public:
typedef Error (*FixUpEmbeddedPckFunc)(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);

private:
Ref<ImageTexture> logo;
String name;
Expand All @@ -418,8 +472,6 @@ class EditorExportPlatformPC : public EditorExportPlatform {

int chmod_flags;

FixUpEmbeddedPckFunc fixup_embedded_pck_func;

public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);

Expand All @@ -437,6 +489,7 @@ class EditorExportPlatformPC : public EditorExportPlatform {
virtual Error prepare_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { return OK; }
virtual Error export_project_data(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags);
virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { return OK; }

void set_extension(const String &p_extension, const String &p_feature_key = "default");
void set_name(const String &p_name);
Expand All @@ -456,9 +509,6 @@ class EditorExportPlatformPC : public EditorExportPlatform {
int get_chmod_flags() const;
void set_chmod_flags(int p_flags);

FixUpEmbeddedPckFunc get_fixup_embedded_pck_func() const;
void set_fixup_embedded_pck_func(FixUpEmbeddedPckFunc p_fixup_embedded_pck_func);

EditorExportPlatformPC();
};

Expand Down
17 changes: 5 additions & 12 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,21 +798,14 @@ void EditorNode::_fs_changed() {
ERR_PRINT(vformat("Cannot export project with preset \"%s\" due to configuration errors:\n%s", preset_name, config_error));
err = missing_templates ? ERR_FILE_NOT_FOUND : ERR_UNCONFIGURED;
} else {
platform->clear_messages();
err = platform->export_project(preset, export_defer.debug, export_path);
}
}
switch (err) {
case OK:
break;
case ERR_FILE_NOT_FOUND:
export_error = vformat("Project export failed for preset \"%s\". The export template appears to be missing.", preset_name);
break;
case ERR_FILE_BAD_PATH:
export_error = vformat("Project export failed for preset \"%s\". The target path \"%s\" appears to be invalid.", preset_name, export_path);
break;
default:
export_error = vformat("Project export failed with error code %d for preset \"%s\".", (int)err, preset_name);
break;
if (err != OK) {
export_error = vformat("Project export for preset \"%s\" failed.", preset_name);
} else if (platform->get_worst_message_type() >= EditorExportPlatform::EXPORT_MESSAGE_WARNING) {
export_error = vformat("Project export for preset \"%s\" completed with errors.", preset_name);
}
}
}
Expand Down
Loading