Skip to main content

Message Passing

Recall the update function in ConcreteGeneralModel.

update : env -> event -> data -> bdata -> ( ( data, bdata ), List (Msg tar msg sommsg), ( env, Bool ) )

However, layers generally do not need bdata, so Messenger provides a ConcreteLayer type that hides bdata (making it a ()):

type alias ConcreteLayer data cdata userdata tar msg scenemsg =
{ init : LayerInit cdata userdata msg data
, update : LayerUpdate cdata userdata tar msg scenemsg data
, updaterec : LayerUpdateRec cdata userdata tar msg scenemsg data
, view : LayerView cdata userdata data
, matcher : Matcher data tar
}

Here LayerUpdate is defined by:

type alias LayerUpdate cdata userdata tar msg scenemsg data =
Env cdata userdata -> WorldEvent -> data -> ( data, List (Msg tar msg (SceneOutputMsg scenemsg userdata)), ( Env cdata userdata, Bool ) )

LayerUpdateRec is defined by:

type alias LayerUpdateRec cdata userdata tar msg scenemsg data =
Env cdata userdata -> msg -> data -> ( data, List (Msg tar msg (SceneOutputMsg scenemsg userdata)), Env cdata userdata )

Users can provide the tar and msg type in Scenes/Home/SceneBase.elm.

Now let's consider implementing the example mentioned in Introduction. You can either start a new project or use the hello world project.

Create a scene with three layers:

messenger scene Recursion
messenger layer Recursion A
messenger layer Recursion B
messenger layer Recursion C

Add them to the scene (Scenes/Recursion/Model.elm):

import Scenes.Recursion.A.Model as A
import Scenes.Recursion.B.Model as B
import Scenes.Recursion.C.Model as C
...
, layers =
[ A.layer NullLayerMsg envcd
, B.layer NullLayerMsg envcd
, C.layer NullLayerMsg envcd
]

To send integers between layers, we need a IntMsg. So edit Scenes/Recursion/SceneBase.elm:

type LayerMsg
= IntMsg Int
| NullLayerMsg

For layer A, edit Scenes/Recursion/A/Model.elm:

updaterec env msg data =
case msg of
IntMsg x ->
if 0 <= x && x < 10 then
( data, [ Other ( "B", IntMsg (3 * x) ), Other ( "B", IntMsg (10 - 3 * x) ), Other ( "C", IntMsg x ) ], env )

else
( data, [], env )

_ ->
( data, [], env )

For layer B, edit Scenes/Recursion/B/Model.elm:

update env evt data =
if env.globalData.sceneStartFrame == 10 then
( data, [ Other ( "A", IntMsg 2 ) ], ( env, False ) )

else
( data, [], ( env, False ) )

and

updaterec env msg data =
case msg of
IntMsg x ->
( data, [ Other ( "A", IntMsg (x - 1) ) ], env )

_ ->
( data, [], env )

Finally, for layer C, edit Scenes/Recursion/C/Model.elm:

updaterec env msg data =
case msg of
IntMsg x ->
let
_ =
Debug.log "C received" x
in
( data, [], env )

_ ->
( data, [], env )

Now make and see the result!