Skip to content

Commit

Permalink
Handling of nodes in the C#.
Browse files Browse the repository at this point in the history
  • Loading branch information
pleroy committed Aug 17, 2024
1 parent 2bf414f commit 7dce603
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 57 deletions.
9 changes: 9 additions & 0 deletions ksp_plugin_adapter/disposable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ namespace principia {
namespace ksp_plugin_adapter {

static class DisposableIteratorExtensions {
public static IEnumerable<Node> Nodes(
this DisposableIterator nodes_iterator) {
for (;
!nodes_iterator.IteratorAtEnd();
nodes_iterator.IteratorIncrement()) {
yield return nodes_iterator.IteratorGetNode();
}
}

public static IEnumerable<TQP> DiscreteTrajectoryPoints(
this DisposableIterator apsis_iterator) {
for (;
Expand Down
32 changes: 16 additions & 16 deletions ksp_plugin_adapter/ksp_plugin_adapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2479,14 +2479,14 @@ out DisposableIterator
sun_world_position,
MapNodePool.MaxNodesPerProvenance,
out DisposableIterator approaches_iterator);
map_node_pool_.RenderMarkers(
ascending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
ascending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.Prediction,
MapObject.ObjectType.AscendingNode),
plotting_frame_selector_);
map_node_pool_.RenderMarkers(
descending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
descending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.Prediction,
MapObject.ObjectType.DescendingNode),
Expand Down Expand Up @@ -2531,14 +2531,14 @@ out DisposableIterator
ascending_nodes_iterator,
out DisposableIterator
descending_nodes_iterator);
map_node_pool_.RenderMarkers(
ascending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
ascending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.Prediction,
MapObject.ObjectType.AscendingNode),
plotting_frame_selector_);
map_node_pool_.RenderMarkers(
descending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
descending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.Prediction,
MapObject.ObjectType.DescendingNode),
Expand All @@ -2564,14 +2564,14 @@ out DisposableIterator
sun_world_position,
MapNodePool.MaxNodesPerProvenance,
out DisposableIterator approaches_iterator);
map_node_pool_.RenderMarkers(
ascending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
ascending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.FlightPlan,
MapObject.ObjectType.AscendingNode),
plotting_frame_selector_);
map_node_pool_.RenderMarkers(
descending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
descending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.FlightPlan,
MapObject.ObjectType.DescendingNode),
Expand Down Expand Up @@ -2616,14 +2616,14 @@ out DisposableIterator
ascending_nodes_iterator,
out DisposableIterator
descending_nodes_iterator);
map_node_pool_.RenderMarkers(
ascending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
ascending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.FlightPlan,
MapObject.ObjectType.AscendingNode),
plotting_frame_selector_);
map_node_pool_.RenderMarkers(
descending_nodes_iterator.DiscreteTrajectoryPoints(),
map_node_pool_.RenderNodes(
descending_nodes_iterator.Nodes(),
new MapNodePool.Provenance(vessel_guid,
MapNodePool.NodeSource.FlightPlan,
MapObject.ObjectType.DescendingNode),
Expand Down
3 changes: 2 additions & 1 deletion ksp_plugin_adapter/localization/en-us.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ Localization {
#Principia_MapNode_AscendingNode = Ascending Node
#Principia_MapNode_DescendingNode = Descending Node
#Principia_MapNode_NodeHeader = <<1>> <<2>>:\n<<3>> // <<1>>: source; <<2>>: node_name; <<3>>: plane.
#Principia_MapNode_NodeCaptionLine2 = <<1>> m/s // <<1>>: properties.velocity.z.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithoutAngle = <<1>> m/s // <<1>>: payload.node.out_of_plane_velocity.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithAngle = <<1>> m/s\n<<2>>° // <<1>>: payload.node.out_of_plane_velocity.FormatN(0), <<2>>: payload.node.apparent_inclination_in_degrees.FormatN(0)
#Principia_MapNode_ApproachHeader = <<1>> Target Approach: <<2>> m // <<1>>: source, <<2>>: separation.FormatN(0).
#Principia_MapNode_ApproachCaptionLine2 = <<1>> m/s // <<1>>: speed.FormatN(0).
#Principia_MapNode_ImpactHeader = <<3>> <<1>> Impact:\n<<4>> m
Expand Down
3 changes: 2 additions & 1 deletion ksp_plugin_adapter/localization/fr-fr.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ Localization {
#Principia_MapNode_AscendingNode = Nœud ascendant
#Principia_MapNode_DescendingNode = Nœud descendant
#Principia_MapNode_NodeHeader = <<2>> <<1>> :\n<<3>> // <<1>>: source; <<2>>: node_name; <<3>>: plane.
#Principia_MapNode_NodeCaptionLine2 = <<1>> m/s // <<1>>: properties.velocity.z.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithoutAngle = <<1>> m/s // <<1>>: payload.node.out_of_plane_velocity.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithAngle = <<1>> m/s\n<<2>>° // <<1>>: payload.node.out_of_plane_velocity.FormatN(0), <<2>>: payload.node.apparent_inclination_in_degrees.FormatN(0)
#Principia_MapNode_ApproachHeader = Rapprochement <<1>> à la cible : <<2>> m // <<1>>: source, <<2>>: separation.FormatN(0).
#Principia_MapNode_ApproachCaptionLine2 = <<1>> m/s // <<1>>: speed.FormatN(0).
#Principia_MapNode_ImpactHeader = Impact <<3>> :\n<<4>> m sur <<A:1>>
Expand Down
3 changes: 2 additions & 1 deletion ksp_plugin_adapter/localization/ru.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ Localization {
#Principia_MapNode_AscendingNode = восходящий узел^m
#Principia_MapNode_DescendingNode = нисходящий узел^m
#Principia_MapNode_NodeHeader = <<C:<<X:1>> <<X:2>>>>:\n<<3>> // <<1>>: source; <<2>>: node_name; <<3>>: plane.
#Principia_MapNode_NodeCaptionLine2 = <<1>> м/с // <<1>>: properties.velocity.z.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithoutAngle = <<1>> м/с // <<1>>: payload.node.out_of_plane_velocity.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithAngle = <<1>> м/с\n<<2>>° // <<1>>: payload.node.out_of_plane_velocity.FormatN(0), <<2>>: payload.node.apparent_inclination_in_degrees.FormatN(0)
#Principia_MapNode_ApproachHeader = <<C:<<X:1>> приближение^n>> к цели: <<2>> м // <<1>>: source, <<2>>: separation.FormatN(0).
#Principia_MapNode_ApproachCaptionLine2 = <<1>> м/с // <<1>>: speed.FormatN(0).
#Principia_MapNode_ImpactHeader = <<C:<<X:3>> столкновение^n>> с <<gen:1>>:\n<<4>> м
Expand Down
3 changes: 2 additions & 1 deletion ksp_plugin_adapter/localization/zh-cn.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,8 @@ Localization {
#Principia_MapNode_AscendingNode = 升交点
#Principia_MapNode_DescendingNode = 降交点
#Principia_MapNode_NodeHeader = <<1>><<2>>:\n<<3>> // <<1>>: source; <<2>>: node_name; <<3>>: plane.
#Principia_MapNode_NodeCaptionLine2 = <<1>> m/s // <<1>>: properties.velocity.z.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithoutAngle = <<1>> m/s // <<1>>: payload.node.out_of_plane_velocity.FormatN(0)
#Principia_MapNode_NodeCaptionLine2WithAngle = <<1>> m/s\n<<2>>° // <<1>>: payload.node.out_of_plane_velocity.FormatN(0), <<2>>: payload.node.apparent_inclination_in_degrees.FormatN(0)
#Principia_MapNode_ApproachHeader = <<1>>目标最近:<<2>> m // <<1>>: source, <<2>>: separation.FormatN(0).
#Principia_MapNode_ApproachCaptionLine2 = <<1>> m/s // <<1>>: speed.FormatN(0).
#Principia_MapNode_ImpactHeader = <<3>><<1>>撞击: \n<<4>> m
Expand Down
142 changes: 105 additions & 37 deletions ksp_plugin_adapter/map_node_pool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,74 @@ public void RenderMarkers(
IEnumerable<TQP> markers,
Provenance provenance,
ReferenceFrameSelector<PlottingFrameParameters> reference_frame) {
PrepareToRenderMarkers(provenance,
reference_frame,
out UnityEngine.Color colour,
out MapObject associated_map_object);

var pool = nodes_[provenance];
foreach (TQP marker in markers) {
MapNodeProperties node_properties = new MapNodeProperties {
visible = true,
object_type = provenance.type,
colour = colour,
reference_frame = reference_frame,
payload = new LegacyMapNodePayload {
time = marker.t,
world_position = (Vector3d)marker.qp.q,
velocity = (Vector3d)marker.qp.p
},
source = provenance.source,
associated_map_object = associated_map_object,
};

if (pool.nodes_used == pool.nodes.Count) {
pool.nodes.Add(MakePoolNode());
}
properties_[pool.nodes[pool.nodes_used++]] = node_properties;
}
}

public void RenderNodes(
IEnumerable<Node> markers,
Provenance provenance,
ReferenceFrameSelector<PlottingFrameParameters> reference_frame) {
PrepareToRenderMarkers(provenance,
reference_frame,
out UnityEngine.Color colour,
out MapObject associated_map_object);

var pool = nodes_[provenance];
foreach (Node marker in markers) {
MapNodeProperties node_properties = new MapNodeProperties {
visible = true,
object_type = provenance.type,
colour = colour,
reference_frame = reference_frame,
payload = new NodeMapNodePayload {
time = marker.time,
world_position = (Vector3d)marker.world_position,
node = marker
},
source = provenance.source,
associated_map_object = associated_map_object,
};

if (pool.nodes_used == pool.nodes.Count) {
pool.nodes.Add(MakePoolNode());
}
properties_[pool.nodes[pool.nodes_used++]] = node_properties;
}
}

private void PrepareToRenderMarkers(
Provenance provenance,
ReferenceFrameSelector<PlottingFrameParameters> reference_frame,
out UnityEngine.Color colour,
out MapObject associated_map_object) {
if (!nodes_.ContainsKey(provenance)) {
nodes_.Add(provenance, new SingleProvenancePool());
}
var pool = nodes_[provenance];
MapObject associated_map_object;
UnityEngine.Color colour;
switch (provenance.type) {
case MapObject.ObjectType.Apoapsis:
case MapObject.ObjectType.Periapsis:
Expand Down Expand Up @@ -158,25 +220,6 @@ public void RenderMarkers(
throw Log.Fatal($"Unexpected type {provenance.type}");
}
colour.a = 1;

foreach (TQP marker in markers) {
MapNodeProperties node_properties = new MapNodeProperties {
visible = true,
object_type = provenance.type,
colour = colour,
reference_frame = reference_frame,
world_position = (Vector3d)marker.qp.q,
velocity = (Vector3d)marker.qp.p,
source = provenance.source,
time = marker.t,
associated_map_object = associated_map_object,
};

if (pool.nodes_used == pool.nodes.Count) {
pool.nodes.Add(MakePoolNode());
}
properties_[pool.nodes[pool.nodes_used++]] = node_properties;
}
}

private KSP.UI.Screens.Mapview.MapNode MakePoolNode() {
Expand Down Expand Up @@ -247,9 +290,10 @@ private KSP.UI.Screens.Mapview.MapNode MakePoolNode() {
switch (properties.object_type) {
case MapObject.ObjectType.Periapsis:
case MapObject.ObjectType.Apoapsis: {
var payload = properties.payload as LegacyMapNodePayload;
CelestialBody celestial = properties.reference_frame.Centre();
Vector3d position = properties.world_position;
double speed = properties.velocity.magnitude;
Vector3d position = payload.world_position;
double speed = payload.velocity.magnitude;
caption.Header = L10N.CelestialString(
properties.object_type == MapObject.ObjectType.Periapsis
? "#Principia_MapNode_PeriapsisHeader"
Expand All @@ -273,16 +317,25 @@ private KSP.UI.Screens.Mapview.MapNode MakePoolNode() {
source,
node_name,
plane);
caption.captionLine2 = L10N.CacheFormat(
"#Principia_MapNode_NodeCaptionLine2",
properties.velocity.z.FormatN(0));
var payload = properties.payload as NodeMapNodePayload;
if (properties.reference_frame.Centre() == null) {
caption.captionLine2 = L10N.CacheFormat(
"#Principia_MapNode_NodeCaptionLine2WithoutAngle",
payload.node.out_of_plane_velocity.FormatN(0));
} else {
caption.captionLine2 = L10N.CacheFormat(
"#Principia_MapNode_NodeCaptionLine2WithAngle",
payload.node.out_of_plane_velocity.FormatN(0),
payload.node.apparent_inclination_in_degrees.FormatN(0));
}
break;
}
case MapObject.ObjectType.ApproachIntersect: {
var payload = properties.payload as LegacyMapNodePayload;
double separation =
(properties.reference_frame.target.GetWorldPos3D() -
properties.world_position).magnitude;
double speed = properties.velocity.magnitude;
payload.world_position).magnitude;
double speed = payload.velocity.magnitude;
caption.Header = L10N.CacheFormat("#Principia_MapNode_ApproachHeader",
source,
separation.FormatN(0));
Expand All @@ -292,9 +345,10 @@ private KSP.UI.Screens.Mapview.MapNode MakePoolNode() {
break;
}
case MapObject.ObjectType.PatchTransition: {
var payload = properties.payload as LegacyMapNodePayload;
CelestialBody celestial = properties.reference_frame.Centre();
Vector3d position = properties.world_position;
double speed = properties.velocity.magnitude;
Vector3d position = payload.world_position;
double speed = payload.velocity.magnitude;
caption.Header = L10N.CelestialString(
"#Principia_MapNode_ImpactHeader",
new[]{ celestial },
Expand All @@ -310,7 +364,7 @@ private KSP.UI.Screens.Mapview.MapNode MakePoolNode() {
caption.captionLine1 = "T" +
new PrincipiaTimeSpan(
Planetarium.GetUniversalTime() -
properties.time).
properties.payload.time).
Format(with_leading_zeroes: false,
with_seconds: true);
// The font used by map nodes does not support the minus sign, so we
Expand All @@ -322,23 +376,37 @@ private KSP.UI.Screens.Mapview.MapNode MakePoolNode() {
caption.captionLine3 = caption.captionLine3?.Replace(minus, "-");
};
new_node.OnUpdatePosition += (KSP.UI.Screens.Mapview.MapNode node) =>
ScaledSpace.LocalToScaledSpace(properties_[node].world_position);
ScaledSpace.LocalToScaledSpace(
properties_[node].payload.world_position);
return new_node;
}

private class MapNodeProperties {
public bool visible;
public MapObject.ObjectType object_type;
// The payload is computed by the C++ side.
private abstract class MapNodePayload {
public double time;
public Vector3d world_position;
}

// TODO(phl): Move away from legacy payloads.
private class LegacyMapNodePayload : MapNodePayload {
// Velocity in the plotting frame. Note that the handedness is
// inconsistent with World; for practical purposes only the norm or
// individual coordinates of this vector should be used here.
public Vector3d velocity;
}

private class NodeMapNodePayload : MapNodePayload {
public Node node;
}

private class MapNodeProperties {
public bool visible;
public MapObject.ObjectType object_type;
public MapNodePayload payload;
public UnityEngine.Color colour;
public MapObject associated_map_object;
public ReferenceFrameSelector<PlottingFrameParameters> reference_frame;
public NodeSource source;
public double time;
}

private IntPtr Plugin => adapter_.Plugin();
Expand Down

0 comments on commit 7dce603

Please sign in to comment.