@@ -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