# Open Joint Motion Animation
proc OpenJointAnimation {} {
    global ajm_xangle ajm_yangle ajm_zangle
    global ajm_time ajm_speed ajm_time_incr

    set ajm_xangle 0.0
    set ajm_yangle 0.0
    set ajm_zangle 0.0

    if {[winfo exists .ajm]==0} {

    # toplevel window
    toplevel .ajm
    wm protocol .ajm WM_DELETE_WINDOW CloseJointAnimation
    wm title .ajm "Swumsuit: Joint Motion Animation"

    # Togl window (here, only frame)
    frame .ajm.toglframe -width 500 -height 500

    # Other windows...
    frame .ajm.panel
    frame .ajm.panel.force -relief groove -borderwidth 2
    frame .ajm.panel.speed -relief groove -borderwidth 2
    frame .ajm.panel.speed.updown
    frame .ajm.panel.scale -relief groove -borderwidth 2
    frame .ajm.panel.scale.time
    global Output
    button .ajm.panel.export  -text " $Output " \
                         -command PopupExportDialog -height 2
    global sourcedir
    button .ajm.panel.play -bitmap @${sourcedir}/bitmap_play.xbm \
                         -command AjmPlayPause -width 45 -height 38
    global Close
    button .ajm.panel.exit  -text " $Close " \
                         -command CloseJointAnimation -height 2

    global num_frames
    scale .ajm.panel.scale.scale -orient horizontal \
               -from 0 -to $num_frames -var ajm_time -showvalue false
    bind  .ajm.panel.scale.scale <B1-Motion> { UnHilightSegEntry ; HilightSegEntry ; UpdateFrame }
    bind  .ajm.panel.scale.scale <ButtonPress-1> { UnHilightSegEntry ; HilightSegEntry ; UpdateFrame }
    bindtags .ajm.panel.scale.scale { Scale .ajm all .ajm.panel.scale.scale }
    global Frame
    label .ajm.panel.scale.time.label -text " $Frame: "
    label .ajm.panel.scale.time.time  -text "0" -width 7 -anchor e


    button .ajm.panel.speed.updown.up -bitmap @${sourcedir}/bitmap_up.xbm \
              -command "incr ajm_speed 1 ; AjmSetTimeIncr"
    button .ajm.panel.speed.updown.down -bitmap @${sourcedir}/bitmap_down.xbm \
              -command "incr ajm_speed -1 ; AjmSetTimeIncr"
    global Speed
    label  .ajm.panel.speed.label -text "$Speed:"
    label  .ajm.panel.speed.ratio -text "x1   " -width 5

    frame  .ajm.panel.axes
    canvas .ajm.panel.axes.c1 -width 50 -height 9
    canvas .ajm.panel.axes.c2 -width 50 -height 9
    canvas .ajm.panel.axes.c3 -width 50 -height 9
    .ajm.panel.axes.c1 create line 0 5 50 5 -width 2 -fill red
    .ajm.panel.axes.c2 create line 0 5 50 5 -width 2 -fill blue
    .ajm.panel.axes.c3 create line 0 5 50 5 -width 2 -fill green
    label  .ajm.panel.axes.l1 -text ":xb  "
    label  .ajm.panel.axes.l2 -text ":yb  "
    label  .ajm.panel.axes.l3 -text ":zb  "
    pack   .ajm.panel.axes.l3 \
           .ajm.panel.axes.c3 \
           .ajm.panel.axes.l2 \
           .ajm.panel.axes.c2 \
           .ajm.panel.axes.l1 \
           .ajm.panel.axes.c1 \
                 -side right

    # rotation
    global Rotation_angle
    label  .ajm.panel.axes.l4 -text " $Rotation_angle"
    entry  .ajm.panel.axes.e1 -textvariable ajm_xangle -width 7
    entry  .ajm.panel.axes.e2 -textvariable ajm_yangle -width 7
    entry  .ajm.panel.axes.e3 -textvariable ajm_zangle -width 7
    bind   .ajm.panel.axes.e1 <Key-Return> AjmEntryRotate
    bind   .ajm.panel.axes.e2 <Key-Return> AjmEntryRotate
    bind   .ajm.panel.axes.e3 <Key-Return> AjmEntryRotate
    pack   .ajm.panel.axes.l4 \
           .ajm.panel.axes.e1 \
           .ajm.panel.axes.e2 \
           .ajm.panel.axes.e3 \
                 -side left

    pack  .ajm.panel.speed.updown.up .ajm.panel.speed.updown.down \
                                     -side top
    pack  .ajm.panel.speed.label  \
          .ajm.panel.speed.ratio .ajm.panel.speed.updown -side left 

    pack  .ajm.panel.speed.updown -side left 

    pack  .ajm.panel.scale.time.label -side left -anchor w
    pack  .ajm.panel.scale.time.time -side right
    pack  .ajm.panel.scale.scale -side left -expand 1 -fill x
    pack  .ajm.panel.scale.time -side right 

    pack .ajm.panel.axes  -side top -fill x -pady 3
    pack .ajm.panel.scale -side top -fill x
    pack .ajm.panel.play -side left -padx 0
    #pack .ajm.panel.export -side left -padx 0
    pack .ajm.panel.exit -side right -padx 0
    pack .ajm.panel.speed -side right

    pack .ajm.toglframe .ajm.panel -side top -fill x

    # Open togl window
    togl .ajm.togl -width 500 -height 500 -rgba true \
             -double true -depth true -privatecmap false -time 100 
    bind .ajm.togl <ButtonPress-1> {AjmRotStart %x %y %W}
    bind .ajm.togl <B1-Motion> {AjmRotMove %x %y %W}
    bind .ajm.togl <ButtonPress-3> {AjmRotStartZ %y %W}
    bind .ajm.togl <B3-Motion> {AjmRotMoveZ %y %W}
    place .ajm.togl -x 1 -y 1

    ChangeIcon .ajm

    } else {
        wm deiconify .ajm
    }
    
    # store joint motion into OpenGL part
    StoreJointMotion 

    # start animation
    global ajm_time_incr
    set ajm_time_incr 1
    AnimateJointMotion
}

