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)
{
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);
_writeLine(("CREATE \"" + pathView.str() + "\"").c_str());
char lineBuf[256];
@ -327,6 +334,13 @@ bool BlenderConnection::createBlend(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);
_writeLine(("OPEN \"" + pathView.str() + "\"").c_str());
char lineBuf[256];
@ -341,6 +355,13 @@ bool BlenderConnection::openBlend(const SystemString& path)
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");
char lineBuf[256];
_readLine(lineBuf, sizeof(lineBuf));
@ -349,12 +370,20 @@ bool BlenderConnection::saveBlend()
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)
{
HECL::SystemUTF8View relView(relPath);
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"
" obj_scene = None\n"
" for scene in data_to.scenes:\n"
@ -368,7 +397,7 @@ void BlenderConnection::PyOutStream::linkBlend(const SystemString& relPath, cons
"else:\n"
" obj = bpy.data.objects['%s']\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());
}

View File

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

View File

@ -15,7 +15,7 @@ class Nodegrid:
self.col_roffs = [[0.0,0.0]] * self.ncol
for i in range(self.ncol):
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.use_custom_color = True
frame_node.color = FRAME_COLORS[i]

View File

@ -6,14 +6,15 @@ bl_info = {
"name": "HECL",
"author": "Jack Andersen <jackoalan@gmail.com>",
"version": (1, 0),
"blender": (2, 69),
"blender": (2, 74),
"tracker_url": "https://github.com/RetroView/hecl/issues/new",
"location": "Properties > Scene > HECL",
"description": "Enables blender to gather meshes, materials, and textures for hecl",
"category": "System"}
# Package import
from . import hmdl, sact
from . import hmdl, sact, Nodegrid
Nodegrid = Nodegrid.Nodegrid
import bpy, os, sys
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+))''')
@ -44,6 +44,22 @@ ackbytes = readpipeline()
if ackbytes != b'ACK':
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
while True:
cmdline = readpipeline()
@ -80,34 +96,46 @@ while True:
elif cmdargs[0] == 'PYBEGIN':
writepipeline(b'READY')
globals = dict()
globals = {'hecl':hecl}
compbuf = str()
prev_leading_spaces = 0
bracket_count = 0
while True:
try:
line = readpipeline()
# End check
if line == b'PYEND':
# Ensure remaining block gets executed
if len(compbuf):
exec_compbuf(compbuf, globals)
compbuf = str()
writepipeline(b'DONE')
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')
continue
leading_spaces = len(linestr) - len(linestr.lstrip())
if prev_leading_spaces and not leading_spaces:
compbuf += '\n'
co = code.compile_command(compbuf, filename='<HECL>')
if co is not None:
exec(co, globals)
compbuf = str()
prev_leading_spaces = leading_spaces
# Block lines always get appended right away
if linestr.endswith(':') or leading_spaces or bracket_count:
if len(compbuf):
compbuf += '\n'
compbuf += linestr
bracket_count += count_brackets(linestr)
writepipeline(b'OK')
continue
# Complete non-block statement in compbuf
if len(compbuf):
compbuf += '\n'
compbuf += linestr
co = code.compile_command(compbuf, filename='<HECL>')
if co is not None:
exec(co, globals)
compbuf = str()
exec_compbuf(compbuf, globals)
# Establish new compbuf
compbuf = linestr
bracket_count += count_brackets(linestr)
except Exception as e:
writepipeline(b'EXCEPTION')
raise

View File

@ -44,12 +44,13 @@ public:
LogModule.report(LogVisor::FatalError, "hecl extract must be ran within a project directory");
size_t ErrorRef = LogVisor::ErrorCount;
HECL::ProjectRootPath newProjRoot(baseFile);
HECL::SystemString rootDir = info.cwd + '/' + baseFile;
HECL::ProjectRootPath newProjRoot(rootDir);
newProjRoot.makeDir();
m_fallbackProj.reset(new HECL::Database::Project(newProjRoot));
if (LogVisor::ErrorCount > ErrorRef)
LogModule.report(LogVisor::FatalError, "unable to init project at '%s'", baseFile.c_str());
LogModule.report(LogVisor::Info, _S("initialized project at '%s/.hecl'"), 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'"), rootDir.c_str());
m_useProj = m_fallbackProj.get();
}
else
@ -68,7 +69,7 @@ public:
HECL::Database::IDataSpec* ds = entry->m_factory(*m_useProj, HECL::Database::TOOL_EXTRACT);
if (ds)
{
if (ds->canExtract(*m_useProj, m_einfo, m_reps))
if (ds->canExtract(m_einfo, m_reps))
m_specPasses.emplace_back(entry, ds);
else
delete ds;
@ -184,7 +185,7 @@ public:
#endif
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)
{
#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;
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;}
virtual void doExtract(Project&, const ExtractPassInfo& info, FExtractProgress progress)
virtual void doExtract(const ExtractPassInfo& info, FExtractProgress progress)
{(void)info;(void)progress;}
/**
@ -233,10 +233,10 @@ public:
ProjectPath path;
ProjectPath cookedPath;
};
virtual bool canCook(const Project&, const CookTaskInfo& info,
virtual bool canCook(const CookTaskInfo& info,
SystemString& reasonNo)
{(void)info;reasonNo=_S("not implemented");return false;}
virtual void doCook(const Project&, const CookTaskInfo& info)
virtual void doCook(const CookTaskInfo& info)
{(void)info;}
/**
@ -252,13 +252,13 @@ public:
ProjectPath subpath;
ProjectPath outpath;
};
virtual bool canPackage(const Project&, const PackagePassInfo& info,
virtual bool canPackage(const PackagePassInfo& info,
SystemString& reasonNo)
{(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)
{(void)info;(void)implicitsOut;}
virtual void doPackage(const Project&, const PackagePassInfo& info)
virtual void doPackage(const PackagePassInfo& info)
{(void)info;}
};

View File

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