# OpenVerse Avatar Editor
# 
# This file contains all the functions for AvEd
# The OpenVerse avatar editor.
#
# Module Name		- Avitar Editor Module
# Current Maintainter 	- Cruise <cruise@openverse.org>
# Sourced By		- InitMainWindow
#
# Copyright (C) 1999 David Gale <cruise@openverse.org>
# For more information visit http://OpenVerse.org/
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
# USA.

# Additional Notes
#
# Implemented string compare functions which show to increase performance.
# Implemented more performance things surrounging functions with braces.
# Now uses translator. (06/27/00 - CRUISE)
proc AvEd {} {
	global MV AE
	
	if {[winfo exists .aved]} {destroy .aved}

	set AE(animate) 0
	set AE(loaded) 0
	set AE(name_baloon) 0
	set AE(color) 1
	set AE(existing) 0
	set AE(images) {}
	set AE(name_x) 0
	set AE(name_y) 40
	set AE(baloon_x) 20
	set AE(baloon_y) 0
	set AE(delay.img) 200
	set AE(delay.final) 8000
	toplevel .aved
	wm title .aved [Trns openverse_avatar_editor]
	wm resizable . 0 0

	frame .aved.col
	radiobutton .aved.col.black -text [Trns black] -variable AE(color) -value 1 -command AvEd_ChangeColor
	radiobutton .aved.col.white -text [Trns white] -variable AE(color) -value 2 -command AvEd_ChangeColor
	radiobutton .aved.col.blue -text [Trns blue] -variable AE(color) -value 3 -command AvEd_ChangeColor
	canvas .aved.c -height 200.0 -width 320.0 -relief sunken \
		-background black
	frame .aved.b -relief sunken
	frame .aved.bb -relief sunken
	frame .aved.bbbb -relief sunken
	frame .aved.bbb -relief sunken
	frame .aved.b.l
	frame .aved.b.r
	frame .aved.b.l.a
	frame .aved.b.l.b
	frame .aved.b.l.c
	frame .aved.b.l.d
	button .aved.b.l.b.7 -text [Trns balloon] -command "AvEd_NameBaloon"
	button .aved.b.l.b.8 -text [Trns up] -command "AvEd_Pos 8"
	button .aved.b.l.b.9 -text [Trns name] -command "AvEd_NameBaloon"
	button .aved.b.l.c.4 -text [Trns left] -command "AvEd_Pos 4"
	frame .aved.b.l.c.5
	button .aved.b.l.c.5.t -text [Trns select_image] -borderwidth 2 \
		-command "AvEd_PickImage 0"
	menubutton .aved.b.l.c.5.b -text [Trns load_existing] \
		-menu .aved.b.l.c.5.b.m -relief raised -borderwidth 2
	menu .aved.b.l.c.5.b.m
	button .aved.b.l.c.6 -text [Trns right] -command "AvEd_Pos 6"
	button .aved.b.l.d.1 -text [Trns play] -command "AvEd_AnimateAvatar 1"
	button .aved.b.l.d.2 -text [Trns down] -command "AvEd_Pos 2"
	button .aved.b.l.d.3 -text [Trns stop] -command "AvEd_AnimateAvatar 0"

	frame .aved.b.r.cmds -relief sunken -borderwidth 2
	button .aved.b.r.cmds.save -text [Trns save] -command "AvEd_Save"
	checkbutton .aved.b.r.cmds.anim -text [Trns animated] \
		-variable AE(animate) \
		-command AvEd_Animated -relief raised -borderwidth 2
	button .aved.b.r.cmds.add -text [Trns add_image] \
		-command "AvEd_PickImage 1" -borderwidth 2
	button .aved.b.r.cmds.quit -text [Trns quit] -command {destroy .aved}

	frame .aved.bb.files
	frame .aved.bb.files.l
	listbox .aved.bb.files.l.list -height 6 -width 40 \
		-yscrollcommand ".aved.bb.files.l.yscroll set" \
		-xscrollcommand ".aved.bb.files.xscroll set" 
	scrollbar .aved.bb.files.l.yscroll -command ".aved.bb.files.l.list yview"
	scrollbar .aved.bb.files.xscroll -command ".aved.bb.files.l.list \
		 xview" -orient horizontal
	
	button .aved.bbbb.del -text [Trns delete_selected] -command "AvEd_DeleteOne"

	frame .aved.bbb.delays
	scale .aved.bbb.delays.img -from 1 -to 10000 -label [Trns sequence_delay] \
		-variable AE(delay.img) -orient horizontal -relief raised \
		-borderwidth 2
	scale .aved.bbb.delays.fin -from 1 -to 10000 -label [Trns final_delay] \
		-variable AE(delay.final) -orient horizontal -relief raised \
		-borderwidth 2

	pack .aved.col -side top 
	pack .aved.col.black .aved.col.white .aved.col.blue -side left -fill both -expand y
	pack .aved.c -side top 
	pack .aved.bbb -side bottom -fill both -expand y
	pack .aved.bbbb -side bottom -fill both -expand y
	pack .aved.bb -side bottom -fill both -expand y
	pack .aved.b -side bottom -fill both -expand y
	pack .aved.b.l -side left -fill y
	pack .aved.b.r -side left -fill both -expand y
	pack .aved.b.l.a -fill x -expand y
	pack .aved.b.l.b -fill x -expand y
	pack .aved.b.l.c -fill x -expand y
	pack .aved.b.l.d -fill x -expand y
	pack .aved.b.l.b.7 .aved.b.l.b.8 .aved.b.l.b.9 -side left -fill both -expand y
	pack .aved.b.l.c.4 .aved.b.l.c.5 .aved.b.l.c.6 -side left -fill both -expand y
	pack .aved.b.l.d.1 .aved.b.l.d.2 .aved.b.l.d.3 -side left -fill both -expand y
	pack .aved.b.l.c.5.t -side top -fill both -expand y
	pack .aved.b.l.c.5.b -side bottom -fill both -expand y

	pack .aved.b.r.cmds -side left -fill both -expand y
	pack .aved.b.r.cmds.save -fill both -expand y
	pack .aved.b.r.cmds.anim -fill both -expand y
	pack .aved.b.r.cmds.add -fill both -expand y
	pack .aved.b.r.cmds.quit -fill both -expand y

	pack .aved.bb.files -side bottom -fill both -expand y
	pack .aved.bb.files.xscroll -side top -fill x -expand y
	pack .aved.bb.files.l -fill both -expand y
	pack .aved.bb.files.l.list -side left -fill both -expand y
	pack .aved.bb.files.l.yscroll -side left -fill y -expand y

	pack .aved.bbb.delays -fill both -expand y
	pack .aved.bbb.delays.img .aved.bbb.delays.fin -side left -fill both -expand y

	pack .aved.bbbb.del -side left -fill both -expand y

	bind .aved.bb.files.l.list <ButtonRelease> {catch {AvEd_SelectImage [selection get]}}
	bind .aved.b.l.d.2 <ButtonPress> "AvEd_Pos 2"
	bind .aved.b.l.c.4 <ButtonPress> "AvEd_Pos 4"
	bind .aved.b.l.c.6 <ButtonPress> "AvEd_Pos 6"
	bind .aved.b.l.b.8 <ButtonPress> "AvEd_Pos 8"
	bind .aved <Destroy> "Unset_AvEd"

	set avatars 0
	set depth 0
	set count 0
	foreach file [List_Avatars] {
		if !$depth {
			incr depth
			.aved.b.l.c.5.b.m add cascade -menu \
				.aved.b.l.c.5.b.m.m$depth -label "[Trns avatars] $depth"
			menu .aved.b.l.c.5.b.m.m$depth
		}
		set AE(loadavatar.$count) "[file tail $file]"
		.aved.b.l.c.5.b.m.m$depth add command -label [file tail $file] \
			-command "AvEd_LoadExisting $count \"$MV(anims)\" \"$MV(images)\""
		incr avatars
		incr count
		if {$avatars > 19} {
			incr depth
			.aved.b.l.c.5.b.m add cascade -menu \
				.aved.b.l.c.5.b.m.m$depth -label "[Trns avatars] $depth"
			menu .aved.b.l.c.5.b.m.m$depth
			set avatars 0
		}
	}
	AvEd_Animated
	AvEd_NameBaloon
}

# This function is used to build a popup window to save the file.
#
# Notes:
# Now uses translator (06/27/00 CRUISE)
#
proc AvEd_Save {} {
	global AE MV
	
	if !$AE(loaded) {return}
	if {[winfo exists .avedsave]} {destroy .avedsave}
	set types {
		{{Avatar Files}		{.av .AV .Av}	}
		{{Avatar Files}		{}	TEXT}
		{{All Files}		*	}
	}
	
	if $AE(existing) {
		set file [tk_getSaveFile -initialdir [file nativename "$MV(homedir)/anims"] -initialfile [file nativename "$MV(homedir)/anims/$AE(existing.file)"] -filetypes $types]
	} else {
		set file [tk_getSaveFile -initialdir [file nativename "$MV(homedir)/anims"] -filetypes $types]
	}
	set AE(save.file.name) $file
	AvEd_SaveIt 1
}

# This function actually saves the file. It will check to see if it exists
# before it saves it.
#
# Notes:
# Now uses translator (06/27/00 CRUISE)
#
proc AvEd_SaveIt {overwrite} {
	global MV AE

	set filename [file tail $AE(save.file.name)]
	if {[string tolower [string range $filename [expr [string length $filename] -3] end]] != ".av"} {
		set filename "$filename.av"
	}

	if {[file exists "$MV(anims)/$filename"] && !$overwrite} {
		if ![tk_dialog .aved.save_error [Trns file_exists] \
			[Trns aved_save_warning] \
                	"" 0 [Trns cancel] [Trns save]] {
			destroy .avedsave
			return
		}
        }
	destroy .avedsave
	set outfile [open "$MV(anims)/$filename" w]
	puts $outfile "set MV(anim.frames) [.aved.bb.files.l.list size]"
	puts $outfile "set MV(anim.current) 1"
	puts $outfile "set MV(anim.delay) $AE(delay.img)"
	puts $outfile "set MV(anim.final_delay) $AE(delay.final)"
	puts $outfile "set MV(anim.animated) $AE(animate)"
	if $AE(animate) {
		puts $outfile "set MV(anim.stop) 0"
	} else {
		puts $outfile "set MV(anim.stop) 1"
	}
	puts $outfile "set MV(anim.new) 1"
	puts $outfile "set MV(anim.x_off) $AE(name_x)"
	puts $outfile "set MV(anim.y_off) $AE(name_y)"
	puts $outfile "set MV(anim.baloon_x) $AE(baloon_x)"
	puts $outfile "set MV(anim.baloon_y) $AE(baloon_y)"
	for {set c 0} {$c < [.aved.bb.files.l.list size]} {incr c} {
		puts $outfile "set MV(anim.$c) [.aved.bb.files.l.list get $c $c]"
	}
	close $outfile
	AvEd
	DoAvatars
}

proc AvEd_Pos {dir} {
	global AE

	if !$AE(loaded) {return}
	if $AE(name_baloon) {
		switch $dir {
			2 {incr AE(name_y)}
			4 {incr AE(name_x) -1}
			6 {incr AE(name_x)}
			8 {incr AE(name_y) -1}
		}
		AvEd_KillName
		AvEd_ShowName $AE(name_x) $AE(name_y)
	} else {
		switch $dir {
			2 {incr AE(baloon_y)}
			4 {incr AE(baloon_x) -1}
			6 {incr AE(baloon_x)}
			8 {incr AE(baloon_y) -1}
		}
		AvEd_KillBaloon
		AvEd_ShowBaloon $AE(baloon_x) $AE(baloon_y)
	}
}


proc AvEd_NameBaloon {} {
	global AE
	
	if $AE(name_baloon) {
		.aved.b.l.b.7 configure -state disabled
		.aved.b.l.b.9 configure -state normal
		if $AE(loaded) {
			AvEd_ShowBaloon $AE(baloon_x) $AE(baloon_y)
			AvEd_KillName
		}
		set AE(name_baloon) 0
	} else {
		.aved.b.l.b.7 configure -state normal
		.aved.b.l.b.9 configure -state disabled
		if $AE(loaded) {
			AvEd_KillBaloon
			AvEd_ShowName $AE(name_x) $AE(name_y)
		}
		set AE(name_baloon) 1
	}
}


proc AvEd_ChangeColor {} {
	global AE

	switch $AE(color) {
		1 {
			set color black
		}
		2 {
			set color white
		}
		3 {
			set color blue
		}
	}
	.aved.c configure -background $color
}

proc AvEd_Animated {} {
	global AE

	if $AE(animate) {
		.aved.b.r.cmds.add configure -state normal
		.aved.bbb.delays.img configure -state normal
		.aved.bbb.delays.fin configure -state normal
		.aved.b.l.c.5.t configure -state disabled
		.aved.b.l.d.1 configure -state normal
		.aved.b.l.d.3 configure -state disabled
	} else {
		.aved.b.r.cmds.add configure -state disabled
		.aved.bbb.delays.img configure -state disabled
		.aved.bbb.delays.fin configure -state disabled
		.aved.b.l.c.5.t configure -state normal
		.aved.b.l.d.1 configure -state disabled
		.aved.b.l.d.3 configure -state disabled
		set AE(anim.stop) 1
		set AE(anim.running) 0
	}
}	

