diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Changelog.txt b/Distribution/GameData/REPOSoftTech/DeepFreeze/Changelog.txt index d8c420a..4f49a49 100644 --- a/Distribution/GameData/REPOSoftTech/DeepFreeze/Changelog.txt +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/Changelog.txt @@ -1,4 +1,10 @@ -V0.22.1.0 "KSP 1.1.2 Update" +V0.22.2.0 "Bug Fixes" +Fixed bug with Icons not loading on Linux. +Efficiency clean-up on code modules (speed and memory use). +Fix bug where DeepFreeze is not maintaining and updating Vessel Information for Vessels with Freezer parts, causing Exceptions in the log and vessels not +appearing in the Vessel List in the DeepFreeze GUI window. +Moved Config.cfg file from Plugins to /Plugins/PluginData to prevent resetting Module Manager cache every time you change a setting. +V0.22.1.0 "KSP 1.1.2 Update" Fixed portrait camera issues. Fixed On-Screen messages for Kerbal Name when in Alternate - Cryopod Camera mode. Fixed spacing (scroll lists) in the DeepFreeze GUI menus. diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version b/Distribution/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version index a0dbf4c..ce4b59f 100644 --- a/Distribution/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version +++ b/Distribution/GameData/REPOSoftTech/DeepFreeze/DeepFreezeContinued.version @@ -2,8 +2,8 @@ "NAME":"DeepFreeze Continued...", "URL":"http://ksp-avc.cybutek.net/version.php?id=183", "DOWNLOAD":"http://spacedock.info/mod/142/DeepFreeze%20Continued...", -"VERSION":{"MAJOR":0,"MINOR":22,"PATCH":1,"BUILD":0}, +"VERSION":{"MAJOR":0,"MINOR":22,"PATCH":2,"BUILD":0}, "KSP_VERSION":{"MAJOR":1,"MINOR":1,"PATCH":2}, -"KSP_VERSION_MIN":{"MAJOR":1,"MINOR":1,"PATCH":1}, +"KSP_VERSION_MIN":{"MAJOR":1,"MINOR":1,"PATCH":2}, "KSP_VERSION_MAX":{"MAJOR":1,"MINOR":1,"PATCH":2} } \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze_bundle.xml b/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze_bundle.xml deleted file mode 100644 index 24df987..0000000 --- a/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze_bundle.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - JPLRepo - KSPedia Screens for the DeepFreeze mod. - - - - - - - - - - squadcore - - \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze_kspedia.xml b/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze_kspedia.xml deleted file mode 100644 index 06e9e99..0000000 --- a/Distribution/GameData/REPOSoftTech/DeepFreeze/KSPedia/deepfreeze_kspedia.xml +++ /dev/null @@ -1,159 +0,0 @@ - - - - - DeepFreeze - DeepFreezeMain - - - - Parts - DeepFreezeParts - - - - - Settings - DeepFreezeSettings - - - - - VesselMenu - DeepFreezeVesselMenu - - - - - KACMenu - DeepFreezeKACMenu - - - - - - - - - deepfreeze - Assets/KSPedia/DeepFreezeVesselMenu.prefab - - <Background /> - <Text> - <Text Name="TextDesc1"> - <Text>The vessel Menu - Shown by clicking the DeepFreeze Icon. -The top half of the screen shows you all known Vessels that contain DeepFreeze Freezer parts. -If you have set EC usage and/or Temperature usage settings on in the settings menu you will see the Temperature and/or the current EC status of each part in this menu.</Text> - </Text> - <Text Name="TextDesc2"> - <Text>EC and Tmp Status Values are colour coded. -If you have Remote Tech mod installed you will also see the Remote Tech status. -If you have Kerbal Alarm Clock installed any Alarms associated with a vessel will show an Alarms Button (see the Alarms KSPedia entry). -LastUpd - Indicates the last time the vessel was active and had it's EC and temperature actively updated. -TimeRem - Is approx. time remaining for EC based on current Freezer usage. -In the bottom half of the window will be a list of all Kerbals that are on-board a known Freezer in flight. Freeze & Thaw buttons will appear and allow you to Freeze or thaw your kerbals.</Text> - </Text> - <Text Name="TextDesc3"> - <Text>Lots of information is displayed about your Freezer in the part right click menu. You can also access the Vessel Menu and Freeze and Thaw your kerbals from here.</Text> - </Text> - </Text> - <Tooltips /> - </Screen> - <Screen Name="DeepFreezeSettings"> - <BundleName>deepfreeze</BundleName> - <AssetPath>Assets/KSPedia/DeepFreezeSettings.prefab</AssetPath> - <Title /> - <Background /> - <Text> - <Text Name="TextDesc1"> - <Text>The Settings Menu Options In Order: -- If ElectricCharge is required to run Freezers when there are frozen kerbals. -- If on running out of EC or over Temp freezers will kill frozen kerbals. -- If previous is on kerbals will become comatose for this period of time instead of being killed. -- If on frozen kerbals will be thawed out automatically when vessels are recovered. -- If previous is on the cost of funds to thaw each frozen kerbal automatically. -- The amount of ElectricCharge to thaw or freeze a kerbal in flight. -- The amount of Glykerol required to freeze a kerbal in flight. -- If on Temperature regulation of freezer parts is required. -- If previous is on the minimum temperature a freezer must have (internal) in order to freeze a kerbal successfully (temperature can be seen via the DeepFreeze vessel window or via the part right click menu). -- The maximum temperature a freezer can be to maintain frozen kerbals. -- The amount of heat generated by a Cryopod during a thaw or freeze process. -- The amount of heat generated by the Freezer to maintain each frozen kerbal inside. -- If on Temperatures in menus are shown in Kelvin, if off temperatures are show in Celcius. -- If on Stock application launcher Icon is used. If off (and you have it installed) the Toolbar Mod Icons will be used. -- If on strip lights in Freezers (that have them) will animate. -- Spam the log with lots of debug messages (use for capturing logs for reporting problems). -- If on you get lots of tooltips on every DeepFreeze menu item.</Text> - </Text> - </Text> - <Tooltips /> - </Screen> - <Screen Name="DeepFreezeParts"> - <BundleName>deepfreeze</BundleName> - <AssetPath>Assets/KSPedia/DeepFreezeParts.prefab</AssetPath> - <Title /> - <Background /> - <Text> - <Text Name="headingText"> - <Text>DeepFreeze</Text> - </Text> - <Text Name="TextDesc1"> - <Text>The CRY-0300 has animated doors and the CRY-0300R is transparent (with RasterPropMonitor installed). Both can hold One Kerbal and are equipped with one Cryopod. The CRY-0300R can be radially attached.</Text> - </Text> - <Text Name="TextDesc2"> - <Text>All DeepFreeze Freezers come with a built-in Glykerol storage tank of various capacities. But the Radial Glykerol Tank allows you to bring along extra Glykerol if required.</Text> - </Text> - <Text Name="TextDesc3"> - <Text>The CRY-1300 is a 2.5M Freezer with three Cryopod (kerbal) capacity.</Text> - </Text> - <Text Name="TextDesc4"> - <Text>The CRY-2300 is a 2.5M Freeze with ten Cryopod (kerbal) capacity.</Text> - </Text> - <Text Name="TextDesc5"> - <Text>The CRY-5000 (4 Cryopod) and the X200 Glykerol Container are actually distributed as part of the KPBS Mod but are DeepFreeze parts (and dependant) made to fit-in and be part of KPBS mod. </Text> - </Text> - </Text> - <Tooltips /> - </Screen> - <Screen Name="DeepFreezeMain"> - <BundleName>deepfreeze</BundleName> - <AssetPath>Assets/KSPedia/DeepFreezeMain.prefab</AssetPath> - <Title /> - <Background /> - <Text> - <Text Name="headingText"> - <Text>DeepFreeze</Text> - </Text> - <Text Name="TextDescription"> - <Text>DeepFreeze is a Mod that allows you to Freeze Kerbals using the magic of Glykerol and Electricity. Whilst frozen Kerbals will not consume any resources (from Life Support Mods).</Text> - </Text> - <Text Name="TextParts"> - <Text>DeepFreeze Freezer Parts come in a variety of sizes. From the CRY-0300 and CRY-0300R Single Kerbal Freezers right up to the 10 kerbal capacity CRY-2300.</Text> - </Text> - <Text Name="TextGUI"> - <Text>The GUI Window allows easy access to monitor all your vessels equiped with DeepFreezer parts and buttons to freeze and thaw your Kerbals.</Text> - </Text> - </Text> - <Tooltips /> - </Screen> - <Screen Name="DeepFreezeKACMenu"> - <BundleName>deepfreeze</BundleName> - <AssetPath>Assets/KSPedia/DeepFreezeKACMenu.prefab</AssetPath> - <Title /> - <Background /> - <Text> - <Text Name="TextDesc1"> - <Text>The DeepFreeze Alarms Menu is available if you have also installed the Kerbal Alarm Clock Mod. It can be accessed from the DeepFreeze Vessel Menu (Alarms button at the bottom of the window) at the Space Center or in flight (alarms buttons appear next to the vessels in the list (only if the vessel already has at least one KAC Alarm defined within Kerbal Alarm Clock mod itself.</Text> - </Text> - <Text Name="TextDesc2"> - <Text>Once you have defined a Kerbal Alarm Clock Alarm that is attached to one of your Deepfreeze equipped vessels you can access the Alarms Menu. -All Alarms will be shown for a vessel when selected and you can then modify each alarm. -For each Alarm you are able to define Thaw and/or Freeze commands for each Kerbal on-board. -When the KAC alarm is triggered any DeepFreeze commands you have assigned will be executed at that time. -NB: If you have the Remote Tech mod installed you are only able to modify the DeepFreeze commands that are attached to a KAC alarm IF you have active Remote Tech control of that vessel. You do not need control of the vessel for the commands, once defined, to execute when the alarm is triggered.</Text> - </Text> - </Text> - <Tooltips /> - </Screen> - </Screens> -</KSPedia> \ No newline at end of file diff --git a/Distribution/GameData/REPOSoftTech/DeepFreeze/Plugins/Config.cfg b/Distribution/GameData/REPOSoftTech/DeepFreeze/Plugins/PluginData/Config.cfg similarity index 100% rename from Distribution/GameData/REPOSoftTech/DeepFreeze/Plugins/Config.cfg rename to Distribution/GameData/REPOSoftTech/DeepFreeze/Plugins/PluginData/Config.cfg diff --git a/Source/DFEditorFilter.cs b/Source/DFEditorFilter.cs index ce6ee3b..f1dcb73 100644 --- a/Source/DFEditorFilter.cs +++ b/Source/DFEditorFilter.cs @@ -20,6 +20,8 @@ using KSP.UI.Screens; using RUI.Icons.Selectable; using UnityEngine; +using System.Reflection; +using System.Linq; namespace DF { @@ -46,7 +48,25 @@ private void Awake() { Debug.Log("DFEditorFilter Awake"); GameEvents.onGUIEditorToolbarReady.Add(SubCategories); - //ModuleManager.MMPatchLoader.addPostPatchCallback(DFMMCallBack); + /* + //Attempt to add Module Manager callback - find the base type + System.Type MMType = AssemblyLoader.loadedAssemblies + .Select(a => a.assembly.GetExportedTypes()) + .SelectMany(t => t) + .FirstOrDefault(t => t.FullName == "ModuleManager.MMPatchLoader"); + if (MMType != null) + { + MethodInfo MMPatchLoaderInstanceMethod = MMType.GetMethod("get_Instance", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + if (MMPatchLoaderInstanceMethod != null) + { + object actualMM = MMPatchLoaderInstanceMethod.Invoke(null, + BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static, null, null, null); + MethodInfo MMaddPostPatchCallbackMethod = MMType.GetMethod("addPostPatchCallback", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); + if (actualMM != null && MMaddPostPatchCallbackMethod != null) + MMaddPostPatchCallbackMethod.Invoke(actualMM, new object[] { this.DFMMCallBack() }); + } + + }*/ DFMMCallBack(); //load the icons icon_DeepFreeze_Editor.LoadImage(File.ReadAllBytes("GameData/REPOSoftTech/DeepFreeze/Icons/DeepFreezeEditor.png")); @@ -54,7 +74,7 @@ private void Awake() Debug.Log("DFEditorFilter Awake Complete"); } - public void DFMMCallBack() + public bool DFMMCallBack() { Debug.Log("DFEDitorFilter DFMMCallBack"); avPartItems.Clear(); @@ -68,6 +88,7 @@ public void DFMMCallBack() } } Debug.Log("DFEDitorFilter DFMMCallBack end"); + return true; } private bool EditorItemsFilter(AvailablePart avPart) diff --git a/Source/DFEnums.cs b/Source/DFEnums.cs new file mode 100644 index 0000000..c1a4fbe --- /dev/null +++ b/Source/DFEnums.cs @@ -0,0 +1,32 @@ +/* + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright(C) 2013 Squad.See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license.See<https://creativecommons.org/licenses/by-nc-sa/4.0/> + * for full details. + * + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace DF +{ + public enum DoorState + { + OPEN, + CLOSED, + OPENING, + CLOSING, + UNKNOWN + } +} diff --git a/Source/DFExtDoorMgr.cs b/Source/DFExtDoorMgr.cs new file mode 100644 index 0000000..5f433f0 --- /dev/null +++ b/Source/DFExtDoorMgr.cs @@ -0,0 +1,93 @@ +/* + * DeepFreeze Continued... + * (C) Copyright 2015, Jamie Leighton + * + * Kerbal Space Program is Copyright(C) 2013 Squad.See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. + * This File was not part of the original Deepfreeze but was written by Jamie Leighton. + * (C) Copyright 2015, Jamie Leighton + * + * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) + * creative commons license.See<https://creativecommons.org/licenses/by-nc-sa/4.0/> + * for full details. + * + */ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RSTUtils; + +namespace DF +{ + public class DFExtDoorMgr : InternalModule + { + private DeepFreezer Freezer; + + public override void OnUpdate() + { + base.OnUpdate(); + if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && FlightGlobals.ActiveVessel != null) + { + if (Freezer == null) + { + Freezer = part.FindModuleImplementing<DeepFreezer>(); + Utilities.Log_Debug("DFExtDoorMgr OnUpdate Set part " + part.name); + } + } + } + + public void ButtonExtDoor(bool state) + { + if (Freezer == null) + { + Freezer = part.FindModuleImplementing<DeepFreezer>(); + Utilities.Log_Debug("DFExtDoorMgr buttonExtDoorState set part " + part.name); + } + if (Freezer == null) return; // If freezer is still null just return + if (!Freezer.ExternalDoorActive) return; // if freezer doesn't have an external door just return. + + if (Freezer._externaldoorstate == DoorState.OPEN) + { + //Door is open so we trigger a closedoor. + Freezer.eventCloseDoors(); + Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired triggerred eventCloseDoors"); + } + else + { + if (Freezer._externaldoorstate == DoorState.CLOSED) + { + //Door is closed so we trigger a opendoor. + Freezer.eventOpenDoors(); + Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired triggerred eventOpenDoors"); + } + else + { + // door already opening or closing... + Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired but door state is opening, closing or unknown"); + } + } + } + + public bool ButtonExtDoorState() + { + // Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoorState fired"); + if (Freezer == null) + { + Freezer = part.FindModuleImplementing<DeepFreezer>(); + Utilities.Log_Debug("DFExtDoorMgr buttonExtDoorState set part " + part.name); + } + if (Freezer == null) return false; // if freezer still null return false + if (!Freezer.ExternalDoorActive) return false; // if freezer doesn't have an external door just return. + if (Freezer._externaldoorstate == DoorState.CLOSED || Freezer._externaldoorstate == DoorState.CLOSING || Freezer._externaldoorstate == DoorState.UNKNOWN) + { + Utilities.Log_Debug("DFExtDoorMgr Door is closed or closing or unknown return state false"); + return false; + } + Utilities.Log_Debug("DFExtDoorMgr Door is open or opening return state true"); + return true; + } + } +} diff --git a/Source/DFInstallFix.cs b/Source/DFInstallFix.cs deleted file mode 100644 index 26a88de..0000000 --- a/Source/DFInstallFix.cs +++ /dev/null @@ -1,59 +0,0 @@ -/** - * DFInstallFix.cs - * - * - * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This - * project is in no way associated with nor endorsed by Squad. - * - * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. - * This File was not part of the original Deepfreeze but was written by Jamie Leighton. - * (C) Copyright 2015, Jamie Leighton - * - * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) - * creative commons license. See <https://creativecommons.org/licenses/by-nc-sa/4.0/> - * for full details. - * - */ - -namespace DF -{ - public class DFInstallFix - { - private const string configNodeName = "DFFixes"; - - public bool fixtimecounts { get; set; } - - internal DFInstallFix() - { - fixtimecounts = false; - } - - //Settings Functions Follow - - internal void Load(ConfigNode node) - { - if (node.HasNode(configNodeName)) - { - ConfigNode DFsettingsNode = node.GetNode(configNodeName); - - fixtimecounts = Utilities.GetNodeValue(DFsettingsNode, "fixtimecounts", fixtimecounts); - } - } - - internal void Save(ConfigNode node) - { - ConfigNode settingsNode; - if (node.HasNode(configNodeName)) - { - settingsNode = node.GetNode(configNodeName); - settingsNode.ClearData(); - } - else - { - settingsNode = node.AddNode(configNodeName); - } - - settingsNode.AddValue("fixtimecounts", false); - } - } -} \ No newline at end of file diff --git a/Source/DFIntMemory.cs b/Source/DFIntMemory.cs index d255d25..0516fa9 100644 --- a/Source/DFIntMemory.cs +++ b/Source/DFIntMemory.cs @@ -66,6 +66,22 @@ public VslFrzrCams(Transform frzrcamTransform, InternalModel frzrcamModel, int f //private bool refreshPortraits; // set to true after a vessel coupling has occurred, a timer waits 3 secnds then refreshes the portraits cams. //private double refreshPortraitsTimer; // the timer for the previous var private int AllVslsErrorCount; //stop log spam + private List<string> ComakeysToDelete = new List<string>(); + private List<KeyValuePair<string, KerbalInfo>> comaKerbals = new List<KeyValuePair<string, KerbalInfo>>(); + private double currentTime, lastFixedUpdateTime, checkVesselUpdateTime, checkVesselComaTime; + private List<DeepFreezer> TmpDpFrzrActVsl = new List<DeepFreezer>(); + private List<ProtoCrewMember> unknownkerbals = new List<ProtoCrewMember>(); + private List<ProtoCrewMember> crewkerbals = new List<ProtoCrewMember>(); + private List<Vessel> allVessels = new List<Vessel>(); + private List<Guid> vesselsToDelete = new List<Guid>(); + private List<uint> partsToDelete = new List<uint>(); + private Dictionary<Guid, VesselInfo> knownVessels = new Dictionary<Guid, VesselInfo>(); + private Guid vesselId; + private Vessel vessel; + private int crewCapacity; + private VesselInfo vesselInfo; + private PartInfo partInfo; + private List<DeepFreezer> DpFrzrLoadedVsl = new List<DeepFreezer>(); protected DFIntMemory() { @@ -105,7 +121,7 @@ private void Awake() private void Start() { - Utilities.Log_Debug("DFIntMemory startup"); + Utilities.Log_Debug("DFIntMemory startup"); ChkUnknownFrozenKerbals(); ChkActiveFrozenKerbals(); DeepFreeze.Instance.DFgameSettings.DmpKnownFznKerbals(); @@ -129,6 +145,10 @@ private void Start() { RTWrapper.InitTRWrapper(); } + currentTime = Planetarium.GetUniversalTime(); + lastFixedUpdateTime = currentTime; + vesselInfo = new VesselInfo("testVessel", currentTime); + partInfo = new PartInfo(Guid.Empty, "testPart", currentTime); } private void OnDestroy() @@ -363,7 +383,12 @@ private void Update() private void FixedUpdate() { if (HighLogic.LoadedSceneIsEditor || Time.timeSinceLevelLoad < 5f) return; //Wait 5 seconds on level load before executing + currentTime = Planetarium.GetUniversalTime(); + //We only update every THREE seconds. + if (currentTime - lastFixedUpdateTime < 3f) + return; + lastFixedUpdateTime = currentTime; //Check if the active vessel has changed and if so, process. if (HighLogic.LoadedSceneIsFlight) { @@ -376,7 +401,9 @@ private void FixedUpdate() try { if (DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Any()) + { CheckComaUpdate(); + } } catch (Exception ex) { @@ -413,8 +440,9 @@ private void FixedUpdate() private void CheckComaUpdate() { // Check the knownfrozenkerbals for any tourists kerbals (IE: Comatose) if their time is up and reset them if it is. - var keysToDelete = new List<string>(); - List<KeyValuePair<string, KerbalInfo>> comaKerbals = DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Where(e => e.Value.type == ProtoCrewMember.KerbalType.Tourist).ToList(); + ComakeysToDelete.Clear(); + //comaKerbals.Clear(); + comaKerbals = DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Where(e => e.Value.type == ProtoCrewMember.KerbalType.Tourist).ToList(); foreach (KeyValuePair<string, KerbalInfo> comaKerbal in comaKerbals) { if (comaKerbal.Value.type == ProtoCrewMember.KerbalType.Tourist) @@ -425,7 +453,7 @@ private void CheckComaUpdate() if (crew != null) { DeepFreeze.Instance.setComatoseKerbal(crew, ProtoCrewMember.KerbalType.Crew); - keysToDelete.Add(comaKerbal.Key); + ComakeysToDelete.Add(comaKerbal.Key); } else { @@ -434,16 +462,17 @@ private void CheckComaUpdate() } } } - keysToDelete.ForEach(id => DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(id)); + ComakeysToDelete.ForEach(id => DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(id)); } private void ChkUnknownFrozenKerbals() { // Check the roster list for any unknown dead kerbals (IE: Frozen) that were not in the save file and add them. - List<ProtoCrewMember> unknownkerbals = HighLogic.CurrentGame.CrewRoster.Unowned.ToList(); + //unknownkerbals.Clear(); + unknownkerbals = HighLogic.CurrentGame.CrewRoster.Unowned.ToList(); if (unknownkerbals != null) { - Utilities.Log("There are " + unknownkerbals.Count() + " unknownKerbals in the game roster."); + Utilities.Log("There are " + unknownkerbals.Count + " unknownKerbals in the game roster."); foreach (ProtoCrewMember CrewMember in unknownkerbals) { if (CrewMember.rosterStatus == ProtoCrewMember.RosterStatus.Dead) @@ -478,7 +507,8 @@ private void ChkUnknownFrozenKerbals() internal void ChkActiveFrozenKerbals() { // Check the roster list for any crew kerbals that we think are frozen but aren't any more and delete them. - List<ProtoCrewMember> crewkerbals = HighLogic.CurrentGame.CrewRoster.Crew.ToList(); + //crewkerbals.Clear(); + crewkerbals = HighLogic.CurrentGame.CrewRoster.Crew.ToList(); if (crewkerbals != null) { Utilities.Log("There are " + crewkerbals.Count() + " crew Kerbals in the game roster."); @@ -557,7 +587,7 @@ internal void onVesselCreate(Vessel vessel) if (HighLogic.LoadedSceneIsFlight) { Utilities.Log_Debug("OnVesselCreate activevessel " + FlightGlobals.ActiveVessel.id + " parametervesselid " + vessel.id); - List<DeepFreezer> TmpDpFrzrActVsl = vessel.FindPartModulesImplementing<DeepFreezer>(); + TmpDpFrzrActVsl = vessel.FindPartModulesImplementing<DeepFreezer>(); foreach (DeepFreezer frzr in TmpDpFrzrActVsl) { //Find the part in KnownFreezerParts and update the GUID @@ -681,7 +711,7 @@ private void resetFreezerCams() { ActFrzrCams.Clear(); lastFrzrCam = 0; - Utilities.Log_Debug("ActVslHasDpFrezer " + ActVslHasDpFrezr + " #ofFrzrs " + DpFrzrActVsl.Count()); + Utilities.Log_Debug("ActVslHasDpFrezer " + ActVslHasDpFrezr + " #ofFrzrs " + DpFrzrActVsl.Count); foreach (DeepFreezer Frzr in DpFrzrActVsl) { if (Frzr.part.internalModel != null) @@ -722,11 +752,13 @@ private void CheckVslUpdate() // Called every fixed update from fixedupdate - Check for vessels that have been deleted and remove from Dictionary // also updates current active vessel details/settings // adds new vessel if current active vessel is not known and updates it's details/settings - double currentTime = Planetarium.GetUniversalTime(); - List<Vessel> allVessels = FlightGlobals.Vessels; - var vesselsToDelete = new List<Guid>(); - var partsToDelete = new List<uint>(); - var knownVessels = DeepFreeze.Instance.DFgameSettings.knownVessels; + //double currentTime = Planetarium.GetUniversalTime(); + //allVessels.Clear(); + vesselsToDelete.Clear(); + partsToDelete.Clear(); + //knownVessels.Clear(); + allVessels = FlightGlobals.Vessels; + knownVessels = DeepFreeze.Instance.DFgameSettings.knownVessels; Utilities.Log_Debug("CheckVslUpdate start"); //* Update known vessels. foreach (var entry in knownVessels) @@ -735,14 +767,14 @@ private void CheckVslUpdate() { Utilities.Log("knownvessels id = " + entry.Key + " Name = " + entry.Value.vesselName); } - Utilities.Log_Debug("knownvessels id = " + entry.Key + " Name = " + entry.Value.vesselName); - Guid vesselId = entry.Key; + Utilities.Log_Debug("knownvessels id = " + entry.Key + " Name = " + entry.Value.vesselName); + vesselId = entry.Key; VesselInfo vesselInfo = entry.Value; - Vessel vessel = null; + vessel = null; try { if (AllVslsErrorCount < 5) - vessel = allVessels.Find(v => v.id == vesselId); + vessel = allVessels.FirstOrDefault(v => v.id == vesselId); else continue; } @@ -787,7 +819,7 @@ private void CheckVslUpdate() if (vessel.loaded) { UpdateVesselInfo(vesselInfo, vessel, currentTime); - int crewCapacity = UpdateVesselCounts(vesselInfo, vessel, currentTime); + crewCapacity = UpdateVesselCounts(vesselInfo, vessel, currentTime); if (!vessel.FindPartModulesImplementing<DeepFreezer>().Any()) { Utilities.Log_Debug("Deleting vessel " + vesselInfo.vesselName + " - no freezer parts anymore"); @@ -805,7 +837,7 @@ private void CheckVslUpdate() // If vessel is Not ActiveVessel and has a Transparent Pod reset the Cryopods. if (FlightGlobals.ActiveVessel != vessel) { - List<DeepFreezer> DpFrzrLoadedVsl = new List<DeepFreezer>(); + DpFrzrLoadedVsl.Clear(); DpFrzrLoadedVsl = vessel.FindPartModulesImplementing<DeepFreezer>(); foreach (DeepFreezer frzr in DpFrzrLoadedVsl) { @@ -840,9 +872,9 @@ private void CheckVslUpdate() if (!knownVessels.ContainsKey(vessel.id) && vessel.FindPartModulesImplementing<DeepFreezer>().Any()) { Utilities.Log("New vessel: " + vessel.vesselName + " (" + vessel.id + ")"); - VesselInfo vesselInfo = new VesselInfo(vessel.vesselName, currentTime); + vesselInfo.vesselName = vessel.vesselName; UpdateVesselInfo(vesselInfo, vessel, currentTime); - int crewCapacity = UpdateVesselCounts(vesselInfo, vessel, currentTime); + crewCapacity = UpdateVesselCounts(vesselInfo, vessel, currentTime); knownVessels[vessel.id] = vesselInfo; } } @@ -877,16 +909,26 @@ private void UpdateVesselInfo(VesselInfo vesselInfo, Vessel vessel, double curre vesselInfo.lastUpdate = Planetarium.GetUniversalTime(); vesselInfo.hibernating = false; vesselInfo.hasextDoor = false; - List<DeepFreezer> DpFrzrLoadedVsl = new List<DeepFreezer>(); + vesselInfo.hasextPod = false; + DpFrzrLoadedVsl.Clear(); DpFrzrLoadedVsl = vessel.FindPartModulesImplementing<DeepFreezer>(); foreach (DeepFreezer frzr in DpFrzrLoadedVsl) { // do we have a known part? If not add it - PartInfo partInfo; if (!DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(frzr.part.flightID, out partInfo)) { Utilities.Log("New Freezer Part: " + frzr.name + "(" + frzr.part.flightID + ")" + " (" + vessel.id + ")"); partInfo = new PartInfo(vessel.id, frzr.name, currentTime); + //partInfo.vesselID = vessel.id; + //partInfo.PartName = frzr.name; + partInfo.hibernating = false; + partInfo.ECWarning = false; + partInfo.TempWarning = false; + partInfo.lastUpdate = currentTime; + partInfo.crewMembers.Clear(); + partInfo.crewMemberTraits.Clear(); + + partInfo.hasextDoor = frzr.ExternalDoorActive; partInfo.hasextPod = frzr.isPodExternal; partInfo.numSeats = frzr.FreezerSize; @@ -939,7 +981,7 @@ private int UpdateVesselCounts(VesselInfo vesselInfo, Vessel vessel, double curr { // save current toggles to current vesselinfo // Utilities.Log_Debug("UpdateVesselCounts " + vessel.id); - int crewCapacity = 0; + crewCapacity = 0; vesselInfo.ClearAmounts(); // numCrew = 0; numOccupiedParts = 0; numseats = 0; foreach (Part part in vessel.parts) { @@ -948,11 +990,11 @@ private int UpdateVesselCounts(VesselInfo vesselInfo, Vessel vessel, double curr { Utilities.Log_Debug("part:" + part.name + " Has Freezer"); //first Update the PartInfo counts - PartInfo partInfo; + if (DeepFreeze.Instance.DFgameSettings.knownFreezerParts.TryGetValue(freezer.part.flightID, out partInfo)) { partInfo.numCrew = freezer.part.protoModuleCrew.Count; - partInfo.numFrznCrew = freezer.DFIStoredCrewList.Count(); + partInfo.numFrznCrew = freezer.DFIStoredCrewList.Count; } //Now update the VesselInfo counts crewCapacity += freezer.FreezerSize; diff --git a/Source/DFWrapper.cs b/Source/DFWrapper.cs deleted file mode 100644 index 2360556..0000000 --- a/Source/DFWrapper.cs +++ /dev/null @@ -1,742 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -// TODO: Change this namespace to something specific to your plugin here. -//EG: -// namespace MyPlugin_KACWrapper -namespace DeepFreezeWrapper -{ - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // BELOW HERE SHOULD NOT BE EDITED - this links to the loaded DeepFreeze module without requiring a Hard Dependancy - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - /// <summary> - /// The Wrapper class to access DeepFreeze from another plugin - /// </summary> - public class DFWrapper - { - protected static System.Type DFType; - protected static System.Type KerbalInfoType; - protected static System.Type DeepFreezerType; - protected static System.Type FrznCrewMbrType; - protected static Object actualDF = null; - - /// <summary> - /// This is the DeepFreeze object - /// - /// SET AFTER INIT - /// </summary> - public static DFAPI DeepFreezeAPI; - - /// <summary> - /// Whether we found the DeepFreeze assembly in the loadedassemblies. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean AssemblyExists { get { return (DFType != null); } } - - /// <summary> - /// Whether we managed to hook the running Instance from the assembly. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean InstanceExists { get { return (DeepFreezeAPI != null); } } - - /// <summary> - /// Whether we managed to wrap all the methods/functions from the instance. - /// - /// SET AFTER INIT - /// </summary> - private static Boolean _DFWrapped; - - /// <summary> - /// Whether the object has been wrapped and the APIReady flag is set in the real DeepFreeze - /// </summary> - public static Boolean APIReady { get { return _DFWrapped && DeepFreezeAPI.APIReady; } } - - /// <summary> - /// This method will set up the DeepFreeze object and wrap all the methods/functions - /// </summary> - /// <returns> - /// Bool indicating success of call - /// </returns> - public static Boolean InitDFWrapper() - { - try - { - //reset the internal objects - _DFWrapped = false; - actualDF = null; - DeepFreezeAPI = null; - LogFormatted("Attempting to Grab DeepFreeze Types..."); - - //find the base type - DFType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "DF.DeepFreeze"); - - if (DFType == null) - { - return false; - } - - LogFormatted("DeepFreeze Version:{0}", DFType.Assembly.GetName().Version.ToString()); - - //now the KerbalInfo Type - KerbalInfoType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "DF.KerbalInfo"); - - if (KerbalInfoType == null) - { - return false; - } - - //now the DeepFreezer (partmodule) Type - DeepFreezerType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "DF.DeepFreezer"); - - if (DeepFreezerType == null) - { - return false; - } - - //now the FrznCrewMbr Type - FrznCrewMbrType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "DF.FrznCrewMbr"); - - if (FrznCrewMbrType == null) - { - return false; - } - - //now grab the running instance - LogFormatted("Got Assembly Types, grabbing Instance"); - try - { - actualDF = DFType.GetField("Instance", BindingFlags.Public | BindingFlags.Static).GetValue(null); - } - catch (Exception) - { - LogFormatted("No Instance found - most likely you have an old DeepFreeze installed"); - return false; - } - if (actualDF == null) - { - LogFormatted("Failed grabbing Instance"); - return false; - } - - //If we get this far we can set up the local object and its methods/functions - LogFormatted("Got Instance, Creating Wrapper Objects"); - DeepFreezeAPI = new DFAPI(actualDF); - _DFWrapped = true; - return true; - } - catch (Exception ex) - { - LogFormatted("Unable to setup InitDFWrapper Reflection"); - LogFormatted("Exception: {0}", ex); - _DFWrapped = false; - return false; - } - } - - /// <summary> - /// The API Class that is an analogue of the real DeepFreeze. This lets you access all the API-able properties and Methods of the DeepFreeze - /// </summary> - public class DFAPI - { - internal DFAPI(Object a) - { - try - { - //store the actual object - actualDFAPI = a; - - //these sections get and store the reflection info and actual objects where required. Later in the properties we then read the values from the actual objects - //for events we also add a handler - //Object tstfrozenkerbals = DFType.GetField("FrozenKerbals", BindingFlags.Public | BindingFlags.Static).GetValue(null); - - LogFormatted("Getting APIReady Object"); - APIReadyField = DFType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); - LogFormatted("Success: " + (APIReadyField != null).ToString()); - - LogFormatted("Getting FrozenKerbals Object"); - FrozenKerbalsMethod = DFType.GetMethod("get_FrozenKerbals", BindingFlags.Public | BindingFlags.Instance); - actualFrozenKerbals = FrozenKerbalsMethod.Invoke(actualDFAPI, null); - LogFormatted("Success: " + (actualFrozenKerbals != null).ToString()); - } - catch (Exception ex) - { - LogFormatted("Unable to Instantiate DFAPI object using Reflection"); - LogFormatted("Exception: {0}", ex); - } - } - - private Object actualDFAPI; - - private FieldInfo APIReadyField; - /// <summary> - /// Whether the APIReady flag is set in the real KAC - /// </summary> - /// <returns> - /// Bool Indicating if DeepFreeze is ready for API calls - /// </returns> - public bool APIReady - { - get - { - if (APIReadyField == null) - return false; - - return (Boolean)APIReadyField.GetValue(null); - } - } - - #region Frozenkerbals - - private Object actualFrozenKerbals; - private MethodInfo FrozenKerbalsMethod; - - /// <summary> - /// The dictionary of Frozen Kerbals that are currently active in game - /// </summary> - /// <returns> - /// Dictionary <string, KerbalInfo> of Frozen Kerbals - /// </returns> - internal Dictionary<string, KerbalInfo> FrozenKerbals - { - get - { - if (FrozenKerbalsMethod == null) - return null; - //Object tstfrozenkerbals = DFType.GetField("FrozenKerbals", BindingFlags.Public | BindingFlags.Static).GetValue(null); - FieldInfo gamesettingsfield = DFType.GetField("DFgameSettings", BindingFlags.Instance | BindingFlags.NonPublic); - Object gamesettings = gamesettingsfield.GetValue(actualDFAPI); - actualFrozenKerbals = FrozenKerbalsMethod.Invoke(actualDFAPI, null); - Dictionary<string, KerbalInfo> returnvalue = new Dictionary<string, KerbalInfo>(); - returnvalue = ExtractFrozenKerbalDict(actualFrozenKerbals); - return returnvalue; - } - } - - /// <summary> - /// This converts the actualFrozenKerbals actual object to a new dictionary for consumption - /// </summary> - /// <param name="actualFrozenKerbals"></param> - /// <returns>Dictionary <string, KerbalInfo> of Frozen Kerbals</returns> - private Dictionary<string, KerbalInfo> ExtractFrozenKerbalDict(Object actualFrozenKerbals) - { - Dictionary<string, KerbalInfo> DictToReturn = new Dictionary<string, KerbalInfo>(); - try - { - foreach (var item in (IDictionary)actualFrozenKerbals) - { - var typeitem = item.GetType(); - PropertyInfo[] itemprops = typeitem.GetProperties(BindingFlags.Instance | BindingFlags.Public); - string itemkey = (string)itemprops[0].GetValue(item, null); - object itemvalue = (object)itemprops[1].GetValue(item, null); - KerbalInfo itemkerbalinfo = new KerbalInfo(itemvalue); - DictToReturn[itemkey] = itemkerbalinfo; - } - } - catch (Exception ex) - { - LogFormatted("Unable to extract FrozenKerbals Dictionary: {0}", ex.Message); - } - return DictToReturn; - } - - #endregion Frozenkerbals - } - - #region DeepFreezerPart - - /// <summary> - /// The Class that is an analogue of the real DeepFreezer PartModule. This lets you access all the API-able properties and Methods of the DeepFreezer - /// </summary> - public class DeepFreezer - { - internal DeepFreezer(Object a) - { - actualDeepFreezer = a; - //Fields available from Freezer part - crewXferTOActiveMethod = DeepFreezerType.GetMethod("get_DFIcrewXferTOActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - crewXferTOActive = getcrewXferTOActive; - crewXferFROMActiveMethod = DeepFreezerType.GetMethod("get_DFIcrewXferFROMActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - crewXferFROMActive = getcrewXferFROMActive; - FreezerSizeMethod = DeepFreezerType.GetMethod("get_DFIFreezerSize", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - FreezerSize = getFreezerSize; - TotalFrozenMethod = DeepFreezerType.GetMethod("get_DFITotalFrozen", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - TotalFrozen = getTotalFrozen; - FreezerSpaceMethod = DeepFreezerType.GetMethod("get_DFIFreezerSpace", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - FreezerSpace = getFreezerSpace; - PartFullMethod = DeepFreezerType.GetMethod("get_DFIPartFull", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - PartFull = getPartFull; - IsFreezeActiveMethod = DeepFreezerType.GetMethod("get_DFIIsFreezeActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - IsFreezeActive = getIsFreezeActive; - IsThawActiveMethod = DeepFreezerType.GetMethod("get_DFIIsThawActive", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - IsThawActive = getIsThawActive; - FreezerOutofECMethod = DeepFreezerType.GetMethod("get_DFIFreezerOutofEC", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - FreezerOutofEC = getFreezerOutofEC; - FrzrTmpMethod = DeepFreezerType.GetMethod("get_DFIFrzrTmp", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - FrzrTmp = getFrzrTmp; - StoredCrewListMethod = DeepFreezerType.GetMethod("get_DFIStoredCrewList", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - actualStoredCrewList = StoredCrewListMethod.Invoke(actualDeepFreezer, null); - - //Methods - LogFormatted("Getting beginFreezeKerbalMethod Method"); - beginFreezeKerbalMethod = DeepFreezerType.GetMethod("beginFreezeKerbal", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (beginFreezeKerbalMethod != null).ToString()); - - LogFormatted("Getting beginThawKerbalMethod Method"); - beginThawKerbalMethod = DeepFreezerType.GetMethod("beginThawKerbal", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (beginThawKerbalMethod != null).ToString()); - } - - private Object actualDeepFreezer; - - #region DeepFreezerFieldMethods - - /// <summary> - /// True if a crewXfter TO this DeepFreezer part is currently active - /// </summary> - public bool crewXferTOActive; - - private MethodInfo crewXferTOActiveMethod; - - private bool getcrewXferTOActive - { - get { return (bool)crewXferTOActiveMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// True if a crewXfter FROM this DeepFreezer part is currently active - /// </summary> - public bool crewXferFROMActive; - - private MethodInfo crewXferFROMActiveMethod; - - private bool getcrewXferFROMActive - { - get { return (bool)crewXferFROMActiveMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// The number of cryopods in this DeepFreezer - /// </summary> - public int FreezerSize; - - private MethodInfo FreezerSizeMethod; - - private int getFreezerSize - { - get { return (int)FreezerSizeMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// The number of currently frozen Kerbals in this DeepFreezer - /// </summary> - public int TotalFrozen; - - private MethodInfo TotalFrozenMethod; - - private int getTotalFrozen - { - get { return (int)TotalFrozenMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// The number of empty cryopods in this DeepFreezer - /// </summary> - public int FreezerSpace; - - private MethodInfo FreezerSpaceMethod; - - private int getFreezerSpace - { - get { return (int)FreezerSpaceMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// True if all the cryopods are taken in this DeepFreezer (includes, frozen and thawed kerbals). - /// </summary> - public bool PartFull; - - private MethodInfo PartFullMethod; - - private bool getPartFull - { - get { return (bool)PartFullMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// True if a Freeze kerbal event is currently active in this DeepFreezer - /// </summary> - public bool IsFreezeActive; - - private MethodInfo IsFreezeActiveMethod; - - private bool getIsFreezeActive - { - get { return (bool)IsFreezeActiveMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// True if a Thaw kerbal event is currently active in this DeepFreezer - /// </summary> - public bool IsThawActive; - - private MethodInfo IsThawActiveMethod; - - private bool getIsThawActive - { - get { return (bool)IsThawActiveMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// True if this DeepFreezer is currently out of Electric Charge - /// </summary> - public bool FreezerOutofEC; - - private MethodInfo FreezerOutofECMethod; - - private bool getFreezerOutofEC - { - get { return (bool)FreezerOutofECMethod.Invoke(actualDeepFreezer, null); } - } - - /// <summary> - /// The current freezer temperature status of this DeepFreezer - /// </summary> - public FrzrTmpStatus FrzrTmp; - - private MethodInfo FrzrTmpMethod; - - private FrzrTmpStatus getFrzrTmp - { - get { return (FrzrTmpStatus)FrzrTmpMethod.Invoke(actualDeepFreezer, null); } - } - - private Object actualStoredCrewList; - private MethodInfo StoredCrewListMethod; - - /// <summary> - /// a List<FrznCrewMbr> of all Frozen Crew in this DeepFreezer - /// </summary> - public FrznCrewList StoredCrewList - { - get { return ExtractStoredCrewList(actualStoredCrewList); } - } - - /// <summary> - /// This converts the StoredCrewList actual object to a new List for consumption - /// </summary> - /// <param name="actualStoredCrewList"></param> - /// <returns></returns> - private FrznCrewList ExtractStoredCrewList(Object actualStoredCrewList) - { - FrznCrewList ListToReturn = new FrznCrewList(); - try - { - //iterate each "value" in the dictionary - - foreach (var item in (IList)actualStoredCrewList) - { - FrznCrewMbr r1 = new FrznCrewMbr(item); - ListToReturn.Add(r1); - } - } - catch (Exception ex) - { - LogFormatted("Arrggg: {0}", ex.Message); - //throw ex; - // - } - return ListToReturn; - } - - #endregion DeepFreezerFieldMethods - - #region DeepFreezerMethods - - private MethodInfo beginFreezeKerbalMethod; - - /// <summary> - /// Begin the Freezing of a Kerbal - /// </summary> - /// <param name="CrewMember">ProtoCrewMember that you want frozen</param> - /// <returns>Bool indicating success of call</returns> - public bool beginFreezeKerbal(ProtoCrewMember CrewMember) - { - try - { - beginFreezeKerbalMethod.Invoke(actualDeepFreezer, new System.Object[] { CrewMember }); - return true; - } - catch (Exception ex) - { - LogFormatted("Arrggg: {0}", ex.Message); - return false; - } - } - - private MethodInfo beginThawKerbalMethod; - - /// <summary> - /// Begin the Thawing of a Kerbal - /// </summary> - /// <param name="frozenkerbal">string containing the name of the kerbal you want thawed</param> - /// <returns>Bool indicating success of call</returns> - public bool beginThawKerbal(string frozenkerbal) - { - try - { - beginThawKerbalMethod.Invoke(actualDeepFreezer, new System.Object[] { frozenkerbal }); - return true; - } - catch (Exception ex) - { - LogFormatted("Arrggg: {0}", ex.Message); - return false; - } - } - - #endregion DeepFreezerMethods - } - - public enum FrzrTmpStatus - { - OK = 0, - WARN = 1, - RED = 2, - } - - /// <summary> - /// The Class that is an analogue of the real FrznCrewMbr as part of the StoredCrewList field in the DeepFreezer PartModule. - /// </summary> - public class FrznCrewMbr - { - internal FrznCrewMbr(Object a) - { - actualFrznCrewMbr = a; - CrewNameMethod = FrznCrewMbrType.GetMethod("get_CrewName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - CrewName = getCrewName; - SeatIdxMethod = FrznCrewMbrType.GetMethod("get_SeatIdx", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - SeatIdx = getSeatIdx; - VesselIDMethod = FrznCrewMbrType.GetMethod("get_VesselID", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - VesselID = getVesselID; - VesselNameMethod = FrznCrewMbrType.GetMethod("get_VesselName", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); - VesselName = getVesselName; - } - - private Object actualFrznCrewMbr; - - - /// <summary> - /// Crew Members Name - /// </summary> - public string CrewName; - - private MethodInfo CrewNameMethod; - - private string getCrewName - { - get { return (string)CrewNameMethod.Invoke(actualFrznCrewMbr, null); } - } - - /// <summary> - /// Seat Index for Crew member - /// </summary> - public int SeatIdx; - - private MethodInfo SeatIdxMethod; - - private int getSeatIdx - { - get { return (int)SeatIdxMethod.Invoke(actualFrznCrewMbr, null); } - } - - /// <summary> - /// Vessel ID - /// </summary> - public Guid VesselID; - - private MethodInfo VesselIDMethod; - - private Guid getVesselID - { - get { return (Guid)VesselIDMethod.Invoke(actualFrznCrewMbr, null); } - } - - /// <summary> - /// Vessel Name - /// </summary> - public string VesselName; - - private MethodInfo VesselNameMethod; - - private string getVesselName - { - get { return (string)VesselNameMethod.Invoke(actualFrznCrewMbr, null); } - } - } - - public class FrznCrewList : List<FrznCrewMbr> - { - } - - #endregion DeepFreezerPart - - /// <summary> - /// The Value Class of the FrozenCrewList Dictionary that is an analogue of the real FrozenKerbals Dictionary in the DeepFreezer Class. - /// </summary> - public class KerbalInfo - { - internal KerbalInfo(Object a) - { - actualFrozenKerbalInfo = a; - lastUpdateField = KerbalInfoType.GetField("lastUpdate"); - statusField = KerbalInfoType.GetField("status"); - typeField = KerbalInfoType.GetField("type"); - vesselIDField = KerbalInfoType.GetField("vesselID"); - vesselNameField = KerbalInfoType.GetField("vesselName"); - partIDField = KerbalInfoType.GetField("partID"); - seatIdxField = KerbalInfoType.GetField("seatIdx"); - seatNameField = KerbalInfoType.GetField("seatName"); - experienceTraitNameField = KerbalInfoType.GetField("experienceTraitName"); - } - - private Object actualFrozenKerbalInfo; - - private FieldInfo lastUpdateField; - - /// <summary> - /// last time the FrozenKerbalInfo was updated - /// </summary> - public double lastUpdate - { - get { return (double)lastUpdateField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo statusField; - - /// <summary> - /// RosterStatus of the frozen kerbal - /// </summary> - public ProtoCrewMember.RosterStatus status - { - get { return (ProtoCrewMember.RosterStatus)statusField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo typeField; - - /// <summary> - /// KerbalType of the frozen kerbal - /// </summary> - public ProtoCrewMember.KerbalType type - { - get { return (ProtoCrewMember.KerbalType)typeField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo vesselIDField; - - /// <summary> - /// Guid of the vessel the frozen kerbal is aboard - /// </summary> - public Guid vesselID - { - get { return (Guid)vesselIDField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo vesselNameField; - - /// <summary> - /// Name of the vessel the frozen kerbal is aboard - /// </summary> - public string vesselName - { - get { return (string)vesselNameField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo partIDField; - - /// <summary> - /// partID of the vessel part the frozen kerbal is aboard - /// </summary> - public uint partID - { - get { return (uint)partIDField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo seatIdxField; - - /// <summary> - /// seat index that the frozen kerbal is in - /// </summary> - public int seatIdx - { - get { return (int)seatIdxField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo seatNameField; - - /// <summary> - /// seat name that the frozen kerbal is in - /// </summary> - public string seatName - { - get { return (string)seatNameField.GetValue(actualFrozenKerbalInfo); } - } - - private FieldInfo experienceTraitNameField; - - /// <summary> - /// name of the experience trait for the frozen kerbal - /// </summary> - public string experienceTraitName - { - get { return (string)experienceTraitNameField.GetValue(actualFrozenKerbalInfo); } - } - } - - #region Logging Stuff - - /// <summary> - /// Some Structured logging to the debug file - ONLY RUNS WHEN DLL COMPILED IN DEBUG MODE - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - [System.Diagnostics.Conditional("DEBUG")] - internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) - { - LogFormatted(Message, strParams); - } - - /// <summary> - /// Some Structured logging to the debug file - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - internal static void LogFormatted(String Message, params Object[] strParams) - { - Message = String.Format(Message, strParams); - String strMessageLine = String.Format("{0},{2}-{3},{1}", - DateTime.Now, Message, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, - System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); - UnityEngine.Debug.Log(strMessageLine); - } - - #endregion Logging Stuff - } -} \ No newline at end of file diff --git a/Source/DFtoolbar.png b/Source/DFtoolbar.png deleted file mode 100644 index 2a89f57..0000000 Binary files a/Source/DFtoolbar.png and /dev/null differ diff --git a/Source/DeepFreeze.cs b/Source/DeepFreeze.cs index 5d211e6..7fc3469 100644 --- a/Source/DeepFreeze.cs +++ b/Source/DeepFreeze.cs @@ -51,7 +51,7 @@ public DeepFreeze() APIReady = false; DFsettings = new DFSettings(); DFgameSettings = new DFGameSettings(); - globalConfigFilename = Path.Combine(_AssemblyFolder, "Config.cfg").Replace("\\", "/"); + globalConfigFilename = Path.Combine(_AssemblyFolder, "PluginData/Config.cfg").Replace("\\", "/"); Utilities.Log("globalConfigFilename = " + globalConfigFilename); DeepFreezeEventAdd(); } @@ -413,13 +413,13 @@ internal static String _AssemblyName /// Full Path of the executing Assembly /// </summary> internal static String _AssemblyLocation - { get { return Assembly.GetExecutingAssembly().Location; } } + { get { return Assembly.GetExecutingAssembly().Location.Replace("\\", "/"); } } /// <summary> /// Folder containing the executing Assembly /// </summary> internal static String _AssemblyFolder - { get { return Path.GetDirectoryName(_AssemblyLocation); } } + { get { return Path.GetDirectoryName(_AssemblyLocation).Replace("\\", "/"); } } #endregion Assembly/Class Information } diff --git a/Source/DeepFreeze.csproj b/Source/DeepFreeze.csproj index 2b4f415..6ef209f 100644 --- a/Source/DeepFreeze.csproj +++ b/Source/DeepFreeze.csproj @@ -50,6 +50,10 @@ <Reference Include="Assembly-UnityScript-firstpass"> <HintPath>..\..\KSPDLLs\Assembly-UnityScript-firstpass.dll</HintPath> </Reference> + <Reference Include="KSPAssets, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\KSPDLLs\KSPAssets.dll</HintPath> + </Reference> <Reference Include="KSPUtil"> <HintPath>..\..\KSPDLLs\KSPUtil.dll</HintPath> </Reference> @@ -69,14 +73,25 @@ </Reference> </ItemGroup> <ItemGroup> + <Compile Include="..\..\REPOSoftTechKSPUtils\AppLauncherToolBarExtension.cs"> + <Link>AppLauncherToolBarExtension.cs</Link> + </Compile> + <Compile Include="..\..\REPOSoftTechKSPUtils\RectExtentions.cs"> + <Link>RectExtentions.cs</Link> + </Compile> <Compile Include="..\..\REPOSoftTechKSPUtils\RSTutilities.cs"> <Link>RSTutilities.cs</Link> </Compile> + <Compile Include="..\..\REPOSoftTechKSPUtils\ToolBarManager.cs"> + <Link>ToolBarManager.cs</Link> + </Compile> <Compile Include="APIs\KBWrapper.cs" /> <Compile Include="DeepFreeze.cs" /> <Compile Include="DeepFreezerPart.cs" /> <Compile Include="DFAlarmInfo.cs" /> <Compile Include="DFEditorFilter.cs" /> + <Compile Include="DFEnums.cs" /> + <Compile Include="DFExtDoorMgr.cs" /> <Compile Include="DFGameSettings.cs" /> <Compile Include="DFInstalledMods.cs" /> <Compile Include="DFSettings.cs" /> @@ -154,7 +169,6 @@ <Compile Include="APIs\USIWrapper.cs" /> <Compile Include="Textures.cs" /> <Compile Include="VesselInfo.cs" /> - <Compile Include="APIs\ToolBarManager.cs" /> </ItemGroup> <ItemGroup> <None Include="Distribution\GameData\REPOSoftTech\DeepFreeze\Changelog.txt" /> diff --git a/Source/DeepFreeze.sln b/Source/DeepFreeze.sln deleted file mode 100644 index 947cb61..0000000 --- a/Source/DeepFreeze.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepFreeze", "DeepFreeze.csproj", "{A4B40FD9-3062-4913-9C6D-1980FA813B9B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A4B40FD9-3062-4913-9C6D-1980FA813B9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4B40FD9-3062-4913-9C6D-1980FA813B9B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4B40FD9-3062-4913-9C6D-1980FA813B9B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4B40FD9-3062-4913-9C6D-1980FA813B9B}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Source/DeepFreezeEvents.cs b/Source/DeepFreezeEvents.cs deleted file mode 100644 index 954156b..0000000 --- a/Source/DeepFreezeEvents.cs +++ /dev/null @@ -1,200 +0,0 @@ -/** - * DeepFreezerPart.cs - * - * - * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This - * project is in no way associated with nor endorsed by Squad. - * - * This file is part of Jamie Leighton's Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. - * The original DeepFreeze was licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) - * This File was part of the original Deepfreeze but has been heavily modified and re-written by Jamie Leighton. - * (C) Copyright 2015, Jamie Leighton - * - * Which is licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) - * creative commons license. See <https://creativecommons.org/licenses/by-nc-sa/4.0/> - * for full details. - * - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace DF -{ - [KSPAddon(KSPAddon.Startup.SpaceCentre, false)] - internal class DeepFreezeEvents :MonoBehaviour - { - public static DeepFreezeEvents instance = new DeepFreezeEvents(); - public bool eventAdded; - private const float costToThawKerbal = 10000f; - - public DeepFreezeEvents() - { - Debug.Log("DeepFreezeEvents Constructor"); - eventAdded = false; - Debug.Log("DeepFreezeEvnts.Start called"); - if (!DeepFreezeEvents.instance.eventAdded) - { - DeepFreezeEvents.instance.DeepFreezeEventAdd(); - Debug.Log("!DeepFreezeEvents.instance.eventAdded"); - } - else - Debug.Log("DeepFreezeEvents.instance.eventAdded"); - } - - public void DeepFreezeEventAdd() - { - Debug.Log("DeepFreezeEvents DeepFreezeEventAdd"); - //GameEvents.OnVesselRecoveryRequested.Add(this.OnVesselRecoveryRequested); - GameEvents.onVesselRecovered.Add(this.onVesselRecovered); - GameEvents.onVesselTerminated.Add(this.onVesselTerminated); - GameEvents.onVesselWillDestroy.Add(this.onVesselWillDestroy); - eventAdded = true; - Debug.Log("DeepFreezeEvents DeepFreezeEventAdd ended"); - } - /* - public void OnVesselRecoveryRequested(Vessel vessel) - { - Debug.Log("DeepFreezeEvents OnVesselRecoveryRequested"); - if (vessel.FindPartModulesImplementing<DeepFreezer>().Count > 0 && DeepFreeze.Instance.DFsettings.AutoRecoverFznKerbals) - { - foreach (DeepFreezer freezer in vessel.FindPartModulesImplementing<DeepFreezer>()) - { - freezer.part.CrewCapacity = freezer.StoredCrewList.Count; - foreach (var crewmember in freezer.StoredCrewList) - { - foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) - { - if (kerbal.name == crewmember.CrewName) - { - kerbal.type = ProtoCrewMember.KerbalType.Crew; - kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; - freezer.part.AddCrewmember(kerbal); - Debug.Log("DeepFreezeEvents Crew Added" + kerbal.name); - } - } - } - } - } - } - */ - public void onVesselRecovered(ProtoVessel vessel) - { - Debug.Log("DeepFreezeEvents onVesselRecovered " + vessel.vesselID); - this.Log_Debug("AutoRecover is ON"); - foreach (KeyValuePair<string, KerbalInfo> kerbal in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) - { - if (kerbal.Value.vesselID == vessel.vesselID) - { - if (DeepFreeze.Instance.DFsettings.AutoRecoverFznKerbals) - { - Debug.Log("Calling ThawFrozen Crew to thaw FrozenCrew " + kerbal.Key); - ThawFrozenCrew(kerbal.Key, vessel.vesselID); - } - else - { - Debug.Log("DeepFreeze AutoRecovery of frozen kerbals is set to off. Must be thawed manually."); - - Debug.Log("DeepFreezeEvents frozenkerbal =" + kerbal.Key); - ProtoCrewMember realkerbal = HighLogic.CurrentGame.CrewRoster.Unowned.FirstOrDefault(b => b.name == kerbal.Key); - if (realkerbal != null) - { - realkerbal.type = ProtoCrewMember.KerbalType.Unowned; - realkerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; - this.Log_Debug("Kerbal " + realkerbal.name + " " + realkerbal.type + " " + realkerbal.rosterStatus); - ScreenMessages.PostScreenMessage(kerbal.Key + " was stored frozen at KSC.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - } - } - } - } - } - - public void onVesselTerminated(ProtoVessel vessel) - { - Debug.Log("DeepFreezeEvents onVesselTerminated " + vessel.vesselID); - foreach (KeyValuePair<string, KerbalInfo> kerbal in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) - { - if (kerbal.Value.vesselID == vessel.vesselID) - { - KillFrozenCrew(kerbal.Key); - } - } - } - - public void onVesselWillDestroy(Vessel vessel) - { - Debug.Log("DeepFreezeEvents onVesselWillDestroy"); - foreach (KeyValuePair<string, KerbalInfo> kerbal in DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals) - { - if (kerbal.Value.vesselID == vessel.id) - { - KillFrozenCrew(kerbal.Key); - } - } - } - - public void ThawFrozenCrew(String FrozenCrew, Guid vesselID) - { - Debug.Log("DeepFreezeEvents ThawFrozenCrew"); - Debug.Log("DeepFreezeEvents frozenkerbal =" + FrozenCrew); - ProtoCrewMember kerbal = HighLogic.CurrentGame.CrewRoster.Unowned.FirstOrDefault(a => a.name == FrozenCrew); - if (kerbal != null) - { - Vessel vessel = FlightGlobals.Vessels.Find(v => v.id == vesselID); - if (vessel == null) - { - if (HighLogic.CurrentGame.Mode == Game.Modes.CAREER) - { - if (Funding.CanAfford(costToThawKerbal)) - { - Funding.Instance.AddFunds(-costToThawKerbal, TransactionReasons.Vessels); - this.Log_Debug("Took funds to thaw kerbal"); - } - else - { - this.Log_Debug("Not enough funds to thaw kerbal"); - ScreenMessages.PostScreenMessage("Insufficient funds to thaw " + kerbal.name + " at this time.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - return; - } - } - kerbal.type = ProtoCrewMember.KerbalType.Crew; - kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; - this.Log_Debug("Kerbal " + kerbal.name + " " + kerbal.type + " " + kerbal.rosterStatus); - kerbal.ArchiveFlightLog(); - kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Available; - this.Log_Debug("Kerbal " + kerbal.name + " " + kerbal.type + " " + kerbal.rosterStatus); - ScreenMessages.PostScreenMessage(kerbal.name + " was found and thawed out.", 5.0f, ScreenMessageStyle.UPPER_CENTER); - DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(kerbal.name); - } - else - { - this.Log_Debug("Cannot thaw, vessel still exists " + vessel.situation.ToString() + " at " + vessel.mainBody.bodyName); - ScreenMessages.PostScreenMessage("Cannot thaw " + kerbal.name + " vessel still exists " + vessel.situation.ToString() + " at " + vessel.mainBody.bodyName, 5.0f, ScreenMessageStyle.UPPER_CENTER); - } - } - } - - public void KillFrozenCrew(string FrozenCrew) - { - Debug.Log("DeepFreezeEvents KillFrozenCrew"); - Debug.Log("DeepFreezeEvents frozenkerbal =" + FrozenCrew); - DeepFreeze.Instance.DFgameSettings.KnownFrozenKerbals.Remove(FrozenCrew); - ProtoCrewMember kerbal = HighLogic.CurrentGame.CrewRoster.Unowned.FirstOrDefault(a => a.name == FrozenCrew); - if (kerbal != null) - { - Debug.Log("DeepFreezeEvents" + kerbal.name + " killed"); - kerbal.type = ProtoCrewMember.KerbalType.Crew; - kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Dead; - if (HighLogic.CurrentGame.Parameters.Difficulty.MissingCrewsRespawn == true) - { - kerbal.StartRespawnPeriod(); - Debug.Log("DeepFreezeEvents" + kerbal.name + " respawn started."); - } - } - else - Debug.Log("DeepFreezeEvents" + kerbal.name + " couldn't find them to kill them."); - } - } -} \ No newline at end of file diff --git a/Source/DeepFreezeGUI.cs b/Source/DeepFreezeGUI.cs index 0c3d2ce..117ed5a 100644 --- a/Source/DeepFreezeGUI.cs +++ b/Source/DeepFreezeGUI.cs @@ -23,16 +23,14 @@ using UnityEngine; using Random = System.Random; using KSP.UI.Screens; +using RSTUtils.Extensions; namespace DF { internal class DeepFreezeGUI : MonoBehaviour, Savable { //GUI Properties - private bool gamePaused; - - private IButton button1; - private ApplicationLauncherButton stockToolbarButton; // Stock Toolbar Button + internal AppLauncherToolBar DFMenuAppLToolBar; private float DFWINDOW_WIDTH = 560; private float CFWINDOW_WIDTH = 340; private float KACWINDOW_WIDTH = 485; @@ -83,7 +81,6 @@ internal class DeepFreezeGUI : MonoBehaviour, Savable //settings vars for GUI private bool InputVautoRecover; - private bool InputVdebug; private bool InputVToolTips; private bool InputVECReqd; @@ -111,7 +108,6 @@ internal class DeepFreezeGUI : MonoBehaviour, Savable //Settings vars private bool ECreqdForFreezer; - private bool debugging; private bool ToolTips; private bool AutoRecoverFznKerbals; @@ -130,7 +126,6 @@ internal class DeepFreezeGUI : MonoBehaviour, Savable //SwitchVessel vars private bool showUnabletoSwitchVessel; - private bool showSwitchVessel; private bool switchVesselManual; private string showSwitchVesselStr = string.Empty; @@ -138,116 +133,23 @@ internal class DeepFreezeGUI : MonoBehaviour, Savable private double switchVesselManualTimer; private bool chgECHeatsettings; private double chgECHeatsettingsTimer; - - //GuiVisibility - private bool _Visible; - - public Boolean GuiVisible - { - get { return _Visible; } - set - { - _Visible = value; //Set the private variable - } - } - + public bool Useapplauncher; - - #region AppLauncher - - private void OnGUIAppLauncherReady() - { - Utilities.Log_Debug("OnGUIAppLauncherReady"); - if (ApplicationLauncher.Ready) - { - Utilities.Log_Debug("Adding AppLauncherButton"); - stockToolbarButton = ApplicationLauncher.Instance.AddModApplication( - onAppLaunchToggle, - onAppLaunchToggle, - DummyVoid, - DummyVoid, - DummyVoid, - DummyVoid, - ApplicationLauncher.AppScenes.SPACECENTER | ApplicationLauncher.AppScenes.FLIGHT | - ApplicationLauncher.AppScenes.MAPVIEW | ApplicationLauncher.AppScenes.SPH | ApplicationLauncher.AppScenes.VAB | - ApplicationLauncher.AppScenes.TRACKSTATION, - GameDatabase.Instance.GetTexture("REPOSoftTech/DeepFreeze/Icons/DeepFreezeOff", false)); - } - } - - private void DummyVoid() - { - } - - private void onAppLaunchToggle() - { - GuiVisible = !GuiVisible; - if (stockToolbarButton != null) - stockToolbarButton.SetTexture(GameDatabase.Instance.GetTexture(GuiVisible ? "REPOSoftTech/DeepFreeze/Icons/DeepFreezeOn" : "REPOSoftTech/DeepFreeze/Icons/DeepFreezeOff", false)); - } - - private void DestroyToolBar() - { - if (ToolbarManager.ToolbarAvailable) - { - if (button1 != null) - button1.Destroy(); - } - } - - private void CreateToolBar() - { - if (ToolbarManager.ToolbarAvailable) - { - button1 = ToolbarManager.Instance.add("DeepFreeze", "button1"); - button1.TexturePath = "REPOSoftTech/DeepFreeze/Icons/DFtoolbar"; - button1.ToolTip = "DeepFreeze"; - button1.Visibility = new GameScenesVisibility(GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER, GameScenes.TRACKSTATION); - button1.OnClick += e => GuiVisible = !GuiVisible; - } - } - - private void DestroyStockButton() - { - GameEvents.onGUIApplicationLauncherReady.Remove(OnGUIAppLauncherReady); - if (stockToolbarButton != null) - { - ApplicationLauncher.Instance.RemoveModApplication(stockToolbarButton); - stockToolbarButton = null; - } - } - - private void CreateStockButton() - { - Utilities.Log_Debug("Adding onGUIAppLauncher callbacks"); - if (ApplicationLauncher.Ready) - { - if (stockToolbarButton == null) - OnGUIAppLauncherReady(); - } - else - GameEvents.onGUIApplicationLauncherReady.Add(OnGUIAppLauncherReady); - } - - #endregion AppLauncher - + private double currentTime; + internal void OnDestroy() { - DestroyToolBar(); - DestroyStockButton(); - if (GuiVisible) GuiVisible = !GuiVisible; - GameEvents.onGamePause.Remove(GamePaused); - GameEvents.onGameUnpause.Remove(GameUnPaused); + DFMenuAppLToolBar.Destroy(); } internal void Start() { Utilities.Log_Debug("DeepFreezeGUI startup"); - windowID = new Random().Next(); - CFwindowID = windowID + 1; - KACwindowID = CFwindowID + 1; - VSwindowID = KACwindowID + 1; - VSFwindowID = VSFwindowID + 1; + windowID = Utilities.getnextrandomInt(); + CFwindowID = Utilities.getnextrandomInt(); + KACwindowID = Utilities.getnextrandomInt(); + VSwindowID = Utilities.getnextrandomInt(); + VSFwindowID = Utilities.getnextrandomInt(); DFwindowPos = new Rect(40, Screen.height / 2 - 100, DFWINDOW_WIDTH, WINDOW_BASE_HEIGHT); CFwindowPos = new Rect(450, Screen.height / 2 - 100, CFWINDOW_WIDTH, 250); @@ -275,41 +177,35 @@ internal void Start() DFvslRT = Mathf.Round((DFWINDOW_WIDTH - 28f) * .12f); Utilities.setScaledScreen(); - - // create toolbar button - - if (ToolbarManager.ToolbarAvailable && Useapplauncher == false) - { - CreateToolBar(); - } - else + + DFMenuAppLToolBar = new AppLauncherToolBar("DeepFreeze", "DeepFreeze", + "REPOSoftTech/DeepFreeze/Icons/DFtoolbar", + ApplicationLauncher.AppScenes.SPACECENTER | ApplicationLauncher.AppScenes.FLIGHT | + ApplicationLauncher.AppScenes.MAPVIEW | ApplicationLauncher.AppScenes.SPH | ApplicationLauncher.AppScenes.VAB | + ApplicationLauncher.AppScenes.TRACKSTATION, + GameDatabase.Instance.GetTexture("REPOSoftTech/DeepFreeze/Icons/DeepFreezeOn", false), + GameDatabase.Instance.GetTexture("REPOSoftTech/DeepFreeze/Icons/DeepFreezeOff", false), + GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER, GameScenes.TRACKSTATION); + + //If Settings wants to use ToolBar mod, check it is installed and available. If not set the TST Setting to use Stock. + if (!ToolbarManager.ToolbarAvailable && Useapplauncher) { - // Set up the stock toolbar - CreateStockButton(); + Useapplauncher = true; } - GameEvents.onGamePause.Add(GamePaused); - GameEvents.onGameUnpause.Add(GameUnPaused); - Utilities.Log_Debug("DeepFreezeGUI END startup"); - } - private void GamePaused() - { - gamePaused = true; - } - - private void GameUnPaused() - { - gamePaused = false; + DFMenuAppLToolBar.Start(Useapplauncher); + + Utilities.Log_Debug("DeepFreezeGUI END startup"); } - + private void FixedUpdate() { if (Time.timeSinceLevelLoad < 2f) return; //Wait 2 seconds on level load before executing if (chgECHeatsettings) { - double time = Planetarium.GetUniversalTime(); - if (time - chgECHeatsettingsTimer > 2) + currentTime = Planetarium.GetUniversalTime(); + if (currentTime - chgECHeatsettingsTimer > 2) { chgECHeatsettings = false; } @@ -320,22 +216,19 @@ private void FixedUpdate() private void OnGUI() { - if (!GuiVisible) return; - if (!Textures.StylesSet) Textures.SetupStyles(); if (showSwitchVessel) { - if (!Utilities.WindowVisibile(DFVSwindowPos)) - Utilities.MakeWindowVisible(DFVSwindowPos); + + DFVSwindowPos.ClampToScreen(); DFVSwindowPos = GUILayout.Window(VSwindowID, DFVSwindowPos, windowVS, "DeepFreeze Vessel Switch", GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true), GUILayout.Width(320), GUILayout.MinHeight(100)); } if (showUnabletoSwitchVessel && !switchVesselManual) { - if (!Utilities.WindowVisibile(DFVSFwindowPos)) - Utilities.MakeWindowVisible(DFVSFwindowPos); + DFVSFwindowPos.ClampToScreen(); DFVSFwindowPos = GUILayout.Window(VSFwindowID, DFVSFwindowPos, windowVSF, "DeepFreeze Vessel Switch Failed", GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(true), GUILayout.Width(320), GUILayout.MinHeight(100)); } @@ -347,15 +240,14 @@ private void OnGUI() switchVesselManual = false; } } - if (!GuiVisible || gamePaused || FlightDriver.Pause) + if (!DFMenuAppLToolBar.GuiVisible || DFMenuAppLToolBar.gamePaused || DFMenuAppLToolBar.hideUI) { return; } if (HighLogic.LoadedScene == GameScenes.SPACECENTER || HighLogic.LoadedScene == GameScenes.TRACKSTATION || HighLogic.LoadedScene == GameScenes.FLIGHT) { GUI.skin = HighLogic.Skin; - if (!Utilities.WindowVisibile(DFwindowPos)) - Utilities.MakeWindowVisible(DFwindowPos); + DFwindowPos.ClampInsideScreen(); DFwindowPos = GUILayout.Window(windowID, DFwindowPos, windowDF, "DeepFreeze Kerbals", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true), GUILayout.MinWidth(200), GUILayout.MinHeight(250)); if (showConfigGUI) @@ -382,15 +274,13 @@ private void OnGUI() InputStripLightsOn = StripLightsOn; LoadConfig = false; } - if (!Utilities.WindowVisibile(CFwindowPos)) - Utilities.MakeWindowVisible(CFwindowPos); + CFwindowPos.ClampInsideScreen(); CFwindowPos = GUILayout.Window(CFwindowID, CFwindowPos, windowCF, "DeepFreeze Settings", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true), GUILayout.MinWidth(400), GUILayout.MinHeight(300)); } if (showKACGUI) { - if (!Utilities.WindowVisibile(DFKACwindowPos)) - Utilities.MakeWindowVisible(DFKACwindowPos); + DFKACwindowPos.ClampInsideScreen(); DFKACwindowPos = GUILayout.Window(KACwindowID, DFKACwindowPos, windowKAC, "DeepFreeze Alarms", GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true), GUILayout.MinWidth(360), GUILayout.MinHeight(150)); } @@ -406,7 +296,7 @@ private void windowDF(int id) Rect closeRect = new Rect(DFwindowPos.width - 21, 4, 16, 16); if (GUI.Button(closeRect, closeContent, Textures.ClosebtnStyle)) { - onAppLaunchToggle(); + DFMenuAppLToolBar.onAppLaunchToggle(); return; } @@ -953,30 +843,11 @@ private void windowCF(int id) GUILayout.BeginHorizontal(); if (GUILayout.Button(new GUIContent("Save & Exit Settings", "Exit this menu and Save Settings"), GUILayout.Width(155f))) { + if (Useapplauncher != InputAppL) { - if (InputAppL == true) //Use stock - { - Useapplauncher = InputAppL; - DestroyToolBar(); - CreateStockButton(); - } - else //Use toolbar - { - if (ToolbarManager.ToolbarAvailable) //Is it available? - { - Useapplauncher = InputAppL; - DestroyStockButton(); - CreateToolBar(); - } - else //Otherwise use stock. - { - Useapplauncher = true; - DestroyToolBar(); - CreateStockButton(); - } - - } + Useapplauncher = InputAppL; + DFMenuAppLToolBar.chgAppIconStockToolBar(Useapplauncher); } if (ECreqdForFreezer != InputVECReqd) diff --git a/Source/DeepFreezeOff.png b/Source/DeepFreezeOff.png deleted file mode 100644 index 223c150..0000000 Binary files a/Source/DeepFreezeOff.png and /dev/null differ diff --git a/Source/DeepFreezeOn.png b/Source/DeepFreezeOn.png deleted file mode 100644 index f54c851..0000000 Binary files a/Source/DeepFreezeOn.png and /dev/null differ diff --git a/Source/DeepFreezerPart.cs b/Source/DeepFreezerPart.cs index ff5ebc8..b220610 100644 --- a/Source/DeepFreezerPart.cs +++ b/Source/DeepFreezerPart.cs @@ -28,15 +28,6 @@ namespace DF { - public enum DoorState - { - OPEN, - CLOSED, - OPENING, - CLOSING, - UNKNOWN - } - public class DeepFreezer : PartModule, IResourceConsumer { private float lastUpdate; // time since we last updated the part menu @@ -186,7 +177,7 @@ public void showMenu() { DeepFreezeGUI obj = DeepFreeze.Instance.GetComponent("DeepFreezeGUI") as DeepFreezeGUI; if (obj != null) - obj.GuiVisible = !obj.GuiVisible; + obj.DFMenuAppLToolBar.GuiVisible = !obj.DFMenuAppLToolBar.GuiVisible; else Utilities.Log("DeepFreezer ToggleMenu error"); } @@ -1466,14 +1457,14 @@ private void ChkOngoingTemp(PartInfo partInfo) public override void OnLoad(ConfigNode node) { - Debug.Log("DeepFreezer onLoad"); + //Debug.Log("DeepFreezer onLoad"); base.OnLoad(node); cryopodstateclosed = new bool[FreezerSize]; seatTakenbyFrznKerbal = new bool[FreezerSize]; loadcryopodstatepersistent(); loadexternaldoorstatepersistent(); - Debug.Log("OnLoad: " + node); - Debug.Log("DeepFreezer end onLoad"); + //Debug.Log("OnLoad: " + node); + //Debug.Log("DeepFreezer end onLoad"); } public override void OnStart(StartState state) @@ -1631,12 +1622,12 @@ public override void OnStart(StartState state) public override void OnSave(ConfigNode node) { - Debug.Log("DeepFreezer onSave"); + //Debug.Log("DeepFreezer onSave"); savecryopodstatepersistent(); saveexternaldoorstatepersistent(); base.OnSave(node); - Debug.Log("OnSave: " + node); - Debug.Log("DeepFreezer end onSave"); + //Debug.Log("OnSave: " + node); + //Debug.Log("DeepFreezer end onSave"); } private void OnDestroy() @@ -4619,77 +4610,5 @@ public static void FixedBackgroundUpdate(Vessel v, uint partFlightID, Func<Vesse #endregion BackgroundProcessing } - - #region ExtDoorMgr - - public class DFExtDoorMgr : InternalModule - { - private DeepFreezer Freezer; - - public override void OnUpdate() - { - base.OnUpdate(); - if (HighLogic.LoadedSceneIsFlight && FlightGlobals.ready && FlightGlobals.ActiveVessel != null) - { - if (Freezer == null) - { - Freezer = part.FindModuleImplementing<DeepFreezer>(); - Utilities.Log_Debug("DFExtDoorMgr OnUpdate Set part " + part.name); - } - } - } - - public void ButtonExtDoor(bool state) - { - if (Freezer == null) - { - Freezer = part.FindModuleImplementing<DeepFreezer>(); - Utilities.Log_Debug("DFExtDoorMgr buttonExtDoorState set part " + part.name); - } - if (Freezer == null) return; // If freezer is still null just return - if (!Freezer.ExternalDoorActive) return; // if freezer doesn't have an external door just return. - - if (Freezer._externaldoorstate == DoorState.OPEN) - { - //Door is open so we trigger a closedoor. - Freezer.eventCloseDoors(); - Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired triggerred eventCloseDoors"); - } - else - { - if (Freezer._externaldoorstate == DoorState.CLOSED) - { - //Door is closed so we trigger a opendoor. - Freezer.eventOpenDoors(); - Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired triggerred eventOpenDoors"); - } - else - { - // door already opening or closing... - Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoor fired but door state is opening, closing or unknown"); - } - } - } - - public bool ButtonExtDoorState() - { - // Utilities.Log_Debug("DFExtDoorMgr ButtonExtDoorState fired"); - if (Freezer == null) - { - Freezer = part.FindModuleImplementing<DeepFreezer>(); - Utilities.Log_Debug("DFExtDoorMgr buttonExtDoorState set part " + part.name); - } - if (Freezer == null) return false; // if freezer still null return false - if (!Freezer.ExternalDoorActive) return false; // if freezer doesn't have an external door just return. - if (Freezer._externaldoorstate == DoorState.CLOSED || Freezer._externaldoorstate == DoorState.CLOSING || Freezer._externaldoorstate == DoorState.UNKNOWN) - { - Utilities.Log_Debug("DFExtDoorMgr Door is closed or closing or unknown return state false"); - return false; - } - Utilities.Log_Debug("DFExtDoorMgr Door is open or opening return state true"); - return true; - } - } - - #endregion ExtDoorMgr + } \ No newline at end of file diff --git a/Source/KACWrapper.cs b/Source/KACWrapper.cs deleted file mode 100644 index a4cfc3d..0000000 --- a/Source/KACWrapper.cs +++ /dev/null @@ -1,651 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Reflection; - -// TODO: Change this namespace to something specific to your plugin here. -//EG: -// namespace MyPlugin_KACWrapper -namespace DF -{ - /////////////////////////////////////////////////////////////////////////////////////////// - // BELOW HERE SHOULD NOT BE EDITED - this links to the loaded KAC module without requiring a Hard Dependancy - /////////////////////////////////////////////////////////////////////////////////////////// - - /// <summary> - /// The Wrapper class to access KAC from another plugin - /// </summary> - public class KACWrapper - { - protected static System.Type KACType; - protected static System.Type KACAlarmType; - - protected static Object actualKAC = null; - - /// <summary> - /// This is the Kerbal Alarm Clock object - /// - /// SET AFTER INIT - /// </summary> - public static KACAPI KAC = null; - - /// <summary> - /// Whether we found the KerbalAlarmClock assembly in the loadedassemblies. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean AssemblyExists { get { return (KACType != null); } } - - /// <summary> - /// Whether we managed to hook the running Instance from the assembly. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean InstanceExists { get { return (KAC != null); } } - - /// <summary> - /// Whether we managed to wrap all the methods/functions from the instance. - /// - /// SET AFTER INIT - /// </summary> - private static Boolean _KACWrapped = false; - - /// <summary> - /// Whether the object has been wrapped and the APIReady flag is set in the real KAC - /// </summary> - public static Boolean APIReady { get { return _KACWrapped && KAC.APIReady && !NeedUpgrade; } } - - public static Boolean NeedUpgrade { get; private set; } - - /// <summary> - /// This method will set up the KAC object and wrap all the methods/functions - /// </summary> - /// <param name="Force">This option will force the Init function to rebind everything</param> - /// <returns></returns> - public static Boolean InitKACWrapper() - { - //if (!_KACWrapped ) - //{ - //reset the internal objects - _KACWrapped = false; - actualKAC = null; - KAC = null; - LogFormatted("Attempting to Grab KAC Types..."); - - //find the base type - KACType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "KerbalAlarmClock.KerbalAlarmClock"); - - if (KACType == null) - { - return false; - } - - LogFormatted("KAC Version:{0}", KACType.Assembly.GetName().Version.ToString()); - if (KACType.Assembly.GetName().Version.CompareTo(new System.Version(3, 0, 0, 5)) < 0) - { - //No TimeEntry or alarmchoice options = need a newer version - NeedUpgrade = true; - } - - //now the Alarm Type - KACAlarmType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "KerbalAlarmClock.KACAlarm"); - - if (KACAlarmType == null) - { - return false; - } - - //now grab the running instance - LogFormatted("Got Assembly Types, grabbing Instance"); - - try - { - actualKAC = KACType.GetField("APIInstance", BindingFlags.Public | BindingFlags.Static).GetValue(null); - } - catch (Exception) - { - NeedUpgrade = true; - LogFormatted("No APIInstance found - most likely you have KAC v2 installed"); - //throw; - } - if (actualKAC == null) - { - LogFormatted("Failed grabbing Instance"); - return false; - } - - //If we get this far we can set up the local object and its methods/functions - LogFormatted("Got Instance, Creating Wrapper Objects"); - KAC = new KACAPI(actualKAC); - //} - _KACWrapped = true; - return true; - } - - /// <summary> - /// The Type that is an analogue of the real KAC. This lets you access all the API-able properties and Methods of the KAC - /// </summary> - public class KACAPI - { - internal KACAPI(Object KAC) - { - //store the actual object - actualKAC = KAC; - - //these sections get and store the reflection info and actual objects where required. Later in the properties we then read the values from the actual objects - //for events we also add a handler - LogFormatted("Getting APIReady Object"); - APIReadyField = KACType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); - LogFormatted("Success: " + (APIReadyField != null).ToString()); - - //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPEL HERE - LogFormatted("Getting Alarms Object"); - AlarmsField = KACType.GetField("alarms", BindingFlags.Public | BindingFlags.Static); - actualAlarms = AlarmsField.GetValue(actualKAC); - LogFormatted("Success: " + (actualAlarms != null).ToString()); - - //Events - LogFormatted("Getting Alarm State Change Event"); - onAlarmStateChangedEvent = KACType.GetEvent("onAlarmStateChanged", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (onAlarmStateChangedEvent != null).ToString()); - LogFormatted_DebugOnly("Adding Handler"); - AddHandler(onAlarmStateChangedEvent, actualKAC, AlarmStateChanged); - - //Methods - LogFormatted("Getting Create Method"); - CreateAlarmMethod = KACType.GetMethod("CreateAlarm", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (CreateAlarmMethod != null).ToString()); - - LogFormatted("Getting Delete Method"); - DeleteAlarmMethod = KACType.GetMethod("DeleteAlarm", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (DeleteAlarmMethod != null).ToString()); - - LogFormatted("Getting DrawAlarmAction"); - DrawAlarmActionChoiceMethod = KACType.GetMethod("DrawAlarmActionChoiceAPI", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (DrawAlarmActionChoiceMethod != null).ToString()); - - //LogFormatted("Getting DrawTimeEntry"); - //DrawTimeEntryMethod = KACType.GetMethod("DrawTimeEntryAPI", BindingFlags.Public | BindingFlags.Instance); - //LogFormatted_DebugOnly("Success: " + (DrawTimeEntryMethod != null).ToString()); - - //Commenting out rubbish lines - //MethodInfo[] mis = KACType.GetMethods(BindingFlags.Public | BindingFlags.Instance); - //foreach (MethodInfo mi in mis) - //{ - // LogFormatted("M:{0}-{1}", mi.Name, mi.DeclaringType); - //} - } - - private Object actualKAC; - - private FieldInfo APIReadyField; - - /// <summary> - /// Whether the APIReady flag is set in the real KAC - /// </summary> - public Boolean APIReady - { - get - { - if (APIReadyField == null) - return false; - - return (Boolean)APIReadyField.GetValue(null); - } - } - - #region Alarms - - private Object actualAlarms; - private FieldInfo AlarmsField; - - /// <summary> - /// The list of Alarms that are currently active in game - /// </summary> - internal KACAlarmList Alarms - { - get - { - return ExtractAlarmList(actualAlarms); - } - } - - /// <summary> - /// This converts the KACAlarmList actual object to a new List for consumption - /// </summary> - /// <param name="actualAlarmList"></param> - /// <returns></returns> - private KACAlarmList ExtractAlarmList(Object actualAlarmList) - { - KACAlarmList ListToReturn = new KACAlarmList(); - try - { - //iterate each "value" in the dictionary - - foreach (var item in (IList)actualAlarmList) - { - KACAlarm r1 = new KACAlarm(item); - ListToReturn.Add(r1); - } - } - catch (Exception) - { - //LogFormatted("Arrggg: {0}", ex.Message); - //throw ex; - // - } - return ListToReturn; - } - - #endregion Alarms - - #region Events - - /// <summary> - /// Takes an EventInfo and binds a method to the event firing - /// </summary> - /// <param name="Event">EventInfo of the event we want to attach to</param> - /// <param name="KACObject">actual object the eventinfo is gathered from</param> - /// <param name="Handler">Method that we are going to hook to the event</param> - protected void AddHandler(EventInfo Event, Object KACObject, Action<Object> Handler) - { - //build a delegate - Delegate d = Delegate.CreateDelegate(Event.EventHandlerType, Handler.Target, Handler.Method); - //get the Events Add method - MethodInfo addHandler = Event.GetAddMethod(); - //and add the delegate - addHandler.Invoke(KACObject, new System.Object[] { d }); - } - - //the info about the event; - private EventInfo onAlarmStateChangedEvent; - - /// <summary> - /// Event that fires when the State of an Alarm changes - /// </summary> - public event AlarmStateChangedHandler onAlarmStateChanged; - - /// <summary> - /// Structure of the event delegeate - /// </summary> - /// <param name="e"></param> - public delegate void AlarmStateChangedHandler(AlarmStateChangedEventArgs e); - - /// <summary> - /// This is the structure that holds the event arguments - /// </summary> - public class AlarmStateChangedEventArgs - { - public AlarmStateChangedEventArgs(System.Object actualEvent, KACAPI kac) - { - Type type = actualEvent.GetType(); - this.alarm = new KACAlarm(type.GetField("alarm").GetValue(actualEvent)); - this.eventType = (KACAlarm.AlarmStateEventsEnum)type.GetField("eventType").GetValue(actualEvent); - } - - /// <summary> - /// Alarm that has had the state change - /// </summary> - public KACAlarm alarm; - - /// <summary> - /// What the state was before the event - /// </summary> - public KACAlarm.AlarmStateEventsEnum eventType; - } - - /// <summary> - /// private function that grabs the actual event and fires our wrapped one - /// </summary> - /// <param name="actualEvent">actual event from the KAC</param> - private void AlarmStateChanged(object actualEvent) - { - if (onAlarmStateChanged != null) - { - onAlarmStateChanged(new AlarmStateChangedEventArgs(actualEvent, this)); - } - } - - #endregion Events - - #region Methods - - private MethodInfo CreateAlarmMethod; - - /// <summary> - /// Create a new Alarm - /// </summary> - /// <param name="AlarmType">What type of alarm are we creating</param> - /// <param name="Name">Name of the Alarm for the display</param> - /// <param name="UT">Universal Time for the alarm</param> - /// <returns>ID of the newly created alarm</returns> - internal String CreateAlarm(AlarmTypeEnum AlarmType, String Name, Double UT) - { - return (String)CreateAlarmMethod.Invoke(actualKAC, new System.Object[] { (Int32)AlarmType, Name, UT }); - } - - private MethodInfo DeleteAlarmMethod; - - /// <summary> - /// Delete an Alarm - /// </summary> - /// <param name="AlarmID">Unique ID of the alarm</param> - /// <returns>Success of the deletion</returns> - internal Boolean DeleteAlarm(String AlarmID) - { - return (Boolean)DeleteAlarmMethod.Invoke(actualKAC, new System.Object[] { AlarmID }); - } - - private MethodInfo DrawAlarmActionChoiceMethod; - - /// <summary> - /// Delete an Alarm - /// </summary> - /// <param name="AlarmID">Unique ID of the alarm</param> - /// <returns>Success of the deletion</returns> - internal Boolean DrawAlarmActionChoice(ref AlarmActionEnum Choice, String LabelText, Int32 LabelWidth, Int32 ButtonWidth) - { - Int32 InValue = (Int32)Choice; - Int32 OutValue = (Int32)DrawAlarmActionChoiceMethod.Invoke(actualKAC, new System.Object[] { InValue, LabelText, LabelWidth, ButtonWidth }); - - Choice = (AlarmActionEnum)OutValue; - return (InValue != OutValue); - } - - //Remmed out due to it borking window layout - //private MethodInfo DrawTimeEntryMethod; - ///// <summary> - ///// Delete an Alarm - ///// </summary> - ///// <param name="AlarmID">Unique ID of the alarm</param> - ///// <returns>Success of the deletion</returns> - - //internal Boolean DrawTimeEntry(ref Double Time, TimeEntryPrecisionEnum Prec, String LabelText, Int32 LabelWidth) - //{ - // Double InValue = Time; - // Double OutValue = (Double)DrawTimeEntryMethod.Invoke(actualKAC, new System.Object[] { InValue, (Int32)Prec, LabelText, LabelWidth }); - - // Time = OutValue; - // return (InValue != OutValue); - //} - - #endregion Methods - - public class KACAlarm - { - internal KACAlarm(Object a) - { - actualAlarm = a; - VesselIDField = KACAlarmType.GetField("VesselID"); - IDField = KACAlarmType.GetField("ID"); - NameField = KACAlarmType.GetField("Name"); - NotesField = KACAlarmType.GetField("Notes"); - AlarmTypeField = KACAlarmType.GetField("TypeOfAlarm"); - AlarmTimeProperty = KACAlarmType.GetProperty("AlarmTimeUT"); - AlarmMarginField = KACAlarmType.GetField("AlarmMarginSecs"); - AlarmActionField = KACAlarmType.GetField("AlarmAction"); - RemainingField = KACAlarmType.GetField("Remaining"); - - XferOriginBodyNameField = KACAlarmType.GetField("XferOriginBodyName"); - //LogFormatted("XFEROrigin:{0}", XferOriginBodyNameField == null); - XferTargetBodyNameField = KACAlarmType.GetField("XferTargetBodyName"); - - RepeatAlarmField = KACAlarmType.GetField("RepeatAlarm"); - RepeatAlarmPeriodProperty = KACAlarmType.GetProperty("RepeatAlarmPeriodUT"); - - //PropertyInfo[] pis = KACAlarmType.GetProperties(); - //foreach (PropertyInfo pi in pis) - //{ - // LogFormatted("P:{0}-{1}", pi.Name, pi.DeclaringType); - //} - //FieldInfo[] fis = KACAlarmType.GetFields(); - //foreach (FieldInfo fi in fis) - //{ - // LogFormatted("F:{0}-{1}", fi.Name, fi.DeclaringType); - //} - } - - private Object actualAlarm; - - private FieldInfo VesselIDField; - - /// <summary> - /// Unique Identifier of the Vessel that the alarm is attached to - /// </summary> - public String VesselID - { - get { return (String)VesselIDField.GetValue(actualAlarm); } - set { VesselIDField.SetValue(actualAlarm, value); } - } - - private FieldInfo IDField; - - /// <summary> - /// Unique Identifier of this alarm - /// </summary> - public String ID - { - get { return (String)IDField.GetValue(actualAlarm); } - } - - private FieldInfo NameField; - - /// <summary> - /// Short Text Name for the Alarm - /// </summary> - public String Name - { - get { return (String)NameField.GetValue(actualAlarm); } - set { NameField.SetValue(actualAlarm, value); } - } - - private FieldInfo NotesField; - - /// <summary> - /// Longer Text Description for the Alarm - /// </summary> - public String Notes - { - get { return (String)NotesField.GetValue(actualAlarm); } - set { NotesField.SetValue(actualAlarm, value); } - } - - private FieldInfo XferOriginBodyNameField; - - /// <summary> - /// Name of the origin body for a transfer - /// </summary> - public String XferOriginBodyName - { - get { return (String)XferOriginBodyNameField.GetValue(actualAlarm); } - set { XferOriginBodyNameField.SetValue(actualAlarm, value); } - } - - private FieldInfo XferTargetBodyNameField; - - /// <summary> - /// Name of the destination body for a transfer - /// </summary> - public String XferTargetBodyName - { - get { return (String)XferTargetBodyNameField.GetValue(actualAlarm); } - set { XferTargetBodyNameField.SetValue(actualAlarm, value); } - } - - private FieldInfo AlarmTypeField; - - /// <summary> - /// What type of Alarm is this - affects icon displayed and some calc options - /// </summary> - public AlarmTypeEnum AlarmType { get { return (AlarmTypeEnum)AlarmTypeField.GetValue(actualAlarm); } } - - private PropertyInfo AlarmTimeProperty; - - /// <summary> - /// In game UT value of the alarm - /// </summary> - public Double AlarmTime - { - get { return (Double)AlarmTimeProperty.GetValue(actualAlarm, null); } - set { AlarmTimeProperty.SetValue(actualAlarm, value, null); } - } - - private FieldInfo AlarmMarginField; - - /// <summary> - /// In game seconds the alarm will fire before the event it is for - /// </summary> - public Double AlarmMargin - { - get { return (Double)AlarmMarginField.GetValue(actualAlarm); } - set { AlarmMarginField.SetValue(actualAlarm, value); } - } - - private FieldInfo AlarmActionField; - - /// <summary> - /// What should the Alarm Clock do when the alarm fires - /// </summary> - public AlarmActionEnum AlarmAction - { - get { return (AlarmActionEnum)AlarmActionField.GetValue(actualAlarm); } - set { AlarmActionField.SetValue(actualAlarm, (Int32)value); } - } - - private FieldInfo RemainingField; - - /// <summary> - /// How much Game time is left before the alarm fires - /// </summary> - public Double Remaining { get { return (Double)RemainingField.GetValue(actualAlarm); } } - - private FieldInfo RepeatAlarmField; - - /// <summary> - /// Whether the alarm will be repeated after it fires - /// </summary> - public Boolean RepeatAlarm - { - get { return (Boolean)RepeatAlarmField.GetValue(actualAlarm); } - set { RepeatAlarmField.SetValue(actualAlarm, value); } - } - - private PropertyInfo RepeatAlarmPeriodProperty; - - /// <summary> - /// Value in Seconds after which the alarm will repeat - /// </summary> - public Double RepeatAlarmPeriod - { - get - { - try { return (Double)RepeatAlarmPeriodProperty.GetValue(actualAlarm, null); } - catch (Exception) { return 0; } - } - set { RepeatAlarmPeriodProperty.SetValue(actualAlarm, value, null); } - } - - public enum AlarmStateEventsEnum - { - Created, - Triggered, - Closed, - Deleted, - } - } - - public enum AlarmTypeEnum - { - Raw, - Maneuver, - ManeuverAuto, - Apoapsis, - Periapsis, - AscendingNode, - DescendingNode, - LaunchRendevous, - Closest, - SOIChange, - SOIChangeAuto, - Transfer, - TransferModelled, - Distance, - Crew, - EarthTime, - Contract, - ContractAuto - } - - public enum AlarmActionEnum - { - [Description("Do Nothing-Delete When Past")] - DoNothingDeleteWhenPassed, - - [Description("Do Nothing")] - DoNothing, - - [Description("Message Only-No Affect on warp")] - MessageOnly, - - [Description("Kill Warp Only-No Message")] - KillWarpOnly, - - [Description("Kill Warp and Message")] - KillWarp, - - [Description("Pause Game and Message")] - PauseGame, - } - - public enum TimeEntryPrecisionEnum - { - Seconds = 0, - Minutes = 1, - Hours = 2, - Days = 3, - Years = 4 - } - - public class KACAlarmList : List<KACAlarm> - { - } - } - - #region Logging Stuff - - /// <summary> - /// Some Structured logging to the debug file - ONLY RUNS WHEN DLL COMPILED IN DEBUG MODE - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - [System.Diagnostics.Conditional("DEBUG")] - internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) - { - LogFormatted(Message, strParams); - } - - /// <summary> - /// Some Structured logging to the debug file - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - internal static void LogFormatted(String Message, params Object[] strParams) - { - Message = String.Format(Message, strParams); - String strMessageLine = String.Format("{0},{2}-{3},{1}", - DateTime.Now, Message, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, - System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); - UnityEngine.Debug.Log(strMessageLine); - } - - #endregion Logging Stuff - } -} \ No newline at end of file diff --git a/Source/LocalDev/7za_dir.txt b/Source/LocalDev/7za_dir.txt deleted file mode 100644 index 72fa16e..0000000 --- a/Source/LocalDev/7za_dir.txt +++ /dev/null @@ -1 +0,0 @@ -C:\7za\ diff --git a/Source/LocalDev/ksp_dir.txt b/Source/LocalDev/ksp_dir.txt deleted file mode 100644 index d8e4629..0000000 --- a/Source/LocalDev/ksp_dir.txt +++ /dev/null @@ -1 +0,0 @@ -C:\KSP 1.1\Kerbal Space Program - Test diff --git a/Source/LocalDev/mono_exe.txt b/Source/LocalDev/mono_exe.txt deleted file mode 100644 index 5c5c055..0000000 --- a/Source/LocalDev/mono_exe.txt +++ /dev/null @@ -1 +0,0 @@ -C:\Program Files (x86)\mono\bin\mono.exe diff --git a/Source/LocalDev/pdb2mdb_exe.txt b/Source/LocalDev/pdb2mdb_exe.txt deleted file mode 100644 index 254b355..0000000 --- a/Source/LocalDev/pdb2mdb_exe.txt +++ /dev/null @@ -1 +0,0 @@ -C:\Program Files (x86)\mono\lib\mono\4.5\pdb2mdb.exe diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs index 0ccd1a7..d50958c 100644 --- a/Source/Properties/AssemblyInfo.cs +++ b/Source/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.22.1.0")] -[assembly: AssemblyFileVersion("0.22.1.0")] +[assembly: AssemblyVersion("0.22.2.0")] +[assembly: AssemblyFileVersion("0.22.2.0")] [assembly: KSPAssembly("DeepFreeze", 0, 22)] \ No newline at end of file diff --git a/Source/REPOSoftTechKSPUtils/AppLauncherToolBarExtension.cs b/Source/REPOSoftTechKSPUtils/AppLauncherToolBarExtension.cs new file mode 100644 index 0000000..636f407 --- /dev/null +++ b/Source/REPOSoftTechKSPUtils/AppLauncherToolBarExtension.cs @@ -0,0 +1,355 @@ +/* + * AppLauncherToolBar.cs + * (C) Copyright 2016, Jamie Leighton (JPLRepo) + * REPOSoft Technologies + * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This + * project is in no way associated with nor endorsed by Squad. + * + * This file is part of RST Utils. My attempt at creating my own KSP Mod base Architecture. + * + * RST Utils is free software: you can redistribute it and/or modify + * it under the terms of the MIT License + * + * RST Utils is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the MIT License + * along with RST Utils. If not, see <http://opensource.org/licenses/MIT>. + * + */ +using System; +using KSP.UI.Screens; +using UnityEngine; + +namespace RSTUtils +{ + public class AppLauncherToolBar + { + public static AppLauncherToolBar Instance { get; private set; } + + private bool usingToolbar = false; //Set to true if user is using ToolBar + private IButton button1; //ToolBar button + private string toolBarName; //set to Name for button on ToolBar (modname) + private string toolBarToolTip; // set tooltip for ToolBar button + private string toolBarTexturePath; //The TooBar formatted Texture Path + private GameScenesVisibility toolBarGameScenes; //GameScenes toolbar button can be seen in + + private bool usingStock = false; //Set to true if user is using Stock AppLauncher + private ApplicationLauncherButton stockToolbarButton; // Stock Toolbar Button + private ApplicationLauncher.AppScenes VisibleinScenes; //What scenes is the applauncher button seen in + private UnityEngine.Texture appbtnTexON; //Texture for AppLauncher button when ON + private UnityEngine.Texture appbtnTexOFF; //Texture for AppLauncher button when OFF + private bool showHoverText = false; //Whether to show AppLauncher Hover Text or not. + + private bool _gamePaused; + public Boolean gamePaused + { + get { return _gamePaused; } + private set + { + _gamePaused = value; //Set the private variable + } + } + + private bool _hideUI; + public Boolean hideUI + { + get { return _hideUI; } + private set + { + _hideUI = value; //Set the private variable + } + } + + public bool StockButtonNotNull + { + get { return stockToolbarButton != null; } + } + + public bool ToolBarButtonNotNull + { + get { return button1 != null; } + } + + public bool usingToolBar + { + get { return usingToolbar; } + } + + public bool usingAppLauncher + { + get { return usingStock; } + } + + //GuiVisibility + private bool _Visible; + public Boolean GuiVisible + { + get { return _Visible; } + set + { + _Visible = value; //Set the private variable + } + } + + public bool ShowHoverText + { + get { return showHoverText; } + } + + private void GamePaused() + { + gamePaused = true; + } + + private void GameUnPaused() + { + gamePaused = false; + } + + private void onHideUI() + { + hideUI = true; + } + + private void onShowUI() + { + hideUI = false; + } + /// <summary> + /// Constructor for AppLauncherToolBar. You need to construct one of these for your Mod Menu/GUI environment. + /// </summary> + /// <param name="toolBarName">A string passed into ToolBar indicating the Name of the Mod</param> + /// <param name="toolBarToolTip">A string passed into ToolBar to use for the Icon ToolTip</param> + /// <param name="toolBarTexturePath">A string in ToolBar expected format of the TexturePath for the ToolBarIcon</param> + /// <param name="VisibleinScenes">ApplicationLauncher.AppScenes list - logically OR'd</param> + /// <param name="appbtnTexON">Texture reference for the AppLauncher ON Icon</param> + /// <param name="appbtnTexOFF">Texture reference for the AppLauncher OFF Icon</param> + /// <param name="gameScenes">A list of GameScenes use for ToolBar icon visiblity</param> + public AppLauncherToolBar(string toolBarName, string toolBarToolTip, string toolBarTexturePath, + ApplicationLauncher.AppScenes VisibleinScenes, UnityEngine.Texture appbtnTexON, UnityEngine.Texture appbtnTexOFF, params GameScenes[] gameScenes) + { + Instance = this; + if (ToolbarManager.ToolbarAvailable) + { + this.toolBarName = toolBarName; + this.toolBarToolTip = toolBarToolTip; + this.toolBarTexturePath = toolBarTexturePath; + this.toolBarGameScenes = new GameScenesVisibility(gameScenes); + } + this.VisibleinScenes = VisibleinScenes; + this.appbtnTexON = appbtnTexON; + this.appbtnTexOFF = appbtnTexOFF; + } + + private void OnGUIAppLauncherReady() + { + Utilities.Log_Debug("OnGUIAppLauncherReady"); + if (ApplicationLauncher.Ready) + { + Utilities.Log_Debug("Adding AppLauncherButton"); + stockToolbarButton = ApplicationLauncher.Instance.AddModApplication( + onAppLaunchToggle, + onAppLaunchToggle, + onHoverOn, + onHoverOff, + DummyVoid, + DummyVoid, + VisibleinScenes, + appbtnTexOFF); + } + } + + private void DummyVoid() + { + } + + private void onHoverOn() + { + showHoverText = true; + } + private void onHoverOff() + { + showHoverText = false; + } + + public void onAppLaunchToggle() + { + GuiVisible = !GuiVisible; + if (stockToolbarButton != null) + { + stockToolbarButton.SetTexture(GuiVisible ? appbtnTexON : appbtnTexOFF); + } + } + + private void DestroyToolBar() + { + if (ToolbarManager.ToolbarAvailable) + { + if (button1 != null) + button1.Destroy(); + } + } + + private void CreateToolBar() + { + if (ToolbarManager.ToolbarAvailable) + { + button1 = ToolbarManager.Instance.add(toolBarName, "button1"); + button1.TexturePath = toolBarTexturePath; + button1.ToolTip = toolBarToolTip; + button1.Visibility = toolBarGameScenes; + button1.OnClick += e => GuiVisible = !GuiVisible; + } + } + + private void DestroyStockButton() + { + GameEvents.onGUIApplicationLauncherReady.Remove(OnGUIAppLauncherReady); + if (stockToolbarButton != null) + { + ApplicationLauncher.Instance.RemoveModApplication(stockToolbarButton); + stockToolbarButton = null; + } + } + + private void CreateStockButton() + { + Utilities.Log_Debug("Adding onGUIAppLauncher callbacks"); + if (ApplicationLauncher.Ready) + { + if (stockToolbarButton == null) + OnGUIAppLauncherReady(); + } + else + GameEvents.onGUIApplicationLauncherReady.Add(OnGUIAppLauncherReady); + } + + private void OnGameSceneLoadRequestedForAppLauncher(GameScenes SceneToLoad) + { + if (stockToolbarButton != null) + { + ApplicationLauncherButton[] lstButtons = UnityEngine.Object.FindObjectsOfType<ApplicationLauncherButton>(); + Utilities.Log_Debug("TSTMenu AppLauncher: Destroying Button-Button Count:" + lstButtons.Length); + ApplicationLauncher.Instance.RemoveModApplication(stockToolbarButton); + stockToolbarButton = null; + } + } + + /// <summary> + /// This Class is not using MonoBehaviour but has a Start Method that must be called. + /// Call this in your Start Method for a Mod GUI/Menu Class. + /// </summary> + /// <param name="stock">True if we are to use the Stock Applauncher, False to use ToolBar mod</param> + public void Start(bool stock) + { + DestroyToolBar(); + if (ToolbarManager.ToolbarAvailable && !stock) + { + // Set up ToolBar button + CreateToolBar(); + usingToolbar = true; + usingStock = false; + } + else + { + // Set up the stock toolbar + CreateStockButton(); + usingToolbar = false; + usingStock = true; + } + GameEvents.onGameSceneLoadRequested.Add(OnGameSceneLoadRequestedForAppLauncher); + GameEvents.onGamePause.Add(GamePaused); + GameEvents.onGameUnpause.Add(GameUnPaused); + GameEvents.onHideUI.Add(onHideUI); + GameEvents.onShowUI.Add(onShowUI); + } + + /// <summary> + /// This Class is not using MonoBehaviour but has a Destroy Method that must be called. + /// Call this in your OnDestroy Method for a Mod GUI/Menu Class. + /// </summary> + public void Destroy() + { + DestroyToolBar(); + + // Stock toolbar + Utilities.Log_Debug("Removing onGUIAppLauncher callbacks"); + + DestroyStockButton(); + + if (GuiVisible) GuiVisible = !GuiVisible; + GameEvents.onGameSceneLoadRequested.Remove(OnGameSceneLoadRequestedForAppLauncher); + GameEvents.onGamePause.Remove(GamePaused); + GameEvents.onGameUnpause.Remove(GameUnPaused); + GameEvents.onHideUI.Remove(onHideUI); + GameEvents.onShowUI.Remove(onShowUI); + } + + /// <summary> + /// Sets the ToolBar Icon visible or not. To be extended in future to not require calling from Mod. + /// Currently it is because I haven't incorporated the mod's Setting for Whether the user wants to use Stock AppLauncher or Toolbar. + /// </summary> + /// <param name="visible">True if set to visible, false will turn it off</param> + public void setToolBarBtnVisibility(bool visible) + { + button1.Visible = visible; + } + + /// <summary> + /// Sets the Applauncher Icon visible or not. To be extended in future to not require calling from Mod. + /// Currently it is because I haven't incorporated the mod's Setting for Whether the user wants to use Stock AppLauncher or Toolbar. + /// </summary> + /// <param name="visible">True if set to visible, false will turn it off</param> + public void setAppLSceneVisibility(ApplicationLauncher.AppScenes visibleinScenes) + { + VisibleinScenes = visibleinScenes; + stockToolbarButton.VisibleInScenes = VisibleinScenes; + } + + /// <summary> + /// Call this to change from AppLauncher to Toobar or vice-versa. + /// Will Destroy ToolBar or AppLauncher Icon and create a new one. + /// </summary> + /// <param name="stock">True if using AppLauncher, False if using ToolBar</param> + public void chgAppIconStockToolBar(bool stock) + { + if (!stock && ToolbarManager.ToolbarAvailable) + { + DestroyStockButton(); + DestroyToolBar(); + CreateToolBar(); + usingToolbar = true; + usingStock = false; + + } + else + { + DestroyToolBar(); + DestroyStockButton(); + CreateStockButton(); + usingToolbar = false; + usingStock = true; + } + } + + /// <summary> + /// Change the ToolBar TexturePath - to say change the Icon + /// </summary> + /// <param name="icontoSet">string in ToolBar TexturePath format</param> + public void setToolBarTexturePath(string icontoSet) + { + button1.TexturePath = icontoSet; + } + + /// <summary> + /// Change the AppLauncher Icon Texture - to say change the Icon + /// </summary> + /// <param name="icontoSet">Texture to set Icon to</param> + public void setAppLauncherTexture(Texture icontoSet) + { + stockToolbarButton.SetTexture(icontoSet); + } + } +} diff --git a/Source/REPOSoftTechKSPUtils/RSTutilities.cs b/Source/REPOSoftTechKSPUtils/RSTutilities.cs index 88e2e23..f947ad0 100644 --- a/Source/REPOSoftTechKSPUtils/RSTutilities.cs +++ b/Source/REPOSoftTechKSPUtils/RSTutilities.cs @@ -1,16 +1,18 @@ -/** - * REPOSoftTech KSP Utilities - * (C) Copyright 2015, Jamie Leighton - * - * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This - * project is in no way associated with nor endorsed by Squad. - * - * - * Licensed under the Attribution-NonCommercial-ShareAlike (CC BY-NC-SA 4.0) creative commons license. - * See <https://creativecommons.org/licenses/by-nc-sa/4.0/> for full details (except where else specified in this file). - * - */ - + + +using HighlightingSystem; +/** +* REPOSoftTech KSP Utilities +* (C) Copyright 2015, Jamie Leighton +* +* Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This +* project is in no way associated with nor endorsed by Squad. +* +* +* Licensed under the Attribution-NonCommercial-ShareAlike (CC BY-NC-SA 4.0) creative commons license. +* See <https://creativecommons.org/licenses/by-nc-sa/4.0/> for full details (except where else specified in this file). +* +*/ using System; using System.Collections; using System.Collections.Generic; @@ -29,7 +31,7 @@ public enum GameState EDITOR = 1, EVA = 2, SPACECENTER = 3, - OTHER = 4 + OTHER = 4 } internal static class Utilities @@ -42,15 +44,17 @@ public static int getnextrandomInt() _nextrandomInt ++; return _nextrandomInt; } - + + private static GameState state; + //Set the Game State mode indicator, 0 = inflight, 1 = editor, 2 on EVA or F2 public static bool GameModeisFlight { get { - GameState state = SetModeFlag(); + state = SetModeFlag(); if (state == GameState.FLIGHT) return true; - return false; + return false; } } @@ -58,9 +62,9 @@ public static bool GameModeisEditor { get { - GameState state = SetModeFlag(); + state = SetModeFlag(); if (state == GameState.EDITOR) return true; - return false; + return false; } } @@ -68,9 +72,9 @@ public static bool GameModeisEVA { get { - GameState state = SetModeFlag(); + state = SetModeFlag(); if (state == GameState.EVA) return true; - return false; + return false; } } @@ -78,9 +82,9 @@ public static bool GameModeisSpaceCenter { get { - GameState state = SetModeFlag(); + state = SetModeFlag(); if (state == GameState.SPACECENTER) return true; - return false; + return false; } } @@ -100,15 +104,18 @@ public static GameState SetModeFlag() return GameState.SPACECENTER; } //if (FlightGlobals.fetch != null && FlightGlobals.ActiveVessel != null) // Check if in flight - if (HighLogic.LoadedSceneIsFlight) - { - if (FlightGlobals.fetch != null && FlightGlobals.ActiveVessel != null) - { - if (FlightGlobals.ActiveVessel.isEVA) // EVA kerbal - { - return GameState.EVA; - } - } + if (HighLogic.LoadedSceneIsFlight) + { + if (FlightGlobals.fetch != null) + { + if (FlightGlobals.ActiveVessel != null) + { + if (FlightGlobals.ActiveVessel.isEVA) // EVA kerbal + { + return GameState.EVA; + } + } + } return GameState.FLIGHT; } if (EditorLogic.fetch != null) // Check if in editor @@ -133,43 +140,57 @@ public static double DistanceFromHomeWorld(Vessel vessel) return DstFrmHome; } - public static bool CelestialBodyDistancetoSun(CelestialBody cb, out Vector3d sun_dir, out double sun_dist) - { - // bodies traced against - CelestialBody sun = FlightGlobals.Bodies[0]; - if (cb == sun) //If we have passed in the sun as the cb we default to a distance of 700000Km - { - sun_dir = Vector3d.forward; - sun_dist = sun.Radius + 700000000; - sun_dir /= sun_dist; - return true; - } - sun_dir = sun.position - cb.position; - sun_dist = sun_dir.magnitude; - sun_dir /= sun_dist; - sun_dist -= sun.Radius; - return true; - } - - // return sun luminosity - public static double SolarLuminosity + public static double DistanceFromHomeWorld(string bodyname) { - get - { - // note: it is 0 before loading first vessel in a game session, we compute it in that case - if (PhysicsGlobals.SolarLuminosity <= double.Epsilon) - { - double A = FlightGlobals.GetHomeBody().orbit.semiMajorAxis; - return A * A * 12.566370614359172 * PhysicsGlobals.SolarLuminosityAtHome; - } - return PhysicsGlobals.SolarLuminosity; - } + CelestialBody body = FlightGlobals.Bodies.FirstOrDefault(a => a.name == bodyname); + if (body == null) body = Planetarium.fetch.Home; + Vector3d bodyPos = body.getPositionAtUT(0); + CelestialBody HmePlanet = Planetarium.fetch.Home; + Log_Debug("Home = " + HmePlanet.name + " Pos = " + HmePlanet.getPositionAtUT(0)); + Log_Debug("Body Pos = " + bodyPos); + Vector3d hmeplntPos = HmePlanet.getPositionAtUT(0); + double DstFrmHome = Math.Sqrt(Math.Pow(bodyPos.x - hmeplntPos.x, 2) + Math.Pow(bodyPos.y - hmeplntPos.y, 2) + Math.Pow(bodyPos.z - hmeplntPos.z, 2)); + Log_Debug("Distance from Home Planet = " + DstFrmHome); + return DstFrmHome; } - #endregion GeometryandSpace + public static bool CelestialBodyDistancetoSun(CelestialBody cb, out Vector3d sun_dir, out double sun_dist) + { + // bodies traced against + CelestialBody sun = FlightGlobals.Bodies[0]; + if (cb == sun) //If we have passed in the sun as the cb we default to a distance of 700000Km + { + sun_dir = Vector3d.forward; + sun_dist = sun.Radius + 700000000; + sun_dir /= sun_dist; + return true; + } + sun_dir = sun.position - cb.position; + sun_dist = sun_dir.magnitude; + sun_dir /= sun_dist; + sun_dist -= sun.Radius; + return true; + } + + // return sun luminosity + public static double SolarLuminosity + { + get + { + // note: it is 0 before loading first vessel in a game session, we compute it in that case + if (PhysicsGlobals.SolarLuminosity <= double.Epsilon) + { + double A = FlightGlobals.GetHomeBody().orbit.semiMajorAxis; + return A * A * 12.566370614359172 * PhysicsGlobals.SolarLuminosityAtHome; + } + return PhysicsGlobals.SolarLuminosity; + } + } + + #endregion GeometryandSpace - #region ObjectsandTransforms - public static void PrintTransform(Transform t, string title = "") + #region ObjectsandTransforms + public static void PrintTransform(Transform t, string title = "") { Log_Debug("------" + title + "------"); Log_Debug("Position: " + t.localPosition); @@ -362,52 +383,54 @@ internal static void DumpCameras() Debug.Log("--------------------------------------"); } - - public static Camera findCameraByName(string camera) + + public static Camera findCameraByName(string camera) { return Camera.allCameras.FirstOrDefault(cam => cam.name == camera); } + + private static Camera StockOverlayCamera; /// <summary> /// Returns True if the Stock Overlay Camera Mode is on, otherwise will return false. /// </summary> public static bool StockOverlayCamIsOn - { - get - { - Camera StockOverlayCamera = findCameraByName("InternalSpaceOverlay Host"); - if (StockOverlayCamera != null) return true; - return false; - } - } + { + get + { + StockOverlayCamera = findCameraByName("InternalSpaceOverlay Host"); + if (StockOverlayCamera != null) return true; + return false; + } + } - private static Shader DepthMaskShader; - private static string DepthMaskShaderName = "DepthMask"; - /// <summary> - /// Will search for and change the Mesh (and all it's children) supplied in MeshName Field on the part supplied to Enabled or NotEnabled based on the SetVisible parm. - /// </summary> - /// <param name="part">The part to look for the mesh on</param> - /// <param name="SetVisible">True will Enable the mesh, False will disable the mesh</param> - /// <param name="MeshName">String containing the Mesh name to look for on the part</param> - internal static void SetInternalDepthMask(Part part, bool SetVisible, string MeshName = "") - { - if (DepthMaskShader == null) DepthMaskShader = Shader.Find(DepthMaskShaderName); - if (part.internalModel != null) - { - if (MeshName != "") - { - Transform parentTransform = FindInChildren(part.internalModel.transform, MeshName); - if (parentTransform != null) - { - parentTransform.gameObject.SetActive(SetVisible); - } - } - } - } + private static Shader DepthMaskShader; + private static string DepthMaskShaderName = "DepthMask"; + /// <summary> + /// Will search for and change the Mesh (and all it's children) supplied in MeshName Field on the part supplied to Enabled or NotEnabled based on the SetVisible parm. + /// </summary> + /// <param name="part">The part to look for the mesh on</param> + /// <param name="SetVisible">True will Enable the mesh, False will disable the mesh</param> + /// <param name="MeshName">String containing the Mesh name to look for on the part</param> + internal static void SetInternalDepthMask(Part part, bool SetVisible, string MeshName = "") + { + if (DepthMaskShader == null) DepthMaskShader = Shader.Find(DepthMaskShaderName); + if (part.internalModel != null) + { + if (MeshName != "") + { + Transform parentTransform = FindInChildren(part.internalModel.transform, MeshName); + if (parentTransform != null) + { + parentTransform.gameObject.SetActive(SetVisible); + } + } + } + } - #endregion Cameras + #endregion Cameras - #region Animations - public static IEnumerator WaitForAnimation(Animation animation, string name) + #region Animations + public static IEnumerator WaitForAnimation(Animation animation, string name) { do { @@ -547,22 +570,23 @@ internal static void setHelmets(this Part thisPart, bool helmetOn) // Sets the kerbal layers to make them visible (Thawed) or not (Frozen), setVisible = true sets layers to visible, false turns them off. internal static void setFrznKerbalLayer(Part part, ProtoCrewMember kerbal, bool setVisible) { - if (!setVisible) - { - kerbal.KerbalRef.SetVisibleInPortrait(setVisible); - kerbal.KerbalRef.InPart = null; - } - - kerbal.KerbalRef.gameObject.SetActive(setVisible); - if (setVisible) - { - kerbal.KerbalRef.SetVisibleInPortrait(setVisible); - kerbal.KerbalRef.InPart = part; - } - - } + if (!setVisible) + { + kerbal.KerbalRef.SetVisibleInPortrait(setVisible); + kerbal.KerbalRef.InPart = null; + } + + kerbal.KerbalRef.gameObject.SetActive(setVisible); + if (setVisible) + { + kerbal.KerbalRef.SetVisibleInPortrait(setVisible); + kerbal.KerbalRef.InPart = part; + } + + } - internal static RuntimeAnimatorController kerbalIVAController; + private static RuntimeAnimatorController kerbalIVAController, myController; + private static AnimatorOverrideController myOverrideController; internal static void subdueIVAKerbalAnimations(Kerbal kerbal) { @@ -573,8 +597,8 @@ internal static void subdueIVAKerbalAnimations(Kerbal kerbal) if (anim.name == kerbal.name) { kerbalIVAController = anim.runtimeAnimatorController; - RuntimeAnimatorController myController = anim.runtimeAnimatorController; - AnimatorOverrideController myOverrideController = new AnimatorOverrideController(); + myController = anim.runtimeAnimatorController; + myOverrideController = new AnimatorOverrideController(); myOverrideController.runtimeAnimatorController = myController; myOverrideController["idle_animA_upWord"] = myOverrideController["idle_animH_notDoingAnything"]; myOverrideController["idle_animB"] = myOverrideController["idle_animH_notDoingAnything"]; @@ -607,8 +631,8 @@ internal static void reinvigerateIVAKerbalAnimations(Kerbal kerbal) { if (anim.name == kerbal.name) { - RuntimeAnimatorController myController = kerbalIVAController; - AnimatorOverrideController myOverrideController = new AnimatorOverrideController(); + myController = kerbalIVAController; + myOverrideController = new AnimatorOverrideController(); myOverrideController.runtimeAnimatorController = myController; // Put this line at the end because when you assign a controller on an Animator, unity rebinds all the animated properties anim.runtimeAnimatorController = myOverrideController; @@ -617,99 +641,99 @@ internal static void reinvigerateIVAKerbalAnimations(Kerbal kerbal) } } - #endregion Kerbals + #endregion Kerbals - #region Vessels - // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - /// <summary> - /// Returns True if thatVessel is the activevessel and the camera is in IVA mode, otherwise returns false. - /// </summary> - /// <param name="thatVessel"></param> - /// <returns></returns> - internal static bool VesselIsInIVA(Vessel thatVessel) + #region Vessels + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + /// <summary> + /// Returns True if thatVessel is the activevessel and the camera is in IVA mode, otherwise returns false. + /// </summary> + /// <param name="thatVessel"></param> + /// <returns></returns> + internal static bool VesselIsInIVA(Vessel thatVessel) { // Inactive IVAs are renderer.enabled = false, this can and should be used... // ... but now it can't because we're doing transparent pods, so we need a more complicated way to find which pod the player is in. return HighLogic.LoadedSceneIsFlight && IsActiveVessel(thatVessel) && IsInIVA; } - // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - /// <summary> - /// Returns True if thatVessel is the ActiveVessel, otherwise returns false. - /// </summary> - /// <param name="thatVessel"></param> - /// <returns></returns> - internal static bool IsActiveVessel(Vessel thatVessel) + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + /// <summary> + /// Returns True if thatVessel is the ActiveVessel, otherwise returns false. + /// </summary> + /// <param name="thatVessel"></param> + /// <returns></returns> + internal static bool IsActiveVessel(Vessel thatVessel) { return HighLogic.LoadedSceneIsFlight && thatVessel != null && thatVessel.isActiveVessel; } - - // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - public static bool UserIsInPod(Part thisPart) - { + + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + public static bool UserIsInPod(Part thisPart) + { - // Just in case, check for whether we're not in flight. - if (!HighLogic.LoadedSceneIsFlight) - return false; + // Just in case, check for whether we're not in flight. + if (!HighLogic.LoadedSceneIsFlight) + return false; - // If we're not in IVA, or the part does not have an instantiated IVA, the user can't be in it. - if (!VesselIsInIVA(thisPart.vessel) || thisPart.internalModel == null) - return false; + // If we're not in IVA, or the part does not have an instantiated IVA, the user can't be in it. + if (!VesselIsInIVA(thisPart.vessel) || thisPart.internalModel == null) + return false; - // Now that we got that out of the way, we know that the user is in SOME pod on our ship. We just don't know which. - // Let's see if he's controlling a kerbal in our pod. - if (ActiveKerbalIsLocal(thisPart)) - return true; + // Now that we got that out of the way, we know that the user is in SOME pod on our ship. We just don't know which. + // Let's see if he's controlling a kerbal in our pod. + if (ActiveKerbalIsLocal(thisPart)) + return true; - // There still remains an option of InternalCamera which we will now sort out. - if (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal) - { - // So we're watching through an InternalCamera. Which doesn't record which pod we're in anywhere, like with kerbals. - // But we know that if the camera's transform parent is somewhere in our pod, it's us. - // InternalCamera.Instance.transform.parent is the transform the camera is attached to that is on either a prop or the internal itself. - // The problem is figuring out if it's in our pod, or in an identical other pod. - // Unfortunately I don't have anything smarter right now than get a list of all transforms in the internal and cycle through it. - // This is a more annoying computation than looking through every kerbal in a pod (there's only a few of those, - // but potentially hundreds of transforms) and might not even be working as I expect. It needs testing. - return thisPart.internalModel.GetComponentsInChildren<Transform>().Any(thisTransform => thisTransform == InternalCamera.Instance.transform.parent); - } + // There still remains an option of InternalCamera which we will now sort out. + if (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal) + { + // So we're watching through an InternalCamera. Which doesn't record which pod we're in anywhere, like with kerbals. + // But we know that if the camera's transform parent is somewhere in our pod, it's us. + // InternalCamera.Instance.transform.parent is the transform the camera is attached to that is on either a prop or the internal itself. + // The problem is figuring out if it's in our pod, or in an identical other pod. + // Unfortunately I don't have anything smarter right now than get a list of all transforms in the internal and cycle through it. + // This is a more annoying computation than looking through every kerbal in a pod (there's only a few of those, + // but potentially hundreds of transforms) and might not even be working as I expect. It needs testing. + return thisPart.internalModel.GetComponentsInChildren<Transform>().Any(thisTransform => thisTransform == InternalCamera.Instance.transform.parent); + } - return false; - } + return false; + } - // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - public static bool ActiveKerbalIsLocal(this Part thisPart) - { - return FindCurrentKerbal(thisPart) != null; - } + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + public static bool ActiveKerbalIsLocal(this Part thisPart) + { + return FindCurrentKerbal(thisPart) != null; + } - // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - public static Kerbal FindCurrentKerbal(this Part thisPart) - { - if (thisPart.internalModel == null || !VesselIsInIVA(thisPart.vessel)) - return null; - // InternalCamera instance does not contain a reference to the kerbal it's looking from. - // So we have to search through all of them... - return (from thatSeat in thisPart.internalModel.seats - where thatSeat.kerbalRef != null - where thatSeat.kerbalRef.eyeTransform == InternalCamera.Instance.transform.parent - select thatSeat.kerbalRef).FirstOrDefault(); - } + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + public static Kerbal FindCurrentKerbal(this Part thisPart) + { + if (thisPart.internalModel == null || !VesselIsInIVA(thisPart.vessel)) + return null; + // InternalCamera instance does not contain a reference to the kerbal it's looking from. + // So we have to search through all of them... + return (from thatSeat in thisPart.internalModel.seats + where thatSeat.kerbalRef != null + where thatSeat.kerbalRef.eyeTransform == InternalCamera.Instance.transform.parent + select thatSeat.kerbalRef).FirstOrDefault(); + } - // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - /// <summary> - /// True if Camera is in IVA mode, otherwise false. - /// </summary> - internal static bool IsInIVA + // The following method is taken from RasterPropMonitor as-is. Which is covered by GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 + /// <summary> + /// True if Camera is in IVA mode, otherwise false. + /// </summary> + internal static bool IsInIVA { - get { return CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA; } + get { return CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA; } } - /// <summary> - /// True if Camera is in Internal mode, otherwise false. - /// </summary> + /// <summary> + /// True if Camera is in Internal mode, otherwise false. + /// </summary> internal static bool IsInInternal { - get { return CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal; } + get { return CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal; } } internal static bool ValidVslType(Vessel v) @@ -743,41 +767,67 @@ internal static int getVesselIdx(Vessel vtarget) return -1; } - /// <summary> - /// Will Spawn the Internal Model for a part, we do this for DeepFreeze Mod because it doesn't work if the crew capacity is zero, which may be - /// the case sometimes for DeepFreeze parts. - /// </summary> - /// <param name="part">The Part to spawn the internal model for</param> - /// <returns>True if successful or False if not</returns> - internal static bool spawnInternal(Part part) - { - try - { - if (part.internalModel != null) return true; - part.CreateInternalModel(); - if (part.internalModel != null) - { - part.internalModel.Initialize(part); - part.internalModel.SpawnCrew(); - } - else - { - return false; - } - - return true; - } - catch (Exception) - { - return false; - } - } + /// <summary> + /// Will Spawn the Internal Model for a part, we do this for DeepFreeze Mod because it doesn't work if the crew capacity is zero, which may be + /// the case sometimes for DeepFreeze parts. + /// </summary> + /// <param name="part">The Part to spawn the internal model for</param> + /// <returns>True if successful or False if not</returns> + internal static bool spawnInternal(Part part) + { + try + { + if (part.internalModel != null) return true; + part.CreateInternalModel(); + if (part.internalModel != null) + { + part.internalModel.Initialize(part); + part.internalModel.SpawnCrew(); + } + else + { + return false; + } + + return true; + } + catch (Exception) + { + return false; + } + } - #endregion Vessels - #region Temperature - //Temperature - internal static float KelvintoCelsius(float kelvin) + public static void PartHighlight(Part part, bool on) + { + if (on) + { + if (part.highlighter == null) + { + var color = XKCDColors.Yellow; + var model = part.FindModelTransform("model"); + part.highlighter = model.gameObject.AddComponent<Highlighter>(); + part.highlighter.ConstantOn(color); + part.SetHighlightColor(color); + part.SetHighlight(true, false); + } + } + else + { + if (part.highlighter != null) + { + part.SetHighlightDefault(); + part.highlighter.gameObject.DestroyGameObjectImmediate(); + part.highlighter = null; + } + } + } + + #endregion Vessels + + #region Temperature + //Temperature + internal static float KelvintoCelsius(float kelvin) { return kelvin - 273.15f; } @@ -791,31 +841,35 @@ internal static float CelsiustoKelvin(float celsius) #region Resources + private static List<PartResource> resources; //Resources public static double GetAvailableResource(Part part, String resourceName) { - var resources = new List<PartResource>(); + resources = new List<PartResource>(); part.GetConnectedResources(PartResourceLibrary.Instance.GetDefinition(resourceName).id, ResourceFlowMode.ALL_VESSEL, resources); return resources.Sum(pr => pr.amount); } public const int MAX_TRANSFER_ATTEMPTS = 4; + private static double totalReceived; + private static double requestAmount; + private static double received; public static double RequestResource(Part cvp, String name, double amount) { if (amount <= 0.0) return 0.0; - double totalReceived = 0.0; - double requestAmount = amount; + totalReceived = 0.0; + requestAmount = amount; for (int attempts = 0; (attempts < MAX_TRANSFER_ATTEMPTS) && (amount > 0.000000000001); attempts++) { - double received = cvp.RequestResource(name, requestAmount, ResourceFlowMode.ALL_VESSEL); - Log_Debug("requestResource attempt " + attempts); - Log_Debug("requested power = " + requestAmount.ToString("0.0000000000000000000000")); - Log_Debug("received power = " + received.ToString("0.0000000000000000000000")); + received = cvp.RequestResource(name, requestAmount, ResourceFlowMode.ALL_VESSEL); + //Log_Debug("requestResource attempt " + attempts); + //Log_Debug("requested power = " + requestAmount.ToString("0.0000000000000000000000")); + //Log_Debug("received power = " + received.ToString("0.0000000000000000000000")); totalReceived += received; amount -= received; - Log_Debug("amount = " + amount.ToString("0.0000000000000000000000")); + //Log_Debug("amount = " + amount.ToString("0.0000000000000000000000")); if (received <= 0.0) requestAmount = amount * 0.5; else @@ -839,35 +893,7 @@ internal static void setScaledScreen() scaledScreenWidth = Mathf.RoundToInt(Screen.width / 1); scaledScreenset = true; } - - internal static bool WindowVisibile(Rect winpos) - { - if (!scaledScreenset) setScaledScreen(); - float minmargin = 20.0f; // 20 bytes margin for the window - float xMin = minmargin - winpos.width; - float xMax = scaledScreenWidth - minmargin; - float yMin = minmargin - winpos.height; - float yMax = scaledScreenHeight - minmargin; - bool xRnge = (winpos.x > xMin) && (winpos.x < xMax); - bool yRnge = (winpos.y > yMin) && (winpos.y < yMax); - return xRnge && yRnge; - } - - internal static Rect MakeWindowVisible(Rect winpos) - { - if (!scaledScreenset) setScaledScreen(); - float minmargin = 20.0f; // 20 bytes margin for the window - float xMin = minmargin - winpos.width; - float xMax = scaledScreenWidth - minmargin; - float yMin = minmargin - winpos.height; - float yMax = scaledScreenHeight - minmargin; - - winpos.x = Mathf.Clamp(winpos.x, xMin, xMax); - winpos.y = Mathf.Clamp(winpos.y, yMin, yMax); - - return winpos; - } - + internal static RectOffset SetRectOffset(RectOffset tmpRectOffset, int intValue) { return SetRectOffset(tmpRectOffset, intValue, intValue, intValue, intValue); @@ -891,7 +917,7 @@ internal static RectOffset SetRectOffset(RectOffset tmpRectOffset, int Left, int internal static Rect rectToolTipPosition; internal static Int32 intTooltipVertOffset = 12; internal static Int32 intTooltipMaxWidth = 250; - //timer so it only displays for a preriod of time + //timer so it only displays for a period of time internal static float fltTooltipTime; internal static float fltMaxToolTipTime = 15f; internal static GUIStyle _TooltipStyle; @@ -1051,7 +1077,7 @@ internal static void DeleteScreenMessages(string messagetext, string messagearea break; } //Loop through all the mesages we found. - List<ScreenMessage> activemessagelist = ScreenMessages.Instance.ActiveMessages; + List<ScreenMessage> activemessagelist = ScreenMessages.Instance.ActiveMessages; foreach (var msgtext in messagetexts) { //If the user specified text to search for only delete messages that contain that text. @@ -1110,20 +1136,23 @@ internal static T GetNodeValue<T>(ConfigNode confignode, string fieldname, T def #region Time //Formatting time functions - //Format a Time double variable into format "xxxx:year xxxx:days xxxx:hours xxxx:mins x:xx:secs" - //Future expansion required to format to different formats. - public static String formatTime(double seconds) + private static int y, d, h, m; + private static List<string> parts = new List<string>(); + //Format a Time double variable into format "xxxx:year xxxx:days xxxx:hours xxxx:mins x:xx:secs" + //Future expansion required to format to different formats. + public static String formatTime(double seconds) { - int y = (int)(seconds / (6.0 * 60.0 * 60.0 * 426.08)); + y = (int)(seconds / (6.0 * 60.0 * 60.0 * 426.08)); seconds = seconds % (6.0 * 60.0 * 60.0 * 426.08); - int d = (int)(seconds / (6.0 * 60.0 * 60.0)); + d = (int)(seconds / (6.0 * 60.0 * 60.0)); seconds = seconds % (6.0 * 60.0 * 60.0); - int h = (int)(seconds / (60.0 * 60.0)); + h = (int)(seconds / (60.0 * 60.0)); seconds = seconds % (60.0 * 60.0); - int m = (int)(seconds / 60.0); + m = (int)(seconds / 60.0); seconds = seconds % 60.0; - List<string> parts = new List<string>(); + //List<string> parts = new List<string>(); + parts.Clear(); if (y > 0) { @@ -1155,14 +1184,16 @@ public static String formatTime(double seconds) return String.Join(" ", parts.ToArray()); } return "0s"; - } + } + private static string outputstring; + private static int[] datestructure = new int[5]; //Format a Time double variable into format "YxxxxDxxxhh:mm:ss" //Future expansion required to format to different formats. internal static string FormatDateString(double time) { - string outputstring = String.Empty; - int[] datestructure = new int[5]; + outputstring = String.Empty; + //int[] datestructure = new int[5]; if (GameSettings.KERBIN_TIME) { datestructure[0] = (int)time / 60 / 60 / 6 / 426; // Years @@ -1221,12 +1252,13 @@ public enum ISRUStatus OutputFull } + private static ISRUStatus returnStatus; /// <summary> /// Returns a Status Indicating the Status of a ISRU ModuleResourceConverter, given that it's actual status can be active, but not actually doing anything. /// </summary> internal static ISRUStatus GetModResConverterStatus(ModuleResourceConverter tmpRegRc) { - ISRUStatus returnStatus = ISRUStatus.Inactive; + returnStatus = ISRUStatus.Inactive; if (!tmpRegRc.IsActivated) return ISRUStatus.Inactive; //If it's not Activated, it must be inactive. // Otherwise it's Activated, but is it really working and using EC? Get it's real status. if (tmpRegRc.status.ToLower().Contains("inactive")) returnStatus = ISRUStatus.Inactive; //Status is inactive, it's inactive.. Not sure how but sometimes this remains on load even when it's inactive? Hence the test above. @@ -1274,6 +1306,14 @@ internal static bool IsResearchBodiesInstalled } } + internal static bool IsTSTInstalled + { + get + { + return IsModInstalled("TarsierSpaceTech"); + } + } + internal static bool IsOPMInstalled { get @@ -1283,11 +1323,24 @@ internal static bool IsOPMInstalled { return true; } - return false; + return false; } } - internal static bool IsModInstalled(string assemblyName) + internal static bool IsNHInstalled + { + get + { + CelestialBody sonnah = FlightGlobals.Bodies.FirstOrDefault(a => a.name == "Sonnah"); + if (sonnah != null) + { + return true; + } + return false; + } + } + + internal static bool IsModInstalled(string assemblyName) { Assembly assembly = (from a in assemblies where a.FullName.Contains(assemblyName) diff --git a/Source/REPOSoftTechKSPUtils/RectExtentions.cs b/Source/REPOSoftTechKSPUtils/RectExtentions.cs new file mode 100644 index 0000000..d4fa8ea --- /dev/null +++ b/Source/REPOSoftTechKSPUtils/RectExtentions.cs @@ -0,0 +1,58 @@ +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +using UnityEngine; + +namespace RSTUtils.Extensions +{ + public static class RectExtensions + { + /// <summary> + /// Clamps the rectangle inside the screen region. + /// </summary> + public static Rect ClampInsideScreen(this Rect value) + { + value.x = Mathf.Clamp(value.x, 0, Screen.width - value.width); + value.y = Mathf.Clamp(value.y, 0, Screen.height - value.height); + + return value; + } + + /// <summary> + /// Clamps the rectangle into the screen region by the specified margin. + /// </summary> + public static Rect ClampToScreen(this Rect value, float margin = 25.0f) + { + value.x = Mathf.Clamp(value.x, -(value.width - margin), Screen.width - margin); + value.y = Mathf.Clamp(value.y, -(value.height - margin), Screen.height - margin); + + return value; + } + + /// <summary> + /// Returns whether the mouse is within the coordinates of this rectangle. + /// </summary> + public static bool MouseIsOver(this Rect value) + { + return value.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y)); + } + + public static Rect Translate(this Rect value, Rect rectangle) + { + value.x += rectangle.x; + value.y += rectangle.y; + + return value; + } + } +} \ No newline at end of file diff --git a/Source/APIs/ToolBarManager.cs b/Source/REPOSoftTechKSPUtils/ToolBarManager.cs similarity index 99% rename from Source/APIs/ToolBarManager.cs rename to Source/REPOSoftTechKSPUtils/ToolBarManager.cs index c77fddf..5ef2846 100644 --- a/Source/APIs/ToolBarManager.cs +++ b/Source/REPOSoftTechKSPUtils/ToolBarManager.cs @@ -26,7 +26,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE using System.Reflection; using UnityEngine; -namespace DF +namespace RSTUtils { /**********************************************************\ * --- DO NOT EDIT BELOW THIS COMMENT --- * @@ -699,7 +699,7 @@ public IDrawable Drawable object functionDrawable = null; if (value != null) { - functionDrawable = Activator.CreateInstance(types.functionDrawableType, new Action(() => value.Update()), new Func<Vector2, Vector2>(pos => value.Draw(pos))); + functionDrawable = Activator.CreateInstance(types.functionDrawableType, new Action(value.Update), new Func<Vector2, Vector2>(value.Draw)); } types.button.drawableProperty.SetValue(realButton, functionDrawable, null); drawable_ = value; diff --git a/Source/RPMScreenDeepFreeze.cs b/Source/RPMScreenDeepFreeze.cs new file mode 100644 index 0000000..acd2293 --- /dev/null +++ b/Source/RPMScreenDeepFreeze.cs @@ -0,0 +1,105 @@ +using System; + +// This is the recommended method to drive a PropMonitor from a foreign plugin, +// because I'm using it myself and now I have to make sure it works. :) +// This module is both a nice gimmick and an example. +// +// This method has the advantage of letting you make use of the variable processing and you don't +// need to copy a page of boilerplate either -- instead, you just need an InternalModule +// with a method that returns a string. That's it. +// +// RasterPropMonitor module can, beyond the usual types of page read from a text file, +// and defined directly in the config file, request a page text from an InternalModule +// living in the same prop as it does. To do this, configure the page like this: +// +// PAGE +// { +// PAGEHANDLER +// { +// name = Name of your module +// method = Method name to be called in your module. +// } +// +// Method name must exist in your module and must be a function that takes two int parameters +// and returns a string. Any other parameters you include in the PAGEHANDLER block +// will be passed to your InternalModule as KSPFields. +// +// RasterPropMonitor will load your module, attach it to the prop it lives in and +// poll this function every time it decides the page needs to be refreshed. You need +// to return a string, that will then be processed just like a page definition text file. +// You will obviously want your own namespace. +namespace DF +{ + // It needs to be an InternalModule. + public class RPMScreenDeepFreeze : InternalModule + { + // These KSPFields will actually be loaded from the PAGEHANDLER block + [KSPField] + public string pageTitle; + + // We can keep our response buffered and only return it upon request. + private string response; + + // We only update the response when the number of lines in the flight log changes. + private int lastCount = -1; + + // This method will be found by RasterPropMonitorGenerator and called to provide a page. + // You must return a string. Environment.Newline is the carriage return, nothing fancy. + public string ShowLog(int screenWidth, int screenHeight) + { + if (FlightLogger.eventLog.Count != lastCount) + { + LogToBuffer(screenWidth, screenHeight); + } + return response; + } + + // I honestly have no clue why InternalModules need to be initialised + // like this, and not with a proper constructor or an OnAwake, but that one always works. + // Even a very simple OnAwake can sometimes get the entire IVA to choke. + public void Start() + { + if (!string.IsNullOrEmpty(pageTitle)) + // Notice that UnMangleConfigText is an extension method defined in JUtil class. + // To your module, it won't be available without hardlinking to RPM, which is what you want to avoid. + // It's nothing you couldn't replace with .Replace("<=", "{").Replace("=>", "}").Replace("$$$", Environment.NewLine); though + pageTitle = pageTitle.Replace("<=", "{").Replace("=>", "}").Replace("$$$", Environment.NewLine); + } + + // You can have an OnUpdate in this module, this particular one doesn't need it. + private void LogToBuffer(int screenWidth, int screenHeight) + { + // I think I coded this one backwards somehow, but eh, it's a gimmick. + int activeScreenHeight = screenHeight; + if (!string.IsNullOrEmpty(pageTitle)) + { + activeScreenHeight--; + } + lastCount = FlightLogger.eventLog.Count; + if (lastCount > 0) + { + string fullLog = Utilities.WordWrap(string.Join(Environment.NewLine, FlightLogger.eventLog.ToArray()), screenWidth); + var tempBuffer = fullLog.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + var screenBuffer = new string[activeScreenHeight]; + if (tempBuffer.Length <= activeScreenHeight) + { + screenBuffer = tempBuffer; + } + else + { + for (int i = 0; i < screenBuffer.Length; i++) + { + screenBuffer[i] = tempBuffer[tempBuffer.Length - activeScreenHeight + i]; + } + } + response = string.Join(Environment.NewLine, screenBuffer); + } + else + response = "No records in log."; + if (!string.IsNullOrEmpty(pageTitle)) + { + response = pageTitle + Environment.NewLine + response; + } + } + } +} \ No newline at end of file diff --git a/Source/RTWrapper.cs b/Source/RTWrapper.cs deleted file mode 100644 index d56e5c3..0000000 --- a/Source/RTWrapper.cs +++ /dev/null @@ -1,246 +0,0 @@ -/** - * DeepFreeze Continued... - * (C) Copyright 2015, Jamie Leighton - * - * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This - * project is in no way associated with nor endorsed by Squad. - * - * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. - * This File was not part of the original Deepfreeze but was written by Jamie Leighton based of code and concepts from the Kerbal Alarm Clock Mod. Which was licensed under the MIT license. - * (C) Copyright 2015, Jamie Leighton - * - * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) - * creative commons license. See <https://creativecommons.org/licenses/by-nc-sa/4.0/> - * for full details. - * - */ - -using System; -using System.Linq; -using System.Reflection; - -namespace DF -{ - /// <summary> - /// The Wrapper class to access Remote Tech - /// </summary> - public class RTWrapper - { - protected static System.Type RTAPIType; - protected static Object actualRTAPI = null; - - /// <summary> - /// This is the Remote Tech API object - /// - /// SET AFTER INIT - /// </summary> - public static RTAPI RTactualAPI = null; - - /// <summary> - /// Whether we found the Remote Tech API assembly in the loadedassemblies. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean AssemblyExists { get { return (RTAPIType != null); } } - - /// <summary> - /// Whether we managed to hook the running Instance from the assembly. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean InstanceExists { get { return (actualRTAPI != null); } } - - /// <summary> - /// Whether we managed to wrap all the methods/functions from the instance. - /// - /// SET AFTER INIT - /// </summary> - private static Boolean _RTWrapped = false; - - /// <summary> - /// Whether the object has been wrapped - /// </summary> - public static Boolean APIReady { get { return _RTWrapped; } } - - /// <summary> - /// This method will set up the Remote Tech object and wrap all the methods/functions - /// </summary> - /// <param name="Force">This option will force the Init function to rebind everything</param> - /// <returns></returns> - public static Boolean InitTRWrapper() - { - //reset the internal objects - _RTWrapped = false; - actualRTAPI = null; - LogFormatted("Attempting to Grab Remote Tech Types..."); - - //find the base type - RTAPIType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "RemoteTech.API.API"); - - if (RTAPIType == null) - { - return false; - } - - LogFormatted("Remote Tech Version:{0}", RTAPIType.Assembly.GetName().Version.ToString()); - - //now grab the running instance - LogFormatted("Got Assembly Types, grabbing Instances"); - try - { - actualRTAPI = RTAPIType.GetMember("HasLocalControl", BindingFlags.Public | BindingFlags.Static); - } - catch (Exception) - { - LogFormatted("No Remote Tech isInitialised found"); - //throw; - } - - if (actualRTAPI == null) - { - LogFormatted("Failed grabbing Instance"); - return false; - } - - //If we get this far we can set up the local object and its methods/functions - LogFormatted("Got Instance, Creating Wrapper Objects"); - RTactualAPI = new RTAPI(actualRTAPI); - - _RTWrapped = true; - return true; - } - - /// <summary> - /// The Type that is an analogue of the real Remote Tech. This lets you access all the API-able properties and Methods of Remote Tech - /// </summary> - public class RTAPI - { - internal RTAPI(Object actualRT) - { - //store the actual object - APIactualRT = actualRT; - - //these sections get and store the reflection info and actual objects where required. Later in the properties we then read the values from the actual objects - //for events we also add a handler - - //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPLE HERE - //Methods - LogFormatted("Getting HasLocalControl Method"); - HasLocalControlMethod = RTAPIType.GetMethod("HasLocalControl", BindingFlags.Public | BindingFlags.Static); - LogFormatted_DebugOnly("Success: " + (HasLocalControlMethod != null).ToString()); - - LogFormatted("Getting HasAnyConnection Method"); - HasAnyConnectionMethod = RTAPIType.GetMethod("HasAnyConnection", BindingFlags.Public | BindingFlags.Static); - LogFormatted_DebugOnly("Success: " + (HasAnyConnectionMethod != null).ToString()); - - LogFormatted("Getting GetShortestSignalDelay Method"); - GetShortestSignalDelayMethod = RTAPIType.GetMethod("GetShortestSignalDelay", BindingFlags.Public | BindingFlags.Static); - LogFormatted_DebugOnly("Success: " + (GetShortestSignalDelayMethod != null).ToString()); - } - - private Object APIactualRT; - - #region Methods - - private MethodInfo HasLocalControlMethod; - - /// <summary> - /// Whether the current vessel HasLocalControl - /// </summary> - /// <param name="id">The vessel id reference</param> - /// <returns>Success of call</returns> - internal bool HasLocalControl(Guid id) - { - try - { - return (bool)HasLocalControlMethod.Invoke(APIactualRT, new System.Object[] { id }); - } - catch (Exception ex) - { - LogFormatted("Unable to invoke Remote Tech HasLocalControl Method"); - LogFormatted("Exception: {0}", ex); - return false; - //throw; - } - } - - private MethodInfo HasAnyConnectionMethod; - - /// <summary> - /// Whether the current vessel HasAnyConnection - /// </summary> - /// <param name="id">The vessel id reference</param> - /// <returns>Success of call</returns> - internal bool HasAnyConnection(Guid id) - { - try - { - return (bool)HasAnyConnectionMethod.Invoke(APIactualRT, new System.Object[] { id }); - } - catch (Exception ex) - { - LogFormatted("Unable to invoke Remote Tech HasAnyConnection Method"); - LogFormatted("Exception: {0}", ex); - return false; - //throw; - } - } - - private MethodInfo GetShortestSignalDelayMethod; - - /// <summary> - /// Gets the signal delay - /// </summary> - /// <param name="id">The vessel id reference</param> - /// <returns>A double indicating the signaldelay time</returns> - internal double GetShortestSignalDelay(Guid id) - { - try - { - return (double)GetShortestSignalDelayMethod.Invoke(APIactualRT, new System.Object[] { id }); - } - catch (Exception ex) - { - LogFormatted("Unable to invoke Remote Tech GetShortestSignalDelay Method"); - LogFormatted("Exception: {0}", ex); - return 0; - //throw; - } - } - - #endregion Methods - } - - #region Logging Stuff - - /// <summary> - /// Some Structured logging to the debug file - ONLY RUNS WHEN DLL COMPILED IN DEBUG MODE - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - [System.Diagnostics.Conditional("DEBUG")] - internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) - { - LogFormatted(Message, strParams); - } - - /// <summary> - /// Some Structured logging to the debug file - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - internal static void LogFormatted(String Message, params Object[] strParams) - { - Message = String.Format(Message, strParams); - String strMessageLine = String.Format("{0},{2}-{3},{1}", - DateTime.Now, Message, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, - System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); - UnityEngine.Debug.Log(strMessageLine); - } - - #endregion Logging Stuff - } -} \ No newline at end of file diff --git a/Source/SMInterface.dll b/Source/SMInterface.dll deleted file mode 100644 index b5b97bb..0000000 Binary files a/Source/SMInterface.dll and /dev/null differ diff --git a/Source/TRWrapper.cs b/Source/TRWrapper.cs deleted file mode 100644 index d108a93..0000000 --- a/Source/TRWrapper.cs +++ /dev/null @@ -1,219 +0,0 @@ -/** - * DeepFreeze Continued... - * (C) Copyright 2015, Jamie Leighton - * - * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This - * project is in no way associated with nor endorsed by Squad. - * - * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. - * This File was not part of the original Deepfreeze but was written by Jamie Leighton based of code and concepts from the Kerbal Alarm Clock Mod. Which was licensed under the MIT license. - * (C) Copyright 2015, Jamie Leighton - * - * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) - * creative commons license. See <https://creativecommons.org/licenses/by-nc-sa/4.0/> - * for full details. - * - */ - -using System; -using System.Linq; -using System.Reflection; - -namespace DF -{ - /// <summary> - /// The Wrapper class to access Texture Replacer - /// </summary> - public class TRWrapper - { - protected static System.Type TRType; - protected static System.Type TRPersonaliserType; - - protected static Object actualTR = null; - protected static Object actualTRPersonaliser = null; - - /// <summary> - /// This is the Texture Replacer Personaliser object - /// - /// SET AFTER INIT - /// </summary> - public static TRPersonaliserAPI TexRepPersonaliser = null; - - /// <summary> - /// Whether we found the Texture Replacer assembly in the loadedassemblies. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean AssemblyExists { get { return (TRType != null); } } - - /// <summary> - /// Whether we managed to hook the running Instance from the assembly. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean InstanceExists { get { return (TexRepPersonaliser != null); } } - - /// <summary> - /// Whether we managed to wrap all the methods/functions from the instance. - /// - /// SET AFTER INIT - /// </summary> - private static Boolean _TRWrapped = false; - - /// <summary> - /// Whether the object has been wrapped - /// </summary> - public static Boolean APIReady { get { return _TRWrapped; } } - - /// <summary> - /// This method will set up the Texture Replacer object and wrap all the methods/functions - /// </summary> - /// <param name="Force">This option will force the Init function to rebind everything</param> - /// <returns></returns> - public static Boolean InitTRWrapper() - { - //reset the internal objects - _TRWrapped = false; - actualTR = null; - TexRepPersonaliser = null; - LogFormatted("Attempting to Grab TextureReplacer Types..."); - - //find the base type - TRType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "TextureReplacer.TextureReplacer"); - - if (TRType == null) - { - return false; - } - - LogFormatted("TextureReplacer Version:{0}", TRType.Assembly.GetName().Version.ToString()); - - //find the personaliser class type - TRPersonaliserType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "TextureReplacer.Personaliser"); - - if (TRPersonaliserType == null) - { - return false; - } - - //now grab the running instance - LogFormatted("Got Assembly Types, grabbing Instances"); - try - { - actualTR = TRType.GetField("isInitialised", BindingFlags.Public | BindingFlags.Static).GetValue(null); - } - catch (Exception) - { - LogFormatted("No Texture Replacer isInitialised found"); - //throw; - } - try - { - actualTRPersonaliser = TRPersonaliserType.GetField("instance", BindingFlags.Public | BindingFlags.Static).GetValue(null); - } - catch (Exception) - { - LogFormatted("No Texture Replacer Personaliser Instance found"); - //throw; - } - if (actualTR == null || actualTRPersonaliser == null) - { - LogFormatted("Failed grabbing Instance"); - return false; - } - - //If we get this far we can set up the local object and its methods/functions - LogFormatted("Got Instance, Creating Wrapper Objects"); - TexRepPersonaliser = new TRPersonaliserAPI(actualTRPersonaliser); - - _TRWrapped = true; - return true; - } - - /// <summary> - /// The Type that is an analogue of the real Texture replacer. This lets you access all the API-able properties and Methods of Texture Replacer - /// </summary> - public class TRPersonaliserAPI - { - internal TRPersonaliserAPI(Object TexRepPersonaliser) - { - //store the actual object - APIactualTRPersonaliser = TexRepPersonaliser; - - //these sections get and store the reflection info and actual objects where required. Later in the properties we then read the values from the actual objects - //for events we also add a handler - //LogFormatted("Getting APIReady Object"); - //APIReadyField = TRType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); - //LogFormatted("Success: " + (APIReadyField != null).ToString()); - - //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPLE HERE - //Methods - LogFormatted("Getting personalise Method"); - personaliseIvaMethod = TRPersonaliserType.GetMethod("personaliseIva", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (personaliseIvaMethod != null).ToString()); - } - - private Object APIactualTRPersonaliser; - - #region Methods - - private MethodInfo personaliseIvaMethod; - - /// <summary> - /// Personalise IVA textures of a kerbal - /// </summary> - /// <param name="kerbal">The Kerbal reference</param> - /// <returns>Success of call</returns> - internal void personaliseIva(Kerbal kerbal) - { - try - { - personaliseIvaMethod.Invoke(APIactualTRPersonaliser, new System.Object[] { kerbal }); - } - catch (Exception ex) - { - LogFormatted("Unable to invoke Texture Replacer personaliseIva Method"); - LogFormatted("Exception: {0}", ex); - //throw; - } - } - - #endregion Methods - } - - #region Logging Stuff - - /// <summary> - /// Some Structured logging to the debug file - ONLY RUNS WHEN DLL COMPILED IN DEBUG MODE - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - [System.Diagnostics.Conditional("DEBUG")] - internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) - { - LogFormatted(Message, strParams); - } - - /// <summary> - /// Some Structured logging to the debug file - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - internal static void LogFormatted(String Message, params Object[] strParams) - { - Message = String.Format(Message, strParams); - String strMessageLine = String.Format("{0},{2}-{3},{1}", - DateTime.Now, Message, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, - System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); - UnityEngine.Debug.Log(strMessageLine); - } - - #endregion Logging Stuff - } -} \ No newline at end of file diff --git a/Source/Textures.cs b/Source/Textures.cs index c2ab1bb..2932dc9 100644 --- a/Source/Textures.cs +++ b/Source/Textures.cs @@ -48,7 +48,7 @@ internal static class Textures internal static Texture2D BtnRedCross = new Texture2D(16, 16, TextureFormat.ARGB32, false); internal static Texture2D BtnResize = new Texture2D(16, 16, TextureFormat.ARGB32, false); - internal static String PathIconsPath = System.IO.Path.Combine(DeepFreeze._AssemblyFolder.Substring(0, DeepFreeze._AssemblyFolder.IndexOf("\\DeepFreeze\\") + 11), "Icons").Replace("\\", "/"); + internal static String PathIconsPath = System.IO.Path.Combine(DeepFreeze._AssemblyFolder.Substring(0, DeepFreeze._AssemblyFolder.IndexOf("/DeepFreeze/") + 12), "Icons").Replace("\\", "/"); internal static String PathToolbarIconsPath = PathIconsPath.Substring(PathIconsPath.ToLower().IndexOf("/gamedata/") + 10); @@ -89,14 +89,14 @@ public static Boolean LoadImageFromFile(ref Texture2D tex, String fileName, Stri } else { - RSTUtils.Utilities.Log("TST Cannot find texture to load:" + folderPath + "(" + fileName + ")"); + RSTUtils.Utilities.Log("Cannot find texture to load:" + folderPath + "(" + fileName + ")"); } } catch (Exception ex) { - RSTUtils.Utilities.Log("TST Failed to load (are you missing a file):" + folderPath + "(" + fileName + ")"); + RSTUtils.Utilities.Log("Failed to load (are you missing a file):" + folderPath + "(" + fileName + ")"); RSTUtils.Utilities.Log(ex.Message); } return blnReturn; diff --git a/Source/ToolBarManager.cs b/Source/ToolBarManager.cs deleted file mode 100644 index a6ca1a5..0000000 --- a/Source/ToolBarManager.cs +++ /dev/null @@ -1,879 +0,0 @@ -/* -Copyright (c) 2013-2014, Maik Schreiber -All rights reserved. -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine; - -namespace DF -{ - /**********************************************************\ - * --- DO NOT EDIT BELOW THIS COMMENT --- * - * * - * This file contains classes and interfaces to use the * - * Toolbar Plugin without creating a hard dependency on it. * - * * - * There is nothing in this file that needs to be edited * - * by hand. * - * * - * --- DO NOT EDIT BELOW THIS COMMENT --- * - \**********************************************************/ - - /// <summary> - /// The global tool bar manager. - /// </summary> - public partial class ToolbarManager : IToolbarManager - { - /// <summary> - /// Whether the Toolbar Plugin is available. - /// </summary> - public static bool ToolbarAvailable - { - get - { - if (toolbarAvailable == null) - { - toolbarAvailable = Instance != null; - } - return (bool)toolbarAvailable; - } - } - - /// <summary> - /// The global tool bar manager instance. - /// </summary> - public static IToolbarManager Instance - { - get - { - if ((toolbarAvailable != false) && (instance_ == null)) - { - Type type = ToolbarTypes.getType("Toolbar.ToolbarManager"); - if (type != null) - { - object realToolbarManager = ToolbarTypes.getStaticProperty(type, "Instance").GetValue(null, null); - instance_ = new ToolbarManager(realToolbarManager); - } - } - return instance_; - } - } - } - - #region interfaces - - /// <summary> - /// A toolbar manager. - /// </summary> - public interface IToolbarManager - { - /// <summary> - /// Adds a new button. - /// </summary> - /// <remarks> - /// To replace an existing button, just add a new button using the old button's namespace and ID. - /// Note that the new button will inherit the screen position of the old button. - /// </remarks> - /// <param name="ns">The new button's namespace. This is usually the plugin's name. Must not include special characters like '.'</param> - /// <param name="id">The new button's ID. This ID must be unique across all buttons in the namespace. Must not include special characters like '.'</param> - /// <returns>The button created.</returns> - IButton add(string ns, string id); - } - - /// <summary> - /// Represents a clickable button. - /// </summary> - public interface IButton - { - /// <summary> - /// The text displayed on the button. Set to null to hide text. - /// </summary> - /// <remarks> - /// The text can be changed at any time to modify the button's appearance. Note that since this will also - /// modify the button's size, this feature should be used sparingly, if at all. - /// </remarks> - /// <seealso cref="TexturePath"/> - string Text - { - set; - get; - } - - /// <summary> - /// The color the button text is displayed with. Defaults to Color.white. - /// </summary> - /// <remarks> - /// The text color can be changed at any time to modify the button's appearance. - /// </remarks> - Color TextColor - { - set; - get; - } - - /// <summary> - /// The path of a texture file to display an icon on the button. Set to null to hide icon. - /// </summary> - /// <remarks> - /// <para> - /// A texture path on a button will have precedence over text. That is, if both text and texture path - /// have been set on a button, the button will show the texture, not the text. - /// </para> - /// <para> - /// The texture size must not exceed 24x24 pixels. - /// </para> - /// <para> - /// The texture path must be relative to the "GameData" directory, and must not specify a file name suffix. - /// Valid example: MyAddon/Textures/icon_mybutton - /// </para> - /// <para> - /// The texture path can be changed at any time to modify the button's appearance. - /// </para> - /// </remarks> - /// <seealso cref="Text"/> - string TexturePath - { - set; - get; - } - - /// <summary> - /// The button's tool tip text. Set to null if no tool tip is desired. - /// </summary> - /// <remarks> - /// Tool Tip Text Should Always Use Headline Style Like This. - /// </remarks> - string ToolTip - { - set; - get; - } - - /// <summary> - /// Whether this button is currently visible or not. Can be used in addition to or as a replacement for <see cref="Visibility"/>. - /// </summary> - /// <remarks> - /// Setting this property to true does not affect the player's ability to hide the button using the configuration. - /// Conversely, setting this property to false does not enable the player to show the button using the configuration. - /// </remarks> - bool Visible - { - set; - get; - } - - /// <summary> - /// Determines this button's visibility. Can be used in addition to or as a replacement for <see cref="Visible"/>. - /// </summary> - /// <remarks> - /// The return value from IVisibility.Visible is subject to the same rules as outlined for - /// <see cref="Visible"/>. - /// </remarks> - IVisibility Visibility - { - set; - get; - } - - /// <summary> - /// Whether this button is currently effectively visible or not. This is a combination of - /// <see cref="Visible"/> and <see cref="Visibility"/>. - /// </summary> - /// <remarks> - /// Note that the toolbar is not visible in certain game scenes, for example the loading screens. This property - /// does not reflect button invisibility in those scenes. In addition, this property does not reflect the - /// player's configuration of the button's visibility. - /// </remarks> - bool EffectivelyVisible - { - get; - } - - /// <summary> - /// Whether this button is currently enabled (clickable) or not. This does not affect the player's ability to - /// position the button on their toolbar. - /// </summary> - bool Enabled - { - set; - get; - } - - /// <summary> - /// Whether this button is currently "important." Set to false to return to normal button behaviour. - /// </summary> - /// <remarks> - /// <para> - /// This can be used to temporarily force the button to be shown on screen regardless of the toolbar being - /// currently in auto-hidden mode. For example, a button that signals the arrival of a private message in - /// a chat room could mark itself as "important" as long as the message has not been read. - /// </para> - /// <para> - /// Setting this property does not change the appearance of the button. Use <see cref="TexturePath"/> to - /// change the button's icon. - /// </para> - /// <para> - /// Setting this property to true does not affect the player's ability to hide the button using the - /// configuration. - /// </para> - /// <para> - /// This feature should be used only sparingly, if at all, since it forces the button to be displayed on - /// screen even when it normally wouldn't. - /// </para> - /// </remarks> - bool Important - { - set; - get; - } - - /// <summary> - /// A drawable that is tied to the current button. This can be anything from a popup menu to - /// an informational window. Set to null to hide the drawable. - /// </summary> - IDrawable Drawable - { - set; - get; - } - - /// <summary> - /// Event handler that can be registered with to receive "on click" events. - /// </summary> - /// <example> - /// <code> - /// IButton button = ... - /// button.OnClick += (e) => { - /// Debug.Log("button clicked, mouseButton: " + e.MouseButton); - /// }; - /// </code> - /// </example> - event ClickHandler OnClick; - - /// <summary> - /// Event handler that can be registered with to receive "on mouse enter" events. - /// </summary> - /// <example> - /// <code> - /// IButton button = ... - /// button.OnMouseEnter += (e) => { - /// Debug.Log("mouse entered button"); - /// }; - /// </code> - /// </example> - event MouseEnterHandler OnMouseEnter; - - /// <summary> - /// Event handler that can be registered with to receive "on mouse leave" events. - /// </summary> - /// <example> - /// <code> - /// IButton button = ... - /// button.OnMouseLeave += (e) => { - /// Debug.Log("mouse left button"); - /// }; - /// </code> - /// </example> - event MouseLeaveHandler OnMouseLeave; - - /// <summary> - /// Permanently destroys this button so that it is no longer displayed. - /// Should be used when a plugin is stopped to remove leftover buttons. - /// </summary> - void Destroy(); - } - - /// <summary> - /// A drawable that is tied to a particular button. This can be anything from a popup menu - /// to an informational window. - /// </summary> - public interface IDrawable - { - /// <summary> - /// Update any information. This is called once per frame. - /// </summary> - void Update(); - - /// <summary> - /// Draws GUI widgets for this drawable. This is the equivalent to the OnGUI() message in - /// <see cref="MonoBehaviour"/>. - /// </summary> - /// <remarks> - /// The drawable will be positioned near its parent toolbar according to the drawable's current - /// width/height. - /// </remarks> - /// <param name="position">The left/top position of where to draw this drawable.</param> - /// <returns>The current width/height of this drawable.</returns> - Vector2 Draw(Vector2 position); - } - - #endregion interfaces - - #region events - - /// <summary> - /// Event describing a click on a button. - /// </summary> - public partial class ClickEvent : EventArgs - { - /// <summary> - /// The button that has been clicked. - /// </summary> - public readonly IButton Button; - - /// <summary> - /// The mouse button which the button was clicked with. - /// </summary> - /// <remarks> - /// Is 0 for left mouse button, 1 for right mouse button, and 2 for middle mouse button. - /// </remarks> - public readonly int MouseButton; - } - - /// <summary> - /// An event handler that is invoked whenever a button has been clicked. - /// </summary> - /// <param name="e">An event describing the button click.</param> - public delegate void ClickHandler(ClickEvent e); - - /// <summary> - /// Event describing the mouse pointer moving about a button. - /// </summary> - public abstract partial class MouseMoveEvent - { - /// <summary> - /// The button in question. - /// </summary> - public readonly IButton button; - } - - /// <summary> - /// Event describing the mouse pointer entering a button's area. - /// </summary> - public partial class MouseEnterEvent : MouseMoveEvent - { - } - - /// <summary> - /// Event describing the mouse pointer leaving a button's area. - /// </summary> - public partial class MouseLeaveEvent : MouseMoveEvent - { - } - - /// <summary> - /// An event handler that is invoked whenever the mouse pointer enters a button's area. - /// </summary> - /// <param name="e">An event describing the mouse pointer entering.</param> - public delegate void MouseEnterHandler(MouseEnterEvent e); - - /// <summary> - /// An event handler that is invoked whenever the mouse pointer leaves a button's area. - /// </summary> - /// <param name="e">An event describing the mouse pointer leaving.</param> - public delegate void MouseLeaveHandler(MouseLeaveEvent e); - - #endregion events - - #region visibility - - /// <summary> - /// Determines visibility of a button. - /// </summary> - /// <seealso cref="IButton.Visibility"/> - public interface IVisibility - { - /// <summary> - /// Whether a button is currently visible or not. - /// </summary> - /// <seealso cref="IButton.Visible"/> - bool Visible - { - get; - } - } - - /// <summary> - /// Determines visibility of a button in relation to the currently running game scene. - /// </summary> - /// <example> - /// <code> - /// IButton button = ... - /// button.Visibility = new GameScenesVisibility(GameScenes.EDITOR, GameScenes.SPH); - /// </code> - /// </example> - /// <seealso cref="IButton.Visibility"/> - public class GameScenesVisibility : IVisibility - { - public bool Visible - { - get - { - return (bool)visibleProperty.GetValue(realGameScenesVisibility, null); - } - } - - private object realGameScenesVisibility; - private PropertyInfo visibleProperty; - - public GameScenesVisibility(params GameScenes[] gameScenes) - { - Type gameScenesVisibilityType = ToolbarTypes.getType("Toolbar.GameScenesVisibility"); - realGameScenesVisibility = Activator.CreateInstance(gameScenesVisibilityType, new object[] { gameScenes }); - visibleProperty = ToolbarTypes.getProperty(gameScenesVisibilityType, "Visible"); - } - } - - #endregion visibility - - #region drawable - - /// <summary> - /// A drawable that draws a popup menu. - /// </summary> - public partial class PopupMenuDrawable : IDrawable - { - /// <summary> - /// Event handler that can be registered with to receive "any menu option clicked" events. - /// </summary> - public event Action OnAnyOptionClicked - { - add - { - onAnyOptionClickedEvent.AddEventHandler(realPopupMenuDrawable, value); - } - remove - { - onAnyOptionClickedEvent.RemoveEventHandler(realPopupMenuDrawable, value); - } - } - - private object realPopupMenuDrawable; - private MethodInfo updateMethod; - private MethodInfo drawMethod; - private MethodInfo addOptionMethod; - private MethodInfo addSeparatorMethod; - private MethodInfo destroyMethod; - private EventInfo onAnyOptionClickedEvent; - - public PopupMenuDrawable() - { - Type popupMenuDrawableType = ToolbarTypes.getType("Toolbar.PopupMenuDrawable"); - realPopupMenuDrawable = Activator.CreateInstance(popupMenuDrawableType, null); - updateMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "Update"); - drawMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "Draw"); - addOptionMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "AddOption"); - addSeparatorMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "AddSeparator"); - destroyMethod = ToolbarTypes.getMethod(popupMenuDrawableType, "Destroy"); - onAnyOptionClickedEvent = ToolbarTypes.getEvent(popupMenuDrawableType, "OnAnyOptionClicked"); - } - - public void Update() - { - updateMethod.Invoke(realPopupMenuDrawable, null); - } - - public Vector2 Draw(Vector2 position) - { - return (Vector2)drawMethod.Invoke(realPopupMenuDrawable, new object[] { position }); - } - - /// <summary> - /// Adds a new option to the popup menu. - /// </summary> - /// <param name="text">The text of the option.</param> - /// <returns>A button that can be used to register clicks on the menu option.</returns> - public IButton AddOption(string text) - { - object realButton = addOptionMethod.Invoke(realPopupMenuDrawable, new object[] { text }); - return new Button(realButton, new ToolbarTypes()); - } - - /// <summary> - /// Adds a separator to the popup menu. - /// </summary> - public void AddSeparator() - { - addSeparatorMethod.Invoke(realPopupMenuDrawable, null); - } - - /// <summary> - /// Destroys this drawable. This must always be called before disposing of this drawable. - /// </summary> - public void Destroy() - { - destroyMethod.Invoke(realPopupMenuDrawable, null); - } - } - - #endregion drawable - - #region private implementations - - public partial class ToolbarManager : IToolbarManager - { - private static bool? toolbarAvailable = null; - private static IToolbarManager instance_; - private object realToolbarManager; - private MethodInfo addMethod; - private Dictionary<object, IButton> buttons = new Dictionary<object, IButton>(); - private ToolbarTypes types = new ToolbarTypes(); - - private ToolbarManager(object realToolbarManager) - { - this.realToolbarManager = realToolbarManager; - addMethod = ToolbarTypes.getMethod(types.iToolbarManagerType, "add"); - } - - public IButton add(string ns, string id) - { - object realButton = addMethod.Invoke(realToolbarManager, new object[] { ns, id }); - IButton button = new Button(realButton, types); - buttons.Add(realButton, button); - return button; - } - } - - internal class Button : IButton - { - private object realButton; - private ToolbarTypes types; - private Delegate realClickHandler; - private Delegate realMouseEnterHandler; - private Delegate realMouseLeaveHandler; - - internal Button(object realButton, ToolbarTypes types) - { - this.realButton = realButton; - this.types = types; - realClickHandler = attachEventHandler(types.button.onClickEvent, "clicked", realButton); - realMouseEnterHandler = attachEventHandler(types.button.onMouseEnterEvent, "mouseEntered", realButton); - realMouseLeaveHandler = attachEventHandler(types.button.onMouseLeaveEvent, "mouseLeft", realButton); - } - - private Delegate attachEventHandler(EventInfo @event, string methodName, object realButton) - { - MethodInfo method = GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); - Delegate d = Delegate.CreateDelegate(@event.EventHandlerType, this, method); - @event.AddEventHandler(realButton, d); - return d; - } - - public string Text - { - set - { - types.button.textProperty.SetValue(realButton, value, null); - } - get - { - return (string)types.button.textProperty.GetValue(realButton, null); - } - } - - public Color TextColor - { - set - { - types.button.textColorProperty.SetValue(realButton, value, null); - } - get - { - return (Color)types.button.textColorProperty.GetValue(realButton, null); - } - } - - public string TexturePath - { - set - { - types.button.texturePathProperty.SetValue(realButton, value, null); - } - get - { - return (string)types.button.texturePathProperty.GetValue(realButton, null); - } - } - - public string ToolTip - { - set - { - types.button.toolTipProperty.SetValue(realButton, value, null); - } - get - { - return (string)types.button.toolTipProperty.GetValue(realButton, null); - } - } - - public bool Visible - { - set - { - types.button.visibleProperty.SetValue(realButton, value, null); - } - get - { - return (bool)types.button.visibleProperty.GetValue(realButton, null); - } - } - - public IVisibility Visibility - { - set - { - object functionVisibility = null; - if (value != null) - { - functionVisibility = Activator.CreateInstance(types.functionVisibilityType, new object[] { new Func<bool>(() => value.Visible) }); - } - types.button.visibilityProperty.SetValue(realButton, functionVisibility, null); - visibility_ = value; - } - get - { - return visibility_; - } - } - - private IVisibility visibility_; - - public bool EffectivelyVisible - { - get - { - return (bool)types.button.effectivelyVisibleProperty.GetValue(realButton, null); - } - } - - public bool Enabled - { - set - { - types.button.enabledProperty.SetValue(realButton, value, null); - } - get - { - return (bool)types.button.enabledProperty.GetValue(realButton, null); - } - } - - public bool Important - { - set - { - types.button.importantProperty.SetValue(realButton, value, null); - } - get - { - return (bool)types.button.importantProperty.GetValue(realButton, null); - } - } - - public IDrawable Drawable - { - set - { - object functionDrawable = null; - if (value != null) - { - functionDrawable = Activator.CreateInstance(types.functionDrawableType, new object[] { -new Action(() => value.Update()), -new Func<Vector2, Vector2>((pos) => value.Draw(pos)) -}); - } - types.button.drawableProperty.SetValue(realButton, functionDrawable, null); - drawable_ = value; - } - get - { - return drawable_; - } - } - - private IDrawable drawable_; - - public event ClickHandler OnClick; - - private void clicked(object realEvent) - { - if (OnClick != null) - { - OnClick(new ClickEvent(realEvent, this)); - } - } - - public event MouseEnterHandler OnMouseEnter; - - private void mouseEntered(object realEvent) - { - if (OnMouseEnter != null) - { - OnMouseEnter(new MouseEnterEvent(this)); - } - } - - public event MouseLeaveHandler OnMouseLeave; - - private void mouseLeft(object realEvent) - { - if (OnMouseLeave != null) - { - OnMouseLeave(new MouseLeaveEvent(this)); - } - } - - public void Destroy() - { - detachEventHandler(types.button.onClickEvent, realClickHandler, realButton); - detachEventHandler(types.button.onMouseEnterEvent, realMouseEnterHandler, realButton); - detachEventHandler(types.button.onMouseLeaveEvent, realMouseLeaveHandler, realButton); - types.button.destroyMethod.Invoke(realButton, null); - } - - private void detachEventHandler(EventInfo @event, Delegate d, object realButton) - { - @event.RemoveEventHandler(realButton, d); - } - } - - public partial class ClickEvent : EventArgs - { - internal ClickEvent(object realEvent, IButton button) - { - Type type = realEvent.GetType(); - Button = button; - MouseButton = (int)type.GetField("MouseButton", BindingFlags.Public | BindingFlags.Instance).GetValue(realEvent); - } - } - - public abstract partial class MouseMoveEvent : EventArgs - { - internal MouseMoveEvent(IButton button) - { - this.button = button; - } - } - - public partial class MouseEnterEvent : MouseMoveEvent - { - internal MouseEnterEvent(IButton button) - : base(button) - { - } - } - - public partial class MouseLeaveEvent : MouseMoveEvent - { - internal MouseLeaveEvent(IButton button) - : base(button) - { - } - } - - internal class ToolbarTypes - { - internal readonly Type iToolbarManagerType; - internal readonly Type functionVisibilityType; - internal readonly Type functionDrawableType; - internal readonly ButtonTypes button; - - internal ToolbarTypes() - { - iToolbarManagerType = getType("Toolbar.IToolbarManager"); - functionVisibilityType = getType("Toolbar.FunctionVisibility"); - functionDrawableType = getType("Toolbar.FunctionDrawable"); - Type iButtonType = getType("Toolbar.IButton"); - button = new ButtonTypes(iButtonType); - } - - internal static Type getType(string name) - { - return AssemblyLoader.loadedAssemblies - .SelectMany(a => a.assembly.GetExportedTypes()) - .SingleOrDefault(t => t.FullName == name); - } - - internal static PropertyInfo getProperty(Type type, string name) - { - return type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance); - } - - internal static PropertyInfo getStaticProperty(Type type, string name) - { - return type.GetProperty(name, BindingFlags.Public | BindingFlags.Static); - } - - internal static EventInfo getEvent(Type type, string name) - { - return type.GetEvent(name, BindingFlags.Public | BindingFlags.Instance); - } - - internal static MethodInfo getMethod(Type type, string name) - { - return type.GetMethod(name, BindingFlags.Public | BindingFlags.Instance); - } - } - - internal class ButtonTypes - { - internal readonly Type iButtonType; - internal readonly PropertyInfo textProperty; - internal readonly PropertyInfo textColorProperty; - internal readonly PropertyInfo texturePathProperty; - internal readonly PropertyInfo toolTipProperty; - internal readonly PropertyInfo visibleProperty; - internal readonly PropertyInfo visibilityProperty; - internal readonly PropertyInfo effectivelyVisibleProperty; - internal readonly PropertyInfo enabledProperty; - internal readonly PropertyInfo importantProperty; - internal readonly PropertyInfo drawableProperty; - internal readonly EventInfo onClickEvent; - internal readonly EventInfo onMouseEnterEvent; - internal readonly EventInfo onMouseLeaveEvent; - internal readonly MethodInfo destroyMethod; - - internal ButtonTypes(Type iButtonType) - { - this.iButtonType = iButtonType; - textProperty = ToolbarTypes.getProperty(iButtonType, "Text"); - textColorProperty = ToolbarTypes.getProperty(iButtonType, "TextColor"); - texturePathProperty = ToolbarTypes.getProperty(iButtonType, "TexturePath"); - toolTipProperty = ToolbarTypes.getProperty(iButtonType, "ToolTip"); - visibleProperty = ToolbarTypes.getProperty(iButtonType, "Visible"); - visibilityProperty = ToolbarTypes.getProperty(iButtonType, "Visibility"); - effectivelyVisibleProperty = ToolbarTypes.getProperty(iButtonType, "EffectivelyVisible"); - enabledProperty = ToolbarTypes.getProperty(iButtonType, "Enabled"); - importantProperty = ToolbarTypes.getProperty(iButtonType, "Important"); - drawableProperty = ToolbarTypes.getProperty(iButtonType, "Drawable"); - onClickEvent = ToolbarTypes.getEvent(iButtonType, "OnClick"); - onMouseEnterEvent = ToolbarTypes.getEvent(iButtonType, "OnMouseEnter"); - onMouseLeaveEvent = ToolbarTypes.getEvent(iButtonType, "OnMouseLeave"); - destroyMethod = ToolbarTypes.getMethod(iButtonType, "Destroy"); - } - } - - #endregion private implementations -} \ No newline at end of file diff --git a/Source/USIWrapper.cs b/Source/USIWrapper.cs deleted file mode 100644 index 16436bf..0000000 --- a/Source/USIWrapper.cs +++ /dev/null @@ -1,210 +0,0 @@ -/** - * DeepFreeze Continued... - * (C) Copyright 2015, Jamie Leighton - * - * Kerbal Space Program is Copyright (C) 2013 Squad. See http://kerbalspaceprogram.com/. This - * project is in no way associated with nor endorsed by Squad. - * - * This file is part of JPLRepo's DeepFreeze (continued...) - a Fork of DeepFreeze. Original Author of DeepFreeze is 'scottpaladin' on the KSP Forums. - * This File was not part of the original Deepfreeze but was written by Jamie Leighton based of code and concepts from the Kerbal Alarm Clock Mod. Which was licensed under the MIT license. - * (C) Copyright 2015, Jamie Leighton - * - * Continues to be licensed under the Attribution-NonCommercial-ShareAlike 3.0 (CC BY-NC-SA 4.0) - * creative commons license. See <https://creativecommons.org/licenses/by-nc-sa/4.0/> - * for full details. - * - */ - -using System; -using System.Linq; -using System.Reflection; - -namespace DF -{ - /// <summary> - /// The Wrapper class to access USI LS - /// </summary> - public class USIWrapper - { - protected static System.Type USIType; - protected static System.Type USIUntrackKerbalType; - - protected static Object actualUSI = null; - protected static Object actualUSIUntrackKerbal = null; - - /// <summary> - /// This is the USI LS UntrackKerbal object - /// - /// SET AFTER INIT - /// </summary> - public static USIUntrackKerbalAPI USIUntrackKerbal = null; - - /// <summary> - /// Whether we found the USI LS assembly in the loadedassemblies. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean AssemblyExists { get { return (USIType != null); } } - - /// <summary> - /// Whether we managed to hook the running Instance from the assembly. - /// - /// SET AFTER INIT - /// </summary> - public static Boolean InstanceExists { get { return (USIUntrackKerbal != null); } } - - /// <summary> - /// Whether we managed to wrap all the methods/functions from the instance. - /// - /// SET AFTER INIT - /// </summary> - private static Boolean _USIWrapped = false; - - /// <summary> - /// Whether the object has been wrapped - /// </summary> - public static Boolean APIReady { get { return _USIWrapped; } } - - /// <summary> - /// This method will set up the USI LS object and wrap all the methods/functions - /// </summary> - /// <param name="Force">This option will force the Init function to rebind everything</param> - /// <returns></returns> - public static Boolean InitUSIWrapper() - { - //reset the internal objects - _USIWrapped = false; - actualUSI = null; - USIUntrackKerbal = null; - LogFormatted("Attempting to Grab USI LS Types..."); - - //find the base type - USIType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "LifeSupport.LifeSupportScenario"); - - if (USIType == null) - { - return false; - } - - LogFormatted("USI LS Version:{0}", USIType.Assembly.GetName().Version.ToString()); - - //find the LifeSupportManager class type - USIUntrackKerbalType = AssemblyLoader.loadedAssemblies - .Select(a => a.assembly.GetExportedTypes()) - .SelectMany(t => t) - .FirstOrDefault(t => t.FullName == "LifeSupport.LifeSupportManager"); - - if (USIUntrackKerbalType == null) - { - return false; - } - - //now grab the running instance - LogFormatted("Got Assembly Types, grabbing Instances"); - - try - { - actualUSIUntrackKerbal = USIUntrackKerbalType.GetField("instance", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null); - } - catch (Exception) - { - LogFormatted("No USI LS UntrackKerbal Instance found"); - //throw; - } - //if (actualUSI == null || actualUSIUntrackKerbal == null) - if (actualUSIUntrackKerbal == null) - { - LogFormatted("Failed grabbing Instance"); - return false; - } - - //If we get this far we can set up the local object and its methods/functions - LogFormatted("Got Instance, Creating Wrapper Objects"); - USIUntrackKerbal = new USIUntrackKerbalAPI(actualUSIUntrackKerbal); - - _USIWrapped = true; - return true; - } - - /// <summary> - /// The Type that is an analogue of the real USI LS. This lets you access all the API-able properties and Methods of USI LS - public class USIUntrackKerbalAPI - { - internal USIUntrackKerbalAPI(Object USIUntrackKerbal) - { - //store the actual object - APIactualUSIUntrackKerbal = USIUntrackKerbal; - - //these sections get and store the reflection info and actual objects where required. Later in the properties we then read the values from the actual objects - //for events we also add a handler - //LogFormatted("Getting APIReady Object"); - //APIReadyField = TRType.GetField("APIReady", BindingFlags.Public | BindingFlags.Static); - //LogFormatted("Success: " + (APIReadyField != null).ToString()); - - //WORK OUT THE STUFF WE NEED TO HOOK FOR PEOPLE HERE - //Methods - LogFormatted("Getting UntrackKerbal Method"); - USIUntrackKerbalMethod = USIUntrackKerbalType.GetMethod("UntrackKerbal", BindingFlags.Public | BindingFlags.Instance); - LogFormatted_DebugOnly("Success: " + (USIUntrackKerbalMethod != null).ToString()); - } - - private Object APIactualUSIUntrackKerbal; - - #region Methods - - private MethodInfo USIUntrackKerbalMethod; - - /// <summary> - /// Untrack a kerbal in USI LS - /// </summary> - /// <param name="kerbal">A string containing the kerbal's name</param> - internal void UntrackKerbal(string kerbal) - { - try - { - USIUntrackKerbalMethod.Invoke(APIactualUSIUntrackKerbal, new System.Object[] { kerbal }); - } - catch (Exception ex) - { - LogFormatted("Unable to invoke USI LS UntrackKerbal Method"); - LogFormatted("Exception: {0}", ex); - //throw; - } - } - - #endregion Methods - } - - #region Logging Stuff - - /// <summary> - /// Some Structured logging to the debug file - ONLY RUNS WHEN DLL COMPILED IN DEBUG MODE - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - [System.Diagnostics.Conditional("DEBUG")] - internal static void LogFormatted_DebugOnly(String Message, params Object[] strParams) - { - LogFormatted(Message, strParams); - } - - /// <summary> - /// Some Structured logging to the debug file - /// </summary> - /// <param name="Message">Text to be printed - can be formatted as per String.format</param> - /// <param name="strParams">Objects to feed into a String.format</param> - internal static void LogFormatted(String Message, params Object[] strParams) - { - Message = String.Format(Message, strParams); - String strMessageLine = String.Format("{0},{2}-{3},{1}", - DateTime.Now, Message, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, - System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); - UnityEngine.Debug.Log(strMessageLine); - } - - #endregion Logging Stuff - } -} \ No newline at end of file diff --git a/Source/VesselInfo.cs b/Source/VesselInfo.cs index 3eb9b9a..66b96c7 100644 --- a/Source/VesselInfo.cs +++ b/Source/VesselInfo.cs @@ -53,7 +53,6 @@ internal VesselInfo(string vesselName, double currentTime) this.vesselName = vesselName; hibernating = false; hasextDoor = false; - hasextDoor = false; hasextPod = false; lastUpdate = currentTime; } diff --git a/Source/ksp_dir.txt b/Source/ksp_dir.txt deleted file mode 100644 index 84ac29e..0000000 --- a/Source/ksp_dir.txt +++ /dev/null @@ -1 +0,0 @@ -C:\KSP_win 1.0.5 Test \ No newline at end of file