Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
222f9bb
Implement https://github.com/Facepunch/Rust.Community/pull/89
dassjosh Jul 13, 2026
d1b6d64
Implement https://github.com/Facepunch/Rust.Community/pull/92
dassjosh Jul 13, 2026
d3f402e
Implement https://github.com/Facepunch/Rust.Community/pull/91
dassjosh Jul 13, 2026
2ac5c1a
Implement https://github.com/Facepunch/Rust.Community/pull/82
dassjosh Jul 13, 2026
b6daec1
Initial setup of tooltip component still WIP.
dassjosh Jul 13, 2026
d724e56
Updated TooltipComponent.Offset to be the correct type
dassjosh Jul 13, 2026
4d6f044
Implement DestroyUis. Still WIP need to know how the sent data is str…
dassjosh Jul 14, 2026
6616a73
Updated Tooltip Component with CUI Changes
dassjosh Jul 14, 2026
b966f35
Added FadeDuration to ScrollbarComponent
dassjosh Jul 14, 2026
6d04817
Updated DestroyUis to use proper RPC call
dassjosh Jul 14, 2026
dc72cc1
Remove RectMask2D as that wasn't merged in.
dassjosh Jul 15, 2026
a92d09c
SourceGen build
dassjosh Jul 15, 2026
3c39034
Added Names to Threads
dassjosh Jul 15, 2026
8a1a4bf
Initial work on Pie Menu Builder
dassjosh Jul 15, 2026
41e4355
Added DisabledColor to ColorBlockComponent
dassjosh Jul 15, 2026
f54ed5f
Fixed CanvasGroup having the wrong Type
dassjosh Jul 19, 2026
69dd9b8
Updated Unit Tests for CUI Updates
dassjosh Jul 19, 2026
bc6d8f0
Fixed PieMenuBuilder missing EnterPool
dassjosh Jul 19, 2026
97632a0
UI Debug cleanup
dassjosh Jul 19, 2026
81be7e5
Removed Oxide AddUi Harmony Patch
dassjosh Jul 19, 2026
14e09c1
Removed RectMask2D ComponentType
dassjosh Jul 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ private AnimationHandler()
{
Thread thread = new(AnimationLoop)
{
Name = $"{UiFrameworkExtension.Instance.Name} {nameof(AnimationHandler)}",
IsBackground = true
};
thread.Start();
Expand Down
25 changes: 25 additions & 0 deletions src/Rust.UIFramework/Animation/Handlers/AnimationTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,31 @@ public void OnAnimationFinalized(AnimationId id)
UiPool.Internal.FreeList(playerPanels);
}
}

public void RemoveUiForSend(SendInfo send, List<string> names)
{
if (send.connections == null)
{
for (int index = 0; index < names.Count; index++)
{
string name = names[index];
RemoveUiForSend(send.connection.userid, name);
}

return;
}

List<Connection> connections = send.connections;
for (int connectionIndex = 0; connectionIndex < connections.Count; connectionIndex++)
{
Connection connection = connections[connectionIndex];
for (int index = 0; index < names.Count; index++)
{
string name = names[index];
RemoveUiForSend(connection.userid, name);
}
}
}

