xEvilReeperx Posted November 10, 2014 Share Posted November 10, 2014 I'm trying to load some music into the game database. I have no idea what goes wrong here (it even worked at some time before I refactored the code).The path is right: C:\Kerbal Space Program\GameData\Akustik\Music\Moho.mp3Class extends MonoBehaviourExtended (KSPPluginFramework by TriggerAu), code is inside Start() (tried Awake() before - same error).File = "[B][U]Music/Moho.mp3[/U][/B]";...AssetLoader.LogFormatted_DebugOnly("Adding " + KSPUtil.ApplicationRootPath + "GameData/Akustik/" + File + " to database.");Asset = GameDatabase.Instance.GetAudioClip(KSPUtil.ApplicationRootPath +"GameData/Akustik/" + File); // this fails and I don't know why.AssetLoader.LogFormatted_DebugOnly("AudioClip is " + ((Asset == null) ? "null." : "loaded."));Asset.name = File; // exception because Asset == nullGetAudioClip just searches the GameDatabase of already-loaded audio clips. Your first problem is that your file won't be in GameDatabase; it only loads ogg and wav. The second is that GetAudioClip wants a path relative to GameData, so if your file is in "(KSPROOT)/GameData/Akustik/MyFile.ogg", you should pass "Akustik/MyFile" in to get it Quote Link to comment Share on other sites More sharing options...
*Aqua* Posted November 10, 2014 Share Posted November 10, 2014 Thank you very much! Quote Link to comment Share on other sites More sharing options...
Robotengineer Posted November 11, 2014 Share Posted November 11, 2014 I am having a GUI problem, the .log is saying I am pushing more GUIClips than I am popping, but I don't see how that is possible. Here is the log snippet and the GUI Methods.UnityEngine.TextEditor.ClampPos () UnityEngine.GUI.DoTextField (Rect position, Int32 id, UnityEngine.GUIContent content, Boolean multiline, Int32 maxLength, UnityEngine.GUIStyle style) UnityEngine.GUILayout.DoTextField (System.String text, Int32 maxLength, Boolean multiline, UnityEngine.GUIStyle style, UnityEngine.GUILayoutOption[] options) UnityEngine.GUILayout.TextArea (System.String text, UnityEngine.GUILayoutOption[] options) KerbLog.KlGUI.AutomaticLayoutGUI (Int32 winID) UnityEngine.GUI.CallWindowDelegate (UnityEngine.WindowFunction func, Int32 id, UnityEngine.GUISkin _skin, Int32 forceRect, Single width, Single height, UnityEngine.GUIStyle style)[ERR 11:53:22.035] GUI Error: You are pushing more GUIClips than you are popping. Make sure they are balancedHere are the two GUI functions.public void AutomaticLayoutGUI(int winID) { // begin area GUILayout.BeginArea (new Rect (0, 0, 400, 800)); // horizontal 1 GUILayout.BeginHorizontal (); // The bezel space. GUILayout.Space (10); // vertical 1 GUILayout.BeginVertical (); // H2 GUILayout.BeginHorizontal (); GUILayout.FlexibleSpace (); GUILayout.Label ("Folder name"); GUILayout.FlexibleSpace (); // end H2 GUILayout.EndHorizontal(); fileName = GUILayout.TextField (fileName); // H3 GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace (); GUILayout.Label ("Log name"); GUILayout.FlexibleSpace (); // end H3 GUILayout.EndHorizontal(); LogName = GUILayout.TextField (LogName); // H4 GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace (); GUILayout.Label ("Log"); GUILayout.FlexibleSpace (); // end H4 GUILayout.EndHorizontal(); // S1 ScrollPos = GUILayout.BeginScrollView(ScrollPos); KerbLogtxt = GUILayout.TextArea (KerbLogtxt, GUILayout.ExpandHeight(true)); // end S1 GUILayout.EndScrollView (); GUILayout.Space (5); if (GUILayout.Button ("Save")) { SaveToFile(); } if(GUILayout.Button("Reset")) { SetTimeRun = false; LogName = "Log: "; KerbLogtxt = "Log:"; fileName = ""; } if (GUILayout.Button ("Load")) { ShowLoadGUI = !ShowLoadGUI; } GUILayout.Space (10); // end V1 GUILayout.EndVertical (); GUILayout.Space (10); // end H1 GUILayout.EndHorizontal (); // end area GUILayout.EndArea (); GUI.DragWindow (); } public void LoadGUI(int winID) { bool showloadtxt = false; // start area GUILayout.BeginArea (new Rect (0, 0, 400, 600)); // start horizontal 1 GUILayout.BeginHorizontal (); GUILayout.Space (10); //begin vertical 1 GUILayout.BeginVertical (); //begin horizontal 2 GUILayout.BeginHorizontal (); ShowFolder = GUILayout.Toggle (ShowFolder, "Use Folder"); fileName = GUILayout.TextField (fileName); GUILayout.Space (10); // end horizontal 2 GUILayout.EndHorizontal (); // begin scroll view ScrollPos2 = GUILayout.BeginScrollView (ScrollPos2, GUILayout.ExpandHeight(true)); foreach(string txtfile in LoadName()) { string returntxt = txtfile.Replace(getPath(), ""); returntxt = returntxt.Replace(".txt", ""); showloadtxt = GUILayout.Button(returntxt); if(showloadtxt) { LogName = returntxt; KerbLogtxt = LoadFromtxt(); } } // end scroll view GUILayout.EndScrollView (); GUILayout.Space (10); // end vertical 1 GUILayout.EndVertical (); GUILayout.Space (10); // end horiontal 1 GUILayout.EndHorizontal (); // end area GUILayout.EndArea (); GUI.DragWindow (); } Quote Link to comment Share on other sites More sharing options...
DMagic Posted November 12, 2014 Share Posted November 12, 2014 I am having a GUI problem, the .log is saying I am pushing more GUIClips than I am popping, but I don't see how that is possible. Here is the log snippet and the GUI Methods.I'm guessing that the GUILayout.TextArea method is choking on something, which prevents all of the following GUILayout.EndSomethings from being run. Try to comment out the TextArea, or figure out why it's broken. Quote Link to comment Share on other sites More sharing options...
AlphaAsh Posted November 12, 2014 Share Posted November 12, 2014 Anyone got any ideas on where to look in the API for a way to temporarily modify the cost to launch/rollout a vessel? Such that the little indicator in the VAB/SPH for the vessel cost actually changes? Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 12, 2014 Share Posted November 12, 2014 I would suggest looking at the LateUpdate() method.Rather then having to dig into the code to modify costs, that method allows you to hook into the screen display and change what is displayed without actually changing anything underneath.I used in here in my Landing Height mode to override the altitude display at the top of the screen without actually changing any of the altitude variables on the vessel.I would think this trick would also work in the editor. (Also you would have to track down what that widget is named to override it.)Hope that helps,D. Quote Link to comment Share on other sites More sharing options...
AlphaAsh Posted November 12, 2014 Share Posted November 12, 2014 (edited) I'll look at that. Still going to need to get the total craft value one way or another though and I'm starting to worry I may have to calculate it myself by iterating through parts. Be much nicer if I could just re-use the code that already does that but I suspect there's no API exposure of that.EDIT - Nevermind, I can catch it with OnFundsChanged - just won't be updating the widget. Meh. Edited November 12, 2014 by AlphaAsh Quote Link to comment Share on other sites More sharing options...
Robotengineer Posted November 12, 2014 Share Posted November 12, 2014 I'm guessing that the GUILayout.TextArea method is choking on something, which prevents all of the following GUILayout.EndSomethings from being run. Try to comment out the TextArea, or figure out why it's broken.Thanks, I checked my other functions and it was a problem with them. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted November 12, 2014 Share Posted November 12, 2014 Still going to need to get the total craft value one way or another though and I'm starting to worry I may have to calculate it myself by iterating through parts. Be much nicer if I could just re-use the code that already does that but I suspect there's no API exposure of that.There is, it's just been slightly complicated with the addition of strategies. Here's what AlignedCurrencyFormatter uses:float dryCost = 0f; float fuelCost = 0f; float total = EditorLogic.fetch.ship.GetShipCosts(out dryCost, out fuelCost); // player might have a strategy active which increases/decreases total ship cost var cm = CurrencyModifierQuery.RunQuery(TransactionReasons.VesselRollout, total, 0f, 0f); total += cm.GetEffectDelta(Currency.Funds); // it's not a multiplier, it's the difference between current and modified totalAnother clever option might be to create your own strategy that's temporarily applied in the editor. I have zero experience with that, though Quote Link to comment Share on other sites More sharing options...
AlphaAsh Posted November 12, 2014 Share Posted November 12, 2014 There is, it's just been slightly complicated with the addition of strategies.... Another clever option might be to create your own strategy that's temporarily applied in the editor. I have zero experience with that, thoughI like the second idea a lot because it's already tied in everywhere it needs to be. Still, if it's easy enough to pass back and the widget catches that, then idea one will do. Cheers chap. Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 13, 2014 Share Posted November 13, 2014 (edited) Is there any way to find all partModules in the game, as in every module that is loaded?PartModule[] allPMs = FindObjectsOfType<PartModule>(); only returns ACTIVE modules, not all modules.I was hoping there would be something in protoParts DB, but it either is not there or my search skills are failing me. I'm after the equivalent of the protoParts DB actually as I want to make edits to partModules that will globally affect all parts with that partModule. (Add BaseActions to the partModule.Actions list.)Any thoughts?D. Edited November 13, 2014 by Diazo Quote Link to comment Share on other sites More sharing options...
jamespicone Posted November 13, 2014 Share Posted November 13, 2014 Is there any way to find all partModules in the game, as in every module that is loaded?PartModule[] allPMs = FindObjectsOfType<PartModule>(); only returns ACTIVE modules, not all modules.I was hoping there would be something in protoParts DB, but it either is not there or my search skills are failing me. I'm after the equivalent of the protoParts DB actually as I want to make edits to partModules that will globally affect all parts with that partModule. (Add BaseActions to the partModule.Actions list.)Any thoughts?D.You can loop through all the part prefabs from PartLoader and then look at their modules:foreach (AvailablePart a in PartLoader.LoadedPartsList) { if (a.partPrefab.Modules != null) { foreach (PartModule m in a.partPrefab.Modules) { Debug.Log("Part " + a.name + " has module " + m.name); } }}You'll obviously hit the same module type multiple times, but you can just put them in a list iff you don't have one of that type yet. Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 13, 2014 Share Posted November 13, 2014 (edited) Hmm, that would get me a list of all partModules, but can I edit the partModules themselves from the list that would generate?Testing incoming it looks like.D.edit: Have not tested it yet, but I don't think that will work. That would get me the instance of the partModule on that part, not a global partModule I could edit once and be done.I could edit each partModule individually, but I can see that increasing the load time when you start the game. Hmmm..... Edited November 13, 2014 by Diazo Quote Link to comment Share on other sites More sharing options...
Crzyrndm Posted November 13, 2014 Share Posted November 13, 2014 Unless you're doing something that takes a noticeable period of time to execute on each module, the change in load times would only be a handful of seconds which is entirely inconsequential given KSP's load times... Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 13, 2014 Share Posted November 13, 2014 True, but I'm more worried that the partModule object does not actually exist at that level and is instantiated from the .dll each time the part is loaded into the editor or flight mode. If that is case then this is a dead end and I'll have to find another way.Out to time to actually test tonight so I still have to actually experiment tomorrow to see exactly what is happening.D. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted November 13, 2014 Share Posted November 13, 2014 but I'm more worried that the partModule object does not actually exist at that level and is instantiated from the .dll each time the part is loaded into the editor or flight mode. If that is case then this is a dead end and I'll have to find another way.It's cloned (as part of the part prefab) and then any persistent data gets copied into its fields. I'm not sure it would work in your case; if that action list gets re-created during the second part (say, if it were being loaded from a save to map its actions to an action group*) then any changes you made to the prefab one wouldn't take. It's worth a try anyhow.*I don't know for certain this is how it works. I've never worked with BaseAction Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 13, 2014 Share Posted November 13, 2014 (edited) For all my work with BaseAction, I'm in totally unknown territory also, this is as much a partModule loading question as a baseAction question.While I've yet to run any tests, I have had a sleep on it (and based on your comment about cloning) and my current expectation is that during the loading process each part in the prefrab gets a copy of the appropriate partModules and by the time I can affect anything it is too late for me to affect the global partModule object. This means I will have to walk the entire part prefab cycling through each partModule on each part. After that for new vessels created I think that would be fine, the big question mark is what happens to existing vessels in flight?This is all pure speculation until I can get home and run some tests though, have a work day to get through first.D. Edited November 13, 2014 by Diazo Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 14, 2014 Share Posted November 14, 2014 Grrr.It's looking like this is a dead end.AvailablePart.partPrefab.Modules is null so I can't reference it.It looks like the partModules are stored in the List<string>AvailablePart.moduleInfos, but that appears to just be the partModule names that I'm assuming the list gets referenced to load the partModules when the part is spawned.Which still leaves me with no clue where the default partModules sit around before they get used. My best lead was in the AssemblyLoader class, but I drew a blank there also.Unless anyone has a brainwave, this is a dead end and I'll come at this another way.D. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted November 14, 2014 Share Posted November 14, 2014 It looks like the partModules are stored in the List<string>AvailablePart.moduleInfos, but that appears to just be the partModule names that I'm assuming the list gets referenced to load the partModules when the part is spawned.Which still leaves me with no clue where the default partModules sit around before they get used. My best lead was in the AssemblyLoader class, but I drew a blank there also.There isn't a "default" ModuleScienceExperiment, for example. There are ModuleScienceExperiments, pre-loaded with relevant data (from ConfigNodes like you'd expect), already attached to the part prefab. Here's what one looks like:[LOG 01:26:25.837] DebugTools, mk1pod has components:[LOG 01:26:25.838] DebugTools, ...c: UnityEngine.Transform[LOG 01:26:25.838] DebugTools, ...c: Part[LOG 01:26:25.839] DebugTools, ...c: ModuleCommand[LOG 01:26:25.839] DebugTools, ...c: PartResource[LOG 01:26:25.840] DebugTools, ...c: ModuleSAS[LOG 01:26:25.841] DebugTools, ...c: ModuleReactionWheel[LOG 01:26:25.841] DebugTools, ...c: ModuleScienceExperiment[LOG 01:26:25.842] DebugTools, ...c: ModuleScienceContainer[LOG 01:26:25.842] DebugTools, ...c: PartResource[LOG 01:26:25.843] DebugTools, ...c: FlagDecal[LOG 01:26:25.843] DebugTools, ...c: ModuleTripLogger[LOG 01:26:25.844] DebugTools, --->model has components:[LOG 01:26:25.844] DebugTools, ......c: UnityEngine.Transform[LOG 01:26:25.845] DebugTools, ------>capsule has components:[LOG 01:26:25.846] DebugTools, .........c: UnityEngine.Transform[LOG 01:26:25.846] DebugTools, .........c: UnityEngine.MeshFilter[LOG 01:26:25.847] DebugTools, .........c: UnityEngine.MeshRenderer[LOG 01:26:25.847] DebugTools, --------->collider has components:[LOG 01:26:25.848] DebugTools, ............c: UnityEngine.Transform[LOG 01:26:25.848] DebugTools, ............c: UnityEngine.MeshCollider[LOG 01:26:25.849] DebugTools, --------->flagTransform has components:[LOG 01:26:25.850] DebugTools, ............c: UnityEngine.Transform[LOG 01:26:25.850] DebugTools, ............c: UnityEngine.MeshFilter[LOG 01:26:25.851] DebugTools, ............c: UnityEngine.MeshRenderer[LOG 01:26:25.851] DebugTools, --------->hatch has components:[LOG 01:26:25.852] DebugTools, ............c: UnityEngine.Transform[LOG 01:26:25.852] DebugTools, ............c: UnityEngine.MeshFilter[LOG 01:26:25.853] DebugTools, ............c: UnityEngine.MeshRenderer[LOG 01:26:25.854] DebugTools, --------->rung has components:[LOG 01:26:25.854] DebugTools, ............c: UnityEngine.Transform[LOG 01:26:25.855] DebugTools, ............c: UnityEngine.MeshFilter[LOG 01:26:25.855] DebugTools, ............c: UnityEngine.MeshRenderer[LOG 01:26:25.856] DebugTools, --------->rung has components:[LOG 01:26:25.856] DebugTools, ............c: UnityEngine.Transform[LOG 01:26:25.857] DebugTools, ............c: UnityEngine.MeshFilter[LOG 01:26:25.858] DebugTools, ............c: UnityEngine.MeshRenderer[LOG 01:26:25.859] DebugTools, --------->window has components:[LOG 01:26:25.860] DebugTools, ............c: UnityEngine.Transform[LOG 01:26:25.860] DebugTools, ............c: UnityEngine.MeshFilter[LOG 01:26:25.861] DebugTools, ............c: UnityEngine.MeshRenderer[LOG 01:26:25.862] DebugTools, ------>ladder has components:[LOG 01:26:25.862] DebugTools, .........c: UnityEngine.Transform[LOG 01:26:25.863] DebugTools, .........c: UnityEngine.CapsuleCollider[LOG 01:26:25.863] DebugTools, ------>airlock has components:[LOG 01:26:25.864] DebugTools, .........c: UnityEngine.Transform[LOG 01:26:25.864] DebugTools, .........c: UnityEngine.CapsuleCollider(this being from)[KSPAddon(KSPAddon.Startup.MainMenu, true)]class PrefabDump : MonoBehaviour{ void Start() { var ap = PartLoader.getPartInfoByName("mk1pod"); ap.partPrefab.gameObject.PrintComponents(); }}When a part is spawned, this whole GameObject gets cloned. If you were to destroy the ModuleScienceExperiment on this GO in the main menu, no mk1pods would be able to produce crew reports any more, whether they were loaded from a save game or created fresh.I think you're still sunk, though. I had a look around and couldn't find a way to create a brand-new BaseAction without using reflection Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 14, 2014 Share Posted November 14, 2014 Hmmm.I'm not going to give up just yet then. If I can use that component list to reference the module I may not be done yet. I have an idea or two about making a dummy BaseAction and adding it to the partModule.actions list, but until I can access the partModule itself I can't test that.Thanks for the help,D. Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 16, 2014 Share Posted November 16, 2014 Okay, I actually think I almost have this, maybe.I can add the action to the partmodule and everything looks fine, except it does not show up once I place a part.Adding the action to the ModuleScienceExperiment on the Mk 1 pod, this is running in KSPAddon.Startup.MainMenu:AvailablePart ap = PartLoader.getPartInfoByName("mk1pod"); foreach(Component cp in ap.partPrefab.gameObject.GetComponents<Component>()) { if (cp.GetType().FullName == "ModuleScienceExperiment") { ModuleScienceExperiment mdlGim = (ModuleScienceExperiment)cp; BaseActionList testList = mdlGim.Actions; print("a " + testList.Count); //prints 2 for the two actions on the part testList.Add(new BaseAction(testList, "HWAct", new BaseActionDelegate(HWTest), new KSPAction("HWTestGUI"))); print("b " + testList.Count); //prints 3 to show my action having been added } }This throws no errors or any other indication something has gone wrong.However, when I go to the editor and place a Mk 1 Pod, I get the following in the log which confuses me:[LOG 19:44:17.642] a 3 //start my loop through the AvailablePart in the partLoaded, 3 for 3 actions[LOG 19:44:17.643] ba DeployAction //note I have 3 actions[LOG 19:44:17.644] ba ResetAction //Deploy and Reset come with the module [LOG 19:44:17.644] ba HWAct //new Action I have added[LOG 19:44:17.645] pm acts 2 //start of my loop through the placed parts, 2 for 2 actions[LOG 19:44:17.646] pmba DeployAction //my action is missing on the part[LOG 19:44:17.646] pmba ResetActionSo, any ideas what is going on? When I am in the editor the AvailablePart in the partLoader shows 3 actions the entire time I am in the editor, both before and after I place the part, but the part I place from that AvailablePart does not have the action I added.There are absolutely no message that help, error messages or otherwise, did I mess up the creation of the Action or am I misunderstanding how the AvailablePart class works? I don't even know where to start.D. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted November 17, 2014 Share Posted November 17, 2014 Sorry for delayed response, somehow this post slipped by meI can add the action to the partmodule and everything looks fine, except it does not show up once I place a part....So, any ideas what is going on? When I am in the editor the AvailablePart in the partLoader shows 3 actions the entire time I am in the editor, both before and after I place the part, but the part I place from that AvailablePart does not have the action I added.It looks like PartModule BaseActions are recreated after the prefab gets copied. Sadly, this means you'll have to modify every single spawned instance instead of the general set-and-forget solution you were looking for:[KSPAddon(KSPAddon.Startup.MainMenu, true)]class EditPodModules : MonoBehaviour{ void Start() { PartLoader.getPartInfoByName("mk1pod").partPrefab.AddModule("AddAnAction"); }}class AddAnAction : PartModule{ public override void OnAwake() { Log.Normal("AddAnAction running"); var exp = GetComponent<ModuleScienceExperiment>(); exp.Actions.Add(new BaseAction(exp.Actions, "HWAct", new BaseActionDelegate(TestMethod), new KSPAction("HWTestGUI"))); exp.Actions.ForEach(ba => Log.Normal("Instance part action: {0}", ba.guiName)); } void TestMethod(KSPActionParam p) { print("TestMethod"); }} Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 17, 2014 Share Posted November 17, 2014 Alright, that confirms this as a dead end then.I started down this line of investigation for two reasons. First to avoid having to modify the part as it is placed as I'm worried about code order and other things running on part creation trying to reference the action but running earlier in the start up cycle so the action does not exist yet. In theory this would be easy enough to deal with, in practice I'm still a beginner programmer really and I can see that stymieing me quite easily.Second was to avoid having to add a partModule. This was only for looks on the part detail window, but I did not want to see two ModuleGimbal (ModuleGimbal and ModuleGimbalAction) entries in the partModule list that appears when you right-click.If I have to add a partModule anyway, I'm going to go with the easier route of just using the KSPAction property on the partModule. Is there some way to hide a partModule from showing in the partModule list in the editor? (The list you pop out with RMB that shows details such as engine thrust, ISP, etc.)Thanks for all the help xEvilReeperx,D. Quote Link to comment Share on other sites More sharing options...
xEvilReeperx Posted November 17, 2014 Share Posted November 17, 2014 It looks like you can hide what's displayed by messing with AvailablePart.moduleInfos, although the AddAnAction PartModule from above doesn't seem to appear in that list anyway Quote Link to comment Share on other sites More sharing options...
Diazo Posted November 17, 2014 Share Posted November 17, 2014 Hmmm, interesting.The ModuleGimbalActions partModule I add to the part to add more actions to the ModuleGimbal partModule does show in that list. I wonder what the criteria are to be visible?Experiments incoming.D. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.