Jump to content

creating a new KSPField at runtime with KSPApiExt support


Recommended Posts

Is it possible to add arbitrary number of integer ksp fields at runtime in partmodule ?

Closest example is at KSPAPIExtensions github page for a pre-defined chooser-type field, but i need one for int variable created at runtime.

I did also find some examples in github sources of Infernal Robotics, but they also apply only to predefined variables.

I did compile a variable with KSPField that has functions defined in its getter and setter, no errors were thrown.

I don't know how to formulate my question but this is what i need :

- variable is allocated at runtime as part of array or list

- variable needs to be displayed to user in UI (this is where KSPAPiExt helps)

Also, is KSP API Extensions at all capable of displaying values inside array or (preferably) List ?

 

Link to comment
Share on other sites

Short answer is no, you can't add KSPFields (or KSPActions/KSPEvents) at runtime.

Long answer is that it looks like even though KSP creates an instance of a part to make the ProtoParts database, it still makes a new instance of all the objects on the part when the part is created in the 3D gamespace.

I do have to preface this that I was trying to do this with a KSPAction, not a KSPField, and it was back in KSP 0.25, but I have no reason to think Squad's changed how spawning of parts works.

I was able to create a KSP action at runtime and add it to a part in the 3D gamespace. I was also able to add the action to a ProtoPart in the ProtoParts database.

However, nothing I did was able to make that action I added to the ProtoPart stay in existence when said part was placed in the 3D gamespace which made it useless for my purposes so I stopped experimenting there. That means I never investigated if a dynamically added KSPAction would persist through a save/load cycle.

The action not being present after the ProtoPart -> 3D gamespace transition is also where my conclusion that this process does not copy the ProtoPart, rather it spawns new instances of all the code objects attached to the ProtoPart and reads the data in fresh from the part.cfg values (including the ModuleManager modifications).

The best workaround I found was to make empty "template" KSPActions that I could then change the properties of dynamically at run time.

D.

Edited by Diazo
Link to comment
Share on other sites

Thanks for the reply, i too suspected something along the lines of reausable KSPField (via getter/setter). What did surprise me is that i found examples KSPEvents added at runtime (ModuleFuelTanks.cs @  github has one) and have myself confirmed it works, maybe it was just a typo on your part ?

