diff --git a/docs/SpringRoll/debugger.md b/docs/SpringRoll/debug.md similarity index 100% rename from docs/SpringRoll/debugger.md rename to docs/SpringRoll/debug.md diff --git a/docs/SpringRoll/getting-started.md b/docs/SpringRoll/getting-started.md index c373a17..c80dd7a 100644 --- a/docs/SpringRoll/getting-started.md +++ b/docs/SpringRoll/getting-started.md @@ -86,25 +86,25 @@ const app = new window.springroll.Application(); SpringRoll consists of a handful of modules intended to help developers improve the accessibility of their game. ### Application Module -The `Application` class provides the main communication bus through which the game can send and receive messages to the container. It also manages global game state, such as pause and captions display. More information can be found in the [Application module documentation](./application-class). It also consists of a simple [plugin architecture](./plugin-architecture) for hooking into the load sequence of applications. +The `Application` class provides the main communication bus through which the game can send and receive messages to the container. It also manages global game state, such as pause and captions display. More information can be found in the [Application module documentation](./application-class). It also consists of a simple [plugin architecture](./plugins) for hooking into the load sequence of applications. ### Accessibility Module -SpringRoll contains submodules for various accessibility testing and enhancement. The [Color Filter module](./src/accessibility/color-filter) provides filters for testing color blindness support in your game. Enabling the class allows developers to see what their game would look like for various types of color vision deficiency. The [Speech Synth module](./accessibility/speech-synth) gives developers the ability to synthesize speech from text. +SpringRoll contains submodules for various accessibility testing and enhancement. The [Color Filter module](./accessibility/color-filter) provides filters for testing color blindness support in your game. Enabling the class allows developers to see what their game would look like for various types of color vision deficiency. The [Speech Synth module](./accessibility/speech-synth) gives developers the ability to synthesize speech from text. ### Controller Module The [Controller module](./controller) provides a mechanism for mapping keyboard input to functions which can help centralize user input management and make supporting multiple input mechanisms easier. ### Debugger Module -The [Debugger module](./src/debug) provides a centralized set of methods for logging that can be enabled or disabled at runtime. +The [Debugger module](./debug) provides a centralized set of methods for logging that can be enabled or disabled at runtime. ### Localization Module -The Localization module provides support for supporting [multiple languages in games](./src/localization/localizer) and [captions](./src/localization/captions) +The Localization module provides support for supporting [multiple languages in games](./localization/localizer) and [captions](./localization/captions) ### Scale Manager Module -The [Scale Manager module](./src/scale-manager) helps developers to react to screen size changes. +The [Scale Manager module](./scale-manager) helps developers to react to screen size changes. ### State Manager Module -The [State Manager module](./src/state) provides classes for creating subscribable properties that notify listeners when they are changed. This is used for managing pause, captions, and audio mute state in the [Application class](./src/), but can also be used for other generic uses. +The [State Manager module](./state) provides classes for creating subscribable properties that notify listeners when they are changed. This is used for managing pause, captions, and audio mute state in the [Application class](./application-class), but can also be used for other generic uses. ## BrowserStack Testing To test Springroll v2 on BrowserStack. Copy `.env.sample` and rename it to `.env`. Replace the placeholder values with your own BrowserStack credentials, and then run `npm run test:bs`. diff --git a/docs/SpringRoll/plugin-architecture.md b/docs/SpringRoll/plugins.md similarity index 100% rename from docs/SpringRoll/plugin-architecture.md rename to docs/SpringRoll/plugins.md diff --git a/docs/springroll-container/_category_.json b/docs/springroll-container/_category_.json new file mode 100644 index 0000000..cbdc716 --- /dev/null +++ b/docs/springroll-container/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "SpringRoll - Container", + "position": 2, + "link": { + "type": "generated-index", + "description": "SpringRoll Container" + } +} diff --git a/docs/springroll-container/getting-started.md b/docs/springroll-container/getting-started.md new file mode 100644 index 0000000..5836421 --- /dev/null +++ b/docs/springroll-container/getting-started.md @@ -0,0 +1,688 @@ +--- +sidebar_position: 1 +sidebar_label: Getting Started +sidebar_class_name: green +--- +# SpringRoll Container + +The SpringRoll Container is an ` +``` + +and that you've imported this module: + +```javascript +import { Container } from 'springroll-container'; +``` + +### Opening a Local Game + +```javascript +const container = new Container('#game'); + +container.openPath('local/path/to/game.html'); +``` + +### Opening a Game Hosted at Another Domain + +```javascript +const container = new Container('#game'); + +container.openLocal('https://example.com/path/to/game.html'); +``` + +### Opening a Game Hosted on SpringRollConnect + +```javascript +const container = new Container('#game'); + +container.openRemote('https://springroll-connect.example.com/api/release/game-slug'); +``` + +### Opening a Game with a Pause Button + +```javascript +import { PausePlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + // Assuming that there is a + +
+ + + +
+ +
+ + +
+ +
+ + +
+``` + +Note that the captions plugin sets a class of `muted` or `unmuted` on the caption buttons as they are toggled. + +### SoundPlugin + +The sound plugin allows users to control the volume of individual audio channels within the game. +SpringRoll supports three audio channels: VO, SFX, and Music and we encourage developers to use them as it empowers users to customize their game play to suite their needs. + +The sound plugin supports a total of eight controls: + +- A global sound mute +- Mute buttons for each of the three audio channels mentioned above - VO, SFX, Music +- A global sound volume slider +- Volume sliders for each of the three audio channels mentioned above - VO, SFX, Music + +```javascript +import { SoundPlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + new SoundPlugin({ + soundButtons: '#soundButton', // mutes or unmutes all game audio + musicButtons: '#musicButton', // mutes or unmutes the music + voButtons: '#voButton', // mutes or unmutes the voice over + sfxButtons: '#sfxButton', // mutes or unmutes the game's sound effects + + // The sound button expects these to be HTML range inputs + soundSliders: '#soundSlider', // controls the game's audio volume + musicSliders: '#musicSlider', // controls the game's music volume + voSliders: '#voSlider', // controls the game's voice-over volume + sfxSliders: '#sfxSlider', // controls the game's sound effects volume + }), + ] +}); +container.openPath('game.html'); +``` + +`SoundPlugin` will set a class of `muted` or `unmuted` on each button as they are toggled + +### Mechanics + +Mechanics are various configurable aspects of the game that can determine how a user plays the game (see table below for details). +Some games will support many of these features, some none at all. We doubt one game will use all of them though. + +Each plugin is responsible for one of the listed mechanics and should be provided a +[HTML range input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range), and an optional default value. +Each mechanic's value will range between 0 to 1, and the default initial value is always 0.5. + +```javascript +import { + HitAreaScalePlugin, DragThresholdScalePlugin, HealthPlugin, ObjectCountPlugin, + CompletionPercentagePlugin, SpeedScalePlugin, TimersScalePlugin, InputCountPlugin, + Container + } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + new HitAreaScalePlugin('#hitAreaScaleSlider', {defaultHitAreaScale = 0.5}), + new DragThresholdScalePlugin('#dragThresholdScaleSlider', {defaultDragThresholdScale = 0.5}), + new HealthPlugin('#healthSlider', {defaultHealth = 0.5}), + new ObjectCountPlugin('#objectCountSlider', {defaultObjectCount = 0.5}), + new CompletionPercentagePlugin('#completionPercentageSlider', {defaultCompletionPercentage = 0.5}), + new SpeedScalePlugin('#speedScaleSlider', {defaultSpeedScale = 0.5}), + new TimersScalePlugin('#timersScaleSlider', {defaultTimersScale = 0.5}), + new InputCountPlugin('#inputCountSlider', {defaultInputCount = 0.5}), + ] +}); +container.openPath('game.html'); +``` + +MechanicsPlugin Options: + +See the [SpringRoll Application Docs](https://github.com/SpringRoll/SpringRoll/tree/master/src) for more detailed information. +| Feature | Key | Description | +| ------------------- | ----------------- | ------------- | +| Hit Area Scale | hitAreaScale | Allows the player to define how large or small they want hit boxes for clicking/touching to be in the game. Gives the player the ability to make elements easier or harder to hit. | +| Drag Threshold Area | dragThresholdArea | Allows the player to define how sensitive they want object drag detection to be. More or less sensitivity can make certain game challenges more completable for players | +| Health | health | Allows the player to define how many attempts, retries, lives, or health they have in the game. | +| Object Count | objectCount | Allows the player to define how many objects, hidden or otherwise, are required to complete objectives throughout gameplay. | +| Speed Scale | speedScale | Allows the player to define how quickly or slowly game mechanics move. | +| Completion Percentage | completionPercentage | Allows the player to define what percentage of a task is required to be finished to complete that task. | +| Timer Scale | timerScale | Allows the player to adjust timers in game to give more or less time to complete tasks. | +| Input Count | inputCount | Allows the player to define how many clicks, taps, or keyboard inputs are required to complete objectives. | + +### PointerSizePlugin, ButtonSizePlugin, LayersPlugin + +The Button Size plugin allows users to control the size of buttons within the game. The size value ranges from 0 to 1, defaulting to 0.5. + +The Pointer Size plugin allows users to control the size of custom pointers within the game. The size value ranges from 0 to 1, defaulting to 0.5. + +The Layers plugin allows users to hide distracting layers within a game. This is a ranged value from 0 to 1. 0 indicates "show all layers" +whereas 1 indicates "hide all distracting layers". By default, this value is 0. + +Note that each game may implement this differently. + +Note that these plugins accept HTML range inputs, rather than buttons. + +```javascript +import { ButtonSizePlugin, PointerSizePlugin, LayersPlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + new ButtonSizePlugin('#button-slider-selector', { + defaultButtonSize: 0.5, // button size goes from 0.0 to 1.0. Default = 0.5 + }), + + new PointerSizePlugin('#pointer-slider-selector', { + defaultPointerSize: 0.5, //pointer size goes from 0.0 to 1.0. Default = 0.5 + }), + + new LayersPlugin('#layers-slider-selector', { + defaultValue = 0 // goes from 0.0 to 1.0 + }) + ] +}); + +container.openPath('game.html'); +``` + +### HUDPlugin + +The HUD plugin allows users to position HUD elements within a game by docking to different sides of the screen. + +```javascript +import { HUDPlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + // expects exactly four(4) radio buttons with values "top", "bottom", "left", "right, + new HUDPlugin('#hud-position-button-selector', { + defaultValue: "top" //the initial starting value, defaults to "top" + }), + ] +}); + +container.openPath('game.html'); +``` + +The HUD Plugin requests the supported positions directly from the game itself and builds out an internal list of positions dynamically, +e.g. if the game supports Top and Bottom HUD docking (stored internally as `['top', 'bottom']`) then the plugin will hide the "left" and "right" +radio buttons so only the valid ones are displayed to users. + +See [the SpringRoll Application Class docs](https://github.com/SpringRoll/SpringRoll/tree/main/src#responding-to-the-container) for more information on +the request format and how game developers provide those values. + +### Controls + +There are two plugins associated with in-game controls: `ControlSensitivityPlugin` and `KeyboardMapPlugin`. +The Control Sensitivity Plugin allows the user to determine the sensitivity of custom pointers in game. This plugin expects an HTML Input +The Keyboard Map Plugin allows users to re-map the keys/controls used in-game to something they are more comfortable with. + +```javascript +import { ControlSensitivityPlugin, KeyboardMapPlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + //ControlSensitivityPlugin expects an input of type=range for it's input. + new ControlSensitivityPlugin('#sensitivity-slider-selector', { + defaultSensitivity: 0.5, //control sensitivity goes from 0.0 to 1.0. Default = 0.5 + }), + //The KeyboardMapPlugin expects a div or similar container element as it's selector. It will automatically build out the + //buttons to use for re-mapping controls based on what the application returns. See note below for HTML structure. + new KeyboardMapPlugin('#key-container', { + //you can provide a custom classname that will be attached to each key button that is generated + customClassName: 'custom-button-class' //default='springrollContainerKeyBinding__button'. + }) + ] +}); +container.openPath('game.html'); +``` + +*The Key Binding functionality of the `KeyboardMapPlugin` works similarly to the HUDPlugin in that it requests information from the Springroll Application. See [the SpringRoll Application Class docs](https://github.com/SpringRoll/SpringRoll/tree/v2/src#handling-state-change) for more information on the request format. + +The HTML output within the key container will look like the following: +The className shown is the default, but can be overridden through the `customClassName` option. The IDs are generated based on the action name. + +```html +
+ + + + +
+``` + +Keybindings are tracked visually by setting the textContent of the buttons themselves. + +### ColorVisionPlugin + +```javascript +import { ColorVisionPlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + // expects exactly five(5) radio buttons with values "none", "achromatopsia", "tritanopia", "deuteranopia", + // and "protanopia" indicating the types of color visions supported. + new ColorVisionPlugin('input[name=color-vision-radios]'{ + defaultValue: 'none' // initial checked radio box, defaults to "none" + }), + ] +}); +container.openPath('game.html'); +``` + +*The color vision radio group builds out the supported values dynamically based on what the application reports back and hides +any unsupported values. See [the SpringRoll Application Class docs](https://github.com/SpringRoll/SpringRoll/tree/main/src#responding-to-the-container) +for more information on the request format. + +### Fullscreen Plugin + +The fullscreen plugin hooks up an element or elements to set the iframe to full screen then communicates this through Bellhop. The plugin will also add the class ```'--fullScreen'``` to the element(s) given + +```javascript +import { FullScreenPlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + + plugins: [ + // FullScreenPlugin expects the selector for the element(s) to hook onto + new FullScreenPlugin('#fullScreenButton'), + ] + }); + +container.openPath('game.html'); + +``` + +The plugin will accept either a selector or an array of selectors as a parameter + +```javascript +new FullScreenPlugin('#fullScreenButton'); +new FullScreenPlugin(['#fullScreenButton', '.fullScreenButtonSideNav']); + +// It will also accept one string with all selectors each separated by a comma +new FullScreenPlugin('#fullScreenButton, .fullScreenButtonSideNav'); + + +``` + +The typical html can look something like this however, the element may be positioned anywhere in the html as long as it is not inside the iframe + +```html + + + +``` + +`isFullScreen` returns true if there is a fullscreen element `FullScreenPlugin.isFullScreen` + +### Multiple Plugin Controls + +All Plugins accept one or more HTML elements as controls in their constructor. +For example the SoundPlugin can accept more than one volume slider or button if your set up requires it: + +```javascript + new SoundPlugin({ + soundButtons: '#soundButton, #soundButtonTwo', + soundSliders: '#soundSlider', + musicButtons: '#musicButton', + musicSliders: '#musicSlider, #musicSliderTwo', + }); +``` + +As long as the string you pass to the constructor is a valid selector string the plugin will use anything you pass to it. The plugins will keep settings in sync across the controls if necessary as well. Sliders will update each other, buttons will set a dataSet attribute or class (see individual plugin sections for the exact attribute), and any other controls will match each other appropriately. + +*Note: at this time there is no support for multiple HTMLElements as parameters. If you are passing an HTMLElement as the parameter rather than a selector string you cannot pass multiple controls. If you do wish to use multiple controls, pass the plugin a selector string instead. + +## Play Options + +The `openPath` method of the Container provides a mechanism for providing options directly to the game, called +`playOptions`: + +```javascript +var container = new Container('#game'); +container.openPath('game.html', { + playOptions: { + difficulty: 7, + theme: 'blue' + } +}); +``` + +The Container adds any data included this way as queryString parameters that can be read by the SpringRoll Application. +Once the application finishes its `init` process, this data will be available directly on the application instance: + +```javascript +var app = new springroll.Application({ + // various options here +}); + +app.on('init', function() { + springroll.Debug.log('Play Options are', app.playOptions); // { difficulty: 7, theme: 'blue' } +}); +``` + +Any JSON-serializable object can be set as a `playOption`. + +## Context +Container has an optional parameter at instantiation time which allows the opener to attach any data they require to the Container +instance which any plugins can interact with to share data. This data can be mutated or replaced at any time. + +```javascript + +const initialContext = { + hostEnvironment: 'web', + gameBuildInfo: { + commit: '#abcd123', + name: 'game-name' + } +}; + +const container = new Container('#game', { context: initialContext }); + +// Once the container instance is created you can access the context from any plugin or anywhere else there is access to Container +console.log(container.context); // { "hostEnvironment": "web", "gameBuildInfo": { "commit": "#abcd123", "name": "game-name" } } + +``` + +The context can be accessed via the `container.context` getter. It can also be modified by simply adding or changing fields + +```javascript +container.context.newField = 'hello'; +container.context.gamebBuildInfo = 'newInfo'; + +// { "hostEnvironment": "web", "gameBuildInfo": "newInfo", "newField": "hello" } +console.log(container.context); +``` + +You can also overwrite the context object entirely if you need to: + +```javascript +container.context = { + newField: { + newKey: 'newField' + } +} +``` + +The only caveat here is that this will check to make sure the new data is an object. If not it will log an error and leave the +context unchanged. + + +## Saved Data API + +The SavedData API is made up of three classes: `SavedData`, `SavedDataHandler`, and the `UserDataPlugin`. +It allows the container (or the SpringRoll Application) to store key-value pairs in local/session storage. It also gives access to the +IndexedDB API. +It is primarily used to store user data for use across the SpringRoll environment. Examples are listed below for each class. + +### SavedData + +The `SavedData` class is the most direct way to access the Container storage options. It is used primarily in plugin classes, but may be used wherever necessary. + +The following is an example of interacting with Local/Session Storage + +```javascript +import { SavedData } from 'springroll-container'; + +//the last argument, tempOnly, is optional (default = false) and decides whether the value should be saved in session (temporary), +//or local (not temporary) storage. +const tempOnly = false; +SavedData.write('user-value-key', 'user-value', tempOnly); + +//SavedData.read() checks localStorage first and then sessionStorage. If the key exists in both only the localStorage will be returned. +let data = SavedData.read('user-value-key'); //data will be either the value in storage, if it exists, or null if it does not. + +SavedData.remove('user-value-key'); //removes the value from both local and session storage. +``` + +The following is an example of interacting with [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) through the UserData class + +``` javascript +import { SavedData } from 'springroll-container'; + +// Firstly, construct the SavedData object. This is only needed for IndexedDB work +const savedData = new SavedData('dbName'); + +// Then, open a connection to the database (this is using all default parameters, more info on parameters below) +savedData.IDBOpen('dbName','1', {}, {}, (result) => console.log(result)) + +``` + +If you want to make changes to the strucutre of the DB you would do so during the open connection step +via Additions and Deletions: + +Additions is an optional parameter expecting a JSON object with any additions to the databases structure namely new [stores](https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/createObjectStore) and [indexes](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/createIndex). These are placed inside of an array + +Deletions is an optional parameter used to delete any [indexes](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/deleteIndex) or [stores](https://developer.mozilla.org/en-US/docs/Web/API/IDBDatabase/deleteObjectStore) + +``` javascript + +let additions = { + stores: [{ + storeName: 'storeOne', + // optionally define a keyPath and/or set autoIncrement to true or false + options: { keyPath: "taskTitle" } + }, + { + storeName: 'storeTwo' + }], + indexes: [{ + indexName: 'newIndex', + keyPath: 'key', + // Any objectParameters for the Index + options: { + unique: false + } + }] +}; + +// Deletions is an optional parameter used to delete any indexes or stores +let deletions = { + stores: ['storeOne', 'storeTwo'], + indexes: ['newIndex'] +}; + +// Optionally pass in the new database version. Set to true to increment the database version. +// Leave this parameter out or pass in false to connect without making any changes to the structure of the database +let dbVersion = 1 + +// The name of the database to connect to +let dbName = 'dbName'; + +// Finally, pass these parameters in to establish a connection with the database +savedData.onOpenDb(dbName, dbVersion, additions, deletions); +``` + +There are other methods currently supported to interact with the database. These allow you to [Add a record](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/add), [Delete a record](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/delete), [Read a record](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/get), or [Read all records](https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/getAll). Each will return a success, or on failure, an error message + +All the below methods accept a callback as a last parameter if you need to do something with the response. + +``` javascript + +//Delete a record by the key in a specific store +savedData.IDBRemove('storeName', 'key'); + +//add a record to a store. The record can be any type of object accepted by indexedDB +savedData.IDBAdd('storeName', 'record'); + +//returns the record with the given key from the store with the given storeName +savedData.IDBRead('storeName', 'key'); + +//Return all records from a database or optionally a specified amount defined by the second parameter +savedData.IDBReadAll('storeName'); +savedData.IDBReadAll('storeName', 5); + +// Return all keys in a given Index. [Docs](https://developer.mozilla.org/en-US/docs/Web/API/IDBIndex/getAllKeys) +// See [here](https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange) for keyRange info +const keyRange = IDBKeyRange.bound("A", "F"); +const count = 5; +savedData.IDBGetIndexKeys('storeName', 'indexName', query, 5); + +// Finally, close the connection to the database +savedData.closeDb(); + +All other methods will work the same as the documentation [here](https://github.com/SpringRoll/SpringRoll/tree/main/src/state#userdata); + +### SavedDataHandler +The SavedDataHandler class is used primarily in the `UserDataPlugin` to interact with the `SavedData` class. But can be used directly +if you require a callback when reading or writing from `SavedData`. Like `SavedData` all of the methods are static. + +```javascript +import { SavedDataHandler } from 'springroll-container'; + +SavedDataHandler.write('user-value-name', 'value-to-be-stored', () => console.log('user-value-name written to storage')); + +SavedDataHandler.read('user-value-name', value => console.log('Returned value: ' + value)); + +SavedDataHandler.remove('user-value-name', () => console.log('user-value-name removed from storage')); +``` + +We don't expect this handler to be used very often, but it is available if required. + +### UserDataPlugin + +This plugin allows the container to respond to requests from the Springroll Application's [User Data Class](https://github.com/SpringRoll/SpringRoll/tree/master/src/state). +It is included in the container constructor like any other plugin: + +```javascript +import { UserDataPlugin, Container } from 'springroll-container'; + +const container = new Container('#game', { + plugins: [ + new UserDataPlugin(), + ] +}); +container.openPath('game.html'); +``` + +There is no configuration required for the UserDataPlugin as it just handles requests from the Application. + +## License + +Copyright (c) 2024 [SpringRoll](http://github.com/SpringRoll) + +Released under the MIT License. diff --git a/docs/springroll-container/plugins.md b/docs/springroll-container/plugins.md new file mode 100644 index 0000000..bc5eeb6 --- /dev/null +++ b/docs/springroll-container/plugins.md @@ -0,0 +1,116 @@ +--- +sidebar_position: 2 +sidebar_label: Authoring Plugins +sidebar_class_name: green +--- +# Authoring Plugins + +The process for writing a Container plugin differs based on whether it is going to be a built-in plugin, or external. + +Plugins for Container should take the form of an ES6 module, preferably with a named export. E.g.: +```javascript +export class MyContainerPlugin() {...} +``` + +When developing a plugin for Container v2.x there are 3 main lifecycle hooks to keep in mind: `preload`, `init`, and `start`. + +`preload()`: Preload must return a `Promise`. It can be async. The method is passed the Container instance. In general, most plugins will only need to access the [Bellhop client](https://github.com/SpringRoll/Bellhop). However, the entire Container instance is available should you require it. +*Note: if this method is missing or the returned promise is rejected, Container will automatically discard your plugin and it will not be loaded in properly.* + +Example: +```javascript +export class ContainerPlugin() { + constructor() {...} + + async preload({ client }) { + this.client = client; + } +} +``` + +`init()`: The init method is called once all plugin `preload` promises have resolved. Most setup that involves interacting with the Springroll Application via Bellhop would happen here. Any event listeners (bellhop or otherwise) should go here. `init()` is also passed the Container instance if you need it. + +`start()`: The `start()` method is called after all preloaded plugins have finished their `init()` calls. This method allows plugins to depend on others by allowing a second plugin to `start()` after a first plugin has ran `init()`. This can help ease race conditions between plugins, as they are not guarenteed to call `init()` in a consistent order. Similarly to `preload()`, `start()` is also passed the Container instance if required. + +In general every plugin will follow a similar blueprint and will look something like this: +```javascript +export class ContainerPlugin() { + constructor() {...} + + async preload({ client }) { + this.client = client; + } + + init() {...} + + start() {...} + + //Any other helper functions required +} +``` + +However, some more customized plugins plugins may have additional concerns. These are detailed below.``` + +## External Plugin +External Plugins are generally specific to an application or organization and follow the above blueprint. They don't tend to follow a Springroll Application feature like `sound` or `captions`, and may just be additional custom functionality for your particular page. In this case, you can implement the methods you need for your plugin with no additional considerations. + +## Porting Container v1.x plugins to v2.x +Exactly how you go about porting your plugin from the SpringRollContainer 1 to 2 will depend on how the original plugin was written. The `init()` function for Container 2.0 plugins will loosely correspond to the older `setup()` from Container 1.0. + +The older hook methods `open` and `opened` should now be implemented as event listeners in the main plugin.: +```javascript +export class MyPlugin { + preload() { + return Promise.resolve(); + } + + init({ client }) { + client.on('opened', () => { + // do things + }); + + client.on('open', () => { + // do things + }); + } +} +``` + + +## Internal a.k.a. Built-In Plugins +If you're developing for SpringrollContainer directly the process is still the same but there are base plugin classes available to keep your plugins DRY and more consistent. + +### [BasePlugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/base-plugins/BasePlugin.js) +[Example Plugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/plugins/KeyboardMapPlugin.js) +The most barebones plugin class avaialable. Should be used if none of the other plugins match your needs. +Provides very basic implementations of `preload()`, `init()`, and `start()`. + +| It also provides a few useful helper functions: | | +| --- | --- | +| `SendProperty(prop, value)` | Sends a single property and it's value through Bellhop to the application. `prop` should match the springroll feature name. Also [saves the property](https://github.com/SpringRoll/SpringRollContainer#saved-data-api) for re-use | +| `warn(warningText)` | prints out an informative console warning | +--- + +### [ButtonPlugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/base-plugins/ButtonPlugin.js) +[Example Plugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/plugins/CaptionsTogglePlugin.js) +The `ButtonPlugin` is useful for any plugin that requires a `mute` state (i.e. on or off). It extends the `BasePlugin` and has access to all of the methods above. +| It also includes: | | +| --- | --- | +| `_setMuteProp(prop, button, muted)` | Sets the current state of the property, and sends it to the application. This also handles applying styles to the button or buttons to match. `button` can be a single instance of a button or an array of matching buttons. +--- + +### [SliderPlugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/base-plugins/SliderPlugin.js) +[Example Plugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/plugins/LayersPlugin.js) +If your plugin requires a range input to control volume or a similar setting this plugin will handle most of it. It can only accept one setting to control however so if you require more than one setting (e.g. `MusicVolume` and `VoiceOverVolume`) consider breaking it out into multiple plugins or just using `BasePlugin`. If your plugin extends this base class all you have to do is pass the configuration options through the `super()` call and the `SliderPlugin` handles the rest. + +### [RadioGroupPlugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/base-plugins/RadioGroupPlugin.js) +[Example Plugin](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/plugins/ColorVisionPlugin.js) +The RadioGroupPlugin is used for any plugin that uses groups of radio buttons to allow selection between pre-determined options. Similarly to the SliderPlugin above, the RadioGroupPlugin handles most of the set up behind the scenes and you won't have to interact directly with any of its methods. + +### UI-Elements +Container also provides a few base ui-element classes to help set up any HTML controls you have. These are: +- [Slider](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/ui-elements/Slider.js) +- [Button](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/ui-elements/Button.js) +- [RadioGroup](https://github.com/SpringRoll/SpringRollContainer/blob/main/src/ui-elements/RadioGroup.js) + +Note: these are used automatically by the `RadioGroupPlugin` and `SliderPlugin`. So these should only be required if you're not using one of those two as your base. diff --git a/docusaurus.config.ts b/docusaurus.config.ts index ebc8dde..995e9ff 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -66,9 +66,15 @@ const config: Config = { items: [ { type: 'docSidebar', - sidebarId: 'tutorialSidebar', + sidebarId: 'springrollSidebar', position: 'left', - label: 'Tutorial', + label: 'SpringRoll', + }, + { + type: 'docSidebar', + sidebarId: 'containerSidebar', + position: 'left', + label: 'SpringRoll Container', }, {to: '/blog', label: 'Blog', position: 'left'}, { @@ -85,8 +91,12 @@ const config: Config = { title: 'Docs', items: [ { - label: 'Tutorial', - to: '/docs/intro', + label: 'SpringRoll', + to: '/docs/springroll/getting-started', + }, + { + label: 'SpringRoll Container', + to: '/docs/springroll-container/getting-started', }, ], }, diff --git a/sidebars.ts b/sidebars.ts index acc7685..39683c0 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -12,7 +12,8 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; */ const sidebars: SidebarsConfig = { // By default, Docusaurus generates a sidebar from the docs folder structure - tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], + springrollSidebar: [{type: 'autogenerated', dirName: 'springroll'}], + containerSidebar: [{type: 'autogenerated', dirName: 'springroll-container'}] // But you can create a sidebar manually /* diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9726961..1e0f998 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -19,7 +19,7 @@ function HomepageHeader() {
+ to="/docs/springroll/getting-started"> SpringRoll Tutorial - 5min ⏱️
diff --git a/static/img/favicon.ico b/static/img/favicon.ico index 8bed833..242aa63 100644 Binary files a/static/img/favicon.ico and b/static/img/favicon.ico differ