From 9b9f5d111d464753c611b239630ccdcf5829fd87 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Tue, 13 Aug 2024 23:54:51 -0400 Subject: [PATCH] Partial Entity Exposed field implementation --- Editor/src/ComponentsPanel/NetScriptPanel.cpp | 35 ++++++++++++++ Editor/src/Windows/EditorInterface.cpp | 27 ++++++----- .../src/Scene/Components/NetScriptComponent.h | 21 ++++++++- Nuake/src/Scripting/ScriptingEngineNet.cpp | 46 +++++++++++++++++-- Nuake/src/Scripting/ScriptingEngineNet.h | 1 + NuakeNet/src/Entity.cs | 4 ++ 6 files changed, 117 insertions(+), 17 deletions(-) diff --git a/Editor/src/ComponentsPanel/NetScriptPanel.cpp b/Editor/src/ComponentsPanel/NetScriptPanel.cpp index 3d51746c..a32ec44c 100644 --- a/Editor/src/ComponentsPanel/NetScriptPanel.cpp +++ b/Editor/src/ComponentsPanel/NetScriptPanel.cpp @@ -208,6 +208,41 @@ void NetScriptPanel::Draw(Nuake::Entity entity) field.Value = currentValue; } + if (field.Type == Nuake::NetScriptExposedVarType::Entity) + { + if (!field.Value.has_value()) + { + field.Value = field.DefaultValue; + } + + + int entityId = std::any_cast(field.Value); + auto entity = Nuake::Engine::GetCurrentScene()->GetEntityByID(entityId); + bool invalid = !entity.IsValid(); + std::string buttonLabel; + if (invalid) + { + buttonLabel = "Invalid Entity*"; + } + else + { + buttonLabel = entity.GetComponent().Name; + } + + ImGui::Button(buttonLabel.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)); + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITY")) + { + Nuake::Entity payload_entity = *(const Nuake::Entity*)payload->Data; + + field.Value = payload_entity.GetID(); + } + ImGui::EndDragDropTarget(); + } + } + ImGui::TableNextColumn(); } } diff --git a/Editor/src/Windows/EditorInterface.cpp b/Editor/src/Windows/EditorInterface.cpp index 18e6afb3..e5c034fc 100644 --- a/Editor/src/Windows/EditorInterface.cpp +++ b/Editor/src/Windows/EditorInterface.cpp @@ -139,7 +139,6 @@ namespace Nuake { Overlay(); ImGuizmo::BeginFrame(); - ImGuizmo::SetOrthographic(false); ImVec2 regionAvail = ImGui::GetContentRegionAvail(); @@ -321,7 +320,7 @@ namespace Nuake { if (!Engine::IsPlayMode() && ImGui::GetIO().WantCaptureMouse && m_IsHoveringViewport && Input::IsMouseButtonPressed(GLFW_MOUSE_BUTTON_1) && !ImGuizmo::IsUsing() && m_IsViewportFocused) { - const auto windowPosNuake = Vector2(windowPos.x, windowPos.y); + auto& gbuffer = Engine::GetCurrentScene()->m_SceneRenderer->GetGBuffer(); auto pixelPos = Input::GetMousePosition() - windowPosNuake; @@ -367,6 +366,8 @@ namespace Nuake { } ImGui::End(); + + } void EditorInterface::DrawStatusBar() @@ -671,15 +672,17 @@ namespace Nuake { bool open = ImGui::TreeNodeEx(name.c_str(), base_flags); - if(nameComponent.IsPrefab && e.HasComponent()) + bool isDragging = false; + if (nameComponent.IsPrefab && e.HasComponent()) + { ImGui::PopStyleColor(); - else - if (ImGui::BeginDragDropSource()) - { - ImGui::SetDragDropPayload("ENTITY", (void*)&e, sizeof(Entity)); - ImGui::Text(name.c_str()); - ImGui::EndDragDropSource(); - } + } + else if (ImGui::BeginDragDropSource()) + { + ImGui::SetDragDropPayload("ENTITY", (void*)&e, sizeof(Entity)); + ImGui::Text(name.c_str()); + ImGui::EndDragDropSource(); + } if (ImGui::BeginDragDropTarget()) { @@ -706,7 +709,7 @@ namespace Nuake { ImGui::EndDragDropTarget(); } - if (ImGui::IsItemClicked()) + if (!isDragging && ImGui::IsItemHovered() && ImGui::IsMouseReleased(0)) Selection = EditorSelection(e); if (ImGui::BeginPopupContextItem()) @@ -1785,7 +1788,7 @@ namespace Nuake { } ImGui::End(); - std::string title = ICON_FA_TREE + std::string(" Hierarchy"); + std::string title = ICON_FA_TREE + std::string(" Hierarchy"); if (ImGui::Begin(title.c_str())) { std::string searchQuery = ""; diff --git a/Nuake/src/Scene/Components/NetScriptComponent.h b/Nuake/src/Scene/Components/NetScriptComponent.h index 9d4e86d8..eb2f5042 100644 --- a/Nuake/src/Scene/Components/NetScriptComponent.h +++ b/Nuake/src/Scene/Components/NetScriptComponent.h @@ -95,6 +95,15 @@ namespace Nuake { varJ["DefaultValue"][2] = value.z; break; } + case NetScriptExposedVarType::Entity: + { + int value = std::any_cast(e.Value); + varJ["Value"] = value; + + value = std::any_cast(e.DefaultValue); + varJ["DefaultValue"] = value; + break; + } default: varJ["Value"] = 0; break; @@ -150,12 +159,10 @@ namespace Nuake { { float x = exposedVarJson["Value"][0]; float y = exposedVarJson["Value"][1]; - exposedVar.Value = Vector2(x, y); x = exposedVarJson["DefaultValue"][0]; y = exposedVarJson["DefaultValue"][1]; - exposedVar.DefaultValue = Vector2(x, y); break; } @@ -170,6 +177,16 @@ namespace Nuake { y = exposedVarJson["DefaultValue"][1]; z = exposedVarJson["DefaultValue"][2]; exposedVar.DefaultValue = Vector3(x, y, z); + break; + } + case NetScriptExposedVarType::Entity: + { + int x = exposedVarJson["Value"]; + exposedVar.Value = x; + + x = exposedVarJson["DefaultValue"]; + exposedVar.DefaultValue = x; + break; } default: exposedVar.DefaultValue = 0; diff --git a/Nuake/src/Scripting/ScriptingEngineNet.cpp b/Nuake/src/Scripting/ScriptingEngineNet.cpp index 64aeb43f..39f23743 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.cpp +++ b/Nuake/src/Scripting/ScriptingEngineNet.cpp @@ -181,6 +181,8 @@ namespace Nuake const std::string baseTypeName = std::string(type->GetBaseType().GetFullName()); if (baseTypeName == "Nuake.Net.Entity") { + m_BaseEntityType = type->GetBaseType(); + auto typeSplits = String::Split(type->GetFullName(), '.'); std::string shortenedTypeName = typeSplits[typeSplits.size() - 1]; @@ -223,6 +225,10 @@ namespace Nuake { varType = ExposedVarTypes::Vector3; } + else if (typeName == "Nuake.Net.Entity") + { + varType = ExposedVarTypes::Entity; + } if (varType != ExposedVarTypes::Unsupported) { @@ -323,12 +329,20 @@ namespace Nuake } case ExposedVarTypes::Entity: { - exposedVar.Value = classInstance.GetFieldValue(varName); + struct EntityWrapper + { + int32_t id; + int32_t handle; + }; + + exposedVar.Value = classInstance.GetFieldValue(varName).id; break; } } } + m_EntityToManagedObjects.emplace(entity.GetID(), classInstance); + // Override with user values set in the editor. for (auto& exposedVarUserValue : component.ExposedVar) { @@ -338,13 +352,39 @@ namespace Nuake Coral::String coralString = Coral::String::New(stringValue); classInstance.SetFieldValue(exposedVarUserValue.Name, coralString); } + else if (exposedVarUserValue.Type == NetScriptExposedVarType::Entity) + { + int entityId = std::any_cast(exposedVarUserValue.Value); + Entity scriptEntity = entity.GetScene()->GetEntityByID(entityId); + if (scriptEntity.IsValid()) + { + if (HasEntityScriptInstance(scriptEntity)) + { + // In the case the entity has a script & instance, we pass that. + // This gives access to the objects scripts. + auto scriptInstance = GetEntityScript(scriptEntity); + classInstance.SetFieldValue(exposedVarUserValue.Name, scriptInstance); + } + else + { + // In the case where the entity doesnt have an instance, we create one + auto newEntity = m_BaseEntityType.CreateInstance(); + newEntity.SetPropertyValue("ECSHandle", scriptEntity.GetHandle()); + newEntity.SetPropertyValue("ID", scriptEntity.GetID()); + + classInstance.SetFieldValue(exposedVarUserValue.Name, newEntity); + } + } + else + { + Logger::Log("Invalid entity exposed variable set", ".net", CRITICAL); + } + } else { classInstance.SetFieldValue(exposedVarUserValue.Name, exposedVarUserValue.Value); } } - - m_EntityToManagedObjects.emplace(entity.GetID(), classInstance); } Coral::ManagedObject ScriptingEngineNet::GetEntityScript(const Entity& entity) diff --git a/Nuake/src/Scripting/ScriptingEngineNet.h b/Nuake/src/Scripting/ScriptingEngineNet.h index 80430e85..e5f9c797 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.h +++ b/Nuake/src/Scripting/ScriptingEngineNet.h @@ -51,6 +51,7 @@ namespace Nuake { const std::string m_NetDirectory = ".net"; const std::string m_ContextName = "NuakeEngineContext"; + Coral::Type m_BaseEntityType; bool m_IsInitialized = false; Coral::HostInstance* m_HostInstance; diff --git a/NuakeNet/src/Entity.cs b/NuakeNet/src/Entity.cs index a28b0e0c..8f62ebc7 100644 --- a/NuakeNet/src/Entity.cs +++ b/NuakeNet/src/Entity.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -17,6 +18,7 @@ namespace Nuake.Net Vector3 Position; } + [StructLayout(LayoutKind.Sequential)] public class Entity { internal static unsafe delegate* EntityHasComponentIcall; @@ -49,8 +51,10 @@ namespace Nuake.Net NAVMESH } + public int ID { get; set; } public int ECSHandle { get; set; } + public virtual void OnInit() { } public virtual void OnUpdate(float dt) { } public virtual void OnFixedUpdate(float dt) { }