mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-07-23 10:59:54 +02:00
Finished animation framework
This commit is contained in:
parent
208e8192b4
commit
0961ad8d73
5 changed files with 129 additions and 97 deletions
|
|
@ -12,6 +12,7 @@ const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
export default class DhCountdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
export default class DhCountdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
previusCountdownData = null;
|
previusCountdownData = null;
|
||||||
|
changedCountdownsForAnimation = new Set();
|
||||||
countdownChangeAnimationTimeout = null;
|
countdownChangeAnimationTimeout = null;
|
||||||
|
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
|
|
@ -58,7 +59,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**@inheritdoc */
|
|
||||||
async _renderFrame(options) {
|
async _renderFrame(options) {
|
||||||
const frame = await super._renderFrame(options);
|
const frame = await super._renderFrame(options);
|
||||||
|
|
||||||
|
|
@ -71,6 +71,52 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options);
|
||||||
|
|
||||||
|
/**/
|
||||||
|
this.element.hidden = !game.user.isGM && this.#getCountdowns().length === 0;
|
||||||
|
if (options?.force) {
|
||||||
|
document.getElementById('ui-right-column-1')?.appendChild(this.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
if (this.changedCountdownsForAnimation.size) {
|
||||||
|
if (this.countdownChangeAnimationTimeout)
|
||||||
|
clearTimeout(this.countdownChangeAnimationTimeout);
|
||||||
|
|
||||||
|
for (const countdownKey of this.changedCountdownsForAnimation) {
|
||||||
|
this.element.querySelector(`.countdown-container[data-countdown="${countdownKey}"]`)
|
||||||
|
.classList.add('change-glow');
|
||||||
|
|
||||||
|
/* If the countdown is not currently visible, add a glow to the CountdownType pill */
|
||||||
|
const visibleTypes = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes) ?? []
|
||||||
|
const countdown = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns)
|
||||||
|
.countdowns[countdownKey];
|
||||||
|
if (!visibleTypes.includes(countdown?.type)) {
|
||||||
|
this.element.querySelector(`.header-type-toggles .header-type[data-type="${countdown.type}"]`)
|
||||||
|
.classList.add('change-glow');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.countdownChangeAnimationTimeout = setTimeout(() => {
|
||||||
|
this.changedCountdownsForAnimation.clear();
|
||||||
|
for (const element of this.element.querySelectorAll('.countdown-container')) {
|
||||||
|
element.classList.remove('change-glow');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const element of this.element.querySelectorAll('.header-type-toggles .header-type')) {
|
||||||
|
element.classList.remove('change-glow');
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.previusCountdownData =
|
||||||
|
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns).countdowns;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns countdown data filtered by ownership */
|
/** Returns countdown data filtered by ownership */
|
||||||
#getCountdowns() {
|
#getCountdowns() {
|
||||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||||
|
|
@ -84,12 +130,8 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
|
|
||||||
_getCountdownData() {
|
_getCountdownData() {
|
||||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||||
const typeModes = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes) ?? [];
|
|
||||||
|
|
||||||
return this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => {
|
return this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => {
|
||||||
if (!typeModes.includes(countdown.type))
|
|
||||||
return acc;
|
|
||||||
|
|
||||||
const playersWithAccess = game.users.reduce((acc, user) => {
|
const playersWithAccess = game.users.reduce((acc, user) => {
|
||||||
const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown);
|
const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown);
|
||||||
if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
||||||
|
|
@ -112,7 +154,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
!countdownEditable ||
|
!countdownEditable ||
|
||||||
(isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0'));
|
(isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0'));
|
||||||
|
|
||||||
acc[key] = {
|
acc[countdown.type][key] = {
|
||||||
...countdown,
|
...countdown,
|
||||||
editable: countdownEditable,
|
editable: countdownEditable,
|
||||||
noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0,
|
noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0,
|
||||||
|
|
@ -121,25 +163,27 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
loopTooltip: isLooping && game.i18n.localize(loopTooltip)
|
loopTooltip: isLooping && game.i18n.localize(loopTooltip)
|
||||||
};
|
};
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, Object.keys(CONFIG.DH.GENERAL.countdownType).reduce((acc, key) => {
|
||||||
|
acc[key] = {};
|
||||||
|
return acc;
|
||||||
|
}, {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async _prepareContext(options) {
|
async _prepareContext(options) {
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
context.isGM = game.user.isGM;
|
context.isGM = game.user.isGM;
|
||||||
this.previusCountdownData =
|
|
||||||
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns).countdowns;
|
|
||||||
|
|
||||||
context.iconOnly =
|
context.iconOnly =
|
||||||
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) ===
|
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode)
|
||||||
CONFIG.DH.GENERAL.countdownAppMode.iconOnly;
|
=== CONFIG.DH.GENERAL.countdownAppMode.iconOnly;
|
||||||
|
|
||||||
const userCountdownTypes = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes) ?? [];
|
context.userCountdownTypes =
|
||||||
|
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes) ?? [];
|
||||||
context.typeToggles = Object.values(CONFIG.DH.GENERAL.countdownType).map(type => ({
|
context.typeToggles = Object.values(CONFIG.DH.GENERAL.countdownType).map(type => ({
|
||||||
type: type.id,
|
type: type.id,
|
||||||
label: game.i18n.localize(type.label),
|
label: game.i18n.localize(type.label),
|
||||||
active: userCountdownTypes.includes(type.id)
|
active: context.userCountdownTypes.includes(type.id)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
context.countdowns = this._getCountdownData();
|
context.countdowns = this._getCountdownData();
|
||||||
|
|
@ -191,26 +235,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
currentTypes.includes(type) ? currentTypes.filter(x => x !== type) : [...currentTypes, type];
|
currentTypes.includes(type) ? currentTypes.filter(x => x !== type) : [...currentTypes, type];
|
||||||
await game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes, newTypes);
|
await game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes, newTypes);
|
||||||
|
|
||||||
for (const type of Object.keys(CONFIG.DH.GENERAL.countdownType)) {
|
this.render();
|
||||||
const toggleElement = this.element.querySelector(`.header-type-toggles .header-type[data-type="${type}"]`);
|
|
||||||
if (newTypes.includes(type))
|
|
||||||
toggleElement.classList.remove('inactive');
|
|
||||||
|
|
||||||
else
|
|
||||||
toggleElement.classList.add('inactive');
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedCountdownsElement = await foundry.applications.handlebars.renderTemplate(
|
|
||||||
'systems/daggerheart/templates/ui/countdowns/parts/countdowns.hbs',
|
|
||||||
{
|
|
||||||
countdowns: this._getCountdownData(),
|
|
||||||
iconOnly: game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) ===
|
|
||||||
CONFIG.DH.GENERAL.countdownAppMode.iconOnly,
|
|
||||||
isGM: game.user.isGM
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
this.element.querySelector('#countdowns .countdowns-container').innerHTML = updatedCountdownsElement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #onEditCountdowns() {
|
static async #onEditCountdowns() {
|
||||||
|
|
@ -267,10 +292,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
}
|
}
|
||||||
|
|
||||||
static async gmSetSetting(data) {
|
static async gmSetSetting(data) {
|
||||||
// if(Object.keys(data).some(x => x.includes('countdowns'))) {
|
|
||||||
// this.previusCountdownData = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns).countdowns;
|
|
||||||
// }
|
|
||||||
|
|
||||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data);
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data);
|
||||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||||
action: socketEvent.Refresh,
|
action: socketEvent.Refresh,
|
||||||
|
|
@ -328,26 +349,4 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
refreshType: RefreshType.Countdown
|
refreshType: RefreshType.Countdown
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {*} context
|
|
||||||
* @param {*} options
|
|
||||||
*/
|
|
||||||
async performChangeAnimations(changedCountdowns) {
|
|
||||||
if (this.countdownChangeAnimationTimeout)
|
|
||||||
clearTimeout(this.countdownChangeAnimationTimeout);
|
|
||||||
|
|
||||||
this.countdownChangeAnimationTimeout = setTimeout(() => {
|
|
||||||
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onRender(context, options) {
|
|
||||||
await super._onRender(context, options);
|
|
||||||
this.element.hidden = !game.user.isGM && this.#getCountdowns().length === 0;
|
|
||||||
if (options?.force) {
|
|
||||||
document.getElementById('ui-right-column-1')?.appendChild(this.element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,16 @@ export default class DhCountdowns extends foundry.abstract.DataModel {
|
||||||
|
|
||||||
handleChange() {
|
handleChange() {
|
||||||
const previousCountdowns = foundry.ui.countdowns.previusCountdownData;
|
const previousCountdowns = foundry.ui.countdowns.previusCountdownData;
|
||||||
const changedCountdowns = Object.values(this.countdowns).reduce((acc, [key, countdown]) => {
|
const changedCountdowns = Object.entries(this.countdowns).reduce((acc, [key, countdown]) => {
|
||||||
const previousCountdown = previousCountdowns[key];
|
const previousCountdown = previousCountdowns[key];
|
||||||
if (!previousCountdown || (previousCountdown.current !== countdown.current)) {
|
if (!previousCountdown || (previousCountdown.progress.current !== countdown.progress.current)) {
|
||||||
acc.push(key);
|
acc.push(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
foundry.ui.performChangeAnimations(changedCountdowns);
|
foundry.ui.countdowns.changedCountdownsForAnimation.add(...changedCountdowns);
|
||||||
}
|
}
|
||||||
|
|
||||||
migrateData(source) {
|
migrateData(source) {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ export default class RegisterHandlebarsHelpers {
|
||||||
empty: this.empty,
|
empty: this.empty,
|
||||||
pluralize: this.pluralize,
|
pluralize: this.pluralize,
|
||||||
positive: this.positive,
|
positive: this.positive,
|
||||||
isNullish: this.isNullish
|
isNullish: this.isNullish,
|
||||||
|
debug: this.debug
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
static add(a, b) {
|
static add(a, b) {
|
||||||
|
|
@ -92,4 +93,8 @@ export default class RegisterHandlebarsHelpers {
|
||||||
static isNullish(a) {
|
static isNullish(a) {
|
||||||
return a === null || a === undefined;
|
return a === null || a === undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static debug(a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@
|
||||||
&.inactive {
|
&.inactive {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.change-glow {
|
||||||
|
animation: change-glow 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -101,10 +105,20 @@
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
max-height: 312px;
|
max-height: 312px;
|
||||||
|
|
||||||
|
.countdown-category-container {
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.countdown-container {
|
.countdown-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
&.change-glow {
|
||||||
|
animation: change-glow 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
&.icon-only {
|
&.icon-only {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
|
|
@ -203,4 +217,14 @@
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes change-glow {
|
||||||
|
0% {
|
||||||
|
box-shadow: 0 0 1px 1px @golden;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
box-shadow: 0 0 2px 2px @golden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,44 @@
|
||||||
{{#each countdowns as | countdown id |}}
|
{{#each countdowns as | category key |}}
|
||||||
<div class="countdown-container {{#if ../iconOnly}}icon-only{{/if}}" data-countdown="{{id}}">
|
<div class="countdown-category-container {{#unless (includes @root.userCountdownTypes key)}}hidden{{/unless}}">
|
||||||
<div class="countdown-main-container">
|
{{#each category as |countdown id|}}
|
||||||
<img src="{{countdown.img}}" {{#if ../iconOnly}}data-tooltip="{{countdown.name}}"{{/if}}/>
|
<div class="countdown-container {{#if ../iconOnly}}icon-only{{/if}}" data-countdown="{{id}}">
|
||||||
<div class="countdown-content">
|
<div class="countdown-main-container">
|
||||||
{{#unless ../iconOnly}}
|
<img src="{{countdown.img}}" {{#if ../iconOnly}}data-tooltip="{{countdown.name}}"{{/if}}/>
|
||||||
<header>{{countdown.name}}</header>
|
<div class="countdown-content">
|
||||||
{{/unless}}
|
{{#unless ../iconOnly}}
|
||||||
<div class="countdown-tools">
|
<header>{{countdown.name}}</header>
|
||||||
<div class="countdown-tool-controls">
|
{{/unless}}
|
||||||
{{#if countdown.editable}}<a data-action="decreaseCountdown"><i class="fa-solid fa-minus"></i></a>{{/if}}
|
<div class="countdown-tools">
|
||||||
<div class="progress-tag">
|
<div class="countdown-tool-controls">
|
||||||
{{countdown.progress.current}}/{{countdown.progress.start}}
|
{{#if countdown.editable}}<a data-action="decreaseCountdown"><i class="fa-solid fa-minus"></i></a>{{/if}}
|
||||||
|
<div class="progress-tag">
|
||||||
|
{{countdown.progress.current}}/{{countdown.progress.start}}
|
||||||
|
</div>
|
||||||
|
{{#if countdown.editable}}<a data-action="increaseCountdown"><i class="fa-solid fa-plus"></i></a>{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="countdown-tool-icons">
|
||||||
|
{{#if (not ../iconOnly)}}
|
||||||
|
{{#if (and countdown.noPlayerAccess @root.isGM)}}
|
||||||
|
<i class="fa-solid fa-eye-slash" data-tooltip="{{localize "DAGGERHEART.UI.Countdowns.noPlayerAccess"}}"></i>
|
||||||
|
{{/if}}
|
||||||
|
{{#unless (eq countdown.progress.looping "noLooping")}}
|
||||||
|
<span data-tooltip="{{countdown.loopTooltip}}">
|
||||||
|
<a class="looping-container {{#if countdown.shouldLoop}}should-loop{{/if}}" {{#if countdown.loopDisabled}}disabled{{/if}} data-action="loopCountdown">
|
||||||
|
<i class="loop-marker fa-solid fa-repeat"></i>
|
||||||
|
{{#if (eq countdown.progress.looping "increasing")}}
|
||||||
|
<i class="direction-marker fa-solid fa-angles-up" data-tooltip="{{localize "DAGGERHEART.UI.Countdowns.increasingLoop"}}"></i>
|
||||||
|
{{else if (eq countdown.progress.looping "decreasing")}}
|
||||||
|
<i class="direction-marker fa-solid fa-angles-down" data-tooltip="{{localize "DAGGERHEART.UI.Countdowns.decreasingLoop"}}"></i>
|
||||||
|
{{/if}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{#if countdown.editable}}<a data-action="increaseCountdown"><i class="fa-solid fa-plus"></i></a>{{/if}}
|
|
||||||
</div>
|
|
||||||
<div class="countdown-tool-icons">
|
|
||||||
{{#if (not ../iconOnly)}}
|
|
||||||
{{#if (and countdown.noPlayerAccess @root.isGM)}}
|
|
||||||
<i class="fa-solid fa-eye-slash" data-tooltip="{{localize "DAGGERHEART.UI.Countdowns.noPlayerAccess"}}"></i>
|
|
||||||
{{/if}}
|
|
||||||
{{#unless (eq countdown.progress.looping "noLooping")}}
|
|
||||||
<span data-tooltip="{{countdown.loopTooltip}}">
|
|
||||||
<a class="looping-container {{#if countdown.shouldLoop}}should-loop{{/if}}" {{#if countdown.loopDisabled}}disabled{{/if}} data-action="loopCountdown">
|
|
||||||
<i class="loop-marker fa-solid fa-repeat"></i>
|
|
||||||
{{#if (eq countdown.progress.looping "increasing")}}
|
|
||||||
<i class="direction-marker fa-solid fa-angles-up" data-tooltip="{{localize "DAGGERHEART.UI.Countdowns.increasingLoop"}}"></i>
|
|
||||||
{{else if (eq countdown.progress.looping "decreasing")}}
|
|
||||||
<i class="direction-marker fa-solid fa-angles-down" data-tooltip="{{localize "DAGGERHEART.UI.Countdowns.decreasingLoop"}}"></i>
|
|
||||||
{{/if}}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
{{/unless}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue