diff --git a/module.json b/module.json index 029966e..5a340f5 100644 --- a/module.json +++ b/module.json @@ -1,8 +1,7 @@ { "id": "dh-improved-countdowns", - "name": "dh-improved-countdowns", "title": "Improved Countdowns", - "version": "1.0.0", + "version": "1.1.0", "compatibility": { "minimum": "13", "verified": "13" @@ -38,5 +37,8 @@ "path": "lang/en.json" } ], - "description": "A modern, draggable countdown tracker for the Daggerheart system." + "description": "A modern, draggable countdown tracker for the Daggerheart system.", + "url": "https://github.com/cptn-cosmo/dh-improved-countdowns", + "manifest": "https://github.com/cptn-cosmo/dh-improved-countdowns/releases/latest/download/module.json", + "download": "https://github.com/cptn-cosmo/dh-improved-countdowns/releases/download/1.1.0/dh-improved-countdowns.zip" } \ No newline at end of file diff --git a/scripts/countdown-app.js b/scripts/countdown-app.js index 6e46131..48745ca 100644 --- a/scripts/countdown-app.js +++ b/scripts/countdown-app.js @@ -51,6 +51,15 @@ export class CountdownTrackerApp extends HandlebarsApplicationMixin(ApplicationV const isGM = game.user.isGM; const isMinimized = game.settings.get("dh-improved-countdowns", "minimized"); const isLocked = game.settings.get("dh-improved-countdowns", "locked"); + const iconShape = game.settings.get("dh-improved-countdowns", "iconShape"); + const displayMode = game.settings.get("dh-improved-countdowns", "displayMode"); + const barOrientation = game.settings.get("dh-improved-countdowns", "barOrientation"); + const visualColor = game.settings.get("dh-improved-countdowns", "visualColor"); + const enableVisualOverlay = game.settings.get("dh-improved-countdowns", "enableVisualOverlay"); + const enableVisualBorder = game.settings.get("dh-improved-countdowns", "enableVisualBorder"); + const gmAlwaysShowNumbers = game.settings.get("dh-improved-countdowns", "gmAlwaysShowNumbers"); + + const showNumbers = (isGM && gmAlwaysShowNumbers) || displayMode === "number"; // Fetch countdowns from system settings const systemCountdownSetting = game.settings.get("daggerheart", "Countdowns"); @@ -60,9 +69,15 @@ export class CountdownTrackerApp extends HandlebarsApplicationMixin(ApplicationV for (const [id, countdown] of Object.entries(systemCountdownSetting.countdowns)) { const ownership = this.#getPlayerOwnership(game.user, systemCountdownSetting, countdown); if (ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) { + const current = countdown.progress.current; + const max = countdown.progress.start; + const percentage = Math.max(0, Math.min(100, (current / max) * 100)); + countdowns[id] = { ...countdown, - editable: isGM || ownership === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER + editable: isGM || ownership === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER, + percentage, + cssClass: `shape-${iconShape}` }; } } @@ -72,7 +87,13 @@ export class CountdownTrackerApp extends HandlebarsApplicationMixin(ApplicationV countdowns, isGM, isMinimized, - isLocked + isLocked, + showNumbers, + iconShape, + barOrientation, + visualColor, + enableVisualOverlay, + enableVisualBorder }; } diff --git a/scripts/module.js b/scripts/module.js index fb2364d..c36b4ab 100644 --- a/scripts/module.js +++ b/scripts/module.js @@ -28,6 +28,88 @@ Hooks.once('init', () => { default: false, onChange: () => CountdownTrackerApp.instance?.render() }); + + game.settings.register("dh-improved-countdowns", "iconShape", { + name: "Icon Shape", + hint: "Choose the shape of the countdown icons.", + scope: "client", + config: true, + type: String, + choices: { + "rounded": "Rounded Square", + "circle": "Circle" + }, + default: "rounded", + onChange: () => CountdownTrackerApp.instance?.render() + }); + + game.settings.register("dh-improved-countdowns", "displayMode", { + name: "Display Mode", + hint: "Choose how the countdown value is displayed.", + scope: "world", + config: true, + type: String, + choices: { + "number": "Number", + "visual": "Visual (Bar/Clock)" + }, + default: "number", + onChange: () => CountdownTrackerApp.instance?.render() + }); + + game.settings.register("dh-improved-countdowns", "barOrientation", { + name: "Bar Orientation", + hint: "Choose the orientation of the progress bar (for square icons).", + scope: "client", + config: true, + type: String, + choices: { + "vertical": "Vertical", + "horizontal": "Horizontal" + }, + default: "vertical", + onChange: () => CountdownTrackerApp.instance?.render() + }); + + game.settings.register("dh-improved-countdowns", "visualColor", { + name: "Visual Color", + hint: "Choose the color for the progress overlay and border.", + scope: "client", + config: true, + type: String, + default: "#ffffff", + onChange: () => CountdownTrackerApp.instance?.render() + }); + + game.settings.register("dh-improved-countdowns", "enableVisualOverlay", { + name: "Enable Fill Overlay", + hint: "Show the filled progress overlay (Bar or Clock).", + scope: "client", + config: true, + type: Boolean, + default: true, + onChange: () => CountdownTrackerApp.instance?.render() + }); + + game.settings.register("dh-improved-countdowns", "enableVisualBorder", { + name: "Enable Border Progress", + hint: "Show a progress border around the icon.", + scope: "client", + config: true, + type: Boolean, + default: false, + onChange: () => CountdownTrackerApp.instance?.render() + }); + + game.settings.register("dh-improved-countdowns", "gmAlwaysShowNumbers", { + name: "GM Always Shows Numbers", + hint: "If enabled, the GM will always see the numerical value even if Display Mode is set to Visual.", + scope: "client", // This should be client-scoped as it's a preference for the GM user + config: true, + type: Boolean, + default: true, + onChange: () => CountdownTrackerApp.instance?.render() + }); }); Hooks.once('ready', () => { diff --git a/styles/countdown.css b/styles/countdown.css index 82d9af2..118a6b8 100644 --- a/styles/countdown.css +++ b/styles/countdown.css @@ -141,10 +141,18 @@ position: relative; width: 48px; height: 48px; - border-radius: 50%; background: rgba(0, 0, 0, 0.3); border: 2px solid rgba(255, 255, 255, 0.1); overflow: hidden; + transition: border-radius 0.3s ease; +} + +.icon-container.shape-circle { + border-radius: 50%; +} + +.icon-container.shape-rounded { + border-radius: 8px; } .countdown-icon { @@ -156,14 +164,64 @@ .value-overlay { position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + display: flex; + align-items: center; + justify-content: center; +} + +.value-overlay.number { font-size: 22px; font-weight: 800; color: #fff; text-shadow: 0 0 4px rgba(0, 0, 0, 0.9), 0 0 8px rgba(0, 0, 0, 0.9); +} + +.value-overlay.visual { + background: rgba(0, 0, 0, 0.2); +} + +/* Clock Visual */ +.clock-visual { + width: 100%; + height: 100%; + border-radius: 50%; + /* Opacity and Color handled inline via template */ +} + +/* Bar Visual */ +.bar-visual { + position: absolute; + bottom: 0; + left: 0; + /* Box shadow removed as it might interfere with custom colors/transparency */ + transition: all 0.3s ease; + /* Color handled inline via template */ +} + +/* SVG Border Visual */ +.progress-border-svg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; pointer-events: none; + /* Rotation handled inline to start at top */ +} + +.bar-visual.vertical { + width: 100%; + /* height is set inline */ +} + +.bar-visual.horizontal { + height: 100%; + /* width is set inline */ } /* +/- Controls */ diff --git a/templates/countdown-tracker.hbs b/templates/countdown-tracker.hbs index bac9e07..57dfb98 100644 --- a/templates/countdown-tracker.hbs +++ b/templates/countdown-tracker.hbs @@ -9,10 +9,12 @@ {{/if}} - + - + @@ -24,19 +26,53 @@ {{#unless ../isMinimized}}