mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Completed transition to injected svgs
This commit is contained in:
12
client/src/@types/unit.d.ts
vendored
12
client/src/@types/unit.d.ts
vendored
@@ -79,4 +79,16 @@ interface GeneralSettings {
|
||||
prohibitAG: boolean;
|
||||
prohibitAfterburner: boolean;
|
||||
prohibitAirWpn: boolean;
|
||||
}
|
||||
|
||||
interface UnitIconOptions {
|
||||
showState: boolean,
|
||||
showVvi: boolean,
|
||||
showHotgroup: boolean,
|
||||
showUnitIcon: boolean,
|
||||
showShortLabel: boolean,
|
||||
showFuel: boolean,
|
||||
showAmmo: boolean,
|
||||
showSummary: boolean,
|
||||
rotateToHeading: boolean
|
||||
}
|
||||
@@ -67,7 +67,10 @@ export class Dropdown {
|
||||
selectValue(idx: number) {
|
||||
if (idx < this.#optionsList.length) {
|
||||
var option = this.#optionsList[idx];
|
||||
this.#value.innerHTML = `<div class = "ol-ellipsed"> ${option} </div>`;
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-ellipsed");
|
||||
el.innerText = option;
|
||||
this.#value.appendChild(el);
|
||||
this.#index = idx;
|
||||
this.#close();
|
||||
this.#callback(option);
|
||||
|
||||
@@ -88,7 +88,7 @@ export class Slider {
|
||||
|
||||
#onValue() {
|
||||
if (this.#valueText != null && this.#slider != null)
|
||||
this.#valueText.innerHTML = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit
|
||||
this.#valueText.innerText = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit
|
||||
this.setActive(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,11 +40,16 @@ export class UnitContextMenu extends ContextMenu {
|
||||
this.#customFormationCallback = callback;
|
||||
}
|
||||
|
||||
setOptions(options: { [key: string]: string }, callback: CallableFunction) {
|
||||
this.getContainer()?.replaceChildren(...Object.keys(options).map((option: string, idx: number) => {
|
||||
setOptions(options: { [key: string]: {text: string, tooltip: string }}, callback: CallableFunction) {
|
||||
this.getContainer()?.replaceChildren(...Object.keys(options).map((key: string, idx: number) => {
|
||||
const option = options[key];
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = options[option];
|
||||
button.addEventListener("click", () => callback(option));
|
||||
var el = document.createElement("div");
|
||||
el.title = option.tooltip;
|
||||
el.innerText = option.text;
|
||||
el.id = key;
|
||||
button.addEventListener("click", () => callback(key));
|
||||
button.appendChild(el);
|
||||
return (button);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -140,28 +140,14 @@ function setupEvents() {
|
||||
case "Space":
|
||||
setPaused(!getPaused());
|
||||
break;
|
||||
case "KeyW":
|
||||
case "KeyA":
|
||||
case "KeyS":
|
||||
case "KeyD":
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
case "KeyW": case "KeyA": case "KeyS": case "KeyD":
|
||||
case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown":
|
||||
getMap().handleMapPanning(ev);
|
||||
break;
|
||||
case "Digit1":
|
||||
case "Digit2":
|
||||
case "Digit3":
|
||||
case "Digit4":
|
||||
case "Digit5":
|
||||
case "Digit6":
|
||||
case "Digit7":
|
||||
case "Digit8":
|
||||
case "Digit9":
|
||||
case "Digit1": case "Digit2": case "Digit3": case "Digit4": case "Digit5": case "Digit6": case "Digit7": case "Digit8": case "Digit9":
|
||||
// Using the substring because the key will be invalid when pressing the Shift key
|
||||
if (ev.ctrlKey && ev.shiftKey)
|
||||
getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5)));
|
||||
getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5)));
|
||||
else if (ev.ctrlKey && !ev.shiftKey)
|
||||
getUnitsManager().selectedUnitsSetHotgroup(parseInt(ev.code.substring(5)));
|
||||
else
|
||||
@@ -176,14 +162,7 @@ function setupEvents() {
|
||||
return;
|
||||
}
|
||||
switch (ev.code) {
|
||||
case "KeyW":
|
||||
case "KeyA":
|
||||
case "KeyS":
|
||||
case "KeyD":
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
case "KeyW": case "KeyA": case "KeyS": case "KeyD": case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown":
|
||||
getMap().handleMapPanning(ev);
|
||||
break;
|
||||
}
|
||||
@@ -201,8 +180,8 @@ function setupEvents() {
|
||||
|
||||
document.addEventListener("tryConnection", () => {
|
||||
const form = document.querySelector("#splash-content")?.querySelector("#authentication-form");
|
||||
const username = (<HTMLInputElement> (form?.querySelector("#username"))).value;
|
||||
const password = (<HTMLInputElement> (form?.querySelector("#password"))).value;
|
||||
const username = (<HTMLInputElement>(form?.querySelector("#username"))).value;
|
||||
const password = (<HTMLInputElement>(form?.querySelector("#password"))).value;
|
||||
setCredentials(username, btoa("admin" + ":" + password));
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Map, Marker } from "leaflet";
|
||||
import { DivIcon, Map, Marker } from "leaflet";
|
||||
import { MarkerOptions } from "leaflet";
|
||||
import { LatLngExpression } from "leaflet";
|
||||
|
||||
@@ -8,6 +8,7 @@ export class CustomMarker extends Marker {
|
||||
}
|
||||
|
||||
onAdd(map: Map): this {
|
||||
this.setIcon(new DivIcon()); // Default empty icon
|
||||
super.onAdd(map);
|
||||
this.createIcon();
|
||||
return this;
|
||||
|
||||
@@ -22,6 +22,7 @@ require("../../public/javascripts/leaflet.nauticscale.js")
|
||||
export const IDLE = "IDLE";
|
||||
export const MOVE_UNIT = "MOVE_UNIT";
|
||||
export const visibilityControls: string[] = ["human", "dcs", "aircraft", "groundunit-sam", "groundunit-other", "navyunit", "airbase"];
|
||||
export const visibilityControlsTootlips: string[] = ["Toggle human players visibility", "Toggle DCS controlled units visibility", "Toggle aircrafts visibility", "Toggle SAM units visibility", "Toggle ground units (not SAM) visibility", "Toggle navy units visibility", "Toggle airbases visibility"];
|
||||
|
||||
export class Map extends L.Map {
|
||||
#state: string;
|
||||
@@ -116,7 +117,7 @@ export class Map extends L.Map {
|
||||
|
||||
/* Option buttons */
|
||||
this.#optionButtons["visibility"] = visibilityControls.map((option: string, index: number) => {
|
||||
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, "", "toggleUnitVisibility", `{"type": "${option}"}`);
|
||||
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleUnitVisibility", `{"type": "${option}"}`);
|
||||
});
|
||||
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);
|
||||
}
|
||||
@@ -194,7 +195,7 @@ export class Map extends L.Map {
|
||||
})
|
||||
this.#destinationPreviewMarkers = [];
|
||||
|
||||
if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length < 20) {
|
||||
if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length > 1 && getUnitsManager().getSelectedUnits({ excludeHumans: true }).length < 20) {
|
||||
/* Create the unit destination preview markers */
|
||||
this.#destinationPreviewMarkers = getUnitsManager().getSelectedUnits({ excludeHumans: true }).map((unit: Unit) => {
|
||||
var marker = new DestinationPreviewMarker(this.getMouseCoordinates());
|
||||
@@ -425,6 +426,9 @@ export class Map extends L.Map {
|
||||
getUnitsManager().selectedUnitsClearDestinations();
|
||||
}
|
||||
getUnitsManager().selectedUnitsAddDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : e.latlng, !e.originalEvent.shiftKey, this.#destinationGroupRotation)
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#destinationRotationCenter = null;
|
||||
this.#computeDestinationRotation = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,18 +444,18 @@ export class Map extends L.Map {
|
||||
#onMouseDown(e: any) {
|
||||
this.hideAllContextMenus();
|
||||
|
||||
if (this.#state == MOVE_UNIT && e.originalEvent.button == 2) {
|
||||
this.#computeDestinationRotation = true;
|
||||
this.#destinationRotationCenter = this.getMouseCoordinates();
|
||||
if (this.#state == MOVE_UNIT) {
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#destinationRotationCenter = null;
|
||||
this.#computeDestinationRotation = false;
|
||||
if (e.originalEvent.button == 2) {
|
||||
this.#computeDestinationRotation = true;
|
||||
this.#destinationRotationCenter = this.getMouseCoordinates();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#onMouseUp(e: any) {
|
||||
if (this.#state == MOVE_UNIT) {
|
||||
this.#computeDestinationRotation = false;
|
||||
this.#destinationRotationCenter = null;
|
||||
this.#destinationGroupRotation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#onMouseMove(e: any) {
|
||||
|
||||
@@ -18,14 +18,24 @@ export class HotgroupPanel extends Panel {
|
||||
}
|
||||
|
||||
addHotgroup(hotgroup: number) {
|
||||
const hotgroupHtml = `<div class="unit-hotgroup">
|
||||
<div class="unit-hotgroup-id">${hotgroup}</div>
|
||||
</div>
|
||||
x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}`
|
||||
// Hotgroup number
|
||||
var hotgroupDiv = document.createElement("div");
|
||||
hotgroupDiv.classList.add("unit-hotgroup");
|
||||
var idDiv = document.createElement("div");
|
||||
idDiv.classList.add("unit-hotgroup-id");
|
||||
idDiv.innerText = String(hotgroup);
|
||||
hotgroupDiv.appendChild(idDiv);
|
||||
|
||||
// Hotgroup unit count
|
||||
var countDiv = document.createElement("div");
|
||||
countDiv.innerText = `x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}`;
|
||||
|
||||
var el = document.createElement("div");
|
||||
el.appendChild(hotgroupDiv);
|
||||
el.appendChild(countDiv);
|
||||
el.classList.add("hotgroup-selector");
|
||||
el.innerHTML = hotgroupHtml;
|
||||
el.toggleAttribute(`data-hotgroup-${hotgroup}`, true)
|
||||
|
||||
this.getElement().appendChild(el);
|
||||
|
||||
el.addEventListener("click", () => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { SVGInjector } from "@tanem/svg-injector";
|
||||
import { getUnitsManager } from "..";
|
||||
import { Dropdown } from "../controls/dropdown";
|
||||
import { Slider } from "../controls/slider";
|
||||
@@ -346,7 +347,10 @@ export class UnitControlPanel extends Panel {
|
||||
var button = document.createElement("button");
|
||||
button.title = title;
|
||||
button.value = value;
|
||||
button.innerHTML = `<img src="/resources/theme/images/buttons/${url}" />`
|
||||
var img = document.createElement("img");
|
||||
img.src = `/resources/theme/images/buttons/${url}`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
button.appendChild(img);
|
||||
button.addEventListener("click", callback);
|
||||
return button;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { aircraftDatabase } from './aircraftdatabase';
|
||||
import { groundUnitsDatabase } from './groundunitsdatabase';
|
||||
import { CustomMarker } from '../map/custommarker';
|
||||
import { SVGInjector } from '@tanem/svg-injector';
|
||||
import { UnitDatabase } from './unitdatabase';
|
||||
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: '/resources/theme/images/markers/marker-icon.png',
|
||||
@@ -124,17 +125,23 @@ export class Unit extends CustomMarker {
|
||||
return "";
|
||||
}
|
||||
|
||||
getActiveMarkerElements() {
|
||||
// Default values
|
||||
getDatabase(): UnitDatabase | null {
|
||||
// Overloaded by child classes
|
||||
return null;
|
||||
}
|
||||
|
||||
getIconOptions(): UnitIconOptions {
|
||||
// Default values, overloaded by child classes if needed
|
||||
return {
|
||||
state: false,
|
||||
vvi: false,
|
||||
hotgroup: false,
|
||||
unitIcon: true,
|
||||
shortLabel: false,
|
||||
fuel: false,
|
||||
ammo: false,
|
||||
summary: false
|
||||
showState: false,
|
||||
showVvi: false,
|
||||
showHotgroup: false,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: false,
|
||||
showFuel: false,
|
||||
showAmmo: false,
|
||||
showSummary: false,
|
||||
rotateToHeading: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +172,7 @@ export class Unit extends CustomMarker {
|
||||
|
||||
setHotgroup(hotgroup: number | null) {
|
||||
this.#hotgroup = hotgroup;
|
||||
this.#updateMarker();
|
||||
}
|
||||
|
||||
getHotgroup() {
|
||||
@@ -172,7 +180,7 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
setHighlighted(highlighted: boolean) {
|
||||
if (this.#highlighted != highlighted) {
|
||||
if (this.getSelectable() && this.#highlighted != highlighted) {
|
||||
this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted);
|
||||
this.#highlighted = highlighted;
|
||||
this.getGroupMembers().forEach((unit: Unit) => unit.setHighlighted(highlighted));
|
||||
@@ -297,19 +305,13 @@ export class Unit extends CustomMarker {
|
||||
this.setIcon(icon);
|
||||
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("unit");
|
||||
el.setAttribute("data-object", `unit-${this.getMarkerCategory()}`);
|
||||
el.setAttribute("data-coalition", this.getMissionData().coalition);
|
||||
|
||||
// Generate and append elements depending on active options
|
||||
// State icon
|
||||
if (this.getActiveMarkerElements().state){
|
||||
var state = document.createElement("div");
|
||||
state.classList.add("unit-state");
|
||||
el.appendChild(state);
|
||||
}
|
||||
|
||||
// Generate and append elements depending on active options
|
||||
// Velocity vector
|
||||
if (this.getActiveMarkerElements().vvi) {
|
||||
if (this.getIconOptions().showVvi) {
|
||||
var vvi = document.createElement("div");
|
||||
vvi.classList.add("unit-vvi");
|
||||
vvi.toggleAttribute("data-rotate-to-heading");
|
||||
@@ -317,7 +319,7 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
// Hotgroup indicator
|
||||
if (this.getActiveMarkerElements().hotgroup) {
|
||||
if (this.getIconOptions().showHotgroup) {
|
||||
var hotgroup = document.createElement("div");
|
||||
hotgroup.classList.add("unit-hotgroup");
|
||||
var hotgroupId = document.createElement("div");
|
||||
@@ -327,26 +329,34 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
// Main icon
|
||||
if (this.getActiveMarkerElements().unitIcon) {
|
||||
if (this.getIconOptions().showUnitIcon) {
|
||||
var unitIcon = document.createElement("div");
|
||||
unitIcon.classList.add("unit-icon");
|
||||
var img = document.createElement("img");
|
||||
img.src = `/resources/theme/images/units/${this.getMarkerCategory()}.svg`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
unitIcon.appendChild(img);
|
||||
unitIcon.toggleAttribute("data-rotate-to-heading", this.getIconOptions().rotateToHeading);
|
||||
el.append(unitIcon);
|
||||
}
|
||||
|
||||
// State icon
|
||||
if (this.getIconOptions().showState){
|
||||
var state = document.createElement("div");
|
||||
state.classList.add("unit-state");
|
||||
el.appendChild(state);
|
||||
}
|
||||
|
||||
// Short label
|
||||
if (this.getActiveMarkerElements().shortLabel) {
|
||||
if (this.getIconOptions().showShortLabel) {
|
||||
var shortLabel = document.createElement("div");
|
||||
shortLabel.classList.add("unit-short-label");
|
||||
shortLabel.innerText = aircraftDatabase.getByName(this.getBaseData().name)?.shortLabel || ""; //TODO: fix, use correct database
|
||||
shortLabel.innerText = this.getDatabase()?.getByName(this.getBaseData().name)?.shortLabel || "";
|
||||
el.append(shortLabel);
|
||||
}
|
||||
|
||||
// Fuel indicator
|
||||
if (this.getActiveMarkerElements().fuel) {
|
||||
if (this.getIconOptions().showFuel) {
|
||||
var fuelIndicator = document.createElement("div");
|
||||
fuelIndicator.classList.add("unit-fuel");
|
||||
var fuelLevel = document.createElement("div");
|
||||
@@ -356,7 +366,7 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
// Ammo indicator
|
||||
if (this.getActiveMarkerElements().ammo){
|
||||
if (this.getIconOptions().showAmmo){
|
||||
var ammoIndicator = document.createElement("div");
|
||||
ammoIndicator.classList.add("unit-ammo");
|
||||
for (let i = 0; i <= 3; i++)
|
||||
@@ -365,7 +375,7 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
// Unit summary
|
||||
if (this.getActiveMarkerElements().summary) {
|
||||
if (this.getIconOptions().showSummary) {
|
||||
var summary = document.createElement("div");
|
||||
summary.classList.add("unit-summary");
|
||||
var callsign = document.createElement("div");
|
||||
@@ -544,18 +554,18 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
#onContextMenu(e: any) {
|
||||
var options: { [key: string]: string } = {};
|
||||
var options: {[key: string]: {text: string, tooltip: string}} = {};
|
||||
|
||||
options["Center"] = `<div id="center-map">Center map</div>`;
|
||||
options["center-map"] = {text: "Center map", tooltip: "Center the map on the unit and follow it"};
|
||||
|
||||
if (getUnitsManager().getSelectedUnits().length > 0 && !(getUnitsManager().getSelectedUnits().length == 1 && (getUnitsManager().getSelectedUnits().includes(this)))) {
|
||||
options['Attack'] = `<div id="attack">Attack</div>`;
|
||||
options["attack"] = {text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons"};
|
||||
if (getUnitsManager().getSelectedUnitsType() === "Aircraft")
|
||||
options['Follow'] = `<div id="follow">Follow</div>`;
|
||||
options["follow"] = {text: "Follow", tooltip: "Follow the unit at a user defined distance and position"};;
|
||||
}
|
||||
else if ((getUnitsManager().getSelectedUnits().length > 0 && (getUnitsManager().getSelectedUnits().includes(this))) || getUnitsManager().getSelectedUnits().length == 0) {
|
||||
if (this.getBaseData().category == "Aircraft") {
|
||||
options["Refuel"] = `<div id="refuel">Refuel</div>`; // TODO Add some way of knowing which aircraft can AAR
|
||||
options["refuel"] = {text: "AAR Refuel", tooltip: "Refuel unit at the nearest AAR Tanker. If no tanker is available the unit will RTB."}; // TODO Add some way of knowing which aircraft can AAR
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,28 +579,28 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
#executeAction(e: any, action: string) {
|
||||
if (action === "Center")
|
||||
if (action === "center-map")
|
||||
getMap().centerOnUnit(this.ID);
|
||||
if (action === "Attack")
|
||||
if (action === "attack")
|
||||
getUnitsManager().selectedUnitsAttackUnit(this.ID);
|
||||
else if (action === "Refuel")
|
||||
else if (action === "refuel")
|
||||
getUnitsManager().selectedUnitsRefuel();
|
||||
else if (action === "Follow")
|
||||
else if (action === "follow")
|
||||
this.#showFollowOptions(e);
|
||||
}
|
||||
|
||||
#showFollowOptions(e: any) {
|
||||
var options: { [key: string]: string } = {};
|
||||
var options: {[key: string]: {text: string, tooltip: string}} = {};
|
||||
|
||||
options = {
|
||||
'Trail': `<div id="trail">Trail</div>`,
|
||||
'Echelon (LH)': `<div id="echelon-lh">Echelon (left)</div>`,
|
||||
'Echelon (RH)': `<div id="echelon-rh">Echelon (right)</div>`,
|
||||
'Line abreast (LH)': `<div id="line-abreast">Line abreast (left)</div>`,
|
||||
'Line abreast (RH)': `<div id="line-abreast">Line abreast (right)</div>`,
|
||||
'Front': `<div id="front">In front</div>`,
|
||||
'Diamond': `<div id="diamond">Diamond</div>`,
|
||||
'Custom': `<div id="custom">Custom</div>`
|
||||
'trail': {text: "Trail", tooltip: "Follow unit in trail formation"},
|
||||
'echelon-lh': {text: "Echelon (LH)", tooltip: "Follow unit in echelon left formation"},
|
||||
'echelon-rh': {text: "Echelon (RH)", tooltip: "Follow unit in echelon right formation"},
|
||||
'line-abreast-lh': {text: "Line abreast (LH)", tooltip: "Follow unit in line abreast left formation"},
|
||||
'line-abreast-rh': {text: "Line abreast (RH)", tooltip: "Follow unit in line abreast right formation"},
|
||||
'front': {text: "Front", tooltip: "Fly in front of unit"},
|
||||
'diamond': {text: "Diamond", tooltip: "Follow unit in diamond formation"},
|
||||
'custom': {text: "Custom", tooltip: "Set a custom formation position"},
|
||||
}
|
||||
|
||||
getMap().getUnitContextMenu().setOptions(options, (option: string) => {
|
||||
@@ -601,7 +611,7 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
#applyFollowOptions(action: string) {
|
||||
if (action === "Custom") {
|
||||
if (action === "custom") {
|
||||
document.getElementById("custom-formation-dialog")?.classList.remove("hide");
|
||||
getMap().getUnitContextMenu().setCustomFormationCallback((offset: { x: number, y: number, z: number }) => {
|
||||
getUnitsManager().selectedUnitsFollowUnit(this.ID, offset);
|
||||
@@ -657,18 +667,18 @@ export class Unit extends CustomMarker {
|
||||
element.querySelector(".unit")?.toggleAttribute("data-is-dead", !this.getBaseData().alive);
|
||||
|
||||
/* Set current unit state */
|
||||
if (this.getMissionData().flags.Human) // Unit is human
|
||||
if (this.getMissionData().flags.Human) // Unit is human
|
||||
element.querySelector(".unit")?.setAttribute("data-state", "human");
|
||||
else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus)
|
||||
else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus)
|
||||
element.querySelector(".unit")?.setAttribute("data-state", "dcs");
|
||||
else // Unit is under Olympus control
|
||||
else // Unit is under Olympus control
|
||||
element.querySelector(".unit")?.setAttribute("data-state", this.getTaskData().currentState.toLowerCase());
|
||||
|
||||
/* Set altitude and speed */
|
||||
if (element.querySelector(".unit-altitude"))
|
||||
(<HTMLElement>element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(this.getFlightData().altitude / 0.3048 / 100));
|
||||
if (element.querySelector(".unit-speed"))
|
||||
(<HTMLElement>element.querySelector(".unit-speed")).innerHTML = String(Math.floor(this.getFlightData().speed * 1.94384));
|
||||
(<HTMLElement>element.querySelector(".unit-speed")).innerText = String(Math.floor(this.getFlightData().speed * 1.94384));
|
||||
|
||||
/* Rotate elements according to heading */
|
||||
element.querySelectorAll("[data-rotate-to-heading]").forEach(el => {
|
||||
@@ -791,16 +801,17 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
export class AirUnit extends Unit {
|
||||
getActiveMarkerElements() {
|
||||
getIconOptions() {
|
||||
return {
|
||||
state: true,
|
||||
vvi: true,
|
||||
hotgroup: true,
|
||||
unitIcon: true,
|
||||
shortLabel: true,
|
||||
fuel: true,
|
||||
ammo: true,
|
||||
summary: true
|
||||
showState: true,
|
||||
showVvi: true,
|
||||
showHotgroup: true,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: true,
|
||||
showFuel: true,
|
||||
showAmmo: true,
|
||||
showSummary: true,
|
||||
rotateToHeading: false
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -813,6 +824,10 @@ export class Aircraft extends AirUnit {
|
||||
getMarkerCategory() {
|
||||
return "aircraft";
|
||||
}
|
||||
|
||||
getDatabase(): UnitDatabase | null {
|
||||
return aircraftDatabase;
|
||||
}
|
||||
}
|
||||
|
||||
export class Helicopter extends AirUnit {
|
||||
@@ -830,16 +845,17 @@ export class GroundUnit extends Unit {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
getActiveMarkerElements() {
|
||||
getIconOptions() {
|
||||
return {
|
||||
state: true,
|
||||
vvi: false,
|
||||
hotgroup: true,
|
||||
unitIcon: true,
|
||||
shortLabel: true,
|
||||
fuel: false,
|
||||
ammo: false,
|
||||
summary: false
|
||||
showState: true,
|
||||
showVvi: false,
|
||||
showHotgroup: true,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: true,
|
||||
showFuel: false,
|
||||
showAmmo: false,
|
||||
showSummary: false,
|
||||
rotateToHeading: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -849,6 +865,10 @@ export class GroundUnit extends Unit {
|
||||
var markerCategory = (role === "SAM") ? "groundunit-sam" : "groundunit-other";
|
||||
return markerCategory;
|
||||
}
|
||||
|
||||
getDatabase(): UnitDatabase | null {
|
||||
return groundUnitsDatabase;
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnit extends Unit {
|
||||
@@ -856,16 +876,17 @@ export class NavyUnit extends Unit {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
getActiveMarkerElements() {
|
||||
getIconOptions() {
|
||||
return {
|
||||
state: true,
|
||||
vvi: false,
|
||||
hotgroup: true,
|
||||
unitIcon: true,
|
||||
shortLabel: true,
|
||||
fuel: false,
|
||||
ammo: false,
|
||||
summary: false
|
||||
showState: true,
|
||||
showVvi: false,
|
||||
showHotgroup: true,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: true,
|
||||
showFuel: false,
|
||||
showAmmo: false,
|
||||
showSummary: false,
|
||||
rotateToHeading: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -879,6 +900,20 @@ export class Weapon extends Unit {
|
||||
super(ID, data);
|
||||
this.setSelectable(false);
|
||||
}
|
||||
|
||||
getIconOptions() {
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: false,
|
||||
showHotgroup: false,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: false,
|
||||
showFuel: false,
|
||||
showAmmo: false,
|
||||
showSummary: false,
|
||||
rotateToHeading: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class Missile extends Weapon {
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
export class UnitDatabase {
|
||||
blueprints: {[key: string]: UnitBlueprint} = {};
|
||||
blueprints: { [key: string]: UnitBlueprint } = {};
|
||||
|
||||
constructor()
|
||||
{
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
/* Returns a list of all possible roles in a database */
|
||||
getRoles()
|
||||
{
|
||||
getRoles() {
|
||||
var roles: string[] = [];
|
||||
for (let unit in this.blueprints)
|
||||
{
|
||||
for (let loadout of this.blueprints[unit].loadouts)
|
||||
{
|
||||
for (let role of loadout.roles)
|
||||
{
|
||||
for (let unit in this.blueprints) {
|
||||
for (let loadout of this.blueprints[unit].loadouts) {
|
||||
for (let role of loadout.roles) {
|
||||
if (role !== "" && !roles.includes(role))
|
||||
roles.push(role);
|
||||
}
|
||||
@@ -25,18 +20,15 @@ export class UnitDatabase {
|
||||
}
|
||||
|
||||
/* Gets a specific blueprint by name */
|
||||
getByName(name: string)
|
||||
{
|
||||
getByName(name: string) {
|
||||
if (name in this.blueprints)
|
||||
return this.blueprints[name];
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Gets a specific blueprint by label */
|
||||
getByLabel(label: string)
|
||||
{
|
||||
for (let unit in this.blueprints)
|
||||
{
|
||||
getByLabel(label: string) {
|
||||
for (let unit in this.blueprints) {
|
||||
if (this.blueprints[unit].label === label)
|
||||
return this.blueprints[unit];
|
||||
}
|
||||
@@ -44,15 +36,11 @@ export class UnitDatabase {
|
||||
}
|
||||
|
||||
/* Get all blueprints by role */
|
||||
getByRole(role: string)
|
||||
{
|
||||
getByRole(role: string) {
|
||||
var units = [];
|
||||
for (let unit in this.blueprints)
|
||||
{
|
||||
for (let loadout of this.blueprints[unit].loadouts)
|
||||
{
|
||||
if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase()))
|
||||
{
|
||||
for (let unit in this.blueprints) {
|
||||
for (let loadout of this.blueprints[unit].loadouts) {
|
||||
if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase())) {
|
||||
units.push(this.blueprints[unit])
|
||||
break;
|
||||
}
|
||||
@@ -62,13 +50,10 @@ export class UnitDatabase {
|
||||
}
|
||||
|
||||
/* Get the names of all the loadouts for a specific unit and for a specific role */
|
||||
getLoadoutNamesByRole(name: string, role: string)
|
||||
{
|
||||
getLoadoutNamesByRole(name: string, role: string) {
|
||||
var loadouts = [];
|
||||
for (let loadout of this.blueprints[name].loadouts)
|
||||
{
|
||||
if (loadout.roles.includes(role) || loadout.roles.includes(""))
|
||||
{
|
||||
for (let loadout of this.blueprints[name].loadouts) {
|
||||
if (loadout.roles.includes(role) || loadout.roles.includes("")) {
|
||||
loadouts.push(loadout.name)
|
||||
}
|
||||
}
|
||||
@@ -76,10 +61,8 @@ export class UnitDatabase {
|
||||
}
|
||||
|
||||
/* Get the loadout content from the unit name and loadout name */
|
||||
getLoadoutByName(name: string, loadoutName: string)
|
||||
{
|
||||
for (let loadout of this.blueprints[name].loadouts)
|
||||
{
|
||||
getLoadoutByName(name: string, loadoutName: string) {
|
||||
for (let loadout of this.blueprints[name].loadouts) {
|
||||
if (loadout.name === loadoutName)
|
||||
return loadout;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
getUnitsByHotgroup(hotgroup: number) {
|
||||
return Object.values(this.#units).filter((unit: Unit) => {return unit.getBaseData().alive && unit.getHotgroup() == hotgroup});
|
||||
return Object.values(this.#units).filter((unit: Unit) => { return unit.getBaseData().alive && unit.getHotgroup() == hotgroup });
|
||||
}
|
||||
|
||||
addUnit(ID: number, data: UnitData) {
|
||||
@@ -88,10 +88,8 @@ export class UnitsManager {
|
||||
});
|
||||
}
|
||||
|
||||
setHiddenType(key: string, value: boolean)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
setHiddenType(key: string, value: boolean) {
|
||||
if (value) {
|
||||
if (this.#hiddenTypes.includes(key))
|
||||
delete this.#hiddenTypes[this.#hiddenTypes.indexOf(key)];
|
||||
}
|
||||
@@ -100,8 +98,7 @@ export class UnitsManager {
|
||||
Object.values(this.getUnits()).forEach((unit: Unit) => unit.updateVisibility());
|
||||
}
|
||||
|
||||
getHiddenTypes()
|
||||
{
|
||||
getHiddenTypes() {
|
||||
return this.#hiddenTypes;
|
||||
}
|
||||
|
||||
@@ -123,7 +120,7 @@ export class UnitsManager {
|
||||
}
|
||||
}
|
||||
|
||||
getSelectedUnits(options?: {excludeHumans?: boolean}) {
|
||||
getSelectedUnits(options?: { excludeHumans?: boolean }) {
|
||||
var selectedUnits = [];
|
||||
for (let ID in this.#units) {
|
||||
if (this.#units[ID].getSelected()) {
|
||||
@@ -132,7 +129,7 @@ export class UnitsManager {
|
||||
}
|
||||
if (options) {
|
||||
if (options.excludeHumans)
|
||||
selectedUnits = selectedUnits.filter((unit: Unit) => {return !unit.getMissionData().flags.Human});
|
||||
selectedUnits = selectedUnits.filter((unit: Unit) => { return !unit.getMissionData().flags.Human });
|
||||
}
|
||||
return selectedUnits;
|
||||
}
|
||||
@@ -190,14 +187,14 @@ export class UnitsManager {
|
||||
|
||||
/*********************** Actions on selected units ************************/
|
||||
selectedUnitsAddDestination(latlng: L.LatLng, mantainRelativePosition: boolean, rotation: number) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
|
||||
/* Compute the destination for each unit. If mantainRelativePosition is true, compute the destination so to hold the relative distances */
|
||||
var unitDestinations: {[key: number]: LatLng} = {};
|
||||
var unitDestinations: { [key: number]: LatLng } = {};
|
||||
if (mantainRelativePosition)
|
||||
unitDestinations = this.selectedUnitsComputeGroupDestination(latlng, rotation);
|
||||
else
|
||||
selectedUnits.forEach((unit: Unit) => {unitDestinations[unit.ID] = latlng});
|
||||
selectedUnits.forEach((unit: Unit) => { unitDestinations[unit.ID] = latlng });
|
||||
|
||||
for (let idx in selectedUnits) {
|
||||
const unit = selectedUnits[idx];
|
||||
@@ -206,7 +203,7 @@ export class UnitsManager {
|
||||
const leader = this.getUnitByID(unit.getFormationData().leaderID)
|
||||
if (leader && leader.getSelected())
|
||||
leader.addDestination(latlng);
|
||||
else
|
||||
else
|
||||
unit.addDestination(latlng);
|
||||
}
|
||||
else {
|
||||
@@ -219,7 +216,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsClearDestinations() {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
const unit = selectedUnits[idx];
|
||||
if (unit.getTaskData().currentState === "Follow") {
|
||||
@@ -235,7 +232,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsLandAt(latlng: LatLng) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].landAt(latlng);
|
||||
}
|
||||
@@ -243,21 +240,21 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsChangeSpeed(speedChange: string) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].changeSpeed(speedChange);
|
||||
}
|
||||
}
|
||||
|
||||
selectedUnitsChangeAltitude(altitudeChange: string) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].changeAltitude(altitudeChange);
|
||||
}
|
||||
}
|
||||
|
||||
selectedUnitsSetSpeed(speed: number) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].setSpeed(speed);
|
||||
}
|
||||
@@ -265,7 +262,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsSetAltitude(altitude: number) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].setAltitude(altitude);
|
||||
}
|
||||
@@ -273,7 +270,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsSetROE(ROE: string) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].setROE(ROE);
|
||||
}
|
||||
@@ -281,7 +278,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsSetReactionToThreat(reactionToThreat: string) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].setReactionToThreat(reactionToThreat);
|
||||
}
|
||||
@@ -289,7 +286,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsSetEmissionsCountermeasures(emissionCountermeasure: string) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].setEmissionsCountermeasures(emissionCountermeasure);
|
||||
}
|
||||
@@ -298,7 +295,7 @@ export class UnitsManager {
|
||||
|
||||
|
||||
selectedUnitsAttackUnit(ID: number) {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].attackUnit(ID);
|
||||
}
|
||||
@@ -314,7 +311,7 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
selectedUnitsRefuel() {
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].refuel();
|
||||
}
|
||||
@@ -328,15 +325,15 @@ export class UnitsManager {
|
||||
// Y: top-bottom, positive top
|
||||
// Z: left-right, positive right
|
||||
offset = { "x": 0, "y": 0, "z": 0 };
|
||||
if (formation === "Trail") { offset.x = -50; offset.y = -30; offset.z = 0; }
|
||||
else if (formation === "Echelon (LH)") { offset.x = -50; offset.y = -10; offset.z = -50; }
|
||||
else if (formation === "Echelon (RH)") { offset.x = -50; offset.y = -10; offset.z = 50; }
|
||||
else if (formation === "Line abreast (RH)") { offset.x = 0; offset.y = 0; offset.z = 50; }
|
||||
else if (formation === "Line abreast (LH)") { offset.x = 0; offset.y = 0; offset.z = -50; }
|
||||
else if (formation === "Front") { offset.x = 100; offset.y = 0; offset.z = 0; }
|
||||
if (formation === "trail") { offset.x = -50; offset.y = -30; offset.z = 0; }
|
||||
else if (formation === "echelon-lh") { offset.x = -50; offset.y = -10; offset.z = -50; }
|
||||
else if (formation === "echelon-rh") { offset.x = -50; offset.y = -10; offset.z = 50; }
|
||||
else if (formation === "line-abreast-rh") { offset.x = 0; offset.y = 0; offset.z = 50; }
|
||||
else if (formation === "line-abreast-lh") { offset.x = 0; offset.y = 0; offset.z = -50; }
|
||||
else if (formation === "front") { offset.x = 100; offset.y = 0; offset.z = 0; }
|
||||
else offset = undefined;
|
||||
}
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
var count = 1;
|
||||
var xr = 0; var yr = 1; var zr = -1;
|
||||
var layer = 1;
|
||||
@@ -347,7 +344,7 @@ export class UnitsManager {
|
||||
unit.followUnit(ID, { "x": offset.x * count, "y": offset.y * count, "z": offset.z * count });
|
||||
else {
|
||||
/* More complex formations with variable offsets */
|
||||
if (formation === "Diamond") {
|
||||
if (formation === "diamond") {
|
||||
var xl = xr * Math.cos(Math.PI / 4) - yr * Math.sin(Math.PI / 4);
|
||||
var yl = xr * Math.sin(Math.PI / 4) + yr * Math.cos(Math.PI / 4);
|
||||
unit.followUnit(ID, { "x": -yl * 50, "y": zr * 10, "z": xl * 50 });
|
||||
@@ -364,14 +361,12 @@ export class UnitsManager {
|
||||
this.#showActionMessage(selectedUnits, `following unit ${this.getUnitByID(ID)?.getBaseData().unitName}`);
|
||||
}
|
||||
|
||||
selectedUnitsSetHotgroup(hotgroup: number)
|
||||
{
|
||||
selectedUnitsSetHotgroup(hotgroup: number) {
|
||||
this.getUnitsByHotgroup(hotgroup).forEach((unit: Unit) => unit.setHotgroup(null));
|
||||
this.selectedUnitsAddToHotgroup(hotgroup);
|
||||
}
|
||||
|
||||
selectedUnitsAddToHotgroup(hotgroup: number)
|
||||
{
|
||||
selectedUnitsAddToHotgroup(hotgroup: number) {
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].setHotgroup(hotgroup);
|
||||
@@ -380,11 +375,10 @@ export class UnitsManager {
|
||||
getHotgroupPanel().refreshHotgroups();
|
||||
}
|
||||
|
||||
selectedUnitsComputeGroupDestination(latlng: LatLng, rotation: number)
|
||||
{
|
||||
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
|
||||
selectedUnitsComputeGroupDestination(latlng: LatLng, rotation: number) {
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
|
||||
/* Compute the center of the group */
|
||||
var center = {x: 0, y: 0};
|
||||
var center = { x: 0, y: 0 };
|
||||
selectedUnits.forEach((unit: Unit) => {
|
||||
var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude);
|
||||
center.x += mercator.x / selectedUnits.length;
|
||||
@@ -392,20 +386,19 @@ export class UnitsManager {
|
||||
});
|
||||
|
||||
/* Compute the distances from the center of the group */
|
||||
|
||||
var unitDestinations: {[key: number]: LatLng} = {};
|
||||
var unitDestinations: { [key: number]: LatLng } = {};
|
||||
selectedUnits.forEach((unit: Unit) => {
|
||||
var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude);
|
||||
var distancesFromCenter = {dx: mercator.x - center.x, dy: mercator.y - center.y};
|
||||
var distancesFromCenter = { dx: mercator.x - center.x, dy: mercator.y - center.y };
|
||||
|
||||
/* Rotate the distance according to the group rotation */
|
||||
var rotatedDistancesFromCenter: {dx: number, dy: number} = {dx: 0, dy: 0};
|
||||
var rotatedDistancesFromCenter: { dx: number, dy: number } = { dx: 0, dy: 0 };
|
||||
rotatedDistancesFromCenter.dx = distancesFromCenter.dx * Math.cos(deg2rad(rotation)) - distancesFromCenter.dy * Math.sin(deg2rad(rotation));
|
||||
rotatedDistancesFromCenter.dy = distancesFromCenter.dx * Math.sin(deg2rad(rotation)) + distancesFromCenter.dy * Math.cos(deg2rad(rotation));
|
||||
|
||||
/* Compute the final position of the unit */
|
||||
var destMercator = latLngToMercator(latlng.lat, latlng.lng); // Convert destination point to mercator
|
||||
var unitMercator = {x: destMercator.x + rotatedDistancesFromCenter.dx, y: destMercator.y + rotatedDistancesFromCenter.dy}; // Compute final position of this unit in mercator coordinates
|
||||
var unitMercator = { x: destMercator.x + rotatedDistancesFromCenter.dx, y: destMercator.y + rotatedDistancesFromCenter.dy }; // Compute final position of this unit in mercator coordinates
|
||||
var unitLatLng = mercatorToLatLng(unitMercator.x, unitMercator.y);
|
||||
unitDestinations[unit.ID] = new LatLng(unitLatLng.lat, unitLatLng.lng);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user