diff --git a/lang/en.json b/lang/en.json index a6dde5c..4a235b7 100644 --- a/lang/en.json +++ b/lang/en.json @@ -17,5 +17,14 @@ "COSMOS_DH_TWEAKS.Settings.ResetFearPosition.ButtonText": "Reset Position", "COSMOS_DH_TWEAKS.Settings.ResetFearPosition.Success": "Fear tracker position has been reset.", "COSMOS_DH_TWEAKS.ContextMenu.LockPosition": "Lock Position", - "COSMOS_DH_TWEAKS.ContextMenu.UnlockPosition": "Unlock Position" + "COSMOS_DH_TWEAKS.ContextMenu.UnlockPosition": "Unlock Position", + "COSMOS_DH_TWEAKS.Settings.FearTrackerScale.Name": "Fear Tracker Scale", + "COSMOS_DH_TWEAKS.Settings.FearTrackerScale.Hint": "Scale the size of the Fear Tracker window and its icons.", + "COSMOS_DH_TWEAKS.Settings.ResetFearScale.Name": "Reset Fear Tracker Scale", + "COSMOS_DH_TWEAKS.Settings.ResetFearScale.Hint": "Resets the Fear Tracker scale back to 100%.", + "COSMOS_DH_TWEAKS.Settings.ResetFearScale.ButtonText": "Reset Scale", + "COSMOS_DH_TWEAKS.Settings.ResetFearScale.Success": "Fear tracker scale has been reset.", + "COSMOS_DH_TWEAKS.ContextMenu.ResetPosition": "Reset Position", + "COSMOS_DH_TWEAKS.ContextMenu.ResetScale": "Reset Scale", + "COSMOS_DH_TWEAKS.ContextMenu.ScaleHeader": "Scale" } diff --git a/scripts/cosmos-dh-tweaks.mjs b/scripts/cosmos-dh-tweaks.mjs index 6240cff..eac433a 100644 --- a/scripts/cosmos-dh-tweaks.mjs +++ b/scripts/cosmos-dh-tweaks.mjs @@ -69,6 +69,35 @@ Hooks.once("init", () => { default: false }); + game.settings.register("cosmos-dh-tweaks", "fearTrackerScale", { + name: "COSMOS_DH_TWEAKS.Settings.FearTrackerScale.Name", + hint: "COSMOS_DH_TWEAKS.Settings.FearTrackerScale.Hint", + scope: "client", + config: true, + type: Number, + range: { + min: 0.5, + max: 1.5, + step: 0.05 + }, + default: 1.0, + onChange: () => { + if (ui.resources && ui.resources.rendered) { + ui.resources.updateScale(); + ui.resources.adjustSizeToMaxFear(); + } + } + }); + + game.settings.register("cosmos-dh-tweaks", "resetFearScale", { + name: "COSMOS_DH_TWEAKS.Settings.ResetFearScale.Name", + hint: "COSMOS_DH_TWEAKS.Settings.ResetFearScale.Hint", + scope: "client", + config: true, + type: Boolean, + default: false + }); + // Override the FearTracker class in CONFIG const OriginalFearTracker = CONFIG.ui.resources; if (OriginalFearTracker) { @@ -106,9 +135,16 @@ Hooks.once("init", () => { this.updateTitleBarStatus(); this.updateLockStatus(); + this.updateScale(); this.adjustSizeToMaxFear(); } + updateScale() { + if (!this.element) return; + const scale = game.settings.get("cosmos-dh-tweaks", "fearTrackerScale") ?? 1.0; + this.element.style.setProperty('--cosmo-fear-scale', scale); + } + updateTitleBarStatus() { if (!this.element) return; const removeTitleBar = game.settings.get("cosmos-dh-tweaks", "removeFearTitleBar"); @@ -192,24 +228,35 @@ Hooks.once("init", () => { } calculatePerfectSize(targetWidth, measurements) { - const { skullW, skullH, gapX, gapY, padX, padY, headerH } = measurements; + const scale = game.settings.get("cosmos-dh-tweaks", "fearTrackerScale") ?? 1.0; + + // Divide measurements by scale to work with unscaled base measurements + const skullW = measurements.skullW / scale; + const skullH = measurements.skullH / scale; + const gapX = measurements.gapX / scale; + const gapY = measurements.gapY / scale; + const padX = measurements.padX / scale; + const padY = measurements.padY / scale; + const headerH = measurements.headerH / scale; + const display = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).displayFear; const maxFear = this.maxFear; if (display === 'bar') { const barElement = this.element.querySelector('#resource-fear'); - const barH = barElement ? barElement.getBoundingClientRect().height : 30; + const barH = barElement ? (barElement.getBoundingClientRect().height / scale) : 30; const perfectH = barH + padY + headerH; const minW = 200; - const perfectW = Math.max(minW, targetWidth || 222); + const targetWUnscaled = targetWidth ? (targetWidth / scale) : 222; + const perfectW = Math.max(minW, targetWUnscaled); return { - width: perfectW, - height: perfectH + width: perfectW * scale, + height: perfectH * scale }; } else { - const w = targetWidth || 222; - let cols = Math.round((w - padX + gapX) / (skullW + gapX)); + const targetWUnscaled = targetWidth ? (targetWidth / scale) : 222; + let cols = Math.round((targetWUnscaled - padX + gapX) / (skullW + gapX)); cols = Math.max(1, Math.min(maxFear, cols)); const perfectW = cols * skullW + (cols - 1) * gapX + padX + 2; @@ -217,8 +264,8 @@ Hooks.once("init", () => { const perfectH = rows * skullH + (rows - 1) * gapY + padY + headerH + 2; return { - width: perfectW, - height: perfectH + width: perfectW * scale, + height: perfectH * scale }; } } @@ -289,6 +336,7 @@ Hooks.once("init", () => { if (existing) existing.remove(); const isLocked = game.settings.get("cosmos-dh-tweaks", "lockFearTrackerPosition"); + const currentScale = game.settings.get("cosmos-dh-tweaks", "fearTrackerScale") ?? 1.0; const menu = document.createElement('div'); menu.className = 'cosmo-fear-context-menu'; @@ -301,6 +349,20 @@ Hooks.once("init", () => {
  • ${lockText}
  • +
  • + ${game.i18n.localize("COSMOS_DH_TWEAKS.ContextMenu.ResetPosition")} +
  • +
  • + ${game.i18n.localize("COSMOS_DH_TWEAKS.ContextMenu.ResetScale")} +
  • +
  • ${game.i18n.localize("COSMOS_DH_TWEAKS.ContextMenu.ScaleHeader")}
  • +
  • + + + + + +
  • `; @@ -319,6 +381,37 @@ Hooks.once("init", () => { menu.remove(); }); + menu.querySelector('[data-action="reset-position"]').addEventListener('click', async (event) => { + event.preventDefault(); + await game.user.unsetFlag(CONFIG.DH.id, 'app.resources.position'); + if (this.rendered) { + const defaultPos = CONFIG.ui.resources.DEFAULT_OPTIONS.position; + await this.setPosition(defaultPos); + } + ui.notifications.info(game.i18n.localize("COSMOS_DH_TWEAKS.Settings.ResetFearPosition.Success")); + menu.remove(); + }); + + menu.querySelector('[data-action="reset-scale"]').addEventListener('click', async (event) => { + event.preventDefault(); + await game.settings.set("cosmos-dh-tweaks", "fearTrackerScale", 1.0); + this.updateScale(); + this.adjustSizeToMaxFear(); + ui.notifications.info(game.i18n.localize("COSMOS_DH_TWEAKS.Settings.ResetFearScale.Success")); + menu.remove(); + }); + + menu.querySelectorAll('.scale-btn').forEach(btn => { + btn.addEventListener('click', async (event) => { + event.preventDefault(); + const newScale = parseFloat(btn.dataset.scale); + await game.settings.set("cosmos-dh-tweaks", "fearTrackerScale", newScale); + this.updateScale(); + this.adjustSizeToMaxFear(); + menu.remove(); + }); + }); + const closeMenu = (event) => { if (!menu.contains(event.target)) { menu.remove(); @@ -628,12 +721,12 @@ Hooks.on("destroyToken", (token) => { }); Hooks.on("renderSettingsConfig", (app, html, data) => { - const input = html.querySelector + const posInput = html.querySelector ? html.querySelector('[name="cosmos-dh-tweaks.resetFearPosition"]') : html.find('[name="cosmos-dh-tweaks.resetFearPosition"]')[0]; - if (input) { - const formGroup = input.closest('.form-group'); + if (posInput) { + const formGroup = posInput.closest('.form-group'); if (formGroup) { const formFields = formGroup.querySelector('.form-fields'); if (formFields) { @@ -656,4 +749,33 @@ Hooks.on("renderSettingsConfig", (app, html, data) => { } } } + + const scaleInput = html.querySelector + ? html.querySelector('[name="cosmos-dh-tweaks.resetFearScale"]') + : html.find('[name="cosmos-dh-tweaks.resetFearScale"]')[0]; + + if (scaleInput) { + const formGroup = scaleInput.closest('.form-group'); + if (formGroup) { + const formFields = formGroup.querySelector('.form-fields'); + if (formFields) { + const button = document.createElement('button'); + button.type = 'button'; + button.className = 'cosmo-reset-fear-scale-btn'; + button.innerHTML = ` ${game.i18n.localize("COSMOS_DH_TWEAKS.Settings.ResetFearScale.ButtonText")}`; + button.addEventListener('click', async (e) => { + e.preventDefault(); + await game.settings.set("cosmos-dh-tweaks", "fearTrackerScale", 1.0); + if (ui.resources && ui.resources.rendered) { + ui.resources.updateScale(); + ui.resources.adjustSizeToMaxFear(); + } + ui.notifications.info(game.i18n.localize("COSMOS_DH_TWEAKS.Settings.ResetFearScale.Success")); + }); + + formFields.innerHTML = ''; + formFields.appendChild(button); + } + } + } }); diff --git a/styles/cosmos-dh-tweaks.css b/styles/cosmos-dh-tweaks.css index 38264d7..6847e08 100644 --- a/styles/cosmos-dh-tweaks.css +++ b/styles/cosmos-dh-tweaks.css @@ -156,8 +156,8 @@ text-align: center; } -/* Reset button styling */ -button.cosmo-reset-fear-pos-btn { +button.cosmo-reset-fear-pos-btn, +button.cosmo-reset-fear-scale-btn { background: rgba(197, 164, 94, 0.1); border: 1px solid rgb(153, 122, 79); color: #d3d3d3; @@ -172,8 +172,123 @@ button.cosmo-reset-fear-pos-btn { transition: background-color 0.2s, color 0.2s, border-color 0.2s; } -button.cosmo-reset-fear-pos-btn:hover { +button.cosmo-reset-fear-pos-btn:hover, +button.cosmo-reset-fear-scale-btn:hover { background: rgba(197, 164, 94, 0.25); border-color: #ffffff; color: #ffffff; } + +/* Fear Tracker Scaling */ +#resources { + --cosmo-fear-scale: 1; +} + +/* Scale the skull icons */ +#resources #resource-fear i { + width: calc(3rem * var(--cosmo-fear-scale, 1)) !important; + height: calc(3rem * var(--cosmo-fear-scale, 1)) !important; + font-size: calc(1.125rem * var(--cosmo-fear-scale, 1)) !important; +} + +/* Scale hover state font-size for GMs */ +#resources.isGM #resource-fear i:hover { + font-size: calc(1.25rem * var(--cosmo-fear-scale, 1)) !important; +} + +/* Scale the control buttons (+ and -) */ +#resources #resource-fear .controls { + width: calc(30px * var(--cosmo-fear-scale, 1)) !important; + height: calc(30px * var(--cosmo-fear-scale, 1)) !important; + font-size: calc(1.25rem * var(--cosmo-fear-scale, 1)) !important; +} + +#resources #resource-fear .controls:hover { + font-size: calc(1.5rem * var(--cosmo-fear-scale, 1)) !important; +} + +/* Scale the resource bar */ +#resources #resource-fear .resource-bar { + font-size: calc(1.25rem * var(--cosmo-fear-scale, 1)) !important; + padding: calc(0.25rem * var(--cosmo-fear-scale, 1)) calc(0.5rem * var(--cosmo-fear-scale, 1)) !important; +} + +/* Scale the window padding and flex gap */ +#resources .window-content { + padding: calc(0.5rem * var(--cosmo-fear-scale, 1)) !important; +} + +#resources #resource-fear { + gap: calc(0.5rem * var(--cosmo-fear-scale, 1)) calc(0.25rem * var(--cosmo-fear-scale, 1)) !important; +} + +/* Scale the window header */ +#resources header.window-header { + font-size: calc(14px * var(--cosmo-fear-scale, 1)) !important; + min-height: calc(30px * var(--cosmo-fear-scale, 1)) !important; + height: calc(30px * var(--cosmo-fear-scale, 1)) !important; +} + +#resources header.window-header h1 { + font-size: calc(14px * var(--cosmo-fear-scale, 1)) !important; +} + +#resources header.window-header button, +#resources header.window-header a, +#resources header.window-header i { + font-size: calc(14px * var(--cosmo-fear-scale, 1)) !important; +} + +#resources header.window-header button, +#resources header.window-header a { + width: calc(30px * var(--cosmo-fear-scale, 1)) !important; + height: calc(30px * var(--cosmo-fear-scale, 1)) !important; + line-height: calc(30px * var(--cosmo-fear-scale, 1)) !important; +} + +/* Context menu scale controls styling */ +.cosmo-context-menu-header { + padding: 6px 12px 2px 12px; + font-size: 11px; + text-transform: uppercase; + color: #a49a85; + font-weight: bold; + letter-spacing: 0.5px; + border-top: 1px solid rgba(153, 122, 79, 0.3); + margin-top: 4px; +} + +.cosmo-context-menu-scale-controls { + display: flex; + padding: 4px 12px 8px 12px; + gap: 4px; + justify-content: space-between; +} + +.cosmo-context-menu-scale-controls button.scale-btn { + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(153, 122, 79, 0.4); + color: #d3d3d3; + padding: 2px 6px; + border-radius: 3px; + cursor: pointer; + font-size: 11px; + font-family: inherit; + transition: all 0.2s ease; + flex: 1; + text-align: center; +} + +.cosmo-context-menu-scale-controls button.scale-btn:hover { + background: rgba(197, 164, 94, 0.25); + border-color: #ffffff; + color: #ffffff; +} + +.cosmo-context-menu-scale-controls button.scale-btn.active { + background: rgba(197, 164, 94, 0.4); + border-color: rgb(197, 164, 94); + color: #ffffff; + font-weight: bold; +} +