2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-10 03:47:42 +00:00

database refinements; blender shell

This commit is contained in:
Jack Andersen
2015-05-23 18:51:16 -10:00
parent 20ca4e407f
commit 461893d7a1
18 changed files with 488 additions and 571 deletions

View File

@@ -0,0 +1,198 @@
#if _WIN32
#else
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <system_error>
#include <string>
#endif
#include "CBlenderConnection.hpp"
#ifdef __APPLE__
#define DEFAULT_BLENDER_BIN "/Applications/Blender.app/Contents/MacOS/blender"
#elif _WIN32
#define DEFAULT_BLENDER_BIN "%ProgramFiles%\\Blender Foundation\\Blender\\blender.exe"
#else
#define DEFAULT_BLENDER_BIN "blender"
#endif
#define TEMP_SHELLSCRIPT "/home/jacko/hecl/blender/blendershell.py"
size_t CBlenderConnection::readLine(char* buf, size_t bufSz)
{
size_t readBytes = 0;
while (true)
{
if (readBytes >= bufSz)
throw std::length_error("Pipe buffer overrun");
ssize_t ret = read(m_readpipe[0], buf, 1);
if (ret < 0)
goto err;
else if (ret == 1)
{
if (*buf == '\n')
{
*buf = '\0';
return readBytes;
}
++readBytes;
++buf;
}
else
{
*buf = '\0';
return readBytes;
}
}
err:
throw std::error_code(errno, std::system_category());
return 0;
}
size_t CBlenderConnection::writeLine(const char* buf)
{
ssize_t ret, nlerr;
ret = write(m_writepipe[1], buf, strlen(buf));
if (ret < 0)
goto err;
nlerr = write(m_writepipe[1], "\n", 1);
if (nlerr < 0)
goto err;
return (size_t)ret;
err:
throw std::error_code(errno, std::system_category());
}
size_t CBlenderConnection::readBuf(char* buf, size_t len)
{
ssize_t ret = read(m_readpipe[0], buf, len);
if (ret < 0)
throw std::error_code(errno, std::system_category());
return ret;
}
size_t CBlenderConnection::writeBuf(const char* buf, size_t len)
{
ssize_t ret = write(m_writepipe[1], buf, len);
if (ret < 0)
throw std::error_code(errno, std::system_category());
return ret;
}
void CBlenderConnection::closePipe()
{
close(m_readpipe[0]);
close(m_writepipe[1]);
}
CBlenderConnection::CBlenderConnection(bool silenceBlender)
{
/* Construct communication pipes */
pipe(m_readpipe);
pipe(m_writepipe);
/* User-specified blender path */
char* blenderBin = getenv("BLENDER_BIN");
/* Child process of blender */
pid_t pid = fork();
if (!pid)
{
close(m_writepipe[1]);
close(m_readpipe[0]);
if (silenceBlender)
{
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
char errbuf[256];
char readfds[32];
snprintf(readfds, 32, "%d", m_writepipe[0]);
char writefds[32];
snprintf(writefds, 32, "%d", m_readpipe[1]);
/* User-specified blender first */
if (blenderBin)
{
execlp(blenderBin, blenderBin, "--background", "-P", TEMP_SHELLSCRIPT,
"--", readfds, writefds, NULL);
if (errno != ENOENT)
{
snprintf(errbuf, 256, "NOLAUNCH %s\n", strerror(errno));
write(m_writepipe[1], errbuf, strlen(errbuf));
exit(1);
}
}
/* Default blender next */
execlp(DEFAULT_BLENDER_BIN, DEFAULT_BLENDER_BIN, "--background", "-P", TEMP_SHELLSCRIPT,
"--", readfds, writefds, NULL);
if (errno != ENOENT)
{
snprintf(errbuf, 256, "NOLAUNCH %s\n", strerror(errno));
write(m_writepipe[1], errbuf, strlen(errbuf));
exit(1);
}
/* Unable to find blender */
write(m_writepipe[1], "NOBLENDER\n", 10);
exit(1);
}
close(m_writepipe[0]);
close(m_readpipe[1]);
m_blenderProc = pid;
/* Handle first response */
char lineBuf[256];
readLine(lineBuf, sizeof(lineBuf));
if (!strcmp(lineBuf, "NOLAUNCH"))
{
closePipe();
throw std::runtime_error("Unable to launch blender");
}
else if (!strcmp(lineBuf, "NOBLENDER"))
{
closePipe();
if (blenderBin)
throw std::runtime_error("Unable to find blender at '" + std::string(blenderBin) + "' or '" +
std::string(DEFAULT_BLENDER_BIN) + "'");
else
throw std::runtime_error("Unable to find blender at '" +
std::string(DEFAULT_BLENDER_BIN) + "'");
}
else if (!strcmp(lineBuf, "NOADDON"))
{
closePipe();
throw std::runtime_error("HECL addon not installed within blender");
}
else if (strcmp(lineBuf, "READY"))
{
closePipe();
throw std::runtime_error("read '" + std::string(lineBuf) + "' from blender; expected 'READY'");
}
writeLine("ACK");
writeLine("HELLOBLENDER!!");
readLine(lineBuf, sizeof(lineBuf));
printf("%s\n", lineBuf);
quitBlender();
}
CBlenderConnection::~CBlenderConnection()
{
closePipe();
}
void CBlenderConnection::quitBlender()
{
writeLine("QUIT");
char lineBuf[256];
readLine(lineBuf, sizeof(lineBuf));
printf("%s\n", lineBuf);
}

View File

@@ -1,14 +1,34 @@
#ifndef CBLENDERCONNECTION_HPP
#define CBLENDERCONNECTION_HPP
#if _WIN32
#define _WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#else
#include <unistd.h>
#endif
class CBlenderConnection
{
#if _WIN32
HANDLE m_blenderProc;
HANDLE m_readpipe;
HANDLE m_writepipe;
#else
pid_t m_blenderProc;
int m_readpipe[2];
int m_writepipe[2];
#endif
size_t readLine(char* buf, size_t bufSz);
size_t writeLine(const char* buf);
size_t readBuf(char* buf, size_t len);
size_t writeBuf(const char* buf, size_t len);
void closePipe();
public:
CBlenderConnection();
CBlenderConnection(bool silenceBlender=false);
~CBlenderConnection();
void quitBlender();
};
#endif // CBLENDERCONNECTION_HPP

View File

@@ -97,7 +97,7 @@ def generate_skeleton_info(armature, endian_char='<'):
def cook(writefd, platform_type, endian_char):
mesh_obj = bpy.data.objects[bpy.context.scene.hecl_mesh_obj]
if mesh_obj.type != 'MESH':
raise RuntimeError("{0} is not a mesh".format(mesh_obj.name))
raise RuntimeError("%s is not a mesh" % mesh_obj.name)
# Partial meshes
part_meshes = set()
@@ -162,7 +162,6 @@ def cook(writefd, platform_type, endian_char):
for mat in bpy.data.materials:
if mat.name.endswith('_%u_%u' % (grp_idx, mat_idx)):
hecl_str = hmdl_shader.shader(mat, mesh_obj, bpy.data.filepath)
else:
mat = mesh_obj.data.materials[mat_idx]

View File

@@ -42,8 +42,11 @@ def recursive_color_trace(mat_obj, mesh_obj, blend_path, node, socket=None):
elif node.type == 'TEXTURE':
if not node.texture or not hasattr(node.texture, 'name'):
raise RuntimeError("HMDL texture nodes must specify a texture object")
if not node.inputs['Vector'].is_linked:
raise RuntimeError("HMDL texture nodes must have a 'Geometry', 'Group' UV modifier node linked")
raise RuntimeError("HMDL texture nodes must have a 'Geometry' or 'Group' UV modifier node linked")
# Determine matrix generator type
matrix_str = None
@@ -89,6 +92,8 @@ def recursive_color_trace(mat_obj, mesh_obj, blend_path, node, socket=None):
if soc_from.name == 'UV':
uv_name = soc_from.node.uv_layer
uv_idx = mesh_obj.data.uv_layers.find(uv_name)
if uv_idx == -1:
raise RuntimeError('UV Layer "%s" doesn\'t exist' % uv_name)
uvsource_str = 'hecl_TexCoord[%d]' % uv_idx
elif soc_from.name == 'Normal':
@@ -163,8 +168,11 @@ def recursive_alpha_trace(mat_obj, mesh_obj, blend_path, node, socket=None):
elif node.type == 'TEXTURE':
if not node.texture or not hasattr(node.texture, 'name'):
raise RuntimeError("HMDL texture nodes must specify a texture object")
if not node.inputs['Vector'].is_linked:
raise RuntimeError("HMDL texture nodes must have a 'Geometry', 'Group' UV modifier node linked")
raise RuntimeError("HMDL texture nodes must have a 'Geometry' or 'Group' UV modifier node linked")
# Determine matrix generator type
matrix_str = None
@@ -210,6 +218,8 @@ def recursive_alpha_trace(mat_obj, mesh_obj, blend_path, node, socket=None):
if soc_from.name == 'UV':
uv_name = soc_from.node.uv_layer
uv_idx = mesh_obj.data.uv_layers.find(uv_name)
if uv_idx == -1:
raise RuntimeError('UV Layer "%s" doesn\'t exist' % uv_name)
uvsource_str = 'hecl_TexCoord[%d]' % uv_idx
elif soc_from.name == 'Normal':

View File

@@ -3,7 +3,7 @@ HMDL Export Blender Addon
By Jack Andersen <jackoalan@gmail.com>
This file defines the `hmdl_skin` class to iteratively construct
a Skinning Info Section for `PAR1` HMDL files. Used by draw-format
a Skinning Info Section for HMDL files. Used by draw-format
generators to select an optimal skin entry for a draw primitive,
or have a new one established.
'''
@@ -96,6 +96,3 @@ class hmdl_skin:
return info_bytes

View File

@@ -1,9 +1,13 @@
import bpy, sys, os
# Extract pipe file descriptors from arguments
print(sys.argv)
if '--' not in sys.argv:
bpy.ops.wm.quit_blender()
args = sys.argv[sys.argv.index('--')+1:]
readfd = int(args[0])
writefd = int(args[1])
print('READ', readfd, 'WRITE', writefd)
def readpipeline():
retval = bytearray()
@@ -20,6 +24,12 @@ def quitblender():
writepipeline(b'QUITTING')
bpy.ops.wm.quit_blender()
# Check that HECL addon is installed/enabled
if 'hecl' not in bpy.context.user_preferences.addons:
if 'FINISHED' not in bpy.ops.wm.addon_enable(module='hecl'):
writepipeline(b'NOADDON')
bpy.ops.wm.quit_blender()
# Intro handshake
writepipeline(b'READY')
ackbytes = readpipeline()
@@ -34,9 +44,12 @@ while True:
quitblender()
elif cmdline[0] == b'OPEN':
bpy.ops.wm.open_mainfile(filepath=cmdline[1].encode())
bpy.ops.wm.open_mainfile(filepath=cmdline[1].decode())
writepipeline(b'SUCCESS')
elif cmdline[0] == b'TYPE':
objname = cmdline[1].encode()
objname = cmdline[1].decode()
else:
writepipeline(b'RESP ' + cmdline[0])