from slithy.library import *
from slithy.util import *
from resources import fonts, images
import math


bg = Fill( style = 'horz', color = black, color2 = Color(0,0,0.7) )

def rectangles( x=(SCALAR, 0.2, 2.0),
              y=(SCALAR, 0, 90) ):
    set_camera( Rect( -4, -4, 4, 4 ) )
    clear( white )

    color( blue, 0.4 )
    rectangle( -x, -x, x, x )
    rotate( y )
    rectangle( -x, -x, x, x )

def rectangles_noclear( x=(SCALAR, 0.2, 2.0),
              y=(SCALAR, 0, 90) ):
    set_camera( Rect( -4, -4, 4, 4 ) )
    #clear( white )

    color( red, 0.4 )
    rectangle( -x, -x, x, x )
    rotate( y )
    rectangle( -2*x, -0.5*x, 2*x, 0.5*x )

font_list = fonts.values()

def show_fonts( shade=(SCALAR, 0.0, 1.0),
              whichfont=(INTEGER, 0, len(font_list)-1),
              string=(STRING, 'hello, world!'),
              flip=(BOOLEAN) ):
    set_camera( Rect( -2, -1, 2, 1 ) )
    clear( white )

    if flip:
        scale( -1, 1 )

    color( green.interp( purple, shade ) )
    text( 0, 0, string, font = font_list[whichfont], size = 0.3 )

def simple_shapes( x=(SCALAR, 0, 1) ):
    set_camera( Rect( -1, -1, 1, 1 ) )
    clear( white )
    thickness( 0.01 )

    color( blue )
    line( -0.1, 0.1,
          -0.3, 0.7,
          -0.5, 0.1,
          -0.3, 0.1 + 0.5*x )

    circle( 0.3, 0.5, 0.6 )
    color( yellow, 0.3 )
    dot( 0.3 - 0.1 * x, 0.6, 0.5 )
    color( yellow )
    dot( 0.3 - 0.2 * x, 0.7, 0.4 )

    color( green )
    z = -0.3 - 0.5333 * x
    rectangle( -0.1, -0.1, z, 0.25 / z )

    color( red )
    polygon( 0.5, -0.8,
             0.1, -0.8,
             0.1, -0.1,
             0.2, -0.1,
             0.2, -0.7,
             0.4, -0.7,
             0.4, -0.1,
             0.5, -0.1,
	     0.6 - x * 0.6, -0.45 )

def coord_transforms( x=(SCALAR, 0, 1) ):
    clear( white )

    # translate the blue pentagon
    color( blue, 0.2 )
    push()
    translate( -0.4, -0.5 )
    for i in range(4):
        polygon( 0, 0, -0.5, 0, -0.5, 0.5, -0.25, 0.7, 0, 0.5 )
        translate( x * -0.06, x * 0.2 )
    pop()

    # rotate the green rectangle
    color( green, 0.2 )
    push()
    translate( 0, 0.3 )
    for i in range(4):
        rectangle( -0.2, -0.5, 0.2, 0.5 )
        rotate( -(x * 15), -0.05, -0.3 )
    pop()

    # scale (nonuniformly) the red circle
    color( red, 0.2 )
    push()
    translate( 0.6, -0.4 )
    for i in range(4):
        dot( 0.4 )
        scale( 1-(x*0.2), 1-(x*0.45), 0.15, -0.25 )
    pop()


