mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
markers rework - editor functions
This commit is contained in:
parent
def32b7f74
commit
95f9d990d9
8 changed files with 633 additions and 214 deletions
10
index.css
10
index.css
|
|
@ -238,8 +238,7 @@ i.icon-lock {
|
|||
}
|
||||
|
||||
#routeEditor > *,
|
||||
#labelEditor div,
|
||||
#markerEditor div {
|
||||
#labelEditor div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
|
@ -1525,7 +1524,8 @@ div.states > .coaIcon > use {
|
|||
|
||||
#stateNameEditor div.label,
|
||||
#provinceNameEditor div.label,
|
||||
#regimentBody div.label {
|
||||
#regimentBody div.label,
|
||||
#markerEditor div.label {
|
||||
display: inline-block;
|
||||
width: 5.5em;
|
||||
}
|
||||
|
|
@ -1974,10 +1974,6 @@ div.textual span,
|
|||
dominant-baseline: central;
|
||||
}
|
||||
|
||||
#markerEditor > button {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.highlighted {
|
||||
outline-width: 2px;
|
||||
outline-style: dashed;
|
||||
|
|
|
|||
85
index.html
85
index.html
|
|
@ -2036,39 +2036,66 @@
|
|||
</div>
|
||||
|
||||
<div id="markerEditor" class="dialog" style="display: none">
|
||||
<div id="markerBody" style="padding-bottom: .3em">
|
||||
<div data-tip="Marker type. Style changes will apply to all markers of the same type. Leave blank if the marker is unique">
|
||||
<div class="label">Type:</div>
|
||||
<input id="markerType" />
|
||||
</div>
|
||||
|
||||
<button id="markerGroup" data-tip="Change marker type" class="icon-tags"></button>
|
||||
<div id="markerGroupSection" style="display: none">
|
||||
<select id="markerSelectGroup" data-tip="Select type for the selected marker" style="width: 10em"></select>
|
||||
<input id="markerInputGroup" data-tip="Create new type for selected marker" placeholder="type new name" style="display: none; width: 10em"/>
|
||||
<i id="markerAddGroup" data-tip="Create new markers type" class="icon-plus pointer"></i>
|
||||
<i id="markerRemoveGroup" data-tip="Remove all markers of that type" class="icon-trash pointer"></i>
|
||||
<div data-tip="Marker icon. Paste any Unicode symbol or select from the predefined list">
|
||||
<div class="label">Icon:</div>
|
||||
<input id="markerIcon" style="width:5em" />
|
||||
<button id="markerIconSelect" style="padding: 0; width: 4.5em">select</button>
|
||||
</div>
|
||||
|
||||
<div data-tip="Marker icon size in pixels">
|
||||
<div class="label">Icon size:</div>
|
||||
<input id="markerIconSize" type="number" min="2" max="20" step="0.5" />
|
||||
</div>
|
||||
|
||||
<div data-tip="Marker icon shift (by X and by Y axis), percent. Set to 50 to position icon in center">
|
||||
<div class="label">Icon shift:</div>
|
||||
<input id="markerIconShiftX" type="number" min="0" max="100" step="1" style="width:5em" />
|
||||
<input id="markerIconShiftY" type="number" min="0" max="100" step="1" style="width:5em" />
|
||||
</div>
|
||||
|
||||
<div data-tip="Size of the marker">
|
||||
<div class="label">Marker size:</div>
|
||||
<input id="markerSize" type="number" min="2" max="500" />
|
||||
</div>
|
||||
|
||||
<div data-tip="Marker pin shape">
|
||||
<div class="label">Pin shape:</div>
|
||||
<select id="markerPin" >
|
||||
<option value="bubble">Bubble</option>
|
||||
<option value="pin">Pin</option>
|
||||
<option value="square">Square</option>
|
||||
<option value="squarish">Squarish</option>
|
||||
<option value="diamond">Diamond</option>
|
||||
<option value="hex">Hex</option>
|
||||
<option value="hexy">Hexy</option>
|
||||
<option value="shieldy">Shieldy</option>
|
||||
<option value="shield">Shield</option>
|
||||
<option value="pentagon">Pentagon</option>
|
||||
<option value="heptagon">Heptagon</option>
|
||||
<option value="circle">Circle</option>
|
||||
<option value="no">No</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div data-tip="Pin fill and stroke colors">
|
||||
<div class="label">Pin colors:</div>
|
||||
<input id="markerFill" type="color" style="width:5em" />
|
||||
<input id="markerStroke" type="color" style="width:5em" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="markerIcon" data-tip="Change marker icon and edit positioning" class="icon-star"></button>
|
||||
<div id="markerIconSection" style="display: none">
|
||||
<i data-tip="Change marker icon size" class="icon-resize-full"></i>
|
||||
<input id="markerIconSize" data-tip="Change marker icon size" type="range" min=5 max=30 step=.5 value=22 style="width:12em"><br>
|
||||
<i data-tip="Marker Icon" class="icon-info"></i>
|
||||
<button id="markerIconSelect" data-tip="Click to select icon"></button>
|
||||
<i data-tip="Change marker horizontal shift" class="icon-resize-horizontal"></i>
|
||||
<input id="markerIconShiftX" data-tip="Change icon horizontal shift" type="number" value=50>
|
||||
<i data-tip="Change marker vertical shift" class="icon-resize-vertical"></i>
|
||||
<input id="markerIconShiftY" data-tip="Change vertical shift" type="number" min=0 max=100 value=50>
|
||||
<div id="markerBottom">
|
||||
<button id="markerNotes" data-tip="Edit place legend (notes)" class="icon-edit"></button>
|
||||
<button id="markerLock" class="icon-lock-open"></button>
|
||||
<button id="markerAdd" data-tip="Add additional marker of that type" class="icon-plus"></button>
|
||||
<button id="markerRemove" data-tip="Remove the marker. Shortcut: Delete" class="icon-trash fastDelete"></button>
|
||||
</div>
|
||||
|
||||
<button id="markerStyle" data-tip="Change marker size and colors" class="icon-brush"></button>
|
||||
<div id="markerStyleSection" style="display: none">
|
||||
<i data-tip="Change marker base (pin) style" class="icon-map-pin"></i>
|
||||
<input id="markerSize" data-tip="Change marker size" type="range" min=.01 max=10 step=.1 value=1 style="width:12em">
|
||||
<input id="markerBaseStroke" data-tip="Change pin stroke color" type="color" value="#ffffff">
|
||||
<input id="markerBaseFill" data-tip="Change pin fill color" type="color" alue="#000000">
|
||||
</div>
|
||||
|
||||
<button id="markerToggleBubble" data-tip="Toggle pin (bubble) display" class="icon-info-circled"></button>
|
||||
<button id="markerLegendButton" data-tip="Edit place legend (free text notes)" class="icon-edit"></button>
|
||||
<button id="markerAdd" data-tip="Add additional marker of that type" class="icon-plus"></button>
|
||||
<button id="markerRemove" data-tip="Remove the marker. Shortcut: Delete" class="icon-trash fastDelete"></button>
|
||||
</div>
|
||||
|
||||
<div id="regimentEditor" class="dialog" style="display: none">
|
||||
|
|
|
|||
49
main.js
49
main.js
|
|
@ -338,11 +338,39 @@ function findBurgForMFCG(params) {
|
|||
|
||||
// apply default biomes data
|
||||
function applyDefaultBiomesSystem() {
|
||||
const name = ["Marine", "Hot desert", "Cold desert", "Savanna", "Grassland", "Tropical seasonal forest", "Temperate deciduous forest", "Tropical rainforest", "Temperate rainforest", "Taiga", "Tundra", "Glacier", "Wetland"];
|
||||
const name = [
|
||||
"Marine",
|
||||
"Hot desert",
|
||||
"Cold desert",
|
||||
"Savanna",
|
||||
"Grassland",
|
||||
"Tropical seasonal forest",
|
||||
"Temperate deciduous forest",
|
||||
"Tropical rainforest",
|
||||
"Temperate rainforest",
|
||||
"Taiga",
|
||||
"Tundra",
|
||||
"Glacier",
|
||||
"Wetland"
|
||||
];
|
||||
const color = ["#466eab", "#fbe79f", "#b5b887", "#d2d082", "#c8d68f", "#b6d95d", "#29bc56", "#7dcb35", "#409c43", "#4b6b32", "#96784b", "#d5e7eb", "#0b9131"];
|
||||
const habitability = [0, 4, 10, 22, 30, 50, 100, 80, 90, 12, 4, 0, 12];
|
||||
const iconsDensity = [0, 3, 2, 120, 120, 120, 120, 150, 150, 100, 5, 0, 150];
|
||||
const icons = [{}, {dune: 3, cactus: 6, deadTree: 1}, {dune: 9, deadTree: 1}, {acacia: 1, grass: 9}, {grass: 1}, {acacia: 8, palm: 1}, {deciduous: 1}, {acacia: 5, palm: 3, deciduous: 1, swamp: 1}, {deciduous: 6, swamp: 1}, {conifer: 1}, {grass: 1}, {}, {swamp: 1}];
|
||||
const icons = [
|
||||
{},
|
||||
{dune: 3, cactus: 6, deadTree: 1},
|
||||
{dune: 9, deadTree: 1},
|
||||
{acacia: 1, grass: 9},
|
||||
{grass: 1},
|
||||
{acacia: 8, palm: 1},
|
||||
{deciduous: 1},
|
||||
{acacia: 5, palm: 3, deciduous: 1, swamp: 1},
|
||||
{deciduous: 6, swamp: 1},
|
||||
{conifer: 1},
|
||||
{grass: 1},
|
||||
{},
|
||||
{swamp: 1}
|
||||
];
|
||||
const cost = [10, 200, 150, 60, 50, 70, 70, 80, 90, 200, 1000, 5000, 150]; // biome movement cost
|
||||
const biomesMartix = [
|
||||
// hot ↔ cold [>19°C; <-4°C]; dry ↕ wet
|
||||
|
|
@ -494,9 +522,7 @@ function invokeActiveZooming() {
|
|||
+markers.attr("rescale") &&
|
||||
pack.markers?.forEach(marker => {
|
||||
const {i, x, y, size = 30, hidden} = marker;
|
||||
if (hidden) return;
|
||||
|
||||
const el = document.getElementById(`marker${i}`);
|
||||
const el = !hidden && document.getElementById(`marker${i}`);
|
||||
if (!el) return;
|
||||
|
||||
const zoomedSize = Math.max(rn(size / 5 + 24 / scale, 2), 1);
|
||||
|
|
@ -1483,7 +1509,18 @@ function addZones(number = 1) {
|
|||
});
|
||||
}
|
||||
|
||||
const invasion = rw({Invasion: 4, Occupation: 3, Raid: 2, Conquest: 2, Subjugation: 1, Foray: 1, Skirmishes: 1, Incursion: 2, Pillaging: 1, Intervention: 1});
|
||||
const invasion = rw({
|
||||
Invasion: 4,
|
||||
Occupation: 3,
|
||||
Raid: 2,
|
||||
Conquest: 2,
|
||||
Subjugation: 1,
|
||||
Foray: 1,
|
||||
Skirmishes: 1,
|
||||
Incursion: 2,
|
||||
Pillaging: 1,
|
||||
Intervention: 1
|
||||
});
|
||||
const name = getAdjective(invader.name) + " " + invasion;
|
||||
data.push({name, type: "Invasion", cells: cellsArray, fill: "url(#hatch1)"});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ window.Markers = (function () {
|
|||
TIME && console.time("addMarkers");
|
||||
|
||||
const culturesSet = document.getElementById("culturesSet").value;
|
||||
// TODO: don't put multiple markers to the same cell
|
||||
|
||||
addVolcanoes();
|
||||
addHotSprings();
|
||||
|
|
@ -120,7 +121,9 @@ window.Markers = (function () {
|
|||
const {cells, burgs} = pack;
|
||||
|
||||
const meanFlux = d3.mean(cells.fl.filter(fl => fl));
|
||||
let bridges = Array.from(cells.i.filter(i => cells.burg[i] && cells.t[i] !== 1 && burgs[cells.burg[i]].population > 20 && cells.r[i] && cells.fl[i] > meanFlux));
|
||||
let bridges = Array.from(
|
||||
cells.i.filter(i => cells.burg[i] && cells.t[i] !== 1 && burgs[cells.burg[i]].population > 20 && cells.r[i] && cells.fl[i] > meanFlux)
|
||||
);
|
||||
let quantity = getQuantity(bridges, 1, 5);
|
||||
if (!quantity) return;
|
||||
|
||||
|
|
@ -143,13 +146,233 @@ window.Markers = (function () {
|
|||
let quantity = getQuantity(taverns, 1, 100);
|
||||
if (!quantity) return;
|
||||
|
||||
const colors = ["Dark", "Light", "Bright", "Golden", "White", "Black", "Red", "Pink", "Purple", "Blue", "Green", "Yellow", "Amber", "Orange", "Brown", "Grey"];
|
||||
const animals = ["Antelope", "Ape", "Badger", "Bear", "Beaver", "Bison", "Boar", "Buffalo", "Cat", "Crane", "Crocodile", "Crow", "Deer", "Dog", "Eagle", "Elk", "Fox", "Goat", "Goose", "Hare", "Hawk", "Heron", "Horse", "Hyena", "Ibis", "Jackal", "Jaguar", "Lark", "Leopard", "Lion", "Mantis", "Marten", "Moose", "Mule", "Narwhal", "Owl", "Panther", "Rat", "Raven", "Rook", "Scorpion", "Shark", "Sheep", "Snake", "Spider", "Swan", "Tiger", "Turtle", "Wolf", "Wolverine", "Camel", "Falcon", "Hound", "Ox"];
|
||||
const adjectives = ["New", "Good", "High", "Old", "Great", "Big", "Major", "Happy", "Main", "Huge", "Far", "Beautiful", "Fair", "Prime", "Ancient", "Golden", "Proud", "Lucky", "Fat", "Honest", "Giant", "Distant", "Friendly", "Loud", "Hungry", "Magical", "Superior", "Peaceful", "Frozen", "Divine", "Favorable", "Brave", "Sunny", "Flying"];
|
||||
const methods = ["Boiled", "Grilled", "Roasted", "Spit-roasted", "Stewed", "Stuffed", "Jugged", "Mashed", "Baked", "Braised", "Poached", "Marinated", "Pickled", "Smoked", "Dried", "Dry-aged", "Corned", "Fried", "Pan-fried", "Deep-fried", "Dressed", "Steamed", "Cured", "Syrupped", "Flame-Broiled"];
|
||||
const courses = ["beef", "pork", "bacon", "chicken", "lamb", "chevon", "hare", "rabbit", "hart", "deer", "antlers", "bear", "buffalo", "badger", "beaver", "turkey", "pheasant", "duck", "goose", "teal", "quail", "pigeon", "seal", "carp", "bass", "pike", "catfish", "sturgeon", "escallop", "pie", "cake", "pottage", "pudding", "onions", "carrot", "potato", "beet", "garlic", "cabbage", "eggplant", "eggs", "broccoli", "zucchini", "pepper", "olives", "pumpkin", "spinach", "peas", "chickpea", "beans", "rice", "pasta", "bread", "apples", "peaches", "pears", "melon", "oranges", "mango", "tomatoes", "cheese", "corn", "rat tails", "pig ears"];
|
||||
const colors = [
|
||||
"Dark",
|
||||
"Light",
|
||||
"Bright",
|
||||
"Golden",
|
||||
"White",
|
||||
"Black",
|
||||
"Red",
|
||||
"Pink",
|
||||
"Purple",
|
||||
"Blue",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Amber",
|
||||
"Orange",
|
||||
"Brown",
|
||||
"Grey"
|
||||
];
|
||||
const animals = [
|
||||
"Antelope",
|
||||
"Ape",
|
||||
"Badger",
|
||||
"Bear",
|
||||
"Beaver",
|
||||
"Bison",
|
||||
"Boar",
|
||||
"Buffalo",
|
||||
"Cat",
|
||||
"Crane",
|
||||
"Crocodile",
|
||||
"Crow",
|
||||
"Deer",
|
||||
"Dog",
|
||||
"Eagle",
|
||||
"Elk",
|
||||
"Fox",
|
||||
"Goat",
|
||||
"Goose",
|
||||
"Hare",
|
||||
"Hawk",
|
||||
"Heron",
|
||||
"Horse",
|
||||
"Hyena",
|
||||
"Ibis",
|
||||
"Jackal",
|
||||
"Jaguar",
|
||||
"Lark",
|
||||
"Leopard",
|
||||
"Lion",
|
||||
"Mantis",
|
||||
"Marten",
|
||||
"Moose",
|
||||
"Mule",
|
||||
"Narwhal",
|
||||
"Owl",
|
||||
"Panther",
|
||||
"Rat",
|
||||
"Raven",
|
||||
"Rook",
|
||||
"Scorpion",
|
||||
"Shark",
|
||||
"Sheep",
|
||||
"Snake",
|
||||
"Spider",
|
||||
"Swan",
|
||||
"Tiger",
|
||||
"Turtle",
|
||||
"Wolf",
|
||||
"Wolverine",
|
||||
"Camel",
|
||||
"Falcon",
|
||||
"Hound",
|
||||
"Ox"
|
||||
];
|
||||
const adjectives = [
|
||||
"New",
|
||||
"Good",
|
||||
"High",
|
||||
"Old",
|
||||
"Great",
|
||||
"Big",
|
||||
"Major",
|
||||
"Happy",
|
||||
"Main",
|
||||
"Huge",
|
||||
"Far",
|
||||
"Beautiful",
|
||||
"Fair",
|
||||
"Prime",
|
||||
"Ancient",
|
||||
"Golden",
|
||||
"Proud",
|
||||
"Lucky",
|
||||
"Fat",
|
||||
"Honest",
|
||||
"Giant",
|
||||
"Distant",
|
||||
"Friendly",
|
||||
"Loud",
|
||||
"Hungry",
|
||||
"Magical",
|
||||
"Superior",
|
||||
"Peaceful",
|
||||
"Frozen",
|
||||
"Divine",
|
||||
"Favorable",
|
||||
"Brave",
|
||||
"Sunny",
|
||||
"Flying"
|
||||
];
|
||||
const methods = [
|
||||
"Boiled",
|
||||
"Grilled",
|
||||
"Roasted",
|
||||
"Spit-roasted",
|
||||
"Stewed",
|
||||
"Stuffed",
|
||||
"Jugged",
|
||||
"Mashed",
|
||||
"Baked",
|
||||
"Braised",
|
||||
"Poached",
|
||||
"Marinated",
|
||||
"Pickled",
|
||||
"Smoked",
|
||||
"Dried",
|
||||
"Dry-aged",
|
||||
"Corned",
|
||||
"Fried",
|
||||
"Pan-fried",
|
||||
"Deep-fried",
|
||||
"Dressed",
|
||||
"Steamed",
|
||||
"Cured",
|
||||
"Syrupped",
|
||||
"Flame-Broiled"
|
||||
];
|
||||
const courses = [
|
||||
"beef",
|
||||
"pork",
|
||||
"bacon",
|
||||
"chicken",
|
||||
"lamb",
|
||||
"chevon",
|
||||
"hare",
|
||||
"rabbit",
|
||||
"hart",
|
||||
"deer",
|
||||
"antlers",
|
||||
"bear",
|
||||
"buffalo",
|
||||
"badger",
|
||||
"beaver",
|
||||
"turkey",
|
||||
"pheasant",
|
||||
"duck",
|
||||
"goose",
|
||||
"teal",
|
||||
"quail",
|
||||
"pigeon",
|
||||
"seal",
|
||||
"carp",
|
||||
"bass",
|
||||
"pike",
|
||||
"catfish",
|
||||
"sturgeon",
|
||||
"escallop",
|
||||
"pie",
|
||||
"cake",
|
||||
"pottage",
|
||||
"pudding",
|
||||
"onions",
|
||||
"carrot",
|
||||
"potato",
|
||||
"beet",
|
||||
"garlic",
|
||||
"cabbage",
|
||||
"eggplant",
|
||||
"eggs",
|
||||
"broccoli",
|
||||
"zucchini",
|
||||
"pepper",
|
||||
"olives",
|
||||
"pumpkin",
|
||||
"spinach",
|
||||
"peas",
|
||||
"chickpea",
|
||||
"beans",
|
||||
"rice",
|
||||
"pasta",
|
||||
"bread",
|
||||
"apples",
|
||||
"peaches",
|
||||
"pears",
|
||||
"melon",
|
||||
"oranges",
|
||||
"mango",
|
||||
"tomatoes",
|
||||
"cheese",
|
||||
"corn",
|
||||
"rat tails",
|
||||
"pig ears"
|
||||
];
|
||||
const types = ["hot", "cold", "fire", "ice", "smoky", "misty", "shiny", "sweet", "bitter", "salty", "sour", "sparkling", "smelly"];
|
||||
const drinks = ["wine", "brandy", "jinn", "whisky", "rom", "beer", "cider", "mead", "liquor", "spirit", "vodka", "tequila", "absinthe", "nectar", "milk", "kvass", "kumis", "tea", "water", "juice", "sap"];
|
||||
const drinks = [
|
||||
"wine",
|
||||
"brandy",
|
||||
"jinn",
|
||||
"whisky",
|
||||
"rom",
|
||||
"beer",
|
||||
"cider",
|
||||
"mead",
|
||||
"liquor",
|
||||
"spirit",
|
||||
"vodka",
|
||||
"tequila",
|
||||
"absinthe",
|
||||
"nectar",
|
||||
"milk",
|
||||
"kvass",
|
||||
"kumis",
|
||||
"tea",
|
||||
"water",
|
||||
"juice",
|
||||
"sap"
|
||||
];
|
||||
|
||||
while (quantity) {
|
||||
const [cell] = extractAnyElement(taverns);
|
||||
|
|
@ -282,7 +505,14 @@ window.Markers = (function () {
|
|||
|
||||
const subjects = ["Locals", "Old folks", "Old books", "Tipplers"];
|
||||
const species = ["Ogre", "Troll", "Cyclops", "Giant", "Monster", "Beast", "Dragon", "Undead", "Ghoul", "Vampire"];
|
||||
const modusOperandi = ["steals their cattle", "doesn't mind eating children", "doesn't mind of human flesh", "keeps the region at bay", "eats their kids", "abducts young women"];
|
||||
const modusOperandi = [
|
||||
"steals their cattle",
|
||||
"doesn't mind eating children",
|
||||
"doesn't mind of human flesh",
|
||||
"keeps the region at bay",
|
||||
"eats their kids",
|
||||
"abducts young women"
|
||||
];
|
||||
|
||||
while (quantity) {
|
||||
const [cell] = extractAnyElement(hills);
|
||||
|
|
@ -376,7 +606,38 @@ window.Markers = (function () {
|
|||
let quantity = getQuantity(roads, 50, 100);
|
||||
if (!quantity) return;
|
||||
|
||||
const animals = ["Apes", "Badgers", "Bears", "Beavers", "Bisons", "Boars", "Cats", "Crows", "Dogs", "Foxes", "Hares", "Hawks", "Hyenas", "Jackals", "Jaguars", "Leopards", "Lions", "Owls", "Panthers", "Rats", "Ravens", "Rooks", "Scorpions", "Sharks", "Snakes", "Spiders", "Tigers", "Wolfs", "Wolverines", "Falcons"];
|
||||
const animals = [
|
||||
"Apes",
|
||||
"Badgers",
|
||||
"Bears",
|
||||
"Beavers",
|
||||
"Bisons",
|
||||
"Boars",
|
||||
"Cats",
|
||||
"Crows",
|
||||
"Dogs",
|
||||
"Foxes",
|
||||
"Hares",
|
||||
"Hawks",
|
||||
"Hyenas",
|
||||
"Jackals",
|
||||
"Jaguars",
|
||||
"Leopards",
|
||||
"Lions",
|
||||
"Owls",
|
||||
"Panthers",
|
||||
"Rats",
|
||||
"Ravens",
|
||||
"Rooks",
|
||||
"Scorpions",
|
||||
"Sharks",
|
||||
"Snakes",
|
||||
"Spiders",
|
||||
"Tigers",
|
||||
"Wolfs",
|
||||
"Wolverines",
|
||||
"Falcons"
|
||||
];
|
||||
const types = {brigands: 4, bandits: 3, robbers: 1, highwaymen: 1};
|
||||
|
||||
while (quantity) {
|
||||
|
|
@ -385,7 +646,18 @@ window.Markers = (function () {
|
|||
const culture = cells.culture[cell];
|
||||
const biome = cells.biome[cell];
|
||||
const height = cells.p[cell];
|
||||
const locality = height >= 70 ? "highlander" : [1, 2].includes(biome) ? "desert" : [3, 4].includes(biome) ? "mounted" : [5, 6, 7, 8, 9].includes(biome) ? "forest" : biome === 12 ? "swamp" : "angry";
|
||||
const locality =
|
||||
height >= 70
|
||||
? "highlander"
|
||||
: [1, 2].includes(biome)
|
||||
? "desert"
|
||||
: [3, 4].includes(biome)
|
||||
? "mounted"
|
||||
: [5, 6, 7, 8, 9].includes(biome)
|
||||
? "forest"
|
||||
: biome === 12
|
||||
? "swamp"
|
||||
: "angry";
|
||||
const name = `${Names.getCulture(culture)} ${ra(animals)}`;
|
||||
const legend = `A gang of ${locality} ${rw(types)}`;
|
||||
notes.push({id, name, legend});
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ function clicked() {
|
|||
else if (grand.id === "burgIcons") editBurg();
|
||||
else if (parent.id === "ice") editIce();
|
||||
else if (parent.id === "terrain") editReliefIcon();
|
||||
else if (grand.id === "markers") editMarker();
|
||||
else if (grand.id === "markers" || great.id === "markers") editMarker();
|
||||
else if (grand.id === "coastline") editCoastline();
|
||||
else if (great.id === "armies") editRegiment();
|
||||
else if (pack.cells.t[i] === 1) {
|
||||
|
|
@ -332,7 +332,15 @@ function drawLegend(name, data) {
|
|||
const width = bbox.width + colOffset * 2;
|
||||
const height = bbox.height + colOffset / 2 + vOffset;
|
||||
|
||||
legend.insert("rect", ":first-child").attr("id", "legendBox").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", backClr).attr("fill-opacity", opacity);
|
||||
legend
|
||||
.insert("rect", ":first-child")
|
||||
.attr("id", "legendBox")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.attr("fill", backClr)
|
||||
.attr("fill-opacity", opacity);
|
||||
|
||||
fitLegendBox();
|
||||
}
|
||||
|
|
@ -385,7 +393,15 @@ function createPicker() {
|
|||
const closePicker = () => contaiter.style("display", "none");
|
||||
|
||||
const contaiter = d3.select("body").append("svg").attr("id", "pickerContainer").attr("width", "100%").attr("height", "100%");
|
||||
contaiter.append("rect").attr("x", 0).attr("y", 0).attr("width", "100%").attr("height", "100%").attr("opacity", 0.2).on("mousemove", cl).on("click", closePicker);
|
||||
contaiter
|
||||
.append("rect")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", "100%")
|
||||
.attr("height", "100%")
|
||||
.attr("opacity", 0.2)
|
||||
.on("mousemove", cl)
|
||||
.on("click", closePicker);
|
||||
const picker = contaiter
|
||||
.append("g")
|
||||
.attr("id", "picker")
|
||||
|
|
@ -484,9 +500,25 @@ function createPicker() {
|
|||
const width = bbox.width + 8;
|
||||
const height = bbox.height + 9;
|
||||
|
||||
picker.insert("rect", ":first-child").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", "#ffffff").attr("stroke", "#5d4651").on("mousemove", pos);
|
||||
picker
|
||||
.insert("rect", ":first-child")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.attr("fill", "#ffffff")
|
||||
.attr("stroke", "#5d4651")
|
||||
.on("mousemove", pos);
|
||||
picker.insert("text", ":first-child").attr("x", 291).attr("y", -10).attr("id", "pickerCloseText").text("✕");
|
||||
picker.insert("rect", ":first-child").attr("x", 288).attr("y", -21).attr("id", "pickerCloseRect").attr("width", 14).attr("height", 14).on("mousemove", cl).on("click", closePicker);
|
||||
picker
|
||||
.insert("rect", ":first-child")
|
||||
.attr("x", 288)
|
||||
.attr("y", -21)
|
||||
.attr("id", "pickerCloseRect")
|
||||
.attr("width", 14)
|
||||
.attr("height", 14)
|
||||
.on("mousemove", cl)
|
||||
.on("click", closePicker);
|
||||
picker.insert("text", ":first-child").attr("x", 12).attr("y", -10).attr("id", "pickerLabel").text("Color Picker").on("mousemove", pos);
|
||||
picker.insert("rect", ":first-child").attr("x", 0).attr("y", -30).attr("width", width).attr("height", 30).attr("id", "pickerHeader").on("mousemove", pos);
|
||||
picker.attr("transform", `translate(${(svgWidth - width) / 2},${(svgHeight - height) / 2})`);
|
||||
|
|
@ -705,7 +737,14 @@ function highlightElement(element) {
|
|||
|
||||
const highlight = debug.append("rect").attr("x", box.x).attr("y", box.y).attr("width", box.width).attr("height", box.height).attr("transform", transform);
|
||||
|
||||
highlight.classed("highlighted", 1).transition(enter).style("outline-offset", "0px").transition(exit).style("outline-color", "transparent").delay(1000).remove();
|
||||
highlight
|
||||
.classed("highlighted", 1)
|
||||
.transition(enter)
|
||||
.style("outline-offset", "0px")
|
||||
.transition(exit)
|
||||
.style("outline-color", "transparent")
|
||||
.delay(1000)
|
||||
.remove();
|
||||
|
||||
const tr = parseTransform(transform);
|
||||
let x = box.x + box.width / 2;
|
||||
|
|
@ -922,6 +961,7 @@ function selectIcon(initial, callback) {
|
|||
}
|
||||
}
|
||||
|
||||
input.oninput = e => callback(input.value);
|
||||
table.onclick = e => {
|
||||
if (e.target.tagName === "TD") {
|
||||
input.value = e.target.innerHTML;
|
||||
|
|
@ -948,6 +988,31 @@ function selectIcon(initial, callback) {
|
|||
});
|
||||
}
|
||||
|
||||
function confirmationDialog(options) {
|
||||
const {
|
||||
title = "Confirm action",
|
||||
message = "Are you sure you want to continue? <br>The action cannot be reverted",
|
||||
cancel = "Cancel",
|
||||
confirm = "Continue",
|
||||
onCancel,
|
||||
onConfirm
|
||||
} = options;
|
||||
|
||||
const buttons = {
|
||||
[confirm]: function () {
|
||||
if (onConfirm) onConfirm();
|
||||
$(this).dialog("close");
|
||||
},
|
||||
[cancel]: function () {
|
||||
if (onCancel) onCancel();
|
||||
$(this).dialog("close");
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById("alertMessage").innerHTML = message;
|
||||
$("#alert").dialog({resizable: false, title, buttons});
|
||||
}
|
||||
|
||||
// add and register event listeners to clean up on editor closure
|
||||
function listen(element, event, handler) {
|
||||
element.addEventListener(event, handler);
|
||||
|
|
|
|||
|
|
@ -196,7 +196,8 @@ function drawHeightmap() {
|
|||
for (const i of d3.range(20, 101)) {
|
||||
if (paths[i].length < 10) continue;
|
||||
const color = getColor(i, scheme);
|
||||
if (terracing) terrs.append("path").attr("d", paths[i]).attr("transform", "translate(.7,1.4)").attr("fill", d3.color(color).darker(terracing)).attr("data-height", i);
|
||||
if (terracing)
|
||||
terrs.append("path").attr("d", paths[i]).attr("transform", "translate(.7,1.4)").attr("fill", d3.color(color).darker(terracing)).attr("data-height", i);
|
||||
terrs.append("path").attr("d", paths[i]).attr("fill", color).attr("data-height", i);
|
||||
}
|
||||
|
||||
|
|
@ -798,7 +799,10 @@ function drawReligions() {
|
|||
if (!vArray[r]) vArray[r] = [];
|
||||
vArray[r].push(points);
|
||||
body[r] += "M" + points.join("L");
|
||||
gap[r] += "M" + vertices.p[chain[0][0]] + chain.reduce((r2, v, i, d) => (!i ? r2 : !v[2] ? r2 + "L" + vertices.p[v[0]] : d[i + 1] && !d[i + 1][2] ? r2 + "M" + vertices.p[v[0]] : r2), "");
|
||||
gap[r] +=
|
||||
"M" +
|
||||
vertices.p[chain[0][0]] +
|
||||
chain.reduce((r2, v, i, d) => (!i ? r2 : !v[2] ? r2 + "L" + vertices.p[v[0]] : d[i + 1] && !d[i + 1][2] ? r2 + "M" + vertices.p[v[0]] : r2), "");
|
||||
}
|
||||
|
||||
const bodyData = body.map((p, i) => [p.length > 10 ? p : null, i, religions[i].color]).filter(d => d[0]);
|
||||
|
|
@ -966,7 +970,12 @@ function drawStates() {
|
|||
const gapString = gapData.map(d => `<path id="state-gap${d[1]}" d="${d[0]}" fill="none" stroke="${d[2]}"/>`).join("");
|
||||
const clipString = bodyData.map(d => `<clipPath id="state-clip${d[1]}"><use href="#state${d[1]}"/></clipPath>`).join("");
|
||||
const haloString = haloData
|
||||
.map(d => `<path id="state-border${d[1]}" d="${d[0]}" clip-path="url(#state-clip${d[1]})" stroke="${d3.color(d[2]) ? d3.color(d[2]).darker().hex() : "#666666"}"/>`)
|
||||
.map(
|
||||
d =>
|
||||
`<path id="state-border${d[1]}" d="${d[0]}" clip-path="url(#state-clip${d[1]})" stroke="${
|
||||
d3.color(d[2]) ? d3.color(d[2]).darker().hex() : "#666666"
|
||||
}"/>`
|
||||
)
|
||||
.join("");
|
||||
|
||||
statesBody.html(bodyString + gapString);
|
||||
|
|
@ -1219,7 +1228,10 @@ function getProvincesVertices() {
|
|||
if (!vArray[p]) vArray[p] = [];
|
||||
vArray[p].push(points);
|
||||
body[p] += "M" + points.join("L");
|
||||
gap[p] += "M" + vertices.p[chain[0][0]] + chain.reduce((r, v, i, d) => (!i ? r : !v[2] ? r + "L" + vertices.p[v[0]] : d[i + 1] && !d[i + 1][2] ? r + "M" + vertices.p[v[0]] : r), "");
|
||||
gap[p] +=
|
||||
"M" +
|
||||
vertices.p[chain[0][0]] +
|
||||
chain.reduce((r, v, i, d) => (!i ? r : !v[2] ? r + "L" + vertices.p[v[0]] : d[i + 1] && !d[i + 1][2] ? r + "M" + vertices.p[v[0]] : r), "");
|
||||
}
|
||||
|
||||
// find province visual center
|
||||
|
|
@ -1300,7 +1312,12 @@ function drawGrid() {
|
|||
const maxWidth = Math.max(+mapWidthInput.value, graphWidth);
|
||||
const maxHeight = Math.max(+mapHeightInput.value, graphHeight);
|
||||
|
||||
d3.select(pattern).attr("stroke", stroke).attr("stroke-width", width).attr("stroke-dasharray", dasharray).attr("stroke-linecap", linecap).attr("patternTransform", tr);
|
||||
d3.select(pattern)
|
||||
.attr("stroke", stroke)
|
||||
.attr("stroke-width", width)
|
||||
.attr("stroke-dasharray", dasharray)
|
||||
.attr("stroke-linecap", linecap)
|
||||
.attr("patternTransform", tr);
|
||||
gridOverlay
|
||||
.append("rect")
|
||||
.attr("width", maxWidth)
|
||||
|
|
@ -1510,23 +1527,23 @@ function toggleMarkers(event) {
|
|||
drawMarkers();
|
||||
if (event && isCtrlClick(event)) editStyle("markers");
|
||||
} else {
|
||||
if (event && isCtrlClick(event)) {
|
||||
editStyle("markers");
|
||||
return;
|
||||
}
|
||||
if (event && isCtrlClick(event)) return editStyle("markers");
|
||||
markers.selectAll("*").remove();
|
||||
turnButtonOff("toggleMarkers");
|
||||
}
|
||||
}
|
||||
|
||||
function drawMarkers() {
|
||||
const html = pack.markers.map(drawMarker);
|
||||
const rescale = +markers.attr("rescale");
|
||||
const html = pack.markers.map(marker => drawMarker(marker, rescale));
|
||||
markers.html(html.join(""));
|
||||
}
|
||||
|
||||
const getPin = (shape = "bubble", fill = "#fff", stroke = "#000") => {
|
||||
if (shape === "bubble") return `<path d="M6,19 l9,10 L24,19" fill="${stroke}" stroke="none" /><circle cx="15" cy="15" r="10" fill="${fill}" stroke="${stroke}"/>`;
|
||||
if (shape === "pin") return `<path d="m 15,3 c -5.5,0 -9.7,4.09 -9.7,9.3 0,6.8 9.7,17 9.7,17 0,0 9.7,-10.2 9.7,-17 C 24.7,7.09 20.5,3 15,3 Z" fill="${fill}" stroke="${stroke}"/>`;
|
||||
if (shape === "bubble")
|
||||
return `<path d="M6,19 l9,10 L24,19" fill="${stroke}" stroke="none" /><circle cx="15" cy="15" r="10" fill="${fill}" stroke="${stroke}"/>`;
|
||||
if (shape === "pin")
|
||||
return `<path d="m 15,3 c -5.5,0 -9.7,4.09 -9.7,9.3 0,6.8 9.7,17 9.7,17 0,0 9.7,-10.2 9.7,-17 C 24.7,7.09 20.5,3 15,3 Z" fill="${fill}" stroke="${stroke}"/>`;
|
||||
if (shape === "square") return `<path d="m 20,25 -5,4 -5,-4 z" fill="${stroke}"/><path d="M 5,5 H 25 V 25 H 5 Z" fill="${fill}" stroke="${stroke}"/>`;
|
||||
if (shape === "squarish") return `<path d="m 5,5 h 20 v 20 h -6 l -4,4 -4,-4 H 5 Z" fill="${fill}" stroke="${stroke}" />`;
|
||||
if (shape === "diamond") return `<path d="M 2,15 15,1 28,15 15,29 Z" fill="${fill}" stroke="${stroke}" />`;
|
||||
|
|
@ -1540,14 +1557,14 @@ const getPin = (shape = "bubble", fill = "#fff", stroke = "#000") => {
|
|||
if (shape === "no") return "";
|
||||
};
|
||||
|
||||
function drawMarker(marker) {
|
||||
function drawMarker(marker, rescale = 1) {
|
||||
const {i, icon, x, y, dx = 50, dy = 50, px = 12, size = 30} = marker;
|
||||
const id = `marker${i}`;
|
||||
const zoomSize = Math.max(rn(size / 5 + 24 / scale, 2), 1);
|
||||
const zoomSize = rescale ? Math.max(rn(size / 5 + 24 / scale, 2), 1) : 1;
|
||||
const viewX = rn(x - zoomSize / 2, 1);
|
||||
const viewY = rn(y - zoomSize, 1);
|
||||
|
||||
return `<svg id="${id}" viewbox="0 0 30 30" width="${zoomSize}" height="${zoomSize}" x="${viewX}" y="${viewY}">${getPin()}<text x="${dx}%" y="${dy}%" font-size="${px}px" >${icon}</text></svg>`;
|
||||
return `<svg id="${id}" viewbox="0 0 30 30" width="${zoomSize}" height="${zoomSize}" x="${viewX}" y="${viewY}"><g>${getPin()}</g><text x="${dx}%" y="${dy}%" font-size="${px}px" >${icon}</text></svg>`;
|
||||
}
|
||||
|
||||
function toggleLabels(event) {
|
||||
|
|
@ -1717,15 +1734,21 @@ function drawEmblems() {
|
|||
}
|
||||
|
||||
const burgNodes = nodes.filter(node => node.type === "burg");
|
||||
const burgString = burgNodes.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.shift)}" y="${rn(d.y - d.shift)}" width="${d.size}em" height="${d.size}em"/>`).join("");
|
||||
const burgString = burgNodes
|
||||
.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.shift)}" y="${rn(d.y - d.shift)}" width="${d.size}em" height="${d.size}em"/>`)
|
||||
.join("");
|
||||
emblems.select("#burgEmblems").attr("font-size", sizeBurgs).html(burgString);
|
||||
|
||||
const provinceNodes = nodes.filter(node => node.type === "province");
|
||||
const provinceString = provinceNodes.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.shift)}" y="${rn(d.y - d.shift)}" width="${d.size}em" height="${d.size}em"/>`).join("");
|
||||
const provinceString = provinceNodes
|
||||
.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.shift)}" y="${rn(d.y - d.shift)}" width="${d.size}em" height="${d.size}em"/>`)
|
||||
.join("");
|
||||
emblems.select("#provinceEmblems").attr("font-size", sizeProvinces).html(provinceString);
|
||||
|
||||
const stateNodes = nodes.filter(node => node.type === "state");
|
||||
const stateString = stateNodes.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.shift)}" y="${rn(d.y - d.shift)}" width="${d.size}em" height="${d.size}em"/>`).join("");
|
||||
const stateString = stateNodes
|
||||
.map(d => `<use data-i="${d.i}" x="${rn(d.x - d.shift)}" y="${rn(d.y - d.shift)}" width="${d.size}em" height="${d.size}em"/>`)
|
||||
.join("");
|
||||
emblems.select("#stateEmblems").attr("font-size", sizeStates).html(stateString);
|
||||
|
||||
invokeActiveZooming();
|
||||
|
|
|
|||
|
|
@ -3,23 +3,28 @@ function editMarker() {
|
|||
if (customization) return;
|
||||
closeDialogs(".stable");
|
||||
|
||||
const element = d3.event.target.parentElement;
|
||||
elSelected = d3.select(element).call(d3.drag().on("start", dragMarker)).classed("draggable", true);
|
||||
const marker = pack.markers.find(({i}) => Number(elSelected.attr("id").slice(6)) === i);
|
||||
const element = d3.event.target.closest("svg");
|
||||
const marker = pack.markers.find(({i}) => Number(element.id.slice(6)) === i);
|
||||
if (!marker) return;
|
||||
|
||||
elSelected = d3.select(element).raise().call(d3.drag().on("start", dragMarker)).classed("draggable", true);
|
||||
|
||||
// dom elements
|
||||
const markerSelectGroup = document.getElementById("markerSelectGroup");
|
||||
const markerType = document.getElementById("markerType");
|
||||
const markerIcon = document.getElementById("markerIcon");
|
||||
const markerIconSelect = document.getElementById("markerIconSelect");
|
||||
const markerIconSize = document.getElementById("markerIconSize");
|
||||
const markerIconShiftX = document.getElementById("markerIconShiftX");
|
||||
const markerIconShiftY = document.getElementById("markerIconShiftY");
|
||||
|
||||
const markerSize = document.getElementById("markerSize");
|
||||
const markerBaseStroke = document.getElementById("markerBaseStroke");
|
||||
const markerBaseFill = document.getElementById("markerBaseFill");
|
||||
const markerPin = document.getElementById("markerPin");
|
||||
const markerFill = document.getElementById("markerFill");
|
||||
const markerStroke = document.getElementById("markerStroke");
|
||||
|
||||
const markerToggleBubble = document.getElementById("markerToggleBubble");
|
||||
const markerIconSelect = document.getElementById("markerIconSelect");
|
||||
const markerNotes = document.getElementById("markerNotes");
|
||||
const addMarker = document.getElementById("addMarker");
|
||||
const markerAdd = document.getElementById("markerAdd");
|
||||
const markerRemove = document.getElementById("markerRemove");
|
||||
|
||||
updateInputs();
|
||||
|
||||
|
|
@ -31,22 +36,27 @@ function editMarker() {
|
|||
});
|
||||
|
||||
const listeners = [
|
||||
listen(markerSelectGroup, "change", changeGroup),
|
||||
listen(document.getElementById("markerIcon"), "click", toggleIconSection),
|
||||
listen(markerType, "change", changeMarkerType),
|
||||
listen(markerIcon, "input", changeMarkerIcon),
|
||||
listen(markerIconSelect, "click", selectMarkerIcon),
|
||||
listen(markerIconSize, "input", changeIconSize),
|
||||
listen(markerIconShiftX, "input", changeIconShiftX),
|
||||
listen(markerIconShiftY, "input", changeIconShiftY),
|
||||
listen(document.getElementById("markerIconSelect"), "click", selectMarkerIcon),
|
||||
listen(document.getElementById("markerStyle"), "click", toggleStyleSection),
|
||||
listen(markerSize, "input", changeMarkerSize),
|
||||
listen(markerBaseStroke, "input", changePinStroke),
|
||||
listen(markerBaseFill, "input", changePinFill),
|
||||
listen(markerToggleBubble, "click", togglePinVisibility),
|
||||
listen(document.getElementById("markerLegendButton"), "click", editMarkerLegend),
|
||||
listen(document.getElementById("markerAdd"), "click", toggleAddMarker),
|
||||
listen(document.getElementById("markerRemove"), "click", removeMarker)
|
||||
listen(markerPin, "change", changeMarkerPin),
|
||||
listen(markerFill, "input", changePinFill),
|
||||
listen(markerStroke, "input", changePinStroke),
|
||||
listen(markerNotes, "click", editMarkerLegend),
|
||||
listen(markerAdd, "click", toggleAddMarker),
|
||||
listen(markerRemove, "click", confirmMarkerDeletion)
|
||||
];
|
||||
|
||||
function getSameTypeMarkers() {
|
||||
const currentType = marker.type;
|
||||
if (!currentType) return [marker];
|
||||
return pack.markers.filter(({type}) => type === currentType);
|
||||
}
|
||||
|
||||
function dragMarker() {
|
||||
const dx = +this.getAttribute("x") - d3.event.x;
|
||||
const dy = +this.getAttribute("y") - d3.event.y;
|
||||
|
|
@ -70,173 +80,147 @@ function editMarker() {
|
|||
}
|
||||
|
||||
function updateInputs() {
|
||||
const {icon, type = "", size = 30, dx = 50, dy = 50, px = 12, stroke = "#000", fill = "#fff", pin = "bubble"} = marker;
|
||||
const {icon, type = "", size = 30, dx = 50, dy = 50, px = 12, stroke = "#000000", fill = "#ffffff", pin = "bubble"} = marker;
|
||||
|
||||
markerSelectGroup.value = type;
|
||||
markerType.value = type;
|
||||
markerIcon.value = icon;
|
||||
markerIconSize.value = px;
|
||||
markerIconShiftX.value = dx;
|
||||
markerIconShiftY.value = dy;
|
||||
|
||||
markerSize.value = size;
|
||||
markerBaseStroke.value = stroke;
|
||||
markerBaseFill.value = fill;
|
||||
|
||||
markerToggleBubble.className = pin;
|
||||
markerIconSelect.innerHTML = icon;
|
||||
markerPin.value = pin;
|
||||
markerFill.value = fill;
|
||||
markerStroke.value = stroke;
|
||||
}
|
||||
|
||||
function toggleGroupSection() {
|
||||
if (markerGroupSection.style.display === "inline-block") {
|
||||
markerEditor.querySelectorAll("button:not(#markerGroup)").forEach(b => (b.style.display = "inline-block"));
|
||||
markerGroupSection.style.display = "none";
|
||||
} else {
|
||||
markerEditor.querySelectorAll("button:not(#markerGroup)").forEach(b => (b.style.display = "none"));
|
||||
markerGroupSection.style.display = "inline-block";
|
||||
}
|
||||
function changeMarkerType() {
|
||||
marker.type = this.value;
|
||||
}
|
||||
|
||||
function changeGroup() {
|
||||
elSelected.attr("xlink:href", "#" + this.value);
|
||||
elSelected.attr("data-id", "#" + this.value);
|
||||
}
|
||||
|
||||
function toggleIconSection() {
|
||||
console.log(marker);
|
||||
if (markerIconSection.style.display === "inline-block") {
|
||||
markerEditor.querySelectorAll("button:not(#markerIcon)").forEach(b => (b.style.display = "inline-block"));
|
||||
markerIconSection.style.display = "none";
|
||||
markerIconSelect.style.display = "none";
|
||||
} else {
|
||||
markerEditor.querySelectorAll("button:not(#markerIcon)").forEach(b => (b.style.display = "none"));
|
||||
markerIconSection.style.display = "inline-block";
|
||||
markerIconSelect.style.display = "inline-block";
|
||||
}
|
||||
function changeMarkerIcon() {
|
||||
const icon = this.value;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.icon = icon;
|
||||
redrawIcon(marker);
|
||||
});
|
||||
}
|
||||
|
||||
function selectMarkerIcon() {
|
||||
selectIcon(this.innerHTML, v => {
|
||||
this.innerHTML = v;
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select("#defs-markers").select(id).select("text").text(v);
|
||||
selectIcon(marker.icon, icon => {
|
||||
markerIcon.value = icon;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.icon = icon;
|
||||
redrawIcon(marker);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function changeIconSize() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select("#defs-markers")
|
||||
.select(id)
|
||||
.select("text")
|
||||
.attr("font-size", this.value + "px");
|
||||
const px = +this.value;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.px = px;
|
||||
redrawIcon(marker);
|
||||
});
|
||||
}
|
||||
|
||||
function changeIconShiftX() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select("#defs-markers")
|
||||
.select(id)
|
||||
.select("text")
|
||||
.attr("x", this.value + "%");
|
||||
const dx = +this.value;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.dx = dx;
|
||||
redrawIcon(marker);
|
||||
});
|
||||
}
|
||||
|
||||
function changeIconShiftY() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select("#defs-markers")
|
||||
.select(id)
|
||||
.select("text")
|
||||
.attr("y", this.value + "%");
|
||||
}
|
||||
|
||||
function toggleStyleSection() {
|
||||
if (markerStyleSection.style.display === "inline-block") {
|
||||
markerEditor.querySelectorAll("button:not(#markerStyle)").forEach(b => (b.style.display = "inline-block"));
|
||||
markerStyleSection.style.display = "none";
|
||||
} else {
|
||||
markerEditor.querySelectorAll("button:not(#markerStyle)").forEach(b => (b.style.display = "none"));
|
||||
markerStyleSection.style.display = "inline-block";
|
||||
}
|
||||
const dy = +this.value;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.dy = dy;
|
||||
redrawIcon(marker);
|
||||
});
|
||||
}
|
||||
|
||||
function changeMarkerSize() {
|
||||
const id = elSelected.attr("data-id");
|
||||
document.querySelectorAll("use[data-id='" + id + "']").forEach(e => {
|
||||
const x = +e.dataset.x,
|
||||
y = +e.dataset.y;
|
||||
const desired = (e.dataset.size = +markerSize.value);
|
||||
const size = Math.max(desired * 5 + 25 / scale, 1);
|
||||
const size = +this.value;
|
||||
const rescale = +markers.attr("rescale");
|
||||
|
||||
e.setAttribute("x", x - size / 2);
|
||||
e.setAttribute("y", y - size / 2);
|
||||
e.setAttribute("width", size);
|
||||
e.setAttribute("height", size);
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.size = size;
|
||||
const {i, x, y, hidden} = marker;
|
||||
const el = !hidden && document.getElementById(`marker${i}`);
|
||||
if (!el) return;
|
||||
|
||||
const zoomedSize = rescale ? Math.max(rn(size / 5 + 24 / scale, 2), 1) : size;
|
||||
el.setAttribute("width", zoomedSize);
|
||||
el.setAttribute("height", zoomedSize);
|
||||
el.setAttribute("x", rn(x - zoomedSize / 2, 1));
|
||||
el.setAttribute("y", rn(y - zoomedSize, 1));
|
||||
});
|
||||
invokeActiveZooming();
|
||||
}
|
||||
|
||||
function changePinStroke() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select(id).select("path").attr("fill", this.value);
|
||||
d3.select(id).select("circle").attr("stroke", this.value);
|
||||
function changeMarkerPin() {
|
||||
const pin = this.value;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.pin = pin;
|
||||
redrawPin(marker);
|
||||
});
|
||||
}
|
||||
|
||||
function changePinFill() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select(id).select("circle").attr("fill", this.value);
|
||||
const fill = this.value;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.fill = fill;
|
||||
redrawPin(marker);
|
||||
});
|
||||
}
|
||||
|
||||
function changeIconStrokeWidth() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select("#defs-markers").select(id).select("text").attr("stroke-width", this.value);
|
||||
function changePinStroke() {
|
||||
const stroke = this.value;
|
||||
getSameTypeMarkers().forEach(marker => {
|
||||
marker.stroke = stroke;
|
||||
redrawPin(marker);
|
||||
});
|
||||
}
|
||||
|
||||
function changeIconStroke() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select("#defs-markers").select(id).select("text").attr("stroke", this.value);
|
||||
function redrawIcon({i, hidden, icon, dx = 50, dy = 50, px = 12}) {
|
||||
const iconElement = !hidden && document.querySelector(`#marker${i} > text`);
|
||||
if (iconElement) {
|
||||
iconElement.innerHTML = icon;
|
||||
iconElement.setAttribute("x", dx + "%");
|
||||
iconElement.setAttribute("y", dy + "%");
|
||||
iconElement.setAttribute("font-size", px + "px");
|
||||
}
|
||||
}
|
||||
|
||||
function changeIconFill() {
|
||||
const id = elSelected.attr("data-id");
|
||||
d3.select("#defs-markers").select(id).select("text").attr("fill", this.value);
|
||||
}
|
||||
|
||||
function togglePinVisibility() {
|
||||
const id = elSelected.attr("data-id");
|
||||
let show = 1;
|
||||
if (this.className === "icon-info-circled") {
|
||||
this.className = "icon-info";
|
||||
show = 0;
|
||||
} else this.className = "icon-info-circled";
|
||||
d3.select(id).select("circle").attr("opacity", show);
|
||||
d3.select(id).select("path").attr("opacity", show);
|
||||
function redrawPin({i, hidden, pin = "bubble", fill = "#fff", stroke = "#000"}) {
|
||||
const pinGroup = !hidden && document.querySelector(`#marker${i} > g`);
|
||||
if (pinGroup) pinGroup.innerHTML = getPin(pin, fill, stroke);
|
||||
}
|
||||
|
||||
function editMarkerLegend() {
|
||||
const id = elSelected.attr("id");
|
||||
const id = element.id;
|
||||
editNotes(id, id);
|
||||
}
|
||||
|
||||
function toggleAddMarker() {
|
||||
document.getElementById("addMarker").click();
|
||||
addMarker.click();
|
||||
}
|
||||
|
||||
function removeMarker() {
|
||||
alertMessage.innerHTML = "Are you sure you want to remove the marker?";
|
||||
$("#alert").dialog({
|
||||
resizable: false,
|
||||
function confirmMarkerDeletion() {
|
||||
confirmationDialog({
|
||||
title: "Remove marker",
|
||||
buttons: {
|
||||
Remove: function () {
|
||||
$(this).dialog("close");
|
||||
const index = notes.findIndex(n => n.id === elSelected.attr("id"));
|
||||
if (index != -1) notes.splice(index, 1);
|
||||
elSelected.remove();
|
||||
$("#markerEditor").dialog("close");
|
||||
},
|
||||
Cancel: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
message: "Are you sure you want to remove this marker? The action cannot be reverted",
|
||||
confirm: "Remove",
|
||||
onConfirm: deleteMarker
|
||||
});
|
||||
}
|
||||
|
||||
function deleteMarker() {
|
||||
notes = notes.filter(note => note.id !== element.id);
|
||||
pack.markers = pack.markers.filter(m => m.i !== marker.i);
|
||||
element.remove();
|
||||
$("#markerEditor").dialog("close");
|
||||
}
|
||||
|
||||
function closeMarkerEditor() {
|
||||
listeners.forEach(removeListener => removeListener());
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ toolsContent.addEventListener("click", function (event) {
|
|||
},
|
||||
open: function () {
|
||||
const pane = $(this).dialog("widget").find(".ui-dialog-buttonpane");
|
||||
$('<span><input id="dontAsk" class="checkbox" type="checkbox"><label for="dontAsk" class="checkbox-label dontAsk"><i>do not ask again</i></label><span>').prependTo(pane);
|
||||
$(
|
||||
'<span><input id="dontAsk" class="checkbox" type="checkbox"><label for="dontAsk" class="checkbox-label dontAsk"><i>do not ask again</i></label><span>'
|
||||
).prependTo(pane);
|
||||
},
|
||||
close: function () {
|
||||
const box = $(this).dialog("widget").find(".checkbox")[0];
|
||||
|
|
@ -262,7 +264,8 @@ function regenerateBurgs() {
|
|||
|
||||
const score = new Int16Array(cells.s.map(s => s * Math.random())); // cell score for capitals placement
|
||||
const sorted = cells.i.filter(i => score[i] > 0 && cells.culture[i]).sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes
|
||||
const burgsCount = manorsInput.value == 1000 ? rn(sorted.length / 5 / (grid.points.length / 10000) ** 0.8) + states.length : +manorsInput.value + states.length;
|
||||
const burgsCount =
|
||||
manorsInput.value == 1000 ? rn(sorted.length / 5 / (grid.points.length / 10000) ** 0.8) + states.length : +manorsInput.value + states.length;
|
||||
const spacing = (graphWidth + graphHeight) / 150 / (burgsCount ** 0.7 / 66); // base min distance between towns
|
||||
|
||||
//clear locked list since ids will change
|
||||
|
|
@ -414,6 +417,7 @@ function regenerateIce() {
|
|||
}
|
||||
|
||||
function regenerateMarkers(event) {
|
||||
// TODO: rework for new markers system
|
||||
if (isCtrlClick(event)) prompt("Please provide markers number multiplier", {default: 1, step: 0.01, min: 0, max: 100}, v => addNumberOfMarkers(v));
|
||||
else addNumberOfMarkers(gauss(1, 0.5, 0.3, 5, 2));
|
||||
|
||||
|
|
@ -475,7 +479,18 @@ function addLabelOnClick() {
|
|||
const id = getNextId("label");
|
||||
|
||||
let group = labels.select("#addedLabels");
|
||||
if (!group.size()) group = labels.append("g").attr("id", "addedLabels").attr("fill", "#3e3e4b").attr("opacity", 1).attr("stroke", "#3a3a3a").attr("stroke-width", 0).attr("font-family", "Almendra SC").attr("font-size", 18).attr("data-size", 18).attr("filter", null);
|
||||
if (!group.size())
|
||||
group = labels
|
||||
.append("g")
|
||||
.attr("id", "addedLabels")
|
||||
.attr("fill", "#3e3e4b")
|
||||
.attr("opacity", 1)
|
||||
.attr("stroke", "#3a3a3a")
|
||||
.attr("stroke-width", 0)
|
||||
.attr("font-family", "Almendra SC")
|
||||
.attr("font-size", 18)
|
||||
.attr("data-size", 18)
|
||||
.attr("filter", null);
|
||||
|
||||
const example = group.append("text").attr("x", 0).attr("x", 0).text(name);
|
||||
const width = example.node().getBBox().width;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue