######################################################
# polar.slf -- Example to show the coupling of sliders
######################################################

### Get some generic capabilities ###
tclinit { 
  package require slideui
}


### Define the variables and the sliders ###
tclinit {
  proc CreatePointObject { name } {
    set this $name

    global $this

    # x
    set ${this}(x) 0.0
    set ${this}(x_resolution) 0.01
    set ${this}(x_min) -1.0
    set ${this}(x_max) 1.0

    # y
    set ${this}(y) 0.0
    set ${this}(y_resolution) 0.01
    set ${this}(y_min) -1.0
    set ${this}(y_max) 1.0

    # r
    set ${this}(r) 0.0
    set ${this}(r_resolution) 0.01
    set ${this}(r_min) 0.0
    set ${this}(r_max) 1.42

    # theta
    set ${this}(theta) 0.0
    set ${this}(theta_resolution) 0.1
    set ${this}(theta_min) -180.0
    set ${this}(theta_max) 180.0
  }


  proc UpdatePointUI { this field value } {
    # This procedure updates the values of the coupled sliders
    # and ensures that their values stay in bounds

    global $this

    # puts "UpdatePointUI $this $field $value"

    set x [subst $${this}(x)]
    set y [subst $${this}(y)]
    set r [subst $${this}(r)]
    set theta [subst $${this}(theta)]
    set radians [DegToRad $theta]

    switch $field {
      x -
      y {
        # puts "UpdatePointUI: Modified Cartesian Coordinates"

        set r [expr sqrt($x * $x + $y * $y)]
	if { $x == 0.0 && $y == 0.0 } {
          set radians 0.0
        } else {
          set radians [expr atan2($y, $x)]
        }
        set theta [RadToDeg $radians]

        set ${this}(r) [Min [Max $r [subst $${this}(r_min)]] [subst $${this}(r_max)]]
        set ${this}(theta) [Min [Max $theta [subst $${this}(theta_min)]] [subst $${this}(theta_max)]]

	if { [subst $${this}(r_min)] > $r || $r > [subst $${this}(r_max)] || 
             [subst $${this}(theta_min)] > $theta || $theta > [subst $${this}(theta_max)] } {
          set r [subst $${this}(r)]
          set theta [subst $${this}(theta)]
          set radians [DegToRad $theta]

          set x [expr $r * cos($radians)]
          set y [expr $r * sin($radians)]

	  set ${this}(x) [Min [Max $x [subst $${this}(x_min)]] [subst $${this}(x_max)]]
	  set ${this}(y) [Min [Max $y [subst $${this}(y_min)]] [subst $${this}(y_max)]]
        }
      }

      r -
      theta {
        # puts "UpdatePointUI: Modified Polar Coordinates"

        set x [expr $r * cos($radians)]
        set y [expr $r * sin($radians)]

	set ${this}(x) [Min [Max $x [subst $${this}(x_min)]] [subst $${this}(x_max)]]
	set ${this}(y) [Min [Max $y [subst $${this}(y_min)]] [subst $${this}(y_max)]]

	if { [subst $${this}(x_min)] > $x || $x > [subst $${this}(x_max)] || 
             [subst $${this}(y_min)] > $y || $y > [subst $${this}(y_max)] } {
          set x [subst $${this}(x)]
          set y [subst $${this}(y)]
          set r [expr sqrt($x * $x + $y * $y)]
          if { $x == 0.0 && $y == 0.0 } {
            set radians 0.0
          } else {
            set radians [expr atan2($y, $x)]
          }
          set theta [RadToDeg $radians]

          set ${this}(r) [Min [Max $r [subst $${this}(r_min)]] [subst $${this}(r_max)]]
          set ${this}(theta) [Min [Max $theta [subst $${this}(theta_min)]] [subst $${this}(theta_max)]]
        }
      }

      default {
        puts "ERROR: UpdatePointUI unknown field \"$field\""
      }
    }
  }


  proc CreatePointUI { parent name } {
    set root $parent.f$name
    set this $name

    global $this

    frame $root

    # SLIDER Frame
    frame $root.fScales

    # x - SLIDER
    set widget [CreateScale $root.fScales scaleX \
            ${this}(x) "x" \
            [subst $${this}(x_min)] \
            [subst $${this}(x_max)] \
            [subst $${this}(x_resolution)] \
            "UpdatePointUI $this x"]
    set ${this}(x_scale) $widget
    pack $widget -side top -fill x

    # y - SLIDER
    set widget [CreateScale $root.fScales scaleY \
            ${this}(y) "y" \
            [subst $${this}(y_min)] \
            [subst $${this}(y_max)] \
            [subst $${this}(y_resolution)] \
            "UpdatePointUI $this y"]
    set ${this}(y_scale) $widget
    pack $widget -side top -fill x

    # r - SLIDER
    set widget [CreateScale $root.fScales scaleR \
            ${this}(r) "r" \
            [subst $${this}(r_min)] \
            [subst $${this}(r_max)] \
            [subst $${this}(r_resolution)] \
            "UpdatePointUI $this r"]
    set ${this}(r_scale) $widget
    pack $widget -side top -fill x

    # theta - SLIDER
    set widget [CreateScale $root.fScales scaleTheta \
            ${this}(theta) "theta" \
            [subst $${this}(theta_min)] \
            [subst $${this}(theta_max)] \
            [subst $${this}(theta_resolution)] \
            "UpdatePointUI $this theta"]
    set ${this}(theta_scale) $widget
    pack $widget -side top -fill x

    pack $root.fScales -side top -fill x

    return $root
  }
}

###  Display window ###
tclinit {
  toplevel .slfWindow.point
  CreatePointObject oPoint
  set widget [CreatePointUI .slfWindow.point oPoint]
  pack $widget
}


### SURFACE Definitions ###

surface sBlue
  color ( 0 0 1 )
endsurface

surface sRed
  color ( 1 0 0 )
endsurface

sphere oSphere
  radius 0.1
  zslices 8
  thetaslices 8
endsphere


### Scene GEOMETRY ###

group gMyScene
  instance oSphere
    surface sRed
    translate ( {expr $oPoint(x)} {expr $oPoint(y)} 0 )
  endinstance
endgroup


##################################################
# Set up view
##################################################

group gRoot
  instance gMyScene
  endinstance
endgroup

group gCam
  instance cam
    id iCam
    translate ( 0 0 1 )
  endinstance
endgroup

camera cam
  #projection SLF_PERSPECTIVE
  projection SLF_PARALLEL
  frustum ( -1 -1 -2 ) ( 1 1 -0.2 )
endcamera

light lAmbient
  type SLF_AMBIENT
  color ( 0.2 0.2 0.2 )
endlight

light lTop
  type SLF_DIRECTIONAL
  color ( 1.0 1.0 1.0 )
endlight

group gLight
  instance lTop
    id iTop
    lookat
      eye ( 0 0 0 )
      target ( -1 -1 -1 )
      up ( 0 1 0 )
    endlookat
    translate ( 1 1 1 )
  endinstance
endgroup

render Viewport gCam.iCam.cam gRoot
  light lAmbient
  light gLight.iTop.lTop
endrender

viewport Viewport Window
endviewport

window Window
  background ( 0.25 0.60 1.0 )
endwindow