proc AjmRotStart {x y W } {
    global ajm_startx ajm_starty ajm_xangle0 ajm_yangle0 \
           ajm_xangle ajm_yangle
	set ajm_startx $x
	set ajm_starty $y
        set ajm_vPos [$W position]
	set ajm_xangle0 [lindex $ajm_vPos 0]
	set ajm_yangle0 [lindex $ajm_vPos 1]
}

proc AjmRotStartZ {y W } {
    global ajm_startz ajm_zangle0 ajm_zangle
	set ajm_startz $y
        set ajm_vPos [$W positionz]
	set ajm_zangle0 [lindex $ajm_vPos 0]
}
proc AjmRotMove {x y W} {
    global ajm_startx ajm_starty ajm_xangle0 ajm_yangle0 \
           ajm_xangle ajm_yangle
        set ajm_xangle [expr $ajm_xangle0 + ($x - $ajm_startx)  ]
        set ajm_yangle [expr $ajm_yangle0 + ($y - $ajm_starty)  ]
        $W rotate $ajm_xangle $ajm_yangle
}

proc AjmRotMoveZ {y W} {
    global ajm_startz ajm_zangle0 ajm_zangle
        set ajm_zangle [expr $ajm_zangle0 + ($y - $ajm_startz)  ]
        $W rotatez $ajm_zangle 
}

proc AjmEntryRotate {} {
    global ajm_xangle ajm_yangle ajm_zangle
    .ajm.togl rotate  $ajm_xangle $ajm_yangle
    .ajm.togl rotatez $ajm_zangle
}

proc AjmPlayPause {} {
    global ajm_time_incr
    if { $ajm_time_incr != 0 } then {
        set ajm_time_incr 0
        HilightSegEntry
    } else {
        set ajm_time_incr 1
        UnHilightSegEntry
        UpdateFrame
    }
}

# Hilight appropriate frame entry
proc HilightSegEntry {} {
    global edm_num ajm_time num_frames ajm_time_incr
    if {$edm_num==1} { return }
    if {$ajm_time_incr==1} { return }
    UnHilightSegEntry
    for {set i 1} {$i<=[expr $edm_num-1]} {incr i} {
        # next, hilight appropriate frame entry
        set ajm_time2 $ajm_time
        if {$ajm_time2>[expr $num_frames-1]} {
            set ajm_time2 [expr $num_frames-1]
        }
            .editejm$i.value.text.e[expr $ajm_time2+1] configure \
               -bg yellow
           .editejm$i.graph element create point1 -label "" -pixels 10 \
            -xdata $ajm_time2 \
            -ydata [.editejm$i.value.text.e[expr $ajm_time2+1] get] \
            -fill yellow
    }
}

# Unhilight all frame entries
proc UnHilightSegEntry {} {
    global edm_num num_frames
    for {set i 1} {$i<=[expr $edm_num-1]} {incr i} {
        for {set j 1} {$j<=$num_frames} {incr j} {
            .editejm$i.value.text.e$j configure -bg white
        }
    catch {.editejm$i.graph element delete point1 }
    }
}

proc AjmSetTimeIncr {} {
    global ajm_time_interval ajm_time_interval_default ajm_speed 
    if { $ajm_speed > 0.5 } then {
        set ajm_time_interval \
            [expr int($ajm_time_interval_default/pow(2,$ajm_speed))]
        if {[winfo exists .ajm.panel.speed.ratio]==1} {
            .ajm.panel.speed.ratio configure -text "x[expr int(pow(2,$ajm_speed))]   "
        }
        for {set k 1} {$k<=4} {incr k} {
            if {[winfo exists .ii$k.f3.speed.ratio]==1} {
                .ii$k.f3.speed.ratio configure -text "x[expr int(pow(2,$ajm_speed))]   "
            }
        }
    } elseif { $ajm_speed < -0.5 } {
        set ajm_time_interval \
            [expr int($ajm_time_interval_default*pow(2,-$ajm_speed))]
        if {[winfo exists .ajm.panel.speed.ratio]==1} {
            .ajm.panel.speed.ratio configure -text "x1/[expr int(pow(2,-$ajm_speed))]"
        }
        for {set k 1} {$k<=4} {incr k} {
            if {[winfo exists .ii$k.f3.speed.ratio]==1} {
                .ii$k.f3.speed.ratio configure -text "x1/[expr int(pow(2,-$ajm_speed))]"
            }
        }
    } else {
        set ajm_time_interval $ajm_time_interval_default
        if {[winfo exists .ajm.panel.speed.ratio]==1} {
            .ajm.panel.speed.ratio configure -text "x1   "
        }
        for {set k 1} {$k<=4} {incr k} {
            if {[winfo exists .ii$k.f3.speed.ratio]==1} {
                .ii$k.f3.speed.ratio configure -text "x1   "
            }
        }
    }
}


# Animate joint motion
proc AnimateJointMotion { } {
    global ajm_time ajm_time_incr ajm_nondtime ajm_time_interval \
           num_frames
    for { set j 1 } { $j <= 10000000000000 } { incr j } {
    for { set ajm_time 0 } { $ajm_time <= [expr $num_frames-1] } \
        { incr ajm_time $ajm_time_incr} {

        if {$ajm_time_incr==-1}  return
        if {[winfo exists .ajm.togl]==1} {
            .ajm.togl advancetime $ajm_time
            .ajm.panel.scale.time.time configure -text "$ajm_time/$num_frames"
        }
        UpdateFrame
        update
        after $ajm_time_interval

       # sleep for pause
       if {$ajm_time_incr=="0"} { after 30 }

    }
    }
}


# Store joint motion
proc StoreJointMotion { } {
    global num_element
    global segm_num_a
    global axis_num_a
    global joint_angle_a

    # first, get number of lines
    global num_line
    set num_line [.editjm.list index end]
    # next, read line one by one
    for {set i 0} {$i<=[expr $num_line -1]} {incr i} {
        set line [.editjm.list get $i]
        set num_element [llength $line]
        for {set j 0} {$j<=[expr $num_element -1]} {incr j} {
            set element($i,$j) [lindex $line $j]
            # trimming
            set element($i,$j) [string trim $element($i,$j) ]
            # trim "Local_blank", too
            global Local_blank
            set element($i,$j) [string trim $element($i,$j) $Local_blank]
        }
    }

    # store
    catch { .ajm.togl  passnumline $num_line }
    for {set i 0} {$i<=[expr $num_line -1]} {incr i} {

        # find appropriate segment number
        global segm_name
        for {set j 1} {$j<=21} {incr j} {
            set trim_name [string trim $segm_name($j) $Local_blank]
            if {$trim_name==$element($i,1)} {
                set segm_num $j
                set segm_num_a($i) $segm_num 
            }
        }

        # find appropriate rotation axis
        global axis_name
        for {set j 1} {$j<=9} {incr j} {
            if {$axis_name($j)==$element($i,2)} {
                set axis_num $j
                set axis_num_a($i) $axis_num
            }
        }

        set i_line "[expr $i+1] [expr $num_element -3]"
        # store segment number and axis number
        lappend i_line $segm_num
        lappend i_line $axis_num

        # store angles
        for {set j 3} {$j<=[expr $num_element -1]} {incr j} {
            set ins_text [string trim $element($i,$j)]
                lappend i_line $ins_text
                set joint_angle_a($i,[expr $j-3]) $ins_text
        }

        # pass to Togl
        set cmd ".ajm.togl  passiline $i_line"
        catch { eval $cmd }
    }
}

# Close
proc CloseJointAnimation {} {
    global ajm_time_incr
    wm withdraw .ajm
    set ajm_time_incr -1
    UnHilightSegEntry
}

# Global initializing
set ajm_time_incr 1
set ajm_speed 0
set ajm_time_interval_default 100
set ajm_time_interval $ajm_time_interval_default
set ajm_time 0

