Merge pull request #54886 from V-Sekai/blend-io

Add Blend Import
This commit is contained in:
Rémi Verschelde 2022-03-29 23:43:23 +02:00 committed by GitHub
commit ed67d8f8a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 443 additions and 50 deletions

View file

@ -553,6 +553,10 @@
<member name="editor/script/templates_search_path" type="String" setter="" getter="" default="&quot;res://script_templates&quot;">
Search path for project-specific script templates. Godot will search for script templates both in the editor-specific path and in this project-specific path.
</member>
<member name="filesystem/import/blend/enabled" type="bool" setter="" getter="" default="false">
If [code]true[/code], 3D scene files with the [code].blend[/code] extension will be imported by converting them to glTF 2.0.
This requires configuring a path to a Blender executable in the editor settings at [code]filesystem/import/blend/blender_path[/code]. Blender 3.0 or later is required.
</member>
<member name="gui/common/default_scroll_deadzone" type="int" setter="" getter="" default="0">
Default value for [member ScrollContainer.scroll_deadzone], which will be used for all [ScrollContainer]s unless overridden.
</member>

View file

@ -8,12 +8,15 @@ def configure(env):
def get_doc_classes():
return [
"EditorSceneImporterGLTF",
"EditorSceneFormatImporterBlend",
"EditorSceneFormatImporterGLTF",
"GLTFAccessor",
"GLTFAnimation",
"GLTFBufferView",
"GLTFCamera",
"GLTFDocument",
"GLTFDocumentExtension",
"GLTFDocumentExtensionConvertImporterMesh",
"GLTFLight",
"GLTFMesh",
"GLTFNode",
@ -22,8 +25,6 @@ def get_doc_classes():
"GLTFSpecGloss",
"GLTFState",
"GLTFTexture",
"GLTFDocumentExtension",
"GLTFDocumentExtensionConvertImporterMesh",
]

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorSceneFormatImporterBlend" inherits="EditorSceneFormatImporter" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
Importer for Blender's [code].blend[/code] scene file format.
</brief_description>
<description>
Imports Blender scenes in the [code].blend[/code] file format through the glTF 2.0 3D import pipeline. This importer requires Blender to be installed by the user, so that it can be used to export the scene as glTF 2.0.
The location of the Blender binary is set via the [code]filesystem/import/blend/blender_path[/code] editor setting.
This importer is only used if [member ProjectSettings.filesystem/import/blend/enabled] is enabled, otherwise [code].blend[/code] present in the project folder are not imported.
Blend import requires Blender 3.0.
Internally, the EditorSceneFormatImporterBlend uses the Blender glTF "Use Original" mode to reference external textures.
</description>
<tutorials>
</tutorials>
</class>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorSceneFormatImporterGLTF" inherits="EditorSceneFormatImporter" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<class name="EditorSceneFormatImporterGLTF" inherits="EditorSceneFormatImporter" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
<brief_description>
</brief_description>
<description>

View file

@ -24,6 +24,7 @@
<argument index="1" name="state" type="GLTFState" />
<argument index="2" name="flags" type="int" default="0" />
<argument index="3" name="bake_fps" type="int" default="30" />
<argument index="4" name="base_path" type="String" default="&quot;&quot;" />
<description>
</description>
</method>

View file

