Advertisement
TheReadPanda

KSI Source Code

May 25th, 2016
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.94 KB | None | 0 0
  1. using KSP.UI;
  2. using System;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.UI;
  6.  
  7. namespace TRP_Hiring
  8. {
  9. [KSPAddon(KSPAddon.Startup.SpaceCentre, false)]
  10. class KSI_EditACPrefabs_SpaceCentre : MonoBehaviour
  11. {
  12. private void Awake() { gameObject.AddComponent<KSI_EditACPrefab>(); }
  13. }
  14.  
  15. [KSPAddon(KSPAddon.Startup.EditorAny, false)]
  16. class KSI_EditACPrefabs_Editor : KSI_EditACPrefabs_SpaceCentre { }
  17.  
  18.  
  19. class KSI_EditACPrefab : MonoBehaviour
  20. {
  21. private void Awake()
  22. {
  23. try
  24. {
  25. var prefab = GetAstronautComplexScreenPrefab();
  26.  
  27. // There isn't really any specific component we can look for to make it easier
  28. // without also making things less clear so a long transform path it is
  29. var listAndScrollbar = prefab.transform.Find(
  30. "RootCanvas/AstronautComplex anchor/GameObject/bg and aspectFitter/CrewAssignmentDialog/VL/ListAndScrollbar");
  31.  
  32. if (listAndScrollbar == null) throw new Exception("Couldn't find ListAndScrollbar Transform");
  33.  
  34. // temporarily detach Panel/scrolllist_applicants
  35. // we can't just delete it (or set it inactive apparently) or AstronautComplex will throw an exception
  36. //
  37. // we CAN, however, delete all the UI bits from it
  38. var panel = listAndScrollbar.transform.Find("Panel");
  39. Debug.Log("var Panel Worked");
  40. panel.SetParent(null);
  41.  
  42. panel.GetComponentsInChildren<ScrollRect>(true).ToList().ForEach(Destroy);
  43. panel.GetComponentsInChildren<Image>(true).ToList().ForEach(Destroy);
  44. panel.GetComponentsInChildren<CanvasRenderer>(true).ToList().ForEach(Destroy);
  45. panel.GetComponentsInChildren<Mask>(true).ToList().ForEach(Destroy);
  46. panel.GetComponentsInChildren<VerticalLayoutGroup>(true).ToList().ForEach(Destroy);
  47. panel.GetComponentsInChildren<ContentSizeFitter>(true).ToList().ForEach(Destroy);
  48. Debug.Log("Destroy Set");
  49. // destroy all the other children
  50. foreach (Transform ch in listAndScrollbar.transform)
  51. Destroy(ch.gameObject);
  52.  
  53. // reattach panel - AstronautComplex needs something inside here for something but now it won't be
  54. // rendering anything
  55. panel.SetParent(listAndScrollbar);
  56.  
  57. // we won't know what the dimensions our replacement will take until the UI is actually spawned,
  58. // so we'll slip a little trojan right alongside the component (RectTransform) that will contain
  59. // that info. This helper will create the GUI
  60. listAndScrollbar.gameObject.AddComponent<CustomAstronautComplexUISpawner>();
  61.  
  62.  
  63. }
  64. catch (Exception e)
  65. {
  66. Debug.LogError("Failed to edit Astronaut Complex: " + e);
  67. }
  68.  
  69. Destroy(gameObject); // once the spawner is attached to the prefab, this object no longer needed
  70. }
  71.  
  72.  
  73. private static UICanvasPrefab GetAstronautComplexScreenPrefab()
  74. {
  75. // the scene has just been entered and the AC shouldn't have spawned yet
  76. var spawner = FindObjectOfType<KSP.UI.Screens.ACSceneSpawner>();
  77.  
  78. if (spawner == null)
  79. throw new Exception("Did not find AC spawner");
  80. if (spawner.ACScreenPrefab == null)
  81. throw new Exception("AC spawner prefab is null");
  82.  
  83. // this might look bizarre, but Unity seems to crash if you mess with this prefab like we're
  84. // about to do. Luckily ACScreenPrefab is public so we'll quickly make a copy and use that
  85. // as the "prefab" instead
  86. var prefab = Instantiate(spawner.ACScreenPrefab);
  87. prefab.gameObject.SetActive(false);
  88.  
  89. spawner.ACScreenPrefab = prefab;
  90. Debug.Log(prefab.name);
  91. return prefab;
  92. }
  93.  
  94. }
  95.  
  96.  
  97.  
  98. // We'll have to wait until the AstronautComplex UI is actually spawned in
  99. // order to grab the dimensions of the area we'll be replacing. All the
  100. // visual bits should be handled by now so as soon as the panel is actually
  101. // visible, we can grab those dimensions and create the custom GUI using them
  102. class CustomAstronautComplexUISpawner : MonoBehaviour
  103. {
  104. private void Start()
  105. {
  106. #if DEBUG
  107. DebugDimensions();
  108. #endif
  109. // foreach (var textComponent in FindObjectsOfType<Component>()) Debug.Log(textComponent.name); This gave us the names of various 'parts'.
  110. Transform textTransform = FindObjectOfType<Text>().transform;
  111. while(textTransform != null)
  112. {
  113. Debug.Log(textTransform.name);
  114. textTransform = textTransform.transform.parent;
  115. }
  116.  
  117. var vectors = new Vector3[4];
  118. var uiCam = UIMasterController.Instance.GetComponentInChildren<UIMainCamera>();
  119.  
  120. if (uiCam == null)
  121. {
  122. Debug.LogError("UIMainCamera not found");
  123. return;
  124. }
  125.  
  126. var camera = uiCam.GetComponent<Camera>();
  127.  
  128. if (camera == null)
  129. {
  130. Debug.LogError("Camera attached to UIMainCamera not found");
  131. return;
  132. }
  133.  
  134. GetComponent<RectTransform>().GetWorldCorners(vectors);
  135.  
  136.  
  137. for (int i = 0; i < 4; ++i)
  138. vectors[i] = camera.WorldToScreenPoint(vectors[i]);
  139.  
  140.  
  141. // note: these are in screen space
  142. var rect = new Rect(vectors[1].x, Screen.height - vectors[1].y, vectors[2].x - vectors[1].x,
  143. vectors[2].y - vectors[3].y);
  144.  
  145. gameObject.AddComponent<CustomAstronautComplexUI>().Initialize(rect);
  146.  
  147. Destroy(this);
  148. }
  149.  
  150.  
  151. private void DebugDimensions()
  152. {
  153. print("Debugging dimensions");
  154.  
  155. var vectors = new Vector3[4];
  156. var camera = UIMasterController.Instance.GetComponentInChildren<UIMainCamera>().GetComponent<Camera>();
  157.  
  158. GetComponent<RectTransform>().GetWorldCorners(vectors);
  159.  
  160. foreach (var item in vectors)
  161. print("Corner: " + item);
  162.  
  163. for (int i = 0; i < 4; ++i)
  164. {
  165. vectors[i] = camera.GetComponent<Camera>().WorldToScreenPoint(vectors[i]);
  166. print("Transformed corner: " + vectors[i]);
  167. }
  168. }
  169. }
  170.  
  171.  
  172. /// <summary>
  173. /// This bit draws the GUI using the legacy GUI. You could easily use the new GUI instead if you prefer
  174. /// </summary>
  175. class CustomAstronautComplexUI : MonoBehaviour
  176. {
  177. private Rect _areaRect = new Rect(-500f, -500f, 200f, 200f);
  178. private Vector2 _guiScalar = Vector2.one;
  179. private Vector2 _guiPivot = Vector2.zero;
  180. private Vector2 _scrollbar = Vector2.zero;
  181. private readonly Texture2D _portraitMale = AssetBase.GetTexture("kerbalicon_recruit");
  182. private readonly Texture2D _portraitFemale = AssetBase.GetTexture("kerbalicon_recruit_female");
  183. private GUIStyle _backgroundStyle; // the background of the whole area our GUI will cover
  184. private GUIStyle _scrollviewStyle; // style of the whole scrollview
  185. private GUIStyle _nameStyle; // style used for kerbal names
  186. private GUIStyle _listItemEntryStyle; // style used for background of each kerbal entry
  187.  
  188. private void Awake()
  189. {
  190. enabled = false;
  191. _backgroundStyle = new GUIStyle(HighLogic.Skin.window)
  192. {
  193. padding = new RectOffset(),
  194. border = new RectOffset()
  195. };
  196.  
  197. _scrollviewStyle = new GUIStyle(HighLogic.Skin.scrollView)
  198. {
  199. padding = new RectOffset(),
  200. border = new RectOffset()
  201. };
  202.  
  203. _nameStyle = new GUIStyle(HighLogic.Skin.label);
  204. _nameStyle.fontSize = (int)(_nameStyle.fontSize * 1.6);
  205. _nameStyle.fontStyle = FontStyle.Bold;
  206.  
  207. // set up a style that will cause the moused over entry to highlight itself. Makes the UI feel a little more
  208. // interactive
  209. _listItemEntryStyle = new GUIStyle(HighLogic.Skin.box);
  210.  
  211. var clone = Instantiate(_listItemEntryStyle.normal.background);
  212. var pixels = clone.GetPixels32();
  213.  
  214. // poor man's lighting algorithm
  215. for (int i = 0; i < pixels.Length; ++i)
  216. pixels[i] = new Color32(
  217. Math.Min((byte)255, (byte)(pixels[i].r + 25)),
  218. Math.Min((byte)255, (byte)(pixels[i].g + 25)),
  219. Math.Min((byte)255, (byte)(pixels[i].b + 25)),
  220. Math.Min((byte)255, (byte)(pixels[i].a + 25)));
  221.  
  222. clone.SetPixels32(pixels);
  223. clone.Apply();
  224.  
  225. _listItemEntryStyle.hover.background = clone;
  226. }
  227.  
  228.  
  229. public void Initialize(Rect guiRect)
  230. {
  231. var uiScaleMultiplier = GameSettings.UI_SCALE;
  232.  
  233. // the supplied rect will have the UI scalar already factored in
  234. //
  235. // to respect the player's UI scale wishes, work out what the unscaled rect
  236. // would be. Then we'll apply the scale again in OnGUI so all of our GUILayout elements
  237. // will respect the multiplier
  238. var correctedRect = new Rect(guiRect.x, guiRect.y, guiRect.width / uiScaleMultiplier,
  239. guiRect.height / uiScaleMultiplier);
  240.  
  241. _areaRect = correctedRect;
  242.  
  243. _guiPivot = new Vector2(_areaRect.x, _areaRect.y);
  244. _guiScalar = new Vector2(GameSettings.UI_SCALE, GameSettings.UI_SCALE);
  245.  
  246. enabled = true;
  247. }
  248.  
  249.  
  250. private static readonly string[] FlavorText = new[]
  251. {
  252. "Loves space! Does not have any other qualifications",
  253. "Enjoys explosions of all kinds",
  254. "Was dared to do it",
  255. "Craves fame",
  256. "Might have some kind of death wish",
  257. "Heard it paid well",
  258. "Wants to go very fast"
  259. };
  260.  
  261. // these slightly reduce garbage created by avoiding array allocations which is one reason OnGUI
  262. // is so terrible
  263. private static readonly GUILayoutOption[] DefaultLayoutOptions = new GUILayoutOption[0];
  264. private static readonly GUILayoutOption[] PortraitOptions = { GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false) };
  265. private static readonly GUILayoutOption[] FixedWidth = { GUILayout.Width(220f) };
  266. private static readonly GUILayoutOption[] HireButtonOptions = { GUILayout.ExpandHeight(true), GUILayout.MaxHeight(40f), GUILayout.MinWidth(40f) };
  267. private static readonly GUILayoutOption[] StatOptions = { GUILayout.MaxWidth(100f) };
  268. private static readonly GUILayoutOption[] FlavorTextOptions = { GUILayout.MaxWidth(200f) };
  269.  
  270. private void OnGUI()
  271. {
  272. GUIUtility.ScaleAroundPivot(_guiScalar, _guiPivot);
  273.  
  274. GUILayout.BeginArea(_areaRect, _backgroundStyle);
  275. {
  276. _scrollbar = GUILayout.BeginScrollView(_scrollbar, false, true, HighLogic.Skin.horizontalScrollbar, HighLogic.Skin.verticalScrollbar, _scrollviewStyle, DefaultLayoutOptions);
  277. {
  278. for (int i = 0; i < 25; ++i) // make sure the scrollbars and stuff works as expected
  279. {
  280. bool male = i % 2 == 0;
  281.  
  282. GUILayout.BeginHorizontal(_listItemEntryStyle, DefaultLayoutOptions);
  283. {
  284. GUILayout.Space(8f);
  285. GUILayout.Box(male ? _portraitMale : _portraitFemale, GUIStyle.none, PortraitOptions);
  286.  
  287. GUILayout.BeginVertical(DefaultLayoutOptions);
  288. {
  289. GUILayout.Label(male ? "John Kerman" : "Jane Kerman", _nameStyle, FixedWidth);
  290. GUILayout.FlexibleSpace();
  291.  
  292. // indent flavor text just a bit
  293. GUILayout.BeginHorizontal(DefaultLayoutOptions);
  294. {
  295. GUILayout.Space(20f);
  296. GUILayout.Label(FlavorText[i % FlavorText.Length], FlavorTextOptions);
  297. }
  298. GUILayout.EndHorizontal();
  299. }
  300. GUILayout.EndVertical();
  301.  
  302.  
  303. GUILayout.FlexibleSpace();
  304. GUILayout.BeginVertical(DefaultLayoutOptions);
  305. {
  306. GUILayout.FlexibleSpace();
  307. GUILayout.Label("Courage here", StatOptions);
  308. GUILayout.Label("Stupidity here", StatOptions);
  309. GUILayout.FlexibleSpace();
  310. }
  311. GUILayout.EndVertical();
  312.  
  313. GUILayout.BeginVertical(DefaultLayoutOptions);
  314. {
  315. GUILayout.FlexibleSpace();
  316. GUILayout.Button("Hire", HighLogic.Skin.button, HireButtonOptions); // logic to hire Kerbal here
  317. GUILayout.FlexibleSpace();
  318. }
  319. GUILayout.EndVertical();
  320. }
  321. GUILayout.EndHorizontal();
  322. }
  323. }
  324. GUILayout.EndScrollView();
  325. }
  326. GUILayout.EndArea();
  327. }
  328. }
  329. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement