module Graphics.UI.GLUT.Turtle.Input(TurtleInput(..), turtleSeries) where
import Graphics.UI.GLUT.Turtle.State(TurtleState(..), initTurtleState, makeShape)
import Text.XML.YJSVG(SVG(..), Color(..), Position(..))
data TurtleInput
= Goto Position
| Forward Double
| RotateRad Double
| Rotate Double
| TurnLeft Double
| Dot Double
| Stamp
| Write String Double String
| PutImage FilePath Double Double
| Undo
| Undonum Int
| Clear
| Sleep Int
| Flush
| Shape [(Double, Double)]
| Shapesize Double Double
| Pensize Double
| Pencolor Color
| Fillcolor Color
| Bgcolor Color
| SetPendown Bool
| SetVisible Bool
| SetFill Bool
| SetPoly Bool
| SetFlush Bool
| PositionStep (Maybe Double)
| DirectionStep (Maybe Double)
| Degrees Double
deriving (Show, Read)
turtleSeries :: [TurtleInput] -> [TurtleState]
turtleSeries tis = let ts0 = initTurtleState in ts0 : ts0 : turtles [] ts0 tis
turtles :: [TurtleState] -> TurtleState -> [TurtleInput] -> [TurtleState]
turtles [] ts0 (Undo : tis) = ts0 : turtles [] ts0 tis
turtles (tsb : tsbs) _ (Undo : tis) =
let ts1 = tsb{undo = True} in ts1 : turtles tsbs ts1 tis
turtles tsbs ts0 (Forward len : tis) = case position ts0 of
Center x0 y0 -> let
x = x0 + len * cos (direction ts0)
y = y0 + len * sin (direction ts0) in
turtles tsbs ts0 $ Goto (Center x y) : tis
TopLeft x0 y0 -> let
x = x0 + len * cos (direction ts0)
y = y0 len * sin (direction ts0) in
turtles tsbs ts0 $ Goto (TopLeft x y) : tis
turtles tsbs ts0 (Rotate dir : tis) = turtles tsbs ts0 $
RotateRad (dir * 2 * pi / degrees ts0) : tis
turtles tsbs ts0 (TurnLeft dd : tis) = turtles tsbs ts0 $
RotateRad (direction ts0 + dd * 2 * pi / degrees ts0) : tis
turtles tsbs ts0 (ti : tis) =
let ts1 = nextTurtle ts0 ti in ts1 : turtles (ts0 : tsbs) ts1 tis
turtles _ _ [] = error "no more input"
reset :: TurtleState -> TurtleState
reset t = t{draw = Nothing, clear = False, undo = False, undonum = 1,
sleep = Nothing, flush = False}
set :: TurtleState -> Maybe SVG -> TurtleState
set t drw = t{draw = drw, drawed = maybe id (:) drw $ drawed t}
nextTurtle :: TurtleState -> TurtleInput -> TurtleState
nextTurtle t (Goto pos) = (reset t){position = pos,
fillPoints = (if fill t then (pos :) else id) $ fillPoints t,
polyPoints = (if poly t then (pos :) else id) $ polyPoints t}
`set` if not $ pendown t then Nothing
else Just $ Line pos (position t) (pencolor t) (pensize t)
nextTurtle t (RotateRad dir) = (reset t){direction = dir}
nextTurtle t@TurtleState{pencolor = clr} (Dot sz) = reset t `set`
Just (Rect (position t) sz sz 0 clr clr)
nextTurtle t@TurtleState{pencolor = clr, fillcolor = fclr} Stamp = reset t `set`
Just (Polyline (makeShape t (direction t) (position t)) fclr clr $
pensize t)
nextTurtle t@TurtleState{pencolor = clr} (Write fnt sz str) = reset t `set`
Just (Text (position t) sz clr fnt str)
nextTurtle t (PutImage fp w h) = reset t `set` Just (Image (position t) w h fp)
nextTurtle t (Undonum un) = (reset t){undonum = un}
nextTurtle t Clear = (reset t){clear = True, drawed = [Fill (RGB 255 255 255)]}
nextTurtle t (Sleep time) = (reset t){sleep = Just time}
nextTurtle t Flush = (reset t){flush = True}
nextTurtle t (Shape sh) = (reset t){shape = sh}
nextTurtle t (Shapesize sx sy) = (reset t){shapesize = (sx, sy)}
nextTurtle t (Pensize ps) = (reset t){pensize = ps}
nextTurtle t (Pencolor clr) = (reset t){pencolor = clr}
nextTurtle t (Fillcolor clr) = (reset t){fillcolor = clr}
nextTurtle t (Bgcolor clr) = (reset t){
draw = Just $ Fill clr, drawed = Fill clr : drawed t}
nextTurtle t (SetPendown pd) = (reset t){pendown = pd}
nextTurtle t (SetVisible v) = (reset t){visible = v}
nextTurtle t (SetFill fl) = (reset t){fill = fl, fillPoints = [position t | fl]}
`set` (if not (fill t) || fl then Nothing else
Just $ Polyline (fillPoints t) (fillcolor t) (pencolor t)
(pensize t))
nextTurtle t (SetPoly p) = (reset t){
poly = p, polyPoints = if p then [position t] else polyPoints t}
nextTurtle t (SetFlush ss) = (reset t){stepbystep = ss}
nextTurtle t (PositionStep ps) = (reset t){positionStep = ps}
nextTurtle t (DirectionStep ds) = (reset t){directionStep = ds}
nextTurtle t (Degrees ds) = (reset t){degrees = ds}
nextTurtle _ _ = error "not defined"