#TimberAPI
1 messages ยท Page 5 of 1
You can probably get the current user, loop over subscribed mods
and try to see if it has the NeedsUpdate flag
Make it recursive for dependencies
always call on crash
dont care about the performance impact
i just want want the crashes
have checked and it does not subscribe automaticly if i verify game files to dep mods
Oke, that sucks
Does steam dependencies automaticly subscribe to them?
So if you didn't have a dependency before and added it. No one knows and will not be added 
exacly
and to staircase
Technically it makes sense and sounds a bit weird to do, but practiclly it's just bad
I wonder what mod.io does
well our modmanager i think adds it if you update the mod
The original use case of mod.io with it's subscribing system
And, if a yellow mark is on a mod thet is at the end of a list with more then a page with mods, no one will ever see the yellow mark ๐ฎ
Time for another box, warning mods
at least when clicking OK with any โ ๏ธ present it should confirm
I'm fairly certain that this might solve at best 50% of the problems, which still many will complain. specially when it will go live
Must also be a warning about the same mod installed from workshop and local ! Crashes the game ....
But i'd guess more like a 10% specially when 1 mod always complains and they go like. Oh well it works before yeet.
also would help if the game checked to see which mods had pending updates and triggered their download
I made the UIBuilder use the same Add methods as unity to the StyleBuilder, except that you don't need to specify the rules and other stuff as well. I thought this would suffice and would be good to use.
After some time making the presets it felt still a bit cumbersome because you would need to know which StyleValueType to use, which isn't quite obvious.
.Add(Property.ClickSound, "UI.Click", StyleValueType.String) <-- string, simple one
.Add(Property.Height, new Dimension(24, Dimension.Unit.Pixel)) <-- dimension, simple, but anoying to write many times.
.Add(Property.Color, "black", StyleValueType.Enum) <-- enum
, but can also be done with Color, which I forgot to add
.
So I am going to change this to all kinds of helper classes, the .Add will still exists since it will be used as core.
Should these methods have a Add prefix
like .AddColor since you adding a color property?
Result would be like
.Color(string colorName), .Color(Color color)
.Width(Length width), .Width(int width, Unit unit) <-- maybe having pixel as default since the devs use this as well.
.ClickSound(string soundId)
This way it would be more iniatif that using the .Add I think
?
Real example old:
.AddClass("api__button__migration-arrow-left-button", builder => builder
.Add(Property.ClickSound, "UI.Click", StyleValueType.String)
.Add(Property.Height, new Dimension(24, Dimension.Unit.Pixel))
.Add(Property.Width, new Dimension(32, Dimension.Unit.Pixel))
Real example new:
.AddClass("api__button__migration-arrow-left-button", builder => builder
.ClickSound("UI.Click")
.Height(24)
.Width(32)
Add prefix is not needed indeed i think, the real example new is epic!
Would defaulting to pixel be usefull
? and if you want something else .Width(32, Dimension.Unit.Percentage)
Not quite sure how the real default measurement works, its a unity unit 
Default pizel is fine, i always specify myself and most often use percent, but pizel as default is logical
Thats how it works in css too
@worn apex any oppinion on this? since you the second person using the UIBuilder ๐
i second tobbert, as he is the one who knows ui more ๐
Now make it usable as easy as win forms ๐
You mean a drag and drop nightmere
?
more like
var form = new Form();
var button = new Button();
button.Text = "Hello World!";
form.Controls.Add(button);
form.Show();
I would say it is already like that except from using new you use uiBuilder.Build<Type>();
And you can create a stylesheet (mostly for performance and also stuff like hovers)
yeah, i still need to tinker around with it some more ๐
My experience with UI toolkits is limited to ncurses,fltk,java swing and winforms๐
ohyea, i did convert the ChooChoo UI to new UIbuilder
was able to directly copy paste indeed
havent gotten to show any yet, as game crashes
but i expect them to work straight out of the box

Already a few done
.AddClass("api__button__arrow_left-button--size-small", builder => builder
.AlignContent(AlignContent.Stretch)
.Add(Property.AlignContent, "stretch", StyleValueType.Enum)
Going to be quite some work, but I think totally worth it
Just amazing how unity docs work
Half of the property links just redirected to CSS documentation 
Hah
Finished helpers for
BorderBottomColor
BorderBottomLeftRadius
BorderBottomRightRadius
BorderBottomWidth
BorderColor
BorderLeftColor
BorderLeftWidth
BorderRadius
BorderRightColor
BorderRightWidth
BorderTopColor
BorderTopLeftRadius
BorderTopRightRadius
BorderTopWidth
BorderWidth
Bottom
Color
Cursor
Display
Flex
FlexBasis
FlexDirection
FlexGrow
FlexShrink
FlexWrap
BackgroundColor
BackgroundImage
AlignContent
AlignItems
AlignSelf
About 1/3th done
Im not going to test all of them, just giving it by best guess how it worked so far and hope for the best 
Alright finished everything I could understand, it's missing some stuff specially for animation/transforming stuff. Might add some helpers for these later if I use them otherwise maybe someone will make a PR if they want a helper extension for it.
AlignContent
AlignItems
AlignSelf
BackgroundColor
BackgroundImage
BorderBottomColor
BorderBottomLeftRadiu
BorderBottomRightRadiu
BorderBottomWidt
BorderColor
BorderLeftColor
BorderLeftWidt
BorderRadiu
BorderRightColor
BorderRightWidt
BorderTopColor
BorderTopLeftRadiu
BorderTopRightRadiu
BorderTopWidt
BorderWidt
Bottom
Color
Cursor
Display
Flex
FlexBasis
FlexDirection
FlexGrow
FlexShrink
FlexWrap
FontSize
Height
JustifyContent
Left
LetterSpacing
Margin
MarginBottom
MarginLeft
MarginTop
MaxHeight
MaxWidth
MinHeight
MinWidth
Opacity
Overflow
Padding
PaddingBottom
PaddingLeft
PaddingRight
PaddingTop
Position
Right
Rotate
TextOverflow
Top
UnityBackgroundImageTintColor
UnityBackgroundScaleMode
UnityFont
UnityFontDefinition
UnityFontStyle
UnityOverflowClipBox
UnityParagraphSpacing
UnitySliceBottom
UnitySliceLeft
UnitySliceRight
UnitySliceScale
UnitySliceTop
UnityTextAlign
UnityTextOverflowPosition
Visibility
WhiteSpace
Width
WordSpacing
// Timberborn
ClickSound
NineSlicedBackgroundImage
BackgroundSliceScale
BackgroundSlice
BackgroundSliceTop
BackgroundSliceRight
BackgroundSliceBottom
BackgroundSliceLef
Properties that don't have a helper
All
BackgroundPosition
BackgroundPositionX
BackgroundPositionY
BackgroundRepeat
BackgroundSize
TextShadow
TransformOrigin
Transition
TransitionDelay
TransitionDuration
TransitionProperty
TransitionTimingFunction
Translate
Before
protected override void InitializeStyleSheet(StyleSheetBuilder styleSheetBuilder)
{
styleSheetBuilder
.AddClickSoundClass("api__button__plus-batch-button", "UI.Click")
.AddBackgroundHoverClass("api__button__plus-batch-button", "ui/images/buttons/plus-batch-multi",
"ui/images/buttons/plus-batch-multi-hover")
.AddClass("api__button__plus-batch-button--size-normal", builder => builder
.Add(Property.Height, new Dimension(20, Dimension.Unit.Pixel))
.Add(Property.Width, new Dimension(20, Dimension.Unit.Pixel))
)
.AddClass("api__button__plus-batch-button--size-small", builder => builder
.Add(Property.Height, new Dimension(18, Dimension.Unit.Pixel))
.Add(Property.Width, new Dimension(18, Dimension.Unit.Pixel))
)
.AddClass("api__button__plus-batch-button--size-large", builder => builder
.Add(Property.Height, new Dimension(24, Dimension.Unit.Pixel))
.Add(Property.Width, new Dimension(24, Dimension.Unit.Pixel))
);
}
After
protected override void InitializeStyleSheet(StyleSheetBuilder styleSheetBuilder)
{
styleSheetBuilder
.AddClickSoundClass("api__button__plus-batch-button", "UI.Click")
.AddBackgroundHoverClass("api__button__plus-batch-button", "ui/images/buttons/plus-batch-multi",
"ui/images/buttons/plus-batch-multi-hover")
.AddClass("api__button__plus-batch-button--size-normal", builder => builder
.Height(20)
.Width(20)
)
.AddClass("api__button__plus-batch-button--size-small", builder => builder
.Height(18)
.Width(18)
)
.AddClass("api__button__plus-batch-button--size-large", builder => builder
.Height(24)
.Width(24)
);
}
Will remove just alot of annoying boiler plate and less searching how to use these types
How easy would it be to dynamically filter the list of groups and tools shown at the bottom? I'm wondering how easy it would be to add a search filter, eg: type /pump (/ could be the hotkey) and it would only show pumps, etc.
I'm guessing it already has to be somewhat dynamic because it changes when devmode is enabled/disabled
Pfooo hmm
There is a enabled state but i think it was computed by the dev state...
Unless you would not mind. An option would be to toggle dev mode for your filter?
I don't think would help,
It looks like Timberborn.ToolSystem.ToolButton has ToolEnabled which could be patched,
TimberAPI already patches IsVisible
Well, I need to say that I completely don't understand the new UI system. Some docs or examples would help. I though I find some in github, and I didn't. Maybe I just dind't search good enough.
There is no documentation for the old or the new in that matter, the new one will be there when everything works
https://github.com/Timberborn-Modding-Central/TimberAPI/tree/main/TimberApi.UIPresets/Buttons
And this is pretty much examples
Have you used the old one ?
Yes, I used to use the old one. Now, I'm struggle to make the visual element.
_neverShutdownCheckbox = _builder.Presets().Toggles()
.CheckmarkInverted(locKey: NeverStopThisGeneratorLocKey, color: UiFactory.PanelNormalColor);
Then
_root = _builder.CreateFragmentBuilder()
.AddComponent(_neverShutdownCheckbox)
.BuildAndInitialize();
Now, I try to find an equivalent. No luck so far.
_neverShutdownCheckbox = _builder.BuildAndInitialize<ToggleBuilder>() as Toggle;
_neverShutdownCheckbox.label = "Toggle label";
_neverShutdownCheckbox.style.color = UiFactory.PanelNormalColor;
This compiles, but I'm not sure it works ๐
Ye no checkmarks so far, just figured out sliders. Will see what I can do in a bit for a small example
Got it. Well, I'll try the old (Unity) way then. Or maybe I'll be lucky to copy the @severe solar approach.
Not sure what his one is ๐
New syntax would be
uibuilder.Create<ToggleBuilder>()
.BuildAndInitialize();
if you would make one from scratch without making it a preset (which isn't recommended).
BuildAndInitialize is not public ๐ฆ
It is, but only the ones you need
The simples form of a preset would be
public class SliderTest : BaseBuilder<LocalizableSliderInt>
{
protected override LocalizableSliderInt InitializeRoot()
{
return UIBuilder.Create<SliderIntBuilder>()
.AddClass("api__slider_circle")
.SetLabelLocKey("AAAAAAAAA")
.SetLowValue(1)
.SetHighValue(100)
.Build();
}
}
var toogle = _builder.Create<ToggleBuilder>()
.SetLocKey(NeverStopThisGeneratorLocKey)
.SetColor(UiFactory.PanelNormalColor)
.BuildAndInitialize();
Gives me
SmartGoodPoweredGeneratorFragment.cs(54, 10): [CS0122] 'BaseBuilder<LocalizableToggle>.BuildAndInitialize()' is inaccessible due to its protection level
It was first thing which tried.
I followed the inheritance chain and it seems the Build method should be public. But it's not either.
Will have to check that out then not sure why that would be a thing
Since I only done buttons maybe it need some extra changes, think instead of finishing another one fully I will make 1 example for each type
Ha! I just got an idea. I will publicsize it!
Could help for now, hopefully that I don't need to change something ๐
Atm it's a bit of a testing phase if everything works as intended
Totally understandable. So many changes.
And after all, you spend your time to make our lives easier. We're not who will be complaining ๐
Some complaining is fine ๐
Since now we have this ๐
Well I do, didn't make it live 
I recall that at the very beginning my problem was to understand the concept of builder => builder. Many days after I started and got some knowledge, it became clear. Just an FYI from someone who used to be a total newbie. Tbh, I have not idea how it can be adressed. If can be at all.

In protobuf world they have concept of MessageOrBuilder. Maybe it somehow sovles the problem.
On the other hand, protobuf has own issues.
No idea what you mean with the problem
uibuilder.Create<ArrowUpButton>()
.Large()
.BuildAndInitialize();
But I guess it's semi fixed ?
And the builder => builder. is just a inline method, you could extract it to an external one as well
In protobuf, you can make a proto by using "builders". There, you can use both the final messages and the builders. So, when you need to set a value to another field, you do something like this:
var t = MyProto1.newBuilder()
.setMyNumber(1)
.setComplexField(MyProto1.ComplexType.newBuilder().setStuff("lol"))
.build();
Right, but it assumes dynamic execution. Which is not that easy to imagine in mind.
But this is pretty much what the new system has, except with a more cleaner syntax imo with the Create<Type> instead of needing to do MyProto1.ComplexType.newBuilder()
I will not argue since I have very weak understanding of it as of now ๐ If it does, then it's great!
Hope to give you soon some more example
I posted it before
Not sure where, but in the discord
Try looking my name and uibuilder or something
Yeah, I saw it and tried. It didn't work for me out of the box.
C:/Users/IH/AppData/LocalLow/Mechanistry/Timberborn/Player.log, really? So simple?! There must be a better way to hide the logs!

Why would you mneed to hide it
It was a sarcasm. I'd put the logs into the game's folder so that noone need to search for them. That's what my logging mod was doung in u5.
I see, you had your own loggin file 
I had a set of files. Sorted by severity and date/time. And they were in the game's directory, which was is very convinient (for me).
I guess, now it's the first mod I'll make for u6.
Like this.
With some sugar to the log records: you could know where they did come from.
Could patch the ToolEnabled
SliderInts, with either a Diamond option or not. Localizable or Text. The top ones are MainMenu sliders, the bottom ones are Game sliders different horizontal tracker
You know, trying to casually add checkboxes
checked activity not working.... looking in code
case ':':
complexSelectorBuilder.AddPseudoClass(PseudoClass.Hover);
Hardcoded hover effect when checking for : selector
Now it works though ๐
Put it live!
One singular toggle which is used for ingame and the sliders are now working
Yep, exactly what I was thinking.
ร have a bit of a stupid idea ... is it possible to render ui elements ontop of each other, something like in the picture?
Probably yes, but I think you want it to be functional like a min max slider? in that case probably not.
ยดbasicly the idea would be to have multiple values selectable between min and max
Unless you create a custom element for it (if that's even possible)
Yea no clue if that's even possible in unity in general

I am not in my pc but does the class MinMaxSlider actually exists ?
If it's possible in unity I can make a base UIElement for it, but will someone else make the presets for it. Or will be at least a very low prio since it's not in the game either
at least not in Timberborn.CoreUI, but well, in unity
but i want more than 2 values, so i'll skip that
the idea is to create an employment"manager"
each manufactury has N amount of beavers.
the sliders represent unemployment / employment triggers based on the producing good for each beaver, so 2*N values to be used.
for the internal workings, the values get sorted and the low N values represent employment triggers, while the high N values represent employment triggers.
I already got it working, just the ui is missing xD
Wouldn't a min max also be possible with that
you only need 3 values right?
- Underflow employment
- Stable employment
- Overflow employment
would need N min-max sliders for that, or i just employ / unemploy all beavers at once, which potentially can lead to "employment unstability"
I think I just understand soemthing not than
maybe, basicly:
i have 4 tresholds:
2 for unemployment, 2 for employment (say 50%, 60% of stock full for employment, 80%, 90% for unemployment of individual beavers.)
between 00% and 50% stock allows for 2 to 2 beavers
between 50% and 60% stock allows for 1 to 2 beavers
between 60% and 80% stock allows for 0 to 2 beavers
between 80% and 90% stock allows for 0 to 1 beavers
between 90% and 100% stock allows for 0 to 0 beavers
i think ill just let the thresholds be determined automatically based on the target value from the user
What do you mean with stock ?
the fill level (0.0-1.0) of the produced good in the district
Ah so you want to manage the total workers based on your inventory in the district
yep
I was more thinking of managing the workers based on total workers, like automated priorrity
ah, yeah, i'll let that be handled by the ingame user determined workplace priority
additional feature 
Ye no clue, it might be possible if you make something completely custom. But I don't understand UXML good enough for that.
yeah .. i ll settle for 2 sliders per building and let the other triggers be determined automatically
Maybe a min max slider for it's percentages
- Full,
- Stable
- Off
And like a second min max slider for the minimum and maximum for full/stable and gradually increase
I think your GameTextSlider should accept floats as bounds ๐
And thanks for your hard work :)
namespace TimberApi.UIPresets.Sliders
{
public abstract class GameTextSlider<[Nullable(0)] TBuilder> : BaseBuilder<TBuilder, Slider> where TBuilder : BaseBuilder<TBuilder, Slider>
{
public TBuilder SetHighValue(int value)
{
this.SliderBuilder.SetHighValue((float)value);
return this.BuilderInstance;
}
}
}
Ah I suppose I didn't chang eit in the preset
Did change it in the base builder
[Nullable(0)] wth is this
dunno, i used dnspy instead of just inspecting to your repo xD
Understandable, I use rider so I just click on anything I want and it decompiles it for me 
รญ think i'll stick with that and postbone the minmax-slider
๐, the small version is mostly used in fragments
.Create<>().Small.Build() ๐
Would it be better to have for most options to have it splitted like
- GameSlider
- GameSliderSmall
- GameSliderDiamond
- GameSliderDiamondSmall

maybe just as an enum you pass to the slider?
Then you would still need to do .Create<>.Size(Size.Smal).Build()
true, i guess its good as it is currently
Might add them later on
as connivence so you can keep most in .Build<>
LOL
Oooh, I wonder if that would be a nicer way to configure SimpleFloodgateTriggers
Would it be possible to allow the "outside" part to be orange instead of the inside part, eg: by dragging an endpoint past the other.
Then for example orange could be closed, and green could be open.
Im bot Totally surr if it stays orange
But you could make ot any color you want its a 1pixel image
I mean that it could be (green<>orange<>green), but if you drag one point past the other then it would show as (orange<>green<>orange)
i.e. relax the constraint that point2 must always be larger than point1, and have some way to show it graphically
Oooh, is this a unity built-in?
Yes
aaaaaah
Yeah only ehh thing, there isn't an INT variant of the min max, which is a bit 
What do floodgate use? IntSlider or Slider?
Do they use an IntSlider and just /10?
No idea, but you could maybe just floor it on change. Not sure about how this will work out though.
looks good
Did you make a typo
? incredients, did you mean ingredients ?
yep, still doing testing
np, looking neet
How exactly do you make this fragment? Any code to share? I ended up loading visuals from other fragments and using them as templates.
I've lend some code from Tobberts unstuckify to get going
https://github.com/TobbyTheBobby/TimberbornMods/blob/main/Assets/Mods/Unstuckify/Scripts/UnstuckifyFragment.cs
https://github.com/TobbyTheBobby/TimberbornMods/blob/main/Assets/Mods/Unstuckify/Scripts/UnstuckifyConfigurator.cs
How about the double slider?
i've created a TimberApi UI preset using the slider preset
https://github.com/Ximsa/Timberborn-EmploymentAutomation/blob/main/UI/EmploymentManagerPanel.cs
I will give it a try then. Last time I tried to make TAPI working, it gave me compilation errors ๐ฆ
Hmm, it seems sliders and toggles are not in workshop yet. Is it a not released functionality?
Nm, now I see 0.7.2.0. Awkward.
@severe solar Hey, the manifest for Unstuckify doesn't mention dependencies. In the game, it's possible to move the mod before API and get troubles.
@stone shoal Is it intentional that GameTextToggle only provides SetText, but not SetLocKey?
@stone shoal Both GameSlider and GameSliderInt provide integer methods for setting high/low.
And there is access level issue. Minmax sliders is ok, but the normal one throws "inaccessible due to protection level".
var t1 = _uiBuilder.Create<GameMinMaxSlider>().Build();
var t2 = _uiBuilder.Create<GameSlider>().Build();
Yes because you using the text variant
Hmm. How do I use the other one?
GameToggle 
Now I got what "text" mean in the name.
Localization is default. With text is if you dont want ro have a label or setting plain text
I found Localizable... On everything too long
No idea why you keep getting this since minmax is literally copy pasted from those sliders
And i test the elements in another dll so csnt access internals as well
Tbh, the generics complexity blows my mind in the setup. It's really hard to understand what inherits what.
And thigs like this:
public class PanelFragment : PanelFragment<PanelFragment> {
protected override PanelFragment BuilderInstance => this;
}
Is a complete blow of the mind.
Ye it is. Could not figure out how to make it simpler while giving the same fully featured functionality
But the usage doesnt have to be complicated
Except if you want to make a preset that you can extend. Which is in a user case very little the case I think
At this point I can't even make my preset, lol ๐คฃ I'm copy/pasting like a monkey with little understanding how it works.
You want to extend a existing one or have one from scratch?
And now, again the accessibility issue:
var toggle = _uiBuilder.Create<GameToggle>().SetLocKey(locKey).Build();
It worked just fine with the text version.
I want: a panel fragment with a toggle, a slider, and a label. Nothing fancy. Only the basic controls.
I'm building via JB project, not via Unity. Framework v4.8, compiler v10. Can it be the issue?
Im compiling from .netstandard 2.1
Just enabled the unsafe mode. It didn;t help.
What language version?
C# 10.0
Though that would bot make sense why localizations only dont work
Does any localization preset work?
Didn't try yet. My UI only needs toggle, checkbox and label (which doesn't have preset yet).
Thats why only thing that I could think of
JB doesn't let me sweitching to netstandard. I guess, it's not that simple.
But the localization element classes are public so idk
It was for me. Or are you on unity?
Nope. I'm in JB standalone project.

NOW i got it.
LocalizableToggle toggle2 = _uiBuilder.Create<GameToggle>().Build();
UiFactory.cs(64, 5): [CS0122] 'LocalizableToggle' is inaccessible due to its protection level
internal class LocalizableToggle : Toggle, ILocalizableElement
Indeed, it's inaccessible.
Thats a Timberborn class right
Why do you return internal types, man? ๐
I think I can publiczie it and it should work.
But, hell, it's not easy to guess.
Why would a Uielement be internall in the first place
How would unity use it for its UIBuilder
IIRC, it's a policy of Timberborn team. I asked once for another class. They said, whatever is not used outside the package must be internal. Period.
And Unity doesn't care, iirc.
You can use internal class as a component.
Ye I dont mind that part. But this is an UIElement which they dont use directly so I would assume it needs to be public 
Ill see if I can extend it publicly with publizicer and maybe that works... Else I have to copy all elemente again
Can you just return Toggle? What benefits do we get from it being LocalizableToggle?
Because generics
And else it would bot be a localization toggle it would just be plain text
oh
Well, in my case I create controls via my wrapper anyway. So I'll stick with the text version. I can make loc lookup on my side just fine.
var toggle = _uiBuilder.Create<GameTextToggle>().SetText(Loc.T(locKey)).Build();
Btw, is tehre any difference between:
var root = _uiBuilder.Create<PanelFragment>().
.add().add().add()
.BuildAndInitialize()
and simple:
var root = _uiBuilder.Create<PanelFragment>().BuildAndInitialize();
root.add()
root.add()
root.add()
?
I didn't notice any.
@stone shoal What about the sliders set high/low methods? Are they supposed to always accept the int values?
No that one is wrong, only the int one needs ints
No difference. Just whatever you prefers
@stone shoal Is there a version with a small version of the circle?
Create.small.build
Now, it's the time to try the minmax slider ๐ This is what I was doing it all about.
It's a very useful control! Thanks, mate!
I still need to work on it, thought. The max range is supposed to be 90%, but it's 65% 
This is fantastic ๐
@calm copper can you replace this dll and see if the GameSlider (localization) works ?
without access problems
Sure, one moment.
Still no.
var slider = _uiBuilder.Create<GameTextSlider>().Small().Build();
var slider2 = _uiBuilder.Create<GameSlider>().Small().Build();
JB says it's still: public override LocalizableSlider Build() => this.SliderBuilder.AddClass(this.SizeClass).AddClass(this.DraggerClass).Build();
Ah right
The method is public. The type is not.
Can you make something like Build<Slider>()?
But then you only don't know that it has a locKey
I'd say, after I do build, I only need a visual element. That's the whole point of having builders.
Yeah but if you want to make your own element and such
Tobbert uses it
I am going to use it for some things
Well, then it makes sense.
Now they both link to my own public class
By a chance, can you make a new method? Like "BuildVisualElement"? ๐
For people like me, who need just common controls.
wym build visual element ?
This is my case, and it's generic. I do it in all my mods that need UI fragments:
public VisualElement InitializeFragment() {
_neverShutdownCheckbox = _uiFactory.CreateToggle(
NeverStopThisGeneratorLocKey, _ => {
_generator.NeverShutdown = _neverShutdownCheckbox.value;
UpdateControls();
});
_chargeBatteriesSlider = _uiFactory.CreateMinMaxSlider(
value => {
_generator.DischargeBatteriesThreshold = value.x;
_generator.ChargeBatteriesThreshold = value.y;
UpdateControls();
}, lowValue: 0.1f, highValue: 0.9f - BatteriesChargeRangeSize);
_chargeBatteriesText = _uiFactory.CreateLabel();
_chargeBatteriesText.style.marginTop = 5;
_root = _uiFactory.CreateCenteredPanelFragmentBuilder()
.AddComponent(_neverShutdownCheckbox)
.AddComponent(_chargeBatteriesText)
.AddComponent(_chargeBatteriesSlider)
.BuildAndInitialize();
_root.ToggleDisplayStyle(visible: false);
return _root;
}
I don't care about the element once it was built.
And honestly, I believe everyone should follow this practice. "building" is the final step.
I still don't quite understand what you mean with BuildVisualElement. The whole UIBuilder in general is create it once
. And now that you can create your own presets the recommended way is making one for each thing you want
Like your whole fragment would be one preset
_uiBuilder.Create<T>()....Build() creates a specific control. E.g. LocalizedToggle. My point, it should create VisualElement. It means, thatr after you've built it, it;'s now a generic visual element. Not slidfer, not toggle, not anything like this. Just a visaul element of which the UI is built.
That makes no sense to me, if your preset is a Toggle you get a Toggle. Why would you get a VisualElement. Every element is a VisualElement down the line so it would also not matter.
But ye your idea is already implemented as I also wanted it to be that way.
public class MyTestElement : BaseBuilder<VisualElement>
{
protected override VisualElement InitializeRoot()
{
return UIBuilder.Create<VisualElementBuilder>()
.AddComponent<ArrowUpButton>()
.AddComponent<ArrowDownButton>()
.AddComponent<GameSlider>(slider => slider.Small())
.Build();
}
}
uiBuilder.Build<MyTestElement>() where you need to initialize it
If I need a toggle, I request a "toggle builder". Once built, it's not anymore anything specific.
What's the end target of any builder, anyway? To create a visual element.
The element you decided to have as end
You can say it, if it's your intention to build API. But for Unity, UI is composed of .... visual elements.
A toggle is an visual element...
Correct. And you shouldn't.
Unity's UI as a hirerchy of the visual elements. The basic ones.
I don't want to continue this, if you think it's wrong sure. But in unity or anything else it's normal
So you also not going to do .Q<Toggle> to set the value of it. because it should be a visual element 
Mate, I mean no offence here. You make it. You decide. Whatever you make, will be the product. โฎ๏ธ
I know, but what you say is just wrong... or what you say has nothing to do with what you actually mean
It's saying a class should return object, because in C# everything is an object
I guess, we just have different vision to what "build" should build. It's your system, so you decide. I just gave an opinion.
okay, Your opinion doesn't make sense to me(in a non offense way, idk how to say it in english a better way) in the system which could make things hard accessible. I want it to be presets like Vue javascript based component, where you can extend the functionality of a button or make a bundle of components so you can easily reuse them.
I wish this functionality was also in UXML, but have not yet found it. Would help so much...
No offence taken, English is not my first language either. I still have a bunch of arguments to throw to keep this battle burning, but... I won't ๐ You're making a great thing! Do it the way, you believe is right. And I reserve a right to disagree with your decisions 
if you really obsessive of getting a visual element back use .Build(typeof(Preset))
Wait, I can do it?!
ofc, it's required for dynamic element building ๐
Hmm, I probably misunderstood it. This isn't working:
var slider2 = _uiBuilder.Create<GameMinMaxSlider>().SetLocKey("blah").Build<Slider>();
I guess you ddid
test.Add(uiBuilder.Build(typeof(GameSlider)));
You cannot use the Create method it doesn't know what to return. So only preconfigured presets can be used.
Like these
var slider2 = _uiBuilder.Build(typeof(GameMinMaxSlider)); gives a visual element, indeed.
However, my (humble) opinion was to get a specific builder, do the building stuff (like setting the control specific properties), and then build to get a generic component => visual element. But I think we've discussed it already, so no need to start it over. This is not what you have in your mind, and it's totally OKAY.
But that's litarly #1064983064020799498 message ?
๐
Builder/Presets aren't really different
They the same thing but with different purpose
The second part I could not figure out how to do different ๐
No. It's literally not. Don't you see a missing part? The create method call?
im so sure were almost talking about the same but just some missing knowledge
The create method call, what about it ?
Can you show me ?
Like in vc ?
Sure. Here I'd want to get a MinMaxSlider builder:
var slider = _uiBuilder.Create<GameTextMinMaxSlider>()
.SetLowLimit(lowValue)
.SetHighLimit(highValue);
Why? Because I'd continue and add a listener.
_root.Add(slider)
Here, I don't care that "slider" is a slider. I't a visual component at this point. Because the root is a visual component!
An this how we get back to the internal classes from Timberborn.
With
var slider = _uiBuilder.Create<GameTextMinMaxSlider>()
.SetLowLimit(lowValue)
.SetHighLimit(highValue);
You mean actually
var slider = _uiBuilder.Create<GameTextMinMaxSlider>()
.SetLowLimit(lowValue)
.SetHighLimit(highValue)
.Build();
Right ?
No. "Build" will retrun an internal class...
(it's how we started it, so we are looping to the beginning)
Yes but that was just a bug, that I now know of ๐
It should end with .Build to receive it's element which you can add to the root with _root.Add(slider)
That's why I suggest a separate method. E.g. "build" returns you a specific class, like the internal one. And some other returns you a root class like visual element.
It's not the best desing, though.
where TElement : VisualElement, new()
you mean this 
Yes, that was my point.
Ye that's was always already the case, which is how it should be.
But you said it need to be a VisualElement, you never said that it returned the Builder/Preset
And a Toggle is just an extension of a VisualElement. I never was talking about a builder as it's return type.
Gimme sec to try to fix it for all
LocalizableSlider is not a public class. I just cannot use this methid wihtout publcizie teh stock game packages!
Also not with the latest dll I sent ?
At this poihnt, I'd be fine to get the base class - the slider.
This opne
only works for the specific GameSlider the rest has not the fix
?
The new DLL.
Both of them
Well, I probably did something wrong. Could you please send them again? I only installed one.
Here the whole core folder
THIS works just fine!
aight
You still get a Slider returned instead of VisualElement ๐
Won't work
Was just a test
Need to manually fix the rest beforehadn...
The toggle still has the issue. But it's expected, right?
Got it.
@calm copper this should fix everything
Need to test if it will break the mod ximsa before putting live
Going to bed now. Thanks, I'll check it tomorrow. 
Does TimberAPI not work without Rosetta on M1 Macs?
No, it does not
Wanted to play with it but it really affects performance ๐ฆ
Can't do much about that, it's a general mono issue
Checked. It works. Thanks! Was it released?
Wait, no. GameToggle still uses Timberborn UI element.
No it has not, some mods crash so waiting thay they can be fixed around the same time
Yup, just got unstuckify failed ๐
But its not fixed with the folder I send or with the released one?
Both. I use "TimberAPI-fixed.zip" which you've sent the last.
Btw, I didn't notice changes in files sizes. Only the dates. Did you pack it right?
My bad. Copied the new DLLs into a wrong folder. The fixed version works fine. All controls are accessible.
But I got another issues. I create GameMinMaxSlider with no locKey set (I don't need any text) and get this error. Seems like this field is required.
Hmm maybe I do it differently than the other localizations or they crash as well
Either way, yes you should add a lockey in any localization element
Otherwise it will crash
But I thought it should bot crash on experimental, at least thats what the devs sais ince
I doesn't crash, it only complains. I shown stack trace just to lety you knwo where it comes from.
I figured out, that if I need an empty text control, then it makes sense to create a text control instead of localizable. It does make sense.
Its a bit odd
Not sure what would be better
Maybe I could just make it that empty ones dont get localized
But I cannot override thay method I believe
This sounds reasonable.
Btw, GameTextMinMaxSlider doesn't have method SetText. is it intended?
GameMinMaxSlider has SetLocKey.
Well, what is "text" for the minmax slider anyway? What the loc key is used for? The unity control doesn't seem to have any text at all: https://docs.unity3d.com/ScriptReference/EditorGUILayout.MinMaxSlider.html
I.e. there is nothing to localize there.
Does it jave a setlabel?
Some are settext some are setlabel. Depending on whats used in Timberborn
Chechboxes use the text position instead of the label. Thats why its on the right side
The text version does. The localizable doesn't.
Ah, so the "text' is the label. Now it makes sense. It's setlocKey in one case and setlabel in another.
Yes text is just general word for things not localized
Of you know something better lmk
Text is just fine.
In general the text one should not be used much except of you want no text imo. If I cannot fix the no text in the localization elementd
For the minmax slider, I'd suggest couple of useful behaviors that other ppl also may be interested to use. Are you up to make it a part of TAPI? Or is your intention to keep at as simple as possible in terms of UI controls?
Depends on the behaviours. Since all i csn do is changing the style a bit
How kt behaves is feom unity itself
Ah, then nm. My ideas definitely not style related.
I found it useful to limit the minimum delta between min/max and also introduce a step to not have weird float values.
Nigjt night
Good night!
reminds me that i should also localize employmentautomation ...
Saying about the employment automation. @worn apex you stole my idea! ๐ I was working on it in scope of Automation mod, but I'm happy you've made it
No need to spend efforts now 
tbh, i also wanted to automate power production a while back, but then saw your mod ๐
@worn apex @calm copper @severe solar
I put TimberApi 0.7.3.0 live with the local localization elements, so things might have broken
Igor another update for you ๐
https://mod.io/g/timberborn/m/timberapi 0.7.4.0
BuildingSpecification is back
So you can add recipies to builidngs with json file?
Yes
Nice ๐ got an example file? (For zxuiji and todor and more modders, file to edit the building)
Just tested. Didn't see any issues. Except Unstuckify crashed ๐
Interesting, while i didn't have to make any changes to the code, i had to update the dependencies from timberapi 0.7.2.0 to 0.7.4.0 in the project for it to correctly load in Timberborn 
Do you need to specificy it's version ?
It's minimum though
What did go wrong otherwise ?
It could still be a recompile problem, that the code for you is the same but it requires a recompile to work internally.
i mean, its more of c# anomaly, since the mod needed to be recompiled without change in the code to work again ๐
Yea that can happen sometimes. Happened with Timberborn as well
Probably because of the class change that didn't exist before
Small peek 
Those menus and "cards" should be more opaque, difficult to see some of the text
I suspect the "slash" is to show two different color schemes, eg dark vs light, and not actually part of the regular appearance.
How/what is PickObjectTool used for? Like picking stream gauge for floodgate automation?
Yes, I think so
It was in the game before but got removed. Maybe its bkt needed anymore and something else can be used.
It highlights specific types when active iirc
and I see the "SWA" debug message is now gone, (due to ModStarter being disabled in the "building specification" PR
I hadn't gotten around to being confused enough by it to "devify" the Unity engine to print full tracebacks
also it would have meant downloading the new version of Unity again, to get the dev player
very annoying to have to download and install 4gb of unity, just to get 200mb of player
Yea I never noticed it wasn't in the debug part but in an new feature test
@stone shoal How to make a button to resize to its text and get centered in the UI fragment?
The "apply to all" button gets 100% of the fragment width. I'd like it to shrink to the text and get centered.
are unity buttons stretched by default 
idk ๐
You can always set it to a fixed width
It's a bad idea given we have localization
It's unity's base behaviour to stretch buttons
Base game does it as well ๐
maybe with flex grow 
I wish I knew what it is ๐คฃ
Well, for now I'm fine with the 100% size. The UI is acceptable.
And the mistake was...? ๐
Set flex direction to row
I don't have padding in the buttons though 
The question, do I need to add them 
Might add a AddPadding, AddSmallPadding, AddPaddingBig to some
The element the button is inside how big is that one ?
Does that one go full width ?
It's a good question. Idk.
From the old Unity GUI system, I recall that you need to add some flexible spaces. So, in this case it should be like: <flex space>+<button>+<flex space>. No idea how it would map to the UI system.
never worked with that only UIToolkit
var test = new VisualElement
{
style =
{
width = 600,
paddingBottom = 20,
paddingRight = 20,
paddingLeft = 20,
paddingTop = 20,
backgroundColor = Color.gray,
flexDirection = FlexDirection.Row,
justifyContent = Justify.Center,
}
};
My testing area is just this
so probably your visual element does not take up the whole space
Did you remove the width 100% ?
From this
Nope, the code above is all what I do.
I guess, the new visual element (row)t gets a new space. It adjusts to the inner content, and that's it.
Nailed it!
Just need to deal with the padding.
... guess I was drunk when making this 3 years ago or something
Created a padding, but only for all directions
.ModifyRoot(builder => builder.SetStyle(style =>
{
style.paddingLeft = 10;
style.paddingRight = 10;
}))
the 10 values are not pixels, if you want it to be pixels you need to use the new Length(10, Unit.Pixels)
If you want to have it a full round
.ModifyRoot(builder => builder.SetPadding(10))
Would look bit better ๐
Nice
I'd adjust the paddins, tho. The button like this is too big. But it's a cosmetics.
np ๐
Does GameTextMinMaxSlider has the modify root ability? My IDE says it's not.
๐
You need to extend it than and make your own preset with it
public class MyMinMax : GameTextMinMaxSlider
{
protected override MinMaxSlider InitializeRoot()
{
base.InitializeRoot();
return MinMaxSliderBuilder.SetPadding(12).Build();
}
}
Or if you want your own methods to be added
public class MyMinMax : GameTextMinMaxSlider<MyMinMax>
{
protected override MyMinMax BuilderInstance => this;
protected override MinMaxSlider InitializeRoot()
{
base.InitializeRoot();
return MinMaxSliderBuilder.SetPadding(12).Build();
}
}
That is that
. and is kinda recommende way though ๐
, if you do it with stylesheet at least ๐
And now, I'll finally get a couple of badtides on Plains! 
How are you making the min max now a interger ?
rounding it on change ?
@calm copper , @worn apex
https://timberapi.com/timber-api/uibuilder/basic-usage.html
https://timberapi.com/timber-api/uibuilder/creating-presets.html
This are the first 1,5 pages for the docs. any feedback on the writing?
Wanted to do more today, but my jaw locked at 5AM until 11:30 AM, so I was dead tired and didn't want to work on it 
looks good, well ... besides me not knowing what a unity ui class thing is. But that's a skill issue on my end
You mean this part
.AddClass("my-arrow-down-button", builder => builder
.ClickSound("UI.Click")
.Height(20)
.Width(20)
);
```?
yup
it's like a css class
never done css ๐
Well then
Yeah no idea how to even explain that ๐
https://www.w3schools.com/csSref/sel_class.php this helps like not at all kek
The CSS class selector matches elements based on the contents of their class attribute. 
But would it be understandable enough how to use it even if you didn't know it ?
For at least simple stuff like buttons
There is going to be a specific page for the StyleSheets though, so will probably go in more depth there
i read: You "decorate" UI things with classes, and the magic UI thing makes stuff based on the assigned classes / your class from the stylesheetbuilder
Looks good. The approach seems clear. One question I have is why referring my-arrow-down-button three times? Is there a case when we would use other names?
I'd expect that InitializeStyleSheet creates a stylesheet for the class that we added in InitializeRoot.
If you have worked with html/css its like that
And yes it's very common to use other names. for example when making a multi element preset
Or when you have different sizes like the TimberApi presets have. That requires a class like my-arrow-down-button--big which has the dimensions to make a big button
For the miltiple references of the same class within the stylesheetbuilder is just a helper foe the backgrounds. one background property will be merged with the manual creating one. The background helper adds a normal and pseudo class for you, you could do this yourself as well if you find that more clean.
This will be more explained in the dedicated stylesheet page
Alternatively you could just import a USS file for it, might be easier for large complex stuff
Sounds reasonable. Not sure I get it well organized in my mind, tho ๐ My only case for now was a single control. But it makes sense to have multiple styles if you have a complex control with multiple elements.
Which is totally fine ๐ for common things it can be done as minimal as possible with a single class
And maybe you don't need it at all due the existing presets
Still need to fix lists, input fields... but lists are being a winy b**
This thing I never tried. My must have are: labels, buttons, checkboxes, sliders. It covers 100% of what I do.
I had some challenge to center a button, tho ๐ I'd love to have a preset for it.
Not sure about that one, how would you see this in practice
There are alot of things that can cause it not to work
This.
I mean more like in code :P, since it will conflict when you limit the size of the box you still end up having the same problem
Altough I already forgot what the problem and fix in the end was
, in the end it was a pretty simple fix right 
In this specific case, if I just use a button, I get a button that is stretched to 100% of the UI fragment. It's fine in most cases. It's just me, who doesn't like this kind of UI design. I like buttons that resize themselves to the text and get centered (see the image). Doing it like this:
var center = new VisualElement {
style = {
justifyContent = Justify.Center,
flexDirection = FlexDirection.Row
}
};
center.Add(_applyToAllEnginesButton);
I'd say, it's juts a code sugar. Or maybe some style at all.
Yeah, I cannot add a center to the button itself. I might be able to add something like CenteredVisualElement. where you add you buttons to or something
But these things are quite specific use cases though, so not too sure about it yet
Since if I do this, why can't I simply have a preset that have buttons be place at the left and right of the full width etc...
This sounds like a good option. left-right-center. Depends on the use-case.
Anyway, it's not something super important. My code works well, and it's not huge.
Just took 30 mins of research, lol.
I think you have 2 or 4 more than just those. Maybe Ill make a builder for it in the end but will see
In the end it's just like CSS, and CSS is always a nightmare. Specially since this is more like the old css
Do Buttons not show up? Do they have to be NineSliceButtons?
and is there an easy way to create them in code without using VisualElementLoader?
I'd guess you aren't using TimberApi for it ? and I have no idea what the actual problem is.
I could, what's the easiest way? Should I be using UIBuilder?
oh, haha, you just subclass NineSliceButton, and make it public,
heh
Depends on what you prefer really and what you used to, the devs probably prefer doing normal UXML, USS. I myself use both in different scenario's.
Adding a few buttons UIBuilder is just way easier, no custom stuff needed.
But when creating a whole custom layout i'd probably do the structure in UXML and then use the UIBuilder for buttons and all
And no, it doesn't have to be NineSlicedButtons
I tried a UIElements.Button with just text, and it was not displayed
Because you don't have styling
yea
This is the documentation I have so far for the UIBUilder
hmm, does 0.7.5.0 still have the old-style functions or am I missing a using statement?
old style from update 5 ?
or are the docs wrong:
.AddClass("my-arrow-down-button", builder => builder
.ClickSound("UI.Click")
.Height(20)
.Width(20)
);
No this is correct for the stylesheet builder
PropertyBuilder only has an Add method though
no
Not the one from nuget
manifest says 0.7.5.0
You have the import using TimberApi.UIBuilderSystem.StyleSheetSystem.Extensions; ?

still crashes,
What kind of button do you want to make ?
ahh, helps if I load TimberApi
I need to add it to required mods,
what's the minimum required version for this 0.7.4.0?
I want to make a button that will show next to a mod in Mod Settings when it can be updated
The maximum is 0.6.4
0.7.4.0 is broken in the latset update
for game 0.6.4.0, then TimberApi 0.7.4.0 should be used?
for game 0.6.5.0 (and.1), then TimberApi 0.7.5.0 should be used?
but both will have UIBuilder with style sheets and extension support, etc
yes
now I'm getting -- Couldn't get an instance of UpdateButton, it wasn't bound. Do I need to add a binding in the configurator?
I guess I forgot to add that to the guide
hmm, doesn't like AsSingleton
ohh, I see it
now I need a reasonable icon that means "update available, click me to update"
maybe something like โป
Or a download icon
How are do you know if there is an update
Will that be for steam of mod.io mods
for Steam, that's what I'm tinkering with
I don't know, that's why I want to throw together a bare minimum to test,
ui/images/game/reset.png is close, but needs to be flipped
Just copy paste the image and flip it in paint or something
yea,
nit: in your examples the css class is my-arrow-down-button, but you're making an ArrowLeftButton and using the arrow-left image
issue is how do I reference that image then, because I'm not building an asset bundle
You could make an asset bundle or just https://timberborn.wiki.gg/wiki/Creating_Mods_(Update_6)#Images
This page documents the native mod support coming to Timberborn in Update 6. The new system makes the most common modding tasks easier to accomplish, less prone to errors, less prone to compatibility issues, and overall makes the game more fun to experiment with.
They can be used as well, probably
blegh, I need a hover image too
I may just use the arrow-right for now,
because I don't want to invest too much time before I know it'll work
Is there a builder for an Image?
I can't find one.
I tried, but it complains about "Couldn't get an instance of ...MyImage, it wasn't bound."
ahh, nm figured it, missing binding(s)
yea, but to insert it -- like where you'd insert a button
otherwise, how is it best to do something like:
UIBuilder.Create<ImageBuilder>()
.AddClass("unavailable-image")
.Build();
Images are just visual elements with a background
but how to create them and add class in an easy way?
Presents use UIBuilder.Create<SomethingBuilder> right?
If you have a preset Image yes
Build<Imagination> would not magically create something that doesn't exist
Since I haven't added a Image preset it probably doesn't work
Timberborn modding documentation
You make a preset which is a complete visual element how you want it including the image
If you want a button with a duck on it you make like DuckButton preset which has te duck image included
I just want the image,
You could make a generic button icon preset. Which I was thinking about but since you cannot use StyleSheets for that I didn't do it.
doesn't need to be on a button
Then make a DuckImage preset
Which is just a VisualElement, with a background attached to it.
at the moment I have this:
public class UnavailableImage : BaseBuilder<Image> {
protected override Image InitializeRoot() {
return UIBuilder.Create<ImageBuilder>()
.AddClass("unavailable-image")
.Build();
}
protected override void InitializeStyleSheet(StyleSheetBuilder styleSheetBuilder) {
styleSheetBuilder
.AddBackgroundClass("unavailable-image", "sprites/statusicons/stranded")
.AddClass("unavailable-image", builder => builder
.Height(28)
.Width(28)
.MarginLeft(7));
}
}
but it means I also have to have:
public class ImageBuilder : ImageBuilder<ImageBuilder, Image> {
protected override ImageBuilder BuilderInstance => this;
}
public abstract class ImageBuilder<TBuilder, TElement> : BaseElementBuilder<TBuilder, TElement>
where TBuilder : BaseElementBuilder<TBuilder, TElement>
where TElement : Image, new() {
protected override TElement InitializeRoot() {
return new TElement();
}
}
so I've probably missed somewhere I could make simpler
If you want to make a element builder yes, but im pretty sure Image isn't a visual element 
but if you don't get errors it must be so not too sure about that element never seen it.
the code compiles and works
If you change your ImageBuilder to a VisualElementBuilder it probably works
What doesn't it do than ?
I think the ImageBuilder may be unnecessary and there should be a way to do it without it,
Image is a VisualElement: https://docs.unity3d.com/ScriptReference/UIElements.Image.html
Gmm
If I change to VisualElementBuilder, it complains that it can't cast Timberborn.CoreUI.NineSliceVisualElement to UnityEngine.UIElements.Image
public class UnavailableImage : BaseBuilder<VisualElement> {
protected override Image InitializeRoot() {
return UIBuilder.Create<VisualElementBuilder>()
.AddClass("unavailable-image")
.Build();
}
protected override void InitializeStyleSheet(StyleSheetBuilder styleSheetBuilder) {
styleSheetBuilder
.AddBackgroundClass("unavailable-image", "sprites/statusicons/stranded")
.AddClass("unavailable-image", builder => builder
.Height(28)
.Width(28)
.MarginLeft(7));
}
}
yea, the issue is that VisualElementBuilder isn't a Unity.UIElements.VisualElement builder, it's a Timberborn.CoreUI.NineSliceVisualElement builder
BaseBuilder<NineSliceVisualElement> ๐
Excepected it to both work since it should extend from it 
?
ahh, this works:
public class UnavailableImage : BaseBuilder<NineSliceVisualElement> {
protected override NineSliceVisualElement InitializeRoot() {
return UIBuilder.Create<VisualElementBuilder>()
.AddClass("unavailable-image")
.Build();
}
protected override void InitializeStyleSheet(StyleSheetBuilder styleSheetBuilder) {
styleSheetBuilder
.AddBackgroundClass("unavailable-image", "sprites/statusicons/stranded")
.AddClass("unavailable-image", builder => builder
.Height(28)
.Width(28)
.MarginLeft(7));
}
}
Nice
Not sure if a ImageBuilder is wanted, what you did should have worked I think. Don't know what the use case of a specific Image element is.
eg:
The stranded icon means that the mod is no longer available on Steam,
From my https://discord.com/channels/558398674389172225/1283367971280126087 mod ๐
Ye I understand the just wanting image, but I don't know about the element in itself if there is anything special about it
you mean for Image vs just using a VisualElement?
Yea
Is it the same as <img> vs <div>?
Might be
You can do <img src="file.png" height=20 width=20> but you can also do <div style="background: url(file.png); height: 20px; width: 20px"></div>
If you could add a github issue for the image builder
There are more important elements (lists/input) that need to go first
Dang my english sucks 
I think it's fine as it is,
I sas just trying to copy what eMka had in https://github.com/eMkaQQ/timberborn-modding/blob/main/Assets/Mods/ModSettings/AssetBundles/Resources/UI/Views/ModSettings/ModSettingsButton.uxml
Yea it isn't really problem with english, I write like this in my own language as well... I just mix my sentences often
Hm ye
hmm, I just noticed in that uxml it imports the Style twice?
That code would exactly work the same if replaced with VisualElement. Will probably add it then later
wym ?
in eMka's ModSettingsButton.uxml, line 2 and 4 import the same Style?
my thoughts too
Or some unity spagethi
The UIBuilder is neet, but also not, I dunno
I am too used to vue components I think
Just making some base elements and reusing those it just easier
hmm, AssetRipper doesn't seem to be able to extract style sheets,
It does not 
But I can 
It isn't 100% plug and play, there are some errors you just need to not throw ๐
And then just fetch all stylesheets that exists and export it to a file
@stone shoal The latest update bnroke TAPI.
ofc it did :_)
240912T002609.570 [EXCEPTION] [TimberApi.SpecificationSystem.GeneratedSpecificationAssetRepository.AddSpecificationRange] MissingMethodException: Method not found: System.Collections.Generic.IEnumerable`1<!!0> Timberborn.PrefabSystem.PrefabService.GetAllMonoBehaviours<!0>()
at TimberApi.SpecificationSystem.GeneratedSpecificationAssetRepository.AddSpecificationRange (System.Collections.Generic.IEnumerable`1[T] generatedSpecifications) (at <3bc3cd6b6ef245de810c597ec3546feb>:0)
at TimberApi.SpecificationSystem.GeneratedSpecificationLoader.PostLoad () (at <3bc3cd6b6ef245de810c597ec3546feb>:0)
at TimberApi.SingletonSystem.SingletonLifecycleServicePatcher+<>c.<LoadAllPrefix>b__0_1 (TimberApi.SingletonSystem.ITimberApiPostLoadableSingleton singleton) (at <7c2bfc8705134b58ad9bc73b7d342569>:0)
at TimberApi.SingletonSystem.SingletonLifecycleServicePatcher.LoadSingleton[T] (System.Collections.Generic.IEnumerable`1[T] singletons, System.Action`1[T] action) (at <7c2bfc8705134b58ad9bc73b7d342569>:0)
at TimberApi.SingletonSystem.SingletonLifecycleServicePatcher.LoadAllPrefix (Timberborn.SingletonSystem.ISingletonRepository ____singletonRepository) (at <7c2bfc8705134b58ad9bc73b7d342569>:0)
at (wrapper dynamic-method) MonoMod.Utils.DynamicMethodDefinition.Timberborn.SingletonSystem.SingletonLifecycleService.LoadAll_Patch1(Timberborn.SingletonSystem.SingletonLifecycleService)
at Timberborn.SingletonSystem.SingletonLifecycleAdapter.Start () (at <6bee00ff3470403b85721900595bca6e>:0)
And I was just in the middle of testing my mod 
for animation controller, yes
They changed something for waterfalls. Maybe for this reason.
The referenced script (Timberborn.Common.AnimationCurveProvider) on this Behaviour is missing!
I only used it to get all prefabs though so..
Probably not a hard fix, but I can't fix it now
Probably doesn't even need a fix, just a recompile,
ILSpy says 0.6.5.1 has:
System.Collections.Generic.IEnumerable`1<!!T> Timberborn.PrefabSystem.PrefabService.GetAllMonoBehaviours<(UnityEngine.MonoBehaviour) T> ()
So I suspect the diff is:
-public IEnumerable<T> GetAllMonoBehaviours<T>()
+public IEnumerable<T> GetAllMonoBehaviours<T>() where T : MonoBehaviour
kinda annoying ngl
Idk what version you are on, but this isn't even the diff
That whole method doesn't even exist
prefabService.GetAllMonoBehaviours<T>() was renamed to prefabService.GetAll<>(). When I updated all the places, it started working.
In case anyone needs TAPI for development before it's properly fixed by @stone shoal
No more need to buy an expensive monitor. TY, @calm copper ๐
BTW, all the mods I use that depends on TAPI are working.
Great! I didn't know which branch is the current, so picked the one with the most recent commits. It's probably not exactly 7.5.0, but if it works on your big set of mods, then it's durable enough ๐
Based on the manifest the one you used was for 6.4.0.
Why?
np
When I extracted the zip my antivirus quarantined all the files
heh.. TAPI's = Timberborn Antivirus Periodic Injury system ๐ ๐
I am trying to use flywheels, but i dont think its possible with the latest update
I was on 0.6.5.1. I didn't realize that there was a new TB version out at the time.
My antivirus expired a month ago. Still not upgraded 
Did your antivirus find anyting? ๐
It just said the files were dangerous and quarantined them but it did that with any mods I download from mod.io so just had to restore the files and itโs all fine. Just overly protective Norton antivirus lol
https://www.virustotal.com/gui/file/d0419ea5aa0494c6594cc4850762840ae3f3d5b0873f4a7e75b71514db43261d?nocache=1
Nothing wrong here
VirusTotal
Just use windows defender... You dont need multiple anti viruses on top of each other
no updates regarding timber API ๐
Beside it working?
is it?
Yes
New version was released in Steam and Mod.io.
excellent!
test.Add(_uiBuilder.Create<DefaultListView>()
.SetItemSource(Test)
.SetBindItem(BindItem)
.SetMakeItem(VisualElement).Build());
Got it functional ๐
It required to have a SetBindItem otherwise unity just won't render it....
Now I need to fix the styling
I will make it throw an error if you didn't set the required method for this one, since I cannot force it within the builder code
The `DefaultListView` requires `SetMakeItem` to be set within the building process.
Could you add
---
MinimumGameVersion: 0.6.1.0
MaximumGameVersion: 0.6.9.9
---
style annotations to the bottom of the file changelogs so that Mod Manager detects which versions are compatible with the game. It does make it much easier to update mods that have the annotations.
Pretty sure. O did
I don't see it for TimberAPI,
ohh, not in the changelog,
do you add it as proper metadata?
Because I add it somewhere else. Does it not work?
This is what Mod Manager sees:
There is 0.6.7.0-04e31ee
Updated it
nice, thanks!
lucikly it looks like not much/any breakage between 0.6.6.1 and 0.6.7.0
I see lots of internal refactoring, that was made possible by the breakage caused by 0.6.6.0
test.Add(_uiBuilder.Create<DefaultListView>()
.SetItemSource(Test)
.SetBindItem(BindItem)
.SetMakeItem(VisualElement).Build());
Finally got it to work
It's a bit more complex than your average preset, it requires you to extend the DefaultListViewItemWrapper preset and add what you want to view inside.
public class MyListItem : DefaultListViewItemWrapper
{
protected override NineSliceVisualElement InitializeRoot()
{
base.InitializeRoot();
VisualElementBuilder.SetWidth(200);
VisualElementBuilder.AddComponent<GameTextLabel>(label => label.SetText("First item"));
return VisualElementBuilder.Build();
}
}
This will add the hover effect and make the items always display in the center of the item height of the list.
If you want your own hover effect you could make this yourself as well. Which wasn't even possible in UIBuilder V1
Dropdowns
var gameDropdown = _uiBuilder.Build<GameDropdown, Dropdown>();
_dropdownItemsSetter.SetItems(gameDropdown, new TestDropdownProvider());
Setter needs to be done after element initialization otherwise you crash, this is just a Timberborn thing
test.Add(_uiBuilder.Create<DefaultScrollView>()
.SetMaxHeight(150)
.SetMaxWidth(150)
.AddComponent<ArrowDownButton>()
.AddComponent<ArrowDownButton>()
.AddComponent<ArrowDownButton>()
.AddComponent<ArrowDownButton>()
.AddComponent<ArrowDownButton>()
.Build());
Your average scroller
Is always full flex width, height until you set a max width, height

It seems some properties were missing, If I change this, this will break everything agin 
Added something that if it would happen again, it doesn't break ๐
Will probably update it when something breaks in update or release
Didn't expect this to be so quick. Nice! 
You could already use them basicly, dropdowns are pre designed by timberborn itself
just do new Dropdown(), initialize it, fill it with a dropdown setter
You can still use the UIBuilder by doing AddComponent(new Dropdown())
Textfields + multilines
test.Add(_uiBuilder.Create<DefaultScrollView>()
.SetMaxHeight(150)
.SetMaxWidth(150)
.AddComponent<DefaultTextField>()
.AddComponent<DefaultTextField>(field => field.SetTextAlign(TextAnchor.MiddleLeft))
.AddComponent<DefaultTextField>(field => field.SetTextAlign(TextAnchor.MiddleRight))
.AddComponent<DefaultTextField>()
.AddComponent<DefaultTextField>(field => field.Large())
.Build());
test.Add(_uiBuilder.Create<VisualElementBuilder>()
.AddComponent<DefaultTextField>(field => field.MultiLine().SetHeight(100).SetWidth(100))
.AddComponent<DefaultTextField>(field => field.MultiLine().SetHeight(100).SetWidth(100).Large())
.Build()
);
@vast otter @austere tangle mind testing this with many mods, specially things that add UI.
Thought it would make things crash, but unstuckify and employment automation seem to work
, I think I have all presets which I had before + more. If people are missing presets preferably by PR, or ask if they want to have it in TimberApi 
Now only the FragmentBuilder and BoxBuilder and then UIBuilder V2 is fully finished
with 39 mods, it is OK ?
Hopefully ๐
I don't know which mods add UI, this is where the breaking change is in ๐
I know 2 and those work
Ups, first crash
With the live one it works right ?
Dam your before me
I think this is even a other change 
YA, no issues
big chance its good statistic checking now
Could you guess which of those mods add a button ?
A button that includes text
Smart power sure it does
Thats from emka, he doesn't use TimberApi
Smart power crashes before I can even start it 
ya smart power it is
I get this error
[Error : Unity Log] MissingMethodException: Method not found: System.Reflection.MethodInfo HarmonyLib.AccessTools.DeclaredMethod(string,System.Type[],System.Type[])
Stack trace:
S
With smart power
i have smart power v1.11.0 from steam 
Crash not at main menu but at game load
Smart Power UI
Correct
Do you 2 still run bepinex ?
nope
Nope
Let's see if that makes a difference
Okay that was the problem
How do you poen timberborns console
?
i have the Player.log open in notepad++
%appdata%\..\LocalLow\Mechanistry\Timberborn\
not for my 22 mods atleast
Not include here the mods that depends on TAPI ....
@calm copper I am going to break your smart power mod, I renamed a preset (which had still the old format). When would you have time for an update ?
here is the beta build that breaks it #1064983064020799498 message
Sure Igor will be "happy" to take a break from fixing TimberCommons ๐ฎ
public VisualElement InitializeFragment()
{
return _builder.Create<VisualElementBuilder>()
.AddComponent<FragmentBuilder>(builder => builder.AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.AddComponent<FragmentBuilder>(builder => builder.PalePurple().AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.AddComponent<FragmentBuilder>(builder => builder.Purple().AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.AddComponent<FragmentBuilder>(builder => builder.PurpleStriped().AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.AddComponent<FragmentBuilder>(builder => builder.Red().AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.AddComponent<FragmentBuilder>(builder => builder.RedStriped().AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.AddComponent<FragmentBuilder>(builder => builder.Blue().AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.AddComponent<FragmentBuilder>(builder => builder.Gray().AddComponent<GameTextLabel>(button => button.SetText("Workplace").Big()))
.BuildAndInitialize();
}
Fragments are simple :), Tomorrow ill try to fix the BoxBuilder than everything what could be done before, can be done now.
I really should've just waited one week before doing my UI. ๐ At least I learned some stuff.
Luckly the only thing the fragment builder does is adding a background and some padding
That's all I did in my fragments as well. ๐ And then added the components. But all good. I am glad I learned how the UIbuilder and presets work. And the next UI is already in the waiting.
540
Nice 
The UI stuff was really what was hindering me on releasing tool mods, as I wanted a way to configure the tools in game. What I had prepared in U5 lost the focus of the tool and closed it, but got that figured out now. Really appreciate your work for the UI components.
Yeah understandable UI is annoying
. Even with the full on unity way I don't like it, but it's not as bad as old unity UI.
TimberApi only exists because I tried to make a mod and required tools for it. Now I don't have mods only tools 
I can do it today, but we need to release at the same time I guess.
By a chance, can you keep the old preset for one version? This way there will be no "broken period".
Or let me know which preset you're going to break. I used to make my own visual elements in the past, I can temporarily switch back to that practice.
ButtonGame
I will update it tomorrow (like 12h from now)
Ok. I'll rollback to my old solution (direct element creation).
You could also copy the preset
That moment when I feel I'm doing a right thing creating own UI wrappers ๐คฃ
@stone shoal I don't remember this gap between the bullet and the orange bar. Is it a preset thing or TB related?
Do you also rename ButtonGame? Do I need to copy it?
SmartPower v1.11.1 is released. It doesn't use GameButton and ButtonGame.
Now, back to TimberCommons ๐
No clue
Didnt see it before and havent changed it
test.Add(_uiBuilder.Create<BoxBuilder>()
.AddCloseButton("ButtonName")
.AddHeader("Settings")
.SetWidth(500)
.SetHeight(500)
.AddComponent<DefaultTextField>()
.AddComponent<DefaultTextField>()
.AddComponent<DefaultTextField>()
.Build());
https://mod.io/g/timberborn/m/timberapi
0.7.7.0
- Added
AddClassto all presets, for adjusting presets with stylesheets. - Fixed missing
ModifyRootto all presets. - Renamed
ButtonGamepreset toGameButton. - Renamed many abstract presets to
...Buton - Added
ListViewpresets. - Added
TextFieldpresets. - Added
ScrollViewpresets. - Added
Dropdownpresets. - Added
FragmentBuilder. - Added
BoxBuilder.
UIBuilder V2 is now completed, If I missed something feel free to ping.
Timber API is crashing when trying to edit maps.
Normal game play works fine. @stone shoal
Is not because of TimberApi, automationtoolgroup a mod that adds this tool doesn't work
Got it. Sorry. Will report it to the correct place.
, Cleaned up all test code for potentially new features. Put it in a zip for later usage
Facing some issues getting the dropdown to working. Do you possibly have some example code with the DropDownItemSetter?
NullReferenceException: Object reference not set to an instance of an object
at Timberborn.DropdownSystem.Dropdown.ClearItems () [0x0000e] in <768dcf31afb34b8591dcd0bf9a174de4>:0
at Timberborn.DropdownSystem.DropdownItemsSetter.SetItems (Timberborn.DropdownSystem.Dropdown dropdown,
While I did read this: #1064983064020799498 message
I didn't realize what it meant until just now. After the BuildAndInitialize() of the _builder. I had thought, based on the example code just above that message, that the dropdownItemsetter was to just be called separately. But no, it must be even later.
Nevertheless, it's partially working. Respectively at least not crashing. Though I do need to figure out a few things again. Should've made a few commits...
Did you fixnit already?
Work in progress, I've got some stuff to load, but I had deleted half my implementation for the dropdownprovider, as I had assumed the issue there.
We'll see in the next build if it works out.
Still trying to work something out with the FragementBuilder as well. Haven't figured out if I am actually getting the dropdownlist inside of it or not.
You can always checkout the usages from the game with the only difference is the creation of it. The rest need to be done outside of the builder anyway
Was going more for the look from Timberborn, So still a few kinks to work out. And guess I need to bind in the localization ๐คญ
My problem is understanding which part is timberborn, and what is timberapi. I did end up completely copying a simple dropdownprovider from the ripped game, and that made me check out the dropdown build I had implemented. Which then made me realize that, since I was having a nullreference, something wasn't be initialized correctly.
Pretty much nothing is TimberApi. It only creates a instance of the dropdown and it csn give the element a name.
The you do like .Q<> stuff to get it again and initialize it after having run buildAndInitislize
timberapi crash again?
Dont know have you tried it?
when i enable timberapi it always crash ๐ฆ
This don't mean the TAPI is the culprit, you must see what mod is not update to work with the latest TimberApi version.
without the crash log, see in the yellow marked path, no one can help you
Getting BindingNotFoundException: TimberApi.Tools.ToolSystem.ToolService isn't instantiable due to its missing dependency: Timberborn.SelectionToolSystem.SelectionToolProcessorFactory when trying to load the MapEditor with my tool open. Inside game works fine. Noticed @calm copper added the [MapEditor] to the Configurator, yet that didn't do much for me. Any ideas?
Thanks in advance for some tips. I won't get around to further testing till tomorrow.
hmm how is it is the toolbar in map editor replaced or only ingame 
The message means Timberborn.SelectionToolSystem.SelectionToolProcessorFactory wasn't added to DI container. I guess the map editor doesn't use selection tools? Kinda surprising. Copying config with editor tag added probably will solve it
[Context("MapEditor")] public class SelectionToolSystemConfigurator : IConfigurator { public void Configure(IContainerDefinition containerDefinition) { containerDefinition.Bind<SelectionToolProcessorFactory>().AsSingleton(); } }
Only ingame for now
Thanks for the suggestion. It did resolve that one, but it just came up with the next. I did try a few other things, but I didn't manage it all. I also faced issue that the GroupIds are not available, as the map editor is obviously not set up the same. So currently I don't see a solution that would inhibit the mod being loaded, as the tool has no use in the map-editor anyways. I guess it'll have to be up to the users to ensure it is disabled before doing any map editing. Or is there a known solution to avoid loading tools using timberapi with the map editor? or are there no such tools around?
I think I need to add a property to tools to load them in specific scenes 
Defaulting to Game
Would be appreciated in the long run. I have currently resorted to just noting in the descriptions of the mods that they are not usable in the Map Editor.
I don't even quite know why the tool system is running in map editor to be fair, since I also disabled the bottombar rework patches
But in the long run I want it to be in the map editor as well. Since knatte had before too many map editor buildings
And like you said, not all tools makes sense to have in map editor ๐
This is because of a custom tool you added right ?
Yes, it applies both to the "Cutter Tool" and the "Forest Tool" mods I did. After integrating the missing bindings due to Timberborn not loaded Forestry, etc. It then failed because TimberApi couldn't link to the GroupIds (which are obviously then also not available in the mapeditor toolbar).
If you need something to test something with it sometime, the Cutter Tool code is on github, you can find the link through the Mod.io page.
Are there any Update 6 mods using ToolSpecification or is that no longer a thing in Update 6?
heh, theToolSpecificationDeserializer class is defined in ToolSpecificationDeserliaser.cs (yes, with that typo)
Pipet
Knatte also uses it for more groups, but just editing not creating new ones
And any mod that wants a 3rd row
I got this kind of spam in logs when using min-max slider.
241011T220332.960 [ERROR] [UnityEngine.UIElements.UIRLayoutUpdater.Update] Layout update is struggling to process current layout (consider simplifying to avoid recursive layout): PanelRootElement ScalablePanelSettings (x:0.00, y:0.00, width:2400.00, height:1350.00) world rect: (x:0.00, y:0.00, width:2400.00, height:1350.00)
241011T220332.967 [ERROR] [UnityEngine.UIElements.UIRLayoutUpdater.Update] Layout update is struggling to process current layout (consider simplifying to avoid recursive layout): PanelRootElement ScalablePanelSettings (x:0.00, y:0.00, width:2400.00, height:1350.00) world rect: (x:0.00, y:0.00, width:2400.00, height:1350.00)
241011T220332.974 [ERROR] [UnityEngine.UIElements.UIRLayoutUpdater.Update] Layout update is struggling to process current layout (consider simplifying to avoid recursive layout): PanelRootElement ScalablePanelSettings (x:0.00, y:0.00, width:2400.00, height:1350.00) world rect: (x:0.00, y:0.00, width:2400.00, height:1350.00)
241011T220332.988 [ERROR] [UnityEngine.UIElements.UIRLayoutUpdater.Update] Layout update is struggling to process current layout (consider simplifying to avoid recursive layout): PanelRootElement ScalablePanelSettings (x:0.00, y:0.00, width:2400.00, height:1350.00) world rect: (x:0.00, y:0.00, width:2400.00, height:1350.00)
241011T220332.994 [ERROR] [UnityEngine.UIElements.UIRLayoutUpdater.Update] Layout update is struggling to process current layout (consider simplifying to avoid recursive layout): PanelRootElement ScalablePanelSettings (x:0.00, y:0.00, width:2400.00, height:1350.00) world rect: (x:0.00, y:0.00, width:2400.00, height:1350.00)
241011T220333.000 [ERROR] [UnityEngine.UIElements.UIRLayoutUpdater.Update] Layout update is struggling to process current layout (consider simplifying to avoid recursive layout): PanelRootElement ScalablePanelSettings (x:0.00, y:0.00, width:2400.00, height:1350.00) world rect: (x:0.00, y:0.00, width:2400.00, height:1350.00)
No idea why. There were no such problems before. Tried to search on the Unity forums, but didn't get a clear answer why.
It started approximately at the moment when the UI of the slider got broken. Since it's an editor component, maybe something needs to be adjusted to it before brining to the game. Just a thought.
Wym an editor component. Its the same as a button etc
Hmm. Disregard the word "editor" ๐ I found docs for this component in the sections which is different to the common "script" section.
Anyway, it's not working... strange. There are visual artefacts compared to the initial u6 versions. And there are log warnings. I wish I knew why.
Very weird... I can probably check next week on it
[Context("Bootstrapper")]
public class TestConfigurator : IConfigurator
{
public void Configure(IContainerDefinition containerDefinition)
{
Debug.LogWarning("SWAGGGEEEEEEEEEEEEEEEE");
}
}
I needed the bootstrap configurator for multiple things and didn't want to do multiple patches sooo... Now it's possible to have a Bootstrapper context!
Before I didn't have it in TimberApi, because you don't want to use it mostly. But now I don't control that part anymore and why not make it accesible for everyone ๐
Aaaand, I didn't need it anymore. But going to keep it anyway ๐
yes
Like pmduda said: yes
Use case is low, and most things should not use it. But if you need a list to persist over the duration of the game eg. ModRepoistory it's very handy
speaking of low usecase, is it somehow possible to create a min-max slider with "current value"-indication? i.e.
Including the min, max ?
as values underneeth it ?
just the additional bar in the middle is enough ๐
Now I am confused I thought you were talking about the labels 
You want a slider with 3 bars ?
si
Nope
๐
It might be possible but I don't even know how to make a normal slider without it being in unity.
If you really want to maybe this helps altough it's for a toggle and I think it's outdated 
Outdated as in syntaxt changed, not too badly just using some attributes instead of extending factories or something
or i ll just be lazy and write the current value into the slider label xD
Than you still have 2 bars instead of 3 ๐
i just want to represent 3 values, whilst 2 are modifiable by user, the rest is a "don't care"
Adding the values in labels isn't hard, you could just do it in a preset. Make a visual element with a flex.
Add label
Add slider
Add label
Now you have them all in the same row
Do I get it right that it's the best context to apply harmony patches? It seems to me so.
You got that indeed false 
IModStarter is the best place for harmony patches
This is just for the Bootstrapper configurator just like the MapEditorConfigurator, GameConfigurator and MainMenuConfigurator
Good idea about the mod starter
For some reason, all this time I was only considering the configurator ๐คฆ
Sh*t happens, configurators are already pretty late in that sense, without IModStarter I could not even patch it.
(โฏยฐโกยฐ)โฏ๏ธต โปโโป
lol

6th time the charm
I really need to fix that it saves the screenshot the the clipboard
Fixed
Did you find and punished those 6 losers already? ๐ก๏ธ



