using System.Diagnostics; using Oxide.Core.Libraries.Covalence; using Oxide.Game.Rust.Libraries; using System.Text; using System.Collections.Generic; using Oxide.Core; using System.Linq; using Oxide.Plugins.UiEngineFrameworkMethods; using UnityEngine; using Oxide.Core.Plugins; using CompanionServer.Handlers; using ProtoBuf; using UnityEngine.UI; using Network; using System.Data.SqlTypes; using System; using Oxide.Game.Rust.Cui; using Newtonsoft.Json; using UnityEngine.PlayerLoop; namespace Oxide.Plugins { [Info("UiEngineFramework", "mr01sam", "1.0.1")] [Description("Extended tools for making CUI graphics.")] public partial class UiEngineFramework : CovalencePlugin { protected static UiEngineFramework INSTANCE { get; set; } public static Oxide.Core.VersionNumber? PluginVersion => INSTANCE?.Version; [PluginReference] private Plugin ImageLibrary; private void OnServerInitialized() { INSTANCE = this; TOKEN = Guid.NewGuid(); UiEngine.Load(); SCOPE = UiEngine.Init(this); } private void Unload() { UiEngine.Unload(); SCOPE = null; INSTANCE = null; } private void OnPluginUnloaded(Plugin plugin) { if (plugin.Name == Name) { return; } UiEngine.Dispose(plugin.Name); } private static void Debug(string message, Func condition = null) { if (condition != null && !condition.Invoke()) { return; } INSTANCE.Puts($"DEBUG: {message}"); } internal UiEngineInstance SCOPE; private void OnUserDisconnected(IPlayer player) { var userId = ulong.Parse(player.Id); NextTick(() => { UiEngine.ClearDataForPlayer(userId); }); } internal static bool IsAssetPath(string path) { return !string.IsNullOrWhiteSpace(path) && path.StartsWith("assets/"); } //private static Timer UiDiagTimer = null; //[Command("ui.list.svr")] //private void CmdUiListSvr(IPlayer player, string command, string[] args) //{ // if (!player.IsServer) { return; } // var basePlayer = player.Object as BasePlayer; // var scope = SCOPE.Player(basePlayer); // if (UiDiagTimer != null) // { // UiDiagTimer.Destroy(); // UiDiagTimer = null; // return; // } // if (args.Length == 0) // { // player.Message("Requires plugin name"); // return; // } // var plug = args[0]; // UiDiagTimer = timer.Every(2f, () => // { // var targetScope = UiEngine.Get(plug); // Puts($"COUNT: {targetScope.PlayerInstances.Count}"); // }); //} //[Command("ui.list")] //private void CmdUiList(IPlayer player, string command, string[] args) //{ // if (!player.IsAdmin) { return; } // var basePlayer = player.Object as BasePlayer; // var scope = SCOPE.Player(basePlayer); // if (UiDiagTimer != null) // { // UiDiagTimer.Destroy(); // scope.Destroy("ui.diaglist"); // UiDiagTimer = null; // return; // } // if (args.Length == 0) // { // player.Message("Requires plugin name"); // return; // } // var plug = args[0]; // var targetScope = UiEngine.Get(plug); // var targetPlayerScope = targetScope.Player(basePlayer); // var u = new UI // { // ID = "ui.diaglist", // Parent = "Overall", // Origin = Origin.UpperRight, // Height = 600, // Width = 200, // Color = COLOR.Black // }; // scope.Show(u); // DiagList(basePlayer, plug); // UiDiagTimer = timer.Every(2f, () => // { // DiagList(basePlayer, plug); // }); //} //[Command("ui.diag")] //private void CmdUiDiag(IPlayer player, string command, string[] args) //{ // if (!player.IsAdmin) { return; } // var basePlayer = player.Object as BasePlayer; // var scope = SCOPE.Player(basePlayer); // if (UiDiagTimer != null) // { // UiDiagTimer.Destroy(); // scope.Destroy("ui.diag"); // UiDiagTimer = null; // return; // } // if (args.Length == 0) // { // player.Message("Requires plugin name"); // return; // } // var plug = args[0]; // var targetScope = UiEngine.Get(plug); // var targetPlayerScope = targetScope.Player(basePlayer); // var u = new UI // { // ID = "ui.diag", // Parent = "Overall", // Origin = Origin.UpperRight, // Height = 600, // Width = 200, // Color = COLOR.Black // }; // scope.Show(u); // DiagContent(basePlayer, plug); // UiDiagTimer = timer.Every(2f, () => // { // DiagContent(basePlayer, plug); // }); //} //private void DiagList(BasePlayer basePlayer, string plugin) //{ // var scope = SCOPE.Player(basePlayer); // var targetScope = UiEngine.Get(plugin); // var targetPlayerScope = targetScope.Player(basePlayer); // var c = new UI // { // ID = "ui.diaglist.content", // Parent = "ui.diaglist", // Height = 40, // Origin = Origin.RowUpper, // Layout = new UiLayout // { // Cols = 2, // Rows = 2 // }, // Children = UI.ForEach(new[] // { // new // { // Label = "Plugin", // Value = plugin // }, // new // { // Label = "Players", // Value = targetScope.InstanceCount().ToString() // } // }, (e) => // { // return new UI[] // { // new UI // { // Text = e.Label, // TextAlign = UnityEngine.TextAnchor.MiddleLeft, // TextSize = 8 // }, // new UI // { // Text = e.Value, // TextAlign = UnityEngine.TextAnchor.MiddleLeft, // TextSize = 8 // } // }; // }) // }; // var d = new UI // { // ID = "ui.diaglist.elements", // Parent = "ui.diaglist", // Layout = new UiLayout // { // Rows = 100, // Cols = 2 // }, // Trim = D4(top: 50), // Children = UI.ForEach(targetScope.PlayerInstances, (inst) => // { // return new UI // { // Text = inst.Value?._basePlayer.displayName, // TextSize = 5 // }; // }) // }; // scope.Show(c, d); //} //private void DiagContent(BasePlayer basePlayer, string plugin) //{ // var scope = SCOPE.Player(basePlayer); // var targetScope = UiEngine.Get(plugin); // var targetPlayerScope = targetScope.Player(basePlayer); // var c = new UI // { // ID = "ui.diag.content", // Parent = "ui.diag", // Height = 40, // Origin = Origin.RowUpper, // Layout = new UiLayout // { // Cols = 2, // Rows = 3 // }, // Children = UI.ForEach(new[] // { // new // { // Label = "Plugin", // Value = plugin // }, // new // { // Label = "Actions", // Value = targetPlayerScope.Actions.Count.ToString() // }, // new // { // Label = "Elements", // Value = targetPlayerScope.ActiveElements.Count.ToString() // } // }, (e) => // { // return new UI[] // { // new UI // { // Text = e.Label, // TextAlign = UnityEngine.TextAnchor.MiddleLeft, // TextSize = 8 // }, // new UI // { // Text = e.Value, // TextAlign = UnityEngine.TextAnchor.MiddleLeft, // TextSize = 8 // } // }; // }) // }; // var d = new UI // { // ID = "ui.diag.elements", // Parent = "ui.diag", // Layout = new UiLayout // { // Rows = 100, // Cols = 2 // }, // Trim = D4(top: 50), // Children = UI.ForEach(targetPlayerScope.ActiveElementsIds, (id) => // { // return new UI // { // Text = id, // TextSize = 5 // }; // }) // }; // scope.Show(c, d); //} } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public partial class UiEnginePlayer { /* Build Specific */ private List _buildElements = new List(); private List _localElements = new List(); private string _buildId; private string _buildParent; private int _buildDepth = 0; private UiRectTransform _buildRectTransform; private UiRectTransform _secondaryRectTransform; private void BuildElement(UI template, IUiComponent component) { var element = new UiElement { ID = _buildId, Parent = _buildParent, Padding = template.Padding, Visible = template.Visible, Update = false, FadeOut = template.FadeOut, IsSubElement = _buildDepth > 0, Duration = template.Duration, Components = new List() { _buildDepth == 0 ? _buildRectTransform : _secondaryRectTransform }, Children = new List(), SubElements = new List() }; if (component != null) { element.Components.Add(component); } if (_buildDepth == 0) { if (template.NeedsCursor) { element.Components.Add(new UiNeedsCursorComponent()); } if (template.NeedsKeyboard) { element.Components.Add(new UiNeedsKeyboardComponent()); } if (template.Layout != null) { element.Limit = template.Layout.Value.Rows * template.Layout.Value.Cols; } } _localElements.Add(element); //_buildElements.Add(element); _buildDepth++; if (_buildDepth > 0) { _buildParent = template.ID; _buildId += $":d{_buildDepth}"; } } private void Build(UI template) { if (template == null) { return; } // Assign to parent var parentElement = ActiveElements.GetValueOrDefault(template.Parent, UiElement.Empty); if (!parentElement.IsNull && !parentElement.IsSubElement) { if (parentElement.Children == null) { parentElement.Children = new List(); } if (template.InheritPadding) { template.InheritedPadding = parentElement.Padding; } else { template.InheritedPadding = D4(0f); } parentElement.Children.Add(template.ID); } // Reset build _buildDepth = 0; _buildId = template.ID; _buildParent = template.Parent; _localElements = new List(); // Compound Element var isCompoundElement = (template.Button != null || !template.Color.IsTransparentOrNull); // Default Layout if (template.Layout != null) { var layout = template.Layout.Value; if (layout.Cols <= 0) { layout.Cols = 1; } if (layout.Rows <= 0) { layout.Rows = 1; } template.Layout = layout; } /* RectTransform */ if (template.Origin == null) { template.Origin = (template.Width > 0 || template.Height > 0) ? Origin.LowerLeft : Origin.Full; } // Origin var origin = template.Origin.Value; // Determine Growth if (template.GrowX == Growth.Auto) { template.GrowX = origin.xmin < 0.5 ? Growth.Positive : origin.xmax > 0.5 ? Growth.Negative : Growth.Neutral; } if (template.GrowY == Growth.Auto) { template.GrowY = origin.ymin < 0.5 ? Growth.Positive : origin.ymax > 0.5 ? Growth.Negative : Growth.Neutral; } // Grid Positional if (template.Row.HasValue) { if (template.Height == 0) { template.Height = template.Row.Value.x; } template.Position = P4(down: template.Row.Value.x * template.Row.Value.y); } if (template.Col.HasValue) { if (template.Width == 0) { template.Width = template.Col.Value.x; } template.Position = P4(right: template.Col.Value.x * template.Col.Value.y); } // Position var oxmin = template.Position.xmax - template.Position.xmin; var oxmax = template.Position.xmax - template.Position.xmin; var oymin = template.Position.ymax - template.Position.ymin; var oymax = template.Position.ymax - template.Position.ymin; // Height / Width oxmin += template.GrowX == Growth.Negative ? -template.Width : template.GrowX == Growth.Neutral ? -template.Width / 2f : 0f; oxmax += template.GrowX == Growth.Negative ? 0 : template.GrowX == Growth.Neutral ? template.Width / 2f : template.Width; oymin += template.GrowY == Growth.Negative ? -template.Height : template.GrowY == Growth.Neutral ? -template.Height / 2f : 0f; oymax += template.GrowY == Growth.Negative ? 0 : template.GrowY == Growth.Neutral ? template.Height / 2f : template.Height; // Apply Inherited Padding if (origin.xmin == 0) { oxmin += template.InheritedPadding.xmin; if (template.Width > 0) { oxmax = oxmin + template.Width; } } if (origin.ymin == 0) { oymin += template.InheritedPadding.ymin; if (template.Height > 0) { oymax = oymin + template.Height; } } if (origin.xmax == 1) { oxmax -= template.InheritedPadding.xmax; if (template.Width > 0) { oxmin = oxmax - template.Width; } } if (origin.ymax == 1) { oymax -= template.InheritedPadding.ymax; if (template.Height > 0) { oymin = oymax - template.Height; } } var offsets = D4(oxmin, oymin, oxmax, oymax); // Apply Trim offsets = offsets.Merge(template.Trim); // Apply Insets if (!isCompoundElement) { offsets = offsets.Merge(template.Inset); } // Primary _buildRectTransform = new UiRectTransform { Anchors = origin, Offsets = offsets }; _secondaryRectTransform = new UiRectTransform { Anchors = Origin.Full, Offsets = D4(template.Inset.xmin, template.Inset.ymin, -template.Inset.xmax, -template.Inset.ymax) }; /* Button Image Auto */ if (!template.ButtonImage.IsEmptyImage() && template.ButtonImageType == ImageType.Auto) { var imageStr = template.ButtonImage.ToString(); if (UiEngine.IsAssetImage(imageStr)) { template.ButtonImageType = ImageType.Sprite; } else if (int.TryParse(imageStr, out _)) { template.ButtonImageType = ImageType.Item; } else { if (template.ButtonImageColor.IsNull) { template.ButtonImageType = ImageType.Raw; } else { template.ButtonImageType = ImageType.Simple; } } if (template.ButtonImage != null && template.ButtonImageColor.IsNull) { template.ButtonImageColor = COLOR.White; } } /* Empty Button Image */ if (template.ButtonImage != null && UiEngine.IsEmptyImage(template.ButtonImage.ToString())) { template.ButtonImage = null; if (template.Color.IsTransparentOrNull) // TODO verify { template.Color = template.ButtonImageColor; } } /* Setup Button Image */ if (template.ButtonImage != null && template.ButtonImageType != ImageType.Sprite) { template.Image = template.ButtonImage; template.ImageColor = template.ButtonImageColor; template.ImageType = template.ButtonImageType; template.ButtonImage = null; template.ButtonImageColor = COLOR.Unset; } /* ImageType */ if (!template.Image.IsEmptyImage() && template.ImageType == ImageType.Auto) { var imageStr = template.Image.ToString(); //if (imageStr.StartsWith("assets/")) //{ // template.ImageType = ImageType.Sprite; //} //else if (int.TryParse(imageStr, out _)) //{ // template.ImageType = ImageType.Raw; //} //else //{ // template.ImageType = ImageType.Simple; //} if (UiEngine.IsAssetImage(imageStr)) { template.ImageType = ImageType.Sprite; } else if (int.TryParse(imageStr, out _)) { template.ImageType = ImageType.Item; } else { if (template.ImageColor.IsNull) { template.ImageType = ImageType.Raw; } else { template.ImageType = ImageType.Simple; } } } /* Empty Image */ if (template.Image != null && template.Image.IsEmptyImage()) { template.Image = null; if (template.Color.IsTransparentOrNull) { template.Color = template.ImageColor; } } /* If Image is Null but ImageColor is specified, and Color is not specified, used ImageColor */ if (template.Image.IsEmptyImage() && template.Color.IsNull && !template.ImageColor.IsTransparentOrNull) { template.Color = template.ImageColor; } /* Auto set image colors */ if (!template.Image.IsEmptyImage() && template.ImageColor.IsNull) { template.ImageColor = COLOR.White; } if (!template.Image.IsEmptyImage() && template.ButtonImageColor.IsNull) { template.ButtonImageColor = COLOR.White; } /* Image */ if (template.Button == null && !template.Color.IsTransparentOrNull) { if (template.Image != null && template.ImageType == (ImageType.Sprite | ImageType.Raw)) { BuildElement(template, new UiRawImageComponent { FadeIn = template.FadeIn, Color = template.Color, Png = template.ImageType == (ImageType.Raw) ? UiEngine.GetImageData(template.Image.ToString()) : null, Sprite = template.ImageType == ImageType.Sprite ? UiEngine.GetImageData(template.Image.ToString()) : null, Material = template.Material }); } else { var image = new UiImageComponent { FadeIn = template.FadeIn, Color = template.Color, Material = template.Material }; BuildElement(template, image); } } /* Button */ if (template.Button != null) { BuildElement(template, new UiButtonComponent { FadeIn = template.FadeIn, //Color = template.ButtonImageColor.IsTransparent ? template.Color : template.ButtonImageColor, Color = template.ButtonImageType == ImageType.Sprite ? template.ButtonImageColor : template.Color, Material = template.Material, Command = template.Button.GetCommand(Plugin, template.ID), Sprite = template.ButtonImageType == ImageType.Sprite ? UiEngine.GetImageData(template.ButtonImage.ToString()) : null }); //if (template.Image == null && !template.Color.IsTransparent) //{ // BuildElement(template, new UiImageComponent // { // FadeIn = template.FadeIn, // Color = template.Color, // Material = template.Material // }); //} if (template.Button is UiActionButton) { Actions[template.ID] = ((UiActionButton)template.Button).Action; } } /* InputField */ if (template.Input != null) { BuildElement(template, new UiInputComponent { FadeIn = template.FadeIn, Text = template.InputDefaultText, FontSize = template.TextSize, Font = template.TextFont, Color = template.TextColor, Command = template.Input.GetCommand(Plugin, template.ID), Align = template.TextAlign, LineType = template.InputLineType, CharsLimit = template.InputCharLimit, AutoFocus = template.InputAutoFocus, IsPassword = template.InputIsPassword }); if (template.Input is UiInputAction) { Actions[template.ID] = ((UiInputAction)template.Input).Action; } } /* Second Image */ if (template.Image != null) { if (template.ImageType == ImageType.Raw) { BuildElement(template, new UiRawImageComponent { FadeIn = template.FadeIn, Color = template.ImageColor, Png = template.ImageType == ImageType.Raw ? UiEngine.GetImageData(template.Image.ToString()) : null, Material = template.Material }); } else { var image = new UiImageComponent { FadeIn = template.FadeIn, Color = template.ImageColor, Material = template.ImageMaterial }; switch (template.ImageType) { case ImageType.Sprite: image.Sprite = UiEngine.GetImageData(template.Image.ToString()); break; case ImageType.Item: image.ItemId = int.Parse(template.Image.ToString()); image.SkinId = template.ImageSkinId; break; default: image.Png = UiEngine.GetImageData(template.Image.ToString()); break; } BuildElement(template, image); } } /* Text */ if (template.Text != null) { BuildElement(template, new UiTextComponent { FadeIn = template.FadeIn, Text = template.Text, FontSize = template.TextSize, FontType = template.TextFont, Color = template.TextColor, Align = template.TextAlign }); } /* RectTransform if Empty */ if (_localElements.Count == 0) { BuildElement(template, null); } /* Layout */ int? limit = null; #region Layout if (template.Layout != null) { var layout = template.Layout.Value; limit = layout.Rows * layout.Cols; var cellW = 1f / layout.Cols; var cellH = 1f / layout.Rows; var top = 1f; var bottom = 0f; var left = 0f; var colGap = layout.Gaps.x; var rowGap = layout.Gaps.y; var ox = 0f; var oy = 0f; var i = 0; var fixedW = layout.ColWidth > 0; var fixedH = layout.RowHeight > 0; var rowReverse = layout.ReverseRows; for(int r = 0; r < layout.Rows; r++) { var h = layout.RowHeights?.GetValueOrDefault(r, layout.RowHeight) ?? layout.RowHeight; for (int c = 0; c < layout.Cols; c++) { var cellId = $"{template.ID}:l{i}"; var cxmin = fixedW ? 0 : left; var cxmax = fixedW ? 0 : left + cellW; var cymin = fixedH ? 1 : rowReverse ? bottom : top - cellH; var cymax = fixedH ? 1 : rowReverse ? (bottom + cellH) : top; var w = layout.ColWidths?.GetValueOrDefault(c, layout.ColWidth) ?? layout.ColWidth; var coxmin = fixedW ? ox : 0; var coxmax = fixedW ? ox + w : 0; var coymin = fixedH ? oy - h : 0; var coymax = fixedH ? oy : 0; var cell = new UiElement { ID = cellId, Parent = template.ID, Visible = template.Visible, IsSubElement = true, FadeOut = template.FadeOut, Components = new List { new UiRectTransform { Anchors = D4(cxmin, cymin, cxmax, cymax), Offsets = D4(coxmin, coymin, coxmax, coymax) } }, Children = new List(), SubElements = new List() }; _localElements.Add(cell); // End Col left += cellW; ox += fixedW ? w : 0f; ox += colGap; i++; } // End Row left = 0f; ox = 0; top -= cellH; bottom += cellH; oy -= fixedH ? h : 0; oy -= rowGap; } } #endregion // Assign those secondary elements as subelements if (_localElements.Count > 0) { for (int i = 1; i < _localElements.Count; i++) { _localElements[0].SubElements.Add(_localElements[i].ID); } for (int i = 0; i < template.Children.Count; i++) { var child = template.Children[i]; if (child == null) { continue; } _localElements[0].Children.Add(child.ID); } } // Add local elements to build _buildElements.AddRange(_localElements); /* Children */ int cc = 0; foreach (var child in template.Children) { if (child == null || !child.Enabled) { continue; } child.Parent = template.ID; child.InheritedPadding = child.InheritPadding ? template.Padding : D4(0); if (child.InheritFade && template.FadeOut > 0) { child.FadeOut = template.FadeOut; } if (child.InheritFade && template.FadeIn > 0) { child.FadeIn = template.FadeIn; } if (limit != null) { var cellId = $"{template.ID}:l{cc % limit}"; child.Parent = cellId; child.Visible = template.Visible && cc < limit; } else { child.Visible = template.Visible; } Build(child); cc++; } } } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { #region Consts public const char Quote = '"'; public const char Colon = ':'; public const char Space = ' '; public const char Comma = ','; public const char BraceOpen = '['; public const char BraceClose = ']'; public const char CurlyOpen = '{'; public const char CurlyClose = '}'; public const string FieldName = "name"; public const string FieldDestroyUI = "destroyUi"; public const string FieldFadeOut = "fadeOut"; public const string FieldUpdate = "update"; public const string FieldParent = "parent"; public const string FieldComponents = "components"; public const string FieldType = "type"; #endregion #region Serializer public class UiSerializer { private const int BufferSizePerElement = 1024; public char[] _chars; public int _charsLength = 0; public int _bufferSize = 0; public int _timesSized = 0; public void InitBuffer(int elementCount) { var estimatedBufferSize = elementCount * BufferSizePerElement; _chars = new char[estimatedBufferSize]; _bufferSize = estimatedBufferSize; } public void ExtendBufferIfNeeded() { if (_charsLength >= _bufferSize - BufferSizePerElement) { _bufferSize += BufferSizePerElement; System.Array.Resize(ref _chars, _bufferSize); _timesSized++; } } public void AppendChar(char c) { _chars[_charsLength++] = c; } private void AppendString(string s) { foreach (char c in s) { _chars[_charsLength++] = c; } } public void Print() { INSTANCE.Puts($"{string.Join("", _chars)}"); } public void Output() { Interface.Oxide.DataFileSystem.WriteObject($"{INSTANCE.Name}/Output", JsonConvert.DeserializeObject(string.Join("", _chars))); } public void AddKey(string key) { // " + key + " + : + "? + value + "? AppendChar(Quote); AppendString(key); AppendChar(Quote); AppendChar(Colon); } public void AddKeyValue(string key, object value, bool quotes = true, bool comma = true, bool ignore = false) { if (ignore) { return; } // " + key + " + : + "? + value + "? AppendChar(Quote); AppendString(key); AppendChar(Quote); AppendChar(Colon); if (quotes) AppendChar(Quote); AppendString(value.ToString()); if (quotes) AppendChar(Quote); if (comma) AppendChar(Comma); } public void AddComponent(IUiComponent component, bool comma = true) { AppendChar(CurlyOpen); component.Serialize(this); AppendChar(CurlyClose); if (comma) AppendChar(Comma); } public void StartElement(string name, string parent) { AppendChar(CurlyOpen); AddKeyValue(FieldName, name); AddKeyValue(FieldDestroyUI, name); AddKeyValue(FieldParent, parent); AddKey(FieldComponents); AppendChar(BraceOpen); } public void EndElement(bool comma = true) { AppendChar(BraceClose); AppendChar(CurlyClose); if (comma) AppendChar(Comma); } public void Start() { AppendChar(BraceOpen); } public void End() { AppendChar(BraceClose); } public void Serialize(UiEnginePlayer scope, IEnumerable elements) { var count = elements.Count(); if (count <= 0) { return; } InitBuffer(count); AppendChar(BraceOpen); for (int i = 0; i < count; i++) { var element = elements.ElementAt(i); if (element.Visible == false) { element.Update = false; CuiHelper.DestroyUi(scope._basePlayer, element.ID); scope.ActiveElements[element.ID] = element; continue; } scope.ActiveElements[element.ID] = element; element.Serialize(this); if (i < count - 1) { AppendChar(Comma); } } foreach (var element in elements) { } AppendChar(BraceClose); } } public interface IUiSerializable { public void Serialize(UiSerializer uiSerializer); } #endregion #region Components public interface IUiComponent : IUiSerializable, INullable { } public interface IUiGraphicComponent : IUiComponent { public string ImageKey { get; set; } public UiColor Color { get; set; } public string Sprite { get; set; } public string Png { get; set; } public string Material { get; set; } } public struct UiRectTransform : IUiComponent { public Dim4 Anchors { get; set; } public Dim4 Offsets { get; set; } public readonly bool IsNull => Anchors.Equals(null) && Offsets.Equals(null); public void Serialize(UiSerializer b) { b.AddKeyValue(FieldType, "RectTransform"); b.AddKeyValue("anchormin", $"{Anchors.xmin} {Anchors.ymin}"); b.AddKeyValue("anchormax", $"{Anchors.xmax} {Anchors.ymax}"); b.AddKeyValue("offsetmin", $"{Offsets.xmin} {Offsets.ymin}"); b.AddKeyValue("offsetmax", $"{Offsets.xmax} {Offsets.ymax}", comma: false); } } public struct UiRawImageComponent : IUiComponent, IUiGraphicComponent { public float FadeIn; public UiColor Color { get; set; } public string Sprite { get; set; } public string Png { get; set; } public string Material { get; set; } [JsonIgnore] public string ImageKey { get; set; } public readonly bool IsNull => Color.Equals(null) && Sprite.Equals(null) && Png.Equals(null) && Material.Equals(null); public void Serialize(UiSerializer b) { b.AddKeyValue("color", $"{Color.r} {Color.g} {Color.b} {Color.a}"); b.AddKeyValue("fadeIn", FadeIn, quotes: false, ignore: FadeIn <= 0); b.AddKeyValue("material", Material ?? string.Empty, ignore: string.IsNullOrWhiteSpace(Material)); b.AddKeyValue("sprite", Sprite ?? string.Empty, ignore: string.IsNullOrWhiteSpace(Sprite)); b.AddKeyValue("png", Png ?? string.Empty, ignore: string.IsNullOrWhiteSpace(Png)); b.AddKeyValue(FieldType, "UnityEngine.UI.RawImage", comma: false); } } public struct UiImageComponent : IUiComponent, IUiGraphicComponent { public float FadeIn; public UiColor Color { get; set; } public int ItemId { get; set; } public ulong SkinId { get; set; } public string Sprite { get; set; } public string Png { get; set; } public string Material { get; set; } [JsonIgnore] public string ImageKey { get; set; } public readonly bool IsNull => ItemId.Equals(default) && SkinId.Equals(default) && Color.Equals(default) && Sprite.Equals(default) && Png.Equals(default) && Material.Equals(default); public void Serialize(UiSerializer b) { b.AddKeyValue(FieldType, "UnityEngine.UI.Image"); b.AddKeyValue("fadeIn", FadeIn, quotes: false, ignore: FadeIn <= 0); b.AddKeyValue("itemid", ItemId, quotes: false, ignore: ItemId==0); b.AddKeyValue("skinid", SkinId, quotes: false, ignore: ItemId==0 || SkinId==0); b.AddKeyValue("sprite", Sprite ?? string.Empty, ignore: string.IsNullOrWhiteSpace(Sprite)); b.AddKeyValue("material", Material ?? string.Empty, ignore: string.IsNullOrWhiteSpace(Material)); b.AddKeyValue("png", Png ?? string.Empty, ignore: string.IsNullOrWhiteSpace(Png)); b.AddKeyValue("color", $"{Color.r} {Color.g} {Color.b} {Color.a}", comma: false); } } public struct UiInputComponent : IUiComponent { public float FadeIn; public string Text { get; set; } public int FontSize { get; set; } public string Font { get; set; } public TextAnchor Align { get; set; } public UiColor Color { get; set; } public int CharsLimit { get; set; } public string Command { get; set; } public bool? NeedsKeyboard { get; set; } public bool? AutoFocus { get; set; } public bool IsPassword { get; set; } public InputField.LineType? LineType { get; set; } public readonly bool IsNull => FadeIn.Equals(default) && Command.Equals(default) && Color.Equals(default) && Text.Equals(default) && FontSize.Equals(default) && Font.Equals(default) && Align.Equals(default) && CharsLimit.Equals(default); public void Serialize(UiSerializer b) { b.AddKeyValue("fadeIn", FadeIn, quotes: false, ignore: FadeIn <= 0); b.AddKeyValue(FieldType, "UnityEngine.UI.InputField"); b.AddKeyValue("text", Text ?? string.Empty); b.AddKeyValue("fontSize", FontSize == 0 ? 14 : FontSize, quotes: false); b.AddKeyValue("font", Font ?? FONT.Bold); b.AddKeyValue("command", $"{Command}"); b.AddKeyValue("align", $"{Align}"); b.AddKeyValue("autofocus", AutoFocus, ignore: AutoFocus == null); b.AddKeyValue("password", IsPassword, ignore: IsPassword == false); b.AddKeyValue("characterLimit", CharsLimit, quotes: false, ignore: CharsLimit <= 0); b.AddKeyValue("lineType", LineType ?? InputField.LineType.SingleLine); b.AddKeyValue("color", $"{Color.r} {Color.g} {Color.b} {Color.a}", comma: false); } } public struct UiButtonComponent : IUiComponent { public float FadeIn; public UiColor Color { get; set; } public string Command { get; set; } public string Material { get; set; } public string Sprite { get; set; } public readonly bool IsNull => FadeIn.Equals(default) && Command.Equals(default) && Color.Equals(default) && Sprite.Equals(default) && Material.Equals(default); public void Serialize(UiSerializer b) { b.AddKeyValue("fadeIn", FadeIn, quotes: false, ignore: FadeIn <= 0); b.AddKeyValue(FieldType, "UnityEngine.UI.Button"); b.AddKeyValue("sprite", $"{Sprite}", ignore: string.IsNullOrWhiteSpace(Sprite)); b.AddKeyValue("material", Material, ignore: string.IsNullOrWhiteSpace(Material)); b.AddKeyValue("command", $"{Command}"); b.AddKeyValue("color", $"{Color.r} {Color.g} {Color.b} {Color.a}", comma: false); } } public struct UiTextComponent : IUiComponent { public float FadeIn; public UiColor Color; public string Text; public int FontSize; public string FontType; public TextAnchor Align; public readonly bool IsNull => FadeIn.Equals(default) && Text.Equals(default) && Color.Equals(default) && FontSize.Equals(default) && FontType.Equals(default) && Align.Equals(default); public void Serialize(UiSerializer b) { b.AddKeyValue("fadeIn", FadeIn, quotes: false, ignore: FadeIn <= 0); b.AddKeyValue(FieldType, "UnityEngine.UI.Text"); b.AddKeyValue("text", Text ?? string.Empty); b.AddKeyValue("fontSize", FontSize == 0 ? 14 : FontSize, quotes: false); b.AddKeyValue("font", FontType ?? FONT.Bold); b.AddKeyValue("color", $"{Color.r} {Color.g} {Color.b} {Color.a}"); b.AddKeyValue("align", $"{Align}", comma: false); } } public struct UiNeedsCursorComponent : IUiComponent { public readonly bool IsNull => false; public void Serialize(UiSerializer b) { b.AddKeyValue(FieldType, "NeedsCursor"); } } public struct UiNeedsKeyboardComponent : IUiComponent { public readonly bool IsNull => false; public void Serialize(UiSerializer b) { b.AddKeyValue(FieldType, "NeedsKeyboard", comma: false); } } #endregion #region Elements public struct UiElement : IUiSerializable { public static UiElement Empty = new UiElement(); public bool Visible; public string ID; public string Parent; public float FadeOut; public bool Update; public int Page; public int Limit; public float? Duration; public Dim4 Padding; public bool IsSubElement; public List Components; public List SubElements; public List Children; public readonly bool IsNull => this.Equals(Empty); public readonly T GetComponent() where T : IUiComponent { try { return (T)Components.FirstOrDefault(x => x is T); } catch (Exception) { return default; } } public void SetComponent(T component) where T : IUiComponent { if (Components == null) { Components = new List(); } for (int i = 0; i < Components.Count; i++) { if (Components[i] is T) { Components.RemoveAt(i); if (component is IUiGraphicComponent casted) { if (!string.IsNullOrWhiteSpace(casted.ImageKey)) { if (UiEngine.IsAssetImage(casted.ImageKey)) { casted.Sprite = UiEngine.GetImageData(casted.ImageKey); } else { casted.Png = UiEngine.GetImageData(casted.ImageKey); } } Components.Add(casted); } else { Components.Add(component); } return; } } } public void UpdateComponent(Func action) where T: IUiComponent { var c = GetComponent(); if (c.Equals(default)) { return; } c = action.Invoke(c); SetComponent(c); } public void Serialize(UiSerializer b) { this.ID = ID ?? Guid.NewGuid().ToString(); this.Parent = Parent ?? "Overlay"; b.ExtendBufferIfNeeded(); b.AppendChar(CurlyOpen); b.AddKeyValue(FieldName, ID); b.AddKeyValue(FieldFadeOut, FadeOut, quotes: false, ignore: FadeOut <= 0); b.AddKeyValue(FieldUpdate, Update.ToString().ToLower(), quotes: false); b.AddKeyValue(FieldParent, Parent); b.AddKeyValue("enabled", Visible.ToString().ToLower(), quotes: false); b.AddKey(FieldComponents); b.AppendChar(BraceOpen); if (Components != null) { for (int i = 0; i < Components.Count; i++) { b.AppendChar(CurlyOpen); Components[i].Serialize(b); b.AppendChar(CurlyClose); if (i < Components.Count - 1) { b.AppendChar(Comma); } } b.AppendChar(BraceClose); } b.AppendChar(Comma); b.AddKeyValue(FieldDestroyUI, ID, ignore: Update, comma: false); b.AppendChar(CurlyClose); } } #endregion } } namespace Oxide.Plugins.UiEngineFrameworkMethods { public static class ExtensionMethods { //internal static bool IsEmpty(this object str) => str == null || string.IsNullOrWhiteSpace(str.ToString()); internal static bool IsEmptyImage(this object imageKey) { return imageKey == null || string.IsNullOrWhiteSpace(imageKey.ToString()) || UiEngineFramework.UiEngine._emptyImages.Contains(imageKey.ToString()); } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public interface IUI { } public static class Origin { public static readonly Dim4 LowerLeft = new Dim4(0, 0, 0, 0); public static readonly Dim4 LowerCenter = new Dim4(0.5f, 0, 0.5f, 0); public static readonly Dim4 LowerRight = new Dim4(1f, 0, 1f, 0); public static readonly Dim4 MiddleLeft = new Dim4(0, 0.5f, 0, 0.5f); public static readonly Dim4 MiddleCenter = new Dim4(0.5f, 0.5f, 0.5f, 0.5f); public static readonly Dim4 MiddleRight = new Dim4(1f, 0.5f, 1f, 0.5f); public static readonly Dim4 UpperLeft = new Dim4(0, 1f, 0, 1f); public static readonly Dim4 UpperCenter = new Dim4(0.5f, 1f, 0.5f, 1f); public static readonly Dim4 UpperRight = new Dim4(1f, 1f, 1f, 1f); public static readonly Dim4 RowLower = new Dim4(0, 0, 1, 0); public static readonly Dim4 RowMiddle = new Dim4(0, 0.5f, 1, 0.5f); public static readonly Dim4 RowUpper = new Dim4(0, 1, 1, 1); public static readonly Dim4 ColLeft = new Dim4(0, 0, 0, 1); public static readonly Dim4 ColCenter = new Dim4(0.5f, 0, 0.5f, 1); public static readonly Dim4 ColRight = new Dim4(1, 0, 1, 1); public static readonly Dim4 Full = new Dim4(0, 0, 1, 1); public static Dim4 SplitX(int by, int index) { var sect = 1f / (float)by; return new Dim4(sect*index, 0, sect * (index+1), 1); } public static Dim4 SplitY(int by, int index) { var sect = 1f / (float)by; return new Dim4(0, sect * index, 1, sect * (index + 1)); } } public static Dim2 Row(float height, int index) { return D2(height, index); } public static Dim2 Col(int width, int index) { return D2(width, index); } public static Dim2 D2(float all = 0) => new Dim2(all, all); public static Dim2 D2(float x = 0, float y = 0) => new Dim2(x, y); public static Dim4 D4(float all = 0) => new Dim4(all, all, all, all); public static Dim4 D4(float left = 0, float bottom = 0, float right = 0, float top = 0) => new Dim4(left, bottom, right, top); public static Dim4 P4(float left = 0, float up = 0, float right = 0, float down = 0) => new Dim4(left, down, right, up); public struct Dim4 { public static Dim4 ZERO = new Dim4(0); public Dim4(float xmin = 0, float ymin = 0, float xmax = 0, float ymax = 0) { this.xmin = float.IsNaN(xmin) ? 0f : xmin; this.ymin = float.IsNaN(ymin) ? 0f : ymin; this.xmax = float.IsNaN(xmax) ? 0f : xmax; this.ymax = float.IsNaN(ymax) ? 0f : ymax; } public float xmin; public float xmax; public float ymin; public float ymax; public Dim4 Merge(Dim4 other) { return D4(this.xmin + other.xmin, this.ymin + other.ymin, this.xmax - other.xmax, this.ymax - other.ymax); } public override string ToString() => $"{xmin} {ymin} {xmax} {ymax}"; } public struct Dim2 { public Dim2(float x = 0, float y = 0) { this.x = x; this.y = y; } public float x; public float y; } public enum Growth { Auto, Negative, Positive, Neutral } public enum ImageType { Auto, Sprite, Simple, Raw, Item } public struct UiLayout : INullable { public int Rows; public int Cols; public Dim2 Gaps; public float RowHeight; public float ColWidth; public bool ReverseRows; public Dictionary RowHeights; public Dictionary ColWidths; public readonly bool IsNull => Equals(new UiLayout()); } public partial class UI : IUI { public static readonly UI Empty = new UI { Enabled = true, }; public bool Enabled { get; set; } = true; public bool Visible { get; set; } = true; public string ID { get; set; } = Guid.NewGuid().ToString(); public string Parent { get; set; } public List Children { get; set; } = new List(); public UiColor Color { get; set; } = COLOR.Unset; public string Material { get; set; } /* RectTransform */ public Growth GrowX { get; set; } = Growth.Auto; public Growth GrowY { get; set; } = Growth.Auto; public float Height { get; set; } = 0f; public float Width { get; set; } = 0f; public Dim4? Origin { get; set; } = null; public Dim4 Padding { get; set; } = D4(0f); internal Dim4 InheritedPadding { get; set; } = D4(0f); public bool InheritPadding { get; set; } = true; public Dim4 Inset { get; set; } = D4(0f); public Dim4 Position { get; set; } = D4(0f); public Dim4 Trim { get; set; } = D4(0f); /* Text */ public string Text { get; set; } = null; public UiColor TextColor { get; set; } = Color(1, 1, 1, 1); public int TextSize { get; set; } = 14; public string TextFont { get; set; } public TextAnchor TextAlign { get; set; } /* Image */ public object Image { get; set; } = null; public string ImageMaterial { get; set; } = "assets/icons/iconmaterial.mat"; public UiColor ImageColor { get; set; } = COLOR.Unset; public ImageType ImageType { get; set; } = ImageType.Auto; public ulong ImageSkinId { get; set; } /* Button */ public IUiButton? Button { get; set; } //public string ButtonSprite { get; set; } public object ButtonImage { get; set; } public ImageType ButtonImageType { get; set; } = ImageType.Auto; public UiColor ButtonImageColor { get; set; } = COLOR.Unset; //public UiColor ButtonSpriteColor { get; set; } = Color(1, 1, 1, 1); //public UTAction OnClick { get; set; } /* Outline */ public float Outline { get; set; } = 0; public UiColor OutlineColor { get; set; } = Color(1, 1, 1, 1); /* InputField */ //public UTInputAction OnInput { get; set; } public IUiInput? Input { get; set; } = null; public string InputDefaultText { get; set; } public int InputCharLimit { get; set; } public bool InputIsPassword { get; set; } = false; public bool InputIsReadOnly { get; set; } = false; public bool InputNeedsKeyboard { get; set; } = false; public UnityEngine.UI.InputField.LineType InputLineType { get; set; } = UnityEngine.UI.InputField.LineType.SingleLine; public bool? InputAutoFocus { get; set; } /* Fade */ public float FadeIn = 0f; public float FadeOut = 0f; public bool InheritFade = true; /* Timing */ public float? Duration = null; /* Cursor / Keyboard */ public bool NeedsCursor = false; public bool NeedsKeyboard = false; /* Layout */ public UiLayout? Layout = null; /* Grid Positional */ public Dim2? Row = null; public Dim2? Col = null; } public partial class UI { public static List For(int i, Func action) { var entries = new List(); for (int j = 0; j < i; j++) { entries.Add(action.Invoke(j)); } return entries; } public static List ForEach(IEnumerable collection, Func action) { var entries = new List(); foreach (var e in collection) { entries.Add(action.Invoke(e)); } return entries; } public static List ForEach(IEnumerable collection, Func action) { var entries = new List(); int i = 0; foreach (var e in collection) { entries.Add(action.Invoke(e, i)); i++; } return entries; } public static List ForEach(IEnumerable collection, Func> action) { var entries = new List(); foreach (var e in collection) { entries.AddRange(action.Invoke(e)); } return entries; } } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { private static Guid TOKEN; private static bool IsSecure(ref string[] args) { if (args.Length == 0) { return false; } var token = Guid.Parse(args[0]); if (token != TOKEN) { return false; } args = args.Skip(1).ToArray(); return true; } [Command("ui.click")] private void CmdUiClick(IPlayer player, string command, string[] args) { if (!IsSecure(ref args)) { return; } var plugin = args[0]; var id = args[1]; var basePlayer = player.Object as BasePlayer; args = args.Length <= 2 ? new string[] { } : args.Skip(2).Select(x => x[1..^1]).ToArray(); var scope = UiEngine.Get(plugin).Player(basePlayer); scope.InvokeAction(id, args); } [Command("ui.submit")] private void CmdUiSubmit(IPlayer player, string command, string[] args) { if (!IsSecure(ref args)) { return; } var plugin = args[0]; var id = args[1]; var basePlayer = player.Object as BasePlayer; var argCount = int.Parse(args[2]); var argValues = argCount == 0 ? new List { } : args.Skip(3).Take(argCount).Select(x => x[1..^1]).ToList(); var input = string.Join(" ", args.Skip(3 + argCount)); if (string.IsNullOrEmpty(input)) { input = string.Empty; } argValues.Add(input); var scope = UiEngine.Get(plugin).Player(basePlayer); scope.InvokeAction(id, argValues.ToArray()); } [Command("ui.page")] private void CmdUiPage(IPlayer player, string command, string[] args) { if (!IsSecure(ref args)) { return; } var plugin = args[0]; var id = args[1]; var mod = int.Parse(args[2]); var basePlayer = player.Object as BasePlayer; var scope = UiEngine.Get(plugin).Player(basePlayer); if (!scope.ActiveElementsIds.Contains(id)) { return; } var p = scope.Get(id); var curPage = p.Page; var maxPage = (int)Math.Ceiling(p.Children.Count / (float)p.Limit); if (p.Limit == 0) { PrintWarning($"Paging cannot be done for '{p.ID}' because this element does not have a layout."); } if (curPage + mod < 0 || curPage + mod >= maxPage) { return; } p.Page = curPage + mod; scope.Update(p); int sfxIdx = 4; if (args.Length >= 5) { var txtid = args[3]; var txtformat = args[4]; scope.Update(txtid, (element) => { element.UpdateComponent((component) => { component.Text = string.Format(txtformat, p.Page+1, maxPage); return component; }); return element; }); sfxIdx = 5; } // TODO Playsfx if (args.Length > sfxIdx) { var sfx = args[sfxIdx]; PlaySFX(basePlayer, sfx); } } [Command("ut.close")] private void CmdUiClose(IPlayer player, string command, string[] args) { if (!IsSecure(ref args)) { return; } var plugin = args[0]; var id = args[1]; var basePlayer = player.Object as BasePlayer; var scope = UiEngine.Get(plugin).Player(basePlayer); scope.Destroy(id); // TODO Playsfx if (args.Length > 2) { var sfx = args[2]; PlaySFX(basePlayer, sfx); } } private interface IUiCommandable : INullable { string GetCommand(string plugin, string ui); } public interface IUiButton : INullable { string GetCommand(string plugin, string ui); } public interface IUiInput : INullable { string GetCommand(string plugin, string ui); } public struct UiPagerButton : IUiButton { public bool IsNull { get; } public string LayoutUi { get; set; } public int PageMod { get; set; } public string TextUi { get; set; } public string TextFormat { get; set; } public string Sfx { get; set; } public string GetCommand(string plugin, string ui) { if (string.IsNullOrWhiteSpace(TextUi)) { return $"ui.page {TOKEN} {plugin} {LayoutUi} {PageMod} {Sfx}"; } return $"ui.page {TOKEN} {plugin} {LayoutUi} {PageMod} {TextUi} {TextFormat} {Sfx}"; } } public struct UiInputCommand : IUiInput { public string Command; public bool IsNull => Command == null; public string GetCommand(string plugin, string ui) { return $"{Command}"; } } public struct UiInputAction : IUiInput { public UiActionWithInput? Action { get; set; } public readonly bool IsNull => Action == null; public string GetCommand(string plugin, string ui) { return $"ui.submit {TOKEN} {plugin} {ui} {Action.Value.Args.Length} {string.Join(" ", Action.Value.Args.Select(x => ("\'" + x.ToString() + "\'")))}"; } } public struct UiActionButton : IUiButton { public UiAction? Action { get; set; } public readonly bool IsNull => Action == null; public string GetCommand(string plugin, string ui) { return $"ui.click {TOKEN} {plugin} {ui} {string.Join(" ", Action.Value.Args.Select(x => ("\'" + x.ToString() + "\'")))}"; } } public struct UiCommandButton : IUiButton { public string Command; public bool IsNull => Command == null; public string GetCommand(string plugin, string ui) { return $"{Command}"; } } public static UiInputCommand SubmitCommand(string command) { return new UiInputCommand { Command = command }; } public static UiInputAction SubmitAction(Action action, params object[] args) { return new UiInputAction { Action = new UiActionWithInput { Action = action, Args = args } }; } public static UiCommandButton ClickCommand(string command) { return new UiCommandButton { Command = command }; } public static UiActionButton ClickAction(Action action, params object[] args) { return new UiActionButton { Action = new UiAction { Action = action, Args = args } }; } public static UiPagerButton ClickPage(string ui, int pageMod, string sfx = null) { return new UiPagerButton { PageMod = pageMod, LayoutUi = ui, Sfx = sfx }; } public static UiPagerButton ClickPage(string ui, int pageMod, string textUi, string textFormat, string sfx = null) { return new UiPagerButton { PageMod = pageMod, TextUi = textUi, TextFormat = textFormat, LayoutUi = ui, Sfx = sfx }; } public interface IUiAction { void Invoke(string[] args); } public struct UiAction : IUiAction, INullable { public Action Action { get; set; } public object[] Args { get; set; } public readonly bool IsNull => Action == null; public void Invoke(string[] args) { Action.Invoke(args); } } public struct UiActionWithInput : IUiAction, INullable { public Action Action { get; set; } public object[] Args { get; set; } public readonly bool IsNull => Action == null; public void Invoke(string[] args) { Action.Invoke(args.Last(), args.Take(args.Length-1).ToArray()); } } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public class UiEngine { private static Dictionary AllInstances; private static Dictionary _imageAssetPaths { get; set; } private static Dictionary _imagesToLoad { get; set; } internal static HashSet _emptyImages { get; set; } public static void AddImage(string key, string value) { if (string.IsNullOrWhiteSpace(value)) { _emptyImages.Add(key); } else if (IsAssetPath(value)) { _imageAssetPaths[key] = value; } else { _imagesToLoad[key] = value; } } public static void AddImages(Dictionary images) { foreach (var kvp in images) { AddImage(kvp.Key, kvp.Value); } } public static bool IsEmptyImage(string imageKey) { return string.IsNullOrWhiteSpace(imageKey) || _emptyImages.Contains(imageKey); } public static bool IsAssetImage(string imageKey) { if (IsAssetPath(imageKey)) { return true; } return _imageAssetPaths.ContainsKey(imageKey); } public static string GetImageData(string imageKey) { if (_emptyImages.Contains(imageKey)) { return string.Empty; } if (IsAssetPath(imageKey)) { return imageKey; } if (_imageAssetPaths.ContainsKey(imageKey)) { return _imageAssetPaths[imageKey]; } var result = INSTANCE.ImageLibrary.Call("GetImage", imageKey); return result; } public static void LoadAddedImages(Action callback = null) { INSTANCE.ImageLibrary.Call("ImportImageList", INSTANCE.Name, _imagesToLoad, 0UL, true, callback); _imagesToLoad.Clear(); } public static UiEngineInstance Init(Plugin plugin) { if (!AllInstances.ContainsKey(plugin.Name)) { AllInstances[plugin.Name] = new UiEngineInstance(plugin.Name); } return AllInstances[plugin.Name]; } public static UiEngineInstance Get(string plugin) { return AllInstances.GetValueOrDefault(plugin); } internal static void Load() { AllInstances = new Dictionary(); _imagesToLoad = new Dictionary(); _imageAssetPaths = new Dictionary(); _emptyImages = new HashSet(); } internal static void ClearDataForPlayer(ulong userId) { foreach(var instance in AllInstances.Values) { instance.Remove(userId); } } internal static void Dispose(string plugin) { var instance = AllInstances?.GetValueOrDefault(plugin); if (instance == null) { return; } instance.Dispose(); AllInstances.Remove(plugin); _imagesToLoad.Clear(); _imageAssetPaths.Clear(); _emptyImages.Clear(); } internal static void Unload() { foreach(var instance in AllInstances) { instance.Value?.Dispose(); } } } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public class UiEngineInstance { public string Plugin { get; private set; } internal Dictionary PlayerInstances { get; set; } internal UiEngineInstance(string plugin) { Plugin = plugin; PlayerInstances = new Dictionary(); } internal int TotalActiveElements() { var total = 0; foreach (var playerInstance in PlayerInstances.Values) { total += playerInstance.ActiveElementsIds.Count(); } return total; } internal int InstanceCount() { return PlayerInstances.Count; } public UiEnginePlayer Player(BasePlayer basePlayer) { if (basePlayer == null) { return null; } if (!basePlayer.IsConnected || basePlayer.Connection == null || basePlayer.IsBot || basePlayer.IsNpc) { Remove(basePlayer.userID); return null; } if (!PlayerInstances.ContainsKey(basePlayer.userID)) { PlayerInstances[basePlayer.userID] = new UiEnginePlayer(basePlayer, Plugin); } return PlayerInstances[basePlayer.userID]; } internal void Remove(ulong userId) { PlayerInstances.Remove(userId); } public void Dispose() { foreach (var instance in PlayerInstances) { instance.Value.DestroyAll(); } PlayerInstances.Clear(); } } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public partial class UiEnginePlayer { internal string Plugin { get; set; } internal BasePlayer _basePlayer { get; set; } private bool _showOutput = false; internal Dictionary ActiveElements = new Dictionary(); internal Dictionary Actions = new Dictionary(); public string[] ActiveElementsIds => ActiveElements.Keys.ToArray(); internal UiEnginePlayer(BasePlayer basePlayer, string plugin) { _basePlayer = basePlayer; Plugin = plugin; } public void Show(UI template, bool output) { _showOutput = true; Show(template); Output(); _showOutput = false; } public void Show(IEnumerable elements) { AddUI(elements); } public void Show(params UI[] templates) => Show((IEnumerable)templates); public void Show(IEnumerable templates) { foreach (var template in templates) { if (template == null || !template.Enabled) { continue; } //CuiHelper.DestroyUi(_basePlayer, template.ID); Destroy(template.ID); Build(template); }; AddUI(_buildElements); _buildElements.Clear(); } public void Destroy(params string[] ids) => Destroy((IEnumerable)ids); public void Destroy(IEnumerable ids) { foreach (var id in ids) { var element = ActiveElements.GetValueOrDefault(id, UiElement.Empty); if (!element.IsNull && element.Children != null) { foreach (var childId in element.Children) { Destroy(childId); } } if (!element.IsNull && element.SubElements != null) { foreach (var subId in element.SubElements) { Destroy(subId); } } ActiveElements.Remove(id); Actions.Remove(id); CuiHelper.DestroyUi(_basePlayer, id); } } public void DestroyAll() { foreach (var id in ActiveElements.Keys.ToArray()) { Destroy(id); } ActiveElements.Clear(); } public UiElement Get(string elementId) { var element = ActiveElements.GetValueOrDefault(elementId, UiElement.Empty); if (element.IsNull) { INSTANCE.PrintWarning($"Could not find element '{elementId}' for {_basePlayer?.displayName}"); } return element; } public void Update(UiElement uiElement) { uiElement.Update = true; if (uiElement.Limit == 0) { _buildElements.Add(uiElement); } else { UpdateHelper(uiElement); } AddUI(_buildElements); _buildElements.Clear(); } public void Update(string id, Func action) { var element = ActiveElements.GetValueOrDefault(id, UiElement.Empty); if (element.IsNull || element.Components == null) { return; } element = action.Invoke(element); Update(element); } public void UpdateText(string id, UiTextComponent update) { Update(id, (element) => { element.UpdateComponent((comp) => { comp.Text = update.Text; return comp; }); return element; }); } public void UpdateInput(string id, UiInputComponent update) { Update(id + ":d1", (element) => { element.UpdateComponent((comp) => { comp.Text = update.Text; return comp; }); return element; }); } public void UpdateImage(string id, UiImageComponent update) { Update(id, (element) => { element.UpdateComponent((comp) => { comp.Color = update.Color; return comp; }); return element; }); } public void UpdateButton(string id, UiButtonComponent update) { Update(id, (element) => { element.UpdateComponent((comp) => { comp.Color = update.Color; return comp; }); return element; }); } internal void InvokeAction(string id, string[] args) { var action = Actions.GetValueOrDefault(id); if (action == null) { INSTANCE.PrintWarning($"Action {id} doesn't exist"); return; } action.Invoke(args); } private void UpdateHelper(UiElement uiElement) { _buildElements.Add(uiElement); if (uiElement.Children != null) { foreach (var subElementId in uiElement.SubElements) { var subElement = ActiveElements.GetValueOrDefault(subElementId, UiElement.Empty); if (subElement.IsNull) { continue; } subElement.Update = false; subElement.Visible = uiElement.Visible; UpdateHelper(subElement); } int i = 0; foreach (var childId in uiElement.Children) { var child = ActiveElements.GetValueOrDefault(childId, UiElement.Empty); if (child.IsNull) { continue; } child.Update = false; if (uiElement.Visible && uiElement.Limit != 0) // is a layout { var min = uiElement.Limit * uiElement.Page; var max = uiElement.Limit * (uiElement.Page + 1); child.Visible = i >= min && i < max; } else { child.Visible = uiElement.Visible; } UpdateHelper(child); i++; } } } private void Output() { var strings = new List() { $"{("ID"),-50}{("PARENT"),-50}{("ENABLED"),-10}{("UPDATE"),-10}" }; strings.AddRange(ActiveElements.Select(x => $"{x.Key, -50}{x.Value.Parent,-50}{x.Value.Visible,-10}{x.Value.Update,-10}")); Interface.Oxide.DataFileSystem.WriteObject($"{INSTANCE.Name}/Output2", strings); } private void WriteData(string file, string data) { Interface.Oxide.DataFileSystem.WriteObject($"{INSTANCE.Name}/{file}", data); } private void AddUI(IEnumerable elements) { Stopwatch stopWatch = new Stopwatch(); var b = new UiSerializer(); b.Serialize(this, elements); if (b._charsLength == 0) { return; } if (_showOutput) { Debug("Show output"); b.Output(); } AddUi2(_basePlayer, new string(b._chars, 0, b._charsLength)); foreach (var element in elements) { if (!element.Duration.HasValue) { continue; } if (element.Duration == 0) { Destroy(element.ID); } else { INSTANCE.timer.In(element.Duration.Value, () => { Destroy(element.ID); }); } } } private static NetWrite ClientRPCStart(BaseEntity entity, string funcName) { if (Network.Net.sv.IsConnected() && entity.net != null) { var write = Network.Net.sv.StartWrite(); write.PacketID(Message.Type.RPCMessage); write.EntityID(entity.net.ID); write.UInt32(StringPool.Get(funcName)); write.UInt64(0); return write; } return null; } private static void AddUI(SendInfo sendInfo, char[] chars, int charsLength, int bufferSize) { var write = ClientRPCStart(CommunityEntity.ServerInstance, "AddUI"); var bytes = new byte[bufferSize]; if (write != null) { var byteCount = Encoding.UTF8.GetBytes(chars, 0, charsLength, bytes, 0); write.BytesWithSize(bytes, byteCount); write.Send(sendInfo); } } public static void AddUi2(BasePlayer player, string json) { try { CommunityEntity.ServerInstance.ClientRPCEx(new SendInfo { connection = player.net.connection }, null, "AddUI", json); } catch(Exception e) { INSTANCE.PrintError($"UI ERROR: {player == null} {player.net == null} {CommunityEntity.ServerInstance == null} {json == null}"); } } } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public struct UiColor : INullable { public float r { get; } public float g { get; } public float b { get; } public float a { get; } private string _hexString; public readonly bool IsTransparentOrNull => IsTransparent || IsNull; public readonly bool IsTransparent => a == 0; public readonly bool IsNull => a < 0; internal UiColor(bool init) { this.r = 0; this.g = 0; this.b = 0; this.a = -1; this._hexString = null; } public UiColor(float r, float g, float b, float a) { this.r = SetValue(r); this.g = SetValue(g); this.b = SetValue(b); this.a = SetValue(a); this._hexString = null; } public readonly UiColor Add(float r = 0, float b = 0, float g = 0, float a = 0) { return new UiColor(this.r + r, this.g + g, this.b + b, this.a + a); } public readonly UiColor Add(UiColor other) { return new UiColor(r + other.r, g + other.g, b + other.b, a: a); } public readonly UiColor Set(float? r = null, float? b = null, float? g = null, float? a = null) { return new UiColor(r ?? this.r, g ?? this.g, b ?? this.b, a ?? this.a); } public readonly UiColor Saturate(float saturation) { return this.Add(saturation, saturation, saturation); } private static float SetValue(float val) => Math.Max(0, Math.Min(1, val)); public string AsHex() { if (_hexString != null) { return _hexString; } var r = (int) Math.Round(this.r * 255f); var g = (int)Math.Round(this.g * 255f); var b = (int)Math.Round(this.b * 255f); _hexString = "#" + r.ToString("X2") + g.ToString("X2") + b.ToString("X2"); return _hexString; } public override string ToString() => $"{r} {g} {b} {a}"; } public static UiColor Color(float r = 0, float g = 0, float b = 0, float a = 1) => new UiColor(r, g, b, a); public static UiColor Color(string colorStr) { if (string.IsNullOrWhiteSpace(colorStr)) { return COLOR.Unset; } var split = colorStr.Split(' '); return new UiColor(float.Parse(split[0]), float.Parse(split[1]), float.Parse(split[2]), float.Parse(split[3])); } public static class COLOR { public static readonly UiColor Red = new UiColor(1, 0, 0, 1); public static readonly UiColor DarkRed = new UiColor(0.5f, 0, 0, 1); public static readonly UiColor LightRed = new UiColor(1, 0.5f, 0.5f, 1); public static readonly UiColor Green = new UiColor(0, 1, 0, 1); public static readonly UiColor DarkGreen = new UiColor(0, 0.5f, 0, 1); public static readonly UiColor LightGreen = new UiColor(0.5f, 1, 0.5f, 1); public static readonly UiColor Blue = new UiColor(0, 0, 1, 1); public static readonly UiColor DarkBlue = new UiColor(0, 0, 0.5f, 1); public static readonly UiColor LightBlue = new UiColor(0.5f, 0.5f, 1, 1); public static readonly UiColor Yellow = new UiColor(1, 1, 0, 1); public static readonly UiColor DarkYellow = new UiColor(0.5f, 0.5f, 0, 1); public static readonly UiColor LightYellow = new UiColor(1, 1, 0.5f, 1); public static readonly UiColor Cyan = new UiColor(0, 1, 1, 1); public static readonly UiColor DarkCyan = new UiColor(0, 0.5f, 0.5f, 1); public static readonly UiColor LightCyan = new UiColor(0.5f, 1, 1, 1); public static readonly UiColor Magenta = new UiColor(1, 0, 1, 1); public static readonly UiColor DarkMagenta = new UiColor(0.5f, 0, 0.5f, 1); public static readonly UiColor LightMagenta = new UiColor(1, 0.5f, 1, 1); public static readonly UiColor White = new UiColor(1, 1, 1, 1); public static readonly UiColor OffWhite = new UiColor(0.9f, 0.9f, 0.9f, 1); public static readonly UiColor Black = new UiColor(0, 0, 0, 1); public static readonly UiColor OffBlack = new UiColor(0.1f, 0.1f, 0.1f, 1); public static readonly UiColor Gray = new UiColor(0.5f, 0.5f, 0.5f, 1); public static readonly UiColor DarkGray = new UiColor(0.25f, 0.25f, 0.25f, 1); public static readonly UiColor LightGray = new UiColor(0.75f, 0.75f, 0.75f, 1); public static readonly UiColor Unset = new UiColor(true); public static readonly UiColor Transparent = new UiColor(0, 0, 0, 0); public static class Rust { public static UiColor Blue = new UiColor(0.08627f, 0.25490f, 0.38431f, 1); public static UiColor LightBlue = new UiColor(0.25490f, 0.61176f, 0.86275f, 1); //public static UiColor Red = new UiColor(0.68627 0.21569 0.1f4118 1); public static UiColor Red = new UiColor(0.77255f, 0.23922f, 0.15686f, 1); public static UiColor Maroon = new UiColor(0.46667f, 0.22745f, 0.18431f, 1); public static UiColor LightMaroon = new UiColor(1.00000f, 0.32549f, 0.21961f, 1); //public static UiColor LightRed = new UiColor(0.9f, 1373f, 0.77647f, 0.75686f, 1); //public static UiColor Green = new UiColor(0.25490, 0.30980, 0.1f4510, 1); public static UiColor Green = new UiColor(0.35490f, 0.40980f, 0.24510f, 1); public static UiColor LightGreen = new UiColor(0.76078f, 0.94510f, 0.41176f, 1); public static UiColor Gray = new UiColor(0.45490f, 0.43529f, 0.40784f, 1); public static UiColor LightGray = new UiColor(0.69804f, 0.66667f, 0.63529f, 1); public static UiColor Orange = new UiColor(1, 0.53333f, 0.18039f, 1); public static UiColor LightOrange = new UiColor(1, 0.82353f, 0.44706f, 1); public static UiColor White = new UiColor(0.87451f, 0.83529f, 0.8f, 1); public static UiColor LightWhite = new UiColor(0.97647f, 0.97647f, 0.97647f, 1); public static UiColor Lime = new UiColor(0.64706f, 1, 0, 1); public static UiColor LightLime = new UiColor(0.69804f, 0.83137f, 0.46667f, 1); public static UiColor DarkGray = new UiColor(0.08627f, 0.08627f, 0.08627f, 1); public static UiColor DarkBrown = new UiColor(0.15686f, 0.15686f, 0.12549f, 1); public static UiColor LightBrown = new UiColor(0.54509f, 0.51372f, 0.4705f, 1); } } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public static class FONT { public static readonly string Droid = "DroidSansMono.ttf"; public static readonly string PermanentMarker = "PermanentMarker.ttf"; public static readonly string Bold = "RobotoCondensed-Bold.ttf"; public static readonly string Regular = "RobotoCondensed-Regular.ttf"; } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public static void PlaySFX(BasePlayer basePlayer, string sfx) { EffectNetwork.Send(new Effect(sfx, basePlayer, 0, Vector3.zero, Vector3.forward), basePlayer.net.connection); } public static void PlaySFX(BasePlayer basePlayer, string sfx, Vector3 pos) { EffectNetwork.Send(new Effect(sfx, basePlayer, 0, pos, Vector3.forward), basePlayer.net.connection); } public static class FX { public static readonly string ResearchFail = "assets/prefabs/deployable/research table/effects/research-fail.prefab"; public static readonly string ResearchStart = "assets/prefabs/deployable/research table/effects/research-start.prefab"; public static readonly string ResearchSuccess = "assets/prefabs/deployable/research table/effects/research-success.prefab"; public static readonly string ResearchTableDeploy = "assets/prefabs/deployable/research table/effects/research-table-deploy.prefab"; public static readonly string ResearchTableItem = "assets/prefabs/deployable/research table/research_table.item.prefab"; public static readonly string ResearchTableDeployed = "assets/prefabs/deployable/research table/researchtable_deployed.prefab"; public static readonly string LockCodeDeploy = "assets/prefabs/locks/keypad/effects/lock-code-deploy.prefab"; public static readonly string LockCodeDenied = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab"; public static readonly string LockCodeLock = "assets/prefabs/locks/keypad/effects/lock.code.lock.prefab"; public static readonly string LockCodeShock = "assets/prefabs/locks/keypad/effects/lock.code.shock.prefab"; public static readonly string LockCodeUnlock = "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab"; public static readonly string LockCodeUpdated = "assets/prefabs/locks/keypad/effects/lock.code.updated.prefab"; public static readonly string TinySound = "assets/content/sound/templates/tiny-sound.prefab"; public static readonly string UISound = "assets/content/sound/templates/ui-sound.prefab"; public static readonly string ItemSelectFX = "assets/bundled/prefabs/fx/notice/item.select.fx.prefab"; public static readonly string LootCopyFX = "assets/bundled/prefabs/fx/notice/loot.copy.fx.prefab"; public static readonly string ItemUnlock = "assets/bundled/prefabs/fx/item_unlock.prefab"; } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public static class MATERIAL { public static readonly string DarknessClamp = "assets/content/image effects/darkclamp/darknessclamp.mat"; public static readonly string LinearFog = "assets/content/image effects/linear fog/linearfog.mat"; public static readonly string DefaultScope = "assets/content/image effects/scope/defaultscope.mat"; public static readonly string Cable = "assets/content/materials/cable.mat"; public static readonly string ColliderMesh = "assets/content/materials/collider_mesh.mat"; public static readonly string ColliderMeshConvex = "assets/content/materials/collider_mesh_convex.mat"; public static readonly string ColliderTrigger = "assets/content/materials/collider_trigger.mat"; public static readonly string DeployableAcceptable = "assets/content/materials/deployable/deployable_acceptable.mat"; public static readonly string DeployableDenied = "assets/content/materials/deployable/deployable_denied.mat"; public static readonly string FoliageDisplaceCircle = "assets/content/materials/displacement/foliagedisplace_circle.mat"; public static readonly string FoliageDisplaceSquare = "assets/content/materials/displacement/foliagedisplace_square.mat"; public static readonly string Gradient = "assets/content/materials/gradient.mat"; public static readonly string Ground = "assets/content/materials/ground.mat"; public static readonly string GuideBad = "assets/content/materials/guide_bad.mat"; public static readonly string GuideGood = "assets/content/materials/guide_good.mat"; public static readonly string GuideHighlight = "assets/content/materials/guide_highlight.mat"; public static readonly string GuideNeutral = "assets/content/materials/guide_neutral.mat"; public static readonly string ItemMaterial = "assets/content/materials/itemmaterial.mat"; public static readonly string MaleMaterial = "assets/content/materials/male.material.mat"; public static readonly string GLOpaque = "assets/content/shaders/gl/gl opaque.mat"; public static readonly string GLTransparent = "assets/content/shaders/gl/gl transparent.mat"; public static readonly string BinocularOverlay = "assets/content/ui/binocular_overlay.mat"; public static readonly string GoggleOverlay = "assets/content/ui/goggle_overlay.mat"; public static readonly string HelmetSlitOverlay = "assets/content/ui/helmet_slit_overlay.mat"; public static readonly string CompassStrip = "assets/content/ui/ingame/compass/compassstrip.mat"; public static readonly string NameFontMaterial = "assets/content/ui/namefontmaterial.mat"; public static readonly string PlayerPreviewGlow = "assets/content/ui/playerpreviewglow.mat"; public static readonly string PlayerPreviewRemoveSegments = "assets/content/ui/playerpreviewremovesegments.mat"; public static readonly string PlayerPreviewSegments = "assets/content/ui/playerpreviewsegments.mat"; public static readonly string Scope1 = "assets/content/ui/scope_1.mat"; public static readonly string Scope2 = "assets/content/ui/scope_2.mat"; public static readonly string UIMaskClear = "assets/content/ui/ui.maskclear.mat"; public static readonly string UIBackgroundBlurInGameMenu = "assets/content/ui/uibackgroundblur-ingamemenu.mat"; public static readonly string UIBackgroundBlurNotice = "assets/content/ui/uibackgroundblur-notice.mat"; public static readonly string UIBackgroundBlur = "assets/content/ui/uibackgroundblur.mat"; public static readonly string FogOfWar = "assets/icons/fogofwar.mat"; public static readonly string Greyout = "assets/icons/greyout.mat"; public static readonly string IconMaterial = "assets/icons/iconmaterial.mat"; } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public static class SIZE { public const int XXXS = 4; public const int XXS = 8; public const int XS = 16; public const int S = 24; public const int M = 28; public const int L = 32; public const int XL = 48; public const int XXL = 64; public const int XXXL = 128; } } } namespace Oxide.Plugins { public partial class UiEngineFramework : CovalencePlugin { public static class SPRITE { public static readonly string Add = "assets/icons/add.png"; public static readonly string Ammunition = "assets/icons/ammunition.png"; public static readonly string ArrowRight = "assets/icons/arrow_right.png"; public static readonly string Authorize = "assets/icons/authorize.png"; public static readonly string Bite = "assets/icons/bite.png"; public static readonly string Bleeding = "assets/icons/bleeding.png"; public static readonly string Blueprint = "assets/icons/blueprint.png"; public static readonly string BlueprintUnderlay = "assets/icons/blueprint_underlay.png"; public static readonly string Blunt = "assets/icons/blunt.png"; public static readonly string BpLock = "assets/icons/bp-lock.png"; public static readonly string Broadcast = "assets/icons/broadcast.png"; public static readonly string BuildStairs = "assets/icons/build/stairs.png"; public static readonly string BuildWallDoorwayDoor = "assets/icons/build/wall.doorway.door.png"; public static readonly string BuildWallWindowBars = "assets/icons/build/wall.window.bars.png"; public static readonly string Bullet = "assets/icons/bullet.png"; public static readonly string CargoShipBody = "assets/icons/cargo_ship_body.png"; public static readonly string Cart = "assets/icons/cart.png"; public static readonly string ChangeCode = "assets/icons/change_code.png"; public static readonly string Check = "assets/icons/check.png"; public static readonly string ChinookMapBlades = "assets/icons/chinook_map_blades.png"; public static readonly string ChinookMapBody = "assets/icons/chinook_map_body.png"; public static readonly string CircleClosed = "assets/icons/circle_closed.png"; public static readonly string CircleClosedToEdge = "assets/icons/circle_closed_toedge.png"; public static readonly string CircleGradient = "assets/icons/circle_gradient.png"; public static readonly string CircleGradientWhite = "assets/icons/circle_gradient_white.png"; public static readonly string CircleOpen = "assets/icons/circle_open.png"; public static readonly string Clear = "assets/icons/clear.png"; public static readonly string ClearList = "assets/icons/clear_list.png"; public static readonly string Close = "assets/icons/close.png"; public static readonly string CloseDoor = "assets/icons/close_door.png"; public static readonly string Clothing = "assets/icons/clothing.png"; public static readonly string Cold = "assets/icons/cold.png"; public static readonly string CommunityServers = "assets/icons/community_servers.png"; public static readonly string Connection = "assets/icons/connection.png"; public static readonly string Construction = "assets/icons/construction.png"; public static readonly string Cooking = "assets/icons/cooking.png"; public static readonly string Crate = "assets/icons/crate.png"; public static readonly string CupWater = "assets/icons/cup_water.png"; public static readonly string CursorHand = "assets/icons/cursor-hand.png"; public static readonly string Deauthorize = "assets/icons/deauthorize.png"; public static readonly string Demolish = "assets/icons/demolish.png"; public static readonly string DemolishCancel = "assets/icons/demolish_cancel.png"; public static readonly string DemolishImmediate = "assets/icons/demolish_immediate.png"; public static readonly string Discord1 = "assets/icons/discord 1.png"; public static readonly string Discord = "assets/icons/discord.png"; public static readonly string Download = "assets/icons/download.png"; public static readonly string Drop = "assets/icons/drop.png"; public static readonly string Drowning = "assets/icons/drowning.png"; public static readonly string Eat = "assets/icons/eat.png"; public static readonly string Electric = "assets/icons/electric.png"; public static readonly string Embrella = "assets/icons/embrella.png"; public static readonly string Enter = "assets/icons/enter.png"; public static readonly string Examine = "assets/icons/examine.png"; public static readonly string Exit = "assets/icons/exit.png"; public static readonly string Explosion = "assets/icons/explosion.png"; public static readonly string ExplosionSprite = "assets/icons/explosion_sprite.png"; public static readonly string Extinguish = "assets/icons/extinguish.png"; public static readonly string FacebookBox = "assets/icons/facebook-box.png"; public static readonly string Facebook = "assets/icons/facebook.png"; public static readonly string Facepunch = "assets/icons/facepunch.png"; public static readonly string Fall = "assets/icons/fall.png"; public static readonly string FavouriteServers = "assets/icons/favourite_servers.png"; public static readonly string File = "assets/icons/file.png"; public static readonly string FlagsAf = "assets/icons/flags/af.png"; public static readonly string FlagsAr = "assets/icons/flags/ar.png"; public static readonly string FlagsCa = "assets/icons/flags/ca.png"; public static readonly string FlagsCs = "assets/icons/flags/cs.png"; public static readonly string FlagsDa = "assets/icons/flags/da.png"; public static readonly string FlagsDe = "assets/icons/flags/de.png"; public static readonly string FlagsEl = "assets/icons/flags/el.png"; public static readonly string FlagsEnPt = "assets/icons/flags/en-pt.png"; public static readonly string FlagsEn = "assets/icons/flags/en.png"; public static readonly string FlagsEsEs = "assets/icons/flags/es-es.png"; public static readonly string FlagsFi = "assets/icons/flags/fi.png"; public static readonly string FlagsFr = "assets/icons/flags/fr.png"; public static readonly string FlagsHe = "assets/icons/flags/he.png"; public static readonly string FlagsHu = "assets/icons/flags/hu.png"; public static readonly string FlagsIt = "assets/icons/flags/it.png"; public static readonly string FlagsJa = "assets/icons/flags/ja.png"; public static readonly string FlagsKo = "assets/icons/flags/ko.png"; public static readonly string FlagsNl = "assets/icons/flags/nl.png"; public static readonly string FlagsNo = "assets/icons/flags/no.png"; public static readonly string FlagsPl = "assets/icons/flags/pl.png"; public static readonly string FlagsPtBr = "assets/icons/flags/pt-br.png"; public static readonly string FlagsPtPt = "assets/icons/flags/pt-pt.png"; public static readonly string FlagsRo = "assets/icons/flags/ro.png"; public static readonly string FlagsRu = "assets/icons/flags/ru.png"; public static readonly string FlagsSr = "assets/icons/flags/sr.png"; public static readonly string FlagsSvSe = "assets/icons/flags/sv-se.png"; public static readonly string FlagsTr = "assets/icons/flags/tr.png"; public static readonly string FlagsUk = "assets/icons/flags/uk.png"; public static readonly string FlagsVi = "assets/icons/flags/vi.png"; public static readonly string FlagsZhCn = "assets/icons/flags/zh-cn.png"; public static readonly string FlagsZhTw = "assets/icons/flags/zh-tw.png"; public static readonly string Fog = "assets/icons/fog.png"; public static readonly string Folder = "assets/icons/folder.png"; public static readonly string FolderUp = "assets/icons/folder_up.png"; public static readonly string ForkAndSpoon = "assets/icons/fork_and_spoon.png"; public static readonly string Freezing = "assets/icons/freezing.png"; public static readonly string FriendsServers = "assets/icons/friends_servers.png"; public static readonly string Gear = "assets/icons/gear.png"; public static readonly string Grenade = "assets/icons/grenade.png"; public static readonly string Greyout = "assets/icons/greyout.png"; public static readonly string GreyoutLarge = "assets/icons/greyout_large.png"; public static readonly string Health = "assets/icons/health.png"; public static readonly string HistoryServers = "assets/icons/history_servers.png"; public static readonly string Home = "assets/icons/home.png"; public static readonly string HorseRide = "assets/icons/horse_ride.png"; public static readonly string Hot = "assets/icons/hot.png"; public static readonly string Ignite = "assets/icons/ignite.png"; public static readonly string Info = "assets/icons/info.png"; public static readonly string Inventory = "assets/icons/inventory.png"; public static readonly string IsBroken = "assets/icons/isbroken.png"; public static readonly string IsCooking = "assets/icons/iscooking.png"; public static readonly string IsLoading = "assets/icons/isloading.png"; public static readonly string IsOnFire = "assets/icons/isonfire.png"; public static readonly string Joystick = "assets/icons/joystick.png"; public static readonly string Key = "assets/icons/key.png"; public static readonly string KnockDoor = "assets/icons/knock_door.png"; public static readonly string LanServers = "assets/icons/lan_servers.png"; public static readonly string Level = "assets/icons/level.png"; public static readonly string LevelMetal = "assets/icons/level_metal.png"; public static readonly string LevelStone = "assets/icons/level_stone.png"; public static readonly string LevelTop = "assets/icons/level_top.png"; public static readonly string LevelWood = "assets/icons/level_wood.png"; public static readonly string Lick = "assets/icons/lick.png"; public static readonly string LightCampfire = "assets/icons/light_campfire.png"; public static readonly string Lightbulb = "assets/icons/lightbulb.png"; public static readonly string Loading = "assets/icons/loading.png"; public static readonly string Lock = "assets/icons/lock.png"; public static readonly string Loot = "assets/icons/loot.png"; public static readonly string MapArrow = "assets/icons/maparrow.png"; public static readonly string Market = "assets/icons/market.png"; public static readonly string Maximum = "assets/icons/maximum.png"; public static readonly string Meat = "assets/icons/meat.png"; public static readonly string Medical = "assets/icons/medical.png"; public static readonly string MenuDots = "assets/icons/menu_dots.png"; public static readonly string ModdedServers = "assets/icons/modded_servers.png"; public static readonly string Occupied = "assets/icons/occupied.png"; public static readonly string Open = "assets/icons/open.png"; public static readonly string OpenDoor = "assets/icons/open_door.png"; public static readonly string Peace = "assets/icons/peace.png"; public static readonly string Pickup = "assets/icons/pickup.png"; public static readonly string Pills = "assets/icons/pills.png"; public static readonly string PlayerAssist = "assets/icons/player_assist.png"; public static readonly string PlayerCarry = "assets/icons/player_carry.png"; public static readonly string PlayerLoot = "assets/icons/player_loot.png"; public static readonly string Poison = "assets/icons/poison.png"; public static readonly string Portion = "assets/icons/portion.png"; public static readonly string Power = "assets/icons/power.png"; public static readonly string Press = "assets/icons/press.png"; public static readonly string Radiation = "assets/icons/radiation.png"; public static readonly string Rain = "assets/icons/rain.png"; public static readonly string Reddit = "assets/icons/reddit.png"; public static readonly string Refresh = "assets/icons/refresh.png"; public static readonly string Resource = "assets/icons/resource.png"; public static readonly string Rotate = "assets/icons/rotate.png"; public static readonly string Rust = "assets/icons/rust.png"; public static readonly string Save = "assets/icons/save.png"; public static readonly string Shadow = "assets/icons/shadow.png"; public static readonly string Sign = "assets/icons/sign.png"; public static readonly string Slash = "assets/icons/slash.png"; public static readonly string Sleeping = "assets/icons/sleeping.png"; public static readonly string SleepingBag = "assets/icons/sleepingbag.png"; public static readonly string Square = "assets/icons/square.png"; public static readonly string SquareGradient = "assets/icons/square_gradient.png"; public static readonly string Stab = "assets/icons/stab.png"; public static readonly string Star = "assets/icons/star.png"; public static readonly string Steam = "assets/icons/steam.png"; public static readonly string SteamInventory = "assets/icons/steam_inventory.png"; public static readonly string Stopwatch = "assets/icons/stopwatch.png"; public static readonly string Store = "assets/icons/store.png"; public static readonly string Study = "assets/icons/study.png"; public static readonly string Subtract = "assets/icons/subtract.png"; public static readonly string Target = "assets/icons/target.png"; public static readonly string Tools = "assets/icons/tools.png"; public static readonly string Translate = "assets/icons/translate.png"; public static readonly string Traps = "assets/icons/traps.png"; public static readonly string Triangle = "assets/icons/triangle.png"; public static readonly string Tweeter = "assets/icons/tweeter.png"; public static readonly string Twitter1 = "assets/icons/twitter 1.png"; public static readonly string Twitter = "assets/icons/twitter.png"; public static readonly string Unlock = "assets/icons/unlock.png"; public static readonly string Upgrade = "assets/icons/upgrade.png"; public static readonly string Voice = "assets/icons/voice.png"; public static readonly string VoteDown = "assets/icons/vote_down.png"; public static readonly string VoteUp = "assets/icons/vote_up.png"; public static readonly string Warning = "assets/icons/warning.png"; public static readonly string Warning2 = "assets/icons/warning_2.png"; public static readonly string Weapon = "assets/icons/weapon.png"; public static readonly string Web = "assets/icons/web.png"; public static readonly string Wet = "assets/icons/wet.png"; public static readonly string Workshop = "assets/icons/workshop.png"; public static readonly string XP = "assets/icons/xp.png"; } } }