v1.3.1
This commit is contained in:
@@ -118,7 +118,7 @@ async function analyzeWSmessage(msg){
|
||||
}
|
||||
|
||||
else if (event == 'willDisappear'){
|
||||
streamDeck.clearContext(action,coordinates);
|
||||
streamDeck.clearContext(action,coordinates,context);
|
||||
}
|
||||
|
||||
else if (event == 'keyDown'){
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<b>Note:</b><br>
|
||||
At the moment Windows and OSX are supported. Linux has been reported to work, there is no official Linux support for the Stream Deck, but there exist a 3rd party <a href="https://timothycrosley.com/project-7-streamdeck_ui">Stream Deck UI</a> that appears be compatible. To get it working on Linux requires more work, and help I can personally offer is limited.<br>
|
||||
The module works on the native Foundry application, Chrome and Firefox. Safari (you'll need the latest dev version to get Foundry to work on it) doesn't work if your Foundry server is secured, unless you use something like Nginx with which I cannot help you.<br>
|
||||
<b>Note:</b> At the moment Windows and OSX support has been confirmed. Linux support is unknown, there is no official Linux support for the Stream Deck, but there exist a 3rd party <a href="https://timothycrosley.com/project-7-streamdeck_ui">Stream Deck UI</a> that might be compatible.<br>
|
||||
<b>In any case: Proceed at your own risk, I will not take any responsibility if you spent money and the module doesn't work!</b>
|
||||
|
||||
<b>Please read the documentation carefully, especially if you want to modify the default profile!</b>
|
||||
@@ -74,7 +72,7 @@ Module manifest: https://raw.githubusercontent.com/CDeenen/MaterialDeck/Master/m
|
||||
|
||||
## Software Versions & Module Incompatibilities
|
||||
<b>Foundry VTT:</b> Tested on 0.7.9<br>
|
||||
<b>Module Incompatibilities:</b> Combat Utility Belt conditions do not work with the Token Action.<br>
|
||||
<b>Module Incompatibilities:</b> None known.<br>
|
||||
|
||||
## 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.
|
||||
|
||||
21
changelog.md
21
changelog.md
@@ -1,4 +1,25 @@
|
||||
# Changelog Material Deck Module
|
||||
### v1.3.1 - 27-02-2021
|
||||
Additions:
|
||||
<ul>
|
||||
<li>Token Action & Move Action: You can now choose what token should be targeted with the action using: 'Selected Token', 'Token Name', 'Actor Name', 'Token Id' or 'Actor Id'. Added relevant user permissions to the permission configuration</li>
|
||||
<li>Token Action => On Click: Added options 'Select Token' and 'Center on Token and Select Token'</li>
|
||||
<li>Playlist Action: Added relative offset mode, with the option to display the offset target name for playlists</li>
|
||||
<li>Playlist Action => Stop All: Added option to display the name of the playlist at the current offset</li>
|
||||
</ul>
|
||||
|
||||
Fixes:
|
||||
<ul>
|
||||
<li>Default user permissions would not be loaded if no previously saved permissions were present, resulting in MD assuming nobody has any permissions</li>
|
||||
<li>Other Actions => Control Buttons => Lighting Controls: Would create a button for ambient sound instead of lighting</li>
|
||||
<li>Token Action => Display Token Icon: It used to show the icon, even if unchecked, if no stat with default icon was selected</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<b>Compatible server app and SD plugin:</b><br>
|
||||
Material Server v1.0.2 (unchanged): https://github.com/CDeenen/MaterialServer/releases <br>
|
||||
SD plugin v1.3.1 (<b>must be updated!</b>): https://github.com/CDeenen/MaterialDeck_SD/releases<br>
|
||||
|
||||
### v1.3.0 - 25-02-2021
|
||||
Additions:
|
||||
<ul>
|
||||
|
||||
@@ -164,6 +164,10 @@
|
||||
"MaterialDeck.Perm.TOKEN.CONDITIONS.label": "Set Conditions",
|
||||
"MaterialDeck.Perm.TOKEN.CONDITIONS.hint": "Allow the users to set conditions for the controlled token",
|
||||
"MaterialDeck.Perm.TOKEN.CUSTOM.label": "Custom On-Click",
|
||||
"MaterialDeck.Perm.TOKEN.CUSTOM.hint": "Allow the users to set custom on-click functions"
|
||||
"MaterialDeck.Perm.TOKEN.CUSTOM.hint": "Allow the users to set custom on-click functions",
|
||||
"MaterialDeck.Perm.TOKEN.NON_OWNED.label": "Non-Owned and Non-Observer Tokens",
|
||||
"MaterialDeck.Perm.TOKEN.NON_OWNED.hint": "Allow users access to tokens with non-owned or limited permission",
|
||||
"MaterialDeck.Perm.TOKEN.OBSERVER.label": "Observer",
|
||||
"MaterialDeck.Perm.TOKEN.OBSERVER.hint": "Allow users access to tokens with observer permission"
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"name": "MaterialDeck",
|
||||
"title": "Material Deck",
|
||||
"description": "Material Deck allows you to control Foundry using an Elgato Stream Deck",
|
||||
"version": "1.3.0",
|
||||
"minimumSDversion": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"minimumSDversion": "1.3.1",
|
||||
"minimumMSversion": "1.0.2",
|
||||
"author": "CDeenen",
|
||||
"esmodules": [
|
||||
|
||||
101
src/playlist.js
101
src/playlist.js
@@ -23,38 +23,30 @@ export class PlaylistControl{
|
||||
return;
|
||||
}
|
||||
this.active = true;
|
||||
if (settings.playlistMode == undefined) settings.playlistMode = 'playlist';
|
||||
if (settings.playlistMode == 'playlist'){
|
||||
const mode = settings.playlistMode ? settings.playlistMode : 'playlist';
|
||||
if (mode == 'playlist'){
|
||||
this.updatePlaylist(settings,context);
|
||||
}
|
||||
else if (settings.playlistMode == 'track'){
|
||||
else if (mode == 'track'){
|
||||
this.updateTrack(settings,context);
|
||||
}
|
||||
else {
|
||||
let src = 'modules/MaterialDeck/img/playlist/stop.png';
|
||||
if (game.playlists.playing.length > 0)
|
||||
streamDeck.setIcon(context,src,settings.background,2,'#00FF00',true);
|
||||
else
|
||||
streamDeck.setIcon(context,src,settings.background,1,'#000000',true);
|
||||
const src = 'modules/MaterialDeck/img/playlist/stop.png';
|
||||
const ringColor = (game.playlists.playing.length > 0) ? '#00FF00' : '#000000';
|
||||
const ring = (game.playlists.playing.length > 0) ? 2 : 1;
|
||||
const txt = settings.displayPlaylistName ? this.getPlaylist(this.playlistOffset).name : '';
|
||||
streamDeck.setIcon(context,src,settings.background,ring,ringColor,true);
|
||||
streamDeck.setTitle(txt,context);
|
||||
}
|
||||
}
|
||||
|
||||
updatePlaylist(settings,context){
|
||||
let name = "";
|
||||
|
||||
let background = settings.background;
|
||||
if(background == undefined) background = '#000000';
|
||||
|
||||
let ringColor = "#000000"
|
||||
|
||||
let ringOffColor = settings.offRing;
|
||||
if (ringOffColor == undefined) ringOffColor = '#FF0000';
|
||||
|
||||
let ringOnColor = settings.onRing;
|
||||
if (ringOnColor == undefined) ringOnColor = '#00FF00';
|
||||
|
||||
let playlistType = settings.playlistType;
|
||||
if (playlistType == undefined) playlistType = 'playStop';
|
||||
const background = settings.background ? settings.background : '#000000';
|
||||
const ringOffColor = settings.offRing ? settings.offRing : '#FF0000';
|
||||
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
|
||||
const playlistType = settings.playlistType ? settings.playlistType : 'playStop';
|
||||
|
||||
//Play/Stop
|
||||
if (playlistType == 'playStop'){
|
||||
@@ -79,26 +71,28 @@ export class PlaylistControl{
|
||||
if (isNaN(playlistOffset)) playlistOffset = 0;
|
||||
if (playlistOffset == this.playlistOffset) ringColor = ringOnColor;
|
||||
}
|
||||
//Relative Offset
|
||||
else if (playlistType == 'relativeOffset') {
|
||||
let playlistOffset = parseInt(settings.offset);
|
||||
if (isNaN(playlistOffset)) playlistOffset = 0;
|
||||
let number = parseInt(this.playlistOffset + playlistOffset);
|
||||
const nrOfPlaylists = parseInt(game.settings.get(MODULE.moduleName,'playlists').playlistNumber);
|
||||
if (number < 0) number += nrOfPlaylists;
|
||||
else if (number > nrOfPlaylists) number -= nrOfPlaylists;
|
||||
const targetPlaylist = this.getPlaylist(number);
|
||||
if (targetPlaylist != undefined) name = targetPlaylist.name;
|
||||
}
|
||||
streamDeck.setIcon(context,"",background,2,ringColor);
|
||||
streamDeck.setTitle(name,context);
|
||||
}
|
||||
|
||||
updateTrack(settings,context){
|
||||
let name = "";
|
||||
|
||||
let background = settings.background;
|
||||
if(background == undefined) background = '#000000';
|
||||
|
||||
let ringColor = "#000000"
|
||||
|
||||
let ringOffColor = settings.offRing;
|
||||
if (ringOffColor == undefined) ringOffColor = '#FF0000';
|
||||
|
||||
let ringOnColor = settings.onRing;
|
||||
if (ringOnColor == undefined) ringOnColor = '#00FF00';
|
||||
|
||||
let playlistType = settings.playlistType;
|
||||
if (playlistType == undefined) playlistType = 'playStop';
|
||||
const background = settings.background ? settings.background : '#000000';
|
||||
const ringOffColor = settings.offRing ? settings.offRing : '#FF0000';
|
||||
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
|
||||
const playlistType = settings.playlistType ? settings.playlistType : 'playStop';
|
||||
|
||||
//Play/Stop
|
||||
if (playlistType == 'playStop'){
|
||||
@@ -125,11 +119,14 @@ export class PlaylistControl{
|
||||
}
|
||||
}
|
||||
//Offset
|
||||
else {
|
||||
else if (playlistType == 'offset') {
|
||||
let trackOffset = parseInt(settings.offset);
|
||||
if (isNaN(trackOffset)) trackOffset = 0;
|
||||
if (trackOffset == this.trackOffset) ringColor = ringOnColor;
|
||||
}
|
||||
//Relative Offset
|
||||
else if (playlistType == 'relativeOffset') {
|
||||
}
|
||||
streamDeck.setIcon(context,"",background,2,ringColor);
|
||||
streamDeck.setTitle(name,context);
|
||||
}
|
||||
@@ -179,16 +176,17 @@ export class PlaylistControl{
|
||||
trackNr--;
|
||||
trackNr += this.trackOffset;
|
||||
|
||||
if (settings.playlistMode == undefined) settings.playlistMode = 'playlist';
|
||||
if (settings.playlistType == undefined) settings.playlistType = 'playStop';
|
||||
if (settings.playlistMode == 'stopAll') {
|
||||
const playlistMode = settings.playlistMode ? settings.playlistMode : 'playlist';
|
||||
const playlistType = settings.playlistType ? settings.playlistType : 'playStop';
|
||||
|
||||
if (playlistMode == 'stopAll') {
|
||||
this.stopAll(true);
|
||||
}
|
||||
else {
|
||||
if (settings.playlistType == 'playStop') {
|
||||
if (playlistType == 'playStop') {
|
||||
let playlist = this.getPlaylist(playlistNr);
|
||||
if (playlist != undefined){
|
||||
if (settings.playlistMode == 'playlist')
|
||||
if (playlistMode == 'playlist')
|
||||
this.playPlaylist(playlist,playlistNr);
|
||||
else {
|
||||
let track = playlist.data.sounds[trackNr];
|
||||
@@ -198,17 +196,34 @@ export class PlaylistControl{
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (settings.playlistMode == 'playlist') {
|
||||
else if (playlistType == 'offset'){
|
||||
if (playlistMode == 'playlist') {
|
||||
this.playlistOffset = parseInt(settings.offset);
|
||||
if (isNaN(this.playlistOffset)) this.playlistOffset = 0;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
this.trackOffset = parseInt(settings.offset);
|
||||
if (isNaN(this.trackOffset)) this.trackOffset = 0;
|
||||
}
|
||||
this.updateAll();
|
||||
}
|
||||
else if (playlistType == 'relativeOffset'){
|
||||
if (playlistMode == 'playlist') {
|
||||
let playlistOffset = parseInt(settings.offset);
|
||||
if (isNaN(playlistOffset)) playlistOffset = 0;
|
||||
let number = parseInt(this.playlistOffset + playlistOffset);
|
||||
const nrOfPlaylists = parseInt(game.settings.get(MODULE.moduleName,'playlists').playlistNumber);
|
||||
if (number < 0) number += nrOfPlaylists;
|
||||
else if (number > nrOfPlaylists) number -= nrOfPlaylists;
|
||||
this.playlistOffset = number;
|
||||
}
|
||||
else {
|
||||
let value = parseInt(settings.offset);
|
||||
if (isNaN(value)) return;
|
||||
this.trackOffset += value;
|
||||
}
|
||||
this.updateAll();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,11 +60,13 @@ const defaultUserPermissions = {
|
||||
VISION: [false,true,true,true],
|
||||
WILDCARD: [false,true,true,true],
|
||||
CONDITIONS: [false,true,true,true],
|
||||
CUSTOM: [false,false,true,true]
|
||||
CUSTOM: [false,false,true,true],
|
||||
NON_OWNED: [false,false,true,true],
|
||||
OBSERVER: [false,true,true,true]
|
||||
}
|
||||
}
|
||||
|
||||
export const registerSettings = function() {
|
||||
export const registerSettings = async function() {
|
||||
/**
|
||||
* Main settings
|
||||
*/
|
||||
@@ -75,7 +77,7 @@ export const registerSettings = function() {
|
||||
name: "MaterialDeck.Sett.Enable",
|
||||
scope: "client",
|
||||
config: true,
|
||||
default: true,
|
||||
default: false,
|
||||
type: Boolean,
|
||||
onChange: x => window.location.reload()
|
||||
});
|
||||
@@ -195,6 +197,21 @@ export const registerSettings = function() {
|
||||
type: soundboardConfigForm,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
let permissionSettings = game.settings.get(MODULE.moduleName,'userPermission');
|
||||
if (permissionSettings == undefined || permissionSettings == null || MODULE.isEmpty(permissionSettings)) {
|
||||
permissionSettings = {
|
||||
enable: defaultEnable,
|
||||
permissions: defaultUserPermissions
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (permissionSettings.permissions.TOKEN.NON_OWNED == undefined) permissionSettings.permissions.TOKEN.NON_OWNED = [false,false,true,true];
|
||||
if (permissionSettings.permissions.TOKEN.OBSERVER == undefined) permissionSettings.permissions.TOKEN.OBSERVER = [false,true,true,true];
|
||||
}
|
||||
game.settings.set(MODULE.moduleName,'userPermission',permissionSettings);
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class helpMenu extends FormApplication {
|
||||
|
||||
52
src/token.js
52
src/token.js
@@ -7,7 +7,7 @@ export class TokenControl{
|
||||
this.wildcardOffset = 0;
|
||||
}
|
||||
|
||||
async update(tokenId){
|
||||
async update(tokenId=null){
|
||||
if (this.active == false) return;
|
||||
for (let i=0; i<32; i++){
|
||||
const data = streamDeck.buttonContext[i];
|
||||
@@ -21,14 +21,35 @@ export class TokenControl{
|
||||
const icon = settings.displayIcon ? settings.displayIcon : false;
|
||||
const background = settings.background ? settings.background : "#000000";
|
||||
let stats = settings.stats ? settings.stats : 'none';
|
||||
const selection = settings.selection ? settings.selection : 'selected';
|
||||
const tokenIdentifier = settings.tokenName ? settings.tokenName : '';
|
||||
|
||||
let validToken = false;
|
||||
let token;
|
||||
if (selection == 'selected') token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
||||
else if (selection != 'selected' && tokenIdentifier == '') {}
|
||||
else if (selection == 'tokenName') token = canvas.tokens.children[0].children.find(p => p.name == tokenIdentifier);
|
||||
else if (selection == 'actorName') token = canvas.tokens.children[0].children.find(p => p.actor.name == tokenIdentifier);
|
||||
else if (selection == 'tokenId') token = canvas.tokens.children[0].children.find(p => p.id == tokenIdentifier);
|
||||
else if (selection == 'actorId') token = canvas.tokens.children[0].children.find(p => p.actor.id == tokenIdentifier);
|
||||
|
||||
if (token != undefined) validToken = true;
|
||||
|
||||
let tokenName = "";
|
||||
let txt = "";
|
||||
let iconSrc = "";
|
||||
let overlay = false;
|
||||
let statsOld;
|
||||
if (tokenId != undefined) {
|
||||
const token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
||||
if (validToken) {
|
||||
if (token.owner == false && token.observer == true && MODULE.getPermission('TOKEN','OBSERVER') == false ) {
|
||||
streamDeck.noPermission(context);
|
||||
return;
|
||||
}
|
||||
if (token.owner == false && token.observer == false && MODULE.getPermission('TOKEN','NON_OWNED') == false ) {
|
||||
streamDeck.noPermission(context);
|
||||
return;
|
||||
}
|
||||
|
||||
tokenName = token.data.name;
|
||||
if (name) txt += tokenName;
|
||||
if (name && stats != 'none') txt += "\n";
|
||||
@@ -49,7 +70,7 @@ export class TokenControl{
|
||||
stats = 'none';
|
||||
}
|
||||
|
||||
iconSrc = token.data.img;
|
||||
if (icon) iconSrc = token.data.img;
|
||||
|
||||
if (stats == 'custom'){
|
||||
const custom = settings.custom ? settings.custom : '';
|
||||
@@ -432,20 +453,39 @@ export class TokenControl{
|
||||
}
|
||||
|
||||
async keyPress(settings){
|
||||
if (MODULE.selectedTokenId == undefined) return;
|
||||
const tokenId = MODULE.selectedTokenId;
|
||||
|
||||
const token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
||||
const selection = settings.selection ? settings.selection : 'selected';
|
||||
const tokenIdentifier = settings.tokenName ? settings.tokenName : '';
|
||||
|
||||
let token;
|
||||
if (selection == 'selected') token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
||||
else if (selection != 'selected' && tokenIdentifier == '') {}
|
||||
else if (selection == 'tokenName') token = canvas.tokens.children[0].children.find(p => p.name == tokenIdentifier);
|
||||
else if (selection == 'actorName') token = canvas.tokens.children[0].children.find(p => p.actor.name == tokenIdentifier);
|
||||
else if (selection == 'tokenId') token = canvas.tokens.children[0].children.find(p => p.id == tokenIdentifier);
|
||||
else if (selection == 'actorId') token = canvas.tokens.children[0].children.find(p => p.actor.id == tokenIdentifier);
|
||||
|
||||
if (token == undefined) return;
|
||||
if (token.owner == false && token.observer == true && MODULE.getPermission('TOKEN','OBSERVER') == false ) return;
|
||||
if (token.owner == false && token.observer == false && MODULE.getPermission('TOKEN','NON_OWNED') == false ) return;
|
||||
|
||||
const onClick = settings.onClick ? settings.onClick : 'doNothing';
|
||||
|
||||
if (onClick == 'doNothing') //Do nothing
|
||||
return;
|
||||
else if (onClick == 'select'){ //select token
|
||||
token.control();
|
||||
}
|
||||
else if (onClick == 'center'){ //center on token
|
||||
let location = token.getCenter(token.x,token.y);
|
||||
canvas.animatePan(location);
|
||||
}
|
||||
else if (onClick == 'centerSelect'){ //center on token and select
|
||||
const location = token.getCenter(token.x,token.y);
|
||||
canvas.animatePan(location);
|
||||
token.control();
|
||||
}
|
||||
else if (onClick == 'charSheet'){ //Open character sheet
|
||||
const element = document.getElementById(token.actor.sheet.id);
|
||||
if (element == null) token.actor.sheet.render(true);
|
||||
|
||||
Reference in New Issue
Block a user