#Make a mod with a UITK GUI
1 messages · Page 3 of 1
lmao
munix can you make the unity package for me pls 
I get that this may not be a "good UX design", but I also want continuity between what players get today in FP and what I will deliver in a UITK FP
i'll send u the file with the exposed controls
fair
sure
I might as well package the KerbalUI theme along with it since I wanted to split it off into a Unity package, too
yeah makes sense, that way anyone can just make a new unity proj, add UITK and add the package
and it will be same as a template
yeah exactly
and since I already have code for UitkForKsp2 1.3 ready, I can go ahead and push those all out at once
idk if the way i did it is the best way
ie RadioButtons you have to add a RadioButtonGroup
and then go to the zHelpers>RadioButton
fget im dumb
actually you just put the choices you want on the RadioButtonGroup separated by commas
so choice A, choice B, choice C
and it auto generates
alright, so like the dropdown
what if you want to put some non-text content into the radio buttons, for example an image?
no can do
thats what i was gonna allow on my dropdown
and it is working, but still not good enough for use
the Unity's builtins only allow text
I mean, this works just fine
don't mind the "mod-icon" thing, Copilot was just hyper lmao
Oh ok like that
tho i think inthe UI Builder shoulndt work? maybe?
maybe with the controls under zHelper you can tho
works fine, I can put anything inside the radio button
even from the editor
and if you want the content to be on the left of the radio button circle instead of on the right, you can just change flex direction
even with the builder generated ones (choice A, choice B, etc)?
if so they did some cool magic with their controls damn
lmao it does this
yeah as i thought
can you check if the radio button works fine if you add it manually?
yep, just fine
oh ok then its ok like that
i though the manually added one wouldnt work
tho for dropdowns i think you cant add images, just text
yeah, then i'd need to go into the code to see how they're generated
yeah no problem, it's not important
it is generated at runtime too iirc
yeah either way it would be only after the 28th xD
yeah, i iirc the options appear as a child of that
I'm trying to center a window in the controller's Start() method, but root.transform doesn't have any position set and boundingbox doesn't have any value. After a couple of seconds it's initialized. I remember reading that you @shadow tree had this issue. What was the fix? Where would I need to change the position, what method?
_container.CenterByDefault()
not yet released
that's in 1.3
but I'm trying to get it released today
so if you wait a bit, all you'll need to do is that
so CenterByDefault() isn't release yet?
nope
i think @marble shale is using it
ok, I'll wait, thanks
OH
yeah you're right lmao
I got the drag disabling mixed up with this
then yeah, you can use it right away
tho anyone with an outdated version of UITK for KSP2 will not be able to see your window
it will give a "method doesnt exist" exception
if thats the case just tell them to update their UITK
there's also a second, more customizable method, element.SetDefaultPosition, which is what the CenterByDefault method calls in the background like this:
element.SetDefaultPosition(windowSize => new Vector2(
(ReferenceResolution.Width - windowSize.x) / 2,
(ReferenceResolution.Height - windowSize.y) / 2
));
you provide a callback inside which you can use the actual window size to compute the position from it
I don't seem to have CenterByDefault, nor SetDefaultPosition
maybe I need to update?
it's in version 1.2
oops, I'm on 0.5.1
you're on what 
btw munix
for that log that he has
wouldnt be better on Debug
since Debug is usually hidden for players, while Info is shown?
oh and by the way, the way I do it in SpaceWarp is document.rootVisualElement[0].CenterByDefault()
the issue is that the rootVisualElement is not the VisualElement you have as the .root in your UXML, it gets wrapped inside a TemplateContainer element when instantiated from a VisualTreeAsset
and your actual root element is the only child of the TemplateContainer, which spans the whole width and height of the screen usually
yes, I've seen that
and changing the position of the TemplateContainer can lead to some stuff like dragging not working properly on some parts of the screen etc
I've noticed that already. So I set it's width to the width of the window
hm, I guess that might work, too?
but anyway, if you notice any issues with the positioning and other stuff, that's why
I felt like it was better to just manipulate the inner element
I mean I set the width of the first visual element (child of rootVisualElement)
oh got it
yeah, then you should just call the extension methods on that element, instead of on the rootVisualElement
and it should be fine
oh yeah thats what ur suposed to do
actually munix
i think that .rootVisualElement
would work well if we didnt put our canvas sizes to 1920.1080
cuz then the .rooVisualElement would be the right size
tho i need ot test that
I've never used a canvas size of 1920x1080
modlist is this for example
I don't think the template container has anything to do with that
it's always the full size of the screen afaik
hmm well tbh i havent tested so yeah it's probably just the screen size
idk why they dont just follow the canvas size when instantiating
I don't even know where the canvas size is saved
it's not in the UXML and it's not in its meta file
so I don't think that information goes into the bundle at all
Yesterday when I upgraded to 1.2.0, Root[0].CenterByDefault(); was working correctly. Today, after I changed something else in the code it's not working anymore, window is still being created at 0, 0. I can't find out what's happening, no error is being thrown, nothing in the log, like everything's fine. It's not because of 1.3.0 as both versions are giving me the same result. I did have issue installing 'UITK for KSP2' package into unity and had broken uss/themes until I (somehow) fixed them, but that couldn't create issues with CenterByDefault(), could it?
Do you have an idea what might be issue?
huh, that's weird
yeah, the Unity project stuff should have no effect on that, since it's pretty much the same files, just in a package
maybe when you called it?
usually we call it on InitializeDocument
I haven't changed that since yesterday. It's being called in the Start() method of the controller script attached to the UIDocument. Code is something like this:
(flight scene entered)
MainGui = Window.CreateFromUxml(...)
MainGuiController mainGuiController = MainGui.gameObject.AddComponent<MainGuiController>();
...
public class MainGuiController : MonoBehaviour
public void Start()
...
MainGui = GetComponent<UIDocument>();
Root = MainGui.rootVisualElement;
Root[0].CenterByDefault();
you could try to replace the method call with what it does and add some debug logs to see if you're given the wrong sizes:
element.SetDefaultPosition(windowSize =>
{
Logger.Log($"width: {windowSize.x}, height: {windowSize.y}");
return new Vector2((ReferenceResolution.Width - windowSize.x) / 2, ReferenceResolution.Height - windowSize.y) / 2);
});
@dusty berry is there a way with the dropdown element to make the label take less or no space? When I include a label, I lose the down arrow in the dropdown. Also, I'd like to have more control over the space allocated for the label as well as it's horizontal alignement.
Here's what I've got without the dropdown label specified
In the top example there's a button labeled Celestial, and in the bottom example it's just an ordinary label. I'd like the dropdown bit to take up at least 1/2 the allowable window width after margin and to be right justified with the other visual element left justified.
yup
check the uss class of the label
and edit it