def text_positioning( shade = (SCALAR, 0, 1),
              pos = (INTEGER, 0, 8),
              justify = (SCALAR, 0, 1) ):
    set_camera( Rect( -1, -0.5, 1, 0.8 ) )
    clear( white )
    thickness( 0.01 )

    # select one of these nine anchor strings
    anchor = ('c', 'nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w')[pos]

    color( shade * 0.6 + 0.2 )
    d = text( 0, 0, [ u'\u201ctwas brillig\n',
                      'and the ', fonts['ehrhardt'], green, 'slithy', RESET, ' toves\n',
                      u'did gyre and gimble in the wabe\u201d' ],
              font = fonts['times'], size = 0.15, justify = justify, anchor = anchor )

    # mark the text's reference point with a red dot
    color( red, 0.8 )
    dot( 0.03 )

    # draw the bbox
    frame( d['left'], d['bottom'], d['right'], d['top'] )

    color( blue )
    text( -0.05, 0.6, 'anchor:\njustify:', anchor = 'fe', font = fonts['times'], size = 0.1, justify = 1 )
    text( 0.05, 0.6, anchor + '\n%4.2f' % (justify,), anchor = 'fw', font = fonts['ehrhardt'], size = 0.1 )

p = Path()
p.moveto( 0, 0 ).lineto( 1, 0 )
p.arc( 0, 0, 0, 90, 1 )
p.qcurveto( 0, 0, -0.5, 0.5 ).lineto( -0.5, 0 )
p.closepath()

def static_path_object( offset = (SCALAR, 0, 0.5) ):
    set_camera( Rect( -1, -1, 1, 1 ).outset( 0.1 ) )
    clear( white )

    translate( -0.25, -0.5 )

    push()
    translate( -offset, -offset )
    color( red )
    fill( p )
    pop()

    translate( offset, offset )
    color( black )
    widestroke( p, 0.06 )

def dynamic_path_object( x = (SCALAR, 0, 10) ):
    set_camera( Rect( -1, -1, 1, 1 ) )
    clear( white )
    
    mypath = Path()
    mypath.moveto( 0, 0 ).lineto( 0, 1 )
    mypath.rcurveto( 1, x, 2, -x, 3, 0 )
    mypath.rlineto( 0, -1 ).closepath()

    scale( 0.5 )
    translate( -1.5, -1 )
    color( green )
    fill( mypath )

def path_arrows( x=(SCALAR, 0, 1),
               a=(SCALAR, 0, 1),
               width=(SCALAR, 0.2, 0.3),
               length=(SCALAR, 0.2, 0.3) ):
    set_camera( Rect( -2, -2, 1.5, 1.5 ) )
    clear( white )

    p = Path()
    p.moveto( 0, 0 ).curveto(1,-x,x,1-x,1,1)
    p.moveto( 1, -x ).rlineto( .2 + .8*x, x ).rlineto( 0, -0.2-0.8*x )
    p.moveto( 0, 1 ).rlineto( 0, 0.5 ).rlineto( -0.5, 0 ).rlineto( 0, -0.5 ).closepath()
    p.moveto( 0, -1 ).qcurveto( -x, -x, -1, 0 )

    translate( -0.5, -0.5 )
    color( red )
    widestroke( p, 0.05 )
    color( red, a )
    arrow( p, (0,width,length), (1,width,length) )

def arc_arrows( spin = (SCALAR, 0, 720),
               pieces = (INTEGER, 2, 9, 5),
               flip = (BOOLEAN) ):
    set_camera( Rect( -1, -1, 1, 1 ) )
    clear( white )
    
    p = Path()
    if flip:
        p.arcn( 0, 0, 360.0 / pieces - 10.0, 0, 0.8 )
    else:
        p.arc( 0, 0, 0, 360.0 / pieces - 10.0, 0.8 )

    rotate( spin )
    color( blue )
    for i in range(pieces):
        widestroke( p, 0.05 )
        arrow( p, (0,0.2,0.1) )
        rotate( 360.0 / pieces )


def bitmap_image( x = (SCALAR, 0, 1) ):
    set_camera( Rect( -1, -1, 1, 1 ) )
    im = images['tanguy']
    rotate( x * 90 )
    image( 0, 0, im, width = 1.0, anchor = 'c' )

    height = im.size[1] / float(im.size[0])

    color( yellow.interp( purple, x ) )
    polygon( 0.6, 0, 0.8, 0.2, 0.8, -0.2 )
    polygon( -0.6, 0, -0.8, 0.2, -0.8, -0.2 )
    polygon( 0, height/2+0.1, 0.2, height/2+0.3, -0.2, height/2+0.3 )
    polygon( 0, height/-2-.1, 0.2, height/-2-0.3, -0.2, height/-2-0.3 )


