{-# LANGUAGE RecordWildCards #-}

module Potato.Flow.Render (
  RenderCache(..)
  , RenderContext(..)
  , emptyRenderContext
  , emptyRenderCache
  , renderCache_clearAtKeys
  , renderCache_lookup
  , render -- TODO DELETE use render_new instead because it uses cache
  , render_new

  , RenderedCanvasRegion(..)
  , renderedCanvas_box
  , renderedCanvasRegion_nonEmptyCount
  , emptyRenderedCanvasRegion
  , printRenderedCanvasRegion
  , potatoRenderWithOwlTree
  , potatoRenderPFState
  , renderedCanvasToText
  , renderedCanvasRegionToText

  , renderWithBroadPhase
  , moveRenderedCanvasRegion
  , updateCanvas

  -- exposed for testing
  , moveRenderedCanvasRegionNoReRender
) where

import           Relude

import           Potato.Flow.RenderCache
import           Potato.Flow.BroadPhase
import           Potato.Flow.Math
import           Potato.Flow.Methods.SEltMethods
import           Potato.Flow.Methods.Types
import           Potato.Flow.Serialization.Snake
import Potato.Flow.Types
import Potato.Flow.OwlState
import           Potato.Flow.OwlItem
import Potato.Flow.Owl
import           Potato.Flow.Controller.Types
import           Potato.Flow.Controller.OwlLayers
import           Potato.Flow.Methods.LineTypes


import qualified Data.IntMap             as IM
import qualified Data.Text               as T
import qualified Data.Text.IO as T
import qualified Data.Vector.Unboxed     as V
import qualified Data.Sequence as Seq
import Control.Exception (assert)

-- rather pointless abstraction but it's useful to have during refactors such that I don't ned to provide an explicit LayerMetaMap
class OwlRenderSet a where
  findSuperOwl :: a -> REltId -> Maybe (SuperOwl, Bool)
  sortForRendering :: a -> Seq.Seq SuperOwl -> Seq.Seq SuperOwl
  findSuperOwlForRendering :: a -> REltId -> Maybe SuperOwl
  findSuperOwlForRendering a
ors Int
rid = case a -> Int -> Maybe (SuperOwl, Bool)
forall a. OwlRenderSet a => a -> Int -> Maybe (SuperOwl, Bool)
findSuperOwl a
ors Int
rid of
    Maybe (SuperOwl, Bool)
Nothing -> Maybe SuperOwl
forall a. Maybe a
Nothing
    Just (SuperOwl
sowl, Bool
b) -> if Bool
b then Maybe SuperOwl
forall a. Maybe a
Nothing else SuperOwl -> Maybe SuperOwl
forall a. a -> Maybe a
Just SuperOwl
sowl

instance OwlRenderSet OwlTree where
  findSuperOwl :: OwlTree -> Int -> Maybe (SuperOwl, Bool)
findSuperOwl OwlTree
ot = (SuperOwl -> (SuperOwl, Bool))
-> Maybe SuperOwl -> Maybe (SuperOwl, Bool)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (,Bool
False) (Maybe SuperOwl -> Maybe (SuperOwl, Bool))
-> (Int -> Maybe SuperOwl) -> Int -> Maybe (SuperOwl, Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OwlTree -> Int -> Maybe SuperOwl
owlTree_findSuperOwl OwlTree
ot
  sortForRendering :: OwlTree -> Seq SuperOwl -> Seq SuperOwl
sortForRendering OwlTree
a Seq SuperOwl
sowls = SuperOwlParliament -> Seq SuperOwl
unSuperOwlParliament (SuperOwlParliament -> Seq SuperOwl)
-> SuperOwlParliament -> Seq SuperOwl
forall a b. (a -> b) -> a -> b
$ OwlTree -> Seq SuperOwl -> SuperOwlParliament
makeSortedSuperOwlParliament OwlTree
a Seq SuperOwl
sowls

instance OwlRenderSet (OwlTree, LayerMetaMap) where
  findSuperOwl :: (OwlTree, LayerMetaMap) -> Int -> Maybe (SuperOwl, Bool)
findSuperOwl (OwlTree
ot,LayerMetaMap
lmm) Int
rid = Maybe (SuperOwl, Bool)
r where
    hidden :: Bool
hidden = OwlTree -> Int -> LayerMetaMap -> Bool
layerMetaMap_isInheritHidden OwlTree
ot Int
rid LayerMetaMap
lmm
    r :: Maybe (SuperOwl, Bool)
r = (SuperOwl -> (SuperOwl, Bool))
-> Maybe SuperOwl -> Maybe (SuperOwl, Bool)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (,Bool
hidden) (Maybe SuperOwl -> Maybe (SuperOwl, Bool))
-> Maybe SuperOwl -> Maybe (SuperOwl, Bool)
forall a b. (a -> b) -> a -> b
$ OwlTree -> Int -> Maybe SuperOwl
owlTree_findSuperOwl OwlTree
ot Int
rid
  sortForRendering :: (OwlTree, LayerMetaMap) -> Seq SuperOwl -> Seq SuperOwl
sortForRendering (OwlTree
ot,LayerMetaMap
_) Seq SuperOwl
sowls = OwlTree -> Seq SuperOwl -> Seq SuperOwl
forall a. OwlRenderSet a => a -> Seq SuperOwl -> Seq SuperOwl
sortForRendering OwlTree
ot Seq SuperOwl
sowls

-- RenderContext is a helper container type that provides both read and write data for various render operations
data RenderContext = RenderContext {
  RenderContext -> RenderCache
_renderContext_cache :: RenderCache -- r/w
  , RenderContext -> OwlTree
_renderContext_owlTree :: OwlTree -- r
  , RenderContext -> LayerMetaMap
_renderContext_layerMetaMap :: LayerMetaMap -- r
  , RenderContext -> BroadPhaseState
_renderContext_broadPhase :: BroadPhaseState -- r
  , RenderContext -> RenderedCanvasRegion
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion -- r/w
}

emptyRenderContext :: LBox -> RenderContext
emptyRenderContext :: LBox -> RenderContext
emptyRenderContext LBox
lbox = RenderContext {
    _renderContext_cache :: RenderCache
_renderContext_cache = RenderCache
emptyRenderCache
    , _renderContext_owlTree :: OwlTree
_renderContext_owlTree = OwlTree
emptyOwlTree
    , _renderContext_layerMetaMap :: LayerMetaMap
_renderContext_layerMetaMap = LayerMetaMap
forall a. IntMap a
IM.empty
    , _renderContext_broadPhase :: BroadPhaseState
_renderContext_broadPhase = BroadPhaseState
emptyBroadPhaseState
    , _renderContext_renderedCanvasRegion :: RenderedCanvasRegion
_renderContext_renderedCanvasRegion = LBox -> RenderedCanvasRegion
emptyRenderedCanvasRegion LBox
lbox
  }


instance HasOwlTree RenderContext where
  hasOwlTree_owlTree :: RenderContext -> OwlTree
hasOwlTree_owlTree = OwlTree -> OwlTree
forall o. HasOwlTree o => o -> OwlTree
hasOwlTree_owlTree (OwlTree -> OwlTree)
-> (RenderContext -> OwlTree) -> RenderContext -> OwlTree
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RenderContext -> OwlTree
_renderContext_owlTree

instance OwlRenderSet RenderContext where
  findSuperOwl :: RenderContext -> Int -> Maybe (SuperOwl, Bool)
findSuperOwl RenderContext {LayerMetaMap
OwlTree
RenderCache
BroadPhaseState
RenderedCanvasRegion
_renderContext_cache :: RenderContext -> RenderCache
_renderContext_owlTree :: RenderContext -> OwlTree
_renderContext_layerMetaMap :: RenderContext -> LayerMetaMap
_renderContext_broadPhase :: RenderContext -> BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderContext -> RenderedCanvasRegion
_renderContext_cache :: RenderCache
_renderContext_owlTree :: OwlTree
_renderContext_layerMetaMap :: LayerMetaMap
_renderContext_broadPhase :: BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion
..} Int
rid = (OwlTree, LayerMetaMap) -> Int -> Maybe (SuperOwl, Bool)
forall a. OwlRenderSet a => a -> Int -> Maybe (SuperOwl, Bool)
findSuperOwl (OwlTree
_renderContext_owlTree, LayerMetaMap
_renderContext_layerMetaMap) Int
rid
  sortForRendering :: RenderContext -> Seq SuperOwl -> Seq SuperOwl
sortForRendering RenderContext {LayerMetaMap
OwlTree
RenderCache
BroadPhaseState
RenderedCanvasRegion
_renderContext_cache :: RenderContext -> RenderCache
_renderContext_owlTree :: RenderContext -> OwlTree
_renderContext_layerMetaMap :: RenderContext -> LayerMetaMap
_renderContext_broadPhase :: RenderContext -> BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderContext -> RenderedCanvasRegion
_renderContext_cache :: RenderCache
_renderContext_owlTree :: OwlTree
_renderContext_layerMetaMap :: LayerMetaMap
_renderContext_broadPhase :: BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion
..} Seq SuperOwl
sowls = (OwlTree, LayerMetaMap) -> Seq SuperOwl -> Seq SuperOwl
forall a. OwlRenderSet a => a -> Seq SuperOwl -> Seq SuperOwl
sortForRendering (OwlTree
_renderContext_owlTree, LayerMetaMap
_renderContext_layerMetaMap) Seq SuperOwl
sowls



emptyChar :: PChar
emptyChar :: Char
emptyChar = Char
' '


-- TODO for selection rendering you want to make it V.Vector (Maybe PChar) or maybe you can just use a map?
{-
class IsRenderedCanvasRegion rc where
  isRenderedCanvasRegion_area :: LBox
  isRenderedCanvasRegion_generateMaybe :: (Int, Int) -> ((Int, Int) -> Maybe PChar) -> rc
-}

-- A rendered region in Canvas space
data RenderedCanvasRegion = RenderedCanvasRegion {
  RenderedCanvasRegion -> LBox
_renderedCanvasRegion_box        :: LBox
  , RenderedCanvasRegion -> Vector MWidePChar
_renderedCanvasRegion_contents :: V.Vector MWidePChar -- ^ row major
} deriving (RenderedCanvasRegion -> RenderedCanvasRegion -> Bool
(RenderedCanvasRegion -> RenderedCanvasRegion -> Bool)
-> (RenderedCanvasRegion -> RenderedCanvasRegion -> Bool)
-> Eq RenderedCanvasRegion
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RenderedCanvasRegion -> RenderedCanvasRegion -> Bool
== :: RenderedCanvasRegion -> RenderedCanvasRegion -> Bool
$c/= :: RenderedCanvasRegion -> RenderedCanvasRegion -> Bool
/= :: RenderedCanvasRegion -> RenderedCanvasRegion -> Bool
Eq, Int -> RenderedCanvasRegion -> ShowS
[RenderedCanvasRegion] -> ShowS
RenderedCanvasRegion -> String
(Int -> RenderedCanvasRegion -> ShowS)
-> (RenderedCanvasRegion -> String)
-> ([RenderedCanvasRegion] -> ShowS)
-> Show RenderedCanvasRegion
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RenderedCanvasRegion -> ShowS
showsPrec :: Int -> RenderedCanvasRegion -> ShowS
$cshow :: RenderedCanvasRegion -> String
show :: RenderedCanvasRegion -> String
$cshowList :: [RenderedCanvasRegion] -> ShowS
showList :: [RenderedCanvasRegion] -> ShowS
Show)

renderedCanvas_box :: RenderedCanvasRegion -> LBox
renderedCanvas_box :: RenderedCanvasRegion -> LBox
renderedCanvas_box = RenderedCanvasRegion -> LBox
_renderedCanvasRegion_box

emptyRenderedCanvasRegion :: LBox -> RenderedCanvasRegion
emptyRenderedCanvasRegion :: LBox -> RenderedCanvasRegion
emptyRenderedCanvasRegion lb :: LBox
lb@(LBox XY
_ (V2 Int
w Int
h)) = RenderedCanvasRegion {
    _renderedCanvasRegion_box :: LBox
_renderedCanvasRegion_box = LBox
lb
    , _renderedCanvasRegion_contents :: Vector MWidePChar
_renderedCanvasRegion_contents = Int -> MWidePChar -> Vector MWidePChar
forall a. Unbox a => Int -> a -> Vector a
V.replicate (Int
wInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
h) MWidePChar
emptyMWidePChar
  }

-- empty spaces due to wide chars to the left are not counted
renderedCanvasRegion_nonEmptyCount :: RenderedCanvasRegion -> Int
renderedCanvasRegion_nonEmptyCount :: RenderedCanvasRegion -> Int
renderedCanvasRegion_nonEmptyCount = Vector MWidePChar -> Int
forall a. Unbox a => Vector a -> Int
V.length (Vector MWidePChar -> Int)
-> (RenderedCanvasRegion -> Vector MWidePChar)
-> RenderedCanvasRegion
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MWidePChar -> Bool) -> Vector MWidePChar -> Vector MWidePChar
forall a. Unbox a => (a -> Bool) -> Vector a -> Vector a
V.filter (\MWidePChar
x -> MWidePChar
x MWidePChar -> MWidePChar -> Bool
forall a. Eq a => a -> a -> Bool
/= MWidePChar
emptyMWidePChar) (Vector MWidePChar -> Vector MWidePChar)
-> (RenderedCanvasRegion -> Vector MWidePChar)
-> RenderedCanvasRegion
-> Vector MWidePChar
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RenderedCanvasRegion -> Vector MWidePChar
_renderedCanvasRegion_contents

-- | brute force renders a RenderedCanvasRegion (ignores broadphase)
potatoRenderWithOwlTree :: OwlTree -> [OwlSubItem] -> RenderedCanvasRegion -> RenderedCanvasRegion
potatoRenderWithOwlTree :: OwlTree
-> [OwlSubItem] -> RenderedCanvasRegion -> RenderedCanvasRegion
potatoRenderWithOwlTree OwlTree
ot [OwlSubItem]
osubitems RenderedCanvasRegion
prevrcr = RenderedCanvasRegion
r where
  drawerswithcache :: [(SEltDrawer, Maybe OwlItemCache)]
drawerswithcache = (OwlSubItem -> (SEltDrawer, Maybe OwlItemCache))
-> [OwlSubItem] -> [(SEltDrawer, Maybe OwlItemCache)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\OwlSubItem
osubitem -> (OwlSubItem -> Maybe OwlItemCache -> SEltDrawer
getDrawerWithCache OwlSubItem
osubitem Maybe OwlItemCache
forall a. Maybe a
Nothing, Maybe OwlItemCache
forall a. Maybe a
Nothing)) [OwlSubItem]
osubitems 
  llbx :: LBox
llbx = RenderedCanvasRegion -> LBox
_renderedCanvasRegion_box RenderedCanvasRegion
prevrcr
  r :: RenderedCanvasRegion
r = OwlTree
-> LBox
-> [(SEltDrawer, Maybe OwlItemCache)]
-> RenderedCanvasRegion
-> RenderedCanvasRegion
forall a.
HasOwlTree a =>
a
-> LBox
-> [(SEltDrawer, Maybe OwlItemCache)]
-> RenderedCanvasRegion
-> RenderedCanvasRegion
render_withCache OwlTree
ot LBox
llbx [(SEltDrawer, Maybe OwlItemCache)]
drawerswithcache RenderedCanvasRegion
prevrcr

potatoRenderPFState :: OwlPFState -> RenderedCanvasRegion
potatoRenderPFState :: OwlPFState -> RenderedCanvasRegion
potatoRenderPFState OwlPFState {SCanvas
OwlTree
_owlPFState_owlTree :: OwlTree
_owlPFState_canvas :: SCanvas
_owlPFState_owlTree :: OwlPFState -> OwlTree
_owlPFState_canvas :: OwlPFState -> SCanvas
..} = OwlTree
-> [OwlSubItem] -> RenderedCanvasRegion -> RenderedCanvasRegion
potatoRenderWithOwlTree OwlTree
_owlPFState_owlTree ((OwlItem -> OwlSubItem) -> [OwlItem] -> [OwlSubItem]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap OwlItem -> OwlSubItem
_owlItem_subItem ([OwlItem] -> [OwlSubItem])
-> (OwlTree -> [OwlItem]) -> OwlTree -> [OwlSubItem]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((OwlItemMeta, OwlItem) -> OwlItem)
-> [(OwlItemMeta, OwlItem)] -> [OwlItem]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (OwlItemMeta, OwlItem) -> OwlItem
forall a b. (a, b) -> b
snd ([(OwlItemMeta, OwlItem)] -> [OwlItem])
-> (OwlTree -> [(OwlItemMeta, OwlItem)]) -> OwlTree -> [OwlItem]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IntMap (OwlItemMeta, OwlItem) -> [(OwlItemMeta, OwlItem)]
forall a. IntMap a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (IntMap (OwlItemMeta, OwlItem) -> [(OwlItemMeta, OwlItem)])
-> (OwlTree -> IntMap (OwlItemMeta, OwlItem))
-> OwlTree
-> [(OwlItemMeta, OwlItem)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OwlTree -> IntMap (OwlItemMeta, OwlItem)
_owlTree_mapping (OwlTree -> [OwlSubItem]) -> OwlTree -> [OwlSubItem]
forall a b. (a -> b) -> a -> b
$ OwlTree
_owlPFState_owlTree) (LBox -> RenderedCanvasRegion
emptyRenderedCanvasRegion (SCanvas -> LBox
_sCanvas_box SCanvas
_owlPFState_canvas))


render_withCache :: (HasOwlTree a) => a -> LBox -> [(SEltDrawer, Maybe OwlItemCache)] -> RenderedCanvasRegion -> RenderedCanvasRegion
render_withCache :: forall a.
HasOwlTree a =>
a
-> LBox
-> [(SEltDrawer, Maybe OwlItemCache)]
-> RenderedCanvasRegion
-> RenderedCanvasRegion
render_withCache a
ot LBox
llbx [(SEltDrawer, Maybe OwlItemCache)]
drawerswithcache RenderedCanvasRegion
prevrcr = RenderedCanvasRegion
r where

  genfn :: Int -> (Int, MWidePChar)
genfn Int
i = (Int, MWidePChar)
newc' where
    -- construct parent point and index
    pt :: XY
pt = LBox -> Int -> XY
toPoint LBox
llbx Int
i
    pindex :: Int
pindex = LBox -> XY -> Int
toIndex (RenderedCanvasRegion -> LBox
_renderedCanvasRegion_box RenderedCanvasRegion
prevrcr) XY
pt

    -- go through drawers in reverse order until you find a match
    --mdrawn = join . find isJust $ (fmap (\d -> _sEltDrawer_renderFn d _renderContext_owlTree pt) drawers)
    -- go through caches (they should have all been updated in the previous step) until you find a match
    drawfn :: (SEltDrawer, Maybe OwlItemCache) -> Maybe MWidePChar
drawfn (SEltDrawer
drawer, Maybe OwlItemCache
mcache) = case Maybe OwlItemCache
mcache of
      Maybe OwlItemCache
Nothing -> Maybe MWidePChar
drawnocache
      --Just _ -> drawnocache
      Just OwlItemCache
cache -> case OwlItemCache -> Maybe PreRender
owlItemCache_preRender OwlItemCache
cache of
        Maybe PreRender
Nothing -> Maybe MWidePChar
drawnocache
        Just PreRender
pr -> case (?callStack::CallStack) => PreRender -> XY -> MWidePChar
PreRender -> XY -> MWidePChar
preRender_lookup PreRender
pr XY
pt of
          (-1, Char
_) -> Maybe MWidePChar
forall a. Maybe a
Nothing
          MWidePChar
x       -> MWidePChar -> Maybe MWidePChar
forall a. a -> Maybe a
Just MWidePChar
x
      where
        drawnocache :: Maybe MWidePChar
drawnocache = case SEltDrawer -> SEltDrawerRenderFn
_sEltDrawer_renderFn SEltDrawer
drawer a
ot XY
pt of
          Maybe Char
Nothing -> Maybe MWidePChar
forall a. Maybe a
Nothing
          Just Char
x  -> MWidePChar -> Maybe MWidePChar
forall a. a -> Maybe a
Just (Int8
0, Char
x)
    mdrawn :: Maybe MWidePChar
mdrawn = Maybe (Maybe MWidePChar) -> Maybe MWidePChar
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe MWidePChar) -> Maybe MWidePChar)
-> ([Maybe MWidePChar] -> Maybe (Maybe MWidePChar))
-> [Maybe MWidePChar]
-> Maybe MWidePChar
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe MWidePChar -> Bool)
-> [Maybe MWidePChar] -> Maybe (Maybe MWidePChar)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find Maybe MWidePChar -> Bool
forall a. Maybe a -> Bool
isJust ([Maybe MWidePChar] -> Maybe MWidePChar)
-> [Maybe MWidePChar] -> Maybe MWidePChar
forall a b. (a -> b) -> a -> b
$ ((SEltDrawer, Maybe OwlItemCache) -> Maybe MWidePChar)
-> [(SEltDrawer, Maybe OwlItemCache)] -> [Maybe MWidePChar]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (SEltDrawer, Maybe OwlItemCache) -> Maybe MWidePChar
drawfn [(SEltDrawer, Maybe OwlItemCache)]
drawerswithcache

    -- render what we found or empty otherwise
    newc' :: (Int, MWidePChar)