Anyways, the only reason i did not test this is my module is grown too complex to just throw in a piece of code and test it without running everything else i wrote so far (i'd hate to comment out stuff at this point). Hmm i guess i'll make a small test-project to try this, though it looks it won't work.

What bugs me is that i can both add a KSPEvent at compile time and at runtime. I just tried to replicate this for KSPField but PartModule.Fields[] does not have Add() method. This makes for a difficult if not impossible solution.

Edited by fatcargo
Link to comment
Share on other sites

Hmm, I would argue that ModuleFuelTanks.cs is not "adding" an event, it's making a new event every time the part loads, so it's a different event each time.

I realize I am being nitpicky about this, but there is an important difference between the two.

Adding an event: For an event to qualify as being added, KSP would take over once it had been added and it would be added to the save/load. That means once you'd run your AddEvent code once, the event would be present on that part from then on, even across save/loads. (I required this for my purposes which is why I dropped it.) Tagging a method with KSPEvent in Visual Studio qualifies for this definition.

Recreating the event: This method requires the event to be recreated every time the part loads, you have to take care of save/loading data, making sure the event shows/hides when needed, etc. Depending on your use-case this might work for you I guess. This is what ModularFuelTanks.cs is using.

The lack of persistence is the big difference, one of the primary purposes of the KSPField is to provide easy persistence for mods and you won't have that without writing your own save/load code yourself.

D.

Edited by Diazo
Link to comment
Share on other sites

I won't comment on the actual issue but keep in mind that KSP API Extensions  is not supported anymore, and that the useful bit (the field editors)  are in stock.

Link to comment
Share on other sites

Thanks for the heads up ! I'm still trying to bypass compile-time-only KSPField and try to go for runtime version :) With the above info now i look differently at ModularFuelTanks - having a separate window both saves on complications of jamming everyting in part context menu and provides better logic/UI for its intended purpose.

Right now i'm stuck/fiddling with BaseField as constructor ie var bfi = new BaseField(KSPField, FieldInfo, object) and i'm clueless on the last "object" part. FieldInfo i do understand to some degree, though i'm not sure entirely how it connect to actual Field and how to create that at runtime (if needed) :) .

One more thing though : if i want to dump a variable with KSPField attribute (" attribute " is a proper c# naming ?) to a file or string, how do i do it ? Could i use this serialized data to make my own FieldInfo ?

I could drop the whole ksp field thing, but my module will then loose support for tweakables. Not fatal for functioning, just annoying.

Edited by fatcargo
typo
Link to comment
Share on other sites

BaseField expects to be backed by a real field on an object.  There's no way around that.  There are ways to dynamically build a type at runtime but I would not recommend going down that path.  You might try to look at other ways to tackle the problem you're trying to solve.

Link to comment
Share on other sites

OK i'll give this one more try : is there a way to add interactive controls to part right-click menu that are not bound to fields and can display values ? I ask because creating a special window just to manage tweakable values would break VAB/SPH immersion/workflow.

Link to comment
Share on other sites

1 hour ago, fatcargo said:

OK i'll give this one more try : is there a way to add interactive controls to part right-click menu that are not bound to fields and can display values ? I ask because creating a special window just to manage tweakable values would break VAB/SPH immersion/workflow.

Resources are the only thing I can think of.  But can we back up a step?  What information are you trying to display?  If you want to have tweakable fields, then presumably you want to have something that does something with those values, so how could that be created dynamically?

Link to comment
Share on other sites

I'll try to explain. To me, the overall topic is quite complicated : i'm trying to build fully configurable module that enables part creators to put multiple animation sequences in part.cfg in any combination they want with parameters.

So far, i have made most of code to run this and have tested snippets in separate steps. It all passed. Now i wanted to add ability for multi-animated part creators to allow end users (the actual players) to control how much of each animation is to be played.

Example : remember that player can tweak how much the ramps on cargo fuselages can open ? Well, its ok and simple because there is a predefined animation that has known amount of tweak paramaters (in this case only one). With my module, i do not know how many animations a part creator will make, so i don't know how many tweakables there will be. And it would be nice to have control of how much frames of each animation is going to play out in those multi-animated combos.

Again, thanks for spending time to help me, i really appreciate it. I'll be back here tomorrow.

Edited by fatcargo
Link to comment
Share on other sites

I thought of multiple modules for animations using existing plugins as well, but there is no control over their ordering to fire animations in desired sequence and no binding to same part right-click menu button (same event) to fire that sequence. Note that there may be any number of sequences with arbitrary ordering of animations.

Here is a piece of part.cfg i consider to be a central part of entire plugin, i hope this explains enough :

MODULE
{
 name = ChainedAnimationsModule

 CHAIN
 {
  name = Open Gate 1
  repeat = 0
  chainSequence = animation=GateShieldAnimation, command=once, speed=1, wait=1
  chainSequence = animation=Gate1Animation, command=once, speed=1
 }
 CHAIN
 {
  name = Open Gate Shield
  repeat = 0
  chainSequence = animation=GateShieldAnimation, command=once, speed=1, wait=1
 }

}

In above sample, a part has animations which need to be executed in certain order because they depend on each other. There are two actions a player can execute on that part. Both actions have their own sequence of animations.

A first action "Open Gate 1" has two animations because GateShieldAnimation needs to happen before Gate1Animation, otherwise the part will have collisions between its components and will be mechanically inconsistent.

A second action "Open Gate Shield" has only one animation in sequence because no other components of that part will collide if its animation runs, it does not depend on any other animation to run without apparent collisions.

Oh, and as a bonus you can see i have added "named arguments" that can be put inside as values giving extra control over how a particular animation gets executed within a sequence.

Edited by fatcargo
clenaup, code tags
Link to comment
Share on other sites

On 6/7/2016 at 4:36 PM, fatcargo said:

I don't know how to formulate my question but this is what i need :

- variable is allocated at runtime as part of array or list

- variable needs to be displayed to user in UI (this is where KSPAPiExt helps)

Also, is KSP API Extensions at all capable of displaying values inside array or (preferably) List ?

The easiest option is going to be just tossing 10-15 KSPFields in there and hiding the ones you aren't using. If you're dead-set on having your cake though, you can use your list as the backing field and then write a UI_Control that displays it to your liking.

 

Link to comment
Share on other sites

@fatcargo Okay, but (1) How far do you need to take it and (2) Does every animation need a deployment limit?  If you only ever needed two animations, it would be simple enough to write an animation module that handles two.  On the other hand if you don't need the deployment limits for every animation, you could put them in one module since you can dynamically create a BaseEvent using a lambda.

Another alternative is to have each animation on its own module and then have another module that ties them together and controls them.

Link to comment
Share on other sites

With the warning that I've never actually used it, have you looked at the ModuleAnimateGroup that's in stock?

From discussion way back when, this was added with the intent of handling parts with multiple animations on them.

D.

Link to comment
Share on other sites

Ok here we go :)

@xEvilReeperx : yes i already had that hard-code-then-hide idea, and it is very likely to end up in code.

@blowfish : as far as animations go, i'm trying to make my module as flexible as possible, which means i'll take it as far as i can.

@Diazo : yes i found posts about ModuleAnimationGroup and it aaalmost got it with triggering all modules that have  IAnimatedModule (see here) but it still has limit of two different animations with fixed "roles", to keep things reasonably simple.

@ All : Guys, thanks you made my day :) As i was exploring the subject of animations in KSP and Unity, i became aware of more and more options, and variations. Thus my apetite for module complexity has grown and has reached a saturation limit which i may cross after first release, when things settle down and people start responding (which is a whole different can of worms every modder opens when posting his/hers work :) ).

Edited by fatcargo
Link to comment
Share on other sites

@fatcargo My point is that if in practice you're only ever going to have three animations, trying to design for infinite animations is going to be way more complicated than it needs to be.  I've made mistakes like this in the past - you end up writing a lot of code that in practice you never actually use.

And did you consider what I said about having a separate module for linking the individual animation modules together?  I think that might give the flexibility you want without doing impossible things (i.e. adding fields at runtime).

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

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...