Added C# -> Trenchbrom entity definition with reflection system

This commit is contained in:
Antoine Pilote
2024-08-30 21:44:08 -04:00
parent d46f74aa24
commit 85b41e9ea0
18 changed files with 439 additions and 107 deletions

View File

@@ -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;
}

View File

@@ -2,6 +2,8 @@
#include <src/Vendors/imgui/imgui.h>
#include "Engine.h"
#include "src/Core/FileSystem.h"
#include <src/Scripting/ScriptingEngineNet.h>
#include <src/Scripting/ScriptingEngineNet.h>
//#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<std::string>(t.Value);
}
else if (t.Type == ExposedVarTypes::Int)
{
classProp.value = std::to_string(std::any_cast<int>(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();

View File

@@ -169,6 +169,8 @@ namespace Nuake
}
FileSystem::SetRootDirectory(FileSystem::GetParentPath(project->FullPath));
ScriptingEngineNet::Get().LoadProjectAssembly(project);
return true;
}

View File

@@ -19,6 +19,7 @@
#include <fstream>
#include <iostream>
#include <ShlObj.h>
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<Directory> FileSystem::RootDirectory;

View File

@@ -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;

View File

@@ -2,10 +2,10 @@
#include <string>
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;
};

View File

@@ -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";
}

View File

@@ -17,6 +17,7 @@ namespace Nuake {
std::vector<Ref<Physics::RigidBody>> Rigidbody;
std::string target = "";
std::string TargetName = "";
std::vector<Entity> 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;
}
};

View File

@@ -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);

View File

@@ -112,13 +112,13 @@ namespace Nuake
void PhysicsSystem::InitializeQuakeMap()
{
auto quakeBrushesView = m_Scene->m_Registry.view<TransformComponent, BSPBrushComponent, ModelComponent>();
auto quakeBrushesView = m_Scene->m_Registry.view<TransformComponent, BSPBrushComponent>();
for (auto e : quakeBrushesView)
{
const auto [transformComponent, brushComponent, modelComponent] = quakeBrushesView.get<TransformComponent, BSPBrushComponent, ModelComponent>(e);
const auto [transformComponent, brushComponent] = quakeBrushesView.get<TransformComponent, BSPBrushComponent>(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<Physics::RigidBody>(0.0f, startPosition, startRotation, startTransform, collisionShape, entity);
brushComponent.Rigidbody.push_back(rigidBody);
rigidBody->SetIsTrigger(brushComponent.IsTrigger);
PhysicsManager::Get().RegisterBody(rigidBody);
}
}

View File

@@ -28,6 +28,8 @@ extern "C" {
#include <vector>
#include <map>
#include <src/Resource/ResourceLoader.h>
#include <src/Scene/Components/NetScriptComponent.h>
#include <src/Scripting/ScriptingEngineNet.h>
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<std::string, std::string> props)
{
std::vector<Vertex> vertices;
std::vector<unsigned int> 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<WrenScriptComponent>();
wrenScript.Script = fgdBrush.Script;
wrenScript.mModule = 0; // TODO
}
if (bsp.IsTrigger)
{
TriggerZone& trigger = brushEntity.AddComponent<TriggerZone>();
trigger.target = target;
NetScriptComponent& netScript = brushEntity.AddComponent<NetScriptComponent>();
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<Vector3> 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> material = MaterialManager::Get()->GetMaterial(lastTexturePath);
mesh->SetMaterial(material);
bsp.Meshes.push_back(mesh);
ModelComponent& modelComponent = brushEntity.AddComponent<ModelComponent>();
Ref<Model> model = CreateRef<Model>();
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<std::string, std::string> 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);
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include <string>
#include <map>
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<std::string, std::string> props);
public:
QuakeMapBuilder() {}

View File