newc' = case Maybe MWidePChar
mdrawn of
      Just MWidePChar
c  -> (Int
pindex, MWidePChar
c)
      Maybe MWidePChar
Nothing -> (Int
pindex, MWidePChar
emptyMWidePChar)

  -- go through each point in target LBox and render it
  newc :: Vector (Int, MWidePChar)
newc = Int -> (Int -> (Int, MWidePChar)) -> Vector (Int, MWidePChar)
forall a. Unbox a => Int -> (Int -> a) -> Vector a
V.generate (LBox -> Int
lBox_area LBox
llbx) Int -> (Int, MWidePChar)
genfn
  r :: RenderedCanvasRegion
r = RenderedCanvasRegion
prevrcr {
      _renderedCanvasRegion_contents = V.update (_renderedCanvasRegion_contents prevrcr) newc
    }


-- TODO DELETE use render_new instead
-- | renders just a portion of the RenderedCanvasRegion
-- caller is expected to provide all SElts that intersect the rendered LBox (broadphase is ignored)
-- SElts are rendered in ORDER
render :: LBox -> [OwlSubItem] -> RenderContext -> RenderContext
render :: LBox -> [OwlSubItem] -> RenderContext -> RenderContext
render LBox
llbx [OwlSubItem]
osubitems rctx :: RenderContext
rctx@RenderContext {LayerMetaMap
OwlTree
RenderCache
BroadPhaseState
RenderedCanvasRegion
_renderContext_cache :: RenderContext -> RenderCache
_renderContext_owlTree :: RenderContext -> OwlTree
_renderContext_layerMetaMap :: RenderContext -> LayerMetaMap
_renderContext_broadPhase :: RenderContext -> BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderContext -> RenderedCanvasRegion
_renderContext_cache :: RenderCache
_renderContext_owlTree :: OwlTree
_renderContext_layerMetaMap :: LayerMetaMap
_renderContext_broadPhase :: BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion
..} = RenderContext
r where
  drawerswithcache :: [(SEltDrawer, Maybe OwlItemCache)]
