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

Convert 3.x ESCN skeletons, animations, and shaders upon import #87106

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions core/io/resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,10 @@ String Resource::get_id_for_path(const String &p_path) const {
#endif
}

void Resource::_start_load(const StringName &p_res_format_type, int p_res_format_version) {}

void Resource::_finish_load(const StringName &p_res_format_type, int p_res_format_version) {}

void Resource::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_path", "path"), &Resource::_set_path);
ClassDB::bind_method(D_METHOD("take_over_path", "path"), &Resource::_take_over_path);
Expand Down
3 changes: 3 additions & 0 deletions core/io/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ class Resource : public RefCounted {
void set_id_for_path(const String &p_path, const String &p_id);
String get_id_for_path(const String &p_path) const;

virtual void _start_load(const StringName &p_res_format_type, int p_res_format_version);
virtual void _finish_load(const StringName &p_res_format_type, int p_res_format_version);

Resource();
~Resource();
};
Expand Down
4 changes: 4 additions & 0 deletions core/io/resource_format_binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,8 @@ Error ResourceLoaderBinary::load() {
internal_index_cache[path] = res;
}

res->_start_load("binary", ver_format);

int pc = f->get_32();

//set properties
Expand Down Expand Up @@ -889,6 +891,8 @@ Error ResourceLoaderBinary::load() {
res->set_edited(false);
#endif

res->_finish_load("binary", ver_format);

if (progress) {
*progress = (i + 1) / float(internal_resources.size());
}
Expand Down
51 changes: 47 additions & 4 deletions editor/import/3d/resource_importer_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3270,11 +3270,43 @@ void EditorSceneFormatImporterESCN::get_extensions(List<String> *r_extensions) c
r_extensions->push_back("escn");
}