proc AvEd_LoadExisting {what dir imgs} {
	global AE


	source "$dir/$AE(loadavatar.$what)"
	set AE(existing) 1
	set AE(existing.file) "$AE(loadavatar.$what)"
	if $AE(loaded) {AvEd}
	set AE(animate) $MV(anim.animated)
	set AE(delay.img) $MV(anim.delay)
	set AE(delay.final) $MV(anim.final_delay)
	set AE(name_x) $MV(anim.x_off)
	set AE(name_y) $MV(anim.y_off)
	set AE(baloon_x) $MV(anim.baloon_x)
	set AE(baloon_y) $MV(anim.baloon_y)
	for {set c 0} {$c < $MV(anim.frames)} {incr c} {
		AvEd_AddImageOld $imgs/$MV(anim.$c)
	}
	AvEd_Animated
}

# This function adds an image to an animation series.
#
# Notes:
# Now uses translator (06/27/00 CRUISE)
#
proc AvEd_AddImageOld {what} {
	global MV AE

	if {[catch {image create photo aved -file "$what"}]} {
		ThrowError "[Trns unable_to_load_image] $what"
		return
	}
	if !$AE(loaded) {
		.aved.c create image 160 100 -image aved
		if $AE(name_baloon) {
			AvEd_ShowName $AE(name_x) $AE(name_y)
		} else {
			AvEd_ShowBaloon $AE(baloon_x) $AE(baloon_y)
		}
	}
	set AE(loaded) 1
	.aved.bb.files.l.list insert end [file tail $what]	
	lappend AE(images) [file tail $what]
	.aved.bb.files.l.list see end
}

# This function adds an image to an animation series.
#
# Notes:
# Now uses translator (06/27/00 CRUISE)
#
proc AvEd_AddImage {add} {
	global MV AE

	#
	# Bugfix 10/17/2001 by Cruise.
	#
	# Wasn't giving the error message when a user tried to load a
	# bad image because it had $what instead of $AE(loadimage)
	#
	if {[catch {image create photo aved -file "$AE(loadimage)"}]} {
		ThrowError "[Trns unable_to_load_image] $AE(loadimage)"
		return
	}
	if !$AE(loaded) {
		.aved.c create image 160 100 -image aved
		if $AE(name_baloon) {
			AvEd_ShowName $AE(name_x) $AE(name_y)
		} else {
			AvEd_ShowBaloon $AE(baloon_x) $AE(baloon_y)
		}
	}
	set AE(loaded) 1
	if $add {
		DebugIt "(AvEd) Adding New Image" other
		.aved.bb.files.l.list insert end [file tail $AE(loadimage)]	
		lappend AE(images) [file tail $AE(loadimage)]
		.aved.bb.files.l.list see end
	} else {
		DebugIt "(AvEd) Replacing Image" other
		.aved.bb.files.l.list delete 0 end
		.aved.bb.files.l.list insert end [file tail $AE(loadimage)]
		set AE(images) [file tail $AE(loadimage)]
		.aved.bb.files.l.list see end
	}
}

proc AvEd_SelectImage {what} {
	global MV AE

	image create photo aved -file "$MV(images)/$what"
}

proc AvEd_KillBaloon {} {
	global AE

	.aved.c delete $AE(baloon)
	.aved.c delete $AE(text)
}

proc AvEd_ShowBaloon {x y} {
	global AE

	set width 60
	set rows 2
	set height 20
	set hoff 8

	set AE(baloon) [.aved.c create polygon \
	[expr (160 + $x) - 20] [expr 100 + $y] \
	[expr (160 + $x)] [expr 100 + $y] \
	[expr (160 + $x) + 20] [expr (100 + $y) - $hoff] \
	[expr (160 + $x) + $width - 20] [expr (100 + $y) - $hoff] \
	[expr (160 + $x) + $width] [expr 100 + $y] \
	[expr (160 + $x) + $width] [expr (100 + $y) + $height]\
	[expr (160 + $x) + $width - 20] [expr (100 + $y) + $height +$hoff] \
	[expr (160 + $x) + 20] [expr (100 + $y) + $hoff + $height] \
	[expr (160 + $x)] [expr (100 + $y) + $height] \
	[expr (160 + $x)] [expr (100 + $y) + 5] \
	[expr (160 + $x) - 20] [expr 100 + $y] \
	-fill white -outline black -smooth 1]
	set AE(text) [.aved.c create text [expr (160 + $x) + \
		($width / 2)] [expr (100 + $y) + (6 * $rows)] \
		-width 200 -text "Hello!"]
}

proc AvEd_KillName {} {
	global AE

	.aved.c delete $AE(nametext)
	.aved.c delete $AE(nameplate)
}

proc AvEd_ShowName {x y} {
	global MV AE

	set width [expr [string length $MV(nick)] * 8]
	set AE(nameplate) [.aved.c create rectangle \
		[expr (160 + $x) - ($width / 2)] \
		[expr (100 + $y) - 8] \
		[expr (160 + $x) + ($width / 2)] \
		[expr (100 + $y) + 8] -fill black]
	set AE(nametext) [.aved.c create text \
		[expr 160 + $x] [expr 100 + $y] -text $MV(nick) -fill white]

}


proc AvEd_AnimateAvatar {how} {
	global MV AE

	if {![winfo exists .aved]} {
		set AE(anim.stop) 1
		set AE(anim.running) 0
		return
	}
	switch -- $how {
		0 {
			.aved.b.l.d.1 configure -state normal
			.aved.b.l.d.3 configure -state disabled
			set AE(anim.stop) 1
			set AE(anim.running) 0
		}
		1 {
			.aved.b.l.d.1 configure -state disabled
			.aved.b.l.d.3 configure -state normal
			set AE(anim.stop) 0
			set AE(anim.current) 1
			set AE(anim.new) 1
			AvEd_AnimateAvatar -1
		}	
		"-1" {
			set delay 0
			if {$AE(anim.current) == 1 && !$AE(anim.new)} {
				set delay $AE(delay.final)
			}
			set AE(anim.new) 0
			if $AE(anim.stop) {
				image create photo aved -file "$MV(images)/[.aved.bb.files.l.list get 0]"
				set AE(anim.running) 0
				return
			}
			image create photo aved -file "$MV(images)/[.aved.bb.files.l.list get [expr $AE(anim.current) -1]]"
			.aved.bb.files.l.list selection clear 0 end
			.aved.bb.files.l.list selection set [expr $AE(anim.current) -1]
			.aved.bb.files.l.list see [expr $AE(anim.current) -1]
			set AE(anim.running) 1
			incr AE(anim.current)
			if {$AE(anim.current) > [.aved.bb.files.l.list size]} {
				set AE(anim.current) 1
			}
			update idletasks
			set do_delay [expr $AE(delay.img) + $delay]
			after $do_delay AvEd_AnimateAvatar -1
		}
	}
}

proc AvEd_PickImage {add} {
	global MV AE

	set types {
		{{GIF Image Files}	{.gif .GIF .Gif}	}
		{{GIF Image Files}	{}	GIFF}
		{{All Files}		*	}
	}
	set file [tk_getOpenFile -initialdir [file nativename "$MV(homedir)/images"] -filetypes $types]
	# Performance Enhancement DRG
	if {![string compare $file ""]} {return}
	if {![file exists "$MV(homedir)/images/[file tail $file]"]} {
		file copy $file "$MV(homedir)/images/"
	} else {
		if {[file size "$MV(homedir)/images/[file tail $file]"] != [file size $file]} {
			file copy -force $file "$MV(homedir)/images/"
		}
	}
	#
	# Don't allow images with spaces in their name... re-name them.
	# Cruise - 10/18/01
	#
	set filename [file tail $file]
	if {[string first " " $filename] != -1} {
		set newfile ""
		for {set c 0} {$c < [string length $filename]} {incr c} {
			switch -- [string range $filename $c $c] {
				" " {append newfile "_"}
				default {append newfile [string range $filename $c $c]}
			}
		}
		file rename "$MV(homedir)/images/$filename" "$MV(homedir)/images/$newfile"
		set filename $newfile
	}
	set AE(loadimage) "$MV(homedir)/images/$filename"
	# Performance Enhancement DRG
	if {[string compare $filename ""]} {
		AvEd_AddImage $add
	}
}


proc AvEd_DeleteOne {} {
	global MV AE

	set what ""
	catch {set what [selection get]}
	set lidx [.aved.bb.files.l.list curselection]
	# Performance Enhancement DRG
	if {[string compare $lidx ""]} {
		.aved.bb.files.l.list delete $lidx
		set idx [lsearch $AE(images) $what]
		set AE(images) [lreplace $AE(images) $idx $idx]
	}
}

proc Unset_AvEd {} {
	global AE
	catch {unset AE}
}
