


namespace eval AutoAnimate {
    variable _w
    variable _w_list
    variable _escenas
    variable _datos_escenas
    variable _auto_id
    variable _color_fondo
    variable _color_sel
    #variable _escena_sel
    variable _menu_b_derecho_nombres
    variable _menu_b_derecho_comandos
    variable _inicializdo
    variable _hay_cambios
    variable _after_focus
    variable _batch_out

    proc IniVariables { wlist } {
	variable _auto_id
	#variable _escena_sel
	variable _menu_b_derecho_nombres
	variable _menu_b_derecho_comandos
	variable _inicializado
	variable _hay_cambios
	variable _escenas
	variable _datos_escenas
	variable _after_focus
	
	if { ![ info exist _inicializado]} {
	    set _auto_id 1
	    #set _escena_sel ""
	    set _menu_b_derecho_nombres(0)    [ list [_ "Enable"] [_ "Disable"] [_ "Delete"] [_ "Animate scene"]]
	    set _menu_b_derecho_comandos(0)   { {HabilitaEscena} {DesHabilitaEscena} {BorraEscena} {AnimaEscena}}
	    set _inicializado 1
	    set _hay_cambios 0
	    set _after_focus ""
	    set _batch_out ""
	} else {
	    if { [ info exist _datos_escenas]} {
		foreach esc $_datos_escenas(lista) {
		    set que $_datos_escenas($esc,tipo)
		    set datos $_datos_escenas($esc,datos)
		    set nombre [ AnyadeEscena $que $wlist $esc]
		    $nombre setdatos $datos
		    $nombre haycambios 0
		}
		array unset _datos_escenas
		set _hay_cambios 0
	    }
	}
    }

    proc StopAnimacion { wbot cmd} {
	variable _escenas
	foreach esc $_escenas {
	    $esc stop
	}
	$wbot conf -text [_ "Animate"] -command $cmd
    }

    proc Animar { wbot { meter_comentarios_batch 0} } {
	variable _escenas
	variable _w_list

	if { ![ info exist _escenas]} {
	    WarnWin [_ "You have to define at least one scene"]
	    return
	}

	set old_cmd [ $wbot cget -command]
	$wbot conf -text [_ "Stop"] -command "::AutoAnimate::StopAnimacion $wbot \"$old_cmd\""

	if { $meter_comentarios_batch} {
	    set tt [ CalcTiempoTotal]
	    .central.s process *****COMMENTS Batch AutoAnimate script, duration $tt seconds, created on [ clock format [ clock seconds]]
	    set tp 0.0
	}

	# para que el UseMoreWindows no nos pregunte nada
	# 1 - Yes, 2 - beginner, else no (0)
	set old_morewin [ .central.s info variable UseMoreWindows]
	.central.s process escape escape escape escape \
		utilities variables UseMoreWindows 0 \
		escape escape escape escape

	foreach esc $_escenas {
	    [ winfo parent $_w_list] see [ $esc widget]
	    focus [ $esc widget]
	    if { $meter_comentarios_batch} {
		.central.s process *****COMMENTS ${tp}/$tt s. Now [ $esc quesoy]( [ $esc comoestoy]) [$esc gettime]s.
		set tp [ expr $tp + [ $esc gettime]]
	    }
	    if { ![ $esc animar]} {
		break
	    }
	}
	.central.s process escape escape escape escape \
		utilities variables UseMoreWindows $old_morewin \
		escape escape escape escape

	$wbot conf -text [_ "Animate"] -command $old_cmd
    }

    proc PopUpMenuBotonDerecho { m w x y} {
	#$w gidmakecurrent
	set xx [expr [ winfo rootx $w] + $y + 2]
	set yy [expr [ winfo rooty $w] + $y]
	catch {
	    tk_popup $m $xx $yy 0
	}
    }

    proc BorraEscena { nombre } {
	variable _escenas

	$nombre borrar
	if { ![ info exist _escenas]} { return}
	set idx [ lsearch $_escenas $nombre]
	if { $idx != -1} {
	    set tmp1 {}
	    if { $idx > 0} {
		set tmp1 [ lrange $_escenas 0 [ expr $idx - 1]]
	    }
	    set n [ expr [ llength $_escenas] - 1]
	    set tmp2 {}
	    if { $idx < $n} {
		set tmp2 [ lrange $_escenas [ expr $idx + 1] end]
	    }
	    set _escenas [ concat $tmp1 $tmp2]
	}

	MuestraTiempoTotal "" "" ""
    }

    proc HabilitaEscena { nombre } {
	$nombre habilitar
    }

    proc DesHabilitaEscena { nombre } {
	$nombre deshabilitar
    }

    proc AnimaEscena { nombre} {
	$nombre animar
    }

    proc MenuBotonDerecho { nombre w} {
	variable _menu_b_derecho_nombres
	variable _menu_b_derecho_comandos

	set old_cmds $_menu_b_derecho_comandos(0)
	set _menu_b_derecho_comandos(0) {}
	foreach cmd $old_cmds {
	    lappend _menu_b_derecho_comandos(0) [ list -np- ::AutoAnimate::$cmd $nombre]
	}

	menu $w.m3d -tearoff no
	CreateCascadedMenu $w.m3d \
		::AutoAnimate::_menu_b_derecho_nombres \
		::AutoAnimate::_menu_b_derecho_comandos \
		"" 0
	
	bind $w <3> "::AutoAnimate::PopUpMenuBotonDerecho $w.m3d %W %x %y"
	
	set _menu_b_derecho_comandos(0) $old_cmds
    }

    proc CalcTiempoTotal { } {
	variable _escenas

	set tt 0.0
	foreach esc $_escenas {
	    set tt [ expr $tt + [ $esc gettime]]
	}
	return $tt
    }

    proc MuestraTiempoTotal { n1 n2 op} {
	variable _w
	variable _hay_cambios

	set tt [ CalcTiempoTotal]

	$_w.f.fstate.l2 conf -text $tt -width [ string length $tt]
	set _hay_cambios 1
    }

    proc EnfocaEscena { w} {
	variable _after_focus

	set ultf [ focus -lastfor $w]
	if { ( "$ultf" == "") || \
		![ string match [ winfo class $ultf] Entry] } { 
	    focus $w
	} else {
	    #$ultf selection clear
	    #focus $w
	    if { "$_after_focus" == ""} {
		set _after_focus [ after 2000 "$ultf selection clear; focus $w; set ::AutoAnimate::_after_focus \"\""]
	    }
	}
    }

    proc AnyadeEscena { que w { nombre_dado ""}} {
	variable _escenas
	variable _auto_id
	variable _color_fondo
	variable _color_sel
	variable _hay_cambios

	if { "$nombre_dado" == ""} {
	    set nombre Scene_$_auto_id
	} else {
	    set nombre $nombre_dado
	    if { [ regexp {.*_Scene_([0-9]+)$} $nombre_dado dum aa]} {
		set _auto_id $aa
	    }
	}
	if { "$que" == "ZoomPan"} {
	    #DefineEscenaZoomPan $nombre
	    set nombre [ ::ZoomPan::ZoomPan $nombre $w.sc_$_auto_id]
	} elseif { "$que" == "Rotacion"} {
	    set nombre [ ::Rotacion::Rotacion $nombre $w.sc_$_auto_id]
	    #DefineEscenaRotacion $nombre
	} elseif { "$que" == "RenderState"} {
	    set nombre [ ::RenderState::RenderState $nombre $w.sc_$_auto_id]
	}
	frame $w.sc_$_auto_id -bd 0 -highlightthickness 1 -highlightcolor $_color_sel -takefocus 1
	
	#grid $w.sc_$_auto_id.f
	grid $w.sc_$_auto_id
	bind $w.sc_$_auto_id <FocusIn> "[ winfo parent $w] see $w.sc_$_auto_id"
	bind $w.sc_$_auto_id <Enter> "::AutoAnimate::EnfocaEscena $w.sc_$_auto_id"
	# bind $w.sc_$_auto_id <Enter> "
	# set ::AutoAnimate::_escena_sel [ focus -lastfor $w.sc_$_auto_id] ; 
	# focus $w.sc_$_auto_id"
	# bind $w.sc_$_auto_id <Leave> "
	# if { \"::AutoAnimate::_escena_sel\" != \"\"} { 
	#     focus $::AutoAnimate::_escena_sel;
	# }"

	# creamos el menu para que despues lo propage
	MenuBotonDerecho $nombre $w.sc_$_auto_id

	# al crear ya nos propaga el bind <3> para todos los subwidgets
	$nombre crear

	lappend _escenas $nombre
	$nombre timetrace ::AutoAnimate::MuestraTiempoTotal

	incr _auto_id
        set _hay_cambios 1
	return $nombre
    }

    proc BorraTodo { w} {
	variable _escenas
	variable _datos_escenas
	variable _hay_cambios

	if { [ info exist _escenas]} {
	    #WarnWinText "guion $_hay_cambios"
	    foreach esc $_escenas {
		if { [ $esc haycambios]} {
		    set _hay_cambios 1
		    break
		}
	    }
	    if { $_hay_cambios} {
		set retval [tk_dialogRAM $w._tmp Warning \
			"The last changes have not been saved. Do you want to save them?"\
			warning 0 Yes No Cancel]
		# cancel, salimos
		if { $retval == 2 } { return 0 }
		# no los guardamos
		# if { $retval == 1 } { return 1 }
		# los guardamos
		if { $retval == 0 } { GuardarGuion $w }
	    }
	    foreach esc $_escenas {
		set _datos_escenas($esc,tipo) [ $esc quesoy]
		set _datos_escenas($esc,datos) [ $esc getdatos]
		$esc borrar
	    }
	    set _datos_escenas(lista) $_escenas
	    unset _escenas
	}
	return 1
    }

    proc Fin { w} {
	BorraTodo $w
	destroy $w
    }
    
