// called every screen refresh private void OnWindow(int windowID) { GUILayout.BeginHorizontal(); if (GUILayout.Button(new GUIContent("Asparagus", aspTexture, "Create fuel lines and stage the ship, asparagus-style"), picbutton)) { mystate = ASPState.ADDASP; osd("Adding parts in asparagus style..."); } if (GUILayout.Button(new GUIContent("Onion", onionTexture, "Create fuel lines and stage the ship, onion-style"), picbutton)) { mystate = ASPState.ADDONION; osd("Adding parts in onion style..."); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button(new GUIContent("Delete all " + partsWeCanUse [partToUseIndex].title, nofuelTexture, "Delete all " + partsWeCanUse [partToUseIndex].title + " parts on the ship"), picbutton)) { osd("Deleting parts..."); mystate = ASPState.DELETEFUEL; } GUILayout.EndHorizontal(); if (partsWeCanUse.Count() > 1) { // choose part to use for fuel lines GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); GUILayout.Label("Part to use:", labelstyle); GUILayout.EndVertical(); GUILayout.BeginVertical(); int oldPartToUseIndex = partToUseIndex; partToUseIndex = GUILayout.SelectionGrid(partToUseIndex, partGrid, 1, togglestyle); if (oldPartToUseIndex != partToUseIndex) { // shrink window windowRect.height = 0; windowRect.width = 0; } GUILayout.EndVertical(); GUILayout.EndHorizontal(); } if (partTextureNames [partToUseIndex] != null) { GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); GUILayout.Label("Texture:", labelstyle); GUILayout.EndVertical(); GUILayout.BeginVertical(); int numTextures = partTextureNames [partToUseIndex].Count(); GUIContent[] texSelect = new GUIContent[numTextures]; for (int i = 0; i < numTextures; i++) { texSelect [i] = new GUIContent(partTextureNames [partToUseIndex] [i], partTextures [partToUseIndex] [i]); } textureIndex = GUILayout.SelectionGrid(textureIndex, texSelect, 2, gridstyle); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.BeginVertical(); GUILayout.Label("Rainbow:", labelstyle); GUILayout.EndVertical(); GUILayout.BeginVertical(); rainbow = GUILayout.Toggle(rainbow, new GUIContent("Rainbow", rainbowTexture, "Oh, rainBOWs. Yeah I like those!")); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } GUILayout.BeginHorizontal(); GUILayout.Label("Options:"); GUILayout.EndHorizontal(); if (SmartStageAvailable) { GUILayout.BeginHorizontal(); useSmartStage = GUILayout.Toggle(useSmartStage, new GUIContent(" Use SmartStage", smartstageTexture, "Stage the ship using SmartStage instead of AutoAsparagus"), togglestyle); GUILayout.EndHorizontal(); } if (!useSmartStage) { GUILayout.BeginHorizontal(); stageParachutes = GUILayout.Toggle(stageParachutes, new GUIContent(" Stage parachutes", parachuteTexture, "Stage parachutes to fire with decouplers"), togglestyle); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); stagesepratrons = GUILayout.Toggle(stagesepratrons, new GUIContent(" Stage sepratrons", sepratronTexture, "Stage sepratrons to fire with decouplers"), togglestyle); GUILayout.EndHorizontal(); if (!stageLaunchClamps) { minheight = windowRect.height; minwidth = windowRect.width; } bool oldclamps = stageLaunchClamps; GUILayout.BeginHorizontal(); stageLaunchClamps = GUILayout.Toggle(stageLaunchClamps, new GUIContent(" Stage launch clamps", launchclampTexture, "Move launch clamps to the bottom or next-to-bottom stage"), togglestyle); GUILayout.EndHorizontal(); if (stageLaunchClamps != oldclamps) { if (!stageLaunchClamps) { // shrink window to old dimesions windowRect.height = minheight; windowRect.width = minwidth; } } if (stageLaunchClamps) { GUILayout.BeginHorizontal(); //GUILayout.Label ("Launch clamps:"); launchClampsStage = GUILayout.SelectionGrid(launchClampsStage, launchClampsText, 1, togglestyle); GUILayout.EndHorizontal(); } } GUILayout.BeginHorizontal(); vizualize = GUILayout.Toggle(vizualize, new GUIContent(" Show visualizations", "Show visualizations such as highlights and levels"), togglestyle); GUILayout.EndHorizontal(); #if DEBUG GUILayout.BeginHorizontal(); if (GUILayout.Button("DEV - Reload ship", buttonStyle)) { newReloadShip(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("DEV - Dump the ship", buttonStyle)) { ASPConsoleStuff.ListTheShip(); tanks = ASPStaging.findFuelTanks(EditorLogic.fetch.ship.Parts); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); if (GUILayout.Button("DEV - flush output buffer", buttonStyle)) { // flush output buffer for (int i = 1; i <= 20; i++) { print(""); } } GUILayout.EndHorizontal(); #endif GUI.DragWindow(); if (Event.current.type == EventType.Repaint) // why, Unity, why? { tooltip = GUI.tooltip; } }
/*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; } } } }