BlenderConnection updates

This commit is contained in:
Jack Andersen 2015-07-27 16:25:33 -10:00
parent 873eba1183
commit 17522ff48f
11 changed files with 152 additions and 50 deletions

View File

@ -5,11 +5,10 @@ add_definitions(-DUNICODE=1 -D_UNICODE=1 -D_CRT_SECURE_NO_WARNINGS=1 /wd4267 /wd
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-multichar -fno-exceptions")
endif()
set(HECL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
list(APPEND HECL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/blender)
set(ATHENA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/Athena/include)
set(LOG_VISOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/LogVisor/include)
set(ANGELSCRIPT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/AngelScript/angelscript/include)
set(LIBPNG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/libpng)
set(SQUISH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/libSquish)
add_definitions(-DAS_USE_NAMESPACE=1 -DAS_NO_EXCEPTIONS=1)
add_subdirectory(extern)

View File

@ -9,7 +9,11 @@
#include <LogVisor/LogVisor.hpp>
#include "BlenderConnection.hpp"
static LogVisor::LogModule Log("BlenderConnection");
namespace HECL
{
LogVisor::LogModule BlenderLog("BlenderConnection");
BlenderConnection* SharedBlenderConnection = nullptr;
#ifdef __APPLE__
#define DEFAULT_BLENDER_BIN "/Applications/Blender.app/Contents/MacOS/blender"
@ -28,7 +32,7 @@ size_t BlenderConnection::_readLine(char* buf, size_t bufSz)
{
if (readBytes >= bufSz)
{
Log.report(LogVisor::FatalError, "Pipe buffer overrun\n");
BlenderLog.report(LogVisor::FatalError, "Pipe buffer overrun\n");
*(buf-1) = '\0';
return bufSz - 1;
}
@ -58,7 +62,7 @@ size_t BlenderConnection::_readLine(char* buf, size_t bufSz)
}
}
err:
Log.report(LogVisor::FatalError, strerror(errno));
BlenderLog.report(LogVisor::FatalError, strerror(errno));
return 0;
}
@ -81,7 +85,7 @@ size_t BlenderConnection::_writeLine(const char* buf)
#endif
return (size_t)ret;
err:
Log.report(LogVisor::FatalError, strerror(errno));
BlenderLog.report(LogVisor::FatalError, strerror(errno));
return 0;
}
@ -98,7 +102,7 @@ size_t BlenderConnection::_readBuf(char* buf, size_t len)
#endif
return ret;
err:
Log.report(LogVisor::FatalError, strerror(errno));
BlenderLog.report(LogVisor::FatalError, strerror(errno));
return 0;
}
@ -115,7 +119,7 @@ size_t BlenderConnection::_writeBuf(const char* buf, size_t len)
#endif
return ret;
err:
Log.report(LogVisor::FatalError, strerror(errno));
BlenderLog.report(LogVisor::FatalError, strerror(errno));
return 0;
}
@ -257,27 +261,27 @@ BlenderConnection::BlenderConnection(bool silenceBlender)
if (!strcmp(lineBuf, "NOLAUNCH"))
{
_closePipe();
Log.report(LogVisor::FatalError, "Unable to launch blender");
BlenderLog.report(LogVisor::FatalError, "Unable to launch blender");
}
else if (!strcmp(lineBuf, "NOBLENDER"))
{
_closePipe();
if (blenderBin)
Log.report(LogVisor::FatalError, _S("Unable to find blender at '%s' or '%s'"),
BlenderLog.report(LogVisor::FatalError, _S("Unable to find blender at '%s' or '%s'"),
blenderBin, DEFAULT_BLENDER_BIN);
else
Log.report(LogVisor::FatalError, _S("Unable to find blender at '%s'"),
BlenderLog.report(LogVisor::FatalError, _S("Unable to find blender at '%s'"),
DEFAULT_BLENDER_BIN);
}
else if (!strcmp(lineBuf, "NOADDON"))
{
_closePipe();
Log.report(LogVisor::FatalError, "HECL addon not installed within blender");
BlenderLog.report(LogVisor::FatalError, "HECL addon not installed within blender");
}
else if (strcmp(lineBuf, "READY"))
{
_closePipe();
Log.report(LogVisor::FatalError, "read '%s' from blender; expected 'READY'", lineBuf);
BlenderLog.report(LogVisor::FatalError, "read '%s' from blender; expected 'READY'", lineBuf);
}
_writeLine("ACK");
@ -288,7 +292,20 @@ BlenderConnection::~BlenderConnection()
_closePipe();
}
bool BlenderConnection::openBlend(const std::string& path)
bool BlenderConnection::createBlend(const SystemString& path)
{
_writeLine(("CREATE" + path).c_str());
char lineBuf[256];
_readLine(lineBuf, sizeof(lineBuf));
if (!strcmp(lineBuf, "FINISHED"))
{
m_loadedBlend = path;
return true;
}
return false;
}
bool BlenderConnection::openBlend(const SystemString& path)
{
_writeLine(("OPEN" + path).c_str());
char lineBuf[256];
@ -313,7 +330,7 @@ bool BlenderConnection::cookBlend(std::function<char*(uint32_t)> bufGetter,
_readLine(lineBuf, sizeof(lineBuf));
if (strcmp(expectedType.c_str(), lineBuf))
{
Log.report(LogVisor::Error, "expected '%s' to contain '%s' not '%s'",
BlenderLog.report(LogVisor::Error, "expected '%s' to contain '%s' not '%s'",
m_loadedBlend.c_str(), expectedType.c_str(), lineBuf);
return false;
}
@ -331,7 +348,7 @@ bool BlenderConnection::cookBlend(std::function<char*(uint32_t)> bufGetter,
if (!strcmp("SUCCESS", lineBuf))
return true;
else if (!strcmp("EXCEPTION", lineBuf))
Log.report(LogVisor::FatalError, "blender script exception");
BlenderLog.report(LogVisor::FatalError, "blender script exception");
return false;
}
@ -342,3 +359,5 @@ void BlenderConnection::quitBlender()
char lineBuf[256];
_readLine(lineBuf, sizeof(lineBuf));
}
}

View File

@ -13,6 +13,14 @@
#include <functional>
#include <mutex>
#include "HECL/HECL.hpp"
namespace HECL
{
extern LogVisor::LogModule BlenderLog;
extern class BlenderConnection* SharedBlenderConnection;
class BlenderConnection
{
std::mutex m_lock;
@ -35,7 +43,8 @@ public:
BlenderConnection(bool silenceBlender=false);
~BlenderConnection();
bool openBlend(const std::string& path);
bool createBlend(const SystemString& path);
bool openBlend(const SystemString& path);
enum CookPlatform
{
CP_MODERN = 0,
@ -54,23 +63,34 @@ public:
struct StreamBuf : std::streambuf
{
BlenderConnection* m_parent;
std::string m_lineBuf;
StreamBuf(BlenderConnection* parent) : m_parent(parent) {}
StreamBuf(const StreamBuf& other) = delete;
StreamBuf(StreamBuf&& other) = default;
int_type overflow(int_type ch)
{
if (ch != traits_type::eof())
if (ch != traits_type::eof() && ch != '\n')
{
char_type chi = ch;
m_parent->_writeBuf(&chi, 1);
m_lineBuf += char_type(ch);
return ch;
}
m_parent->_writeLine(m_lineBuf.c_str());
char readBuf[16];
m_parent->_readLine(readBuf, 16);
if (strcmp(readBuf, "OK"))
BlenderLog.report(LogVisor::FatalError, "error sending '%s' to blender", m_lineBuf.c_str());
m_lineBuf.clear();
return ch;
}
} m_sbuf;
PyOutStream(BlenderConnection* parent)
: m_lk(parent->m_lock), m_parent(parent), m_sbuf(parent), std::ostream(&m_sbuf)
{
m_parent->_writeBuf("\033PYBEGIN\n", 9);
m_parent->_writeLine("PYBEGIN");
char readBuf[16];
m_parent->_readLine(readBuf, 16);
if (strcmp(readBuf, "READY"))
BlenderLog.report(LogVisor::FatalError, "unable to open PyOutStream with blender");
}
public:
PyOutStream(const PyOutStream& other) = delete;
@ -80,7 +100,13 @@ public:
~PyOutStream()
{
if (m_parent)
m_parent->_writeBuf("\033PYEND\n", 7);
{
m_parent->_writeLine("PYEND");
char readBuf[16];
m_parent->_readLine(readBuf, 16);
if (strcmp(readBuf, "DONE"))
BlenderLog.report(LogVisor::FatalError, "unable to close PyOutStream with blender");
}
}
};
inline PyOutStream beginPythonOut()
@ -89,6 +115,20 @@ public:
}
void quitBlender();
static inline BlenderConnection& SharedConnection()
{
if (!SharedBlenderConnection)
SharedBlenderConnection = new BlenderConnection();
return *SharedBlenderConnection;
}
static inline void Shutdown()
{
delete SharedBlenderConnection;
}
};
}
#endif // BLENDERCONNECTION_HPP

View File

@ -1,3 +1,17 @@
list(APPEND PY_SOURCES
addon/__init__.py
addon/hmdl/__init__.py
addon/hmdl/HMDLMesh.py
addon/hmdl/HMDLShader.py
addon/hmdl/HMDLSkin.py
addon/hmdl/HMDLTxtr.py
addon/sact/__init__.py
addon/sact/SACTAction.py
addon/sact/SACTEvent.py
addon/sact/SACTSubtype.py)
add_library(HECLBlender
BlenderConnection.cpp
BlenderConnection.hpp)
BlenderConnection.hpp
blendershell.py
${PY_SOURCES})

