//Draw function for the window private void drawTargeter(int windowID) { int i, j; //Draw the search box first so it keeps its focus if (expand) { GUIStyle textFieldStyle = GUI.skin.GetStyle("TextField"); textFieldStyle.padding = new RectOffset(3, 3, 1, 1); searchStr = GUI.TextField(new Rect(6, pos.height - 24, pos.width - 13 - 23 * filters.Count, 18), searchStr, textFieldStyle); } //Display the current target String curTarg = "Target: "; if (FlightGlobals.fetch != null && FlightGlobals.fetch.VesselTarget != null) //Is there an active target? curTarg += FlightGlobals.fetch.VesselTarget.GetName(); else curTarg += "(None)"; //Display only title if collapsed float titleWidth = pos.width - 22 - 20; if (!expand) { curTarg = "Targetron v" + VERSION; titleWidth = pos.width - 30; } leftStyle.normal.textColor = new Color(1.0f, 0.858f, 0.0f); //Orange GUI.Label(new Rect(6, 0, titleWidth, 24), curTarg, leftStyle); if (expand) { GUIContent temp = null; switch (sortMode) { case 0: temp = new GUIContent(buttonDistAsc, "Sorting By Distance (Ascending)"); break; case 1: temp = new GUIContent(buttonDistDesc, "Sorting By Distance (Descending)"); break; case 2: temp = new GUIContent(buttonNameAsc, "Sorting By Name (Ascending)"); break; case 3: temp = new GUIContent(buttonNameDesc, "Sorting By Name (Descending)"); break; } if (GUI.Button(new Rect(pos.width - 22 - 20, 1, 20, 20), temp, buttonStyle)) { if (Event.current.button == 1) { sortMode--; if (sortMode < 0) sortMode = 3; } else { sortMode++; if (sortMode > 3) sortMode = 0; } switch (sortMode) { case 0: targets.Sort(sortByDistanceA); //Sort target vessels by their distance from the active ship break; case 1: targets.Sort(sortByDistanceD); //Sort target vessels by their distance from the active ship break; case 2: targets.Sort(sortByDistanceA); targets.Sort((x, y) => String.CompareOrdinal(x.vessel.GetName(), y.vessel.GetName())); break; case 3: targets.Sort(sortByDistanceA); targets.Sort((y, x) => String.CompareOrdinal(x.vessel.GetName(), y.vessel.GetName())); break; } } } //Display toggle for collapsing window String tooltipText = "Minimize"; if (!expand) tooltipText = "Maximize"; expand = GUI.Toggle(new Rect(pos.width - 20, 4, 20, 20), expand, new GUIContent(string.Empty, tooltipText), expandStyle); if (expand) //If window is expanded { if (pos.height == 20) expandWindow(); //Expand window if it has not already been done //Display the scroll view for target list scrollPosition = GUI.BeginScrollView(new Rect(4, 24, pos.width - 8, pos.height - 27 - 22), scrollPosition, new Rect(1, 16, pos.width - 33, top > pos.height - 27 - 22 ? top : pos.height - 27 - 22), false, true); top = 0; int vesselFilter; float diff; foreach (Target target in targets) //Iterate through each target vessel { bool showVessel = true; if (target == null || target.vessel == null || target.vessel.transform == null) showVessel = false; else if (searchStr.Length > 0 && !target.vessel.GetName().ToLower().Contains(searchStr.ToLower())) showVessel = false; else { for (i = 0; i < filters.Count; i++) { if (filters[i].matchType(target.vessel.vesselType, vesselTypes) && !filters[i].Enabled) showVessel = false; } } if (!showVessel) continue; vesselFilter = 0; for (i = 0; i < filters.Count; i++) { if (target.vessel.vesselType == filters[i].Type) vesselFilter = i; } GUILayout.BeginHorizontal(new GUIContent(filters[vesselFilter].Texture), rowStyle, GUILayout.Width(pos.width - 33), GUILayout.Height(24)); GUILayout.Space(22); //If the vessel name is too large to display, add ellipsis (...) and cut to length try { String _name = target.vessel.GetName(); diff = pos.width - 55 - rightStyle.CalcSize(new GUIContent("(" + formatDistance(target.lastDistance) + ")")).x - 42; if (leftStyle.CalcSize(new GUIContent(_name)).x - 2 >= diff - 2) { _name = _name.Substring(0, _name.Length - 1); for (j = 0; j < target.vessel.GetName().Length; j++) { _name = _name.Substring(0, _name.Length - 1); if (leftStyle.CalcSize(new GUIContent(_name + "...")).x + 2 <= diff - 2) break; } _name += "..."; } //Set the text color if (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.Equals(target.vessel)) leftStyle.normal.textColor = new Color(1.0f, 0.858f, 0.0f); //Orange for current target else if (target.vessel.isCommandable) leftStyle.normal.textColor = new Color(0.718f, 0.996f, 0.0f); //Green if vessel can be controlled else leftStyle.normal.textColor = new Color(0.756f, 0.756f, 0.756f); //Gray for debris rightStyle.normal.textColor = leftStyle.normal.textColor; //Match distance color to name //Display the vessel name GUILayout.Label(_name, leftStyle, GUILayout.Width(diff), GUILayout.Height(24)); //Context opens on right click unless in IVA mode int contextBtn = 1; if (Camera.current != null && Camera.current.name != null && (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA || CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal)) contextBtn = 0; //Check if vessel name is right clicked (normal) or left clicked (IVA) Rect lastRect = GUILayoutUtility.GetLastRect(); lastRect.x -= 23; lastRect.width = pos.width - 70; if (lastRect.Contains(Event.current.mousePosition) && Event.current.type == EventType.mouseUp && Event.current.button == contextBtn) contextActive = target; //Display the distance GUILayout.Label("(" + formatDistance(target.lastDistance) + ")", rightStyle, GUILayout.ExpandWidth(false)); //Add button to set vessel as target if (GUILayout.Button(new GUIContent(buttonTarget, "Set as Target"), buttonStyle)) FlightGlobals.fetch.SetVesselTarget(target.vessel); //Add button to control vessel if (GUILayout.Button(new GUIContent(buttonRocket, "Control Vessel"), buttonStyle)) { saveConfig(); //GamePersistence.SaveGame("persistent", HighLogic.SaveFolder, SaveMode.OVERWRITE); FlightGlobals.SetActiveVessel(target.vessel); } } catch (Exception e) { Debug.Log("Targetron Error: Failed to draw vessel listing\n" + e.StackTrace); } GUILayout.EndHorizontal(); top += 24; } // For testing purposes /* for (int i = 0; i < 50; i++) { GUILayout.BeginHorizontal(GUILayout.Width(pos.width - 41), GUILayout.Height(24)); String name = "Totally sweet, but long name " + i*i*i; float diff = pos.width - 41 - rightStyle.CalcSize(new GUIContent("(" + formatDistance(1024 * i) + ")")).x - 50; if (leftStyle.CalcSize(new GUIContent(name)).x > diff) { for (int j = 0; j < name.Length - 2; j++) { name = name.Substring(0, name.Length - 1); if (leftStyle.CalcSize(new GUIContent(name + "...")).x <= diff) break; } name += "..."; } GUILayout.Label(name, leftStyle, GUILayout.Width(diff)); GUILayout.Label("(" + formatDistance(1024 * i) + ")", rightStyle, GUILayout.ExpandWidth(false)); if (GUILayout.Button(new GUIContent(buttonTarget, "Set as Target"), buttonStyle)) { } if (GUILayout.Button(new GUIContent(buttonRocket, "Control Vessel"), buttonStyle)) { } GUILayout.EndHorizontal(); top += 24; }*/ GUI.EndScrollView(); //Draw each filter button, graying it out if disabled for (i = 0; i < filters.Count; i++) { if (filters[i].Enabled) { GUI.contentColor = enabledColor; GUI.backgroundColor = enabledBGColor; } else { GUI.contentColor = disabledColor; GUI.backgroundColor = disabledBGColor; } if ( !GUI.Button(new Rect(pos.width - 28 - 23 * i, pos.height - 25, 24, 24), new GUIContent(filters[i].Texture, filters[i].getName()), buttonStyle2)) continue; filters[i].toggle(); if (Event.current.button == 1) { filterRC = i; filterRCval = filters[i].Enabled; } else { if (filterRC >= 0) { if (i > filterRC) { for (j = filterRC + 1; j <= i; j++) filters[j].Enabled = filterRCval; } else { for (j = i; j < filterRC; j++) filters[j].Enabled = filterRCval; } } filterRC = -1; } } GUI.contentColor = enabledColor; GUI.backgroundColor = enabledBGColor; //Establish resize handles at bottom left and bottom right of the screen Vector3 mousePos = Input.mousePosition; mousePos.y = Screen.height - mousePos.y; // Convert to GUI coords Rect windowHandle = new Rect(pos.x + pos.width - 4, pos.y + pos.height - 4, 4, 4); //Bottom right handle Rect windowHandle2 = new Rect(pos.x, pos.y + pos.height - 6, 6, 6); //Bottom left handle if (!handleClicked && !handleClicked2 && windowHandle.Contains(mousePos)) //Check if mouse is within bottom right handle { //Set the cursor to NW resize Cursor.SetCursor(cursorResizeNW, new Vector2(16, 16), CursorMode.Auto); resetCursor = true; if (Input.GetMouseButtonDown(0)) //Check if left mouse button is pressed { handleClicked = true; //Set flag for bottom right handle clickedPosition = mousePos; //Save click position originalWindow = pos; //Save original window position/size } } else if (!handleClicked && !handleClicked2 && windowHandle2.Contains(mousePos)) //Check if mouse is within bottom left handle { //Set the cursor to SW resize Cursor.SetCursor(cursorResizeSW, new Vector2(16, 16), CursorMode.Auto); resetCursor = true; if (Input.GetMouseButtonDown(0)) //Check if left mouse button is pressed { handleClicked2 = true; //Set flag for bottom left handle clickedPosition = mousePos; //Save click position originalWindow = pos; //Save original window position/size } } else if (!handleClicked && !handleClicked2 && resetCursor) { Cursor.SetCursor(null, Vector2.zero, CursorMode.Auto); //Reset the cursor resetCursor = false; } if ((handleClicked || handleClicked2)) //If either resize handle is active { // Resize window by dragging if (Input.GetMouseButton(0)) { if (handleClicked) //Bottom right handle { pos.width = Mathf.Clamp(originalWindow.width + (mousePos.x - clickedPosition.x), minWindowWidth, maxWindowWidth); pos.height = Mathf.Clamp(originalWindow.height + (mousePos.y - clickedPosition.y), minWindowHeight, maxWindowHeight); } else //Bottom left handle { pos.width = Mathf.Clamp(originalWindow.width + (clickedPosition.x - mousePos.x), minWindowWidth, maxWindowWidth); pos.x = originalWindow.x - pos.width + originalWindow.width; pos.height = Mathf.Clamp(originalWindow.height + (mousePos.y - clickedPosition.y), minWindowHeight, maxWindowHeight); } } // Finish resizing window if (Input.GetMouseButtonUp(0)) { handleClicked = false; handleClicked2 = false; } } } else if (pos.height > 20) //Collapse flag set, check if collapse is needed collapseWindow(); //Collapse the window tooltip = GUI.tooltip; //Make window draggable with left mouse button if (!handleClicked && !handleClicked2 && !Input.GetMouseButton(1)) GUI.DragWindow(); }
private void OnDraw() { if (!toggleOn || !inFlight) return; // Get the current skin for later restore GUISkin defSkin = GUI.skin; // Set the ksp skin GUI.skin = HighLogic.Skin; if (buttonStyle == null) { initStyles(); //Collapse the window, if necessary if (!expand) collapseWindow(); } //Make sure the window isn't dragged off screen if (pos.x < 0) pos.x = 0; if (pos.y < 0) pos.y = 0; if (pos.x > Screen.width - pos.width) pos.x = Screen.width - pos.width; if (pos.y > Screen.height - pos.height) pos.y = Screen.height - pos.height; //Display the window pos = GUI.Window(WINDOWID_GUI, pos, drawTargeter, string.Empty); if (contextActive != null) { if (!contextActive.Equals(lcontextActive)) { String longestText = "Control Vessel"; //if (!contextActive.vessel.loaded) // longestText = "Queue Vessel Rename"; int numDocks = 0; foreach (ModuleDockingNode m in contextActive.availableDocks) { numDocks++; if (("Target " + m.part.partInfo.title).Length > longestText.Length) longestText = "Target " + m.part.partInfo.title; } Vector2 textSize = contextStyle.CalcSize(new GUIContent(longestText)); float left = Input.mousePosition.x - 25; float _top = Screen.height - Input.mousePosition.y + 10; if (left + textSize.x + 5 > Screen.width) left = Screen.width - textSize.x - 5; if (left < 0) left = 0; if (_top + (numDocks + 3) * Mathf.RoundToInt(contextStyle.fixedHeight) > Screen.height) _top = Screen.height - Mathf.RoundToInt(contextStyle.fixedHeight) - numDocks * Mathf.RoundToInt(contextStyle.fixedHeight); if (_top < 0) _top = 0; contextPos = new Rect(left, _top, textSize.x + 5, (numDocks + 3) * Mathf.RoundToInt(contextStyle.fixedHeight)); lcontextActive = contextActive; } contextPos = GUI.Window(WINDOWID_CONTEXT, contextPos, drawContext, string.Empty); GUI.BringWindowToFront(WINDOWID_CONTEXT); } else lcontextActive = null; //Display the tooltip, if necessary if (contextActive == null && tooltip != string.Empty) { Vector2 textSize = tooltipStyle.CalcSize(new GUIContent(tooltip)); float left = Input.mousePosition.x + 5; float _top = Screen.height - Input.mousePosition.y - 35; if (left + textSize.x + 10 > Screen.width) left = Screen.width - textSize.x - 10; if (_top < 0) _top = 0; tooltipPos = new Rect(left, _top, textSize.x + 10, textSize.y - 3); tooltipPos = GUI.Window(WINDOWID_TOOLTIP, tooltipPos, drawTooltip, string.Empty); GUI.BringWindowToFront(WINDOWID_TOOLTIP); } //Highlight target red if docking node /*if (FlightGlobals.fetch.VesselTarget is ModuleDockingNode) { ModuleDockingNode d = (ModuleDockingNode)FlightGlobals.fetch.VesselTarget; //Create specific instance to acccess docking node details d.part.SetHighlightColor(Color.red); d.part.SetHighlight(true); } else if (contextActive != null && activeDockingNode != null && activeDockingNode.part.highlightType == Part.HighlightType.Disabled) activeDockingNode.part.SetHighlight(true); if (lastActiveDockingNode != null && (contextActive == null || activeDockingNode == null || !lastActiveDockingNode.Equals(activeDockingNode))) { lastActiveDockingNode.part.SetHighlight(false); lastActiveDockingNode = null; }*/ // Restore the skin so we don't interfere others plugins skins? GUI.skin = defSkin; }
//Draw the right click context menu window contents private void drawContext(int windowID) { int _top = 0; if (GUI.Button(new Rect(0, _top, contextPos.width, 20), "Target Vessel", contextStyle)) { if (contextActive != null) FlightGlobals.fetch.SetVesselTarget(contextActive.vessel); contextActive = null; } _top += Mathf.RoundToInt(contextStyle.fixedHeight); if (GUI.Button(new Rect(0, _top, contextPos.width, 20), "Control Vessel", contextStyle)) { saveConfig(); //GamePersistence.SaveGame("persistent", HighLogic.SaveFolder, SaveMode.OVERWRITE); if (contextActive != null) FlightGlobals.SetActiveVessel(contextActive.vessel); contextActive = null; } _top += Mathf.RoundToInt(contextStyle.fixedHeight); const string renameStr = "Rename Vessel"; String renameHint = string.Empty; if (contextActive != null && !contextActive.vessel.loaded) { //renameStr = "Queue Vessel Rename"; renameHint = "Too far to rename"; GUI.enabled = false; } if (GUI.Button(new Rect(0, _top, contextPos.width, 20), new GUIContent(renameStr, renameHint), contextStyle)) { if (contextActive != null) contextActive.vessel.RenameVessel(); contextActive = null; } GUI.enabled = true; _top += Mathf.RoundToInt(contextStyle.fixedHeight); if (contextActive == null) return; lastActiveDockingNode = activeDockingNode; activeDockingNode = null; foreach (ModuleDockingNode m in contextActive.availableDocks) { if (Vector3.Distance(FlightGlobals.ActiveVessel.GetTransform().position, m.GetTransform().position) >= 196.0f) GUI.enabled = false; GUIStyle temp = contextStyle; if (FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget.Equals(m)) temp = contextStyle2; if (new Rect(0, _top, contextPos.width, 20).Contains(Event.current.mousePosition)) { m.part.SetHighlightColor(Color.red); m.part.SetHighlight(true); } else { m.part.SetHighlightDefault(); m.part.SetHighlight(false); } if (GUI.Button(new Rect(0, _top, contextPos.width, 20), "Target " + m.part.partInfo.title, temp)) { FlightGlobals.fetch.SetVesselTarget(m); m.part.SetHighlightDefault(); m.part.SetHighlight(false); contextActive = null; } GUI.enabled = true; _top += Mathf.RoundToInt(contextStyle.fixedHeight); } }
private static int sortByDistanceD(Target a, Target b) { return sortByDistance(b, a); }
private static int sortByDistanceA(Target a, Target b) { return sortByDistance(a, b); }
//Sorts Vessels by their distance from the active vessel private static int sortByDistance(Target a, Target b) { if (FlightGlobals.fetch == null || FlightGlobals.fetch.activeVessel == null || FlightGlobals.fetch.activeVessel.transform == null) return 0; if (a.vessel == null && b.vessel == null) return 0; if (a.vessel == null && b.vessel != null) return 1; if (a.vessel != null && b.vessel == null) return -1; if (a.vessel != null && (a.vessel.orbit != null && FlightGlobals.fetch.activeVessel.orbit.referenceBody == a.vessel.orbit.referenceBody)) { if (b.vessel != null && (b.vessel.orbit == null || a.vessel.orbit.referenceBody != b.vessel.orbit.referenceBody)) return -1; } if (b.vessel != null && (b.vessel.orbit == null || FlightGlobals.fetch.activeVessel.orbit.referenceBody != b.vessel.orbit.referenceBody)) return a.lastDistance.CompareTo(b.lastDistance); if (b.vessel != null && (a.vessel != null && (a.vessel.orbit == null || a.vessel.orbit.referenceBody != b.vessel.orbit.referenceBody))) return 1; return a.lastDistance.CompareTo(b.lastDistance); }
public void Update() { if (FlightGlobals.fetch != null && FlightGlobals.fetch.vessels != null && FlightGlobals.fetch.activeVessel != null) //Check if in flight { if (!inFlight) inFlight = true; //Update the list of nearby vessels every 1s if (expand && toggleOn && DateTime.Now.Ticks > lastChecked + 10000000) { lastChecked = DateTime.Now.Ticks; //Save the list check time //targets.Clear(); //Clear the target vessel list bool found; foreach (Vessel vessel in FlightGlobals.fetch.vessels) //Iterate through each available vessel { if (!vessel.Equals(FlightGlobals.fetch.activeVessel)) { found = false; foreach (Target t in targets) { if (vessel.GetInstanceID() == t.vessel.GetInstanceID()) { found = true; t.update(); break; } } if (!found) targets.Add(new Target(vessel, null, 0)); //Add the vessel to the target vessel list, if it is not the active ship } } //foreach (Target t in targets) //{ // if (!FlightGlobals.fetch.vessels.Contains(t.vessel) || t.vessel.Equals(FlightGlobals.fetch.activeVessel)) // targets.Remove(t); //} targets = targets.Where(target => FlightGlobals.fetch.vessels.Contains(target.vessel) && !target.vessel.Equals(FlightGlobals.fetch.activeVessel)).ToList(); switch (sortMode) { case 0: targets.Sort(sortByDistanceA); //Sort target vessels by their distance from the active ship break; case 1: targets.Sort(sortByDistanceD); //Sort target vessels by their distance from the active ship break; case 2: targets.Sort(sortByDistanceA); targets.Sort((x, y) => String.CompareOrdinal(x.vessel.GetName(), y.vessel.GetName())); break; case 3: targets.Sort(sortByDistanceA); targets.Sort((y, x) => String.CompareOrdinal(x.vessel.GetName(), y.vessel.GetName())); break; } //Find available docks List<uint> dockerIDs = new List<uint>(); foreach (Target t in targets) { t.availableDocks.Clear(); if (!t.vessel.loaded) continue; //Iterate twice, first to get IDs of docked nodes, then to add other ports to list of available for (int i = 0; i < 2; i++) { foreach (Part p in t.vessel.parts) //Iterate through all parts { foreach (PartModule m in p.Modules) //Iterate through all modules of each part { if (!m.ClassName.Equals("ModuleDockingNode")) continue; ModuleDockingNode d = (ModuleDockingNode)m; //Create specific instance to acccess docking node details if (i == 0) //First loop iteration, compile docked port IDs { if (d.state.ToLower().Contains("docked")) //Port is a "docker" { dockerIDs.Add(d.part.flightID); //ID of current part dockerIDs.Add(d.dockedPartUId); //ID of docked part } } else //Second iteration, add undocked modules to list of available { if (!dockerIDs.Contains(d.part.flightID)) t.availableDocks.Add(d); } } } } } } } else if (inFlight) { inFlight = false; saveConfig(); contextActive = null; filterRC = -1; } //Close the context menu on left click anywhere outside of it if (contextActive != null && Input.GetMouseButton(0) && !contextPos.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y))) contextActive = null; if (filterRC >= 0 && (Input.GetMouseButton(0) || Input.GetMouseButton(1)) && !pos.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y))) filterRC = -1; //Close the context menu on right click when in IVA if (contextActive != null && (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA || CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal) && Input.GetMouseButton(1)) contextActive = null; }