mirror of https://github.com/AxioDL/metaforce.git
Work on mesh transfer from blender
This commit is contained in:
parent
391ee13816
commit
bebeffb247
|
@ -113,7 +113,7 @@ err:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BlenderConnection::_readBuf(char* buf, size_t len)
|
size_t BlenderConnection::_readBuf(void* buf, size_t len)
|
||||||
{
|
{
|
||||||
int ret = read(m_readpipe[0], buf, len);
|
int ret = read(m_readpipe[0], buf, len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -124,7 +124,7 @@ err:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BlenderConnection::_writeBuf(const char* buf, size_t len)
|
size_t BlenderConnection::_writeBuf(const void* buf, size_t len)
|
||||||
{
|
{
|
||||||
int ret = write(m_writepipe[1], buf, len);
|
int ret = write(m_writepipe[1], buf, len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -391,6 +391,8 @@ bool BlenderConnection::openBlend(const SystemString& path)
|
||||||
"BlenderConnection::openBlend() musn't be called with stream active");
|
"BlenderConnection::openBlend() musn't be called with stream active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (path == m_loadedBlend)
|
||||||
|
return true;
|
||||||
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];
|
||||||
|
@ -429,7 +431,8 @@ void BlenderConnection::deleteBlend()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderConnection::PyOutStream::linkBlend(const std::string& target, const std::string& objName,
|
void BlenderConnection::PyOutStream::linkBlend(const std::string& target,
|
||||||
|
const std::string& objName,
|
||||||
bool link)
|
bool link)
|
||||||
{
|
{
|
||||||
format("if '%s' not in bpy.data.scenes:\n"
|
format("if '%s' not in bpy.data.scenes:\n"
|
||||||
|
@ -453,6 +456,121 @@ void BlenderConnection::PyOutStream::linkBlend(const std::string& target, const
|
||||||
objName.c_str(), objName.c_str(), target.c_str(), objName.c_str());
|
objName.c_str(), objName.c_str(), target.c_str(), objName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlenderConnection::DataStream::Mesh::Mesh(BlenderConnection& conn)
|
||||||
|
{
|
||||||
|
uint32_t matCount;
|
||||||
|
conn._readBuf(&matCount, 4);
|
||||||
|
materials.reserve(matCount);
|
||||||
|
for (int i=0 ; i<matCount ; ++i)
|
||||||
|
{
|
||||||
|
char mat[2048];
|
||||||
|
conn._readLine(mat, 2048);
|
||||||
|
materials.push_back(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t submeshCount;
|
||||||
|
conn._readBuf(&submeshCount, 4);
|
||||||
|
submeshes.reserve(submeshCount);
|
||||||
|
for (int i=0 ; i<submeshCount ; ++i)
|
||||||
|
submeshes.emplace_back(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlenderConnection::DataStream::Mesh::Submesh::Submesh(BlenderConnection& conn)
|
||||||
|
{
|
||||||
|
uint32_t count;
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
pos.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
pos.emplace_back(conn);
|
||||||
|
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
norm.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
norm.emplace_back(conn);
|
||||||
|
|
||||||
|
conn._readBuf(&colorLayerCount, 4);
|
||||||
|
for (int i=0 ; i<colorLayerCount ; ++i)
|
||||||
|
{
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
color[i].reserve(count);
|
||||||
|
for (int j=0 ; j<count ; ++j)
|
||||||
|
color[i].emplace_back(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn._readBuf(&uvLayerCount, 4);
|
||||||
|
for (int i=0 ; i<uvLayerCount ; ++i)
|
||||||
|
{
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
uv[i].reserve(count);
|
||||||
|
for (int j=0 ; j<count ; ++j)
|
||||||
|
uv[i].emplace_back(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
boneNames.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
{
|
||||||
|
char name[128];
|
||||||
|
conn._readLine(name, 128);
|
||||||
|
boneNames.emplace_back(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
skins.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
{
|
||||||
|
skins.emplace_back();
|
||||||
|
std::vector<SkinBind>& binds = skins.back();
|
||||||
|
uint32_t bindCount;
|
||||||
|
conn._readBuf(&bindCount, 4);
|
||||||
|
binds.reserve(bindCount);
|
||||||
|
for (int j=0 ; j<bindCount ; ++j)
|
||||||
|
binds.emplace_back(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
skinBanks.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
{
|
||||||
|
skinBanks.emplace_back();
|
||||||
|
std::vector<Index>& bank = skinBanks.back();
|
||||||
|
uint32_t idxCount;
|
||||||
|
conn._readBuf(&idxCount, 4);
|
||||||
|
bank.reserve(idxCount);
|
||||||
|
for (int j=0 ; j<idxCount ; ++j)
|
||||||
|
bank.emplace_back(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
surfaces.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
surfaces.emplace_back(conn, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlenderConnection::DataStream::Mesh::Submesh::Surface::Surface
|
||||||
|
(BlenderConnection& conn, const Submesh& parent)
|
||||||
|
: centroid(conn), materialIdx(conn), aabbMin(conn), aabbMax(conn),
|
||||||
|
reflectionNormal(conn), skinBankIdx(conn)
|
||||||
|
{
|
||||||
|
uint32_t count;
|
||||||
|
conn._readBuf(&count, 4);
|
||||||
|
verts.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
verts.emplace_back(conn, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlenderConnection::DataStream::Mesh::Submesh::Surface::Vert::Vert
|
||||||
|
(BlenderConnection& conn, const Submesh& parent)
|
||||||
|
{
|
||||||
|
conn._readBuf(&iPos, 4);
|
||||||
|
conn._readBuf(&iNorm, 4);
|
||||||
|
if (parent.colorLayerCount)
|
||||||
|
conn._readBuf(iColor, 4 * parent.colorLayerCount);
|
||||||
|
if (parent.uvLayerCount)
|
||||||
|
conn._readBuf(iUv, 4 * parent.uvLayerCount);
|
||||||
|
conn._readBuf(&iSkin, 4);
|
||||||
|
}
|
||||||
|
|
||||||
void BlenderConnection::quitBlender()
|
void BlenderConnection::quitBlender()
|
||||||
{
|
{
|
||||||
_writeLine("QUIT");
|
_writeLine("QUIT");
|
||||||
|
|
|
@ -40,8 +40,8 @@ class BlenderConnection
|
||||||
std::string m_startupBlend;
|
std::string m_startupBlend;
|
||||||
size_t _readLine(char* buf, size_t bufSz);
|
size_t _readLine(char* buf, size_t bufSz);
|
||||||
size_t _writeLine(const char* buf);
|
size_t _writeLine(const char* buf);
|
||||||
size_t _readBuf(char* buf, size_t len);
|
size_t _readBuf(void* buf, size_t len);
|
||||||
size_t _writeBuf(const char* buf, size_t len);
|
size_t _writeBuf(const void* buf, size_t len);
|
||||||
void _closePipe();
|
void _closePipe();
|
||||||
public:
|
public:
|
||||||
BlenderConnection(int verbosityLevel=1);
|
BlenderConnection(int verbosityLevel=1);
|
||||||
|
@ -223,29 +223,197 @@ public:
|
||||||
return ANIMOutStream(m_parent);
|
return ANIMOutStream(m_parent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
inline PyOutStream beginPythonOut(bool deleteOnError=false)
|
PyOutStream beginPythonOut(bool deleteOnError=false)
|
||||||
{
|
{
|
||||||
if (m_lock)
|
if (m_lock)
|
||||||
BlenderLog.report(LogVisor::FatalError, "lock already held for BlenderConnection::beginPythonOut()");
|
BlenderLog.report(LogVisor::FatalError, "lock already held for BlenderConnection::beginPythonOut()");
|
||||||
return PyOutStream(this, deleteOnError);
|
return PyOutStream(this, deleteOnError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DataStream
|
||||||
|
{
|
||||||
|
friend class BlenderConnection;
|
||||||
|
BlenderConnection* m_parent;
|
||||||
|
DataStream(BlenderConnection* parent)
|
||||||
|
: m_parent(parent)
|
||||||
|
{
|
||||||
|
m_parent->m_lock = true;
|
||||||
|
m_parent->_writeLine("DATABEGIN");
|
||||||
|
char readBuf[16];
|
||||||
|
m_parent->_readLine(readBuf, 16);
|
||||||
|
if (strcmp(readBuf, "READY"))
|
||||||
|
BlenderLog.report(LogVisor::FatalError, "unable to open DataStream with blender");
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
DataStream(const DataStream& other) = delete;
|
||||||
|
DataStream(DataStream&& other)
|
||||||
|
: m_parent(other.m_parent) {other.m_parent = nullptr;}
|
||||||
|
~DataStream() {close();}
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
if (m_parent && m_parent->m_lock)
|
||||||
|
{
|
||||||
|
m_parent->_writeLine("DATAEND");
|
||||||
|
char readBuf[16];
|
||||||
|
m_parent->_readLine(readBuf, 16);
|
||||||
|
if (strcmp(readBuf, "DONE"))
|
||||||
|
BlenderLog.report(LogVisor::FatalError, "unable to close DataStream with blender");
|
||||||
|
m_parent->m_lock = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> getMeshList()
|
||||||
|
{
|
||||||
|
m_parent->_writeLine("MESHLIST");
|
||||||
|
uint32_t count;
|
||||||
|
m_parent->_readBuf(&count, 4);
|
||||||
|
std::vector<std::string> retval;
|
||||||
|
retval.reserve(count);
|
||||||
|
for (int i=0 ; i<count ; ++i)
|
||||||
|
{
|
||||||
|
char name[128];
|
||||||
|
m_parent->_readLine(name, 128);
|
||||||
|
retval.push_back(name);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Intermediate mesh representation prepared by blender from a single mesh object */
|
||||||
|
struct Mesh
|
||||||
|
{
|
||||||
|
/* HECL source of each material */
|
||||||
|
std::vector<std::string> materials;
|
||||||
|
|
||||||
|
/* Encapsulates mesh data up to maximum indexing space,
|
||||||
|
* overflowing to additional Submeshes as needed */
|
||||||
|
struct Submesh
|
||||||
|
{
|
||||||
|
/* Vertex buffer data */
|
||||||
|
struct Vector2f
|
||||||
|
{
|
||||||
|
float val[2];
|
||||||
|
Vector2f(BlenderConnection& conn) {conn._readBuf(val, 8);}
|
||||||
|
};
|
||||||
|
struct Vector3f
|
||||||
|
{
|
||||||
|
float val[3];
|
||||||
|
Vector3f(BlenderConnection& conn) {conn._readBuf(val, 12);}
|
||||||
|
};
|
||||||
|
struct Vector4f
|
||||||
|
{
|
||||||
|
float val[4];
|
||||||
|
Vector4f(BlenderConnection& conn) {conn._readBuf(val, 16);}
|
||||||
|
};
|
||||||
|
struct Index
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
Index(BlenderConnection& conn) {conn._readBuf(&val, 4);}
|
||||||
|
};
|
||||||
|
std::vector<Vector3f> pos;
|
||||||
|
std::vector<Vector3f> norm;
|
||||||
|
uint32_t colorLayerCount = 0;
|
||||||
|
std::vector<Vector4f> color[4];
|
||||||
|
uint32_t uvLayerCount = 0;
|
||||||
|
std::vector<Vector2f> uv[8];
|
||||||
|
|
||||||
|
/* Skinning data */
|
||||||
|
std::vector<std::string> boneNames;
|
||||||
|
struct SkinBind
|
||||||
|
{
|
||||||
|
uint32_t boneIdx;
|
||||||
|
float weight;
|
||||||
|
SkinBind(BlenderConnection& conn) {conn._readBuf(&boneIdx, 8);}
|
||||||
|
};
|
||||||
|
std::vector<std::vector<SkinBind>> skins;
|
||||||
|
std::vector<std::vector<Index>> skinBanks;
|
||||||
|
|
||||||
|
/* Islands of the same material/skinBank are represented here */
|
||||||
|
struct Surface
|
||||||
|
{
|
||||||
|
Vector3f centroid;
|
||||||
|
Index materialIdx;
|
||||||
|
Vector3f aabbMin;
|
||||||
|
Vector3f aabbMax;
|
||||||
|
Vector3f reflectionNormal;
|
||||||
|
Index skinBankIdx;
|
||||||
|
|
||||||
|
/* Vertex indexing data */
|
||||||
|
struct Vert
|
||||||
|
{
|
||||||
|
uint32_t iPos;
|
||||||
|
uint32_t iNorm;
|
||||||
|
uint32_t iColor[4] = {uint32_t(-1)};
|
||||||
|
uint32_t iUv[8] = {uint32_t(-1)};
|
||||||
|
uint32_t iSkin;
|
||||||
|
|
||||||
|
Vert(BlenderConnection& conn, const Submesh& parent);
|
||||||
|
};
|
||||||
|
std::vector<Vert> verts;
|
||||||
|
|
||||||
|
Surface(BlenderConnection& conn, const Submesh& parent);
|
||||||
|
};
|
||||||
|
std::vector<Surface> surfaces;
|
||||||
|
|
||||||
|
Submesh(BlenderConnection& conn);
|
||||||
|
};
|
||||||
|
std::vector<Submesh> submeshes;
|
||||||
|
|
||||||
|
Mesh(BlenderConnection& conn);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compile mesh by name */
|
||||||
|
Mesh compileMesh(const std::string& name, int maxIdx=65535, int maxSkinBanks=10)
|
||||||
|
{
|
||||||
|
char req[128];
|
||||||
|
snprintf(req, 128, "MESHCOMPILE %s %d %d", name.c_str(), maxIdx, maxSkinBanks);
|
||||||
|
m_parent->_writeLine(req);
|
||||||
|
|
||||||
|
char readBuf[256];
|
||||||
|
m_parent->_readLine(readBuf, 256);
|
||||||
|
if (strcmp(readBuf, "OK"))
|
||||||
|
BlenderLog.report(LogVisor::FatalError, "unable to cook mesh '%s': %s", name.c_str(), readBuf);
|
||||||
|
|
||||||
|
return Mesh(*m_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compile all meshes into one */
|
||||||
|
Mesh compileAllMeshes(int maxIdx=65535, int maxSkinBanks=10)
|
||||||
|
{
|
||||||
|
char req[128];
|
||||||
|
snprintf(req, 128, "MESHCOMPILEALL %d %d", maxIdx, maxSkinBanks);
|
||||||
|
m_parent->_writeLine(req);
|
||||||
|
|
||||||
|
char readBuf[256];
|
||||||
|
m_parent->_readLine(readBuf, 256);
|
||||||
|
if (strcmp(readBuf, "OK"))
|
||||||
|
BlenderLog.report(LogVisor::FatalError, "unable to cook all meshes: %s", readBuf);
|
||||||
|
|
||||||
|
return Mesh(*m_parent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DataStream beginData()
|
||||||
|
{
|
||||||
|
if (m_lock)
|
||||||
|
BlenderLog.report(LogVisor::FatalError, "lock already held for BlenderConnection::beginDataIn()");
|
||||||
|
return DataStream(this);
|
||||||
|
}
|
||||||
|
|
||||||
void quitBlender();
|
void quitBlender();
|
||||||
|
|
||||||
static inline BlenderConnection& SharedConnection()
|
static BlenderConnection& SharedConnection()
|
||||||
{
|
{
|
||||||
if (!SharedBlenderConnection)
|
if (!SharedBlenderConnection)
|
||||||
SharedBlenderConnection = new BlenderConnection(HECL::VerbosityLevel);
|
SharedBlenderConnection = new BlenderConnection(HECL::VerbosityLevel);
|
||||||
return *SharedBlenderConnection;
|
return *SharedBlenderConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void closeStream()
|
void closeStream()
|
||||||
{
|
{
|
||||||
if (m_lock)
|
if (m_lock)
|
||||||
deleteBlend();
|
deleteBlend();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void Shutdown()
|
static void Shutdown()
|
||||||
{
|
{
|
||||||
if (SharedBlenderConnection)
|
if (SharedBlenderConnection)
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,6 +75,17 @@ def count_brackets(linestr):
|
||||||
bracket_count -= 1
|
bracket_count -= 1
|
||||||
return bracket_count
|
return bracket_count
|
||||||
|
|
||||||
|
# Read line of space-separated/quoted arguments
|
||||||
|
def read_cmdargs():
|
||||||
|
cmdline = readpipeline()
|
||||||
|
if cmdline == b'':
|
||||||
|
print('HECL connection lost')
|
||||||
|
bpy.ops.wm.quit_blender()
|
||||||
|
cmdargs = []
|
||||||
|
for match in ARGS_PATTERN.finditer(cmdline.decode()):
|
||||||
|
cmdargs.append(match.group(match.lastindex))
|
||||||
|
return cmdargs
|
||||||
|
|
||||||
# Complete sequences of statements compiled/executed here
|
# Complete sequences of statements compiled/executed here
|
||||||
def exec_compbuf(compbuf, globals):
|
def exec_compbuf(compbuf, globals):
|
||||||
if double_verbose:
|
if double_verbose:
|
||||||
|
@ -82,7 +93,8 @@ def exec_compbuf(compbuf, globals):
|
||||||
co = compile(compbuf, '<HECL>', 'exec')
|
co = compile(compbuf, '<HECL>', 'exec')
|
||||||
exec(co, globals)
|
exec(co, globals)
|
||||||
|
|
||||||
def anim_loop(globals):
|
# Command loop for writing animation key data to blender
|
||||||
|
def animin_loop(globals):
|
||||||
writepipeline(b'ANIMREADY')
|
writepipeline(b'ANIMREADY')
|
||||||
while True:
|
while True:
|
||||||
crv_type = struct.unpack('b', os.read(readfd, 1))
|
crv_type = struct.unpack('b', os.read(readfd, 1))
|
||||||
|
@ -114,15 +126,35 @@ def anim_loop(globals):
|
||||||
pt.interpolation = 'LINEAR'
|
pt.interpolation = 'LINEAR'
|
||||||
pt.co = (key_data[0], key_data[1])
|
pt.co = (key_data[0], key_data[1])
|
||||||
|
|
||||||
|
# Command loop for reading data from blender
|
||||||
|
def dataout_loop():
|
||||||
|
writepipeline(b'READY')
|
||||||
|
while True:
|
||||||
|
cmdargs = read_cmdargs()
|
||||||
|
print(cmdargs)
|
||||||
|
|
||||||
|
if cmdargs[0] == 'DATAEND':
|
||||||
|
break
|
||||||
|
|
||||||
|
elif cmdargs[0] == 'MESHLIST':
|
||||||
|
for meshobj in bpy.data.objects:
|
||||||
|
if meshobj.type == 'MESH':
|
||||||
|
writepipeline(meshobj.name.encode())
|
||||||
|
|
||||||
|
elif cmdargs[0] == 'MESHCOMPILE':
|
||||||
|
meshName = cmdargs[1]
|
||||||
|
maxIdx = int(cmdargs[2])
|
||||||
|
maxSkinBanks = int(cmdargs[3])
|
||||||
|
|
||||||
|
if meshName not in bpy.data.objects:
|
||||||
|
writepipeline(b'mesh not found')
|
||||||
|
continue
|
||||||
|
|
||||||
|
hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName])
|
||||||
|
|
||||||
# Command loop
|
# Command loop
|
||||||
while True:
|
while True:
|
||||||
cmdline = readpipeline()
|
cmdargs = read_cmdargs()
|
||||||
if cmdline == b'':
|
|
||||||
print('HECL connection lost')
|
|
||||||
bpy.ops.wm.quit_blender()
|
|
||||||
cmdargs = []
|
|
||||||
for match in ARGS_PATTERN.finditer(cmdline.decode()):
|
|
||||||
cmdargs.append(match.group(match.lastindex))
|
|
||||||
print(cmdargs)
|
print(cmdargs)
|
||||||
|
|
||||||
if cmdargs[0] == 'QUIT':
|
if cmdargs[0] == 'QUIT':
|
||||||
|
@ -172,7 +204,7 @@ while True:
|
||||||
if len(compbuf):
|
if len(compbuf):
|
||||||
exec_compbuf(compbuf, globals)
|
exec_compbuf(compbuf, globals)
|
||||||
compbuf = str()
|
compbuf = str()
|
||||||
anim_loop(globals)
|
animin_loop(globals)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# End check
|
# End check
|
||||||
|
@ -217,6 +249,13 @@ while True:
|
||||||
elif cmdargs[0] == 'PYEND':
|
elif cmdargs[0] == 'PYEND':
|
||||||
writepipeline(b'ERROR')
|
writepipeline(b'ERROR')
|
||||||
|
|
||||||
|
elif cmdargs[0] == 'DATABEGIN':
|
||||||
|
writepipeline(b'READY')
|
||||||
|
dataout_loop()
|
||||||
|
|
||||||
|
elif cmdargs[0] == 'DATAEND':
|
||||||
|
writepipeline(b'ERROR')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
hecl.command(cmdargs, writepipeline, writepipebuf)
|
hecl.command(cmdargs, writepipeline, writepipebuf)
|
||||||
|
|
||||||
|
|
|
@ -210,6 +210,22 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static HECL::SystemString MakePathArgAbsolute(const HECL::SystemString& arg,
|
||||||
|
const HECL::SystemString& cwd)
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
if (arg.size() >= 2 && iswalpha(arg[0]) && arg[1] == _S(':'))
|
||||||
|
return arg;
|
||||||
|
if (arg[0] == _S('\\') || arg[0] == _S('/'))
|
||||||
|
return arg;
|
||||||
|
return cwd + _S('\\') + arg;
|
||||||
|
#else
|
||||||
|
if (arg[0] == _S('/') || arg[0] == _S('\\'))
|
||||||
|
return arg;
|
||||||
|
return cwd + _S('/') + arg;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void ToolPrintProgress(const HECL::SystemChar* message, const HECL::SystemChar* submessage,
|
void ToolPrintProgress(const HECL::SystemChar* message, const HECL::SystemChar* submessage,
|
||||||
int lidx, float factor, int& lineIdx)
|
int lidx, float factor, int& lineIdx)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
HECL::SystemString subPath;
|
HECL::SystemString subPath;
|
||||||
HECL::ProjectRootPath root = HECL::SearchForProject(arg, subPath);
|
HECL::ProjectRootPath root = HECL::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath);
|
||||||
if (root)
|
if (root)
|
||||||
{
|
{
|
||||||
if (!m_fallbackProj)
|
if (!m_fallbackProj)
|
||||||
|
@ -118,7 +118,6 @@ public:
|
||||||
|
|
||||||
HECL::SystemString toolName() const {return _S("cook");}
|
HECL::SystemString toolName() const {return _S("cook");}
|
||||||
|
|
||||||
using ProjectDataSpec = HECL::Database::Project::ProjectDataSpec;
|
|
||||||
int run()
|
int run()
|
||||||
{
|
{
|
||||||
for (const HECL::ProjectPath& path : m_selectedItems)
|
for (const HECL::ProjectPath& path : m_selectedItems)
|
||||||
|
|
|
@ -555,11 +555,27 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Return new ProjectPath with extension added
|
* @brief Return new ProjectPath with extension added
|
||||||
* @param ext file extension to add
|
* @param ext file extension to add
|
||||||
|
* @param replace remove existing extension (if any) before appending new extension
|
||||||
* @return new path with extension
|
* @return new path with extension
|
||||||
*/
|
*/
|
||||||
ProjectPath getWithExtension(const SystemChar* ext) const
|
ProjectPath getWithExtension(const SystemChar* ext, bool replace=false) const
|
||||||
{
|
{
|
||||||
ProjectPath pp(*this);
|
ProjectPath pp(*this);
|
||||||
|
if (replace)
|
||||||
|
{
|
||||||
|
auto relIt = pp.m_relPath.end();
|
||||||
|
auto absIt = pp.m_absPath.end();
|
||||||
|
while (relIt != pp.m_relPath.begin() && *relIt != _S('.') && *relIt != _S('/'))
|
||||||
|
{
|
||||||
|
--relIt;
|
||||||
|
--absIt;
|
||||||
|
}
|
||||||
|
if (*relIt == _S('.'))
|
||||||
|
{
|
||||||
|
pp.m_relPath.resize(relIt - pp.m_relPath.begin());
|
||||||
|
pp.m_absPath.resize(absIt - pp.m_absPath.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
pp.m_relPath += ext;
|
pp.m_relPath += ext;
|
||||||
pp.m_absPath += ext;
|
pp.m_absPath += ext;
|
||||||
return pp;
|
return pp;
|
||||||
|
|
Loading…
Reference in New Issue