    proc LeerGuion { wparent wlist} {
	variable _hay_cambios
	variable _datos_escenas

	set fname [ tk_getOpenFile -defaultextension ".asr" -filetypes \
		{ { {Animation script file} {.asr}} {{All Files} *}} \
		-parent $wparent \
		-title "Load animation script"]
	if { "$fname" == ""} { return 0}

	if { ![ BorraTodo $wparent ]} { return 0}
	if { [ info exist _datos_escenas]} { array unset _datos_escenas}

	set fi [ open $fname]
	set err 0
	set hay 0
	set nombre_escena ""
	while { ![eof $fi]} {
	    gets $fi linea
	    if { [ regexp {^Animation script: (.*)$} $linea dum nombre_tmp]} {
		set nombre_escena $nombre_tmp
		set hay 1
		break
	    }
	}
	if { $hay} { # a leer escena del script $nombre
	    while { ![eof $fi]} {
		gets $fi linea
		# la 'nombre_escena tipo_escena \{' inicial
		if { [ regexp {^([^ ]+) ([^ ]+) \{$} $linea dum escena que]} {
		    # a leer la escena
		    set no_existe [ catch {
			set nombre [ AnyadeEscena $que $wlist $escena]
			gets $fi linea
			$nombre setdatos $linea
			$nombre haycambios 0
		    }   ]
		    if { $no_existe} {
			WarnWinText "Unknow scene '$que'"
		    }
		    # la '\}' final
		    gets $fi linea
		} elseif { [ regexp {^Animation script: (.*)$} $linea dum nombre_tmp]} {
		    # otro guion, de momento no implementado, break
		    break
		}
	    }
	} else {
	    WarnWin "Nothing read."
	    set err 1
	}
	close $fi
	if { !$err} {
	    #WarnWin "Animation script $fname read." $wparent
	}
	set _hay_cambios 0
    }
    
    proc GuardarGuion { wparent} {
	variable _escenas
	variable _hay_cambios

	if { ![ info exist _escenas] || ( [ llength $_escenas] == 0)} {
	    WarnWin "Nothing to do.[ llength $_escenas]"
	}
	set fname [ tk_getSaveFile -defaultextension ".asr" -filetypes \
		{ { {Animation script file} {.asr}} { {All Files} *}} \
		-parent $wparent \
		-title "Save animation script"]
	if { "$fname" == ""} { return 0}
	
	set fo [ open $fname w]
	puts $fo "# Animation script '$fname' created on [ clock format [ clock seconds]]"
	puts $fo "Animation script: [ file tail $fname]"
	set err 0
	foreach esc $_escenas {
	    puts $fo "$esc [ $esc quesoy] {"
	    puts $fo [ $esc getdatos]
	    $esc haycambios 0
	    puts $fo "}"
	}
	if { !$err} {
	    puts $fo "End animation script\n"
	}
	close $fo

	if { !$err} {
	    WarnWin "Animation script $fname saved." $wparent
	    set _hay_cambios 0
	}
    }

    proc WriteBatchFile { que args} {
	if { ( "$::AutoAnimate::_batch_out" != "") && ( "$que" == "process")} {
	    if { [ llength $args] == 1} {
		puts $::AutoAnimate::_batch_out $args
	    } else {
		set n [ llength $args]
		set i 0
		for { set i 0} { $i < [ expr $n - 1]} { incr i} {
		    set cmd [ lindex $args $i]
		    puts -nonewline $::AutoAnimate::_batch_out "$cmd "
		}
		if { $n} {
		    puts $::AutoAnimate::_batch_out [ lindex $args [ expr $n - 1]]
		}
	    }
	    eval .central.s $que $args
	} else {
	    return [ eval .central.s $que $args]
	}
    }

    proc GuardarGuionBatch { wparent wbot} {
	variable _escenas
	variable _hay_cambios
	variable _batch_out

	if { ![ info exist _escenas] || ( [ llength $_escenas] == 0)} {
	    WarnWin "Nothing to do.[ llength $_escenas]"
	}
	set fname [ tk_getSaveFile -filetypes { { {All Files} *}} \
		  -parent $wparent -title "Save batch file"]
	if { "$fname" == ""} { return 0}

	set err 0
	set fo [ open $fname w]
	set _batch_out $fo

	rename ::.central.s ____Old_Central_s
	rename ::AutoAnimate::WriteBatchFile ::.central.s

	set err [ catch {
	    # lo queremos con comentarios en batch
	    ::AutoAnimate::Animar $wbot 1
	}]

	rename ::.central.s ::AutoAnimate::WriteBatchFile
	rename ____Old_Central_s ::.central.s

	close $fo

	if { !$err} {
	    WarnWin "Batch file $fname saved." $wparent
	    set _hay_cambios 0
	}
    }

    proc Crear { { w .wAutoAnimate} } {
	variable _w
	variable _w_list
	variable _escenas
	variable _color_fondo
	variable _color_sel

	#toplevel $w
	#wm title $w "automatic animation"
	
	InitWindow $w [_ "Automatic animation"] PrePostAutoAnimateWindowGeom ::AutoAnimate::Crear

	set _w $w
	set _color_fondo [ CCGetRGB $w [ $w cget -background]]
	set _color_sel [ CCColorSombra $_color_fondo 65]
	#global old new
	
	frame $w.fviews -bd 0

	set sw [ ScrolledWindow $w.fviews.sc -relief groove -bd 2]
	set sf [ ScrollableFrame $sw.f]
	$sw setwidget $sf
	set wlist [ $sf getframe]
	set _w_list $wlist

	grid $w.fviews.sc -sticky news
	grid rowconfigure $w.fviews 0 -weight 1
	grid columnconfigure $w.fviews 0 -weight 1

	frame $w.f -bd 0

	frame $w.f.fadd -bd 0
	button $w.f.fadd.anyadeZoom -text [_ "+ zoom/pan"] -bd 1 -padx 2 \
		-command "::AutoAnimate::AnyadeEscena ZoomPan $wlist"
	button $w.f.fadd.anyadeRot -text [_ "+ rotation"] -bd 1 -padx 2 \
		-command "::AutoAnimate::AnyadeEscena Rotacion $wlist"
	button $w.f.fadd.anyadeRender -text [_ "+ render"] -bd 1 -padx 2 \
		-command "::AutoAnimate::AnyadeEscena RenderState $wlist"
	grid $w.f.fadd.anyadeZoom $w.f.fadd.anyadeRot $w.f.fadd.anyadeRender -padx 2 -pady 4 -sticky w

	#global GIDDEFAULT
	#set img_open [ image create photo -file [ file join $GIDDEFAULT bitmaps open2.gif]]
	#set img_save [ image create photo -file [ file join $GIDDEFAULT bitmaps save.gif]]

	frame $w.farch -bd 0
	button $w.farch.leer -text [_ "Load script"] -bd 1 -padx 2 \
		 -command "::AutoAnimate::LeerGuion $w $wlist"
	button $w.farch.guardar -text [_ "Save script"] -bd 1 -padx 2 \
		 -command "::AutoAnimate::GuardarGuion $w"
	button $w.farch.guardarbatch -text [_ "Export as batch"] -bd 1 -padx 2 \
		 -command "::AutoAnimate::GuardarGuionBatch $w  $w.botones.animar"
	#button $w.farch.leer -image $img_open -bd 1 -highlightthickness 0 \
	#	 -relief flat -bg $_color_fondo \
	#	 -command "::AutoAnimate::LeerGuion $w $wlist"
	#button $w.farch.guardar -image $img_save -bd 1 -highlightthickness 0 \
	#	 -relief flat -bg $_color_fondo \
	#	 -command "::AutoAnimate::GuardarGuion $w"
	#ChangeToNewLook $w.farch.leer
	#ChangeToNewLook $w.farch.guardar

	grid $w.farch.leer $w.farch.guardar $w.farch.guardarbatch -pady 4 -padx 2 -sticky w

	frame $w.f.fstate -bd 0
	label $w.f.fstate.l1 -text [_ "Total time:"]
	label $w.f.fstate.l2 -text 0
	label $w.f.fstate.l3 -text [_ "sec."]
	grid $w.f.fstate.l1 $w.f.fstate.l2 $w.f.fstate.l3 -pady 4 -sticky e

	grid $w.f.fadd -sticky w
	grid $w.f.fstate -row 0 -column 1 -sticky e

	grid rowconfigure $w.f 0 -weight 1
	grid columnconfigure $w.f 0 -weight 1
	grid columnconfigure $w.f 1 -weight 1

	frame $w.botones -bd 0 -background [ CCColorActivo $_color_fondo]

	button $w.botones.animar -text [_ "Animate"] -bd 1 \
		-command "::AutoAnimate::Animar $w.botones.animar"
	button $w.botones.animctrl -text [_ "Animation controls"]... -bd 1 \
		-command PostAnimateControls
	button $w.botones.cerrar -text [_ "Close"] -bd 1 \
		-command "::AutoAnimate::Fin $w"
	grid  $w.botones.animar $w.botones.animctrl $w.botones.cerrar -pady 10 -padx 4 -sticky ews
	
	grid $w.farch -sticky nwe -pady 4 -padx 4
	grid $w.fviews -sticky wens -pady 4 -padx 4
	grid $w.f -sticky swe
	grid $w.botones -sticky sew

	#grid rowconfigure $w 0 -weight 1
	grid rowconfigure $w 1 -weight 1
	#grid rowconfigure $w 2 -weight 1
	#grid rowconfigure $w 3 -weight 1
	grid columnconfigure $w 0 -weight 1

	IniVariables $wlist

	# delay 0 en animatecontrols, pues ya se generan prou imagenes
	global GidPriv
	
	if {  ![ info exist GidPriv(PostAnimateControlsSavingAnimation) ] || \
		!$GidPriv(PostAnimateControlsSavingAnimation) } {
	    set GidPriv(PostAnimateControlsDelayTime) 0
	    set GidPriv(PostAnimateControlsSaveRedraws) 1
	}
    }
}


namespace eval ::ZoomPan:: {
    variable _datos
    variable _hay_cambios

    namespace export ZoomPan

    proc ZoomPan { nombre w } {
	variable _datos

	# globalizamos el nombre
	if { ![ string match "::*" $nombre]} {
	    set ns [ uplevel 1 namespace current]
	    if { "::" != $ns} {
		append ns "::"
	    }
	    set nombre "$ns$nombre"
	}

	# miramos si ya existe
	if { "[ info commands $nombre]" != ""} {
	    return -code error "command name \"$nombre\" already exists."
	}

	# guardamos datos
	set _datos($nombre,_w) $w
	set _hay_cambios($nombre) 0
	set _datos($nombre,animando) 0
	set _datos($nombre,stop) 0

	# creamos los metodos
	proc $nombre {que args} "::ZoomPan::procesa $nombre \$que \$args"

	return $nombre
    }

    proc procesa { nombre que args} {
	variable _datos
	variable _hay_cambios

	switch -exact -- $que {
	    crear {
		::ZoomPan::Crear $nombre
	    }
	    animar {
		::ZoomPan::Animar $nombre
	    }
	    deshabilitar {
		::ZoomPan::DesHabilitar $nombre
	    }
	    habilitar {
		::ZoomPan::Habilitar $nombre
	    }
	    borrar {
		::ZoomPan::Borrar $nombre
	    }
	    gettime {
		if { $::ZoomPan::_datos($nombre,_habilitado)} {
		    return $::ZoomPan::_datos($nombre,_time)
		} else {
		    return 0
		}
	    }
	    timetrace {
		::ZoomPan::TimeTraceProc $nombre $args
	    }
	    quesoy {
		return ZoomPan
	    }
	    comoestoy {
		if { $_datos($nombre,_habilitado)} { 
		    return [_ "Enabled"]
		} else { 
		    return [_ "Disabled"]
		}
	    }
	    getdatos {
		::ZoomPan::GetDatos $nombre
	    }
	    setdatos {
		::ZoomPan::SetDatos $nombre $args
	    }
	    haycambios {
		#WarnWinText "ZoomPan [ llength [ lindex $args 0]] -[ lindex $args 0]- /$_hay_cambios($nombre)/"
		if { [ llength [ lindex $args 0]] == 0} {
		    return $_hay_cambios($nombre)
		} else {
		    set _hay_cambios($nombre) [ lindex $args 0]
		}
	    }
	    widget {
		return $_datos($nombre,_w)
	    }
	    stop {
		if { $_datos($nombre,animando)} {
		    set _datos($nombre,stop) 1
		}
	    }
	}
    }

    proc GetGiDView { var nombre} {
	variable _hay_cambios

	set ${var} [ .central.s info view]
	set _hay_cambios($nombre) 1
    }

    proc Crear { nombre} {
	variable _datos
	variable _hay_cambios
	
	set w $_datos($nombre,_w)

	#frame $w -bd 0
	label $w.l1 -text [_ "Zoom/Pan"]:
	button $w.bf -text [_ "Start view"] -bd 1 -padx 2 \
		-command "::ZoomPan::GetGiDView ::ZoomPan::_datos($nombre,_old) $nombre"
	button $w.bt -text [_ "End view"] -bd 1 -padx 2 \
		-command "::ZoomPan::GetGiDView ::ZoomPan::_datos($nombre,_new) $nombre"
	label $w.l2 -text [_ "Duration"]:
	entry $w.e -width 3 -textvariable ::ZoomPan::_datos($nombre,_time) -justify right
	label $w.l3 -text [_ "s."] -bd 1
	
	grid $w.l1 $w.bf $w.bt $w.l2 $w.e $w.l3
	
	# activar el menu del 3r boton
	set scr [ bind $w <3>]
	foreach s "$w.l1 $w.bf $w.bt $w.l2 $w.e $w.l3" {
	    bind $s <3> $scr
	}
	
	set _datos($nombre,_time) 5
	set _datos($nombre,_habilitado) 1
	set _datos($nombre,_trace) ""
	set _hay_cambios($nombre) 1

	return $w
    }

    proc Animar { nombre} {
	variable _datos

	if { !$_datos($nombre,_habilitado)} {
	    return 1
	}
	
	if { ![ info exist _datos($nombre,_old)]} {
	    WarnWin [_ "select the $nombre 'from' view"]
	    return 0
	}
	if { ![ info exist _datos($nombre,_new)]} {
	    WarnWin [_ "select the $nombre 'to' view"]
	    return 0
	}
	if { ( $_datos($nombre,_time) < 0.0) || ( $_datos($nombre,_time) > 1000)} {
	    WarnWin [_ "The Time for the $nombre Zoom/Pan is too little (<0) or too big (>1000): $_datos($nombre,_time)"]
	    return 0
	}
	
	for { set i 0} { $i < [ llength $_datos($nombre,_old)]} { incr i} {
	    set oldcomp [ lindex $_datos($nombre,_old) $i]
	    set key [ string tolower [ lindex $oldcomp 0]]
	    if { "$key" == "x"} {
		set zp_old(left) [ lindex $oldcomp 1]
		set zp_old(right) [ lindex $oldcomp 2]
	    } elseif { "$key" == "y"} {
		set zp_old(top) [ lindex $oldcomp 1]
		set zp_old(bottom) [ lindex $oldcomp 2]
	    }
	}
	for { set i 0} { $i < [ llength $_datos($nombre,_new)]} { incr i} {
	    set newcomp [ lindex $_datos($nombre,_new) $i]
	    set key [ string tolower [ lindex $newcomp 0]]
	    if { "$key" == "x"} {
		set zp_new(left) [ lindex $newcomp 1]
		set zp_new(right) [ lindex $newcomp 2]
	    } elseif { "$key" == "y"} {
		set zp_new(top) [ lindex $newcomp 1]
		set zp_new(bottom) [ lindex $newcomp 2]
	    }
	}
	
	set zp_old(width) [ expr $zp_old(right) - $zp_old(left)]
	set zp_old(height) [ expr $zp_old(top) - $zp_old(bottom)]
	set zp_new(width) [ expr $zp_new(right) - $zp_new(left)]
	set zp_new(height) [ expr $zp_new(top) - $zp_new(bottom)]
	
	set npasos [ expr $_datos($nombre,_time) * 25.0]
	if { !$npasos} { # hacemos el zoom/pan directamente
	    .central.s process escape escape escape escape view SetView \"$_datos($nombre,_old)\" escape
	    .central.s process escape escape escape escape view SetView \"$_datos($nombre,_new)\" escape
	    return 1
	}
	set es_cero 1
	foreach t "left right top bottom" {
	    set inc($t) [ expr ( $zp_new($t) - $zp_old($t)) / $npasos]
	    set paso($t) $zp_old($t)
	    if { $inc($t) != 0.0} {
		set es_cero 0
	    }
	}
	
	if { $es_cero} {
	    WarnWin [_ "No Zoom/Pan is done."]
	    return 0
	}
	
	set que_zoom in
	if { $zp_new(width) > $zp_old(width)} {
	    set que_zoom out
	}
	
	proc get_zoom_from_view { que_zoom t_paso t_zoom} {
	    upvar $t_paso new
	    upvar $t_zoom zoom
	    
	    set old(view) [ .central.s info view]
	    for { set i 0} { $i < [ llength $old(view)]} { incr i} {
		set oldcomp [ lindex $old(view) $i]
		set key [ string tolower [ lindex $oldcomp 0]]
		if { "$key" == "x"} {
		    set old(left) [ lindex $oldcomp 1]
		    set old(right) [ lindex $oldcomp 2]
		} elseif { "$key" == "y"} {
		    set old(top) [ lindex $oldcomp 1]
		    set old(bottom) [ lindex $oldcomp 2]
		}
	    }
	    set old(width) [ expr $old(right) - $old(left)]
	    set old(height) [ expr $old(top) - $old(bottom)]
	    
	    if { "$que_zoom" == "in"} {
		set zoom(left) [ expr 2.0 * ( $new(left) - $old(left)) / $old(width) - 1.0]
		set zoom(right) [ expr 2.0 * ( $new(right) - $old(left)) / $old(width) - 1.0]
		set zoom(bottom) [ expr 2.0 * ( $new(bottom) - $old(bottom)) / $old(height) - 1.0]
		set zoom(top) [ expr 2.0 * ( $new(top) - $old(bottom)) / $old(height) - 1.0]
	    } else {
		set zoom(left) [ expr 2.0 * ( $old(left) - $new(left)) / $new(width) - 1.0]
		set zoom(right) [ expr 2.0 * ( $old(right) - $new(left)) / $new(width) - 1.0]
		set zoom(bottom) [ expr 2.0 * ( $old(bottom) - $new(bottom)) / $new(height) - 1.0]
		set zoom(top) [ expr 2.0 * ( $old(top) - $new(bottom)) / $new(height) - 1.0]
	    }
	}

	set _datos($nombre,animando) 1
	# nos aseguramos el primer estado
	.central.s process escape escape escape escape view SetView \"$_datos($nombre,_old)\" escape
	
	for { set i 0} { $i < $npasos} { incr i} {
	    foreach t "left right top bottom" {
		set paso($t) [ expr $paso($t) + $inc($t)]
	    }
	    set paso(width) [ expr $paso(right) - $paso(left)]
	    set paso(height) [ expr $paso(top) - $paso(bottom)]
	    get_zoom_from_view $que_zoom paso zoom_paso
	    #WarnWinText "$zoom_paso(left) $zoom_paso(right) --- $zoom_paso(top) $zoom_paso(bottom)"
	    .central.s process zoom $que_zoom leftmouse $zoom_paso(left) $zoom_paso(bottom) \
		    leftmouse $zoom_paso(right) $zoom_paso(top)
	    
	    after 40
	    update
	    update idletasks
	    if { $_datos($nombre,stop)} { 
		set _datos($nombre,animando) 0
		set _datos($nombre,stop) 0
		return 0
		#break
	    }
	}
	set _datos($nombre,animando) 0
	set _datos($nombre,stop) 0

	return 1
    }

