diff --git a/vue/public/refactor-four.js b/vue/public/refactor-four.js index 84e9215f..856ab383 100644 --- a/vue/public/refactor-four.js +++ b/vue/public/refactor-four.js @@ -1,3 +1,29 @@ +function restoreDefaultOptions() { + // remove ALL saved data from LocalStorage + localStorage.clear(); + // set defaut values + mapWidthInput.value = window.innerWidth; + mapHeightInput.value = window.innerHeight; + changeMapSize(); + graphSize = sizeInput.value = sizeOutput.value = 1; + $("#options i[class^='icon-lock']").each(function() { + this.setAttribute("data-locked", 0); + this.className = "icon-lock-open"; + if (this.id === "lockNeutralInput" || this.id === "lockSwampinessInput") { + this.setAttribute("data-locked", 1); + this.className = "icon-lock"; + } + }); + neutralInput.value = neutralOutput.value = 200; + swampinessInput.value = swampinessOutput.value = 10; + outlineLayersInput.value = "-6,-3,-1"; + transparencyInput.value = transparencyOutput.value = 0; + changeDialogsTransparency(0); + pngResolutionInput.value = 5; + pngResolutionOutput.value = "5x"; + randomizeOptions(); +} + // Heighmap Template: Volcano function templateVolcano(mod) { addMountain(); diff --git a/vue/public/refactor-one.js b/vue/public/refactor-one.js index b07d96f4..4c74b2e8 100644 --- a/vue/public/refactor-one.js +++ b/vue/public/refactor-one.js @@ -2089,3 +2089,155 @@ function templateVolcano(mod) { // convert length to distance routeLength.innerHTML = rn(l * distanceScale.value) + " " + distanceUnit.value; } + + function addRoutePoint(point) { + const controlPoints = debug.select(".controlPoints").size() + ? debug.select(".controlPoints") + : debug.append("g").attr("class", "controlPoints"); + controlPoints.append("circle") + .attr("cx", point.x).attr("cy", point.y).attr("r", 0.35) + .call(d3.drag().on("drag", routePointDrag)) + .on("click", function(d) { + if ($("#routeSplit").hasClass('pressed')) { + routeSplitInPoint(this); + } else { + $(this).remove(); + routeRedraw(); + } + }); + } + + function routePointDrag() { + d3.select(this).attr("cx", d3.event.x).attr("cy", d3.event.y); + routeRedraw(); + } + + function routeRedraw() { + let points = []; + debug.select(".controlPoints").selectAll("circle").each(function() { + const el = d3.select(this); + points.push({scX: +el.attr("cx"), scY: +el.attr("cy")}); + }); + lineGen.curve(d3.curveCatmullRom.alpha(0.1)); + elSelected.attr("d", lineGen(points)); + // get route distance + const l = elSelected.node().getTotalLength(); + routeLength.innerHTML = rn(l * distanceScale.value) + " " + distanceUnit.value; + } + + function addNewRoute() { + let routeType = elSelected && elSelected.node() ? elSelected.node().parentNode.id : "searoutes"; + const group = routes.select("#"+routeType); + const id = routeType + "" + group.selectAll("*").size(); + elSelected = group.append("path").attr("data-route", "new").attr("id", id).on("click", editRoute); + routeUpdateGroups(); + $("#routeEditor").dialog({ + title: "Edit Route", minHeight: 30, width: "auto", resizable: false, + close: function() { + if ($("#addRoute").hasClass('pressed')) completeNewRoute(); + if ($("#routeSplit").hasClass('pressed')) $("#routeSplit").removeClass('pressed'); + unselect(); + } + }); + } + + function newRouteAddPoint() { + const point = d3.mouse(this); + const x = rn(point[0],2), y = rn(point[1],2); + addRoutePoint({x, y}); + routeRedraw(); + } + + function completeNewRoute() { + $("#routeNew, #addRoute").removeClass('pressed'); + restoreDefaultEvents(); + if (!elSelected.size()) return; + if (elSelected.attr("data-route") === "new") { + routeRedraw(); + elSelected.attr("data-route", ""); + const node = elSelected.node(); + const l = node.getTotalLength(); + let pathCells = []; + for (let i = 0; i <= l; i ++) { + const p = node.getPointAtLength(i); + const cell = diagram.find(p.x, p.y); + if (!cell) {return;} + pathCells.push(cell.index); + } + const uniqueCells = [...new Set(pathCells)]; + uniqueCells.map(function(c) { + if (cells[c].path !== undefined) {cells[c].path += 1;} + else {cells[c].path = 1;} + }); + } + tip("", true); + } + + function routeUpdateGroups() { + routeGroup.innerHTML = ""; + routes.selectAll("g").each(function() { + const opt = document.createElement("option"); + opt.value = opt.innerHTML = this.id; + routeGroup.add(opt); + }); + } + + function routeSplitInPoint(clicked) { + const group = d3.select(elSelected.node().parentNode); + $("#routeSplit").removeClass('pressed'); + const points1 = [],points2 = []; + let points = points1; + debug.select(".controlPoints").selectAll("circle").each(function() { + const el = d3.select(this); + points.push({scX: +el.attr("cx"), scY: +el.attr("cy")}); + if (this === clicked) { + points = points2; + points.push({scX: +el.attr("cx"), scY: +el.attr("cy")}); + } + el.remove(); + }); + lineGen.curve(d3.curveCatmullRom.alpha(0.1)); + elSelected.attr("d", lineGen(points1)); + const id = routeGroup.value + "" + group.selectAll("*").size(); + group.append("path").attr("id", id).attr("d", lineGen(points2)).on("click", editRoute); + routeDrawPoints(); + } + + $("#routeGroup").change(function() { + $(elSelected.node()).detach().appendTo($("#"+this.value)); + }); + + // open legendsEditor + document.getElementById("routeLegend").addEventListener("click", function() { + let id = elSelected.attr("id"); + editLegends(id, id); + }); + + $("#routeNew").click(function() { + if ($(this).hasClass('pressed')) { + completeNewRoute(); + } else { + // enter creation mode + $(".pressed").removeClass('pressed'); + $("#routeNew, #addRoute").addClass('pressed'); + debug.select(".controlPoints").selectAll("*").remove(); + addNewRoute(); + viewbox.style("cursor", "crosshair").on("click", newRouteAddPoint); + tip("Click on map to add route point", true); + } + }); + + $("#routeRemove").click(function() { + alertMessage.innerHTML = `Are you sure you want to remove the route?`; + $("#alert").dialog({resizable: false, title: "Remove route", + buttons: { + Remove: function() { + $(this).dialog("close"); + elSelected.remove(); + $("#routeEditor").dialog("close"); + }, + Cancel: function() {$(this).dialog("close");} + } + }) + }); + } diff --git a/vue/public/refactor-three.js b/vue/public/refactor-three.js index c28a1a0c..43af2dd0 100644 --- a/vue/public/refactor-three.js +++ b/vue/public/refactor-three.js @@ -1,319 +1,456 @@ +function editBurg() { + if (customization) return; + unselect(); + closeDialogs("#burgEditor, .stable"); + elSelected = d3.select(this); + const id = +elSelected.attr("data-id"); + if (id === undefined) return; + d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("start", elementDrag)).classed("draggable", true); - function drawIconsList() { - let icons = [ - // emoticons in FF: - ["2693", "โš“", "Anchor"], - ["26EA", "โ›ช", "Church"], - ["1F3EF", "๐Ÿฏ", "Japanese Castle"], - ["1F3F0", "๐Ÿฐ", "Castle"], - ["1F5FC", "๐Ÿ—ผ", "Tower"], - ["1F3E0", "๐Ÿ ", "House"], - ["1F3AA", "๐ŸŽช", "Tent"], - ["1F3E8", "๐Ÿจ", "Hotel"], - ["1F4B0", "๐Ÿ’ฐ", "Money bag"], - ["1F4A8", "๐Ÿ’จ", "Dashing away"], - ["1F334", "๐ŸŒด", "Palm"], - ["1F335", "๐ŸŒต", "Cactus"], - ["1F33E", "๐ŸŒพ", "Sheaf"], - ["1F5FB", "๐Ÿ—ป", "Mountain"], - ["1F30B", "๐ŸŒ‹", "Volcano"], - ["1F40E", "๐ŸŽ", "Horse"], - ["1F434", "๐Ÿด", "Horse Face"], - ["1F42E", "๐Ÿฎ", "Cow"], - ["1F43A", "๐Ÿบ", "Wolf Face"], - ["1F435", "๐Ÿต", "Monkey face"], - ["1F437", "๐Ÿท", "Pig face"], - ["1F414", "๐Ÿ”", "Chiken"], - ["1F411", "๐Ÿ‘", "Eve"], - ["1F42B", "๐Ÿซ", "Camel"], - ["1F418", "๐Ÿ˜", "Elephant"], - ["1F422", "๐Ÿข", "Turtle"], - ["1F40C", "๐ŸŒ", "Snail"], - ["1F40D", "๐Ÿ", "Snake"], - ["1F433", "๐Ÿณ", "Whale"], - ["1F42C", "๐Ÿฌ", "Dolphin"], - ["1F420", "๐ŸŸ", "Fish"], - ["1F432", "๐Ÿฒ", "Dragon Head"], - ["1F479", "๐Ÿ‘น", "Ogre"], - ["1F47B", "๐Ÿ‘ป", "Ghost"], - ["1F47E", "๐Ÿ‘พ", "Alien"], - ["1F480", "๐Ÿ’€", "Skull"], - ["1F374", "๐Ÿด", "Fork and knife"], - ["1F372", "๐Ÿฒ", "Food"], - ["1F35E", "๐Ÿž", "Bread"], - ["1F357", "๐Ÿ—", "Poultry leg"], - ["1F347", "๐Ÿ‡", "Grapes"], - ["1F34F", "๐Ÿ", "Apple"], - ["1F352", "๐Ÿ’", "Cherries"], - ["1F36F", "๐Ÿฏ", "Honey pot"], - ["1F37A", "๐Ÿบ", "Beer"], - ["1F377", "๐Ÿท", "Wine glass"], - ["1F3BB", "๐ŸŽป", "Violin"], - ["1F3B8", "๐ŸŽธ", "Guitar"], - ["26A1", "โšก", "Electricity"], - ["1F320", "๐ŸŒ ", "Shooting star"], - ["1F319", "๐ŸŒ™", "Crescent moon"], - ["1F525", "๐Ÿ”ฅ", "Fire"], - ["1F4A7", "๐Ÿ’ง", "Droplet"], - ["1F30A", "๐ŸŒŠ", "Wave"], - ["231B", "โŒ›", "Hourglass"], - ["1F3C6", "๐Ÿ†", "Goblet"], - ["26F2", "โ›ฒ", "Fountain"], - ["26F5", "โ›ต", "Sailboat"], - ["26FA", "โ›บ", "Tend"], - ["1F489", "๐Ÿ’‰", "Syringe"], - ["1F4D6", "๐Ÿ“š", "Books"], - ["1F3AF", "๐ŸŽฏ", "Archery"], - ["1F52E", "๐Ÿ”ฎ", "Magic ball"], - ["1F3AD", "๐ŸŽญ", "Performing arts"], - ["1F3A8", "๐ŸŽจ", "Artist palette"], - ["1F457", "๐Ÿ‘—", "Dress"], - ["1F451", "๐Ÿ‘‘", "Crown"], - ["1F48D", "๐Ÿ’", "Ring"], - ["1F48E", "๐Ÿ’Ž", "Gem"], - ["1F514", "๐Ÿ””", "Bell"], - ["1F3B2", "๐ŸŽฒ", "Die"], - // black and white icons in FF: - ["26A0", "โš ", "Alert"], - ["2317", "โŒ—", "Hash"], - ["2318", "โŒ˜", "POI"], - ["2307", "โŒ‡", "Wavy"], - ["21E6", "โ‡ฆ", "Left arrow"], - ["21E7", "โ‡ง", "Top arrow"], - ["21E8", "โ‡จ", "Right arrow"], - ["21E9", "โ‡ฉ", "Left arrow"], - ["21F6", "โ‡ถ", "Three arrows"], - ["2699", "โš™", "Gear"], - ["269B", "โš›", "Atom"], - ["0024", "$", "Dollar"], - ["2680", "โš€", "Die1"], - ["2681", "โš", "Die2"], - ["2682", "โš‚", "Die3"], - ["2683", "โšƒ", "Die4"], - ["2684", "โš„", "Die5"], - ["2685", "โš…", "Die6"], - ["26B4", "โšด", "Pallas"], - ["26B5", "โšต", "Juno"], - ["26B6", "โšถ", "Vesta"], - ["26B7", "โšท", "Chiron"], - ["26B8", "โšธ", "Lilith"], - ["263F", "โ˜ฟ", "Mercury"], - ["2640", "โ™€", "Venus"], - ["2641", "โ™", "Earth"], - ["2642", "โ™‚", "Mars"], - ["2643", "โ™ƒ", "Jupiter"], - ["2644", "โ™„", "Saturn"], - ["2645", "โ™…", "Uranus"], - ["2646", "โ™†", "Neptune"], - ["2647", "โ™‡", "Pluto"], - ["26B3", "โšณ", "Ceres"], - ["2654", "โ™”", "Chess king"], - ["2655", "โ™•", "Chess queen"], - ["2656", "โ™–", "Chess rook"], - ["2657", "โ™—", "Chess bishop"], - ["2658", "โ™˜", "Chess knight"], - ["2659", "โ™™", "Chess pawn"], - ["2660", "โ™ ", "Spade"], - ["2663", "โ™ฃ", "Club"], - ["2665", "โ™ฅ", "Heart"], - ["2666", "โ™ฆ", "Diamond"], - ["2698", "โš˜", "Flower"], - ["2625", "โ˜ฅ", "Ankh"], - ["2626", "โ˜ฆ", "Orthodox"], - ["2627", "โ˜ง", "Chi Rho"], - ["2628", "โ˜จ", "Lorraine"], - ["2629", "โ˜ฉ", "Jerusalem"], - ["2670", "โ™ฐ", "Syriacย cross"], - ["2020", "โ€ ", "Dagger"], - ["262A", "โ˜ช", "Muslim"], - ["262D", "โ˜ญ", "Soviet"], - ["262E", "โ˜ฎ", "Peace"], - ["262F", "โ˜ฏ", "Yin yang"], - ["26A4", "โšค", "Heterosexuality"], - ["26A2", "โšข", "Female homosexuality"], - ["26A3", "โšฃ", "Male homosexuality"], - ["26A5", "โšฅ", "Male and female"], - ["26AD", "โšญ", "Rings"], - ["2690", "โš", "White flag"], - ["2691", "โš‘", "Black flag"], - ["263C", "โ˜ผ", "Sun"], - ["263E", "โ˜พ", "Moon"], - ["2668", "โ™จ", "Hot springs"], - ["2600", "โ˜€", "Black sun"], - ["2601", "โ˜", "Cloud"], - ["2602", "โ˜‚", "Umbrella"], - ["2603", "โ˜ƒ", "Snowman"], - ["2604", "โ˜„", "Comet"], - ["2605", "โ˜…", "Black star"], - ["2606", "โ˜†", "White star"], - ["269D", "โš", "Outlined star"], - ["2618", "โ˜˜", "Shamrock"], - ["21AF", "โ†ฏ", "Lightning"], - ["269C", "โšœ", "FleurDeLis"], - ["2622", "โ˜ข", "Radiation"], - ["2623", "โ˜ฃ", "Biohazard"], - ["2620", "โ˜ ", "Skull"], - ["2638", "โ˜ธ", "Dharma"], - ["2624", "โ˜ค", "Caduceus"], - ["2695", "โš•", "Aeculapius staff"], - ["269A", "โšš", "Hermes staff"], - ["2697", "โš—", "Alembic"], - ["266B", "โ™ซ", "Music"], - ["2702", "โœ‚", "Scissors"], - ["2696", "โš–", "Scales"], - ["2692", "โš’", "Hammer and pick"], - ["2694", "โš”", "Swords"] - ]; + // update Burg details + const type = elSelected.node().parentNode.id; + const labelGroup = burgLabels.select("#"+type); + const iconGroup = burgIcons.select("#"+type); + burgNameInput.value = manors[id].name; + updateBurgsGroupOptions(); + burgSelectGroup.value = labelGroup.attr("id"); + burgSelectDefaultFont.value = fonts.indexOf(labelGroup.attr("data-font")); + burgSetLabelSize.value = labelGroup.attr("data-size"); + burgLabelColorInput.value = toHEX(labelGroup.attr("fill")); + burgLabelOpacity.value = labelGroup.attr("opacity") === undefined ? 1 : +labelGroup.attr("opacity"); + const tr = parseTransform(elSelected.attr("transform")); + burgLabelAngle.value = tr[2]; + burgLabelAngleOutput.innerHTML = Math.abs(+tr[2]) + "ยฐ"; + burgIconSize.value = iconGroup.attr("size"); + burgIconFillOpacity.value = iconGroup.attr("fill-opacity") === undefined ? 1 : +iconGroup.attr("fill-opacity"); + burgIconFillColor.value = iconGroup.attr("fill"); + burgIconStrokeWidth.value = iconGroup.attr("stroke-width"); + burgIconStrokeOpacity.value = iconGroup.attr("stroke-opacity") === undefined ? 1 : +iconGroup.attr("stroke-opacity"); + burgIconStrokeColor.value = iconGroup.attr("stroke"); + const cell = cells[manors[id].cell]; + if (cell.region !== "neutral" && cell.region !== undefined) { + burgToggleCapital.disabled = false; + const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 1 : 0 : 0; + d3.select("#burgToggleCapital").classed("pressed", capital); + } else { + burgToggleCapital.disabled = true; + d3.select("#burgToggleCapital").classed("pressed", false); + } + d3.select("#burgTogglePort").classed("pressed", cell.port !== undefined); + burgPopulation.value = manors[id].population; + burgPopulationFriendly.value = rn(manors[id].population * urbanization.value * populationRate.value * 1000); - let table = document.getElementById("markerIconTable"), row = ""; - table.addEventListener("click", clickMarkerIconTable, false); - table.addEventListener("mouseover", hoverMarkerIconTable, false); - - for (let i=0; i < icons.length; i++) { - if (i%20 === 0) row = table.insertRow(0); - let cell = row.insertCell(0); - let icon = String.fromCodePoint(parseInt(icons[i][0],16)); - cell.innerHTML = icon; - cell.id = "markerIcon" + icon.codePointAt(); - cell.setAttribute("data-desc", icons[i][2]); - } + $("#burgEditor").dialog({ + title: "Edit Burg: " + manors[id].name, + minHeight: 30, width: "auto", resizable: false, + position: {my: "center top+40", at: "top", of: d3.event}, + close: function() { + d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("drag", null)).classed("draggable", false); + elSelected = null; } + }); - function clickMarkerIconTable(e) { - if (e.target !== e.currentTarget) { - let table = document.getElementById("markerIconTable"); - let selected = table.getElementsByClassName("selected"); - if (selected.length) selected[0].removeAttribute("class"); - e.target.className = "selected"; - let id = elSelected.attr("href"); - let icon = e.target.innerHTML; - d3.select("#defs-markers").select(id).select("text").text(icon); - } - e.stopPropagation(); - } + if (modules.editBurg) return; + modules.editBurg = true; - function hoverMarkerIconTable(e) { - if (e.target !== e.currentTarget) { - let desc = e.target.getAttribute("data-desc"); - tip(e.target.innerHTML + " " + desc); - } - e.stopPropagation(); - } + loadDefaultFonts(); - // change marker icon size - document.getElementById("markerIconSize").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select("#defs-markers").select(id).select("text").attr("font-size", this.value + "px"); - }); - - // change marker icon x shift - document.getElementById("markerIconShiftX").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select("#defs-markers").select(id).select("text").attr("x", this.value + "%"); - }); - - // change marker icon y shift - document.getElementById("markerIconShiftY").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select("#defs-markers").select(id).select("text").attr("y", this.value + "%"); - }); - - // apply custom unicode icon on input - document.getElementById("markerIconCustom").addEventListener("input", function() { - if (!this.value) return; - let id = elSelected.attr("href"); - d3.select("#defs-markers").select(id).select("text").text(this.value); - }); - - $("#markerStyleButton").click(function() { - $("#markerEditor > button").not(this).toggle(); - $("#markerStyleButtons").toggle(); - }); - - // change marker size - document.getElementById("markerSize").addEventListener("input", function() { - let id = elSelected.attr("data-id"); - let used = document.querySelectorAll("use[data-id='"+id+"']"); - let size = this.value; - used.forEach(function(e) {e.setAttribute("data-size", size);}); - invokeActiveZooming(); - }); - - // change marker base color - document.getElementById("markerBase").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select(id).select("path").attr("fill", this.value); - d3.select(id).select("circle").attr("stroke", this.value); - }); - - // change marker fill color - document.getElementById("markerFill").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select(id).select("circle").attr("fill", this.value); - }); - - // change marker icon y shift - document.getElementById("markerIconFill").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select("#defs-markers").select(id).select("text").attr("fill", this.value); - }); - - // change marker icon y shift - document.getElementById("markerIconStrokeWidth").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select("#defs-markers").select(id).select("text").attr("stroke-width", this.value); - }); - - // change marker icon y shift - document.getElementById("markerIconStroke").addEventListener("input", function() { - let id = elSelected.attr("href"); - d3.select("#defs-markers").select(id).select("text").attr("stroke", this.value); - }); - - // toggle marker bubble display - document.getElementById("markerToggleBubble").addEventListener("click", function() { - let id = elSelected.attr("href"); - 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); - }); - - // open legendsEditor - document.getElementById("markerLegendButton").addEventListener("click", function() { - let id = elSelected.attr("id"); - let symbol = elSelected.attr("href"); - let icon = d3.select("#defs-markers").select(symbol).select("text").text(); - let name = "Marker " + icon; - editLegends(id, name); - }); - - // click on master button to add new markers on click - document.getElementById("markerAdd").addEventListener("click", function() { - document.getElementById("addMarker").click(); - }); - - // remove marker on click - document.getElementById("markerRemove").addEventListener("click", function() { - alertMessage.innerHTML = "Are you sure you want to remove the marker?"; - $("#alert").dialog({resizable: false, title: "Remove marker", - buttons: { - Remove: function() { - $(this).dialog("close"); - elSelected.remove(); - $("#markerEditor").dialog("close"); - }, - Cancel: function() {$(this).dialog("close");} - } - }); + function updateBurgsGroupOptions() { + burgSelectGroup.innerHTML = ""; + burgIcons.selectAll("g").each(function(d) { + const opt = document.createElement("option"); + opt.value = opt.innerHTML = d3.select(this).attr("id"); + burgSelectGroup.add(opt); }); } + $("#burgEditor > button").not("#burgAddfromEditor").not("#burgRelocate").not("#burgRemove").click(function() { + if ($(this).next().is(":visible")) { + $("#burgEditor > button").show(); + $(this).next("div").hide(); + } else { + $("#burgEditor > *").not(this).hide(); + $(this).next("div").show(); + } + }); + + $("#burgEditor > div > button").click(function() { + if ($(this).next().is(":visible")) { + $("#burgEditor > div > button").show(); + $(this).parent().prev().show(); + $(this).next("div").hide(); + } else { + $("#burgEditor > div > button").not(this).hide(); + $(this).parent().prev().hide(); + $(this).next("div").show(); + } + }); + + $("#burgSelectGroup").change(function() { + const id = +elSelected.attr("data-id"); + const g = this.value; + moveBurgToGroup(id, g); + }); + + $("#burgInputGroup").change(function() { + let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, ""); + if (Number.isFinite(+newGroup.charAt(0))) newGroup = "g" + newGroup; + if (burgLabels.select("#"+newGroup).size()) { + tip('The group "'+ newGroup + '" is already exists'); + return; + } + burgInputGroup.value = ""; + // clone old group assigning new id + const id = elSelected.node().parentNode.id; + const l = burgLabels.select("#"+id).node().cloneNode(false); + l.id = newGroup; + const i = burgIcons.select("#"+id).node().cloneNode(false); + i.id = newGroup; + burgLabels.node().insertBefore(l, null); + burgIcons.node().insertBefore(i, null); + // select new group + const opt = document.createElement("option"); + opt.value = opt.innerHTML = newGroup; + burgSelectGroup.add(opt); + $("#burgSelectGroup").val(newGroup).change(); + $("#burgSelectGroup, #burgInputGroup").toggle(); + updateLabelGroups(); + }); + + $("#burgAddGroup").click(function() { + if ($("#burgInputGroup").css("display") === "none") { + $("#burgInputGroup").css("display", "inline-block"); + $("#burgSelectGroup").css("display", "none"); + burgInputGroup.focus(); + } else { + $("#burgSelectGroup").css("display", "inline-block"); + $("#burgInputGroup").css("display", "none"); + } + }); + + $("#burgRemoveGroup").click(function() { + const group = d3.select(elSelected.node().parentNode); + const type = group.attr("id"); + const id = +elSelected.attr("data-id"); + const count = group.selectAll("*").size(); + const message = "Are you sure you want to remove all Burgs (" + count + ") of that group?"; + alertMessage.innerHTML = message; + $("#alert").dialog({resizable: false, title: "Remove Burgs", + buttons: { + Remove: function() { + $(this).dialog("close"); + group.selectAll("*").each(function(d) { + const id = +d3.select(this).attr("data-id"); + if (id === undefined) return; + const cell = manors[id].cell; + const state = manors[id].region; + if (states[state]) { + if (states[state].capital === id) states[state].capital = "select"; + states[state].burgs --; + } + manors[id].region = "removed"; + cells[cell].manor = undefined; + }); + burgLabels.select("#"+type).selectAll("*").remove(); + burgIcons.select("#"+type).selectAll("*").remove(); + $("#icons g[id*='anchors'] [data-id=" + id + "]").parent().children().remove(); + closeDialogs(".stable"); + updateCountryEditors(); + $("#burgEditor").dialog("close"); + }, + Cancel: function() {$(this).dialog("close");} + } + }); + + }); + + $("#burgNameInput").on("input", function() { + if (this.value === "") { + tip("Name should not be blank, set opacity to 0 to hide label or remove button to delete"); + return; + } + const id = +elSelected.attr("data-id"); + burgLabels.selectAll("[data-id='" + id + "']").text(this.value); + manors[id].name = this.value; + $("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + this.value); + }); + + $("#burgNameReCulture, #burgNameReRandom").click(function() { + const id = +elSelected.attr("data-id"); + const culture = this.id === "burgNameReCulture" ? manors[id].culture : Math.floor(Math.random() * cultures.length); + const name = generateName(culture); + burgLabels.selectAll("[data-id='" + id + "']").text(name); + manors[id].name = name; + burgNameInput.value = name; + $("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + name); + }); + + $("#burgToggleExternalFont").click(function() { + if ($("#burgInputExternalFont").css("display") === "none") { + $("#burgInputExternalFont").css("display", "inline-block"); + $("#burgSelectDefaultFont").css("display", "none"); + burgInputExternalFont.focus(); + } else { + $("#burgSelectDefaultFont").css("display", "inline-block"); + $("#burgInputExternalFont").css("display", "none"); + } + }); + + $("#burgSelectDefaultFont").change(function() { + const type = elSelected.node().parentNode.id; + const group = burgLabels.select("#"+type); + if (burgSelectDefaultFont.value === "") return; + const font = fonts[burgSelectDefaultFont.value].split(':')[0].replace(/\+/g, " "); + group.attr("font-family", font).attr("data-font", fonts[burgSelectDefaultFont.value]); + }); + + $("#burgInputExternalFont").change(function() { + fetchFonts(this.value).then(fetched => { + if (!fetched) return; + burgToggleExternalFont.click(); + burgInputExternalFont.value = ""; + if (fetched === 1) $("#burgSelectDefaultFont").val(fonts.length - 1).change(); + }); + }); + + $("#burgSetLabelSize").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgLabels.select("#"+type); + group.attr("data-size", +this.value); + invokeActiveZooming(); + }); + + $("#burgLabelColorInput").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgLabels.select("#"+type); + group.attr("fill", this.value); + }); + + $("#burgLabelOpacity").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgLabels.select("#"+type); + group.attr("opacity", +this.value); + }); + + $("#burgLabelAngle").on("input", function() { + const id = +elSelected.attr("data-id"); + const el = burgLabels.select("[data-id='"+ id +"']"); + const tr = parseTransform(el.attr("transform")); + const c = el.node().getBBox(); + burgLabelAngleOutput.innerHTML = Math.abs(+this.value) + "ยฐ"; + const angle = +this.value; + const transform = `translate(${tr[0]},${tr[1]}) rotate(${angle} ${(c.x+c.width/2)} ${(c.y+c.height/2)})`; + el.attr("transform", transform); + }); + + $("#burgIconSize").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgIcons.select("#"+type); + const size = +this.value; + group.attr("size", size); + group.selectAll("*").each(function() {d3.select(this).attr("r", size)}); + }); + + $("#burgIconFillOpacity").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgIcons.select("#"+type); + group.attr("fill-opacity", +this.value); + }); + + $("#burgIconFillColor").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgIcons.select("#"+type); + group.attr("fill", this.value); + }); + + $("#burgIconStrokeWidth").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgIcons.select("#"+type); + group.attr("stroke-width", +this.value); + }); + + $("#burgIconStrokeOpacity").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgIcons.select("#"+type); + group.attr("stroke-opacity", +this.value); + }); + + $("#burgIconStrokeColor").on("input", function() { + const type = elSelected.node().parentNode.id; + const group = burgIcons.select("#"+type); + group.attr("stroke", this.value); + }); + + $("#burgToggleCapital").click(function() { + const id = +elSelected.attr("data-id"); + const state = manors[id].region; + if (states[state] === undefined) return; + const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 0 : 1 : 1; + if (capital && states[state].capital !== "select") { + // move oldCapital to a town group + const oldCapital = states[state].capital; + moveBurgToGroup(oldCapital, "towns"); + } + states[state].capital = capital ? id : "select"; + d3.select("#burgToggleCapital").classed("pressed", capital); + const g = capital ? "capitals" : "towns"; + moveBurgToGroup(id, g); + }); + + $("#burgTogglePort").click(function() { + const id = +elSelected.attr("data-id"); + const cell = cells[manors[id].cell]; + const markAsPort = cell.port === undefined ? true : undefined; + cell.port = markAsPort; + d3.select("#burgTogglePort").classed("pressed", markAsPort); + if (markAsPort) { + const type = elSelected.node().parentNode.id; + const ag = type === "capitals" ? "#capital-anchors" : "#town-anchors"; + const group = icons.select(ag); + const size = +group.attr("size"); + const x = rn(manors[id].x - size * 0.47, 2); + const y = rn(manors[id].y - size * 0.47, 2); + group.append("use").attr("xlink:href", "#icon-anchor").attr("data-id", id) + .attr("x", x).attr("y", y).attr("width", size).attr("height", size) + .on("click", editIcon); + } else { + $("#icons g[id*='anchors'] [data-id=" + id + "]").remove(); + } + }); + + $("#burgPopulation").on("input", function() { + const id = +elSelected.attr("data-id"); + burgPopulationFriendly.value = rn(this.value * urbanization.value * populationRate.value * 1000); + manors[id].population = +this.value; + }); + + $("#burgRelocate").click(function() { + if ($(this).hasClass('pressed')) { + $(".pressed").removeClass('pressed'); + restoreDefaultEvents(); + tip("", true); + } else { + $(".pressed").removeClass('pressed'); + const id = elSelected.attr("data-id"); + $(this).addClass('pressed').attr("data-id", id); + viewbox.style("cursor", "crosshair").on("click", relocateBurgOnClick); + tip("Click on map to relocate burg. Hold Shift for continuous move", true); + } + }); + + // open legendsEditor + document.getElementById("burglLegend").addEventListener("click", function() { + let burg = +elSelected.attr("data-id"); + let id = "burg" + burg; + let name = manors[burg].name; + editLegends(id, name); + }); + + // move burg to a different cell + function relocateBurgOnClick() { + const point = d3.mouse(this); + const index = getIndex(point); + const i = +$("#burgRelocate").attr("data-id"); + if (isNaN(i) || !manors[i]) return; + + if (cells[index].height < 20) { + tip("Cannot place burg in the water! Select a land cell", null, "error"); + return; + } + + if (cells[index].manor !== undefined && cells[index].manor !== i) { + tip("There is already a burg in this cell. Please select a free cell", null, "error"); + $('#grid').fadeIn(); + d3.select("#toggleGrid").classed("buttonoff", false); + return; + } + + let region = cells[index].region; + const oldRegion = manors[i].region; + // relocating capital to other country you "conquer" target cell + if (states[oldRegion] && states[oldRegion].capital === i) { + if (region !== oldRegion) { + tip("Capital cannot be moved to another country!", null, "error"); + return; + } + } + + if (d3.event.shiftKey === false) { + $("#burgRelocate").removeClass("pressed"); + restoreDefaultEvents(); + tip("", true); + if (region !== oldRegion) { + recalculateStateData(oldRegion); + recalculateStateData(region); + updateCountryEditors(); + } + } + + const x = rn(point[0],2), y = rn(point[1],2); + burgIcons.select("circle[data-id='"+i+"']").attr("transform", null).attr("cx", x).attr("cy", y); + burgLabels.select("text[data-id='"+i+"']").attr("transform", null).attr("x", x).attr("y", y); + const anchor = icons.select("use[data-id='"+i+"']"); + if (anchor.size()) { + const size = anchor.attr("width"); + const xa = rn(x - size * 0.47, 2); + const ya = rn(y - size * 0.47, 2); + anchor.attr("transform", null).attr("x", xa).attr("y", ya); + } + cells[index].manor = i; + cells[manors[i].cell].manor = undefined; + manors[i].x = x, manors[i].y = y, manors[i].region = region, manors[i].cell = index; + } + + // open in MFCG + $("#burgSeeInMFCG").click(function() { + const id = +elSelected.attr("data-id"); + const name = manors[id].name; + const cell = manors[id].cell; + const pop = rn(manors[id].population); + const size = pop > 65 ? 65 : pop < 6 ? 6 : pop; + const s = seed + "" + id; + const hub = cells[cell].crossroad > 2 ? 1 : 0; + const river = cells[cell].river ? 1 : 0; + const coast = cells[cell].port !== undefined ? 1 : 0; + const sec = pop > 40 ? 1 : Math.random() < pop / 100 ? 1 : 0; + const thr = sec && Math.random() < 0.8 ? 1 : 0; + const url = "http://fantasycities.watabou.ru/"; + let params = `?name=${name}&size=${size}&seed=${s}&hub=${hub}&random=0&continuous=0`; + params += `&river=${river}&coast=${coast}&citadel=${id&1}&plaza=${sec}&temple=${thr}&walls=${sec}&shantytown=${sec}`; + const win = window.open(url+params, '_blank'); + win.focus(); + }); + + $("#burgAddfromEditor").click(function() { + clickToAdd(); // to load on click event function + $("#addBurg").click(); + }); + + $("#burgRemove").click(function() { + alertMessage.innerHTML = `Are you sure you want to remove the Burg?`; + $("#alert").dialog({resizable: false, title: "Remove Burg", + buttons: { + Remove: function() { + $(this).dialog("close"); + const id = +elSelected.attr("data-id"); + d3.selectAll("[data-id='" + id + "']").remove(); + const cell = manors[id].cell; + const state = manors[id].region; + if (states[state]) { + if (states[state].capital === id) states[state].capital = "select"; + states[state].burgs --; + } + manors[id].region = "removed"; + cells[cell].manor = undefined; + closeDialogs(".stable"); + updateCountryEditors(); + }, + Cancel: function() {$(this).dialog("close");} + } + }) + }); +} + // clear elSelected variable function unselect() { tip("", true); diff --git a/vue/public/refactor-two.js b/vue/public/refactor-two.js index 6a33ddb9..a3ff8c1d 100644 --- a/vue/public/refactor-two.js +++ b/vue/public/refactor-two.js @@ -1,154 +1,3 @@ - function addRoutePoint(point) { - const controlPoints = debug.select(".controlPoints").size() - ? debug.select(".controlPoints") - : debug.append("g").attr("class", "controlPoints"); - controlPoints.append("circle") - .attr("cx", point.x).attr("cy", point.y).attr("r", 0.35) - .call(d3.drag().on("drag", routePointDrag)) - .on("click", function(d) { - if ($("#routeSplit").hasClass('pressed')) { - routeSplitInPoint(this); - } else { - $(this).remove(); - routeRedraw(); - } - }); - } - - function routePointDrag() { - d3.select(this).attr("cx", d3.event.x).attr("cy", d3.event.y); - routeRedraw(); - } - - function routeRedraw() { - let points = []; - debug.select(".controlPoints").selectAll("circle").each(function() { - const el = d3.select(this); - points.push({scX: +el.attr("cx"), scY: +el.attr("cy")}); - }); - lineGen.curve(d3.curveCatmullRom.alpha(0.1)); - elSelected.attr("d", lineGen(points)); - // get route distance - const l = elSelected.node().getTotalLength(); - routeLength.innerHTML = rn(l * distanceScale.value) + " " + distanceUnit.value; - } - - function addNewRoute() { - let routeType = elSelected && elSelected.node() ? elSelected.node().parentNode.id : "searoutes"; - const group = routes.select("#"+routeType); - const id = routeType + "" + group.selectAll("*").size(); - elSelected = group.append("path").attr("data-route", "new").attr("id", id).on("click", editRoute); - routeUpdateGroups(); - $("#routeEditor").dialog({ - title: "Edit Route", minHeight: 30, width: "auto", resizable: false, - close: function() { - if ($("#addRoute").hasClass('pressed')) completeNewRoute(); - if ($("#routeSplit").hasClass('pressed')) $("#routeSplit").removeClass('pressed'); - unselect(); - } - }); - } - - function newRouteAddPoint() { - const point = d3.mouse(this); - const x = rn(point[0],2), y = rn(point[1],2); - addRoutePoint({x, y}); - routeRedraw(); - } - - function completeNewRoute() { - $("#routeNew, #addRoute").removeClass('pressed'); - restoreDefaultEvents(); - if (!elSelected.size()) return; - if (elSelected.attr("data-route") === "new") { - routeRedraw(); - elSelected.attr("data-route", ""); - const node = elSelected.node(); - const l = node.getTotalLength(); - let pathCells = []; - for (let i = 0; i <= l; i ++) { - const p = node.getPointAtLength(i); - const cell = diagram.find(p.x, p.y); - if (!cell) {return;} - pathCells.push(cell.index); - } - const uniqueCells = [...new Set(pathCells)]; - uniqueCells.map(function(c) { - if (cells[c].path !== undefined) {cells[c].path += 1;} - else {cells[c].path = 1;} - }); - } - tip("", true); - } - - function routeUpdateGroups() { - routeGroup.innerHTML = ""; - routes.selectAll("g").each(function() { - const opt = document.createElement("option"); - opt.value = opt.innerHTML = this.id; - routeGroup.add(opt); - }); - } - - function routeSplitInPoint(clicked) { - const group = d3.select(elSelected.node().parentNode); - $("#routeSplit").removeClass('pressed'); - const points1 = [],points2 = []; - let points = points1; - debug.select(".controlPoints").selectAll("circle").each(function() { - const el = d3.select(this); - points.push({scX: +el.attr("cx"), scY: +el.attr("cy")}); - if (this === clicked) { - points = points2; - points.push({scX: +el.attr("cx"), scY: +el.attr("cy")}); - } - el.remove(); - }); - lineGen.curve(d3.curveCatmullRom.alpha(0.1)); - elSelected.attr("d", lineGen(points1)); - const id = routeGroup.value + "" + group.selectAll("*").size(); - group.append("path").attr("id", id).attr("d", lineGen(points2)).on("click", editRoute); - routeDrawPoints(); - } - - $("#routeGroup").change(function() { - $(elSelected.node()).detach().appendTo($("#"+this.value)); - }); - - // open legendsEditor - document.getElementById("routeLegend").addEventListener("click", function() { - let id = elSelected.attr("id"); - editLegends(id, id); - }); - - $("#routeNew").click(function() { - if ($(this).hasClass('pressed')) { - completeNewRoute(); - } else { - // enter creation mode - $(".pressed").removeClass('pressed'); - $("#routeNew, #addRoute").addClass('pressed'); - debug.select(".controlPoints").selectAll("*").remove(); - addNewRoute(); - viewbox.style("cursor", "crosshair").on("click", newRouteAddPoint); - tip("Click on map to add route point", true); - } - }); - - $("#routeRemove").click(function() { - alertMessage.innerHTML = `Are you sure you want to remove the route?`; - $("#alert").dialog({resizable: false, title: "Remove route", - buttons: { - Remove: function() { - $(this).dialog("close"); - elSelected.remove(); - $("#routeEditor").dialog("close"); - }, - Cancel: function() {$(this).dialog("close");} - } - }) - }); - } function editIcon() { if (customization) return; @@ -414,584 +263,3 @@ }) }); } - - function editBurg() { - if (customization) return; - unselect(); - closeDialogs("#burgEditor, .stable"); - elSelected = d3.select(this); - const id = +elSelected.attr("data-id"); - if (id === undefined) return; - d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("start", elementDrag)).classed("draggable", true); - - // update Burg details - const type = elSelected.node().parentNode.id; - const labelGroup = burgLabels.select("#"+type); - const iconGroup = burgIcons.select("#"+type); - burgNameInput.value = manors[id].name; - updateBurgsGroupOptions(); - burgSelectGroup.value = labelGroup.attr("id"); - burgSelectDefaultFont.value = fonts.indexOf(labelGroup.attr("data-font")); - burgSetLabelSize.value = labelGroup.attr("data-size"); - burgLabelColorInput.value = toHEX(labelGroup.attr("fill")); - burgLabelOpacity.value = labelGroup.attr("opacity") === undefined ? 1 : +labelGroup.attr("opacity"); - const tr = parseTransform(elSelected.attr("transform")); - burgLabelAngle.value = tr[2]; - burgLabelAngleOutput.innerHTML = Math.abs(+tr[2]) + "ยฐ"; - burgIconSize.value = iconGroup.attr("size"); - burgIconFillOpacity.value = iconGroup.attr("fill-opacity") === undefined ? 1 : +iconGroup.attr("fill-opacity"); - burgIconFillColor.value = iconGroup.attr("fill"); - burgIconStrokeWidth.value = iconGroup.attr("stroke-width"); - burgIconStrokeOpacity.value = iconGroup.attr("stroke-opacity") === undefined ? 1 : +iconGroup.attr("stroke-opacity"); - burgIconStrokeColor.value = iconGroup.attr("stroke"); - const cell = cells[manors[id].cell]; - if (cell.region !== "neutral" && cell.region !== undefined) { - burgToggleCapital.disabled = false; - const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 1 : 0 : 0; - d3.select("#burgToggleCapital").classed("pressed", capital); - } else { - burgToggleCapital.disabled = true; - d3.select("#burgToggleCapital").classed("pressed", false); - } - d3.select("#burgTogglePort").classed("pressed", cell.port !== undefined); - burgPopulation.value = manors[id].population; - burgPopulationFriendly.value = rn(manors[id].population * urbanization.value * populationRate.value * 1000); - - $("#burgEditor").dialog({ - title: "Edit Burg: " + manors[id].name, - minHeight: 30, width: "auto", resizable: false, - position: {my: "center top+40", at: "top", of: d3.event}, - close: function() { - d3.selectAll("[data-id='" + id + "']").call(d3.drag().on("drag", null)).classed("draggable", false); - elSelected = null; - } - }); - - if (modules.editBurg) return; - modules.editBurg = true; - - loadDefaultFonts(); - - function updateBurgsGroupOptions() { - burgSelectGroup.innerHTML = ""; - burgIcons.selectAll("g").each(function(d) { - const opt = document.createElement("option"); - opt.value = opt.innerHTML = d3.select(this).attr("id"); - burgSelectGroup.add(opt); - }); - } - - $("#burgEditor > button").not("#burgAddfromEditor").not("#burgRelocate").not("#burgRemove").click(function() { - if ($(this).next().is(":visible")) { - $("#burgEditor > button").show(); - $(this).next("div").hide(); - } else { - $("#burgEditor > *").not(this).hide(); - $(this).next("div").show(); - } - }); - - $("#burgEditor > div > button").click(function() { - if ($(this).next().is(":visible")) { - $("#burgEditor > div > button").show(); - $(this).parent().prev().show(); - $(this).next("div").hide(); - } else { - $("#burgEditor > div > button").not(this).hide(); - $(this).parent().prev().hide(); - $(this).next("div").show(); - } - }); - - $("#burgSelectGroup").change(function() { - const id = +elSelected.attr("data-id"); - const g = this.value; - moveBurgToGroup(id, g); - }); - - $("#burgInputGroup").change(function() { - let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, ""); - if (Number.isFinite(+newGroup.charAt(0))) newGroup = "g" + newGroup; - if (burgLabels.select("#"+newGroup).size()) { - tip('The group "'+ newGroup + '" is already exists'); - return; - } - burgInputGroup.value = ""; - // clone old group assigning new id - const id = elSelected.node().parentNode.id; - const l = burgLabels.select("#"+id).node().cloneNode(false); - l.id = newGroup; - const i = burgIcons.select("#"+id).node().cloneNode(false); - i.id = newGroup; - burgLabels.node().insertBefore(l, null); - burgIcons.node().insertBefore(i, null); - // select new group - const opt = document.createElement("option"); - opt.value = opt.innerHTML = newGroup; - burgSelectGroup.add(opt); - $("#burgSelectGroup").val(newGroup).change(); - $("#burgSelectGroup, #burgInputGroup").toggle(); - updateLabelGroups(); - }); - - $("#burgAddGroup").click(function() { - if ($("#burgInputGroup").css("display") === "none") { - $("#burgInputGroup").css("display", "inline-block"); - $("#burgSelectGroup").css("display", "none"); - burgInputGroup.focus(); - } else { - $("#burgSelectGroup").css("display", "inline-block"); - $("#burgInputGroup").css("display", "none"); - } - }); - - $("#burgRemoveGroup").click(function() { - const group = d3.select(elSelected.node().parentNode); - const type = group.attr("id"); - const id = +elSelected.attr("data-id"); - const count = group.selectAll("*").size(); - const message = "Are you sure you want to remove all Burgs (" + count + ") of that group?"; - alertMessage.innerHTML = message; - $("#alert").dialog({resizable: false, title: "Remove Burgs", - buttons: { - Remove: function() { - $(this).dialog("close"); - group.selectAll("*").each(function(d) { - const id = +d3.select(this).attr("data-id"); - if (id === undefined) return; - const cell = manors[id].cell; - const state = manors[id].region; - if (states[state]) { - if (states[state].capital === id) states[state].capital = "select"; - states[state].burgs --; - } - manors[id].region = "removed"; - cells[cell].manor = undefined; - }); - burgLabels.select("#"+type).selectAll("*").remove(); - burgIcons.select("#"+type).selectAll("*").remove(); - $("#icons g[id*='anchors'] [data-id=" + id + "]").parent().children().remove(); - closeDialogs(".stable"); - updateCountryEditors(); - $("#burgEditor").dialog("close"); - }, - Cancel: function() {$(this).dialog("close");} - } - }); - - }); - - $("#burgNameInput").on("input", function() { - if (this.value === "") { - tip("Name should not be blank, set opacity to 0 to hide label or remove button to delete"); - return; - } - const id = +elSelected.attr("data-id"); - burgLabels.selectAll("[data-id='" + id + "']").text(this.value); - manors[id].name = this.value; - $("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + this.value); - }); - - $("#burgNameReCulture, #burgNameReRandom").click(function() { - const id = +elSelected.attr("data-id"); - const culture = this.id === "burgNameReCulture" ? manors[id].culture : Math.floor(Math.random() * cultures.length); - const name = generateName(culture); - burgLabels.selectAll("[data-id='" + id + "']").text(name); - manors[id].name = name; - burgNameInput.value = name; - $("div[aria-describedby='burgEditor'] .ui-dialog-title").text("Edit Burg: " + name); - }); - - $("#burgToggleExternalFont").click(function() { - if ($("#burgInputExternalFont").css("display") === "none") { - $("#burgInputExternalFont").css("display", "inline-block"); - $("#burgSelectDefaultFont").css("display", "none"); - burgInputExternalFont.focus(); - } else { - $("#burgSelectDefaultFont").css("display", "inline-block"); - $("#burgInputExternalFont").css("display", "none"); - } - }); - - $("#burgSelectDefaultFont").change(function() { - const type = elSelected.node().parentNode.id; - const group = burgLabels.select("#"+type); - if (burgSelectDefaultFont.value === "") return; - const font = fonts[burgSelectDefaultFont.value].split(':')[0].replace(/\+/g, " "); - group.attr("font-family", font).attr("data-font", fonts[burgSelectDefaultFont.value]); - }); - - $("#burgInputExternalFont").change(function() { - fetchFonts(this.value).then(fetched => { - if (!fetched) return; - burgToggleExternalFont.click(); - burgInputExternalFont.value = ""; - if (fetched === 1) $("#burgSelectDefaultFont").val(fonts.length - 1).change(); - }); - }); - - $("#burgSetLabelSize").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgLabels.select("#"+type); - group.attr("data-size", +this.value); - invokeActiveZooming(); - }); - - $("#burgLabelColorInput").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgLabels.select("#"+type); - group.attr("fill", this.value); - }); - - $("#burgLabelOpacity").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgLabels.select("#"+type); - group.attr("opacity", +this.value); - }); - - $("#burgLabelAngle").on("input", function() { - const id = +elSelected.attr("data-id"); - const el = burgLabels.select("[data-id='"+ id +"']"); - const tr = parseTransform(el.attr("transform")); - const c = el.node().getBBox(); - burgLabelAngleOutput.innerHTML = Math.abs(+this.value) + "ยฐ"; - const angle = +this.value; - const transform = `translate(${tr[0]},${tr[1]}) rotate(${angle} ${(c.x+c.width/2)} ${(c.y+c.height/2)})`; - el.attr("transform", transform); - }); - - $("#burgIconSize").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgIcons.select("#"+type); - const size = +this.value; - group.attr("size", size); - group.selectAll("*").each(function() {d3.select(this).attr("r", size)}); - }); - - $("#burgIconFillOpacity").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgIcons.select("#"+type); - group.attr("fill-opacity", +this.value); - }); - - $("#burgIconFillColor").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgIcons.select("#"+type); - group.attr("fill", this.value); - }); - - $("#burgIconStrokeWidth").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgIcons.select("#"+type); - group.attr("stroke-width", +this.value); - }); - - $("#burgIconStrokeOpacity").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgIcons.select("#"+type); - group.attr("stroke-opacity", +this.value); - }); - - $("#burgIconStrokeColor").on("input", function() { - const type = elSelected.node().parentNode.id; - const group = burgIcons.select("#"+type); - group.attr("stroke", this.value); - }); - - $("#burgToggleCapital").click(function() { - const id = +elSelected.attr("data-id"); - const state = manors[id].region; - if (states[state] === undefined) return; - const capital = states[manors[id].region] ? id === states[manors[id].region].capital ? 0 : 1 : 1; - if (capital && states[state].capital !== "select") { - // move oldCapital to a town group - const oldCapital = states[state].capital; - moveBurgToGroup(oldCapital, "towns"); - } - states[state].capital = capital ? id : "select"; - d3.select("#burgToggleCapital").classed("pressed", capital); - const g = capital ? "capitals" : "towns"; - moveBurgToGroup(id, g); - }); - - $("#burgTogglePort").click(function() { - const id = +elSelected.attr("data-id"); - const cell = cells[manors[id].cell]; - const markAsPort = cell.port === undefined ? true : undefined; - cell.port = markAsPort; - d3.select("#burgTogglePort").classed("pressed", markAsPort); - if (markAsPort) { - const type = elSelected.node().parentNode.id; - const ag = type === "capitals" ? "#capital-anchors" : "#town-anchors"; - const group = icons.select(ag); - const size = +group.attr("size"); - const x = rn(manors[id].x - size * 0.47, 2); - const y = rn(manors[id].y - size * 0.47, 2); - group.append("use").attr("xlink:href", "#icon-anchor").attr("data-id", id) - .attr("x", x).attr("y", y).attr("width", size).attr("height", size) - .on("click", editIcon); - } else { - $("#icons g[id*='anchors'] [data-id=" + id + "]").remove(); - } - }); - - $("#burgPopulation").on("input", function() { - const id = +elSelected.attr("data-id"); - burgPopulationFriendly.value = rn(this.value * urbanization.value * populationRate.value * 1000); - manors[id].population = +this.value; - }); - - $("#burgRelocate").click(function() { - if ($(this).hasClass('pressed')) { - $(".pressed").removeClass('pressed'); - restoreDefaultEvents(); - tip("", true); - } else { - $(".pressed").removeClass('pressed'); - const id = elSelected.attr("data-id"); - $(this).addClass('pressed').attr("data-id", id); - viewbox.style("cursor", "crosshair").on("click", relocateBurgOnClick); - tip("Click on map to relocate burg. Hold Shift for continuous move", true); - } - }); - - // open legendsEditor - document.getElementById("burglLegend").addEventListener("click", function() { - let burg = +elSelected.attr("data-id"); - let id = "burg" + burg; - let name = manors[burg].name; - editLegends(id, name); - }); - - // move burg to a different cell - function relocateBurgOnClick() { - const point = d3.mouse(this); - const index = getIndex(point); - const i = +$("#burgRelocate").attr("data-id"); - if (isNaN(i) || !manors[i]) return; - - if (cells[index].height < 20) { - tip("Cannot place burg in the water! Select a land cell", null, "error"); - return; - } - - if (cells[index].manor !== undefined && cells[index].manor !== i) { - tip("There is already a burg in this cell. Please select a free cell", null, "error"); - $('#grid').fadeIn(); - d3.select("#toggleGrid").classed("buttonoff", false); - return; - } - - let region = cells[index].region; - const oldRegion = manors[i].region; - // relocating capital to other country you "conquer" target cell - if (states[oldRegion] && states[oldRegion].capital === i) { - if (region !== oldRegion) { - tip("Capital cannot be moved to another country!", null, "error"); - return; - } - } - - if (d3.event.shiftKey === false) { - $("#burgRelocate").removeClass("pressed"); - restoreDefaultEvents(); - tip("", true); - if (region !== oldRegion) { - recalculateStateData(oldRegion); - recalculateStateData(region); - updateCountryEditors(); - } - } - - const x = rn(point[0],2), y = rn(point[1],2); - burgIcons.select("circle[data-id='"+i+"']").attr("transform", null).attr("cx", x).attr("cy", y); - burgLabels.select("text[data-id='"+i+"']").attr("transform", null).attr("x", x).attr("y", y); - const anchor = icons.select("use[data-id='"+i+"']"); - if (anchor.size()) { - const size = anchor.attr("width"); - const xa = rn(x - size * 0.47, 2); - const ya = rn(y - size * 0.47, 2); - anchor.attr("transform", null).attr("x", xa).attr("y", ya); - } - cells[index].manor = i; - cells[manors[i].cell].manor = undefined; - manors[i].x = x, manors[i].y = y, manors[i].region = region, manors[i].cell = index; - } - - // open in MFCG - $("#burgSeeInMFCG").click(function() { - const id = +elSelected.attr("data-id"); - const name = manors[id].name; - const cell = manors[id].cell; - const pop = rn(manors[id].population); - const size = pop > 65 ? 65 : pop < 6 ? 6 : pop; - const s = seed + "" + id; - const hub = cells[cell].crossroad > 2 ? 1 : 0; - const river = cells[cell].river ? 1 : 0; - const coast = cells[cell].port !== undefined ? 1 : 0; - const sec = pop > 40 ? 1 : Math.random() < pop / 100 ? 1 : 0; - const thr = sec && Math.random() < 0.8 ? 1 : 0; - const url = "http://fantasycities.watabou.ru/"; - let params = `?name=${name}&size=${size}&seed=${s}&hub=${hub}&random=0&continuous=0`; - params += `&river=${river}&coast=${coast}&citadel=${id&1}&plaza=${sec}&temple=${thr}&walls=${sec}&shantytown=${sec}`; - const win = window.open(url+params, '_blank'); - win.focus(); - }); - - $("#burgAddfromEditor").click(function() { - clickToAdd(); // to load on click event function - $("#addBurg").click(); - }); - - $("#burgRemove").click(function() { - alertMessage.innerHTML = `Are you sure you want to remove the Burg?`; - $("#alert").dialog({resizable: false, title: "Remove Burg", - buttons: { - Remove: function() { - $(this).dialog("close"); - const id = +elSelected.attr("data-id"); - d3.selectAll("[data-id='" + id + "']").remove(); - const cell = manors[id].cell; - const state = manors[id].region; - if (states[state]) { - if (states[state].capital === id) states[state].capital = "select"; - states[state].burgs --; - } - manors[id].region = "removed"; - cells[cell].manor = undefined; - closeDialogs(".stable"); - updateCountryEditors(); - }, - Cancel: function() {$(this).dialog("close");} - } - }) - }); - } - - function editMarker() { - if (customization) return; - - unselect(); - closeDialogs("#markerEditor, .stable"); - elSelected = d3.select(this).call(d3.drag().on("start", elementDrag)).classed("draggable", true); - - $("#markerEditor").dialog({ - title: "Edit Marker", - minHeight: 30, width: "auto", maxWidth: 275, resizable: false, - position: {my: "center top+30", at: "bottom", of: d3.event}, - close: unselect - }); - - // update inputs - let id = elSelected.attr("href"); - let symbol = d3.select("#defs-markers").select(id); - let icon = symbol.select("text"); - markerSelectGroup.value = id.slice(1); - markerIconSize.value = parseFloat(icon.attr("font-size")); - markerIconShiftX.value = parseFloat(icon.attr("x")); - markerIconShiftY.value = parseFloat(icon.attr("y")); - markerIconFill.value = icon.attr("fill"); - markerIconStrokeWidth.value = icon.attr("stroke-width"); - markerIconStroke.value = icon.attr("stroke"); - markerSize.value = elSelected.attr("data-size"); - markerBase.value = symbol.select("path").attr("fill"); - markerFill.value = symbol.select("circle").attr("fill"); - let opacity = symbol.select("circle").attr("opacity"); - markerToggleBubble.className = opacity === "0" ? "icon-info" : "icon-info-circled"; - - let table = document.getElementById("markerIconTable"); - let selected = table.getElementsByClassName("selected"); - if (selected.length) selected[0].removeAttribute("class"); - selected = document.querySelectorAll("#markerIcon" + icon.text().codePointAt()); - if (selected.length) selected[0].className = "selected"; - markerIconCustom.value = selected.length ? "" : icon.text(); - - if (modules.editMarker) return; - modules.editMarker = true; - - $("#markerGroup").click(function() { - $("#markerEditor > button").not(this).toggle(); - $("#markerGroupSection").toggle(); - updateMarkerGroupOptions(); - }); - - function updateMarkerGroupOptions() { - markerSelectGroup.innerHTML = ""; - d3.select("#defs-markers").selectAll("symbol").each(function() { - let opt = document.createElement("option"); - opt.value = opt.innerHTML = this.id; - markerSelectGroup.add(opt); - }); - let id = elSelected.attr("href").slice(1); - markerSelectGroup.value = id; - } - - // on add marker type click - document.getElementById("markerAddGroup").addEventListener("click", function() { - if ($("#markerInputGroup").css("display") === "none") { - $("#markerInputGroup").css("display", "inline-block"); - $("#markerSelectGroup").css("display", "none"); - markerInputGroup.focus(); - } else { - $("#markerSelectGroup").css("display", "inline-block"); - $("#markerInputGroup").css("display", "none"); - } - }); - - // on marker type change - document.getElementById("markerSelectGroup").addEventListener("change", function() { - elSelected.attr("href", "#"+this.value); - elSelected.attr("data-id", "#"+this.value); - }); - - // on new type input - document.getElementById("markerInputGroup").addEventListener("change", function() { - let newGroup = this.value.toLowerCase().replace(/ /g, "_").replace(/[^\w\s]/gi, ""); - if (Number.isFinite(+newGroup.charAt(0))) newGroup = "m" + newGroup; - if (d3.select("#defs-markers").select("#"+newGroup).size()) { - tip('The type "'+ newGroup + '" is already exists'); - return; - } - markerInputGroup.value = ""; - // clone old group assigning new id - let id = elSelected.attr("href"); - let l = d3.select("#defs-markers").select(id).node().cloneNode(true); - l.id = newGroup; - elSelected.attr("href", "#"+newGroup); - elSelected.attr("data-id", "#"+newGroup); - document.getElementById("defs-markers").insertBefore(l, null); - - // select new group - let opt = document.createElement("option"); - opt.value = opt.innerHTML = newGroup; - markerSelectGroup.add(opt); - $("#markerSelectGroup").val(newGroup).change(); - $("#markerSelectGroup, #markerInputGroup").toggle(); - updateMarkerGroupOptions(); - }); - - $("#markerIconButton").click(function() { - $("#markerEditor > button").not(this).toggle(); - $("#markerIconButtons").toggle(); - if (!$("#markerIconTable").text()) drawIconsList(icons); - }); - - $("#markerRemoveGroup").click(function() { - let id = elSelected.attr("href"); - let used = document.querySelectorAll("use[data-id='"+id+"']"); - let count = used.length === 1 ? "1 element" : used.length + " elements"; - const message = "Are you sure you want to remove the marker (" + count + ")?"; - alertMessage.innerHTML = message; - $("#alert").dialog({resizable: false, title: "Remove marker", - buttons: { - Remove: function() { - $(this).dialog("close"); - if (id !== "#marker0") d3.select("#defs-markers").select(id).remove(); - used.forEach(function(e) {e.remove();}); - updateMarkerGroupOptions(); - $("#markerEditor").dialog("close"); - }, - Cancel: function() {$(this).dialog("close");} - } - }); - });