blender interface updates

This commit is contained in:
Jack Andersen 2015-08-05 12:59:59 -10:00
parent 31aa40cc77
commit 807b42d475
10 changed files with 134 additions and 49 deletions

View File

@ -313,6 +313,13 @@ BlenderConnection::~BlenderConnection()
bool BlenderConnection::createBlend(const SystemString& path) bool BlenderConnection::createBlend(const SystemString& path)
{ {
std::unique_lock<std::mutex> lk(m_lock, std::try_to_lock);
if (!lk)
{
BlenderLog.report(LogVisor::FatalError,
"BlenderConnection::createBlend() musn't be called with stream active");
return false;
}
HECL::SystemUTF8View pathView(path); HECL::SystemUTF8View pathView(path);
_writeLine(("CREATE \"" + pathView.str() + "\"").c_str()); _writeLine(("CREATE \"" + pathView.str() + "\"").c_str());
char lineBuf[256]; char lineBuf[256];
@ -327,6 +334,13 @@ bool BlenderConnection::createBlend(const SystemString& path)
bool BlenderConnection::openBlend(const SystemString& path) bool BlenderConnection::openBlend(const SystemString& path)
{ {
std::unique_lock<std::mutex> lk(m_lock, std::try_to_lock);
if (!lk)
{
BlenderLog.report(LogVisor::FatalError,
"BlenderConnection::openBlend() musn't be called with stream active");
return false;
}
HECL::SystemUTF8View pathView(path); HECL::SystemUTF8View pathView(path);
_writeLine(("OPEN \"" + pathView.str() + "\"").c_str()); _writeLine(("OPEN \"" + pathView.str() + "\"").c_str());
char lineBuf[256]; char lineBuf[256];
@ -341,6 +355,13 @@ bool BlenderConnection::openBlend(const SystemString& path)
bool BlenderConnection::saveBlend() bool BlenderConnection::saveBlend()
{ {
std::unique_lock<std::mutex> lk(m_lock, std::try_to_lock);
if (!lk)
{
BlenderLog.report(LogVisor::FatalError,
"BlenderConnection::saveBlend() musn't be called with stream active");
return false;
}
_writeLine("SAVE"); _writeLine("SAVE");
char lineBuf[256]; char lineBuf[256];
_readLine(lineBuf, sizeof(lineBuf)); _readLine(lineBuf, sizeof(lineBuf));
@ -349,12 +370,20 @@ bool BlenderConnection::saveBlend()
return false; return false;
} }
void BlenderConnection::PyOutStream::linkBlend(const SystemString& relPath, const std::string& objName, void BlenderConnection::deleteBlend()
{
if (m_loadedBlend.size())
{
HECL::Unlink(m_loadedBlend.c_str());
m_loadedBlend.clear();
}
}
void BlenderConnection::PyOutStream::linkBlend(const SystemString& target, const std::string& objName,
bool link) bool link)
{ {
HECL::SystemUTF8View relView(relPath);
format("if '%s' not in bpy.data.scenes:\n" format("if '%s' not in bpy.data.scenes:\n"
" with bpy.data.libraries.load('//%s', link=%s, relative=True) as (data_from, data_to):\n" " with bpy.data.libraries.load('%s', link=%s, 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"
" for scene in data_to.scenes:\n" " for scene in data_to.scenes:\n"
@ -368,7 +397,7 @@ void BlenderConnection::PyOutStream::linkBlend(const SystemString& relPath, cons
"else:\n" "else:\n"
" obj = bpy.data.objects['%s']\n" " obj = bpy.data.objects['%s']\n"
"\n", "\n",
objName.c_str(), relView.str().c_str(), link?"True":"False", objName.c_str(), target.c_str(), link?"True":"False",
objName.c_str(), objName.c_str()); objName.c_str(), objName.c_str());
} }

View File

@ -47,6 +47,7 @@ public:
bool createBlend(const SystemString& path); bool createBlend(const SystemString& path);
bool openBlend(const SystemString& path); bool openBlend(const SystemString& path);
bool saveBlend(); bool saveBlend();
void deleteBlend();
enum CookPlatform enum CookPlatform
{ {
CP_MODERN = 0, CP_MODERN = 0,
@ -62,31 +63,43 @@ public:
friend class BlenderConnection; friend class BlenderConnection;
std::unique_lock<std::mutex> m_lk; std::unique_lock<std::mutex> m_lk;
BlenderConnection* m_parent; BlenderConnection* m_parent;
bool m_deleteOnError;
struct StreamBuf : std::streambuf struct StreamBuf : std::streambuf
{ {
BlenderConnection* m_parent; PyOutStream& m_parent;
std::string m_lineBuf; std::string m_lineBuf;
StreamBuf(BlenderConnection* parent) : m_parent(parent) {} bool m_deleteOnError;
StreamBuf(PyOutStream& parent, bool deleteOnError)
: m_parent(parent), m_deleteOnError(deleteOnError) {}
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 (!m_parent.m_lk)
BlenderLog.report(LogVisor::FatalError, "lock not held for PyOutStream writing");
if (ch != traits_type::eof() && ch != '\n') if (ch != traits_type::eof() && ch != '\n')
{ {
m_lineBuf += char_type(ch); m_lineBuf += char_type(ch);
return ch; return ch;
} }
m_parent->_writeLine(m_lineBuf.c_str()); m_parent.m_parent->_writeLine(m_lineBuf.c_str());
char readBuf[16]; char readBuf[16];
m_parent->_readLine(readBuf, 16); m_parent.m_parent->_readLine(readBuf, 16);
if (strcmp(readBuf, "OK")) if (strcmp(readBuf, "OK"))
{
if (m_deleteOnError)
m_parent.m_parent->deleteBlend();
BlenderLog.report(LogVisor::FatalError, "error sending '%s' to blender", m_lineBuf.c_str()); BlenderLog.report(LogVisor::FatalError, "error sending '%s' to blender", m_lineBuf.c_str());
}
m_lineBuf.clear(); m_lineBuf.clear();
return ch; return ch;
} }
} m_sbuf; } m_sbuf;
PyOutStream(BlenderConnection* parent) PyOutStream(BlenderConnection* parent, bool deleteOnError)
: 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(*this, deleteOnError),
m_deleteOnError(deleteOnError),
std::ostream(&m_sbuf)
{ {
m_parent->_writeLine("PYBEGIN"); m_parent->_writeLine("PYBEGIN");
char readBuf[16]; char readBuf[16];
@ -99,9 +112,10 @@ public:
PyOutStream(PyOutStream&& other) PyOutStream(PyOutStream&& other)
: m_lk(std::move(other.m_lk)), m_parent(other.m_parent), m_sbuf(std::move(other.m_sbuf)) : m_lk(std::move(other.m_lk)), m_parent(other.m_parent), m_sbuf(std::move(other.m_sbuf))
{other.m_parent = nullptr;} {other.m_parent = nullptr;}
~PyOutStream() ~PyOutStream() {close();}
void close()
{ {
if (m_parent) if (m_parent && m_lk)
{ {
m_parent->_writeLine("PYEND"); m_parent->_writeLine("PYEND");
char readBuf[16]; char readBuf[16];
@ -109,9 +123,12 @@ public:
if (strcmp(readBuf, "DONE")) if (strcmp(readBuf, "DONE"))
BlenderLog.report(LogVisor::FatalError, "unable to close PyOutStream with blender"); BlenderLog.report(LogVisor::FatalError, "unable to close PyOutStream with blender");
} }
m_lk.unlock();
} }
void format(const char* fmt, ...) void format(const char* fmt, ...)
{ {
if (!m_lk)
BlenderLog.report(LogVisor::FatalError, "lock not held for PyOutStream::format()");
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
char* result = nullptr; char* result = nullptr;
@ -123,9 +140,9 @@ public:
} }
void linkBlend(const SystemString& target, const std::string& objName, bool link=true); void linkBlend(const SystemString& target, const std::string& objName, bool link=true);
}; };
inline PyOutStream beginPythonOut() inline PyOutStream beginPythonOut(bool deleteOnError=false)
{ {
return PyOutStream(this); return PyOutStream(this, deleteOnError);
} }
void quitBlender(); void quitBlender();

View File

@ -15,7 +15,7 @@ class Nodegrid:
self.col_roffs = [[0.0,0.0]] * self.ncol self.col_roffs = [[0.0,0.0]] * self.ncol
for i in range(self.ncol): for i in range(self.ncol):
self.heights.append(0.0) self.heights.append(0.0)
frame_node = new_nodetree.nodes.new('NodeFrame') frame_node = nodetree.nodes.new('NodeFrame')
frame_node.label = FRAME_NAMES[i] frame_node.label = FRAME_NAMES[i]
frame_node.use_custom_color = True frame_node.use_custom_color = True
frame_node.color = FRAME_COLORS[i] frame_node.color = FRAME_COLORS[i]

View File

@ -6,14 +6,15 @@ bl_info = {
"name": "HECL", "name": "HECL",
"author": "Jack Andersen <jackoalan@gmail.com>", "author": "Jack Andersen <jackoalan@gmail.com>",
"version": (1, 0), "version": (1, 0),
"blender": (2, 69), "blender": (2, 74),
"tracker_url": "https://github.com/RetroView/hecl/issues/new", "tracker_url": "https://github.com/RetroView/hecl/issues/new",
"location": "Properties > Scene > HECL", "location": "Properties > Scene > HECL",
"description": "Enables blender to gather meshes, materials, and textures for hecl", "description": "Enables blender to gather meshes, materials, and textures for hecl",
"category": "System"} "category": "System"}
# Package import # Package import
from . import hmdl, sact from . import hmdl, sact, Nodegrid
Nodegrid = Nodegrid.Nodegrid
import bpy, os, sys import bpy, os, sys
from bpy.app.handlers import persistent from bpy.app.handlers import persistent

View File

@ -1,4 +1,4 @@
import bpy, sys, os, re, code import bpy, sys, os, re
ARGS_PATTERN = re.compile(r'''(?:"([^"]+)"|'([^']+)'|(\S+))''') ARGS_PATTERN = re.compile(r'''(?:"([^"]+)"|'([^']+)'|(\S+))''')
@ -44,6 +44,22 @@ ackbytes = readpipeline()
if ackbytes != b'ACK': if ackbytes != b'ACK':
quitblender() quitblender()
# Count brackets
def count_brackets(linestr):
bracket_count = 0
for ch in linestr:
if ch in {'[','{','('}:
bracket_count += 1
elif ch in {']','}',')'}:
bracket_count -= 1
return bracket_count
# Complete sequences of statements compiled/executed here
def exec_compbuf(compbuf, globals):
#print('EXEC', compbuf)
co = compile(compbuf, '<HECL>', 'exec')
exec(co, globals)
# Command loop # Command loop
while True: while True:
cmdline = readpipeline() cmdline = readpipeline()
@ -80,34 +96,46 @@ while True:
elif cmdargs[0] == 'PYBEGIN': elif cmdargs[0] == 'PYBEGIN':
writepipeline(b'READY') writepipeline(b'READY')
globals = dict() globals = {'hecl':hecl}
compbuf = str() compbuf = str()
prev_leading_spaces = 0 bracket_count = 0
while True: while True:
try: try:
line = readpipeline() line = readpipeline()
# End check
if line == b'PYEND': if line == b'PYEND':
# Ensure remaining block gets executed
if len(compbuf):
exec_compbuf(compbuf, globals)
compbuf = str()
writepipeline(b'DONE') writepipeline(b'DONE')
break break
linestr = line.decode()
if linestr.isspace() or not len(linestr): # Syntax filter
linestr = line.decode().rstrip()
if not len(linestr) or linestr.lstrip()[0] == '#':
writepipeline(b'OK') writepipeline(b'OK')
continue continue
leading_spaces = len(linestr) - len(linestr.lstrip()) leading_spaces = len(linestr) - len(linestr.lstrip())
if prev_leading_spaces and not leading_spaces:
compbuf += '\n' # Block lines always get appended right away
co = code.compile_command(compbuf, filename='<HECL>') if linestr.endswith(':') or leading_spaces or bracket_count:
if co is not None:
exec(co, globals)
compbuf = str()
prev_leading_spaces = leading_spaces
if len(compbuf): if len(compbuf):
compbuf += '\n' compbuf += '\n'
compbuf += linestr compbuf += linestr
co = code.compile_command(compbuf, filename='<HECL>') bracket_count += count_brackets(linestr)
if co is not None: writepipeline(b'OK')
exec(co, globals) continue
compbuf = str()
# Complete non-block statement in compbuf
if len(compbuf):
exec_compbuf(compbuf, globals)
# Establish new compbuf
compbuf = linestr
bracket_count += count_brackets(linestr)
except Exception as e: except Exception as e:
writepipeline(b'EXCEPTION') writepipeline(b'EXCEPTION')
raise raise

View File

@ -44,12 +44,13 @@ public:
LogModule.report(LogVisor::FatalError, "hecl extract must be ran within a project directory"); LogModule.report(LogVisor::FatalError, "hecl extract must be ran within a project directory");
size_t ErrorRef = LogVisor::ErrorCount; size_t ErrorRef = LogVisor::ErrorCount;
HECL::ProjectRootPath newProjRoot(baseFile); HECL::SystemString rootDir = info.cwd + '/' + baseFile;
HECL::ProjectRootPath newProjRoot(rootDir);
newProjRoot.makeDir(); newProjRoot.makeDir();
m_fallbackProj.reset(new HECL::Database::Project(newProjRoot)); m_fallbackProj.reset(new HECL::Database::Project(newProjRoot));
if (LogVisor::ErrorCount > ErrorRef) if (LogVisor::ErrorCount > ErrorRef)
LogModule.report(LogVisor::FatalError, "unable to init project at '%s'", baseFile.c_str()); LogModule.report(LogVisor::FatalError, "unable to init project at '%s'", rootDir.c_str());
LogModule.report(LogVisor::Info, _S("initialized project at '%s/.hecl'"), baseFile.c_str()); LogModule.report(LogVisor::Info, _S("initialized project at '%s/.hecl'"), rootDir.c_str());
m_useProj = m_fallbackProj.get(); m_useProj = m_fallbackProj.get();
} }
else else
@ -68,7 +69,7 @@ public:
HECL::Database::IDataSpec* ds = entry->m_factory(*m_useProj, HECL::Database::TOOL_EXTRACT); HECL::Database::IDataSpec* ds = entry->m_factory(*m_useProj, HECL::Database::TOOL_EXTRACT);
if (ds) if (ds)
{ {
if (ds->canExtract(*m_useProj, m_einfo, m_reps)) if (ds->canExtract(m_einfo, m_reps))
m_specPasses.emplace_back(entry, ds); m_specPasses.emplace_back(entry, ds);
else else
delete ds; delete ds;
@ -184,7 +185,7 @@ public:
#endif #endif
int lineIdx = 0; int lineIdx = 0;
ds.m_instance->doExtract(*m_useProj, m_einfo, ds.m_instance->doExtract(m_einfo,
[&lineIdx](const HECL::SystemChar* message, int lidx, float factor) [&lineIdx](const HECL::SystemChar* message, int lidx, float factor)
{ {
#ifndef _WIN32 #ifndef _WIN32

2
hecl/extern/Athena vendored

@ -1 +1 @@
Subproject commit f06afb429ccddad1be6878d1b9d6ffebb245909b Subproject commit 9ed090b12629ddb8a431b871340276da61e88442

@ -1 +1 @@
Subproject commit 8e89d7efd060d756bf756c09c0d285eb944f6610 Subproject commit aeb6089053a46c51b55727e68406bb7577c2e60e

View File

@ -217,9 +217,9 @@ public:
typedef std::function<void(const HECL::SystemChar*, int, float)> FExtractProgress; typedef std::function<void(const HECL::SystemChar*, int, float)> FExtractProgress;
virtual bool canExtract(Project&, const ExtractPassInfo& info, std::vector<ExtractReport>& reps) virtual bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
{(void)info;LogModule.report(LogVisor::Error, "not implemented");return false;} {(void)info;LogModule.report(LogVisor::Error, "not implemented");return false;}
virtual void doExtract(Project&, const ExtractPassInfo& info, FExtractProgress progress) virtual void doExtract(const ExtractPassInfo& info, FExtractProgress progress)
{(void)info;(void)progress;} {(void)info;(void)progress;}
/** /**
@ -233,10 +233,10 @@ public:
ProjectPath path; ProjectPath path;
ProjectPath cookedPath; ProjectPath cookedPath;
}; };
virtual bool canCook(const Project&, const CookTaskInfo& info, virtual bool canCook(const CookTaskInfo& info,
SystemString& reasonNo) SystemString& reasonNo)
{(void)info;reasonNo=_S("not implemented");return false;} {(void)info;reasonNo=_S("not implemented");return false;}
virtual void doCook(const Project&, const CookTaskInfo& info) virtual void doCook(const CookTaskInfo& info)
{(void)info;} {(void)info;}
/** /**
@ -252,13 +252,13 @@ public:
ProjectPath subpath; ProjectPath subpath;
ProjectPath outpath; ProjectPath outpath;
}; };
virtual bool canPackage(const Project&, const PackagePassInfo& info, virtual bool canPackage(const PackagePassInfo& info,
SystemString& reasonNo) SystemString& reasonNo)
{(void)info;reasonNo=_S("not implemented");return false;} {(void)info;reasonNo=_S("not implemented");return false;}
virtual void gatherDependencies(const Project&, const PackagePassInfo& info, virtual void gatherDependencies(const PackagePassInfo& info,
std::unordered_set<ProjectPath>& implicitsOut) std::unordered_set<ProjectPath>& implicitsOut)
{(void)info;(void)implicitsOut;} {(void)info;(void)implicitsOut;}
virtual void doPackage(const Project&, const PackagePassInfo& info) virtual void doPackage(const PackagePassInfo& info)
{(void)info;} {(void)info;}
}; };

View File

@ -122,6 +122,15 @@ inline std::string operator+(const char* lhs, const SystemStringView& rhs) {retu
typedef struct stat Sstat; typedef struct stat Sstat;
#endif #endif
static inline void Unlink(const SystemChar* file)
{
#if _WIN32
_wunlink(file);
#else
unlink(file);
#endif
}
static inline void MakeDir(const SystemChar* dir) static inline void MakeDir(const SystemChar* dir)
{ {
#if _WIN32 #if _WIN32