mirror of
https://github.com/antopilo/Nuake.git
synced 2026-02-25 14:32:55 +03:00
Added C# -> Trenchbrom entity definition with reflection system
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -169,6 +169,8 @@ namespace Nuake
|
||||
}
|
||||
|
||||
FileSystem::SetRootDirectory(FileSystem::GetParentPath(project->FullPath));
|
||||
ScriptingEngineNet::Get().LoadProjectAssembly(project);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
14
NuakeNet/src/BrushScript.cs
Normal file
14
NuakeNet/src/BrushScript.cs
Normal 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
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user