Skip to content

Commit 1157061

Browse files
committed
Remove system control from scene controls
- move system control tools to right above the player list - move combat hud controls to combat tracker
1 parent 57fa72b commit 1157061

File tree

8 files changed

+190
-113
lines changed

8 files changed

+190
-113
lines changed

module/documents/items/classFeature/invoker/invoker-integration.mjs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,25 +57,27 @@ const renderApp = () => (gameWellspringManager ??= new GameWellspringManager()).
5757

5858
const regExp = /^\/(ws|wellsprings?)$/i;
5959

60-
function onChatMessage(chatLog, message, data) {
60+
function onChatMessage(chatLog, message) {
6161
if (game.user.isGM && regExp.test(message)) {
6262
renderApp();
6363
return false;
6464
}
6565
}
6666

67-
function initialize() {
68-
const name = GameWellspringManager.name;
69-
Hooks.on(SystemControls.HOOK_GET_SYSTEM_TOOLS, (tools) => {
70-
tools[name] = {
71-
name: name,
72-
title: 'FU.ClassFeatureInvocationsWellspringManagerTitle',
73-
icon: 'fas fa-earth-asia',
74-
button: true,
75-
visible: game.user.isGM,
76-
onChange: () => renderApp(),
77-
};
67+
/**
68+
* @param {SystemControlTool[]} tools
69+
*/
70+
function onGetSystemTools(tools) {
71+
tools.push({
72+
name: 'FU.ClassFeatureInvocationsWellspringManagerTitle',
73+
icon: 'fas fa-earth-asia',
74+
visible: game.user.isGM,
75+
onClick: () => renderApp(),
7876
});
77+
}
78+
79+
function initialize() {
80+
Hooks.on(SystemControls.HOOK_GET_SYSTEM_TOOLS, onGetSystemTools);
7981

8082
Hooks.on('projectfu.actor.dataPrepared', ActorWellspringManager.onActorPrepared);
8183

module/helpers/system-controls.mjs

Lines changed: 43 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,62 @@
11
import { SYSTEM } from './config.mjs';
22

33
/**
4-
* @typedef SceneControlTool
5-
* The data structure for a single tool in the {@link SceneControl#tools} record.
4+
* @typedef SystemControlTool
65
* @property {string} name
7-
* @property {number} order
8-
* @property {string} title
96
* @property {string} icon
107
* @property {boolean} [visible]
118
* @property {boolean} [toggle]
129
* @property {boolean} [active]
13-
* @property {boolean} [button]
14-
* @property {(event: Event, active: boolean) => void} [onChange] A callback invoked when the tool is activated
15-
* or deactivated
16-
* @property {ToolclipConfiguration} [toolclip] Configuration for rendering the tool's toolclip
10+
* @property {(event: Event, active: boolean) => void} [onClick]
1711
*/
1812

19-
/**
20-
* @typedef SceneControl
21-
* The data structure for a set of controls in the {@link SceneControls#controls} record.
22-
* @property {string} name
23-
* @property {number} order
24-
* @property {string} title
25-
* @property {string} icon
26-
* @property {boolean} [visible]
27-
* @property {Record<string, SceneControlTool>} tools
28-
* @property {string} activeTool
29-
* @property {(event: Event, active: boolean) => void} [onChange]
30-
* A callback invoked when control set is activated or deactivated
31-
* @property {(event: Event, tool: SceneControlTool) => void} [onToolChange]
32-
* A callback invoked when the active tool changes
33-
*/
34-
35-
/**
36-
* @param {Record<string, SceneControl>} controls
37-
* @remarks {@link https://foundryvtt.com/api/v13/classes/foundry.applications.ui.SceneControls.html#controls}
38-
*/
39-
function initializeSystemControl(controls) {
40-
/** @type SceneControlTool[] */
41-
const tools = {};
42-
43-
Hooks.callAll(SystemControls.HOOK_GET_SYSTEM_TOOLS, tools);
44-
45-
controls[SYSTEM] = {
46-
name: SYSTEM,
47-
title: 'FU.UiControlTitle',
48-
icon: 'fus-star2',
49-
tools: tools,
50-
activeTool: '',
51-
onChange: (event, active) => {},
52-
layer: SYSTEM,
53-
};
54-
}
55-
5613
// Register the hook into Foundry
5714
let initialized;
58-
class SystemControlsLayer extends foundry.canvas.layers.InteractionLayer {}
5915
export const SystemControls = Object.freeze({
6016
initialize() {
6117
if (!initialized) {
62-
initialized = true;
63-
CONFIG.Canvas.layers[SYSTEM] = {
64-
layerClass: SystemControlsLayer,
65-
group: 'interface',
66-
};
18+
Hooks.on('renderPlayers', (app, element) => {
19+
const containerElement = document.createElement('div');
20+
containerElement.classList.add('system-controls');
21+
22+
/** @type {SystemControlTool[]} */
23+
const systemTools = [];
24+
Hooks.callAll(SystemControls.HOOK_GET_SYSTEM_TOOLS, systemTools);
25+
26+
const menuItems = systemTools
27+
.filter((tool) => tool.visible !== false)
28+
.map((tool) => {
29+
const toolButton = document.createElement('button');
30+
toolButton.type = 'button';
31+
toolButton.classList.add('control', 'ui-control');
32+
toolButton.innerHTML = `<i class="${tool.icon}"></i>`;
33+
toolButton.dataset.tooltip = game.i18n.localize(tool.name);
34+
toolButton.dataset.tooltipDirection = game.tooltip.constructor.TOOLTIP_DIRECTIONS.UP;
35+
36+
if (tool.toggle) {
37+
let active = tool.active;
38+
toolButton.classList.add('toggle');
39+
toolButton.ariaPressed = active;
40+
toolButton.addEventListener('click', (e) => {
41+
active = !active;
42+
toolButton.ariaPressed = active;
43+
if (tool.onClick) {
44+
tool.onClick(e, active);
45+
}
46+
});
47+
} else {
48+
if (tool.onClick) {
49+
toolButton.addEventListener('click', (e) => {
50+
tool.onClick(e, false);
51+
});
52+
}
53+
}
54+
return toolButton;
55+
});
6756

68-
Hooks.on('getSceneControlButtons', initializeSystemControl);
57+
containerElement.append(...menuItems);
58+
element.prepend(containerElement);
59+
});
6960
}
7061
},
7162
HOOK_GET_SYSTEM_TOOLS: `${SYSTEM}.getSystemControlTools`,

module/sheets/actor-party-sheet.mjs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ export class FUPartySheet extends FUActorSheet {
332332
* @param {HTMLElement} target The capturing HTML element which defined a [data-action]
333333
* @returns {Promise<void>}
334334
*/
335-
static async #revealMetaCurrency(event, target) {
335+
static async #revealMetaCurrency() {
336336
MetaCurrencyTrackerApplication.renderApp();
337337
}
338338

@@ -603,22 +603,20 @@ export class FUPartySheet extends FUActorSheet {
603603
*/
604604

605605
// Set up sidebar menu option
606-
Hooks.on(SystemControls.HOOK_GET_SYSTEM_TOOLS, (tools) => {
607-
const name = 'FU.Party';
608-
tools[name] = {
609-
name: name,
610-
title: 'FU.Party',
606+
Hooks.on(SystemControls.HOOK_GET_SYSTEM_TOOLS, onGetSystemTools);
607+
608+
/**
609+
* @param {SystemControlTool[]} tools
610+
*/
611+
function onGetSystemTools(tools) {
612+
tools.push({
613+
name: 'FU.Party',
611614
icon: 'fa-solid fa fa-users',
612-
button: true,
613-
active: false,
614-
toggle: false,
615-
onChange: (event, active) => {
616-
if (active) {
617-
FUPartySheet.toggleActive();
618-
}
615+
onClick: () => {
616+
FUPartySheet.toggleActive();
619617
},
620-
};
621-
});
618+
});
619+
}
622620

623621
/**
624622
* @param {StudyEvent} ev
@@ -665,7 +663,7 @@ async function onRenderChatMessage(message, html) {
665663
for (const el of elements) {
666664
el.addEventListener(
667665
'click',
668-
async (event) => {
666+
async () => {
669667
const uuid = el.dataset.uuid;
670668
const party = await FUPartySheet.getActive();
671669
return party.sheet.revealNpc(uuid);

module/ui/combat-hud.mjs

Lines changed: 76 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,67 @@
11
import { SETTINGS } from '../settings.js';
2-
import { SystemControls } from '../helpers/system-controls.mjs';
32
import { SYSTEM } from '../helpers/config.mjs';
43
import { FUHooks } from '../hooks.mjs';
54
import { FUCombat } from './combat.mjs';
65
import { FUPartySheet } from '../sheets/actor-party-sheet.mjs';
76
import { systemTemplatePath } from '../helpers/system-utils.mjs';
87

98
Hooks.once('setup', () => {
10-
if (game.settings.get(SYSTEM, SETTINGS.experimentalCombatHud)) {
11-
Hooks.on(SystemControls.HOOK_GET_SYSTEM_TOOLS, (tools) => {
12-
tools['projectfu-combathud-toggle'] = CombatHUD.getToggleControlButton();
13-
tools['projectfu-combathud-saved-toggle'] = CombatHUD.getSavedControlButton();
14-
tools['projectfu-combathud-reset'] = CombatHUD.getResetControlButton();
15-
});
9+
/**
10+
* @typedef HudButtonData
11+
* @property {string} name
12+
* @property {string} icon
13+
* @property {boolean} [visible]
14+
* @property {boolean} [toggle]
15+
* @property {boolean} [active]
16+
* @property {(event: Event, active: boolean) => void} [onClick] A callback invoked when the tool is activated
17+
* or deactivated
18+
*/
19+
20+
/**
21+
* @param {HTMLElement} containerElement
22+
* @param {HudButtonData} buttonData
23+
*/
24+
function createButton(containerElement, buttonData) {
25+
const button = document.createElement('button');
26+
button.type = 'button';
27+
button.classList.add('control', 'ui-control');
28+
button.innerHTML = `<i class="${buttonData.icon}"></i>`;
29+
button.dataset.tooltip = game.i18n.localize(buttonData.name);
30+
31+
if (buttonData.toggle) {
32+
let active = buttonData.active;
33+
button.classList.add('toggle');
34+
button.ariaPressed = active;
35+
button.addEventListener('click', (e) => {
36+
active = !active;
37+
button.ariaPressed = active;
38+
if (buttonData.onClick) {
39+
buttonData.onClick(e, active);
40+
}
41+
});
42+
} else {
43+
if (buttonData.onClick) {
44+
button.addEventListener('click', (e) => {
45+
buttonData.onClick(e, false);
46+
});
47+
}
48+
}
49+
50+
containerElement.appendChild(button);
1651
}
52+
53+
Hooks.on('renderCombatTracker', (app, element) => {
54+
if (game.settings.get(SYSTEM, SETTINGS.experimentalCombatHud)) {
55+
const containerElement = document.createElement('div');
56+
containerElement.id = 'combat-hud-controls';
57+
createButton(containerElement, CombatHUD.getToggleControlButton());
58+
createButton(containerElement, CombatHUD.getSavedControlButton());
59+
createButton(containerElement, CombatHUD.getResetControlButton());
60+
61+
const combatTrackerSection = element.querySelector('#combat-tracker').parentElement;
62+
combatTrackerSection.prepend(containerElement);
63+
}
64+
});
1765
});
1866

1967
export class CombatHUD extends foundry.applications.api.HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
@@ -433,7 +481,7 @@ export class CombatHUD extends foundry.applications.api.HandlebarsApplicationMix
433481
/**
434482
* Determine whether or not the current user has sufficient permission to edit
435483
* @param {HTMLElement} elem - The HTMLElement (or jQuery wrapper) for the ActiveEffect in question
436-
* @param {"update" | "delete"} op - The operation to check -- either "update" or "delete"
484+
* @param {'update' | 'delete'} op - The operation to check -- either "update" or "delete"
437485
* @returns
438486
*/
439487
_canModifyEffectContextMenu(elem, op = 'update') {
@@ -918,7 +966,7 @@ export class CombatHUD extends foundry.applications.api.HandlebarsApplicationMix
918966
this.render(true);
919967
}
920968

921-
_onUpdateCombatant(combatant, changes) {
969+
_onUpdateCombatant() {
922970
this._onUpdateHUD();
923971
}
924972

@@ -1161,17 +1209,18 @@ export class CombatHUD extends foundry.applications.api.HandlebarsApplicationMix
11611209
CombatHUD.update();
11621210
}
11631211

1212+
/**
1213+
* @return {HudButtonData}
1214+
*/
11641215
static getToggleControlButton() {
11651216
return {
1166-
name: 'projectfu-combathud-toggle',
1167-
title: game.i18n.localize('FU.CombatHudControlButtonTitle'),
1217+
name: game.i18n.localize('FU.CombatHudControlButtonTitle'),
11681218
icon: 'fas fa-thumbtack',
1169-
button: false,
11701219
toggle: true,
11711220
visible: game.combat ? game.combat.isActive : false,
11721221
active: !game.settings.get(SYSTEM, SETTINGS.optionCombatHudMinimized),
11731222

1174-
onChange: () => {
1223+
onClick: () => {
11751224
console.log('Click toggle');
11761225
if (game.settings.get(SYSTEM, SETTINGS.optionCombatHudMinimized)) {
11771226
CombatHUD.restore();
@@ -1182,32 +1231,34 @@ export class CombatHUD extends foundry.applications.api.HandlebarsApplicationMix
11821231
};
11831232
}
11841233

1234+
/**
1235+
* @return {HudButtonData}
1236+
*/
11851237
static getSavedControlButton() {
11861238
return {
1187-
name: 'projectfu-combathud-saved-toggle',
1188-
title: game.i18n.localize('FU.CombatHudSaveButtonTitle'),
1239+
name: game.i18n.localize('FU.CombatHudSaveButtonTitle'),
11891240
icon: 'fas fa-lock',
1190-
button: false,
11911241
toggle: true,
11921242
visible: game.combat ? game.combat.isActive : false,
11931243
active: game.settings.get(SYSTEM, SETTINGS.optionCombatHudSaved),
1194-
onChange: () => {
1244+
onClick: () => {
11951245
console.log('Click save');
11961246
const isSaved = game.settings.get(SYSTEM, SETTINGS.optionCombatHudSaved);
11971247
game.settings.set(SYSTEM, SETTINGS.optionCombatHudSaved, !isSaved);
11981248
},
11991249
};
12001250
}
12011251

1252+
/**
1253+
* @return {HudButtonData}
1254+
*/
12021255
static getResetControlButton() {
12031256
return {
1204-
name: 'projectfu-combathud-reset',
1205-
title: game.i18n.localize('FU.CombatHudResetButtonTitle'),
1257+
name: game.i18n.localize('FU.CombatHudResetButtonTitle'),
12061258
icon: 'fas fa-undo',
1207-
button: true,
12081259
// visible: game.combat ? game.combat.isActive : false,
12091260
visible: true,
1210-
onChange: () => {
1261+
onClick: () => {
12111262
console.log('Click reset');
12121263
CombatHUD.reset();
12131264
},
@@ -1224,7 +1275,10 @@ export class CombatHUD extends foundry.applications.api.HandlebarsApplicationMix
12241275
async _getCombatantThumbnail(combatant) {
12251276
if (combatant._videoSrc && !combatant.img) {
12261277
if (combatant._thumb) return combatant._thumb;
1227-
return (combatant._thumb = await game.video.createThumbnail(combatant._videoSrc, { width: 200, height: 200 }));
1278+
return (combatant._thumb = await game.video.createThumbnail(combatant._videoSrc, {
1279+
width: 200,
1280+
height: 200,
1281+
}));
12281282
}
12291283
return combatant.img ?? CONST.DEFAULT_TOKEN;
12301284
}

0 commit comments

Comments
 (0)