    proc Habilitar { nombre} {
	variable _datos

	if { !$_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 1

	    set w $_datos($nombre,_w)
	    $w.l1 conf -foreground black
	    $w.bf conf -state normal
	    $w.bt conf -state normal
	    $w.l2 conf -foreground black
	    $w.e conf -state normal
	    $w.l3 conf -foreground black
	    
	}
    }

    proc DesHabilitar { nombre} {
	variable _datos

	if { $_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 0

	    set w $_datos($nombre,_w)
	    $w.l1 conf -foreground grey60
	    $w.bf conf -state disable
	    $w.bt conf -state disable
	    $w.l2 conf -foreground grey60
	    $w.e conf -state disable
	    $w.l3 conf -foreground grey60
	}
    }

    proc Borrar { nombre} {
	variable _datos

	destroy $_datos($nombre,_w)
	if { "$_datos($nombre,_trace)" != ""} {
	    trace vdelete ::ZoomPan::_datos($nombre,_time) w $_datos($nombre,_trace)
	    trace vdelete ::ZoomPan::_datos($nombre,_habilitado) w $_datos($nombre,_trace)
	}
	unset _datos($nombre,_w)
	unset _datos($nombre,_time)
	unset _datos($nombre,_habilitado)
	unset _datos($nombre,_trace)
	if { [ info exist _datos($nombre,_old)]} { unset _datos($nombre,_old)}
	if { [ info exist _datos($nombre,_new)]} { unset _datos($nombre,_new)}
	rename $nombre ""
    }

    proc TimeTraceProc { nombre fn} {
	variable _datos
	trace variable ::ZoomPan::_datos($nombre,_time) w $fn    
	trace variable ::ZoomPan::_datos($nombre,_habilitado) w $fn    
	set _datos($nombre,_trace) $fn
	set ::ZoomPan::_datos($nombre,_time) $::ZoomPan::_datos($nombre,_time)
    }

    proc GetDatos { nombre} {
	variable _datos
	
	if { ![ info exist _datos($nombre,_old)]} {
	    WarnWin [_ "Select the %s 'from' view" $nombre]
	    return 0
	}
	if { ![ info exist _datos($nombre,_new)]} {
	    WarnWin [_ "Select the %s 'to' view" $nombre]
	    return 0
	}
	if { ( $_datos($nombre,_time) < 0.0) || ( $_datos($nombre,_time) > 1000)} {
	    WarnWin [_ "The Time for the %d Zoom/Pan is too little (<0) or too big (>1000): %s" $nombre $_datos($nombre,_time)]
	    return 0
	}

	return [ array get _datos $nombre*]
    }
    
    proc SetDatos { nombre datos} {
	variable _datos
	
	set seg_w $_datos($nombre,_w)
	set seg_trace $_datos($nombre,_trace)
	array set _datos [ lindex [ lindex $datos 0] 0]
	set _datos($nombre,_w) $seg_w
	set _datos($nombre,_trace) $seg_trace
	if { $_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 0
	    Habilitar $nombre
	} else {
	    set _datos($nombre,_habilitado) 1
	    DesHabilitar $nombre
	}
	return 1
    }
}
# end ::ZoomPan


namespace eval ::Rotacion:: {
    variable _datos
    variable _hay_cambios

    namespace export Rotacion

    proc Rotacion { nombre w } {
	variable _datos
	variable _hay_cambios
	
	# globalizamos el nombre
	if { ![ string match "::*" $nombre]} {
	    set ns [ uplevel 1 namespace current]
	    if { "::" != $ns} {
		append ns "::"
	    }
	    set nombre "$ns$nombre"
	}
	
	# miramos si ya existe
	if { "[ info commands $nombre]" != ""} {
	    return -code error "command name \"$nombre\" already exists."
	}

	# guardamos datos
	set _datos($nombre,_w) $w
	set _hay_cambios($nombre) 0
	set _datos($nombre,animando) 0
	set _datos($nombre,stop) 0

	# creamos los metodos
	proc $nombre {que args} "::Rotacion::procesa $nombre \$que \$args"

	return $nombre
    }

    proc procesa { nombre que args} {
	variable _datos
	variable _hay_cambios
	
	switch -exact -- $que {
	    crear {
		::Rotacion::Crear $nombre
	    }
	    animar {
		::Rotacion::Animar $nombre
	    }
	    deshabilitar {
		::Rotacion::DesHabilitar $nombre
	    }
	    habilitar {
		::Rotacion::Habilitar $nombre
	    }
	    borrar {
		::Rotacion::Borrar $nombre
	    }
	    gettime {
		if { $::Rotacion::_datos($nombre,_habilitado)} {
		    return $::Rotacion::_datos($nombre,_time)
		} else {
		    return 0
		}
	    }
	    timetrace {
		::Rotacion::TimeTraceProc $nombre $args
	    }
	    quesoy {
		return Rotacion
	    }
	    comoestoy {
		if { $_datos($nombre,_habilitado)} { 
		    return [_ "Enabled"]
		} else { 
		    return [_ "Disabled"]
		}
	    }
	    getdatos {
		::Rotacion::GetDatos $nombre
	    }
	    setdatos {
		::Rotacion::SetDatos $nombre $args
	    }
	    haycambios {
		#WarnWinText "Rotacion [ llength [ lindex $args 0]] -[ lindex $args 0]- /$_hay_cambios($nombre)/"
		if { [ llength [ lindex $args 0]] == 0} {
		    return $_hay_cambios($nombre)
		} else {
		    set _hay_cambios($nombre) [ lindex $args 0]
		}
	    }
	    widget {
		return $_datos($nombre,_w)
	    }
	    stop {
		if { $_datos($nombre,animando)} {
		    set _datos($nombre,stop) 1
		}
	    }
	}
    }

    proc GetGiDPoint { var var_old nombre} {
	variable _hay_cambios

	set old_view [ .central.s info view]
	for { set i 0} { $i < [ llength $old_view]} { incr i} {
	    set oldcomp [ lindex $old_view $i]
	    set key [ string tolower [ lindex $oldcomp 0]]
	    if { "$key" == "c"} {
		set $var_old [ lrange $oldcomp 1 end]
	    }
	}
	
	set xyz [ GidUtils::GetCoordinates [_ "Enter rotation center for Rotation (ESC to leave)"]]
	if { $::GidPriv(selcoord,id) == -1} {
	    set $var ""
	} elseif { $::GidPriv(selcoord,id) == 0} {
	    set $var $xyz
	} else {
	    set $var $::GidPriv(selcoord,id)
	}
	set _hay_cambios($nombre) 1
    }