def image_with_caption( x = (SCALAR, 0, 1) ):
    set_camera( Rect( -1, -1, 1, 1 ).outset(0.25) )
    clear( white )

    d = image( 0, 0, images['tanguy'], width = x+1 )
    text( d['left'], d['bottom'] - 0.1, 'Yves Tanguy',
          font = fonts['times'], size = 0.1, anchor = 'w' )
    text( d['right'], d['top'] + 0.1, 'Indefinite Divisibility',
          font = fonts['ehrhardt'], size = 0.1, anchor = 'e' )

camera_list = ( Rect( -1, -1, 1, 1 ),
                Rect( -2, -1, 2, 1 ),
                Rect( -1, -4, 1, 4 ),
                Rect( -4, -4, 4, 4 ),
                )

def diagram_cameras( cam = (SCALAR, 0, len(camera_list)-1),
                     ):
    r = interp_cameralist( cam, camera_list )    # from slithy.util
    set_camera( r )
    clear( white )
    
    for i in range(-8,9):
        for j in range(-8,9):
            color( green.interp(yellow, (math.sqrt(i*i+j*j) / 12.0) ) )
            dot( 0.25, i, j )

    image( 0, 0, images['tanguy'], width = 1.0 )

    color( red, 0.1 )
    thickness( 0.01 )
    rectangle( r )

def util_split_sequence( x = (SCALAR, 0, 1, 0),
               overlap = (SCALAR, 0, 1, 0.3),
               ):
    set_camera( Rect( -4, -3, 4, 3 ) )
    clear( black )

    translate( 0, 2.2 )

    for fn, name in ((split_sequence, 'split_sequence'),
                     (split_sequence_smooth, 'split_sequence_smooth'),
                     (split_sequence_hat, 'split_sequence_hat'),):
        u = fn( 7, x, overlap )
        push()
        translate( -3, 0 )
        for i in u:
            color( green.interp( yellow, i ) )
            dot( 0.45 )
            translate( 1, 0 )
        pop()

        color( white )
        text( 0, -0.5, name, font = fonts['times'], size = 0.4, anchor = 'n' )

        translate( 0, -2 )

def change_caption( cap, newtext ):
    serial()
    fade_out( 0.25, cap )
    set( cap.text, newtext )
    fade_in( 0.25, cap )
    end()

def new_diagram( d, cap, dc, newfn, newtext ):
    parallel()
    change_caption( cap, newtext )
    
    serial()
    fade_out( 0.25, d )
    exit( d )
    d = Drawable( dc, newfn, _alpha = 0.0 )
    enter( d )
    fade_in( 0.25, d )
    end()
    end()

    return d
    

