mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-07-22 02:19: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) {
|
||||
previusCountdownData = null;
|
||||
changedCountdownsForAnimation = new Set();
|
||||
countdownChangeAnimationTimeout = null;
|
||||
|
||||
constructor(options = {}) {
|
||||
|
|
@ -58,7 +59,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
}
|
||||
};
|
||||
|
||||
/**@inheritdoc */
|
||||
async _renderFrame(options) {
|
||||
const frame = await super._renderFrame(options);
|
||||
|
||||
|
|
@ -71,6 +71,52 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
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 */
|
||||
#getCountdowns() {
|
||||
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() {
|
||||
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 }) => {
|
||||
if (!typeModes.includes(countdown.type))
|
||||
return acc;
|
||||
|
||||
const playersWithAccess = game.users.reduce((acc, user) => {
|
||||
const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown);
|
||||
if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
||||
|
|
@ -112,7 +154,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
!countdownEditable ||
|
||||
(isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0'));
|
||||
|
||||
acc[key] = {
|
||||
acc[countdown.type][key] = {
|
||||
...countdown,
|
||||
editable: countdownEditable,
|
||||
noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0,
|
||||
|
|
@ -121,25 +163,27 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
loopTooltip: isLooping && game.i18n.localize(loopTooltip)
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
}, Object.keys(CONFIG.DH.GENERAL.countdownType).reduce((acc, key) => {
|
||||
acc[key] = {};
|
||||
return acc;
|
||||
}, {}));
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext(options) {
|
||||
const context = await super._prepareContext(options);
|
||||
context.isGM = game.user.isGM;
|
||||
this.previusCountdownData =
|
||||
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns).countdowns;
|
||||
|
||||
context.iconOnly =
|
||||
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) ===
|
||||
CONFIG.DH.GENERAL.countdownAppMode.iconOnly;
|
||||
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode)
|
||||
=== 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 => ({
|
||||
type: type.id,
|
||||
label: game.i18n.localize(type.label),
|
||||
active: userCountdownTypes.includes(type.id)
|
||||
active: context.userCountdownTypes.includes(type.id)
|
||||
}));
|
||||
|
||||
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];
|
||||
await game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes, newTypes);
|
||||
|
||||
for (const type of Object.keys(CONFIG.DH.GENERAL.countdownType)) {
|
||||
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;
|
||||
this.render();
|
||||
}
|
||||
|
||||
static async #onEditCountdowns() {
|
||||
|
|
@ -267,10 +292,6 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
}
|
||||
|
||||
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);
|
||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||
action: socketEvent.Refresh,
|
||||
|
|
@ -328,26 +349,4 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
|||
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() {
|
||||
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];
|
||||
if (!previousCountdown || (previousCountdown.current !== countdown.current)) {
|
||||
if (!previousCountdown || (previousCountdown.progress.current !== countdown.progress.current)) {
|
||||
acc.push(key);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
foundry.ui.performChangeAnimations(changedCountdowns);
|
||||
foundry.ui.countdowns.changedCountdownsForAnimation.add(...changedCountdowns);
|
||||
}
|
||||
|
||||
migrateData(source) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ export default class RegisterHandlebarsHelpers {
|
|||
empty: this.empty,
|
||||
pluralize: this.pluralize,
|
||||
positive: this.positive,
|
||||
isNullish: this.isNullish
|
||||
isNullish: this.isNullish,
|
||||
debug: this.debug
|
||||
});
|
||||
}
|
||||
static add(a, b) {
|
||||
|
|
@ -92,4 +93,8 @@ export default class RegisterHandlebarsHelpers {
|
|||
static isNullish(a) {
|
||||
return a === null || a === undefined;
|
||||
}
|
||||
|
||||
static debug(a) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@
|
|||
&.inactive {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
&.change-glow {
|
||||
animation: change-glow 1s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -101,10 +105,20 @@
|
|||
overflow: auto;
|
||||
max-height: 312px;
|
||||
|
||||
.countdown-category-container {
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.countdown-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
&.change-glow {
|
||||
animation: change-glow 1s ease-in-out infinite;
|
||||
}
|
||||
|
||||
&.icon-only {
|
||||
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 |}}
|
||||
<div class="countdown-container {{#if ../iconOnly}}icon-only{{/if}}" data-countdown="{{id}}">
|
||||
<div class="countdown-main-container">
|
||||
<img src="{{countdown.img}}" {{#if ../iconOnly}}data-tooltip="{{countdown.name}}"{{/if}}/>
|
||||
<div class="countdown-content">
|
||||
{{#unless ../iconOnly}}
|
||||
<header>{{countdown.name}}</header>
|
||||
{{/unless}}
|
||||
<div class="countdown-tools">
|
||||
<div class="countdown-tool-controls">
|
||||
{{#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}}
|
||||
{{#each countdowns as | category key |}}
|
||||
<div class="countdown-category-container {{#unless (includes @root.userCountdownTypes key)}}hidden{{/unless}}">
|
||||
{{#each category as |countdown id|}}
|
||||
<div class="countdown-container {{#if ../iconOnly}}icon-only{{/if}}" data-countdown="{{id}}">
|
||||
<div class="countdown-main-container">
|
||||
<img src="{{countdown.img}}" {{#if ../iconOnly}}data-tooltip="{{countdown.name}}"{{/if}}/>
|
||||
<div class="countdown-content">
|
||||
{{#unless ../iconOnly}}
|
||||
<header>{{countdown.name}}</header>
|
||||
{{/unless}}
|
||||
<div class="countdown-tools">
|
||||
<div class="countdown-tool-controls">
|
||||
{{#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>
|
||||
{{#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>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
Loading…
Add table
Add a link
Reference in a new issue