Skip to content

Commit

Permalink
Merge pull request #85448 from mxaddict/master
Browse files Browse the repository at this point in the history
Update `blender_path` behavior to require exact path to executable instead of trying to guess it
  • Loading branch information
akien-mga committed Jan 29, 2024
2 parents 0796d08 + ad106a2 commit 8febe50
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 120 deletions.
2 changes: 1 addition & 1 deletion doc/classes/EditorSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@
<member name="filesystem/file_dialog/thumbnail_size" type="int" setter="" getter="">
The thumbnail size to use in the editor's file dialogs (in pixels). See also [member docks/filesystem/thumbnail_size].
</member>
<member name="filesystem/import/blender/blender3_path" type="String" setter="" getter="">
<member name="filesystem/import/blender/blender_path" type="String" setter="" getter="">
The path to the directory containing the Blender executable used for converting the Blender 3D scene files [code].blend[/code] to glTF 2.0 format during import. Blender 3.0 or later is required.
To enable this feature for your specific project, use [member ProjectSettings.filesystem/import/blender/enabled].
</member>
Expand Down
2 changes: 1 addition & 1 deletion doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,7 @@
</member>
<member name="filesystem/import/blender/enabled" type="bool" setter="" getter="" default="true">
If [code]true[/code], Blender 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/blender/blender3_path[/code]. Blender 3.0 or later is required.
This requires configuring a path to a Blender executable in the editor settings at [code]filesystem/import/blender/blender_path[/code]. Blender 3.0 or later is required.
</member>
<member name="filesystem/import/blender/enabled.android" type="bool" setter="" getter="" default="false">
Override for [member filesystem/import/blender/enabled] on Android where Blender can't easily be accessed from Godot.
Expand Down
2 changes: 1 addition & 1 deletion editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "filesystem/file_dialog/thumbnail_size", 64, "32,128,16")

// Import (for glft module)
EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_DIR, "filesystem/import/blender/blender3_path", "", "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/import/blender/blender_path", "", "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "filesystem/import/blender/rpc_port", 6011, "0,65535,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "filesystem/import/blender/rpc_server_uptime", 5, "0,300,1,or_greater,suffix:s", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
EDITOR_SETTING_USAGE(Variant::STRING, PROPERTY_HINT_GLOBAL_FILE, "filesystem/import/fbx/fbx2gltf_path", "", "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</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/blender/blender3_path[/code] editor setting.
The location of the Blender binary is set via the [code]filesystem/import/blender/blender_path[/code] editor setting.
This importer is only used if [member ProjectSettings.filesystem/import/blender/enabled] is enabled, otherwise [code].blend[/code] files 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.
Expand Down
8 changes: 1 addition & 7 deletions modules/gltf/editor/editor_import_blend_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,7 @@ String dict_to_xmlrpc(const Dictionary &p_dict) {
}

Error EditorImportBlendRunner::start_blender(const String &p_python_script, bool p_blocking) {
String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path");

#ifdef WINDOWS_ENABLED
blender_path = blender_path.path_join("blender.exe");
#else
blender_path = blender_path.path_join("blender");
#endif
String blender_path = EDITOR_GET("filesystem/import/blender/blender_path");

List<String> args;
args.push_back("--background");
Expand Down
155 changes: 62 additions & 93 deletions modules/gltf/editor/editor_scene_importer_blend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,7 @@
#endif

static bool _get_blender_version(const String &p_path, int &r_major, int &r_minor, String *r_err = nullptr) {
String path = p_path;
#ifdef WINDOWS_ENABLED
path = path.path_join("blender.exe");
#else
path = path.path_join("blender");
#endif

#if defined(MACOS_ENABLED)
if (!FileAccess::exists(path)) {
path = p_path.path_join("Blender");
}
#endif

if (!FileAccess::exists(path)) {
if (!FileAccess::exists(p_path)) {
if (r_err) {
*r_err = TTR("Path does not contain a Blender installation.");
}
Expand All @@ -77,7 +64,7 @@ static bool _get_blender_version(const String &p_path, int &r_major, int &r_mino
List<String> args;
args.push_back("--version");
String pipe;
Error err = OS::get_singleton()->execute(path, args, &pipe);
Error err = OS::get_singleton()->execute(p_path, args, &pipe);
if (err != OK) {
if (r_err) {
*r_err = TTR("Can't execute Blender binary.");
Expand All @@ -87,7 +74,7 @@ static bool _get_blender_version(const String &p_path, int &r_major, int &r_mino
int bl = pipe.find("Blender ");
if (bl == -1) {
if (r_err) {
*r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s."), path);
*r_err = vformat(TTR("Unexpected --version output from Blender binary at: %s."), p_path);
}
return false;
}
Expand Down Expand Up @@ -126,7 +113,7 @@ void EditorSceneFormatImporterBlend::get_extensions(List<String> *r_extensions)
Node *EditorSceneFormatImporterBlend::import_scene(const String &p_path, uint32_t p_flags,
const HashMap<StringName, Variant> &p_options,
List<String> *r_missing_deps, Error *r_err) {
String blender_path = EDITOR_GET("filesystem/import/blender/blender3_path");
String blender_path = EDITOR_GET("filesystem/import/blender/blender_path");

if (blender_major_version == -1 || blender_minor_version == -1) {
_get_blender_version(blender_path, blender_major_version, blender_minor_version, nullptr);
Expand Down Expand Up @@ -369,7 +356,7 @@ static bool _test_blender_path(const String &p_path, String *r_err = nullptr) {
bool EditorFileSystemImportFormatSupportQueryBlend::is_active() const {
bool blend_enabled = GLOBAL_GET("filesystem/import/blender/enabled");

if (blend_enabled && !_test_blender_path(EDITOR_GET("filesystem/import/blender/blender3_path").operator String())) {
if (blend_enabled && !_test_blender_path(EDITOR_GET("filesystem/import/blender/blender_path").operator String())) {
// Intending to import Blender, but blend not configured.
return true;
}
Expand Down Expand Up @@ -409,11 +396,59 @@ void EditorFileSystemImportFormatSupportQueryBlend::_validate_path(String p_path
}
}

bool EditorFileSystemImportFormatSupportQueryBlend::_autodetect_path(String p_path) {
if (_test_blender_path(p_path)) {
auto_detected_path = p_path;
return true;
bool EditorFileSystemImportFormatSupportQueryBlend::_autodetect_path() {
// Autodetect
auto_detected_path = "";

#if defined(MACOS_ENABLED)
Vector<String> find_paths = {
"/opt/homebrew/bin/blender",
"/opt/local/bin/blender",
"/usr/local/bin/blender",
"/usr/local/opt/blender",
"/Applications/Blender.app/Contents/MacOS/Blender",
};
{
List<String> mdfind_args;
mdfind_args.push_back("kMDItemCFBundleIdentifier=org.blenderfoundation.blender");

String output;
Error err = OS::get_singleton()->execute("mdfind", mdfind_args, &output);
if (err == OK) {
for (const String &find_path : output.split("\n")) {
find_paths.push_back(find_path.path_join("Contents/MacOS/Blender"));
}
}
}
#elif defined(WINDOWS_ENABLED)
Vector<String> find_paths = {
"C:\\Program Files\\Blender Foundation\\blender.exe",
"C:\\Program Files (x86)\\Blender Foundation\\blender.exe",
};
{
char blender_opener_path[MAX_PATH];
DWORD path_len = MAX_PATH;
HRESULT res = AssocQueryString(0, ASSOCSTR_EXECUTABLE, ".blend", "open", blender_opener_path, &path_len);
if (res == S_OK) {
find_paths.push_back(String(blender_opener_path).get_base_dir().path_join("blender.exe"));
}
}

#elif defined(UNIX_ENABLED)
Vector<String> find_paths = {
"/usr/bin/blender",
"/usr/local/bin/blender",
"/opt/blender/bin/blender",
};
#endif

for (const String &find_path : find_paths) {
if (_test_blender_path(find_path)) {
auto_detected_path = find_path;
return true;
}
}

return false;
}

Expand All @@ -427,7 +462,7 @@ void EditorFileSystemImportFormatSupportQueryBlend::_select_install(String p_pat
}
void EditorFileSystemImportFormatSupportQueryBlend::_browse_install() {
if (blender_path->get_text() != String()) {
browse_dialog->set_current_dir(blender_path->get_text());
browse_dialog->set_current_file(blender_path->get_text());
}

browse_dialog->popup_centered_ratio();
Expand Down Expand Up @@ -479,76 +514,10 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {
EditorNode::get_singleton()->get_gui_base()->add_child(browse_dialog);
}

String path = EDITOR_GET("filesystem/import/blender/blender3_path");
String path = EDITOR_GET("filesystem/import/blender/blender_path");

if (path == "") {
// Autodetect
auto_detected_path = "";

#if defined(MACOS_ENABLED)

{
Vector<String> mdfind_paths;
{
List<String> mdfind_args;
mdfind_args.push_back("kMDItemCFBundleIdentifier=org.blenderfoundation.blender");

String output;
Error err = OS::get_singleton()->execute("mdfind", mdfind_args, &output);
if (err == OK) {
mdfind_paths = output.split("\n");
}
}

bool found = false;
for (const String &found_path : mdfind_paths) {
found = _autodetect_path(found_path.path_join("Contents/MacOS"));
if (found) {
break;
}
}
if (!found) {
found = _autodetect_path("/opt/homebrew/bin");
}
if (!found) {
found = _autodetect_path("/opt/local/bin");
}
if (!found) {
found = _autodetect_path("/usr/local/bin");
}
if (!found) {
found = _autodetect_path("/usr/local/opt");
}
if (!found) {
found = _autodetect_path("/Applications/Blender.app/Contents/MacOS");
}
}
#elif defined(WINDOWS_ENABLED)
{
char blender_opener_path[MAX_PATH];
DWORD path_len = MAX_PATH;
HRESULT res = AssocQueryString(0, ASSOCSTR_EXECUTABLE, ".blend", "open", blender_opener_path, &path_len);
if (res == S_OK && _autodetect_path(String(blender_opener_path).get_base_dir())) {
// Good.
} else if (_autodetect_path("C:\\Program Files\\Blender Foundation")) {
// Good.
} else {
_autodetect_path("C:\\Program Files (x86)\\Blender Foundation");
}
}

#elif defined(UNIX_ENABLED)
if (_autodetect_path("/usr/bin")) {
// Good.
} else if (_autodetect_path("/usr/local/bin")) {
// Good
} else {
_autodetect_path("/opt/blender/bin");
}
#endif
if (auto_detected_path != "") {
path = auto_detected_path;
}
if (path.is_empty() && _autodetect_path()) {
path = auto_detected_path;
}

blender_path->set_text(path);
Expand All @@ -569,7 +538,7 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() {

if (confirmed) {
// Can only confirm a valid path.
EditorSettings::get_singleton()->set("filesystem/import/blender/blender3_path", blender_path->get_text());
EditorSettings::get_singleton()->set("filesystem/import/blender/blender_path", blender_path->get_text());
EditorSettings::get_singleton()->save();
} else {
// Disable Blender import
Expand Down
2 changes: 1 addition & 1 deletion modules/gltf/editor/editor_scene_importer_blend.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class EditorFileSystemImportFormatSupportQueryBlend : public EditorFileSystemImp
String auto_detected_path;
void _validate_path(String p_path);

bool _autodetect_path(String p_path);
bool _autodetect_path();

void _path_confirmed();

Expand Down
46 changes: 31 additions & 15 deletions modules/gltf/register_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,39 @@ static void _editor_init() {

// Blend to glTF importer.

String blender_path = EDITOR_GET("filesystem/import/blender/blender_path");
if (blender_path.is_empty() && EditorSettings::get_singleton()->has_setting("filesystem/import/blender/blender3_path")) {
blender_path = EditorSettings::get_singleton()->get("filesystem/import/blender/blender3_path");

if (!blender_path.is_empty()) {
#if defined(MACOS_ENABLED)
if (blender_path.contains(".app")) {
blender_path += "/Contents/MacOS/Blender";
} else {
blender_path += "/blender";
}
#elif defined(WINDOWS_ENABLED)
blender_path += "\\blender.exe";
#elif defined(UNIX_ENABLED)
blender_path += "/blender";
#endif

EditorSettings::get_singleton()->set("filesystem/import/blender/blender_path", blender_path);
}

EditorSettings::get_singleton()->erase("filesystem/import/blender/blender3_path");
EditorSettings::get_singleton()->save();
}

bool blend_enabled = GLOBAL_GET("filesystem/import/blender/enabled");
String blender3_path = EDITOR_GET("filesystem/import/blender/blender3_path");
if (blend_enabled) {
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
if (blender3_path.is_empty()) {
WARN_PRINT(TTR("Blend file import is enabled in the project settings, but no Blender path is configured in the editor settings. Blend files will not be imported."));
} else if (!da->dir_exists(blender3_path)) {
WARN_PRINT(TTR("Blend file import is enabled, but the Blender path doesn't point to an accessible directory. Blend files will not be imported."));
} else {
Ref<EditorSceneFormatImporterBlend> importer;
importer.instantiate();
ResourceImporterScene::add_scene_importer(importer);

Ref<EditorFileSystemImportFormatSupportQueryBlend> blend_import_query;
blend_import_query.instantiate();
EditorFileSystem::get_singleton()->add_import_format_support_query(blend_import_query);
}
Ref<EditorSceneFormatImporterBlend> importer;
importer.instantiate();
ResourceImporterScene::add_scene_importer(importer);

Ref<EditorFileSystemImportFormatSupportQueryBlend> blend_import_query;
blend_import_query.instantiate();
EditorFileSystem::get_singleton()->add_import_format_support_query(blend_import_query);
}
memnew(EditorImportBlendRunner);
EditorNode::get_singleton()->add_child(EditorImportBlendRunner::get_singleton());
Expand Down

0 comments on commit 8febe50

Please sign in to comment.