its the easiest way to do it
i'd advise you to only target the dropdown tho, else you'll edit everything
so something like
DropdownField > [ussClass of label here]
_logger.LogDebug($"Before CenterByDefault()");
//Root[0].CenterByDefault();
Root[0].SetDefaultPosition(windowSize =>
{
_logger.LogDebug($"ReferenceResolution.Width: {ReferenceResolution.Width}, ReferenceResolution.Height: {ReferenceResolution.Height}");
_logger.LogDebug($"width: {windowSize.x}, height: {windowSize.y}");
return new Vector2((ReferenceResolution.Width - windowSize.x) / 2, (ReferenceResolution.Height - windowSize.y) / 2);
});
_logger.LogDebug($"After CenterByDefault()");
and this is what the log says:
[Debug :MicroEngineer.MainGuiController] Before CenterByDefault()
[Debug :MicroEngineer.MainGuiController] After CenterByDefault()
I'm confused. How is this possible?
its possible bcuz the error is on the windowsize
that's totally fine, that should happen, since SetDefaultPosition registers an event handler
so it won't get executed right away
it should only get executed when the window first gets displayed
you can also edit the dropdown itself to take more space (maybe put grow? or edit its width)
here's the implementation
ok but loggers inside the function aren't being triggered at all
I can't see why the geometry would never change, that's weird
where/when do you set the window as hidden/shown?
I don't? It just shows when MainGui = Window.CreateFromUxml(Uxmls.Instance.MainGui, "MainGui", MicroEngineerMod.Instance.transform, true); is executed
and now that I typed this, could it be that I passed the transfrom of the plugin class?
oh so you never hide it? it's just displayed as soon as the mod gets loaded?
yes, I'm testing it right now, so I just set it up that it automatically triggers when the scene is loaded
Should this be .DropdownField > .unity-base-field__label? I've got it without the leading . and it's not having an effect as far as I can tell.
I would suggest just trying to bind your own handler for GeometryChangedEvent with some logging inside and see if it ever gets executed
it might have to do with the handler only being bound to the element after the geometry changes, aka the window is already drawn
ok, I'll try that
without the .
you're targeting the c# chass
tho again maybe its better for you to target the actual dropdown
Here are the styles that are applied to the Label in the dropdown
The new one is not showing up as applied
shouldn't it be Dropdown? @dusty berry
That one is defined with Grow = 0 and Width = 0
at least if it's using the ExposedControls one
I don't know how USS works with C# inheritance
Interestingly changing it to just Dropdown does fix the loss of the down arrow when a label is set.
yeah that's what I thought, you can't target a base C# class in a selector
(Dropdown is a class extending DropdownField)
If doing this makes the dropdown able to show the down arrow with a label set then maybe the C# class needs a minor tweak so it can do that without this?
Though it doens't (yet) solve my issue
if anything, we need to provide default styles
for these exposed controls
I just really didn't have the time to do it for the 1.3 release
im pretty sure in UITK is DropdownField but i might be wrong
oh but you can still target the UITK class no?
oh wtf thats wierd
cuz it uses the same constructor
its literally public Dropdown() : base()
maybe it doesnt take into account inheriteds
yeah, but typeof(Dropdown) =/= typeof(DropdownField) is what I'm assuming is the issue
huh
I'm getting about what I want and all I need to do was tell it not to display the Label
set the minwidth for labels to be a set amount
to provide uniformity to your UI
i think that 50% would be a good starting point
wait what
wtf
OHHHHHHHHHHHHH
I tried setting min width and width both to 0, no effect
Correct! They are not
I mean, you could also just circumvent the bug by not giving the dropdown any label, probably?
well that explains a lot
indeed
Nope, they you just get a lot of empty space where the label would be
or using the dropdowns given labels
See posts above
i might have to fix that with UxmlAttributes
That's less than ideal as (a) I can't control the jsutification, and (b) I can't control the width
Ok, more accurately, none of the things I tried worked
yep
tho (dw its not at this scale) but as any other thing in programmin, less elements = better performance
the console ie has a max of 1000 entries, each entry has 3 labels, when you have 1000 entries it lags quite a bit
but these are BIG numbers
This is interesting! I was aiming for something like this
And got this!
So, apparently using a forward slash gives a sub menu? Who knew!
Perhaps I can use this in the celestial object and vessel selection for moons and docking ports?
But what would I get if you try to pick the thing to the left of the slash instead of the thing after it?
Well, in preview it doesn't let you pick the thing to the left, but I think I've got a way around that...
@dusty berry is there any documentation for how the dropdown parses the Choices string?
not rlly
that i know of
btw i im not sure those submenus will work in game
im 99% sure they wont
by try it in play mode
So far I've found that trying to make a list of submenu items, the sub items are not parsed by | or ;, and using another / gives you a third level. Using a , gives you the next row
Also not \
yeah then its just like unity's parsing
but again
im pretty sure that wont work in game
unity parsing is "TopLevel/submenu1/submenu2/item"
Ahh, found it! Very tedious, but it does display something nice. Whether it works in game is unknown
Moho,Eve,Eve's Moon/Gilly,Kerbin,Kerbin's Moon/Mun,Kerbin's Moon/Minums,Duna,Duna's Moon/Ike,Dres,Jool
You have to list it as Top, Top/one, Top/two, Top/three, ...
This will take fewer rows to display than the old way
@shadow tree ok, so GeometryChangedEvent does trigger, but it won't for CenterByDefault() or SetDefaultPosition
Root[0].RegisterCallback<GeometryChangedEvent>(CenterWindow);
_logger.LogDebug($"Before CenterByDefault()");
//Root[0].CenterByDefault();
Root[0].SetDefaultPosition(windowSize =>
{
_logger.LogDebug($"ReferenceResolution.Width: {ReferenceResolution.Width}, ReferenceResolution.Height: {ReferenceResolution.Height}");
_logger.LogDebug($"width: {windowSize.x}, height: {windowSize.y}");
return new Vector2((ReferenceResolution.Width - windowSize.x) / 2, (ReferenceResolution.Height - windowSize.y) / 2);
});
_logger.LogDebug($"After CenterByDefault()");
private void CenterWindow(GeometryChangedEvent evt)
{
_logger.LogDebug("GeometryChangedEvent triggered.");
if (evt.newRect.width == 0 || evt.newRect.height == 0)
return;
Root[0].transform.position = new Vector2((ReferenceResolution.Width - evt.newRect.width) / 2, (ReferenceResolution.Height - evt.newRect.height) / 2);
Root[0].UnregisterCallback<GeometryChangedEvent>(CenterWindow);
_logger.LogDebug("GeometryChangedEvent finished.");
}
and log says:
[Debug :MicroEngineer.MainGuiController] Before CenterByDefault()
[Debug :MicroEngineer.MainGuiController] After CenterByDefault()
[Debug :MicroEngineer.MainGuiController] GeometryChangedEvent triggered.
[Debug :MicroEngineer.MainGuiController] GeometryChangedEvent finished.
and window is now correctly positioned at the center of the screen.
that's really weird
must be something on my side, cause I know it was working before, but anyway, my problem is solved for now. If anyone else doesn't have this, it'll be ok
I mean I was thinking I may have messed something up in the UitkForKsp2 1.3 update, but the SpaceWarp mod list still gets centered fine
I tried it with 1.3 and 1.2, same
Font question @shadow tree . I'm nearly done with building the basic layout of the FP UI in Unity and I'm working on the Resonant Orbits tab. What I've got now is this
Which as you can see has some undisplayed characters that look like square boxes. What I'd like is something like this
Which uses the "⦾" character
apparently that's not mapped in the font I've got. What's the default font for IMGUI that I've presumably been using? Maybe I can just switch to that for the visual element where I need that character
Also, separate question. Is there a way to make the toggle light appear to teh left of the label instead of to the right as it is in my current UITK layout above?
I believe this is HTML code ⦾, aka circled white bullet
Ahhh, this is probably how to get the order flopped on the toggle button!
Confirmed!
@shadow tree, why would Unity be looking for a font in an OSX folder? I'm booted into Windows, not OSX. This may be why I'm having trouble changing fonts...
huh?
nah that doesn't mean anything, afaik it just has some default fallback font assets for each OS
it's only when you specifically try to use OS fonts, which you aren't
what we mostly use are the dynamic font assets
I just tried to build my FP asset bundle with this in assets
And I got this
I cloned my FP UITK off the work I did in MNC, but the first thing I did was to change the file name to FP_UI and resave
Then I changed the uss to FlightPlanTheme.uss and resaved
Now I build and it makes mnc_ui.bundle?
I mean, it comes down to what bundle your assets are assigned to
It doesn't have anything to do with their filenames
So i missed a step and need to reassign my assets to a new bundle?
Yes, in the bottom right corner
When you click on a file
You should see mnc_ui.bundle
And you need to change that to whatever you want the new bundle name to be
For all the files that should go in
I did it wrong
Wait, I think I figured it out. I needed to click on things in the asset's folder and tell it they're in the new bundle!
So, step 1 - make new bundle in the list. Step 2 assign assets to new bundle. Step 3 build?
Which assets do I need to include? I've just added the .uss and the .uxml
I need to add my icons, too, don't I?
Awww fuck me... Now this?
What is this bitch up to?
I haven't changed any files, just added things to the bundle.
@shadow tree , what do I do with this?
I've closed/saved/reopened and confirmed my assets are in fp_ui.bundle
For some reason mnc_ui.bundle is in my AssetBundles.manifest, and not fp_ui.bundle
And I somehow had a ModList scene in a folder that was marked for the bundle. Why that hadn't been a problem with mnc_ui.bundle I have no idea.
Seriously tho, unity is giving me all kinds of warnings and errors all the time which I can dismiss by clearing the console and most of the time they don't come back... and it's making me nervous as I'm not used to getting "red" errors which you just dismiss and continue as if nothing happened. But that's unity I guess?
usually just add/remove a empty line in any c# script
to force unity to reload the assembly
I'm seeing some strange behavior when creating windows with Window.CreateFromElement. I'm iterating through a list of windows and creating each one with CreateFromElement.
Each loop has:
EntryWindowController ewc = new EntryWindowController(poppedOutWindow);
and inside EntryWindowController there's: Root = Uxmls.Instance.EntryWindow.CloneTree();
then back outside there's var w = Window.CreateFromElement(ewc.Root, poppedOutWindow.Name, null, true);
It appears that each created window is connected to the previous one, as they're being added to hierarchy of the same tree. I can drag individual windows normally, but each successive window reacts to the DisplayStyle.None of the previous one.
Also, before I'm iterating to create these poppedout windows, I'm creating the MainGui window with MainGui = Window.CreateFromUxml(Uxmls.Instance.MainGui, "MainGui", MicroEngineerMod.Instance.transform, true); and attaching the controller component MainGuiController mainGuiController = MainGui.gameObject.AddComponent<MainGuiController>();, which then internally again calls the EntryWindowController and adds its root to MainGui's #body visual element. And MainGui isn't affected.
I can't find a logical reason for this (or I'm misinterpreting how CreateFromElement should function), so I'm guessing there's an issue with how windows are created with CreateFromElement?
oh and, as you can see in the video, each created window is created at the position that is right below the previous one, so it looks like they're definitely being added to the same fantom visual element
is the video supposed to be showing that bug with the collective hiding of the windows?
and I mean you can look at the code of CreateFromElement for yourself
but in short, it takes the element you give it, creates a new game object, attaches a new UI Document to the game object, and attaches the element to the UI Document, and the game object is attached either to the parent transform you specify, or to the game's Main UI Canvas object if not specified
there should be 0 connections between the various UI Documents created in different calls of the CreateFromElement method
Don't know about that bug. What's happening here is that I should be having totally independent windows, but they seem to react to the previous window hiding some visual elements inside it with DisplayStyle.None. They move upwards when it hides, downward when it's displayed again, as if they're connected to the same root.
strange...
oh I finally get what you mean
I pass null for the transform, so they get attached to the Main Canvas. But still, MainGui isn't affected by this and it's also connected to the Main Canvas
@shadow tree , I previously had this error from Unity: "Cannot mark assets and scenes in one AssetBundle", which I cleared by deleting the ModListScene from the Scenes folder. Now, bizarely, the ModListScenes.unity file has reappeared. I can delete it again and presumably will be able to build again, but I'm wondering if there's some handy thing tucked away in my unity project which is setting up me the bomb.
Yep, deleting the mofo allows me to build again. Who or what is putting that thing in there for me when my back is turned?
no clue why it would reappear
do you have that scene open in the editor maybe?
try to make a new empty scene, open it, and delete the old one
idk
There is definitely something in here that's forking me.
I need there to be 0 scenes...
that’s not possible
your project is a scene
what i think is happening, is that your are in this “ModListScene” and you try to delete it
when you save, it just recreates it
When that scene exists it refuses to build the asset
When ANY scene exists, I mean
using UnityEditor;
using System.IO;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";
if(!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory,
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows);
}
}```
Clicking on the error takes me to this code
What?
You can have as many scenes as you want, they are in no way tied to projects
And googling that error led me took me to this: #1114994858017423460 message
Which is where I learned that if I delete the scene I can build - which is true
But in there it says that you cannot have a scene flagged for inclusion in a bundle
That's a pretty different problem
Unless that's the case in your project, and if it is, you just need to remove it from the bundle
I tried that, believe me I did
So you're sure that the scene isn't included in any bundles?
I clicked on the gd scene and made sure it was removed. Until I dleted it I got no joy
It's just weird that nobody who cloned the same SpaceWarpUI project encountered the issue
Fun with Unity™️
Also, where is the ghost in the machine making ModListScene? Why wouldn't it be FP_UIscene or something like that?
I'm special. I thought we'd already established this?
Because the scene is opened by default when you open the project, so I'm assuming that when you try to close the project, the currently open scene tries to save
I've created a new scene (called appropriately New Scene), and now when I attempt to build I get this
So I took zero actions to add that scene to the bundle. Just Create > Scene.
And if I delete it I can build
It is showing as not part of any bundle
Also, the Scenes folder where it lives is not in any bundle
My AssetBundles shows this
Why does it say you're trying to include scripts and built bundles into a bundle?
idk
Looking in Fp_ui.bundle I see this
There are also scripts in the Kerbalui bundle
No there aren't, it's impossible to put them into a bundle
Scriptable objects/game objects are not scripts
OK, I saw "Script:" and just assumed it was, well, a script...
No clue what it means, I can't really read Unity manifests
Could you maybe zip your Assets folder and send it to me to take a look at?
Oh crap, now I've really done it... The game is stuck on loading UI ToolKit
Weird. closed it and restarted and made it in...
lmao that's a new one
alright, let me take a look at the assets, just had to answer a work call
No worries. Also good news of a sort. My tabs kinda sorta work!
That said, in a UITK UI, why are key presses from the numpad affecting my sound? Is this a You Need BANANA thing?
If so, I may need to make that a required dependency...
play the video and watch
huh
interesting
and that didn't happen with IMGUI?
or did you have to block input there?
because if so, you'll probably also have to block it in UITK
It did until I added the disable game input when clicking into a text field part
yeah I figured
I can add an API for it in the library
and do it by default for TextFields
same as with the drag issues
Rats. I was hoping that maybe UITK was immune to that and I wouldn't need it...
I'm assuming it's due to KSP 2 using the InputLegacy module
and not the "modern" one
That would be fantastic!
adding it to my to-do™️
Joy, without input blocking then naturally '.' and ',' play with timewarp too. And so many inputs are numeric...
In the meantime I'll see if I can translate the input blocking I was doing in IMGUI to my UITK text fields.
I've got some more work to do with those as they are not turning themselves red when the input field can't be parsed as a number - which is what I want them to do
NewPeValueOSM.RegisterValueChangedCallback((evt) =>
{
if (float.TryParse(evt.newValue, out float newFloat))
{
NewPeValueOSM.style.color = Color.white;
_newPeValue = newFloat;
}
else
{
NewPeValueOSM.style.color = Color.red;
}
});```
I've got code like this to prevent dragging, which does work, but my coloring code does not
NewPeValueOSM.RegisterCallback<PointerDownEvent>(evt => evt.StopPropagation());
NewPeValueOSM.RegisterCallback<PointerUpEvent>(evt => evt.StopPropagation());
NewPeValueOSM.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation());```
mind giving me the line of code that does the blocking?
I'm just too lazy to go searching for it lmao
the code seems fine at a glance, does it run and it's just that the style isn't properly changing? or does the event not run at all?
GameInputState = !InputFields.Contains(GUI.GetNameOfFocusedControl());
What I've done before is to add the names of the controls that I want to affect to a list and then check this
I'm not sure if it's being activated. I'll add a breakpoint and see if it is.
or just a log line
GameInputState? that seems to be a property of something
ah got it, Game.Input.Enable/Disable();
document.rootVisualElement.Query<TextField>().ForEach(textField =>
{
textField.RegisterCallback<FocusInEvent>(_ => GameManager.Instance?.Game?.Input.Disable());
textField.RegisterCallback<FocusOutEvent>(_ => GameManager.Instance?.Game?.Input.Enable());
});
so technically this should help
Hang on, here's the trace
OnGUI calls this at the end
// check editor focus and unset Input if needed
UI_Fields.CheckEditor();```
CheckEditor is just this
```cs
static public void CheckEditor()
{
GameInputState = !InputFields.Contains(GUI.GetNameOfFocusedControl());
}```
InputFields is this
```cs
public static List<string> InputFields = new List<string>();```
already looked it up in FP code, but thanks 😆
Ahhh, yeah. You're so much faster than me!
you can try calling this after your create your window (document)
so like this then?
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;
document.rootVisualElement.Query<TextField>().ForEach(textField =>
{
textField.RegisterCallback<FocusInEvent>(_ => GameManager.Instance?.Game?.Input.Disable());
textField.RegisterCallback<FocusOutEvent>(_ => GameManager.Instance?.Game?.Input.Enable());
});
}```
Or would that need to be _container.rootVisualElement?
yeah, should work
Hmmm... I've got multiples of these
// pass = float.TryParse(NewPeValue.value, out _newPeValue);
NewPeValueOSM.RegisterValueChangedCallback((evt) =>
{
if (float.TryParse(evt.newValue, out float newFloat))
{
NewPeValueOSM.style.color = Color.white;
_newPeValue = newFloat;
}
else
{
NewPeValueOSM.style.color = Color.red;
}
});
NewPeValueOSM.value = _newPeValue.ToString();
NewPeValueOSM.RegisterCallback<PointerDownEvent>(evt => evt.StopPropagation());
NewPeValueOSM.RegisterCallback<PointerUpEvent>(evt => evt.StopPropagation());
NewPeValueOSM.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation());
FlightPlanPlugin.Logger.LogInfo($"InitializeElements: {testLog++}: NewPeValue.RegisterValueChangedCallback event initialized.");
// pass = float.TryParse(NewApValue.value, out _newPeValue);
NewApValueOSM.RegisterValueChangedCallback((evt) =>
{
if (float.TryParse(evt.newValue, out float newFloat))
{
NewApValueOSM.style.color = Color.white;
_newApValue = newFloat;
}
else
{
NewApValueOSM.style.color = Color.red;
}
});
NewApValueOSM.value = _newApValue.ToString();
NewApValueOSM.RegisterCallback<PointerDownEvent>(evt => evt.StopPropagation());
NewApValueOSM.RegisterCallback<PointerUpEvent>(evt => evt.StopPropagation());
NewApValueOSM.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation());```
Would there be some way to do this too like for the input blocking so I can just do it for all TextFields in one spot?
Maybe not for the value setting part, but for the color?
oh yeah, the Query method gets you a list of all elements in the hierarchy that fit what you search for, which can either be just the type in <...>, or the other arguments of the method - it takes the name of element or a class of the element
so you can either do it for all TextFields, or if you want to only apply it to some specific ones, you could give them all a class like .verify-number and then do something like document.rootVisualElement.Query<TextField>(className: "verify-number").ForEach(textField => DoSomething(textField));
it's basically the same method as element.Q, but it gives you all found elements instead of just the first one
there's more about it here, including examples
This mostly works
document.rootVisualElement.Query<TextField>().ForEach(textField =>
{
textField.RegisterCallback<FocusInEvent>(_ => GameManager.Instance?.Game?.Input.Disable());
textField.RegisterCallback<FocusOutEvent>(_ => GameManager.Instance?.Game?.Input.Enable());
textField.RegisterValueChangedCallback((evt) =>
{
if (float.TryParse(evt.newValue, out _))
{
textField.style.color = Color.white;
textField.contentContainer.style.color = Color.white;
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}. nValue = {evt.newValue}. setting color to white");
}
else
{
textField.style.color = Color.red;
textField.contentContainer.style.color = Color.red;
FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}. nValue = {evt.newValue}. setting color to red");
}
});
textField.RegisterCallback<PointerDownEvent>(evt => evt.StopPropagation());
textField.RegisterCallback<PointerUpEvent>(evt => evt.StopPropagation());
textField.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation());
});```
It definitely hits the code and reports back that it's changing the color, but there's no actual effect in the GUI
That's in SetupDocument, and this code in InitializeElemets seems to also work in that I'm getting appropriate log messages when I edit this field.
NewApValueOSM.RegisterValueChangedCallback((evt) =>
{
if (float.TryParse(evt.newValue, out float newFloat))
{
_newApValue = newFloat;
FlightPlanPlugin.Logger.LogInfo($"NewApValueOSM: {_newApValue}");
}
});```
@shadow tree , @bronze crater , I've got two threories. Either I'm trying to set the wrong thing for color (in which case it would help me to learn to find the right thing), or maybe I'm setting it but it's being stepped on by some other style. In the former case I need to modify my plugin code, in the latter presumably I need to moify the styles being applied to the visual element in the asset bundel - which means in the unity editor I think.
But the keyboard input blocking and preventing of dragging parts work fine
thanks for testing the input blocking part, I'll put it into UitkForKsp2 then
as for your style issue, it should definitely not be the second case, inline element-scoped styles should have precedence over any USS styles as far as I know
at least that's how it works in CSS and from what I've seen so far, I haven't had any reason to think it's otherwise here
i agree with munix it should be the first thing, but i don’t have access to any computers so i can’t really try anything out
Thanks guys. This helps as it rules out a line of inquiry.
I'll just need to sort out what is the right thing to poke and then procede to poke it as needed.
I mean I can't be 100% sure but call it an educated guess
If poking doesn't work I may prod...
oh and by the way, I tried out building the bundles from the files you sent me and I had no issues
@shadow tree where can I find any info about what to do with dropdown menus? I mean I can create them, but I'm not sure what to do to get info out of them. Apparently I can set up a handler for things like this TargetSelectionDropdown.RegisterValueChangedCallback(evt => { _selectedTarget = evt.currentTarget}), but what I'm doing for that event is a pure WAG. Is there documentation on how to use a dropdown? How to know it's been toyed with by the user and how to get the value they've selected?
I don't think you can do anything else than that event
though I don't get _selectedTarget = evt.currentTarget in your example
evt.currentTarget gives you the element on which the event was triggered, so in this case the dropdown
I would assume you probably want evt.newValue and evt.previousValue?
Thanks I'll give that a shot
@shadow tree / @dusty berry , is there any way to affect the un-clicked display of a dropdown? The Label property is just text that displays to the left of the dropdown, and in the case of my target selector dropdown that space is occupied by a button. What I'd like is to have the currently selected option shown in the gray box with the dropdown arrow if possible, or replacing the dropdown arrow if necessary.
the selected text should already be showing up there
(though with my in-editor testing the text was white and barely visible, so you just need to change its colors)
Ahhh, I'll look more closely then and see if it's actually there. Thanks
you can just start the live preview and try to choose an option to see it
(you can just set the choices attribute for testing)
oh nevermind, I see you already have it filled in
It must be something in my styles then, as what I've got is not working like what you're seeing...
OK, I've found it - or something that positively affects it. The solution I found was to add a style selector for .unity-base-popup-field__input and configure it like this
The only weird thing now is the clipping on the text as seen in the burn time option dropdown. There I picked "at cheapest Eq. node" from the list and you can see it displays only "at cheapest " and then a sliver of the "E" in "Eq. node"
I mean it has a set width in the image you sent
There's a right margin padding of 40!
oh 😄
But why???? I override that!
The grayed out Dropdown element for PopupTextElement shows it's right margin as 40
That's this part
Which is supposed to have these styles applied
Found it! Another style selector: .unity-base-popup-field__text. I'm able to control that stupid thing now too
@shadow tree While I can control the dropdown to show fine in preview by setting .unity-base-popup-field__text, it's not working in the actual game. I can pick things, and see in my debug logging that things are getting picked, but it acts like I haven't got this control applied at all. So, fine in unity preview, stomped on in the game. Is there anything I can to to try to convince the UI that it really really really should use the setting I'm giving it?
@marble shale, this is how I've done it, works good:
CategoryDropdown = Root.Q<DropdownField>("category__dropdown"); //get a reference to the control
CategoryDropdown.choices = Enum.GetNames(typeof(MicroEntryCategory)).ToList(); //define a list of strings to populate the control
CategoryDropdown.RegisterValueChangedCallback(BuildAvailableEntries); //specify method that will trigger on value changes
if (CategoryDropdown.value == null) ... //value property holds the selected value
or wait, are you talking about setting a style to the control?
for the styling, these 2 elements control how to text is displayed. I overrode .unity-popup-field__input and .unity-base-popup-field__text to get what I want.
Though I'm curious how to set the style for hovering list items you get when you're selecting something, since I cannot see visual elements for those in the hierarchy... but I didn't dig into this more deeply yet
Yes, that's what I'm doing too - overriding .unity-popup-field__input and .unity-base-popup-field__text. It works fine in the preview, but when I get into the game it's back to being like without the override, which makes the text selection invisible. For example, in the Unity editor I see this:
But in the game I get this:
My dropdown menues work in that you can use them to select something, and what you've selected will be known to the mod and can take effect, but they also don't work in that there's no visual feedback that what you've selected is selected except to go back into the dropdown and see there's now a check mark beside the selected option.
I've got these in my selectors. I'm not sure what's going on with the Dropdown > .unity-base-field__label one. I think that's one @dusty berry helped me with and has to do with getting the Dropdown to not show a label beside it as I need to set that separately. The bottom two are where I override .unity-popup-field__input and .unity-base-popup-field__text
well there is a visual feedback, text color is very very dark blue so it's hard to see 🙂
and what did you put in those 2 styles?
Ok, sure - no effective visual feedback.... 😛
This for the first
this is what I have:
.unity-base-popup-field__text {
font-size: 14px;
-unity-text-align: middle-center;
color: rgb(192, 199, 213);
}
.unity-popup-field__input {
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
width: 90%;
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
font-size: 10px;
-unity-text-align: middle-center;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
border-left-color: var(--yellowish-translucent-1);
border-right-color: var(--yellowish-translucent-1);
border-top-color: var(--yellowish-translucent-1);
border-bottom-color: var(--yellowish-translucent-1);
height: 20px;
}
what about text color in .unity-base-popup-field__text ?
set it manually, don't trust what it says it is 😛
I think I may be setting it with this...
Nope, never mind, that doesn't set text color either
I mean - here, click on the color and change it to something else
it says it's light blue right now, but don't trust it
Also, when I just set that to be the thing it says it is, the text gets dimmer
try it in game when it's set. Should be ok
I think I was able to find the color I'm using in the .unity-label selector and I've set it in thei selector now. I'll try rebuilding it with this
Yay! It works!
Though it's interesting that the text is coming up centered when in my preview it's left justified. I don't think I mind, but it's interesting.
yes, I too have some slight issues with alignment. Not everything is how it appears in unity
Do you do anything with custom fonts at all? My IMGUI UI uses a font character for one of my small buttons, and that character is apparently undefined in the standard UITK fonts. I'd like to find a font set that has it, but I'm not really sure how to do that.
I'm just using LEDCounter7 for window title, but that's it.
and these are special characters I copy-pasted from some website
but in your case, I'd say it would be easier to just convert that character to an imate. That circle thingy in MNC, right?
no, it was in resonant orbit calc.
oh it's in flight plan now, got it 🙂
yeah, those are fairly simple. You could even do it yourself in paint, photoshop or wherever in a minute
Yeah, it's a super simple shape. I should just whip it up as a png and be done with it.
@shadow tree, I've got some of my target selection using dictionaries approach working, but I'm getting NREs on a Clear() operation on the dictionary and that confuses me. What I do is this (within my FpUiController class)
private static List<VesselComponent> allVessels;
private static List<PartComponent> allPorts;
private static List<CelestialBodyComponent> allBodies;
private static List<string> targets;
private static Dictionary<string, VesselComponent> targetVessels;
private static Dictionary<string, PartComponent> targetPorts;
private static Dictionary<string, CelestialBodyComponent> targetBodies;
private static SimulationObjectModel thisVessel = null;
public static bool SelectTarget, doNewList;
public static bool SelectDockingPort = false;
void ListBodies()
{
CelestialBodyComponent _rootBody = _activeVessel.mainBody;
while (_rootBody.referenceBody != null)
{
_rootBody = _rootBody.referenceBody;
}
// allBodies.Clear();
targetBodies.Clear();
ListSubBodies(_rootBody, 0);
}
void ListSubBodies(CelestialBodyComponent body, int level)
{
foreach (CelestialBodyComponent sub in body.orbitingBodies)
{
string tabs = new string('\t', level);
// allBodies.Add(sub);
targetBodies.Add(tabs + sub.Name, sub);
ListSubBodies(sub, level + 1);
}
}```
It's barfing on the targetBodies.Clear(); line, NREs
Ahh, so wrap that in a test for null, then after the first time it will be set.
not really, you aren't setting the value for it anywhere
there is no targetBodies = ...
what about this? targetBodies.Add(tabs + sub.Name, sub);
that doesn't initialize the field, you're calling an Add method on null
you need to first assign a value to the field to be able to do anything with it
private static Dictionary<string, CelestialBodyComponent> targetBodies = new();
if there's no =, it's null
it's basically a glorified pointer, and if you don't create a new object and assign its reference to the field, it is basically a null pointer
With ports and vessels I do this, so maybe those are OK? targetPorts = allPorts.ToDictionary(x => x.Name, x => x);
Cool. Testing now. I'll have this thing working in UITK soon
though it needs to happen before you try to call "Clear" on it
if you do
but you probably don't need that
I don't call Clear on those, just assign to them
Is there a way to make the BepInEx logger spit out a list of strings or dictionary keys? I'm getting this from my foolish attempt to logg the results of what I'm doing:
[Info :Flight Plan] TargetType: Setting to Target Type to 'Vessel' [Info :Flight Plan] Choices: System.Collections.Generic.List1[System.String]
[Error : Unity Log] NullReferenceException: Object reference not set to an instance of an object
Stack trace:
FlightPlan.FpUiController.TargetType () (at C:/KSP2Mods/FlightPlan/FlightPlanProject/FlightPlanPlugin.cs:2198)`
no, you need to convert it to a string
from this code
else
{
TargetTypeButton.text = "Vessel";
ListVessels();
TargetSelectionDropdown.choices = new List<string>(targetVessels.Keys);
FlightPlanPlugin.Logger.LogInfo($"TargetType: Setting to Target Type to 'Vessel'");
FlightPlanPlugin.Logger.LogInfo($"Choices: {TargetSelectionDropdown.choices}");
FlightPlanPlugin.Logger.LogInfo($"Keys: {targetPorts.Keys}");
}```
like this?
FlightPlanPlugin.Logger.LogInfo($"Choices: {TargetSelectionDropdown.choices.ToString()}");
FlightPlanPlugin.Logger.LogInfo($"Keys: {targetPorts.Keys.ToString()}");```
that's exactly the same thing as before
Yeah, I was afraid of that...
if you try to put any object inside a string, ToString() will get called automatically in the background
so that was the result you got
just call string.Join("your separator", targetPorts.Keys)
Close! That works great on the list of strings, but not working on the keys. I'll fiddle with it, but at least I've confirmed the right stuff seems to be going into choices now
aren't your Keys strings?
they are.
argetPorts = allPorts.ToDictionary(x => x.Name, x => x);
The first lambda is the key, right?
I think I see the problem, but I also think it's moot. When I set TargetSelectionDropdown.choices = new List<string>(targetVessels.Keys) I need to wrap targetVessels.Keys inside a List<string>(). I may need to do the same with the logger, but what's the point since I'm setting choices to this anyway. It would just be redundant.
btw you can also just use
TargetSelectionDropdown.choices = targetVessels.Keys.ToList();
that method should be available on any IEnumerable
@shadow tree , I need to be able to programmatically set the color and alpha of a label in my FP UI. When I try googling how to do this I get info on IMGUI. How can I do this, and also where can I find info like this so I don't just keep pinging you?
nvm! Figured it out. Thios is workiong for me
// Indicate Status of last GUI function
float _transparency = 1;
if (_UT > FPStatus.StatusTime) _transparency = (float)MuUtils.Clamp(1 - (_UT - FPStatus.StatusTime) / FPStatus.StatusFadeTime.Value, 0, 1);
Color textColor = new Color(1,1,1,1);
if (FPStatus.status == FPStatus.Status.OK)
textColor = new Color(0, 1, 0, _transparency);
if (FPStatus.status == FPStatus.Status.WARNING)
textColor = new Color(1, 1, 0, _transparency);
if (FPStatus.status == FPStatus.Status.ERROR)
textColor = new Color(1, 0, 0, _transparency);
Status.text = FPStatus.StatusText;
Status.style.color = textColor;```
The color and transparency seem to work fine with this method.
I'd suggest creating a new style in Unity and then add it in runtime with status.AddToClassList("your-class-name"); That way you keep all the styles in the uss file.
Would that work for something where I'm dynamically playing with the transparency as I am here? Would I then just update the style dynamically?
You define styles you'd like to use in runtime. For example .warning, .ok, .error, you define color you want in those 3 styles (in uss). And then in runtime you add or remove them when you need to with AddToClassList("warning"); and RemoveFromClassList("warning");
If all all I wanted to do was pick a color and set it, that would work - but it's more complicated than that. In this case I have a status message that I display in some color (red, yellow, green), but in addition to the color I also dynamically vary the transparency so that it starts out fully visible for FPStatus.StatusTime seconds, then after it's been displayed for that long it begins to fade out over the next FPStatus.StatusFadeTime.Value seconds. Nifty, huhj? So, the transparency is literally changing on every update between those two times.
New (bizzare) issue. My UITK GUI for FP is nearly complete. I'm at the point where I can test it and see that everything (well... almost everything) is working. One odd thing is that no matter what I set the new inclination value to be, it assumes it's zero. I've been up and dowm my code making strong use of vs's Find All References feature and I'll be damned if I can figure out why this one bugger doesn't work when all the others do. It could be a (must be?) a dumn typo staring me in the face - but I've not found it yet.
Interesting. If color (transparency) needs to change every frame and slowly fade out, then yes, I'd to it in runtime as well. Though I'm curious if it could be also handled by uss somehow too. I'm guessing it can't
I can plug numbers into any of these fields (well, I've not tested New LAN yet, but it's next) and I get what I expect.
I also get my log spammed with styupid unity warnings that I definitely don't need
When I call MakeNode (press Make Node button) it's running this code
case ManeuverType.newInc:// Working
double.TryParse(NewIncValueOSM.value, out double stupidInc);
if (stupidInc != FPSettings.TargetInc_deg)
{
FlightPlanPlugin.Logger.LogInfo($"WTF MF? stupidInc = {stupidInc} =/= FPSettings.TargetInc_deg = {FPSettings.TargetInc_deg}");
FPSettings.TargetInc_deg = stupidInc;
}
_pass = FlightPlanPlugin.Instance.SetInclination(_requestedBurnTime, FPSettings.TargetInc_deg, -0.5);
break;```
If the NewIncValueOSM field were different than the FPSettings.TargetInc_deg it would tell me, but it doesn't and I get 0 when I can plainly see it's 30.
And the logging above also shows that 30 get's in - which happens here:
NewIncValueOSM.RegisterValueChangedCallback((evt) =>
{
if (float.TryParse(evt.newValue, out float newFloat))
{
FPSettings.TargetInc_deg = newFloat;
FlightPlanPlugin.Logger.LogInfo($"NewIncValueOSM: {FPSettings.TargetInc_deg}");
}
else
FlightPlanPlugin.Logger.LogInfo($"NewIncValueOSM: unable to parse '{evt.newValue}'");
});
There's another place it's effectively checked, too which is here
textField.RegisterValueChangedCallback((evt) =>
{
if (float.TryParse(evt.newValue, out _))
{
textField.style.color = Color.white;
textField.contentContainer.style.color = Color.white;
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}. nValue = {evt.newValue}. setting color to white");
}
else
{
textField.style.color = Color.red;
textField.contentContainer.style.color = Color.red;
FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}. nValue = {evt.newValue}. setting color to red");
}
});```
Which, BTW does NOT set the color to red when the value can't be parsed - a separate issue...
I've hunted through the code for every place where FPSettings.TargetInc_deg is written to and accounted for them all. How can this one thing not be working when all the others work perfectly?
@tough jacinth , you know - your color suggestion may help with setting the color of fields that are not parsing correctly. Certainly the code I've got is failing to fix it - no clue why.
Hard to figure out by just reading through this... what type are NewIncValueOSM and FPSettings.TargetInc_deg?
public static double TargetInc_deg
{
get => KBaseSettings.SFile.GetDouble("TargetInc_deg", 0);
set { KBaseSettings.SFile.SetDouble("TargetInc_deg", value); }
}```
NewIncValueOSM = _container.Q<TextField>("NewIncValueOSM");```
Worth a shot.
.text is the label for the input I think. Both .value and .text are type string
I'm using .text for my TextFields. I remember a while ago trying with .value and something wasn't working
Oh and I'm also close to finishing UITK rewrite for MicroEngineer. Hoping to release a prerelease soon. It took waaay much longer than I anticipated.
Same!
MNC was easy comparted to FP.
Starting from scratch isn't so bad, but refactoring soooo much stuff...
Yeah, and I'm rewriting part of the logic since it was sometimes coupled with UI
Yeah, stuff gets woven the first time through and then you have to untangle it..
Hey, are you getting a weird flickering effect all over the games UI at times? I'm seeing that and I can't figure what's causing it. Might be new in 0.1.3, might be UITK, no clue
It's intermittent for me, but I could probably make a video of it
Nope, can't say that I am
Where is the vector part of the root window where I might be able to adjust the z? I've only found the rect which has height, width, x, and y.
UIDocument.rootVisualElement[0].transform.position
you can also try with RectTransform rectTransform = UIDocument.GetComponent<RectTransform>(); (replace UIDocument with the instance of your UIDocument class.
but again, haven't tried it
and I'm off for the night, cya
@shadow tree , I seems I'm doing something really bad in my target selection code. Currently I've got this:
TargetSelectionDropdown.RegisterValueChangedCallback(evt =>
{
if (TargetTypeButton.text == "Celestial")
{
_activeVessel.SetTargetByID(targetBodies[evt.newValue].GlobalId);
_currentTarget = _activeVessel.TargetObject;
}
else if (TargetTypeButton.text == "Vessel")
{
_activeVessel.SetTargetByID(targetVessels[evt.newValue].GlobalId);
_currentTarget = _activeVessel.TargetObject;
}
else if (TargetTypeButton.text == "Port")
{
_activeVessel.SetTargetByID(targetPorts[evt.newValue].GlobalId);
_currentTarget = _activeVessel.TargetObject;
}
FlightPlanPlugin.Logger.LogInfo($"Selected Target: {_currentTarget.Name}");
});```
Where targetBodies is set like this
void ListBodies()
{
CelestialBodyComponent _rootBody = _activeVessel.mainBody;
while (_rootBody.referenceBody != null)
{
_rootBody = _rootBody.referenceBody;
}
// allBodies.Clear();
if (targetBodies != null)
targetBodies.Clear();
ListSubBodies(_rootBody, 0);
}
void ListSubBodies(CelestialBodyComponent body, int level)
{
foreach (CelestialBodyComponent sub in body.orbitingBodies)
{
string tabs = new string(' ', level * 2);
// allBodies.Add(sub);
targetBodies.Add(tabs + sub.Name, sub);
ListSubBodies(sub, level + 1);
}
}```
All three of the target selection branches seem to be broken, this is just how a celestial target is set - which seems provoke an endless stream of warnings in map view vs. and endless stream of NREs
I don't see the value of targetBodies being set anywhere
do you set it in the field definition line?
yes
private static Dictionary<string, CelestialBodyComponent> targetBodies = new();```
#🔴mod-dev message
I'd have to go back and double check, but I believe what I'm doing here is basically the same thing I did in the IMGUI version in that there's a call to _activeVessel.SetTargetByID followed by setting the _currentTarget = _activeVessel.TargetObject;
Is this possibly a problem? When I set allVessels to the return from GetAllVessels() am I getting a new fewsh copy of that list, or am I possibly grabbing the actual list and stomping on it?
else
{
// Make a list of all vessels other than this one
// allVessels = GameManager.Instance.Game.SpaceSimulation.UniverseModel.GetAllVessels();
allVessels = Game.SpaceSimulation.UniverseModel.GetAllVessels();
allVessels.Remove(_activeVessel);
allVessels.RemoveAll(v => v.IsDebris());
targetVessels = allVessels.ToDictionary(x => x.Name, x => x);
}
should it be something like allVessels = new Game.SpaceSimulation.UniverseModel.GetAllVessels();
well have you tried debugging what you're getting in the individual steps? like evt.newValue, targetBodies[evt.newValue], targetBodies[evt.newValue].GlobalId etc
Not yet, but of course I can.
yeah that's a pretty good question
public List<VesselComponent> GetAllVessels()
{
return _allVessels.ValuesList;
}```
I'm not sure but it's possible you're removing it from the game's vessel list
That was my thought just now. It could explain some of the insanity I'm seeing.
if anything, you should probably just be calling allVessels.Filter to get a new copy of the list without some elements
rather than modifying the original with .Remove
Oh, that might do it.
I've not used Filter before, but I'll give that a try
Where can I find info on how to use the Filter method?
There doesn't seem to be a .Filter method on this list...
Ahh!
I guess it's just easier to get into with (some amount of) knowledge of Java, C++, PHP, etc
How's this look?
else
{
// Make a list of all vessels other than this one
allVessels = Game.SpaceSimulation.UniverseModel.GetAllVessels();
// allVessels.Remove(_activeVessel);
// allVessels.RemoveAll(v => v.IsDebris());
targetVessels = allVessels.Where(v => !v.IsDebris()).Where(v => v.GlobalId != _activeVessel.GlobalId).ToDictionary(x => x.Name, x => x);
}```
I assume I just have multiple Where() calls to filter like this
it should work as well, but I think that will make it iterate through the list twice, where you could just have allVessels.Where(v => !v.IsDebris() && v.GlobalId != _activeVessel.GlobalId) to iterate once
Ahh, that would be better! Thanks!
though it's also possible that there's some optimizations in the background for these LINQ queries, I can't say for sure
yeah, they are like a generic API for querying/transforming IEnumerables, is my understanding of it, and you can either use this functional style, or you could also write it in the query form like
targetVessels =
(from vessel in allVessels
where !vessel.IsDebris()
&& vessel.GlobalId != _activeVessel.GlobalId
select vessel).ToDictionary(v => v.Name, v => v);
it's basically an SQL-like language for dealing with .NET collections
I think I've got things working well in FlightPlan now, though I do still get spammed with Unity debug warnings whenever in map view with a celestial body selected. Not really sure why that is, but I suspect it's outside my code. Is there a way to suppress those debug warnings in the console? I thought I'd turned off the debug log level in the BepInEx config.
Well that only applies to BepInEx logs
And these come from the game/Unity engine instead
So BepInEx has nothing to do with them really
You'd have to probably do something like Harmony patch the Unity logging methods to get rid of it
I'll run a test unmodded to see what happens when I select a celestial target in the normal way. If this spam doesn't show up that way, then presumably I'm doing it differently, and thus perhaps wrong, in FP. At least the vessel/part selection is working better now!
FYI, with all mods disabled I see the unity debug spam in map mode with a celestial target selected. I haven't tried this in a completely unmodded game, just with all mods disabled, as it's a minor PITA to branch off a copy of the unmodded game and make that a debug version with a console - not really a big deal, just annoying enough that I haven't done it... yet.
@shadow tree / @dusty berry , I'm still struggling to get a tryparse test of text input fields that will actually have the effect I want. In the IMGUI version of the mod I can do this pretty easily and turn the text in the input field as well as the border around the text red as a visual clue to the player that what they've typed doesn't parse. I'm easily able to perform the necessary try parse test in the UITK version, but so far completely unable to have even the slightest impact on the color the god damn text input field. @tough jacinth suggested creating a custom style in the Unity editor and applying that, but I've not figured out how to make that work. Right now, what I've got is this.
document.rootVisualElement.Query<TextField>().ForEach(textField =>
{
textField.RegisterCallback<FocusInEvent>(_ => GameManager.Instance?.Game?.Input.Disable());
textField.RegisterCallback<FocusOutEvent>(_ => GameManager.Instance?.Game?.Input.Enable());
textField.RegisterValueChangedCallback((evt) =>
{
bool pass = false;
FlightPlanPlugin.Logger.LogInfo($"TryParse attempt for {textField.name}. Tooltip = {textField.tooltip}");
if (textField.tooltip != "Time in hh:mm:ss format")
pass = float.TryParse(evt.newValue, out _);
else
pass = TimeSpan.TryParse(evt.newValue, out _);
if (pass)
{
// textField.style.color = Color.white;
// textField.contentContainer.style.color = Color.white;
textField.style.backgroundColor = Color.black;
textField.style.borderBottomColor = Color.white;
textField.style.borderTopColor = Color.white;
textField.style.borderLeftColor = Color.white;
textField.style.borderRightColor = Color.white;
textField.style.unityTextOutlineColor = Color.white;
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}. nValue = {evt.newValue}. setting color to white");
}
else
{
// textField.style.color = Color.red;
// textField.contentContainer.style.color = Color.red;
textField.style.backgroundColor = Color.red;
textField.style.backgroundColor = Color.black;
textField.style.borderBottomColor = Color.white;
textField.style.borderTopColor = Color.white;
textField.style.borderLeftColor = Color.white;
textField.style.borderRightColor = Color.white;
textField.style.unityTextOutlineColor = Color.white; FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}. nValue = {evt.newValue}. setting color to red");
}
});```
I first tied the commented out lines, but they had no effect, so I tried the new lines that follow those - which similarly have no effect.
Is there something in a textField that I can poke to set the color? I've explored around inside that stucture and not found anything yet. There's a customStyle field, but all I can to is get it, not set it. There's a Children() method, but it applied to VisualElements and I'm not sure how to use that.
have you tried just making a new class with the desired styles, making sure the text field with the class looks like you want it to in the builder, and then just adding/removing the class itself during runtime?
that's what I do in the mod list
I have not. I'm not entirely certain I understand what you're suggesting.
Is this something that replaces TextField in the unity editor?
Like making my own custom control and then using that?
Oh good, that sounded like a lot of work.
USS class, not C# class
I think you're suggesting something along the lines of what Falki suggested - possibly the exact same thing
I think I can make such a class, but I'm unclear what to do with it. Suppose I play around in the editor and make one and see in preview that it has the effect I want, what then?
How can I programmatically apply it?
element.AddToClassList("class-name");
and RemoveFromClassList
I'm assuming
you can just google if that exists, I'm not sure
Ok, but I want to apply it to only the input field and not the label, however I've only got access to the whole enchilada.
well then just write the class so it affects only the input field
Ahh, so make a class that, when applied to the whole enchilada, only affects the text input field. This makes sense in principle.
If I can accomplish that in the unity editor then I think I may actually be able to make this work. I'm going to go work on that.
yeah you can just do something like .unity-text-field.invalid > .unity-text-field__input {...}
maybe will need more specificity, not sure
gotta experiment with it
Well, that's a good clue to get me started. As I tend to be pretty clueless with the stylesheet this helps me a lot.
OK! Getting somewhere! I've got this that seems to work when applied.
No effect...
document.rootVisualElement.Query<TextField>().ForEach(textField =>
{
textField.RegisterCallback<FocusInEvent>(_ => GameManager.Instance?.Game?.Input.Disable());
textField.RegisterCallback<FocusOutEvent>(_ => GameManager.Instance?.Game?.Input.Enable());
textField.RegisterValueChangedCallback((evt) =>
{
bool pass = false;
FlightPlanPlugin.Logger.LogInfo($"TryParse attempt for {textField.name}. Tooltip = {textField.tooltip}");
if (textField.tooltip != "Time in hh:mm:ss format")
pass = float.TryParse(evt.newValue, out _);
else
pass = TimeSpan.TryParse(evt.newValue, out _);
if (pass)
{
textField.RemoveFromClassList(".unity-text-field-invalid");
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}. nValue = {evt.newValue}. setting color to white");
}
else
{
textField.AddToClassList(".unity-text-field-invalid");
textField.style.unityTextOutlineColor = Color.white; FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}. nValue = {evt.newValue}. setting color to red");
}
});
textField.RegisterCallback<PointerDownEvent>(evt => evt.StopPropagation());
textField.RegisterCallback<PointerUpEvent>(evt => evt.StopPropagation());
textField.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation());
});```
I may be very close to getting this to work, but there's something I'm doing wrong here. I can drop that style onto the visual element I want it to effect and see the effect in preview, but in game nothing.
With my new style class applied to one of the input text fields in the unity editor, the UI starts with that field red, but also doesn't remove the class when the field is parsing correctly
Similarly when messing with another text field that doesn't start with this class applied in the unity editor I get this
It seems I can apply this class in the unity editor and see exactly the effect I want, but I'm unable to add or remove it from the element in a way that makes the mod behave as I want. The logic for when to apply or remove is working fine, just not the AddToClassList or RemoveFromClassList
textField.RegisterValueChangedCallback((evt) =>
{
bool pass = false;
FlightPlanPlugin.Logger.LogInfo($"TryParse attempt for {textField.name}. Tooltip = {textField.tooltip}");
if (textField.tooltip != "Time in hh:mm:ss format")
pass = float.TryParse(evt.newValue, out _);
else
pass = TimeSpan.TryParse(evt.newValue, out _);
if (pass)
{
textField.RemoveFromClassList(".unity-text-field-invalid");
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}. nValue = '{evt.newValue}': Removed .unity-text-field-invalid from class list");
}
else
{
textField.AddToClassList(".unity-text-field-invalid");
FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}. nValue = '{evt.newValue}': Added .unity-text-field-invalid to class list");
}
});```
Tried changing the Add/Remove to this, still no effect.
textField.RegisterValueChangedCallback((evt) =>
{
bool pass = false;
FlightPlanPlugin.Logger.LogInfo($"TryParse attempt for {textField.name}. Tooltip = {textField.tooltip}");
if (textField.tooltip != "Time in hh:mm:ss format")
pass = float.TryParse(evt.newValue, out _);
else
pass = TimeSpan.TryParse(evt.newValue, out _);
if (pass)
{
textField.RemoveFromClassList(".unity-text-field-invalid > .unity-base-text-field__input");
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}. nValue = '{evt.newValue}': Removed .unity-text-field-invalid from class list");
}
else
{
textField.AddToClassList(".unity-text-field-invalid > .unity-base-text-field__input");
FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}. nValue = '{evt.newValue}': Added .unity-text-field-invalid to class list");
}
});```
@shadow tree / @dusty berry / @tough jacinth : Huzzah! It works! The trick, which wasn't apparent to me at first, is that you must not include the leading "." in the style name! This works!
textField.RegisterValueChangedCallback((evt) =>
{
bool pass = false;
FlightPlanPlugin.Logger.LogInfo($"TryParse attempt for {textField.name}. Tooltip = {textField.tooltip}");
if (textField.tooltip != "Time in hh:mm:ss format")
pass = float.TryParse(evt.newValue, out _);
else
pass = TimeSpan.TryParse(evt.newValue, out _);
if (pass)
{
textField.RemoveFromClassList("unity-text-field-invalid");
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}. nValue = '{evt.newValue}': Removed unity-text-field-invalid from class list");
}
else
{
textField.AddToClassList("unity-text-field-invalid");
FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}. nValue = '{evt.newValue}': Added unity-text-field-invalid to class list");
List<string> classList = new(textField.GetClasses());
// FlightPlanPlugin.Logger.LogInfo($"{textField.name} classList = {classList}");
for (int i = 0; i < classList.Count(); i++)
FlightPlanPlugin.Logger.LogInfo($"{textField.name} Class {i} = {classList[i]}");
}
});```
Only by looking at all the classes applied was I able to deduce that the name in the Unity editor maps to a slightly different name in the game, and all that was needed was to remove the leading "." that I had to get this to work.
nice!
@shadow tree, I'm in the home stretch getting FP converted to UITK. The one thing remaining is in the Advanced Planetary Transfer option (which wasn't completely working before, but was at least generating porkchop plots). I've got things where if you click that button it will make a part of the UI visible that looks like what was being displayed previously, and even better it will report the "worker" progress in % as it computed the porkchop, but it's at that point that it falls appart.
I'm generating a 2D texture, and the opld IMGUI code is no beuno with the new UITK GUI. I'm looking for a way to assign the texture generated to be the background image of the visual element I've created for the plot.
Is that more or less the right approach?
Yeah, it's my guess and worth a shot, but so far I don't know how to even find where to set the background image
I can set it in Unity Editor obviously
so you have a texture2D generated at runtime and you can't seem to get it onto the visual element?
Yes!
oh thats easy
i just need to get the right way
but basically
you just have to convert your texture2d Into a background image
public void DoGUI()
{
// old IMGUI way - don't do this!
GUILayout.Box(_texture, GUIStyle.none, GUILayout.Width(_texture.width), GUILayout.Height(_texture.height));
// do stuff to convert texture2d to background image
// assign background image to visual element
FpUiController.PorkchopDisplay.contentContainer.?```
So, DoGUI get's called to put the plot on there when event is repaint
The VisualElement I want to affect is FpUiController.PorkchopDisplay
Background.FromTexture2D(your texture here)
something like this?
FpUiController.PorkchopDisplay.Background.FromTexture2D(_texture);```
Right now it's telling me there's no such thing as .Background in PorkchopDisplay
FpUiController.PorkchopDisplay.style.backgroundImage = Background.FromTexture2D(_texture);
OK, cool! We're getting somewhere! What would the using be to get Background? It's not using UitkForKsp2.API;
Found it! using UnityEngine.UIElements;
No I just need to figure out how to get the mouse position in the visual element. The old IMGUI way was this...
if (Event.current.type == EventType.Repaint)
{
HoveredPoint = null;
Rect rect = GUILayoutUtility.GetLastRect();
rect.x += 1;
rect.y += 2;
Vector2 mouse = Event.current.mousePosition;
if (rect.Contains(mouse))
{
Vector2 pos = mouse - rect.position;
HoveredPoint = new[] { (int)pos.x, (int)(rect.height - pos.y - 1) };
}
else
{
if (_mouseDown && _lastHoveredPoint != null)
{
// zoom the selection box if we leave the area when mouse is down
ZoomSelectionBox(_lastHoveredPoint);
}
}```
I'm guessing there's a way to get the rect from the VisualElement, and then maybe the rest is about the same
This perhaps? We'll see
// Rect rect = GUILayoutUtility.GetLastRect();
Rect rect = FpUiController.PorkchopDisplay.contentRect;
At all time. As the user moves the mouse over the porkchop plot I'll be displaying the deltaV needed if they were to select that point
So I also need to know when the click a point, where did they click - but that should be the same as where is the mouse rn
There is this in the old MJ code
if (_mouseDown)
{
//GUI.Box(new Rect(rect.x + Math.Min(SelectedPoint[0], HoveredPoint[0]),
// rect.y + rect.height - Math.Max(SelectedPoint[1], HoveredPoint[1]),
// Math.Abs(SelectedPoint[0] - HoveredPoint[0]),
// Math.Abs(SelectedPoint[1] - HoveredPoint[1])), "", _selectionStyle);
FpUiController.PorkchopDisplay.contentRect = new Rect(rect.x + Math.Min(SelectedPoint[0], HoveredPoint[0]),
rect.y + rect.height - Math.Max(SelectedPoint[1], HoveredPoint[1]),
Math.Abs(SelectedPoint[0] - HoveredPoint[0]),
Math.Abs(SelectedPoint[1] - HoveredPoint[1])), "", _selectionStyle);
}```
Where I commented out the old MJ way and attempted to make it do the same in UITK - this is wrong...
I see that it doesn't want to let me set contentRect only get.
that
theres probably an easy way
with probably an event
but i havent played with it yet
Getting a lot closer! This works for getting the mouse position in the VisualElement
if (Event.current.type == EventType.Repaint)
{
HoveredPoint = null;
// Rect rect = GUILayoutUtility.GetLastRect();
Rect rect = FpUiController.PorkchopDisplay.contentContainer.worldBound;
rect.x += 1;
rect.y += 2;
Vector2 mouse = Event.current.mousePosition;
if (rect.Contains(mouse))
{
Vector2 pos = mouse - rect.position;
HoveredPoint = new[] { (int)pos.x, (int)(rect.height - pos.y - 1) };
FlightPlanPlugin.Logger.LogInfo($"HoveredPoint: ({HoveredPoint[0]}, {HoveredPoint[1]})");
}
else
{
if (_mouseDown && _lastHoveredPoint != null)
{
// zoom the selection box if we leave the area when mouse is down
ZoomSelectionBox(_lastHoveredPoint);
}
}
Turns out Rect rect = FpUiController.PorkchopDisplay.contentRect just get's you the size of the rect, but not where it is in the game's screen. By using .contentContainer.worldBound I can get where the VisualElement is on the screen and then use that to see if the mouse is inside it. I'm able to get logging out for the mouse position, and already it's updating the deltaV displaid accordingly, but so far no action when clicked.
I need to make my FpUiController.PorkchopDisplay not draggable, but still able to let me know when the mouse is up or down. I'm doing something about like that with all my TextField objects in SetupDocument like this:
document.rootVisualElement.Query<TextField>().ForEach(textField =>
{
textField.RegisterCallback<FocusInEvent>(_ => GameManager.Instance?.Game?.Input.Disable());
textField.RegisterCallback<FocusOutEvent>(_ => GameManager.Instance?.Game?.Input.Enable());
textField.RegisterValueChangedCallback((evt) =>
{
bool pass = false;
FlightPlanPlugin.Logger.LogDebug($"TryParse attempt for {textField.name}. Tooltip = {textField.tooltip}");
if (textField.tooltip != "Time in hh:mm:ss format")
pass = float.TryParse(evt.newValue, out _);
else
pass = MyTryParse(evt.newValue, out _);
if (pass)
{
textField.RemoveFromClassList("unity-text-field-invalid");
FlightPlanPlugin.Logger.LogInfo($"TryParse success for {textField.name}, nValue = '{evt.newValue}': Removed unity-text-field-invalid from class list");
}
else
{
textField.AddToClassList("unity-text-field-invalid");
FlightPlanPlugin.Logger.LogInfo($"TryParse failure for {textField.name}, nValue = '{evt.newValue}': Added unity-text-field-invalid to class list");
FlightPlanPlugin.Logger.LogInfo($"document.rootVisualElement.transform.position.z = {document.rootVisualElement.transform.position.z}");
}
});
textField.RegisterCallback<PointerDownEvent>(evt => evt.StopPropagation());
textField.RegisterCallback<PointerUpEvent>(evt => evt.StopPropagation());
textField.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation());
});```
Would it be possibly that all I need is something like PorkchopDisplay.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation())?
Nope...
Curiously... This seems to be working, or getting me closer. I'm still able to get hovered points out and the zoom window code is trying to do something, but it's also bogging down with recalculation.
PorkchopDisplay.RegisterCallback<PointerDownEvent>(evt => evt.StopPropagation());
PorkchopDisplay.RegisterCallback<PointerUpEvent>(evt => evt.StopPropagation());
PorkchopDisplay.RegisterCallback<PointerMoveEvent>(evt => evt.StopPropagation());```
well, you should probably have all the code inside those handlers, not split across multiple ones
so if you want something to keep happening while the mouse is down, do it in the first handler and then call StopPropagation
I think
well actually not really while the mouse is down, but you know what I mean
Yeah... I see. I've been kinda focused on making what I've got work, but that gives me a bastardized blend of things since what I've got for this part was built to work with IMGUI
It's quite a mess right now. Due, in large part, to my not fully understanding what all of the MJ code is really trying to do and so I just try to find a UITK equivalent when what I probably need here is a full overhaul to just do it the new way period.
This is curious..
The interesting things here are that (a) the worker is getting called a lot to recalculate stuff, ans well as (b) that I'm able to zoom in - though it takes a lot longer than it should. The Reset button will get you back, though it takes longer than it should too
I had thought I was turning off the display for the worker when it wasn't needed, but maybe not?
Offtopic, but, how do you get BepInEx's log in a separate window like that?
in its configuration
theres an option for that
idk if it shows in game, i always change that in the config folder
probably not yeah, maybe just have a bool that you set true or false when its open or clsoed
found it, thanks!
Hey, I've switched my font from JetBrains to Ariel, and added the ariel.ttf file to my font assets, but I'm getting this warning spamming my log
[Warning: Unity Log] Font not found for path: FontAssets/DynamicOSFontAssets/GlobalFallback/OSX/Arial SDF [Warning: Unity Log] Font not found for path: FontAssets/DynamicOSFontAssets/GlobalFallback/OSX/Arial SDF
This is kinda curious since it says it's using something from OSX, but I'm booted into Windows and my Windows install can't even see the OSX install I've got - but whatever.
I suspect what I need to do is to make or find and install an Ariel SDF, but I don't know how.
I expect I'll need to do that with another TTF I've installed.
@shadow tree what do I need to do here to make Unity happy?
Oh wait.. I think I found it! Create > Text > Font Asset, right?
yeah
the dynamic OS font assets stuff doesn't really mean anything
it just means that if a user has macOS and the font you want to use is not available, it will try to use the Arial font from the system
or something like that
Curiously, as soon as I created the Ariel SDF it seemed to have picked that up. I didn't need to change this in the inspector.
But I did for my use of Orbitron Black here
by the way, I'm not 100% sure, but I think you shouldn't redistribute Arial and you'd need to buy a license to use the font that way
the fact that it comes for free with your OS only means that the maker of the OS paid for the license, but not you
No, wait. I see what's going on... There's an Ariel.SDF that's in Unity, but I'm not sure it works. The one I made is ariel.SDF (lowercase)
you should be able to use the system-installed variant
Good to know. Thankfully Orbitron is distributed for free and licensed for commercial and personal use so I won't need to worry about that. I'll need to sort out what I'm doing with Ariel, though.
Liberation Sans might be better, since it's made to look the same as Arial, but it's free
I saw that one, and it's a possibility
Here's a wierd thing. When I set the Font Asset in the inspector for a sytle I've got (.unity-label), it seems to be there, but if I move off that an back to it then it's gone and I see this.
I see the same thing wehn inspecting something that has .unity-label applied to it
by the way if you're setting Font Asset, you shouldn't/don't need to set the Font
how does the USS for it look before/after?
Why do they have both? Is it preferred or better to set the asset?
this explains it a bit
and just in general, I haven't had any luck getting "Font" to work, while "Font Asset" works just fine in-game
OK, so use font assets is preferred, but it should work seemlessly regardless.
This is frustraiting. Setting Font Asset just does not take. I can set it, and it looks set, but even if I close with save, and reopen the GD thing is set to None
just try setting it manually in the USS then
Setting Font is the only reliable way I've got to set it in the editor and actually have it stay f-ing set
What does that mean?
open your USS file, find the selector that you want to apply it to, and add -unity-font-definition: url("/Assets/your/path/font-asset-file.asset");
yeah I mean I can't help much with the editor, I've only written the USS by hand
OMG, this stupid thing fucked over my title! Gaaaaaa!
Worse, it fucked it over before I did the close and save, so no amount of Ctrl Z will save me now...
I know now what was fucking it. It was setting the Font Asset to the one I created from the Orbitron TTF. Unsetting that make it work fine.
@shadow tree , I've removed the ariel.ttf and SDF from my package, and hand edited FlightPlanTheme.uss to have zero references to ariel, replacing them all with references to LiberationSans (which is installed in the /Assets/Themes/Fonts folder). I'm getting a massive number of warnings (201) and some errors (7) when I build the project, and some of them refer to Ariel SDF. I'm kind of at a loss for how to even track these down. Double clicking on one of the Ariel warnings takes me to SetPropertyReader.cs.
I don't appear to have any references to ariel in the uxml either
loading the project gives me a smaller number of warnings (42), but a larger number of errors (13). Not sure what to do to track these down.
Oh, this is bizzare... the warning count is climbing, currently up to 132, and nearly every bit of text has now vanished in the Unity Editor Viewport...
Seems to be that it really doesn't like when I specify the font asset...
That's weird, I did a search in it and didn't find them. I'll have to do that again - must have done it wrong
I see those now.
Must have typoed the search string
And styles set in UXML have precedence over the ones in USS files, so it would probably have an effect
This is really odd. the uxml says I've got arial in three places, two of which are my gui frame, and one is the tab heading. When I go into the Unity Editor though it doesn't show that in either of these. I could maybe hand edit these, but I'm not sure quite how to do that. Is it ok/safe to just delete the -unity-font-definition: resource('FontAssets/DynamicOSFontAssets/GlobalFallback/OSX/Arial SDF'); portion of something like style="-unity-font-definition: resource('FontAssets/DynamicOSFontAssets/GlobalFallback/OSX/Arial SDF'); -unity-font-style: bold;"
yeah, you can definitely delete that
Any clue how to track down things like these?
I've got a bunch of the Invalid value for font Keyword...
And building it I just got these
sounds like you included those files in asset bundles, which you can't
already built bundles and .cs files can't go into asset bundles
Do you mean I shouldn't be putting my fonts into a folder like this within the project?
no, the files that are mentioned in the warnings such as Assets/ExposedControls.cs, Assets/Editor/CreateAssetBundles.cs, Assets/AssetBundles/kerbalui etc
they have an assigned bundle to be built into, but they can't go in it
there shouldn’t be anything from assetbundles included
I honestly have no idea how those got into the bundle or where they are.
at the bottom*
there mustn't be any bundle assigned to those folders/files
on the folders containing the files, too?
what is the asset label for the “AssetBundle” folder
there could even be one on the Assets folder as a whole, technically
None?
I'm probably not understanding the question...
Or how to get the answer...
Going back to ExposedControls.cs, I believe I've got that (and need it) for radio buttons. Do I have it in the wrong folder or something?
kerbalui seems to be in the fp_ui.bundle.
Well... kerbalui.manifest that is
Should I be assigning the files in my AssetBundles folder to asset bundles?
no, what Unity is saying is that you are assigning files in AssetBundles to bundles, which you're not supposed to
and that you're doing that with the .cs files as well, which shouldn't go into bundles
in the first case it's because you can't put already compiled bundles into other bundles, and you can't put code into asset bundles, since that needs to be compiled into DLLs, not into asset bundles
here you clicked on the AssetBundles file, but try clicking just on the folder itself to see if it has a bundle assigned
and try to do the same for the other folders in which the issues pop up
so Assets, AssetBundles, Editor
The folder itself is apparently unassigned
or if you don't mind, you can zip up the Assets folder and I can take a quick look for you
Walking through the folders in Assets it seems UI TooKit is assigned to fp_ui.bundle, as is FlightPlanTheme.uss and FP_UI.uxml, but the others are all 'None'
so from what I can see, you have the file Assets/AssetBundles/kerbalui.manifest assigned to fp_ui.bundle
but that's all I could find
the rest should not be an issue as far as I can tell
Is that a problem? Should I change that?
I mean, I don't think it will be an issue, but it doesn't belong in there
nope, it's just file containing metadata about the already built kerbalui bundle
so it shouldn't go into any bundles
OK it's set to None now
alright, so now the only way I can imagine those warnings popping up is if you had your whole Assets folder assigned to a bundle
no clue otherwise why they would be there
How can I check that?
just click on Assets
Hey, I'm still stuck in font hell, or at least font purgatory... The copy of LiberationSans I first downloaded seemed to have been borked in that selecting any of the SDFs other than regular (bold, bolditallic, and itallic) would render fonts, but selecting regular would not - though specifiying the ttf would work as long as you don't also point to the SDF. I found a different (larger files) version that seems to work as an SDF, but I still get Invalid value for font Keyword warnings on opening the UI project in Unity editor, and also get spam in the log like this any time I move my mouse over various elements in the mod's UI
[Warning: Unity Log] Font not found for path: [Warning: Unity Log] Invalid value for font Keyword [Warning: Unity Log] Font not found for path: [Warning: Unity Log] Invalid value for font Keyword [Warning: Unity Log] Font not found for path: [Warning: Unity Log] Invalid value for font Keyword [Warning: Unity Log] Font not found for path: [Warning: Unity Log] Invalid value for font Keyword [Warning: Unity Log] Font not found for path: [Warning: Unity Log] Invalid value for font Keyword [Warning: Unity Log] Font not found for path: [Warning: Unity Log] Invalid value for font Keyword
They're only warnings, and the mod does render, but I'm not certain if it's rendering right.
why? any visual bugs?
are you setting only Font Asset or also Font?
it should probably never be both at the same time, and Font Asset is preferred
I'll try unsetting the Font. The last time I tried that I was using the borked SDF, so maybe that's it.
Though there's definitely a difference in how the UI renders in game vs. in the editor
It seems like it may be my other font, Orbitron, that could be causing this. That's a shame. I really liked that font for the title bar.
I mean, if it works in-game, just ignore the warnings
Yeah, if I must I will - but I'd prefer to root them out and have something cleaner if I can.
Can I (should I) get rid of font assets I'm not using and have no intention of using like the JetBrains fonts? I may want to also get rid of the various LiberationSans and Obritron variants I'm not using, but I definitely don't want to use JetBrains and it's hanging out in my Fonts folder
oh your project is a customized clone of SpaceWarpUI right?
the newer and better way to do it is just to have an empty Unity project and install UitkForKsp2 as a Unity package
that way you'll only have your own files in your project
but it'd require you to make a new project and migrate your files over there
technically it shouldn't be too difficult, but it is some extra work
I'm not completely opposed to that. I assume I could litterally drag the uxml and uss files over into the new project to jump start it.
yeah, along with all the corresponding manifest/meta files
yes, of course those too. Just make a new project, drag over the old files, and press on?
I'm probably missing some bits in Step 1 (make a new project), but I think I understand steps 2 and 3
two more steps - gotta install the UitkForKsp2.Controls package from git URL like this: https://github.com/jan-bures/UitkForKsp2.Controls.git
and then in File->Build Settings go to Player Settings and there switch color space to Linear
(Or else you'll go insane)
ah don't even remind me of those literal months we spent trying to figure out the wrong colors
lmao
For the new project, should I select 2D core or what for the template?
Yeah, it was core. OK, I'll give this a shot. Seems like it should be easy.
FYI, that git is telling me it's v 1.3.0... Should it be 1.4.x?
OK, cool. Steps 1, 2, and 3 complete. For bringing things over how much of what's in my old Assets folder should I be bringing over to the new one? Presumably the Icons folder for sure, and the Theme\Fonts folder. What about the other things? The old Scenes folder is actually empty, so nothing there to bring.
well, just everything that you added
no need to copy over anything that was already in there
you probably just need Editor (it has the script to build bundles), Icons, and a folder with your own Fonts (doesn't need to be in Theme)
and then of course all your uxml/uss files and their metadata
well, ignore for now and see what the console says
the errors are in C# files
but Unity seems to be a bitch about it sometimes and all I needed to do to fix my issues last time was to add a space, let it recompile, and then go back and remove the space
lmao
LOL, still have the Font keyword issues, but it seems to have loaded otherwise
I did have to fix the canvas size, not sure why
it doesn't carry over, I didn't even manage to find in which file it's actually set when I was looking for it
And things that were docked are not... Do you hjappen to know how to dock UE windows? I don't recall now
Figured it out, just drag...
Canvas is definitely a bit goofed, but it seems to look OK otherwise
I'll try building the asset and see what I get!
Can't find the build asset thing when right clicking in the project. I closed and reopened and I've got the dumb warning dialog again...
I think I may be missing a step...
did you copy over the Editor folder?
There's just one file Create Asset
Nope, that option does not show up in the Assets menu or when right clicking in the project
any errors in the console that might be related?
oh yeah that's the issue that I was talking about
honestly have no clue how to reliably get rid of that, since everything can actually compile fine, but Unity refuses to do it
what I did (I think) was I went and opened that file, modified it a couple of times and let Unity recompile, and then at some point it just started working
@dusty berry sorry for bothering you but any idea how to get rid of this in some better way?
let me check
what I usually do is create an assembly definition and remove it, or try editing some code back and forth to get Unity to recompile it properly
and in the end it always somehow fixes itself
you could try 2 things
- add a line on some script thats on unity
- reimport the uitkforksp2 package
if those works its just unity being dumb and import stuff in tthe wrong order
honestly this sort of stuff is why working with Unity is so frustrating to me
i think that maybe settings uitk as a dependency of uitkforksp2 might solve
it is
why does it happen with all my Unity projects then 
also UITK is experimental at this version so
SpaceWarpUI, KerbalUI, UitkForKsp2.Controls, now AppBar
lmao
all of them I had these issues, and many others
Well they are all mod projects xD
if you're building a game these usually dont happen
yeah but it's not like I have ThunderKit or anything
so it should be the same as building a game
still, you have a experimental package
you cant really blame unity if you're using an experimental package xD
thus me wanting so much to migrate to the 1.0 version
but its under a license
but still, this seems to me like a deeper underlying issue, since it's just Unity not being able to find referenced types and namespaces from a package that's installed
smh
agreed
but unity was never meant to work with multiple dlls
they kidna hacked its way into it
and only recently made it adn actual, properly implemented feature
huh true wtf
theres probably ways to fix this.
wait a sec
"com.bbepis.bepinex": {
"version": "file:BepInEx_KSP2",
"depth": 0,
"source": "embedded",
"dependencies": {}
this is the package-lock
maybe if we set uitk as a dependency for uitkforksp2
tho im not sure how to do that