View File

@ -55,6 +55,33 @@ while True:
else:
writepipeline(b'CANCELLED')
elif cmdline[0] == b'CREATE':
bpy.context.user_preferences.filepaths.save_version = 0
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=cmdline[1].decode()):
writepipeline(b'FINISHED')
else:
writepipeline(b'CANCELLED')
elif cmdline[0] == b'PYBEGIN':
writepipeline(b'READY')
globals = dict()
locals = dict()
while True:
try:
line = readpipeline()
if line == b'PYEND':
writepipeline(b'DONE')
break
co = compile(line+'\n', '<HECL>', 'single')
exec(co, globals, locals)
except Exception as e:
writepipeline(b'EXCEPTION')
break
writepipeline(b'OK')
elif cmdline[0] == b'PYEND':
writepipeline(b'ERROR')
else:
hecl.command(cmdline, writepipeline, writepipebuf)

View File

@ -31,5 +31,6 @@ endif()
target_link_libraries(hecl
${WHOLE_START} HECLDatabaseInit ${DATA_SPEC_LIBS} ${WHOLE_END}
HECLDatabase HECLCommon AthenaCore AngelScript NOD LogVisor png squish blowfish z lzo2
HECLDatabase HECLBlender HECLCommon AthenaCore AngelScript NOD
LogVisor png squish blowfish z lzo2
)