int get_text_format_version(String p_path) {
Error error;
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &error);
ERR_FAIL_COND_V_MSG(error != OK || f.is_null(), -1, "Cannot open file '" + p_path + "'.");
String line = f->get_line().strip_edges();
// skip empty lines and comments
while (line.is_empty() || line.begins_with(";")) {
line = f->get_line().strip_edges();
if (f->eof_reached()) {
break;
}
}
int format_index = line.find("format");
ERR_FAIL_COND_V_MSG(format_index == -1, -1, "No format specifier in file '" + p_path + "'.");
String format_str = line.substr(format_index).get_slicec('=', 1).strip_edges();
ERR_FAIL_COND_V_MSG(!format_str.substr(0, 1).is_numeric(), -1, "Invalid format in file '" + p_path + "'.");
int format = format_str.to_int();
return format;
}

Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t p_flags, const HashMap<StringName, Variant> &p_options, List<String> *r_missing_deps, Error *r_err) {
Error error;
int format = get_text_format_version(p_path);
ERR_FAIL_COND_V(format == -1, nullptr);
Ref<PackedScene> ps = ResourceFormatLoaderText::singleton->load(p_path, p_path, &error);
ERR_FAIL_COND_V_MSG(!ps.is_valid(), nullptr, "Cannot load scene as text resource from path '" + p_path + "'.");
Node *scene = ps->instantiate();
ERR_FAIL_COND_V(!scene, nullptr);
if (format == 2) {
TypedArray<Node> skel_nodes = scene->find_children("*", "AnimationPlayer");
for (int32_t node_i = 0; node_i < skel_nodes.size(); node_i++) {
// Force re-compute animation tracks.
AnimationPlayer *player = cast_to<AnimationPlayer>(skel_nodes[node_i]);
ERR_CONTINUE(!player);
player->advance(0);
}
}
TypedArray<Node> nodes = scene->find_children("*", "MeshInstance3D");
for (int32_t node_i = 0; node_i < nodes.size(); node_i++) {
MeshInstance3D *mesh_3d = cast_to<MeshInstance3D>(nodes[node_i]);
Expand All @@ -3283,9 +3315,22 @@ Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t
// Ignore the aabb, it will be recomputed.
ImporterMeshInstance3D *importer_mesh_3d = memnew(ImporterMeshInstance3D);
importer_mesh_3d->set_name(mesh_3d->get_name());
importer_mesh_3d->set_transform(mesh_3d->get_relative_transform(mesh_3d->get_parent()));
importer_mesh_3d->set_skin(mesh_3d->get_skin());
Node *parent = mesh_3d->get_parent();
Transform3D rel_transform = mesh_3d->get_relative_transform(parent);
if (rel_transform == Transform3D() && parent && parent != mesh_3d) {
// If we're here, we probably got a "data.parent is null" error
// Node3D.data.parent hasn't been set yet but Node.data.parent has, so we need to get the transform manually
Node3D *parent_3d = mesh_3d->get_parent_node_3d();
if (parent == parent_3d) {
rel_transform = mesh_3d->get_transform();
} else if (parent_3d) {
rel_transform = parent_3d->get_relative_transform(parent) * mesh_3d->get_transform();
} // Otherwise, parent isn't a Node3D.
}
importer_mesh_3d->set_transform(rel_transform);
Ref<Skin> skin = mesh_3d->get_skin();
importer_mesh_3d->set_skeleton_path(mesh_3d->get_skeleton_path());
importer_mesh_3d->set_skin(skin);
Ref<ArrayMesh> array_mesh_3d_mesh = mesh_3d->get_mesh();
if (array_mesh_3d_mesh.is_valid()) {
// For the MeshInstance3D nodes, we need to convert the ArrayMesh to an ImporterMesh specially.
Expand Down Expand Up @@ -3326,7 +3371,5 @@ Node *EditorSceneFormatImporterESCN::import_scene(const String &p_path, uint32_t
}
}

ERR_FAIL_NULL_V(scene, nullptr);

return scene;
}
84 changes: 82 additions & 2 deletions editor/plugins/text_shader_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
#include "servers/rendering/shader_preprocessor.h"
#include "servers/rendering/shader_types.h"

#ifndef DISABLE_DEPRECATED
#include "servers/rendering/shader_converter.h"
#endif

/*** SHADER SYNTAX HIGHLIGHTER ****/

Dictionary GDShaderSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_line) {
Expand Down Expand Up @@ -699,6 +703,28 @@ void TextShaderEditor::_menu_option(int p_option) {
case EDIT_COMPLETE: {
code_editor->get_text_editor()->request_code_completion();
} break;
#ifndef DISABLE_DEPRECATED
case EDIT_CONVERT: {
if (shader.is_null()) {
return;
}
String code = code_editor->get_text_editor()->get_text();
if (code.is_empty()) {
return;
}
ShaderDeprecatedConverter converter;
if (!converter.is_code_deprecated(code)) {
if (converter.get_error_text() != String()) {
shader_convert_error_dialog->set_text(vformat(RTR("Line %d: %s"), converter.get_error_line(), converter.get_error_text()));
shader_convert_error_dialog->popup_centered();
ERR_PRINT("Shader conversion failed: " + converter.get_error_text());
}
confirm_convert_shader->popup_centered();
return;
}
_convert_shader();
} break;
#endif
case SEARCH_FIND: {
code_editor->get_find_replace_bar()->popup_search();
} break;
Expand Down Expand Up @@ -755,6 +781,43 @@ void TextShaderEditor::_notification(int p_what) {
} break;
}
}
#ifndef DISABLE_DEPRECATED
void TextShaderEditor::_convert_shader() {
if (shader.is_null()) {
return;
}
String code = code_editor->get_text_editor()->get_text();
if (code.is_empty()) {
return;
}
ShaderDeprecatedConverter converter;
if (!converter.convert_code(code)) {
String err_text = converter.get_error_text();
if (err_text.is_empty()) {
err_text = TTR("Unknown error occurred while converting the shader.");
} else if (converter.get_error_line() > 0) {
err_text = vformat("%s (line %d)", err_text, converter.get_error_line());
}

shader_convert_error_dialog->set_text(err_text);
shader_convert_error_dialog->popup_centered();
ERR_PRINT("Shader conversion failed: " + err_text);
return;
}
String new_code = converter.emit_code();

#ifdef DEBUG_ENABLED
print_line(converter.get_report());
#endif
if (new_code == code) {
return;
}
// Ensure undoable.
code_editor->get_text_editor()->set_text(new_code);
code_editor->get_text_editor()->tag_saved_version();
code_editor->_validate_script();
}
#endif
nikitalita marked this conversation as resolved.
Show resolved Hide resolved

