feat: introduce a custom configuration UI for environment overlay settings, including a new template and styles.
This commit is contained in:
parent
773a95641b
commit
9192703e96
3 changed files with 228 additions and 19 deletions
|
|
@ -4,11 +4,20 @@ const FLAG_KEY = "environmentUuid";
|
||||||
Hooks.once("init", () => {
|
Hooks.once("init", () => {
|
||||||
console.log(`${MODULE_ID} | Initializing Daggerheart Environment Overlay`);
|
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", {
|
game.settings.register(MODULE_ID, "borderColor", {
|
||||||
name: "Overlay Border Color",
|
name: "Overlay Border Color",
|
||||||
hint: "Color of the environment token border.",
|
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: false,
|
||||||
type: String,
|
type: String,
|
||||||
default: "#f3c267",
|
default: "#f3c267",
|
||||||
onChange: () => renderEnvironmentOverlay()
|
onChange: () => renderEnvironmentOverlay()
|
||||||
|
|
@ -16,45 +25,115 @@ Hooks.once("init", () => {
|
||||||
|
|
||||||
game.settings.register(MODULE_ID, "iconSize", {
|
game.settings.register(MODULE_ID, "iconSize", {
|
||||||
name: "Icon Size",
|
name: "Icon Size",
|
||||||
hint: "Size of the environment token in pixels.",
|
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: false,
|
||||||
type: Number,
|
type: Number,
|
||||||
range: {
|
|
||||||
min: 30,
|
|
||||||
max: 200,
|
|
||||||
step: 5
|
|
||||||
},
|
|
||||||
default: 80,
|
default: 80,
|
||||||
onChange: () => renderEnvironmentOverlay()
|
onChange: () => renderEnvironmentOverlay()
|
||||||
});
|
});
|
||||||
|
|
||||||
game.settings.register(MODULE_ID, "iconShape", {
|
game.settings.register(MODULE_ID, "iconShape", {
|
||||||
name: "Icon Shape",
|
name: "Icon Shape",
|
||||||
hint: "Shape of the environment token overlay.",
|
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: false,
|
||||||
type: String,
|
type: String,
|
||||||
choices: {
|
|
||||||
"rounded": "Rounded Square",
|
|
||||||
"square": "Square",
|
|
||||||
"circle": "Circle"
|
|
||||||
},
|
|
||||||
default: "rounded",
|
default: "rounded",
|
||||||
onChange: () => renderEnvironmentOverlay()
|
onChange: () => renderEnvironmentOverlay()
|
||||||
});
|
});
|
||||||
|
|
||||||
game.settings.register(MODULE_ID, "showName", {
|
game.settings.register(MODULE_ID, "showName", {
|
||||||
name: "Show Actor Name",
|
name: "Show Actor Name",
|
||||||
hint: "Display the environment actor's name below the token.",
|
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
onChange: () => renderEnvironmentOverlay()
|
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
|
* Handle Scene Configuration Render
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
/* Scene Config Styles */
|
||||||
.dh-environment-wrapper {
|
.dh-environment-wrapper {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
|
@ -72,7 +158,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#dh-environment-overlay img {
|
#dh-environment-overlay img {
|
||||||
border-radius: 50%; /* Default fallback */
|
border-radius: 50%;
|
||||||
|
/* Default fallback */
|
||||||
border: 3px solid var(--dh-overlay-color, #ffcc00);
|
border: 3px solid var(--dh-overlay-color, #ffcc00);
|
||||||
box-shadow: 0 0 10px var(--dh-overlay-color, rgba(0, 0, 0, 0.5));
|
box-shadow: 0 0 10px var(--dh-overlay-color, rgba(0, 0, 0, 0.5));
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
|
|
|
||||||
43
templates/overlay-config.hbs
Normal file
43
templates/overlay-config.hbs
Normal 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>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue