This module aims to provide a platform for FVTT users to create and publish their own lighting animations, and provide a good selection of community made lighting animations to GameMasters.
Download this module and enjoy the new Lighting Animations provided!
Read through the Contribution Tutorial below and add your lighting animations!
Tutorial below. PRs are always open to add your own lighting animations.
If you wish to remove or significantly alter the logic for one or more of your already added lights, please provide a reason added in your PR description - I want to avoid breaking users scenes where possible.
To create and publish your own custom lighting animation, you'll need to run through a couple of steps:
- Register your animation metadata in
lights.json
- Build your actual animation in
modules/animations.js
And optionally
- Provide translations in the
lang
files
Once this is done, you can create a Pull Request and integrate your work into the module, covered in
- Integrating into the module
We will run through each of these steps below. I will also provide an example implementation at the end.
If you have any issues following this tutorial, feel free to ping me on Discord at Blitz#6797
If you already know how develop and edit modules, skip to the next section.
Prerequisites: Foundry 0.7.5+, Git
To get started, first you'll need to clone this repo into your modules
directory.
In a terminal, navigate to the modules
directory and run:
$ git clone https://github.com/BlitzKraig/fvtt-CommunityLighting.git
Once the repo is cloned, ensure the directory name matches the name provided in module.json
- CommunityLighting
Launch Foundry
Launch a world
Open Manage Modules
, and enable CommunityLighting by Blitz
You are now ready to begin creating your lighting animations. Open the module directory in the editor of your choice, and follow the rest of the tutorial.
You must first register your lights metadata in a specific JSON file, so CommunityLighting knows how to set up your animations.
First, add your Author object inside lights.json
. You can use any name you want, but please keep all of your metadata inside the one Author object.
"ExampleUser": {
}
This is where you lights definitions will live, alongside optional details.
You can add your Discord tag if you want users to be able to contact you via discord when they're having issues with your particular animation, or links to your Github, Twitter and Youtube, which will appear in the attributions page (Not yet built). These are all completely optional.
"ExampleUser": {
"discord": "ExampleUser#00000",
"links": {
"github": "https://githubhere",
"twitter": "https://twitterhere",
"youtube": "https://youtubehere"
}
}
Next, you can define your lights. These definitions will be stored inside a lights
array, and must at least contain a name
and a animationFunction
.
The name
will be displayed in the animation selection dropdown for an ambient light. Try to keep these unique if possible.
The animationFunction
must match your animation function name, which we'll set up down below. It should consist of alphabetical characters only, preferably in camelCase
.
You can optionally add a description
, intensityDescription
and speedDescription
, which will be displayed in a later update, describing your light, what the intensity slider does, and what the speed slider does. These sliders are provided by Foundry core, and can be seen in the configuration panel for a light.
Finally, you can add an optional translationName
, which will allow all of these details to be translated using Foundrys translation features, which we'll cover later. The translationName
should consist of alphabetical characters only, preferably in camelCase
.
{
"Blitz": {
...
},
"ExampleUser": {
"discord": "ExampleUser#00000",
"links": {
"github": "https://githubhere",
"twitter": "https://twitterhere",
"youtube": "https://youtubehere"
},
"lights": [
{
"translationName": "coolLight",
"name": "My Cool Light",
"animationFunction": "coolLight",
"description": "A basic, but very cool light",
"intensityDescription": "Controls how radical the light will be!",
"speedDescription": "Controls how often the light will be radical."
},
{
"name": "My Less Cool Light",
"animationFunction": "boringLight"
}
]
}
}
Note that the first
light
object, "My Cool Light" contains all of the optional properties, while the second object "My Less Cool Light" contains the bare minimum to get started. I recommend providing as much detail as possible.
Your JSON is complete! Make sure you have your commas in the right places, and you've not mangled any other author objects in the process.
Custom Shaders are supported, but not yet documented.
In order to use a custom shader, please see the Custom Shader Example
light under Blitz
in lights.json.
Add any shader code to modules/shaders.js
Once you've defined your lights in the JSON, we'll move on to actually building them.
Open the modules/animations.js
file.
Scroll down to the bottom of the file and create your animation function, using the name you defined in animationFunction
in the JSON file.
Try to keep all of your own lights together in the file. I'd suggest prefixing the
animationFunction
and function with your author name until I implement some better organization.
Your animation function needs to accept 2 arguments, an integer and an Object, which are passed in from Foundry core:
dt
- DeltaTime - Time since last 'frame', in 1/60th of a second{speed, intensity}
- The values from the speed & intensity sliders - Both1
to10
You can copy & paste one of the animation functions already in the file as a starting point.
coolLight(dt, {
speed = 5,
intensity = 5
}) {
// Your code here
}
IMPORTANT The function name (
coolLight
) matches theanimationFunction
(coolLight
) provided in the JSON in step 1
The = 5
on the speed
and intensity
declarations simply tell the function to default these variables to 5
if they are not provided by the caller.
Inside this function, the this
keyword will refer to the lightsource being animated.
this.illumination
and this.coloration
refer to the shaders that handle the light circle, and the color.
Most of your modifications will probably be to their uniforms
objects, which contain multiple properties you can play with.
For example:
this.illumination.uniforms.alpha = 0.5
will set the illumination to half brightness.
Some useful uniforms:
- illumination
alpha
- The illuminations opacity -0.0
to1.0
ratio
- The ratio of bright to dim light -0.0
to1.0
- coloration
alpha
- The colors opacity -0.0
to1.0
ratio
- The ratio of bright to dim color -0.0
to1.0
color
- The displayed color - RGB Array[0,0,0]
to[1,1,1]
sharpness
- Currently unsupported - Foundry core removed this, but is expected to add it again soon.
You can change a lot more than just the shader uniforms, but you'll have to experiment to see exactly what you can do.
Keep in mind that to 'animate' a light, you will need to alter these values based on something else (usually time, often using a wave function). You can check blitzPulseTest
inside animations.js
to see how the pulse animation works, based on Pulse in Foundry Core.
You can also use the static methods in CLAnimationHelpers
to help simplify some of the process. See blitzSimpleFlash
for a fairly easy example, using the binaryTimer
helper to flip a light between two states at regular intervals.
If you've come up with something useful that can be easily re-used by other animations, feel free to add it into
animationhelpers.js
, and it will appear in theCLAnimationHelpers
class for other authors to use if approved.
Additionally, if you need to keep track of any specific value, it is recommended to add a property to this
, prefixed with an underscore, eg. this._myCustomVar = 0
This will allow you to check or update this._myCustomVar
every 'frame'
Your animation code might look something like this:
coolLight(dt, {
speed = 5,
intensity = 5
}) {
/* Example code for a simple flashing light */
/* `speed` controls how quickly the light will flip on and off */
/* `intensity` controls how dim the light will be when it is 'off' */
CLAnimationHelpers.binaryTimer(this, speed); // Use the binaryTimer helper to set `this._flipped` to true/false, based on speed
if (this._flipped) {
// Set the alpha somewhere between 0 and 0.9, depending on intensity
let alpha = 1 - (0.1 * intensity);
this.illumination.uniforms.alpha = alpha; // Update the shader displaying the light emission
this.coloration.uniforms.alpha = alpha; // Update the shader displaying the color of the light
} else {
// Set the alpha back to full
this.illumination.uniforms.alpha = 1;
this.coloration.uniforms.alpha = 1;
}
}
}
The example code above is provided for simplicity, and is not very performant. It also does not respect the Opacity value set on the light, as this directly alters the coloration alpha. There is a more advanced version of this in
modules/animations.js
,blitzSimpleFlash
When you're ready to test, save the file.
Refresh Foundry, and double click on an Ambient Light, or create a new one.
Find your animation in the Light Animation Type
dropdown, and select it.
Save the light and see how your animation looks!
If you want to support translating your light names, descriptions etc., you need to make sure you have a translationName
setup in the light object inside lights.json
, as described in step 1
"ExampleUser": {
...
"lights": [
{
"translationName": "coolLight",
...
}
]
Once you've done this, open up lang/en.json
, or another language file in that dir.
In this file, add your Authors object, with the same spelling and capitalisation as in lights.json
{
"COMMUNITYLIGHTING": {
"authors": {
...,
"ExampleUser": {
}
}
}
}
Inside your Author object, add a new object for each translation-supported light, using the translationName
as the obect name
{
"COMMUNITYLIGHTING": {
"authors": {
...,
"ExampleUser": {
"coolLight": {
}
}
}
}
}
Inside each translateable light, add the properties you wish to translate.
Currently supported properties are name
, description
, intensityDescription
and speedDescription
.
If you add translations here, you don't need to add those same properties in your light object in
lights.json
, but having both shouldn't cause any problems.
{
"COMMUNITYLIGHTING": {
"authors": {
...,
"ExampleUser": {
"coolLight": {
"name": "My Cool Light",
"description": "A basic, but very cool light",
"intensityDescription": "Controls how radical the light will be!",
"speedDescription": "Controls how often the light will be radical."
}
}
}
}
}
And that's it, the module will handle the rest for you.
If you're a polyglot, consider adding more translations for different languages!
Create a Pull Request, targetting the integration
branch.
I'll review your changes as soon as I can, and put your work into the next release.
Initially, I'll try to keep up with attributions in the github.
Eventually, I'm planning a more advanced system inside foundry that will automatically update using the data you added into lights.json
, crediting authors and optionally allowing users to get in touch if they're having issues.
https://raw.githubusercontent.com/BlitzKraig/fvtt-CommunityLighting/master/module.json
- Ability to hide/show animations from the selection UI
- Optional selection UI overhaul - Searchable, categorized
- Full custom shader support
- More animation helpers
- Improved onboarding and documentation
- Support for Advanced Lighting Toolkit (Upcoming module)
This module is open for feedback and suggestions! I would love to improve it and implement new features.
For bugs/feedback, create an issue on GitHub, or contact me on Discord at Blitz#6797
Additionally, light authors can provide their Discord/GitHub contact details, if they so choose. These details can be found by hovering over the animation name in the light config (Not yet implemented).