    proc Crear { nombre} {
	variable _datos
	variable _hay_cambios

	set w $_datos($nombre,_w)
	#frame $w -bd 0
	
	frame $w.t -bd 0

	label $w.t.l1 -text [_ "Rotation"]:

	button $w.t.rc -text [_ "Center"] -bd 1 \
		-command "::Rotacion::GetGiDPoint ::Rotacion::_datos($nombre,_centro) ::Rotacion::_datos($nombre,_centro_anterior) $nombre"

	ComboBox $w.t.cb1 -editable 0 -width 5 -bd 1 \
		-textvariable ::Rotacion::_datos($nombre,_modo)  -values "Obj Scr"
	label $w.t.ld -text [_ "Duration"]:
	entry $w.t.ed -width 3 -textvariable ::Rotacion::_datos($nombre,_time) -justify right
	label $w.t.ls -text [_ "sec."] -bd 1

	frame $w.b -bd 0
	label $w.b.lx -text [_ "X angle"]:
	entry $w.b.ex -width 4 -textvariable ::Rotacion::_datos($nombre,_angulo_x)
	label $w.b.ly -text [_ "Y angle"]:
	entry $w.b.ey -width 4 -textvariable ::Rotacion::_datos($nombre,_angulo_y)
	label $w.b.lz -text [_ "Z angle"]:
	entry $w.b.ez -width 4 -textvariable ::Rotacion::_datos($nombre,_angulo_z)

	grid $w.t.l1 $w.t.rc $w.t.cb1 $w.t.ld $w.t.ed $w.t.ls
	grid $w.b.lx $w.b.ex $w.b.ly $w.b.ey $w.b.lz $w.b.ez

	grid $w.t -sticky w
	grid $w.b -sticky e

	set _datos($nombre,_modo) Obj
	set _datos($nombre,_angulo_x) 180
	set _datos($nombre,_angulo_y) 180
	set _datos($nombre,_angulo_z) 180
	set _datos($nombre,_time) 5
	set _datos($nombre,_centro) ""
	set _datos($nombre,_centro_anterior) ""
	set _datos($nombre,_habilitado) 1
	set _datos($nombre,_trace) ""
	set _hay_cambios($nombre) 1

	# activar el menu del 3r boton
	set scr [ bind $w <3>]
	foreach s "$w.t.l1 $w.t.rc $w.t.cb1 $w.t.ld $w.t.ed $w.t.ls 
	$w.b.lx $w.b.ex $w.b.ly $w.b.ey $w.b.lz $w.b.ez" {
	    bind $s <3> $scr
	}

	return $w
    }

    proc Animar { nombre} {
	variable _datos

	if { !$_datos($nombre,_habilitado)} {
	    return 1
	}
	if { ( $_datos($nombre,_angulo_x) < -36000.0) || ( $_datos($nombre,_angulo_x) > 36000.0)} {
	    WarnWin [_ "The angle for the $nombre Rotation X is too little (<-36000) or too big (>36000): $_datos($nombre,_angulo_x)"]
	    return 0
	}
	if { ( $_datos($nombre,_angulo_y) < -36000.0) || ( $_datos($nombre,_angulo_y) > 36000.0)} {
	    WarnWin [_ "The angle for the $nombre Rotation Y is too little (<-36000) or too big (>36000): $_datos($nombre,_angulo_y)"]
	    return 0
	}
	if { ( $_datos($nombre,_angulo_z) < -36000.0) || ( $_datos($nombre,_angulo_z) > 36000.0)} {
	    WarnWin [_ "The angle for the $nombre Rotation Z is too little (<-36000) or too big (>36000): $_datos($nombre,_angulo_z)"]
	    return 0
	}
	if { ( $_datos($nombre,_time) < 0.0) || ( $_datos($nombre,_time) > 1000)} {
	    WarnWin [_ "The Time for the $nombre Rotation is too little (<0) or too big (>1000): $_datos($nombre,_time)"]
	    return 0
	}
	
	set npasos [ expr int( $_datos($nombre,_time) * 25.0)]
	set rpasos [ expr $_datos($nombre,_time) * 25.0]
	if { !$npasos} { # lo rotamos y ya esta
	    if { [ llength $_datos($nombre,_centro)] == 1} { 
		.central.s process rotate center join $_datos($nombre,_centro) escape
	    } elseif { [ llength $_datos($nombre,_centro)] == 3} { 
		.central.s process rotate center $_datos($nombre,_centro) escape
	    }
	    set old_redraw [.central.s info variables AutomaticRedraw]
	    .central.s process escape escape escape escape utilities variables \
		    AutomaticRedraw -1 escape escape 
	    .central.s process rotate $_datos($nombre,_modo) x $_datos($nombre,_angulo_x) escape
	    .central.s process rotate $_datos($nombre,_modo) y $_datos($nombre,_angulo_y) escape
	    .central.s process rotate $_datos($nombre,_modo) z $_datos($nombre,_angulo_z) escape
	    .central.s process escape escape escape escape utilities variables \
		    AutomaticRedraw $old_redraw escape escape 
	    .central.s process redraw
	    # devolvemos el anterior centro
	    if { [ llength $_datos($nombre,_centro_anterior)] == 1} { 
		.central.s process rotate center join $_datos($nombre,_centro_anterior) escape
	    } elseif { [ llength $_datos($nombre,_centro_anterior)] == 3} { 
		.central.s process rotate center $_datos($nombre,_centro_anterior) escape
	    }
	    return 1
	}
	set es_cero 1
	set max [ expr abs( $_datos($nombre,_angulo_x))]
	if { [ expr abs( $_datos($nombre,_angulo_y))] > $max} {
	    set max [ expr abs( $_datos($nombre,_angulo_y))]
	}
	if { [ expr abs( $_datos($nombre,_angulo_z))] > $max} {
	    set max [ expr abs( $_datos($nombre,_angulo_z))]
	}
	set epsilon [ expr $max * 1e-6]
	set inc_x [ expr ( $_datos($nombre,_angulo_x)) / $rpasos]
	set inc_y [ expr ( $_datos($nombre,_angulo_y)) / $rpasos]
	set inc_z [ expr ( $_datos($nombre,_angulo_z)) / $rpasos]
	set paso_x 0.0
	set paso_y 0.0
	set paso_z 0.0
	if { $inc_x != 0.0} {
	    set es_cero 0
	}
	if { $inc_y != 0.0} {
	    set es_cero 0
	}
	if { $inc_z != 0.0} {
	    set es_cero 0
	}

	if { $es_cero} {
	    WarnWin [_ "No Rotation is done."]
	    return 0
	}

	set _datos($nombre,animando) 1
	# # nos aseguramos el primer estado
	# .central.s process escape escape escape escape view SetView \"$_old(view)\" escape
	if { [ llength $_datos($nombre,_centro)] == 1} { 
	    .central.s process rotate center join $_datos($nombre,_centro) escape
	} elseif { [ llength $_datos($nombre,_centro)] == 3} { 
	    .central.s process rotate center $_datos($nombre,_centro) escape
	}
	for { set i 0} { $i < $npasos} { incr i} {
	    set old_redraw [.central.s info variables AutomaticRedraw]
	    .central.s process escape escape escape escape utilities variables \
		    AutomaticRedraw -1 escape escape 
	    .central.s process rotate $_datos($nombre,_modo) z [ expr -$paso_z] escape
	    .central.s process rotate $_datos($nombre,_modo) y [ expr -$paso_y] escape
	    .central.s process rotate $_datos($nombre,_modo) x [ expr -$paso_x] escape
	    set paso_x [ expr $paso_x + $inc_x]
	    set paso_y [ expr $paso_y + $inc_y]
	    set paso_z [ expr $paso_z + $inc_z]
	    .central.s process rotate $_datos($nombre,_modo) x $paso_x escape
	    .central.s process rotate $_datos($nombre,_modo) y $paso_y escape
	    .central.s process rotate $_datos($nombre,_modo) z $paso_z escape
	    # .central.s process rotate $_datos($nombre,_modo) x $inc_x escape
	    # .central.s process rotate $_datos($nombre,_modo) y $inc_y escape
	    # .central.s process rotate $_datos($nombre,_modo) z $inc_z escape
	    .central.s process escape escape escape escape utilities variables \
		    AutomaticRedraw $old_redraw escape escape 
	    .central.s process redraw
	    after 40
	    update
	    update idletasks
	    #WarnWinText "$i $npasos ( $paso_x, $paso_y, $paso_z)"
	    if { $_datos($nombre,stop)} { 
		set _datos($nombre,animando) 0
		set _datos($nombre,stop) 0
		return 0
		#break
	    }
	}

	set resto_x [ expr $_datos($nombre,_angulo_x) - $paso_x]
	set resto_y [ expr $_datos($nombre,_angulo_y) - $paso_y]
	set resto_z [ expr $_datos($nombre,_angulo_z) - $paso_z]
	if { [ expr abs( $resto_x)] < $epsilon} {
	    set resto_x 0.0
	}
	if { [ expr abs( $resto_y)] < $epsilon} {
	    set resto_y 0.0
	}
	if { [ expr abs( $resto_z)] < $epsilon} {
	    set resto_z 0.0
	}
	if { ( $resto_x != 0.0) || ( $resto_y != 0.0) || ( $resto_z != 0.0)} {
	    set old_redraw [.central.s info variables AutomaticRedraw]
	    .central.s process escape escape escape escape utilities variables \
		    AutomaticRedraw -1 escape escape 
	    .central.s process rotate $_datos($nombre,_modo) z [ expr -$paso_z] escape
	    .central.s process rotate $_datos($nombre,_modo) y [ expr -$paso_y] escape
	    .central.s process rotate $_datos($nombre,_modo) x [ expr -$paso_x] escape
	    .central.s process rotate $_datos($nombre,_modo) x $_datos($nombre,_angulo_x) escape
	    .central.s process rotate $_datos($nombre,_modo) y $_datos($nombre,_angulo_y) escape
	    .central.s process rotate $_datos($nombre,_modo) z $_datos($nombre,_angulo_z) escape
	    .central.s process escape escape escape escape utilities variables \
		    AutomaticRedraw $old_redraw escape escape 
	    .central.s process redraw
	    #WarnWinText "resto ( $_datos($nombre,_angulo_x), $_datos($nombre,_angulo_y), $_datos($nombre,_angulo_z))"
	}
	
	# devolvemos el anterior centro
	if { [ llength $_datos($nombre,_centro_anterior)] == 1} { 
	    .central.s process rotate center join $_datos($nombre,_centro_anterior) escape
	} elseif { [ llength $_datos($nombre,_centro_anterior)] == 3} { 
	    .central.s process rotate center $_datos($nombre,_centro_anterior) escape
	}
	set _datos($nombre,animando) 0
	set _datos($nombre,stop) 0

	return 1
    }

    proc Habilitar { nombre} {
	variable _datos

	if { !$_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 1

	    set w $_datos($nombre,_w)
	    $w.t.l1 conf -foreground black
	    $w.t.rc conf -state normal
	    $w.t.cb1 configure -state normal
	    $w.t.ld conf -foreground black
	    $w.t.ed conf -state normal -foreground black
	    $w.t.ls conf -foreground black
	    $w.b.lx conf -foreground black
	    $w.b.ex conf -state normal -foreground black
	    $w.b.ly conf -foreground black
	    $w.b.ey conf -state normal -foreground black
	    $w.b.lz conf -foreground black
	    $w.b.ez conf -state normal -foreground black
	}
    }

    proc DesHabilitar { nombre} {
	variable _datos

	if { $_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 0

	    set w $_datos($nombre,_w)
	    $w.t.l1 conf -foreground grey60
	    $w.t.rc conf -state disable
	    $w.t.cb1 configure -state disabled
	    $w.t.ld conf -foreground grey60
	    $w.t.ed conf -state disable -foreground grey60
	    $w.t.ls conf -foreground grey60
	    $w.b.lx conf -foreground grey60
	    $w.b.ex conf -state disable -foreground grey60
	    $w.b.ly conf -foreground grey60
	    $w.b.ey conf -state disable -foreground grey60
	    $w.b.lz conf -foreground grey60
	    $w.b.ez conf -state disable -foreground grey60
	}
    }

    proc Borrar { nombre} {
	variable _datos

	destroy $_datos($nombre,_w)
	if { "$_datos($nombre,_trace)" != ""} {
	    trace vdelete ::Rotacion::_datos($nombre,_time) w $_datos($nombre,_trace)
	    trace vdelete ::Rotacion::_datos($nombre,_habilitado) w $_datos($nombre,_trace)
	}
	unset _datos($nombre,_w)
	unset _datos($nombre,_time)
	unset _datos($nombre,_habilitado)
	unset _datos($nombre,_trace)
	if { [ info exist _datos($nombre,_old)]} { unset _datos($nombre,_old)}
	if { [ info exist _datos($nombre,_new)]} { unset _datos($nombre,_new)}
	rename $nombre ""
    }

    proc TimeTraceProc { nombre fn} {
	variable _datos
	trace variable ::Rotacion::_datos($nombre,_time) w $fn    
	trace variable ::Rotacion::_datos($nombre,_habilitado) w $fn    
	set _datos($nombre,_trace) $fn
	set ::Rotacion::_datos($nombre,_time) $::Rotacion::_datos($nombre,_time)
    }

    proc GetDatos { nombre} {
	variable _datos

	if { ( $_datos($nombre,_angulo_x) < -36000.0) || ( $_datos($nombre,_angulo_x) > 36000.0)} {
	    WarnWin [_ "The angle for the $nombre Rotation X is too little (<-36000) or too big (>36000): $_datos($nombre,_angulo_x)"]
	    return 0
	}
	if { ( $_datos($nombre,_angulo_y) < -36000.0) || ( $_datos($nombre,_angulo_y) > 36000.0)} {
	    WarnWin [_ "The angle for the $nombre Rotation Y is too little (<-36000) or too big (>36000): $_datos($nombre,_angulo_y)"]
	    return 0
	}
	if { ( $_datos($nombre,_angulo_z) < -36000.0) || ( $_datos($nombre,_angulo_z) > 36000.0)} {
	    WarnWin [_ "The angle for the $nombre Rotation Z is too little (<-36000) or too big (>36000): $_datos($nombre,_angulo_z)"]
	    return 0
	}
	if { ( $_datos($nombre,_time) < 0.0) || ( $_datos($nombre,_time) > 1000)} {
	    WarnWin [_ "The Time for the $nombre Rotation is too little (<0) or too big (>1000): $_datos($nombre,_time)"]
	    return 0
	}
	
	return [ array get _datos $nombre*]
    }
    
    proc SetDatos { nombre datos} {
	variable _datos

	set seg_w $_datos($nombre,_w)
	set seg_trace $_datos($nombre,_trace)
	array set _datos [ lindex [ lindex $datos 0] 0]
	set _datos($nombre,_w) $seg_w
	set _datos($nombre,_trace) $seg_trace
	if { $_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 0
	    Habilitar $nombre
	} else {
	    set _datos($nombre,_habilitado) 1
	    DesHabilitar $nombre
	}
	return 1
    }
}
# end ::Rotacion

