metaforce/hecl/blender/hecl_blendershell.py

152 lines
4.4 KiB
Python
Raw Normal View History

2015-08-05 22:59:59 +00:00
import bpy, sys, os, re
2015-07-28 23:54:54 +00:00
ARGS_PATTERN = re.compile(r'''(?:"([^"]+)"|'([^']+)'|(\S+))''')
# Extract pipe file descriptors from arguments
2015-08-06 19:10:12 +00:00
print('HECL Blender Launch', sys.argv)
2015-05-24 04:51:16 +00:00
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])
def readpipeline():
retval = bytearray()
while True:
ch = os.read(readfd, 1)
if ch == b'\n' or ch == b'':
return retval
retval += ch
def writepipeline(linebytes):
2015-05-24 22:19:28 +00:00
os.write(writefd, linebytes + b'\n')
def writepipebuf(linebytes):
writepipeline(b'BUF')
os.write(writefd, struct.pack('I', len(linebytes)) + linebytes)
def quitblender():
writepipeline(b'QUITTING')
bpy.ops.wm.quit_blender()
2015-05-24 04:51:16 +00:00
# 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()
2015-05-24 22:19:28 +00:00
# Make addon available to commands
import hecl
# Intro handshake
writepipeline(b'READY')
ackbytes = readpipeline()
if ackbytes != b'ACK':
quitblender()
2015-08-05 22:59:59 +00:00
# Count brackets
def count_brackets(linestr):
bracket_count = 0
for ch in linestr:
if ch in {'[','{','('}:
bracket_count += 1
elif ch in {']','}',')'}:
bracket_count -= 1
return bracket_count
# Complete sequences of statements compiled/executed here
def exec_compbuf(compbuf, globals):
#print('EXEC', compbuf)
co = compile(compbuf, '<HECL>', 'exec')
exec(co, globals)
# Command loop
while True:
2015-07-28 23:54:54 +00:00
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))
print(cmdargs)
2015-07-28 23:54:54 +00:00
if cmdargs[0] == 'QUIT':
quitblender()
2015-07-28 23:54:54 +00:00
elif cmdargs[0] == 'OPEN':
if 'FINISHED' in bpy.ops.wm.open_mainfile(filepath=cmdargs[1]):
2015-05-24 22:19:28 +00:00
writepipeline(b'FINISHED')
else:
writepipeline(b'CANCELLED')
2015-05-24 04:51:16 +00:00
2015-07-28 23:54:54 +00:00
elif cmdargs[0] == 'CREATE':
bpy.ops.wm.read_homefile()
2015-07-28 02:25:33 +00:00
bpy.context.user_preferences.filepaths.save_version = 0
2015-07-28 23:54:54 +00:00
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=cmdargs[1]):
2015-07-28 02:25:33 +00:00
writepipeline(b'FINISHED')
else:
writepipeline(b'CANCELLED')
elif cmdargs[0] == 'SAVE':
bpy.context.user_preferences.filepaths.save_version = 0
if 'FINISHED' in bpy.ops.wm.save_mainfile(check_existing=False):
writepipeline(b'FINISHED')
else:
writepipeline(b'CANCELLED')
2015-07-28 23:54:54 +00:00
elif cmdargs[0] == 'PYBEGIN':
2015-07-28 02:25:33 +00:00
writepipeline(b'READY')
2015-08-05 22:59:59 +00:00
globals = {'hecl':hecl}
compbuf = str()
2015-08-05 22:59:59 +00:00
bracket_count = 0
2015-07-28 02:25:33 +00:00
while True:
try:
line = readpipeline()
2015-08-05 22:59:59 +00:00
# End check
2015-07-28 02:25:33 +00:00
if line == b'PYEND':
2015-08-05 22:59:59 +00:00
# Ensure remaining block gets executed
if len(compbuf):
exec_compbuf(compbuf, globals)
compbuf = str()
2015-07-28 02:25:33 +00:00
writepipeline(b'DONE')
break
2015-08-05 22:59:59 +00:00
# Syntax filter
linestr = line.decode().rstrip()
if not len(linestr) or linestr.lstrip()[0] == '#':
writepipeline(b'OK')
continue
leading_spaces = len(linestr) - len(linestr.lstrip())
2015-08-05 22:59:59 +00:00
# Block lines always get appended right away
if linestr.endswith(':') or leading_spaces or bracket_count:
if len(compbuf):
compbuf += '\n'
compbuf += linestr
bracket_count += count_brackets(linestr)
writepipeline(b'OK')
continue
# Complete non-block statement in compbuf
if len(compbuf):
2015-08-05 22:59:59 +00:00
exec_compbuf(compbuf, globals)
# Establish new compbuf
compbuf = linestr
bracket_count += count_brackets(linestr)
2015-07-28 02:25:33 +00:00
except Exception as e:
writepipeline(b'EXCEPTION')
2015-07-28 23:54:54 +00:00
raise
2015-07-28 02:25:33 +00:00
break
writepipeline(b'OK')
2015-07-28 23:54:54 +00:00
elif cmdargs[0] == 'PYEND':
2015-07-28 02:25:33 +00:00
writepipeline(b'ERROR')
2015-05-24 04:51:16 +00:00
else:
2015-07-28 23:54:54 +00:00
hecl.command(cmdargs, writepipeline, writepipebuf)