public void RemoveUiForSend(SendInfo send, string name)
{
Expand Down
33 changes: 31 additions & 2 deletions src/Rust.UIFramework/Builder/BaseBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,37 @@ public static void DestroyUi(SendInfo send, string name)
{
if (Net.sv.IsConnected() && CommunityEntity.ServerInstance.net != null)
{
Singleton<AnimationTracker>.Instance.RemoveUiForSend(send, name);
UiDestroyRequest.Create(name, send).Enqueue();
DestroyUiRequest.Create(name, send).Enqueue();
}
}

public static void DestroyUis(IEnumerable<string> names) => DestroyUis(Net.sv.connections, names);
public static void DestroyUis(IEnumerable<Connection> connections, IEnumerable<string> names) => DestroyUis(SendInfoBuilder.Get(connections), names);
public static void DestroyUis(List<Connection> connections, IEnumerable<string> names) => DestroyUis(SendInfoBuilder.Get(connections), names);
public static void DestroyUis(IEnumerable<BasePlayer> players, IEnumerable<string> names) => DestroyUis(SendInfoBuilder.Get(players), names);
public static void DestroyUis(List<BasePlayer> players, IEnumerable<string> names) => DestroyUis(SendInfoBuilder.Get(players), names);

public static void DestroyUis(BasePlayer player, IEnumerable<string> names)
{
if (player)
{
DestroyUis(player.Connection, names);
}
}

public static void DestroyUis(Connection connection, IEnumerable<string> names)
{
if (connection is { connected: true })
{
DestroyUis(SendInfoBuilder.Get(connection), names);
}
}

public static void DestroyUis(SendInfo send, IEnumerable<string> names)
{
if (Net.sv.IsConnected() && CommunityEntity.ServerInstance.net != null)
{
DestroyUisRequest.Create(names, send).Enqueue();
}
}
#endregion
Expand Down
16 changes: 8 additions & 8 deletions src/Rust.UIFramework/Builder/BaseUiBuilder.ChildComponents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@ namespace Oxide.Ext.UiFramework.Builder;
public abstract partial class BaseUiBuilder
{
#region ColorBlock
public ColorBlockComponent ColorBlock(UiButton button, in UiColor? highlightColor = null, in UiColor? pressedColor = null, in UiColor? selectedColor = null, in float? colorMultiplier = null, in float? fadeDuration = null)
public ColorBlockComponent ColorBlock(UiButton button, in UiColor? highlightColor = null, in UiColor? pressedColor = null, in UiColor? selectedColor = null, in UiColor? disabledColor = null, in float? colorMultiplier = null, in float? fadeDuration = null)
{
return button.AddColorBlock(highlightColor, pressedColor, selectedColor, colorMultiplier, fadeDuration);
return button.AddColorBlock(highlightColor, pressedColor, selectedColor, disabledColor, colorMultiplier, fadeDuration);
}
#endregion

#region ScrollBar
public (ScrollbarComponent horizontal, ScrollbarComponent vertical) AddScrollBars(UiScrollView view, bool invert = false, bool autoHide = false, string handleSprite = null, string trackSprite = null, float size = JsonDefaults.ScrollBar.Size,
UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null)
UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null, float fadeDuration = JsonDefaults.ScrollBar.FadeDuration)
{
return view.AddScrollBars(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor);
return view.AddScrollBars(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor, fadeDuration);
}

public ScrollbarComponent AddHorizontalScrollBar(UiScrollView view, bool invert = false, bool autoHide = false, string handleSprite = null, string trackSprite = null, float size = JsonDefaults.ScrollBar.Size,
UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null)
UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null, float fadeDuration = JsonDefaults.ScrollBar.FadeDuration)
{
return view.AddHorizontalScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor);
return view.AddHorizontalScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor, fadeDuration);
}

public ScrollbarComponent AddVerticalScrollBar(UiScrollView view, bool invert = false, bool autoHide = false, string handleSprite = null, string trackSprite = null, float size = JsonDefaults.ScrollBar.Size,
UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null)
UiColor? handleColor = null, UiColor? highlightColor = null, UiColor? pressedColor = null, UiColor? trackColor = null, float fadeDuration = JsonDefaults.ScrollBar.FadeDuration)
{
return view.AddVerticalScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor);
return view.AddVerticalScrollBar(invert, autoHide, handleSprite, trackSprite, size, handleColor, highlightColor, pressedColor, trackColor, fadeDuration);
}
#endregion
}
4 changes: 4 additions & 0 deletions src/Rust.UIFramework/Builder/BaseUiBuilder.Components.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Runtime.CompilerServices;
using Oxide.Ext.UiFramework.Colors;
using Oxide.Ext.UiFramework.Components;
using Oxide.Ext.UiFramework.Constants;
using Oxide.Ext.UiFramework.Controls;
using Oxide.Ext.UiFramework.Enums;
using Oxide.Ext.UiFramework.Exceptions;
using Oxide.Ext.UiFramework.Interfaces;
using Oxide.Ext.UiFramework.Json;
using Oxide.Ext.UiFramework.Libraries;
using Oxide.Ext.UiFramework.Offsets;
Expand Down Expand Up @@ -34,6 +36,8 @@ public partial class BaseUiBuilder
Naming.SetComponentName(component, reference, NamingMode, NamingCache, Components.Count);
return component.SetUpdate(UpdateMode);
}

public T SubComponent<T>(BaseUiComponent component) where T : BaseComponent, ISubComponent, new() => component.GetOrAddSubComponent<T>();
#endregion

#region Update
Expand Down
48 changes: 48 additions & 0 deletions src/Rust.UIFramework/Builder/BaseUiBuilder.SubComponents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Oxide.Ext.UiFramework.Components;
using Oxide.Ext.UiFramework.Enums;
using Oxide.Ext.UiFramework.Json;
using Oxide.Ext.UiFramework.Offsets;
using Oxide.Ext.UiFramework.Types;
using Oxide.Ext.UiFramework.UiElements;
using UnityEngine;
Expand Down Expand Up @@ -260,4 +261,51 @@ public LayoutElementComponent LayoutElement(BaseUiComponent component,
return Component<T>(scroll).SetName(Singleton<ScrollViewContentCache>.Instance.GetContentName(scroll.Reference.Name)).SetUpdate(UpdateMode.Update);
}
#endregion

#region Canvas Group
public CanvasGroupComponent CanvasGroup(BaseUiComponent component) => SubComponent<CanvasGroupComponent>(component);

public CanvasGroupComponent CanvasGroup(BaseUiComponent component, float alpha = 1f, bool allowRaycast = true, bool interactable = true, UiCanvasGroupFade? fade = null)
{
CanvasGroupComponent canvas = CanvasGroup(component);
canvas.Alpha = alpha;
canvas.AllowRaycast = allowRaycast;
canvas.Interactable = interactable;
if(fade.HasValue)
{
canvas.Fade = fade.Value;
}
return canvas;
}
#endregion

#region Rect Mask 2D
public MaskComponent Mask(BaseUiComponent component) => SubComponent<MaskComponent>(component);

public MaskComponent Mask(BaseUiComponent component, bool showMaskGraphic)
{
MaskComponent mask = Mask(component);
mask.ShowMaskGraphic = showMaskGraphic;
return mask;
}
#endregion

#region Rect Mask 2D
public TooltipComponent Tooltip(BaseUiComponent component) => SubComponent<TooltipComponent>(component);

public TooltipComponent Tooltip(BaseUiComponent component, string text, CommunityEntity.TooltipType type = CommunityEntity.TooltipType.Default, Tooltip.DelayType delay = JsonDefaults.ToolTip.Delay, TooltipContainer.PositionMode position = JsonDefaults.ToolTip.Position, Vector2? offset = null, bool useCenter = JsonDefaults.ToolTip.UseCenter)
{
TooltipComponent tooltip = Tooltip(component);
tooltip.Text = text;
tooltip.TooltipType = type;
tooltip.Delay = delay;
tooltip.Position = position;
if (offset.HasValue)
{
tooltip.Offset = offset.Value;
}
tooltip.UseCenter = useCenter;
return tooltip;
}
#endregion
}
38 changes: 38 additions & 0 deletions src/Rust.UIFramework/Builder/PieMenu/BasePieMenuBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Collections.Generic;
using Network;
using Oxide.Ext.UiFramework.Pooling;

namespace Oxide.Ext.UiFramework.Builder;

