Jump to content

The official unoffical "help a fellow plugin developer" thread


Recommended Posts

On 6/18/2017 at 4:36 AM, Bonus Eventus said:

I did a simple test with an internal module I've been tinkering with, and caused all kinds of mayhem. The module is simple. It finds a prop transform for a screen model and an empty gameObject, then adds a camera component to the empty gameObject and adds a renderTexture to the screen model. The camera then has its targetTexture assigned to the renderTexture. That's it. 

The game loads fine but when I load the IVA on the pad the main cam is rotated 90 degrees on the x axis or sometimes is flung into deep space before the game crashes. I'm guessing it has something to do with layers and tags. I'm sure there's some camera voodoo I'm unaware of. @linuxgurugamer would probably know what the best practices are.

hum. I don't see where you create an empty GameObject. You search for a transform in a model, add a Camera component to it. Then search for the Camera Component you just added (???) and change the parent to itself. The last part, as many years of SF about time travel taught us, will not end well.

What you want may be closer to this. But know that you need more than 1 camera to show the scene so you would have to create one for each of FlightCamera.fetch.cameras[x] (2 in currently). See JPLRepo post for the details

				
displayTexture = new RenderTexture(dPixelWidth, dPixelHeight, 24, RenderTextureFormat.ARGB32);
displayTexture.Create(); // not sure if mandatory
displayMaterial = internalProp.FindModelTransform(dTransform).GetComponent<Renderer>().material;

cameraParentTransform = internalProp.internalModel.FindModelTransform(cameraName);				

GameObject cameraGameObject = new GameObject("MyNewCamera");				
cameraGameObject.transform.parent = cameraParentTransform;
cameraGameObject.transform.localPosition = Vector3.zero;
cameraGameObject.transform.localRotation = Quaternion.identity;							

Camera cameraFeed = cameraGameObject.AddComponent<Camera>();
cameraFeed.CopyFrom(FlightCamera.fetch.mainCamera);
cameraFeed.fieldOfView = 110;				

UtilisTools.Log(this, "Camera created");				
displayMaterial.mainTexture = displayTexture;

 

Link to comment
Share on other sites

On 6/19/2017 at 5:30 AM, sarbian said:

hum. I don't see where you create an empty GameObject. You search for a transform in a model, add a Camera component to it. Then search for the Camera Component you just added (???) and change the parent to itself. The last part, as many years of SF about time travel taught us, will not end well.

What you want may be closer to this. But know that you need more than 1 camera to show the scene so you would have to create one for each of FlightCamera.fetch.cameras[x] (2 in currently). See JPLRepo post for the details


				
displayTexture = new RenderTexture(dPixelWidth, dPixelHeight, 24, RenderTextureFormat.ARGB32);
displayTexture.Create(); // not sure if mandatory
displayMaterial = internalProp.FindModelTransform(dTransform).GetComponent<Renderer>().material;

cameraParentTransform = internalProp.internalModel.FindModelTransform(cameraName);				

GameObject cameraGameObject = new GameObject("MyNewCamera");				
cameraGameObject.transform.parent = cameraParentTransform;
cameraGameObject.transform.localPosition = Vector3.zero;
cameraGameObject.transform.localRotation = Quaternion.identity;							

Camera cameraFeed = cameraGameObject.AddComponent<Camera>();
cameraFeed.CopyFrom(FlightCamera.fetch.mainCamera);
cameraFeed.fieldOfView = 110;				

UtilisTools.Log(this, "Camera created");				
displayMaterial.mainTexture = displayTexture;

 

Thank you @sarbian, haha, that line adding the component to itself as parent shouldn't have been in there to begin with, it was old code.That JPLRepo post helped a lot. I was confused though about whether I needed to duplicate both the near and far camera or could use one camera at a higher depth. I've since revised the code. This is where I got last night.

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace Utilis
{
	public class UtilisDisplay : InternalModule
	{
		[KSPField]
		public string cameraName = "utilisCamera";

		[KSPField]
		public int width = 512;

		[KSPField]
		public int height = 256;

		public Camera camera;

		public RenderTexture renderTexture;

		private Material material;

		public override void OnAwake()
		{
			if(!HighLogic.LoadedSceneIsFlight) return;

			renderTexture = new RenderTexture(height,width,24,RenderTextureFormat.RGB565);

			renderTexture.anisoLevel = 0;

			renderTexture.antiAliasing = 4;

			renderTexture.filterMode = FilterMode.Trilinear;

			renderTexture.isPowerOfTwo = true;

			renderTexture.Create();

			while (!renderTexture.IsCreated()) ;

			material = gameObject.GetChild("model").GetComponent<Renderer>().material;

			camera = internalModel.FindModelTransform(cameraName).gameObject.AddComponent<Camera>();

			camera.fieldOfView = 100;

			camera.cullingMask = (1 << 0) | (1 << 1) | (1 << 4) | (1 << 9) | (1 << 10) | (1 << 15) | (1 << 18) | (1 << 20) | (1 << 23);

			camera.nearClipPlane = 0.001f;

			camera.farClipPlane = 1000000000f;

			camera.targetTexture = renderTexture;

			Camera[] fCameras = FlightCamera.fetch.cameras;

			foreach(Camera c in fCameras)
			{
				if(c.name == "Camera00")
				{
					camera.depth = c.depth + 1;
				}
			}

			camera.enabled = false;

			camera.Render();

			material.mainTexture = renderTexture;
		}
	}
}

The problem of the main camera flipping out was caused by a null reference I missed in the log. I didn't understand that dTransform was not where the renderer was located, because when I compiled the .mu file I added the part tools component directly. dTransform has no renderer or mesh, what I needed was the "model" transform. 

As of this moment the problem I'm still having is that the render texture appears completely black. At first I thought it was a depth problem. I thought maybe one of the gui cameras at the lowest layer renders a black screen. But that turned out to be wrong, because I switched the depth order and nothing changed. I was thinking I would add the second camera after I confirmed I can render texture was working. 

BTW, I too am confused about RenderTexture.create( ), the docs are a bit ambiguous: "RenderTexture constructor does not actually create the hardware texture; by default the texture is created the first time it is set active. Calling Create lets you create it up front. Create does nothing if the texture is already created."

Edited by Bonus Eventus
Link to comment
Share on other sites

  • 2 weeks later...

Found an odd issue working on a problem with Submarines. It looks like anything that is Splashed / Underwater is considered "VesselType.Debris" . Has anyone else confirmed this, its a problem as I am trying to implement Sonar and I would like to exclude Debris from targeting but be able to keep a list of underwater vessels.

Link to comment
Share on other sites

On 6/30/2017 at 1:11 PM, Dozed12 said:

What's the best way to get the distance from the active vessel to a specific CelestialBody?

Found two things of note: CelestialBody.position and Vessel.GetWorldPos3d(). With these, you could do a little Pythagoras and arrive at a distance.

Alternatively, you could do CelestialBody.GetAltitude(Vessel.GetWorldPos3d()), which would give you distance to nearest sea level. I'm not sure if that works out of the SoI of a given planet, though.

Link to comment
Share on other sites

hey guys this is my first forrey into plugin development having been a part modder for many years but im wanting to look at pushing VRTK and the vive compatablity into ksp, anyone have any ideas o where to start to start rebuilding the UI for vr, a good start would be the ability to walk and teleport around the SPH 

Link to comment
Share on other sites

 Hello fellow potential helpers.

 I used to write tiny games in BASIC on Apple IIe in the 90's.  So, after a few decades hiatus I now have a Learning C# book and have several tabs open to docs.unity3d.com  I installed MS Visual C# 2010, added the KSP Unity references, and after a few days of googling debugging errors I have lines written that will build.  Feeling ok.

 But the code doesn't do what I expect.  Since I don't yet know how to display text on the screen I thought I'd test by bombarding the log just to see what would happen, but nada.  The KSP log shows nothing, but I think it should be adding a single digit floating point number every phyics step.  You folks see anything?

using UnityEngine;
public class spin : MonoBehaviour
{
    public Rigidbody rb;
    void start()
    {
        object rb = GetComponent<Rigidbody>();
    }
        void fixedupdate()
    {
        float rads = rb.angularVelocity.magnitude;
        Debug.Log(rads);
    }
}

 

Link to comment
Share on other sites

4 minutes ago, klond said:

I used to write tiny games in BASIC on Apple IIe in the 90's.  So, after a few decades hiatus I now have a Learning C# book and have several tabs open to docs.unity3d.com  I installed MS Visual C# 2010, added the KSP Unity references, and after a few days of googling debugging errors I have lines written that will build.  Feeling ok.

Cool, welcome back! I've found that C# has inverted my attitude towards compiler errors. Formerly I thought of it as a bad thing when I got a compiler error, but now if I write some new code and get a compiler error, I feel grateful that my latest error was caught by the compiler, whereas otherwise I feel regret that it will take actual testing to find. :)

4 minutes ago, klond said:

You folks see anything?

You need to tell it when to run your module with the KSPAddon attribute. Try tagging your MonoBehaviour class with this to load it at the KSC:

[KSPAddon(KSPAddon.Startup.SpaceCentre, false)]

Also, function names are case sensitive; use Start and FixedUpdate instead. And your GetComponent call will probably return null, because a freshly created MonoBehaviour won't have any components in it by default. Try AddComponent, or get a reference to an object that already has a Rigidbody.

Link to comment
Share on other sites

36 minutes ago, klond said:

 


using UnityEngine;
public class spin : MonoBehaviour
{
    public Rigidbody rb;
    void start()
    {
        object rb = GetComponent<Rigidbody>();
    }
        void fixedupdate()
    {
        float rads = rb.angularVelocity.magnitude;
        Debug.Log(rads);
    }
}

 

using UnityEngine;
public class spin : MonoBehaviour
{
    public Rigidbody rb;
    void FixedUpdate()
    {
        float rads = rb.angularVelocity.magnitude;
        Debug.Log(rads);
    }
}

I believe this is what your wanting.

 

Send message to screen with:

ScreenMessages.PostScreenMessage(meassage, duration, ScreenMessageStyle style);

Edited by Next_Star_Industries
Link to comment
Share on other sites

On 30/06/2017 at 10:11 PM, Dozed12 said:

What's the best way to get the distance from the active vessel to a specific CelestialBody?

There is a built-in method for this : Vector3d.Distance (Vector3d a, Vector3d b). It will return the distance in meter (as a double).

KSP uses different referential, I think you need to use : FlightGlobals.ship_orbit.pos (for your ship) and body.orbit.pos (where body is a CelestialBody). Not 100% sure about those so test it :wink:

 

 

13 hours ago, amankd said:

hey guys this is my first forrey into plugin development having been a part modder for many years but im wanting to look at pushing VRTK and the vive compatablity into ksp, anyone have any ideas o where to start to start rebuilding the UI for vr, a good start would be the ability to walk and teleport around the SPH 

I love to see a VR mod for KSP, there were one for KSP 1.1.2 but the author had trouble getting it to work with newer version, check their github : https://github.com/Vivero/Kerbal-VR

Edited by Li0n
Link to comment
Share on other sites

22 hours ago, 0111narwhalz said:

I may have asked this already, but…

How might I load a save? I see the class QuickSaveLoad, but it appears to lack a Load() method. Classes with Load() seem to use it in an entirely different context.

 

HighLogic.CurrentGame = GamePersistence.LoadGame()

HighLogic.CurrentGame.Start();

 

Two mods that use this to load a game on startup:

https://github.com/sirkut/DevHelper/blob/master/DevHelper/DevHelper.cs#L81-L110

https://github.com/malahx/QuickMods/blob/master/QuickStart/QS_MainMenu.cs#L81-L89

 

Links are provided for reference; straight out copying of the code requires respecting the license (All Rights Reserved for DevHelper and GPL3 for QuickStart).

The only difference between quicksaves and regular saves is that quicksaves return you to a particular ship, whereas regular saves return you to the main menu.  You can load a quicksave as a regular save; not sure about the reverse.

 

Link to comment
Share on other sites

On 7/8/2017 at 9:48 AM, 0111narwhalz said:

Thanks.

Is there some issue with PartModule.vessel and/or PartModule.part.vessel? Use of it seems to yield only NREs.

If so, how should I go about acquiring a vessel reference?

Those 2 are the basics of mods so if you get NRE something else is wrong. You should post a short version of your code.

Link to comment
Share on other sites

  • 3 weeks later...

Hi, how do I retrieve the physical time step length (in in-game time)? I know that there's a setting for "max physics delta-time per frame" and that there's Planetarium.fixedDeltaTime, but those seem to be fixed settings, whereas the physics update time depends on system performance.

I calculated my own value from the difference between Planetarium.GetUniversalTime() values in every FixedUpdate(), but I'm not sure that this is correct (or is it?)

Also, this value needs to stay accurate for Physics-timewarp, where the time step gets bigger if I'm not mistaken.

Link to comment
Share on other sites

2 hours ago, Kobymaru said:

Hi, how do I retrieve the physical time step length (in in-game time)? I know that there's a setting for "max physics delta-time per frame" and that there's Planetarium.fixedDeltaTime, but those seem to be fixed settings, whereas the physics update time depends on system performance

