diff --git a/hecl/blender/BlenderConnection.hpp b/hecl/blender/BlenderConnection.hpp index c9a0364f1..7ba80abf0 100644 --- a/hecl/blender/BlenderConnection.hpp +++ b/hecl/blender/BlenderConnection.hpp @@ -146,6 +146,76 @@ public: free(result); } void linkBlend(const std::string& target, const std::string& objName, bool link=true); + + class ANIMOutStream + { + BlenderConnection* m_parent; + unsigned m_curCount = 0; + unsigned m_totalCount = 0; + bool m_inCurve = false; + public: + enum CurveType + { + CurveRotate, + CurveTranslate, + CurveScale + }; + ANIMOutStream(BlenderConnection* parent) + : m_parent(parent) + { + m_parent->_writeLine("PYANIM"); + char readBuf[16]; + m_parent->_readLine(readBuf, 16); + if (strcmp(readBuf, "ANIMREADY")) + BlenderLog.report(LogVisor::FatalError, "unable to open ANIMOutStream"); + } + ~ANIMOutStream() + { + char tp = -1; + m_parent->_writeBuf(&tp, 1); + char readBuf[16]; + m_parent->_readLine(readBuf, 16); + if (strcmp(readBuf, "ANIMDONE")) + BlenderLog.report(LogVisor::FatalError, "unable to close ANIMOutStream"); + } + void changeCurve(CurveType type, unsigned crvIdx, unsigned keyCount) + { + if (m_curCount != m_totalCount) + BlenderLog.report(LogVisor::FatalError, "incomplete ANIMOutStream for change"); + m_curCount = 0; + m_totalCount = keyCount; + char tp = char(type); + m_parent->_writeBuf(&tp, 1); + struct + { + uint32_t ci; + uint32_t kc; + } info = {uint32_t(crvIdx), uint32_t(keyCount)}; + m_parent->_writeBuf(reinterpret_cast(&info), 8); + m_inCurve = true; + } + void write(unsigned frame, float val) + { + if (!m_inCurve) + BlenderLog.report(LogVisor::FatalError, "changeCurve not called before write"); + if (m_curCount < m_totalCount) + { + struct + { + uint32_t frm; + float val; + } key = {uint32_t(frame), val}; + m_parent->_writeBuf(reinterpret_cast(&key), 8); + ++m_curCount; + } + else + BlenderLog.report(LogVisor::FatalError, "ANIMOutStream keyCount overflow"); + } + }; + ANIMOutStream beginANIMCurve() + { + return ANIMOutStream(m_parent); + } }; inline PyOutStream beginPythonOut(bool deleteOnError=false) { diff --git a/hecl/blender/hecl_blendershell.py b/hecl/blender/hecl_blendershell.py index 19505f49b..19f1e0f31 100644 --- a/hecl/blender/hecl_blendershell.py +++ b/hecl/blender/hecl_blendershell.py @@ -1,4 +1,4 @@ -import bpy, sys, os, re +import bpy, sys, os, re, struct ARGS_PATTERN = re.compile(r'''(?:"([^"]+)"|'([^']+)'|(\S+))''') @@ -73,6 +73,38 @@ def exec_compbuf(compbuf, globals): co = compile(compbuf, '', 'exec') exec(co, globals) +def anim_loop(globals): + writepipeline(b'ANIMREADY') + while True: + crv_type = struct.unpack('b', os.read(readfd, 1)) + if crv_type[0] < 0: + writepipeline(b'ANIMDONE') + return + elif crv_type[0] == 0: + crvs = globals['rotCurves'] + elif crv_type[0] == 1: + crvs = globals['transCurves'] + elif crv_type[0] == 2: + crvs = globals['scaleCurves'] + + key_info = struct.unpack('ii', os.read(readfd, 8)) + crv = crvs[key_info[0]] + crv.keyframe_points.add(count=key_info[1]) + + if crv_type[0] == 1: + trans_head = globals['bone_trans_head'][key_info[0]] + for k in range(key_info[1]): + key_data = struct.unpack('if', os.read(readfd, 8)) + pt = crv.keyframe_points[k] + pt.interpolation = 'LINEAR' + pt.co = (key_data[0], key_data[1] - trans_head) + else: + for k in range(key_info[1]): + key_data = struct.unpack('if', os.read(readfd, 8)) + pt = crv.keyframe_points[k] + pt.interpolation = 'LINEAR' + pt.co = (key_data[0], key_data[1]) + # Command loop while True: cmdline = readpipeline() @@ -117,8 +149,17 @@ while True: try: line = readpipeline() + # ANIM check + if line == b'PYANIM': + # Ensure remaining block gets executed + if len(compbuf): + exec_compbuf(compbuf, globals) + compbuf = str() + anim_loop(globals) + continue + # End check - if line == b'PYEND': + elif line == b'PYEND': # Ensure remaining block gets executed if len(compbuf): exec_compbuf(compbuf, globals) diff --git a/hecl/driver/ToolExtract.hpp b/hecl/driver/ToolExtract.hpp index b92b83c1a..11d637faf 100644 --- a/hecl/driver/ToolExtract.hpp +++ b/hecl/driver/ToolExtract.hpp @@ -185,9 +185,14 @@ public: #endif int lineIdx = 0; + int prevIFactor = -1; ds.m_instance->doExtract(m_einfo, - [&lineIdx](const HECL::SystemChar* message, int lidx, float factor) + [&lineIdx, &prevIFactor](const HECL::SystemChar* message, int lidx, float factor) { + int iFactor = factor * 100.0; + if (iFactor == prevIFactor) + return; + prevIFactor = iFactor; #ifndef _WIN32 if (XTERM_COLOR) HECL::Printf(_S("" HIDE_CURSOR "")); @@ -220,7 +225,7 @@ public: size_t blocks = half - 7; size_t filled = blocks * factor; size_t rem = blocks - filled; - HECL::Printf(_S("" BOLD "%3d%% ["), (int)(factor * 100.0)); + HECL::Printf(_S("" BOLD "%3d%% ["), iFactor); for (int b=0 ; bSetPath(targetBuf); @@ -98,8 +100,8 @@ HRESULT ResolveShellLink(LPCWSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferS { HRESULT hres; IShellLink* psl; - WCHAR szGotPath[MAX_PATH]; - WCHAR szDescription[MAX_PATH]; + WCHAR szGotPath[HECL_MAX_PATH]; + WCHAR szDescription[HECL_MAX_PATH]; WIN32_FIND_DATA wfd; *lpszPath = 0; // Assume failure @@ -130,12 +132,12 @@ HRESULT ResolveShellLink(LPCWSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferS if (SUCCEEDED(hres)) { // Get the path to the link target. - hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH); + hres = psl->GetPath(szGotPath, HECL_MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH); if (SUCCEEDED(hres)) { // Get the description of the target. - hres = psl->GetDescription(szDescription, MAX_PATH); + hres = psl->GetDescription(szDescription, HECL_MAX_PATH); if (SUCCEEDED(hres)) {