示例#1
0
 /* PRIVATE METHODS */
 private void PackedSpin(Data.PRVessel v)
 {
     if (v.vessel.situation != Vessel.Situations.LANDED && v.vessel.situation != Vessel.Situations.SPLASHED && v.vessel.situation != Vessel.Situations.PRELAUNCH)
     {
         v.vessel.SetRotation(Quaternion.AngleAxis(v.momentum.magnitude * TimeWarp.CurrentRate, v.vessel.ReferenceTransform.rotation * v.momentum) * v.vessel.transform.rotation, true);
     }
 }
示例#2
0
        private void OnVesselGoOffRails(Vessel vessel)
        {
            Data.PRVessel v = data.FindPRVessel(vessel);
            if (vessel.situation != Vessel.Situations.LANDED && vessel.situation != Vessel.Situations.SPLASHED && vessel.situation != Vessel.Situations.PRELAUNCH)
            {
                if (v.rotationModeActive && v.storedAngularMomentum.magnitude > threshold)
                {
                    if (GetStabilityMode(vessel) != StabilityMode.AUTOPILOT)
                    {
                        ApplyMomentumDelayed(v);
                    }
                }
                else if (GetStabilityMode(vessel) != StabilityMode.ABSOLUTE)
                {
                    if (GetStabilityMode(vessel) == StabilityMode.RELATIVE && !v.momentumModeActive)
                    {
                        Quaternion shift = Quaternion.Euler(0f, Vector3.Angle(Planetarium.right, v.planetariumRight), 0f);

                        //Set relative rotation if there is a reference
                        if (v.reference != null)
                        {
                            vessel.SetRotation(FromToRotation(shift * v.direction, (v.reference.GetTransform().position - vessel.transform.position).normalized) * (shift * v.rotation), true);
                        }

                        //Reset momentumModeActive heading
                        vessel.Autopilot.SAS.lockedRotation = vessel.ReferenceTransform.rotation;
                    }
                    else
                    {
                        ApplyMomentumDelayed(v);
                    }
                }
            }
        }
示例#3
0
        private void ApplyMomentumNow(Data.PRVessel v)
        {
            Vector3d angularmomentum = v.GoingOffRailsAngularMomentum;

            Vector3d MOI = v.vessel.MOI;

            //These shouldn't happen
            if (MOI.x == 0d)
            {
                MOI.x = 0.001d;
            }
            if (MOI.y == 0d)
            {
                MOI.y = 0.001d;
            }
            if (MOI.z == 0d)
            {
                MOI.z = 0.001d;
            }

            Vector3d angularvelocity = Vector3d.zero;

            angularvelocity.x = angularmomentum.x / MOI.x;
            angularvelocity.y = angularmomentum.y / MOI.y;
            angularvelocity.z = angularmomentum.z / MOI.z;
            //Vector3d av = v.GoingOffRailsAngularMomentum;

            Vector3d   COM            = v.vessel.CoMD;
            Quaternion rotation       = v.vessel.ReferenceTransform.rotation;
            Vector3d   av_by_rotation = rotation * angularvelocity;

            //KSPLog.print(string.Format("Apply angular vel: {0}, MOI: {1}, momentum: {3}", angularvelocity, MOI, angularmomentum));

            //Applying force on every part
            foreach (Part p in v.vessel.parts)
            {
                if (!p.GetComponent <Rigidbody>())
                {
                    continue;
                }
                if (p.mass == 0f)
                {
                    continue;
                }
                Rigidbody partrigidbody = p.GetComponent <Rigidbody> ();

                //Store the Rigidbody's max angular velocity for later restoration.
                if (!RigidBodyMaxAngularVelocityPairs.ContainsKey(partrigidbody))
                {
                    RigidBodyMaxAngularVelocityPairs[partrigidbody] = new RigidBodyMaxAngularVelocitySaveData(partrigidbody.maxAngularVelocity);
                }
                RigidBodyMaxAngularVelocityPairs[partrigidbody].FrameCounter = 10;
                partrigidbody.maxAngularVelocity *= 10f;

                partrigidbody.AddTorque(av_by_rotation, ForceMode.VelocityChange);
                partrigidbody.AddForce(Vector3d.Cross(av_by_rotation, (Vector3d)p.WCoM - COM), ForceMode.VelocityChange);
            }
        }
