private void ResetIVA()
        {
            if (HighLogic.LoadedSceneIsFlight)
            {
                JSIAdvTPodsUtil.Log_Debug("Need to reset IVA in part {0}", part.craftID);

                // Now the cruical bit.
                // If the root part changed, we actually need to recreate the IVA forcibly even if it still exists.
                if (vessel.rootPart != knownRootPart)
                {
                    // In this case we also need to kick the user out of IVA if they're currently in our pod,
                    // otherwise lots of things screw up in a bizarre fashion.
                    if (JSIAdvTPodsUtil.UserIsInPod(part))
                    {
                        JSIAdvTPodsUtil.Log_Debug("The user is in pod {0} and I need to kick them out.", part.partName);
                        CameraManager.Instance.SetCameraFlight();
                    }
                    // This call not just reinitialises the IVA, but also destroys the existing one, if any,
                    // and reloads all the props and modules.
                    JSIAdvTPodsUtil.Log_Debug("Need to actually respawn the IVA model in part {0}", part.partName);
                    //part.CreateInternalModel(); - SpawIVA does this already on the next line.
                }
                // But otherwise the existing one will serve.

                // If the internal model doesn't yet exist, this call will implicitly create it anyway.
                // It will also initialise it, which in this case implies moving it into the correct location in internal space
                // and populate it with crew, which is what we want.
                part.SpawnIVA();
                part.internalModel.SetVisible(true);
                setVisible = true;
                // And then we remember the root part and the active vessel these coordinates refer to.
                knownRootPart    = vessel.rootPart;
                lastActiveVessel = FlightGlobals.ActiveVessel;
            }
        }
Exemple #2
0
 internal void CreateIVACamera()
 {
     JSIAdvTPodsUtil.Log_Debug("CreateIVACamera");
     //Create a new IVA camera if one does not exist.
     if (IVAcamera == null)
     {
         //Create a new Gameobject to attach everything to.
         //Attach the IVA Camera to it.
         if (baseGO == null)
         {
             baseGO = new GameObject("JSIAdvTransparentPods");
         }
         IVAcamera            = baseGO.gameObject.AddComponent <Camera>();
         IVAcamera.clearFlags = CameraClearFlags.Depth;
         IVAcameraTransform   = IVAcamera.transform;
         //Get the Main Flight camera.
         Maincamera = JSIAdvTPodsUtil.GetCameraByName("Camera 00");
         //The IVA cmaera Transform needs to be parented to the InternalSpace Transform.
         IVAcameraTransform.parent = InternalSpace.Instance.transform;
         MaincameraTransform       = Maincamera.transform;
         //Depth of 3 is above the Main Cameras.
         IVAcamera.depth       = 3f;
         IVAcamera.fieldOfView = Maincamera.fieldOfView;
         //Show Only Kerbals and Internal Space layers.
         IVAcamera.cullingMask = 1114112;
         //Attach a Culler class to the camera to cull objects we don't want rendered.
         if (IVACamJSICameraCuller == null && HighLogic.LoadedSceneIsFlight)
         {
             IVACamJSICameraCuller = IVAcamera.gameObject.AddComponent <JSIIVACameraEvents>();
         }
     }
     //Finally turn the new camera on.
     TurnonIVACamera();
 }
Exemple #3
0
 internal void DestroyIVACamera()
 {
     if (IVAcamera != null)
     {
         JSIAdvTPodsUtil.Log_Debug("DestroyIVACamera");
         Destroy(IVACamJSICameraCuller);
         Destroy(IVAcamera);
         baseGO.DestroyGameObject();
     }
 }
Exemple #4
0
 public void OnDestroy()
 {
     JSIAdvTPodsUtil.Log_Debug("OnDestroy");
     DestroyIVACamera();
     GameEvents.OnMapEntered.Remove(TurnoffIVACamera);
     GameEvents.OnMapExited.Remove(TurnonIVACamera);
     GameEvents.onVesselChange.Remove(onVesselChange);
     GameEvents.onLevelWasLoaded.Remove(onLevelWasLoaded);
     GameEvents.onVesselSwitching.Remove(onVesselSwitching);
 }
