top of script window
dialing for behaviors code snippet | show it | return |
-- dial behavior
-- creates a rotating needle that can sweep continuus full circles,
-- arc lengths, random movements, or move to amounts as sent from
-- other handlers
-----------------------------------------------------------------
-- alan <alan.levine@domail.maricopa.edu>

-- assumes quadrant states of
--     v
--     |
--  2  |  1        > 0 degrees is the positive h axis
-- --------- h     > angles are positive in the counter
--  3  |  4          clockwise direction  
--     |           > v axis is positive upward

-----------------------------------------------------------------
property myOriginLoc, myOrigin, myVertex, myTheta, myRadius, myMode, ¬
myMin, myMax,  myDelay, myClock, myDirection, myIncrement, myTrails, ¬
myState, theRadtoDeg

-- myOriginLoc          : symbol param for which corner of the 
--                        starting sprte is the axis of rotation;
--                        [#topLeft,#bottomRight,#topRight,#bottomLeft]
-- myOrigin             : point location of the origin
-- myVertex             : point location of the end of the needle
-- myTheta              : angle of rotation measured counter
--                        colckwise from positive h axis
-- myRadius             : radius of circle of rotation
-- myMode               : symbol representing the type of dial
--                        [#arcSweep,#fullSweep,#randomSweep,#externalTrigger]
-- myMin                : starting angle location for arcSweep or range for 
--                        randomSweep
-- myMax                : ending  angle location for arcSweep or range for 
--                        randomSweep
-- myDelay              : number of ticks between updates
-- myClock              : runing time in ticks since last update
-- myDirection          : clockwise or counter-clockwise
-- myIncrement          : number of degrees to move between updates
-- myTrails             : boolean flag for drawing with trails
-- myState              : flag to indicate whether we have finished for an arc
-- theRadtoDeg          : constant for converting between radians and degrees
-----------------------------------------------------------------

on beginSprite me
  -- initialize the constant for angle conversion
  set theRadToDeg =  180.0 / pi()
  
  -- initialize state to active  
  set myState = #go
  
  -- initialize clock
  set myClock = the ticks
  
  -- set increment to negative  for clockwise sweeps
  if myDirection = "Clockwise" then set myIncrement = - myIncrement
  
  -- initialize trails state
  set the trails of sprite the spriteNum of me = myTrails
  
  -- find the vertex and the points according to the initial sprite and
  -- flag sent from BH dialog box
  
  if myOriginLoc = #topLeft then  
    -- sprite with origin at top left of rect ( member "line24" in quadrant 4)
    set myOrigin = point( getAt( the rect of sprite the spriteNum of me,1),¬
                          getAt( the rect of sprite the spriteNum of me,2) )
    set myVertex = point( getAt( the rect of sprite the spriteNum of me,3),¬
                          getAt( the rect of sprite the spriteNum of me,4) )
    
  else if myOriginLoc = #bottomRight then  
    -- sprite with origin at bottom right of rect ( member "line24" in quadrant 2)
    set myOrigin = point( getAt( the rect of sprite the spriteNum of me,3),¬
                          getAt( the rect of sprite the spriteNum of me,4) )
    set myVertex = point( getAt( the rect of sprite the spriteNum of me,1),¬
                          getAt( the rect of sprite the spriteNum of me,2) )
    
  else if myOriginLoc = #topRight then       
    -- sprite with origin at top right of rect ( member "line13" in quadrant 3)
    set myOrigin = point( getAt( the rect of sprite the spriteNum of me,3),¬
                          getAt( the rect of sprite the spriteNum of me,2) )
    set myVertex = point( getAt( the rect of sprite the spriteNum of me,1),¬
                          getAt( the rect of sprite the spriteNum of me,4) )
  else  
    -- sprite with origin at bottom left of rect ( member "line13" in quadrant 1)
    
    set myOrigin = point( getAt( the rect of sprite the spriteNum of me,1),¬
                          getAt( the rect of sprite the spriteNum of me,4) )
    set myVertex = point( getAt( the rect of sprite the spriteNum of me,3),¬
                          getAt( the rect of sprite the spriteNum of me,2) )
  end if
  
  -- determine the initial angle of the vertex
  
  if the locV of myOrigin = the locV of myVertex then
    -- case where the line is horizontal
    if the locH of myOrigin > the locH of myVertex then
      set myTheta = 0
    else
      set myTheta = 180
    end if    
    set myRadius = abs( the locH of myOrigin - the locH of myVertex )
    
  else  if the locH of myOrigin = the locH of myVertex then
    -- case where the line is vertical  
    if the locV of myOrigin > the locV of myVertex then
      set myTheta = 270
    else
      set myTheta = 90
    end if    
    set myRadius = abs( the locV of myOrigin - the locV of myVertex )   
  else
    
    -- all other cases, need to determine angle with arctangent
    set myTheta = theRadToDeg * atan ( 1.0 * (the locV of myOrigin - ¬
          the locV of myVertex) / (the locH of myVertex - the locH of myOrigin))
    
    -- determines quadrant of vertex point
    -- 1 = NE, 2 = NW, 3=SW, 4=SE   
    if the locV of myVertex < the locV of myOrigin then
      -- we are in quads 1 or 2
      if the locH of myVertex < the locH of myOrigin then
        -- quad 2
        set myTheta = 180 + myTheta
      else
        -- quad 1, no adjustment
      end if
    else
      -- we are in quads 3 or 4
      if the locH of myVertex  < the locH of myOrigin then
        -- quad 3
        set myTheta = 180 + myTheta        
      else
        -- quad 4
        set myTheta = 360 + myTheta  
      end if   
    end if
    
    -- keep track of the starting angle
    set myMin = myTheta
    
    -- calculate radius with distance formula
    set myRadius = sqrt ( power( the locH of myVertex - the locH of myOrigin , 2) +  ¬
                          power( the locV of myVertex - the locV of myOrigin , 2)    )
  end if
  
end

on prepareFrame me
  -- called on every frame update to generate new locations
  
  -- First check if this motion is active  
  if myState = #go then
    
    -- only update if we have passed our delay interval
    if the ticks - myClock > myDelay then
      if myMode = #arcSweep then 
        -- update to new value
        
        set myTheta = myTheta + myIncrement
        
        -- need two tests for ending condition
        if myIncrement > 0 then
          
          -- test for counter-clockwise movement
          if myTheta < myMin + myMax then
            move( me, myTheta)
          else
            set myState = #stop
          end if
        else
          -- test for clockwise movement
          if myTheta > myMin - myMax then
            move(me, myTheta)
          else
            set myState = #stop
          end if
        end if
        
      else if myMode = #fullSweep  then 
        -- full sweeps, just increment and draw
        
        set myTheta = myTheta + myIncrement
        move(me, myTheta)
        
      else if myMode = #randomSweep then
        -- random sweeps, calculate for range withing specified
        -- inputs, in appropriate direction from starting point
        
        if  myIncrement > 0 then
          set myTheta = myMin + random(myMax)
        else
          set myTheta = myMin - random(myMax)
        end if
        
        move(me, myTheta)
      end if
      
      -- update the clock
      set myClock = the ticks
      
    end if    
    updateStage
  end if
  
end

on move me, newTheta
  -- general purpose call to move the needle to the new value (degrees)
  
  set myTheta = newTheta
  
  -- correct for angles that go negative
  if myTheta < 0 then set myTheta = 360 +  myTheta 
  
  -- we need to work off of a local variable so we can test quadrants
  
  set localTheta = myTheta
  
  -- reduce the local theta to less than 360
  repeat while localTheta >= 360
    set localTheta = localTheta - 360
  end repeat
  
  -- 0 degree angle special case
  if  localTheta = 0 then
    
    -- update new vertex point
    set myVertex = myOrigin + point(integer( myradius),0)
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) = the number of member "line13"
    
    -- scale the sprite by its rect
    set the rect of sprite (the spriteNum of me) = ¬
         rect(the locH of myOrigin, the locV of myVertex, the locH of myVertex, ¬
              the locV of myOrigin + the lineSize of sprite (the spriteNum of me) )
    
  else if localTheta < 90 then
    -- quadrant 1
    
    -- update new vertex point
    set myVertex = myOrigin + point( integer(myRadius * ¬
       cos (localTheta / theRadToDeg )), - integer(myRadius * ¬
       sin (localTheta / theRadToDeg)))
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) = the number of member "line13"
    
    -- scale the sprite by its rect
    set the rect of sprite (the spriteNum of me) = ¬
        rect(the locH of myOrigin, the locV of myVertex, ¬
             the locH of myVertex, the locV of myOrigin)
    
  else  if  localTheta = 90 then
    -- 90 degree angle special case
    
    -- update new vertex point
    set myVertex = myOrigin - point( 0, integer( myradius))
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) = the number of member "line24"
    
    -- scale the sprite by its rect
    set the rect of sprite (the spriteNum of me) = ¬
          rect(the locH of myVertex - the lineSize of sprite (the spriteNum of me), ¬
               the locV of myVertex, the locH of myOrigin, the locV of myOrigin)
    
  else  if  localTheta < 180 then
    -- quadrant 2
    
    -- update new vertex point
    set myVertex = myOrigin + point( integer(myRadius * ¬
        cos (localTheta / theRadToDeg )), - integer(myRadius * ¬
        sin (localTheta / theRadToDeg)))
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) = the number of member "line24" 
    
    -- scale the sprite by its rect
    set the rect of sprite (the spriteNum of me) = ¬
       rect(the locH of myVertex, the locV of myVertex, ¬
            the locH of myOrigin, the locV of myOrigin)
    
  else  if  localTheta = 180 then
    -- 180 degree angle special case
    
    -- update new vertex point
    set myVertex = myOrigin - point(integer( myradius),0)
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) =  the number of member "line13"  
    -- scale the sprite by its rect
    set the rect of sprite (the spriteNum of me) = ¬
       rect(the locH of myVertex, the locV of myOrigin - ¬
             the lineSize of sprite (the spriteNum of me), ¬
             the locH of myOrigin, the locV of myVertex)
    
  else  if  localTheta < 270 then
    -- quadrant 3
    
    -- update new vertex point
    set myVertex = myOrigin + point( integer(myRadius * ¬
       cos (localTheta / theRadToDeg )),  - integer(myRadius * ¬
       sin (localTheta / theRadToDeg)))
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) = the number of member "line13"
    
    -- scale the sprite by its rect    
    set the rect of sprite (the spriteNum of me) = ¬
       rect(the locH of myVertex, the locV of myOrigin, ¬
            the locH of myOrigin, the locV of myVertex)
    
  else if localTheta = 270 then
    -- 270 degree angle special case
    
    -- update new vertex point
    set myVertex = myOrigin + point( 0, integer( myradius))
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) = the number of member "line24"
    
    -- scale the sprite by its rect      
    set the rect of sprite (the spriteNum of me) = ¬
       rect(the locH of myVertex, the locV of myVertex, ¬
            the locH of myOrigin + the lineSize of sprite (the spriteNum of me), ¬
            the locV of myOrigin)
    
  else
    -- quadrant 4
    
    -- update new vertex point
    set myVertex = myOrigin + point( integer(myRadius * ¬
       cos (localTheta / theRadToDeg )), - integer(myRadius * ¬
       sin (localTheta / theRadToDeg)))
    
    -- set appropriate line sprite
    set the memberNum of sprite (the spriteNum of me) = the number of member "line24"
    
    -- scale the sprite by its rect
    set the rect of sprite (the spriteNum of me) = ¬
      rect(the locH of myVertex, the locV of myVertex, ¬
           the locH of myOrigin, the locV of myOrigin)
    
  end if
end


on getPropertyDescriptionList
  
  set p_list = [ #myOriginLoc: 
               [ #comment:"Origin Location:", ¬
                 #format: #string, #default:1, ¬
                 #range:[#topLeft,#bottomRight,#topRight,#bottomLeft] ],  ¬
                 #myMode: ¬
               [ #comment:   "Type of Dial:",¬
                 #format: #symbol, #default: 1, ¬
                  #range: [#arcSweep,#fullSweep,#randomSweep,#externalTrigger ]]   ]
  
  addProp p_list, #myMax, [#comment: "arc sweep (deg)", ¬
     #format: #integer, #default:360, #range:[#min:1,#max:360] ]
  
  addProp p_list, #myIncrement, [#comment: "increment per move (deg)", ¬
     #format: #integer, #default:10] 
  
  addProp p_list, #myDirection, [#comment: "direction", ¬
     #format: #symbol, #default:1, #range:["Counter-Clockwise", "Clockwise"] ]
  
  addProp p_list, #myDelay, [#comment: "delay time (ticks)", ¬
     #format: #integer, #default:60] 
  
  addProp p_list, #myTrails, [#comment: "trails", ¬
     #format: #boolean, #default:0] 
  
  return p_list   
end
This is the entire behavior, minus get PropertyDescription. It must deal with all 4 quadrants to handle the trig functions.

lingo era = v6