示例#4
0
 private void ApplyMomentumDelayed(Data.PRVessel v)
 {
     //Wait a few ticks to apply these.
     //Note that if the vessel immediately went back on rails,
     //these values would be updated when it came off again and all
     //would be well.
     v.GoingOffRailsFrameCounter    = 3;
     v.GoingOffRailsAngularMomentum = v.storedAngularMomentum;
 }
示例#5
0
        private void PackedRotation(Data.PRVessel v)
        {
            Quaternion shift = Quaternion.Euler(0f, Vector3.Angle(Planetarium.right, v.planetariumRight), 0f);

            if (v.vessel.situation != Vessel.Situations.LANDED && v.vessel.situation != Vessel.Situations.SPLASHED && v.vessel.situation != Vessel.Situations.PRELAUNCH)
            {
                v.vessel.SetRotation(FromToRotation(shift * v.direction, (v.reference.GetTransform().position - v.vessel.transform.position).normalized) * (shift * v.rotation), true);
            }
        }
        private void BodyGUI(int windowID)
        {
            Data.PRVessel v = data.FindPRVessel(activeVessel);

            GUILayout.BeginVertical();
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button(close))
            {
                showBodyWindow = false;
            }
            GUILayout.EndHorizontal();
            GUILayout.Label("Select target in map \nto set as reference");
            if (GUILayout.Button("Set", GUILayout.ExpandWidth(true)))
            {
                if (activeVessel.targetObject != null)
                {
                    if (activeVessel.targetObject.GetType() == typeof(CelestialBody) || activeVessel.targetObject.GetType() == typeof(Vessel))
                    {
                        v.reference = activeVessel.targetObject;
                    }
                    v.dynamicReference = false;
                }
                else
                {
                    v.dynamicReference = false;
                    v.reference        = null;
                }
            }
            if (GUILayout.Button("Unset", GUILayout.ExpandWidth(true)))
            {
                v.reference        = null;
                v.dynamicReference = false;
            }
            GUILayout.Space(10);
            if (GUILayout.Button("Sun", GUILayout.ExpandWidth(true)))
            {
                v.reference        = Sun.Instance.sun;
                v.dynamicReference = false;
            }
            if (GUILayout.Button(activeVessel.mainBody.name, GUILayout.ExpandWidth(true)))
            {
                v.reference        = activeVessel.mainBody;
                v.dynamicReference = false;
            }
            if (GUILayout.Button("Dynamic", GUILayout.ExpandWidth(true)))
            {
                v.dynamicReference = true;
                //v.reference = v.vessel.mainBody; --> This should not be necessary!
            }

            GUILayout.EndVertical();
            GUI.DragWindow();
        }
示例#7
0
 private void AdjustSAS(Data.PRVessel v)
 {
     if (v.reference != null)
     {
         if (v.lastTransform != null && v.lastPosition != null)
         {
             Vector3d    newPosition = (Vector3d)v.lastTransform.position - v.reference.GetTransform().position;
             QuaternionD delta       = FromToRotation(v.lastPosition, newPosition);
             QuaternionD adjusted    = delta * (QuaternionD)v.vessel.Autopilot.SAS.lockedRotation;
             v.vessel.Autopilot.SAS.lockedRotation = adjusted;
         }
     }
 }
示例#8
0
        /* PRIVATE METHODS */
        private void PackedSpin(Data.PRVessel v)
        {
            Vector3 _angularVelocity = Vector3.zero;

            _angularVelocity.x = v.storedAngularMomentum.x / v.vessel.MOI.x;
            _angularVelocity.y = v.storedAngularMomentum.y / v.vessel.MOI.y;
            _angularVelocity.z = v.storedAngularMomentum.z / v.vessel.MOI.z;

            if (v.vessel.situation != Vessel.Situations.LANDED && v.vessel.situation != Vessel.Situations.SPLASHED && v.vessel.situation != Vessel.Situations.PRELAUNCH)
            {
                v.vessel.SetRotation(Quaternion.AngleAxis(_angularVelocity.magnitude * TimeWarp.CurrentRate, v.vessel.ReferenceTransform.rotation * _angularVelocity) * v.vessel.transform.rotation, true);
            }
        }
