# lmel.py
# One of 7 python scripts that implement a simple L system. 
# Useage:
#     lmel.render(lstring, path_to_output_mel, database)
#
# The database is created by lscriptreader.py.
# The output mel script can optionally be sourced via a socket connection
# with Maya using mayaport.py, for example,
#    port = database['port']
#    mayasocket.source(path_to_output_mel, port)
#
# Malcolm Kesson
# 18 Jan 2012, 26 Jan 2012
  
import math, os, random
  
def getval(data):
    if len(data) == 1:
        return float(data[0])
    v1 = float(data[0])
    v2 = float(data[1])
    return random.uniform(v1, v2)
    
# Interpret the L string
def render(lstr, melfile, database):
    mel = []
    scale_invert_stack = []
    scale_invert = False
    scale_invert_stack.append(scale_invert)
    
    move_sign = 1
    angle_sign = 1
  
    move_data = database['move']
    angle_data = database['angle']
    scale_data = database['scale']
    
    for c in lstr:
        if c == '+':   move_sign = 1
        elif c == '-': move_sign = -1
        elif c == '>': angle_sign = 1
        elif c == '<': angle_sign = -1
        elif c == 'S': scale_invert = (True, False)[scale_invert == True] # toggle True/False
        
        elif c == 'x': mel.append('rotate -r %1.3f 0 0 $tnode;\n' % (math.fabs(getval(angle_data)) * angle_sign))
        elif c == 'y': mel.append('rotate -r 0 %1.3f 0 $tnode;\n' % (math.fabs(getval(angle_data)) * angle_sign))
        elif c == 'z': mel.append('rotate -r 0 0 %1.3f $tnode;\n' % (math.fabs(getval(angle_data)) * angle_sign))
        elif c == 's':
            scale = getval(scale_data)
            scale = (scale, 1.0/scale)[scale_invert == True]
            mel.append('scale  -r %1.3f %1.3f %1.3f $tnode;\n' % (scale,scale,scale))
        elif c == 'X': mel.append('move -r %1.3f 0 0 $tnode;\n' % (math.fabs(getval(move_data)) * move_sign))
        elif c == 'Y': mel.append('move -r 0 %1.3f 0 $tnode;\n' % (math.fabs(getval(move_data)) * move_sign))
        elif c == 'Z': mel.append('move -r 0 0 %1.3f $tnode;\n' % (math.fabs(getval(move_data)) * move_sign))
        elif c == '{': 
            mel.append('push($tnode);\n')
            scale_invert_stack.append(scale_invert)
        elif c == '}': 
            mel.append('$tnode = pop();\n')
            scale_invert = scale_invert_stack.pop()
        elif c == '1': mel.append('$tnode = addCurveTo($tnode);\n')
        elif c == '4': mel.append('$tnode = addConeTo($tnode);\n')
  
    f = open(melfile, 'w')
    try:
        maya_dir = os.environ['MAYA_APP_DIR']
    except Exception, e:
        # Specify the full path to the maya directory
        maya_script_dir = '???'
    procspath = maya_dir + '/scripts/LMelProcs.mel'
    f.write('source "%s";\n' % procspath)
    f.write('global string $stack[];\n')
    f.write('$nulls = `ls -tr "LSYS"`;\n')
    f.write('if(size($nulls) > 0) {\n')
    f.write('    select $nulls;\n')
    f.write('    delete;\n')
    f.write('    }\n')
    f.write('$geoList = `ls -geometry`;\n')
    f.write('select $geoList;\n')
    f.write('delete;\n')
    f.write('$nulls = `ls -tr "null*"`;\n');
    f.write('select $nulls;\n')
    f.write('delete;\n')
    
    f.write('clear($stack);\n')
    f.write('$root = `group -em -n LSYS`;\n')
    f.write('$tnode = `group -em`;\n')
    f.write('parent -r $tnode $root;\n')
    f.write(''.join(mel))
    f.close()