Skip to content

Commit c41b414

Browse files
committed
Position off screen markers better
1 parent e1ea5ff commit c41b414

File tree

2 files changed

+66
-24
lines changed

2 files changed

+66
-24
lines changed

GameData/PlanningNode/PlanningNode-Changelog.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ KERBALCHANGELOG
3030
change = Zoom in when switching SOI
3131
type = Change
3232
}
33+
CHANGE
34+
{
35+
change = Better off screen marker positioning
36+
type = Fix
37+
}
3338
}
3439
VERSION
3540
{

Source/PlanningNodeMarker.cs

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -68,39 +68,63 @@ public void MoveTo(CelestialBody parent, Vessel vessel, Vector3 direction)
6868
private void OnGUI()
6969
{
7070
if (myNode != null && textWhere != null) {
71-
var screenWhere = PlanetariumCamera.Camera.WorldToScreenPoint(
72-
ScaledSpace.LocalToScaledSpace(textWhere));
73-
74-
if (screenWhere.z > 0
75-
&& screenWhere.x >= 0 && screenWhere.x <= Screen.width
76-
&& screenWhere.y >= 0 && screenWhere.y <= Screen.height) {
77-
// In front of camera, so draw
78-
79-
var camDist = cameraDist(textWhere);
80-
if (0 < camDist && camDist < ringScale) {
81-
var offset = 0.6f * ringScale / camDist + 10;
82-
71+
var camDist = cameraDist(textWhere);
72+
if (0 < camDist && camDist < ringScale) {
73+
var screenWhere = PlanetariumCamera.Camera.WorldToScreenPoint(
74+
ScaledSpace.LocalToScaledSpace(textWhere))
75+
+ (0.6f * ringScale / camDist + 10) * Vector3.down;
76+
77+
if (screenWhere.z > 0 && viewport.Contains(screenWhere)) {
78+
// In front of camera, so draw button
8379
labelStyle.normal.textColor = myNode.color;
8480
if (GUI.Button(
85-
new Rect(screenWhere.x - 50, Screen.height - screenWhere.y + offset, 100, 30),
81+
new Rect(
82+
screenWhere.x - halfTextWidth,
83+
Screen.height - screenWhere.y,
84+
textWidth, 30),
8685
myNode.GetCaption(vessel),
8786
labelStyle
8887
)) {
8988
EditMe?.Invoke(myNode);
9089
}
90+
} else {
91+
// Off edge of screen or behind camera, draw marker at edge of screen
92+
labelStyle.normal.textColor = new Color(
93+
myNode.color.r, myNode.color.g, myNode.color.b, 0.6f);
94+
var edgePos = edgePosition((screenWhere.z < 0 ? -1f : 1f)
95+
* ((Vector2)screenWhere - screenCenterOffset));
96+
GUI.Label(
97+
new Rect(edgePos.x - halfTextWidth, edgePos.y, textWidth, 30),
98+
myNode.GetCaption(vessel),
99+
labelStyle
100+
);
91101
}
92-
} else {
93-
Vector2 edgePos = (screenWhere.z < 0 ? -1f : 1f) * screenRadius * (
94-
new Vector2(screenWhere.x - Screen.width / 2, Screen.height / 2 - screenWhere.y).normalized
102+
}
103+
}
104+
}
105+
106+
private Vector2 edgePosition(Vector2 fromCenter)
107+
{
108+
if (fromCenter.x == 0) {
109+
// Infinite slope, handle specially
110+
return new Vector2(screenCenterOffset.x,
111+
fromCenter.y > 0 ? viewport.yMin : viewport.yMax);
112+
} else {
113+
// Safe to divide by x
114+
float slope = fromCenter.y / fromCenter.x;
115+
if (slope > viewportSlope || slope < -viewportSlope) {
116+
// Top / bottom
117+
return new Vector2(
118+
Mathf.Clamp(screenCenterOffset.x + fromCenter.y / slope,
119+
viewport.xMin, viewport.xMax),
120+
fromCenter.y > 0 ? viewport.yMin : viewport.yMax
95121
);
96-
GUI.Label(
97-
new Rect(
98-
Mathf.Clamp(Screen.width / 2 + edgePos.x, 50, Screen.width - 100),
99-
Mathf.Clamp(Screen.height / 2 + edgePos.y, 50, Screen.height - 50),
100-
100, 30
101-
),
102-
myNode.GetCaption(vessel),
103-
labelStyle
122+
} else {
123+
// Left / right
124+
return new Vector2(
125+
fromCenter.x < 0 ? viewport.xMin : viewport.xMax,
126+
Mathf.Clamp(screenCenterOffset.y - slope * fromCenter.x,
127+
viewport.yMin, viewport.yMax)
104128
);
105129
}
106130
}
@@ -167,11 +191,24 @@ private float cameraDist(Vector3d pos)
167191
);
168192
}
169193

194+
// Markers must be within this area to be interactable,
195+
// otherwise they'll be clipped to its edges
196+
private static readonly Rect viewport = new Rect(
197+
50, 50, Screen.width - 100, Screen.height - 100);
198+
199+
private static readonly float viewportSlope = viewport.height / viewport.width;
200+
201+
private static readonly Vector2 screenCenterOffset = 0.5f * new Vector2(
202+
Screen.width, Screen.height);
203+
170204
// Scale the markers to the size of their containing SOI
171205
private float ringScale => 0.006f * (float)(myNode?.origin?.sphereOfInfluence ?? 84000000);
172206

173207
private readonly float screenRadius = 0.5f * Mathf.Sqrt(Screen.width * Screen.width + Screen.height * Screen.height);
174208

209+
private const float textWidth = 100f;
210+
private const float halfTextWidth = 0.5f * textWidth;
211+
175212
private Vessel vessel;
176213
private Vector3d where;
177214
private Vector3d textWhere;

0 commit comments

Comments
 (0)