示例#9
0
        private void OnVesselWillDestroy(Vessel vessel)
        {
            Debug.Log("[PR] Deleting " + vessel.vesselName + " as reference.");

            foreach (Vessel _vessel in FlightGlobals.Vessels)
            {
                Data.PRVessel v = data.FindPRVessel(_vessel);
                if (!object.ReferenceEquals(_vessel, vessel))
                {
                    if (object.ReferenceEquals(vessel, v.reference))
                    {
                        v.reference = null;
                    }
                }
            }
        }
示例#10
0
        private void ApplyMomentum(Data.PRVessel v)
        {
            Vector3    av       = v.momentum;
            Vector3    COM      = v.vessel.CoM;
            Quaternion rotation = v.vessel.ReferenceTransform.rotation;

            //Applying force on every part
            foreach (Part p in v.vessel.parts)
            {
                if (!p.GetComponent <Rigidbody>())
                {
                    continue;
                }
                p.GetComponent <Rigidbody>().AddTorque(rotation * av, ForceMode.VelocityChange);
                p.GetComponent <Rigidbody>().AddForce(Vector3.Cross(rotation * av, (p.transform.position - COM)), ForceMode.VelocityChange);
            }
        }
示例#11
0
        private void FixedUpdate()
        {
            if (activeVessel != FlightGlobals.ActiveVessel)
            {
                activeVessel = FlightGlobals.ActiveVessel;
                Interface.instance.desiredRPMstr = data.FindPRVessel(activeVessel).desiredRPM.ToString();
            }

            foreach (Data.PRVessel v in data.PRVessels)
            {
                v.processed = false;
            }

            if (RigidBodyMaxAngularVelocityPairs.Count > 0)
            {
                List <Rigidbody> toremove = null;
                foreach (KeyValuePair <Rigidbody, RigidBodyMaxAngularVelocitySaveData> kp in RigidBodyMaxAngularVelocityPairs)
                {
                    kp.Value.FrameCounter--;
                    if (kp.Value.FrameCounter == 0)
                    {
                        try
                        {
                            kp.Key.maxAngularVelocity = kp.Value.OriginalValue;
                        }
                        catch
                        {
                        }

                        if (toremove == null)
                        {
                            toremove = new List <Rigidbody>();
                        }
                        toremove.Add(kp.Key);
                    }
                }

                if (toremove != null)
                {
                    for (int i = 0; i < toremove.Count; ++i)
                    {
                        RigidBodyMaxAngularVelocityPairs.Remove(toremove[i]);
                    }
                }
            }

            #region ### Cycle through all vessels ###
            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                Data.PRVessel v = data.FindPRVessel(vessel);

                v.processed = true;
                if (v.dynamicReference)
                {
                    if (v.reference == null || (v.reference.GetType() != typeof(CelestialBody) || v.reference.GetName() != vessel.mainBody.GetName())) //Main body mode; continuous update of reference to mainBody
                    {
                        Debug.Log("[PR] Updated the reference of " + v.vessel.vesselName + " from " + (v.reference != null ? v.reference.GetName() : "Null") + " to " + vessel.mainBody.name);
                        v.reference        = vessel.mainBody;
                        v.direction        = (v.reference.GetTransform().position - vessel.transform.position).normalized;
                        v.rotation         = vessel.transform.rotation;
                        v.planetariumRight = Planetarium.right;
                        v.lastActive       = false;
                    }
                }
                if (vessel.packed)
                {
                    #region ### PACKED ###
                    if (vessel.loaded) //is okay, rotation doesnt need to be persistent when rotating
                    {
                        var currentStabilityMode = GetStabilityMode(vessel);

                        //Debug.Log("[PR] - currentStabilityMode: " + Enum.GetName(typeof(StabilityMode), currentStabilityMode));

                        if (currentStabilityMode == StabilityMode.PROGRADE)
                        {
                            var rotation = Quaternion.FromToRotation(vessel.transform.up.normalized, vessel.obt_velocity.normalized);

                            vessel.transform.Rotate(rotation.eulerAngles, Space.World);

                            v.vessel.SetRotation(vessel.transform.rotation);
                        }
                        else if (v.storedAngularMomentum.magnitude >= threshold)
                        {
                            if (currentStabilityMode != StabilityMode.AUTOPILOT)
                            {
                                PackedSpin(v);
                            }
                        }
                        else if (currentStabilityMode != StabilityMode.ABSOLUTE)
                        {
                            if (currentStabilityMode == StabilityMode.RELATIVE && v.rotationModeActive && !v.momentumModeActive && v.storedAngularMomentum.magnitude < threshold)
                            {
                                if (v.rotationModeActive == true && v.reference != null)
                                {
                                    if (v.reference == v.lastReference)
                                    {
                                        PackedRotation(v);
                                    }
                                }
                            }
                            else
                            {
                                PackedSpin(v);
                            }
                        }
                    }

                    v.lastActive = false;

                    #endregion
                }
                else
                {
                    #region ### UNPACKED ###
                    //Did this vessel just go off rails?
                    if (v.GoingOffRailsFrameCounter != -1)
                    {
                        --v.GoingOffRailsFrameCounter;
                        if (v.GoingOffRailsFrameCounter == 0)
                        {
                            ApplyMomentumNow(v);
                            v.GoingOffRailsFrameCounter = -1;
                        }
                    }
                    else
                    {
                        //Update Momentum when unpacked
                        if (GetStabilityMode(vessel) != StabilityMode.OFF && !v.momentumModeActive && vessel.angularVelocity.magnitude < threshold) //C1
                        {
                            v.storedAngularMomentum = Vector3.zero;
                        }
                        else
                        {
                            v.storedAngularMomentum = vessel.angularMomentum;
                            //KSPLog.print(string.Format("SAVE angular vel: {0}, Momentum: {1}, MOI: {2}", vessel.angularVelocity, vessel.angularMomentum, vessel.MOI));
                        }
                    }

                    //Update mjMode when unpacked
                    v.mjMode = MechJebWrapper.GetMode(vessel);
                    v.rtMode = RemoteTechWrapper.GetMode(vessel);

                    //Apply Momentum to activeVessel using Fly-By-Wire
                    if (GetStabilityMode(vessel) == StabilityMode.RELATIVE && v.momentumModeActive) //C1 \ IsControllable
                    {
                        float desiredRPM = (vessel.angularVelocity.magnitude * 60f * (1f / Time.fixedDeltaTime)) / 360f;
                        if (v.desiredRPM >= 0)
                        {
                            vessel.ctrlState.roll = Mathf.Clamp((v.desiredRPM - desiredRPM), -1f, +1f);
                        }
                        else
                        {
                            vessel.ctrlState.roll = -Mathf.Clamp((-v.desiredRPM - desiredRPM), -1f, +1f);
                        }
                    }

                    //Update rotation
                    v.rotation = vessel.transform.rotation;

                    v.planetariumRight = Planetarium.right;

                    //Adjust SAS for Relative Rotation
                    if (v.rotationModeActive && v.reference != null) //C2
                    {
                        //Update direction
                        v.direction = (v.reference.GetTransform().position - vessel.transform.position).normalized;
                        if (GetStabilityMode(vessel) == StabilityMode.RELATIVE && !v.momentumModeActive)
                        {
                            if (v.lastActive && v.reference == v.lastReference)
                            {
                                AdjustSAS(v);
                            }
                            v.lastActive = true;
                        }
                        else
                        {
                            v.lastActive = false;
                        }

                        v.lastPosition = (Vector3d)v.lastTransform.position - v.reference.GetTransform().position;
                    }
                    else
                    {
                        v.direction    = Vector3.zero;
                        v.lastPosition = Vector3.zero;
                        v.lastActive   = false;
                    }
                    #endregion
                }

                v.lastTransform = vessel.ReferenceTransform;
                v.lastReference = v.reference;
            }
            #endregion

            data.PRVessels.RemoveAll(v => v.processed == false);
        }
