mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Merge pull request #1014 from Pax1601/features/navpoints
Features/navpoints
This commit is contained in:
@@ -3,6 +3,7 @@ import { getApp } from "../../olympusapp";
|
|||||||
import { DrawingsInitEvent, DrawingsUpdatedEvent, MapOptionsChangedEvent, SessionDataLoadedEvent } from "../../events";
|
import { DrawingsInitEvent, DrawingsUpdatedEvent, MapOptionsChangedEvent, SessionDataLoadedEvent } from "../../events";
|
||||||
import { MapOptions } from "../../types/types";
|
import { MapOptions } from "../../types/types";
|
||||||
import { Circle, DivIcon, Layer, LayerGroup, layerGroup, Marker, Polygon, Polyline } from "leaflet";
|
import { Circle, DivIcon, Layer, LayerGroup, layerGroup, Marker, Polygon, Polyline } from "leaflet";
|
||||||
|
import { NavpointMarker } from "../markers/navpointmarker";
|
||||||
|
|
||||||
export abstract class DCSDrawing {
|
export abstract class DCSDrawing {
|
||||||
#name: string;
|
#name: string;
|
||||||
@@ -452,6 +453,57 @@ export class DCSTextBox extends DCSDrawing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DCSNavpoint extends DCSDrawing {
|
||||||
|
#point: NavpointMarker;
|
||||||
|
|
||||||
|
constructor(drawingData, parent) {
|
||||||
|
super(drawingData, parent);
|
||||||
|
|
||||||
|
this.#point = new NavpointMarker([drawingData.lat, drawingData.lng], drawingData.callsignStr, drawingData.comment);
|
||||||
|
|
||||||
|
this.setVisibility(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLayer() {
|
||||||
|
return this.#point;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLabelLayer() {
|
||||||
|
return this.#point;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOpacity(opacity: number): void {
|
||||||
|
if (opacity === this.#point.options.opacity) return;
|
||||||
|
|
||||||
|
this.#point.options.opacity = opacity;
|
||||||
|
|
||||||
|
/* Hack to force marker redraw */
|
||||||
|
const originalVisibility = this.getVisibility();
|
||||||
|
this.setVisibility(false);
|
||||||
|
this.setVisibility(originalVisibility);
|
||||||
|
|
||||||
|
getApp().getDrawingsManager().requestUpdateEventDispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisibility(visibility: boolean): void {
|
||||||
|
if (visibility && !this.getParent().getLayerGroup().hasLayer(this.#point)) this.#point.addTo(this.getParent().getLayerGroup());
|
||||||
|
//@ts-ignore Leaflet typings are wrong
|
||||||
|
if (!visibility && this.getParent().getLayerGroup().hasLayer(this.#point)) this.#point.removeFrom(this.getParent().getLayerGroup());
|
||||||
|
|
||||||
|
if (visibility && !this.getParent().getVisibility()) this.getParent().setVisibility(true);
|
||||||
|
|
||||||
|
getApp().getDrawingsManager().requestUpdateEventDispatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
getOpacity(): number {
|
||||||
|
return this.#point.options.opacity ?? 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
getVisibility(): boolean {
|
||||||
|
return this.getParent().getLayerGroup().hasLayer(this.#point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class DCSDrawingsContainer {
|
export class DCSDrawingsContainer {
|
||||||
#drawings: DCSDrawing[] = [];
|
#drawings: DCSDrawing[] = [];
|
||||||
#subContainers: DCSDrawingsContainer[] = [];
|
#subContainers: DCSDrawingsContainer[] = [];
|
||||||
@@ -475,7 +527,10 @@ export class DCSDrawingsContainer {
|
|||||||
initFromData(drawingsData) {
|
initFromData(drawingsData) {
|
||||||
let hasContainers = false;
|
let hasContainers = false;
|
||||||
Object.keys(drawingsData).forEach((layerName: string) => {
|
Object.keys(drawingsData).forEach((layerName: string) => {
|
||||||
if (drawingsData[layerName]["name"] === undefined) {
|
if (layerName === 'navpoints') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (drawingsData[layerName]["name"] === undefined && drawingsData[layerName]["callsignStr"] === undefined) {
|
||||||
const newContainer = new DCSDrawingsContainer(layerName, this);
|
const newContainer = new DCSDrawingsContainer(layerName, this);
|
||||||
this.addSubContainer(newContainer);
|
this.addSubContainer(newContainer);
|
||||||
newContainer.initFromData(drawingsData[layerName]);
|
newContainer.initFromData(drawingsData[layerName]);
|
||||||
@@ -487,6 +542,7 @@ export class DCSDrawingsContainer {
|
|||||||
|
|
||||||
Object.keys(drawingsData).forEach((layerName: string) => {
|
Object.keys(drawingsData).forEach((layerName: string) => {
|
||||||
const primitiveType = drawingsData[layerName]["primitiveType"];
|
const primitiveType = drawingsData[layerName]["primitiveType"];
|
||||||
|
const isANavpoint = !!drawingsData[layerName]['callsignStr'];
|
||||||
|
|
||||||
// Possible primitives:
|
// Possible primitives:
|
||||||
// "Line","TextBox","Polygon","Icon"
|
// "Line","TextBox","Polygon","Icon"
|
||||||
@@ -499,6 +555,14 @@ export class DCSDrawingsContainer {
|
|||||||
|
|
||||||
let newDrawing = new DCSEmptyLayer(drawingsData[layerName], othersContainer) as DCSDrawing;
|
let newDrawing = new DCSEmptyLayer(drawingsData[layerName], othersContainer) as DCSDrawing;
|
||||||
|
|
||||||
|
if (isANavpoint) {
|
||||||
|
newDrawing = new DCSNavpoint(drawingsData[layerName], othersContainer);
|
||||||
|
if (hasContainers) othersContainer.addDrawing(newDrawing);
|
||||||
|
else this.addDrawing(newDrawing);
|
||||||
|
if (othersContainer.getDrawings().length === 0) this.removeSubContainer(othersContainer); // Remove empty container
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (primitiveType) {
|
switch (primitiveType) {
|
||||||
case "Polygon":
|
case "Polygon":
|
||||||
newDrawing = new DCSPolygon(drawingsData[layerName], othersContainer);
|
newDrawing = new DCSPolygon(drawingsData[layerName], othersContainer);
|
||||||
@@ -521,6 +585,12 @@ export class DCSDrawingsContainer {
|
|||||||
if (othersContainer.getDrawings().length === 0) this.removeSubContainer(othersContainer); // Remove empty container
|
if (othersContainer.getDrawings().length === 0) this.removeSubContainer(othersContainer); // Remove empty container
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initNavpoints(drawingsData) {
|
||||||
|
const newContainer = new DCSDrawingsContainer('Navpoints', this);
|
||||||
|
this.addSubContainer(newContainer);
|
||||||
|
newContainer.initFromData(drawingsData);
|
||||||
|
}
|
||||||
|
|
||||||
getLayerGroup() {
|
getLayerGroup() {
|
||||||
return this.#layerGroup;
|
return this.#layerGroup;
|
||||||
}
|
}
|
||||||
@@ -655,6 +725,7 @@ export class DrawingsManager {
|
|||||||
initDrawings(data: { drawings: Record<string, Record<string, any>> }): boolean {
|
initDrawings(data: { drawings: Record<string, Record<string, any>> }): boolean {
|
||||||
if (data && data.drawings) {
|
if (data && data.drawings) {
|
||||||
this.#drawingsContainer.initFromData(data.drawings);
|
this.#drawingsContainer.initFromData(data.drawings);
|
||||||
|
if (data.drawings.navpoints) this.#drawingsContainer.initNavpoints(data.drawings.navpoints);
|
||||||
if (this.#sessionDataDrawings["Mission drawings"]) this.#drawingsContainer.fromJSON(this.#sessionDataDrawings["Mission drawings"]);
|
if (this.#sessionDataDrawings["Mission drawings"]) this.#drawingsContainer.fromJSON(this.#sessionDataDrawings["Mission drawings"]);
|
||||||
DrawingsInitEvent.dispatch(this.#drawingsContainer);
|
DrawingsInitEvent.dispatch(this.#drawingsContainer);
|
||||||
this.#initialized = true;
|
this.#initialized = true;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import "./markers/stylesheets/bullseye.css";
|
|||||||
import "./markers/stylesheets/units.css";
|
import "./markers/stylesheets/units.css";
|
||||||
import "./markers/stylesheets/spot.css";
|
import "./markers/stylesheets/spot.css";
|
||||||
import "./markers/stylesheets/measure.css";
|
import "./markers/stylesheets/measure.css";
|
||||||
|
import "./markers/stylesheets/navpoint.css";
|
||||||
import "./stylesheets/map.css";
|
import "./stylesheets/map.css";
|
||||||
|
|
||||||
import { initDraggablePath } from "./coalitionarea/draggablepath";
|
import { initDraggablePath } from "./coalitionarea/draggablepath";
|
||||||
|
|||||||
48
frontend/react/src/map/markers/navpointmarker.ts
Normal file
48
frontend/react/src/map/markers/navpointmarker.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { DivIcon, LatLngExpression, MarkerOptions } from "leaflet";
|
||||||
|
import { CustomMarker } from "./custommarker";
|
||||||
|
|
||||||
|
export class NavpointMarker extends CustomMarker {
|
||||||
|
#callsignStr: string;
|
||||||
|
#comment: string;
|
||||||
|
|
||||||
|
constructor(latlng: LatLngExpression, callsignStr: string, comment?: string) {
|
||||||
|
super(latlng, { interactive: false, draggable: false });
|
||||||
|
this.#callsignStr = callsignStr;
|
||||||
|
comment ? this.#comment = comment : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
createIcon() {
|
||||||
|
/* Set the icon */
|
||||||
|
let icon = new DivIcon({
|
||||||
|
className: "leaflet-navpoint-icon",
|
||||||
|
iconAnchor: [0, 0],
|
||||||
|
iconSize: [50, 50],
|
||||||
|
});
|
||||||
|
this.setIcon(icon);
|
||||||
|
|
||||||
|
let el = document.createElement("div");
|
||||||
|
el.classList.add("navpoint");
|
||||||
|
|
||||||
|
// Main icon
|
||||||
|
let pointIcon = document.createElement("div");
|
||||||
|
pointIcon.classList.add("navpoint-icon");
|
||||||
|
el.append(pointIcon);
|
||||||
|
|
||||||
|
// Label
|
||||||
|
let mainLabel: HTMLDivElement = document.createElement("div");;
|
||||||
|
mainLabel.classList.add("navpoint-main-label");
|
||||||
|
mainLabel.innerText = this.#callsignStr;
|
||||||
|
el.append(mainLabel);
|
||||||
|
|
||||||
|
// Further description
|
||||||
|
if (this.#comment) {
|
||||||
|
let commentBox: HTMLDivElement = document.createElement("div");;
|
||||||
|
commentBox.classList.add("navpoint-comment-box");
|
||||||
|
commentBox.innerText = this.#comment;
|
||||||
|
mainLabel.append(commentBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getElement()?.appendChild(el);
|
||||||
|
this.getElement()?.classList.add("ol-navpoint-marker");
|
||||||
|
}
|
||||||
|
}
|
||||||
27
frontend/react/src/map/markers/stylesheets/navpoint.css
Normal file
27
frontend/react/src/map/markers/stylesheets/navpoint.css
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
.ol-navpoint-marker>.navpoint {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.ol-navpoint-marker>.navpoint>.navpoint-icon {
|
||||||
|
height: 8px;
|
||||||
|
width: 8px;
|
||||||
|
background: white;
|
||||||
|
flex: none;
|
||||||
|
transform: rotate3d(0, 0, 1, 45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-navpoint-marker>.navpoint>.navpoint-main-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 10px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ol-navpoint-marker .navpoint-comment-box {
|
||||||
|
font-size: 8px;
|
||||||
|
font-style: italic;
|
||||||
|
color: white;
|
||||||
|
max-width: 50px;
|
||||||
|
}
|
||||||
@@ -1076,6 +1076,44 @@ function getUnitDescription(unit)
|
|||||||
return unit:getDescr()
|
return unit:getDescr()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- This function gets the navpoints from the DCS mission
|
||||||
|
function Olympus.getNavPoints()
|
||||||
|
local function extract_tag(str)
|
||||||
|
return str:match("^%[(.-)%]")
|
||||||
|
end
|
||||||
|
|
||||||
|
local navpoints = {}
|
||||||
|
if mist.DBs.navPoints ~= nil then
|
||||||
|
for coalitionName, coalitionNavpoints in pairs(mist.DBs.navPoints) do
|
||||||
|
if navpoints[coalitionName] == nil then
|
||||||
|
navpoints[coalitionName] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
for index, navpointDrawingData in pairs(coalitionNavpoints) do
|
||||||
|
local navpointCustomLayer = extract_tag(navpointDrawingData['callsignStr']);
|
||||||
|
|
||||||
|
-- Let's convert DCS coords to lat lon
|
||||||
|
local vec3 = { x = navpointDrawingData['x'], y = 0, z = navpointDrawingData['y'] }
|
||||||
|
local lat, lng = coord.LOtoLL(vec3)
|
||||||
|
navpointDrawingData['lat'] = lat
|
||||||
|
navpointDrawingData['lng'] = lng
|
||||||
|
navpointDrawingData['coalition'] = coalitionName
|
||||||
|
|
||||||
|
if navpointCustomLayer ~= nil then
|
||||||
|
if navpoints[coalitionName][navpointCustomLayer] == nil then
|
||||||
|
navpoints[coalitionName][navpointCustomLayer] = {}
|
||||||
|
end
|
||||||
|
navpoints[coalitionName][navpointCustomLayer][navpointDrawingData['callsignStr']] = navpointDrawingData
|
||||||
|
else
|
||||||
|
navpoints[coalitionName][navpointDrawingData['callsignStr']] = navpointDrawingData
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return navpoints
|
||||||
|
end
|
||||||
|
|
||||||
-- This function is periodically called to collect the data of all the existing drawings in the mission to be transmitted to the olympus.dll
|
-- This function is periodically called to collect the data of all the existing drawings in the mission to be transmitted to the olympus.dll
|
||||||
function Olympus.initializeDrawings()
|
function Olympus.initializeDrawings()
|
||||||
local drawings = {}
|
local drawings = {}
|
||||||
@@ -1129,6 +1167,10 @@ function Olympus.initializeDrawings()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local navpoints = Olympus.getNavPoints()
|
||||||
|
|
||||||
|
drawings['navpoints'] = navpoints
|
||||||
|
|
||||||
Olympus.drawingsByLayer["drawings"] = drawings
|
Olympus.drawingsByLayer["drawings"] = drawings
|
||||||
|
|
||||||
-- Send the drawings to the DLL
|
-- Send the drawings to the DLL
|
||||||
|
|||||||
Reference in New Issue
Block a user