Add ability to search for blender version dynamically

This commit is contained in:
Phillip Stephens 2021-02-21 18:49:40 -08:00
parent 77bef70555
commit 8fc39c4ce6
3 changed files with 99 additions and 83 deletions

View File

@ -57,7 +57,7 @@ class PathHasher:
read_str = readpipestr() read_str = readpipestr()
return int(read_str[0:8], 16) return int(read_str[0:8], 16)
# Ensure Blender 2.90 is being used # Ensure Blender 2.90+ is being used
if bpy.app.version < (2, 90, 0): if bpy.app.version < (2, 90, 0):
writepipestr(b'NOT290') writepipestr(b'NOT290')
_quitblender() _quitblender()

2
hecl/extern/athena vendored

@ -1 +1 @@
Subproject commit 1805568808e8c78450365fef7d55cf7d0c985ab0 Subproject commit 1d0727fae08bf0c8260174015e3b74679b2eb6f0

View File

@ -48,6 +48,11 @@ using namespace std::literals;
namespace hecl::blender { namespace hecl::blender {
static const uint32_t MinBlenderMajorSearch = 2;
static const uint32_t MaxBlenderMajorSearch = 2;
static const uint32_t MinBlenderMinorSearch = 90;
static const uint32_t MaxBlenderMinorSearch = 91;
logvisor::Module BlenderLog("hecl::blender::Connection"); logvisor::Module BlenderLog("hecl::blender::Connection");
Token SharedBlenderToken; Token SharedBlenderToken;
@ -342,6 +347,7 @@ Connection::Connection(int verbosityLevel) {
/* User-specified blender path */ /* User-specified blender path */
#if _WIN32 #if _WIN32
wchar_t BLENDER_BIN_BUF[2048];
std::wstring blenderBinBuf; std::wstring blenderBinBuf;
const wchar_t* blenderBin = _wgetenv(L"BLENDER_BIN"); const wchar_t* blenderBin = _wgetenv(L"BLENDER_BIN");
#else #else
@ -364,12 +370,24 @@ Connection::Connection(int verbosityLevel) {
if (!RegFileExists(blenderBin)) { if (!RegFileExists(blenderBin)) {
/* No steam; try default */ /* No steam; try default */
wchar_t progFiles[256]; wchar_t progFiles[256];
if (!GetEnvironmentVariableW(L"ProgramFiles", progFiles, 256)) if (GetEnvironmentVariableW(L"ProgramFiles", progFiles, 256)) {
BlenderLog.report(logvisor::Fatal, FMT_STRING(L"unable to determine 'Program Files' path")); for (size_t major = MinBlenderMajorSearch; major <= MaxBlenderMajorSearch; ++major) {
blenderBinBuf = fmt::format(FMT_STRING(L"{}\\Blender Foundation\\Blender 2.90\\blender.exe"), progFiles); bool found = false;
blenderBin = blenderBinBuf.c_str(); for (size_t minor = MinBlenderMinorSearch; minor <= MaxBlenderMinorSearch; ++minor) {
if (!RegFileExists(blenderBin)) _snwprintf(BLENDER_BIN_BUF, 2048, L"%s\\Blender Foundation\\Blender %i.%i\\blender.exe", progFiles, major,
BlenderLog.report(logvisor::Fatal, FMT_STRING(L"unable to find {}"), blenderBin); minor);
if (RegFileExists(BLENDER_BIN_BUF)) {
blenderBin = BLENDER_BIN_BUF;
found = true;
break;
}
}
if (found) {
break;
}
}
}
} }
} }
@ -395,7 +413,8 @@ Connection::Connection(int verbosityLevel) {
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0,
nullptr); nullptr);
BlenderLog.report(logvisor::Fatal, FMT_STRING(L"unable to launch blender from {}: {}"), blenderBin, messageBuffer); BlenderLog.report(logvisor::Fatal, FMT_STRING(L"unable to launch blender from {}: {}"), blenderBin,
messageBuffer);
} }
close(m_writepipe[0]); close(m_writepipe[0]);
@ -417,7 +436,8 @@ Connection::Connection(int verbosityLevel) {
if (err == ERROR_BROKEN_PIPE) if (err == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path. break; // pipe done - normal exit path.
else else
BlenderLog.report(logvisor::Error, FMT_STRING("Error with ReadFile: {:08X}"), err); // Something bad happened. BlenderLog.report(logvisor::Error, FMT_STRING("Error with ReadFile: {:08X}"),
err); // Something bad happened.
} }
// Display the character read on the screen. // Display the character read on the screen.
@ -623,14 +643,14 @@ std::streamsize PyOutStream::StreamBuf::xsputn(const char_type* __first, std::st
return __n; return __n;
} }
constexpr std::array<std::string_view, 12> BlendTypeStrs{ constexpr std::array<std::string_view, 12> BlendTypeStrs{"NONE"sv, "MESH"sv, "CMESH"sv, "ARMATURE"sv,
"NONE"sv, "MESH"sv, "CMESH"sv, "ARMATURE"sv, "ACTOR"sv, "AREA"sv, "ACTOR"sv, "AREA"sv, "WORLD"sv, "MAPAREA"sv,
"WORLD"sv, "MAPAREA"sv, "MAPUNIVERSE"sv, "FRAME"sv, "PATH"sv "MAPUNIVERSE"sv, "FRAME"sv, "PATH"sv};
};
bool Connection::createBlend(const ProjectPath& path, BlendType type) { bool Connection::createBlend(const ProjectPath& path, BlendType type) {
if (m_lock) { if (m_lock) {
BlenderLog.report(logvisor::Fatal, FMT_STRING("BlenderConnection::createBlend() musn't be called with stream active")); BlenderLog.report(logvisor::Fatal,
FMT_STRING("BlenderConnection::createBlend() musn't be called with stream active"));
return false; return false;
} }
_writeStr(fmt::format(FMT_STRING("CREATE \"{}\" {}"), path.getAbsolutePathUTF8(), BlendTypeStrs[int(type)])); _writeStr(fmt::format(FMT_STRING("CREATE \"{}\" {}"), path.getAbsolutePathUTF8(), BlendTypeStrs[int(type)]));
@ -646,7 +666,8 @@ bool Connection::createBlend(const ProjectPath& path, BlendType type) {
bool Connection::openBlend(const ProjectPath& path, bool force) { bool Connection::openBlend(const ProjectPath& path, bool force) {
if (m_lock) { if (m_lock) {
BlenderLog.report(logvisor::Fatal, FMT_STRING("BlenderConnection::openBlend() musn't be called with stream active")); BlenderLog.report(logvisor::Fatal,
FMT_STRING("BlenderConnection::openBlend() musn't be called with stream active"));
return false; return false;
} }
if (!force && path == m_loadedBlend) if (!force && path == m_loadedBlend)
@ -678,7 +699,8 @@ bool Connection::openBlend(const ProjectPath& path, bool force) {
bool Connection::saveBlend() { bool Connection::saveBlend() {
if (m_lock) { if (m_lock) {
BlenderLog.report(logvisor::Fatal, FMT_STRING("BlenderConnection::saveBlend() musn't be called with stream active")); BlenderLog.report(logvisor::Fatal,
FMT_STRING("BlenderConnection::saveBlend() musn't be called with stream active"));
return false; return false;
} }
_writeStr("SAVE"); _writeStr("SAVE");
@ -710,7 +732,8 @@ void PyOutStream::close() {
} }
void PyOutStream::linkBlend(std::string_view target, std::string_view objName, bool link) { void PyOutStream::linkBlend(std::string_view target, std::string_view objName, bool link) {
format(FMT_STRING("if '{}' not in bpy.data.scenes:\n" format(
FMT_STRING("if '{}' not in bpy.data.scenes:\n"
" with bpy.data.libraries.load('''{}''', link={}, relative=True) as (data_from, data_to):\n" " with bpy.data.libraries.load('''{}''', link={}, relative=True) as (data_from, data_to):\n"
" data_to.scenes = data_from.scenes\n" " data_to.scenes = data_from.scenes\n"
" obj_scene = None\n" " obj_scene = None\n"
@ -731,7 +754,8 @@ void PyOutStream::linkBlend(std::string_view target, std::string_view objName, b
} }
void PyOutStream::linkArmature(std::string_view target, std::string_view armName) { void PyOutStream::linkArmature(std::string_view target, std::string_view armName) {
format(FMT_STRING("target_arm_name = '{}'\n" format(FMT_STRING(
"target_arm_name = '{}'\n"
"if target_arm_name not in bpy.data.armatures:\n" "if target_arm_name not in bpy.data.armatures:\n"
" with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n" " with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n"
" if target_arm_name not in data_from.armatures:\n" " if target_arm_name not in data_from.armatures:\n"
@ -745,7 +769,8 @@ void PyOutStream::linkArmature(std::string_view target, std::string_view armName
} }
void PyOutStream::linkMesh(std::string_view target, std::string_view meshName) { void PyOutStream::linkMesh(std::string_view target, std::string_view meshName) {
format(FMT_STRING("target_mesh_name = '{}'\n" format(FMT_STRING(
"target_mesh_name = '{}'\n"
"if target_mesh_name not in bpy.data.objects:\n" "if target_mesh_name not in bpy.data.objects:\n"
" with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n" " with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n"
" if target_mesh_name not in data_from.objects:\n" " if target_mesh_name not in data_from.objects:\n"
@ -770,7 +795,8 @@ void PyOutStream::linkBackground(std::string_view target, std::string_view scene
"bpy.context.scene.background_set = obj_scene\n"), "bpy.context.scene.background_set = obj_scene\n"),
target, target); target, target);
} else { } else {
format(FMT_STRING("if '{}' not in bpy.data.scenes:\n" format(FMT_STRING(
"if '{}' not in bpy.data.scenes:\n"
" with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n" " with bpy.data.libraries.load('''{}''', link=True, relative=True) as (data_from, data_to):\n"
" data_to.scenes = data_from.scenes\n" " data_to.scenes = data_from.scenes\n"
" obj_scene = None\n" " obj_scene = None\n"
@ -900,9 +926,7 @@ void Mesh::normalizeSkinBinds() {
Mesh::Mesh(Connection& conn, HMDLTopology topologyIn, int skinSlotCount, bool useLuvs) Mesh::Mesh(Connection& conn, HMDLTopology topologyIn, int skinSlotCount, bool useLuvs)
: topology(topologyIn), sceneXf(conn), aabbMin(conn), aabbMax(conn) { : topology(topologyIn), sceneXf(conn), aabbMin(conn), aabbMax(conn) {
conn._readVectorFunc(materialSets, [&]() { conn._readVectorFunc(materialSets, [&]() { conn._readVector(materialSets.emplace_back()); });
conn._readVector(materialSets.emplace_back());
});
MeshOptimizer opt(conn, materialSets[0], useLuvs); MeshOptimizer opt(conn, materialSets[0], useLuvs);
opt.optimize(*this, skinSlotCount); opt.optimize(*this, skinSlotCount);
@ -1137,9 +1161,7 @@ World::Area::Area(Connection& conn) {
conn._readVector(docks); conn._readVector(docks);
} }
World::World(Connection& conn) { World::World(Connection& conn) { conn._readVector(areas); }
conn._readVector(areas);
}
Light::Light(Connection& conn) : sceneXf(conn), color(conn) { Light::Light(Connection& conn) : sceneXf(conn), color(conn) {
conn._readBuf(&layer, 29); conn._readBuf(&layer, 29);
@ -1197,9 +1219,7 @@ Actor::Actor(Connection& conn) {
conn._readVector(actions); conn._readVector(actions);
} }
PathMesh::PathMesh(Connection& conn) { PathMesh::PathMesh(Connection& conn) { conn._readVector(data); }
conn._readVector(data);
}
const Bone* Armature::lookupBone(const char* name) const { const Bone* Armature::lookupBone(const char* name) const {
for (const Bone& b : bones) for (const Bone& b : bones)
@ -1230,9 +1250,7 @@ const Bone* Armature::getRoot() const {
return nullptr; return nullptr;
} }
Armature::Armature(Connection& conn) { Armature::Armature(Connection& conn) { conn._readVector(bones); }
conn._readVector(bones);
}
Bone::Bone(Connection& conn) { Bone::Bone(Connection& conn) {
name = conn._readStdString(); name = conn._readStdString();
@ -1452,9 +1470,7 @@ std::vector<ProjectPath> DataStream::getTextures() {
m_parent->_checkOk("unable to get textures"sv); m_parent->_checkOk("unable to get textures"sv);
std::vector<ProjectPath> texs; std::vector<ProjectPath> texs;
m_parent->_readVectorFunc(texs, [&]() { m_parent->_readVectorFunc(texs, [&]() { texs.push_back(m_parent->_readPath()); });
texs.push_back(m_parent->_readPath());
});
return texs; return texs;
} }