namespace eval ::RenderState:: {
    variable _datos
    variable _hay_cambios

    namespace export RenderState

    proc RenderState { nombre w } {
	variable _datos
	variable _hay_cambios
	
	# globalizamos el nombre
	if { ![ string match "::*" $nombre]} {
	    set ns [ uplevel 1 namespace current]
	    if { "::" != $ns} {
		append ns "::"
	    }
	    set nombre "$ns$nombre"
	}
	
	# miramos si ya existe
	if { "[ info commands $nombre]" != ""} {
	    return -code error "command name \"$nombre\" already exists."
	}

	# guardamos datos
	set _datos($nombre,_w) $w
	set _hay_cambios($nombre) 0
	set _datos($nombre,animando) 0
	set _datos($nombre,stop) 0

	# creamos los metodos
	proc $nombre {que args} "::RenderState::procesa $nombre \$que \$args"

	return $nombre
    }

    proc procesa { nombre que args} {
	variable _datos
	variable _hay_cambios
	
	switch -exact -- $que {
	    crear {
		::RenderState::Crear $nombre
	    }
	    animar {
		::RenderState::Animar $nombre
	    }
	    deshabilitar {
		::RenderState::DesHabilitar $nombre
	    }
	    habilitar {
		::RenderState::Habilitar $nombre
	    }
	    borrar {
		::RenderState::Borrar $nombre
	    }
	    gettime {
		if { $::RenderState::_datos($nombre,_habilitado)} {
		    return $::RenderState::_datos($nombre,_time)
		} else {
		    return 0
		}
	    }
	    timetrace {
		::RenderState::TimeTraceProc $nombre $args
	    }
	    quesoy {
		return RenderState
	    }
	    comoestoy {
		if { $_datos($nombre,_habilitado)} { 
		    return [_ "Enabled"]
		} else { 
		    return [_ "Disabled"]
		}
	    }
	    getdatos {
		::RenderState::GetDatos $nombre
	    }
	    setdatos {
		::RenderState::SetDatos $nombre $args
	    }
	    haycambios {
		#WarnWinText "RenderState [ llength [ lindex $args 0]] -[ lindex $args 0]- /$_hay_cambios($nombre)/"
		if { [ llength [ lindex $args 0]] == 0} {
		    return $_hay_cambios($nombre)
		} else {
		    set _hay_cambios($nombre) [ lindex $args 0]
		}
	    }
	    widget {
		return $_datos($nombre,_w)
	    }
	    stop {
		if { $_datos($nombre,animando)} {
		    set _datos($nombre,stop) 1
		}
	    }
	}
    }

    proc GetRenderMode { } {
	set que_render Normal
	set whatuse [lindex [.central.s info Project] 4]
	switch $whatuse {
	    GEOMETRYUSE - MESHUSE {
		set que_render [lindex [.central.s info Project] 6]
		switch $que_render {
		    normal {
			set que_render Normal
		    }
		    polygons {
			set que_render Flat
		    }
		    render {
			set que_render Smooth
		    }
		    custom {
			set que_render Normal
		    }
		}
	    }
	    POSTUSE - GRAFUSE {
		set que_render [.central.s info post get cur_display_render]
		switch $que_render {
		    normal {
			set que_render Normal
		    }
		    Flat {
			set que_render Flat
		    }
		    Smooth {
			set que_render Smooth
		    }
		}
	    }
	}
	return $que_render
    }
    
    proc Crear { nombre} {
	variable _datos
	variable _hay_cambios

	set w $_datos($nombre,_w)
	#frame $w -bd 0
	
	frame $w.t -bd 0

	label $w.t.l1 -text [_ "Render state"]:

	ComboBox $w.t.cb1 -editable 0 -width 7 -bd 1 \
		-textvariable ::RenderState::_datos($nombre,_modo) -values "Normal Flat Smooth"
	#label $w.t.ld -text [_ "Duration"]:
	#entry $w.t.ed -width 3 -textvariable ::RenderState::_datos($nombre,_time) -justify right
	#label $w.t.ls -text [_ "sec."] -bd 1

	grid $w.t.l1 $w.t.cb1 
	# $w.t.ld $w.t.ed $w.t.ls

	grid $w.t -sticky w

	set _datos($nombre,_modo) [ GetRenderMode]
	set _datos($nombre,_time) 0
	set _datos($nombre,_habilitado) 1
	set _datos($nombre,_trace) ""
	set _hay_cambios($nombre) 1

	# activar el menu del 3r boton
	set scr [ bind $w <3>]
	foreach s "$w.t.l1 $w.t.cb1" {
	    bind $s <3> $scr
	}
	return $w
    }

    proc Animar { nombre} {
	variable _datos

	if { !$_datos($nombre,_habilitado)} {
	    return 1
	}

	set _datos($nombre,animando) 1

	.central.s process render $_datos($nombre,_modo)

	set _datos($nombre,animando) 0
	set _datos($nombre,stop) 0

	return 1
    }

    proc Habilitar { nombre} {
	variable _datos

	if { !$_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 1

	    set w $_datos($nombre,_w)
	    $w.t.l1 conf -foreground black
	    $w.t.cb1 configure -state normal
	}
    }

    proc DesHabilitar { nombre} {
	variable _datos

	if { $_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 0

	    set w $_datos($nombre,_w)
	    $w.t.l1 conf -foreground grey60
	    $w.t.cb1 configure -state disabled
	}
    }

    proc Borrar { nombre} {
	variable _datos

	destroy $_datos($nombre,_w)
	if { "$_datos($nombre,_trace)" != ""} {
	    trace vdelete ::RenderState::_datos($nombre,_time) w $_datos($nombre,_trace)
	    trace vdelete ::RenderState::_datos($nombre,_habilitado) w $_datos($nombre,_trace)
	}
	unset _datos($nombre,_w)
	unset _datos($nombre,_time)
	unset _datos($nombre,_habilitado)
	unset _datos($nombre,_trace)
	if { [ info exist _datos($nombre,_old)]} { unset _datos($nombre,_old)}
	if { [ info exist _datos($nombre,_new)]} { unset _datos($nombre,_new)}
	rename $nombre ""
    }

    proc TimeTraceProc { nombre fn} {
	variable _datos
	trace variable ::RenderState::_datos($nombre,_time) w $fn    
	trace variable ::RenderState::_datos($nombre,_habilitado) w $fn    
	set _datos($nombre,_trace) $fn
	set ::RenderState::_datos($nombre,_time) $::RenderState::_datos($nombre,_time)
    }

    proc GetDatos { nombre} {
	variable _datos
	
	return [ array get _datos $nombre*]
    }
    
    proc SetDatos { nombre datos} {
	variable _datos

	set seg_w $_datos($nombre,_w)
	set seg_trace $_datos($nombre,_trace)
	array set _datos [ lindex [ lindex $datos 0] 0]
	set _datos($nombre,_w) $seg_w
	set _datos($nombre,_trace) $seg_trace
	if { $_datos($nombre,_habilitado)} {
	    set _datos($nombre,_habilitado) 0
	    Habilitar $nombre
	} else {
	    set _datos($nombre,_habilitado) 1
	    DesHabilitar $nombre
	}
	return 1
    }
}
# end ::RenderState

