diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index f01a2390..b027f814 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ # These are supported funding model platforms -github: Azgaar + patreon: Azgaar diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 698d23ae..00000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,89 +0,0 @@ -# Fantasy Map Generator - -Azgaar's Fantasy Map Generator is a client-side JavaScript web application for creating fantasy maps. It generates detailed fantasy worlds with countries, cities, rivers, biomes, and cultural elements. - -Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. - -## Working Effectively - -- **CRITICAL**: This is a static web application - NO build process needed. No npm install, no compilation, no bundling. -- Run the application using HTTP server (required - cannot run with file:// protocol): - - `python3 -m http.server 8000` - takes 2-3 seconds to start -- Access at: `http://localhost:8000` - -## Validation - -- Always manually validate any changes by: - 1. Starting the HTTP server (NEVER CANCEL - wait for full startup) - 2. Navigate to the application in browser - 3. Click the "►" button to open the menu and generate a new map - 4. **CRITICAL VALIDATION**: Verify the map generates with countries, cities, roads, and geographic features - 5. Test UI interaction: click "Layers" button, verify layer controls work - 6. Test regeneration: click "New Map!" button, verify new map generates correctly -- **Known Issues**: Google Analytics and font loading errors are normal (blocked external resources) - -## Repository Structure - -### Core Files - -- `index.html` - Main application entry point -- `main.js` - Core application logic -- `versioning.js` - Version management and update handling - -### Key Directories - -- `modules/` - core functionality modules: - - `modules/ui/` - UI components (editors, tools, style management) - - `modules/dynamic/` - runtime modules (export, installation) - - `modules/renderers/` - drawing and rendering logic -- `utils/` - utility libraries (math, arrays, strings, etc.) -- `styles/` - visual style presets (JSON files) -- `libs/` - Third-party libraries (D3.js, TinyMCE, etc.) -- `images/` - backgrounds, UI elements -- `charges/` - heraldic symbols and coat of arms elements -- `config/` - Heightmap templates and configurations -- `heightmaps/` - Terrain generation data - -## Common Tasks - -### Making Code Changes - -1. Edit JavaScript files directly (no compilation needed) -2. Refresh browser to see changes immediately -3. **ALWAYS test map generation** after making changes -4. Update version in `versioning.js` for all changes -5. Update file hashes in `index.html` for changed files (format: `file.js?v=1.108.1`) - -### Debugging Map Generation - -- Open browser developer tools console -- Look for timing logs, e.g. "TOTAL: ~0.76s" -- Map generation logs show each step (heightmap, rivers, states, etc.) -- Error messages will indicate specific generation failures - -### Testing Different Map Types - -- Use "New Map!" button for quick regeneration -- Access "Layers" menu to change map visualization -- Available presets: Political, Cultural, Religions, Biomes, Heightmap, Physical, Military - -## Troubleshooting - -### Application Won't Load - -- Ensure using HTTP server (not file://) -- Check console for JavaScript errors -- Verify all files are present in repository - -### Map Generation Fails - -- Check browser console for error messages -- Look for specific module failures in generation logs -- Try refreshing page and generating new map - -### Performance Issues - -- Map generation should complete in ~1 second for standard configurations -- If slower, check browser console for errors - -Remember: This is a sophisticated client-side application that generates complete fantasy worlds with political systems, geography, cultures, and detailed cartographic elements. Always validate that your changes preserve the core map generation functionality. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index acedeb18..b254d0ad 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -14,8 +14,8 @@ # Versioning - diff --git a/components/slider-input.js b/components/slider-input.js deleted file mode 100644 index f1732027..00000000 --- a/components/slider-input.js +++ /dev/null @@ -1,78 +0,0 @@ -{ - const style = /* css */ ` - slider-input { - display: flex; - align-items: center; - gap: .4em; - } - `; - - const styleElement = document.createElement("style"); - styleElement.setAttribute("type", "text/css"); - styleElement.innerHTML = style; - document.head.appendChild(styleElement); -} - -{ - const template = document.createElement("template"); - template.innerHTML = /* html */ ` - - - `; - - class SliderInput extends HTMLElement { - constructor() { - super(); - this.appendChild(template.content.cloneNode(true)); - - const range = this.querySelector("input[type=range]"); - const number = this.querySelector("input[type=number]"); - - range.value = number.value = this.value || this.getAttribute("value") || 50; - range.min = number.min = this.getAttribute("min") || 0; - range.max = number.max = this.getAttribute("max") || 100; - range.step = number.step = this.getAttribute("step") || 1; - - range.addEventListener("input", this.handleEvent.bind(this)); - number.addEventListener("input", this.handleEvent.bind(this)); - range.addEventListener("change", this.handleEvent.bind(this)); - number.addEventListener("change", this.handleEvent.bind(this)); - } - - handleEvent(e) { - const value = e.target.value; - const isNaN = Number.isNaN(Number(value)); - if (isNaN || value === "") return e.stopPropagation(); - - const range = this.querySelector("input[type=range]"); - const number = this.querySelector("input[type=number]"); - this.value = range.value = number.value = value; - - this.dispatchEvent( - new CustomEvent(e.type, { - detail: {value}, - bubbles: true, - composed: true - }) - ); - } - - set value(value) { - const range = this.querySelector("input[type=range]"); - const number = this.querySelector("input[type=number]"); - range.value = number.value = value; - } - - get value() { - const number = this.querySelector("input[type=number]"); - return number.value; - } - - get valueAsNumber() { - const number = this.querySelector("input[type=number]"); - return number.valueAsNumber; - } - } - - customElements.define("slider-input", SliderInput); -} diff --git a/icons.css b/icons.css index 4740f091..ae40ee00 100644 --- a/icons.css +++ b/icons.css @@ -253,7 +253,7 @@ .icon-coa:before {content:'\f3ed'; font-size: .9em; color: #999;} /* '' */ .icon-half:before {font-weight: bold;content:'½';} .icon-voice:before {content:'🔊';} -.icon-robot:before {content:'🤖';} + .icon-die:before {content:'🎲';} .icon-button-die:before {content:'🎲'; padding-right: .4em;} .icon-button-power:before {content:'💪'; padding-right: .6em;} diff --git a/index.css b/index.css index 373bf63c..555b650c 100644 --- a/index.css +++ b/index.css @@ -122,6 +122,10 @@ a { fill: none; } +#biomes { + stroke-width: 0.7; +} + #landmass { mask: url(#land); fill-rule: evenodd; @@ -166,7 +170,6 @@ t, #texture, #landmass, #vignette, -#gridOverlay, #fogging { pointer-events: none; } @@ -187,12 +190,20 @@ t, font-size: 0.8em; } +#statesBody { + stroke-width: 3; +} + #statesHalo { fill: none; stroke-linecap: round; stroke-linejoin: round; } +#provincesBody { + stroke-width: 0.2; +} + #statesBody, #provincesBody, #relig, @@ -345,14 +356,6 @@ text.drag { font-weight: bold; } -button.ui-button:disabled { - filter: brightness(0.95); -} - -button.ui-button:disabled:hover { - cursor: default; -} - .ui-dialog, #optionsContainer { user-select: none; @@ -522,53 +525,7 @@ input[type="color"]::-webkit-color-swatch-wrapper { font-size: smaller; } -#options input[type="text"] { - border: 0px; - width: 62%; - font-size: smaller; -} - -#options output { - text-align: right; - font-size: smaller; -} - -#options input[type="number"] { - font-size: 0.8em; - border: 0; - text-align: right; - background-color: transparent; - width: 3.3em; -} - -#options input[type="number"]::-webkit-inner-spin-button, -#options input[type="number"]::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -#options input[type="number"] { - appearance: textfield; - -moz-appearance: textfield; -} - -#options input[type="number"]:hover { - outline: 1px solid var(--dark-solid); -} - -#options input.paired { - text-align: center; - background-color: white; -} - -#options input.long { - width: 100%; - background-color: white; - text-align: left; -} - #options input[type="range"] { - width: 100%; height: 8px; background: 0; appearance: none; @@ -611,7 +568,55 @@ input[type="color"]::-webkit-color-swatch-wrapper { height: 2px; } -#options select { +#options input[type="number"] { + font-size: 0.8em; +} + +#options input[type="text"] { + border: 0px; + width: 62%; + font-size: smaller; +} + +#optionsContent output { + text-align: right; + font-size: smaller; +} + +#optionsContent input[type="number"] { + border: 0; + text-align: right; + background-color: transparent; + width: 3.3em; + -moz-appearance: textfield; +} + +#optionsContent input[type="number"]::-webkit-inner-spin-button, +#optionsContent input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +#optionsContent input[type="number"]:hover { + outline: 1px solid var(--dark-solid); +} + +#optionsContent input.paired { + text-align: center; + background-color: white; +} + +#optionsContent input.long { + width: 100%; + background-color: white; + text-align: left; +} + +#optionsContent input[type="range"] { + width: 100%; +} + +#optionsContent select { width: 100%; } @@ -636,6 +641,19 @@ input[type="color"]::-webkit-color-swatch-wrapper { transform: translate(0px, 1px); } +#styleElements input[type="range"] { + width: 64%; +} + +#styleElements select { + width: 64%; +} + +#styleElements input[type="number"] { + width: 6em; + border: 0; +} + #styleSelectFont > option { font-size: 2em; } @@ -674,7 +692,6 @@ input[type="color"]::-webkit-color-swatch-wrapper { border: none; padding: 0.45em 0.75em; margin: 0.4em 0; - white-space: nowrap; font-family: var(--monospace); animation: glowing 2s infinite; } @@ -707,6 +724,9 @@ input[type="color"]::-webkit-color-swatch-wrapper { padding: 0.45em 0.75em; margin: 0.35em 0; transition: 0.1s; + font-size: 1em; + text-transform: capitalize; + overflow: hidden; white-space: nowrap; text-overflow: ellipsis; @@ -723,7 +743,7 @@ input[type="color"]::-webkit-color-swatch-wrapper { #toolsContent > .grid { display: grid; - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(4, 1fr); margin: 0.2em 0; } @@ -770,7 +790,7 @@ fieldset { text-overflow: ellipsis; } -.tabcontent li.buttonoff { +.tabcontent .buttonoff { background-color: var(--bg-disabled); color: #444444aa; } @@ -1248,6 +1268,7 @@ i.resetButton:active { padding: 0; height: 2px; background: #d4d4d4; + top: -0.35em; position: relative; appearance: none; -webkit-appearance: none; @@ -1512,6 +1533,20 @@ div.states > .burgCulture { width: 6em; } +div.states .burgPopulation { + width: 4.8em; +} + +div.states .burgType { + width: 3em; +} + +div.states .burgType > span { + padding: 0 1px; + color: #6e5e66; + transition: 0.2s; +} + div.states span.inactive { color: #c6c2c2; } @@ -1809,6 +1844,11 @@ div.editorLine { padding: 0px 3px !important; } +#unitsBody > div > * { + display: inline-block; + margin-bottom: 0.2em; +} + .unitsHeader { margin: 0.8em 0 0 -1.1em; font-weight: bold; @@ -1820,19 +1860,26 @@ div.editorLine { margin: 6px 0 0 6px; } -#unitsBody label { - display: inline-block; +#unitsBody > div > div { width: 9em; } +#unitsBody > div > input[type="range"] { + width: 7em; +} + #unitsBody > div > select, #unitsBody > div > input[type="text"] { - width: 14.4em; - border: 1px solid #e9e9e9; + width: 12em; } -#unitsBody input[type="range"] { - width: 9em; +#unitsBody > div > input[type="number"] { + width: 4.35em; +} + +#unitsBody > div > input, +#unitsBody > div > select { + border: 1px solid #e9e9e9; } #unitsEditor i.icon-lock-open, @@ -2367,34 +2414,6 @@ svg.button { margin-left: 0.25em; } -@keyframes clockwiseBorderPulse { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} - -#chat-widget-container { - user-select: none; -} - -#chat-widget-minimized { - animation: fadeIn 1s ease-in; - transform: scale(0.65); - opacity: var(--bg-opacity); -} - -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: var(--bg-opacity); - } -} - @media print { div, canvas { diff --git a/index.html b/index.html index 5a18e579..6453976a 100644 --- a/index.html +++ b/index.html @@ -11,8 +11,8 @@ name="description" content="Free web app that helps fantasy writers, game masters, and cartographers create and edit fantasy maps" /> - + - + - + - - - - - + + + + + + @@ -442,7 +438,7 @@ xture @@ -490,6 +487,7 @@ id="toggleHeight" data-tip="Heightmap: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="H" + class="buttonoff" onclick="toggleHeight(event)" > Heightmap @@ -498,6 +496,7 @@ id="toggleBiomes" data-tip="Biomes: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="B" + class="buttonoff" onclick="toggleBiomes(event)" > Biomes @@ -506,6 +505,7 @@ id="toggleCells" data-tip="Cells structure: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="E" + class="buttonoff" onclick="toggleCells(event)" > Cells @@ -514,6 +514,7 @@ id="toggleGrid" data-tip="Grid: click to toggle, drag to raise or lower. Ctrl + click to edit layer style and select type" data-shortcut="G" + class="buttonoff" onclick="toggleGrid(event)" > Grid @@ -522,6 +523,7 @@ id="toggleCoordinates" data-tip="Coordinate grid: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="O" + class="buttonoff" onclick="toggleCoordinates(event)" > Coordinates @@ -530,6 +532,7 @@ id="toggleCompass" data-tip="Wind (Compass) Rose: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="W" + class="buttonoff" onclick="toggleCompass(event)" > Wind Rose @@ -546,6 +549,7 @@ id="toggleRelief" data-tip="Relief and biome icons: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="F" + class="buttonoff" onclick="toggleRelief(event)" > Relief @@ -554,6 +558,7 @@ id="toggleReligions" data-tip="Religions: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="R" + class="buttonoff" onclick="toggleReligions(event)" > Religions @@ -562,6 +567,7 @@ id="toggleCultures" data-tip="Cultures: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="C" + class="buttonoff" onclick="toggleCultures(event)" > Cultures @@ -578,6 +584,7 @@ id="toggleProvinces" data-tip="Provinces: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="P" + class="buttonoff" onclick="toggleProvinces(event)" > Provinces @@ -586,6 +593,7 @@ id="toggleZones" data-tip="Zones: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="Z" + class="buttonoff" onclick="toggleZones(event)" > Zones @@ -602,15 +610,17 @@ id="toggleRoutes" data-tip="Trade routes: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="U" + class="buttonoff" onclick="toggleRoutes(event)" > Routes
  • Temperature
  • @@ -618,6 +628,7 @@ id="togglePopulation" data-tip="Population map: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="N" + class="buttonoff" onclick="togglePopulation(event)" > Population @@ -626,15 +637,17 @@ id="toggleIce" data-tip="Icebergs and glaciers: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="J" + class="buttonoff" onclick="toggleIce(event)" > Ice
  • Precipitation
  • @@ -642,6 +655,7 @@ id="toggleEmblems" data-tip="Emblems: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="Y" + class="buttonoff" onclick="toggleEmblems(event)" > Emblems @@ -655,10 +669,10 @@ Labels
  • Icons
  • @@ -666,6 +680,7 @@ id="toggleMilitary" data-tip="Military forces: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="M" + class="buttonoff" onclick="toggleMilitary(event)" > Military @@ -674,6 +689,7 @@ id="toggleMarkers" data-tip="Markers: click to toggle, drag to raise or lower the layer. Ctrl + click to edit layer style" data-shortcut="K" + class="buttonoff" onclick="toggleMarkers(event)" > Markers @@ -682,6 +698,7 @@ id="toggleRulers" data-tip="Rulers: click to toggle, drag to move, click on label to delete. Ctrl + click to edit layer style" data-shortcut="= (equal sign)" + class="buttonoff" onclick="toggleRulers(event)" > Rulers @@ -819,24 +836,27 @@ - + Terracing - + + 0 Reduce layers - + + 5 Simplify line - + + 0 @@ -854,7 +874,7 @@ Color scheme - + @@ -1229,7 +1241,7 @@ - + @@ -1269,14 +1281,16 @@ Fill opacity - + + 0.3 Labels size - + + 8 @@ -1293,7 +1307,8 @@ Body opacity - + + @@ -1311,21 +1326,24 @@ Halo width - + + 10 Halo opacity - + + 1 Halo blur - + + 4 @@ -1334,36 +1352,62 @@ Fill opacity - + + 1 Box Size - + + 3 - State size + State Size - + - Province size + Province Size - + - Burg size + Burg Size - + @@ -1451,14 +1495,15 @@ Back opacity - + + Back fill - + @@ -1466,7 +1511,7 @@ Back stroke - + Width @@ -1528,9 +1573,7 @@ - + - + Year and era @@ -1640,10 +1683,10 @@ Cultures number - + - + @@ -1669,41 +1712,53 @@ - + States number - - + + + + + - + Provinces ratio - - + + + + + - + Size variety - - + + + + + - + Growth rate - - + + + + + @@ -1724,17 +1779,14 @@ data-tip="Define how many organized religions and cults should be generated. Cultures will have their own folk religions in any case" > - + Religions number - - + + + + + @@ -1763,16 +1815,22 @@ > Interface size - - + + + + + Tooltip size - - + + + + + @@ -1792,8 +1850,11 @@ Transparency - - + + + + + @@ -1836,17 +1897,6 @@ - - - Azgaar assistant - - - - - Speaker voice @@ -2010,8 +2060,8 @@ @@ -2095,7 +2145,7 @@ id="regenerateStateLabels" data-tip="Click to update state labels placement based on current borders" > - State Labels + Labels @@ -2189,8 +2239,8 @@
    Create
    - - + +
    @@ -2699,24 +2749,6 @@ /> - - - - - + @@ -3644,10 +3667,10 @@ >
    -
    -
    Emblem:
    -
    - +
    +
    Emblem:
    + +
    @@ -4100,24 +4123,72 @@