#*********************blobby.py*************************
#
#   William Baker
#
#   usage:   python blobby.py 
#
#   Blobby man is back in Box form.  Visual does not 
#   allow automatic picking of ellipsoids yet, so until
#   then it will be boxy blobby man.
#
#   The ever-popular blobby man.  Users can rotate limbs
#   using the left mouse button and select a limb using
#   the middle mouse button.  The active limb is indicated 
#   by appearing white, other limbs are blue.
#
#*********************************************************

from visual import *
from math import *

# Initialize the frame system
# and create hierarchy (i.e. PushMatrix)
world_fr=frame()
head_fr=frame(frame=world_fr)
luarm_fr=frame(frame=world_fr)
ruarm_fr=frame(frame=world_fr)
lfarm_fr=frame(frame=luarm_fr)
rfarm_fr=frame(frame=ruarm_fr)
lhand_fr=frame(frame=lfarm_fr)
rhand_fr=frame(frame=rfarm_fr)
luleg_fr=frame(frame=world_fr)
ruleg_fr=frame(frame=world_fr)
llleg_fr=frame(frame=luleg_fr)
rlleg_fr=frame(frame=ruleg_fr)
lfoot_fr=frame(frame=llleg_fr)
rfoot_fr=frame(frame=rlleg_fr)

# Initialize body parts in their correct frames
torso = box(frame=world_fr,pos=(0,0,0), length=1, height=2.5, width=.5,
        color=(.2,.2,.9))

head = box(frame=head_fr,pos=(0,.5,0), length=.8, height=1, width=.75,
        color=(.2,.2,.9))

luarm = box(frame=luarm_fr, pos=(.5,0,0), length=1, height=.3, width=.1,
        color=(.2,.2,.9))

ruarm = box(frame=ruarm_fr, pos=(-.5,0,0), length=1, height=.3, 
        width=.1,color=(.2,.2,.9))

lfarm = box(frame=lfarm_fr, pos=(.5,0,0), length=1, height=.3, width=.1,
        color=(.2,.2,.9))

rfarm = box(frame=rfarm_fr, pos=(-.5,0,0), length=1, height=.3, 
        width=.1,color=(.2,.2,.9))

lhand = box(frame=lhand_fr, pos=(.25,0,0), length=.45, height=.3, 
        width=.1,color=(.2,.2,.9))

rhand = box(frame=rhand_fr, pos=(-.25,0,0), length=.45, height=.3, 
        width=.1,color=(.2,.2,.9))

luleg = box(frame=luleg_fr, pos=(0,-.75,0), length=.5, height=1.5, 
        width=.3, color=(.2,.2,.9))

ruleg = box(frame=ruleg_fr, pos=(0,-.75,0), length=.5, height=1.5, 
        width=.3, color=(.2,.2,.9))

llleg = box(frame=llleg_fr, pos=(0,-.75,0), length=.5, height=1.5, 
        width=.3, color=(.2,.2,.9))

rlleg = box(frame=rlleg_fr, pos=(0,-.75,0), length=.5, height=1.5, 
        width=.3, color=(.2,.2,.9))

lfoot = box(frame=lfoot_fr, pos=(.25,0,0), length=.45, height=.1, 
        width=.3,color=(.2,.2,.9))

rfoot = box(frame=rfoot_fr, pos=(-.25,0,0), length=.45, height=.1, 
        width=.3,color=(.2,.2,.9))

# Move the frames to their correct starting locations (i.e. glTranslate)
# All .pos are relative to the frame that they are in
world_fr.pos=(0,0,0)
head_fr.pos=(0,1.3,0)
luarm_fr.pos=(.55,1.1,0)
ruarm_fr.pos=(-.55,1.1,0)
lfarm_fr.pos=(1.05,0,0)
rfarm_fr.pos=(-1.05,0,0)
lhand_fr.pos=(1.0,0,0)
rhand_fr.pos=(-1.0,0,0)
luleg_fr.pos=(.35,-1.3,0)
ruleg_fr.pos=(-.35,-1.3,0)
llleg_fr.pos=(0,-1.6,0)
rlleg_fr.pos=(0,-1.6,0)
lfoot_fr.pos=(0,-1.6,0)
rfoot_fr.pos=(0,-1.6,0)

# resetcolors()
# Resets all blobby parts to blue
def resetcolors():
    torso.color=(.2,.2,.9)
    head.color=(.2,.2,.9)
    luarm.color=(.2,.2,.9)
    ruarm.color=(.2,.2,.9)
    lfarm.color=(.2,.2,.9)
    rfarm.color=(.2,.2,.9)
    lhand.color=(.2,.2,.9)
    rhand.color=(.2,.2,.9)
    luleg.color=(.2,.2,.9)
    ruleg.color=(.2,.2,.9)
    llleg.color=(.2,.2,.9)
    rlleg.color=(.2,.2,.9)
    lfoot.color=(.2,.2,.9)
    rfoot.color=(.2,.2,.9)


picked=None             # What body part is picked
dragging=false          # Is the mouse being dragged?

# Set the window title
scene.title="Blobby (Boxy) man for VPython, By William Baker, Math198 Spring 2005"

# Set up the scene, we want autoscaling off or VPython will resize
# the scene and it can be distracting
scene.center=(0,-1,0)
scene.autoscale=0

# Mouse controls
while 1:

    # Were there mouse events? 
    if scene.mouse.events:
        m1 = scene.mouse.getevent() # obtain drag or drop event
        if m1.click == 'middle':
            if m1.pick != None:     # When we clicked did we get an
                                    # object?
                picked=m1.pick.frame
                resetcolors()       # Set picked to white, others blue
                m1.pick.color=(1,1,1)
            else:
                picked=None
                resetcolors()
        
        # If we just clicked, get the mouse start position
        elif m1.press == 'left' and picked != None:
            origpos=scene.mouse.project(normal=(0,0,1))
        elif m1.drag== 'left' and picked != None:
            dragging=true
        elif m1.drop== 'left':
            dragging=false
    
    # If we are dragging the mouse
    if dragging==true:

        # Get the current mouse position
        currentpos=scene.mouse.project(normal=(0,0,1))
        if currentpos[1]-origpos[1]!=0:
            picked.rotate(angle=(currentpos[1]-origpos[1])/4,
                        axis=(0,0,1))
        if currentpos[0]-origpos[0]!=0:
            picked.rotate(angle=(currentpos[0]-origpos[0])/4,
                        axis=(0,1,0))

        # Reset the mouse position
        origpos=currentpos
                