def show_examples():
    c = get_camera().inset( 0.05 )
    dc, tc = c.ysplit( 5, 1, gutter = 0.05 )

    tx1 = Text( dc,
                text = 'This animation will run through some examples of parameterized diagrams.',
                font = fonts['body'], size = 24, color = white, justify = 0.5, vjustify = 0.5,
                _alpha = 0.0 )
    cap = Text( tc,
                text = ['Press ', yellow, fonts['bodyi'], 'space', RESET, ' to continue.'],
                font = fonts['body'], size = 18, color = white, justify = 0.5, vjustify = 0.5,
                _alpha = 0.0 )
    d = Drawable( dc, rectangles, _alpha = 0.0 )
                
    start_animation( bg, tx1 )

    fade_in( 0.5, tx1 )
    wait( 1.0 )
    enter( cap )
    fade_in( 0.5, cap )

    pause()

    fade_out( 0.5, tx1, cap )
    exit( tx1 )
    enter( d )
    fade_in( 0.5, d )
    change_caption( cap, 'This simple diagram has two parameters.' )

    smooth( 0.75, d.x, 2.0 )
    smooth( 0.5, d.x, 1.0 )
    smooth( 0.5, d.x, 2.0 )
    wait( 0.5 )
    smooth( 0.75, d.y, 135 )
    smooth( 0.75, d.y, 45 )
    smooth( 0.75, d.y, 90 )

    pause()

    d = new_diagram( d, cap, c, rectangles_noclear,
                     'Diagram functions don\'t have to clear their canvas before drawing.  They can draw on top of other slide elements, like this caption.' )

    smooth( 0.75, d.x, 2.0 )
    smooth( 0.5, d.x, 1.0 )
    smooth( 0.5, d.x, 2.0 )
    wait( 0.5 )
    smooth( 0.75, d.y, 135 )
    smooth( 0.75, d.y, 45 )
    smooth( 0.75, d.y, 90 )

    pause()

    d = new_diagram( d, cap, dc, simple_shapes,
                     'The library provides a number of simple drawing commands.' )

    smooth( 2.0, d.x, 1.0 )
    smooth( 1.0, d.x, 0.5 )
    smooth( 0.5, d.x, 1.5 )

    pause()

    d = new_diagram( d, cap, dc, coord_transforms,
                     'Coordinate transforms and a transform stack are available.' )

    smooth( 2.0, d.x, 1.0 )
    smooth( 1.0, d.x, 0.5 )

    pause()

    d = new_diagram( d, cap, dc, show_fonts,
                     'Slithy can draw text using TrueType and Type 1 fonts.' )

    smooth( 2.0, d.whichfont, len(font_list)-1 )
    smooth( 1.0, d.shade, 1.0 )
    for i in range(6):
        set( d.string, get(d.string)[:-1] )
        wait( 0.2 )
    for i in 'there!':
        set( d.string, get(d.string)+i )
        wait( 0.2 )
    smooth( 2.0, d.whichfont, 0 )

    pause()

    d = new_diagram( d, cap, dc, text_positioning,
                     'The text function has a variety of positioning and justification options.' )

    wait( 0.5 )
    smooth( 0.5, d.shade, 0.8 )
    smooth( 3.0, d.pos, 8 )
    wait( 0.25 )
    set( d.pos, 2 )
    wait( 0.5 )
    smooth( 0.5, d.justify, 1.0 )
    wait( 0.5 )
    smooth( 0.5, d.justify, 0.5 )

    pause()

    d = new_diagram( d, cap, dc, static_path_object,
                     'Path objects can be used to draw more complicated shapes.' )

    wait( 1.0 )
    smooth( 3.0, d.offset, 0.5 )

    pause()

    d = new_diagram( d, cap, dc, dynamic_path_object,
                     'Path objects can be constructed within diagram functions if necessary.' )

    wait( 0.5 )
    smooth( 1.0, d.x, 8 )
    smooth( 2.0, d.x, 4 )

    pause()

    d = new_diagram( d, cap, dc, path_arrows,
                     'Arrowheads can be added to path objects.' )

    wait( 0.5 )
    smooth( 2.0, d.a, 1 )
    smooth( 1.0, d.x, 1 )
    smooth( 1.0, d.x, 0.5 )
    wait( 0.5 )
    smooth( 0.5, d.width, 0.3 )
    smooth( 0.5, d.length, 0.3 )

    pause()

    d = new_diagram( d, cap, dc, arc_arrows,
                     'Arrows are fun to draw.' )

    smooth( 4.0, d.spin, 1080 )

    pause()

    d = new_diagram( d, cap, dc, bitmap_image,
                     'Bitmap images (from most common file formats) can be drawn.' )

    wait( 0.5 )
    smooth( 3.0, d.x, 1.0 )

    pause()

    d = new_diagram( d, cap, dc, image_with_caption,
                     'Both the image and text functions return position information, to allow other elements to be aligned with them.' )

    wait( 0.5 )
    smooth( 3.0, d.x, 1.0 )

    pause()

    d = new_diagram( d, cap, dc, diagram_cameras,
                     'The diagram function uses a camera rectangle to specify the visible portion of the plane.' )

    wait( 0.25 )
    smooth( 1.0, d.cam, 1.0 )
    wait( 0.25 )
    smooth( 1.0, d.cam, 2.0 )
    wait( 0.25 )
    smooth( 1.0, d.cam, 3.0 )

    pause()

    d = new_diagram( d, cap, dc.restrict_aspect(0.5), diagram_cameras,
                     'Slithy manages fitting this camera rectangle within the object\'s viewport.  Here the same animation is running in a different viewport.' )

    wait( 0.25 )
    smooth( 1.0, d.cam, 1.0 )
    wait( 0.25 )
    smooth( 1.0, d.cam, 2.0 )
    wait( 0.25 )
    smooth( 1.0, d.cam, 3.0 )

    pause()

    d = new_diagram( d, cap, dc, util_split_sequence,
                     'A utility library provides some convenience functions.' )

    linear( 2.0, d.x, 1 )
    linear( 2.0, d.x, 0 )
    wait( 0.5 )
    set( d.overlap, 0.8 )
    linear( 2.0, d.x, 1 )
    linear( 2.0, d.x, 0 )
    wait( 0.5 )
    set( d.overlap, 0.0 )
    linear( 2.0, d.x, 1 )
    linear( 2.0, d.x, 0 )

    pause()

    fade_out( 0.5, d, cap )
    enter( tx1 )
    set( tx1.text, ['The source for this animation can be found in ',
                    yellow, fonts['bodyi'], 'examples.py', RESET,
                    ' in the Slithy distribution.  Try running this file to experiment with the animations and diagrams in the object tester.'] )
    fade_in( 0.5, tx1 )
    wait( 0.5 )
    set( cap.text, ['The end.  Hit ', yellow, fonts['bodyi'], 'Esc', RESET, ' to quit.'] )
    fade_in( 0.5, cap )

    pause()

    fade_out( 0.5, tx1, cap )

    return end_animation()
