feat: introduce a custom configuration UI for environment overlay settings, including a new template and styles.

This commit is contained in:
CPTN Cosmo 2025-12-31 00:03:36 +01:00
parent 773a95641b
commit 9192703e96
3 changed files with 228 additions and 19 deletions

View file

@ -4,11 +4,20 @@ const FLAG_KEY = "environmentUuid";
Hooks.once("init", () => {
console.log(`${MODULE_ID} | Initializing Daggerheart Environment Overlay`);
// Register Menu
game.settings.registerMenu(MODULE_ID, "overlayConfig", {
name: "Overlay Configuration",
label: "Configure Overlay Style",
hint: "Customize the size, shape, and color of the environment overlay.",
icon: "fas fa-palette",
type: EnvironmentOverlayConfig,
restricted: true
});
game.settings.register(MODULE_ID, "borderColor", {
name: "Overlay Border Color",
hint: "Color of the environment token border.",
scope: "world",
config: true,
config: false,
type: String,
default: "#f3c267",
onChange: () => renderEnvironmentOverlay()
@ -16,45 +25,115 @@ Hooks.once("init", () => {
game.settings.register(MODULE_ID, "iconSize", {
name: "Icon Size",
hint: "Size of the environment token in pixels.",
scope: "world",
config: true,
config: false,
type: Number,
range: {
min: 30,
max: 200,
step: 5
},
default: 80,
onChange: () => renderEnvironmentOverlay()
});
game.settings.register(MODULE_ID, "iconShape", {
name: "Icon Shape",
hint: "Shape of the environment token overlay.",
scope: "world",
config: true,
config: false,
type: String,
choices: {
"rounded": "Rounded Square",
"square": "Square",
"circle": "Circle"
},
default: "rounded",
onChange: () => renderEnvironmentOverlay()
});
game.settings.register(MODULE_ID, "showName", {
name: "Show Actor Name",
hint: "Display the environment actor's name below the token.",
scope: "world",
config: true,
config: false,
type: Boolean,
default: true,
onChange: () => renderEnvironmentOverlay()
});
});
/**
* Configuration Application
*/
/**
* Configuration Application
*/
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
class EnvironmentOverlayConfig extends HandlebarsApplicationMixin(ApplicationV2) {
static DEFAULT_OPTIONS = {
tag: "form",
id: "dh-environment-overlay-config",
window: {
title: "Environment Overlay Configuration",
icon: "fas fa-palette",
resizable: false
},
position: {
width: 500,
height: "auto"
},
classes: ["daggerheart", "dialog", "dh-style", "module"],
actions: {
reset: EnvironmentOverlayConfig.onReset
},
form: {
handler: EnvironmentOverlayConfig.onSubmit,
closeOnSubmit: true
}
};
static PARTS = {
form: {
template: "modules/dh-environment-overlay/templates/overlay-config.hbs"
}
};
async _prepareContext(options) {
return {
borderColor: game.settings.get(MODULE_ID, "borderColor"),
iconSize: game.settings.get(MODULE_ID, "iconSize"),
iconShape: game.settings.get(MODULE_ID, "iconShape"),
showName: game.settings.get(MODULE_ID, "showName"),
shapes: {
"rounded": "Rounded Square",
"square": "Square",
"circle": "Circle"
}
};
}
_onRender(context, options) {
super._onRender(context, options);
// Update range value display
const html = this.element;
const rangeInput = html.querySelector('input[name="iconSize"]');
const rangeValue = html.querySelector('.range-value');
if (rangeInput && rangeValue) {
rangeInput.addEventListener('input', (event) => {
rangeValue.textContent = event.target.value;
});
}
}
static async onReset(event, target) {
await game.settings.set(MODULE_ID, "borderColor", "#f3c267");
await game.settings.set(MODULE_ID, "iconSize", 80);
await game.settings.set(MODULE_ID, "iconShape", "rounded");
await game.settings.set(MODULE_ID, "showName", true);
this.render();
ui.notifications.info("Environment Overlay settings reset to defaults.");
}
static async onSubmit(event, form, formData) {
const data = formData.object;
for (let [key, value] of Object.entries(data)) {
await game.settings.set(MODULE_ID, key, value);
}
}
}
/**
* Handle Scene Configuration Render
*/

View file

@ -1,3 +1,89 @@
/* Configuration Window Styles */
#dh-environment-overlay-config {
font-family: 'Montserrat', sans-serif;
color: light-dark(var(--dark-blue), var(--golden));
background-image: light-dark(url('/systems/daggerheart/assets/parchments/dh-parchment-light.png'), url('/systems/daggerheart/assets/parchments/dh-parchment-dark.png'));
background-repeat: no-repeat;
background-position: center;
border: none;
padding: 15px !important;
}
#dh-environment-overlay-config .form-group {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 15px;
}
#dh-environment-overlay-config .form-fields {
flex: 1;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
}
#dh-environment-overlay-config .range-value {
min-width: 30px;
text-align: center;
font-weight: bold;
color: light-dark(var(--dark-blue), var(--golden));
}
#dh-environment-overlay-config .window-header {
background: transparent;
border-bottom: none;
color: light-dark(var(--dark-blue), var(--golden));
font-family: 'Cinzel Decorative', serif;
}
#dh-environment-overlay-config .window-title {
font-family: 'Cinzel Decorative', serif;
color: light-dark(var(--dark-blue), var(--golden));
}
#dh-environment-overlay-config h1 {
font-family: 'Cinzel Decorative', serif;
color: light-dark(var(--dark-blue), var(--golden));
}
#dh-environment-overlay-config label {
font-family: 'Montserrat', sans-serif;
color: light-dark(var(--dark-blue), var(--golden));
}
#dh-environment-overlay-config .notes {
font-family: 'Montserrat', sans-serif;
color: light-dark(var(--dark-blue-50), var(--golden-90));
}
#dh-environment-overlay-config .sheet-footer {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 10px;
}
#dh-environment-overlay-config .sheet-footer button {
font-family: 'Cinzel', serif;
color: light-dark(var(--dark-blue), var(--golden));
background: light-dark(transparent, var(--deep-black));
border: 1px solid light-dark(var(--dark-blue), var(--golden));
box-shadow: 0 0 5px var(--soft-shadow);
height: 40px;
width: 140px;
display: flex;
align-items: center;
justify-content: center;
}
#dh-environment-overlay-config .sheet-footer button:hover {
border-color: light-dark(var(--dark-blue), var(--golden));
color: light-dark(var(--dark-blue), var(--golden));
background: rgba(255, 255, 255, 0.1);
}
/* Scene Config Styles */
.dh-environment-wrapper {
margin-top: 10px;
@ -72,7 +158,8 @@
}
#dh-environment-overlay img {
border-radius: 50%; /* Default fallback */
border-radius: 50%;
/* Default fallback */
border: 3px solid var(--dh-overlay-color, #ffcc00);
box-shadow: 0 0 10px var(--dh-overlay-color, rgba(0, 0, 0, 0.5));
background-color: #000;

View file

@ -0,0 +1,43 @@
<form autocomplete="off">
<p class="notes">Configure the visual appearance of the Environment Overlay.</p>
<div class="form-group">
<label data-tooltip="Default: 80">Icon Size (px)</label>
<div class="form-fields">
<input type="range" name="iconSize" value="{{iconSize}}" min="30" max="200" step="5" data-dtype="Number">
<span class="range-value">{{iconSize}}</span>
</div>
</div>
<div class="form-group">
<label data-tooltip="Default: Rounded Square">Icon Shape</label>
<div class="form-fields">
<select name="iconShape" data-dtype="String">
{{selectOptions shapes selected=iconShape}}
</select>
</div>
</div>
<div class="form-group">
<label data-tooltip="Default: #f3c267">Border & Glow Color</label>
<div class="form-fields">
<color-picker name="borderColor" value="{{borderColor}}"></color-picker>
</div>
</div>
<div class="form-group">
<label data-tooltip="Default: Checked">Show Actor Name</label>
<div class="form-fields">
<input type="checkbox" name="showName" {{checked showName}}>
</div>
</div>
<footer class="sheet-footer flexrow">
<button type="submit" name="submit">
<i class="fas fa-save"></i> Save Changes
</button>
<button type="button" data-action="reset">
<i class="fas fa-undo"></i> Reset Defaults
</button>
</footer>
</form>