示例#12
0
        private void MainGUI(int windowID)
        {
            Data.PRVessel v = data.FindPRVessel(activeVessel);
            Texture       toggle;

            if (MainWindowActive)
            {
                toggle = GameDatabase.Instance.GetTexture("PersistentRotation/Textures/minimize_w", false);
            }
            else
            {
                toggle = GameDatabase.Instance.GetTexture("PersistentRotation/Textures/maximize_w", false);
            }

            GUILayout.BeginVertical();

            //Minimize und Option Buttons
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button(options))
            {
                showConfigWindow = !showConfigWindow;
            }
            if (GUILayout.Button(toggle))
            {
                MainWindowActive = !MainWindowActive;
                MainWindowRect   = new Rect(MainWindowRect.x, MainWindowRect.y, 200, 10);
            }
            GUILayout.EndHorizontal();

            //If maximized
            if (MainWindowActive)
            {
                if (activeVessel.IsControllable)
                {
                    GUILayout.BeginHorizontal();
                    if (v.rotationModeActive)
                    {
                        GUI.contentColor = Color.green;
                    }
                    else
                    {
                        GUI.contentColor = Color.red;
                    }

                    if (GUILayout.Button("Rotation", GUILayout.ExpandWidth(true)))
                    {
                        mode = 1;
                    }

                    if (v.momentumModeActive)
                    {
                        GUI.contentColor = Color.green;
                    }
                    else
                    {
                        GUI.contentColor = Color.red;
                    }

                    if (GUILayout.Button("Momentum", GUILayout.ExpandWidth(true)))
                    {
                        mode = 2;
                    }

                    GUI.contentColor = Color.white;

                    GUILayout.EndHorizontal();

                    GUILayout.Space(15f);

                    if (mode == 1)
                    {
                        if (GUILayout.Button("Relative Rotation", GUILayout.ExpandWidth(true)))
                        {
                            showBodyWindow = !showBodyWindow;
                        }


                        if (v.reference != null)
                        {
                            if (v.dynamicReference)
                            {
                                GUILayout.Label("Reference: Dynamic (" + v.reference.GetName() + ")");
                            }
                            else
                            {
                                GUILayout.Label("Reference: " + v.reference.GetName());
                            }
                        }
                        else
                        {
                            GUILayout.Label("Reference: None");
                        }

                        string _text = "Activate";
                        if (v.rotationModeActive)
                        {
                            _text = "Deactivate";
                        }

                        if (GUILayout.Button(_text, GUILayout.ExpandWidth(true)))
                        {
                            if (v.rotationModeActive == false)
                            {
                                v.rotationModeActive = true;
                                v.momentumModeActive = false;

                                if (v.reference != null)
                                {
                                    v.direction = (v.reference.GetTransform().position - activeVessel.transform.position).normalized;
                                }
                                v.rotation         = activeVessel.transform.rotation;
                                v.planetariumRight = Planetarium.right;
                            }
                            else
                            {
                                v.rotationModeActive = false;
                            }
                        }
                    }
                    else if (mode == 2)
                    {
                        GUILayout.Label("Overwrite RPM:");
                        GUILayout.BeginHorizontal();
                        desiredRPMstr = GUILayout.TextField(desiredRPMstr);
                        GUILayout.Label(" RPM");
                        GUILayout.EndHorizontal();
                        GUILayout.Space(10f);
                        string _text = "Activate";
                        if (v.momentumModeActive)
                        {
                            _text = "Deactivate";
                        }

                        if (GUILayout.Button(_text, GUILayout.ExpandWidth(true)))
                        {
                            v.rotationModeActive = false;

                            if (v.momentumModeActive)
                            {
                                v.momentumModeActive = false;
                            }
                            else
                            {
                                try
                                {
                                    v.desiredRPM         = float.Parse(desiredRPMstr);
                                    v.momentumModeActive = true;
                                }
                                catch
                                {
                                    desiredRPMstr = v.desiredRPM.ToString();
                                }
                            }
                        }
                    }
                }
                else
                {
                    GUILayout.Label("Vessel is not controllable.");
                }
                GUI.DragWindow();
            }
            GUILayout.EndVertical();
        }