drawerswithcache = (OwlSubItem -> (SEltDrawer, Maybe OwlItemCache))
-> [OwlSubItem] -> [(SEltDrawer, Maybe OwlItemCache)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\OwlSubItem
osubitem -> (OwlSubItem -> Maybe OwlItemCache -> SEltDrawer
getDrawerWithCache OwlSubItem
osubitem Maybe OwlItemCache
forall a. Maybe a
Nothing, Maybe OwlItemCache
forall a. Maybe a
Nothing)) [OwlSubItem]
osubitems 
  prevrcr :: RenderedCanvasRegion
prevrcr = RenderedCanvasRegion
_renderContext_renderedCanvasRegion
  r :: RenderContext
r = RenderContext
rctx {
      _renderContext_renderedCanvasRegion = render_withCache _renderContext_owlTree llbx drawerswithcache prevrcr
    }

mapREltIdToCaches :: OwlTree -> [REltId] -> RenderCache -> (RenderCache, [(OwlSubItem, Maybe OwlItemCache)])
mapREltIdToCaches :: OwlTree
-> [Int]
-> RenderCache
-> (RenderCache, [(OwlSubItem, Maybe OwlItemCache)])
mapREltIdToCaches OwlTree
ot [Int]
rids RenderCache
rcache = (RenderCache, [(OwlSubItem, Maybe OwlItemCache)])
r1 where

  mapaccumlfn :: IntMap OwlItemCache
-> Int -> (IntMap OwlItemCache, (OwlSubItem, Maybe OwlItemCache))
mapaccumlfn IntMap OwlItemCache
cacheacc Int
rid = (IntMap OwlItemCache, (OwlSubItem, Maybe OwlItemCache))
r2 where
    -- see if it was in the previous cache
    mprevcache :: Maybe OwlItemCache
mprevcache = Int -> IntMap OwlItemCache -> Maybe OwlItemCache
forall a. Int -> IntMap a -> Maybe a
IM.lookup Int
rid (RenderCache -> IntMap OwlItemCache
unRenderCache RenderCache
rcache)
    sowl :: SuperOwl
sowl = (?callStack::CallStack) => OwlTree -> Int -> SuperOwl
OwlTree -> Int -> SuperOwl
owlTree_mustFindSuperOwl OwlTree
ot Int
rid
    OwlItem OwlInfo
_ OwlSubItem
osubitem = SuperOwl -> OwlItem
_superOwl_elt SuperOwl
sowl
    mupdatedcache :: Maybe OwlItemCache
mupdatedcache = OwlTree -> OwlSubItem -> Maybe OwlItemCache
forall a. HasOwlTree a => a -> OwlSubItem -> Maybe OwlItemCache
updateOwlSubItemCache OwlTree
ot OwlSubItem
osubitem
    r2 :: (IntMap OwlItemCache, (OwlSubItem, Maybe OwlItemCache))
r2 = case Maybe OwlItemCache
mprevcache of
      Just OwlItemCache
c -> (IntMap OwlItemCache
cacheacc, (OwlSubItem
osubitem, OwlItemCache -> Maybe OwlItemCache
forall a. a -> Maybe a
Just OwlItemCache
c))
      Maybe OwlItemCache
Nothing -> case Maybe OwlItemCache
mupdatedcache of
        Just OwlItemCache
c  -> (Int -> OwlItemCache -> IntMap OwlItemCache -> IntMap OwlItemCache
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert Int
rid OwlItemCache
c IntMap OwlItemCache
cacheacc, (OwlSubItem
osubitem, OwlItemCache -> Maybe OwlItemCache
forall a. a -> Maybe a
Just OwlItemCache
c))
        Maybe OwlItemCache
Nothing -> (IntMap OwlItemCache
cacheacc, (OwlSubItem
osubitem, Maybe OwlItemCache
forall a. Maybe a
Nothing))
  (IntMap OwlItemCache
newcache, [(OwlSubItem, Maybe OwlItemCache)]
owlswithcache) = (IntMap OwlItemCache
 -> Int -> (IntMap OwlItemCache, (OwlSubItem, Maybe OwlItemCache)))
-> IntMap OwlItemCache
-> [Int]
-> (IntMap OwlItemCache, [(OwlSubItem, Maybe OwlItemCache)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL IntMap OwlItemCache
-> Int -> (IntMap OwlItemCache, (OwlSubItem, Maybe OwlItemCache))
mapaccumlfn (RenderCache -> IntMap OwlItemCache
unRenderCache RenderCache
rcache) [Int]
rids
  r1 :: (RenderCache, [(OwlSubItem, Maybe OwlItemCache)])
r1 = (IntMap OwlItemCache -> RenderCache
RenderCache IntMap OwlItemCache
newcache, [(OwlSubItem, Maybe OwlItemCache)]
owlswithcache)



-- | renders just a portion of the RenderedCanvasRegion
-- updates cache as appropriate
-- caller is expected to provide all REltIds that intersect the rendered LBox (broadphase is ignored)
-- REltIds are rendered in ORDER
render_new :: LBox -> [REltId] -> RenderContext -> RenderContext
render_new :: LBox -> [Int] -> RenderContext -> RenderContext
render_new LBox
llbx [Int]
rids rctx :: RenderContext
rctx@RenderContext {LayerMetaMap
OwlTree
RenderCache
BroadPhaseState
RenderedCanvasRegion
_renderContext_cache :: RenderContext -> RenderCache
_renderContext_owlTree :: RenderContext -> OwlTree
_renderContext_layerMetaMap :: RenderContext -> LayerMetaMap
_renderContext_broadPhase :: RenderContext -> BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderContext -> RenderedCanvasRegion
_renderContext_cache :: RenderCache
_renderContext_owlTree :: OwlTree
_renderContext_layerMetaMap :: LayerMetaMap
_renderContext_broadPhase :: BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion
..} = RenderContext
rctxout where
  (RenderCache
newcache, [(OwlSubItem, Maybe OwlItemCache)]
owlswithcache) = OwlTree
-> [Int]
-> RenderCache
-> (RenderCache, [(OwlSubItem, Maybe OwlItemCache)])
mapREltIdToCaches OwlTree
_renderContext_owlTree [Int]
rids RenderCache
_renderContext_cache
  drawerswithcache :: [(SEltDrawer, Maybe OwlItemCache)]
drawerswithcache = ((OwlSubItem, Maybe OwlItemCache)
 -> (SEltDrawer, Maybe OwlItemCache))
-> [(OwlSubItem, Maybe OwlItemCache)]
-> [(SEltDrawer, Maybe OwlItemCache)]
forall a b. (a -> b) -> [a] -> [b]
map (\(OwlSubItem
x, Maybe OwlItemCache
c)-> (OwlSubItem -> Maybe OwlItemCache -> SEltDrawer
getDrawerWithCache OwlSubItem
x Maybe OwlItemCache
c, Maybe OwlItemCache
c)) [(OwlSubItem, Maybe OwlItemCache)]
owlswithcache 
  rctxout :: RenderContext
rctxout = RenderContext
rctx {
      _renderContext_cache = newcache
      , _renderContext_renderedCanvasRegion = render_withCache _renderContext_owlTree llbx drawerswithcache _renderContext_renderedCanvasRegion
    }


renderedCanvasToText :: RenderedCanvasRegion -> Text
renderedCanvasToText :: RenderedCanvasRegion -> Text
renderedCanvasToText RenderedCanvasRegion
rcr = LBox -> RenderedCanvasRegion -> Text
renderedCanvasRegionToText (RenderedCanvasRegion -> LBox
_renderedCanvasRegion_box RenderedCanvasRegion
rcr) RenderedCanvasRegion
rcr


-- TODO this does not handle wide chars at all fack
-- | assumes region LBox is strictly contained in _renderedCanvasRegion_box
renderedCanvasRegionToText :: LBox -> RenderedCanvasRegion -> Text
renderedCanvasRegionToText :: LBox -> RenderedCanvasRegion -> Text
renderedCanvasRegionToText LBox
lbx RenderedCanvasRegion {Vector MWidePChar
LBox
_renderedCanvasRegion_box :: RenderedCanvasRegion -> LBox
_renderedCanvasRegion_contents :: RenderedCanvasRegion -> Vector MWidePChar
_renderedCanvasRegion_box :: LBox
_renderedCanvasRegion_contents :: Vector MWidePChar
..} = if Bool -> Bool
not Bool
validBoxes 
  then Text -> Text
forall a t. (?callStack::CallStack, IsText t) => t -> a
error (Text
"render region outside canvas:\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> LBox -> Text
forall b a. (Show a, IsString b) => a -> b
show LBox
lbx Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> LBox -> Text
forall b a. (Show a, IsString b) => a -> b
show LBox
_renderedCanvasRegion_box)
  else Text
r 
  where
    validBoxes :: Bool
validBoxes = LBox -> LBox -> Maybe LBox
intersect_lBox_include_zero_area LBox
lbx LBox
_renderedCanvasRegion_box Maybe LBox -> Maybe LBox -> Bool
forall a. Eq a => a -> a -> Bool
== LBox -> Maybe LBox
forall a. a -> Maybe a
Just LBox
lbx
    -- TODO preloop and include widechars

    l :: Int
l = LBox -> Int
lBox_area LBox
lbx
    (LBox XY
_ (V2 Int
lw Int
_)) = LBox
lbx
    unfoldfn :: (Int, Bool, Bool) -> Maybe (Maybe Char, (Int, Bool, Bool))
unfoldfn (Int
i, Bool
eol, Bool
waseol) = if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
l
      then Maybe (Maybe Char, (Int, Bool, Bool))
forall a. Maybe a
Nothing
      else if Bool
eol
        -- use -2 to indicate eol
        then (Maybe Char, (Int, Bool, Bool))
-> Maybe (Maybe Char, (Int, Bool, Bool))
forall a. a -> Maybe a
Just ((Maybe Char, (Int, Bool, Bool))
 -> Maybe (Maybe Char, (Int, Bool, Bool)))
-> (Maybe Char, (Int, Bool, Bool))
-> Maybe (Maybe Char, (Int, Bool, Bool))
forall a b. (a -> b) -> a -> b
$ (Maybe Char
eolchar, (Int
i, Bool
False, Bool
newwaseol))
        else (Maybe Char, (Int, Bool, Bool))
-> Maybe (Maybe Char, (Int, Bool, Bool))
forall a. a -> Maybe a
Just ((Maybe Char, (Int, Bool, Bool))
 -> Maybe (Maybe Char, (Int, Bool, Bool)))
-> (Maybe Char, (Int, Bool, Bool))
-> Maybe (Maybe Char, (Int, Bool, Bool))
forall a b. (a -> b) -> a -> b
$ (Maybe Char
regchar, (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1, Bool
neweol, Bool
newwaseol))
        where
          neweol :: Bool
neweol = (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
lw Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
          -- maintain waseol status if there is offset
          newwaseol :: Bool
newwaseol = Bool
eol Bool -> Bool -> Bool
|| (Bool
waseol Bool -> Bool -> Bool
&& Int8
ofs Int8 -> Int8 -> Bool
forall a. Ord a => a -> a -> Bool
> Int8
0)
          (Int8
ofs, Char
pch) = Vector MWidePChar
_renderedCanvasRegion_contents Vector MWidePChar -> Int -> MWidePChar
forall a. Unbox a => Vector a -> Int -> a
V.! Int
pindex
          eolchar :: Maybe Char
eolchar = Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'\n'
          regchar :: Maybe Char
regchar = if Bool
waseol Bool -> Bool -> Bool
&& Int8
ofs Int8 -> Int8 -> Bool
forall a. Ord a => a -> a -> Bool
> Int8
0
            -- TODO is this what we want? Will this overwrite the previous wide char? Also this should never happen as broadphase should have included the widechar at bol
            -- if we were at eol and there is offset then use ' ' padding character
            then Char -> Maybe Char
forall a. a -> Maybe a
Just Char
' '
            else if Int8
ofs Int8 -> Int8 -> Bool
forall a. Ord a => a -> a -> Bool
> Int8
0
              -- if there is offset, skip the character
              then Maybe Char
forall a. Maybe a
Nothing
              else Char -> Maybe Char
forall a. a -> Maybe a
Just Char
pch
          pt :: XY
pt = LBox -> Int -> XY
toPoint LBox
lbx Int
i
          pindex :: Int
pindex = LBox -> XY -> Int
toIndex LBox
_renderedCanvasRegion_box XY
pt
    
    -- TODO use something more efficient than a string
    r' :: [Maybe Char]
r' = ((Int, Bool, Bool) -> Maybe (Maybe Char, (Int, Bool, Bool)))
-> (Int, Bool, Bool) -> [Maybe Char]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (Int, Bool, Bool) -> Maybe (Maybe Char, (Int, Bool, Bool))
unfoldfn (Int
0, Bool
False, Bool
True)
    r :: Text
r = String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ (Maybe Char -> Maybe Char) -> [Maybe Char] -> String
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Maybe Char -> Maybe Char
forall a. a -> a
id [Maybe Char]
r' 
  

printRenderedCanvasRegion :: RenderedCanvasRegion -> IO ()
printRenderedCanvasRegion :: RenderedCanvasRegion -> IO ()
printRenderedCanvasRegion rc :: RenderedCanvasRegion
rc@RenderedCanvasRegion {Vector MWidePChar
LBox
_renderedCanvasRegion_box :: RenderedCanvasRegion -> LBox
_renderedCanvasRegion_contents :: RenderedCanvasRegion -> Vector MWidePChar
_renderedCanvasRegion_box :: LBox
_renderedCanvasRegion_contents :: Vector MWidePChar
..} = Text -> IO ()
T.putStrLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ LBox -> RenderedCanvasRegion -> Text
renderedCanvasRegionToText LBox
_renderedCanvasRegion_box RenderedCanvasRegion
rc

renderWithBroadPhase :: LBox -> RenderContext -> RenderContext
renderWithBroadPhase :: LBox -> RenderContext -> RenderContext
renderWithBroadPhase  LBox
lbx rctx :: RenderContext
rctx@RenderContext {LayerMetaMap
OwlTree
RenderCache
BroadPhaseState
RenderedCanvasRegion
_renderContext_cache :: RenderContext -> RenderCache
_renderContext_owlTree :: RenderContext -> OwlTree
_renderContext_layerMetaMap :: RenderContext -> LayerMetaMap
_renderContext_broadPhase :: RenderContext -> BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderContext -> RenderedCanvasRegion
_renderContext_cache :: RenderCache
_renderContext_owlTree :: OwlTree
_renderContext_layerMetaMap :: LayerMetaMap
_renderContext_broadPhase :: BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion
..} = RenderContext
r where
  bpt :: BPTree
bpt = (BroadPhaseState -> BPTree
_broadPhaseState_bPTree BroadPhaseState
_renderContext_broadPhase)
  rids :: [Int]
rids = LBox -> BPTree -> [Int]
broadPhase_cull LBox
lbx BPTree
bpt

  -- TODO I THINK THIS IS INCORRECT DELETE, specifically, broadPhase_cull will give hidden elements that we can't find with findSuperOwlForRendering
  {-sowls' = flip fmap rids $ \rid -> case findSuperOwlForRendering ot rid of
      Nothing -> error "this should never happen, because broadPhase_cull should only give existing seltls"
      Just sowl -> sowl-}

  sowls' :: [SuperOwl]
sowls' = [Maybe SuperOwl] -> [SuperOwl]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe SuperOwl] -> [SuperOwl]) -> [Maybe SuperOwl] -> [SuperOwl]
forall a b. (a -> b) -> a -> b
$ (Int -> Maybe SuperOwl) -> [Int] -> [Maybe SuperOwl]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Int
rid -> OwlTree -> Int -> Maybe SuperOwl
forall a. OwlRenderSet a => a -> Int -> Maybe SuperOwl
findSuperOwlForRendering OwlTree
_renderContext_owlTree Int
rid) [Int]
rids

  sowls :: Seq SuperOwl
sowls = OwlTree -> Seq SuperOwl -> Seq SuperOwl
forall a. OwlRenderSet a => a -> Seq SuperOwl -> Seq SuperOwl
sortForRendering OwlTree
_renderContext_owlTree (Seq SuperOwl -> Seq SuperOwl) -> Seq SuperOwl -> Seq SuperOwl
forall a b. (a -> b) -> a -> b
$ [SuperOwl] -> Seq SuperOwl
forall a. [a] -> Seq a
Seq.fromList [SuperOwl]
sowls'
  sortedrids :: [Int]
sortedrids = (SuperOwl -> Int) -> [SuperOwl] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SuperOwl -> Int
_superOwl_id ([SuperOwl] -> [Int]) -> [SuperOwl] -> [Int]
forall a b. (a -> b) -> a -> b
$ Seq SuperOwl -> [SuperOwl]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq SuperOwl
sowls

  r :: RenderContext
r = LBox -> [Int] -> RenderContext -> RenderContext
render_new LBox
lbx [Int]
sortedrids RenderContext
rctx

moveRenderedCanvasRegionNoReRender :: LBox -> RenderedCanvasRegion -> RenderedCanvasRegion
moveRenderedCanvasRegionNoReRender :: LBox -> RenderedCanvasRegion -> RenderedCanvasRegion
moveRenderedCanvasRegionNoReRender LBox
lbx RenderedCanvasRegion {Vector MWidePChar
LBox
_renderedCanvasRegion_box :: RenderedCanvasRegion -> LBox
_renderedCanvasRegion_contents :: RenderedCanvasRegion -> Vector MWidePChar
_renderedCanvasRegion_box :: LBox
_renderedCanvasRegion_contents :: Vector MWidePChar
..} = Bool -> RenderedCanvasRegion -> RenderedCanvasRegion
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Int
area Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0) RenderedCanvasRegion
outrcr where
  -- unnecessary to init with empty vector as moveRenderedCanvasRegion will re-render those areas
  -- but it's still nice to do and makes testing easier
  area :: Int
area = LBox -> Int
lBox_area LBox
lbx
  emptyv :: Vector MWidePChar
emptyv = Int -> MWidePChar -> Vector MWidePChar
forall a. Unbox a => Int -> a -> Vector a
V.replicate Int
area MWidePChar
emptyMWidePChar
  newv :: Vector MWidePChar
newv = case LBox -> LBox -> Maybe LBox
intersect_lBox LBox
lbx LBox
_renderedCanvasRegion_box of
    Just LBox
intersectlbx -> Vector MWidePChar
copiedv where
      (Int
l,Int
r,Int
t,Int
b) = LBox -> (Int, Int, Int, Int)
lBox_to_axis LBox
intersectlbx
      -- [(newIndex, oldIndex)]
      indices' :: [Maybe (Int, Int)]
indices' = [LBox -> XY -> Maybe Int
toIndexSafe LBox
_renderedCanvasRegion_box (Int -> Int -> XY
forall a. a -> a -> V2 a
V2 Int
x Int
y) Maybe Int -> (Int -> Maybe (Int, Int)) -> Maybe (Int, Int)
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return ((Int, Int) -> Maybe (Int, Int))
-> (Int -> (Int, Int)) -> Int -> Maybe (Int, Int)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LBox -> XY -> Int
toIndex LBox
lbx (Int -> Int -> XY
forall a. a -> a -> V2 a
V2 Int
x Int
y),) | Int
x <- [Int
l..(Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)], Int
y <- [Int
t..(Int
bInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)]]
      indices :: [(Int, Int)]
indices = [Maybe (Int, Int)] -> [(Int, Int)]
forall a. [Maybe a] -> [a]
catMaybes [Maybe (Int, Int)]
indices'
      indexedValues :: [(Int, MWidePChar)]
indexedValues = ((Int, Int) -> (Int, MWidePChar))
-> [(Int, Int)] -> [(Int, MWidePChar)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Int
idx, Int
oldidx) -> (Int
idx, Vector MWidePChar
_renderedCanvasRegion_contents Vector MWidePChar -> Int -> MWidePChar
forall a. Unbox a => Vector a -> Int -> a
V.! Int
oldidx)) [(Int, Int)]
indices
      copiedv :: Vector MWidePChar
copiedv = Vector MWidePChar -> [(Int, MWidePChar)] -> Vector MWidePChar
forall a. Unbox a => Vector a -> [(Int, a)] -> Vector a
(V.//) Vector MWidePChar
emptyv [(Int, MWidePChar)]
indexedValues
    Maybe LBox
Nothing -> Vector MWidePChar
emptyv

  outrcr :: RenderedCanvasRegion
outrcr = RenderedCanvasRegion {
      _renderedCanvasRegion_box :: LBox
_renderedCanvasRegion_box = LBox
lbx
      , _renderedCanvasRegion_contents :: Vector MWidePChar
_renderedCanvasRegion_contents = Vector MWidePChar
newv
    }

moveRenderedCanvasRegion ::  LBox -> RenderContext -> RenderContext
moveRenderedCanvasRegion :: LBox -> RenderContext -> RenderContext
moveRenderedCanvasRegion LBox
lbx rctx :: RenderContext
rctx@RenderContext {LayerMetaMap
OwlTree
RenderCache
BroadPhaseState
RenderedCanvasRegion
_renderContext_cache :: RenderContext -> RenderCache
_renderContext_owlTree :: RenderContext -> OwlTree
_renderContext_layerMetaMap :: RenderContext -> LayerMetaMap
_renderContext_broadPhase :: RenderContext -> BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderContext -> RenderedCanvasRegion
_renderContext_cache :: RenderCache
_renderContext_owlTree :: OwlTree
_renderContext_layerMetaMap :: LayerMetaMap
_renderContext_broadPhase :: BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion
..} = RenderContext
r where
  prevrc :: RenderedCanvasRegion
prevrc = RenderedCanvasRegion
_renderContext_renderedCanvasRegion
  rctx1 :: RenderContext
rctx1 = RenderContext
rctx {
      _renderContext_renderedCanvasRegion = moveRenderedCanvasRegionNoReRender lbx prevrc
    }
  r :: RenderContext
r = (LBox -> RenderContext -> RenderContext)
-> RenderContext -> [LBox] -> RenderContext
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr LBox -> RenderContext -> RenderContext
renderWithBroadPhase RenderContext
rctx1 (LBox -> LBox -> [LBox]
substract_lBox LBox
lbx (RenderedCanvasRegion -> LBox
_renderedCanvasRegion_box RenderedCanvasRegion
prevrc))

updateCanvas :: SuperOwlChanges -> NeedsUpdateSet -> RenderContext -> RenderContext
updateCanvas :: SuperOwlChanges -> [LBox] -> RenderContext -> RenderContext
updateCanvas SuperOwlChanges
cslmap [LBox]
needsupdateaabbs rctx :: RenderContext
rctx@RenderContext {LayerMetaMap
OwlTree
RenderCache
BroadPhaseState
RenderedCanvasRegion
_renderContext_cache :: RenderContext -> RenderCache
_renderContext_owlTree :: RenderContext -> OwlTree
_renderContext_layerMetaMap :: RenderContext -> LayerMetaMap
_renderContext_broadPhase :: RenderContext -> BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderContext -> RenderedCanvasRegion
_renderContext_cache :: RenderCache
_renderContext_owlTree :: OwlTree
_renderContext_layerMetaMap :: LayerMetaMap
_renderContext_broadPhase :: BroadPhaseState
_renderContext_renderedCanvasRegion :: RenderedCanvasRegion
..} = case [LBox]
needsupdateaabbs of
  [] -> RenderContext
rctx
  -- TODO create disjoint union of all boxes and render than one at a time instead union_lBoxing them all
  --aoeu@(b:bs) -> trace "UPDATE CANVAS" $ traceShow aoeu $ case intersect_lBox (renderedCanvas_box _renderContext_renderedCanvasRegion) (foldl' union_lBox b bs) of
  (LBox
b:[LBox]
bs) -> case LBox -> LBox -> Maybe LBox
intersect_lBox (RenderedCanvasRegion -> LBox
renderedCanvas_box RenderedCanvasRegion
_renderContext_renderedCanvasRegion) ((LBox -> LBox -> LBox) -> LBox -> [LBox] -> LBox
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' LBox -> LBox -> LBox
union_lBox LBox
b [LBox]
bs) of
    Maybe LBox
Nothing -> RenderContext
rctx
    Just LBox
aabb -> RenderContext
r where
      rids :: [Int]
rids = LBox -> BPTree -> [Int]
broadPhase_cull LBox
aabb (BroadPhaseState -> BPTree
_broadPhaseState_bPTree BroadPhaseState
_renderContext_broadPhase)

      msowls :: [Maybe SuperOwl]
msowls = ((Int -> Maybe SuperOwl) -> [Int] -> [Maybe SuperOwl])
-> [Int] -> (Int -> Maybe SuperOwl) -> [Maybe SuperOwl]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Int -> Maybe SuperOwl) -> [Int] -> [Maybe SuperOwl]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Int]
rids ((Int -> Maybe SuperOwl) -> [Maybe SuperOwl])
-> (Int -> Maybe SuperOwl) -> [Maybe SuperOwl]
forall a b. (a -> b) -> a -> b
$ \Int
rid -> case Int -> SuperOwlChanges -> Maybe (Maybe SuperOwl)
forall a. Int -> IntMap a -> Maybe a
IM.lookup Int
rid SuperOwlChanges
cslmap of
        Maybe (Maybe SuperOwl)