The KSP way is TimeWarp.fixedDeltaTime (and some other in TimeWarp). You can also check Unity native method since KSP use them outside of high time warp : Time

Link to comment
Share on other sites

I feel like I am doing something stupid, so I will post here rather than make an entire thread.

This method is basically supposed to just create a list of KSPFields and KSPEvents attached to a part, sort them by name, and then cache it for later:

        private void Start()
        {
            List<BaseField> myFieldList = new List<BaseField>();
            List<BaseEvent> myEventList = new List<BaseEvent>();
            foreach (BaseEvent e in part.Events)
            {
                myEventList.Add(e);
            }
            foreach (BaseField bf in part.Fields)
            {
                myFieldList.Add(bf);
            }
            if (part.Modules.Count > 0)
            {
                foreach (PartModule pm in part.Modules)
                {
                    if (pm.Fields.Count > 0)
                    {
                        foreach (BaseField bf in pm.Fields)
                        {
                            myFieldList.Add(bf);
                        }
                    }
                    if (pm.Events.Count() > 0)
                    {
                        foreach (BaseEvent e in pm.Events)
                        {
                            myEventList.Add(e);
                        }
                    }
                }
                sortedFields = myFieldList.OrderBy(baseField => baseField.guiName).ToList();
                sortedEvents = myEventList.OrderBy(baseEvent => baseEvent.guiName).ToList();
            }
        }

It works great, until I get to this bit:

                    if (pm.Events.Count() > 0)
                    {
                        foreach (BaseEvent e in pm.Events)
                        {
                            myEventList.Add(e);
                        }
                    }

For some reason, the act of adding a BaseEvent from a Part Module to a List causes KSP to duplicate all the buttons in the PAW. I can put anything else in the foreach loop, and the buttons are fine, but the moment I try and add them to a list, everything gets duplicated. I've commented out each line of code one by one, and thats the only line that causes the issue. I can also interact with the Fields in exactly the same way, with no duplication.

It doesn't make any sense to me, I am not interacting with the Events in any way, except examining the list.

So, my questions then: Am I missing something obvious, and if not, can I get around this somehow?

I've already tried:

- Turning the List<BaseEvent> into a BaseEventList

- Using AddRange to try to bypass examining the individual events

- Adding the PartModules and Events to a separate list, and examining that so I'm not interacting directly with PartModule.Events.

Edited by severedsolo
Link to comment
Share on other sites

KSP uses reflection to grab all of the events, so maybe it's catching your cached event list somehow. See what happens if you move the process out of start and instead wait a few frames or seconds. Maybe the base part's event loading process occurs after the part module process.

Link to comment
Share on other sites

2 minutes ago, DMagic said:

KSP uses reflection to grab all of the events, so maybe it's catching your cached event list somehow. See what happens if you move the process out of start and instead wait a few frames or seconds. Maybe the base part's event loading process occurs after the part module process.

I would suggest waiting at least 20 tics (ie:  1/3 sec) if you do, I've had issues with delayed actions and found that in some cases, it took this long before things got settled down

Link to comment
Share on other sites

17 minutes ago, linuxgurugamer said:

Have you tried removing the extra button from the PAW?

I have (I assume you mean by changing guiActive to false, unless there is another way to do this) - this just removes both buttons, so they seem to be linked to the same Event.

16 minutes ago, DMagic said:

KSP uses reflection to grab all of the events, so maybe it's catching your cached event list somehow. See what happens if you move the process out of start and instead wait a few frames or seconds. Maybe the base part's event loading process occurs after the part module process.

I did originally move it to FixedUpdate but that was probably not waiting long enough.

I actually just figured out a solution (as you always do just after you post for help!)

                       foreach (BaseEvent e in pm.Events)
                        {
                            int id = e.id;
                            myEventList.Add(pm.Events[id]);
                        }

Adding the Event by ID seems to bypass whatever the issue is. Probably what @DMagic said though, as my list would be referencing the original event, which would explain why both buttons disappear when removed.

Edited by severedsolo
Link to comment
Share on other sites

Hi,

I am trying to find out if KSP has a GameEvent or some kind of notification on part deployment (can be antenna, solar panel, landing gear etc) and ActionGroup (eg toggle antenna extend/retract). The closest one I can find is `GameEvents.onPartActionUIDismiss` which is almost suitable for me. But I am not finding an easy way to hook to ActionGroup activation.

The reason for this is to run some update codes on demand, rather than FixedUpdate() pulse to check and run if change is detected.

Thanks!

Edited by TaxiService
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...