示例#13
0
        private void FixedUpdate()
        {
            if (activeVessel != FlightGlobals.ActiveVessel)
            {
                activeVessel = FlightGlobals.ActiveVessel;
                Interface.instance.desiredRPMstr = data.FindPRVessel(activeVessel).desiredRPM.ToString();
            }

            foreach (Data.PRVessel v in data.PRVessels)
            {
                v.processed = false;
            }

            #region ### Cycle through all vessels ###
            foreach (Vessel vessel in FlightGlobals.Vessels)
            {
                Data.PRVessel v = data.FindPRVessel(vessel);

                v.processed = true;
                if (v.dynamicReference)
                {
                    if (v.reference == null || (v.reference.GetType() != typeof(CelestialBody) || v.reference.GetName() != vessel.mainBody.GetName())) //Main body mode; continuous update of reference to mainBody
                    {
                        Debug.Log("[PR] Updated the reference of " + v.vessel.vesselName + " from " + (v.reference != null ? v.reference.GetName() : "Null") + " to " + vessel.mainBody.name);
                        v.reference        = vessel.mainBody;
                        v.direction        = (v.reference.GetTransform().position - vessel.transform.position).normalized;
                        v.rotation         = vessel.transform.rotation;
                        v.planetariumRight = Planetarium.right;
                        v.lastActive       = false;
                    }
                }
                if (vessel.packed)
                {
                    #region ### PACKED ###
                    if (vessel.loaded) //is okay, rotation doesnt need to be persistent when rotating
                    {
                        if (v.momentum.magnitude >= threshold)
                        {
                            PackedSpin(v);
                        }
                        else if (GetStabilityMode(vessel) != StabilityMode.ABSOLUTE)
                        {
                            if (GetStabilityMode(vessel) == StabilityMode.RELATIVE && v.rotationModeActive && !v.momentumModeActive && v.momentum.magnitude < threshold)
                            {
                                if (v.rotationModeActive == true && v.reference != null)
                                {
                                    if (v.reference == v.lastReference)
                                    {
                                        PackedRotation(v);
                                    }
                                }
                            }
                            else
                            {
                                PackedSpin(v);
                            }
                        }
                    }

                    v.lastActive = false;

                    #endregion
                }
                else
                {
                    #region ### UNPACKED ###
                    //Update Momentum when unpacked
                    if (GetStabilityMode(vessel) != StabilityMode.OFF && !v.momentumModeActive && vessel.angularVelocity.magnitude < threshold) //C1
                    {
                        v.momentum = Vector3.zero;
                    }
                    else
                    {
                        v.momentum = vessel.angularVelocity;
                    }
                    //Update mjMode when unpacked
                    v.mjMode = MechJebWrapper.GetMode(vessel);
                    v.rtMode = RemoteTechWrapper.GetMode(vessel);

                    //Apply Momentum to activeVessel using Fly-By-Wire
                    if (GetStabilityMode(vessel) == StabilityMode.RELATIVE && v.momentumModeActive) //C1 \ IsControllable
                    {
                        float desiredRPM = (vessel.angularVelocity.magnitude * 60f * (1f / Time.fixedDeltaTime)) / 360f;
                        if (v.desiredRPM >= 0)
                        {
                            vessel.ctrlState.roll = Mathf.Clamp((v.desiredRPM - desiredRPM), -1f, +1f);
                        }
                        else
                        {
                            vessel.ctrlState.roll = -Mathf.Clamp((-v.desiredRPM - desiredRPM), -1f, +1f);
                        }
                    }

                    //Update rotation
                    v.rotation = vessel.transform.rotation;

                    v.planetariumRight = Planetarium.right;

                    //Adjust SAS for Relative Rotation
                    if (v.rotationModeActive && v.reference != null) //C2
                    {
                        //Update direction
                        v.direction = (v.reference.GetTransform().position - vessel.transform.position).normalized;
                        if (GetStabilityMode(vessel) == StabilityMode.RELATIVE && !v.momentumModeActive)
                        {
                            if (v.lastActive && v.reference == v.lastReference)
                            {
                                AdjustSAS(v);
                            }
                            v.lastActive = true;
                        }
                        else
                        {
                            v.lastActive = false;
                        }

                        v.lastPosition = (Vector3d)v.lastTransform.position - v.reference.GetTransform().position;
                    }
                    else
                    {
                        v.direction    = Vector3.zero;
                        v.lastPosition = Vector3.zero;
                        v.lastActive   = false;
                    }
                    #endregion
                }

                v.lastTransform = vessel.ReferenceTransform;
                v.lastReference = v.reference;
            }
            #endregion

            data.PRVessels.RemoveAll(v => v.processed == false);
        }