Skip to content

Instantly share code, notes, and snippets.

@HappyFaceIndustries
Created May 8, 2016 05:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HappyFaceIndustries/d997e268d38bd638881e4033606216f9 to your computer and use it in GitHub Desktop.
Save HappyFaceIndustries/d997e268d38bd638881e4033606216f9 to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
using UnityEngine;
namespace Telescope
{
public class ModuleTelescope2 : PartModule
{
//KSPFields
[KSPField(guiName = "FOV")]
public float FOV = 60f;
[KSPField]
public string CameraTransformName = "camera";
[KSPField]
public string WindowName = "Telescope View";
[KSPField]
public float SkyboxExposure = 0f;
//camera values
private Transform cameraTransform;
private Camera[] cameras;
private RenderTexture targetTexture;
private GameObject localCameraObj;
private GameObject scaledCameraObj;
private GameObject galaxyCameraObj;
private float CurrentFOV;
//GUI values
private bool UIOpen = false;
private bool showUI = true;
private float fov_ui = 0f;
private GUISkin skin = HighLogic.Skin;
private Rect WindowRect = new Rect(20, 80, 512, 512);
private string[] visibleObjects;
//constants
const double RadToDeg = 57.2957801818848;
const double KPtoAtms = 0.009869232;
//renderers
private Renderer[] skyboxRenderers;
private List<Renderer> scaledPlanetRenderers;
private AtmosphereFromGround[] atmospheres;
private MethodInfo atmosphereSetMaterialMethod;
//camera rendering info cache
Dictionary<AtmosphereFromGround, Vector4> atmoInfo = new Dictionary<AtmosphereFromGround, Vector4> ();
//lifetime methods
public override void OnStart (StartState state)
{
//set the reference transform
part.SetReferenceTransform (cameraTransform);
//do nothing else unless we are in flight
if (!HighLogic.LoadedSceneIsFlight)
return;
//camera transform
cameraTransform = part.FindModelTransform (CameraTransformName);
if (cameraTransform == null)
{
Debug.LogError ("cameraTransform not found, deleting ModuleTelescope");
DestroyImmediate (this);
return;
}
//target texture
targetTexture = new RenderTexture (512, 512, 24);
targetTexture.antiAliasing = GameSettings.ANTI_ALIASING;
targetTexture.Create ();
//set up the cameras
SetupCamera ();
//fetch the renderers
skyboxRenderers = (from Renderer r in (FindObjectsOfType (typeof(Renderer)) as IEnumerable<Renderer>)
where (r.name == "XP" || r.name == "XN" || r.name == "YP" || r.name == "YN" || r.name == "ZP" || r.name == "ZN")
select r).ToArray<Renderer> ();
scaledPlanetRenderers = ScaledSpace.Instance.scaledSpaceTransforms.Where(t => t.renderer != null).Select (t => t.renderer).ToList();
scaledPlanetRenderers.Add (ScaledSun.Instance.renderer);
atmospheres = UnityEngine.Object.FindObjectsOfType<AtmosphereFromGround> ();
atmosphereSetMaterialMethod = typeof(AtmosphereFromGround).GetMethod ("SetMaterial", BindingFlags.NonPublic | BindingFlags.Instance);
//register for GameEvents
GameEvents.onShowUI.Add (OnShowUI);
GameEvents.onHideUI.Add (OnHideUI);
}
public override void OnUpdate ()
{
//do nothing unless we are in flight
if (!HighLogic.LoadedSceneIsFlight)
return;
Events ["ShowUI"].guiActive = !UIOpen;
Events ["HideUI"].guiActive = UIOpen;
}
public void LateUpdate()
{
//do nothing unless we are in flight
if (!HighLogic.LoadedSceneIsFlight)
return;
RenderCameras ();
}
public void OnDestroy()
{
//do nothing unless we are in flight
if (!HighLogic.LoadedSceneIsFlight)
return;
GameEvents.onShowUI.Remove (OnShowUI);
GameEvents.onHideUI.Remove (OnHideUI);
if(scaledCameraObj != null)
Destroy (scaledCameraObj);
if(galaxyCameraObj != null)
Destroy (galaxyCameraObj);
}
//editor information
public override string GetInfo ()
{
return "It's a telescope!";
}
//GUI
private void OnGUI()
{
//do nothing unless we are in flight
if (!HighLogic.LoadedSceneIsFlight)
return;
if (!showUI)
return;
if (MapView.MapIsEnabled)
return;
if (UIOpen)
{
GUI.skin = skin;
WindowRect = GUILayout.Window ("ModuleTelescope_UI".GetHashCode (), WindowRect, Window, WindowName, GUILayout.ExpandHeight (true), GUILayout.ExpandWidth (true));
}
}
private void Window(int id)
{
GUILayout.Box (targetTexture);
fov_ui = GUILayout.HorizontalSlider (fov_ui, 0f, 1f, GUILayout.ExpandWidth (true));
CurrentFOV = Mathf.Pow (fov_ui, 8f) * FOV;
GUILayout.BeginHorizontal ();
foreach (var planet in visibleObjects)
{
GUILayout.Label (planet);
GUILayout.Space (15f);
}
GUILayout.EndHorizontal ();
GUI.DragWindow ();
}
//KSPEvents
[KSPEvent(guiName = "Show GUI", guiActive = true, guiActiveUnfocused = false)]
public void ShowUI ()
{
UIOpen = true;
}
[KSPEvent(guiName = "Hide GUI", guiActive = true, guiActiveUnfocused = false)]
public void HideUI ()
{
UIOpen = false;
}
[KSPEvent(guiName = "Control From Here", guiActive = true, guiActiveUnfocused = false)]
public void SetReference()
{
vessel.SetReferenceTransform (part);
}
//GameEvents
private void OnShowUI()
{
showUI = true;
}
private void OnHideUI()
{
showUI = false;
}
//camera methods
public void RenderCameras()
{
//get cameraWorldPos
Vector3d cameraWorldPos = ScaledSpace.ScaledToLocalSpace (cameraTransform.position);
//set cameras' FOV
SetFOV (CurrentFOV);
//position scaled camera
scaledCameraObj.transform.position = ScaledSpace.LocalToScaledSpace (vessel.GetWorldPos3D ());
scaledCameraObj.transform.rotation = cameraTransform.rotation;
//position galaxy camera
galaxyCameraObj.transform.rotation = cameraTransform.rotation;
//galaxy skybox rendering
//recalculate exposure setting for skybox
var exposure = CalculateExposure (cameraWorldPos);
var origColor = skyboxRenderers [0].sharedMaterial.GetColor (HighLogic.ShaderPropertyID_Color);
for (int i = 0; i < skyboxRenderers.Length; i++)
{
var sr = skyboxRenderers [i];
Color color = Color.Lerp (GalaxyCubeControl.Instance.minGalaxyColor, GalaxyCubeControl.Instance.maxGalaxyColor, exposure);
sr.material.SetColor (HighLogic.ShaderPropertyID_Color, color);
}
//render galaxyCamera
cameras [3].Render ();
//set exposure back to what it was
for (int i = 0; i < skyboxRenderers.Length; i++)
{
var sr = skyboxRenderers [i];
sr.material.SetColor (HighLogic.ShaderPropertyID_Color, origColor);
}
//scaled space rendering
//render atmospheres
foreach (var afg in atmospheres)
{
//cache the atmosphere info
if (!atmoInfo.ContainsKey (afg))
atmoInfo.Add (afg, new Vector4 (afg.cameraPos.x, afg.cameraPos.y, afg.cameraPos.z, afg.cameraHeight));
else
atmoInfo [afg] = new Vector4 (afg.cameraPos.x, afg.cameraPos.y, afg.cameraPos.z, afg.cameraHeight);
//set the atmosphere's camera to the scaled camera
afg.cameraPos = cameraTransform.position;
afg.cameraHeight = cameraTransform.position.magnitude;
afg.cameraHeight2 = afg.cameraHeight * afg.cameraHeight;
atmosphereSetMaterialMethod.Invoke (afg, new object[]{ false });
}
//render planets
foreach (var scaledPlanetRenderer in scaledPlanetRenderers)
{
scaledPlanetRenderer.enabled = true;
}
cameras [2].Render ();
//reset atmoInfo
foreach (var afg in atmospheres)
{
//reset the atmosphere info from the cache
if (atmoInfo.ContainsKey (afg))
{
var info = atmoInfo [afg];
afg.cameraPos = new Vector3 (info.x, info.y, info.z);
afg.cameraHeight = info.z;
afg.cameraHeight2 = info.z * info.z;
atmosphereSetMaterialMethod.Invoke (afg, new object[]{ false });
}
}
//localspace rendering
cameras [1].Render ();
cameras [0].Render ();
//update visibleObjects array
UpdateVisibleObjects ();
}
public void SetupCamera()
{
//initialize camera array
cameras = new Camera[4];
//fetch template cameras
Camera flightCameraNear = FlightCamera.fetch.cameras [0];
Camera flightCameraFar = FlightCamera.fetch.cameras [1];
Camera scaledSpaceCamera = FindCamera ("Camera ScaledSpace");
Camera galaxyCamera = FindCamera ("GalaxyCamera");
//create localCameraObj
localCameraObj = new GameObject ("ModuleTelescope_localCamera");
localCameraObj.transform.parent = cameraTransform;
ResetTransform (localCameraObj);
//create scaledCameraObj
scaledCameraObj = new GameObject ("ModuleTelescope_scaledCamera");
scaledCameraObj.transform.parent = ScaledSpace.SceneTransform;
ResetTransform (scaledCameraObj);
//create galaxyCameraObj
galaxyCameraObj = new GameObject ("ModuleTelescope_galaxyCamera");
ResetTransform (galaxyCameraObj);
//create near local camera
GameObject cam0Obj = new GameObject ("flightCameraNear");
cam0Obj.transform.parent = cameraTransform;
var cam0 = cam0Obj.AddComponent<Camera> ();
cam0.CopyFrom (flightCameraNear);
cam0.targetTexture = targetTexture;
cameras [0] = cam0;
ResetTransform (cam0Obj);
//create far local camera
GameObject cam1Obj = new GameObject ("flightCameraFar");
cam1Obj.transform.parent = cameraTransform;
var cam1 = cam1Obj.AddComponent<Camera> ();
cam1.CopyFrom (flightCameraFar);
cam1.targetTexture = targetTexture;
cameras [1] = cam1;
ResetTransform (cam1Obj);
//create scaledspace camera
GameObject cam2Obj = new GameObject ("scaledSpaceCamera");
cam2Obj.transform.parent = scaledCameraObj.transform;
var cam2 = cam2Obj.AddComponent<Camera> ();
cam2Obj.AddComponent ("FlareLayer");
cam2.CopyFrom (scaledSpaceCamera);
cam2.targetTexture = targetTexture;
cameras [2] = cam2;
ResetTransform (cam2Obj);
//create galaxy camera
GameObject cam3Obj = new GameObject ("galaxyCamera");
cam3Obj.transform.parent = galaxyCameraObj.transform;
var cam3 = cam3Obj.AddComponent<Camera> ();
cam3.CopyFrom (galaxyCamera);
cam3.targetTexture = targetTexture;
cameras [3] = cam3;
ResetTransform (cam3Obj);
}
public void SetFOV(float fov)
{
//set the FOV
foreach (var c in cameras)
{
c.fieldOfView = fov;
}
}
private Camera FindCamera(string cameraName)
{
foreach (var cam in Camera.allCameras)
{
if (cam.name == cameraName)
return cam;
}
Debug.LogError ("Could not find camera " + cameraName);
return null;
}
private float CalculateExposure(Vector3d cameraWorldPos)
{
float pressure = (float)(FlightGlobals.getStaticPressure (cameraWorldPos) * KPtoAtms);
return Mathf.Lerp (SkyboxExposure, 0f, pressure);
}
private void ResetTransform(GameObject obj)
{
ResetTransform (obj.transform);
}
private void ResetTransform(Transform trns)
{
trns.localRotation = Quaternion.identity;
trns.localPosition = Vector3.zero;
trns.localScale = Vector3.one;
}
private void UpdateVisibleObjects()
{
List<string> tempList = new List<string> ();
foreach (var scaledPlanetRenderer in scaledPlanetRenderers)
{
if (scaledPlanetRenderer.IsVisibleFrom (cameras [2]))
tempList.Add (scaledPlanetRenderer.name);
}
visibleObjects = tempList.ToArray ();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment