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

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