from koko.lib.shapes import *
from koko.lib.text import *

# Minion (Dispicable Me)
# Model origin is on floor at foot level in center

# Looks like sphere defn is (xcenter, ycenter, zcenter, radius)
# Looks like cylinder defn is (xcenter, ycenter, z1, z2, radius)

# scale_z defn is (part, scale_factor, z_invarient_point) height of point on z axis that stays in place

cad.mm_per_unit = 10

scale = 0.5

# Body
# Body is created from 2 spheres and a cylinder.  The loweer sphere is squashed slightly to provide a flatter bottom.
minion_body = (scale_z(sphere(0,0,scale, scale), scale, 0.5)           # lower sphere
               + scale_z(sphere(0,0,scale*2.5, scale), scale*2.5, 0.9) # upper sphere
               + cylinder(0,0, scale,scale*2.5, scale))

# Mouth
mouth = extrusion(text("C", 0,0, 0.14), 0, scale)
mouth = rotate_y(rotate_z(mouth, 180), -90)
mouth = scale_z(scale_y(mouth, 0, 3.0), 0, 1.5)
mouth = move(mouth, scale*0.9, 0, scale*2.15)
minion_body -= mouth

# Dungerees
# Dungerees are a copy of the body scaled up slightly so that they cover it.  Chunks are then cut out to leave the final dungeree shape.
dungerees = scale_xy(scale_z(minion_body, scale, 1.05), 0, 0, 1.05)
dungerees -= cube(-scale*1.5,scale*1.5, -scale*1.5,scale*1.5, scale*1.9, scale*4)
dungerees -= cube(-scale*0.9,scale*0.9, -scale*1.5,scale*1.5, scale*1.1, scale*1.7)

pocket = scale_xy(scale_z(dungerees, scale, 1.05), 0, 0, 1.05)
pocket &= cube(0,scale*1.5, -scale*0.3,scale*0.3, scale*1.0,scale*1.5)
dungerees += pocket
gru = extrusion(text("G", 0,0, 0.14), 0, 0.03)
gru = rotate_y(rotate_z(gru, 90), -90)
dungerees -= move(gru, scale*1.05, 0, scale*1.2)

# Glasses
glasses_lens = (cylinder(0,0, 0,scale/4, scale*0.25)
                - cylinder(0,0, 0,scale/4, scale*0.18))
glasses_lens = rotate_y(glasses_lens, 90)

glasses = (move(glasses_lens, scale*1.1, -(scale*0.22), scale*2.5)
           + move(glasses_lens, scale*1.1, scale*0.22, scale*2.5))
glasses_strap = (cylinder(0,0, 0,scale*0.2, scale*1.05)
                 - cylinder(0,0, 0,scale*0.2, scale))
glasses_strap = move(glasses_strap, 0,0,scale*2.4)

# Eyes
# Eyes are squashed flat so that the don't protrude from the glasses lens but still cover all of the glasses strap.
eye = scale_x(sphere(0,0,0, scale*0.2), 0, 0.5)
eyes = (move(eye, scale*1.0, -(scale*0.22), scale*2.5)
        + move(eye, scale*1.0, (scale*0.22), scale*2.5))

# Pupils
pupil = scale_x(sphere(0,0,0, scale*0.07), 0, 0.5)
pupils = (move(pupil, scale*1.08, -(scale*0.20), scale*2.45)
           + move(pupil, scale*1.08, (scale*0.20), scale*2.45))


# Legs
leg = move(rotate_y(cone(0,0, 0,scale*0.7, scale*0.5), 180), 0, 0, scale*0.7)
legs = (move(leg, 0, -scale*0.3, 0)
        + move(leg, 0, scale*0.3, 0))

# Feet
# Made from a squashed sphere that's then truncated
foot = scale_z(sphere(0,0, -scale*0.5, scale*0.5), scale*0.5, 0.5)
foot = scale_y(foot, 0, 0.7)
foot -= cube(-scale,scale, -scale,scale, -scale,0)
feet = (move(foot, scale*0.1, -scale*0.3, 0)
        + move(foot, scale*0.1, scale*0.3, 0))

# Arms
# assemble with elbow joint at 0,0,0 so we don't need to bother with any trig to position it
armr = cylinder(0,0, 0,scale*0.7, scale*0.1) # Upper
armr = rotate_x(armr, -10)
armr += cylinder(0,0, -scale*0.7,0, scale*0.1) # Lower
elbow = sphere(0,0,0, scale*0.1)
armr += elbow
armr = move(armr, 0, -scale*1.05, scale*1.1)
arml = reflect_y(armr, 0)

# Hands
# Construct these seperately so that we can make them black
handr = scale_z(sphere(0,0,0, scale*0.2), 0, 2.0)
handr += move(rotate_y(scale_z(sphere(0,0,0, scale*0.10), 0, 2.0), -40), -scale*0.2, 0, 0)
handr += move(rotate_y(scale_z(sphere(0,0,0, scale*0.10), 0, 2.0), 40), scale*0.2, 0, 0)
handr = move(handr, 0, -scale*1.05, scale*0.2)
handr -= cube(-scale*2,scale*2, -scale*2,scale*2, -scale,0) # chop off at ground level
handl = reflect_y(handr, 0)

# And finally the piece de resistance...
# The Key Ring Loop
loop = (cylinder(0,0, 0,scale/4, scale*0.35)
                - cylinder(0,0, 0,scale/4, scale*0.2))
loop = rotate_y(loop, 90)
loop = move(loop, scale/8, 0, scale*3.5)


# Create a seperation layer so that we can have a revolving head section
# Build the peg outer surface from 3 cylinders from the top down
# note that the slice is currently based on the scale, but should be based on absolute seperation requirements
# Current seperation is 0.07*scale
seperation = 0.07
slice = (cylinder(0,0, scale*1.9,scale*(1.9+seperation), scale*2.0)
         + cylinder(0,0, scale*1.4,scale*1.9, scale*0.4)
         + cylinder(0,0, scale*1.0,scale*1.4, scale*0.8)
         )
# Subtract the peg inner surface
slice_inner = (cylinder(0,0, scale*(1.4-seperation),scale*2.5, scale*(0.4-seperation))
               + cylinder(0,0, scale*(1.0+seperation),scale*(1.4-seperation), scale*(0.8-seperation))
          )
slice -= slice_inner
# Move the slice parts to the side so that we can visualise it.
#slice = move(slice, 0, scale*2, 0)
#slice_inner = move(slice_inner, 0, scale*5, 0)
#minion_body -= slice

# Assemble parts seperately so that we can give them unique colours
#cad.shapes = minion_body, dungerees, glasses, glasses_strap, eyes, pupils, legs, feet, armr, arml, handr, handl, loop
cad.shape = (minion_body + dungerees + glasses + glasses_strap + eyes + pupils + legs + feet + armr + arml + handr + handl + loop) - slice