Nothing -> case OwlTree -> Int -> Maybe (SuperOwl, Bool)
forall a. OwlRenderSet a => a -> Int -> Maybe (SuperOwl, Bool)
findSuperOwl OwlTree
_renderContext_owlTree Int
rid of
          Maybe (SuperOwl, Bool)
Nothing -> Text -> Maybe SuperOwl
forall a t. (?callStack::CallStack, IsText t) => t -> a
error Text
"this should never happen, because broadPhase_cull should only give existing seltls"
          -- changes could indicate hidden, if that's the case, give a dummy object to render
          Just (SuperOwl
sowl, Bool
hidden) -> if Bool
hidden then Maybe SuperOwl
forall a. Maybe a
Nothing else SuperOwl -> Maybe SuperOwl
forall a. a -> Maybe a
Just SuperOwl
sowl
        Just Maybe SuperOwl
msowl -> case Maybe SuperOwl
msowl of
          Maybe SuperOwl
Nothing -> Text -> Maybe SuperOwl
forall a t. (?callStack::CallStack, IsText t) => t -> a
error Text
"this should never happen, because deleted seltl would have been culled in broadPhase_cull"
          Just SuperOwl
sowl -> SuperOwl -> Maybe SuperOwl
forall a. a -> Maybe a
Just SuperOwl
sowl
      sowls :: Seq SuperOwl
sowls = OwlTree -> Seq SuperOwl -> Seq SuperOwl
forall a. OwlRenderSet a => a -> Seq SuperOwl -> Seq SuperOwl
sortForRendering OwlTree
_renderContext_owlTree (Seq SuperOwl -> Seq SuperOwl) -> Seq SuperOwl -> Seq SuperOwl
forall a b. (a -> b) -> a -> b
$ [SuperOwl] -> Seq SuperOwl
forall a. [a] -> Seq a
Seq.fromList ([Maybe SuperOwl] -> [SuperOwl]
forall a. [Maybe a] -> [a]
catMaybes [Maybe SuperOwl]
msowls)
      sortedrids :: [Int]
sortedrids = (SuperOwl -> Int) -> [SuperOwl] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SuperOwl -> Int
_superOwl_id ([SuperOwl] -> [Int]) -> [SuperOwl] -> [Int]
forall a b. (a -> b) -> a -> b
$ Seq SuperOwl -> [SuperOwl]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq SuperOwl
sowls
      r :: RenderContext
r = LBox -> [Int] -> RenderContext -> RenderContext
render_new LBox
aabb [Int]
sortedrids RenderContext
rctx