public abstract class BasePieMenuBuilder : BasePoolable
{
public void AddUi(BasePlayer player)
{
if (player && player.IsConnected)
{
SendUi(SendInfoBuilder.Get(player));
}
else
{
TryDispose();
}
}

public void AddUi(Connection connection)
{
if (connection is { connected: true })
{
SendUi(SendInfoBuilder.Get(connection));
}
else
{
TryDispose();
}
}

public void AddUi(IEnumerable<Connection> connections) => SendUi(SendInfoBuilder.Get(connections));
public void AddUi(IEnumerable<BasePlayer> players) => SendUi(SendInfoBuilder.Get(players));
public void AddUi() => SendUi(SendInfoBuilder.Get(Net.sv.connections));

public abstract void SendUi(SendInfo send);
}
13 changes: 13 additions & 0 deletions src/Rust.UIFramework/Builder/PieMenu/CachedPieMenu.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;
using Network;
using Oxide.Ext.UiFramework.Helpers;

namespace Oxide.Ext.UiFramework.Builder;

public class CachedPieMenu(byte[] menu) : BasePieMenuBuilder
{
public override void SendUi(SendInfo send)
{
RpcFunctions.SendPieMenu(send, menu);
}
}
88 changes: 88 additions & 0 deletions src/Rust.UIFramework/Builder/PieMenu/PieMenuBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using Facepunch;
using Network;
using Oxide.Ext.UiFramework.Colors;
using Oxide.Ext.UiFramework.Extensions;
using Oxide.Ext.UiFramework.Helpers;
using Oxide.Ext.UiFramework.Plugins;
using ProtoBuf;

namespace Oxide.Ext.UiFramework.Builder;

public class PieMenuBuilder : BasePieMenuBuilder
{
private string _closeCommand;
private readonly List<PieMenuItemBuilder> _items = [];

public IUiFrameworkPlugin Plugin { get; private set; }

public static PieMenuBuilder Create(IUiFrameworkCorePlugin plugin) => plugin.PluginPool.Get<PieMenuBuilder>().Init(plugin);

private PieMenuBuilder Init(IUiFrameworkPlugin plugin)
{
Plugin = plugin;
return this;
}

public PieMenuBuilder SetCloseCommand(string command)
{
_closeCommand = command;
return this;
}

public PieMenuItemBuilder AddItem()
{
PieMenuItemBuilder builder = PieMenuItemBuilder.Create(Plugin);
_items.Add(builder);
return builder;
}

public PieMenuBuilder AddItem(Action<PieMenuItemBuilder> action)
{
PieMenuItemBuilder builder = AddItem();
action(builder);
return this;
}

public PieMenuItemBuilder AddItem(string name, string description, string image, bool disabled, bool selected, int order,
PieMenu.MenuOption.ColorMode.PieMenuSpriteColorOption colorMode, UiColor color, string command = null, string nextCommand = null, string prevCommand = null, string disabledCommand = null)
{
return AddItem().SetName(name).SetDescription(description).SetCommand(command).SetImage(image).SetDisabled(disabled).SetSelected(selected).SetOrder(order)
.SetColorMode(colorMode).SetColor(color).SetNextCommand(nextCommand).SetPreviousCommand(prevCommand).SetDisabledCommand(disabledCommand);
}

public CachedPieMenu ToCache()
{
using BufferStream stream = Pool.Get<BufferStream>().Initialize();
using CustomPie pie = ToProto();
pie.WriteToStream(stream);
TryDispose();
return new CachedPieMenu(stream.GetBuffer().ToArray());
}

public override void SendUi(SendInfo send)
{
using CustomPie pie = ToProto();
RpcFunctions.SendPieMenu(send, pie);
}

private CustomPie ToProto()
{
CustomPie pie = Pool.Get<CustomPie>();
List<CustomPieMenu> menus = pie.menus = Pool.Get<List<CustomPieMenu>>();
pie.closeCommand = _closeCommand;
for (int index = 0; index < _items.Count; index++)
{
PieMenuItemBuilder item = _items[index];
menus.Add(item.Build());
}
return pie;
}

protected override void EnterPool()
{
_closeCommand = null;
_items.FreeValues();
}
}
Loading