src/Model/Layer/Layers.elm (181 lines of code) (raw):

module Model.Layer.Layers exposing (..) import Random import Model.Layer.Def exposing (DefId, Index(..), Kind, makeIndex, getIndex, Opacity(..)) import Model.Layer.Layer exposing (..) import Model.Layer.Layer as Layer exposing (Msg) import Model.Layer.Export exposing (encodeKind) import Model.Layer.Context exposing (Context) import Model.Layer.Broadcast as Broadcast exposing (Msg) type alias Layers = List Layer type alias Initial = List { visibility: Visibility , blend: Blend , fromDef: DefId } init : (Index -> Layer.Msg -> msg) -> Context -> Initial -> ( Layers, Cmd msg ) -- TODO: Result (List String) init mapMsg ctx initial = initial |> List.indexedMap Tuple.pair |> List.map (Tuple.mapFirst makeIndex) |> List.map (\( index, { visibility, blend, fromDef } ) -> registry.byId fromDef |> Maybe.map (\def -> def.init index ctx) |> Maybe.map (\( model, cmd ) -> ( layer index (ZOrder <| getIndex index) visibility blend model, cmd )) ) |> List.filterMap identity -- filter out those layers that weren't found in the registry |> List.foldr -- we shouldn't lose any layers here since we just add them back (\( layer, cmd ) ( prevLayers, prevCmds ) -> let (Layer { index } _) = layer in ( layer :: prevLayers , Cmd.map (mapMsg <| makeIndex index) cmd :: prevCmds ) ) ( [], [] ) |> Tuple.mapSecond Cmd.batch update : (Index -> Layer.Msg -> msg) -> Context -> Index -> Layer.Msg -> Layers -> ( Layers, Cmd msg ) update mapMsg ctx layerToUpdate msg = updateMap mapMsg (\((Layer { index } model) as layer) -> if index == getIndex layerToUpdate then registry.byModel model |> Maybe.map (\def -> def.update (makeIndex index) ctx msg model) |> Maybe.map (\( newModel, cmd ) -> ( layer |> replaceModel newModel, cmd )) |> Maybe.withDefault ( layer, Cmd.none ) else ( layer, Cmd.none ) ) broadcast : (Index -> Layer.Msg -> msg) -> Context -> Index -> Broadcast.Msg -> Layers -> ( Layers, Cmd msg ) broadcast mapMsg ctx layerToBroadcastTo broadcastMsg = updateMap mapMsg (\((Layer { index } model) as layer) -> if index == getIndex layerToBroadcastTo then registry.byModel model |> Maybe.map (\def -> def.absorb (makeIndex index) ctx broadcastMsg model) |> Maybe.map (\( newModel, cmd ) -> ( layer |> replaceModel newModel, cmd )) |> Maybe.withDefault ( layer, Cmd.none ) else ( layer, Cmd.none ) ) broadcastAll : (Index -> Layer.Msg -> msg) -> Context -> Broadcast.Msg -> Layers -> ( Layers, Cmd msg ) broadcastAll mapMsg ctx broadcastMsg = updateMap mapMsg (\((Layer { index } model) as layer) -> registry.byModel model |> Maybe.map (\def -> def.absorb (makeIndex index) ctx broadcastMsg model) |> Maybe.map (\( newModel, cmd ) -> ( layer |> replaceModel newModel, cmd )) |> Maybe.withDefault ( layer, Cmd.none ) ) subscribe : (Index -> Layer.Msg -> msg) -> Context -> Layers -> Sub msg subscribe mapMsg ctx layers = layers |> List.map (\(Layer _ model) -> registry.byModel model |> Maybe.map (\def -> def.subscribe ctx model) ) |> List.filterMap identity |> List.map (Sub.map (\( msgIndex, msg ) -> mapMsg msgIndex msg)) |> Sub.batch modify : (Layer -> Layer) -> Index -> Layers -> Layers modify f indexToChange = List.map (\((Layer { index } _) as layer) -> if index == getIndex indexToChange then f layer else layer ) render : Context -> Layers -> List ( Index, ZOrder, View ) render ctx layers = layers |> List.map (\(Layer { index, zOrder, blend, visibility, opacity } model) -> case visibility of Hidden -> Nothing _ -> registry.byModel model |> Maybe.map (\def -> def.view (makeIndex index) ctx ( Just blend, Opacity opacity ) model) |> Maybe.map (\view -> ( makeIndex index, ZOrder zOrder, view )) ) |> List.filterMap identity updateMap -- do not expose : (Index -> Layer.Msg -> msg) -> (Layer -> ( Layer, Cmd Layer.Msg )) -> Layers -> ( Layers, Cmd msg ) updateMap mapMsg mapF layers = layers |> List.map mapF |> List.foldr -- we shouldn't lose any layers here since we just add them back (\( layer, cmd ) ( prevLayers, prevCmds ) -> let (Layer { index } _) = layer in ( layer :: prevLayers , Cmd.map (mapMsg <| makeIndex index) cmd :: prevCmds ) ) ( [], [] ) |> Tuple.mapSecond Cmd.batch collectStats : Layers -> List { index : Int , def : DefId , kind : Kind , visibility : Visibility } collectStats layers = layers |> List.map (\(Layer { index, visibility } model) -> registry.byModel model |> Maybe.map (\def -> { index = index , def = def.id , kind = def.kind , visibility = visibility } ) ) |> List.filterMap identity randomizeStats : Layers -> List ( Index, Random.Generator ( Blend, Opacity ) ) randomizeStats forLayers = List.map (\(Layer { index, blend } _) -> ( makeIndex index, Layer.randomStats blend ) ) forLayers