{-# LANGUAGE BlockArguments #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeApplications #-} module MetaBrush.Document ( AABB(..) , Document(..), emptyDocument , Stroke(..), Guide(..) , PointData(..), BrushPointData(..) , FocusState(..) , _selection, _brush ) where -- base import GHC.Generics ( Generic ) -- containers import Data.Map.Strict ( Map ) import qualified Data.Map.Strict as Map ( empty ) import Data.Sequence ( Seq ) -- generic-lens import Data.Generics.Product.Fields ( field' ) import Data.Generics.Product.Typed ( HasType(typed) ) -- lens import Control.Lens ( Lens' ) -- text import Data.Text ( Text ) -- MetaBrush import Math.Bezier.Stroke ( StrokePoint(..) ) import Math.Vector2D ( Point2D(..), Vector2D(..) ) import MetaBrush.Unique ( Unique ) -------------------------------------------------------------------------------- data AABB = AABB { topLeft, botRight :: !( Point2D Double ) } deriving stock Show data Document = Document { displayName :: !Text , mbFilePath :: !( Maybe FilePath ) , unsavedChanges :: !Bool , viewportCenter :: !( Point2D Double ) , zoomFactor :: !Double , documentUnique :: Unique , strokes :: ![ Stroke ] , guides :: !( Map Unique Guide ) } deriving stock ( Show, Generic ) data Stroke = Stroke { strokeName :: Text , strokeVisible :: !Bool , strokeUnique :: Unique , strokePoints :: !( Seq ( StrokePoint PointData ) ) } deriving stock ( Show, Generic ) data Guide = Guide { guidePoint :: !( Point2D Double ) -- ^ point on the guide line , guideNormal :: !( Vector2D Double ) -- ^ /normalised/ normal vector of the guide , guideUnique :: Unique } deriving stock ( Show, Generic ) data PointData = PointData { pointState :: FocusState , brushShape :: Seq ( StrokePoint BrushPointData ) } deriving stock ( Show, Generic ) data BrushPointData = BrushPointData { brushPointState :: FocusState } deriving stock ( Show, Generic ) data FocusState = Normal | Hover | Selected deriving stock ( Show, Eq ) _selection :: HasType FocusState pt => Lens' ( StrokePoint pt ) FocusState _selection = field' @"pointData" . typed @FocusState _brush :: Lens' ( StrokePoint PointData ) ( Seq ( StrokePoint BrushPointData ) ) _brush = field' @"pointData" . field' @"brushShape" emptyDocument :: Text -> Unique -> Document emptyDocument docName unique = Document { displayName = docName , mbFilePath = Nothing , unsavedChanges = False , viewportCenter = Point2D 0 0 , zoomFactor = 1 , documentUnique = unique , strokes = [] , guides = Map.empty }