show_examples = show_examples()


def title_slide():
    junk, title_v, junk, url_v, cap_v = get_camera().ysplit( 1, 3, 1, 3, 2 )
    title = Text( title_v.inset( 0.1 ), text = 'Slithy parameterized diagram demo', size = 30,
                  font = fonts['body'], color = white, justify = 0.5, vjustify = 0.5, _alpha = 0.0 )
    url = Text( url_v.inset( 0.1 ), text = 'http://www.cs.washington.edu/homes/dougz/slithy/', size = 14,
                font = fonts['body'], color = 0.8, justify = 0.5, vjustify = 0.5, _alpha = 0.0 )
    cap = Text( cap_v.inset( 0.1 ),
                text = ['Press ', yellow, fonts['bodyi'], 'space', RESET, ' to continue.'],
                font = fonts['body'], size = 18, color = white, justify = 0.5, vjustify = 0.5,
                _alpha = 0.0 )

    start_animation( bg, title, url )

    fade_in( 0.5, title, url )
    wait( 1.0 )
    enter( cap )
    fade_in( 0.5, cap )

    pause()
    fade_out( 0.5, cap, title, url )

    return end_animation()
title_slide = title_slide()

test_objects( title_slide, show_examples,
              rectangles, rectangles_noclear, show_fonts, simple_shapes,
              coord_transforms, text_positioning, static_path_object,
              dynamic_path_object, path_arrows, arc_arrows,
              bitmap_image, image_with_caption, diagram_cameras,
              util_split_sequence,  
              clear_color = black, visual='5/6/5/0/16/4' )