@@ -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<BSPBrushComponent>())
{
return Coral::String::New(entity.GetComponent<BSPBrushComponent>().target);
}
}
return Coral::String::New("");
}
Coral::Array<int> EntityGetTargets(Coral::String target)
{
std::vector<int> targetsFound = std::vector<int>();
if (target == "")
{
return Coral::Array<int>::New(targetsFound);
}
Ref<Scene> scene = Engine::GetCurrentScene();
auto brushView = scene->m_Registry.view<BSPBrushComponent>();
for (auto e : brushView)
{
BSPBrushComponent& brushComponent = brushView.get<BSPBrushComponent>(e);
if (brushComponent.TargetName == target)
{
Entity entity = { (entt::entity)(e), scene.get() };
targetsFound.push_back(entity.GetHandle());
}
}
return Coral::Array<int>::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);

View File

@@ -14,6 +14,7 @@
#include <random>
#include <regex>
#include <src/Scene/Components/BSPBrushComponent.h>
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<NetScriptComponent>())
{
return;
}
std::vector<std::string> detectedExposedVar;
NetScriptComponent& component = entity.GetComponent<NetScriptComponent>();
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<ExposedVar> ScriptingEngineNet::GetExposedVarForTypes(Entity entity)
{
if (!entity.HasComponent<NetScriptComponent>())
@@ -189,7 +224,16 @@ namespace Nuake
auto& component = entity.GetComponent<NetScriptComponent>();
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<ExposedVar>();
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<Coral::String>("Description");
isTrigger = attribute.GetFieldValue<bool>("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<ExposedVar>();
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>())
{
BSPBrushComponent& brushComponent = entity.GetComponent<BSPBrushComponent>();
classInstance.SetPropertyValue("TargetName", brushComponent.TargetName);
classInstance.SetPropertyValue("Target", brushComponent.target);
}
std::vector<std::string> detectedExposedVar;
detectedExposedVar.reserve(std::size(m_GameEntityTypes[className].exposedVars));
@@ -384,7 +470,13 @@ namespace Nuake
}
case ExposedVarTypes::String:
{
exposedVar.Value = std::string(classInstance.GetFieldValue<Coral::String>(varName));
try {
//exposedVar.Value = std::string(classInstance.GetFieldValue<Coral::String>(varName));
}
catch (...)
{
}
break;
}
case ExposedVarTypes::Bool:

View File

@@ -32,6 +32,7 @@ namespace Nuake {
Vector2,
Vector3,
Vector4,
Int,
Unsupported
};
@@ -46,6 +47,9 @@ namespace Nuake {
{
Coral::Type* coralType;
std::vector<ExposedVar> 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<std::string, NetGameScriptObject> m_GameEntityTypes;
std::unordered_map<std::string, NetGameScriptObject> m_BrushEntityTypes;
std::unordered_map<uint32_t, Coral::ManagedObject> 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<ExposedVar> GetExposedVarForTypes(Entity entity);
std::vector<CompilationError> BuildProjectAssembly(Ref<Project> project);
@@ -118,6 +125,7 @@ namespace Nuake {
Coral::ManagedAssembly GetNuakeAssembly() const { return m_NuakeAssembly; }
std::unordered_map<std::string, NetGameScriptObject> GetBrushEntities() const { return m_BrushEntityTypes; }
private:
std::string GenerateGUID();
};

View File

@@ -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
{
}
}

View File

@@ -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*<int, NativeString> EntityGetNameIcall;
internal static unsafe delegate*<int, NativeString, void> EntitySetNameIcall;
internal static unsafe delegate*<int, bool> EntityIsValidIcall;
internal static unsafe delegate*<NativeString, NativeArray<int>> EntityGetTargetsIcall;
internal static unsafe delegate*<int, NativeString> EntityGetTargetIcall;
public enum ComponentTypes
{
@@ -55,6 +58,37 @@ namespace Nuake.Net
NAVMESH
}
public List<Entity> Targets
{
get
{
unsafe
{
var targetIds = EntityGetTargetsIcall(Target);
List<Entity> targets = new List<Entity>();
foreach(var target in targetIds)
{
bool hasInstance = EntityHasManagedInstanceIcall(target);
Entity entityInstance;
if (hasInstance)
{
entityInstance = Scene.GetEntity<Entity>(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)
{

View File

@@ -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*</* start */ float, float, float,