Exemple #5
0
 public void onVesselSwitching(Vessel oldvessel, Vessel newvessel)
 {
     JSIAdvTPodsUtil.Log_Debug("OnVesselSwitching");
     if (oldvessel != null)
     {
         JSIAdvTPodsUtil.Log_Debug("From: {0} ({1})", oldvessel.vesselName, oldvessel.id);
     }
     if (newvessel != null)
     {
         JSIAdvTPodsUtil.Log_Debug("To: {0} ({1}) ", newvessel.vesselName, newvessel.id);
     }
     CheckStowaways();
 }
        public void CheckStowaways()
        {
            // 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 that are not the active vessel should be doing this. So if this part/vessel is not part of the active vessel then:-
            //Search the seats and where there is a kerbalRef try to Unregister them from the PortraitGallery.
            if (part.internalModel != null)
            {
                if (FlightGlobals.ActiveVessel.id != vessel.id)
                {
                    foreach (InternalSeat seat in part.internalModel.seats)
                    {
                        if (seat.kerbalRef != null)
                        {
                            try
                            {
                                seat.kerbalRef.SetVisibleInPortrait(false);
                                KerbalPortraitGallery.Instance.UnregisterActiveCrew(seat.kerbalRef);
                            }
                            catch (Exception)
                            {
                                JSIAdvTPodsUtil.Log_Debug("Unregister Portrait on inactive part failed {0}", seat.kerbalRef.crewMemberName);
                            }
                        }
                    }
                }
                else
                {
                    foreach (InternalSeat seat in part.internalModel.seats)
                    {
                        if (seat.kerbalRef != null)
                        {
                            try
                            {
                                seat.kerbalRef.SetVisibleInPortrait(true);
                                //KerbalPortraitGallery.Instance.UnregisterActiveCrew(seat.kerbalRef);
                                //KerbalPortraitGallery.Instance.RegisterActiveCrew(seat.kerbalRef);
                            }
                            catch (Exception)
                            {
                                JSIAdvTPodsUtil.Log_Debug("Register Portrait on inactive part failed {0}", seat.kerbalRef.crewMemberName);
                            }
                        }
                    }
                }
            }
        }
Exemple #7
0
 //This will Unregister all crew on all active/loaded vessels. As there is no PUBLIC access anymore to the portraits list.
 //Kludgy, slow, horrendous. But no other choice. This is only done ONVesselChange and OnVesselSwitch.
 public void CheckStowaways()
 {
     /*
      * List <ProtoCrewMember> vslcrew = new List<ProtoCrewMember>();
      * //First we do all loaded vessels that are NOT active vessel.
      * foreach (
      *      Vessel fgVessel in
      *          FlightGlobals.Vessels.Where(p => p.loaded && p.isActiveVessel == false))
      *  {
      *      try
      *      {
      *          vslcrew.AddRange(fgVessel.GetVesselCrew());
      *      }
      *      catch (Exception)
      *      {
      *          JSIAdvTPodsUtil.Log_Debug("Failed to build VesselCrew list in CheckStowaways");
      *      }
      *
      *  }
      * foreach (ProtoCrewMember crewmbr in vslcrew)
      * {
      *  try
      *  {
      *      crewmbr.KerbalRef.SetVisibleInPortrait(false);
      *      KerbalPortraitGallery.Instance.UnregisterActiveCrew(crewmbr.KerbalRef);
      *  }
      *  catch (Exception)
      *  {
      *      JSIAdvTPodsUtil.Log_Debug("Failed to UnregisterActiveCrew from PortraitGallery : {0}" , crewmbr.name);
      *  }
      * }*/
     //Now we do the Activevessel - but we also REGISTER the activevessel crew back to the PortraitGallery.
     if (FlightGlobals.ActiveVessel != null)
     {
         foreach (ProtoCrewMember crewmbr in FlightGlobals.ActiveVessel.GetVesselCrew())
         {
             try
             {
                 crewmbr.KerbalRef.SetVisibleInPortrait(true);
                 KerbalPortraitGallery.Instance.UnregisterActiveCrew(crewmbr.KerbalRef);
                 KerbalPortraitGallery.Instance.RegisterActiveCrew(crewmbr.KerbalRef);
             }
             catch (Exception)
             {
                 JSIAdvTPodsUtil.Log_Debug("Failed to Un/registerActiveCrew from PortraitGallery : {0}", crewmbr.name);
             }
         }
     }
 }
Exemple #8
0
 public void Awake()
 {
     JSIAdvTPodsUtil.Log_Debug("OnAwake in {0}", HighLogic.LoadedScene);
     if (Instance != null)
     {
         Destroy(this);
     }
     //DontDestroyOnLoad(this);
     Instance = this;
     GameEvents.OnMapEntered.Add(TurnoffIVACamera);
     GameEvents.OnMapExited.Add(TurnonIVACamera);
     GameEvents.onVesselChange.Add(onVesselChange);
     GameEvents.onVesselSwitching.Add(onVesselSwitching);
     PartstoFilterfromIVADict = new List <Part>();
 }
