// But before the rest of the world is to be drawn, if the internal exists and is the active internal,
 // it should become invisible. This is only checked when transparentPodSetting is "OFF" or on "AUTO"
 // and the current vessel reference part is this part or the mouse is over this part.
 public void LateUpdate()
 {
     if (HighLogic.LoadedSceneIsEditor)
     {
         if (transparentPodSetting == "OFF" || (transparentPodSetting == "AUTO" && !mouseOver))
         {
             SetShaders(false);
             JUtil.SetCameraCullingMaskForIVA("Main Camera", false);
             part.internalModel.SetVisible(false);
         }
         else
         {
             SetShaders(true);
             JUtil.SetCameraCullingMaskForIVA("Main Camera", true);
             part.internalModel.SetVisible(true);
         }
         mouseOver = false;
         return;
     }
     if (JUtil.IsInIVA())
     {
         return;
     }
     if (transparentPodSetting == "OFF" || ((transparentPodSetting == "AUTO" && FlightGlobals.ActiveVessel.referenceTransformId != this.part.flightID) &&
                                            (transparentPodSetting == "AUTO" && !mouseOver)))
     {
         if (JUtil.cameraMaskShowsIVA && vessel.isActiveVessel && part.internalModel != null && !JUtil.UserIsInPod(part))
         {
             part.internalModel.SetVisible(false);
         }
     }
     mouseOver = false;
 }
 // During the drawing of the GUI, when the portraits are to be drawn, if the internal exists, it should be visible,
 // so that portraits show up correctly. This is only checked when transparentPodSetting is "OFF" or on "AUTO"
 // and this part is part of the active vessel.
 public void OnGUI()
 {
     if (HighLogic.LoadedSceneIsFlight)
     {
         if (JUtil.IsInIVA())
         {
             return;
         }
         if ((transparentPodSetting == "OFF" || transparentPodSetting == "AUTO") && vessel.isActiveVessel && part.internalModel != null)
         {
             part.internalModel.SetVisible(true);
         }
     }
 }
 // During the drawing of the GUI, when the portraits are to be drawn, if the internal exists, it should be visible,
 // so that portraits show up correctly. This is only checked when transparentPodSetting is "OFF" or on "AUTO"
 // and the current vessel reference part is this part or the mouse is over this part.
 public void OnGUI()
 {
     if (HighLogic.LoadedSceneIsEditor || JUtil.IsInIVA())
     {
         return;
     }
     if (transparentPodSetting == "OFF" || ((transparentPodSetting == "AUTO" && FlightGlobals.ActiveVessel.referenceTransformId != this.part.flightID) &&
                                            (transparentPodSetting == "AUTO" && !mouseOver)))
     {
         if (JUtil.cameraMaskShowsIVA && vessel.isActiveVessel && part.internalModel != null)
         {
             part.internalModel.SetVisible(true);
         }
     }
 }
        public override void OnUpdate()
        {
            // In the editor, none of this logic should matter, even though the IVA probably exists already.
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            // If the root part changed, or the IVA is mysteriously missing, we reset it and take note of where it ended up.
            if (vessel.rootPart != knownRootPart || lastActiveVessel != FlightGlobals.ActiveVessel || part.internalModel == null)
            {
                ResetIVA();
            }

            // So we do have an internal model, right?
            if (part.internalModel != null)
            {
                if (JUtil.IsInIVA())
                {
                    // If the user is IVA, we move the internals to the original position,
                    // so that they show up correctly on InternalCamera. This particularly concerns
                    // the pod the user is inside of.
                    part.internalModel.transform.parent        = originalParent;
                    part.internalModel.transform.localRotation = originalRotation;
                    part.internalModel.transform.localPosition = originalPosition;
                    part.internalModel.transform.localScale    = originalScale;

                    if (!JUtil.UserIsInPod(part))
                    {
                        // If the user is in some other pod than this one, we also hide our IVA to prevent them from being drawn above
                        // everything else.
                        part.internalModel.SetVisible(false);
                    }

                    // Unfortunately even if I do that, it means that at least one kerbal on the ship will see his own IVA twice in two different orientations,
                    // one time through the InternalCamera (which I can't modify) and another through the Camera 00.
                    // So we have to also undo the culling mask change as well.
                    JUtil.SetMainCameraCullingMaskForIVA(false);

                    // So once everything is hidden again, we undo the change in shaders to conceal the fact that you can't see other internals.
                    SetShaders(false);
                }
                else
                {
                    // If the current part is not part of the active vessel, we calculate the distance from the part to the flight camera.
                    // If this distance is > 500m we turn off transparency for the part.
                    // Uses Maths calcs intead of built in Unity functions as this is up to 5 times faster.
                    if (!vessel.isActiveVessel)
                    {
                        Vector3   heading;
                        float     distanceSquared;
                        Transform thisPart     = this.part.transform;
                        Transform flightCamera = FlightCamera.fetch.transform;
                        heading.x        = thisPart.position.x - flightCamera.position.x;
                        heading.y        = thisPart.position.y - flightCamera.position.y;
                        heading.z        = thisPart.position.z - flightCamera.position.z;
                        distanceSquared  = heading.x * heading.x + heading.y * heading.y + heading.z * heading.z;
                        distanceToCamera = Mathf.Sqrt(distanceSquared);

                        if (distanceToCamera > distanceToCameraThreshold)
                        {
                            SetShaders(false);
                            JUtil.SetMainCameraCullingMaskForIVA(true);
                            return;
                        }
                    }
                    distanceToCamera = 0f;

                    // If transparentPodSetting = OFF or AUTO and not the focused active part we treat the part like a non-transparent part.
                    // and we turn off the shaders (if set) and exit OnUpdate. onGUI and LateUpdate will do the rest.
                    if (transparentPodSetting == "OFF" || ((transparentPodSetting == "AUTO" && FlightGlobals.ActiveVessel.referenceTransformId != this.part.flightID) &&
                                                           (transparentPodSetting == "AUTO" && !mouseOver)))
                    {
                        SetShaders(false);
                        JUtil.SetMainCameraCullingMaskForIVA(true);
                        return;
                    }
                    // Otherwise, we're out of IVA, so we can proceed with setting up the pods for exterior view.
                    JUtil.SetMainCameraCullingMaskForIVA(true);

                    // Make the internal model visible...
                    part.internalModel.SetVisible(true);

                    // And for a good measure we make sure the shader change has been applied.
                    SetShaders(true);

                    // Now we attach the restored IVA directly into the pod at zero local coordinates and rotate it,
                    // so that it shows up on the main outer view camera in the correct location.
                    part.internalModel.transform.parent        = part.transform;
                    part.internalModel.transform.localRotation = MagicalVoodooRotation;
                    part.internalModel.transform.localPosition = Vector3.zero;
                    part.internalModel.transform.localScale    = Vector3.one;
                }
            }
        }
        public override void OnUpdate()
        {
            // In the editor, none of this logic should matter, even though the IVA probably exists already.
            if (HighLogic.LoadedSceneIsEditor)
            {
                return;
            }

            // If the root part changed, or the IVA is mysteriously missing, we reset it and take note of where it ended up.
            if (vessel.rootPart != knownRootPart || lastActiveVessel != FlightGlobals.ActiveVessel || part.internalModel == null)
            {
                ResetIVA();
            }

            // Now we need to make sure that the list of portraits in the GUI conforms to what actually is in the active vessel.
            // This is important because IVA/EVA buttons clicked on kerbals that are not in the active vessel cause problems
            // that I can't readily debug, and it shouldn't happen anyway.

            // Only the pods in the active vessel should be doing it since the list refers to them.
            if (vessel.isActiveVessel)
            {
                // First, every pod should check through the list of portaits and remove everyone who is from some other vessel, or NO vessel.
                var stowaways = new List <Kerbal>();
                foreach (Kerbal thatKerbal in KerbalGUIManager.ActiveCrew)
                {
                    if (thatKerbal.InPart == null)
                    {
                        stowaways.Add(thatKerbal);
                    }
                    else
                    {
                        if (thatKerbal.InVessel != vessel)
                        {
                            stowaways.Add(thatKerbal);
                        }
                    }
                }
                foreach (Kerbal thatKerbal in stowaways)
                {
                    KerbalGUIManager.RemoveActiveCrew(thatKerbal);
                }
                // Then, every pod should check the list of seats in itself and see if anyone is missing who should be present.
                foreach (InternalSeat seat in part.internalModel.seats)
                {
                    if (seat.kerbalRef != null && !KerbalGUIManager.ActiveCrew.Contains(seat.kerbalRef))
                    {
                        if (seat.kerbalRef.protoCrewMember.rosterStatus != ProtoCrewMember.RosterStatus.Dead || seat.kerbalRef.protoCrewMember.type != ProtoCrewMember.KerbalType.Unowned)
                        {
                            KerbalGUIManager.AddActiveCrew(seat.kerbalRef);
                        }
                    }
                }
            }

            // So we do have an internal model, right?
            if (part.internalModel != null)
            {
                if (JUtil.IsInIVA())
                {
                    // If the user is IVA, we move the internals to the original position,
                    // so that they show up correctly on InternalCamera. This particularly concerns
                    // the pod the user is inside of.
                    part.internalModel.transform.parent        = originalParent;
                    part.internalModel.transform.localRotation = originalRotation;
                    part.internalModel.transform.localPosition = originalPosition;
                    part.internalModel.transform.localScale    = originalScale;

                    if (!JUtil.UserIsInPod(part))
                    {
                        // If the user is in some other pod than this one, we also hide our IVA to prevent them from being drawn above
                        // everything else.
                        part.internalModel.SetVisible(false);
                    }

                    // Unfortunately even if I do that, it means that at least one kerbal on the ship will see his own IVA twice in two different orientations,
                    // one time through the InternalCamera (which I can't modify) and another through the Camera 00.
                    // So we have to also undo the culling mask change as well.
                    JUtil.SetMainCameraCullingMaskForIVA(false);

                    // So once everything is hidden again, we undo the change in shaders to conceal the fact that you can't see other internals.
                    SetShaders(false);
                }
                else
                {
                    // If transparentPodSetting = OFF or AUTO and not the focused active part we treat the part like a non-transparent part.
                    // and we turn off the shaders (if set) and exit OnUpdate. onGUI and LateUpdate will do the rest.
                    if (transparentPodSetting == "OFF" || ((transparentPodSetting == "AUTO" && FlightGlobals.ActiveVessel.referenceTransformId != this.part.flightID) &&
                                                           (transparentPodSetting == "AUTO" && !mouseOver)))
                    {
                        SetShaders(false);
                        JUtil.SetMainCameraCullingMaskForIVA(true);
                        return;
                    }
                    // Otherwise, we're out of IVA, so we can proceed with setting up the pods for exterior view.
                    JUtil.SetMainCameraCullingMaskForIVA(true);

                    // Make the internal model visible...
                    part.internalModel.SetVisible(true);

                    // And for a good measure we make sure the shader change has been applied.
                    SetShaders(true);

                    // Now we attach the restored IVA directly into the pod at zero local coordinates and rotate it,
                    // so that it shows up on the main outer view camera in the correct location.
                    part.internalModel.transform.parent        = part.transform;
                    part.internalModel.transform.localRotation = MagicalVoodooRotation;
                    part.internalModel.transform.localPosition = Vector3.zero;
                    part.internalModel.transform.localScale    = Vector3.one;
                }
            }
        }