sumghai Posted June 2, 2014 Share Posted June 2, 2014 Premisesfr's Command Pod plugin allows Kerbal occupants inside a properly-configured command pod to be visible from outside the vessel (essentially, see-through windows from the outside). While the add-on still works in 0.23.5 for the most part, there are a number of outstanding issues: - The camera for the internal IVA view is dependent on the orientation of the root (first) part of a vessel, rather than that of the command pod / crew cabin itself - A vessel with more than one sfr-powered command pod / crew cabin will end up aligning the internal IVA view to the root part / first sfr-powered command pod / crew cabin defined - It is not clear whether the plugin is restricted to actual command pods, or if crew cabins with no command authority are also able to use this plugin - sfr only visits the forums occasionally, such that plugin maintenance issues are slow to be addressed (his only method of distribution is also the now-defunct Spaceport) - Some add-ons, such as Alskari's Hollow Structure and Hulls and BobCat Industries' Tesla Recon Rover, have the sfr plugin as a dependency, yet suffer from the aforementioned issues.Finally, I personally would like to make this as a dependency FusTek Station Parts / upcoming FusTek Space Exploration Vehicle part packs, but the current version of the plugin as-is is unsuitable due to the aforementioned issues.ObjectiveMy primary objective is to rework the plugin to address the aforementioned issues, and publish it via more publicly-available channels such as CurseForge, Dropbox or MediaFire.My secondary objective is to seek a new, permanent home of the plugin code, preferably with a popular dependency such as Firespitter - I personally prefer to spend most of my time making new parts than wrestling code, hence the intention for the handover.Licencing / Permissionssfr's source code file states that his work is licenced under CC BY-SA 3.0, and so as long as the derivative provides full credit to sfr, and is redistributed under the same license, it should be kosher. /* * sfr * License: BY: Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0): http://creativecommons.org/licenses/by-sa/3.0/ */Help NeededGiven the following source code, I would like to: - Strip out the portions pertaining to the hatch animation, as it is unnecessary IMHO - Figure out how to change the IVA camera to align with the module's own transform, instead of the root part - Ensure that multiple sfr-powered pods / cabins can work simultaneously, each with their own independent IVA camera transforms - Ensure that the plugin can also work for non-command pod crewed cabins, such as my FusTek Kupola and various non-command pod compartments Alskari made for HSHHere's the full source code as originally included in the Spaceport download:/* * sfr * License: BY: Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0): http://creativecommons.org/licenses/by-sa/3.0/ */using System;using System.Collections.Generic;using System.Linq;using UnityEngine;namespace sfrPartModules1{ class sfrUtility { public static Camera FindCamera(string name) { foreach (Camera c in Camera.allCameras) if (c.name == name) return c; return null; } public static void LogCameras() { int i = 0; foreach (Camera c in Camera.allCameras) { Debug.Log("Cam " + i++ + " " + c.name + " " + c.cullingMask); Debug.Log(c.transform.position + " " + c.transform.rotation.eulerAngles + " " + c.fov + " " + c.depth + " " + c.clearFlags); } } public static void LogModules(Part part) { int i = 0; foreach (PartModule p in part.Modules) Debug.Log("Mod " + i++ + " " + p.name + " " + p.GUIName + " " + p.guiText); } } public class sfrCommandPod : CommandPod { public string doorTransformName; public float openAngle = 45f; Transform doorTransform; Shader glassShader, metalShader, diffuseShader; void AddShader(string transformName, Shader s) { Transform t = FindModelTransform(transformName); t.renderer.material.shader = s; } int CrewNumber = 0; bool DoorOpen = false; int CrewBoarding() { int Result = 0; if (CrewNumber < protoModuleCrew.Count) Result = 1; else if (CrewNumber > protoModuleCrew.Count) Result = -1; else if (CrewNumber == protoModuleCrew.Count) Result = 0; CrewNumber = protoModuleCrew.Count; return Result; } IEnumerator<WaitForSeconds> OpenDoor() { if (!DoorOpen) doorTransform.Rotate(0, 0, openAngle, Space.Self); yield return new WaitForSeconds(2); // Debug.Log("Crew member on board"); doorTransform.Rotate(0, 0, -openAngle, Space.Self); } protected override void onPartAwake() {// Debug.LogWarning("onPartAwake " + GameInfo.gameScene); base.onPartAwake(); metalShader = Shader.Find("Specular"); glassShader = Shader.Find("Transparent/Specular"); diffuseShader = Shader.Find("Diffuse"); AddShader("Pod", metalShader); AddShader("DoorAxle", metalShader); AddShader("Hatch", metalShader); AddShader("WindGlass", glassShader); AddShader("SideGlass", glassShader); AddShader("UpGlass", glassShader); Transform t = FindModelTransform("DoorLight"); Light l = t.GetComponent<Light>(); l.shadows = LightShadows.Soft; } protected override void onPartStart() {// Debug.LogWarning("onPartStart " + GameInfo.gameScene); base.onPartStart(); doorTransform = FindModelTransform(doorTransformName);// Debug.Log(doorTransform); if (protoModuleCrew.Count == 0) { doorTransform.Rotate(0, 0, openAngle, Space.Self); DoorOpen = true; } } protected override void onStartComplete() { base.onStartComplete();// Debug.LogWarning("onStartComplete " + GameInfo.gameScene); } protected override void onFlightStart() { base.onFlightStart();// Debug.LogWarning("onFlightStart " + GameInfo.gameScene); sfrUtility.LogModules(this); } protected override bool onPartActivate() { return base.onPartActivate();// Debug.LogWarning("onPartActivate " + GameInfo.gameScene); } protected override void onPartDeactivate() { base.onPartDeactivate();// Debug.LogWarning("onPartActivate " + GameInfo.gameScene); } protected override void onPartUpdate() {// Debug.LogWarning("OnPartUpdate " + GameInfo.gameScene); base.onPartUpdate(); int Boarding = CrewBoarding(); if (Boarding > 0) {// Debug.Log("Crew member boarded"); StartCoroutine(OpenDoor()); DoorOpen = false; } else if (Boarding < 0) { if (protoModuleCrew.Count == 0) { doorTransform.Rotate(0, 0, openAngle, Space.Self); DoorOpen = true; } else StartCoroutine(OpenDoor()); } } protected override void onEditorUpdate() {// Debug.LogWarning("OnEditorUpdate " + GameInfo.gameScene); base.onEditorUpdate(); } } public class sfrInternal : PartModule { Transform kspParent; Vector3 kspPosition = new Vector3(18.3f, -6.9f, 0); Quaternion kspRotation = new Quaternion(0, 0.7f, -0.7f, 0); bool isActive = true; public override void OnAwake() { base.OnAwake();// Debug.LogWarning("sfrInternal OnAwake " + GameInfo.gameScene + " " + part + " " + vessel); } public override void OnLoad(ConfigNode node) { base.OnLoad(node);// Debug.LogWarning("sfrInternal OnLoad " + node.name); } public override void OnSave(ConfigNode node) { base.OnSave(node);// Debug.LogWarning("sfrInternal OnSave " + node.name); } public override void OnStart(StartState state) { base.OnStart(state);// Debug.LogWarning("sfrInternal OnStart, StartState: " + state); Camera c = sfrUtility.FindCamera("Main Camera"); if (c) c.cullingMask |= 1 << 16 | 1 << 20; if(!part.internalModel) { try { part.CreateInternalModel(); } catch (Exception e) { Debug.LogException(e, this); } } if(part.internalModel) { if (state != StartState.Editor) kspParent = part.internalModel.transform.parent; part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } } public override void OnUpdate() { base.OnUpdate();// Debug.LogWarning("sfrInternal OnUpdate"); if (isActive != part.vessel.isActiveVessel) { Camera c = sfrUtility.FindCamera("Main Camera"); if (c) c.cullingMask |= 1 << 16 | 1 << 20; part.CreateInternalModel(); kspParent = InternalCamera.Instance.transform.parent; // part.internalModel.transform.parent; part.internalModel.SetVisible(true); part.vessel.SetActiveInternalPart(part); if (part.protoModuleCrew.Count > 0 && isActive) { part.vessel.SpawnCrew(); } part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } if(!part.internalModel) { part.CreateInternalModel(); kspParent = InternalCamera.Instance.transform.parent; // part.internalModel.transform.parent; part.internalModel.SetVisible(true); part.vessel.SetActiveInternalPart(part); if (part.protoModuleCrew.Count > 0 && isActive) { part.vessel.SpawnCrew(); } part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } try { if (sfrUtility.FindCamera("InternalCamera")) { if (part.vessel.isActiveVessel) { part.internalModel.transform.position = kspPosition; // Vector3.zero; part.internalModel.transform.parent = kspParent; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); } } else { part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } } catch (Exception e) { Debug.LogException(e, this); } } }}And here's my early attempt at stripping out the hatch animation code and removing the non-glass shaders:/* * TransparentViewports plugin (transView) * * Author: Robin "sumghai" Chang * and members of the Kerbal Space Program user community * * Based on: sfr Command Pod plugin by sfr * * License: Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) * http://www.creativecommons.org/licenses/by-sa/3.0/ */using System;using System.Collections.Generic;using System.Linq;using UnityEngine;namespace transViewPartModules1{ class transViewUtility { public static Camera FindCamera(string name) { foreach (Camera c in Camera.allCameras) if (c.name == name) return c; return null; } public static void LogCameras() { int i = 0; foreach (Camera c in Camera.allCameras) { Debug.Log("Cam " + i++ + " " + c.name + " " + c.cullingMask); Debug.Log(c.transform.position + " " + c.transform.rotation.eulerAngles + " " + c.fov + " " + c.depth + " " + c.clearFlags); } } public static void LogModules(Part part) { int i = 0; foreach (PartModule p in part.Modules) Debug.Log("Mod " + i++ + " " + p.name + " " + p.GUIName + " " + p.guiText); } } public class transViewCommandPod : CommandPod { Shader glassShader, metalShader, diffuseShader; void AddShader(string transformName, Shader s) { Transform t = FindModelTransform(transformName); t.renderer.material.shader = s; } protected override void onPartAwake() {// Debug.LogWarning("onPartAwake " + GameInfo.gameScene); base.onPartAwake(); //metalShader = Shader.Find("Specular"); glassShader = Shader.Find("Transparent/Specular"); //diffuseShader = Shader.Find("Diffuse"); //AddShader("Pod", metalShader); //AddShader("DoorAxle", metalShader); //AddShader("Hatch", metalShader); AddShader("WindGlass", glassShader); AddShader("SideGlass", glassShader); AddShader("UpGlass", glassShader); //Transform t = FindModelTransform("DoorLight"); //Light l = t.GetComponent<Light>(); //l.shadows = LightShadows.Soft; } protected override void onPartStart() {// Debug.LogWarning("onPartStart " + GameInfo.gameScene); base.onPartStart(); } protected override void onStartComplete() { base.onStartComplete();// Debug.LogWarning("onStartComplete " + GameInfo.gameScene); } protected override void onFlightStart() { base.onFlightStart();// Debug.LogWarning("onFlightStart " + GameInfo.gameScene); transViewUtility.LogModules(this); } protected override bool onPartActivate() { return base.onPartActivate();// Debug.LogWarning("onPartActivate " + GameInfo.gameScene); } protected override void onPartDeactivate() { base.onPartDeactivate();// Debug.LogWarning("onPartActivate " + GameInfo.gameScene); } protected override void onPartUpdate() {// Debug.LogWarning("OnPartUpdate " + GameInfo.gameScene); base.onPartUpdate(); } protected override void onEditorUpdate() {// Debug.LogWarning("OnEditorUpdate " + GameInfo.gameScene); base.onEditorUpdate(); } } public class transViewInternal : PartModule { Transform kspParent; Vector3 kspPosition = new Vector3(18.3f, -6.9f, 0); Quaternion kspRotation = new Quaternion(0, 0.7f, -0.7f, 0); bool isActive = true; public override void OnAwake() { base.OnAwake();// Debug.LogWarning("transViewInternal OnAwake " + GameInfo.gameScene + " " + part + " " + vessel); } public override void OnLoad(ConfigNode node) { base.OnLoad(node);// Debug.LogWarning("transViewInternal OnLoad " + node.name); } public override void OnSave(ConfigNode node) { base.OnSave(node);// Debug.LogWarning("transViewInternal OnSave " + node.name); } public override void OnStart(StartState state) { base.OnStart(state);// Debug.LogWarning("transViewInternal OnStart, StartState: " + state); Camera c = transViewUtility.FindCamera("Main Camera"); if (c) c.cullingMask |= 1 << 16 | 1 << 20; if(!part.internalModel) { try { part.CreateInternalModel(); } catch (Exception e) { Debug.LogException(e, this); } } if(part.internalModel) { if (state != StartState.Editor) kspParent = part.internalModel.transform.parent; part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } } public override void OnUpdate() { base.OnUpdate();// Debug.LogWarning("transViewInternal OnUpdate"); if (isActive != part.vessel.isActiveVessel) { Camera c = transViewUtility.FindCamera("Main Camera"); if (c) c.cullingMask |= 1 << 16 | 1 << 20; part.CreateInternalModel(); kspParent = InternalCamera.Instance.transform.parent; // part.internalModel.transform.parent; part.internalModel.SetVisible(true); part.vessel.SetActiveInternalPart(part); if (part.protoModuleCrew.Count > 0 && isActive) { part.vessel.SpawnCrew(); } part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } if(!part.internalModel) { part.CreateInternalModel(); kspParent = InternalCamera.Instance.transform.parent; // part.internalModel.transform.parent; part.internalModel.SetVisible(true); part.vessel.SetActiveInternalPart(part); if (part.protoModuleCrew.Count > 0 && isActive) { part.vessel.SpawnCrew(); } part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } try { if (transViewUtility.FindCamera("InternalCamera")) { if (part.vessel.isActiveVessel) { part.internalModel.transform.position = kspPosition; // Vector3.zero; part.internalModel.transform.parent = kspParent; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); } } else { part.internalModel.transform.parent = part.transform; part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0); part.internalModel.transform.localPosition = Vector3.zero; } } catch (Exception e) { Debug.LogException(e, this); } } }}I have yet to compile this, but in the meantime, I'd like to figure out how to fix the IVA camera transforms first - specifically, which parts of the code are responsible for defining the IVA camera transform orientation, and how would I change it so that it works on a per-module basis rather than via the vessel's root part?Thanks in advance. Link to comment Share on other sites More sharing options...
Snjo Posted June 2, 2014 Share Posted June 2, 2014 The internal model has a hard coded rotation of 90,180,0, so if you add that to the part's rotation, that might work.(I have not read through the source yet, but just thought I'd chime in with that piece of non obvious info) Link to comment Share on other sites More sharing options...
sumghai Posted June 3, 2014 Author Share Posted June 3, 2014 The internal model has a hard coded rotation of 90,180,0, so if you add that to the part's rotation, that might work.(I have not read through the source yet, but just thought I'd chime in with that piece of non obvious info)Ah, I see. I'm guessing this means I have to go through, find the following lines:part.internalModel.transform.localRotation = new Quaternion(0, 0.7f, -0.7f, 0);and apply the hard-coded internal rotation to the existing quaternions somehow?I'll look into this a little later this week - thanks!(NB Advice and suggestions still welcome - I dabbled in C# for work-related purposes, just not nearly enough for KSP plugin authoring) Link to comment Share on other sites More sharing options...
dtoxic Posted June 13, 2014 Share Posted June 13, 2014 (edited) any news or an eta release on this plugin ?another thing maybe it helps (but probably just a shot in the dark)i;am using this plugin and bobcat home 3 (tesla rover) and my log is spammed with NullReferenceException: Object reference not set to an instance of an objecti think its cause the source code doesn't have damage colliders defined in it maybe you can take a look at that if you have spare time but like i said its probably just a shot in the darktake care Edited June 13, 2014 by dtoxic additional info Link to comment Share on other sites More sharing options...
sumghai Posted June 13, 2014 Author Share Posted June 13, 2014 any news or an eta release on this plugin ?I've spoken to Mihara, and he's working on his own version of a PartModule to support transparent pods, which will probably be bundled with JSI RasterPropMonitor. WIP tests can be seen here, and while there are still a few minor issues, for the most part it resolves the main problem mentioned in this thread. Not sure about the NullReferenceExceptions, however. Link to comment Share on other sites More sharing options...
dtoxic Posted June 13, 2014 Share Posted June 13, 2014 I've spoken to Mihara, and he's working on his own version of a PartModule to support transparent pods, which will probably be bundled with JSI RasterPropMonitor. WIP tests can be seen here, and while there are still a few minor issues, for the most part it resolves the main problem mentioned in this thread. Not sure about the NullReferenceExceptions, however.ok thx for the info Link to comment Share on other sites More sharing options...
Mihara Posted June 13, 2014 Share Posted June 13, 2014 For the record, https://github.com/Mihara/RasterPropMonitor/blob/master/RasterPropMonitor/Auxiliary%20modules/JSITransparentPod.csI think it works about as good as I can make it, unless someone finds another issue. Link to comment Share on other sites More sharing options...
dtoxic Posted June 13, 2014 Share Posted June 13, 2014 when can we get the compiled version to try it out? Link to comment Share on other sites More sharing options...
sumghai Posted June 13, 2014 Author Share Posted June 13, 2014 when can we get the compiled version to try it out? Mihara just sent me an updated dev build with a few fixes - he and I agreed that we need to do some more stress testing with regards to how docking, crew transfer, potential conflicts with the core JSI RPM props etc may affect the transparent pod PartModule.Once he and I feel we're confident we've sussed out these issues, Mihara may make the auxiliary function available for wider testing. Link to comment Share on other sites More sharing options...
dtoxic Posted June 13, 2014 Share Posted June 13, 2014 cool hope both of you get it to work Link to comment Share on other sites More sharing options...
sumghai Posted June 16, 2014 Author Share Posted June 16, 2014 Mihara and I have verified that his new PartModule is working properly, and resolved practically all of the issues we've encountered (other than the inability to view the insides of other transparent pods while in IVA):http://forum.kerbalspaceprogram.com/threads/57603-0-23-5-RasterPropMonitor-make-your-IVA-a-glass-cockpit-%28v0-16%29-20-Apr?p=1211267&viewfull=1#post1211267As such, I believe this thread has served its purpose Link to comment Share on other sites More sharing options...
UbioZur Posted June 16, 2014 Share Posted June 16, 2014 closed as requested by sumghai. Link to comment Share on other sites More sharing options...
Recommended Posts