private void LateUpdate()
        {
            var minDist = CelestialBodyUtils.GetThirdPowerRootSafe((float)_celestialBody.Mass) * 0.8f;

            DrawVelocity(minDist);
            DrawCircle(minDist);
        }
        void DrawOrbitInEditorFor(CelestialBody body)
        {
            int pointsCount = _simControl.sceneElementsDisplayParameters.orbitPointsCount;

            if (body.isActiveAndEnabled)
            {
                if (!Application.isPlaying && body.attractor != null && body.orbitData.isDirty)
                {
                    if (body.attractor.mass <= 0)
                    {
                        body.attractor.mass = 1e-007;                        //to avoid div by zero
                    }
                    body.CalculateNewOrbitData();
                }
                Handles.color = Color.white;
                var points = body.GetOrbitPointsDouble(pointsCount, false, _simControl.sceneElementsDisplayParameters.maxOrbitDistance);
                for (int i = 1; i < points.Length; i++)
                {
                    Handles.DrawLine((Vector3)points[i - 1], (Vector3)points[i]);
                }
                if (_simControl.sceneElementsDisplayParameters.drawOrbitsEclipticProjection && points.Length > 0)
                {
                    var point1 = points[0] - _simControl.eclipticNormal * CelestialBodyUtils.DotProduct(points[0], _simControl.eclipticNormal);
                    var point2 = Vector3d.zero;
                    Handles.color = Color.gray;
                    for (int i = 1; i < points.Length; i++)
                    {
                        point2 = points[i] - _simControl.eclipticNormal * CelestialBodyUtils.DotProduct(points[i], _simControl.eclipticNormal);
                        Handles.DrawLine((Vector3)point1, (Vector3)point2);
                        point1 = point2;
                    }
                }
            }
        }
 private void DrawCircle(float radius)
 {
     if (radius > MinimalRadius)
     {
         _circleLine.enabled    = true;
         _circleLine.startWidth = CircleWidth;
         _circleLine.endWidth   = CircleWidth;
         Vector3 axysX;
         Vector3 axysY;
         if (_celestialBody.AttractorRef != null && _celestialBody.OrbitData.IsValidOrbit)
         {
             axysX = (Vector3)_celestialBody.OrbitData.SemiMinorAxisBasis;
             axysY = (Vector3)_celestialBody.OrbitData.SemiMajorAxisBasis;
         }
         else
         {
             axysX = _celestialBody.Velocity.sqrMagnitude > 0 ? (Vector3)_celestialBody.Velocity.normalized : (Vector3)_celestialBody.SimControlRef.EclipticUp;
             axysY = (Vector3)CelestialBodyUtils.CrossProduct(axysX, (Vector3)_celestialBody.SimControlRef.EclipticNormal);
         }
         _circleLine.positionCount = CirclePointsCount;
         for (int i = 0; i < CirclePointsCount; i++)
         {
             float angle         = i * (2f * Mathf.PI / CirclePointsCount);
             var   pointPosition = transform.position + axysX * Mathf.Sin(angle) * radius + axysY * Mathf.Cos(angle) * radius;
             _circleLine.SetPosition(i, pointPosition);
         }
     }
     else
     {
         _circleLine.enabled = false;
     }
 }
        /// <summary>
        /// Draw two crossing lines in scene view
        /// </summary>
        static void DrawX(Vector3 pos, float size, Color col, Vector3 normal, Vector3 up)
        {
            Handles.color = col;
            Vector3 right = CelestialBodyUtils.CrossProduct(up, normal).normalized;

            Handles.DrawLine(pos + up * size, pos - up * size);
            Handles.DrawLine(pos + right * size, pos - right * size);
        }
 private Vector3 GetVelocityPoint()
 {
     if (CelestialBodyRef != null)
     {
         var v       = (Vector3)CelestialBodyRef.Velocity;
         var minDist = CelestialBodyUtils.GetThirdPowerRootSafe((float)CelestialBodyRef.Mass);
         return(v.normalized * (minDist + v.magnitude));
     }
     return(transform.localPosition);
 }
        void DrawInclinationMarkForBody(CelestialBody body, float scale)
        {
            var norm = CelestialBodyUtils.CrossProduct((Vector3)body.orbitData.orbitNormal, (Vector3)_simControl.eclipticNormal);

            Handles.color = Color.white;
            var p = CelestialBodyUtils.CrossProduct(norm, (Vector3)_simControl.eclipticNormal).normalized;

            Handles.DrawLine((Vector3)body.orbitFocusPoint, (Vector3)body.orbitFocusPoint + p * 3f * scale);
            Handles.DrawLine((Vector3)body.orbitFocusPoint, (Vector3)body.orbitFocusPoint + CelestialBodyUtils.RotateVectorByAngle(p, (float)body.orbitData.inclination, -norm.normalized) * 3f * scale);
            Handles.DrawWireArc((Vector3)body.orbitFocusPoint, -norm, p, (float)(body.orbitData.inclination * Mathd.Rad2Deg), 1f * scale);
            DrawLabelScaled((Vector3)body.orbitFocusPoint + p * scale, (body.orbitData.inclination * Mathd.Rad2Deg).ToString("0") + "\u00B0", Color.white, 10);
        }
        Vector3 GetWorldRaycastPos(Vector2 screenPos)
        {
            var ray = cam.ScreenPointToRay(screenPos);

            if (isShiftDown)
            {
                var normal = new Vector3(-ray.direction.x, 0, -ray.direction.z);
                var hitPos = CelestialBodyUtils.GetRayPlaneIntersectionPoint(worldPosOnXZPlane, normal, ray.origin, ray.direction);
                return(new Vector3(worldPosOnXZPlane.x, hitPos.y, worldPosOnXZPlane.z));
            }
            else
            {
                return(CelestialBodyUtils.GetRayPlaneIntersectionPoint(Vector3.zero, Vector3.up, ray.origin, ray.direction));
            }
        }
        private float GetCurrentScale(float Mass)
        {
            switch (ScaleType)
            {
            case ScaleFunctionType.SqrPow2:
                if (Mass < 0)
                {
                    Mass = 0;
                }
                return(Mathf.Sqrt(Mass) * ScaleMultiplier);

            case ScaleFunctionType.SqrPow3:
                return(CelestialBodyUtils.GetThirdPowerRootSafe(Mass) * ScaleMultiplier);
            }
            return(ScaleMultiplier);
        }
        /// <summary>
        /// Draw simple arrow in scene window at given world coordinates
        /// </summary>
        void DrawArrow(Vector3 from, Vector3 to, Color col, Vector3 normal)
        {
            var   dir        = to - from;
            float dist       = dir.magnitude;
            var   dirNorm    = dir / dist;        //normalized vector
            float headSize   = dist / 6f;
            var   _colBefore = Handles.color;

            Handles.color = col;
            Vector3 sideNormal = CelestialBodyUtils.CrossProduct(dir, normal).normalized;

            Handles.DrawLine(from, from + dirNorm * (dist - headSize));
            Handles.DrawLine(from + dirNorm * (dist - headSize) + sideNormal * headSize / 2f, from + dirNorm * (dist - headSize) - sideNormal * headSize / 2f);
            Handles.DrawLine(from + dirNorm * (dist - headSize) + sideNormal * headSize / 2f, from + dir);
            Handles.DrawLine(from + dirNorm * (dist - headSize) - sideNormal * headSize / 2f, from + dir);
            Handles.color = _colBefore;
        }
 private void OnPointerInput(Vector2 pointerScreenPosition, Vector2 lastPointerPosition, int buttonIndex)
 {
     if (_currentTarget != null)
     {
         if (_currentTarget.CelestialBodyRef != null)
         {
             var     ray         = Camera.main.ScreenPointToRay(pointerScreenPosition);
             Vector3 orbitNormal = _currentTarget.CelestialBodyRef.GetVelocityPlaneNormal();
             var     currentRayPlanarHitPoint = CelestialBodyUtils.GetRayPlaneIntersectionPoint(_currentTarget.transform.position, orbitNormal, ray.origin, ray.direction);
             if (!float.IsNaN(currentRayPlanarHitPoint.x) && !float.IsInfinity(currentRayPlanarHitPoint.x))
             {
                 var lastRay = Camera.main.ScreenPointToRay(lastPointerPosition);
                 var lastRayPlanarHitPoint = CelestialBodyUtils.GetRayPlaneIntersectionPoint(_currentTarget.transform.position, orbitNormal, lastRay.origin, lastRay.direction);
                 if (!float.IsNaN(currentRayPlanarHitPoint.x) && !float.IsInfinity(currentRayPlanarHitPoint.x))
                 {
                     var delta = currentRayPlanarHitPoint - lastRayPlanarHitPoint;
                     _currentTarget.transform.position += delta;
                 }
             }
         }
     }
 }
        /// <summary>
        /// Process mouse drag and hover events and draw velocity vectors if enabled
        /// </summary>
        void ProcessVelocityArrows()
        {
            if (!_simControl.sceneElementsDisplayParameters.drawVelocityVectors)
            {
                return;
            }
            Vector3d velocity = new Vector3d();
            Vector3  hpos     = new Vector3();
            Vector3  pos      = new Vector3();

            for (int i = 0; i < _bodies.Length; i++)
            {
                if (_bodies[i].isActiveAndEnabled)
                {
                    velocity = _simControl.sceneElementsDisplayParameters.editGlobalVelocity ?
                               _bodies[i].velocity :
                               _bodies[i].relativeVelocity;
                    pos = (Vector3)(_bodies[i].position + velocity * _simControl.sceneElementsDisplayParameters.velocitiesArrowsScale);
                    Handles.DrawCapFunction capFunc;
                    switch (_simControl.sceneElementsDisplayParameters.velocityHandlerType)
                    {
                    case VelocityHandlerType.Circle:
                        capFunc = Handles.CircleCap;
                        break;

                    case VelocityHandlerType.Sphere:
                        capFunc = Handles.SphereCap;
                        break;

                    case VelocityHandlerType.Dot:
                        capFunc = Handles.DotCap;
                        break;

                    default:
                        continue;
                    }
                    Handles.color = Color.white;
                    hpos          = Handles.FreeMoveHandle(pos, Quaternion.identity, _simControl.sceneElementsDisplayParameters.handleScale * HandleUtility.GetHandleSize(pos), Vector3.zero, capFunc);
                    if (pos != hpos)
                    {
                        //===== Project onto orbit plane
                        if (_bodies[i].attractor != null && !_simControl.sceneElementsDisplayParameters.editGlobalVelocity && (_simControl.sceneElementsDisplayParameters.keepOrbitPlaneWhileChangeVelocity || _simControl.keepBodiesOnEclipticPlane))
                        {
                            Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
                            hpos = CelestialBodyUtils.GetRayPlaneIntersectionPoint((Vector3)_bodies[i].position, (Vector3)_bodies[i].orbitData.orbitNormal, ray.origin, ray.direction);
                        }
                        //=====
                        velocity = (new Vector3d(hpos) - _bodies[i].position) / _simControl.sceneElementsDisplayParameters.velocitiesArrowsScale;
                        Undo.RecordObject(_bodies[i], "Velocity change");
                        if (_simControl.sceneElementsDisplayParameters.editGlobalVelocity)
                        {
                            _bodies[i].velocity = velocity;
                        }
                        else
                        {
                            _bodies[i].relativeVelocity = velocity;
                        }
                        _bodies[i].orbitData.isDirty = true;
                        if (_simControl.sceneElementsDisplayParameters.selectBodyWhenDraggingVelocity)
                        {
                            Selection.activeGameObject = _bodies[i].gameObject;
                        }
                    }
                }
            }
            ShowAllVelocitiesVectors();
        }
        void DrawOrbitElementsAndLabels()
        {
            var prms = _simControl.sceneElementsDisplayParameters;

            for (int i = 0; i < _bodies.Length; i++)
            {
                if (_bodies[i].isValidOrbit)
                {
                    if (prms.drawPeriapsisPoint)
                    {
                        //===== Periapsis
                        DrawX((Vector3)_bodies[i].orbitPeriapsisPoint, prms.circlesScale, Color.green, (Vector3)_bodies[i].orbitData.orbitNormal, (Vector3)_bodies[i].orbitData.semiMajorAxisBasis);
                    }
                    if (prms.drawPeriapsisLabel)
                    {
                        DrawLabelScaled((Vector3)_bodies[i].orbitPeriapsisPoint, "P", Color.white, 10f);
                    }
                    if (prms.drawApoapsisPoint || prms.drawApoapsisLabel)
                    {
                        //===== Apoapsis
                        if (!double.IsInfinity(_bodies[i].orbitApoapsisPoint.x) && !double.IsNaN(_bodies[i].orbitApoapsisPoint.x))
                        {
                            if (prms.drawApoapsisPoint)
                            {
                                DrawX((Vector3)_bodies[i].orbitApoapsisPoint, prms.circlesScale, Color.green, (Vector3)_bodies[i].orbitData.orbitNormal, (Vector3)_bodies[i].orbitData.semiMajorAxisBasis);
                            }
                            if (prms.drawApoapsisLabel)
                            {
                                DrawLabelScaled((Vector3)_bodies[i].orbitApoapsisPoint, "A", Color.white, 10f);
                            }
                        }
                    }
                    if (prms.drawCenterOfMassPoint)
                    {
                        //===== Center of mass
                        Handles.color = Color.white;
                        Handles.DrawWireDisc((Vector3)_bodies[i].centerOfMass, (Vector3)_bodies[i].orbitData.orbitNormal, 1f);
                    }
                    Vector3 asc;
                    if ((prms.drawAscendingNodeLabel || prms.drawAscendingNodeLine || prms.drawAscendingNodePoint) && _bodies[i].GetAscendingNode(out asc))
                    {
                        //===== Ascending node
                        asc = asc + (Vector3)_bodies[i].attractor.position;
                        if (prms.drawAscendingNodePoint)
                        {
                            DrawX(asc, prms.circlesScale, Color.blue, (Vector3)_bodies[i].orbitData.orbitNormal, (Vector3)_bodies[i].orbitData.semiMajorAxisBasis);
                        }
                        if (prms.drawAscendingNodeLine)
                        {
                            Handles.color = new Color(0.1f, 0.3f, 0.8f, 0.8f);
                            Handles.DrawLine((Vector3)_bodies[i].attractor.position, asc);
                        }
                        if (prms.drawAscendingNodeLabel)
                        {
                            DrawLabelScaled(asc, "ASC", Color.white, 10f);
                        }
                    }
                    Vector3 desc;
                    if ((prms.drawDescendingNodeLabel || prms.drawDescendingNodeLine || prms.drawDescendingNodePoint) && _bodies[i].GetDescendingNode(out desc))
                    {
                        //===== Descending node
                        desc = desc + (Vector3)_bodies[i].attractor.position;
                        if (prms.drawDescendingNodePoint)
                        {
                            DrawX(desc, prms.circlesScale, Color.blue, (Vector3)_bodies[i].orbitData.orbitNormal, (Vector3)_bodies[i].orbitData.semiMajorAxisBasis);
                        }
                        if (prms.drawDescendingNodeLine)
                        {
                            Handles.color = new Color(0.8f, 0.3f, 0.1f, 0.8f);
                            Handles.DrawLine((Vector3)_bodies[i].attractor.position, desc);
                        }
                        if (prms.drawDescendingNodeLabel)
                        {
                            DrawLabelScaled(desc, "DESC", Color.white, 10f);
                        }
                    }
                    if (prms.drawInclinationLabel)
                    {
                        //===== Inclination
                        DrawInclinationMarkForBody(_bodies[i], prms.normalAxisScale);
                    }
                    if (prms.drawRadiusVector)
                    {
                        //===== Radius vector
                        Handles.color = Color.gray;
                        Handles.DrawLine((Vector3)_bodies[i].attractor.position, (Vector3)_bodies[i].position);
                    }
                    if (prms.drawOrbitsNormal)
                    {
                        //===== Orbit normal
                        Handles.color = new Color(0.16f, 0.92f, 0.88f, 0.8f);
                        Handles.DrawLine((Vector3)_bodies[i].orbitCenterPoint, (Vector3)_bodies[i].orbitCenterPoint + (Vector3)_bodies[i].orbitData.orbitNormal * prms.normalAxisScale * 5f);
                        Handles.DrawWireDisc((Vector3)_bodies[i].orbitCenterPoint, (Vector3)_bodies[i].orbitData.orbitNormal, prms.normalAxisScale * 2f);
                    }
                    if (prms.drawSemiAxis)
                    {
                        //===== SemiMinor axis normal
                        Handles.color = Color.blue;
                        Handles.DrawLine((Vector3)_bodies[i].orbitCenterPoint, (Vector3)_bodies[i].orbitCenterPoint + (Vector3)_bodies[i].orbitData.semiMinorAxisBasis * prms.normalAxisScale * 5f);
                        //===== SemiMajor axis normal
                        Handles.color = Color.red;
                        Handles.DrawLine((Vector3)_bodies[i].orbitCenterPoint, (Vector3)_bodies[i].orbitCenterPoint + (Vector3)_bodies[i].orbitData.semiMajorAxisBasis * prms.normalAxisScale * 5f);
                    }
                }                //if valid orbit


                if (_simControl.sceneElementsDisplayParameters.drawBodiesEclipticProjection)
                {
                    Handles.color = Color.yellow;
                    var ProjectionPos = _bodies[i].position - _simControl.eclipticNormal * CelestialBodyUtils.DotProduct(_bodies[i].position, _simControl.eclipticNormal);
                    if ((ProjectionPos - _bodies[i].position).sqrMagnitude > 1e-003d)
                    {
                        Handles.DrawDottedLine((Vector3)_bodies[i].position, (Vector3)ProjectionPos, 2f);
                        Handles.DrawWireDisc((Vector3)ProjectionPos, (Vector3)_simControl.eclipticNormal, _simControl.sceneElementsDisplayParameters.circlesScale);
                    }
                }
            }             //for _bodies
        }