From 8d928228455a8c14854fa6aab146d8be25b43094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Sun, 10 Mar 2024 12:20:33 +0100 Subject: [PATCH] Added EditorFlags: Hide entities in hierarchy and editor scene - Also some Style changes --- GlitchyEditor/BeefProj.toml | 1 + .../resources/Textures/EditorIcons.dds | Bin 278656 -> 311424 bytes .../resources/Textures/EditorIcons.psd | Bin 76971 -> 83914 bytes .../src/EditWindows/EntityHierarchyWindow.bf | 146 +++++++++++++----- GlitchyEditor/src/EditorIcons.bf | 15 ++ GlitchyEngine/BeefProj.toml | 2 +- GlitchyEngine/src/Editor/EditorFlags.bf | 8 + GlitchyEngine/src/ImGui/ImGuiExtension.bf | 4 +- GlitchyEngine/src/ImGui/ImGuiLayer.bf | 2 + GlitchyEngine/src/Scripting/ScriptGlue.bf | 38 +++++ .../World/Components/EditorFlagsComponent.bf | 7 + GlitchyEngine/src/World/Entity.bf | 18 +++ ScriptCore/Editor/EditorFlags.cs | 20 +++ ScriptCore/Entity.cs | 14 ++ ScriptCore/ScriptGlue.cs | 7 + 15 files changed, 242 insertions(+), 40 deletions(-) create mode 100644 GlitchyEngine/src/Editor/EditorFlags.bf create mode 100644 GlitchyEngine/src/World/Components/EditorFlagsComponent.bf create mode 100644 ScriptCore/Editor/EditorFlags.cs diff --git a/GlitchyEditor/BeefProj.toml b/GlitchyEditor/BeefProj.toml index bb200ed..2cd40b7 100644 --- a/GlitchyEditor/BeefProj.toml +++ b/GlitchyEditor/BeefProj.toml @@ -5,6 +5,7 @@ Dependencies = {corlib = "*", GlitchLog = "*", GlitchyEngine = "*"} Name = "GlitchyEditor" TargetType = "BeefGUIApplication" StartupObject = "GlitchyEngine.Program" +ProcessorMacros = ["GE_EDITOR_IMGUI_DEMO"] [Configs.Debug.Win64] PostBuildCmds = ["CopyFilesIfNewer(\"$(WorkspaceDir)/bin/vswhere.exe\", \"$(TargetDir)\")"] diff --git a/GlitchyEditor/resources/Textures/EditorIcons.dds b/GlitchyEditor/resources/Textures/EditorIcons.dds index 8d55e891d0354d972ca881f1a5299726fa3b4e06..5781d7a76e04b5e60f93a99263a1961088d9f663 100644 GIT binary patch delta 5003 zcmbtYVQdt~7540!1nP5q32ti1b~qlkcxNPz zwmsV!X)XCJPX5wd%dL-V`24yk&pa0vHaB19iO986&RvsboirZ&ncFLXT4M;i%Iu&w zMk2XopXIYx>Ud_fiCSU(nC<6pz4$0U-*-@Co-wNAs>|jE8e5T_+0#t@kmL4Q7StykqRgXdIJfHNI=OdIT3WRpP zd?qz+m8;;$ybaH2O>0Ev3?sL`#GUjOk@^*jt9Z$FUTv)`)$DGmW|5@3cBc!b(?H4q zMX*10VM`3KG5h|_Kf7Md^siQCn!nvELzm4ywnR>!D+dPcy@v_%+62H6p&$$J`L7hv zuBAW;4|d-#|(&7w?7GE*hO=aD=DEJZO{ zm}_N85jtn4^q7=_BHy|ZpF`ULBOSud`GmTi^eZAXW^ng?T-p(4tF4Lw4SKoFu8P6+ zEKJy=m_)I52<;xUe*)$d^lHTv3KkHJYWJ6d3;RuWNmg{Qy`H7&UF5lEU9AU2?kna1 zD(St90HYh24#j36fgQLP_&>32_DN?e)B6UzL5m9uA`QOq5j0d=?B|$#45)p&9g(xo zvyA5vJtvi5Hn-o|r7hR4+wPL@eqfL_2D2CnmyW*%ccG5qJ5R1r^KoT zwn7Ad!@@`6W&*Zr28wElZ$?Gpf})OHz)j*$587#Ik1^Zb*?NuE(FRs0X1B8zP{>w+ z2-^fZcBvOJ^mj9isnz~I@f0S&Zt0vhtHAyRYCCB}!lW^3Ogt8lbAMpdD*)C4-IU7B zi0{UUmNmTd;8qb_Ycz{QtJwjlcK0i}*?gL(N9%>XpViPN3iZdm)K z8^6I-Z?gZ$r~b+|xRHV`xT0GTRJ;{dvh1k(NbEH!9W`sGxSiH@V-}qxXhtM5X17eu zuz8=bfYjw7ks;hkp^ZiqAK^kIZcQW6DQy)PNupi24xP%!MM_J%&loaf?i$Ov=28oZ zuwD>!98+slk^@=uIk^_|r&bge6jsu)&FskzQ5ccFXh!%uS^N zZ+8`P@`6>+BGi0Tl3I*fr{r1o8mwSn!Nxx|Cb#{YttOMV;s0S63Ph+f^@*se z1;(xAK9PyUY4!v^`Py1<2uY*$xIE|mUQKL3^dIAy4?0EqZMFf}7csWR4M*oevqq-w zFpJ4qW@Lzb+Ek?BYeuUZ^I(Hy6*8n>n>6Ynu5~H5>z^vsRFmX7uZ~e;smF%+fXr1H zIok9jj&e+m$UkBn*LXfofak}8G#>5$mP!e@`ktc;K=kGC)Xu21*BiEL?Qb4hD*CE@GD8LBqjnXb3S_TD z!Cr`Cr@4EB$d8yx)k~^;P4_Dhk-EWV`Qh{kZH9|bw1>8_N`cBO1o?FvSOvTn{X|2G zESAEaRzXoRjR~u(pluH%~>ZGX7b{IF++?&aY)5;jVKtq`D>{vs;MeWBRr}q zmM*cV1QA~w#%v4mpGn0 zvs80c$9+x?k43+A<9nlMq6s6-mWZy#o+#^sj{O#VT62)wxwx{l2L*#D! zURWt(8&*TqSfu7Y0Tv94g6f!t9B}KL=gb(Bb2k@NM&1k3KPFBD3yToLD*F11BxtnB>>*%19y4A`YeNj>PsYB9nQ5ynp5UiG$H3>W=iEt zze}Ji1LSER*~{SiGzPQL#wEMdX}T}cdMAFW#1DsVl<)tOKE;JEr-nGHibw8N6nuZDfqSv5mraSeO z5Dzjfy8CE`+-dY5R0}!Zw_dFu()(~H6o+CPuup5{)QtHq=`=vSxGAbMlokSZXi{~~ z(kmKb#|)59(xs2QeaYmNQ0clm5m5bFljG2Uxb2)+xNX++V9R&tVrY=b$$y#ZR%pKH zR%jPZ%Ubs5Ok(^nVSeadJpmK@O8tD$kW~xjZu;q8fW=LGy}V3beYE@x-I0}Cnf+)P P78*mpxwV-8AV>I?-J2{v=b;`;K}ak{NUz3o|IKqj#i28-DH)O zxIa}k-vJ4H?~cbq4!&={hr*YbMxuzVL%?VyPi|-yhYpg(0J#fp<{>^S^=P8p2_li` zC%c7zn4am1G(SS=$Pk93LQo5{q{X;#bghW@k^##YHXLz=2zLp8E%CWRc%C8)5w6H! z9a;kGYTia0xc|W#;BF(=yBB9+cG@tx@$J2QaP3hU|CL1uNZ>VV=*@JgQ)&S?P`l7x zM<;6!Yu+H@2k91`dNnL!m$IgT;MpL=IsjeD_2Ygq`Vmn#mVP`|ahjn85L$;Q{giDJ zu>cK=DT_XcQ4Z+`uzt6Kb18Bf+OW!TzHm8c5 zoxyqHPH)VwL`*Azy*PRuh(C~FVqWprP>%!OTao$EX%6XCa6_1(=tA%J#_b9O7X{3l zaj+c*8~+;a$Fg=OS?7w`5D2bXq!A&ZOj(N?JNK>D3}#s zsWhG;&SDUF1jTQ&n6;Qp6}sh(->VQKCY&8O*aw5v`KXf{7Uqh!pa@#5Q^sE=qb_)^ zU`?X&4LV(<`bfYF(KckI=lvqOKD|@3WXlTm-2*cqG(2I#|WufCRV1(77&^@n0Mo`>96? z3xxxxD@}5 zq2&S@UqnZzImMeX+uRSf!1S)0)v{+PCAtd$nJ$(XHR+0GPxD7z%zug&%=wFtPwcvq zR5IR9#OOBCIuNY1m6B)Pww(Js$@vt61jS*gF3iu!_h@fb=rJ#mAm#uO`eLfdQqgqfK=PntGJjJ<`JTNM6U#w6D|L5A$r{fA~5;0RSF`~$Ec?o_HU^|2Y6V`@$k#U zm{@=8mCYZ}Hs@|NeHqE*P1zqT^^#oJ8IOwQ1xs8-L5ZtSiD4p-oTLXPLxg{eQ1~J5 z{|xcf194v973>Zwc>969jd&p8#$0b}7M$EruK5Aj zbnBL{Owr!-O%mWbwC?de))wRw0e8zoGqu;s-5F%6v318crn_egx1|*#Y!&w53d7Na z%LJU{_#Do?n80Ei)cmz_Z$Nv`*WE8__Rp1AdU)Y0z1(NwAb+b69}lC{ofgqY*72!2UOH+|92|r GSjitBQ~`1T diff --git a/GlitchyEditor/resources/Textures/EditorIcons.psd b/GlitchyEditor/resources/Textures/EditorIcons.psd index 4711f9cff65015f8724accf4baaa532b1606e1af..ce42cce50ba8dcf05c73afdd1e3fd5ab135f5615 100644 GIT binary patch delta 11845 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 delta 5293 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 flags)) + { + bool hidden = flags.Flags.HasFlag(.HideInScene); + + SubTexture2D icon = hidden ? EditorIcons.Instance.Entity_Hidden : EditorIcons.Instance.Entity_Visible; + + ImGui.Vec4 tintColor = hidden ? *ImGui.GetStyleColorVec4(.TextDisabled) : *ImGui.GetStyleColorVec4(.Text); + + if (ImGui.ImageButtonEx(ImGui.GetID("visibilityToggle"), icon, .(16, 16), .Zero, .Ones, .Zero, tintColor)) + { + flags.Flags ^= .HideInScene; + } + + if (ImGui.IsItemHovered()) + { + ImGui.BeginTooltip(); + + if (hidden) + { + ImGui.TextUnformatted("Entity is hidden. Click to show the entity."); + } + else + { + ImGui.TextUnformatted("Entity is visible. Click to hide the entity."); + } + + ImGui.EndTooltip(); + } + } + + ImGui.PopStyleColor(3); + ImGui.PopStyleVar(2); + } + private void ImGuiPrintEntityTree(TreeNode tree) { + Entity entity = tree.Value; + + if (entity.EditorFlags.HasFlag(.HideInHierarchy)) + return; + + ImGui.PushID(entity.UUID.GetHashCode()); + + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + + ShowVisibilityButton(entity); + + ImGui.TableNextColumn(); + String name = null; - var nameComponent = tree.Value.GetComponent(); + var nameComponent = entity.GetComponent(); if(nameComponent != null) { @@ -374,44 +442,42 @@ namespace GlitchyEditor.EditWindows } else { - name = scope:: $"Entity {(tree.Value.Handle.[Friend]Index)}"; + name = scope:: $"Entity {(entity.Handle.[Friend]Index)}"; } - ImGui.TreeNodeFlags flags = .OpenOnArrow | .DefaultOpen | .SpanAvailWidth | .OpenOnDoubleClick; + ImGui.TreeNodeFlags flags = .OpenOnArrow | .DefaultOpen | .SpanAllColumns | .OpenOnDoubleClick; if(tree.Children.Count == 0) flags |= .Leaf; - bool inSelectedList = IsEntitySelected(tree.Value); + bool inSelectedList = IsEntitySelected(entity); if(inSelectedList) flags |= .Selected; - if (_entitiesToUnfold.Contains(tree.Value)) + if (_entitiesToUnfold.Contains(entity)) { - _entitiesToUnfold.Remove(tree.Value); + _entitiesToUnfold.Remove(entity); ImGui.SetNextItemOpen(true, .None); } - bool isOpen = ImGui.TreeNodeEx((void*)(uint)tree.Value.Handle.[Friend]Index, flags, $"{name}"); + bool isOpen = ImGui.TreeNodeEx((void*)(uint)entity.Handle.[Friend]Index, flags, $"{name}"); - if (_entityToHighlight == tree.Value) + if (_entityToHighlight == entity) { ImGui.SetScrollHereY(0); _entityToHighlight = .(); } - ImGui.PushID((void*)(uint)tree.Value.Handle.[Friend]Index); - bool deleted = false; if (ImGui.BeginPopupContextItem("treeNodePopup")) { // Only select if it isn't already selected, because it otherwise clears the selection when ctrl is released - if (!IsEntitySelected(tree.Value)) + if (!IsEntitySelected(entity)) { - SelectEntity(tree.Value, !ImGui.GetIO().KeyCtrl); + SelectEntity(entity, !ImGui.GetIO().KeyCtrl); } ShowEntityContextMenu(out deleted); @@ -419,8 +485,6 @@ namespace GlitchyEditor.EditWindows ImGui.EndPopup(); } - ImGui.PopID(); - if (deleted) { if (isOpen) @@ -435,7 +499,7 @@ namespace GlitchyEditor.EditWindows { isDragged = true; - UUID id = tree.Value.UUID; + UUID id = entity.UUID; ImGui.SetDragDropPayload(.Entity, &id, sizeof(UUID)); ImGui.Text(name); @@ -443,7 +507,7 @@ namespace GlitchyEditor.EditWindows ImGui.EndDragDropSource(); } - EntityDropTarget(tree.Value); + EntityDropTarget(entity); bool clicked = ImGui.IsItemClicked() && !ImGui.IsItemToggledOpen(); bool clickedRight = ImGui.IsItemClicked(.Right); @@ -461,17 +525,19 @@ namespace GlitchyEditor.EditWindows if (clicked || clickedRight) { - lastClickedEntity = tree.Value; + lastClickedEntity = entity; } - if (!isDragged && (hovered && !ImGui.IsMouseDown(.Left) && !ImGui.IsMouseDown(.Right)) && tree.Value == lastClickedEntity) + if (!isDragged && (hovered && !ImGui.IsMouseDown(.Left) && !ImGui.IsMouseDown(.Right)) && entity == lastClickedEntity) { if (!inSelectedList) { - SelectEntity(tree.Value, !ImGui.GetIO().KeyCtrl); + SelectEntity(entity, !ImGui.GetIO().KeyCtrl); inSelectedList = true; } } + + ImGui.PopID(); } private void EntityDropTarget(Entity target) @@ -565,37 +631,41 @@ namespace GlitchyEditor.EditWindows InsertIntoTree(entity); } - - if(ImGui.TreeNodeEx("Scene", .DefaultOpen)) + + ImGui.Rect rect = .(); + rect.Min = (ImGui.Vec2)((float2)ImGui.GetWindowContentRegionMin() + (float2)ImGui.GetWindowPos()); + rect.Max = (ImGui.Vec2)((float2)rect.Min + (float2)ImGui.GetContentRegionAvail()); + + if(ImGui.BeginDragDropTargetCustom(rect, ImGui.GetID("sceneDropTarget"))) { - if(ImGui.BeginDragDropTarget()) + Payload? payload = ImGui.AcceptDragDropPayload(.Entity); + + if(payload != null) { - Payload? payload = ImGui.AcceptDragDropPayload(.Entity); + UUID movedEntityId = payload->Data; + + Entity movedEntity = _editor.CurrentScene.GetEntityByID(movedEntityId); - if(payload != null) - { - UUID movedEntityId = payload->Data; - - Entity movedEntity = _editor.CurrentScene.GetEntityByID(movedEntityId); - - // Also mark transform as dirty - var transformComponent = movedEntity.GetComponent(); - transformComponent.Parent = .InvalidEntity; - //transformComponent?.IsDirty = true; - } - - ImGui.EndDragDropTarget(); + var transformComponent = movedEntity.GetComponent(); + transformComponent.Parent = .InvalidEntity; } + ImGui.EndDragDropTarget(); + } + + if (ImGui.BeginTable("entityTable", 2, .RowBg | .NoBordersInBody | .SizingFixedFit)) + { + ImGui.TableSetupColumn("Visibility", .IndentDisable | .NoResize); + ImGui.TableSetupColumn("Entities", .IndentEnable | .WidthStretch); + for(var child in root.Children) { ImGuiPrintEntityTree(child); } - ImGui.TreePop(); + ImGui.EndTable(); } } - // Otherwise else { // Show search results as flat list diff --git a/GlitchyEditor/src/EditorIcons.bf b/GlitchyEditor/src/EditorIcons.bf index 4bc44b3..4a4f6a1 100644 --- a/GlitchyEditor/src/EditorIcons.bf +++ b/GlitchyEditor/src/EditorIcons.bf @@ -8,6 +8,8 @@ namespace GlitchyEditor { class EditorIcons : RefCounted { + private static EditorIcons _editorIcons; + AssetHandle _texture; public SubTexture2D DirectionalLight ~ _.ReleaseRef(); @@ -27,6 +29,10 @@ namespace GlitchyEditor public SubTexture2D File_Material ~ _.ReleaseRef(); public SubTexture2D File_CSharpScript ~ _.ReleaseRef(); public SubTexture2D File_Shader ~ _.ReleaseRef(); + public SubTexture2D Entity_Visible ~ _.ReleaseRef(); + public SubTexture2D Entity_Hidden ~ _.ReleaseRef(); + + public static EditorIcons Instance => _editorIcons; public SamplerState SamplerState { @@ -36,6 +42,8 @@ namespace GlitchyEditor public this(String texturePath, float2 iconSize) { + _editorIcons = this; + _texture = Content.LoadAsset(texturePath, null, true); float2 pen = .(); @@ -57,6 +65,13 @@ namespace GlitchyEditor File_Material = GetNextGridTexture(ref pen, iconSize); File_CSharpScript = GetNextGridTexture(ref pen, iconSize); File_Shader = GetNextGridTexture(ref pen, iconSize); + Entity_Visible = GetNextGridTexture(ref pen, iconSize); + Entity_Hidden = GetNextGridTexture(ref pen, iconSize); + } + + public ~this() + { + _editorIcons = null; } private SubTexture2D GetNextGridTexture(ref float2 pen, float2 iconSize) diff --git a/GlitchyEngine/BeefProj.toml b/GlitchyEngine/BeefProj.toml index 43d3136..babd331 100644 --- a/GlitchyEngine/BeefProj.toml +++ b/GlitchyEngine/BeefProj.toml @@ -3,7 +3,7 @@ Dependencies = {GlitchLog = "*", corlib = "*", DirectX = "*", FreeType = "*", cg [Project] Name = "GlitchyEngine" -ProcessorMacros = ["GE_GRAPHICS_DX11", "GE_SHADER_MATRIX_MISMATCH_IS_ERROR", "GE_SHADER_VAR_TYPE_MISMATCH_IS_ERROR", "GE_SHADER_UNUSED_VARIABLE_IS_WARNING", "GE_WINDOWS"] +ProcessorMacros = ["GE_GRAPHICS_DX11", "GE_SHADER_MATRIX_MISMATCH_IS_ERROR", "GE_SHADER_VAR_TYPE_MISMATCH_IS_ERROR", "GE_SHADER_UNUSED_VARIABLE_IS_WARNING", "GE_WINDOWS", "GE_EDITOR"] [Configs.Paranoid.Win32] PreprocessorMacros = ["DEBUG", "PARANOID", "GE_WINDOWS"] diff --git a/GlitchyEngine/src/Editor/EditorFlags.bf b/GlitchyEngine/src/Editor/EditorFlags.bf new file mode 100644 index 0000000..4efc3bb --- /dev/null +++ b/GlitchyEngine/src/Editor/EditorFlags.bf @@ -0,0 +1,8 @@ +namespace GlitchyEngine.Editor; + +enum EditorFlags +{ + Default = 0, + HideInHierarchy = 1, + HideInScene = 2, +} diff --git a/GlitchyEngine/src/ImGui/ImGuiExtension.bf b/GlitchyEngine/src/ImGui/ImGuiExtension.bf index 56b290e..2026105 100644 --- a/GlitchyEngine/src/ImGui/ImGuiExtension.bf +++ b/GlitchyEngine/src/ImGui/ImGuiExtension.bf @@ -138,7 +138,9 @@ namespace ImGui public static void TextUnformatted(StringView text) => TextUnformattedImpl(text.Ptr, text.Ptr + text.Length); public static void PushID(StringView id) => PushID(id.Ptr, id.Ptr + id.Length); - + + public static void PushID(int id) => PushID((void*)id); + /// Releases references that accumulated calls like ImGui::Image protected internal static extern void CleanupFrame(); diff --git a/GlitchyEngine/src/ImGui/ImGuiLayer.bf b/GlitchyEngine/src/ImGui/ImGuiLayer.bf index 164c1c9..0a37fe4 100644 --- a/GlitchyEngine/src/ImGui/ImGuiLayer.bf +++ b/GlitchyEngine/src/ImGui/ImGuiLayer.bf @@ -136,6 +136,8 @@ namespace GlitchyEngine.ImGui colors[(.)ImGui.Col.Tab] = ImGui.Vec4(0.473f, 0.519f, 0.580f, 1.00f); colors[(.)ImGui.Col.TabUnfocused] = ImGui.Vec4(0.255f, 0.255f, 0.255f, 1.00f); colors[(.)ImGui.Col.CheckMark] = ImGui.Vec4(0.851f, 0.863f, 0.900f, 1.00f); + colors[(.)ImGui.Col.TitleBg] = ImGui.Vec4(0.406f, 0.401f, 0.390f, 1.000f); + colors[(.)ImGui.Col.TitleBgActive] = ImGui.Vec4(0.196f, 0.192f, 0.182f, 1.000f); /*colors[(.)ImGui.Col.Text] = ImGui.Vec4(0.00f, 0.00f, 0.00f, 1.00f); colors[(.)ImGui.Col.TextDisabled] = ImGui.Vec4(0.60f, 0.60f, 0.60f, 1.00f); diff --git a/GlitchyEngine/src/Scripting/ScriptGlue.bf b/GlitchyEngine/src/Scripting/ScriptGlue.bf index 992a05a..cc94cf0 100644 --- a/GlitchyEngine/src/Scripting/ScriptGlue.bf +++ b/GlitchyEngine/src/Scripting/ScriptGlue.bf @@ -10,6 +10,8 @@ using System.Collections; using Box2D; using GlitchyEngine.Scripting; using GlitchyEngine.Serialization; +using GlitchyEngine.Editor; +using GlitchyEngine.World.Components; namespace GlitchyEngine.Scripting; @@ -187,6 +189,23 @@ static class ScriptGlue component = null; return false; } + + /// Gets the entity. Returns true, if the entity was found. + static bool TryGetEntitySafe(UUID entityId, out Entity entity) + { + entity = default; + + Result foundEntity = ScriptEngine.Context.GetEntityByID(entityId); + + if (foundEntity case .Ok(out entity)) + { + return true; + } + + Log.ClientLogger.Error($"No entity with ID {entityId} found."); + return false; + } + #region Exception Helpers @@ -461,6 +480,25 @@ static class ScriptGlue Mono.mono_free(rawName); } + + [RegisterCall("ScriptGlue::Entity_GetEditorFlags")] + static void Entity_GetEditorFlags(UUID entityId, out EditorFlags editorFlags) + { + editorFlags = .Default; +#if GE_EDITOR + if (TryGetEntitySafe(entityId, let entity)) + editorFlags = entity.EditorFlags; +#endif + } + + [RegisterCall("ScriptGlue::Entity_SetEditorFlags")] + static void Entity_SetEditorFlags(UUID entityId, EditorFlags editorFlags) + { +#if GE_EDITOR + if (TryGetEntitySafe(entityId, let entity)) + entity.EditorFlags = editorFlags; +#endif + } #endregion diff --git a/GlitchyEngine/src/World/Components/EditorFlagsComponent.bf b/GlitchyEngine/src/World/Components/EditorFlagsComponent.bf new file mode 100644 index 0000000..9dea12b --- /dev/null +++ b/GlitchyEngine/src/World/Components/EditorFlagsComponent.bf @@ -0,0 +1,7 @@ +using GlitchyEngine.Editor; +namespace GlitchyEngine.World.Components; + +struct EditorFlagsComponent +{ + public EditorFlags Flags; +} diff --git a/GlitchyEngine/src/World/Entity.bf b/GlitchyEngine/src/World/Entity.bf index 999e26d..f0b40c0 100644 --- a/GlitchyEngine/src/World/Entity.bf +++ b/GlitchyEngine/src/World/Entity.bf @@ -1,6 +1,8 @@ using System; using System.Collections; using GlitchyEngine.Core; +using GlitchyEngine.Editor; +using GlitchyEngine.World.Components; using internal GlitchyEngine.World; @@ -74,6 +76,22 @@ namespace GlitchyEngine.World public TransformComponent* Transform => GetComponent(); + public EditorFlags EditorFlags + { + get + { + if (TryGetComponent(let flagsComponent)) + return flagsComponent.Flags; + + return .Default; + } + set + { + if (TryGetComponent(let flagsComponent)) + flagsComponent.Flags = value; + } + } + public T* AddComponent(T value = T()) where T: struct, new { Log.EngineLogger.AssertDebug(!HasComponent(), scope $"Entity already has component."); diff --git a/ScriptCore/Editor/EditorFlags.cs b/ScriptCore/Editor/EditorFlags.cs new file mode 100644 index 0000000..7c2fc27 --- /dev/null +++ b/ScriptCore/Editor/EditorFlags.cs @@ -0,0 +1,20 @@ +namespace GlitchyEngine.Editor; + +/// +/// Flags to controls the visibility of the entity in the editor and how it can be interacted with for editing. +/// +public enum EditorFlags : byte +{ + /// + /// The default behaviour: The entity is visible in the hierarchy and in the scene, and can be interacted with. + /// + Default = 0, + /// + /// The entity is hidden in the hierarchy. + /// + HideInHierarchy = 1, + /// + /// The entity is hidden in the scene. + /// + HideInScene = 2, +} diff --git a/ScriptCore/Entity.cs b/ScriptCore/Entity.cs index 8d22b7a..948aad1 100644 --- a/ScriptCore/Entity.cs +++ b/ScriptCore/Entity.cs @@ -7,6 +7,7 @@ using GlitchyEngine.Core; using GlitchyEngine.Extensions; using GlitchyEngine.Physics; using System.Diagnostics.CodeAnalysis; +using GlitchyEngine.Editor; namespace GlitchyEngine; @@ -23,6 +24,19 @@ public class Entity : EngineObject get => ScriptGlue.Entity_GetName(_uuid); set => ScriptGlue.Entity_SetName(_uuid, value); } + + /// + /// Gets or sets the of the , which specify how the is displayed and interacted with in the editor. + /// + public EditorFlags EditorFlags + { + get + { + ScriptGlue.Entity_GetEditorFlags(_uuid, out EditorFlags flags); + return flags; + } + set => ScriptGlue.Entity_SetEditorFlags(_uuid, value); + } /// /// Only to be called by the engine. Don't call this constructor yourself, it will not result in a valid . diff --git a/ScriptCore/ScriptGlue.cs b/ScriptCore/ScriptGlue.cs index c7a67a6..7a26d4c 100644 --- a/ScriptCore/ScriptGlue.cs +++ b/ScriptCore/ScriptGlue.cs @@ -2,6 +2,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using GlitchyEngine.Core; +using GlitchyEngine.Editor; using GlitchyEngine.Math; using GlitchyEngine.Physics; using GlitchyEngine.Serialization; @@ -64,6 +65,12 @@ internal static class ScriptGlue [MethodImpl(MethodImplOptions.InternalCall)] public static extern string Entity_SetName(UUID entityId, string name); + + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void Entity_GetEditorFlags(UUID uuid, out EditorFlags flags); + + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void Entity_SetEditorFlags(UUID uuid, EditorFlags editorFlags); #endregion Entity