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() else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-multichar -fno-exceptions") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-multichar -fno-exceptions")
endif() 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(ATHENA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/Athena/include)
set(LOG_VISOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/LogVisor/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(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) set(SQUISH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/extern/libSquish)
add_definitions(-DAS_USE_NAMESPACE=1 -DAS_NO_EXCEPTIONS=1) add_definitions(-DAS_USE_NAMESPACE=1 -DAS_NO_EXCEPTIONS=1)
add_subdirectory(extern) add_subdirectory(extern)

View File

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

View File

@ -13,6 +13,14 @@
#include <functional> #include <functional>
#include <mutex> #include <mutex>
#include "HECL/HECL.hpp"
namespace HECL
{
extern LogVisor::LogModule BlenderLog;
extern class BlenderConnection* SharedBlenderConnection;
class BlenderConnection class BlenderConnection
{ {
std::mutex m_lock; std::mutex m_lock;
@ -35,7 +43,8 @@ public:
BlenderConnection(bool silenceBlender=false); BlenderConnection(bool silenceBlender=false);
~BlenderConnection(); ~BlenderConnection();
bool openBlend(const std::string& path); bool createBlend(const SystemString& path);
bool openBlend(const SystemString& path);
enum CookPlatform enum CookPlatform
{ {
CP_MODERN = 0, CP_MODERN = 0,
@ -54,23 +63,34 @@ public:
struct StreamBuf : std::streambuf struct StreamBuf : std::streambuf
{ {
BlenderConnection* m_parent; BlenderConnection* m_parent;
std::string m_lineBuf;
StreamBuf(BlenderConnection* parent) : m_parent(parent) {} StreamBuf(BlenderConnection* parent) : m_parent(parent) {}
StreamBuf(const StreamBuf& other) = delete; StreamBuf(const StreamBuf& other) = delete;
StreamBuf(StreamBuf&& other) = default; StreamBuf(StreamBuf&& other) = default;
int_type overflow(int_type ch) int_type overflow(int_type ch)
{ {
if (ch != traits_type::eof()) if (ch != traits_type::eof() && ch != '\n')
{ {
char_type chi = ch; m_lineBuf += char_type(ch);
m_parent->_writeBuf(&chi, 1); 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; return ch;
} }
} m_sbuf; } m_sbuf;
PyOutStream(BlenderConnection* parent) PyOutStream(BlenderConnection* parent)
: m_lk(parent->m_lock), m_parent(parent), m_sbuf(parent), std::ostream(&m_sbuf) : 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: public:
PyOutStream(const PyOutStream& other) = delete; PyOutStream(const PyOutStream& other) = delete;
@ -80,7 +100,13 @@ public:
~PyOutStream() ~PyOutStream()
{ {
if (m_parent) 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() inline PyOutStream beginPythonOut()
@ -89,6 +115,20 @@ public:
} }
void quitBlender(); void quitBlender();
static inline BlenderConnection& SharedConnection()
{
if (!SharedBlenderConnection)
SharedBlenderConnection = new BlenderConnection();
return *SharedBlenderConnection;
}
static inline void Shutdown()
{
delete SharedBlenderConnection;
}
}; };
}
#endif // BLENDERCONNECTION_HPP #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 add_library(HECLBlender
BlenderConnection.cpp BlenderConnection.cpp
BlenderConnection.hpp) BlenderConnection.hpp
blendershell.py
${PY_SOURCES})

View File

@ -55,6 +55,33 @@ while True:
else: else:
writepipeline(b'CANCELLED') 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: else:
hecl.command(cmdline, writepipeline, writepipebuf) hecl.command(cmdline, writepipeline, writepipebuf)

View File

@ -31,5 +31,6 @@ endif()
target_link_libraries(hecl target_link_libraries(hecl
${WHOLE_START} HECLDatabaseInit ${DATA_SPEC_LIBS} ${WHOLE_END} ${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) ToolExtract(const ToolPassInfo& info)
: ToolBase(info) : ToolBase(info)
{ {
if (!info.project)
LogModule.report(LogVisor::FatalError, "hecl extract must be ran within a project directory");
if (!m_info.args.size()) if (!m_info.args.size())
LogModule.report(LogVisor::FatalError, "hecl extract needs a source path as its first argument"); 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.srcpath = m_info.args[0];
m_einfo.extractArgs.reserve(info.args.size() - 1); m_einfo.extractArgs.reserve(info.args.size() - 1);
m_einfo.force = info.force; m_einfo.force = info.force;

View File

@ -9,6 +9,7 @@
#include <regex> #include <regex>
#include <list> #include <list>
#include "HECL/Database.hpp" #include "HECL/Database.hpp"
#include "../blender/BlenderConnection.hpp"
#include "LogVisor/LogVisor.hpp" #include "LogVisor/LogVisor.hpp"
LogVisor::LogModule LogModule("HECLDriver"); 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 regVERBOSE(_S("-v(v*)"), std::regex::ECMAScript|std::regex::optimize);
static const HECL::SystemRegex regFORCE(_S("-f"), 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 LogVisor::LogModule AthenaLog("Athena");
static void AthenaExc(const Athena::error::Level& level, const char* file, static void AthenaExc(const Athena::error::Level& level, const char* file,
const char*, int line, const char* fmt, ...) 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_list ap;
va_start(ap, fmt); va_start(ap, fmt);
AthenaLog.reportSource(vLevel, file, line, fmt, ap); AthenaLog.reportSource(LogVisor::Level(level), file, line, fmt, ap);
va_end(ap); va_end(ap);
} }
@ -105,9 +89,6 @@ int main(int argc, const char** argv)
LogVisor::RegisterConsoleLogger(); LogVisor::RegisterConsoleLogger();
atSetExceptionHandler(AthenaExc); atSetExceptionHandler(AthenaExc);
//CBlenderConnection bconn(false);
//return 0;
/* Basic usage check */ /* Basic usage check */
if (argc == 1) if (argc == 1)
{ {
@ -265,12 +246,14 @@ int main(int argc, const char** argv)
int retval = tool->run(); int retval = tool->run();
if (LogVisor::ErrorCount > ErrorRef) if (LogVisor::ErrorCount > ErrorRef)
{ {
HECL::BlenderConnection::Shutdown();
#if WIN_PAUSE #if WIN_PAUSE
system("PAUSE"); system("PAUSE");
#endif #endif
return -1; return -1;
} }
HECL::BlenderConnection::Shutdown();
#if WIN_PAUSE #if WIN_PAUSE
system("PAUSE"); system("PAUSE");
#endif #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}) include_directories(${ZLIB_INCLUDE_DIR})
add_library(png add_library(png
png.h png.h
@ -23,3 +29,6 @@ add_library(png
pngwrite.c pngwrite.c
pngwtran.c pngwtran.c
pngwutil.c) pngwutil.c)
set(LIBPNG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "PNG include path" FORCE)
endif()