Add animation and editing support for the fate compass
This commit is contained in:
parent
7c8d6a7208
commit
7639962130
2 changed files with 115 additions and 23 deletions
|
|
@ -1,7 +1,17 @@
|
||||||
|
import { distanceBetweenFates } from "../utils/distanceBetweenFates.mjs";
|
||||||
import { filePath } from "../consts.mjs";
|
import { filePath } from "../consts.mjs";
|
||||||
|
import { gameTerms } from "../gameTerms.mjs";
|
||||||
import { Logger } from "../utils/Logger.mjs";
|
import { Logger } from "../utils/Logger.mjs";
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
const { FatePath } = gameTerms;
|
||||||
|
|
||||||
|
const CompassRotations = {
|
||||||
|
[FatePath.NORTH]: -90,
|
||||||
|
[FatePath.EAST]: 0,
|
||||||
|
[FatePath.SOUTH]: 90,
|
||||||
|
[FatePath.WEST]: 180,
|
||||||
|
};
|
||||||
|
|
||||||
const conditions = [
|
const conditions = [
|
||||||
{ label: `RipCrypt.common.difficulties.easy`, value: 4 },
|
{ label: `RipCrypt.common.difficulties.easy`, value: 4 },
|
||||||
|
|
@ -17,7 +27,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
tag: `aside`,
|
tag: `aside`,
|
||||||
classes: [
|
classes: [
|
||||||
`ripcrypt`,
|
`ripcrypt`,
|
||||||
`ripcrypt--DelveDiceHUD`
|
`ripcrypt--DelveDiceHUD`,
|
||||||
],
|
],
|
||||||
window: {
|
window: {
|
||||||
frame: false,
|
frame: false,
|
||||||
|
|
@ -25,6 +35,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
tourDelta: this.#tourDelta,
|
tourDelta: this.#tourDelta,
|
||||||
|
setFate: this.#setFate,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -38,7 +49,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
fateCompass: {
|
fateCompass: {
|
||||||
template: filePath(`templates/Apps/DelveDiceHUD/fateCompass.hbs`),
|
template: filePath(`templates/Apps/DelveDiceHUD/fateCompass.hbs`),
|
||||||
},
|
},
|
||||||
currentTour: {
|
sandsOfFate: {
|
||||||
template: filePath(`templates/Apps/DelveDiceHUD/tour/current.hbs`),
|
template: filePath(`templates/Apps/DelveDiceHUD/tour/current.hbs`),
|
||||||
},
|
},
|
||||||
nextTour: {
|
nextTour: {
|
||||||
|
|
@ -47,6 +58,24 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
};
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
// #region Instance Data
|
||||||
|
/**
|
||||||
|
* The current number of degrees the compass pointer should be rotated, this
|
||||||
|
* is not stored in the DB since we only care about the initial rotation on
|
||||||
|
* reload, which is derived from the current fate.
|
||||||
|
* @type {Number}
|
||||||
|
*/
|
||||||
|
_rotation;
|
||||||
|
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this._sandsOfFate = game.settings.get(`ripcrypt`, `sandsOfFate`);
|
||||||
|
this._currentFate = game.settings.get(`ripcrypt`, `currentFate`);
|
||||||
|
this._rotation = CompassRotations[this._currentFate];
|
||||||
|
this._difficulty = game.settings.get(`ripcrypt`, `dc`);
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
// #region Lifecycle
|
// #region Lifecycle
|
||||||
/**
|
/**
|
||||||
* Injects the element into the Foundry UI in the top middle
|
* Injects the element into the Foundry UI in the top middle
|
||||||
|
|
@ -75,16 +104,17 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
ctx.meta.editable = game.user.isGM;
|
ctx.meta.editable = game.user.isGM;
|
||||||
|
|
||||||
switch (partId) {
|
switch (partId) {
|
||||||
case `currentTour`: {
|
case `sandsOfFate`: {
|
||||||
await this._prepareTourContext(ctx);
|
ctx.sandsOfFate = this._sandsOfFate;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
case `difficulty`: {
|
case `difficulty`: {
|
||||||
await this._prepareDifficultyContext(ctx);
|
ctx.dc = this._difficulty;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
case `fateCompass`: {
|
case `fateCompass`: {
|
||||||
await this._prepareFateCompassContext(ctx);
|
ctx.fate = this._currentFate;
|
||||||
|
ctx.rotation = `${this._rotation}deg`;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -93,26 +123,40 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
async _prepareTourContext(ctx) {
|
async animate({ parts = [] } = {}) {
|
||||||
ctx.tour = game.settings.get(`ripcrypt`, `sandsOfFate`);
|
if (parts.includes(`fateCompass`)) {
|
||||||
|
this.#animateCompassTo();
|
||||||
};
|
};
|
||||||
|
|
||||||
async _prepareDifficultyContext(ctx) {
|
if (parts.includes(`sandsOfFate`)) {};
|
||||||
ctx.dc = game.settings.get(`ripcrypt`, `dc`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async _prepareFateCompassContext(ctx) {
|
#animateCompassTo(newFate) {
|
||||||
ctx.direction = game.settings.get(`ripcrypt`, `currentFate`);
|
/** @type {HTMLElement|undefined} */
|
||||||
}
|
const pointer = this.element.querySelector(`.compass-pointer`);
|
||||||
|
if (!pointer) { return };
|
||||||
|
|
||||||
|
let distance = distanceBetweenFates(this._currentFate, newFate);
|
||||||
|
Logger.table({ newFate, fate: this._currentFate, distance, _rotation: this._rotation });
|
||||||
|
if (distance === 3) { distance = -1 };
|
||||||
|
|
||||||
|
this._rotation += distance * 90;
|
||||||
|
|
||||||
|
pointer.style.setProperty(`transform`, `rotate(${this._rotation}deg)`);
|
||||||
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
// #region Actions
|
// #region Actions
|
||||||
static async #tourDelta() {
|
static async #tourDelta() {};
|
||||||
ui.notifications.info(`Delve Tour Changed`, { console: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
static async #setFate() {
|
/** @this {DelveDiceHUD} */
|
||||||
ui.notifications.info(`Fate Set!`, { console: false });
|
static async #setFate(_event, element) {
|
||||||
|
const fate = element.dataset.toFate;
|
||||||
|
this.#animateCompassTo(fate);
|
||||||
|
|
||||||
|
// must be done after animate, otherwise it won't change the rotation
|
||||||
|
this._currentFate = fate;
|
||||||
|
game.settings.set(`ripcrypt`, `currentFate`, fate);
|
||||||
};
|
};
|
||||||
// #endregion
|
// #endregion
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,64 @@
|
||||||
<div id="fate-compass">
|
<div id="fate-compass">
|
||||||
<div class="compass-container">
|
<div class="compass-container">
|
||||||
<div class="compass">
|
<div class="compass">
|
||||||
<button type="button" class="transparent" style="grid-area: N;">N</button>
|
|
||||||
<button type="button" class="transparent" style="grid-area: W;">W</button>
|
|
||||||
<rc-icon
|
<rc-icon
|
||||||
class="compass-pointer"
|
class="compass-pointer"
|
||||||
name="icons/arrow-compass"
|
name="icons/arrow-compass"
|
||||||
var:fill="var(--accent-3)"
|
var:fill="var(--accent-3)"
|
||||||
var:size="1rem"
|
var:size="1rem"
|
||||||
|
style="transform: rotate({{rotation}})"
|
||||||
></rc-icon>
|
></rc-icon>
|
||||||
<button type="button" class="transparent" style="grid-area: E;">E</button>
|
{{#if meta.editable}}
|
||||||
<button type="button" class="transparent" style="grid-area: S;">S</button>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: N;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="North"
|
||||||
|
data-tooltip="Set Fate to North"
|
||||||
|
data-tooltip-direction="LEFT"
|
||||||
|
>
|
||||||
|
N
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: W;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="West"
|
||||||
|
data-tooltip="Set Fate to West"
|
||||||
|
data-tooltip-direction="LEFT"
|
||||||
|
>
|
||||||
|
W
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: E;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="East"
|
||||||
|
data-tooltip="Set Fate to East"
|
||||||
|
data-tooltip-direction="RIGHT"
|
||||||
|
>
|
||||||
|
E
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: S;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="South"
|
||||||
|
data-tooltip="Set Fate to South"
|
||||||
|
data-tooltip-direction="DOWN"
|
||||||
|
>
|
||||||
|
S
|
||||||
|
</button>
|
||||||
|
{{else}}
|
||||||
|
<span style="grid-area: N;">N</span>
|
||||||
|
<span style="grid-area: W;">W</span>
|
||||||
|
<span style="grid-area: E;">E</span>
|
||||||
|
<span style="grid-area: S;">S</span>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue