New UI System

I’ve been implementing a new UI system over the past week or so. This replaces panorama, but it works pretty much identically.

The big difference is that it’s all coded in c#. So all the logic, all the rendering, it’s all c# side. My feeling is that it’s going to be a lot of pain initially for less sustained pain in the future.

It’s all still styled using css… For example, the text boxes above are just:

textentry
{
	padding: 8px;
	background-color: #444;
	color: #bbb;
	border: 1px solid black;
	border-radius: 2px;
	transition: all .1s ease;
	margin: 10px;
	box-shadow: 5px 5px 10px rgba( 0, 0, 0, 0.2 );

	&:hover
	{
		color: #ccc;
		border-color: white;
	}

	&:focus
	{
		background-color: #aaa;
		border: 1px solid #fff;
		color: #333;
		box-shadow: 0px 0px 0 transparent;
	}
}

Although it obviously isn’t html, the backend follows the style of html. Events run upwards to ancestors unless stopped. It’s all actually a lot more simple than before.

The text box is defined in addon code. Here’s some snippets.

public override void OnKeyTyped( char k )
{
	if ( HasSelection() )
	{
		ReplaceSelection( k.ToString() );
	}
	else
	{
		Text = Text.Insert( CaretPos, k.ToString() );
		MoveCaratPos( 1 );
	}
}
public override void OnDoubleClick( string button )
{
	if ( button == "mouseleft")
	{
		SelectWord( GetLetterAt( MousePos ) );
		CaretPos = SelectionEnd;
	}

	base.OnDoubleClick( button );
}
public override void OnEvent( string eventName )
{
	if ( eventName == "onmousedown" )
	{
		var pos = GetLetterAt( MousePos );

		if ( pos >= 0 )
		{
			SetCaretPos( pos );
		}
	}

	if ( eventName == "onmouseup" )
	{
		var pos = GetLetterAt( MousePos );
		if ( SelectionEnd > 0 ) pos = SelectionEnd;
			CaretPos = pos.Clamp( 0, Text.Length );
	}

	if ( eventName == "onmousemove" && HasActive )
	{
		var pos = GetLetterAt( MousePos );
		if ( pos != CaretPos )
		{
			SetSelection( CaretPos, pos );
		}
	}

	base.OnEvent( eventName );
}
public override void OnButtonTyped( string button, KeyModifiers km )
{
	if ( HasSelection() && ( button == "delete" || button == "backspace" ) )
	{
		ReplaceSelection( "" );
		return;
	}

	if ( button == "delete" )
	{
		if ( CaretPos < Text.Length )
		{
			Text = Text.Remove( CaretPos, 1 );
		}
	}

	if ( button == "backspace" )
	{
		if ( CaretPos > 0 )
		{
			Text = Text.Remove( CaretPos - 1, 1 );
			MoveCaratPos( -1 );

		}
	}

	if ( button == "a" && km.Ctrl )
	{
		SelectionStart = 0;
		SelectionEnd = Text.Length;
	}

	if ( button == "home" )
	{
		SetCaretPos( 0, km.Shift );
	}

	if ( button == "end" )
	{
		SetCaretPos( Text.Length, km.Shift );
	}

	if ( button == "left" )
	{
		MoveCaratPos( -1, km.Shift );
	}

	if ( button == "right" )
	{
		MoveCaratPos( 1, km.Shift );
	}
}

We’re just getting started right now, so I’ll be adding features as I need them. The end goal is everything panorama supported but acting more like regular web stuff.

26 Likes

I think it’s a good idea to have everything use C#

3 Likes

Not sure I like UI being done in C#, gives me xamarin forms flashback.

The events solution does seem a bit odd as well, doesn’t c# have events built-in by default?

2 Likes

Looks very cool!

2 Likes

I imagine that these will get ironed out as Garry progresses and adds more functionality.

2 Likes

How do I make my buttons bouncy

1 Like

Nested css :ok_hand:

1 Like

Ui looks nice :+1:
The shadows are a nice touch as well

1 Like

If I might ask what your reasoning is for not just outright using Chromium? Like are you actually going to re-implement flexbox display style or is it going to be psuedo-css with a subset of all css properties? It seems like a really tall order. Are there going to be containers that can dispaly html? I remember in Unreal Engine sandbox you were planning on using Vue.js for binding stuff.

2 Likes

This is the update I’ve been waiting for the most!

With switching to Source2 I was eagerly awaiting the UI aspect to be fully gone over. By far this is going to be one of the most interacted with mechanics in Sandbox aside from normal player controls. It’s wall all players will be starring at and clicking through for settings, inventory, team selection and so much more.

I think having a full c# backend for UI is going to be great in the long run, might have some hiccups and learning curves along the way but I honestly can’t wait!

1 Like

I don’t much like c# events. The way events work here are on purpose so we can use them easily with html layouts if we choose.

It makes binding much simpler imo

textbox.AddEvent( "onkeydown.tab", OnTabPressed );
button.AddEvent( "onmousedown.right", () => Log.Info( "Right Clicked!" ) );

It also means that adding extra events is really simple

panel.OnEvent( "mycustomevent" );

And from a newbie point of view, what could be better than this

public override void OnEvent( string eventname )
{
   Log.Info( $"Event Fired: {eventname}"  );
}
10 Likes
transition: all 0.4s bounce-out;

You can also add your own easing functions

8 Likes

The biggest issue with using a real webkit system for me is always binding data. The hoops you have to jump through are exhausting. This is what we were fighting against when we were adding view.js etc. In the end the performance is never as good as if you were just rendering it directly.

It’s actually a very simple thing. You’re just rendering rects. It shouldn’t need to be complicated.

8 Likes

Do CSS animations work?

1 Like

Transitions do, I haven’t done animations yet but they shouldn’t be a problem.

8 Likes

awesome

1 Like

What does the UI scaffolding look like?
I see you are controlling the panel events with your snippets there, however what are you applying the CSS to? For example, in webkit this is done with HTML, in panorama it’s XML.

Are you creating the panels/rects/markup in C# too? If so, what does it look like for your example?

1 Like

This is very cool. Nice work!

1 Like

It’s just like vgui/derma. I have a html/xml layout system too, but I haven’t wired that back in yet.

8 Likes

Ah nice. That looks very nice.
I can imagine some people would prefer the XML layout system, but having everything in C# like derma was in Lua, but with CSS replacing vugi sounds great.

1 Like