mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Allow setting CV routes in the new UI.
This is a pretty janky system until we get add context menu support. For now the destination is set by dragging the CV marker and cleared by right clicking the destination marker. Once we have a context menu a context action will begin setting the destination the way it did in the old UI, and the destination marker will be draggable.
This commit is contained in:
parent
4a096cb728
commit
31fa2d866f
@ -16,6 +16,7 @@ from game.theater import (
|
|||||||
ControlPoint,
|
ControlPoint,
|
||||||
TheaterGroundObject,
|
TheaterGroundObject,
|
||||||
FrontLine,
|
FrontLine,
|
||||||
|
LatLon,
|
||||||
)
|
)
|
||||||
from game.utils import meters, nautical_miles
|
from game.utils import meters, nautical_miles
|
||||||
from gen.ato import AirTaskingOrder
|
from gen.ato import AirTaskingOrder
|
||||||
@ -57,6 +58,8 @@ class ControlPointJs(QObject):
|
|||||||
nameChanged = Signal()
|
nameChanged = Signal()
|
||||||
blueChanged = Signal()
|
blueChanged = Signal()
|
||||||
positionChanged = Signal()
|
positionChanged = Signal()
|
||||||
|
mobileChanged = Signal()
|
||||||
|
destinationChanged = Signal(list)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -83,6 +86,42 @@ class ControlPointJs(QObject):
|
|||||||
ll = self.theater.point_to_ll(self.control_point.position)
|
ll = self.theater.point_to_ll(self.control_point.position)
|
||||||
return [ll.latitude, ll.longitude]
|
return [ll.latitude, ll.longitude]
|
||||||
|
|
||||||
|
@Property(bool, notify=mobileChanged)
|
||||||
|
def mobile(self) -> bool:
|
||||||
|
return self.control_point.moveable and self.control_point.captured
|
||||||
|
|
||||||
|
@Property(list, notify=destinationChanged)
|
||||||
|
def destination(self) -> LeafletLatLon:
|
||||||
|
if self.control_point.target_position is None:
|
||||||
|
# Qt seems to convert None to [] for list Properties :(
|
||||||
|
return []
|
||||||
|
return self.theater.point_to_ll(self.control_point.target_position).as_list()
|
||||||
|
|
||||||
|
@Slot(list, result=str)
|
||||||
|
def setDestination(self, destination: LeafletLatLon) -> str:
|
||||||
|
if not self.control_point.moveable:
|
||||||
|
return f"{self.control_point} is not mobile"
|
||||||
|
if not self.control_point.captured:
|
||||||
|
return f"{self.control_point} is not owned by player"
|
||||||
|
point = self.theater.ll_to_point(LatLon(*destination))
|
||||||
|
from qt_ui.widgets.map.QLiberationMap import MAX_SHIP_DISTANCE
|
||||||
|
|
||||||
|
move_distance = meters(point.distance_to_point(self.control_point.position))
|
||||||
|
if move_distance > MAX_SHIP_DISTANCE:
|
||||||
|
return (
|
||||||
|
f"Cannot move {self.control_point} more than "
|
||||||
|
f"{MAX_SHIP_DISTANCE.nautical_miles}nm. Attempted "
|
||||||
|
f"{move_distance.nautical_miles}nm"
|
||||||
|
)
|
||||||
|
self.control_point.target_position = point
|
||||||
|
self.destinationChanged.emit(destination)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
@Slot()
|
||||||
|
def cancelTravel(self) -> None:
|
||||||
|
self.control_point.target_position = None
|
||||||
|
self.destinationChanged.emit([])
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
def showInfoDialog(self) -> None:
|
def showInfoDialog(self) -> None:
|
||||||
if self.dialog is None:
|
if self.dialog is None:
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
* - Culling
|
* - Culling
|
||||||
* - Threat zones
|
* - Threat zones
|
||||||
* - Navmeshes
|
* - Navmeshes
|
||||||
* - CV waypoints
|
|
||||||
* - Time of day/weather themeing
|
* - Time of day/weather themeing
|
||||||
* - Exclusion zones
|
* - Exclusion zones
|
||||||
* - Supply route status
|
* - Supply route status
|
||||||
@ -122,24 +121,119 @@ function iconFor(player) {
|
|||||||
|
|
||||||
const SHOW_BASE_NAME_AT_ZOOM = 8;
|
const SHOW_BASE_NAME_AT_ZOOM = 8;
|
||||||
|
|
||||||
function drawControlPoints() {
|
class ControlPoint {
|
||||||
controlPointsLayer.clearLayers();
|
constructor(cp) {
|
||||||
const zoom = map.getZoom();
|
this.cp = cp;
|
||||||
game.controlPoints.forEach((cp) => {
|
this.locationMarker = this.makeLocationMarker();
|
||||||
|
this.destinationMarker = this.makeDestinationMarker();
|
||||||
|
this.path = this.makePath();
|
||||||
|
this.cp.destinationChanged.connect(() => this.onDestinationChanged());
|
||||||
|
}
|
||||||
|
|
||||||
|
hasDestination() {
|
||||||
|
return this.cp.destination.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetLocationMarker() {
|
||||||
|
// It seems that moving this without removing/adding it to the layer does
|
||||||
|
// nothing.
|
||||||
|
this.locationMarker
|
||||||
|
.removeFrom(controlPointsLayer)
|
||||||
|
.setLatLng(this.cp.position)
|
||||||
|
.addTo(controlPointsLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideDestination() {
|
||||||
|
this.destinationMarker.removeFrom(controlPointsLayer);
|
||||||
|
this.path.removeFrom(controlPointsLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
setDestination(destination) {
|
||||||
|
this.cp.setDestination([destination.lat, destination.lng]).then((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(`Could not set control point destination: ${err}`);
|
||||||
|
}
|
||||||
|
// No need to update destination positions. The backend will emit an event
|
||||||
|
// that causes that if we've successfully changed the destination. If it
|
||||||
|
// was not successful, we've already reset the origin so no need for a
|
||||||
|
//change.
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
makeLocationMarker() {
|
||||||
// We might draw other markers on top of the CP. The tooltips from the other
|
// We might draw other markers on top of the CP. The tooltips from the other
|
||||||
// markers are helpful so we want to keep them, but make sure the CP is always
|
// markers are helpful so we want to keep them, but make sure the CP is
|
||||||
// the clickable thing.
|
// always the clickable thing.
|
||||||
L.marker(cp.position, { icon: iconFor(cp.blue), zIndexOffset: 1000 })
|
const zoom = map.getZoom();
|
||||||
.bindTooltip(`<h3 style="margin: 0;">${cp.name}</h3>`, {
|
return L.marker(this.cp.position, {
|
||||||
|
icon: iconFor(this.cp.blue),
|
||||||
|
zIndexOffset: 1000,
|
||||||
|
draggable: this.cp.mobile,
|
||||||
|
autoPan: true,
|
||||||
|
})
|
||||||
|
.bindTooltip(`<h3 style="margin: 0;">${this.cp.name}</h3>`, {
|
||||||
permanent: zoom >= SHOW_BASE_NAME_AT_ZOOM,
|
permanent: zoom >= SHOW_BASE_NAME_AT_ZOOM,
|
||||||
})
|
})
|
||||||
.on("click", function () {
|
.on("click", () => {
|
||||||
cp.showInfoDialog();
|
this.cp.showInfoDialog();
|
||||||
})
|
})
|
||||||
.on("contextmenu", function () {
|
.on("contextmenu", () => {
|
||||||
cp.showPackageDialog();
|
this.cp.showPackageDialog();
|
||||||
})
|
})
|
||||||
.addTo(controlPointsLayer);
|
.on("dragend", (event) => {
|
||||||
|
const marker = event.target;
|
||||||
|
const newPosition = marker.getLatLng();
|
||||||
|
this.setDestination(newPosition);
|
||||||
|
this.resetLocationMarker();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
makeDestinationMarker() {
|
||||||
|
const destination = this.hasDestination() ? this.cp.destination : [0, 0];
|
||||||
|
return L.marker(destination, {
|
||||||
|
icon: iconFor(this.cp.blue),
|
||||||
|
zIndexOffset: 1000,
|
||||||
|
})
|
||||||
|
.bindTooltip(`${this.cp.name} destination`)
|
||||||
|
.on("contextmenu", () => this.cp.cancelTravel());
|
||||||
|
}
|
||||||
|
|
||||||
|
makePath() {
|
||||||
|
const destination = this.hasDestination() ? this.cp.destination : [0, 0];
|
||||||
|
return L.polyline([this.cp.position, destination], {
|
||||||
|
color: "#80BA80",
|
||||||
|
weight: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestinationChanged() {
|
||||||
|
if (this.hasDestination()) {
|
||||||
|
this.destinationMarker.setLatLng(this.cp.destination);
|
||||||
|
this.destinationMarker.addTo(controlPointsLayer);
|
||||||
|
this.path.setLatLngs([this.cp.position, this.cp.destination]);
|
||||||
|
this.path.addTo(controlPointsLayer);
|
||||||
|
} else {
|
||||||
|
this.hideDestination();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawDestination() {
|
||||||
|
this.destinationMarker.addTo(controlPointsLayer);
|
||||||
|
this.path.addTo(controlPointsLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
this.locationMarker.addTo(controlPointsLayer);
|
||||||
|
if (this.hasDestination()) {
|
||||||
|
this.drawDestination();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawControlPoints() {
|
||||||
|
controlPointsLayer.clearLayers();
|
||||||
|
game.controlPoints.forEach((cp) => {
|
||||||
|
new ControlPoint(cp).draw();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user