diff --git a/Editor/src/ComponentsPanel/NetScriptPanel.cpp b/Editor/src/ComponentsPanel/NetScriptPanel.cpp index 47addc2a..00b3488e 100644 --- a/Editor/src/ComponentsPanel/NetScriptPanel.cpp +++ b/Editor/src/ComponentsPanel/NetScriptPanel.cpp @@ -169,6 +169,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity) { if (!field.Value.has_value()) { + if (!field.DefaultValue.has_value()) + { + field.DefaultValue = std::string(); + } + field.Value = field.DefaultValue; } diff --git a/Editor/src/Windows/ProjectInterface.cpp b/Editor/src/Windows/ProjectInterface.cpp index 65ef0868..1edd1a7d 100644 --- a/Editor/src/Windows/ProjectInterface.cpp +++ b/Editor/src/Windows/ProjectInterface.cpp @@ -2,6 +2,8 @@ #include #include "Engine.h" #include "src/Core/FileSystem.h" +#include +#include //#include "ImGuiTextHelper.h" namespace Nuake { @@ -45,7 +47,7 @@ namespace Nuake { ImGui::Text("Trenchbroom path:"); ImGui::SameLine(); - //ImGuiTextSTD("", m_CurrentProject->TrenchbroomPath); + ImGui::Text(m_CurrentProject->TrenchbroomPath.c_str()); ImGui::SameLine(); if (ImGui::Button("Browse")) { @@ -112,6 +114,38 @@ namespace Nuake { ImGui::EndPopup(); } + if (ImGui::Button("Scan from assembly")) + { + file->BrushEntities.clear(); + for (auto& [name, type] : Nuake::ScriptingEngineNet::Get().GetBrushEntities()) + { + FGDBrushEntity brushEntity = FGDBrushEntity(name); + brushEntity.Script = name; + brushEntity.Description = type.Description; + brushEntity.IsTrigger = type.isTrigger; + for (auto& t : type.exposedVars) + { + ClassProperty classProp; + classProp.name = t.Name; + classProp.type = ClassPropertyType::String; + if (t.Type == ExposedVarTypes::String && t.Value.has_value()) + { + classProp.value = std::any_cast(t.Value); + } + else if (t.Type == ExposedVarTypes::Int) + { + classProp.value = std::to_string(std::any_cast(t.Value)); + } + else + { + classProp.value = ""; + } + brushEntity.Properties.push_back(classProp); + } + + file->BrushEntities.push_back(brushEntity); + } + } if (ImGui::Button("Export")) { @@ -201,10 +235,12 @@ namespace Nuake { int i = 0; for (auto& pE : file->BrushEntities) { + ImGui::Text(pE.Name.c_str()); //ImGuiTextSTD("##Name" + std::to_string(i), pE.Name); ImGui::TableNextColumn(); //ImGuiTextSTD("Desc" + std::to_string(i), pE.Description); + ImGui::Text(pE.Description.c_str()); ImGui::TableNextColumn(); ImGui::Checkbox(std::string("Visible##" + std::to_string(i)).c_str(), &pE.Visible); @@ -216,17 +252,7 @@ namespace Nuake { ImGui::TableNextColumn(); //ImGuiTextSTD("Script##" + std::to_string(i), pE.Script); - if (ImGui::BeginDragDropTarget()) - { - if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Script")) - { - char* file = (char*)payload->Data; - std::string fullPath = std::string(file, 256); - pE.Script = FileSystem::AbsoluteToRelative(fullPath); - } - - ImGui::EndDragDropTarget(); - } + //ImGuiTextSTD("Class##" + std::to_string(i), pE.Class); ImGui::TableNextColumn(); diff --git a/Nuake/Engine.cpp b/Nuake/Engine.cpp index 7fbd6043..e165c7fc 100644 --- a/Nuake/Engine.cpp +++ b/Nuake/Engine.cpp @@ -169,6 +169,8 @@ namespace Nuake } FileSystem::SetRootDirectory(FileSystem::GetParentPath(project->FullPath)); + ScriptingEngineNet::Get().LoadProjectAssembly(project); + return true; } diff --git a/Nuake/src/Core/FileSystem.cpp b/Nuake/src/Core/FileSystem.cpp index 4ce2c6a3..3347005f 100644 --- a/Nuake/src/Core/FileSystem.cpp +++ b/Nuake/src/Core/FileSystem.cpp @@ -19,6 +19,7 @@ #include #include +#include namespace Nuake { @@ -42,6 +43,7 @@ namespace Nuake { filePath = std::string(ofn.lpstrFile); } + #endif #ifdef NK_LINUX @@ -141,6 +143,55 @@ namespace Nuake return std::string(); } + std::string FileDialog::OpenFolder() + { + std::string folderPath; + +#ifdef NK_WIN + BROWSEINFOA bi; + CHAR szFolder[260] = { 0 }; + ZeroMemory(&bi, sizeof(BROWSEINFO)); + bi.lpszTitle = "Select a Folder"; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; + bi.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle()); + bi.pszDisplayName = szFolder; + LPITEMIDLIST pidl = SHBrowseForFolderA(&bi); + if (pidl != NULL) + { + SHGetPathFromIDListA(pidl, szFolder); + folderPath = std::string(szFolder); + CoTaskMemFree(pidl); + } +#endif + +#ifdef NK_LINUX + GtkWidget* dialog; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + gint res; + + dialog = gtk_file_chooser_dialog_new("Select Folder", + NULL, + action, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Select", + GTK_RESPONSE_ACCEPT, + NULL); + + res = gtk_dialog_run(GTK_DIALOG(dialog)); + + if (res == GTK_RESPONSE_ACCEPT) { + char* foldername = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + folderPath = foldername; + g_free(foldername); + } + + gtk_widget_destroy(dialog); +#endif + + return folderPath; + } + std::string FileSystem::Root = ""; Ref FileSystem::RootDirectory; diff --git a/Nuake/src/Core/FileSystem.h b/Nuake/src/Core/FileSystem.h index e6ec8c1c..c9d73ba2 100644 --- a/Nuake/src/Core/FileSystem.h +++ b/Nuake/src/Core/FileSystem.h @@ -14,6 +14,7 @@ namespace Nuake public: static std::string OpenFile(const char* filter); static std::string SaveFile(const char* filter); + static std::string OpenFolder(); }; class Directory; diff --git a/Nuake/src/Resource/FGD/ClassProperty.h b/Nuake/src/Resource/FGD/ClassProperty.h index fe57de87..d36f3519 100644 --- a/Nuake/src/Resource/FGD/ClassProperty.h +++ b/Nuake/src/Resource/FGD/ClassProperty.h @@ -2,10 +2,10 @@ #include enum class ClassPropertyType { - String, - Integer, - Float, Boolean, + String, + Float, + Integer, AABB, Choices, Color, @@ -20,4 +20,5 @@ struct ClassProperty { std::string name; ClassPropertyType type; std::string description; + std::string value; }; \ No newline at end of file diff --git a/Nuake/src/Resource/FGD/FGDSerializer.cpp b/Nuake/src/Resource/FGD/FGDSerializer.cpp index a254646b..94379be9 100644 --- a/Nuake/src/Resource/FGD/FGDSerializer.cpp +++ b/Nuake/src/Resource/FGD/FGDSerializer.cpp @@ -112,8 +112,19 @@ namespace Nuake { line += "("; if (p.type == ClassPropertyType::Integer) line += "integer"; + if (p.type == ClassPropertyType::String) + line += "string"; line += ") : "; line += "\"" + p.description + "\""; + line += " : "; + if (p.type == ClassPropertyType::String) + { + line += " \"" + p.value + "\" "; + } + else if (p.type == ClassPropertyType::Integer) + { + line += p.value; + } line += "\n"; } diff --git a/Nuake/src/Scene/Components/BSPBrushComponent.h b/Nuake/src/Scene/Components/BSPBrushComponent.h index dcae95ce..11cbf8de 100644 --- a/Nuake/src/Scene/Components/BSPBrushComponent.h +++ b/Nuake/src/Scene/Components/BSPBrushComponent.h @@ -17,6 +17,7 @@ namespace Nuake { std::vector> Rigidbody; std::string target = ""; + std::string TargetName = ""; std::vector Targets; bool IsSolid = true; @@ -50,6 +51,8 @@ namespace Nuake { j["Hulls"][i] = hullPointsJson; } + SERIALIZE_VAL(target); + SERIALIZE_VAL(TargetName); j["IsSolid"] = IsSolid; END_SERIALIZE(); } @@ -78,6 +81,9 @@ namespace Nuake { } } + DESERIALIZE_VAL(target); + DESERIALIZE_VAL(TargetName); + return true; } }; diff --git a/Nuake/src/Scene/EditorCamera.h b/Nuake/src/Scene/EditorCamera.h index 891a9f69..0b90b85d 100644 --- a/Nuake/src/Scene/EditorCamera.h +++ b/Nuake/src/Scene/EditorCamera.h @@ -14,9 +14,9 @@ namespace Nuake EditorCamera() { - Yaw = 0.0f; - Translation = Vector3(10, 10, 10); - SetDirection(Vector3(-1, -1, -1)); + SetYaw(-90.0f - 45.0f); + SetPitch(-45.0f); + Translation = Vector3(2, 2, 2); } void Update(Timestep ts, const bool hover); diff --git a/Nuake/src/Scene/Systems/PhysicsSystem.cpp b/Nuake/src/Scene/Systems/PhysicsSystem.cpp index abf12b7f..5b29450c 100644 --- a/Nuake/src/Scene/Systems/PhysicsSystem.cpp +++ b/Nuake/src/Scene/Systems/PhysicsSystem.cpp @@ -112,13 +112,13 @@ namespace Nuake void PhysicsSystem::InitializeQuakeMap() { - auto quakeBrushesView = m_Scene->m_Registry.view(); + auto quakeBrushesView = m_Scene->m_Registry.view(); for (auto e : quakeBrushesView) { - const auto [transformComponent, brushComponent, modelComponent] = quakeBrushesView.get(e); + const auto [transformComponent, brushComponent] = quakeBrushesView.get(e); // Doesn't apply to non-solid brushes - if (!brushComponent.IsSolid) + if ((!brushComponent.IsSolid && !brushComponent.IsTrigger)) { continue; } @@ -133,7 +133,7 @@ namespace Nuake auto rigidBody = CreateRef(0.0f, startPosition, startRotation, startTransform, collisionShape, entity); brushComponent.Rigidbody.push_back(rigidBody); - + rigidBody->SetIsTrigger(brushComponent.IsTrigger); PhysicsManager::Get().RegisterBody(rigidBody); } } diff --git a/Nuake/src/Scene/Systems/QuakeMapBuilder.cpp b/Nuake/src/Scene/Systems/QuakeMapBuilder.cpp index e7468358..240711ad 100644 --- a/Nuake/src/Scene/Systems/QuakeMapBuilder.cpp +++ b/Nuake/src/Scene/Systems/QuakeMapBuilder.cpp @@ -28,6 +28,8 @@ extern "C" { #include #include #include +#include +#include namespace Nuake { struct ProcessedMesh @@ -228,7 +230,7 @@ namespace Nuake { void QuakeMapBuilder::CreateFuncBrush(brush* brush, brush_geometry* brush_inst, Scene* scene, Entity& parent, - const std::string& target, const std::string& targetname, FGDBrushEntity fgdBrush) + const std::string& target, const std::string& targetname, FGDBrushEntity fgdBrush, std::map props) { std::vector vertices; std::vector indices; @@ -246,20 +248,27 @@ namespace Nuake { bsp.IsTransparent = !fgdBrush.Visible; bsp.IsFunc = true; bsp.IsTrigger = fgdBrush.IsTrigger; - if (fgdBrush.Script != "" && fgdBrush.Class != "") + if (fgdBrush.Script != "") { - auto& wrenScript = brushEntity.AddComponent(); - wrenScript.Script = fgdBrush.Script; - wrenScript.mModule = 0; // TODO - } - - if (bsp.IsTrigger) - { - TriggerZone& trigger = brushEntity.AddComponent(); - trigger.target = target; + NetScriptComponent& netScript = brushEntity.AddComponent(); + netScript.ScriptPath = fgdBrush.Script; + + ScriptingEngineNet::Get().UpdateEntityWithExposedVar(brushEntity); + for (auto& ev : netScript.ExposedVar) + { + if (props.find(ev.Name) != props.end()) + { + if (ev.Type == NetScriptExposedVarType::String) + { + ev.Value = props[ev.Name]; + ev.DefaultValue = ev.Value; + } + } + } } bsp.target = target; + bsp.TargetName = targetname; parent.AddChild(brushEntity); @@ -271,7 +280,7 @@ namespace Nuake { int index_offset = 0; int lastTextureID = -1; std::string lastTexturePath = ""; - + std::vector pointsInBrush; for (int f = 0; f < brush->face_count; ++f) { face* face = &brush->faces[f]; @@ -302,6 +311,8 @@ namespace Nuake { (vertex.vertex.x - brush->center.x) * ScaleFactor * (1.0f / 64) ); + + pointsInBrush.push_back(vertexPos); Vector2 vertexUV = Vector2(vertex_uv.u, vertex_uv.v); Vector3 vertexNormal = Vector3(vertex.normal.y, vertex.normal.z, vertex.normal.x); Vector3 vertexTangent = Vector3(vertex.tangent.y, vertex.tangent.z, vertex.tangent.x); @@ -354,6 +365,7 @@ namespace Nuake { index_offset += (face_geo_inst->vertex_count); } } + bsp.Hulls.push_back(std::move(pointsInBrush)); if (bsp.IsTrigger) { @@ -372,6 +384,12 @@ namespace Nuake { Ref material = MaterialManager::Get()->GetMaterial(lastTexturePath); mesh->SetMaterial(material); bsp.Meshes.push_back(mesh); + + ModelComponent& modelComponent = brushEntity.AddComponent(); + + Ref model = CreateRef(); + model->AddMesh(mesh); + modelComponent.ModelResource = model; } } @@ -422,11 +440,14 @@ namespace Nuake { bool isWorldSpawn = false; bool isPointEntity = false; Vector3 brushLocalPosition = { 0, 0, 0 }; + std::map properties; for (int i = 0; i < entity_inst->property_count; i++) { property* prop = &(entity_inst->properties)[i]; + std::string key = prop->key; std::string value = prop->value; + properties[key] = value; if (key == "origin") { @@ -515,8 +536,8 @@ namespace Nuake { brush* brush_inst = &entity_inst->brushes[b]; brush_geometry* brush_geo_inst = &entity_geo_inst->brushes[b]; - //if (isEntity) - // CreateFuncBrush(brush_inst, brush_geo_inst, m_Scene, newEntity, target, targetname, fgdBrush); + if (isEntity) + CreateFuncBrush(brush_inst, brush_geo_inst, m_Scene, worldspawnEntity, target, targetname, *fgdBrush, properties); //else // CreateBrush(brush_inst, brush_geo_inst, m_Scene, newEntity, target, targetname); } diff --git a/Nuake/src/Scene/Systems/QuakeMapBuilder.h b/Nuake/src/Scene/Systems/QuakeMapBuilder.h index ab6ffefe..90e1366b 100644 --- a/Nuake/src/Scene/Systems/QuakeMapBuilder.h +++ b/Nuake/src/Scene/Systems/QuakeMapBuilder.h @@ -1,5 +1,6 @@ #pragma once #include +#include struct brush; struct brush_geometry; @@ -23,7 +24,7 @@ namespace Nuake { void CreateFuncBrush(brush* brush, brush_geometry* brush_inst, Scene* scene, Entity& parent, - const std::string& target, const std::string& targetname, FGDBrushEntity fgdBrush); + const std::string& target, const std::string& targetname, FGDBrushEntity fgdBrush, std::map props); public: QuakeMapBuilder() {} diff --git a/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp b/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp index 2e44d192..44c373cf 100644 --- a/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp +++ b/Nuake/src/Scripting/NetModules/SceneNetAPI.cpp @@ -206,6 +206,45 @@ namespace Nuake { return entity.IsValid(); } + Coral::String EntityGetTarget(int handle) + { + Entity entity = { (entt::entity)(handle), Engine::GetCurrentScene().get() }; + if (entity.IsValid()) + { + if (entity.HasComponent()) + { + return Coral::String::New(entity.GetComponent().target); + } + } + + return Coral::String::New(""); + } + + Coral::Array EntityGetTargets(Coral::String target) + { + std::vector targetsFound = std::vector(); + + if (target == "") + { + return Coral::Array::New(targetsFound); + } + + Ref scene = Engine::GetCurrentScene(); + auto brushView = scene->m_Registry.view(); + for (auto e : brushView) + { + BSPBrushComponent& brushComponent = brushView.get(e); + if (brushComponent.TargetName == target) + { + Entity entity = { (entt::entity)(e), scene.get() }; + + targetsFound.push_back(entity.GetHandle()); + } + } + + return Coral::Array::New(targetsFound); + } + int PrefabInstance(Coral::String path, Vector3 position, float qx, float qy, float qz, float qw) { if (!FileSystem::FileExists(path)) @@ -397,7 +436,8 @@ namespace Nuake { RegisterMethod("Entity.EntityGetNameIcall", &EntityGetName); RegisterMethod("Entity.EntitySetNameIcall", &EntitySetName); RegisterMethod("Entity.EntityIsValidIcall", &EntityIsValid); - + RegisterMethod("Entity.EntityGetTargetsIcall", &EntityGetTargets); + RegisterMethod("Entity.EntityGetTargetIcall", &EntityGetTarget); // Prefab RegisterMethod("Prefab.PrefabInstanceIcall", &PrefabInstance); diff --git a/Nuake/src/Scripting/ScriptingEngineNet.cpp b/Nuake/src/Scripting/ScriptingEngineNet.cpp index d02b43e2..1c4809f5 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.cpp +++ b/Nuake/src/Scripting/ScriptingEngineNet.cpp @@ -14,6 +14,7 @@ #include #include +#include void ExceptionCallback(std::string_view InMessage) @@ -66,8 +67,6 @@ namespace Nuake m_IsInitialized = false; return; } - - } ScriptingEngineNet::~ScriptingEngineNet() @@ -180,6 +179,42 @@ namespace Nuake m_EntityToManagedObjects.clear(); } + void ScriptingEngineNet::UpdateEntityWithExposedVar(Entity entity) + { + if (!entity.HasComponent()) + { + return; + } + + std::vector detectedExposedVar; + NetScriptComponent& component = entity.GetComponent(); + for (auto& e : Nuake::ScriptingEngineNet::Get().GetExposedVarForTypes(entity)) + { + bool found = false; + for (auto& c : component.ExposedVar) + { + if (e.Name == c.Name) + { + c.Type = (Nuake::NetScriptExposedVarType)e.Type; + c.DefaultValue = e.Value; + found = true; + } + } + + detectedExposedVar.push_back(e.Name); + + if (!found) + { + Nuake::NetScriptExposedVar exposedVar; + exposedVar.Name = e.Name; + exposedVar.Value = e.Value; + exposedVar.DefaultValue = e.Value; + exposedVar.Type = (Nuake::NetScriptExposedVarType)e.Type; + component.ExposedVar.push_back(exposedVar); + } + } + } + std::vector ScriptingEngineNet::GetExposedVarForTypes(Entity entity) { if (!entity.HasComponent()) @@ -189,7 +224,16 @@ namespace Nuake auto& component = entity.GetComponent(); const auto& filePath = component.ScriptPath; - const std::string& className = FindClassNameInScript(filePath); + + std::string className; + if (String::EndsWith(filePath, ".cs")) + { + className = FindClassNameInScript(filePath);; + } + else + { + className = filePath; + } if (m_GameEntityTypes.find(className) == m_GameEntityTypes.end()) { @@ -246,78 +290,105 @@ namespace Nuake m_PrefabType = m_GameAssembly.GetType("Nuake.Net.Prefab"); auto& exposedFieldAttributeType = m_GameAssembly.GetType("Nuake.Net.ExposedAttribute"); + auto& brushScriptAttributeType = m_GameAssembly.GetType("Nuake.Net.BrushScript"); for (auto& type : m_GameAssembly.GetTypes()) { - const std::string baseTypeName = std::string(type->GetBaseType().GetFullName()); - if (baseTypeName == "Nuake.Net.Entity") + bool isBrushScript = false; + std::string brushDescription; + bool isTrigger = false; + for (auto& attribute : type->GetAttributes()) { - m_BaseEntityType = type->GetBaseType(); - - auto typeSplits = String::Split(type->GetFullName(), '.'); - std::string shortenedTypeName = typeSplits[typeSplits.size() - 1]; - - NetGameScriptObject gameScriptObject; - gameScriptObject.coralType = type; - gameScriptObject.exposedVars = std::vector(); - - for (auto& f : type->GetFields()) + if (attribute.GetType() != brushScriptAttributeType) { - for (auto& a : f.GetAttributes()) - { - if (a.GetType() == exposedFieldAttributeType) - { - ExposedVar exposedVar; - exposedVar.Name = f.GetName(); - - auto typeName = f.GetType().GetFullName(); - ExposedVarTypes varType = ExposedVarTypes::Unsupported; - if (typeName == "System.Single") - { - varType = ExposedVarTypes::Float; - } - else if (typeName == "System.Double") - { - varType = ExposedVarTypes::Double; - } - else if (typeName == "System.String") - { - varType = ExposedVarTypes::String; - } - else if (typeName == "System.Boolean") - { - varType = ExposedVarTypes::Bool; - } - else if (typeName == "System.Numerics.Vector2") - { - varType = ExposedVarTypes::Vector2; - } - else if (typeName == "System.Numerics.Vector3") - { - varType = ExposedVarTypes::Vector3; - } - else if (typeName == "Nuake.Net.Entity") - { - varType = ExposedVarTypes::Entity; - } - else if (typeName == "Nuake.Net.Prefab") - { - varType = ExposedVarTypes::Prefab; - } - - if (varType != ExposedVarTypes::Unsupported) - { - exposedVar.Type = varType; - gameScriptObject.exposedVars.push_back(exposedVar); - } - - Logger::Log("Exposed field detected: " + std::string(f.GetName()) + " of type " + std::string(f.GetType().GetFullName()) ); - } - } + continue; } - m_GameEntityTypes[shortenedTypeName] = gameScriptObject; + brushDescription = attribute.GetFieldValue("Description"); + isTrigger = attribute.GetFieldValue("IsTrigger"); + + isBrushScript = true; } + + const std::string baseTypeName = std::string(type->GetBaseType().GetFullName()); + if (baseTypeName != "Nuake.Net.Entity") + { + continue; + } + + m_BaseEntityType = type->GetBaseType(); + + auto typeSplits = String::Split(type->GetFullName(), '.'); + std::string shortenedTypeName = typeSplits[typeSplits.size() - 1]; + + NetGameScriptObject gameScriptObject; + gameScriptObject.coralType = type; + gameScriptObject.exposedVars = std::vector(); + + for (auto& f : type->GetFields()) + { + for (auto& a : f.GetAttributes()) + { + if (a.GetType() == exposedFieldAttributeType) + { + ExposedVar exposedVar; + exposedVar.Name = f.GetName(); + + auto typeName = f.GetType().GetFullName(); + ExposedVarTypes varType = ExposedVarTypes::Unsupported; + if (typeName == "System.Single") + { + varType = ExposedVarTypes::Float; + } + else if (typeName == "System.Double") + { + varType = ExposedVarTypes::Double; + } + else if (typeName == "System.String") + { + varType = ExposedVarTypes::String; + } + else if (typeName == "System.Boolean") + { + varType = ExposedVarTypes::Bool; + } + else if (typeName == "System.Numerics.Vector2") + { + varType = ExposedVarTypes::Vector2; + } + else if (typeName == "System.Numerics.Vector3") + { + varType = ExposedVarTypes::Vector3; + } + else if (typeName == "Nuake.Net.Entity") + { + varType = ExposedVarTypes::Entity; + } + else if (typeName == "Nuake.Net.Prefab") + { + varType = ExposedVarTypes::Prefab; + } + + if (varType != ExposedVarTypes::Unsupported) + { + exposedVar.Type = varType; + gameScriptObject.exposedVars.push_back(exposedVar); + } + + Logger::Log("Exposed field detected: " + std::string(f.GetName()) + " of type " + std::string(f.GetType().GetFullName()) ); + } + } + } + + // Add to the brush map to retrieve when exporting FGD + if (isBrushScript) + { + gameScriptObject.Description = brushDescription; + gameScriptObject.isTrigger = isTrigger; + m_BrushEntityTypes[shortenedTypeName] = gameScriptObject; + } + + m_GameEntityTypes[shortenedTypeName] = gameScriptObject; } } @@ -344,7 +415,15 @@ namespace Nuake const auto& filePath = component.ScriptPath; - const std::string& className = FindClassNameInScript(filePath); + std::string className; + if (String::EndsWith(filePath, ".cs")) + { + className = FindClassNameInScript(filePath); + } + else + { + className = filePath; + } if(m_GameEntityTypes.find(className) == m_GameEntityTypes.end()) { @@ -361,6 +440,13 @@ namespace Nuake int id = entity.GetID(); classInstance.SetPropertyValue("ECSHandle", handle); classInstance.SetPropertyValue("ID", id); + + if (entity.HasComponent()) + { + BSPBrushComponent& brushComponent = entity.GetComponent(); + classInstance.SetPropertyValue("TargetName", brushComponent.TargetName); + classInstance.SetPropertyValue("Target", brushComponent.target); + } std::vector detectedExposedVar; detectedExposedVar.reserve(std::size(m_GameEntityTypes[className].exposedVars)); @@ -384,7 +470,13 @@ namespace Nuake } case ExposedVarTypes::String: { - exposedVar.Value = std::string(classInstance.GetFieldValue(varName)); + try { + //exposedVar.Value = std::string(classInstance.GetFieldValue(varName)); + } + catch (...) + { + } + break; } case ExposedVarTypes::Bool: diff --git a/Nuake/src/Scripting/ScriptingEngineNet.h b/Nuake/src/Scripting/ScriptingEngineNet.h index 0811f8a2..4841c07b 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.h +++ b/Nuake/src/Scripting/ScriptingEngineNet.h @@ -32,6 +32,7 @@ namespace Nuake { Vector2, Vector3, Vector4, + Int, Unsupported }; @@ -46,6 +47,9 @@ namespace Nuake { { Coral::Type* coralType; std::vector exposedVars; + + bool isTrigger = false; + std::string Description = ""; }; struct CompilationError @@ -81,6 +85,7 @@ namespace Nuake { // This is a map that contains all the instances of entity scripts. std::unordered_map m_GameEntityTypes; + std::unordered_map m_BrushEntityTypes; std::unordered_map m_EntityToManagedObjects; ScriptingEngineNet(); @@ -99,8 +104,10 @@ namespace Nuake { void Initialize(); void Uninitialize(); + bool IsInitialized() const { return m_IsInitialized; } + void UpdateEntityWithExposedVar(Entity entity); std::vector GetExposedVarForTypes(Entity entity); std::vector BuildProjectAssembly(Ref project); @@ -118,6 +125,7 @@ namespace Nuake { Coral::ManagedAssembly GetNuakeAssembly() const { return m_NuakeAssembly; } + std::unordered_map GetBrushEntities() const { return m_BrushEntityTypes; } private: std::string GenerateGUID(); }; diff --git a/NuakeNet/src/BrushScript.cs b/NuakeNet/src/BrushScript.cs new file mode 100644 index 00000000..090cbfc9 --- /dev/null +++ b/NuakeNet/src/BrushScript.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nuake.Net +{ + [BrushScript] + public class Brush : Entity + { + + } +} diff --git a/NuakeNet/src/Entity.cs b/NuakeNet/src/Entity.cs index bfc6ff86..f266ff32 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.Reflection.Metadata; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -27,6 +28,8 @@ namespace Nuake.Net internal static unsafe delegate* EntityGetNameIcall; internal static unsafe delegate* EntitySetNameIcall; internal static unsafe delegate* EntityIsValidIcall; + internal static unsafe delegate*> EntityGetTargetsIcall; + internal static unsafe delegate* EntityGetTargetIcall; public enum ComponentTypes { @@ -55,6 +58,37 @@ namespace Nuake.Net NAVMESH } + public List Targets + { + get + { + unsafe + { + var targetIds = EntityGetTargetsIcall(Target); + + List targets = new List(); + foreach(var target in targetIds) + { + bool hasInstance = EntityHasManagedInstanceIcall(target); + Entity entityInstance; + if (hasInstance) + { + entityInstance = Scene.GetEntity(target); + } + else + { + entityInstance = new Entity(ECSHandle); + } + + targets.Add(entityInstance); + } + + return targets; + } + } + } + + public string Target { get { unsafe { return EntityGetTargetIcall(ECSHandle); } }} public int ID { get; set; } public int ECSHandle { get; set; } = -1; @@ -99,6 +133,11 @@ namespace Nuake.Net { } + public virtual void Activate(Entity triggeredFrom) + { + + } + // Physics public void OnCollisionInternal(int entity) { diff --git a/NuakeNet/src/main.cs b/NuakeNet/src/main.cs index e46b4357..51cfd080 100644 --- a/NuakeNet/src/main.cs +++ b/NuakeNet/src/main.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Nuake.Net @@ -35,6 +36,19 @@ namespace Nuake.Net { } + [AttributeUsage(AttributeTargets.Class)] + public sealed class BrushScript : Attribute + { + public string Description = ""; + public bool IsTrigger = false; + + public BrushScript(string description = "", bool isTrigger = false) + { + Description = description; + IsTrigger = isTrigger; + } + } + public class Debug { internal static unsafe delegate*