#Make a mod with a UITK GUI
1 messages · Page 2 of 1
It's not bad, and it's very clean and organized
The biggest "learning curve" to them is lambdas and how to use them properly
if you don use lambdas you'll end up with 1 method per textfield xD
Is that what we're doing? Using lambdas?
yes, when you do something like
() => WhatYouWantToDoHere
you're doing a lamda expression
the way it works is
Arguments of the method => body of the method
its a short way do create a method (tho you have no way to reference these lamda expressions)
so they are mostly used for methods that will only be used by 1 thing
_container.Q<Button>("LargeTimeDecreaseButton").clicked += () => IncrementTime(-largeStepTime);
_container.Q<Button>("SmallTimeDecreaseButton").clicked += () => IncrementTime(-smallStepTime);
_container.Q<Button>("SmallTimeIncreaseButton").clicked += () => IncrementTime(smallStepTime);
_container.Q<Button>("LargeTimeIncreaseButton").clicked += () => IncrementTime(largeStepTime);
_container.Q<Button>("DecreaseOrbitButton").clicked += () => IncrementOrbit(-1);
_container.Q<Button>("IncreaseOrbitButton").clicked += () => IncrementOrbit(1);```
Did the same for orbits and time
Action<string, int, float> lamba = (name, age, height) => Debug.Log($"Person:{name}\nAge:{age}\nHeight:{height}m");
//its the same as
void DebugPerson(string name, int age, float height)
{
Debug.Log($"Person:{name}\nAge:{age}\nHeight:{height}m");
}
//and you can use just (name, age, height) => Debug.Log($"Person:{name}\nAge:{age}\nHeight:{height}m") wheverever you want
i'll admit that it took me a couple of months to fully internalize the lambda expressions as they are quite finicky sometimes, but here's the docs for them https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions
specially when you start passing functions as lambdas
I've seen them used in the optimization solvers in the old MechJeb code. I never did understand them. I should take some time to.
But, in the meantime, another question!
So some of these GUI things should only be shown situationally. For example the SnapTo for ANt and DNt are only shown if you have a taget and it's orbiting the same reference body you are.
Where can I check that and set the visibility/accessibility of the UI elements?
easy, VisualElement.style.display = DisplayStyle.None;
but take into consideration that this will also make it not be calculated to the elements positions
what does this mean
Those are at the end of the list
If they come and go together and nothing follows them on that row
both labels are on the edges, if i make the display none for the middle visual element
yeah then it wont change anything
but its a good thing to take into consideration when doing these things, if you dont wish for this to happen you can use VisualElement.style.Visibility = Visibility.Hidden
I'm guess ing this next bit might go in Update?
also dont forget to set them back on when the right ocasion comes!
I'm thinking like IMGUI, aren't I>
well, theres no need for it tbh, you could just subscribe to the game's message that corresponds to that state
?
no you deffinetly could do it on update
its just more performant to not do it
but depending on what you do wont have an noticeable impact on the game
It might be tricky with the game's event messages. I could check any time the target changes, but what if you're outside the Mun's SOI headed to the Mun, and some satellite is your target. Maybe your target doesn't change but your reference body changes...Hmmm....
So maybe check any time either changes...
Then the only gotcha is if the other thing is coming to you, which is not likely untilwe've got MP
Yeah, so I would want to subscribe to reference body change and target change, and in either case test to see if the targe is at the same reference body
but either way, if you feel like the game's message wont do justice go for the Update! the game's messages are a bit buggy sometimes so might be more consistent
its trully up to you!
only thing you have to take into consideration is not doing too many expensive things on update
I think I'll go wtih Update for now as it's brute force and going to work, then explore the event solution as being more elegant
sounds good!
Always try brute force first, that way if you mess it up you've broken it.
Oh,,, wait...
Don't do that in the kitchen...
or the lab...
xD or do it! thats how u discover new flavors or explosions, or explosions of flavors
LOL
sounds good, I've scetechd out this
// Test if there is a target
// test if the target is at the same reference body as the active vessel
// If both are true, then _container.Q<Button>("SnapToANtButton").style.display = DisplayStyle.None
oh dont
remember
Q<> is a query
and queries are expensive
its better to store the button as variable if you're gonna do things to it more than once
Button SnapToANtButton;
but yeah the logic behind it is right!
OK, how do I set the button variable to point to the button?
btw we're okay with doing Q<> on the InitializeElements because we're only doing it once
you've been doing that this whole time 😉
SnapToANtButton = _container.Q<Button>("SnapToANtButton");
the difference is that you weren't saving the variable after, you were using it right away
oh btw, UITK has a way to make an element disabled but not hide it
looks something like this
most of the times is prettier to just hide it, but maybe you're looking for something like this 
btw the difference between saving the Button/TextField/Label or whatnot and using it right away is minimal, will most just save a couple kb (or mb depending on the class size) of RAM
but i like to always propagate good code practices, thats why i told you to do it that way
Yeah, for my purposes in this case I'd like to hide it entirely rather than graying it out
then do the DisplayStyle.None
Hey I'm getting an issue with this
private void CenterWindow(GeometryChangedEvent evt)
{
var root = _container.hierarchy[0];
root.transform.position = new Vector3(
(Screen.width - root.boundingBox.width) / 2,
(Screen.height - root.boundingBox.height) / 2);
_container.style.visibility = Visibility.Visible;
_container.UnregisterCallback<GeometryChangedEvent>(CenterWindow);
}```
It says there is no boundingBox
well thats wierd
theres localBound
tho its an easy fix
and worldbound
i didnt realize this earlier but munix made an helper method for that
can you send me a print of where ur calling CenterWindow?
public void SetupDocument()
{
var document = GetComponent<UIDocument>();
if (document.TryGetComponent<DocumentLocalization>(out var localization))
{
localization.Localize();
}
else
{
document.EnableLocalization();
}
_container = document.rootVisualElement;
_container.style.visibility = Visibility.Hidden;
_container.RegisterCallback<GeometryChangedEvent>(CenterWindow);
SnapToANtButton = _container.Q<Button>("SnapToANtButton");
SnapToDNtButton = _container.Q<Button>("SnapToDNtButton");
}```
once here
and once also here
private void CenterWindow(GeometryChangedEvent evt)
{
var root = _container.hierarchy[0];
root.transform.position = new Vector3(
(Screen.width - root.boundingBox.width) / 2,
(Screen.height - root.boundingBox.height) / 2);
_container.style.visibility = Visibility.Visible;
_container.UnregisterCallback<GeometryChangedEvent>(CenterWindow);
}```
It seems like it's recursive?
CenterWindow calls CenterWindow?
on the 2dn one u are Unregistering it
OIC
basically you're saying, call this, and once you call it, never call it again
tho you can delete the CenterWindow method (all of it)
done
and replace
_container = document.rootVisualElement;
_container.style.visibility = Visibility.Hidden;
_container.RegisterCallback<GeometryChangedEvent>(CenterWindow);
with
_container = document.rootVisualElement;
_container[0].CenterByDefault();
_container.style.display = DisplayStyle.None;
just edited it btw!
talk to me!
I dropped in what I have from the Toggle method I had fore IMGUI.
private void SetEnabled(bool newState)
{
interfaceEnabled = toggle;
GameObject.Find(ToolbarFlightButtonID)?.GetComponent<UIValue_WriteBool_Toggle>()?.SetValue(interfaceEnabled);
}```
can you show me how its looking?
So, wrong
easy fix!
you just hid your Window with this on the code that you just made
_container.style.display = DisplayStyle.None;
so just
_container.style.display = DisplayStyle.Flex;
Yep
tho you'll need to do some "conversion"
so maybe put a if(newState) DisplayStyle.Flex
else
DisplayStyle.None
also you probably dont need interfaceEnabled, but some people (munix ie) like to have a variable that you can access to know if your ui is open
if (newState) _container.style.display = DisplayStyle.Flex;
else _container.style.display = DisplayStyle.None;```
I thik I only ever used that variable in the OnGui part of the mod. I could check easily enough
most probably yeah, but again if you want to keep it feel free to!
bool variable only ocuppy 1 byte of RAM (each) so those are your smallest (literally) problems
on the other hand, saving IE a Button (visual element) probably take 10kb (or more) each since they have a LOT of variables inside them
They occupie 1 whole byte? That's 7/8ths waisted space!
xD i'm probably wrong on that tbh, gotta get my variable-to-size knowledge checked
So, I still need to learn how to set the values for things.
oh seems like it is one byte!
the labels you mean?
Those should be updated frequently in some cases, and only when things change in others
Yes, the labels I'm using to dispaly values
those are easy tho
but Label i do recommend saving as a variable
since you'll access them a lot
Basically its as easy as it can get
That makes sense.
Label.text = "Text";
Label!
the same Control/Container name that you have on the UIBuilder corresponds to the class (99% of the time)
This is funny, vs thinks these varaibales can be removed since nothing ever reads them
yet xD
well maybe you're not using them no?
do a RightClick>Find All References
or Shift+F12 if your text-bar-thingie is on them
if you are using them there then just disregard vs being dummy
Oh yeah, that code is commented out
That's only until I track down what I need to test before setting them
sounds good!
btw, for now, for the "select Maneuver node 0 of 1" do it the normal way
in a couple of days i'll release the custom controls
Sure, that's easy.
it will be the easiest change you'll ever do! tho i'd rather that you have them in the right way (via Uitk For KSP2) than having to change it later
I'm thinking that initially for the labels I'll just set them all in Update. I can clean that up later if I like, but that will work
sure, it works!
So I'll set them to their respective labels in SetupDocument, then set their values in Update
I'm thinking right now this mod has both GUI's in it, or all of one and part of the new one with some stub functions
xD i mean you did port most of the IMGUI code into it
what parts dont work?
Look! Two copies!
but im glad it does! sort of xD
Which reminds me, there's the whole other mode it should go into when there are no nodes
you're probably instantiating it wrong then, when are you doing SetEnabled?
Oh
wait, you have 2, the other is IMGUI
makes sense
And here they are with a node
Everything on the right is just dummy data of course
you can make the font smaller if you wish!
I can see I may need to do some more work on the Unity gui, but it's coming along nicely
yeah, its coming along great!
much more readable with this font
also the colors are a lot more vivid
i would maybe make the Header font bigger tho
I'm curious how I can pick a different font. When I tried in Unity it dodn't wnat to let me - I think maybe only only had the one loaded?
i think you can do it by makin an uss class targeting .unity-text-element
and setting the font there
The text inputs look a bit screwy too.
yeah, thats the padding remember? or margin i trully cant remember
Yeah, but I thoguht we fixed that
check in unity!
you migh need to repack the asset bundle then
But screwy in the game
Maybe so, I'll do that when I mess some more with the fonts.
That said, the on hover and pressed buttons look nice
It works in several senses - I need to connect some stuff up and then make it a bit prettier with font changes, etc.
🙏
yeah i mean from now on you can do pretty much whatever you want on the uss
and your ui will work the same
One question though. What about the mode where there are no nodes yet and all it should do is give you an option to make a node.
That's almost like tabs
thats easy
really?
put everything that you want to be hidden on no nodes under the same visual element
and style.display = None
and then on the thing that you want to show
style.display = Flex
OK, I get it
and then on code do that verification/apply these
tho we might need to tweak a couple things so that the window auto-resizes
That makes sense for how it will work in the game. Laying it out in Unity Editor may look odd - like the whole GUI is way taller
yeah it does! its a bit odd indeed, but remember that you're working very zoomed in in the Unity Editor
its a common problem for UX/UI Designers, most of the times you are always very close to the ui and you dont see the bigger picture if you compare the 100% view on the uintyEditor with the game's it should be 1:1
I'm not following quite yet. What I think this means (and I suspect I'm wrong) is that I have a visual element with some text and a button in it for no nodes, and then below that all the stuff I've got now that's below the blue line , and that's al captured in another element. Then in the game I can swap one on and the other off, but in the editor I'll see them both as if they're both one.
That's what I mean buy it looking taller in the editor
are u in the editor already?
Yes
the way you emulate that in the editor is by setting display to none (as you do in code)
Oh!
the one that's marked as edited
everything that you access in code you can access here and viceversa!
Shadow ie built his whole windows only with code
So it would be in the Hierarchy tree, but it only shows in the editor if I want to make it show
I've got it!
This makes sense and it will be easy
exactly! and you can also make the "default" state like that
The only thing that will be longer is the hierarchy tree!
leave the default as displayed and the other as not displayed
Exactly xD
you'll use this same trick for the Tabs in FP
I'm juessing I doe basically the same for FP with the tabs, except I have to figure out the dynamic buttons, but they'll be basically the same
but you'll need to make a TabController to make things easier for you (or not if you like to suffer)
yup xD
I think I've got a tab controller now, but it would need to be refactored into this new approach.
But the logic is there
shouldnt be hard
see, FP wont also be that difficult
the most time consuming part is building the ui in the UI Builder
but thats a good thing because it allows you for a LOT of customization
OK, cool. I'm gonna go play with this. I'm closer than I thought, but there's still quite a bit of work to do just migrating stuff over.
yeah, it would have been good to have UITK since the start to avoid migrating
we did have it in 0.4 but it wasn't nearly production ready
I wish we'd had this at the start!
np! Im here to help! I want the best modding community possible
I think we've got a pretty amazing one!
Indeed! hope it keeps like this as we grow
You know what? The doomers that are so down on the game should try modding. It's a blast!
Seriously!
it is right? you literally do anything you want with the game
This is how I play the game now!
xD this has been my KSP life for the last 2 and a half months
heheh me too!
taking into consideration that the game launched 3 months ago...
It's nuts!
also its very good to see people using our mods, cuz we do spend quite some time on them
I remeber when it came out and I was just hoping somone would eventually start modding it...
I' was shocked how quickly mods appeared!
and instead you did it xD
hehehe yes!
but others first, they broke the ice
Once I reallized it was possible it was like Pandora's box was open
exactly thats what i love about coding
and modding as well
you can lquite literally turn the game inside out if you want
look at RSS RO ie, its almost a new game
neither did i, i dont really like the "simulate real life" i like the arcady aspect of ksp
shoot!
When these new extendable ones come out, can we mod them so that they have a degraded operating mode when not extended?
I want to be able to use them on landers for low grav like Mun and Minmus
yes im pretty sure we can
I like the extended bell in space, but how can you land with that?
tho it will probably look very odd since the plume will be coming from its original position
but nothing that #1094320887228006450 can't fix
That would be cool! I like articulating parts - they're fun to use
my usual design for mid game landers is to have the engines on the sides instead of below, so for me they work
tho, putting a craft that wide in space is a bit difficult
Side mount works OK, but I recall it being wobbly even in KSP1
not with one of my 150 mods (i just dont know which one did it xD)
See, I always go to EPL as quick as I can, then I'm building them on Minmus
yeah same, tho lately i've been playing a more "accurate" way, so orbit, go to the mun, minmus create a space station
its a bit more challenging
which makes the game a more fun and makes you think more about your rockets than just re-do what you did for the last 10 saves
I found that lugging stuff back up to orbit from Mun or Minmus was tedious. Maybe I did it wrong
But otherwise I love an orbital space dock!
well you can just wait on the surface of the moon, wait for your craft to be pointing Kerbin and full throttle xD
Oh I was thinking put the station in Munar orbit
the deltaV to circularize on these small moons is almost not worth it (if you're trying to escape their SOI)
You've have to land, collect resources and make more fuel, haul that back up to orbit, rinse and repeat until you had enough, then you could finally make somehting cool in orbit
orrr
you launch a Orange Tank with a probe core xD
launch it from kerbin, you'll wast only like 5% of it to get to the moon's orbit
tho i usually do this when i'm launching the "fuel tanks station module"
which reminds me that i hve to work on the colonization mod
This makes me wanna play again, but I also want to see if I can get my mods out in UITK form before 0.1.3 hits
Yes! We need more parts!
I want to build colonies!
Everyone will want one!
same!
Tho fisrt i want to finish LFO Editor so anyone can change the game's plumes
1 per planet 
i mean waterfall is a BIG part of KSP1 modding, so nothing more fair than to focus on that first
Green for Jool...
oh no xD you'll loose your colony like that
Why, is the green radioactive?
tho it will be fun to see what people will do with the colors
Hwo will you see your colony on the Red Planet, with aRed colony?
xD
Not a red colony, a red plume!
OH xD
With your plume editor
xD
the goal for LFO
is to be able to add any effect to any GameObject in game
ie someone wanted to make geisers on IKe
I'm gonna make me an Epstein Drive!
with the current LFO its pretty much possible, but we have no editor yet
Do whatever your imagination pleases!
i also have a shader ready that shows Tank frost when the tanks are full
We'll get those or something like them eventually for interplanetary I suppose
That will be fun!
yes! Cvusmo is already making a particle accelerator engine iirc #1112981422836301844
in not sure xD but he did mention making the plume a laser
Did you ever read Project Hail Marry?
Oh it's sooo good! Andy Weir - the guy who wrote The Martian
I think they optioned it as a movie too
ohh that one i know!
It's got a really cool engine in it, but I wouldn't wnat to spoil it for you
Great book!
Amazon.com: project hail mary
xD you can make that engine, i promise i'll read the book before you make it xD
saved!
They're making a movie with Ryan Gosling apparently
Yes, he is!
BladeRunner is one of my fav movies!
The new one?
yup that he's the lead actor
It is good! I think they did a great job with that
yeah, i do like tho dissecate and analyze every movie that i watch and it was very nice to see their scenes
all are very grandious and using colors to drive your attention
Yes! The attention to detail was amazing!
They captured such a dark and grity place so well
i love those dark movies tbh, nightcrawler, Sambojcow Room, Run all movies that i adore!
and all a very dark aesthetic
Those are dark! I've not seen them, but Sambojcow Room sounds very dark!
well it translates to Suicide room xD
Yes, I know! I googled it...
it won the Indie Movie of the year iirc
I wouldn't have none otherwise, but yeah
basically talks about a teenaeer that has everything but was not happy with his life, found a group online that did ||self-harm|| and wanted to have some adventure in his life, then there was a girl.
wont spoil it, but its not a romance xD
but its not a movie that encourages/beautifies it, it actually only shows the ugly part, and in a very dark and realistic way
TLDR; Sad rich teenager get involved in bad things
amazing acting from both lead actors, and every other actor as well
go for it!
How's this look
if (ManeuverNodeControllerMod.Instance.currentTarget != null)
{
if (ManeuverNodeControllerMod.Instance.currentTarget.Orbit.referenceBody == MNCUtility.activeVessel.Orbit.referenceBody)
{
SnapToANtButton.style.display = DisplayStyle.Flex;
SnapToDNtButton.style.display = DisplayStyle.Flex
}
else
{
SnapToANtButton.style.display = DisplayStyle.None;
SnapToDNtButton.style.display = DisplayStyle.None
}
}```
IS Flex the right thing there to turn it on?
OK then, I'm making progress!
I'll look into Extensions, and PR them to UITK for KSP2 so that we can do something like
SnapToANtButton.Display(false)
this for any visual element
Unity Editor Q, is there an easy way to grab abunch of stuff and group it in an container?
well you can shift select things on the hierarchy
tho
unity has a wierd thing
it seems to copy/paste things reversed
so your 1st element will be the last
Tho!
maybe you can just add a visual element about the root one?
i dont know if it will work tho
I've noticed it can be a bit difficult to drag things around and get them where you want. Much easier to drag them where you don't wnat them
but now you know that the project's hierarchy matters xD
Yes it does
xD it really is! thats the downsides of using an old version of UITK
but its the latest we have for this unity version
i think that maybe we can in the future update UITK's version to something like 2021 or 2022 (and a way that wont break mods)
but lets keep things like this for now since it works and works well most of the times
I'm just happy to have what we've got!
oh btw
you can have uxml files inside uxml files
i dont know if you should try xD because you have a window with a LOT of things in
but if you right click in hierarchy you can create a template
that will create a new .uxml file with that contents
Interesting
this is useful ie when you have a lot of modules that add to each other(or that can be toggled)
not so much for your cas,e but you can still use it if you so desire
probably for FP you can take a shot at it
each tab being its own template
That would make a lot of sense I suspect. I think I'll want to explore that!
great! when u come to it i'll be here to help you!
oh btw, you were asking about showing things compactely in UITK like ie your current window
the main thing for this is lower font size, but with that comes less readablity
i always found IMGUI ui hard to read since the font is 1 pixel wide
but you can deffinetly achieve the same on UITK and with the text being renderered in a better way than IMGUI (this is all backend stuff)
also the fact that you can choose whatever font you want also will help a lot, there's fonts made to be readable when small
Hey @dusty berry I took a shot at the top level visual container thing and I was able to make something I thought would work in Unity, but I'm getting errors when I try to call it. In Unity I've got this structure
you mean your code in game is giving you errors?
In my code I'm doing this
private void Update()
{
List<ManeuverNodeData> nodes = NodeManagerPlugin.Instance.Nodes;
// If we've got nodes...
if (nodes.Count > 0)
{
HasNodesGroup.style.display = DisplayStyle.Flex;
NoNodesGroup.style.display = DisplayStyle.None;
...
}
else
{
HasNodesGroup.style.display = DisplayStyle.None;
NoNodesGroup.style.display = DisplayStyle.Flex;
}
}```
yes
Also the GUI comes up before I've loaded a game
Update runs sooner than the window is created (i think)
you could add something like a
private bool initialized = false;
//On the end of the InitializeElements
intialized = true;
//on Update
if(initialized)
tho wait
it can be that its not finding your groups
can you send me the code where u assign those 2 variables?
public void InitializeElements()
{
// Set up variables to be able to access UITK GUI panel groups quickly (Queries are expensive)
NoNodesGroup = _container.Q<VisualElement>("NoNodesGroup");
HasNodesGroup = _container.Q<VisualElement>("HasNodesGroup");```
And defined here
public class MncUiController : KerbalMonoBehaviour
{
private VisualElement _container;
private float largeStepDv;
private float smallStepDv;
private float absDvValue;
private float largeStepTime;
private float smallStepTime;
VisualElement NoNodesGroup;
VisualElement HasNodesGroup;```
okok a sec
The initialized code stopped the errors, but not it never updates even when it should
are you setting intialized = true?
Yes, at the very end of Initialized
_container.Q<Button>("DecreaseOrbitButton").clicked += () => IncrementOrbit(-1);
_container.Q<Button>("IncreaseOrbitButton").clicked += () => IncrementOrbit(1);
initialized = true;
}```
then its not getting to there
And I check it like this
private void Update()
{
if (!initialized) return;
I'll double check now.
np if you want i can take a look at the ksp2 log too
also
well lets see first if there's any significant erorr
In KSP log the only places error shows up are here
[ERR 07:54:04.196] AssetProvider unable to find assets with label 'language_source'.
UnityEngine.Debug:LogError (object)
KSP.Assets.AssetProvider/<>c__DisplayClass20_01<I2.Loc.LanguageSourceAsset>:<LoadByLabel>b__0 (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1<System.Collections.Generic.IList1<I2.Loc.LanguageSourceAsset>>) DelegateList1<UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1<System.Collections.Generic.IList1<I2.Loc.LanguageSourceAsset>>>:Invoke (UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle1<System.Collections.Generic.IList1<I2.Loc.LanguageSourceAsset>>)
UnityEngine.ResourceManagement.ResourceManager:Update (single)
MonoBehaviourCallbackHooks:Update ()
[LOG 07:54:04.200] [System] Loading localizations from Addressables completed in 0.0109s.
...
[ERR 07:54:04.827] [System]
UnityEngine.Debug:LogError (object)
KSP.Logging.KspLog:Error (KSP.Logging.LogFilter,object)
KSP.Logging.GlobalLog:Error (KSP.Logging.LogFilter,object)
KSP.Game.Flow.SequentialFlow:OnActionReject (KSP.Game.Flow.FlowAction,string)
KSP.Game.Flow.FlowAction/<>c__DisplayClass13_0:<Do>b__1 (string)
SpaceWarp.Patching.LoadingActions.InitializeModAction:DoAction (System.Action,System.Action1<string>) KSP.Game.Flow.FlowAction:Do (System.Action1<KSP.Game.Flow.FlowAction>,System.Action`2<KSP.Game.Flow.FlowAction, string>)
KSP.Game.Flow.SequentialFlow:NextFlowAction ()
KSP.Game.Flow.SequentialFlow:Update ()
[LOG 07:54:04.901] [System] Initialization for plugin Cheat Menu completed in 0.0636s.
There are errors in the BIE log, but the are mostly like this
[Error :CustomizableUI.Utility] Error trying to load data. Full error:
System.NullReferenceException: Object reference not set to an instance of an object
at CustomizableUI.Utility.LoadData () [0x0001b] in <4733a2dc16f74f4baf3c58b1b070a514>:0
[Error :CustomizableUI.Manager] Error initializating top level groups.
System.NullReferenceException: Object reference not set to an instance of an object
at CustomizableUI.TopLevelGroup..ctor (System.String groupName, System.Int32 transformIndex) [0x0002c] in <4733a2dc16f74f4baf3c58b1b070a514>:0
at CustomizableUI.GameView..ctor () [0x00000] in <4733a2dc16f74f4baf3c58b1b070a514>:0
at CustomizableUI.Manager.CreateGroups () [0x00006] in <4733a2dc16f74f4baf3c58b1b070a514>:0
at CustomizableUI.Manager.Initialize () [0x00000] in <4733a2dc16f74f4baf3c58b1b070a514>:0
[Error :CustomizableUI.Utility] Error trying to load data. Full error:
System.NullReferenceException: Object reference not set to an instance of an object
at CustomizableUI.Utility.LoadData () [0x0001b] in <4733a2dc16f74f4baf3c58b1b070a514>:0
I don't see any errors actually from MNC in the BIE log
FP reports that MNC is loaded and BIE seems to be OK with it
[Info :Addressables Loader] Loading addressables for Maneuver Node Controller
[Info :Addressables Loader] Did not find addressables for Maneuver Node Controller
[Info :Space Warp] Attempting to load localizations from C:\Kerbal Space Program 2 Debug\BepInEx\plugins\maneuver_node_controller\localizations
[Info :Space Warp] C:\Kerbal Space Program 2 Debug\BepInEx\plugins\maneuver_node_controller\localizations does not exist, not loading localizations.
yeah no errors for MNC
then i think that this might be it
if not then munix can help
swConsole.gameObject.Persist();
to your VisualTreeAsset
i dont recall the name tho
its that thing you did Window.Create() on
Looking for that now. BTW, the close button doesn't work - has no effect when you click it
private void SetEnabled(bool newState)
{
if (newState) _container.style.display = DisplayStyle.Flex;
else _container.style.display = DisplayStyle.None;
//interfaceEnabled = newState;
//GameObject.Find(ToolbarFlightButtonID)?.GetComponent<UIValue_WriteBool_Toggle>()?.SetValue(interfaceEnabled);
}```
is it part of this?
public void SetupDocument()
{
var document = GetComponent<UIDocument>();
if (document.TryGetComponent<DocumentLocalization>(out var localization))
{
localization.Localize();
}
else
{
document.EnableLocalization();
}
_container = document.rootVisualElement;
_container[0].CenterByDefault();
_container.style.display = DisplayStyle.None;
}```
I'm not finding Window.Create()
pretty much all the code is either in Update, or in InitializeElements
I added this to the end of InitializeElements
initialized = true;
ManeuverNodeControllerMod.Logger.LogInfo($"UITK GUI Initialized. initilized set to {initialized}");
}```
And that text is not showing up in my BIE log
At least not when I quick at the main menu before entering a game
If it's crashing inside there then there ought to be something in KSP2.log, right?
sorry for being a bit off!
this is because you're having some problem on the gameObject, i suspect that its getting destroyed (Unity auto destroys all game objects on the scene, unless you tell them not to)
None of the logging messages I've put in are coming out. At least not in the BIE log
I need to get going (work), but I'll be back to this later tonight. Thanks!
One final clue, then I'm off... I tried this in Update
private void Update()
{
if (!initialized)
{
InitializeElements();
return;
}```
And I got a spaming of this in the BIE log
`
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False`
Which means it's one of two lines shown below that's causing the issue
public void InitializeElements()
{
ManeuverNodeControllerMod.Logger.LogInfo($"Starting UITK GUI Initialization. initialized is set to {initialized}");
// Set up variables to be able to access UITK GUI panel groups quickly (Queries are expensive)
NoNodesGroup = _container.Q<VisualElement>("NoNodesGroup");
HasNodesGroup = _container.Q<VisualElement>("HasNodesGroup");
ManeuverNodeControllerMod.Logger.LogInfo($"Panel groups initialized. initialized is set to {initialized}");```
Since it never makes it to the second log output line
huh
btw im assuming
you've build a new AssetBundle
with the new names right?
and didnt change
any of the folder of file names
Yes, but I can build it again.
no need
meaning what?
it seems like its not finding what ur looking for
I agree. that seems likely
if you change any file name that ur using on your assetbundle, you need to update it on the code
wait
I'm now getting this in KSP2.log
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
ArgumentNullException: Value cannot be null.
Parameter name: e
at UnityEngine.UIElements.UQueryExtensions.Q (UnityEngine.UIElements.VisualElement e, System.String name, System.String className) [0x00003] in <b04b98aef47f4637b950c1b3349ee421>:0
at UnityEngine.UIElements.UQueryExtensions.Q[T] (UnityEngine.UIElements.VisualElement e, System.String name, System.String className) [0x0001b] in <b04b98aef47f4637b950c1b3349ee421>:0
at ManeuverNodeController.MncUiController.InitializeElements () [0x00021] in C:\KSP2Mods\ManeuverNodeController\ManeuverNodeControllerProject\ManeuverNodeControllerPlugin.cs:1477
at ManeuverNodeController.MncUiController.Update () [0x0000f] in C:\KSP2Mods\ManeuverNodeController\ManeuverNodeControllerProject\ManeuverNodeControllerPlugin.cs:1276
NoNodesGroup = _container.Q<VisualElement>("NoNodesGroup");
The first suspect naturally
And I just now re-built the bundle
After making sure I'd saved the Unity project (meaning closed, clicked yes to save, reopened, built)
Is VisualElement the wrong type?
It can't be, I can see on the hierarchy that's what it is
And the inspector
I gotta head to work. I'm sure this is something simple. We know where it's bombing now.
its the right type!
whenever you can, can you send me the uxml?
it could be that in the uxml the name is different
and the uxml is what dictates most of this
@shadow tree btw whenever @marble shale is back is you could help him with this 
i THINK that's just addin Persist() on his gameObject but im not sure
I'm not sure, I mean I think all that does is prevent the object from being destroyed when you load a game and then quit to main menu?
yeah and i think thats whast happening to him
and .Persist() is not an actual thing anywhere else, it's an internal extension method in SpaceWarp
using UnityEngine;
namespace SpaceWarp.InternalUtilities;
internal static class InternalExtensions
{
internal static void Persist(this UnityObject obj)
{
UnityObject.DontDestroyOnLoad(obj);
obj.hideFlags |= HideFlags.HideAndDontSave;
}
}
oh ok hmm
not a good idea to make it public but hmm
the thing is, this might actually be a problem for UITK windows
I can at least add it to UitkForKsp2 and call it by default on all the gameobjects I create
bcuz the controller cuild be getting destroyed when loading the game
sure that'd work
first lets see if thats actually the problem
it shouldn't happen
why?
before we added it in SpaceWarp, it would mean that no mods would ever load
but they did
they just got destroyed only after you were already in-game and then left back to the main menu
well dont destroy on load happens as you said on Load of a game
and going back to the menu
cuz thats the only times it changes scenes
maybe his is somehow getting destroyed when loading a save??
lets see
you can just try to remove the call from the mod list or console and see what it does
but I'm off to bed
and tomorrow I need to actually work, I have been slacking off for like two full weeks now
and I have a deadline on Thursday for a thing I haven't even started yet
lmao
Alright I can explain
DontDestroyOnLoad gets culled after going from game back to the menu unless the object has a tag called game manager or has hide and dont save set
oh okok yeah makes sense
And it needs to be in DDOL because otherwise itd definitely be culled
yeah since its a child of the current scene
every child of the current scene gets destroyed
makes sense thx 
Hmm ok a sec
Looks like the uxml has the correct names: <ui:VisualElement name="NoNodesGroup" style="display: none;"> and <ui:VisualElement name="HasNodesGroup">
When I comment out the lines that were causing a problem, I just get a new problem right after that on lines there were not a problem before. I'm suspecting now there's an issue with _container
public void InitializeElements()
{
ManeuverNodeControllerMod.Logger.LogInfo($"Starting UITK GUI Initialization. initialized is set to {initialized}");
// Set up variables to be able to access UITK GUI panel groups quickly (Queries are expensive)
//NoNodesGroup = _container.Q<VisualElement>("NoNodesGroup");
//HasNodesGroup = _container.Q<VisualElement>("HasNodesGroup");
ManeuverNodeControllerMod.Logger.LogInfo($"Panel groups initialized. initialized is set to {initialized}");
// Set up variables to be able to access UITK GUI Buttons quickly (Queries are expensive)
SnapToANtButton = _container.Q<Button>("SnapToANtButton");
SnapToDNtButton = _container.Q<Button>("SnapToDNtButton");
Nowhere
public void SetupDocument()
{
var document = GetComponent<UIDocument>();
if (document.TryGetComponent<DocumentLocalization>(out var localization))
{
localization.Localize();
}
else
{
document.EnableLocalization();
}
_container = document.rootVisualElement;
_container[0].CenterByDefault();
_container.style.display = DisplayStyle.None;
}```
private void Start()
{
SetupDocument();
}```
When I search for this string "window.create()" I don't find it anywhere in the file, and it's a one-file mod I believe
Remember where u put the bundle’s path?
Nvm, it's not a one-file mod
xD its ok
however widening the sear to the whole solution still does not find it
public override void OnInitialized()
{
base.OnInitialized();
MNCSettings.Init(SettingsPath);
Instance = this;
game = GameManager.Instance.Game;
Logger = base.Logger;
var mncUxml = AssetManager.GetAsset<VisualTreeAsset>($"{Info.Metadata.GUID}/mnc_ui/mnc_ui.uxml");
var mncWindow = Window.CreateFromUxml(mncUxml, "Maneuver Node Controller Main Window", transform, true);
mncWindow.gameObject.AddComponent<MncUiController>();
GameManager.Instance.Game.Messages.Subscribe<ManeuverRemovedMessage>(msg =>
{
var message = (ManeuverRemovedMessage)msg;
OnManeuverRemovedMessage(message);
});
// Setup the list of input field names associated with TextField GUI inputs
inputFields.Add("Prograde ∆v");
inputFields.Add("Normal ∆v");
inputFields.Add("Radial ∆v");
inputFields.Add("Absolute ∆v");
inputFields.Add("Small Step ∆v");
inputFields.Add("Large Step ∆v");
inputFields.Add("Small Time Step");
inputFields.Add("Large Time Step");
Logger.LogInfo("Loaded");
if (loaded)
{
Destroy(this);
}
loaded = true;
gameObject.hideFlags = HideFlags.HideAndDontSave;
DontDestroyOnLoad(gameObject);
// _spaceWarpUISkin = Skins.ConsoleSkin;
// horizontalDivider.fixedHeight = 2;
// horizontalDivider.margin = new RectOffset(0, 0, 4, 4);
// Register Flight AppBar button
Appbar.RegisterAppButton(
"Maneuver Node Cont.",
ToolbarFlightButtonID,
AssetManager.GetAsset<Texture2D>($"{Info.Metadata.GUID}/images/icon.png"),
ToggleButton);
// Register all Harmony patches in the project
Harmony.CreateAndPatchAll(typeof(ManeuverNodeControllerMod).Assembly);
}```
Is this a problem? The path looks like it may be missing a part
So the mnc_ui.uxml is not in ../mnc_ui/, it's in ../mnc_ui/assets/
No its right
The Assets folder is the root folder in unity
So no need to reference it
^
This code
var mncUxml = AssetManager.GetAsset<VisualTreeAsset>($"{Info.Metadata.GUID}/mnc_ui/mnc_ui.uxml");
var mncWindow = Window.CreateFromUxml(mncUxml, "Maneuver Node Controller Main Window", transform, true);
mncWindow.DontDestroyOnLoad();```
is saying it need to give it an input argument that's an object
A sec then
it seems to want a UnityEngine.Object called target
well, that it's going to call target...
UnityObject.DontDestroyOnLoad(mncWindow);
mncWindow.hideFlags |= HideFlags.HideAndDontSave;
Yeah, that
UnityObject doesn't exist
UnityEngine.Object
SpaceWarp defines UnityEngine.Object as UnityObject to make it obvious that its not System.Object internally
Ahhh, this looks better. compiling now
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
ArgumentNullException: Value cannot be null.
Parameter name: e
at UnityEngine.UIElements.UQueryExtensions.Q (UnityEngine.UIElements.VisualElement e, System.String name, System.String className) [0x00003] in <b04b98aef47f4637b950c1b3349ee421>:0
at UnityEngine.UIElements.UQueryExtensions.Q[T] (UnityEngine.UIElements.VisualElement e, System.String name, System.String className) [0x0001b] in <b04b98aef47f4637b950c1b3349ee421>:0
at ManeuverNodeController.MncUiController.InitializeElements () [0x00021] in C:\KSP2Mods\ManeuverNodeController\ManeuverNodeControllerProject\ManeuverNodeControllerPlugin.cs:1479
at ManeuverNodeController.MncUiController.Update () [0x0000f] in C:\KSP2Mods\ManeuverNodeController\ManeuverNodeControllerProject\ManeuverNodeControllerPlugin.cs:1278
(Filename: C:/KSP2Mods/ManeuverNodeController/ManeuverNodeControllerProject/ManeuverNodeControllerPlugin.cs Line: 1479)
Basically still same error
🙃
The name is right
The bundle has it
afaik paramenter e is just the exception right @hollow tiger ?
e is the element
or could it be that somehow he's passing e?
Oh wtf i was thinking argument of Q<Element>(arg) not of the internal call
E is the this VisualElement of the Q<Element>(arg)
so _container is whats null then im guessing
If it matters, vs is graying out UnityEngine prior to Object like I don't need that part.
no its just saying that's not needed
Yeah, that what I thought too
Can I see the line you are talking about
Cuz MonoBehaviour derives from UnityEngine.Object
public void InitializeElements()
{
ManeuverNodeControllerMod.Logger.LogInfo($"Starting UITK GUI Initialization. initialized is set to {initialized}");
// Set up variables to be able to access UITK GUI panel groups quickly (Queries are expensive)
NoNodesGroup = _container.Q<VisualElement>("NoNodesGroup");
HasNodesGroup = _container.Q<VisualElement>("HasNodesGroup");
ManeuverNodeControllerMod.Logger.LogInfo($"Panel groups initialized. initialized is set to {initialized}");```
1479 is the NoNodesGroup = line
Where is _container set
public void SetupDocument()
{
var document = GetComponent<UIDocument>();
if (document.TryGetComponent<DocumentLocalization>(out var localization))
{
localization.Localize();
}
else
{
document.EnableLocalization();
}
_container = document.rootVisualElement;
_container[0].CenterByDefault();
_container.style.display = DisplayStyle.None;
}```
Could initializeeleements be called before setupdocument?
I have this in Update
private void Update()
{
if (!initialized)
{
InitializeElements();
return;
}```
If initialized is false, it will (and does) call it again
I get smamed with these errors
because SetupDocument is on Start()
I didn't so much "move" it there as I put it there. I don't see it being called anywhere else so I assumed it's called automatically
Alright, and they are in the same monobehaviour
Are there any exceptions in SetupDocument?
Cuz if an exception happens before _container is set, then _container will be null
send ur KSP2.log if possible
There's my KSP2 log
the problem is elsewhere
[EXC 19:23:54.000] MissingMethodException: void UitkForKsp2.API.Extensions.CenterByDefault(UnityEngine.UIElements.VisualElement)
ManeuverNodeController.MncUiController.Start () (at C:/KSP2Mods/ManeuverNodeController/ManeuverNodeControllerProject/ManeuverNodeControllerPlugin.cs:1271)
is your UITK in game updated?
this is something on UITK for KPS2 1.2.0
xD seems like the problem something else all along
We've moved the error!
This is a good sign...
[Info :Maneuver Node Controller] Starting UITK GUI Initialization. initialized is set to False
[Info :Maneuver Node Controller] Panel groups initialized. initialized is set to False
[Info :Maneuver Node Controller] SnapTo buttons initialized. initialized is set to False
[Info :Maneuver Node Controller] SnapTo labels initialized. initialized is set to False
NullReferenceException: Object reference not set to an instance of an object
at ManeuverNodeController.MncUiController.InitializeElements () [0x00536] in C:\KSP2Mods\ManeuverNodeController\ManeuverNodeControllerProject\ManeuverNodeControllerPlugin.cs:1593
at ManeuverNodeController.MncUiController.Update () [0x0000f] in C:\KSP2Mods\ManeuverNodeController\ManeuverNodeControllerProject\ManeuverNodeControllerPlugin.cs:1278
(Filename: C:/KSP2Mods/ManeuverNodeController/ManeuverNodeControllerProject/ManeuverNodeControllerPlugin.cs Line: 1593)
Found an obvious issue on 1593... trying again
And now we've moved it again!
NullReferenceException: Object reference not set to an instance of an object
at ManeuverNodeController.MncUiController.Update () [0x00866] in C:\KSP2Mods\ManeuverNodeController\ManeuverNodeControllerProject\ManeuverNodeControllerPlugin.cs:1437
(Filename: C:/KSP2Mods/ManeuverNodeController/ManeuverNodeControllerProject/ManeuverNodeControllerPlugin.cs Line: 1437)
It now doesn't spam NREs when I launch but it does when I've got it running, and it's only showing me the old IMGUI version, not both
NextLANValue.text = nextLAN;```
that's one newest offender, but the great news is that's basically the last line in Update, so we're really close!
Another obvious bug found and squasshed
xd now you know that if players have this bug what they need to do!
Now I'm only getting the old GUI...
It was both before, but now it's only the IMGUI and not the UITK GUI
Yeah, I'll have to trace that
are you calling _container.style.Display = true?
Here for sure
private void SetEnabled(bool newState)
{
if (newState) _container.style.display = DisplayStyle.Flex;
else _container.style.display = DisplayStyle.None;
//interfaceEnabled = newState;
//GameObject.Find(ToolbarFlightButtonID)?.GetComponent<UIValue_WriteBool_Toggle>()?.SetValue(interfaceEnabled);
}
Here it's set to none
public void SetupDocument()
{
var document = GetComponent<UIDocument>();
if (document.TryGetComponent<DocumentLocalization>(out var localization))
{
localization.Localize();
}
else
{
document.EnableLocalization();
}
_container = document.rootVisualElement;
_container[0].CenterByDefault();
_container.style.display = DisplayStyle.None;
}```
hmmm
That's it.
are you sure that SetEnabled is being called?
where are you doing it?
you could do it on the Update() of the WindowController
Looks like I only call it for pressing the close button. This would be the problem
xD
There needs to be a way to call it when the app bar button is pressed
or when the hotkey is pressed
and there is!
I think I know how to do that
go ahead, if you need help im here!
LOL, another question! I thought I knew what to do and it was obvious, but maybe not so much for me. I'm trying to call it from the main plugin by having ToggleButton call it.
private void ToggleButton(bool toggle)
{
interfaceEnabled = toggle;
GameObject.Find(ToolbarFlightButtonID)?.GetComponent<UIValue_WriteBool_Toggle>()?.SetValue(interfaceEnabled);
MncUiController.SetEnabled(toggle);
}```
I made SetEnabled a public method, so it is accessible, but now vs is telling me "An object reference is required for the non static field, method, or property"
Do I need to make it a static method?
That seems to mess up other stiff, so probably not
you do have to make either static
or you have to save an instance somewhere
u can just save an instance on the plugin class
since there's where u first instantiate it
and thats also the best way for you to do it
nono
controller = mncWindow;
:D
remember that you insntantiate it with Window.CreateFromUxml?
sorry actually i think it aint this xD
a sec
controller = mncWindow.gameObject.AddComponent<MncUiController>();
this
you have that line on your OnInitialized
the AddComponent<>() returns what youre adding
like this?
public override void OnInitialized()
{
base.OnInitialized();
MNCSettings.Init(SettingsPath);
Instance = this;
game = GameManager.Instance.Game;
Logger = base.Logger;
var mncUxml = AssetManager.GetAsset<VisualTreeAsset>($"{Info.Metadata.GUID}/mnc_ui/mnc_ui.uxml");
var mncWindow = Window.CreateFromUxml(mncUxml, "Maneuver Node Controller Main Window", transform, true);
UnityEngine.Object.DontDestroyOnLoad(mncWindow);
mncWindow.hideFlags |= HideFlags.HideAndDontSave;
mncWindow.gameObject.AddComponent<MncUiController>();
controller = mncWindow.gameObject.AddComponent<MncUiController>();```
no need to call it twice!
actually if you call it twice you'll have 2 controllers
you only want 1
I already had the mncWindow.gameObject.AddComponent<MncUiController>(); line, it was there before...
oh yeah, but you werent storing it
baiscally just remove the 1st one
and you're set
And now maybe ToggleButton will work
then you call controller.SetEnabled(ToggleValue)
dont forget that
when you press the toggle on the AppBar
Bingo!
you have to SetEnabled your controller
:D
Well, mostly... Some things in the new one are a bit off
Yes, that and the Maneuver Node In 9 orbits part
i think ur ussclass is being overriden by smth
Should be in 0 orbits
youre feeding something wrong to it then
Oh I see an issue! Thenew one isn't getting the right UT, or maybe not getting UT at all
The start time for thenodes are very different
The should take Node.Time - UT
btw you can do TextField.value = smth to update its value, as you can see, now is at 00.00 in the new window
I think I can track down most of this madness, but I'm not sure what's up with the text input fields. They look fine int he Unity editor
yeah my guess is they are being overriden by something
probably uss on the KerbalUI (main ui of UITK for KSP2)
Could be. The close button does work, none of the others work yet. Still, this is very close. The text inputs are basically getting a huge verticle squeeze. The look OK more or less on width maybe, but top and bottom are getting crushed
Is that padding or margin, I cna never recall
neither can i xD
but i think its margin
margin is for the object inside the visual element
padding is for the objects outside
basically
padding = the surrouding garden of a house
Margin = How thick the walls are
Ok, then margin is getting set wrong somehow
while the visual element is the house 🙏
yeah, that needs some deeper investigation
let me take a look at the uss, can i?
you might need to target a more specific class
the more specific the class is higher its priority
Here it is
hmm
.unity-base-text-field__input
try changing this to a selector
so
.unity-text-field > .unity-base-text-field__input
also change the one just about that
.text-input to .unity-text-field
What does it mean to change this to a selector?
basically you're making it more deterministic, thus it will have more priority
this is mostly as a hail mary to see if it really is KerbalUI that's messing your UI
I've now got both of these defined, and they're identical defs I think
But I don't know how to do the other one
I mean, all those things are selectors, right?
Oh, wait, I think you're really jsut saying make another selector and name it .unity-text-field, or can I rename the one I've got?
well both will work
you can keep the old ones if you'd like
but renaming might be the right way to go at it
OK, let me see if I understand this. Change the name of .text-input to be .unity-text-field, right?
yes
actually
.text-input
shouldn't even be targeting anything
unless you added it to the elements
I did add it. It does target things
.text-input {
flex-direction: row;
justify-content: space-between;
width: 290px;
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
margin-bottom: 2px;
flex-grow: 1;
}
oh okok
tho lets see if this will work
Wait, I'm still confused. The second thing you suggested sounds like it steps on the first thing - I'm probably misunderstanding...
If I Change the name of .text-input to be .unity-text-field, and I change the name of .unity-text-field > .unity-base-text-field__input am I not just changing one thing twice?
I've got a def for .unity-base-text-field__input already in there
Here's what one of the text fields looks like for it's styles
nono
.unity-text-field > .unity-base-text-field__input
this
is a selector
you are selecting
any of its 1st childs
with that tag
so any of .unity-text-field first childs
with the .unity-base-text-field__input class
yes
I had no idea you could even do that...
Which might be written in greek, I'm not sure
xD
you can also select by name as you done there
and you can select any child (recursively)
if you remove the >
you can also target any TextField, Button, Label etc by writting the class name
OK, I renamed the other one and curiously now it's not targeting anything where before it was
4th entry is what you just did
can i see how it is? i might have mistaken it somewhere
I see that, but I had no idea what it meant. I'm probably not grasping it yet either. Is it saying this-thing overrides/trumps that-thing?
the second one should be this
waht it is saying is
in .parentClassName it will look for any direct child with the class .directChildClassName and target that
OH
sorry
i thought it was the other one who was having problems
youre trying to target this
you have a typo there xD
idk if you copied from me, might have been i do make alot of typos
yours say feild
That was my error I'm certain. Changing it restored the targeting to what it was.
I'll save, rebundle, and give this a shot.
I've got some other thigns to test as well where most of the new buttons should be working now
great!
i think that this was your exact problem btw
since KerbalUI has a selector just like yours
and it can very likely be overriding yours that was less specific
Some, there's an issue with my AddNode. I need to test some other thigns though
well you can change it via code, that's the highest priority
tho either me or munix will have to scavange the code to see where the issue is
let me see what you'll do to set it via code
Some things work, but with the text fields goofed up, it's really hard to tell if the increment/decrement burn buttons work
interesting
its not padding thats doing that
or better
its not margin thats doing that
rather its actually either padding or smth else
When you say change it by code, do you mean maybe go into InitilzeElements and set it from there?
yes
tho you might need reflection for this... i'll help u out w it tho
or if you rather wait for munix, im sure that he'll know something aoubt this (maybe xD)
as he knows more about css and wrote the KerbalUI.uss
Isn't he going on a game sabatical to do his real work?
oh true 🙃
There are a couple of odd things going on with the GUI other than the text fields. For some reason the start time for node[0] (index 1) is messed up, bot other nodes are not
you probably are only updating it when you change
not when its initialized!
Also, the main GUI correctly sees there is not target and so doens't display the ANt or DNt buttons, however the UITK GUI is showing them, when it shold not be
then the ANtButton.display is not being set to None!
// If we've got a target
if (ManeuverNodeControllerMod.Instance.currentTarget != null)
{ // If that target is orbiting the same body the active vessel is
if (ManeuverNodeControllerMod.Instance.currentTarget.Orbit.referenceBody == orbit.referenceBody)
{ // Allow SnapTo ANt and DNt
SnapToANtButton.style.display = DisplayStyle.Flex;
SnapToDNtButton.style.display = DisplayStyle.Flex;
}
else
{ // Do not Allow Snap To ANt or DNt
SnapToANtButton.style.display = DisplayStyle.None;
SnapToDNtButton.style.display = DisplayStyle.None;
}
}```
I think I see the problem!
It should be this!
// If we've got a target
if (ManeuverNodeControllerMod.Instance.currentTarget != null)
{ // If that target is orbiting the same body the active vessel is
if (ManeuverNodeControllerMod.Instance.currentTarget.Orbit.referenceBody == orbit.referenceBody)
{ // Allow SnapTo ANt and DNt
SnapToANtButton.style.display = DisplayStyle.Flex;
SnapToDNtButton.style.display = DisplayStyle.Flex;
}
else
{ // Do not Allow Snap To ANt or DNt
SnapToANtButton.style.display = DisplayStyle.None;
SnapToDNtButton.style.display = DisplayStyle.None;
}
}
else
{ // Do not Allow Snap To ANt or DNt
SnapToANtButton.style.display = DisplayStyle.None;
SnapToDNtButton.style.display = DisplayStyle.None;
}```
I had nothing actually handling the case when currentTarget == null!
I was only switchingoff if it was not null and the target was not in the same SOI
this way their default state is hidden
Yeah, but the root is them bein enabled
even tho their main state is disabled
that works tho!
If it's set that way and you run around selecting and unselecting targets what happens?
I think this way is fool proof
well true!
Now to see why my time is messed up
It really shouldn't be... It's just this one line regardless of what's happening
StartTimeValue.text = MNCUtility.SecondsToTimeString(thisNode.Time - UT, false);
with this defined above
int selectedNode = ManeuverNodeControllerMod.Instance.SelectedNodeIndex;
ManeuverNodeData thisNode = nodes[selectedNode];```
And I know thisNode is working as I use it for basically everything, like displaying the bur vector components - which are comingout right
I kinda sorta fixed the text inputs. I brute forced it. Went in and just set margin =2 and padding =0 on the text input elements themselves. Why fight with it? Using styles is great when they work, but if they don’t work then fuck ‘em
Still not sure what’s up with the time display. It’s sort of like there’s a lag on setting the node index or getting the node info. Probably not that, but weird. I’m headed for bed. I’ll play with it more tomorrow. I know its close now
glad you fixed it, as for the time
i'd said yet again that maybe you're missing something in code, the label just shows what you want it to show, there's no delay on it (unless you make the dealy yourself)
I fixed the start time issue. It was minor (of course). I was inadvertently stepping on my copy of UT and then using the stepped on copy. All I needed to do there was add one line to get the correct UT again.
xD
That said, I've also tracked down why none of my burn time adjust buttons were working. Turns out they were working, but what was going wrong was that variables that are supposed to have the values used were not being initialzed and were all zero, so it acted like the buttons didn't work, when they did
as always the smallest things
then its a problem on the textfields probably
can u put a log inside the "TryParse"?
It's not that. The issue was that although the GUI starts by showing you a default value in the text field, it doesn't actually do anything with that default value unless you change it. If you do change it, then the new value gets into the variable and all works fine. So, where we had this
_container.Q<TextField>("AbsoluteDvInput").RegisterValueChangedCallback((evt) => {
if (float.TryParse(evt.newValue, out float newFloat))
{
_container.Q<TextField>("AbsoluteDvInput").style.color = Color.white;
absDvValue = newFloat;
}
else
{
_container.Q<TextField>("AbsoluteDvInput").style.color = Color.red;
}
});```
I've now got this
pass = float.TryParse(_container.Q<TextField>("AbsoluteDvInput").value, out float absDvValue);
_container.Q<TextField>("AbsoluteDvInput").RegisterValueChangedCallback((evt) => {
if (float.TryParse(evt.newValue, out float newFloat))
{
_container.Q<TextField>("AbsoluteDvInput").style.color = Color.white;
absDvValue = newFloat;
}
else
{
_container.Q<TextField>("AbsoluteDvInput").style.color = Color.red;
}
});```
The idea being that when we initilze things we also want to set the values for these variables.
That said, this first attempt is not working 😕
Oh! I see the problem! Where I tried this
pass = float.TryParse(_container.Q<TextField>("AbsoluteDvInput").value, out float absDvValue);```
I actually needed this!
```cs
pass = float.TryParse(_container.Q<TextField>("AbsoluteDvInput").value, out absDvValue);```
I was redeclaring the damn things!
Nuts... This still doesn't work
im 99% sure
All of these
private float largeStepDv;
private float smallStepDv;
private float absDvValue;
private float largeStepTime;
private float smallStepTime;```
are starting out as zero, and the code I've added in `InitializeElements` is not correcting this
the small steps should all be 5 and the large should all be 25
im guessing that the value on the input starts at 0 too
ok lets do it like this then
here put = amountThatItShouldStart;
The text in the GUI textfield is all showing up ok.
but the thing is
RegisterValueChangedCallback only gets called when you interact with it
so until you interact with it it will stay 0
thats problem 1
have u tried interacting with it? does it work well after you interact?
Yes, everything works fine that way. Just set one of them and that one starts working
what i'll recommends you is
to reduce maintenance work on it
_container.Q<TextField>("AbsoluteDvInput").value = absDvValue.ToString();
on InitializeElements
this way if you change that value on code it will update in game as well
and also do this
this way if you want to such a minor change to the ui you can just change it in code
then
it should start working as normal
its either that or you do what u were doing here
the problem with what ur doing there is if the TryParse fails your problem will be back
while if you feed it directly a float absDvValue it will always be a valid value
I only know that what I tried with the TryParse experiment didn't actually work. I think this new way will though. I'm going to try it.
it ididnt because i suspect you did it wrong, but still wouldnt be a "will work forever" solution
this would be the right way
float.TryParse(_container.Q<TextField>("AbsoluteDvInput").value, out absDvValue);
but again, this is dependent on what you've put on the uxml
Yep, I found that issue: #1114994858017423460 message
But even taking out the erronious redeclaration didn't get it to work
its probably not being able to parse it
when you're doing something like that
where you're not using the TryParse in a if statement
its better to use
absDvValue = float.Parse(_container.Q<TextField>("AbsoluteDvInput").value);
as this will throw an exception if it isnt able to parse
It's mostly working now. This part, the burn vector and time adjustment part, seems to be working perfectly. There is some sort of weird lingering problem with the node creation part.
hm whats actually happening on it?
It used to be that I could create up to 9 nodes on one trajectory without issue. Now when I get to like the 4th or 5th one everything goes bonkers and I get red text all over the screen.
seems like you are creating the nodes 2x
since it stops working at exactly half of it xD
LOL, that may actually be true! I just tried with the IMGUI version and it crapped out on the 5th node too!
so thats something like
the List has 5 nodes, and you're trying to access a 6th node
basically youre passing an index that doesnt exist
It used to do this to me back when I was first making MNC work with multiple nodes. I got it fixed, and in the process moved the node management into Node Manager so I wouldn't have to fix both MNC and FP. Now it's back again
It bombed on making the 5th node. The reason it got to 5 of 6 before was that it had started with one node
since i guess you havent messed with it
oh i see yeah
Correct. Haven't touched NM in a while
I'm gonna roll back to a previous MNC and make sure it's just this one.
Well nuts...
It bombed
I have apparently re-intproduced the problem - quite possibly in NM and I just didn't test it enough. I'm going to roll it back and see
Confirmed gone in NM 5.4 (published on 5/18), and MNC 0.9.2
maybe just revert?
MNC 0.9.3 requires NM 5.5, so I can't tell if there's any problem there.
Well... NM 5.5 does have some things I need in it, so I think the solution is actually to compare 5.5. and 5.4 and see what changed. The main features I added were the ability to delete just one node or all nodes in the past. Those features should have nothing to do with this. I have a hunch I also did something I'm now regretting in the node creation part.
This is gonna be fun... The release notes for NM 5.5 are this.
Updated to bring in MechJeb library functions needed by ManeuverNodeController 0.9.4 and FlightPlan 0.8.9. Node Manager now provides the following things
OrbitExtensions
MathExtensions
MuUtils
MechJebLib\Primatives
MechJebLib\Utils
I don't think that's what's breaking it... I must have stepped on something else and forgot to mention it
But the good nres is that the UITK ver of MNC is not to blame!
yes xD the window seems ready to use!
Relocating to here since this is a general Unity UITK mode kind of question...
@dusty berry the place where I'm getting confused with modifying toggles is here
There's all this stuff under the toggle, and I kind of don't want it, or don't think I need it - like the checkmark part
Selecting the basic unity toggle I see these for styles
One level down on the label I see these
The visual element has these
you cant change it unfortunately
controls are basically a group of uielements controlled by code
everything thats created by code you can't delete
and yhou can only modify via uss classes
you can always just hide the checkmark by setting it to Display. None
The VisualElement contains the checkmark and when I select it I see this in the GUI
So, maybe if I were to override that with a css to make it have 0 width or otherwise just not be there, then I would have a toggle without a check - but then the user cant interact with it. So maybe instead I need to make the label have 0 width and the VisualElement has it all but I need to change it from displaying a chekmark or not to instead change the text displayed and the background for it?
It's sounding more and more like I need to stick with a stock button and write the code in my mod to handle it like a toggle. Honestly that sounds easier to me, but maybe becuase I'm new at Unity/css/etc.
I mean you can just look at the KerbalUI style for toggles
I do a lot of styling magic there to get rid of the checkmark etc
it's the .toggle class
Oooo! This sounds promising! I'll take a look at .toggle in the KerbalUI
but I do agree with Lux in that it's not the best UX practice to mask toggles as buttons
I like the way they behave in the modlist. do I need to replicate this in my uss to get that as a starting point?
Or is there a way for me to just use that since it's already in the theme and I may not need to replicate it?
all you need is just put the toggle class on your toggles
I didn't do it by default for all toggles, because foldouts also contain a toggle and it messes it all up
I'll need to take a better look at it when I have some time
I added KerbalUI.uss to my StyleSheet to see this, but I don't see .toggle on a line by itself, only on the lines I sniped above.
How do I "just put the .toggle class on your toggles"?
on your elements
Ordinarily I'd drag the selector to the thing I want to apply it to
like you would put any other class on them
I'm not asking my question very well...
Ahh that worked! Figures it was easier than I thought.
I've just not done it that way before and didn't realize that's what you meant
yeah I'm probably also not the best person to explain it since I only really use the builder for the live preview and otherwise write all the UXML and USS by hand lmao
so I don't really know the actual process of using the visual editor
Is there a way I could get some text inside the toggle part that lights up and also control it's width?
you know what they say, where there's a will, there's a way 😛
LOL, thanks!
I can't tell you off the top of my head, I'd have to go and experiment with it
but as for the width, that shouldn't be too difficult
just look through the KerbalUI .toggle selectors and the width should be set in there somewhere, then you just have to write a similar/slightly more specific selector and overwrite the value
though if I remember correctly, the style for the toggle is a bit hacky so it might be in multiple places
Since I'm going to want some things to be toggles and some to actually be radio buttons, I've got a hunch that in a number of places I may be ahead to make the stock buttons do what I want. A uss solution might be better, but for me I suspect it would take an age - while I could lift the radio button behavior right out of my current code and have something working much sooner.
oh fuck