@ -0,0 +1,268 @@
/*************************************************************************/
/* editor_scene_importer_blend.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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. */
/*************************************************************************/
#include "editor_scene_importer_blend.h"
#if TOOLS_ENABLED
#include "../gltf_document.h"
#include "../gltf_state.h"
#include "core/config/project_settings.h"
#include "core/io/json.h"
#include "editor/editor_settings.h"
#include "scene/main/node.h"
#include "scene/resources/animation.h"
uint32_t EditorSceneFormatImporterBlend::get_import_flags() const {
return ImportFlags::IMPORT_SCENE | ImportFlags::IMPORT_ANIMATION;
}
void EditorSceneFormatImporterBlend::get_extensions(List<String> *r_extensions) const {
r_extensions->push_back("blend");
}
Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err) {
// Parse JSON config.
const String source_global = ProjectSettings::get_singleton()->globalize_path(p_path).c_escape();
const String sink = ProjectSettings::get_singleton()->get_imported_files_path().plus_file(
vformat("%s-%s.gltf", p_path.get_file().get_basename(), p_path.md5_text()));
const String sink_global = ProjectSettings::get_singleton()->globalize_path(sink).c_escape();
const String json_parameters = vformat("{\"source\": \"%s\", \"sink\": \"%s\"}", source_global, sink_global);
Ref<JSON> json;
json.instantiate();
Error err = json->parse(json_parameters);
if (err != OK) {
if (r_err) {
*r_err = err;
}
ERR_PRINT(vformat("Blend config can't be read at line %s with error: %s",
json->get_error_line(), json->get_error_message()));
return nullptr;
}
Dictionary parameters = json->get_data();
// Handle configuration options.
String parameters_arg;
if (p_options.has(SNAME("blender/nodes/custom_properties")) && p_options[SNAME("blender/nodes/custom_properties")]) {
parameters_arg += "export_extras=True,";
} else {
parameters_arg += "export_extras=False,";
}
if (p_options.has(SNAME("blender/meshes/skins")) && p_options[SNAME("blender/meshes/skins")]) {
int32_t skins = p_options["blender/meshes/skins"];
if (skins == BLEND_BONE_INFLUENCES_NONE) {
parameters_arg += "export_all_influences=False,";
} else if (skins == BLEND_BONE_INFLUENCES_COMPATIBLE) {
parameters_arg += "export_all_influences=False,";
} else if (skins == BLEND_BONE_INFLUENCES_ALL) {
parameters_arg += "export_all_influences=True,";
}
parameters_arg += "export_skins=True,";
} else {
parameters_arg += "export_skins=False,";
}
if (p_options.has(SNAME("blender/nodes/cameras")) && p_options[SNAME("blender/nodes/cameras")]) {
parameters_arg += "export_cameras=True,";
} else {
parameters_arg += "export_cameras=False,";
}
if (p_options.has(SNAME("blender/nodes/lights")) && p_options[SNAME("blender/nodes/lights")]) {
parameters_arg += "export_lights=True,";
} else {
parameters_arg += "export_lights=False,";
}
if (p_options.has(SNAME("blender/meshes/colors")) && p_options[SNAME("blender/meshes/colors")]) {
parameters_arg += "export_colors=True,";
} else {
parameters_arg += "export_colors=False,";
}
if (p_options.has(SNAME("blender/nodes/visible")) && p_options[SNAME("blender/nodes/visible")]) {
int32_t visible = p_options["blender/nodes/visible"];
if (visible == BLEND_VISIBLE_VISIBLE_ONLY) {
parameters_arg += "use_visible=True,";
} else if (visible == BLEND_VISIBLE_RENDERABLE) {
parameters_arg += "use_renderable=True,";
} else if (visible == BLEND_VISIBLE_ALL) {
parameters_arg += "use_visible=False,use_renderable=False,";
}
} else {
parameters_arg += "use_visible=False,use_renderable=False,";
}
if (p_options.has(SNAME("blender/meshes/uvs")) && p_options[SNAME("blender/meshes/uvs")]) {
parameters_arg += "export_texcoords=True,";
} else {
parameters_arg += "export_texcoords=False,";
}
if (p_options.has(SNAME("blender/meshes/normals")) && p_options[SNAME("blender/meshes/normals")]) {
parameters_arg += "export_normals=True,";
} else {
parameters_arg += "export_normals=False,";
}
if (p_options.has(SNAME("blender/meshes/tangents")) && p_options[SNAME("blender/meshes/tangents")]) {
parameters_arg += "export_tangents=True,";
} else {
parameters_arg += "export_tangents=False,";
}
if (p_options.has(SNAME("blender/animation/group_tracks")) && p_options[SNAME("blender/animation/group_tracks")]) {
parameters_arg += "export_nla_strips=True,";
} else {
parameters_arg += "export_nla_strips=False,";
}
if (p_options.has(SNAME("blender/animation/limit_playback")) && p_options[SNAME("blender/animation/limit_playback")]) {
parameters_arg += "export_frame_range=True,";
} else {
parameters_arg += "export_frame_range=False,";
}
if (p_options.has(SNAME("blender/animation/always_sample")) && p_options[SNAME("blender/animation/always_sample")]) {
parameters_arg += "export_force_sampling=True,";
} else {
parameters_arg += "export_force_sampling=False,";
}
if (p_options.has(SNAME("blender/meshes/export_bones_deforming_mesh_only")) && p_options[SNAME("blender/meshes/export_bones_deforming_mesh_only")]) {
parameters_arg += "export_def_bones=True,";
} else {
parameters_arg += "export_def_bones=False,";
}
if (p_options.has(SNAME("blender/nodes/modifiers")) && p_options[SNAME("blender/nodes/modifiers")]) {
parameters_arg += "export_apply=True";
} else {
parameters_arg += "export_apply=False";
}
String unpack_all;
if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) {
unpack_all = "bpy.ops.file.unpack_all(method='USE_LOCAL');";
}
// Prepare Blender export script.
String common_args = vformat("filepath='%s',", parameters["sink"]) +
"export_format='GLTF_SEPARATE',"
"export_yup=True," +
parameters_arg;
String script =
String("import bpy, sys;") +
"print('Blender 3.0 or higher is required.', file=sys.stderr) if bpy.app.version < (3, 0, 0) else None;" +
vformat("bpy.ops.wm.open_mainfile(filepath='%s');", parameters["source"]) +
unpack_all +
vformat("bpy.ops.export_scene.gltf(export_keep_originals=True,%s);", common_args);
print_verbose(script);
// Run script with configured Blender binary.
String blender_path = EDITOR_GET("filesystem/import/blend/blender_path");
List<String> args;
args.push_back("--background");
args.push_back("--python-expr");
args.push_back(script);
String standard_out;
int32_t ret = OS::get_singleton()->execute(blender_path, args, &standard_out, &ret, true);
print_verbose(standard_out);
if (ret != OK) {
if (r_err) {
*r_err = ERR_SCRIPT_FAILED;
}
ERR_PRINT(vformat("Blend import failed with error: %d.", ret));
return nullptr;
}
// Import the generated glTF.
// Use GLTFDocument instead of gltf importer to keep image references.
Ref<GLTFDocument> gltf;
gltf.instantiate();
Ref<GLTFState> state;
state.instantiate();
String base_dir;
if (p_options.has(SNAME("blender/materials/unpack_enabled")) && p_options[SNAME("blender/materials/unpack_enabled")]) {
base_dir = sink.get_base_dir();
}
err = gltf->append_from_file(sink.get_basename() + ".gltf", state, p_flags, p_bake_fps, base_dir);
if (err != OK) {
if (r_err) {
*r_err = FAILED;
}
return nullptr;
}
return gltf->generate_scene(state, p_bake_fps);
}
Ref<Animation> EditorSceneFormatImporterBlend::import_animation(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps) {
return Ref<Animation>();
}
Variant EditorSceneFormatImporterBlend::get_option_visibility(const String &p_path, const String &p_option,
const Map<StringName, Variant> &p_options) {
if (p_option.begins_with("animation/")) {
if (p_option != "animation/import" && !bool(p_options["animation/import"])) {
return false;
}
}
return true;
}
void EditorSceneFormatImporterBlend::get_import_options(const String &p_path, List<ResourceImporter::ImportOption> *r_options) {
#define ADD_OPTION_BOOL(PATH, VALUE) \
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, SNAME(PATH)), VALUE));
#define ADD_OPTION_ENUM(PATH, ENUM_HINT, VALUE) \
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, SNAME(PATH), PROPERTY_HINT_ENUM, ENUM_HINT), VALUE));
ADD_OPTION_ENUM("blender/nodes/visible", "Visible Only,Renderable,All", BLEND_VISIBLE_ALL);
ADD_OPTION_BOOL("blender/nodes/punctual_lights", true);
ADD_OPTION_BOOL("blender/nodes/cameras", true);
ADD_OPTION_BOOL("blender/nodes/custom_properties", true);
ADD_OPTION_ENUM("blender/nodes/modifiers", "No Modifiers,All Modifiers", BLEND_MODIFIERS_ALL);
ADD_OPTION_BOOL("blender/meshes/colors", false);
ADD_OPTION_BOOL("blender/meshes/uvs", true);
ADD_OPTION_BOOL("blender/meshes/normals", true);
ADD_OPTION_BOOL("blender/meshes/tangents", true);
ADD_OPTION_ENUM("blender/meshes/skins", "None,4 Influences (Compatible),All Influences", BLEND_BONE_INFLUENCES_ALL);
ADD_OPTION_BOOL("blender/meshes/export_bones_deforming_mesh_only", false);
ADD_OPTION_BOOL("blender/materials/unpack_enabled", true);
ADD_OPTION_BOOL("blender/animation/limit_playback", true);
ADD_OPTION_BOOL("blender/animation/always_sample", true);
ADD_OPTION_BOOL("blender/animation/group_tracks", true);
#undef ADD_OPTION_BOOL
#undef ADD_OPTION_ENUM
}
#endif // TOOLS_ENABLED

View file

@ -0,0 +1,75 @@
/*************************************************************************/
/* editor_scene_importer_blend.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 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. */
/*************************************************************************/
#ifndef EDITOR_SCENE_IMPORTER_BLEND_H
#define EDITOR_SCENE_IMPORTER_BLEND_H
#ifdef TOOLS_ENABLED
#include "editor/import/resource_importer_scene.h"
class Animation;
class Node;
class EditorSceneFormatImporterBlend : public EditorSceneFormatImporter {
GDCLASS(EditorSceneFormatImporterBlend, EditorSceneFormatImporter);
public:
enum {
BLEND_VISIBLE_VISIBLE_ONLY,
BLEND_VISIBLE_RENDERABLE,
BLEND_VISIBLE_ALL
};
enum {
BLEND_BONE_INFLUENCES_NONE,
BLEND_BONE_INFLUENCES_COMPATIBLE,
BLEND_BONE_INFLUENCES_ALL
};
enum {
BLEND_MODIFIERS_NONE,
BLEND_MODIFIERS_ALL
};
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps) override;
virtual void get_import_options(const String &p_path,
List<ResourceImporter::ImportOption> *r_options) override;
virtual Variant get_option_visibility(const String &p_path, const String &p_option,
const Map<StringName, Variant> &p_options) override;
};
#endif // TOOLS_ENABLED
#endif // EDITOR_SCENE_IMPORTER_BLEND_H

View file

@ -35,8 +35,7 @@
#include "../gltf_document.h"
#include "../gltf_state.h"
#include "scene/3d/node_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/main/node.h"
#include "scene/resources/animation.h"
uint32_t EditorSceneFormatImporterGLTF::get_import_flags() const {
@ -48,26 +47,25 @@ void EditorSceneFormatImporterGLTF::get_extensions(List<String> *r_extensions) c
r_extensions->push_back("glb");
}
Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path,
uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps,
Error *r_err) {
Node *EditorSceneFormatImporterGLTF::import_scene(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err) {
Ref<GLTFDocument> doc;
doc.instantiate();
Ref<GLTFState> state;
state.instantiate();
Error err = doc->append_from_file(p_path, state, p_flags, p_bake_fps);
if (err != OK) {
*r_err = err;
if (r_err) {
*r_err = err;
}
return nullptr;
}
Node *root = doc->generate_scene(state, p_bake_fps);
return root;
return doc->generate_scene(state, p_bake_fps);
}
Ref<Animation> EditorSceneFormatImporterGLTF::import_animation(const String &p_path,
uint32_t p_flags, const Map<StringName, Variant> &p_options,
int p_bake_fps) {
uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) {
return Ref<Animation>();
}

View file

@ -33,14 +33,10 @@
#ifdef TOOLS_ENABLED
#include "../gltf_document_extension.h"
#include "../gltf_state.h"
#include "editor/import/resource_importer_scene.h"
#include "scene/main/node.h"
#include "scene/resources/packed_scene.h"
class Animation;
class Node;
class EditorSceneFormatImporterGLTF : public EditorSceneFormatImporter {
GDCLASS(EditorSceneFormatImporterGLTF, EditorSceneFormatImporter);
@ -48,9 +44,11 @@ class EditorSceneFormatImporterGLTF : public EditorSceneFormatImporter {
public:
virtual uint32_t get_import_flags() const override;
virtual void get_extensions(List<String> *r_extensions) const override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps, List<String> *r_missing_deps, Error *r_err = nullptr) override;
virtual Ref<Animation> import_animation(const String &p_path,
uint32_t p_flags, const Map<StringName, Variant> &p_options, int p_bake_fps) override;
virtual Node *import_scene(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps,
List<String> *r_missing_deps, Error *r_err = nullptr) override;
virtual Ref<Animation> import_animation(const String &p_path, uint32_t p_flags,
const Map<StringName, Variant> &p_options, int p_bake_fps) override;
};
#endif // TOOLS_ENABLED

View file

@ -6758,8 +6758,8 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) {
}
void GLTFDocument::_bind_methods() {
ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps"),
&GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30));
ClassDB::bind_method(D_METHOD("append_from_file", "path", "state", "flags", "bake_fps", "base_path"),
&GLTFDocument::append_from_file, DEFVAL(0), DEFVAL(30), DEFVAL(String()));
ClassDB::bind_method(D_METHOD("append_from_buffer", "bytes", "base_path", "state", "flags", "bake_fps"),
&GLTFDocument::append_from_buffer, DEFVAL(0), DEFVAL(30));
ClassDB::bind_method(D_METHOD("append_from_scene", "node", "state", "flags", "bake_fps"),
@ -7024,20 +7024,22 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> state, const String &p_sear
return OK;
}
Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps) {
Error GLTFDocument::append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags, int32_t p_bake_fps, String p_base_path) {
// TODO Add missing texture and missing .bin file paths to r_missing_deps 2021-09-10 fire
if (r_state == Ref<GLTFState>()) {
r_state.instantiate();
}
r_state->filename = p_path.get_file().get_basename();
r_state->use_named_skin_binds =
p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
r_state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS;
Error err;
FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
ERR_FAIL_COND_V(err != OK, ERR_FILE_CANT_OPEN);
ERR_FAIL_NULL_V(f, ERR_FILE_CANT_OPEN);
err = _parse(r_state, p_path.get_base_dir(), f, p_bake_fps);
String base_path = p_base_path;
if (base_path.is_empty()) {
base_path = p_path.get_base_dir();
}
err = _parse(r_state, base_path, f, p_bake_fps);
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
return err;
}

View file

@ -381,7 +381,7 @@ private:
static float get_max_component(const Color &p_color);
public:
Error append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);
Error append_from_file(String p_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30, String p_base_path = String());
Error append_from_buffer(PackedByteArray p_bytes, String p_base_path, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);
Error append_from_scene(Node *p_node, Ref<GLTFState> r_state, uint32_t p_flags = 0, int32_t p_bake_fps = 30);

View file

@ -49,41 +49,72 @@
#include "gltf_texture.h"
#ifdef TOOLS_ENABLED
#include "core/config/project_settings.h"
#include "editor/editor_node.h"
#include "editor/editor_scene_exporter_gltf_plugin.h"
#include "editor/editor_scene_importer_blend.h"
#include "editor/editor_scene_importer_gltf.h"
#include "editor/editor_settings.h"
static void _editor_init() {
Ref<EditorSceneFormatImporterGLTF> import_gltf;
import_gltf.instantiate();
ResourceImporterScene::get_singleton()->add_importer(import_gltf);
// Blend to glTF importer.
bool blend_enabled = GLOBAL_GET("filesystem/import/blend/enabled");
// Defined here because EditorSettings doesn't exist in `register_gltf_types` yet.
String blender_path = EDITOR_DEF_RST("filesystem/import/blend/blender_path", "");
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING,
"filesystem/import/blend/blender_path", PROPERTY_HINT_GLOBAL_FILE));
if (blend_enabled) {
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (blender_path.is_empty()) {
WARN_PRINT("Blend file import is enabled, but no Blender path is configured. Blend files will not be imported.");
} else if (!da->file_exists(blender_path)) {
WARN_PRINT("Blend file import is enabled, but the Blender path doesn't point to a valid Blender executable. Blend files will not be imported.");
} else {
Ref<EditorSceneFormatImporterBlend> importer;
importer.instantiate();
ResourceImporterScene::get_singleton()->add_importer(importer);
}
}
}
#endif
#endif // TOOLS_ENABLED
void register_gltf_types() {
#ifdef TOOLS_ENABLED
ClassDB::APIType prev_api = ClassDB::get_current_api();
ClassDB::set_current_api(ClassDB::API_EDITOR);
GDREGISTER_CLASS(EditorSceneFormatImporterGLTF);
GDREGISTER_CLASS(GLTFMesh);
EditorPlugins::add_by_type<SceneExporterGLTFPlugin>();
ClassDB::set_current_api(prev_api);
EditorNode::add_init_callback(_editor_init);
#endif
GDREGISTER_CLASS(GLTFSpecGloss);
GDREGISTER_CLASS(GLTFNode);
// glTF API available at runtime.
GDREGISTER_CLASS(GLTFAccessor);
GDREGISTER_CLASS(GLTFAnimation);
GDREGISTER_CLASS(GLTFBufferView);
GDREGISTER_CLASS(GLTFAccessor);
GDREGISTER_CLASS(GLTFTexture);
GDREGISTER_CLASS(GLTFCamera);
GDREGISTER_CLASS(GLTFDocument);
GDREGISTER_CLASS(GLTFDocumentExtension);
GDREGISTER_CLASS(GLTFDocumentExtensionConvertImporterMesh);
GDREGISTER_CLASS(GLTFLight);
GDREGISTER_CLASS(GLTFNode);
GDREGISTER_CLASS(GLTFSkeleton);
GDREGISTER_CLASS(GLTFSkin);
GDREGISTER_CLASS(GLTFCamera);
GDREGISTER_CLASS(GLTFLight);
GDREGISTER_CLASS(GLTFSpecGloss);
GDREGISTER_CLASS(GLTFState);
GDREGISTER_CLASS(GLTFDocumentExtensionConvertImporterMesh);
GDREGISTER_CLASS(GLTFDocumentExtension);
GDREGISTER_CLASS(GLTFDocument);
GDREGISTER_CLASS(GLTFTexture);
#ifdef TOOLS_ENABLED
// Editor-specific API.
ClassDB::APIType prev_api = ClassDB::get_current_api();
ClassDB::set_current_api(ClassDB::API_EDITOR);
GDREGISTER_CLASS(GLTFMesh);
GDREGISTER_CLASS(EditorSceneFormatImporterGLTF);
EditorPlugins::add_by_type<SceneExporterGLTFPlugin>();
// Blend to glTF importer.
GLOBAL_DEF_RST("filesystem/import/blend/enabled", false); // Defined here to catch in docs.
GDREGISTER_CLASS(EditorSceneFormatImporterBlend);
ClassDB::set_current_api(prev_api);
EditorNode::add_init_callback(_editor_init);
#endif // TOOLS_ENABLED
}
void unregister_gltf_types() {