void TextShaderEditor::_editor_settings_changed() {
if (!EditorThemeManager::is_generated_theme_outdated() &&
Expand Down Expand Up @@ -1170,8 +1233,12 @@ TextShaderEditor::TextShaderEditor() {
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_word_wrap"), EDIT_TOGGLE_WORD_WRAP);
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE);
edit_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &TextShaderEditor::_menu_option));

#ifndef DISABLE_DEPRECATED
edit_menu->get_popup()->add_separator();
edit_menu->get_popup()->add_item(TTR("Convert 3.x Shader"), EDIT_CONVERT);
nikitalita marked this conversation as resolved.
Show resolved Hide resolved
#endif
edit_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &TextShaderEditor::_menu_option));
search_menu = memnew(MenuButton);
search_menu->set_shortcut_context(this);
search_menu->set_text(TTR("Search"));
Expand Down Expand Up @@ -1254,7 +1321,20 @@ TextShaderEditor::TextShaderEditor() {
disk_changed->connect("custom_action", callable_mp(this, &TextShaderEditor::save_external_data));

add_child(disk_changed);

#ifndef DISABLE_DEPRECATED
shader_convert_error_dialog = memnew(AcceptDialog);
shader_convert_error_dialog->set_title(TTR("Error converting shader"));
shader_convert_error_dialog->set_hide_on_ok(true);
add_child(shader_convert_error_dialog);

confirm_convert_shader = memnew(ConfirmationDialog);
confirm_convert_shader->set_title(TTR("Confirm Convert 3.x Shader"));
confirm_convert_shader->set_text(TTR("This shader does not appear to be a 3.x shader.\nAre you sure you want to convert it?"));
confirm_convert_shader->get_ok_button()->set_text(TTR("Convert"));
confirm_convert_shader->get_cancel_button()->set_text(TTR("Cancel"));
confirm_convert_shader->connect("confirmed", callable_mp(this, &TextShaderEditor::_convert_shader));
add_child(confirm_convert_shader);
#endif
_editor_settings_changed();
code_editor->show_toggle_scripts_button(); // TODO: Disabled for now, because it doesn't work properly.
}
9 changes: 9 additions & 0 deletions editor/plugins/text_shader_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class TextShaderEditor : public ShaderEditor {
EDIT_TOGGLE_WORD_WRAP,
EDIT_TOGGLE_COMMENT,
EDIT_COMPLETE,
EDIT_CONVERT,
SEARCH_FIND,
SEARCH_FIND_NEXT,
SEARCH_FIND_PREV,
Expand All @@ -150,13 +151,21 @@ class TextShaderEditor : public ShaderEditor {
ConfirmationDialog *disk_changed = nullptr;

ShaderTextEditor *code_editor = nullptr;
#ifndef DISABLE_DEPRECATED
AcceptDialog *shader_convert_error_dialog = nullptr;
ConfirmationDialog *confirm_convert_shader = nullptr;
#endif

bool compilation_success = true;

void _menu_option(int p_option);
void _prepare_edit_menu();
mutable Ref<Shader> shader;
mutable Ref<ShaderInclude> shader_inc;

#ifndef DISABLE_DEPRECATED
void _convert_shader();
#endif
void _editor_settings_changed();
void _apply_editor_settings();
void _project_settings_changed();
Expand Down
15 changes: 13 additions & 2 deletions scene/3d/mesh_instance_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,19 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) {
return true;
}

if (p_name.operator String().begins_with("surface_material_override/")) {
int idx = p_name.operator String().get_slicec('/', 1).to_int();
String name = p_name;

#ifndef DISABLE_DEPRECATED
if (name.begins_with("material/")) {
WARN_DEPRECATED_MSG("This mesh uses an old deprecated parameter name. Consider re-saving this scene in order for it to continue working in future versions." +
(is_inside_tree() ? vformat(" Path: \"%s\"", get_path()) : String()));
}
if (name.begins_with("surface_material_override/") || name.begins_with("material/"))
#else
if (name.begins_with("surface_material_override/"))
#endif
{
nikitalita marked this conversation as resolved.
Show resolved Hide resolved
int idx = name.get_slicec('/', 1).to_int();

if (idx >= surface_override_materials.size() || idx < 0) {
return false;
Expand Down
Loading
Loading