mirror of https://github.com/AxioDL/metaforce.git
More graceful handling of non-installed blender
This commit is contained in:
parent
20dfc56ba7
commit
46b04925c3
|
@ -24,24 +24,21 @@ if 'TMPDIR' in os.environ:
|
||||||
|
|
||||||
err_path += "/hecl_%016X.derp" % os.getpid()
|
err_path += "/hecl_%016X.derp" % os.getpid()
|
||||||
|
|
||||||
def readpipeline():
|
def readpipestr():
|
||||||
retval = bytearray()
|
read_len = struct.unpack('I', os.read(readfd, 4))[0]
|
||||||
while True:
|
return os.read(readfd, read_len)
|
||||||
ch = os.read(readfd, 1)
|
|
||||||
if ch == b'\n' or ch == b'':
|
|
||||||
return retval
|
|
||||||
retval += ch
|
|
||||||
|
|
||||||
def writepipeline(linebytes):
|
def writepipestr(linebytes):
|
||||||
#print('LINE', linebytes)
|
#print('LINE', linebytes)
|
||||||
os.write(writefd, linebytes + b'\n')
|
os.write(writefd, struct.pack('I', len(linebytes)))
|
||||||
|
os.write(writefd, linebytes)
|
||||||
|
|
||||||
def writepipebuf(linebytes):
|
def writepipebuf(linebytes):
|
||||||
#print('BUF', linebytes)
|
#print('BUF', linebytes)
|
||||||
os.write(writefd, linebytes)
|
os.write(writefd, linebytes)
|
||||||
|
|
||||||
def quitblender():
|
def quitblender():
|
||||||
writepipeline(b'QUITTING')
|
writepipestr(b'QUITTING')
|
||||||
bpy.ops.wm.quit_blender()
|
bpy.ops.wm.quit_blender()
|
||||||
|
|
||||||
# If there's a third argument, use it as the .zip path containing the addon
|
# If there's a third argument, use it as the .zip path containing the addon
|
||||||
|
@ -61,17 +58,17 @@ if bpy.context.user_preferences.addons.find('hecl') == -1:
|
||||||
try:
|
try:
|
||||||
import hecl
|
import hecl
|
||||||
except:
|
except:
|
||||||
writepipeline(b'NOADDON')
|
writepipestr(b'NOADDON')
|
||||||
bpy.ops.wm.quit_blender()
|
bpy.ops.wm.quit_blender()
|
||||||
|
|
||||||
# Quit if just installed
|
# Quit if just installed
|
||||||
if did_install:
|
if did_install:
|
||||||
writepipeline(b'ADDONINSTALLED')
|
writepipestr(b'ADDONINSTALLED')
|
||||||
bpy.ops.wm.quit_blender()
|
bpy.ops.wm.quit_blender()
|
||||||
|
|
||||||
# Intro handshake
|
# Intro handshake
|
||||||
writepipeline(b'READY')
|
writepipestr(b'READY')
|
||||||
ackbytes = readpipeline()
|
ackbytes = readpipestr()
|
||||||
if ackbytes != b'ACK':
|
if ackbytes != b'ACK':
|
||||||
quitblender()
|
quitblender()
|
||||||
|
|
||||||
|
@ -79,9 +76,9 @@ if ackbytes != b'ACK':
|
||||||
orig_rot = bpy.context.object.rotation_mode
|
orig_rot = bpy.context.object.rotation_mode
|
||||||
try:
|
try:
|
||||||
bpy.context.object.rotation_mode = 'QUATERNION_SLERP'
|
bpy.context.object.rotation_mode = 'QUATERNION_SLERP'
|
||||||
writepipeline(b'SLERP1')
|
writepipestr(b'SLERP1')
|
||||||
except:
|
except:
|
||||||
writepipeline(b'SLERP0')
|
writepipestr(b'SLERP0')
|
||||||
bpy.context.object.rotation_mode = orig_rot
|
bpy.context.object.rotation_mode = orig_rot
|
||||||
|
|
||||||
# Count brackets
|
# Count brackets
|
||||||
|
@ -96,7 +93,7 @@ def count_brackets(linestr):
|
||||||
|
|
||||||
# Read line of space-separated/quoted arguments
|
# Read line of space-separated/quoted arguments
|
||||||
def read_cmdargs():
|
def read_cmdargs():
|
||||||
cmdline = readpipeline()
|
cmdline = readpipestr()
|
||||||
if cmdline == b'':
|
if cmdline == b'':
|
||||||
print('HECL connection lost')
|
print('HECL connection lost')
|
||||||
bpy.ops.wm.quit_blender()
|
bpy.ops.wm.quit_blender()
|
||||||
|
@ -114,11 +111,11 @@ def exec_compbuf(compbuf, globals):
|
||||||
|
|
||||||
# Command loop for writing animation key data to blender
|
# Command loop for writing animation key data to blender
|
||||||
def animin_loop(globals):
|
def animin_loop(globals):
|
||||||
writepipeline(b'ANIMREADY')
|
writepipestr(b'ANIMREADY')
|
||||||
while True:
|
while True:
|
||||||
crv_type = struct.unpack('b', os.read(readfd, 1))
|
crv_type = struct.unpack('b', os.read(readfd, 1))
|
||||||
if crv_type[0] < 0:
|
if crv_type[0] < 0:
|
||||||
writepipeline(b'ANIMDONE')
|
writepipestr(b'ANIMDONE')
|
||||||
return
|
return
|
||||||
elif crv_type[0] == 0:
|
elif crv_type[0] == 0:
|
||||||
crvs = globals['rotCurves']
|
crvs = globals['rotCurves']
|
||||||
|
@ -146,13 +143,13 @@ def animin_loop(globals):
|
||||||
|
|
||||||
# Command loop for reading data from blender
|
# Command loop for reading data from blender
|
||||||
def dataout_loop():
|
def dataout_loop():
|
||||||
writepipeline(b'READY')
|
writepipestr(b'READY')
|
||||||
while True:
|
while True:
|
||||||
cmdargs = read_cmdargs()
|
cmdargs = read_cmdargs()
|
||||||
print(cmdargs)
|
print(cmdargs)
|
||||||
|
|
||||||
if cmdargs[0] == 'DATAEND':
|
if cmdargs[0] == 'DATAEND':
|
||||||
writepipeline(b'DONE')
|
writepipestr(b'DONE')
|
||||||
return
|
return
|
||||||
|
|
||||||
elif cmdargs[0] == 'MESHLIST':
|
elif cmdargs[0] == 'MESHLIST':
|
||||||
|
@ -163,17 +160,17 @@ def dataout_loop():
|
||||||
writepipebuf(struct.pack('I', meshCount))
|
writepipebuf(struct.pack('I', meshCount))
|
||||||
for meshobj in bpy.data.objects:
|
for meshobj in bpy.data.objects:
|
||||||
if meshobj.type == 'MESH' and not meshobj.library:
|
if meshobj.type == 'MESH' and not meshobj.library:
|
||||||
writepipeline(meshobj.name.encode())
|
writepipestr(meshobj.name.encode())
|
||||||
|
|
||||||
elif cmdargs[0] == 'MESHCOMPILE':
|
elif cmdargs[0] == 'MESHCOMPILE':
|
||||||
maxSkinBanks = int(cmdargs[2])
|
maxSkinBanks = int(cmdargs[2])
|
||||||
|
|
||||||
meshName = bpy.context.scene.hecl_mesh_obj
|
meshName = bpy.context.scene.hecl_mesh_obj
|
||||||
if meshName not in bpy.data.objects:
|
if meshName not in bpy.data.objects:
|
||||||
writepipeline(('mesh %s not found' % meshName).encode())
|
writepipestr(('mesh %s not found' % meshName).encode())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], cmdargs[1], maxSkinBanks)
|
hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], cmdargs[1], maxSkinBanks)
|
||||||
|
|
||||||
elif cmdargs[0] == 'MESHCOMPILENAME':
|
elif cmdargs[0] == 'MESHCOMPILENAME':
|
||||||
|
@ -181,20 +178,20 @@ def dataout_loop():
|
||||||
maxSkinBanks = int(cmdargs[3])
|
maxSkinBanks = int(cmdargs[3])
|
||||||
|
|
||||||
if meshName not in bpy.data.objects:
|
if meshName not in bpy.data.objects:
|
||||||
writepipeline(('mesh %s not found' % meshName).encode())
|
writepipestr(('mesh %s not found' % meshName).encode())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], cmdargs[2], maxSkinBanks)
|
hecl.hmdl.cook(writepipebuf, bpy.data.objects[meshName], cmdargs[2], maxSkinBanks)
|
||||||
|
|
||||||
elif cmdargs[0] == 'MESHCOMPILENAMECOLLISION':
|
elif cmdargs[0] == 'MESHCOMPILENAMECOLLISION':
|
||||||
meshName = cmdargs[1]
|
meshName = cmdargs[1]
|
||||||
|
|
||||||
if meshName not in bpy.data.objects:
|
if meshName not in bpy.data.objects:
|
||||||
writepipeline(('mesh %s not found' % meshName).encode())
|
writepipestr(('mesh %s not found' % meshName).encode())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.hmdl.cookcol(writepipebuf, bpy.data.objects[meshName])
|
hecl.hmdl.cookcol(writepipebuf, bpy.data.objects[meshName])
|
||||||
|
|
||||||
elif cmdargs[0] == 'MESHCOMPILEALL':
|
elif cmdargs[0] == 'MESHCOMPILEALL':
|
||||||
|
@ -209,7 +206,7 @@ def dataout_loop():
|
||||||
bpy.context.scene.objects.active = join_obj
|
bpy.context.scene.objects.active = join_obj
|
||||||
bpy.ops.object.join()
|
bpy.ops.object.join()
|
||||||
|
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.hmdl.cook(writepipebuf, join_obj, cmdargs[1], maxSkinBanks, maxOctantLength)
|
hecl.hmdl.cook(writepipebuf, join_obj, cmdargs[1], maxSkinBanks, maxOctantLength)
|
||||||
|
|
||||||
bpy.context.scene.objects.unlink(join_obj)
|
bpy.context.scene.objects.unlink(join_obj)
|
||||||
|
@ -217,11 +214,11 @@ def dataout_loop():
|
||||||
bpy.data.meshes.remove(join_mesh)
|
bpy.data.meshes.remove(join_mesh)
|
||||||
|
|
||||||
elif cmdargs[0] == 'WORLDCOMPILE':
|
elif cmdargs[0] == 'WORLDCOMPILE':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.swld.cook(writepipebuf)
|
hecl.swld.cook(writepipebuf)
|
||||||
|
|
||||||
elif cmdargs[0] == 'LIGHTCOMPILEALL':
|
elif cmdargs[0] == 'LIGHTCOMPILEALL':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
lampCount = 0;
|
lampCount = 0;
|
||||||
for obj in bpy.context.scene.objects:
|
for obj in bpy.context.scene.objects:
|
||||||
if obj.type == 'LAMP':
|
if obj.type == 'LAMP':
|
||||||
|
@ -292,7 +289,7 @@ def dataout_loop():
|
||||||
castShadow))
|
castShadow))
|
||||||
|
|
||||||
elif cmdargs[0] == 'GETTEXTURES':
|
elif cmdargs[0] == 'GETTEXTURES':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
|
|
||||||
img_count = 0
|
img_count = 0
|
||||||
for img in bpy.data.images:
|
for img in bpy.data.images:
|
||||||
|
@ -307,38 +304,38 @@ def dataout_loop():
|
||||||
writepipebuf(path.encode())
|
writepipebuf(path.encode())
|
||||||
|
|
||||||
elif cmdargs[0] == 'ACTORCOMPILE':
|
elif cmdargs[0] == 'ACTORCOMPILE':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.sact.cook(writepipebuf)
|
hecl.sact.cook(writepipebuf)
|
||||||
|
|
||||||
elif cmdargs[0] == 'ACTORCOMPILECHARACTERONLY':
|
elif cmdargs[0] == 'ACTORCOMPILECHARACTERONLY':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.sact.cook_character_only(writepipebuf)
|
hecl.sact.cook_character_only(writepipebuf)
|
||||||
|
|
||||||
elif cmdargs[0] == 'GETARMATURENAMES':
|
elif cmdargs[0] == 'GETARMATURENAMES':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.sact.get_armature_names(writepipebuf)
|
hecl.sact.get_armature_names(writepipebuf)
|
||||||
|
|
||||||
elif cmdargs[0] == 'GETSUBTYPENAMES':
|
elif cmdargs[0] == 'GETSUBTYPENAMES':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.sact.get_subtype_names(writepipebuf)
|
hecl.sact.get_subtype_names(writepipebuf)
|
||||||
|
|
||||||
elif cmdargs[0] == 'GETACTIONNAMES':
|
elif cmdargs[0] == 'GETACTIONNAMES':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.sact.get_action_names(writepipebuf)
|
hecl.sact.get_action_names(writepipebuf)
|
||||||
|
|
||||||
elif cmdargs[0] == 'GETBONEMATRICES':
|
elif cmdargs[0] == 'GETBONEMATRICES':
|
||||||
armName = cmdargs[1]
|
armName = cmdargs[1]
|
||||||
|
|
||||||
if armName not in bpy.data.objects:
|
if armName not in bpy.data.objects:
|
||||||
writepipeline(('armature %s not found' % armName).encode())
|
writepipestr(('armature %s not found' % armName).encode())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
armObj = bpy.data.objects[armName]
|
armObj = bpy.data.objects[armName]
|
||||||
if armObj.type != 'ARMATURE':
|
if armObj.type != 'ARMATURE':
|
||||||
writepipeline(('object %s not an ARMATURE' % armName).encode())
|
writepipestr(('object %s not an ARMATURE' % armName).encode())
|
||||||
continue
|
continue
|
||||||
|
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
writepipebuf(struct.pack('I', len(armObj.data.bones)))
|
writepipebuf(struct.pack('I', len(armObj.data.bones)))
|
||||||
for bone in armObj.data.bones:
|
for bone in armObj.data.bones:
|
||||||
writepipebuf(struct.pack('I', len(bone.name)))
|
writepipebuf(struct.pack('I', len(bone.name)))
|
||||||
|
@ -364,9 +361,9 @@ try:
|
||||||
if bpy.ops.object.mode_set.poll():
|
if bpy.ops.object.mode_set.poll():
|
||||||
bpy.ops.object.mode_set(mode = 'OBJECT')
|
bpy.ops.object.mode_set(mode = 'OBJECT')
|
||||||
loaded_blend = cmdargs[1]
|
loaded_blend = cmdargs[1]
|
||||||
writepipeline(b'FINISHED')
|
writepipestr(b'FINISHED')
|
||||||
else:
|
else:
|
||||||
writepipeline(b'CANCELLED')
|
writepipestr(b'CANCELLED')
|
||||||
|
|
||||||
elif cmdargs[0] == 'CREATE':
|
elif cmdargs[0] == 'CREATE':
|
||||||
if len(cmdargs) >= 4:
|
if len(cmdargs) >= 4:
|
||||||
|
@ -379,40 +376,40 @@ try:
|
||||||
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=cmdargs[1]):
|
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=cmdargs[1]):
|
||||||
bpy.ops.file.hecl_patching_load()
|
bpy.ops.file.hecl_patching_load()
|
||||||
bpy.context.scene.hecl_type = cmdargs[2]
|
bpy.context.scene.hecl_type = cmdargs[2]
|
||||||
writepipeline(b'FINISHED')
|
writepipestr(b'FINISHED')
|
||||||
else:
|
else:
|
||||||
writepipeline(b'CANCELLED')
|
writepipestr(b'CANCELLED')
|
||||||
|
|
||||||
elif cmdargs[0] == 'GETTYPE':
|
elif cmdargs[0] == 'GETTYPE':
|
||||||
writepipeline(bpy.context.scene.hecl_type.encode())
|
writepipestr(bpy.context.scene.hecl_type.encode())
|
||||||
|
|
||||||
elif cmdargs[0] == 'GETMESHRIGGED':
|
elif cmdargs[0] == 'GETMESHRIGGED':
|
||||||
meshName = bpy.context.scene.hecl_mesh_obj
|
meshName = bpy.context.scene.hecl_mesh_obj
|
||||||
if meshName not in bpy.data.objects:
|
if meshName not in bpy.data.objects:
|
||||||
writepipeline(b'FALSE')
|
writepipestr(b'FALSE')
|
||||||
else:
|
else:
|
||||||
if len(bpy.data.objects[meshName].vertex_groups):
|
if len(bpy.data.objects[meshName].vertex_groups):
|
||||||
writepipeline(b'TRUE')
|
writepipestr(b'TRUE')
|
||||||
else:
|
else:
|
||||||
writepipeline(b'FALSE')
|
writepipestr(b'FALSE')
|
||||||
|
|
||||||
elif cmdargs[0] == 'SAVE':
|
elif cmdargs[0] == 'SAVE':
|
||||||
bpy.context.user_preferences.filepaths.save_version = 0
|
bpy.context.user_preferences.filepaths.save_version = 0
|
||||||
print('SAVING %s' % loaded_blend)
|
print('SAVING %s' % loaded_blend)
|
||||||
if loaded_blend:
|
if loaded_blend:
|
||||||
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=loaded_blend, check_existing=False, compress=True):
|
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=loaded_blend, check_existing=False, compress=True):
|
||||||
writepipeline(b'FINISHED')
|
writepipestr(b'FINISHED')
|
||||||
else:
|
else:
|
||||||
writepipeline(b'CANCELLED')
|
writepipestr(b'CANCELLED')
|
||||||
|
|
||||||
elif cmdargs[0] == 'PYBEGIN':
|
elif cmdargs[0] == 'PYBEGIN':
|
||||||
writepipeline(b'READY')
|
writepipestr(b'READY')
|
||||||
globals = {'hecl':hecl}
|
globals = {'hecl':hecl}
|
||||||
compbuf = str()
|
compbuf = str()
|
||||||
bracket_count = 0
|
bracket_count = 0
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
line = readpipeline()
|
line = readpipestr()
|
||||||
|
|
||||||
# ANIM check
|
# ANIM check
|
||||||
if line == b'PYANIM':
|
if line == b'PYANIM':
|
||||||
|
@ -429,13 +426,13 @@ try:
|
||||||
if len(compbuf):
|
if len(compbuf):
|
||||||
exec_compbuf(compbuf, globals)
|
exec_compbuf(compbuf, globals)
|
||||||
compbuf = str()
|
compbuf = str()
|
||||||
writepipeline(b'DONE')
|
writepipestr(b'DONE')
|
||||||
break
|
break
|
||||||
|
|
||||||
# Syntax filter
|
# Syntax filter
|
||||||
linestr = line.decode().rstrip()
|
linestr = line.decode().rstrip()
|
||||||
if not len(linestr) or linestr.lstrip()[0] == '#':
|
if not len(linestr) or linestr.lstrip()[0] == '#':
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
continue
|
continue
|
||||||
leading_spaces = len(linestr) - len(linestr.lstrip())
|
leading_spaces = len(linestr) - len(linestr.lstrip())
|
||||||
|
|
||||||
|
@ -445,7 +442,7 @@ try:
|
||||||
compbuf += '\n'
|
compbuf += '\n'
|
||||||
compbuf += linestr
|
compbuf += linestr
|
||||||
bracket_count += count_brackets(linestr)
|
bracket_count += count_brackets(linestr)
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Complete non-block statement in compbuf
|
# Complete non-block statement in compbuf
|
||||||
|
@ -457,26 +454,26 @@ try:
|
||||||
bracket_count += count_brackets(linestr)
|
bracket_count += count_brackets(linestr)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
writepipeline(b'EXCEPTION')
|
writepipestr(b'EXCEPTION')
|
||||||
raise
|
raise
|
||||||
break
|
break
|
||||||
writepipeline(b'OK')
|
writepipestr(b'OK')
|
||||||
|
|
||||||
elif cmdargs[0] == 'PYEND':
|
elif cmdargs[0] == 'PYEND':
|
||||||
writepipeline(b'ERROR')
|
writepipestr(b'ERROR')
|
||||||
|
|
||||||
elif cmdargs[0] == 'DATABEGIN':
|
elif cmdargs[0] == 'DATABEGIN':
|
||||||
try:
|
try:
|
||||||
dataout_loop()
|
dataout_loop()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
writepipeline(b'EXCEPTION')
|
writepipestr(b'EXCEPTION')
|
||||||
raise
|
raise
|
||||||
|
|
||||||
elif cmdargs[0] == 'DATAEND':
|
elif cmdargs[0] == 'DATAEND':
|
||||||
writepipeline(b'ERROR')
|
writepipestr(b'ERROR')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
hecl.command(cmdargs, writepipeline, writepipebuf)
|
hecl.command(cmdargs, writepipestr, writepipebuf)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
import traceback
|
import traceback
|
||||||
|
|
|
@ -66,8 +66,10 @@ private:
|
||||||
ProjectPath m_loadedBlend;
|
ProjectPath m_loadedBlend;
|
||||||
std::string m_startupBlend;
|
std::string m_startupBlend;
|
||||||
hecl::SystemString m_errPath;
|
hecl::SystemString m_errPath;
|
||||||
size_t _readLine(char* buf, size_t bufSz);
|
uint32_t _readStr(char* buf, uint32_t bufSz);
|
||||||
size_t _writeLine(const char* buf);
|
uint32_t _writeStr(const char* str, uint32_t len, int wpipe);
|
||||||
|
uint32_t _writeStr(const char* str, uint32_t len) { return _writeStr(str, len, m_writepipe[1]); }
|
||||||
|
uint32_t _writeStr(const char* str) { return _writeStr(str, strlen(str)); }
|
||||||
size_t _readBuf(void* buf, size_t len);
|
size_t _readBuf(void* buf, size_t len);
|
||||||
size_t _writeBuf(const void* buf, size_t len);
|
size_t _writeBuf(const void* buf, size_t len);
|
||||||
void _closePipe();
|
void _closePipe();
|
||||||
|
@ -121,9 +123,9 @@ public:
|
||||||
m_sbuf(*this, deleteOnError)
|
m_sbuf(*this, deleteOnError)
|
||||||
{
|
{
|
||||||
m_parent->m_lock = true;
|
m_parent->m_lock = true;
|
||||||
m_parent->_writeLine("PYBEGIN");
|
m_parent->_writeStr("PYBEGIN");
|
||||||
char readBuf[16];
|
char readBuf[16];
|
||||||
m_parent->_readLine(readBuf, 16);
|
m_parent->_readStr(readBuf, 16);
|
||||||
if (strcmp(readBuf, "READY"))
|
if (strcmp(readBuf, "READY"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to open PyOutStream with blender");
|
BlenderLog.report(logvisor::Fatal, "unable to open PyOutStream with blender");
|
||||||
}
|
}
|
||||||
|
@ -137,9 +139,9 @@ public:
|
||||||
{
|
{
|
||||||
if (m_parent && m_parent->m_lock)
|
if (m_parent && m_parent->m_lock)
|
||||||
{
|
{
|
||||||
m_parent->_writeLine("PYEND");
|
m_parent->_writeStr("PYEND");
|
||||||
char readBuf[16];
|
char readBuf[16];
|
||||||
m_parent->_readLine(readBuf, 16);
|
m_parent->_readStr(readBuf, 16);
|
||||||
if (strcmp(readBuf, "DONE"))
|
if (strcmp(readBuf, "DONE"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to close PyOutStream with blender");
|
BlenderLog.report(logvisor::Fatal, "unable to close PyOutStream with blender");
|
||||||
m_parent->m_lock = false;
|
m_parent->m_lock = false;
|
||||||
|
@ -237,9 +239,9 @@ public:
|
||||||
ANIMOutStream(BlenderConnection* parent)
|
ANIMOutStream(BlenderConnection* parent)
|
||||||
: m_parent(parent)
|
: m_parent(parent)
|
||||||
{
|
{
|
||||||
m_parent->_writeLine("PYANIM");
|
m_parent->_writeStr("PYANIM");
|
||||||
char readBuf[16];
|
char readBuf[16];
|
||||||
m_parent->_readLine(readBuf, 16);
|
m_parent->_readStr(readBuf, 16);
|
||||||
if (strcmp(readBuf, "ANIMREADY"))
|
if (strcmp(readBuf, "ANIMREADY"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to open ANIMOutStream");
|
BlenderLog.report(logvisor::Fatal, "unable to open ANIMOutStream");
|
||||||
}
|
}
|
||||||
|
@ -248,7 +250,7 @@ public:
|
||||||
char tp = -1;
|
char tp = -1;
|
||||||
m_parent->_writeBuf(&tp, 1);
|
m_parent->_writeBuf(&tp, 1);
|
||||||
char readBuf[16];
|
char readBuf[16];
|
||||||
m_parent->_readLine(readBuf, 16);
|
m_parent->_readStr(readBuf, 16);
|
||||||
if (strcmp(readBuf, "ANIMDONE"))
|
if (strcmp(readBuf, "ANIMDONE"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to close ANIMOutStream");
|
BlenderLog.report(logvisor::Fatal, "unable to close ANIMOutStream");
|
||||||
}
|
}
|
||||||
|
@ -307,9 +309,9 @@ public:
|
||||||
: m_parent(parent)
|
: m_parent(parent)
|
||||||
{
|
{
|
||||||
m_parent->m_lock = true;
|
m_parent->m_lock = true;
|
||||||
m_parent->_writeLine("DATABEGIN");
|
m_parent->_writeStr("DATABEGIN");
|
||||||
char readBuf[16];
|
char readBuf[16];
|
||||||
m_parent->_readLine(readBuf, 16);
|
m_parent->_readStr(readBuf, 16);
|
||||||
if (strcmp(readBuf, "READY"))
|
if (strcmp(readBuf, "READY"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to open DataStream with blender");
|
BlenderLog.report(logvisor::Fatal, "unable to open DataStream with blender");
|
||||||
}
|
}
|
||||||
|
@ -322,9 +324,9 @@ public:
|
||||||
{
|
{
|
||||||
if (m_parent && m_parent->m_lock)
|
if (m_parent && m_parent->m_lock)
|
||||||
{
|
{
|
||||||
m_parent->_writeLine("DATAEND");
|
m_parent->_writeStr("DATAEND");
|
||||||
char readBuf[16];
|
char readBuf[16];
|
||||||
m_parent->_readLine(readBuf, 16);
|
m_parent->_readStr(readBuf, 16);
|
||||||
if (strcmp(readBuf, "DONE"))
|
if (strcmp(readBuf, "DONE"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to close DataStream with blender");
|
BlenderLog.report(logvisor::Fatal, "unable to close DataStream with blender");
|
||||||
m_parent->m_lock = false;
|
m_parent->m_lock = false;
|
||||||
|
@ -333,7 +335,7 @@ public:
|
||||||
|
|
||||||
std::vector<std::string> getMeshList()
|
std::vector<std::string> getMeshList()
|
||||||
{
|
{
|
||||||
m_parent->_writeLine("MESHLIST");
|
m_parent->_writeStr("MESHLIST");
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
m_parent->_readBuf(&count, 4);
|
m_parent->_readBuf(&count, 4);
|
||||||
std::vector<std::string> retval;
|
std::vector<std::string> retval;
|
||||||
|
@ -341,7 +343,7 @@ public:
|
||||||
for (uint32_t i=0 ; i<count ; ++i)
|
for (uint32_t i=0 ; i<count ; ++i)
|
||||||
{
|
{
|
||||||
char name[128];
|
char name[128];
|
||||||
m_parent->_readLine(name, 128);
|
m_parent->_readStr(name, 128);
|
||||||
retval.push_back(name);
|
retval.push_back(name);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
#ifndef HECL_UNIFORMBUFFERPOOL_HPP
|
||||||
|
#define HECL_UNIFORMBUFFERPOOL_HPP
|
||||||
|
|
||||||
|
#include <boo/boo.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "BitVector.hpp"
|
||||||
|
|
||||||
|
namespace hecl
|
||||||
|
{
|
||||||
|
|
||||||
|
#define HECL_UBUFPOOL_ALLOCATION_BLOCK 262144
|
||||||
|
|
||||||
|
/** This class provides a uniform structure for packing instanced uniform-buffer
|
||||||
|
* data with consistent stride into a vector of 256K 'Buckets'.
|
||||||
|
*
|
||||||
|
* This results in a space-efficient way of managing GPU data of things like UI
|
||||||
|
* widgets. These can potentially have numerous binding instances, so this avoids
|
||||||
|
* allocating a full GPU buffer object for each. */
|
||||||
|
template <typename UniformStruct>
|
||||||
|
class UniformBufferPool
|
||||||
|
{
|
||||||
|
/* Resolve div_t type using ssize_t as basis */
|
||||||
|
#if _WIN32
|
||||||
|
using IndexTp = SSIZE_T;
|
||||||
|
#else
|
||||||
|
using IndexTp = ssize_t;
|
||||||
|
#endif
|
||||||
|
struct InvalidTp {};
|
||||||
|
using DivTp = std::conditional_t<std::is_same<IndexTp, long long>::value, std::lldiv_t,
|
||||||
|
std::conditional_t<std::is_same<IndexTp, long>::value, std::ldiv_t,
|
||||||
|
std::conditional_t<std::is_same<IndexTp, int>::value, std::div_t, InvalidTp>>>;
|
||||||
|
static_assert(!std::is_same<DivTp, InvalidTp>::value, "unsupported IndexTp for DivTp resolution");
|
||||||
|
|
||||||
|
/** Size of single element, rounded up to 256-multiple */
|
||||||
|
static constexpr IndexTp m_stride = ROUND_UP_256(sizeof(UniformStruct));
|
||||||
|
static_assert(m_stride <= HECL_UBUFPOOL_ALLOCATION_BLOCK, "Stride too large for uniform pool");
|
||||||
|
|
||||||
|
/** Number of rounded elements per 256K bucket */
|
||||||
|
static constexpr IndexTp m_countPerBucket = HECL_UBUFPOOL_ALLOCATION_BLOCK / m_stride;
|
||||||
|
|
||||||
|
/** Buffer size per bucket (ideally 256K) */
|
||||||
|
static constexpr IndexTp m_sizePerBucket = m_stride * m_countPerBucket;
|
||||||
|
|
||||||
|
/** BitVector indicating free allocation blocks */
|
||||||
|
hecl::llvm::BitVector m_freeBlocks;
|
||||||
|
|
||||||
|
/** Efficient way to get bucket and block simultaneously */
|
||||||
|
DivTp getBucketDiv(IndexTp idx) const { return std::div(idx, m_countPerBucket); }
|
||||||
|
|
||||||
|
/** Buffer pool token */
|
||||||
|
boo::GraphicsBufferPoolToken m_token;
|
||||||
|
|
||||||
|
/** Private bucket info */
|
||||||
|
struct Bucket
|
||||||
|
{
|
||||||
|
boo::IGraphicsBufferD* buffer;
|
||||||
|
uint8_t* cpuBuffer = nullptr;
|
||||||
|
size_t useCount = 0;
|
||||||
|
bool dirty = false;
|
||||||
|
Bucket() = default;
|
||||||
|
Bucket(const Bucket& other) = delete;
|
||||||
|
Bucket& operator=(const Bucket& other) = delete;
|
||||||
|
Bucket(Bucket&& other) = default;
|
||||||
|
Bucket& operator=(Bucket&& other) = default;
|
||||||
|
|
||||||
|
void updateBuffer()
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
buffer->unmap();
|
||||||
|
cpuBuffer = nullptr;
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment(UniformBufferPool& pool)
|
||||||
|
{
|
||||||
|
if (!useCount)
|
||||||
|
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Uniform,
|
||||||
|
pool.m_stride, pool.m_countPerBucket);
|
||||||
|
++useCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decrement(UniformBufferPool& pool)
|
||||||
|
{
|
||||||
|
--useCount;
|
||||||
|
if (!useCount)
|
||||||
|
{
|
||||||
|
pool.m_token.deletePoolBuffer(buffer);
|
||||||
|
buffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::vector<Bucket> m_buckets;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** User block-owning token */
|
||||||
|
class Token
|
||||||
|
{
|
||||||
|
friend class UniformBufferPool;
|
||||||
|
UniformBufferPool& m_pool;
|
||||||
|
IndexTp m_index;
|
||||||
|
DivTp m_div;
|
||||||
|
Token(UniformBufferPool& pool)
|
||||||
|
: m_pool(pool)
|
||||||
|
{
|
||||||
|
auto& freeSpaces = pool.m_freeBlocks;
|
||||||
|
auto& buckets = pool.m_buckets;
|
||||||
|
int idx = freeSpaces.find_first();
|
||||||
|
if (idx == -1)
|
||||||
|
{
|
||||||
|
buckets.emplace_back();
|
||||||
|
m_index = freeSpaces.size();
|
||||||
|
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_index = idx;
|
||||||
|
}
|
||||||
|
freeSpaces.reset(m_index);
|
||||||
|
m_div = pool.getBucketDiv(m_index);
|
||||||
|
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
bucket.increment(m_pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Token(const Token& other) = delete;
|
||||||
|
Token& operator=(const Token& other) = delete;
|
||||||
|
Token& operator=(Token&& other) = delete;
|
||||||
|
Token(Token&& other)
|
||||||
|
: m_pool(other.m_pool), m_index(other.m_index),
|
||||||
|
m_div(other.m_div)
|
||||||
|
{
|
||||||
|
other.m_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Token()
|
||||||
|
{
|
||||||
|
if (m_index != -1)
|
||||||
|
{
|
||||||
|
m_pool.m_freeBlocks.set(m_index);
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
bucket.decrement(m_pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UniformStruct& access()
|
||||||
|
{
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
if (!bucket.cpuBuffer)
|
||||||
|
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
|
||||||
|
bucket.dirty = true;
|
||||||
|
return reinterpret_cast<UniformStruct&>(bucket.cpuBuffer[m_div.rem * m_pool.m_stride]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<boo::IGraphicsBufferD*, IndexTp> getBufferInfo() const
|
||||||
|
{
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
return {bucket.buffer, m_div.rem * m_pool.m_stride};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UniformBufferPool() = default;
|
||||||
|
UniformBufferPool(const UniformBufferPool& other) = delete;
|
||||||
|
UniformBufferPool& operator=(const UniformBufferPool& other) = delete;
|
||||||
|
|
||||||
|
/** Load dirty buffer data into GPU */
|
||||||
|
void updateBuffers()
|
||||||
|
{
|
||||||
|
for (Bucket& bucket : m_buckets)
|
||||||
|
if (bucket.dirty)
|
||||||
|
bucket.updateBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Allocate free block into client-owned Token */
|
||||||
|
Token allocateBlock(boo::IGraphicsDataFactory* factory)
|
||||||
|
{
|
||||||
|
if (!m_token)
|
||||||
|
m_token = factory->newBufferPool();
|
||||||
|
return Token(*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HECL_UNIFORMBUFFERPOOL_HPP
|
|
@ -0,0 +1,189 @@
|
||||||
|
#ifndef HECL_VERTEXBUFFERPOOL_HPP
|
||||||
|
#define HECL_VERTEXBUFFERPOOL_HPP
|
||||||
|
|
||||||
|
#include <boo/boo.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "BitVector.hpp"
|
||||||
|
|
||||||
|
namespace hecl
|
||||||
|
{
|
||||||
|
|
||||||
|
#define HECL_VBUFPOOL_ALLOCATION_BLOCK 262144
|
||||||
|
|
||||||
|
/** This class provides a uniform structure for packing instanced vertex-buffer
|
||||||
|
* data with consistent stride into a vector of 256K 'Buckets'.
|
||||||
|
*
|
||||||
|
* This results in a space-efficient way of managing GPU data of things like UI
|
||||||
|
* widgets. These can potentially have numerous binding instances, so this avoids
|
||||||
|
* allocating a full GPU buffer object for each. */
|
||||||
|
template <typename VertStruct>
|
||||||
|
class VertexBufferPool
|
||||||
|
{
|
||||||
|
/* Resolve div_t type using ssize_t as basis */
|
||||||
|
#if _WIN32
|
||||||
|
using IndexTp = SSIZE_T;
|
||||||
|
#else
|
||||||
|
using IndexTp = ssize_t;
|
||||||
|
#endif
|
||||||
|
struct InvalidTp {};
|
||||||
|
using DivTp = std::conditional_t<std::is_same<IndexTp, long long>::value, std::lldiv_t,
|
||||||
|
std::conditional_t<std::is_same<IndexTp, long>::value, std::ldiv_t,
|
||||||
|
std::conditional_t<std::is_same<IndexTp, int>::value, std::div_t, InvalidTp>>>;
|
||||||
|
static_assert(!std::is_same<DivTp, InvalidTp>::value, "unsupported IndexTp for DivTp resolution");
|
||||||
|
|
||||||
|
/** Size of single element */
|
||||||
|
static constexpr IndexTp m_stride = sizeof(VertStruct);
|
||||||
|
static_assert(m_stride <= HECL_VBUFPOOL_ALLOCATION_BLOCK, "Stride too large for vertex pool");
|
||||||
|
|
||||||
|
/** Number of elements per 256K bucket */
|
||||||
|
static constexpr IndexTp m_countPerBucket = HECL_VBUFPOOL_ALLOCATION_BLOCK / m_stride;
|
||||||
|
|
||||||
|
/** Buffer size per bucket (ideally 256K) */
|
||||||
|
static constexpr IndexTp m_sizePerBucket = m_stride * m_countPerBucket;
|
||||||
|
|
||||||
|
/** BitVector indicating free allocation elements */
|
||||||
|
hecl::llvm::BitVector m_freeElements;
|
||||||
|
|
||||||
|
/** Efficient way to get bucket and element simultaneously */
|
||||||
|
DivTp getBucketDiv(IndexTp idx) const { return std::div(idx, m_countPerBucket); }
|
||||||
|
|
||||||
|
/** Buffer pool token */
|
||||||
|
boo::GraphicsBufferPoolToken m_token;
|
||||||
|
|
||||||
|
/** Private bucket info */
|
||||||
|
struct Bucket
|
||||||
|
{
|
||||||
|
boo::IGraphicsBufferD* buffer;
|
||||||
|
uint8_t* cpuBuffer = nullptr;
|
||||||
|
size_t useCount = 0;
|
||||||
|
bool dirty = false;
|
||||||
|
Bucket() = default;
|
||||||
|
Bucket(const Bucket& other) = delete;
|
||||||
|
Bucket& operator=(const Bucket& other) = delete;
|
||||||
|
Bucket(Bucket&& other) = default;
|
||||||
|
Bucket& operator=(Bucket&& other) = default;
|
||||||
|
|
||||||
|
void updateBuffer()
|
||||||
|
{
|
||||||
|
if (buffer)
|
||||||
|
buffer->unmap();
|
||||||
|
cpuBuffer = nullptr;
|
||||||
|
dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment(VertexBufferPool& pool)
|
||||||
|
{
|
||||||
|
if (!useCount)
|
||||||
|
buffer = pool.m_token.newPoolBuffer(boo::BufferUse::Vertex,
|
||||||
|
pool.m_stride, pool.m_countPerBucket);
|
||||||
|
++useCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void decrement(VertexBufferPool& pool)
|
||||||
|
{
|
||||||
|
--useCount;
|
||||||
|
if (!useCount)
|
||||||
|
{
|
||||||
|
pool.m_token.deletePoolBuffer(buffer);
|
||||||
|
buffer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::vector<Bucket> m_buckets;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** User element-owning token */
|
||||||
|
class Token
|
||||||
|
{
|
||||||
|
friend class VertexBufferPool;
|
||||||
|
VertexBufferPool& m_pool;
|
||||||
|
IndexTp m_index;
|
||||||
|
IndexTp m_count;
|
||||||
|
DivTp m_div;
|
||||||
|
Token(VertexBufferPool& pool, IndexTp count)
|
||||||
|
: m_pool(pool), m_count(count)
|
||||||
|
{
|
||||||
|
assert(count <= pool.m_countPerBucket && "unable to fit in bucket");
|
||||||
|
auto& freeSpaces = pool.m_freeElements;
|
||||||
|
auto& buckets = pool.m_buckets;
|
||||||
|
int idx = freeSpaces.find_first_contiguous(count, pool.m_countPerBucket);
|
||||||
|
if (idx == -1)
|
||||||
|
{
|
||||||
|
buckets.emplace_back();
|
||||||
|
m_index = freeSpaces.size();
|
||||||
|
freeSpaces.resize(freeSpaces.size() + pool.m_countPerBucket, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_index = idx;
|
||||||
|
}
|
||||||
|
freeSpaces.reset(m_index, m_index + count);
|
||||||
|
m_div = pool.getBucketDiv(m_index);
|
||||||
|
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
bucket.increment(pool);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
Token(const Token& other) = delete;
|
||||||
|
Token& operator=(const Token& other) = delete;
|
||||||
|
Token& operator=(Token&& other) = delete;
|
||||||
|
Token(Token&& other)
|
||||||
|
: m_pool(other.m_pool), m_index(other.m_index),
|
||||||
|
m_count(other.m_count), m_div(other.m_div)
|
||||||
|
{
|
||||||
|
other.m_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Token()
|
||||||
|
{
|
||||||
|
if (m_index != -1)
|
||||||
|
{
|
||||||
|
m_pool.m_freeElements.set(m_index, m_index + m_count);
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
bucket.decrement(m_pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VertStruct* access()
|
||||||
|
{
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
if (!bucket.cpuBuffer)
|
||||||
|
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
|
||||||
|
bucket.dirty = true;
|
||||||
|
return reinterpret_cast<VertStruct*>(&bucket.cpuBuffer[m_div.rem * m_pool.m_stride]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<boo::IGraphicsBufferD*, IndexTp> getBufferInfo() const
|
||||||
|
{
|
||||||
|
Bucket& bucket = m_pool.m_buckets[m_div.quot];
|
||||||
|
return {bucket.buffer, m_div.rem};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
VertexBufferPool() = default;
|
||||||
|
VertexBufferPool(const VertexBufferPool& other) = delete;
|
||||||
|
VertexBufferPool& operator=(const VertexBufferPool& other) = delete;
|
||||||
|
|
||||||
|
/** Load dirty buffer data into GPU */
|
||||||
|
void updateBuffers()
|
||||||
|
{
|
||||||
|
for (Bucket& bucket : m_buckets)
|
||||||
|
if (bucket.dirty)
|
||||||
|
bucket.updateBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Allocate free block into client-owned Token */
|
||||||
|
Token allocateBlock(boo::IGraphicsDataFactory* factory, IndexTp count)
|
||||||
|
{
|
||||||
|
if (!m_token)
|
||||||
|
m_token = factory->newBufferPool();
|
||||||
|
return Token(*this, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr IndexTp bucketCapacity() { return m_countPerBucket; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HECL_VERTEXBUFFERPOOL_HPP
|
|
@ -82,58 +82,50 @@ static void InstallStartup(const char* path)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BlenderConnection::_readLine(char* buf, size_t bufSz)
|
uint32_t BlenderConnection::_readStr(char* buf, uint32_t bufSz)
|
||||||
{
|
{
|
||||||
size_t readBytes = 0;
|
uint32_t readLen;
|
||||||
while (true)
|
int ret = read(m_readpipe[0], &readLen, 4);
|
||||||
|
if (ret < 4)
|
||||||
{
|
{
|
||||||
if (readBytes >= bufSz)
|
_blenderDied();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readLen >= bufSz)
|
||||||
|
{
|
||||||
|
BlenderLog.report(logvisor::Fatal, "Pipe buffer overrun [%d/%d]", readLen, bufSz);
|
||||||
|
*buf = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = read(m_readpipe[0], buf, readLen);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
BlenderLog.report(logvisor::Fatal, strerror(errno));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (readLen >= 4)
|
||||||
|
if (!memcmp(buf, "EXCEPTION", std::min(readLen, uint32_t(9))))
|
||||||
{
|
{
|
||||||
BlenderLog.report(logvisor::Fatal, "Pipe buffer overrun");
|
_blenderDied();
|
||||||
*(buf-1) = '\0';
|
|
||||||
return bufSz - 1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
while ((ret = read(m_readpipe[0], buf, 1)) < 0 && errno == EINTR) {}
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
BlenderLog.report(logvisor::Fatal, strerror(errno));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (ret == 1)
|
|
||||||
{
|
*(buf+readLen) = '\0';
|
||||||
if (*buf == '\n')
|
return readLen;
|
||||||
{
|
|
||||||
*buf = '\0';
|
|
||||||
if (readBytes >= 4)
|
|
||||||
if (!memcmp(buf, "EXCEPTION", std::min(readBytes, size_t(9))))
|
|
||||||
_blenderDied();
|
|
||||||
return readBytes;
|
|
||||||
}
|
|
||||||
++readBytes;
|
|
||||||
++buf;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*buf = '\0';
|
|
||||||
if (readBytes >= 4)
|
|
||||||
if (!memcmp(buf, "EXCEPTION", std::min(readBytes, size_t(9))))
|
|
||||||
_blenderDied();
|
|
||||||
return readBytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BlenderConnection::_writeLine(const char* buf)
|
uint32_t BlenderConnection::_writeStr(const char* buf, uint32_t len, int wpipe)
|
||||||
{
|
{
|
||||||
int ret, nlerr;
|
int ret, nlerr;
|
||||||
ret = write(m_writepipe[1], buf, strlen(buf));
|
nlerr = write(wpipe, &len, 4);
|
||||||
|
if (nlerr < 4)
|
||||||
|
goto err;
|
||||||
|
ret = write(wpipe, buf, len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err;
|
goto err;
|
||||||
nlerr = write(m_writepipe[1], "\n", 1);
|
return (uint32_t)ret;
|
||||||
if (nlerr < 0)
|
|
||||||
goto err;
|
|
||||||
return (size_t)ret;
|
|
||||||
err:
|
err:
|
||||||
_blenderDied();
|
_blenderDied();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -382,8 +374,8 @@ BlenderConnection::BlenderConnection(int verbosityLevel)
|
||||||
"--", readfds, writefds, vLevel, blenderAddonPath.c_str(), NULL);
|
"--", readfds, writefds, vLevel, blenderAddonPath.c_str(), NULL);
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
{
|
{
|
||||||
snprintf(errbuf, 256, "NOLAUNCH %s\n", strerror(errno));
|
snprintf(errbuf, 256, "NOLAUNCH %s", strerror(errno));
|
||||||
write(m_writepipe[1], errbuf, strlen(errbuf));
|
_writeStr(errbuf, strlen(errbuf), m_readpipe[1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,15 +386,14 @@ BlenderConnection::BlenderConnection(int verbosityLevel)
|
||||||
"--", readfds, writefds, vLevel, blenderAddonPath.c_str(), NULL);
|
"--", readfds, writefds, vLevel, blenderAddonPath.c_str(), NULL);
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
{
|
{
|
||||||
snprintf(errbuf, 256, "NOLAUNCH %s\n", strerror(errno));
|
snprintf(errbuf, 256, "NOLAUNCH %s", strerror(errno));
|
||||||
write(m_writepipe[1], errbuf, strlen(errbuf));
|
_writeStr(errbuf, strlen(errbuf), m_readpipe[1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unable to find blender */
|
/* Unable to find blender */
|
||||||
write(m_writepipe[1], "NOBLENDER\n", 10);
|
_writeStr("NOBLENDER", 9, m_readpipe[1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
close(m_writepipe[0]);
|
close(m_writepipe[0]);
|
||||||
close(m_readpipe[1]);
|
close(m_readpipe[1]);
|
||||||
|
@ -415,13 +406,14 @@ BlenderConnection::BlenderConnection(int verbosityLevel)
|
||||||
|
|
||||||
/* Handle first response */
|
/* Handle first response */
|
||||||
char lineBuf[256];
|
char lineBuf[256];
|
||||||
_readLine(lineBuf, sizeof(lineBuf));
|
_readStr(lineBuf, sizeof(lineBuf));
|
||||||
if (!strcmp(lineBuf, "NOLAUNCH"))
|
|
||||||
|
if (!strncmp(lineBuf, "NOLAUNCH", 8))
|
||||||
{
|
{
|
||||||
_closePipe();
|
_closePipe();
|
||||||
BlenderLog.report(logvisor::Fatal, "Unable to launch blender");
|
BlenderLog.report(logvisor::Fatal, "Unable to launch blender: %s", lineBuf + 9);
|
||||||
}
|
}
|
||||||
else if (!strcmp(lineBuf, "NOBLENDER"))
|
else if (!strncmp(lineBuf, "NOBLENDER", 9))
|
||||||
{
|
{
|
||||||
_closePipe();
|
_closePipe();
|
||||||
if (blenderBin)
|
if (blenderBin)
|
||||||
|
@ -451,9 +443,9 @@ BlenderConnection::BlenderConnection(int verbosityLevel)
|
||||||
_closePipe();
|
_closePipe();
|
||||||
BlenderLog.report(logvisor::Fatal, "read '%s' from blender; expected 'READY'", lineBuf);
|
BlenderLog.report(logvisor::Fatal, "read '%s' from blender; expected 'READY'", lineBuf);
|
||||||
}
|
}
|
||||||
_writeLine("ACK");
|
_writeStr("ACK");
|
||||||
|
|
||||||
_readLine(lineBuf, 7);
|
_readStr(lineBuf, 7);
|
||||||
if (!strcmp(lineBuf, "SLERP0"))
|
if (!strcmp(lineBuf, "SLERP0"))
|
||||||
m_hasSlerp = false;
|
m_hasSlerp = false;
|
||||||
else if (!strcmp(lineBuf, "SLERP1"))
|
else if (!strcmp(lineBuf, "SLERP1"))
|
||||||
|
@ -484,9 +476,9 @@ BlenderConnection::PyOutStream::StreamBuf::overflow(int_type ch)
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
//printf("FLUSHING %s\n", m_lineBuf.c_str());
|
//printf("FLUSHING %s\n", m_lineBuf.c_str());
|
||||||
m_parent.m_parent->_writeLine(m_lineBuf.c_str());
|
m_parent.m_parent->_writeStr(m_lineBuf.c_str());
|
||||||
char readBuf[16];
|
char readBuf[16];
|
||||||
m_parent.m_parent->_readLine(readBuf, 16);
|
m_parent.m_parent->_readStr(readBuf, 16);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
{
|
{
|
||||||
if (m_deleteOnError)
|
if (m_deleteOnError)
|
||||||
|
@ -518,9 +510,9 @@ bool BlenderConnection::createBlend(const ProjectPath& path, BlendType type)
|
||||||
"BlenderConnection::createBlend() musn't be called with stream active");
|
"BlenderConnection::createBlend() musn't be called with stream active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_writeLine(("CREATE \"" + path.getAbsolutePathUTF8() + "\" " + BlendTypeStrs[int(type)] + " \"" + m_startupBlend + "\"").c_str());
|
_writeStr(("CREATE \"" + path.getAbsolutePathUTF8() + "\" " + BlendTypeStrs[int(type)] + " \"" + m_startupBlend + "\"").c_str());
|
||||||
char lineBuf[256];
|
char lineBuf[256];
|
||||||
_readLine(lineBuf, sizeof(lineBuf));
|
_readStr(lineBuf, sizeof(lineBuf));
|
||||||
if (!strcmp(lineBuf, "FINISHED"))
|
if (!strcmp(lineBuf, "FINISHED"))
|
||||||
{
|
{
|
||||||
/* Delete immediately in case save doesn't occur */
|
/* Delete immediately in case save doesn't occur */
|
||||||
|
@ -542,14 +534,14 @@ bool BlenderConnection::openBlend(const ProjectPath& path, bool force)
|
||||||
}
|
}
|
||||||
if (!force && path == m_loadedBlend)
|
if (!force && path == m_loadedBlend)
|
||||||
return true;
|
return true;
|
||||||
_writeLine(("OPEN \"" + path.getAbsolutePathUTF8() + "\"").c_str());
|
_writeStr(("OPEN \"" + path.getAbsolutePathUTF8() + "\"").c_str());
|
||||||
char lineBuf[256];
|
char lineBuf[256];
|
||||||
_readLine(lineBuf, sizeof(lineBuf));
|
_readStr(lineBuf, sizeof(lineBuf));
|
||||||
if (!strcmp(lineBuf, "FINISHED"))
|
if (!strcmp(lineBuf, "FINISHED"))
|
||||||
{
|
{
|
||||||
m_loadedBlend = path;
|
m_loadedBlend = path;
|
||||||
_writeLine("GETTYPE");
|
_writeStr("GETTYPE");
|
||||||
_readLine(lineBuf, sizeof(lineBuf));
|
_readStr(lineBuf, sizeof(lineBuf));
|
||||||
m_loadedType = BlendType::None;
|
m_loadedType = BlendType::None;
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
while (BlendTypeStrs[idx])
|
while (BlendTypeStrs[idx])
|
||||||
|
@ -564,8 +556,8 @@ bool BlenderConnection::openBlend(const ProjectPath& path, bool force)
|
||||||
m_loadedRigged = false;
|
m_loadedRigged = false;
|
||||||
if (m_loadedType == BlendType::Mesh)
|
if (m_loadedType == BlendType::Mesh)
|
||||||
{
|
{
|
||||||
_writeLine("GETMESHRIGGED");
|
_writeStr("GETMESHRIGGED");
|
||||||
_readLine(lineBuf, sizeof(lineBuf));
|
_readStr(lineBuf, sizeof(lineBuf));
|
||||||
if (!strcmp("TRUE", lineBuf))
|
if (!strcmp("TRUE", lineBuf))
|
||||||
m_loadedRigged = true;
|
m_loadedRigged = true;
|
||||||
}
|
}
|
||||||
|
@ -582,9 +574,9 @@ bool BlenderConnection::saveBlend()
|
||||||
"BlenderConnection::saveBlend() musn't be called with stream active");
|
"BlenderConnection::saveBlend() musn't be called with stream active");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_writeLine("SAVE");
|
_writeStr("SAVE");
|
||||||
char lineBuf[256];
|
char lineBuf[256];
|
||||||
_readLine(lineBuf, sizeof(lineBuf));
|
_readStr(lineBuf, sizeof(lineBuf));
|
||||||
if (!strcmp(lineBuf, "FINISHED"))
|
if (!strcmp(lineBuf, "FINISHED"))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -709,7 +701,7 @@ BlenderConnection::DataStream::Mesh::Mesh
|
||||||
for (uint32_t i=0 ; i<count ; ++i)
|
for (uint32_t i=0 ; i<count ; ++i)
|
||||||
{
|
{
|
||||||
char name[128];
|
char name[128];
|
||||||
conn._readLine(name, 128);
|
conn._readStr(name, 128);
|
||||||
boneNames.emplace_back(name);
|
boneNames.emplace_back(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1231,10 +1223,10 @@ BlenderConnection::DataStream::compileMesh(HMDLTopology topology,
|
||||||
char req[128];
|
char req[128];
|
||||||
snprintf(req, 128, "MESHCOMPILE %s %d",
|
snprintf(req, 128, "MESHCOMPILE %s %d",
|
||||||
MeshOutputModeString(topology), skinSlotCount);
|
MeshOutputModeString(topology), skinSlotCount);
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeStr(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to cook mesh: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to cook mesh: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1254,10 +1246,10 @@ BlenderConnection::DataStream::compileMesh(const std::string& name,
|
||||||
char req[128];
|
char req[128];
|
||||||
snprintf(req, 128, "MESHCOMPILENAME %s %s %d", name.c_str(),
|
snprintf(req, 128, "MESHCOMPILENAME %s %s %d", name.c_str(),
|
||||||
MeshOutputModeString(topology), skinSlotCount);
|
MeshOutputModeString(topology), skinSlotCount);
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeStr(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to cook mesh '%s': %s", name.c_str(), readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to cook mesh '%s': %s", name.c_str(), readBuf);
|
||||||
|
|
||||||
|
@ -1273,10 +1265,10 @@ BlenderConnection::DataStream::compileColMesh(const std::string& name)
|
||||||
|
|
||||||
char req[128];
|
char req[128];
|
||||||
snprintf(req, 128, "MESHCOMPILENAMECOLLISION %s", name.c_str());
|
snprintf(req, 128, "MESHCOMPILENAMECOLLISION %s", name.c_str());
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeStr(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to cook collision mesh '%s': %s", name.c_str(), readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to cook collision mesh '%s': %s", name.c_str(), readBuf);
|
||||||
|
|
||||||
|
@ -1297,10 +1289,10 @@ BlenderConnection::DataStream::compileAllMeshes(HMDLTopology topology,
|
||||||
snprintf(req, 128, "MESHCOMPILEALL %s %d %f",
|
snprintf(req, 128, "MESHCOMPILEALL %s %d %f",
|
||||||
MeshOutputModeString(topology),
|
MeshOutputModeString(topology),
|
||||||
skinSlotCount, maxOctantLength);
|
skinSlotCount, maxOctantLength);
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeStr(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to cook all meshes: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to cook all meshes: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1313,10 +1305,10 @@ std::vector<BlenderConnection::DataStream::Light> BlenderConnection::DataStream:
|
||||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an AREA blend"),
|
BlenderLog.report(logvisor::Fatal, _S("%s is not an AREA blend"),
|
||||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||||
|
|
||||||
m_parent->_writeLine("LIGHTCOMPILEALL");
|
m_parent->_writeStr("LIGHTCOMPILEALL");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to gather all lights: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to gather all lights: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1334,10 +1326,10 @@ std::vector<BlenderConnection::DataStream::Light> BlenderConnection::DataStream:
|
||||||
|
|
||||||
std::vector<ProjectPath> BlenderConnection::DataStream::getTextures()
|
std::vector<ProjectPath> BlenderConnection::DataStream::getTextures()
|
||||||
{
|
{
|
||||||
m_parent->_writeLine("GETTEXTURES");
|
m_parent->_writeStr("GETTEXTURES");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to get textures: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to get textures: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1367,10 +1359,10 @@ BlenderConnection::DataStream::Actor BlenderConnection::DataStream::compileActor
|
||||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
||||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||||
|
|
||||||
m_parent->_writeLine("ACTORCOMPILE");
|
m_parent->_writeStr("ACTORCOMPILE");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1384,10 +1376,10 @@ BlenderConnection::DataStream::compileActorCharacterOnly()
|
||||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
||||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||||
|
|
||||||
m_parent->_writeLine("ACTORCOMPILECHARACTERONLY");
|
m_parent->_writeStr("ACTORCOMPILECHARACTERONLY");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to compile actor: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1401,10 +1393,10 @@ BlenderConnection::DataStream::compileWorld()
|
||||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an WORLD blend"),
|
BlenderLog.report(logvisor::Fatal, _S("%s is not an WORLD blend"),
|
||||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||||
|
|
||||||
m_parent->_writeLine("WORLDCOMPILE");
|
m_parent->_writeStr("WORLDCOMPILE");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to compile world: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to compile world: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1417,10 +1409,10 @@ std::vector<std::string> BlenderConnection::DataStream::getArmatureNames()
|
||||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
||||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||||
|
|
||||||
m_parent->_writeLine("GETARMATURENAMES");
|
m_parent->_writeStr("GETARMATURENAMES");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to get armatures of actor: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to get armatures of actor: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1448,10 +1440,10 @@ std::vector<std::string> BlenderConnection::DataStream::getSubtypeNames()
|
||||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
||||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||||
|
|
||||||
m_parent->_writeLine("GETSUBTYPENAMES");
|
m_parent->_writeStr("GETSUBTYPENAMES");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to get subtypes of actor: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to get subtypes of actor: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1479,10 +1471,10 @@ std::vector<std::string> BlenderConnection::DataStream::getActionNames()
|
||||||
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
|
||||||
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
m_parent->m_loadedBlend.getAbsolutePath().c_str());
|
||||||
|
|
||||||
m_parent->_writeLine("GETACTIONNAMES");
|
m_parent->_writeStr("GETACTIONNAMES");
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to get actions of actor: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to get actions of actor: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1516,10 +1508,10 @@ BlenderConnection::DataStream::getBoneMatrices(const std::string& name)
|
||||||
|
|
||||||
char req[128];
|
char req[128];
|
||||||
snprintf(req, 128, "GETBONEMATRICES %s", name.c_str());
|
snprintf(req, 128, "GETBONEMATRICES %s", name.c_str());
|
||||||
m_parent->_writeLine(req);
|
m_parent->_writeStr(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[256];
|
||||||
m_parent->_readLine(readBuf, 256);
|
m_parent->_readStr(readBuf, 256);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to get matrices of armature: %s", readBuf);
|
BlenderLog.report(logvisor::Fatal, "unable to get matrices of armature: %s", readBuf);
|
||||||
|
|
||||||
|
@ -1557,9 +1549,9 @@ BlenderConnection::DataStream::getBoneMatrices(const std::string& name)
|
||||||
|
|
||||||
void BlenderConnection::quitBlender()
|
void BlenderConnection::quitBlender()
|
||||||
{
|
{
|
||||||
_writeLine("QUIT");
|
_writeStr("QUIT");
|
||||||
char lineBuf[256];
|
char lineBuf[256];
|
||||||
_readLine(lineBuf, sizeof(lineBuf));
|
_readStr(lineBuf, sizeof(lineBuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
BlenderConnection& BlenderConnection::SharedConnection()
|
BlenderConnection& BlenderConnection::SharedConnection()
|
||||||
|
|
|
@ -49,6 +49,8 @@ add_library(hecl-common
|
||||||
../include/hecl/ClientProcess.hpp
|
../include/hecl/ClientProcess.hpp
|
||||||
../include/hecl/BitVector.hpp
|
../include/hecl/BitVector.hpp
|
||||||
../include/hecl/MathExtras.hpp
|
../include/hecl/MathExtras.hpp
|
||||||
|
../include/hecl/UniformBufferPool.hpp
|
||||||
|
../include/hecl/VertexBufferPool.hpp
|
||||||
ClientProcess.cpp
|
ClientProcess.cpp
|
||||||
atdna_HMDLMeta.cpp
|
atdna_HMDLMeta.cpp
|
||||||
atdna_Frontend.cpp
|
atdna_Frontend.cpp
|
||||||
|
|
Loading…
Reference in New Issue