Global Component
Although portable components and user components can be used to handle some logic, they are scene-specific, i.e. they cannot run across multiple scenes.
We need a way to run components inside the core that could manipulate core runtime data (like the running scene). Global components are a general model defined as:
type alias GCCommonData userdata scenemsg =
MAbstractScene userdata scenemsg
type alias GCBaseData =
{ dead : Bool
, postProcessor : Renderable -> Renderable
}
type alias GCMsg =
Json.Decode.Value
type alias GCTarget =
String
type alias ConcreteGlobalComponent data userdata scenemsg =
{ init : GlobalComponentInit userdata scenemsg data
, update : GlobalComponentUpdate userdata scenemsg data
, updaterec : GlobalComponentUpdateRec userdata scenemsg data
, view : GlobalComponentView userdata scenemsg data
, id : GCTarget
}
type alias AbstractGlobalComponent userdata scenemsg =
MAbstractGeneralModel (GCCommonData userdata scenemsg) userdata GCTarget GCMsg GCBaseData scenemsg
Differing from user components and portable components, global components have fixed msg and target types, which are Value and String. The common data is the running scene, while the base data is a record of dead and postProcessor. Global components can communicate with each other via the limited Value message. However, you can use whatever data type you want to design the data of the global component and initialize it with any data.
You may load the global components either at the beginning of the game or during runtime via an SOMMsg. To load a global component at the beginning, edit GlobalComponents.elm:
allGlobalComponents : List (GlobalComponentStorage UserData SceneMsg)
allGlobalComponents =
[ FPS.genGC (FPS.InitOption 20 "firacode") Nothing
]
To load, unload, or communicate with global components at runtime, users could use these two SOMMsgs:
type SceneOutputMsg scenemsg userdata
...
| SOMLoadGC (GlobalComponentStorage userdata scenemsg)
| SOMUnloadGC GCTarget
| SOMCallGC ( GCTarget, GCMsg )
Global components will update before the scene and will render after the scene. They can remove themselves by changing dead to True in base data. Besides, global components may post-process the Renderable result generated by the scene by adding a PostProcessor: Renderable -> Renderable in the postProcessor field of the base data.
There are some global components in the messenger-extra library, including FPS and Transition. Users can read the source code of those two global components to understand how global components work.
FPS
This is a global component to show the Frames Per Second (FPS) value on the screen. It stores the last 10 values of delta every Tick event and calculates the average to determine the FPS. To use FPS, add it in GlobalComponents.elm.
Its generator is:
genGC : InitOption -> Maybe GCTarget -> GlobalComponentStorage userdata scenemsg
type alias InitOption =
{ fontSize : Float
, font : String
}
Maybe GCTarget overrides the component name. Use Nothing to default to "fps".
Transition
The Transition GC provides scene transition effects (fade in/out, cross-fade, etc.). It is available in messenger-extra as Messenger.GlobalComponents.Transition.Model.
Two Transition Modes
There are two modes of transition:
- Sequential (NoMix): Scene A fades out first, then scene B fades in. The two stages run sequentially.
- Mixed: Scene A and scene B run simultaneously during the transition, cross-fading between them.
The core effect types are:
type alias SingleTrans =
Renderable -> Float -> Renderable
type alias DoubleTrans =
Renderable -> Renderable -> Float -> Renderable
SingleTrans is used in sequential mode — it takes a renderable and a progress float (0 to 1). DoubleTrans is used in mixed mode — it takes two renderables (old scene + new scene) and a progress float.
Convenience Functions
The easiest way to use transitions is through the convenience SOM constructors:
import Messenger.GlobalComponents.Transition.Model exposing (genSequentialTransitionSOM, genMixedTransitionSOM)
import Messenger.GlobalComponents.Transition.Transitions exposing (fadeIn, fadeOut, fadeMix)
-- Sequential: fade out current scene, then fade in next scene
genSequentialTransitionSOM
( fadeOut, Duration.seconds 1 )
( fadeIn, Duration.seconds 1 )
( "NextScene", Nothing )
-- Mixed: cross-fade between current and next scene
genMixedTransitionSOM
( fadeMix, Duration.seconds 1 )
( "NextScene", Nothing )
Emit these as SOMs in any update function:
Parent <| SOMMsg <| genMixedTransitionSOM ( fadeMix, Duration.seconds 1 ) ( "Home", Nothing )
Built-in Transitions
From Messenger.GlobalComponents.Transition.Transitions:
| Function | Type | Description |
|---|---|---|
fadeIn | SingleTrans | Fade in from black |
fadeOut | SingleTrans | Fade out to black |
fadeInWithColor color | SingleTrans | Fade in from a specific color |
fadeOutWithColor color | SingleTrans | Fade out to a specific color |
fadeInWithRenderable ren | SingleTrans | Fade in from a custom renderable |
fadeOutWithRenderable ren | SingleTrans | Fade out to a custom renderable |
fadeMix | DoubleTrans | Cross-fade between two scenes |
nullTransition | SingleTrans | No-op transition (returns renderable unchanged) |
Low-level API
For advanced use, you can construct the GC manually:
import Messenger.GlobalComponents.Transition.Model exposing (genGC, InitOption)
import Messenger.GlobalComponents.Transition.Base exposing (genNoMixTransition, genMixTransition)
-- Sequential
SOMLoadGC <|
genGC
{ transition = genNoMixTransition ( fadeOut, Duration.seconds 1 ) ( fadeIn, Duration.seconds 1 )
, scene = ( "NextScene", Nothing )
, filterSOM = True
}
Nothing
-- Mixed
SOMLoadGC <|
genGC
{ transition = genMixTransition ( fadeMix, Duration.seconds 1 )
, scene = ( "NextScene", Nothing )
, filterSOM = True
}
Nothing
filterSOM blocks SOMChangeScene and SOMLoadGC during transition when set to True.
Implementing Custom Transitions
A custom SingleTrans simply composites two renderables based on progress:
import Messenger.GlobalComponents.Transition.Base exposing (SingleTrans)
import REGL.Compositors as Comp
myFade : SingleTrans
myFade r t =
Comp.linearFade t r (P.clear Color.black)
Comp.linearFade blends two renderables by the progress t. For mixed transitions, implement DoubleTrans with Comp.linearFade taking two renderables.
See the Transition demo and Home demo for working examples.
Asset Loading
This GC is used to show an asset loading scene when there is a resource loading.
Currently no options are required.