diff --git a/MaterialDeck.js b/MaterialDeck.js index f3d47f8..e584084 100644 --- a/MaterialDeck.js +++ b/MaterialDeck.js @@ -374,6 +374,11 @@ Hooks.on('closeJournalSheet',()=>{ otherControls.updateAll(); }); +Hooks.on('gmScreenOpenClose',(html,isOpen)=>{ + if (enableModule == false || ready == false) return; + externalModules.updateAll({gmScreen:isOpen}); +}); + Hooks.once('init', ()=>{ //CONFIG.debug.hooks = true; registerSettings(); //in ./src/settings.js diff --git a/README.md b/README.md index f4c70ae..80219ef 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ Instructions and more info can be found in the window.location.reload() }); @@ -50,6 +50,13 @@ export const registerSettings = function() { }); + //Create the Help button + game.settings.registerMenu(MODULE.moduleName, 'helpMenu',{ + name: "MaterialDeck.Sett.Help", + label: "MaterialDeck.Sett.Help", + type: helpMenu, + restricted: true + }); /** * Playlist soundboard */ @@ -110,3 +117,45 @@ export const registerSettings = function() { restricted: true }); } + +export class helpMenu extends FormApplication { + constructor(data, options) { + super(data, options); + } + + /** + * Default Options for this FormApplication + */ + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + id: "helpMenu", + title: "Material Deck: "+game.i18n.localize("MaterialDeck.Sett.Help"), + template: "./modules/MaterialDeck/templates/helpMenu.html", + width: "500px" + }); + } + + /** + * Provide data to the template + */ + getData() { + + return { + + } + } + + /** + * Update on form submit + * @param {*} event + * @param {*} formData + */ + async _updateObject(event, formData) { + + } + + activateListeners(html) { + super.activateListeners(html); + + } + } diff --git a/src/token.js b/src/token.js index f177f6d..b70faba 100644 --- a/src/token.js +++ b/src/token.js @@ -4,6 +4,7 @@ import {streamDeck} from "../MaterialDeck.js"; export class TokenControl{ constructor(){ this.active = false; + this.wildcardOffset = 0; } async update(tokenId){ @@ -15,7 +16,7 @@ export class TokenControl{ } } - pushData(tokenId,settings,context,ring=0,ringColor='#000000'){ + async pushData(tokenId,settings,context,ring=0,ringColor='#000000'){ let name = false; let icon = false; let stats = settings.stats; @@ -260,6 +261,40 @@ export class TokenControl{ iconSrc = ""; overlay = true; } + else if (settings.onClick == 'wildcard') { //wildcard images + if (icon == false) return; + const method = settings.wildcardMethod ? settings.wildcardMethod : 'iterate'; + let value = parseInt(settings.wildcardValue); + if (isNaN(value)) value = 1; + + const images = await token.actor.getTokenImages(); + let currentImgNr = 0 + let imgNr; + for (let i=0; i= images.length) imgNr -= images.length; + while (imgNr < 0) imgNr += images.length; + iconSrc = images[imgNr]; + } + else if (method == 'set'){ + imgNr = value - 1 + this.wildcardOffset; + if (value >= images.length) iconSrc = "modules/MaterialDeck/img/black.png"; + else iconSrc = images[imgNr]; + ring = 1; + if (currentImgNr == imgNr) { + ring = 2; + ringColor = "#FF7B00"; + } + } + else return; + + } } else { iconSrc += ""; @@ -461,7 +496,6 @@ export class TokenControl{ animation.speed = animationSpeed; } data.lightAnimation = animation; - token.update(data); } else if (system == 'demonlord' && game.system.id == 'demonlord' && onClick == 'initiative'){ @@ -470,6 +504,172 @@ export class TokenControl{ }) } + else if (settings.onClick == 'wildcard') { //wildcard images + const method = settings.wildcardMethod ? settings.wildcardMethod : 'iterate'; + let value = parseInt(settings.wildcardValue); + if (isNaN(value)) value = 1; + + const images = await token.actor.getTokenImages(); + let imgNr; + let iconSrc; + if (method == 'iterate'){ + let currentImgNr = 0 + for (let i=0; i= images.length) imgNr -= images.length; + while (imgNr < 0) imgNr += images.length; + } + else if (method == 'set'){ + imgNr = value - 1 + this.wildcardOffset; + if (value >= images.length || value < 1) return; + + } + else if (method == 'offset'){ + this.wildcardOffset = value; + this.update(MODULE.selectedTokenId); + } + else return; + + iconSrc = images[imgNr]; + token.update({img: iconSrc}) + } + else if (settings.onClick == 'custom') {//custom onClick function + const formula = settings.customOnClickFormula ? settings.customOnClickFormula : ''; + if (formula == '') return; + + let targetArrayTemp; + let formulaArrayTemp; + let split1 = formula.split(';'); + for (let i=0; i= val) {value = val-1;} + else if (previousOperation == '>' && value <= val) {value = val+1;} + else if (previousOperation == '<=' && value > val) {value = val;} + else if (previousOperation == '>=' && value < val) {value = val;} + } + } + + for (let i=0; i0 && split[i][0] != '@' && split[i] != "" && isNaN(split[i])) split[i] = '['+split[i] + const split2 = split[i].split(']'); + for (let j=0; j + +
+

Introduction

+ Material Deck is a Foundry VTT module that allows you to control certain Foundry functions using an Elgato Stream Deck. + A Stream Deck is a device that has physical buttons with displays behind them. Material Deck uses this to, for example, + control playlists, execute macros, display and control the combat tracker.

+ The module allows a high degree of customization, where each button on the Stream Deck can be assigned any desired function. + Furthermore, it supports folder structures, allowing easy switching between various button configurations so you can easily switch + between the combat tracker, soundboard, or any other (custom) configuration.
+
+ Material Deck is a very large module with tons of features and ways of customizing your experience. This menu will only cover the basics to get you started, + the full documentation can be found on
Github. Please also check the FAQ which answers some common questions, including some basic troubleshooting.
+ +

Latest Releases

+ Module
+ Stream Deck
+ Server
+ +

Getting Started

+ Besides installing this module, you also need to install and run some other things. + +

Installing the Stream Deck Software and Plugin

+
    +
  1. Download and install the Stream Deck software
  2. +
  3. Download the latest plugin file (com.cdeenen.materialdeck.streamDeckPlugin) from here
  4. +
  5. Double-click the file, this should open the Stream Deck software
  6. +
  7. Press 'Install' in the pop-up
  8. +
+ +

Installing the Stream Deck Profile (optional)

+ You can create your own profile, but it is recommended to start with one of the pre-made profiles. Currently, there is a profile for the normal and XL Stream Deck variants. +
    +
  1. Download the latest profile (ending with .streamDeckProfile) from here
  2. +
  3. Double-click the file, this should load the profile into the Stream Deck software
  4. +
+ +

Downloading and Starting Material Server

+ Material Server acts as a bridge application, bridging the communication between the Stream Deck and Material Deck. +
    +
  1. Download the latest version for your operating system here
  2. +
  3. Download and install the prerequisites
  4. +
  5. Extract the archive
  6. +
  7. Double-click the file to start the server
  8. +
+ You need to always have Material Server running when you want to use Material Deck +
+
+ After setting up the module settings I suggest you just play around with one of the profiles to see that happens when you press buttons and do things in Foundry. + Most things should be pretty self explanatory. After that you could look into customizing your experience, as you can read about below. + +

Module Setup

+ + There are four buttons at the top: + + The help button leads you to the page you are currently reading, the other buttons will be explained below.
+
+ Below the buttons you will find the following settings: + + +

Playlist Configuration

+ + The playlist configuration screen configures the playlists that you control using the Playlist action.
+ There are 2 sections: 'Settings', and 'Playlists'. + +

Settings

+

Default Play Mode

+ The play mode determines what to do when a track is playing, while another track is requested. By setting it to 'Unrestricted', you can play as many tracks at the same time as you want. Setting it to 'One track per playlist' will automatically stop all playing tracks in the playlist, ensuring that only one track is playing at a time. Setting 'Play Method' to 'One track in total' will limit playback to only one track in total.
+ This setting sets the default play mode, which can be overridden for each separate playlist, which will be discussed below.
+
+ Options: + + Note: This play method only applies if tracks are started using the Stream Deck, you can still play more tracks using Foundry's internal audio player. + +

Number of Playlists

+ This sets the number of playlists that will be displayed. You can make this number as high or low as you want. This only changes the amount of playlists + that are displayed, not the amount of playlists that can be controlled (there is no upper limit, as long as Foundry doesn't crash). + +

Playlists

+ Here you can select which playlists can be controlled with the module. You can manage as many playlists as you've set at 'Number of playlists', + where the playlist number corresponds with the number you have to fill in in the property inspector (see below).
+ For each playlist you can set the play mode, which overrides the default play mode for that specific playlist.
+
+ Note: While you can assign the same playlist to multiple playlists in this configuration screen, only the play method of the first instance will be applied. + +

Macro Configuration

+ The Macro Configuration screen is to configure the macro board for the Macro action.
+
+ The screen is divided into a number of boxes, each labeled 'Macro #', where each represents a single macro and its settings. The number of macros you can see + depends on what Stream Deck model you've set up in the module configuration.
+
+ For each macro there are 3 options: + + + + +

Soundboard Configuration

+ The Soundboard Configuration screen is used to configure the soundboard for the Soundboard action.
+
+ Similar to the Macro Configuration screen, the screen is divided into a number of boxes, each labeled 'Sound #', where each represents a single sound and its settings. + The number of sounds you can see depends on what Stream Deck model you've set up in the module configuration.
+
+ For each sound there are multiple options: + + + + +

Customization

+ Material Deck is extremely flexible, but most of this flexibility must be performed in the Stream Deck software.
+ Some basic instructions on using the software can be found here.
+
+ Some of the things you can change are: + + All the buttons have many settings to fine-tune your experience. Due to the large amount of things you can change, they will not be discussed here, instead you can read about it at the following links: + + +

Software Versions & Module Incompatibilities

+ Foundry VTT: Tested on 0.7.9
+ Module Incompatibilities: None known.
+ +

Feedback

+ If you have any suggestions or bugs to report, feel free to create an issue, contact me on Discord (Cris#6864), or send me an email: cdeenen@outlook.com. + +

Credits

+ Author: Cristian Deenen (Cris#6864 on Discord)
+
+ Special thanks to Asmodeus#7588 who made this module possible by generously donating a Stream Deck XL +
+ Please consider supporting me on Patreon, and feel free to join the Material Foundry Discord server. +
+ \ No newline at end of file diff --git a/wiki/img/ModuleSettings.png b/wiki/img/ModuleSettings.png index 0cc4a46..5b55dc6 100644 Binary files a/wiki/img/ModuleSettings.png and b/wiki/img/ModuleSettings.png differ diff --git a/wiki/img/SoundboardConfig.png b/wiki/img/SoundboardConfig.png index 601a0b3..6c09587 100644 Binary files a/wiki/img/SoundboardConfig.png and b/wiki/img/SoundboardConfig.png differ