/*public static class PartIconGenerator
* {
* private const string IconHiddenTag = "Icon_Hidden";
* private const string KerbalEvaSubstring = "kerbal";
*
* private static readonly int GameObjectLayer = LayerMask.NameToLayer ("PartsList_Icons");
* // note to future: if creating icons inside editor, you might want to choose a different layer or translate the camera and object out of frame
*
* private static Camera CreateCamera (int pixelWidth, int pixelHeight, Color backgroundColor)
* {
* //var camGo = new GameObject ("PartIconGenerator.Camera", typeof(Camera));
* //var cam = camGo.camera;
* Camera cam = new Camera();
*
* cam.enabled = false;
* cam.cullingMask = (1 << GameObjectLayer);
* cam.clearFlags = ~CameraClearFlags.Nothing;
* cam.nearClipPlane = 0.1f;
* cam.farClipPlane = 10f;
* cam.orthographic = true;
* cam.backgroundColor = backgroundColor;
* cam.aspect = pixelWidth / (float)pixelHeight;
*
* // Camera Size = x / ((( x / y ) * 2 ) * s )
* cam.orthographicSize = pixelWidth / (((pixelWidth / (float)pixelHeight) * 2f) * pixelHeight);
* cam.pixelRect = new Rect (0f, 0f, pixelWidth, pixelHeight);
*
* return cam;
* }
*
* private static Light CreateLight ()
* {
* var light = new GameObject ("PartIconGenerator.Light").AddComponent<Light> ();
*
* light.type = LightType.Directional;
* light.color = XKCDColors.OffWhite;
* light.cullingMask = 1 << GameObjectLayer;
* light.intensity = 0.1f;
*
* return light;
* }
*
* private static GameObject CreateIcon (AvailablePart part)
* {
* // kerbalEVA doesn't seem to init at origin if we aren't explicit
* var go = UnityEngine.Object.Instantiate (part.iconPrefab, Vector3.zero, Quaternion.identity) as GameObject;
*
* // The kerbals are initially facing along positive Z so we'll be looking at their backs if we don't
* // rotate them around
* if (part.name.StartsWith (KerbalEvaSubstring))
* go.transform.rotation = Quaternion.AngleAxis (180f, Vector3.up);
*
* go.SetLayerRecursive (GameObjectLayer);
* go.SetActive (true);
* return go;
* }
*
* private static void AdjustScaleAndCameraPosition (GameObject icon, Camera camera)
* {
* // get size of prefab
* var bounds = CalculateBounds (icon);
* float sphereDiameter = Mathf.Max (bounds.size.x, bounds.size.y, bounds.size.z);
*
* // rescale to size 1 unit so that object will take up as much viewspace as possible in ortho cam (with ortho size = 0.5)
* var currentScale = icon.transform.localScale;
* float scaleFactor = 1f / sphereDiameter;
* icon.transform.localScale = currentScale * scaleFactor;
*
* icon.transform.position = -bounds.center * scaleFactor;
*
* camera.transform.position = Vector3.zero;
*
* // back out, else we'll be inside the model (which is scaled at 1 unit so this should be plenty)
* camera.transform.Translate (new Vector3 (0f, 0f, -5f), Space.Self);
* camera.transform.LookAt (Vector3.zero, Vector3.up);
* }
*
*
* public static Texture2D Create2D (AvailablePart part, int width, int height, Quaternion orientation, Color backgroundColor)
* {
* var cam = CreateCamera (width, height, backgroundColor);
* var icon = CreateIcon (part);
* var light = CreateLight ();
*
* var texture = new Texture2D (width, height, TextureFormat.ARGB32, false);
* var rt = RenderTexture.GetTemporary (width, height, 24);
* var prevRt = RenderTexture.active;
*
* RenderTexture.active = rt;
*
* icon.transform.rotation = orientation * icon.transform.rotation;
*
* AdjustScaleAndCameraPosition (icon, cam);
*
* cam.targetTexture = rt;
* cam.pixelRect = new Rect (0f, 0f, width, height); // doc says this should be ignored but doesn't seem to be (?) -- rendered area very small once targetTexture is set
* cam.Render ();
*
* texture.ReadPixels (new Rect (0f, 0f, width, height), 0, 0, false);
* texture.Apply ();
*
* RenderTexture.active = prevRt;
* RenderTexture.ReleaseTemporary (rt);
* UnityEngine.Object.DestroyImmediate (light);
* UnityEngine.Object.DestroyImmediate (cam);
* UnityEngine.Object.DestroyImmediate (icon);
*
* return texture;
* }
*
* private static Bounds CalculateBounds (GameObject go)
* {
* var renderers = go.GetComponentsInChildren<Renderer> (true).ToList ();
*
* if (renderers.Count == 0)
* return default(Bounds);
*
* var boundsList = new List<Bounds> ();
*
* renderers.ForEach (r => {
* if (r.tag == IconHiddenTag)
* return;
*
* if (r is SkinnedMeshRenderer) {
* var smr = r as SkinnedMeshRenderer;
*
* // the localBounds of the SkinnedMeshRenderer are initially large enough
* // to accomodate all animation frames; they're likely to be far off for
* // parts that do a lot of animation-related movement (like solar panels expanding)
* //
* // We can get correct mesh bounds by baking the current animation into a mesh
* // note: vertex positions in baked mesh are relative to smr.transform; any scaling
* // is already baked in
* var mesh = new Mesh ();
* smr.BakeMesh (mesh);
*
* // while the mesh bounds will now be correct, they don't consider orientation at all.
* // If a long part is oriented along the wrong axis in world space, the bounds we'd get
* // here could be very wrong. We need to come up with essentially the renderer bounds:
* // a bounding box in world space that encompasses the mesh
* var m = Matrix4x4.TRS (smr.transform.position, smr.transform.rotation, Vector3.one
* // remember scale already factored in!
* );
* var vertices = mesh.vertices;
*
* var smrBounds = new Bounds (m.MultiplyPoint3x4 (vertices [0]), Vector3.zero);
*
* for (int i = 1; i < vertices.Length; ++i)
* smrBounds.Encapsulate (m.MultiplyPoint3x4 (vertices [i]));
*
* UnityEngine.Object.Destroy (mesh);
*
* boundsList.Add (smrBounds);
* } else if (r is MeshRenderer) { // note: there are ParticleRenderers, LineRenderers, and TrailRenderers
* r.gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateBounds ();
* boundsList.Add (r.bounds);
* }
* });
*
* Bounds bounds = boundsList [0];
*
* boundsList.Skip (1).ToList ().ForEach (b => bounds.Encapsulate (b));
*
* return bounds;
* }
* }*/
private void OnGUI()
{
if (tooltipstyle == null)
{
setStyles();
}
if (osdtime > Time.time)
{
float osdheight = osdstyle.CalcSize(new GUIContent(osdmessage)).y;
GUILayout.BeginArea(new Rect(0, Screen.height * 0.1f, Screen.width, osdheight), osdstyle);
GUILayout.Label(osdmessage, osdstyle);
GUILayout.EndArea();
}
if (visible)
{
if (refreshwait > 0)
{
refreshwait = refreshwait - 1;
}
else
{
switch (mystate)
{
case ASPState.IDLE:
EditorLogic editor = EditorLogic.fetch;
ShipConstruct ship = editor.ship;
if (ship != null)
{
List <Part> parts = ship.parts;
if ((parts != null) && (parts.Count > 0) && (parts [0] != null))
{
parts [0].SetHighlight(false, true);
if (tanks == null)
{
tanks = ASPStaging.findFuelTanks(parts);
}
else
{
if (vizualize)
{
if ((badDestTank != null) && (badStartTank != null))
{
drawLineBetweenBadParts();
}
foreach (Part p in parts)
{
if (p != null)
{
if ((badStartTank != null) && (p == badStartTank))
{
Vector3 position = Camera.main.WorldToScreenPoint(p.transform.position);
GUI.Label(new Rect(position.x, Screen.height - position.y, 200, 30), "Start tank");
badStartTank.SetHighlightColor(Color.blue);
badStartTank.SetHighlight(true, false);
badStartTank.highlightType = Part.HighlightType.AlwaysOn;
}
else if ((badDestTank != null) && (p == badDestTank))
{
Vector3 position = Camera.main.WorldToScreenPoint(p.transform.position);
GUI.Label(new Rect(position.x, Screen.height - position.y, 200, 30), "Destination tank");
badDestTank.SetHighlightColor(Color.blue);
badDestTank.SetHighlight(true, false);
badDestTank.highlightType = Part.HighlightType.AlwaysOn;
}
else if (blockingTanks.Contains(p))
{
Vector3 position = Camera.main.WorldToScreenPoint(p.transform.position);
GUI.Label(new Rect(position.x, Screen.height - position.y, 200, 30), "X");
p.SetHighlightColor(Color.red);
p.SetHighlight(true, false);
p.highlightType = Part.HighlightType.AlwaysOn;
}
else if (tanks.Contains(p))
{
// draw labels on the tanks
Vector3 position = Camera.main.WorldToScreenPoint(p.transform.position);
string label = "L" + ASPFuelLine.countDecouplersToRoot(p).ToString();
#if DEBUG
//label = label+": "+ASPConsoleStuff.getFriendlyName (p.craftID.ToString ());
#endif
GUI.Label(new Rect(position.x, Screen.height - position.y, 200, 30), label);
if ((p != badStartTank) && (p != badDestTank) && (!blockingTanks.Contains(p)))
{
p.SetHighlightColor(Color.green);
p.SetHighlight(true, false);
p.highlightType = Part.HighlightType.AlwaysOn;
}
}
else if (ASPStaging.isDecoupler(p))
{
p.SetHighlightColor(Color.magenta);
p.SetHighlight(true, false);
p.highlightType = Part.HighlightType.AlwaysOn;
}
else
{
p.SetHighlight(false, false);
}
}
}
}
}
}
windowRect = ClickThruBlocker.GUILayoutWindow(windowID, clampToScreen(windowRect), OnWindow, "AutoAsparagus " + versionString);
mousepos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
if ((tooltip != null) && (tooltip.Length > 0))
{
GUI.depth = 0;
Vector2 size = tooltipstyle.CalcSize(new GUIContent(tooltip));
Rect rect = new Rect(Input.mousePosition.x + 20, (Screen.height - Input.mousePosition.y) + 20, size.x, size.y);
rect = clampToScreen(rect);
GUILayout.BeginArea(rect);
GUILayout.Label(tooltip, tooltipstyle);
GUILayout.EndArea();
}
}
break;
case ASPState.ERROR:
vizualize = true;
mystate = ASPState.IDLE;
break;
case ASPState.ADDASP:
ASPConsoleStuff.ListTheShip();
mystate = ASPState.CONNECT;
ASPFuelLine.AddAsparagusFuelLines(partsWeCanUse [partToUseIndex], textureIndex, partTexturePaths [partToUseIndex], partTextureNames [partToUseIndex], rainbow);
if (mystate == ASPState.CONNECT)
{
osd("Connecting parts...");
}
refreshwait = 100;
break;
case ASPState.ADDONION:
ASPConsoleStuff.ListTheShip();
mystate = ASPState.CONNECT;
ASPFuelLine.AddOnionFuelLines(partsWeCanUse [partToUseIndex], textureIndex, partTexturePaths [partToUseIndex], partTextureNames [partToUseIndex], rainbow);
if (mystate == ASPState.CONNECT)
{
osd("Connecting parts...");
}
refreshwait = 100;
break;
case ASPState.CONNECT:
ASPFuelLine.connectFuelLines();
refreshwait = 100;
osd("Refreshing ship...");
mystate = ASPState.AFTERCONNECT;
break;
case ASPState.AFTERCONNECT:
newReloadShip();
refreshwait = 100;
if (useSmartStage)
{
mystate = ASPState.SMARTSTAGE;
osd("Calling SmartStage...");
ASPConsoleStuff.AAprint("Calling SmartStage");
}
else
{
mystate = ASPState.ADDSTAGES;
osd("Adding empty stages...");
}
break;
case ASPState.ADDSTAGES:
ASPStaging.AddEmptyStages();
mystate = ASPState.STAGE;
osd("Staging decouplers...");
refreshwait = 10;
break;
case ASPState.STAGE:
ASPStaging.AsaparagusTheShip(partsWeCanUse [partToUseIndex].name);
mystate = ASPState.AFTERSTAGE;
osd("Decoupler staging done, refreshing...");
refreshwait = 10;
break;
case ASPState.CLAMPS:
if (stageLaunchClamps)
{
ASPStaging.StageLaunchClamps(launchClampsStage);
}
mystate = ASPState.FINALREFRESH;
osd("Done!");
refreshwait = 10;
break;
case ASPState.DELETEFUEL:
ASPConsoleStuff.ListTheShip();
int count = ASPFuelLine.DeleteAllFuelLines(partsWeCanUse [partToUseIndex].name);
newReloadShip();
osd(count.ToString() + " parts deleted.");
mystate = ASPState.IDLE;
break;
case ASPState.FINALREFRESH:
newReloadShip();
mystate = ASPState.IDLE;
osd("Done!");
#if DEBUG
tanks = ASPStaging.findFuelTanks(EditorLogic.fetch.ship.Parts);
#endif
break;
case ASPState.AFTERSTAGE:
newReloadShip();
if (stageLaunchClamps)
{
osd("Staging launch clamps...");
mystate = ASPState.CLAMPS;
refreshwait = 10;
}
else
{
osd("Done!");
mystate = ASPState.IDLE;
}
break;
case ASPState.SMARTSTAGE:
mystate = ASPState.FINALREFRESH;
try {
computeStagesMethod.Invoke(null, new object[] { });
} catch (Exception e) {
UnityEngine.Debug.LogError("Error invoking method\n" + e.StackTrace);
}
osd("Done!");
break;
}
}
}
}