“Life is a theatre set in which there are but few practicable entrances.”
― Victor Hugo, Les Misérables
MagicMirror module to change screen scenes by time and order with ANIMATION EFFECT.
Click it to see the DEMO.
Its configuration file is in /examples/config.js.example
Since MM 2.25, a new feature, animateCSS is introduced into the MagicMirror.
With this update, my previous MMM-Scenes would be obsoleted. So I remade a new module for MM 2.25
- The update can provide more effects now. ( without my effort. :D )
- custom animation is rarely used, and this update would cover most use cases. So I decided to drop it.
- I redesigned the structure more simply and intuitively. (
roleis introduced.)
The scenario of the MM screen is made up of a series of scenes. Each module has its role in its appearance scenes to enter and exit by design.
When a scene begins, all modules whose roles end will be expelled, and all modules with the parts in that scene will be admitted.
As described in the scenario, your MM screen will play a drama with modules.
- control show/hide modules by assigning role names to the module's class
- various animations for modules exit/enter
- control scenes by notification and WebURL endpoints.
- Loop control
- custom indicators
cd ~/MagicMirror/modules
git clone https://github.com/MMRIZE/MMM-Scenes2
cd MMM-Scenes2
npm installDon't worry, it's not as difficult as it looks. You can find a real-world example in the
examplesdirectory.
{
module: "clock",
position: "top_left",
hiddenOnStart: true,
classes: "role1 role_final" // <-- assign role(s) to the module to control.
},
// ... other modules ...
{
module: "MMM-Scenes2",
position: 'bottom_bar', // Position of indicator
config: {
scenario: [ // `scenario` is REQUIRED
{ // First scene definition
exit: ["role1", "role2"],
enter: ["role3", "role4"],
},
{ // Second scene definition
exit: ["role3"],
enter: ["role_final"],
},
]
}
}This
scenariohas 2 scenes. At the first scene,"role1"and"role2"module(s) will exit from the scene with default animation. Then"role3"and"role4"module(s) will enter into the scene. After some lifetime, the second scene will start."role3"module(s) will be disappeared and"role_final"scene will be revealed. ("role4"will remain at the second scene.) And the whole scenario will repeat.
In other words, the
clockmodule will exit from the first scene as"role1"and will enter into the second scene as"role_final".
config: {
scenario: [ ... ], // Array of scene objects. This is the only option MUST-REQUIRED. You should fulfil this option in your configuration.
//Below are omittable. You don't have to describe all these options in your config.
life: 1000 * 60, // default life of each scene
activeIndicator: '■', // default indicator of current scene
inactiveIndicator: '□', // default indicator of other scenes inactive
// You can ignore the belows if you are not an expert.
lockString: 'mmm-scenes2', // lockString for hide mechanism
defaultEnter: { animation, duration, gap }, // convenient definition of default options for `enter`
defaultExit: { animation, duration, gap }, // convenient definition of default options for `exit`
}| property | default | description |
|---|---|---|
scenario |
[] | REQUIRED The order-set of scenes. You SHOULD set the scene definition (object) as the items of this property. |
life |
1000 * 60 | (ms) The life of each scene after all roles are appeared. After this time, the next scene would start. If set as 0, the scene would be paused unless external control(notification, telegram, ...) happens. |
activeIndicator |
'■' | Default indicator of current active scene. You can reassign it in each scene object. |
inactiveIndicator |
'□' | Default indicator of other inactive scenes. This could also be reassigned in each scene object. |
lockString |
'mmm-scenes2' | Just leave it if you don't know what this is for. |
defaultEnter |
{ animation, duration, gap } | Convenient definition of default options for enter. I'll explain later. |
defaultExit |
{ animation, duration, gap } | Convenient definition of default options for exit. I'll explain later. |
There is no
defaultNextordefaultPreviousbecausenextandpreviousshould differ according to the scene.
scenario would have some series of scene objects. Each object would have these structures.
scenario: [
{
enter: [ ... ],
exit: [ ... ],
name: 'first_scene',
life: 1000 * 30,
activeIndicator: '■',
inactiveIndicator: '□',
next: null, // Since 1.1.0
previous: null, // Since 1.1.0
},
// next scenes.
]- When you don't assign
nameby yourself,scene_N(scene_0, scene_1, ...) would be set automatically. This name would be used for external control, so it would be better to avoidprev,next,pause,resume,playas a scene name. life,activeIndicator,inactiveIndicatorare defined in global configuration, but they could be reassigned in the specificsceneobject by your needs.- When
lifeis set as0, this scene would stop until an external command arrives. (e.g. TelegramBot command). You can set this value as0on the last scene to play the scenario only once. - (new)
nextandpreviousis introduced since 1.1.0. The 2 fields would be used for control the order of scenes. It'll be explained later. enterandexitare the most important fields onsceneobject. See below.
scenario: [
{
enter: [ "role1", "role2", ... ],
// OR
enter: [
{
role: "role1",
animation: "bounceIn",
duration: 1500,
gap: 100,
},
{
role: "role2",
animation: "rotateIn",
}
],
// OR
enter: [
"role1",
{
role: "role2",
animation: "flipInY",
duration: 3000,
}
]
// ... other fields
}
// ... more
],Each enter and exit could have a list of roles. role could be the name which you assigned in classes of modules, or the object which has a definition of the role, or a mix of names and objects.
When you don't need to order different behaviours to the specific roles in the scene, the names are enough to direct which module will enter/exit.
role: the name of role-player module(s).animation: the name of animation. Currently, the possible animations are defined here. Or see thisduration: Speed of animationgap: Each role module transitions sequentially with this delay. If set as 0, all modules of this role start their transition simultaneously.
For your convenience, You can define defaultEnter and defaultExit for the common setting of all roles unless each value is reassigned in the specific scene.
config: {
defaultEnter: {
animation: 'fadeIn',
duration: 1000,
gap: 0,
},
defaultExit: {
animation: 'fadeOut',
duration: 1000,
gap: 0,
},
scenario: [ ... ],
...
}By default, the order of the scenes is linearly executed in the order listed in scenario:[...]. For example, The third scene is executed after the second scene, and so on.
However, there are cases where you may want to arbitrarily adjust the order of the scenes.
previous/nextis used to force the previous and next scenes in each scene, respectively. The possible kind of values are(sceneIndex),(sceneName),null,false, orthe callback functionwhich will return one of those values.
scenario: [
...
{
name: "scene_003",
exit: ["role1", "role2"],
enter: ["role3", "role4"],
next: "scene_005", // sceneName
previous: 2, // Or sceneIndex
},
...This example means; the next scene of the this scene would be "scene_005". And when SCENE_PREV is called, the previous of this scene would be the 3rd scene of the scenranio. (2 means 3rd because index would be zero-based.)
-
If you want to follow the original order in the scenrio, just omit
next/previousor set it asnull. (Default behaviours) -
If you set it to
false, the flow would be blocked.next: falsemeans, you cannot forward anywhere from this scene.
next: false,
previous: false,This example means; SCENE_PREV or SCENE_NEXT will not work once you enter this scene. (but you can escape with SCENE_PLAY by force)
- Finally, instead of a static value, you can use a callback function to provide a value that changes dynamically depending on a condition. This can be useful when branching of the scenario is required.
next: ({ scene, scenario }) => {
// A Parameter `scene` would have the info of current scene.
// A parameter `scenario` would have the whole scenario information.
// console.log(scene, scenario)
return (Math.random() > 0.5) ? "scene_001" : "scene_002"
}This example shows, the next scene would be randomly selected between "scene_001" and "scene_002". Of course, you can program it for your purpose. (For example; Normal scenario / Party scenario by time, ...)
More detailed examples are in the wiki.
Some syntax was changed from
MMM-Scenes. Check it carefully if you are a user of the previous module.
- Each incoming notification could have a
callbackfunction as a member of the payload. It will be called when your notification request is done.
this.sendNotification('SCENE_NEXT', {
callback: (result) => { console.log(result.status) }
})
// Callback result example
{
status: true,
currentScene: { name, enter, exit, ... },
index: 0,
message: "Example..."
}Play the next scene.
Play the previous scene.
Pause at current scene until another command comming.
Resume the scene. The remaining life at pause would be applied with this command.
You can also resume with other commands(e.g. SCENES_NEXT). In that case, the remaining life would be ignored, and the scene would play instantly.
Get information on the current scene.
Play a specific scene.
scene could be a name or an index of a scene in the scenario. If omitted, the current scene would be applied.
When scenes are changed, this notification will be emitted.
You can access MM URL to control this module from outside of MM. e.g.) IFTTT.
http://magicmirror.domain/scenes/pause
http://magicmirror.domain/scenes/resume
http://magicmirror.domain/scenes/next
http://magicmirror.domain/scenes/prev
http://magicmirror.domain/scenes/0
http://magicmirror.domain/scenes/scene_2
You can control MMM-Scenes2 using the Telegram app by installing the MMM-TelegramBot module.
/scene info/scene pause/scene resume/scene next/scene prev/scene index:0/scene name:scene_2
You can assign indicators globally or scene-specifically.
config: {
activeIndicator: '■',
inactiveIndicator: '□',
scenario: [ ... ],
...
}If you have 4 scenes in the scenario, the indicator will be shown as □ ■ □ □(the second scene is active).
config: {
...
scenario: [
{ // First scene
activeIndicator: '❶',
inactiveIndicator: '①',
...
},
...
]
}Like this, you can reassign indicators for specific scenes. In this case, you can see ❶ □ □ □ or ① ■ □ □.
You can decorate the indicators with CSS in your custom.css; The structure of HTML created will be like this
<div class="scenes_indicator">
<span class="scenes_indicator_scene index_0 inactive first">□</span>
<span class="scenes_indicator_scene index_1 active">■</span> <!-- current scene -->
<span class="scenes_indicator_scene index_2 inactive last">□</span>
</div>You can decorate its look like this;
/* custom.css */
.scenes_indicator_scene.inactive {
color: gray;
}
.scenes_indicator_scene.active {
color: red;
font-weight: bold;
font-size: 200%;
}One more thing: You can change the scene by clicking/touching the indicator if your MM supports click/touch.
- I dropped out some features of
MMM-Sceneslikecustomized animationor some things in this module. If you need to implement it again, feel free to tell me. I'll consider it. - If the
lifeof a scene is set as0, that scene will not be forwarded to the next scene. You can use this feature to make control looping or some hidden scenes for specific purposes. - RPI3 or older/weaker SBC doesn't have enough power to handle the animation. In that case, use animation default or avoid serious effects.
next/previousfor branching scenario (even on-fly-time)- Code cleaning
- Released
- Seongnoh Yi (eouia0819@gmail.com)
Click To Play