diff --git a/src/Immersion/Program.cs b/src/Immersion/Program.cs index 78804e0..3e5ffff 100644 --- a/src/Immersion/Program.cs +++ b/src/Immersion/Program.cs @@ -23,8 +23,12 @@ var universe = new Universe(); var world = universe.World; // TODO: Figure out a nice way to get rid of "compile errors" here. -// FIXME: universe.Modules.Register(); -universe.Modules.Register(); +universe.Modules.Import(); +universe.Modules.Import(); +universe.Modules.Import(); +universe.Modules.Import(); +universe.Modules.Import(); +universe.Modules.Import(); var window = Window.Create(WindowOptions.Default with { Title = "gæmstone", @@ -57,9 +61,9 @@ universe.Modules.Register(); universe.Modules.Register(); universe.Modules.Register(); -foreach (var module in universe.Modules) - if (!module.IsInitialized) throw new InvalidOperationException( - $"Module '{module.Entity.Path}' is not initialized"); +using (var disabledModules = world.Filter(new("ModuleInfo, Disabled"))) + foreach (var module in disabledModules.Iter().GetAllEntities()) + throw new InvalidOperationException($"Module '{module.Path}' is not ednbled"); // Initialize Canvas and GameWindow singletons with actual values. world.Entity().Set(new Canvas(Silk.NET.OpenGL.ContextSourceExtensions.CreateOpenGL(window))); diff --git a/src/gaemstone.Client/Systems/EntityInspector.cs b/src/gaemstone.Client/Systems/EntityInspector.cs index 9bf612e..b4d4681 100644 --- a/src/gaemstone.Client/Systems/EntityInspector.cs +++ b/src/gaemstone.Client/Systems/EntityInspector.cs @@ -7,7 +7,6 @@ using gaemstone.ECS; using gaemstone.Flecs; using ImGuiNET; using static gaemstone.Client.Systems.ImGuiManager; -using Icon = gaemstone.Client.Utility.ForkAwesome; using ImGuiInternal = ImGuiNET.Internal.ImGui; namespace gaemstone.Client.Systems; @@ -15,7 +14,6 @@ namespace gaemstone.Client.Systems; [Module] [DependsOn] public partial class EntityInspector - : IModuleInitializer { [Tag] public struct InspectorWindow { } @@ -54,32 +52,49 @@ public partial class EntityInspector } [Component] - public struct DocPriority { public float Value; } + public record struct Priority(float Value); [Component] - public struct DocIcon { public char Value; } + public record struct Icon(char Value); - private const string DefaultWindowTitle = "Inspector Gadget"; + [Path("/flecs/core/Module")] + // [Doc(Color = "#FFE4B2")] + [Add, Set(0), Set(ForkAwesome.Archive)] + public struct Module { } - public static void Initialize(Entity module) - { - void SetDocInfo(string path, float priority, string icon, float r, float g, float b) - => module.World.LookupPathOrThrow(path) - .Add() - .Set(new DocPriority { Value = priority }) - .Set(new DocIcon { Value = icon[0] }) - .SetDocColor(Color.FromRGB(r, g, b).ToHexString()); - - SetDocInfo("/flecs/core/Module" , 0 , Icon.Archive , 1.0f, 0.9f, 0.7f); - SetDocInfo("/flecs/system/System" , 1 , Icon.Cog , 1.0f, 0.7f, 0.7f); - SetDocInfo("/flecs/core/Observer" , 2 , Icon.Eye , 1.0f, 0.8f, 0.8f); - SetDocInfo("/gaemstone/Doc/Relation" , 3 , Icon.ShareAlt , 0.7f, 1.0f, 0.8f); - SetDocInfo("/flecs/core/Component" , 4 , Icon.PencilSquare , 0.6f, 0.6f, 1.0f); - // TODO: Handle tags like Flecs does. - SetDocInfo("/flecs/core/Tag" , 5 , Icon.Tag , 0.7f, 0.8f, 1.0f); - SetDocInfo("/flecs/core/Prefab" , 6 , Icon.Cube , 0.9f, 0.8f, 1.0f); - } + [Path("/flecs/system/System")] + // [Doc(Color = "#FFB2B2")] + [Add, Set(1), Set(ForkAwesome.Cog)] + public struct System { } + + [Path("/flecs/core/Observer")] + // [Doc(Color = "#FFCCCC")] + [Add, Set(2), Set(ForkAwesome.Eye)] + public struct Observer { } + + [Path("/gaemstone/Doc/Relation")] + // [Doc(Color = "#B2FFCC")] + [Add, Set(3), Set(ForkAwesome.ShareAlt)] + public struct Relation { } + + [Path("/flecs/core/Component")] + // [Doc(Color = "#9999FF")] + [Add, Set(4), Set(ForkAwesome.PencilSquare)] + public struct Component { } + + [Path("/gaemstone/Doc/Tag")] + // [Doc(Color = "#B2CCFF")] + [Add, Set(5), Set(ForkAwesome.Tag)] + public struct Tag { } + + [Path("/flecs/core/Prefab")] + // [Doc(Color = "#E4CCFF")] + [Add, Set(6), Set(ForkAwesome.Cube)] + public struct Prefab { } + + + private const string DefaultWindowTitle = "Inspector Gadget"; [System] @@ -87,10 +102,10 @@ public partial class EntityInspector { var hasAnyInspector = false; var inspectorWindow = world.Entity(); - foreach (var entity in Iterator.FromTerm(world, new(inspectorWindow))) + foreach (var entity in world.Term(new(inspectorWindow))) { hasAnyInspector = true; break; } - if (ImGuiUtility.UIButton(0, Icon.Search, DefaultWindowTitle, hasAnyInspector)) + if (ImGuiUtility.UIButton(0, ForkAwesome.Search, DefaultWindowTitle, hasAnyInspector)) NewEntityInspectorWindow(world); } @@ -104,7 +119,7 @@ public partial class EntityInspector ImGui.SetNextWindowSize(new(fontSize * 40, fontSize * 25), ImGuiCond.Appearing); ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[1]); var title = window.GetDocName() ?? DefaultWindowTitle; - if (ImGui.Begin($"{Icon.Search} {title}###{window.NumericId}", + if (ImGui.Begin($"{ForkAwesome.Search} {title}###{window.NumericId}", ref isOpen, ImGuiWindowFlags.NoScrollbar)) { ImGui.PushFont(ImGui.GetIO().Fonts.Fonts[0]); @@ -132,9 +147,9 @@ public partial class EntityInspector ImGui.TableNextColumn(); ImGui.BeginChild("EntityView", new(-float.Epsilon, -float.Epsilon)); if (!ImGui.BeginTabBar("Tabs")) return; - Tab($"{Icon.PencilSquare} Components", ComponentsTab); - Tab($"{Icon.ShareAlt} References", ReferencesTab); - Tab($"{Icon.InfoCircle} Documentation", DocumentationTab); + Tab($"{ForkAwesome.PencilSquare} Components", ComponentsTab); + Tab($"{ForkAwesome.ShareAlt} References", ReferencesTab); + Tab($"{ForkAwesome.InfoCircle} Documentation", DocumentationTab); ImGui.EndTabBar(); ImGui.EndChild(); @@ -157,9 +172,9 @@ public partial class EntityInspector private static void ActionBarAndPath(Entity window, History? history, Entity? selected) { - static bool IconButtonWithToolTip(string icon, string tooltip, bool enabled = true) { + static bool IconButtonWithToolTip(char icon, string tooltip, bool enabled = true) { if (!enabled) ImGui.BeginDisabled(); - var clicked = ImGui.Button(icon); + var clicked = ImGui.Button(icon.ToString()); if (!enabled) ImGui.EndDisabled(); if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) ImGui.SetTooltip(tooltip); @@ -174,22 +189,22 @@ public partial class EntityInspector ImGui.TableNextColumn(); var hasExpanded = window.Has(); - if (IconButtonWithToolTip(Icon.Outdent, "Collapse all items in the Explorer View", hasExpanded)) + if (IconButtonWithToolTip(ForkAwesome.Outdent, "Collapse all items in the Explorer View", hasExpanded)) window.Remove(); if (history != null) { var hasPrev = ((selected != null) ? history.Current?.Prev : history.Current) != null; var hasNext = history.Current?.Next != null; ImGui.SameLine(); - if (IconButtonWithToolTip(Icon.ArrowLeft, "Go to the previously viewed entity", hasPrev)) + if (IconButtonWithToolTip(ForkAwesome.ArrowLeft, "Go to the previously viewed entity", hasPrev)) GoToPrevious(window, history, selected); ImGui.SameLine(); - if (IconButtonWithToolTip(Icon.ArrowRight, "Go to the next viewed entity", hasNext)) + if (IconButtonWithToolTip(ForkAwesome.ArrowRight, "Go to the next viewed entity", hasNext)) GoToNext(window, history); } ImGui.SameLine(); - if (IconButtonWithToolTip(Icon.Crosshairs, "Scroll to the current entity in the Explorer View", (selected != null))) + if (IconButtonWithToolTip(ForkAwesome.Crosshairs, "Scroll to the current entity in the Explorer View", (selected != null))) window.Add(); ImGui.TableNextColumn(); @@ -197,22 +212,22 @@ public partial class EntityInspector PathInput(window, history, selected, availableWidth); ImGui.TableNextColumn(); - if (IconButtonWithToolTip(Icon.PlusCircle, "Create a new child entity", (selected != null))) + if (IconButtonWithToolTip(ForkAwesome.PlusCircle, "Create a new child entity", (selected != null))) SetSelected(window, history, selected?.NewChild().Build()); ImGui.SameLine(); - if (IconButtonWithToolTip(Icon.Pencil, "Rename the current entity", false && (selected != null))) + if (IconButtonWithToolTip(ForkAwesome.Pencil, "Rename the current entity", false && (selected != null))) { } // TODO: Implement this! ImGui.SameLine(); var isDisabled = (selected?.IsDisabled == true); - var icon = !isDisabled ? Icon.BellSlash : Icon.Bell; + var icon = !isDisabled ? ForkAwesome.BellSlash : ForkAwesome.Bell; var tooltip = $"{(!isDisabled ? "Disable" : "Enable")} the current entity"; if (IconButtonWithToolTip(icon, tooltip, (selected != null))) { if (isDisabled) selected?.Enable(); else selected?.Disable(); } ImGui.SameLine(); - if (IconButtonWithToolTip(Icon.Trash, "Delete the current entity", (selected != null))) { + if (IconButtonWithToolTip(ForkAwesome.Trash, "Delete the current entity", (selected != null))) { // TODO: Delete history for deleted entity? SetSelected(window, history, selected?.Parent); selected?.Delete(); // TODO: Confirmation dialog? @@ -361,9 +376,9 @@ public partial class EntityInspector var expId = world.Entity().NumericId; List GetEntries(Entity? parent) { var result = new List(); - using var rule = new Rule(world, new( + using var rule = world.Rule(new( $"(ChildOf, {parent?.NumericId ?? 0})" // Must be child of parent, or root entity. - + $",?{expId}({window.NumericId}, $This)" // Whether entity is expanded in explorer view. + + $",?{expId}({window.NumericId}, $this)" // Whether entity is expanded in explorer view. + $",?Disabled" // Don't filter out disabled entities. )); foreach (var iter in rule.Iter()) { @@ -471,13 +486,13 @@ public partial class EntityInspector var ChildOf = world.Entity(); var Wildcard = world.Entity(); - if (ImGui.CollapsingHeader($"As {Icon.Tag} Component", ImGuiTreeNodeFlags.DefaultOpen)) - foreach (var iter in Iterator.FromTerm(world, new(selected))) + if (ImGui.CollapsingHeader($"As {ForkAwesome.Tag} Component", ImGuiTreeNodeFlags.DefaultOpen)) + foreach (var iter in world.Term(new(selected))) for (var i = 0; i < iter.Count; i++) RenderEntity(window, history, iter.Entity(i)); - if (ImGui.CollapsingHeader($"As {Icon.ShareAlt} Relation", ImGuiTreeNodeFlags.DefaultOpen)) - foreach (var iter in Iterator.FromTerm(world, new(selected, Wildcard))) { + if (ImGui.CollapsingHeader($"As {ForkAwesome.ShareAlt} Relation", ImGuiTreeNodeFlags.DefaultOpen)) + foreach (var iter in world.Term(new(selected, Wildcard))) { var id = iter.FieldId(1); if (id.AsPair() is not (Entity relation, Entity target)) throw new InvalidOperationException(); if (relation == ChildOf) continue; // Hide ChildOf relations. @@ -489,8 +504,8 @@ public partial class EntityInspector } } - if (ImGui.CollapsingHeader($"As {Icon.Bullseye} Target", ImGuiTreeNodeFlags.DefaultOpen)) - foreach (var iter in Iterator.FromTerm(world, new(Wildcard, selected))) { + if (ImGui.CollapsingHeader($"As {ForkAwesome.Bullseye} Target", ImGuiTreeNodeFlags.DefaultOpen)) + foreach (var iter in world.Term(new(Wildcard, selected))) { var id = iter.FieldId(1); if (id.AsPair() is not (Entity relation, Entity target)) throw new InvalidOperationException(); if (relation == ChildOf) continue; // Hide ChildOf relations. @@ -521,7 +536,7 @@ public partial class EntityInspector if (fill) ImGui.SetNextItemWidth(-float.Epsilon); } - Column($"{Icon.Tag} Display Name", """ + Column($"{ForkAwesome.Tag} Display Name", """ A display name for this entity. Names in the entity hierarchy must be unique within the parent entity, This doesn't apply to display names - they are mostly informational. @@ -532,7 +547,7 @@ public partial class EntityInspector selected?.SetDocName((name.Length > 0) ? name : null); if (!hasSelected) ImGui.EndDisabled(); - Column($"{Icon.Comment} Description", + Column($"{ForkAwesome.Comment} Description", "A brief description of this entity."); if (!hasSelected) ImGui.BeginDisabled(); var brief = selected?.GetDocBrief() ?? ""; @@ -540,7 +555,7 @@ public partial class EntityInspector selected?.SetDocBrief((brief.Length > 0) ? brief : null); if (!hasSelected) ImGui.EndDisabled(); - Column($"{Icon.FileText} Documentation", """ + Column($"{ForkAwesome.FileText} Documentation", """ A detailed description, or full documentation, of this entity's purpose and behaviors. It's encouraged to use multiple paragraphs and markdown formatting if necessary. """); @@ -556,7 +571,7 @@ public partial class EntityInspector selected?.SetDocDetail((detail.Length > 0) ? detail : null); if (!hasSelected) ImGui.EndDisabled(); - Column($"{Icon.Link} Link", """ + Column($"{ForkAwesome.Link} Link", """ A link to a website relating to this entity, such as a module's repository, or further documentation. """); @@ -566,7 +581,7 @@ public partial class EntityInspector selected?.SetDocLink((link.Length > 0) ? link : null); if (!hasSelected) ImGui.EndDisabled(); - Column($"{Icon.PaintBrush} Color", """ + Column($"{ForkAwesome.PaintBrush} Color", """ A custom color to represent this entity. Used in the entity inspector's explorer view. """, false); @@ -649,7 +664,7 @@ public partial class EntityInspector var world = entity.World; var component = world.Entity(); - var rule = (Rule)(_findDisplayTypeRule ??= new Rule(world, new( + var rule = (Rule)(_findDisplayTypeRule ??= world.Rule(new( $"$Type, gaemstone.Doc.DisplayType($Type)"))); var typeVar = rule.Variables["Type"]!; @@ -660,7 +675,7 @@ public partial class EntityInspector var type = iter.GetVar(typeVar); if ((type == component) && (entity.GetOrNull(component)?.Size == 0)) type = world.Entity(); - var priority = type?.GetOrNull()?.Value ?? float.MaxValue; + var priority = type?.GetOrNull()?.Value ?? float.MaxValue; if (priority <= curPriority) { curType = type; curPriority = priority; } } @@ -705,8 +720,8 @@ public partial class EntityInspector if (!ImGui.IsRectVisible(pos, pos + dummySize)) { ImGui.Dummy(dummySize); return; } var (displayType, _) = FindDisplayType(entity); - var docColor = Color.TryParseHex(entity.GetDocColor()) ?? Color.TryParseHex(displayType?.GetDocColor()); - var docIcon = entity.GetOrNull()?.Value.ToString() ?? displayType?.GetOrNull()?.Value.ToString(); + var docColor = Color.TryParseHex(entity.GetDocColor()) ?? Color.TryParseHex(displayType?.GetDocColor()); + var docIcon = entity.GetOrNull()?.Value.ToString() ?? displayType?.GetOrNull()?.Value.ToString(); var docName = entity.GetDocName(false); var isDisabled = entity.IsDisabled; diff --git a/src/gaemstone.Client/Systems/InputManager.cs b/src/gaemstone.Client/Systems/InputManager.cs index 76a4430..cc6f088 100644 --- a/src/gaemstone.Client/Systems/InputManager.cs +++ b/src/gaemstone.Client/Systems/InputManager.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Numerics; -using System.Runtime.CompilerServices; using gaemstone.ECS; using gaemstone.Flecs; using Silk.NET.Input; diff --git a/src/gaemstone.Client/Systems/Renderer.cs b/src/gaemstone.Client/Systems/Renderer.cs index c7ba7ac..3dbbed2 100644 --- a/src/gaemstone.Client/Systems/Renderer.cs +++ b/src/gaemstone.Client/Systems/Renderer.cs @@ -95,7 +95,7 @@ public partial class Renderer var cameraMatrix = invertedTransform * cameraProjection; GL.UniformMatrix4(_cameraMatrixUniform, 1, false, in cameraMatrix.M11); - var rule = (Rule)(_renderEntityRule ??= new Rule(world, new(""" + var rule = (Rule)(_renderEntityRule ??= world.Rule(new(""" [in] GlobalTransform, (Mesh, $mesh), [in] MeshHandle($mesh), ?(Texture, $tex), [in] ?TextureHandle($tex) diff --git a/src/gaemstone.Client/Utility/ForkAwesome.cs b/src/gaemstone.Client/Utility/ForkAwesome.cs index f917f77..754e5d8 100644 --- a/src/gaemstone.Client/Utility/ForkAwesome.cs +++ b/src/gaemstone.Client/Utility/ForkAwesome.cs @@ -5,815 +5,815 @@ public class ForkAwesome public const int Min = 0xf000; public const int Max = 0xf372; - public const string Glass = "\uF000"; - public const string Music = "\uF001"; - public const string Search = "\uF002"; - public const string EnvelopeO = "\uF003"; - public const string Heart = "\uF004"; - public const string Star = "\uF005"; - public const string StarO = "\uF006"; - public const string User = "\uF007"; - public const string Film = "\uF008"; - public const string ThLarge = "\uF009"; - public const string Th = "\uF00A"; - public const string ThList = "\uF00B"; - public const string Check = "\uF00C"; - public const string Times = "\uF00D"; - public const string SearchPlus = "\uF00E"; - public const string SearchMinus = "\uF010"; - public const string PowerOff = "\uF011"; - public const string Signal = "\uF012"; - public const string Cog = "\uF013"; - public const string TrashO = "\uF014"; - public const string Home = "\uF015"; - public const string FileO = "\uF016"; - public const string ClockO = "\uF017"; - public const string Road = "\uF018"; - public const string Download = "\uF019"; - public const string ArrowCircleODown = "\uF01A"; - public const string ArrowCircleOUp = "\uF01B"; - public const string Inbox = "\uF01C"; - public const string PlayCircleO = "\uF01D"; - public const string Repeat = "\uF01E"; - public const string Refresh = "\uF021"; - public const string ListAlt = "\uF022"; - public const string Lock = "\uF023"; - public const string Flag = "\uF024"; - public const string Headphones = "\uF025"; - public const string VolumeOff = "\uF026"; - public const string VolumeDown = "\uF027"; - public const string VolumeUp = "\uF028"; - public const string Qrcode = "\uF029"; - public const string Barcode = "\uF02A"; - public const string Tag = "\uF02B"; - public const string Tags = "\uF02C"; - public const string Book = "\uF02D"; - public const string Bookmark = "\uF02E"; - public const string Print = "\uF02F"; - public const string Camera = "\uF030"; - public const string Font = "\uF031"; - public const string Bold = "\uF032"; - public const string Italic = "\uF033"; - public const string TextHeight = "\uF034"; - public const string TextWidth = "\uF035"; - public const string AlignLeft = "\uF036"; - public const string AlignCenter = "\uF037"; - public const string AlignRight = "\uF038"; - public const string AlignJustify = "\uF039"; - public const string List = "\uF03A"; - public const string Outdent = "\uF03B"; - public const string Indent = "\uF03C"; - public const string VideoCamera = "\uF03D"; - public const string PictureO = "\uF03E"; - public const string Pencil = "\uF040"; - public const string MapMarker = "\uF041"; - public const string Adjust = "\uF042"; - public const string Tint = "\uF043"; - public const string PencilSquareO = "\uF044"; - public const string ShareSquareO = "\uF045"; - public const string CheckSquareO = "\uF046"; - public const string Arrows = "\uF047"; - public const string StepBackward = "\uF048"; - public const string FastBackward = "\uF049"; - public const string Backward = "\uF04A"; - public const string Play = "\uF04B"; - public const string Pause = "\uF04C"; - public const string Stop = "\uF04D"; - public const string Forward = "\uF04E"; - public const string FastForward = "\uF050"; - public const string StepForward = "\uF051"; - public const string Eject = "\uF052"; - public const string ChevronLeft = "\uF053"; - public const string ChevronRight = "\uF054"; - public const string PlusCircle = "\uF055"; - public const string MinusCircle = "\uF056"; - public const string TimesCircle = "\uF057"; - public const string CheckCircle = "\uF058"; - public const string QuestionCircle = "\uF059"; - public const string InfoCircle = "\uF05A"; - public const string Crosshairs = "\uF05B"; - public const string TimesCircleO = "\uF05C"; - public const string CheckCircleO = "\uF05D"; - public const string Ban = "\uF05E"; - public const string ArrowLeft = "\uF060"; - public const string ArrowRight = "\uF061"; - public const string ArrowUp = "\uF062"; - public const string ArrowDown = "\uF063"; - public const string Share = "\uF064"; - public const string Expand = "\uF065"; - public const string Compress = "\uF066"; - public const string Plus = "\uF067"; - public const string Minus = "\uF068"; - public const string Asterisk = "\uF069"; - public const string ExclamationCircle = "\uF06A"; - public const string Gift = "\uF06B"; - public const string Leaf = "\uF06C"; - public const string Fire = "\uF06D"; - public const string Eye = "\uF06E"; - public const string EyeSlash = "\uF070"; - public const string ExclamationTriangle = "\uF071"; - public const string Plane = "\uF072"; - public const string Calendar = "\uF073"; - public const string Random = "\uF074"; - public const string Comment = "\uF075"; - public const string Magnet = "\uF076"; - public const string ChevronUp = "\uF077"; - public const string ChevronDown = "\uF078"; - public const string Retweet = "\uF079"; - public const string ShoppingCart = "\uF07A"; - public const string Folder = "\uF07B"; - public const string FolderOpen = "\uF07C"; - public const string ArrowsV = "\uF07D"; - public const string ArrowsH = "\uF07E"; - public const string BarChart = "\uF080"; - public const string TwitterSquare = "\uF081"; - public const string FacebookSquare = "\uF082"; - public const string CameraRetro = "\uF083"; - public const string Key = "\uF084"; - public const string Cogs = "\uF085"; - public const string Comments = "\uF086"; - public const string ThumbsOUp = "\uF087"; - public const string ThumbsODown = "\uF088"; - public const string StarHalf = "\uF089"; - public const string HeartO = "\uF08A"; - public const string SignOut = "\uF08B"; - public const string LinkedinSquare = "\uF08C"; - public const string ThumbTack = "\uF08D"; - public const string ExternalLink = "\uF08E"; - public const string SignIn = "\uF090"; - public const string Trophy = "\uF091"; - public const string GithubSquare = "\uF092"; - public const string Upload = "\uF093"; - public const string LemonO = "\uF094"; - public const string Phone = "\uF095"; - public const string SquareO = "\uF096"; - public const string BookmarkO = "\uF097"; - public const string PhoneSquare = "\uF098"; - public const string Twitter = "\uF099"; - public const string Facebook = "\uF09A"; - public const string Github = "\uF09B"; - public const string Unlock = "\uF09C"; - public const string CreditCard = "\uF09D"; - public const string Rss = "\uF09E"; - public const string HddO = "\uF0A0"; - public const string Bullhorn = "\uF0A1"; - public const string BellO = "\uF0F3"; - public const string Certificate = "\uF0A3"; - public const string HandORight = "\uF0A4"; - public const string HandOLeft = "\uF0A5"; - public const string HandOUp = "\uF0A6"; - public const string HandODown = "\uF0A7"; - public const string ArrowCircleLeft = "\uF0A8"; - public const string ArrowCircleRight = "\uF0A9"; - public const string ArrowCircleUp = "\uF0AA"; - public const string ArrowCircleDown = "\uF0AB"; - public const string Globe = "\uF0AC"; - public const string GlobeE = "\uF304"; - public const string GlobeW = "\uF305"; - public const string Wrench = "\uF0AD"; - public const string Tasks = "\uF0AE"; - public const string Filter = "\uF0B0"; - public const string Briefcase = "\uF0B1"; - public const string ArrowsAlt = "\uF0B2"; - public const string Users = "\uF0C0"; - public const string Link = "\uF0C1"; - public const string Cloud = "\uF0C2"; - public const string Flask = "\uF0C3"; - public const string Scissors = "\uF0C4"; - public const string FilesO = "\uF0C5"; - public const string Paperclip = "\uF0C6"; - public const string FloppyO = "\uF0C7"; - public const string Square = "\uF0C8"; - public const string Bars = "\uF0C9"; - public const string ListUl = "\uF0CA"; - public const string ListOl = "\uF0CB"; - public const string Strikethrough = "\uF0CC"; - public const string Underline = "\uF0CD"; - public const string Table = "\uF0CE"; - public const string Magic = "\uF0D0"; - public const string Truck = "\uF0D1"; - public const string Pinterest = "\uF0D2"; - public const string PinterestSquare = "\uF0D3"; - public const string GooglePlusSquare = "\uF0D4"; - public const string GooglePlus = "\uF0D5"; - public const string Money = "\uF0D6"; - public const string CaretDown = "\uF0D7"; - public const string CaretUp = "\uF0D8"; - public const string CaretLeft = "\uF0D9"; - public const string CaretRight = "\uF0DA"; - public const string Columns = "\uF0DB"; - public const string Sort = "\uF0DC"; - public const string SortDesc = "\uF0DD"; - public const string SortAsc = "\uF0DE"; - public const string Envelope = "\uF0E0"; - public const string Linkedin = "\uF0E1"; - public const string Undo = "\uF0E2"; - public const string Gavel = "\uF0E3"; - public const string Tachometer = "\uF0E4"; - public const string CommentO = "\uF0E5"; - public const string CommentsO = "\uF0E6"; - public const string Bolt = "\uF0E7"; - public const string Sitemap = "\uF0E8"; - public const string Umbrella = "\uF0E9"; - public const string Clipboard = "\uF0EA"; - public const string LightbulbO = "\uF0EB"; - public const string Exchange = "\uF0EC"; - public const string CloudDownload = "\uF0ED"; - public const string CloudUpload = "\uF0EE"; - public const string UserMd = "\uF0F0"; - public const string Stethoscope = "\uF0F1"; - public const string Suitcase = "\uF0F2"; - public const string Bell = "\uF0A2"; - public const string Coffee = "\uF0F4"; - public const string Cutlery = "\uF0F5"; - public const string FileTextO = "\uF0F6"; - public const string BuildingO = "\uF0F7"; - public const string HospitalO = "\uF0F8"; - public const string Ambulance = "\uF0F9"; - public const string Medkit = "\uF0FA"; - public const string FighterJet = "\uF0FB"; - public const string Beer = "\uF0FC"; - public const string HSquare = "\uF0FD"; - public const string PlusSquare = "\uF0FE"; - public const string AngleDoubleLeft = "\uF100"; - public const string AngleDoubleRight = "\uF101"; - public const string AngleDoubleUp = "\uF102"; - public const string AngleDoubleDown = "\uF103"; - public const string AngleLeft = "\uF104"; - public const string AngleRight = "\uF105"; - public const string AngleUp = "\uF106"; - public const string AngleDown = "\uF107"; - public const string Desktop = "\uF108"; - public const string Laptop = "\uF109"; - public const string Tablet = "\uF10A"; - public const string Mobile = "\uF10B"; - public const string CircleO = "\uF10C"; - public const string QuoteLeft = "\uF10D"; - public const string QuoteRight = "\uF10E"; - public const string Spinner = "\uF110"; - public const string Circle = "\uF111"; - public const string Reply = "\uF112"; - public const string GithubAlt = "\uF113"; - public const string FolderO = "\uF114"; - public const string FolderOpenO = "\uF115"; - public const string SmileO = "\uF118"; - public const string FrownO = "\uF119"; - public const string MehO = "\uF11A"; - public const string Gamepad = "\uF11B"; - public const string KeyboardO = "\uF11C"; - public const string FlagO = "\uF11D"; - public const string FlagCheckered = "\uF11E"; - public const string Terminal = "\uF120"; - public const string Code = "\uF121"; - public const string ReplyAll = "\uF122"; - public const string StarHalfO = "\uF123"; - public const string LocationArrow = "\uF124"; - public const string Crop = "\uF125"; - public const string CodeFork = "\uF126"; - public const string ChainBroken = "\uF127"; - public const string Question = "\uF128"; - public const string Info = "\uF129"; - public const string Exclamation = "\uF12A"; - public const string Superscript = "\uF12B"; - public const string Subscript = "\uF12C"; - public const string Eraser = "\uF12D"; - public const string PuzzlePiece = "\uF12E"; - public const string Microphone = "\uF130"; - public const string MicrophoneSlash = "\uF131"; - public const string Shield = "\uF132"; - public const string CalendarO = "\uF133"; - public const string FireExtinguisher = "\uF134"; - public const string Rocket = "\uF135"; - public const string Maxcdn = "\uF136"; - public const string ChevronCircleLeft = "\uF137"; - public const string ChevronCircleRight = "\uF138"; - public const string ChevronCircleUp = "\uF139"; - public const string ChevronCircleDown = "\uF13A"; - public const string Html5 = "\uF13B"; - public const string Css3 = "\uF13C"; - public const string Anchor = "\uF13D"; - public const string UnlockAlt = "\uF13E"; - public const string Bullseye = "\uF140"; - public const string EllipsisH = "\uF141"; - public const string EllipsisV = "\uF142"; - public const string RssSquare = "\uF143"; - public const string PlayCircle = "\uF144"; - public const string Ticket = "\uF145"; - public const string MinusSquare = "\uF146"; - public const string MinusSquareO = "\uF147"; - public const string LevelUp = "\uF148"; - public const string LevelDown = "\uF149"; - public const string CheckSquare = "\uF14A"; - public const string PencilSquare = "\uF14B"; - public const string ExternalLinkSquare = "\uF14C"; - public const string ShareSquare = "\uF14D"; - public const string Compass = "\uF14E"; - public const string CaretSquareODown = "\uF150"; - public const string CaretSquareOUp = "\uF151"; - public const string CaretSquareORight = "\uF152"; - public const string Eur = "\uF153"; - public const string Gbp = "\uF154"; - public const string Usd = "\uF155"; - public const string Inr = "\uF156"; - public const string Jpy = "\uF157"; - public const string Rub = "\uF158"; - public const string Krw = "\uF159"; - public const string Btc = "\uF15A"; - public const string File = "\uF15B"; - public const string FileText = "\uF15C"; - public const string SortAlphaAsc = "\uF15D"; - public const string SortAlphaDesc = "\uF15E"; - public const string SortAmountAsc = "\uF160"; - public const string SortAmountDesc = "\uF161"; - public const string SortNumericAsc = "\uF162"; - public const string SortNumericDesc = "\uF163"; - public const string ThumbsUp = "\uF164"; - public const string ThumbsDown = "\uF165"; - public const string YoutubeSquare = "\uF166"; - public const string Youtube = "\uF167"; - public const string Xing = "\uF168"; - public const string XingSquare = "\uF169"; - public const string YoutubePlay = "\uF16A"; - public const string Dropbox = "\uF16B"; - public const string StackOverflow = "\uF16C"; - public const string Instagram = "\uF16D"; - public const string Flickr = "\uF16E"; - public const string Adn = "\uF170"; - public const string Bitbucket = "\uF171"; - public const string BitbucketSquare = "\uF172"; - public const string Tumblr = "\uF173"; - public const string TumblrSquare = "\uF174"; - public const string LongArrowDown = "\uF175"; - public const string LongArrowUp = "\uF176"; - public const string LongArrowLeft = "\uF177"; - public const string LongArrowRight = "\uF178"; - public const string Apple = "\uF179"; - public const string Windows = "\uF17A"; - public const string Android = "\uF17B"; - public const string Linux = "\uF17C"; - public const string Dribbble = "\uF17D"; - public const string Skype = "\uF17E"; - public const string Foursquare = "\uF180"; - public const string Trello = "\uF181"; - public const string Female = "\uF182"; - public const string Male = "\uF183"; - public const string Gratipay = "\uF184"; - public const string SunO = "\uF185"; - public const string MoonO = "\uF186"; - public const string Archive = "\uF187"; - public const string Bug = "\uF188"; - public const string Vk = "\uF189"; - public const string Weibo = "\uF18A"; - public const string Renren = "\uF18B"; - public const string Pagelines = "\uF18C"; - public const string StackExchange = "\uF18D"; - public const string ArrowCircleORight = "\uF18E"; - public const string ArrowCircleOLeft = "\uF190"; - public const string CaretSquareOLeft = "\uF191"; - public const string DotCircleO = "\uF192"; - public const string Wheelchair = "\uF193"; - public const string VimeoSquare = "\uF194"; - public const string Try = "\uF195"; - public const string PlusSquareO = "\uF196"; - public const string SpaceShuttle = "\uF197"; - public const string Slack = "\uF198"; - public const string EnvelopeSquare = "\uF199"; - public const string Wordpress = "\uF19A"; - public const string Openid = "\uF19B"; - public const string University = "\uF19C"; - public const string GraduationCap = "\uF19D"; - public const string Yahoo = "\uF19E"; - public const string Google = "\uF1A0"; - public const string Reddit = "\uF1A1"; - public const string RedditSquare = "\uF1A2"; - public const string StumbleuponCircle = "\uF1A3"; - public const string Stumbleupon = "\uF1A4"; - public const string Delicious = "\uF1A5"; - public const string Digg = "\uF1A6"; - public const string Drupal = "\uF1A9"; - public const string Joomla = "\uF1AA"; - public const string Language = "\uF1AB"; - public const string Fax = "\uF1AC"; - public const string Building = "\uF1AD"; - public const string Child = "\uF1AE"; - public const string Paw = "\uF1B0"; - public const string Spoon = "\uF1B1"; - public const string Cube = "\uF1B2"; - public const string Cubes = "\uF1B3"; - public const string Behance = "\uF1B4"; - public const string BehanceSquare = "\uF1B5"; - public const string Steam = "\uF1B6"; - public const string SteamSquare = "\uF1B7"; - public const string Recycle = "\uF1B8"; - public const string Car = "\uF1B9"; - public const string Taxi = "\uF1BA"; - public const string Tree = "\uF1BB"; - public const string Spotify = "\uF1BC"; - public const string Deviantart = "\uF1BD"; - public const string Soundcloud = "\uF1BE"; - public const string Database = "\uF1C0"; - public const string FilePdfO = "\uF1C1"; - public const string FileWordO = "\uF1C2"; - public const string FileExcelO = "\uF1C3"; - public const string FilePowerpointO = "\uF1C4"; - public const string FileImageO = "\uF1C5"; - public const string FileArchiveO = "\uF1C6"; - public const string FileAudioO = "\uF1C7"; - public const string FileVideoO = "\uF1C8"; - public const string FileCodeO = "\uF1C9"; - public const string Vine = "\uF1CA"; - public const string Codepen = "\uF1CB"; - public const string Jsfiddle = "\uF1CC"; - public const string LifeRing = "\uF1CD"; - public const string CircleONotch = "\uF1CE"; - public const string Rebel = "\uF1D0"; - public const string Empire = "\uF1D1"; - public const string GitSquare = "\uF1D2"; - public const string Git = "\uF1D3"; - public const string HackerNews = "\uF1D4"; - public const string TencentWeibo = "\uF1D5"; - public const string Qq = "\uF1D6"; - public const string Weixin = "\uF1D7"; - public const string PaperPlane = "\uF1D8"; - public const string PaperPlaneO = "\uF1D9"; - public const string History = "\uF1DA"; - public const string CircleThin = "\uF1DB"; - public const string Header = "\uF1DC"; - public const string Paragraph = "\uF1DD"; - public const string Sliders = "\uF1DE"; - public const string ShareAlt = "\uF1E0"; - public const string ShareAltSquare = "\uF1E1"; - public const string Bomb = "\uF1E2"; - public const string FutbolO = "\uF1E3"; - public const string Tty = "\uF1E4"; - public const string Binoculars = "\uF1E5"; - public const string Plug = "\uF1E6"; - public const string Slideshare = "\uF1E7"; - public const string Twitch = "\uF1E8"; - public const string Yelp = "\uF1E9"; - public const string NewspaperO = "\uF1EA"; - public const string Wifi = "\uF1EB"; - public const string Calculator = "\uF1EC"; - public const string Paypal = "\uF1ED"; - public const string GoogleWallet = "\uF1EE"; - public const string CcVisa = "\uF1F0"; - public const string CcMastercard = "\uF1F1"; - public const string CcDiscover = "\uF1F2"; - public const string CcAmex = "\uF1F3"; - public const string CcPaypal = "\uF1F4"; - public const string CcStripe = "\uF1F5"; - public const string BellSlash = "\uF1F6"; - public const string BellSlashO = "\uF1F7"; - public const string Trash = "\uF1F8"; - public const string Copyright = "\uF1F9"; - public const string At = "\uF1FA"; - public const string Eyedropper = "\uF1FB"; - public const string PaintBrush = "\uF1FC"; - public const string BirthdayCake = "\uF1FD"; - public const string AreaChart = "\uF1FE"; - public const string PieChart = "\uF200"; - public const string LineChart = "\uF201"; - public const string Lastfm = "\uF202"; - public const string LastfmSquare = "\uF203"; - public const string ToggleOff = "\uF204"; - public const string ToggleOn = "\uF205"; - public const string Bicycle = "\uF206"; - public const string Bus = "\uF207"; - public const string Ioxhost = "\uF208"; - public const string Angellist = "\uF209"; - public const string Cc = "\uF20A"; - public const string Ils = "\uF20B"; - public const string Meanpath = "\uF20C"; - public const string Buysellads = "\uF20D"; - public const string Connectdevelop = "\uF20E"; - public const string Dashcube = "\uF210"; - public const string Forumbee = "\uF211"; - public const string Leanpub = "\uF212"; - public const string Sellsy = "\uF213"; - public const string Shirtsinbulk = "\uF214"; - public const string Simplybuilt = "\uF215"; - public const string Skyatlas = "\uF216"; - public const string CartPlus = "\uF217"; - public const string CartArrowDown = "\uF218"; - public const string Diamond = "\uF219"; - public const string Ship = "\uF21A"; - public const string UserSecret = "\uF21B"; - public const string Motorcycle = "\uF21C"; - public const string StreetView = "\uF21D"; - public const string Heartbeat = "\uF21E"; - public const string Venus = "\uF221"; - public const string Mars = "\uF222"; - public const string Mercury = "\uF223"; - public const string Transgender = "\uF224"; - public const string TransgenderAlt = "\uF225"; - public const string VenusDouble = "\uF226"; - public const string MarsDouble = "\uF227"; - public const string VenusMars = "\uF228"; - public const string MarsStroke = "\uF229"; - public const string MarsStrokeV = "\uF22A"; - public const string MarsStrokeH = "\uF22B"; - public const string Neuter = "\uF22C"; - public const string Genderless = "\uF22D"; - public const string FacebookOfficial = "\uF230"; - public const string PinterestP = "\uF231"; - public const string Whatsapp = "\uF232"; - public const string Server = "\uF233"; - public const string UserPlus = "\uF234"; - public const string UserTimes = "\uF235"; - public const string Bed = "\uF236"; - public const string Viacoin = "\uF237"; - public const string Train = "\uF238"; - public const string Subway = "\uF239"; - public const string Medium = "\uF23A"; - public const string MediumSquare = "\uF2F8"; - public const string YCombinator = "\uF23B"; - public const string OptinMonster = "\uF23C"; - public const string Opencart = "\uF23D"; - public const string Expeditedssl = "\uF23E"; - public const string BatteryFull = "\uF240"; - public const string BatteryThreeQuarters = "\uF241"; - public const string BatteryHalf = "\uF242"; - public const string BatteryQuarter = "\uF243"; - public const string BatteryEmpty = "\uF244"; - public const string MousePointer = "\uF245"; - public const string ICursor = "\uF246"; - public const string ObjectGroup = "\uF247"; - public const string ObjectUngroup = "\uF248"; - public const string StickyNote = "\uF249"; - public const string StickyNoteO = "\uF24A"; - public const string CcJcb = "\uF24B"; - public const string CcDinersClub = "\uF24C"; - public const string Clone = "\uF24D"; - public const string BalanceScale = "\uF24E"; - public const string HourglassO = "\uF250"; - public const string HourglassStart = "\uF251"; - public const string HourglassHalf = "\uF252"; - public const string HourglassEnd = "\uF253"; - public const string Hourglass = "\uF254"; - public const string HandRockO = "\uF255"; - public const string HandPaperO = "\uF256"; - public const string HandScissorsO = "\uF257"; - public const string HandLizardO = "\uF258"; - public const string HandSpockO = "\uF259"; - public const string HandPointerO = "\uF25A"; - public const string HandPeaceO = "\uF25B"; - public const string Trademark = "\uF25C"; - public const string Registered = "\uF25D"; - public const string CreativeCommons = "\uF25E"; - public const string Gg = "\uF260"; - public const string GgCircle = "\uF261"; - public const string Tripadvisor = "\uF262"; - public const string Odnoklassniki = "\uF263"; - public const string OdnoklassnikiSquare = "\uF264"; - public const string GetPocket = "\uF265"; - public const string WikipediaW = "\uF266"; - public const string Safari = "\uF267"; - public const string Chrome = "\uF268"; - public const string Firefox = "\uF269"; - public const string Opera = "\uF26A"; - public const string InternetExplorer = "\uF26B"; - public const string Television = "\uF26C"; - public const string Contao = "\uF26D"; - public const string Num500px = "\uF26E"; - public const string Amazon = "\uF270"; - public const string CalendarPlusO = "\uF271"; - public const string CalendarMinusO = "\uF272"; - public const string CalendarTimesO = "\uF273"; - public const string CalendarCheckO = "\uF274"; - public const string Industry = "\uF275"; - public const string MapPin = "\uF276"; - public const string MapSigns = "\uF277"; - public const string MapO = "\uF278"; - public const string Map = "\uF279"; - public const string Commenting = "\uF27A"; - public const string CommentingO = "\uF27B"; - public const string Houzz = "\uF27C"; - public const string Vimeo = "\uF27D"; - public const string BlackTie = "\uF27E"; - public const string Fonticons = "\uF280"; - public const string RedditAlien = "\uF281"; - public const string Edge = "\uF282"; - public const string CreditCardAlt = "\uF283"; - public const string Codiepie = "\uF284"; - public const string Modx = "\uF285"; - public const string FortAwesome = "\uF286"; - public const string Usb = "\uF287"; - public const string ProductHunt = "\uF288"; - public const string Mixcloud = "\uF289"; - public const string Scribd = "\uF28A"; - public const string PauseCircle = "\uF28B"; - public const string PauseCircleO = "\uF28C"; - public const string StopCircle = "\uF28D"; - public const string StopCircleO = "\uF28E"; - public const string ShoppingBag = "\uF290"; - public const string ShoppingBasket = "\uF291"; - public const string Hashtag = "\uF292"; - public const string Bluetooth = "\uF293"; - public const string BluetoothB = "\uF294"; - public const string Percent = "\uF295"; - public const string Gitlab = "\uF296"; - public const string Wpbeginner = "\uF297"; - public const string Wpforms = "\uF298"; - public const string Envira = "\uF299"; - public const string UniversalAccess = "\uF29A"; - public const string WheelchairAlt = "\uF29B"; - public const string QuestionCircleO = "\uF29C"; - public const string Blind = "\uF29D"; - public const string AudioDescription = "\uF29E"; - public const string VolumeControlPhone = "\uF2A0"; - public const string Braille = "\uF2A1"; - public const string AssistiveListeningSystems = "\uF2A2"; - public const string AmericanSignLanguageInterpreting = "\uF2A3"; - public const string Deaf = "\uF2A4"; - public const string Glide = "\uF2A5"; - public const string GlideG = "\uF2A6"; - public const string SignLanguage = "\uF2A7"; - public const string LowVision = "\uF2A8"; - public const string Viadeo = "\uF2A9"; - public const string ViadeoSquare = "\uF2AA"; - public const string Snapchat = "\uF2AB"; - public const string SnapchatGhost = "\uF2AC"; - public const string SnapchatSquare = "\uF2AD"; - public const string FirstOrder = "\uF2B0"; - public const string Yoast = "\uF2B1"; - public const string Themeisle = "\uF2B2"; - public const string GooglePlusOfficial = "\uF2B3"; - public const string FontAwesome = "\uF2B4"; - public const string HandshakeO = "\uF2B5"; - public const string EnvelopeOpen = "\uF2B6"; - public const string EnvelopeOpenO = "\uF2B7"; - public const string Linode = "\uF2B8"; - public const string AddressBook = "\uF2B9"; - public const string AddressBookO = "\uF2BA"; - public const string AddressCard = "\uF2BB"; - public const string AddressCardO = "\uF2BC"; - public const string UserCircle = "\uF2BD"; - public const string UserCircleO = "\uF2BE"; - public const string UserO = "\uF2C0"; - public const string IdBadge = "\uF2C1"; - public const string IdCard = "\uF2C2"; - public const string IdCardO = "\uF2C3"; - public const string Quora = "\uF2C4"; - public const string FreeCodeCamp = "\uF2C5"; - public const string Telegram = "\uF2C6"; - public const string ThermometerFull = "\uF2C7"; - public const string ThermometerThreeQuarters = "\uF2C8"; - public const string ThermometerHalf = "\uF2C9"; - public const string ThermometerQuarter = "\uF2CA"; - public const string ThermometerEmpty = "\uF2CB"; - public const string Shower = "\uF2CC"; - public const string Bath = "\uF2CD"; - public const string Podcast = "\uF2CE"; - public const string WindowMaximize = "\uF2D0"; - public const string WindowMinimize = "\uF2D1"; - public const string WindowRestore = "\uF2D2"; - public const string WindowClose = "\uF2D3"; - public const string WindowCloseO = "\uF2D4"; - public const string Bandcamp = "\uF2D5"; - public const string Grav = "\uF2D6"; - public const string Etsy = "\uF2D7"; - public const string Imdb = "\uF2D8"; - public const string Ravelry = "\uF2D9"; - public const string Eercast = "\uF2DA"; - public const string Microchip = "\uF2DB"; - public const string SnowflakeO = "\uF2DC"; - public const string Superpowers = "\uF2DD"; - public const string Wpexplorer = "\uF2DE"; - public const string Meetup = "\uF2E0"; - public const string Mastodon = "\uF2E1"; - public const string MastodonAlt = "\uF2E2"; - public const string ForkAwesomeIcon = "\uF2E3"; - public const string Peertube = "\uF2E4"; - public const string Diaspora = "\uF2E5"; - public const string Friendica = "\uF2E6"; - public const string GnuSocial = "\uF2E7"; - public const string LiberapaySquare = "\uF2E8"; - public const string Liberapay = "\uF2E9"; - public const string Scuttlebutt = "\uF2EA"; - public const string Hubzilla = "\uF2EB"; - public const string SocialHome = "\uF2EC"; - public const string Artstation = "\uF2ED"; - public const string Discord = "\uF2EE"; - public const string DiscordAlt = "\uF2EF"; - public const string Patreon = "\uF2F0"; - public const string Snowdrift = "\uF2F1"; - public const string Activitypub = "\uF2F2"; - public const string Ethereum = "\uF2F3"; - public const string Keybase = "\uF2F4"; - public const string Shaarli = "\uF2F5"; - public const string ShaarliO = "\uF2F6"; - public const string KeyModern = "\uF2F7"; - public const string Xmpp = "\uF2F9"; - public const string ArchiveOrg = "\uF2FC"; - public const string Freedombox = "\uF2FD"; - public const string FacebookMessenger = "\uF2FE"; - public const string Debian = "\uF2FF"; - public const string MastodonSquare = "\uF300"; - public const string Tipeee = "\uF301"; - public const string React = "\uF302"; - public const string Dogmazic = "\uF303"; - public const string Zotero = "\uF309"; - public const string Nodejs = "\uF308"; - public const string Nextcloud = "\uF306"; - public const string NextcloudSquare = "\uF307"; - public const string Hackaday = "\uF30A"; - public const string Laravel = "\uF30B"; - public const string Signalapp = "\uF30C"; - public const string Gnupg = "\uF30D"; - public const string Php = "\uF30E"; - public const string Ffmpeg = "\uF30F"; - public const string Joplin = "\uF310"; - public const string Syncthing = "\uF311"; - public const string Inkscape = "\uF312"; - public const string MatrixOrg = "\uF313"; - public const string Pixelfed = "\uF314"; - public const string Bootstrap = "\uF315"; - public const string DevTo = "\uF316"; - public const string Hashnode = "\uF317"; - public const string Jirafeau = "\uF318"; - public const string Emby = "\uF319"; - public const string Wikidata = "\uF31A"; - public const string Gimp = "\uF31B"; - public const string C = "\uF31C"; - public const string Digitalocean = "\uF31D"; - public const string Att = "\uF31E"; - public const string Gitea = "\uF31F"; - public const string FileEpub = "\uF321"; - public const string Python = "\uF322"; - public const string Archlinux = "\uF323"; - public const string Pleroma = "\uF324"; - public const string Unsplash = "\uF325"; - public const string Hackster = "\uF326"; - public const string SpellCheck = "\uF327"; - public const string Moon = "\uF328"; - public const string Sun = "\uF329"; - public const string FDroid = "\uF32A"; - public const string Biometric = "\uF32B"; - public const string Wire = "\uF32C"; - public const string TorOnion = "\uF32E"; - public const string VolumeMute = "\uF32F"; - public const string BellRinging = "\uF32D"; - public const string BellRingingO = "\uF330"; - public const string Hal = "\uF333"; - public const string Jupyter = "\uF335"; - public const string Julia = "\uF334"; - public const string Classicpress = "\uF331"; - public const string ClassicpressCircle = "\uF332"; - public const string OpenCollective = "\uF336"; - public const string Orcid = "\uF337"; - public const string Researchgate = "\uF338"; - public const string Funkwhale = "\uF339"; - public const string Askfm = "\uF33A"; - public const string Blockstack = "\uF33B"; - public const string Boardgamegeek = "\uF33C"; - public const string Bunny = "\uF35F"; - public const string Buymeacoffee = "\uF33D"; - public const string CcBy = "\uF33E"; - public const string CcCc = "\uF33F"; - public const string CcNcEu = "\uF341"; - public const string CcNcJp = "\uF342"; - public const string CcNc = "\uF340"; - public const string CcNd = "\uF343"; - public const string CcPd = "\uF344"; - public const string CcRemix = "\uF345"; - public const string CcSa = "\uF346"; - public const string CcShare = "\uF347"; - public const string CcZero = "\uF348"; - public const string ConwayGlider = "\uF349"; - public const string Csharp = "\uF34A"; - public const string EmailBulk = "\uF34B"; - public const string EmailBulkO = "\uF34C"; - public const string Gnu = "\uF34D"; - public const string GooglePlay = "\uF34E"; - public const string Heroku = "\uF34F"; - public const string HomeAssistant = "\uF350"; - public const string Java = "\uF351"; - public const string Mariadb = "\uF352"; - public const string Markdown = "\uF353"; - public const string Mysql = "\uF354"; - public const string Nordcast = "\uF355"; - public const string Plume = "\uF356"; - public const string Postgresql = "\uF357"; - public const string SassAlt = "\uF359"; - public const string Sass = "\uF358"; - public const string Skate = "\uF35A"; - public const string Sketchfab = "\uF35B"; - public const string Tex = "\uF35C"; - public const string Textpattern = "\uF35D"; - public const string Unity = "\uF35E"; - public const string Hedgedoc = "\uF360"; - public const string Fediverse = "\uF361"; - public const string Proftpd = "\uF362"; - public const string Osi = "\uF363"; - public const string Eyeem = "\uF364"; - public const string EyeemO = "\uF365"; - public const string Codeberg = "\uF366"; - public const string Discourse = "\uF367"; - public const string Mumble = "\uF368"; - public const string Freedesktop = "\uF369"; - public const string Javascript = "\uF370"; - public const string Lemmy = "\uF371"; - public const string Ipfs = "\uF372"; - public const string Canonical = "\uF36A"; - public const string Ubuntu = "\uF36B"; + public const char Glass = '\uF000'; + public const char Music = '\uF001'; + public const char Search = '\uF002'; + public const char EnvelopeO = '\uF003'; + public const char Heart = '\uF004'; + public const char Star = '\uF005'; + public const char StarO = '\uF006'; + public const char User = '\uF007'; + public const char Film = '\uF008'; + public const char ThLarge = '\uF009'; + public const char Th = '\uF00A'; + public const char ThList = '\uF00B'; + public const char Check = '\uF00C'; + public const char Times = '\uF00D'; + public const char SearchPlus = '\uF00E'; + public const char SearchMinus = '\uF010'; + public const char PowerOff = '\uF011'; + public const char Signal = '\uF012'; + public const char Cog = '\uF013'; + public const char TrashO = '\uF014'; + public const char Home = '\uF015'; + public const char FileO = '\uF016'; + public const char ClockO = '\uF017'; + public const char Road = '\uF018'; + public const char Download = '\uF019'; + public const char ArrowCircleODown = '\uF01A'; + public const char ArrowCircleOUp = '\uF01B'; + public const char Inbox = '\uF01C'; + public const char PlayCircleO = '\uF01D'; + public const char Repeat = '\uF01E'; + public const char Refresh = '\uF021'; + public const char ListAlt = '\uF022'; + public const char Lock = '\uF023'; + public const char Flag = '\uF024'; + public const char Headphones = '\uF025'; + public const char VolumeOff = '\uF026'; + public const char VolumeDown = '\uF027'; + public const char VolumeUp = '\uF028'; + public const char Qrcode = '\uF029'; + public const char Barcode = '\uF02A'; + public const char Tag = '\uF02B'; + public const char Tags = '\uF02C'; + public const char Book = '\uF02D'; + public const char Bookmark = '\uF02E'; + public const char Print = '\uF02F'; + public const char Camera = '\uF030'; + public const char Font = '\uF031'; + public const char Bold = '\uF032'; + public const char Italic = '\uF033'; + public const char TextHeight = '\uF034'; + public const char TextWidth = '\uF035'; + public const char AlignLeft = '\uF036'; + public const char AlignCenter = '\uF037'; + public const char AlignRight = '\uF038'; + public const char AlignJustify = '\uF039'; + public const char List = '\uF03A'; + public const char Outdent = '\uF03B'; + public const char Indent = '\uF03C'; + public const char VideoCamera = '\uF03D'; + public const char PictureO = '\uF03E'; + public const char Pencil = '\uF040'; + public const char MapMarker = '\uF041'; + public const char Adjust = '\uF042'; + public const char Tint = '\uF043'; + public const char PencilSquareO = '\uF044'; + public const char ShareSquareO = '\uF045'; + public const char CheckSquareO = '\uF046'; + public const char Arrows = '\uF047'; + public const char StepBackward = '\uF048'; + public const char FastBackward = '\uF049'; + public const char Backward = '\uF04A'; + public const char Play = '\uF04B'; + public const char Pause = '\uF04C'; + public const char Stop = '\uF04D'; + public const char Forward = '\uF04E'; + public const char FastForward = '\uF050'; + public const char StepForward = '\uF051'; + public const char Eject = '\uF052'; + public const char ChevronLeft = '\uF053'; + public const char ChevronRight = '\uF054'; + public const char PlusCircle = '\uF055'; + public const char MinusCircle = '\uF056'; + public const char TimesCircle = '\uF057'; + public const char CheckCircle = '\uF058'; + public const char QuestionCircle = '\uF059'; + public const char InfoCircle = '\uF05A'; + public const char Crosshairs = '\uF05B'; + public const char TimesCircleO = '\uF05C'; + public const char CheckCircleO = '\uF05D'; + public const char Ban = '\uF05E'; + public const char ArrowLeft = '\uF060'; + public const char ArrowRight = '\uF061'; + public const char ArrowUp = '\uF062'; + public const char ArrowDown = '\uF063'; + public const char Share = '\uF064'; + public const char Expand = '\uF065'; + public const char Compress = '\uF066'; + public const char Plus = '\uF067'; + public const char Minus = '\uF068'; + public const char Asterisk = '\uF069'; + public const char ExclamationCircle = '\uF06A'; + public const char Gift = '\uF06B'; + public const char Leaf = '\uF06C'; + public const char Fire = '\uF06D'; + public const char Eye = '\uF06E'; + public const char EyeSlash = '\uF070'; + public const char ExclamationTriangle = '\uF071'; + public const char Plane = '\uF072'; + public const char Calendar = '\uF073'; + public const char Random = '\uF074'; + public const char Comment = '\uF075'; + public const char Magnet = '\uF076'; + public const char ChevronUp = '\uF077'; + public const char ChevronDown = '\uF078'; + public const char Retweet = '\uF079'; + public const char ShoppingCart = '\uF07A'; + public const char Folder = '\uF07B'; + public const char FolderOpen = '\uF07C'; + public const char ArrowsV = '\uF07D'; + public const char ArrowsH = '\uF07E'; + public const char BarChart = '\uF080'; + public const char TwitterSquare = '\uF081'; + public const char FacebookSquare = '\uF082'; + public const char CameraRetro = '\uF083'; + public const char Key = '\uF084'; + public const char Cogs = '\uF085'; + public const char Comments = '\uF086'; + public const char ThumbsOUp = '\uF087'; + public const char ThumbsODown = '\uF088'; + public const char StarHalf = '\uF089'; + public const char HeartO = '\uF08A'; + public const char SignOut = '\uF08B'; + public const char LinkedinSquare = '\uF08C'; + public const char ThumbTack = '\uF08D'; + public const char ExternalLink = '\uF08E'; + public const char SignIn = '\uF090'; + public const char Trophy = '\uF091'; + public const char GithubSquare = '\uF092'; + public const char Upload = '\uF093'; + public const char LemonO = '\uF094'; + public const char Phone = '\uF095'; + public const char SquareO = '\uF096'; + public const char BookmarkO = '\uF097'; + public const char PhoneSquare = '\uF098'; + public const char Twitter = '\uF099'; + public const char Facebook = '\uF09A'; + public const char Github = '\uF09B'; + public const char Unlock = '\uF09C'; + public const char CreditCard = '\uF09D'; + public const char Rss = '\uF09E'; + public const char HddO = '\uF0A0'; + public const char Bullhorn = '\uF0A1'; + public const char BellO = '\uF0F3'; + public const char Certificate = '\uF0A3'; + public const char HandORight = '\uF0A4'; + public const char HandOLeft = '\uF0A5'; + public const char HandOUp = '\uF0A6'; + public const char HandODown = '\uF0A7'; + public const char ArrowCircleLeft = '\uF0A8'; + public const char ArrowCircleRight = '\uF0A9'; + public const char ArrowCircleUp = '\uF0AA'; + public const char ArrowCircleDown = '\uF0AB'; + public const char Globe = '\uF0AC'; + public const char GlobeE = '\uF304'; + public const char GlobeW = '\uF305'; + public const char Wrench = '\uF0AD'; + public const char Tasks = '\uF0AE'; + public const char Filter = '\uF0B0'; + public const char Briefcase = '\uF0B1'; + public const char ArrowsAlt = '\uF0B2'; + public const char Users = '\uF0C0'; + public const char Link = '\uF0C1'; + public const char Cloud = '\uF0C2'; + public const char Flask = '\uF0C3'; + public const char Scissors = '\uF0C4'; + public const char FilesO = '\uF0C5'; + public const char Paperclip = '\uF0C6'; + public const char FloppyO = '\uF0C7'; + public const char Square = '\uF0C8'; + public const char Bars = '\uF0C9'; + public const char ListUl = '\uF0CA'; + public const char ListOl = '\uF0CB'; + public const char Strikethrough = '\uF0CC'; + public const char Underline = '\uF0CD'; + public const char Table = '\uF0CE'; + public const char Magic = '\uF0D0'; + public const char Truck = '\uF0D1'; + public const char Pinterest = '\uF0D2'; + public const char PinterestSquare = '\uF0D3'; + public const char GooglePlusSquare = '\uF0D4'; + public const char GooglePlus = '\uF0D5'; + public const char Money = '\uF0D6'; + public const char CaretDown = '\uF0D7'; + public const char CaretUp = '\uF0D8'; + public const char CaretLeft = '\uF0D9'; + public const char CaretRight = '\uF0DA'; + public const char Columns = '\uF0DB'; + public const char Sort = '\uF0DC'; + public const char SortDesc = '\uF0DD'; + public const char SortAsc = '\uF0DE'; + public const char Envelope = '\uF0E0'; + public const char Linkedin = '\uF0E1'; + public const char Undo = '\uF0E2'; + public const char Gavel = '\uF0E3'; + public const char Tachometer = '\uF0E4'; + public const char CommentO = '\uF0E5'; + public const char CommentsO = '\uF0E6'; + public const char Bolt = '\uF0E7'; + public const char Sitemap = '\uF0E8'; + public const char Umbrella = '\uF0E9'; + public const char Clipboard = '\uF0EA'; + public const char LightbulbO = '\uF0EB'; + public const char Exchange = '\uF0EC'; + public const char CloudDownload = '\uF0ED'; + public const char CloudUpload = '\uF0EE'; + public const char UserMd = '\uF0F0'; + public const char Stethoscope = '\uF0F1'; + public const char Suitcase = '\uF0F2'; + public const char Bell = '\uF0A2'; + public const char Coffee = '\uF0F4'; + public const char Cutlery = '\uF0F5'; + public const char FileTextO = '\uF0F6'; + public const char BuildingO = '\uF0F7'; + public const char HospitalO = '\uF0F8'; + public const char Ambulance = '\uF0F9'; + public const char Medkit = '\uF0FA'; + public const char FighterJet = '\uF0FB'; + public const char Beer = '\uF0FC'; + public const char HSquare = '\uF0FD'; + public const char PlusSquare = '\uF0FE'; + public const char AngleDoubleLeft = '\uF100'; + public const char AngleDoubleRight = '\uF101'; + public const char AngleDoubleUp = '\uF102'; + public const char AngleDoubleDown = '\uF103'; + public const char AngleLeft = '\uF104'; + public const char AngleRight = '\uF105'; + public const char AngleUp = '\uF106'; + public const char AngleDown = '\uF107'; + public const char Desktop = '\uF108'; + public const char Laptop = '\uF109'; + public const char Tablet = '\uF10A'; + public const char Mobile = '\uF10B'; + public const char CircleO = '\uF10C'; + public const char QuoteLeft = '\uF10D'; + public const char QuoteRight = '\uF10E'; + public const char Spinner = '\uF110'; + public const char Circle = '\uF111'; + public const char Reply = '\uF112'; + public const char GithubAlt = '\uF113'; + public const char FolderO = '\uF114'; + public const char FolderOpenO = '\uF115'; + public const char SmileO = '\uF118'; + public const char FrownO = '\uF119'; + public const char MehO = '\uF11A'; + public const char Gamepad = '\uF11B'; + public const char KeyboardO = '\uF11C'; + public const char FlagO = '\uF11D'; + public const char FlagCheckered = '\uF11E'; + public const char Terminal = '\uF120'; + public const char Code = '\uF121'; + public const char ReplyAll = '\uF122'; + public const char StarHalfO = '\uF123'; + public const char LocationArrow = '\uF124'; + public const char Crop = '\uF125'; + public const char CodeFork = '\uF126'; + public const char ChainBroken = '\uF127'; + public const char Question = '\uF128'; + public const char Info = '\uF129'; + public const char Exclamation = '\uF12A'; + public const char Superscript = '\uF12B'; + public const char Subscript = '\uF12C'; + public const char Eraser = '\uF12D'; + public const char PuzzlePiece = '\uF12E'; + public const char Microphone = '\uF130'; + public const char MicrophoneSlash = '\uF131'; + public const char Shield = '\uF132'; + public const char CalendarO = '\uF133'; + public const char FireExtinguisher = '\uF134'; + public const char Rocket = '\uF135'; + public const char Maxcdn = '\uF136'; + public const char ChevronCircleLeft = '\uF137'; + public const char ChevronCircleRight = '\uF138'; + public const char ChevronCircleUp = '\uF139'; + public const char ChevronCircleDown = '\uF13A'; + public const char Html5 = '\uF13B'; + public const char Css3 = '\uF13C'; + public const char Anchor = '\uF13D'; + public const char UnlockAlt = '\uF13E'; + public const char Bullseye = '\uF140'; + public const char EllipsisH = '\uF141'; + public const char EllipsisV = '\uF142'; + public const char RssSquare = '\uF143'; + public const char PlayCircle = '\uF144'; + public const char Ticket = '\uF145'; + public const char MinusSquare = '\uF146'; + public const char MinusSquareO = '\uF147'; + public const char LevelUp = '\uF148'; + public const char LevelDown = '\uF149'; + public const char CheckSquare = '\uF14A'; + public const char PencilSquare = '\uF14B'; + public const char ExternalLinkSquare = '\uF14C'; + public const char ShareSquare = '\uF14D'; + public const char Compass = '\uF14E'; + public const char CaretSquareODown = '\uF150'; + public const char CaretSquareOUp = '\uF151'; + public const char CaretSquareORight = '\uF152'; + public const char Eur = '\uF153'; + public const char Gbp = '\uF154'; + public const char Usd = '\uF155'; + public const char Inr = '\uF156'; + public const char Jpy = '\uF157'; + public const char Rub = '\uF158'; + public const char Krw = '\uF159'; + public const char Btc = '\uF15A'; + public const char File = '\uF15B'; + public const char FileText = '\uF15C'; + public const char SortAlphaAsc = '\uF15D'; + public const char SortAlphaDesc = '\uF15E'; + public const char SortAmountAsc = '\uF160'; + public const char SortAmountDesc = '\uF161'; + public const char SortNumericAsc = '\uF162'; + public const char SortNumericDesc = '\uF163'; + public const char ThumbsUp = '\uF164'; + public const char ThumbsDown = '\uF165'; + public const char YoutubeSquare = '\uF166'; + public const char Youtube = '\uF167'; + public const char Xing = '\uF168'; + public const char XingSquare = '\uF169'; + public const char YoutubePlay = '\uF16A'; + public const char Dropbox = '\uF16B'; + public const char StackOverflow = '\uF16C'; + public const char Instagram = '\uF16D'; + public const char Flickr = '\uF16E'; + public const char Adn = '\uF170'; + public const char Bitbucket = '\uF171'; + public const char BitbucketSquare = '\uF172'; + public const char Tumblr = '\uF173'; + public const char TumblrSquare = '\uF174'; + public const char LongArrowDown = '\uF175'; + public const char LongArrowUp = '\uF176'; + public const char LongArrowLeft = '\uF177'; + public const char LongArrowRight = '\uF178'; + public const char Apple = '\uF179'; + public const char Windows = '\uF17A'; + public const char Android = '\uF17B'; + public const char Linux = '\uF17C'; + public const char Dribbble = '\uF17D'; + public const char Skype = '\uF17E'; + public const char Foursquare = '\uF180'; + public const char Trello = '\uF181'; + public const char Female = '\uF182'; + public const char Male = '\uF183'; + public const char Gratipay = '\uF184'; + public const char SunO = '\uF185'; + public const char MoonO = '\uF186'; + public const char Archive = '\uF187'; + public const char Bug = '\uF188'; + public const char Vk = '\uF189'; + public const char Weibo = '\uF18A'; + public const char Renren = '\uF18B'; + public const char Pagelines = '\uF18C'; + public const char StackExchange = '\uF18D'; + public const char ArrowCircleORight = '\uF18E'; + public const char ArrowCircleOLeft = '\uF190'; + public const char CaretSquareOLeft = '\uF191'; + public const char DotCircleO = '\uF192'; + public const char Wheelchair = '\uF193'; + public const char VimeoSquare = '\uF194'; + public const char Try = '\uF195'; + public const char PlusSquareO = '\uF196'; + public const char SpaceShuttle = '\uF197'; + public const char Slack = '\uF198'; + public const char EnvelopeSquare = '\uF199'; + public const char Wordpress = '\uF19A'; + public const char Openid = '\uF19B'; + public const char University = '\uF19C'; + public const char GraduationCap = '\uF19D'; + public const char Yahoo = '\uF19E'; + public const char Google = '\uF1A0'; + public const char Reddit = '\uF1A1'; + public const char RedditSquare = '\uF1A2'; + public const char StumbleuponCircle = '\uF1A3'; + public const char Stumbleupon = '\uF1A4'; + public const char Delicious = '\uF1A5'; + public const char Digg = '\uF1A6'; + public const char Drupal = '\uF1A9'; + public const char Joomla = '\uF1AA'; + public const char Language = '\uF1AB'; + public const char Fax = '\uF1AC'; + public const char Building = '\uF1AD'; + public const char Child = '\uF1AE'; + public const char Paw = '\uF1B0'; + public const char Spoon = '\uF1B1'; + public const char Cube = '\uF1B2'; + public const char Cubes = '\uF1B3'; + public const char Behance = '\uF1B4'; + public const char BehanceSquare = '\uF1B5'; + public const char Steam = '\uF1B6'; + public const char SteamSquare = '\uF1B7'; + public const char Recycle = '\uF1B8'; + public const char Car = '\uF1B9'; + public const char Taxi = '\uF1BA'; + public const char Tree = '\uF1BB'; + public const char Spotify = '\uF1BC'; + public const char Deviantart = '\uF1BD'; + public const char Soundcloud = '\uF1BE'; + public const char Database = '\uF1C0'; + public const char FilePdfO = '\uF1C1'; + public const char FileWordO = '\uF1C2'; + public const char FileExcelO = '\uF1C3'; + public const char FilePowerpointO = '\uF1C4'; + public const char FileImageO = '\uF1C5'; + public const char FileArchiveO = '\uF1C6'; + public const char FileAudioO = '\uF1C7'; + public const char FileVideoO = '\uF1C8'; + public const char FileCodeO = '\uF1C9'; + public const char Vine = '\uF1CA'; + public const char Codepen = '\uF1CB'; + public const char Jsfiddle = '\uF1CC'; + public const char LifeRing = '\uF1CD'; + public const char CircleONotch = '\uF1CE'; + public const char Rebel = '\uF1D0'; + public const char Empire = '\uF1D1'; + public const char GitSquare = '\uF1D2'; + public const char Git = '\uF1D3'; + public const char HackerNews = '\uF1D4'; + public const char TencentWeibo = '\uF1D5'; + public const char Qq = '\uF1D6'; + public const char Weixin = '\uF1D7'; + public const char PaperPlane = '\uF1D8'; + public const char PaperPlaneO = '\uF1D9'; + public const char History = '\uF1DA'; + public const char CircleThin = '\uF1DB'; + public const char Header = '\uF1DC'; + public const char Paragraph = '\uF1DD'; + public const char Sliders = '\uF1DE'; + public const char ShareAlt = '\uF1E0'; + public const char ShareAltSquare = '\uF1E1'; + public const char Bomb = '\uF1E2'; + public const char FutbolO = '\uF1E3'; + public const char Tty = '\uF1E4'; + public const char Binoculars = '\uF1E5'; + public const char Plug = '\uF1E6'; + public const char Slideshare = '\uF1E7'; + public const char Twitch = '\uF1E8'; + public const char Yelp = '\uF1E9'; + public const char NewspaperO = '\uF1EA'; + public const char Wifi = '\uF1EB'; + public const char Calculator = '\uF1EC'; + public const char Paypal = '\uF1ED'; + public const char GoogleWallet = '\uF1EE'; + public const char CcVisa = '\uF1F0'; + public const char CcMastercard = '\uF1F1'; + public const char CcDiscover = '\uF1F2'; + public const char CcAmex = '\uF1F3'; + public const char CcPaypal = '\uF1F4'; + public const char CcStripe = '\uF1F5'; + public const char BellSlash = '\uF1F6'; + public const char BellSlashO = '\uF1F7'; + public const char Trash = '\uF1F8'; + public const char Copyright = '\uF1F9'; + public const char At = '\uF1FA'; + public const char Eyedropper = '\uF1FB'; + public const char PaintBrush = '\uF1FC'; + public const char BirthdayCake = '\uF1FD'; + public const char AreaChart = '\uF1FE'; + public const char PieChart = '\uF200'; + public const char LineChart = '\uF201'; + public const char Lastfm = '\uF202'; + public const char LastfmSquare = '\uF203'; + public const char ToggleOff = '\uF204'; + public const char ToggleOn = '\uF205'; + public const char Bicycle = '\uF206'; + public const char Bus = '\uF207'; + public const char Ioxhost = '\uF208'; + public const char Angellist = '\uF209'; + public const char Cc = '\uF20A'; + public const char Ils = '\uF20B'; + public const char Meanpath = '\uF20C'; + public const char Buysellads = '\uF20D'; + public const char Connectdevelop = '\uF20E'; + public const char Dashcube = '\uF210'; + public const char Forumbee = '\uF211'; + public const char Leanpub = '\uF212'; + public const char Sellsy = '\uF213'; + public const char Shirtsinbulk = '\uF214'; + public const char Simplybuilt = '\uF215'; + public const char Skyatlas = '\uF216'; + public const char CartPlus = '\uF217'; + public const char CartArrowDown = '\uF218'; + public const char Diamond = '\uF219'; + public const char Ship = '\uF21A'; + public const char UserSecret = '\uF21B'; + public const char Motorcycle = '\uF21C'; + public const char StreetView = '\uF21D'; + public const char Heartbeat = '\uF21E'; + public const char Venus = '\uF221'; + public const char Mars = '\uF222'; + public const char Mercury = '\uF223'; + public const char Transgender = '\uF224'; + public const char TransgenderAlt = '\uF225'; + public const char VenusDouble = '\uF226'; + public const char MarsDouble = '\uF227'; + public const char VenusMars = '\uF228'; + public const char MarsStroke = '\uF229'; + public const char MarsStrokeV = '\uF22A'; + public const char MarsStrokeH = '\uF22B'; + public const char Neuter = '\uF22C'; + public const char Genderless = '\uF22D'; + public const char FacebookOfficial = '\uF230'; + public const char PinterestP = '\uF231'; + public const char Whatsapp = '\uF232'; + public const char Server = '\uF233'; + public const char UserPlus = '\uF234'; + public const char UserTimes = '\uF235'; + public const char Bed = '\uF236'; + public const char Viacoin = '\uF237'; + public const char Train = '\uF238'; + public const char Subway = '\uF239'; + public const char Medium = '\uF23A'; + public const char MediumSquare = '\uF2F8'; + public const char YCombinator = '\uF23B'; + public const char OptinMonster = '\uF23C'; + public const char Opencart = '\uF23D'; + public const char Expeditedssl = '\uF23E'; + public const char BatteryFull = '\uF240'; + public const char BatteryThreeQuarters = '\uF241'; + public const char BatteryHalf = '\uF242'; + public const char BatteryQuarter = '\uF243'; + public const char BatteryEmpty = '\uF244'; + public const char MousePointer = '\uF245'; + public const char ICursor = '\uF246'; + public const char ObjectGroup = '\uF247'; + public const char ObjectUngroup = '\uF248'; + public const char StickyNote = '\uF249'; + public const char StickyNoteO = '\uF24A'; + public const char CcJcb = '\uF24B'; + public const char CcDinersClub = '\uF24C'; + public const char Clone = '\uF24D'; + public const char BalanceScale = '\uF24E'; + public const char HourglassO = '\uF250'; + public const char HourglassStart = '\uF251'; + public const char HourglassHalf = '\uF252'; + public const char HourglassEnd = '\uF253'; + public const char Hourglass = '\uF254'; + public const char HandRockO = '\uF255'; + public const char HandPaperO = '\uF256'; + public const char HandScissorsO = '\uF257'; + public const char HandLizardO = '\uF258'; + public const char HandSpockO = '\uF259'; + public const char HandPointerO = '\uF25A'; + public const char HandPeaceO = '\uF25B'; + public const char Trademark = '\uF25C'; + public const char Registered = '\uF25D'; + public const char CreativeCommons = '\uF25E'; + public const char Gg = '\uF260'; + public const char GgCircle = '\uF261'; + public const char Tripadvisor = '\uF262'; + public const char Odnoklassniki = '\uF263'; + public const char OdnoklassnikiSquare = '\uF264'; + public const char GetPocket = '\uF265'; + public const char WikipediaW = '\uF266'; + public const char Safari = '\uF267'; + public const char Chrome = '\uF268'; + public const char Firefox = '\uF269'; + public const char Opera = '\uF26A'; + public const char InternetExplorer = '\uF26B'; + public const char Television = '\uF26C'; + public const char Contao = '\uF26D'; + public const char Num500px = '\uF26E'; + public const char Amazon = '\uF270'; + public const char CalendarPlusO = '\uF271'; + public const char CalendarMinusO = '\uF272'; + public const char CalendarTimesO = '\uF273'; + public const char CalendarCheckO = '\uF274'; + public const char Industry = '\uF275'; + public const char MapPin = '\uF276'; + public const char MapSigns = '\uF277'; + public const char MapO = '\uF278'; + public const char Map = '\uF279'; + public const char Commenting = '\uF27A'; + public const char CommentingO = '\uF27B'; + public const char Houzz = '\uF27C'; + public const char Vimeo = '\uF27D'; + public const char BlackTie = '\uF27E'; + public const char Fonticons = '\uF280'; + public const char RedditAlien = '\uF281'; + public const char Edge = '\uF282'; + public const char CreditCardAlt = '\uF283'; + public const char Codiepie = '\uF284'; + public const char Modx = '\uF285'; + public const char FortAwesome = '\uF286'; + public const char Usb = '\uF287'; + public const char ProductHunt = '\uF288'; + public const char Mixcloud = '\uF289'; + public const char Scribd = '\uF28A'; + public const char PauseCircle = '\uF28B'; + public const char PauseCircleO = '\uF28C'; + public const char StopCircle = '\uF28D'; + public const char StopCircleO = '\uF28E'; + public const char ShoppingBag = '\uF290'; + public const char ShoppingBasket = '\uF291'; + public const char Hashtag = '\uF292'; + public const char Bluetooth = '\uF293'; + public const char BluetoothB = '\uF294'; + public const char Percent = '\uF295'; + public const char Gitlab = '\uF296'; + public const char Wpbeginner = '\uF297'; + public const char Wpforms = '\uF298'; + public const char Envira = '\uF299'; + public const char UniversalAccess = '\uF29A'; + public const char WheelchairAlt = '\uF29B'; + public const char QuestionCircleO = '\uF29C'; + public const char Blind = '\uF29D'; + public const char AudioDescription = '\uF29E'; + public const char VolumeControlPhone = '\uF2A0'; + public const char Braille = '\uF2A1'; + public const char AssistiveListeningSystems = '\uF2A2'; + public const char AmericanSignLanguageInterpreting = '\uF2A3'; + public const char Deaf = '\uF2A4'; + public const char Glide = '\uF2A5'; + public const char GlideG = '\uF2A6'; + public const char SignLanguage = '\uF2A7'; + public const char LowVision = '\uF2A8'; + public const char Viadeo = '\uF2A9'; + public const char ViadeoSquare = '\uF2AA'; + public const char Snapchat = '\uF2AB'; + public const char SnapchatGhost = '\uF2AC'; + public const char SnapchatSquare = '\uF2AD'; + public const char FirstOrder = '\uF2B0'; + public const char Yoast = '\uF2B1'; + public const char Themeisle = '\uF2B2'; + public const char GooglePlusOfficial = '\uF2B3'; + public const char FontAwesome = '\uF2B4'; + public const char HandshakeO = '\uF2B5'; + public const char EnvelopeOpen = '\uF2B6'; + public const char EnvelopeOpenO = '\uF2B7'; + public const char Linode = '\uF2B8'; + public const char AddressBook = '\uF2B9'; + public const char AddressBookO = '\uF2BA'; + public const char AddressCard = '\uF2BB'; + public const char AddressCardO = '\uF2BC'; + public const char UserCircle = '\uF2BD'; + public const char UserCircleO = '\uF2BE'; + public const char UserO = '\uF2C0'; + public const char IdBadge = '\uF2C1'; + public const char IdCard = '\uF2C2'; + public const char IdCardO = '\uF2C3'; + public const char Quora = '\uF2C4'; + public const char FreeCodeCamp = '\uF2C5'; + public const char Telegram = '\uF2C6'; + public const char ThermometerFull = '\uF2C7'; + public const char ThermometerThreeQuarters = '\uF2C8'; + public const char ThermometerHalf = '\uF2C9'; + public const char ThermometerQuarter = '\uF2CA'; + public const char ThermometerEmpty = '\uF2CB'; + public const char Shower = '\uF2CC'; + public const char Bath = '\uF2CD'; + public const char Podcast = '\uF2CE'; + public const char WindowMaximize = '\uF2D0'; + public const char WindowMinimize = '\uF2D1'; + public const char WindowRestore = '\uF2D2'; + public const char WindowClose = '\uF2D3'; + public const char WindowCloseO = '\uF2D4'; + public const char Bandcamp = '\uF2D5'; + public const char Grav = '\uF2D6'; + public const char Etsy = '\uF2D7'; + public const char Imdb = '\uF2D8'; + public const char Ravelry = '\uF2D9'; + public const char Eercast = '\uF2DA'; + public const char Microchip = '\uF2DB'; + public const char SnowflakeO = '\uF2DC'; + public const char Superpowers = '\uF2DD'; + public const char Wpexplorer = '\uF2DE'; + public const char Meetup = '\uF2E0'; + public const char Mastodon = '\uF2E1'; + public const char MastodonAlt = '\uF2E2'; + public const char ForkAwesomeIcon = '\uF2E3'; + public const char Peertube = '\uF2E4'; + public const char Diaspora = '\uF2E5'; + public const char Friendica = '\uF2E6'; + public const char GnuSocial = '\uF2E7'; + public const char LiberapaySquare = '\uF2E8'; + public const char Liberapay = '\uF2E9'; + public const char Scuttlebutt = '\uF2EA'; + public const char Hubzilla = '\uF2EB'; + public const char SocialHome = '\uF2EC'; + public const char Artstation = '\uF2ED'; + public const char Discord = '\uF2EE'; + public const char DiscordAlt = '\uF2EF'; + public const char Patreon = '\uF2F0'; + public const char Snowdrift = '\uF2F1'; + public const char Activitypub = '\uF2F2'; + public const char Ethereum = '\uF2F3'; + public const char Keybase = '\uF2F4'; + public const char Shaarli = '\uF2F5'; + public const char ShaarliO = '\uF2F6'; + public const char KeyModern = '\uF2F7'; + public const char Xmpp = '\uF2F9'; + public const char ArchiveOrg = '\uF2FC'; + public const char Freedombox = '\uF2FD'; + public const char FacebookMessenger = '\uF2FE'; + public const char Debian = '\uF2FF'; + public const char MastodonSquare = '\uF300'; + public const char Tipeee = '\uF301'; + public const char React = '\uF302'; + public const char Dogmazic = '\uF303'; + public const char Zotero = '\uF309'; + public const char Nodejs = '\uF308'; + public const char Nextcloud = '\uF306'; + public const char NextcloudSquare = '\uF307'; + public const char Hackaday = '\uF30A'; + public const char Laravel = '\uF30B'; + public const char Signalapp = '\uF30C'; + public const char Gnupg = '\uF30D'; + public const char Php = '\uF30E'; + public const char Ffmpeg = '\uF30F'; + public const char Joplin = '\uF310'; + public const char Syncthing = '\uF311'; + public const char Inkscape = '\uF312'; + public const char MatrixOrg = '\uF313'; + public const char Pixelfed = '\uF314'; + public const char Bootstrap = '\uF315'; + public const char DevTo = '\uF316'; + public const char Hashnode = '\uF317'; + public const char Jirafeau = '\uF318'; + public const char Emby = '\uF319'; + public const char Wikidata = '\uF31A'; + public const char Gimp = '\uF31B'; + public const char C = '\uF31C'; + public const char Digitalocean = '\uF31D'; + public const char Att = '\uF31E'; + public const char Gitea = '\uF31F'; + public const char FileEpub = '\uF321'; + public const char Python = '\uF322'; + public const char Archlinux = '\uF323'; + public const char Pleroma = '\uF324'; + public const char Unsplash = '\uF325'; + public const char Hackster = '\uF326'; + public const char SpellCheck = '\uF327'; + public const char Moon = '\uF328'; + public const char Sun = '\uF329'; + public const char FDroid = '\uF32A'; + public const char Biometric = '\uF32B'; + public const char Wire = '\uF32C'; + public const char TorOnion = '\uF32E'; + public const char VolumeMute = '\uF32F'; + public const char BellRinging = '\uF32D'; + public const char BellRingingO = '\uF330'; + public const char Hal = '\uF333'; + public const char Jupyter = '\uF335'; + public const char Julia = '\uF334'; + public const char Classicpress = '\uF331'; + public const char ClassicpressCircle = '\uF332'; + public const char OpenCollective = '\uF336'; + public const char Orcid = '\uF337'; + public const char Researchgate = '\uF338'; + public const char Funkwhale = '\uF339'; + public const char Askfm = '\uF33A'; + public const char Blockstack = '\uF33B'; + public const char Boardgamegeek = '\uF33C'; + public const char Bunny = '\uF35F'; + public const char Buymeacoffee = '\uF33D'; + public const char CcBy = '\uF33E'; + public const char CcCc = '\uF33F'; + public const char CcNcEu = '\uF341'; + public const char CcNcJp = '\uF342'; + public const char CcNc = '\uF340'; + public const char CcNd = '\uF343'; + public const char CcPd = '\uF344'; + public const char CcRemix = '\uF345'; + public const char CcSa = '\uF346'; + public const char CcShare = '\uF347'; + public const char CcZero = '\uF348'; + public const char ConwayGlider = '\uF349'; + public const char Csharp = '\uF34A'; + public const char EmailBulk = '\uF34B'; + public const char EmailBulkO = '\uF34C'; + public const char Gnu = '\uF34D'; + public const char GooglePlay = '\uF34E'; + public const char Heroku = '\uF34F'; + public const char HomeAssistant = '\uF350'; + public const char Java = '\uF351'; + public const char Mariadb = '\uF352'; + public const char Markdown = '\uF353'; + public const char Mysql = '\uF354'; + public const char Nordcast = '\uF355'; + public const char Plume = '\uF356'; + public const char Postgresql = '\uF357'; + public const char SassAlt = '\uF359'; + public const char Sass = '\uF358'; + public const char Skate = '\uF35A'; + public const char Sketchfab = '\uF35B'; + public const char Tex = '\uF35C'; + public const char Textpattern = '\uF35D'; + public const char Unity = '\uF35E'; + public const char Hedgedoc = '\uF360'; + public const char Fediverse = '\uF361'; + public const char Proftpd = '\uF362'; + public const char Osi = '\uF363'; + public const char Eyeem = '\uF364'; + public const char EyeemO = '\uF365'; + public const char Codeberg = '\uF366'; + public const char Discourse = '\uF367'; + public const char Mumble = '\uF368'; + public const char Freedesktop = '\uF369'; + public const char Javascript = '\uF370'; + public const char Lemmy = '\uF371'; + public const char Ipfs = '\uF372'; + public const char Canonical = '\uF36A'; + public const char Ubuntu = '\uF36B'; } diff --git a/src/gaemstone.Client/Utility/ImGuiUtility.cs b/src/gaemstone.Client/Utility/ImGuiUtility.cs index 92f5283..6bb7ef0 100644 --- a/src/gaemstone.Client/Utility/ImGuiUtility.cs +++ b/src/gaemstone.Client/Utility/ImGuiUtility.cs @@ -6,8 +6,13 @@ namespace gaemstone.Client.Utility; public static class ImGuiUtility { + public static bool UIButtonToggle(int index, char icon, string tooltip, ref bool enabled) + => UIButtonToggle(index, icon.ToString(), tooltip, ref enabled); public static bool UIButtonToggle(int index, string label, string tooltip, ref bool enabled) { if (UIButton(index, label, tooltip, enabled)) enabled = !enabled; return enabled; } + + public static bool UIButton(int index, char icon, string tooltip, bool active) + => UIButton(index, icon.ToString(), tooltip, active); public static bool UIButton(int index, string label, string tooltip, bool active) { var start = new Vector2(4, 4); diff --git a/src/gaemstone.ECS b/src/gaemstone.ECS index c575046..063fb40 160000 --- a/src/gaemstone.ECS +++ b/src/gaemstone.ECS @@ -1 +1 @@ -Subproject commit c575046a61620434e7ee01679ce86bf0beb0f700 +Subproject commit 063fb40c5c56adbd5bedd39045f1b896b4e420c3 diff --git a/src/gaemstone.SourceGen/ModuleGenerator.cs b/src/gaemstone.SourceGen/ModuleGenerator.cs index af13570..76b52d7 100644 --- a/src/gaemstone.SourceGen/ModuleGenerator.cs +++ b/src/gaemstone.SourceGen/ModuleGenerator.cs @@ -120,7 +120,7 @@ public class ModuleGenerator sb.AppendLine(); sb.AppendLine($$""" - static void IModule.Initialize(Entity module) + static void IModule.OnEnable(Entity module) { var world = module.World; """); @@ -134,12 +134,25 @@ public class ModuleGenerator // TODO: Can BuiltIn modules have systems and such? - if (module.HasInitializer) - sb.AppendLine("\t\tInitialize(module);"); + if (module.HasLifetimeInterface) + sb.AppendLine("\t\tOnEnabled(module);"); - sb.AppendLine("\t}"); + sb.AppendLine($$""" + } + + static void IModule.OnDisable(Entity module) + { + """); - sb.AppendLine("}"); + if (module.IsBuiltIn) + sb.AppendLine("\t\tthrow new global::System.InvalidOperationException();"); + if (module.HasLifetimeInterface) + sb.AppendLine("\t\tOnDisabled(module);"); + + sb.AppendLine($$""" + } + } + """); } private void AppendEntityRegistration( diff --git a/src/gaemstone.SourceGen/Structure/MethodEntityInfo.cs b/src/gaemstone.SourceGen/Structure/MethodEntityInfo.cs index e9e1e85..b59400c 100644 --- a/src/gaemstone.SourceGen/Structure/MethodEntityInfo.cs +++ b/src/gaemstone.SourceGen/Structure/MethodEntityInfo.cs @@ -88,7 +88,7 @@ public class MethodEntityInfo : BaseEntityInfo param.TermIndex = termIndex++; // See if we have any [DependsOn<...>] attributes for this system. - // If not, ModuleGenerator will add [DependsOn]. + // If not, ModuleGenerator will add [DependsOn]. HasPhaseSet = IsSystem && RelationsToAdd.Any(entry => entry.Relation .GetFullName(FullNameStyle.NoGeneric) == "gaemstone.ECS.DependsOnAttribute"); diff --git a/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs b/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs index 172f13e..025444f 100644 --- a/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs +++ b/src/gaemstone.SourceGen/Structure/ModuleEntityInfo.cs @@ -10,7 +10,7 @@ namespace gaemstone.SourceGen.Structure; public class ModuleEntityInfo : TypeEntityInfo { public bool IsPartial { get; } - public bool HasInitializer { get; } + public bool HasLifetimeInterface { get; } public ModuleEntityInfo(ISymbol symbol) : base(symbol) @@ -18,8 +18,8 @@ public class ModuleEntityInfo : TypeEntityInfo var classDecl = (TypeDeclarationSyntax)Symbol.DeclaringSyntaxReferences.First().GetSyntax(); IsPartial = classDecl.Modifiers.Any(t => t.IsKind(SyntaxKind.PartialKeyword)); - HasInitializer = Symbol.AllInterfaces.Any(i => - i.GetFullName(FullNameStyle.NoGeneric) == "gaemstone.ECS.IModuleInitializer"); + HasLifetimeInterface = Symbol.AllInterfaces.Any(i => + i.GetFullName(FullNameStyle.NoGeneric) == "gaemstone.ECS.IModuleLifetime"); IsBuiltIn = Has("BuiltIn"); } diff --git a/src/gaemstone/Doc.cs b/src/gaemstone/Doc.cs index 3e66ea2..1d85fdc 100644 --- a/src/gaemstone/Doc.cs +++ b/src/gaemstone/Doc.cs @@ -13,6 +13,14 @@ public partial class Doc [Tag] public struct Relation { } + /// + /// Tags are just s with 0 size. + /// This functions as a special entity that holds the appearance for tags. + /// Not related to in any way. + /// + [Tag] + public struct Tag { } + // TODO: These need to actually be read at some point. diff --git a/src/gaemstone/ECS/Module.cs b/src/gaemstone/ECS/Module.cs index f2dd52a..3240234 100644 --- a/src/gaemstone/ECS/Module.cs +++ b/src/gaemstone/ECS/Module.cs @@ -6,13 +6,27 @@ namespace gaemstone.ECS; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] public class ModuleAttribute : SingletonAttribute { } +public interface IModuleLifetime +{ + void OnEnable(Entity module); + + void OnDisable(Entity module); +} + + [AttributeUsage(AttributeTargets.Class)] public class BuiltInAttribute : Attribute { } +public interface IModuleImport +{ + static abstract Entity Import(World world); +} + /// /// A concrete implementation of this interface is generated by a source /// generator for each type marked as . +/// (Do not implement this yourself.) /// public interface IModule { @@ -22,10 +36,8 @@ public interface IModule static abstract IReadOnlyList Dependencies { get; } - static abstract void Initialize(Entity module); -} -public interface IModuleInitializer -{ - static abstract void Initialize(Entity module); + static abstract void OnEnable(Entity module); + + static abstract void OnDisable(Entity module); } diff --git a/src/gaemstone/Flecs/Core.cs b/src/gaemstone/Flecs/Core.cs index 649ebf7..6864683 100644 --- a/src/gaemstone/Flecs/Core.cs +++ b/src/gaemstone/Flecs/Core.cs @@ -4,6 +4,7 @@ namespace gaemstone.Flecs; [BuiltIn, Module, Path("/flecs/core")] public partial class Core + : IModuleImport { // Entity Tags @@ -105,4 +106,8 @@ public partial class Core public static implicit operator string?(Identifier id) => id.ToString(); } + + + static Entity IModuleImport.Import(World world) + => world.LookupPathOrThrow("/flecs/core"); } diff --git a/src/gaemstone/Flecs/CoreDoc.cs b/src/gaemstone/Flecs/CoreDoc.cs new file mode 100644 index 0000000..a541154 --- /dev/null +++ b/src/gaemstone/Flecs/CoreDoc.cs @@ -0,0 +1,25 @@ +using System.Runtime.InteropServices; +using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; + +namespace gaemstone.Flecs; + +[BuiltIn, Module, Path("/flecs/coredoc")] +[DependsOn] +[DependsOn] +public unsafe partial class CoreDoc + : IModuleImport +{ + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &CoreDocImport } }, + alloc.AllocateCString("FlecsCoreDoc")))); + } + + [UnmanagedCallersOnly] + private static void CoreDocImport(ecs_world_t* world) + => FlecsCoreDocImport(world); +} diff --git a/src/gaemstone/Flecs/Doc.cs b/src/gaemstone/Flecs/Doc.cs index 20b7464..8e83fd6 100644 --- a/src/gaemstone/Flecs/Doc.cs +++ b/src/gaemstone/Flecs/Doc.cs @@ -6,7 +6,8 @@ using static flecs_hub.flecs; namespace gaemstone.Flecs; [BuiltIn, Module, Path("/flecs/doc")] -public partial class Doc +public unsafe partial class Doc + : IModuleImport { [Tag] public struct Brief { } [Tag] public struct Detail { } @@ -23,6 +24,19 @@ public partial class Doc public static implicit operator string?(Description desc) => desc.ToString(); } + + + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &DocImport } }, + alloc.AllocateCString("FlecsDoc")))); + } + + [UnmanagedCallersOnly] + private static void DocImport(ecs_world_t* world) + => FlecsDocImport(world); } public static unsafe class DocExtensions diff --git a/src/gaemstone/Flecs/Meta.cs b/src/gaemstone/Flecs/Meta.cs new file mode 100644 index 0000000..8bd700f --- /dev/null +++ b/src/gaemstone/Flecs/Meta.cs @@ -0,0 +1,23 @@ +using System.Runtime.InteropServices; +using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; + +namespace gaemstone.Flecs; + +[BuiltIn, Module, Path("/flecs/meta")] +public unsafe partial class Meta + : IModuleImport +{ + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &MetaImport } }, + alloc.AllocateCString("FlecsMeta")))); + } + + [UnmanagedCallersOnly] + private static void MetaImport(ecs_world_t* world) + => FlecsMetaImport(world); +} diff --git a/src/gaemstone/Flecs/Metrics.cs b/src/gaemstone/Flecs/Metrics.cs new file mode 100644 index 0000000..021e351 --- /dev/null +++ b/src/gaemstone/Flecs/Metrics.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; +using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; + +namespace gaemstone.Flecs; + +[BuiltIn, Module, Path("/flecs/timer")] +[DependsOn] +[DependsOn] +[DependsOn] +public unsafe partial class Metrics + : IModuleImport +{ + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &MetricsImport } }, + alloc.AllocateCString("FlecsMetrics")))); + } + + [UnmanagedCallersOnly] + private static void MetricsImport(ecs_world_t* world) + => FlecsMetricsImport(world); +} diff --git a/src/gaemstone/Flecs/Systems/Monitor.cs b/src/gaemstone/Flecs/Monitor.cs similarity index 66% rename from src/gaemstone/Flecs/Systems/Monitor.cs rename to src/gaemstone/Flecs/Monitor.cs index 15dd014..ddd9778 100644 --- a/src/gaemstone/Flecs/Systems/Monitor.cs +++ b/src/gaemstone/Flecs/Monitor.cs @@ -3,18 +3,18 @@ using gaemstone.ECS; using gaemstone.ECS.Utility; using static flecs_hub.flecs; -namespace gaemstone.Flecs.Systems; +namespace gaemstone.Flecs; [BuiltIn, Module, Path("/flecs/monitor")] public unsafe partial class Monitor - : IModuleInitializer + : IModuleImport { - public static void Initialize(Entity module) + static Entity IModuleImport.Import(World world) { using var alloc = TempAllocator.Use(); - ecs_import_c(module.World, + return Entity.GetOrThrow(world, new(ecs_import_c(world, new() { Data = new() { Pointer = &MonitorImport } }, - alloc.AllocateCString("FlecsMonitor")); + alloc.AllocateCString("FlecsMonitor")))); } [UnmanagedCallersOnly] diff --git a/src/gaemstone/Flecs/Pipeline.cs b/src/gaemstone/Flecs/Pipeline.cs index b4800ff..a7bbe07 100644 --- a/src/gaemstone/Flecs/Pipeline.cs +++ b/src/gaemstone/Flecs/Pipeline.cs @@ -1,9 +1,14 @@ +using System.Runtime.InteropServices; using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; namespace gaemstone.Flecs; [BuiltIn, Module, Path("/flecs/pipeline")] -public partial class Pipeline +[DependsOn] +public unsafe partial class Pipeline + : IModuleImport { [Entity] public struct Phase { } @@ -90,4 +95,17 @@ public partial class Pipeline [Entity, Add] [DependsOn] public struct PostFrame { } + + + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &PipelineImport } }, + alloc.AllocateCString("FlecsPipeline")))); + } + + [UnmanagedCallersOnly] + private static void PipelineImport(ecs_world_t* world) + => FlecsPipelineImport(world); } diff --git a/src/gaemstone/Flecs/Systems/Rest.cs b/src/gaemstone/Flecs/Rest.cs similarity index 53% rename from src/gaemstone/Flecs/Systems/Rest.cs rename to src/gaemstone/Flecs/Rest.cs index d20cd8a..49bd764 100644 --- a/src/gaemstone/Flecs/Systems/Rest.cs +++ b/src/gaemstone/Flecs/Rest.cs @@ -3,22 +3,26 @@ using gaemstone.ECS; using gaemstone.ECS.Utility; using static flecs_hub.flecs; -namespace gaemstone.Flecs.Systems; +namespace gaemstone.Flecs; [BuiltIn, Module, Path("/flecs/rest")] +[DependsOn] public unsafe partial class Rest - : IModuleInitializer + : IModuleImport { - public static void Initialize(Entity module) + static Entity IModuleImport.Import(World world) { - using (var alloc = TempAllocator.Use()) - ecs_import_c(module.World, - new() { Data = new() { Pointer = &RestImport } }, - alloc.AllocateCString("FlecsRest")); + using var alloc = TempAllocator.Use(); + + var module = Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &RestImport } }, + alloc.AllocateCString("FlecsRest")))); module.NewChild("Rest").Build() .CreateLookup() .Set(new EcsRest { port = 27750 }); + + return module; } [UnmanagedCallersOnly] diff --git a/src/gaemstone/Flecs/Script.cs b/src/gaemstone/Flecs/Script.cs new file mode 100644 index 0000000..a028131 --- /dev/null +++ b/src/gaemstone/Flecs/Script.cs @@ -0,0 +1,24 @@ +using System.Runtime.InteropServices; +using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; + +namespace gaemstone.Flecs; + +[BuiltIn, Module, Path("/flecs/script")] +[DependsOn] +public unsafe partial class Script + : IModuleImport +{ + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &ScriptImport } }, + alloc.AllocateCString("FlecsScript")))); + } + + [UnmanagedCallersOnly] + private static void ScriptImport(ecs_world_t* world) + => FlecsScriptImport(world); +} diff --git a/src/gaemstone/Flecs/System.cs b/src/gaemstone/Flecs/System.cs new file mode 100644 index 0000000..c3fd6b7 --- /dev/null +++ b/src/gaemstone/Flecs/System.cs @@ -0,0 +1,23 @@ +using System.Runtime.InteropServices; +using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; + +namespace gaemstone.Flecs; + +[BuiltIn, Module, Path("/flecs/system")] +public unsafe partial class System + : IModuleImport +{ + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &SystemImport } }, + alloc.AllocateCString("FlecsSystem")))); + } + + [UnmanagedCallersOnly] + private static void SystemImport(ecs_world_t* world) + => FlecsSystemImport(world); +} diff --git a/src/gaemstone/Flecs/Timer.cs b/src/gaemstone/Flecs/Timer.cs new file mode 100644 index 0000000..84edfdf --- /dev/null +++ b/src/gaemstone/Flecs/Timer.cs @@ -0,0 +1,24 @@ +using System.Runtime.InteropServices; +using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; + +namespace gaemstone.Flecs; + +[BuiltIn, Module, Path("/flecs/timer")] +[DependsOn] +public unsafe partial class Timer + : IModuleImport +{ + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &TimerImport } }, + alloc.AllocateCString("FlecsTimer")))); + } + + [UnmanagedCallersOnly] + private static void TimerImport(ecs_world_t* world) + => FlecsTimerImport(world); +} diff --git a/src/gaemstone/Flecs/Units.cs b/src/gaemstone/Flecs/Units.cs new file mode 100644 index 0000000..e47123c --- /dev/null +++ b/src/gaemstone/Flecs/Units.cs @@ -0,0 +1,23 @@ +using System.Runtime.InteropServices; +using gaemstone.ECS; +using gaemstone.ECS.Utility; +using static flecs_hub.flecs; + +namespace gaemstone.Flecs; + +[BuiltIn, Module, Path("/flecs/units")] +public unsafe partial class Units + : IModuleImport +{ + static Entity IModuleImport.Import(World world) + { + using var alloc = TempAllocator.Use(); + return Entity.GetOrThrow(world, new(ecs_import_c(world, + new() { Data = new() { Pointer = &UnitsImport } }, + alloc.AllocateCString("FlecsUnits")))); + } + + [UnmanagedCallersOnly] + private static void UnitsImport(ecs_world_t* world) + => FlecsUnitsImport(world); +} diff --git a/src/gaemstone/Universe+Modules.cs b/src/gaemstone/Universe+Modules.cs index 906ab18..ce4aba6 100644 --- a/src/gaemstone/Universe+Modules.cs +++ b/src/gaemstone/Universe+Modules.cs @@ -1,8 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; using gaemstone.ECS; using static gaemstone.Flecs.Core; using Module = gaemstone.Flecs.Core.Module; @@ -10,126 +6,100 @@ using Module = gaemstone.Flecs.Core.Module; namespace gaemstone; public class ModuleManager - : IEnumerable.IModuleInfo> { - private readonly Dictionary, IModuleInfo> _modules = new(); - public Universe Universe { get; } - public ModuleManager(Universe universe) - => Universe = universe; + public World World => Universe.World; - internal IModuleInfo? Lookup(Entity entity) - => _modules.GetValueOrDefault(entity); + private readonly Rule _findDisabledDeps; + private readonly Rule _findDependents; - public Entity Register() - where T : IModule + private readonly ECS.Variable _findDisabledDepsThisVar; + private readonly ECS.Variable _findDependentsModuleVar; + + public ModuleManager(Universe universe) { - // if (!typeof(T).IsAssignableTo(typeof(IModule))) throw new ArgumentException( - // $"The specified type {typeof(T)} does not implement IModule", nameof(T)); + Universe = universe; - var module = new ModuleInfo(Universe); - _modules.Add(module.Entity, module); - TryEnableModule(module); - return module.Entity; + World.New("/gaemstone/ModuleInfo").Symbol("ModuleInfo") + .Build().InitComponent(); + + _findDisabledDeps = new(World, new("(DependsOn, $dep), Disabled($dep)")); + _findDependents = new(World, new("ModuleInfo, Disabled, (DependsOn, $module)")); + + _findDisabledDepsThisVar = _findDisabledDeps.ThisVar + ?? throw new InvalidOperationException($"Could not find $this of {nameof(_findDisabledDeps)}"); + _findDependentsModuleVar = _findDependents.Variables["module"] + ?? throw new InvalidOperationException($"Could not find $module of {nameof(_findDependents)}"); } - private void TryEnableModule(IModuleInfo module) + public Entity Import() + where T : IModule, IModuleImport { - if (!module.Dependencies.All(dep => dep.IsDependencyMet)) return; + foreach (var dep in T.Dependencies) + if (World.LookupPathOrNull(dep) == null) throw new InvalidOperationException( + $"Missing required dependency {dep} for built-in module {T.Path}"); - Console.WriteLine($"Enabling module {module.Entity.Path}"); + Console.WriteLine($"Importing built-in module {T.Path}"); - module.Enable(); + var entity = T.Import(World); + entity.Set(new ModuleInfo()); + T.OnEnable(entity); + return entity; + } - // Find other modules that might be missing this module as a dependency. - foreach (var other in _modules.Values) { - if (other.IsInitialized) continue; - var dependency = other.Dependencies.FirstOrDefault(dep => dep.Entity == module.Entity); - if (dependency == null) continue; + public Entity Register() + where T : IModule + { + if (T.IsBuiltIn) throw new ArgumentException( + $"Unexpected operation, {T.Path} is a built-in module"); - dependency.Info = module; - dependency.IsDependencyMet = true; + var builder = World.New(T.Path) + .Add().Add() + .Set(new ModuleInfo()); - TryEnableModule(other); + foreach (var depPath in T.Dependencies) { + var dependency = World.LookupPathOrNull(depPath) ?? + World.New(depPath).Add().Add().Build(); + builder.Add(dependency); } + + var module = builder.Build().CreateLookup(); + + // Ensure all parent entities have the Module tag set. + for (var p = module.Parent; p is Entity parent; p = parent.Parent) + parent.Add(); + + Console.WriteLine($"Registered module {module.Path}"); + + TryEnableModule(module); + return module; } - public interface IModuleInfo + private void TryEnableModule(Entity module) { - Entity Entity { get; } - IReadOnlyCollection Dependencies { get; } - bool IsInitialized { get; } - void Enable(); - } + // Skip if module is already enabled. + if (module.IsEnabled) return; + // Skip if module has any not-yet-enabled dependencies. + if (_findDisabledDeps.Iter().SetVar(_findDisabledDepsThisVar, module).Any()) return; - // IEnumerable implementation - public IEnumerator GetEnumerator() => _modules.Values.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + Console.WriteLine($"Enabling module {module.Path}"); + module.GetOrThrow().OnEnable(module); + module.Enable(); + // Get all modules that depend on this one and try to enabled them if they now have their dependencies met. + foreach (var dependent in _findDependents.Iter().SetVar(_findDependentsModuleVar, module).GetAllEntities()) + TryEnableModule(dependent); + } - public class ModuleDependency + public interface IModuleInfo { - public Entity Entity { get; } - public IModuleInfo? Info { get; internal set; } - public bool IsDependencyMet { get; internal set; } - - public ModuleDependency(Entity entity, - IModuleInfo? info = null, bool isDependencyMet = false) - { - Entity = entity; - Info = info; - IsDependencyMet = isDependencyMet; - } + void OnEnable(Entity entity); } internal class ModuleInfo : IModuleInfo where T : IModule { - public Entity Entity { get; } - public IReadOnlyCollection Dependencies { get; } - public bool IsInitialized { get; private set; } - - public ModuleInfo(Universe universe) - { - var world = universe.World; - - if (T.IsBuiltIn) - { - Entity = world.LookupPathOrThrow(T.Path); - Dependencies = Array.Empty(); - } - else - { - var builder = world.New(T.Path); - var deps = new List(); - - builder.Add(); - foreach (var dependsPath in T.Dependencies) { - var dependency = world.LookupPathOrNull(dependsPath) ?? - world.New(dependsPath).Add().Add().Build(); - - var depModule = universe.Modules.Lookup(dependency); - var isDepInit = (depModule?.IsInitialized == true); - - deps.Add(new(dependency, depModule, isDepInit)); - if (!isDepInit) builder.Add(); - builder.Add(dependency); - } - - Entity = builder.Build().CreateLookup(); - Dependencies = deps.AsReadOnly(); - - // Ensure all parent entities have the Module tag set. - for (var p = Entity.Parent; p is Entity parent; p = parent.Parent) - parent.Add(); - } - } - - public void Enable() - { - Entity.Enable(); - T.Initialize(Entity); - IsInitialized = true; - } + public void OnEnable(Entity entity) + => T.OnEnable(entity); } } diff --git a/src/gaemstone/Universe.cs b/src/gaemstone/Universe.cs index b7a7e97..17bf103 100644 --- a/src/gaemstone/Universe.cs +++ b/src/gaemstone/Universe.cs @@ -9,17 +9,22 @@ public class Universe public Universe() { - World = new(); + World = new(minimal: true); Modules = new(this); // Bootstrap [Relation] tag, since it will be added to some Flecs types. World.New("/gaemstone/Doc/Relation").Build() .CreateLookup(); - // Bootstrap built-in (static) modules from Flecs. - Modules.Register(); - Modules.Register(); - Modules.Register(); + // Bootstrap core module from Flecs. + Modules.Import(); + + // Import addon modules from Flecs we use for the engine. + Modules.Import(); + Modules.Import(); + Modules.Import(); + Modules.Import(); + Modules.Import(); Modules.Register(); }