View File

@ -22,11 +22,21 @@ public:
ToolExtract(const ToolPassInfo& info)
: ToolBase(info)
{
if (!info.project)
LogModule.report(LogVisor::FatalError, "hecl extract must be ran within a project directory");
if (!m_info.args.size())
LogModule.report(LogVisor::FatalError, "hecl extract needs a source path as its first argument");
if (!info.project)
{
/* Get name from input file and init project there */
std::string baseFile = info.args[0];
size_t slashPos = baseFile.rfind(_S('/'));
if (slashPos == HECL::SystemString::npos)
slashPos = baseFile.rfind(_S('\\'));
if (slashPos != HECL::SystemString::npos)
baseFile.assign(baseFile.g
LogModule.report(LogVisor::FatalError, "hecl extract must be ran within a project directory");
}
m_einfo.srcpath = m_info.args[0];
m_einfo.extractArgs.reserve(info.args.size() - 1);
m_einfo.force = info.force;

View File

@ -9,6 +9,7 @@
#include <regex>
#include <list>
#include "HECL/Database.hpp"
#include "../blender/BlenderConnection.hpp"
#include "LogVisor/LogVisor.hpp"
LogVisor::LogModule LogModule("HECLDriver");
@ -64,30 +65,13 @@ static const HECL::SystemRegex regOPEN(_S("-o([^\"]*|\\S*)"), std::regex::ECMASc
static const HECL::SystemRegex regVERBOSE(_S("-v(v*)"), std::regex::ECMAScript|std::regex::optimize);
static const HECL::SystemRegex regFORCE(_S("-f"), std::regex::ECMAScript|std::regex::optimize);
#include "../blender/BlenderConnection.hpp"
static LogVisor::LogModule AthenaLog("Athena");
static void AthenaExc(const Athena::error::Level& level, const char* file,
const char*, int line, const char* fmt, ...)
{
LogVisor::Level vLevel = LogVisor::Info;
switch (level)
{
case Athena::error::MESSAGE:
vLevel = LogVisor::Info;
break;
case Athena::error::WARNING:
vLevel = LogVisor::Warning;
break;
case Athena::error::ERROR:
vLevel = LogVisor::Error;
break;
case Athena::error::FATAL:
vLevel = LogVisor::FatalError;
}
va_list ap;
va_start(ap, fmt);
AthenaLog.reportSource(vLevel, file, line, fmt, ap);
AthenaLog.reportSource(LogVisor::Level(level), file, line, fmt, ap);
va_end(ap);
}
@ -105,9 +89,6 @@ int main(int argc, const char** argv)
LogVisor::RegisterConsoleLogger();
atSetExceptionHandler(AthenaExc);
//CBlenderConnection bconn(false);
//return 0;
/* Basic usage check */
if (argc == 1)
{
@ -265,12 +246,14 @@ int main(int argc, const char** argv)
int retval = tool->run();
if (LogVisor::ErrorCount > ErrorRef)
{
HECL::BlenderConnection::Shutdown();
#if WIN_PAUSE
system("PAUSE");
#endif
return -1;
}
HECL::BlenderConnection::Shutdown();
#if WIN_PAUSE
system("PAUSE");
#endif

2
hecl/extern/Athena vendored

@ -1 +1 @@
Subproject commit 99b6df7cc1192f95f64acb531bf6ab7ea2cdabeb
Subproject commit 83cc8fe3c35c23cfdb207a2267cf73a0e7d014da

@ -1 +1 @@
Subproject commit 450a53fd246cb1dd815acf272604137d9a00ac2a
Subproject commit 80cc3cc277c57d86d9bc8ef2784f68ad95028e9c

View File

@ -1,3 +1,9 @@
if(NOT WIN32)
find_library(PNG_LIB png)
endif()
if(WIN32 OR PNG_LIB STREQUAL PNG_LIB-NOTFOUND)
message("-- Using HECL's built-in libpng")
include_directories(${ZLIB_INCLUDE_DIR})
add_library(png
png.h
@ -23,3 +29,6 @@ add_library(png
pngwrite.c
pngwtran.c
pngwutil.c)
set(LIBPNG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "PNG include path" FORCE)
endif()