Exemple #9
0
 public void OnPreCull()
 {
     for (int i = 0; i < JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Count; i++)
     {
         try
         {
             JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict[i].internalModel.SetVisible(false);
         }
         catch (Exception ex)
         {
             if (precullMsgCount < 10)
             {
                 JSIAdvTPodsUtil.Log_Debug("Unable to Precull internalModel for part {0}", JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict[i].craftID);
                 JSIAdvTPodsUtil.Log_Debug("Err : {0}", ex.Message);
                 precullMsgCount++;
             }
         }
     }
 }
Exemple #10
0
 //Awake Event - when the DLL is loaded
 public void Awake()
 {
     if (Instance != null)
     {
         return;
     }
     Instance = this;
     DontDestroyOnLoad(this);
     settings             = new Settings();
     globalConfigFilename = Path.Combine(_AssemblyFolder, "Config.cfg").Replace("\\", "/");
     JSIAdvTPodsUtil.Log("globalConfigFilename = " + globalConfigFilename);
     if (!File.Exists(globalConfigFilename))
     {
         settings.Save(globalNode);
         globalNode.Save(globalConfigFilename);
     }
     globalNode = ConfigNode.Load(globalConfigFilename);
     settings.Load(globalNode);
     JSIAdvTPodsUtil.debugLoggingEnabled = settings.DebugLogging;
     JSIAdvTPodsUtil.Log("JSIAdvTransparentPods LoadGlobals Awake Complete");
 }
        public override void OnStart(StartState state)
        {
            JSIAdvTPodsUtil.Log_Debug("OnStart {0} in state {1}", part.craftID, state);
            if (state == StartState.Editor && disableLoadingInEditor)
            {
                // Early out for people who want to disable transparency in
                // the editor due to low-spec computers.
                return;
            }

            DepthMaskShader = Shader.Find(DepthMaskShaderName);

            // Apply shaders to transforms on startup.
            if (!string.IsNullOrEmpty(transparentTransforms))
            {
                transparentShader = Shader.Find(transparentShaderName);

                foreach (string transformName in transparentTransforms.Split('|'))
                {
                    try
                    {
                        Transform tr = part.FindModelTransform(transformName.Trim());
                        if (tr != null)
                        {
                            // We both change the shader and backup the original shader so we can undo it later.
                            Shader backupShader = tr.GetComponent <Renderer>().material.shader;
                            tr.GetComponent <Renderer>().material.shader = transparentShader;
                            shadersBackup.Add(tr, backupShader);
                        }
                        Transform itr = part.internalModel.FindModelTransform(transformName.Trim());
                        if (itr != null)
                        {
                            // We both change the shader and backup the original shader so we can undo it later.
                            Shader backupShader = itr.GetComponent <Renderer>().material.shader;
                            itr.GetComponent <Renderer>().material.shader = transparentShader;
                            shadersBackup.Add(itr, backupShader);
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.LogException(e, this);
                    }
                }
            }

            if (!string.IsNullOrEmpty(opaqueShaderName))
            {
                opaqueShader    = Shader.Find(opaqueShaderName);
                hasOpaqueShader = true;
            }

            // In Editor, the camera we want to change is called "Main Camera". In flight, the camera to change is
            // "Camera 00", i.e. close range camera.

            if (state == StartState.Editor)
            {
                // I'm not sure if this change is actually needed, even. Main Camera's culling mask seems to already include IVA objects,
                // they just don't normally spawn them.
                JSIAdvTPodsUtil.SetCameraCullingMaskForIVA("Main Camera", true);
            }

            // If the internal model has not yet been created, try creating it and log the exception if we fail.
            if (part.internalModel == null)
            {
                try
                {
                    part.CreateInternalModel();
                }
                catch (Exception e)
                {
                    Debug.LogException(e, this);
                }
            }

            if (part.internalModel == null && part.partInfo != null)
            {
                // KSP 1.0.x introduced a new feature where it doesn't appear
                // to fully load parts if they're not the root.  In particular,
                // that CreateInternalModel() call above here returns null for
                // non-root parts until one exits the VAB and returns.
                // If the internalModel doesn't exist yet, I find the config
                // for this part, extract the INTERNAL node, and try to create
                // the model myself. Awfully roundabout.

                JSIAdvTPodsUtil.Log_Debug("Let's see if anyone included parts so I can assemble the interior");
                ConfigNode ipNameNode = (from cfg in GameDatabase.Instance.GetConfigs("PART")
                                         where cfg.url == part.partInfo.partUrl
                                         select cfg.config.GetNode("INTERNAL")).FirstOrDefault();

                if (ipNameNode != null)
                {
                    part.internalModel = part.AddInternalPart(ipNameNode);
                }
            }

            // If we ended up with an existing internal model,
            if (part.internalModel != null)
            {
                // Rotate it now, so that it is shown correctly in the editor. - OLD Method.
                if (state == StartState.Editor)
                {
                    // Just rotating the internal is sufficient in this case.
                    part.internalModel.transform.localRotation = MagicalVoodooRotation;
                    //Find all Renderer's with DepthMask shader assigned to them and make them inactive as they cause Z-Fighting in the Editor and are
                    //not needed in the editor - OLD Method.
                    foreach (Renderer renderer in part.internalModel.GetComponentsInChildren <Renderer>(true))
                    {
                        if (renderer.material.shader == DepthMaskShader)
                        {
                            renderer.enabled          = false;
                            renderer.gameObject.layer = 29;
                        }
                    }
                }
                else
                {
                    // Else this is our first startup in flight scene, we reset the IVA.
                    ResetIVA();
                }
            }
            else
            {
                // Some error-proofing. I won't bother doing this every frame, because one error message
                // should suffice, this module is not supposed to be attached to parts that have no internals in the first place.
                JSIAdvTPodsUtil.Log("Wait, where's my internal model?");
            }
        }
        public override void OnUpdate()
        {
            if (Time.timeSinceLevelLoad < 2f)
            {
                return;
            }

            // In the editor, none of this logic should matter, even though the IVA probably exists already.
            if (HighLogic.LoadedSceneIsEditor)
            {
                // 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.
                VoodooRotate();
                setVisible = true;
                return;
            }

            //Now FlightScene Processing

            // 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();
            }

            // 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 the internal to the filter list and exit OnUpdate.
            if (transparentPodSetting == "OFF" || (transparentPodSetting == "AUTO" && !mouseOver))
            {
                SetShaders(false);
                //part.internalModel.SetVisible(false);
                if (!JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Contains(part))
                {
                    JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Add(part);
                }
                setVisible = false;
                return;
            }

            //If we are in IVA mode or If the camera is not in flight mode or PArt is not part of ActiveVessel and user has set LoadedInactive to true we go no further.
            if (JSIAdvTPodsUtil.IsInIVA() || CameraManager.Instance.currentCameraMode != CameraManager.CameraMode.Flight ||
                (vessel.id != FlightGlobals.ActiveVessel.id && LoadGlobals.settings.LoadedInactive))
            {
                return;
            }

            // So we do have an internal model, right?
            if (part.internalModel != null)
            {
                // 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 > distanceToCameraThreshold metres 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 && LoadGlobals.settings.LoadedInactive && CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Flight)
                {
                    Vector3   heading;
                    Transform thisPart     = 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;
                    var distanceSquared = heading.x * heading.x + heading.y * heading.y + heading.z * heading.z;
                    distanceToCamera = Mathf.Sqrt(distanceSquared);

                    if (distanceToCamera > distanceToCameraThreshold)
                    {
                        SetShaders(false);
                        //part.internalModel.SetVisible(false);
                        if (!JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Contains(part))
                        {
                            JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Add(part);
                        }
                        setVisible = false;
                        return;
                    }
                }

                //If not the active vessel IVAs are turned on via the settings then we:
                //Check for obstructions between this IVA and the Camera that may be on lower layers and turn off the IVA if there is one.
                //Not a perfect solution..... and bad performance-wise.
                if (LoadGlobals.settings.LoadedInactive)
                {
                    if (JSIAdvTransparentPods.Instance != null && setVisible)
                    {
                        if (JSIAdvTransparentPods.Instance.IVAcameraTransform != null)
                        {
                            Transform IVAtoWorld = new GameObject().transform;
                            IVAtoWorld.position =
                                InternalSpace.InternalToWorld(part.internalModel.transform.position);
                            IVAtoWorld.rotation = InternalSpace.InternalToWorld(part.internalModel.transform.rotation);
                            Transform IVACameratoWorld = new GameObject().transform;
                            IVACameratoWorld.position =
                                InternalSpace.InternalToWorld(JSIAdvTransparentPods.Instance.IVAcameraTransform.position);
                            IVAtoWorld.rotation = InternalSpace.InternalToWorld(JSIAdvTransparentPods.Instance.IVAcameraTransform.rotation);
                            if (JSIAdvTPodsUtil.IsIVAObstructed(IVAtoWorld, IVACameratoWorld))
                            {
                                if (!JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Contains(part))
                                {
                                    JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Add(part);
                                }
                            }
                            IVAtoWorld.gameObject.DestroyGameObject();
                            IVACameratoWorld.gameObject.DestroyGameObject();
                        }
                    }
                }

                // Make the internal model visible...
                // And for a good measure we make sure the shader change has been applied.
                SetShaders(true);
                if (JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Contains(part))
                {
                    JSIAdvTransparentPods.Instance.PartstoFilterfromIVADict.Remove(part);
                }
                setVisible = true;
                part.internalModel.SetVisible(true);
            }
            else
            {
                JSIAdvTPodsUtil.Log("Where is my Internal model for : {0}", part.craftID);
            }
        }
        public void LateUpdate()
        {
            if (Time.timeSinceLevelLoad < 2f)
            {
                return;
            }

            //Reset the mouseOver flag.
            mouseOver = false;

            //In editor Logic
            if (HighLogic.LoadedSceneIsEditor)
            {
                // If we are in editor mode we need to turn off the internal if the internal is in OFF or AUTO mode and not moused over.
                //Otherwise we make it visible.
                if (transparentPodSetting == "OFF" || (transparentPodSetting == "AUTO" && !mouseOver))
                {
                    SetShaders(false);
                    if (part.internalModel != null)
                    {
                        part.internalModel.SetVisible(false);
                    }
                    setVisible = false;
                }
                else
                {
                    SetShaders(true);
                    if (part.internalModel != null)
                    {
                        part.internalModel.SetVisible(true);
                    }
                    setVisible = true;
                }
                //For some reason we need to keep turning off the Renderers with the DepthMask Shader.. Because setting the
                //activated.
                if (part.internalModel != null)
                {
                    foreach (Renderer renderer in part.internalModel.GetComponentsInChildren <Renderer>(true))
                    {
                        if (renderer.material.shader == DepthMaskShader)
                        {
                            renderer.enabled          = false;
                            renderer.gameObject.layer = 29;
                        }
                    }
                }
            }

            //In flight logic.
            //If we are in flight and the user has the Stock Overlay on and this part is not part of the active vessel we turn off the internal.
            // also if the user has set the LoadedInactive to true - we don't show TransparentPods that aren't on the active vessel.
            // We turn it off rather than registering it for the PreCull list because if Stock Overlay is on the JSI camera is not active.
            if (HighLogic.LoadedSceneIsFlight && CameraManager.Instance != null && InternalSpace.Instance != null)
            {
                if (!vessel.isActiveVessel && (JSIAdvTransparentPods.Instance.StockOverlayCamIsOn || LoadGlobals.settings.LoadedInactive))
                {
                    if (part.internalModel != null)
                    {
                        part.internalModel.SetVisible(false);
                    }
                    setVisible = false;
                    SetShaders(false);
                    CheckStowaways();
                    JSIAdvTPodsUtil.Log_Debug("Internal turned off as stockoverlay is on and part is not in active vessel : ({0}) {1}", part.craftID, vessel.vesselName);
                    return;
                }
                //Finally we check for Stowaways on the PortraitCams
                CheckStowaways();

                //For some reason (probably performance) Squad do not actively update the position and rotation of InternalModels that are not part of the active vessel.
                if (!vessel.isActiveVessel)
                {
                    //Calculate the Vessel position and rotation and then apply that to the InternalModel position and rotation with the MagicalVoodooRotation.
                    Vector3 VesselPosition = part.vessel.transform.position + part.vessel.transform.rotation * part.orgPos;
                    if (part.internalModel != null)
                    {
                        part.internalModel.transform.position = InternalSpace.WorldToInternal(VesselPosition);
                        Quaternion VesselRotation = part.vessel.transform.rotation * part.orgRot;
                        part.internalModel.transform.rotation = InternalSpace.WorldToInternal(VesselRotation) * MagicalVoodooRotation;
                    }
                }
            }
        }
Exemple #14
0
 public void onVesselChange(Vessel vessel)
 {
     JSIAdvTPodsUtil.Log_Debug("OnVesselChange {0} ({1})", vessel.vesselName, vessel.id);
     //CheckStowaways();
 }
Exemple #15
0
 public void onLevelWasLoaded(GameScenes scene)
 {
     JSIAdvTPodsUtil.Log_Debug("OnLevelWasLoaded {0}", scene);
 }
Exemple #16
0
 void Start()
 {
     camera = GetComponent <Camera>();
     JSIAdvTPodsUtil.Log_Debug("Object attached to Camera {0}", camera.name);
 }