Added C# Point entities + automatic export of FGD entities
This commit is contained in:
@@ -118,7 +118,7 @@ namespace Nuake {
|
||||
using namespace Nuake::StaticResources;
|
||||
ImGui::LoadIniSettingsFromMemory((const char*)StaticResources::Resources_default_layout_ini);
|
||||
|
||||
ScriptingContext::Get().Initialize();
|
||||
//ScriptingContext::Get().Initialize();
|
||||
}
|
||||
|
||||
void EditorInterface::Init()
|
||||
@@ -511,6 +511,7 @@ namespace Nuake {
|
||||
{
|
||||
playButtonPressed = ImGui::Button(ICON_FA_PLAY, ImVec2(30, 30)) || Input::IsKeyPressed(Key::F5);
|
||||
tooltip = "Build & Play (F5)";
|
||||
|
||||
}
|
||||
|
||||
if (playButtonPressed)
|
||||
@@ -527,6 +528,7 @@ namespace Nuake {
|
||||
{
|
||||
this->SceneSnapshot = Engine::GetCurrentScene()->Copy();
|
||||
|
||||
|
||||
std::string statusMessage = ICON_FA_HAMMER + std::string(" Building .Net solution...");
|
||||
SetStatusMessage(statusMessage);
|
||||
|
||||
@@ -553,6 +555,8 @@ namespace Nuake {
|
||||
}
|
||||
else
|
||||
{
|
||||
Engine::GetProject()->ExportEntitiesToTrenchbroom();
|
||||
|
||||
SetStatusMessage("Entering play mode...");
|
||||
|
||||
PushCommand(SetGameState(GameState::Playing));
|
||||
|
||||
@@ -169,6 +169,7 @@ namespace Nuake
|
||||
}
|
||||
|
||||
FileSystem::SetRootDirectory(FileSystem::GetParentPath(project->FullPath));
|
||||
ScriptingEngineNet::Get().Initialize();
|
||||
ScriptingEngineNet::Get().LoadProjectAssembly(project);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace Nuake {
|
||||
|
||||
void AudioManager::LoadWavAudio(const std::string& filePath)
|
||||
{
|
||||
const bool STREAMING = true;
|
||||
const bool STREAMING = false;
|
||||
if (STREAMING)
|
||||
{
|
||||
Ref<SoLoud::WavStream> wavStream = CreateRef<SoLoud::WavStream>();
|
||||
|
||||
@@ -494,8 +494,20 @@ namespace Nuake
|
||||
{
|
||||
std::string name = entity.GetComponent<NameComponent>().Name;
|
||||
|
||||
_JoltBodyInterface->SetPositionAndRotation(bodyId, newPosition, newRotation, JPH::EActivation::DontActivate);
|
||||
//_JoltBodyInterface->MoveKinematic(bodyId, newPosition, newRotation, 0.0f);
|
||||
JPH::EMotionType bodyType = _JoltBodyInterface->GetMotionType(bodyId);
|
||||
switch (bodyType)
|
||||
{
|
||||
case JPH::EMotionType::Kinematic:
|
||||
{
|
||||
_JoltBodyInterface->MoveKinematic(bodyId, newPosition, newRotation, 0.0f);
|
||||
break;
|
||||
}
|
||||
case JPH::EMotionType::Static:
|
||||
{
|
||||
_JoltBodyInterface->SetPositionAndRotation(bodyId, newPosition, newRotation, JPH::EActivation::DontActivate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -864,7 +876,7 @@ namespace Nuake
|
||||
_CollisionCallbacks.push_back(std::move(data));
|
||||
}
|
||||
|
||||
const std::vector<CollisionData>& DynamicWorld::GetCollisionsData()
|
||||
const std::vector<CollisionData> DynamicWorld::GetCollisionsData()
|
||||
{
|
||||
std::scoped_lock<std::mutex> lock(_CollisionCallbackMutex);
|
||||
return _CollisionCallbacks;
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Nuake
|
||||
void ClearCollisionData();
|
||||
|
||||
void RegisterCollisionCallback(const CollisionData& data);
|
||||
const std::vector<CollisionData>& GetCollisionsData();
|
||||
const std::vector<CollisionData> GetCollisionsData();
|
||||
private:
|
||||
JPH::Ref<JPH::Shape> GetJoltShape(const Ref<PhysicShape> shape);
|
||||
void SyncEntitiesTranforms();
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Nuake
|
||||
return m_World->CastShape(from, to, shape);
|
||||
}
|
||||
|
||||
const std::vector<Physics::CollisionData>& PhysicsManager::GetCollisions()
|
||||
const std::vector<Physics::CollisionData> PhysicsManager::GetCollisions()
|
||||
{
|
||||
return m_World->GetCollisionsData();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Nuake
|
||||
std::vector<RaycastResult> Raycast(const Vector3& from, const Vector3& to);
|
||||
std::vector<ShapeCastResult> Shapecast(const Vector3& from, const Vector3& to, const Ref<Physics::PhysicShape>& shape);
|
||||
|
||||
const std::vector<Physics::CollisionData>& GetCollisions();
|
||||
const std::vector<Physics::CollisionData> GetCollisions();
|
||||
|
||||
void RegisterBody(Ref<Physics::RigidBody> rb);
|
||||
void RegisterGhostBody(Ref<GhostObject> rb);
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Nuake
|
||||
Quat _rotation;
|
||||
Entity _entity;
|
||||
|
||||
bool _ForceKinematic = false;
|
||||
bool _isTrigger = false;
|
||||
bool m_LockXAxis = false;
|
||||
bool m_LockYAxis = false;
|
||||
@@ -29,7 +30,7 @@ namespace Nuake
|
||||
|
||||
RigidBody();
|
||||
RigidBody(Vector3 position, Entity handle);
|
||||
RigidBody(float mass, Vector3 position, Quat rotation, Matrix4 transform, Ref<PhysicShape> shape, Entity entity, Vector3 initialVel = Vector3(0, 0, 0));
|
||||
RigidBody(float mass, Vector3 position, Quat rotation, Matrix4 transform, Ref<PhysicShape> shape, Entity entity, Vector3 initialVel = Vector3(0, 0, 0), bool forceKinematic = false);
|
||||
|
||||
void UpdateTransform();
|
||||
|
||||
@@ -43,6 +44,7 @@ namespace Nuake
|
||||
void SetLockXAxis(bool lock) { m_LockXAxis = lock; }
|
||||
void SetLockYAxis(bool lock) { m_LockYAxis = lock; }
|
||||
void SetLockZAxis(bool lock) { m_LockZAxis = lock; }
|
||||
bool GetForceKinematic() const { return _ForceKinematic; }
|
||||
|
||||
void SetEntityID(Entity ent);
|
||||
Vector3 GetPosition() const { return _position; }
|
||||
|
||||
@@ -20,12 +20,13 @@ namespace Nuake
|
||||
|
||||
}
|
||||
|
||||
RigidBody::RigidBody(float mass, Vector3 position, Quat rotation, Matrix4 transform, Ref<PhysicShape> shape, Entity entity, Vector3 initialVel) :
|
||||
RigidBody::RigidBody(float mass, Vector3 position, Quat rotation, Matrix4 transform, Ref<PhysicShape> shape, Entity entity, Vector3 initialVel, bool forceKinematic) :
|
||||
_position(position),
|
||||
_collisionShape(shape),
|
||||
_mass(mass),
|
||||
_entity(entity),
|
||||
_rotation(rotation)
|
||||
_rotation(rotation),
|
||||
_ForceKinematic(forceKinematic)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -75,6 +75,9 @@ namespace Nuake
|
||||
|
||||
mCapsuleGizmo = CreateRef<CapsuleGizmo>();
|
||||
mCapsuleGizmo->CreateMesh();
|
||||
|
||||
mDebugLines = std::vector<DebugLine>();
|
||||
mDebugShapes = std::vector<DebugShape>();
|
||||
}
|
||||
|
||||
void SceneRenderer::Cleanup()
|
||||
@@ -84,24 +87,30 @@ namespace Nuake
|
||||
void SceneRenderer::Update(const Timestep time, bool isEditorUpdate)
|
||||
{
|
||||
// Delete debug shapes that are dead
|
||||
std::erase_if(mDebugLines, [](const DebugLine& line)
|
||||
if (mDebugLines.size() > 0)
|
||||
{
|
||||
return line.Life < 0.0f;
|
||||
});
|
||||
std::erase_if(mDebugLines, [](const DebugLine& line)
|
||||
{
|
||||
return line.Life < 0.0f;
|
||||
});
|
||||
|
||||
std::erase_if(mDebugShapes, [](const DebugShape& shape)
|
||||
{
|
||||
return shape.Life < 0.0f;
|
||||
});
|
||||
|
||||
for (auto& line : mDebugLines)
|
||||
{
|
||||
line.Life -= time;
|
||||
for (auto& line : mDebugLines)
|
||||
{
|
||||
line.Life -= time;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& shape : mDebugShapes)
|
||||
if (mDebugShapes.size() > 0)
|
||||
{
|
||||
shape.Life -= time;
|
||||
std::erase_if(mDebugShapes, [](const DebugShape& shape)
|
||||
{
|
||||
return shape.Life < 0.0f;
|
||||
});
|
||||
|
||||
for (auto& shape : mDebugShapes)
|
||||
{
|
||||
shape.Life -= time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,10 +536,7 @@ namespace Nuake
|
||||
if (model.IsTransparent || !visibility.Visible)
|
||||
continue;
|
||||
|
||||
for (Ref<Mesh>& m : model.Meshes)
|
||||
{
|
||||
Renderer::SubmitMesh(m, transform.GetGlobalTransform());
|
||||
}
|
||||
|
||||
}
|
||||
Renderer::Flush(shader, true);
|
||||
|
||||
@@ -620,10 +626,7 @@ namespace Nuake
|
||||
if (model.IsTransparent || !visibility.Visible)
|
||||
continue;
|
||||
|
||||
for (Ref<Mesh>& m : model.Meshes)
|
||||
{
|
||||
Renderer::SubmitMesh(m, transform.GetGlobalTransform());
|
||||
}
|
||||
|
||||
}
|
||||
Renderer::Flush(shader, true);
|
||||
|
||||
@@ -795,10 +798,7 @@ namespace Nuake
|
||||
if (model.IsTransparent || !visibility.Visible)
|
||||
continue;
|
||||
|
||||
for (auto& b : model.Meshes)
|
||||
{
|
||||
Renderer::SubmitMesh(b, transform.GetGlobalTransform(), (uint32_t)e);
|
||||
}
|
||||
|
||||
}
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
@@ -76,6 +76,7 @@ namespace Nuake {
|
||||
std::string Name;
|
||||
std::string Description;
|
||||
std::string Prefab;
|
||||
std::string Script;
|
||||
std::vector<ClassProperty> Properties;
|
||||
FGDBaseEntity BaseClass;
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#include "Project.h"
|
||||
#include "../Core/FileSystem.h"
|
||||
#include "src/Core/FileSystem.h"
|
||||
#include "Engine.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include "src/Audio/AudioManager.h"
|
||||
#include "src/Scripting/ScriptingEngineNet.h"
|
||||
|
||||
#include <json/json.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#include "../Core/Logger.h"
|
||||
#include "Engine.h"
|
||||
#include <src/Audio/AudioManager.h>
|
||||
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
@@ -104,6 +108,73 @@ namespace Nuake
|
||||
return project;
|
||||
}
|
||||
|
||||
void Project::ExportEntitiesToTrenchbroom()
|
||||
{
|
||||
Ref<FGDFile> file = EntityDefinitionsFile;
|
||||
|
||||
file->BrushEntities.clear();
|
||||
for (auto& [name, type] : 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);
|
||||
}
|
||||
|
||||
file->PointEntities.clear();
|
||||
for (auto& [name, type] : ScriptingEngineNet::Get().GetPointEntities())
|
||||
{
|
||||
FGDPointEntity pointEntity = FGDPointEntity(name);
|
||||
pointEntity.Script = name;
|
||||
pointEntity.Description = type.Description;
|
||||
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 = "";
|
||||
}
|
||||
|
||||
pointEntity.Properties.push_back(classProp);
|
||||
}
|
||||
|
||||
file->PointEntities.push_back(pointEntity);
|
||||
}
|
||||
|
||||
file->Export();
|
||||
}
|
||||
|
||||
json Project::Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
|
||||
@@ -59,6 +59,8 @@ namespace Nuake
|
||||
static Ref<Project> New();
|
||||
static Ref<Project> Load(std::string& path);
|
||||
|
||||
void ExportEntitiesToTrenchbroom();
|
||||
|
||||
json Serialize() override;
|
||||
bool Deserialize(const json& j) override;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Nuake {
|
||||
class BSPBrushComponent
|
||||
{
|
||||
public:
|
||||
std::vector<Ref<Mesh>> Meshes;
|
||||
//std::vector<Ref<Mesh>> Meshes;
|
||||
std::vector<std::vector<Vector3>> Hulls;
|
||||
|
||||
std::vector<Ref<Material>> Materials;
|
||||
@@ -27,7 +27,7 @@ namespace Nuake {
|
||||
|
||||
BSPBrushComponent()
|
||||
{
|
||||
Meshes = std::vector<Ref<Mesh>>();
|
||||
//Meshes = std::vector<Ref<Mesh>>();
|
||||
Materials = std::vector<Ref<Material>>();
|
||||
Rigidbody = std::vector<Ref<Physics::RigidBody>>();
|
||||
Hulls = std::vector<std::vector<Vector3>>();
|
||||
|
||||
@@ -131,8 +131,7 @@ namespace Nuake
|
||||
const Quat& startRotation = transformComponent.GetGlobalRotation();
|
||||
const auto collisionShape = CreateRef<Physics::ConvexHullShape>(hull);
|
||||
|
||||
|
||||
auto rigidBody = CreateRef<Physics::RigidBody>(0.0f, startPosition, startRotation, startTransform, collisionShape, entity);
|
||||
auto rigidBody = CreateRef<Physics::RigidBody>(0.0f, startPosition, startRotation, startTransform, collisionShape, entity, Vector3{ 0, 0, 0 }, brushComponent.IsFunc);
|
||||
brushComponent.Rigidbody.push_back(rigidBody);
|
||||
rigidBody->SetIsTrigger(brushComponent.IsTrigger);
|
||||
PhysicsManager::Get().RegisterBody(rigidBody);
|
||||
|
||||
@@ -40,392 +40,6 @@ namespace Nuake {
|
||||
|
||||
Ref<Material> DefaultMaterial;
|
||||
|
||||
void QuakeMapBuilder::CreateTrigger(brush* brush, brush_geometry* brush_inst,
|
||||
Scene* scene, Entity& parent,
|
||||
const std::string& target, const std::string& targetname)
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
Entity brushEntity = scene->CreateEntity("Trigger");
|
||||
TransformComponent& transformComponent = brushEntity.GetComponent<TransformComponent>();
|
||||
TriggerZone& trigger = brushEntity.AddComponent<TriggerZone>();
|
||||
trigger.target = target;
|
||||
|
||||
parent.AddChild(brushEntity);
|
||||
|
||||
transformComponent.SetGlobalPosition(Vector3(brush->center.y * (1.0f / 64),
|
||||
brush->center.z * ScaleFactor * (1.0f / 64),
|
||||
brush->center.x * ScaleFactor * (1.0f / 64)));
|
||||
|
||||
BSPBrushComponent& bsp = brushEntity.AddComponent<BSPBrushComponent>();
|
||||
bsp.IsSolid = false;
|
||||
bsp.target = target;
|
||||
int indexOffset = 0;
|
||||
for (int f = 0; f < brush->face_count; ++f)
|
||||
{
|
||||
face* face = &brush->faces[f];
|
||||
|
||||
face_geometry* face_geo_inst = &brush_inst->faces[f];
|
||||
|
||||
for (int i = 0; i < face_geo_inst->vertex_count; ++i)
|
||||
{
|
||||
face_vertex vertex = face_geo_inst->vertices[i];
|
||||
|
||||
Vector3 vertexPos = Vector3(
|
||||
(vertex.vertex.y - brush->center.y) * ScaleFactor * (1.0f / 64),
|
||||
(vertex.vertex.z - brush->center.z) * ScaleFactor * (1.0f / 64),
|
||||
(vertex.vertex.x - brush->center.x) * ScaleFactor * (1.0f / 64)
|
||||
);
|
||||
|
||||
Vector3 vertexNormal = Vector3(vertex.normal.y, vertex.normal.z, vertex.normal.x);
|
||||
Vector3 vertexTangent = Vector3(vertex.tangent.y, vertex.tangent.z, vertex.tangent.x);
|
||||
|
||||
vertices.push_back(Vertex{
|
||||
vertexPos,
|
||||
Vector2(0,0),
|
||||
vertexNormal,
|
||||
vertexTangent,
|
||||
glm::vec3(0.0, 1.0, 0.0)
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < (face_geo_inst->vertex_count - 2) * 3; ++i)
|
||||
{
|
||||
unsigned int index = face_geo_inst->indices[i];
|
||||
indices.push_back((unsigned int)indexOffset + index);
|
||||
}
|
||||
|
||||
indexOffset += face_geo_inst->vertex_count;
|
||||
}
|
||||
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(vertices, indices);
|
||||
bsp.Meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
void QuakeMapBuilder::CreateBrush(brush* brush, brush_geometry* brush_inst,
|
||||
Scene* scene, Entity& parent,
|
||||
const std::string& target, const std::string& targetname)
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
Entity brushEntity = scene->CreateEntity(targetname);
|
||||
TransformComponent& transformComponent = brushEntity.GetComponent<TransformComponent>();
|
||||
BSPBrushComponent& bsp = brushEntity.AddComponent<BSPBrushComponent>();
|
||||
|
||||
parent.AddChild(brushEntity);
|
||||
|
||||
transformComponent.SetGlobalPosition(Vector3(
|
||||
brush->center.y * ScaleFactor * (1.0f / 64),
|
||||
brush->center.z * ScaleFactor * (1.0f / 64),
|
||||
brush->center.x * ScaleFactor * (1.0f / 64)));
|
||||
|
||||
int index_offset = 0;
|
||||
int lastTextureID = -1;
|
||||
std::string lastTexturePath = "";
|
||||
for (int f = 0; f < brush->face_count; ++f)
|
||||
{
|
||||
face* face = &brush->faces[f];
|
||||
texture_data* texture = &textures[face->texture_idx];
|
||||
|
||||
bool textureIsEmpty = std::string(texture->name) == "__TB_empty" || std::string(texture->name).empty();
|
||||
if (textureIsEmpty)
|
||||
{
|
||||
texture->height = 1;
|
||||
texture->width = 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FileSystem::FileExists("textures/" + std::string(texture->name) + ".material"))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = FileSystem::Root + "textures/" + std::string(texture->name) + ".png";
|
||||
auto tex = TextureManager::Get()->GetTexture(path);
|
||||
|
||||
texture->height = tex->GetHeight();
|
||||
texture->width = tex->GetWidth();
|
||||
}
|
||||
}
|
||||
|
||||
face_geometry* face_geo_inst = &brush_inst->faces[f];
|
||||
|
||||
for (int i = 0; i < face_geo_inst->vertex_count; ++i)
|
||||
{
|
||||
face_vertex vertex = face_geo_inst->vertices[i];
|
||||
vertex_uv vertex_uv = get_valve_uv(vertex.vertex, face, texture->width, texture->height);
|
||||
|
||||
Vector3 vertexPos = Vector3(
|
||||
(vertex.vertex.y - brush->center.y) * ScaleFactor * (1.0f / 64),
|
||||
(vertex.vertex.z - brush->center.z) * ScaleFactor * (1.0f / 64),
|
||||
(vertex.vertex.x - brush->center.x) * ScaleFactor * (1.0f / 64)
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
vertices.push_back(Vertex{
|
||||
vertexPos,
|
||||
vertexUV,
|
||||
vertexNormal,
|
||||
vertexTangent,
|
||||
glm::vec3(0.0, 1.0, 0.0)
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < (face_geo_inst->vertex_count - 2) * 3; ++i)
|
||||
{
|
||||
unsigned int index = face_geo_inst->indices[i];
|
||||
indices.push_back(index_offset + (unsigned int)index);
|
||||
}
|
||||
|
||||
if (lastTextureID != face->texture_idx)
|
||||
{
|
||||
lastTexturePath = FileSystem::Root + "textures/" + std::string(texture->name) + ".png";
|
||||
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(vertices, indices);
|
||||
|
||||
if (const std::string materialPath = "textures/" + std::string(texture->name) + ".material";
|
||||
FileSystem::FileExists(materialPath))
|
||||
{
|
||||
Ref<Material> material = ResourceLoader::LoadMaterial(materialPath);
|
||||
mesh->SetMaterial(material);
|
||||
}
|
||||
else if (std::string(texture->name) != "__TB_empty")
|
||||
{
|
||||
Ref<Material> material = MaterialManager::Get()->GetMaterial(lastTexturePath);
|
||||
mesh->SetMaterial(material);
|
||||
}
|
||||
|
||||
bsp.Meshes.push_back(mesh);
|
||||
|
||||
index_offset = 0;
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
lastTextureID = face->texture_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
index_offset += (face_geo_inst->vertex_count);
|
||||
}
|
||||
}
|
||||
|
||||
if (vertices.size() > 0)
|
||||
{
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(vertices, indices);
|
||||
|
||||
Ref<Material> material = MaterialManager::Get()->GetMaterial(lastTexturePath);
|
||||
mesh->SetMaterial(material);
|
||||
|
||||
bsp.Meshes.push_back(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
void QuakeMapBuilder::CreateFuncBrush(brush* brush, brush_geometry* brush_inst,
|
||||
Scene* scene, Entity& parent,
|
||||
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;
|
||||
|
||||
std::string name = fgdBrush.Name;
|
||||
if (targetname != "")
|
||||
name = targetname;
|
||||
|
||||
Entity brushEntity = scene->CreateEntity(name);
|
||||
|
||||
TransformComponent& transformComponent = brushEntity.GetComponent<TransformComponent>();
|
||||
BSPBrushComponent& bsp = brushEntity.AddComponent<BSPBrushComponent>();
|
||||
|
||||
std::map<std::string, Ref<Material>> m_Materials;
|
||||
|
||||
bsp.IsSolid = !fgdBrush.IsTrigger;
|
||||
bsp.IsTransparent = !fgdBrush.Visible;
|
||||
bsp.IsFunc = true;
|
||||
bsp.IsTrigger = fgdBrush.IsTrigger;
|
||||
if (fgdBrush.Script != "")
|
||||
{
|
||||
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);
|
||||
|
||||
transformComponent.SetLocalPosition(Vector3(
|
||||
brush->center.y * ScaleFactor * (1.0f / 64),
|
||||
brush->center.z * ScaleFactor * (1.0f / 64),
|
||||
brush->center.x * ScaleFactor * (1.0f / 64)));
|
||||
|
||||
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];
|
||||
texture_data* texture = &textures[face->texture_idx];
|
||||
if (std::string(texture->name) == "__TB_empty")
|
||||
{
|
||||
texture->height = 1;
|
||||
texture->width = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string path = FileSystem::Root + std::string(texture->name) + ".png";
|
||||
auto tex = TextureManager::Get()->GetTexture(path);
|
||||
texture->height = tex->GetHeight();
|
||||
texture->width = tex->GetWidth();
|
||||
}
|
||||
|
||||
Ref<Material> currentMaterial;
|
||||
if (std::string(texture->name) != "__TB_empty")
|
||||
{
|
||||
std::string path = FileSystem::Root + "Textures/" + std::string(texture->name) + ".png";
|
||||
|
||||
if (const std::string materialPath = "Materials/" + std::string(texture->name) + ".material";
|
||||
FileSystem::FileExists(materialPath))
|
||||
{
|
||||
Ref<Material> material = ResourceLoader::LoadMaterial(materialPath);
|
||||
m_Materials[path] = material;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Materials.find(path) == m_Materials.end())
|
||||
{
|
||||
m_Materials[path] = MaterialManager::Get()->GetMaterial(path);
|
||||
}
|
||||
}
|
||||
|
||||
currentMaterial = m_Materials[path];
|
||||
texture->height = currentMaterial->m_Albedo->GetHeight();
|
||||
texture->width = currentMaterial->m_Albedo->GetWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
|
||||
currentMaterial = MaterialManager::Get()->GetMaterial("resources/Textures/default/Default.png");
|
||||
texture->height = texture->width = 1;
|
||||
}
|
||||
|
||||
face_geometry* face_geo_inst = &brush_inst->faces[f];
|
||||
|
||||
for (int i = 0; i < face_geo_inst->vertex_count; ++i)
|
||||
{
|
||||
face_vertex vertex = face_geo_inst->vertices[i];
|
||||
vertex_uv vertex_uv = get_valve_uv(vertex.vertex, face, texture->width, texture->height);
|
||||
|
||||
Vector3 vertexPos = Vector3(
|
||||
(vertex.vertex.y - brush->center.y) * ScaleFactor * (1.0f / 64),
|
||||
(vertex.vertex.z - brush->center.z) * ScaleFactor * (1.0f / 64),
|
||||
(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);
|
||||
|
||||
vertices.push_back(Vertex
|
||||
{
|
||||
vertexPos,
|
||||
vertexUV,
|
||||
vertexNormal,
|
||||
vertexTangent,
|
||||
glm::vec3(0.0, 1.0, 0.0)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; i < (face_geo_inst->vertex_count - 2) * 3; ++i)
|
||||
{
|
||||
unsigned int index = face_geo_inst->indices[i];
|
||||
indices.push_back(index_offset + (unsigned int)index);
|
||||
}
|
||||
|
||||
if (!bsp.IsTrigger)
|
||||
{
|
||||
if (lastTextureID != face->texture_idx)
|
||||
{
|
||||
lastTexturePath = FileSystem::Root + "textures/" + std::string(texture->name) + ".png";
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(vertices, indices);
|
||||
|
||||
if (std::string(texture->name) != "__TB_empty")
|
||||
{
|
||||
mesh->SetMaterial(currentMaterial);
|
||||
}
|
||||
|
||||
bsp.Meshes.push_back(mesh);
|
||||
|
||||
index_offset = 0;
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
lastTextureID = face->texture_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
index_offset += (face_geo_inst->vertex_count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
index_offset += (face_geo_inst->vertex_count);
|
||||
}
|
||||
}
|
||||
bsp.Hulls.push_back(std::move(pointsInBrush));
|
||||
|
||||
if (bsp.IsTrigger)
|
||||
{
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(vertices, indices);
|
||||
|
||||
bsp.Meshes.push_back(mesh);
|
||||
vertices.clear();
|
||||
}
|
||||
|
||||
if (vertices.size() > 0)
|
||||
{
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(vertices, indices);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QuakeMapBuilder::BuildQuakeMap(Entity& ent, bool Collisions)
|
||||
{
|
||||
if (!ent.HasComponent<QuakeMapComponent>())
|
||||
@@ -454,6 +68,7 @@ namespace Nuake {
|
||||
|
||||
DefaultMaterial = MaterialManager::Get()->GetMaterial("default");
|
||||
Entity worldspawnEntity = { (entt::entity)-1, m_Scene };
|
||||
Entity currentNonWorldEntity;
|
||||
std::map<std::string, Entity> pointEntities = std::map<std::string, Entity>();
|
||||
for (uint32_t e = 0; e < (uint32_t)entity_count; ++e)
|
||||
{
|
||||
@@ -537,41 +152,248 @@ namespace Nuake {
|
||||
|
||||
if (!isWorldSpawn)
|
||||
{
|
||||
currentNonWorldEntity = m_Scene->CreateEntity(properties["classname"]);
|
||||
ent.AddChild(currentNonWorldEntity);
|
||||
|
||||
auto& transformComponent = currentNonWorldEntity.GetComponent<TransformComponent>();
|
||||
transformComponent.SetLocalPosition({entity_inst->center.y / 64.0f, entity_inst->center.z / 64.0f, entity_inst->center.x / 64.0f });
|
||||
auto& bsp = currentNonWorldEntity.AddComponent<BSPBrushComponent>();
|
||||
|
||||
if (isPointEntity)
|
||||
{
|
||||
if (pointEntities.find(pointEntity->Name) == pointEntities.end())
|
||||
std::string name = pointEntity->Name;
|
||||
if (targetname != "")
|
||||
{
|
||||
Entity pointEntityParent = Engine::GetCurrentScene()->CreateEntity(pointEntity->Name);
|
||||
pointEntities[pointEntity->Name] = pointEntityParent;
|
||||
ent.AddChild(pointEntityParent);
|
||||
name = targetname;
|
||||
}
|
||||
|
||||
Entity newPrefab = Engine::GetCurrentScene()->CreateEntity(pointEntity->Name);
|
||||
bsp.target = target;
|
||||
bsp.TargetName = targetname;
|
||||
|
||||
pointEntities[pointEntity->Name].AddChild(newPrefab);
|
||||
|
||||
auto& prefabComponent = newPrefab.AddComponent<PrefabComponent>();
|
||||
prefabComponent.SetPrefab(Prefab::New(pointEntity->Prefab));
|
||||
newPrefab.GetComponent<TransformComponent>().SetLocalPosition(brushLocalPosition);
|
||||
|
||||
for (auto& e : prefabComponent.PrefabInstance->Entities)
|
||||
if (properties.find("origin") != properties.end())
|
||||
{
|
||||
if (!e.GetComponent<ParentComponent>().HasParent)
|
||||
auto splits = String::Split(properties["origin"], ' ');
|
||||
if (splits.size() == 3)
|
||||
{
|
||||
newPrefab.AddChild(e);
|
||||
int x = atoi(splits[0].c_str());
|
||||
int y = atoi(splits[1].c_str());
|
||||
int z = atoi(splits[2].c_str());
|
||||
|
||||
Vector3 pointPosition = { y / 64.0f, z / 64.0f, x / 64.0f };
|
||||
transformComponent.SetLocalPosition(pointPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if (pointEntity->Script != "")
|
||||
{
|
||||
NetScriptComponent& netScript = currentNonWorldEntity.AddComponent<NetScriptComponent>();
|
||||
netScript.ScriptPath = pointEntity->Script;
|
||||
|
||||
ScriptingEngineNet::Get().UpdateEntityWithExposedVar(currentNonWorldEntity);
|
||||
for (auto& ev : netScript.ExposedVar)
|
||||
{
|
||||
if (properties.find(ev.Name) != properties.end())
|
||||
{
|
||||
if (ev.Type == NetScriptExposedVarType::String)
|
||||
{
|
||||
ev.Value = properties[ev.Name];
|
||||
ev.DefaultValue = ev.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity newPrefab = Engine::GetCurrentScene()->CreateEntity(pointEntity->Name);
|
||||
pointEntities[pointEntity->Name].AddChild(newPrefab);
|
||||
|
||||
auto& prefabComponent = newPrefab.AddComponent<PrefabComponent>();
|
||||
prefabComponent.SetPrefab(Prefab::New(pointEntity->Prefab));
|
||||
newPrefab.GetComponent<TransformComponent>().SetLocalPosition(brushLocalPosition);
|
||||
|
||||
for (auto& e : prefabComponent.PrefabInstance->Entities)
|
||||
{
|
||||
if (!e.GetComponent<ParentComponent>().HasParent)
|
||||
{
|
||||
newPrefab.AddChild(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int b = 0; b < entity_inst->brush_count; ++b)
|
||||
else
|
||||
{
|
||||
brush* brush_inst = &entity_inst->brushes[b];
|
||||
brush_geometry* brush_geo_inst = &entity_geo_inst->brushes[b];
|
||||
std::string name = fgdBrush->Name;
|
||||
if (targetname != "")
|
||||
{
|
||||
name = targetname;
|
||||
}
|
||||
|
||||
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);
|
||||
bsp.IsSolid = !fgdBrush->IsTrigger;
|
||||
bsp.IsTransparent = !fgdBrush->Visible;
|
||||
bsp.IsFunc = true;
|
||||
bsp.IsTrigger = fgdBrush->IsTrigger;
|
||||
bsp.target = target;
|
||||
bsp.TargetName = targetname;
|
||||
|
||||
if (fgdBrush->Script != "")
|
||||
{
|
||||
NetScriptComponent& netScript = currentNonWorldEntity.AddComponent<NetScriptComponent>();
|
||||
netScript.ScriptPath = fgdBrush->Script;
|
||||
|
||||
ScriptingEngineNet::Get().UpdateEntityWithExposedVar(currentNonWorldEntity);
|
||||
for (auto& ev : netScript.ExposedVar)
|
||||
{
|
||||
if (properties.find(ev.Name) != properties.end())
|
||||
{
|
||||
if (ev.Type == NetScriptExposedVarType::String)
|
||||
{
|
||||
ev.Value = properties[ev.Name];
|
||||
ev.DefaultValue = ev.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, Ref<Material>> m_Materials;
|
||||
std::map<Ref<Material>, std::vector<ProcessedMesh>> m_StaticWorld;
|
||||
for (int b = 0; b < entity_inst->brush_count; ++b)
|
||||
{
|
||||
brush* brush_inst = &entity_inst->brushes[b];
|
||||
brush_geometry* brush_geo_inst = &entity_geo_inst->brushes[b];
|
||||
std::vector<Vector3> pointsInBrush;
|
||||
if (isEntity)
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
int index_offset = 0;
|
||||
int lastTextureID = -1;
|
||||
std::string lastTexturePath = "";
|
||||
for (int f = 0; f < brush_inst->face_count; ++f)
|
||||
{
|
||||
face* face = &brush_inst->faces[f];
|
||||
texture_data* texture = &textures[face->texture_idx];
|
||||
Ref<Material> currentMaterial;
|
||||
if (std::string(texture->name) != "__TB_empty")
|
||||
{
|
||||
std::string path = FileSystem::Root + "Textures/" + std::string(texture->name) + ".png";
|
||||
|
||||
if (const std::string materialPath = "Materials/" + std::string(texture->name) + ".material";
|
||||
FileSystem::FileExists(materialPath))
|
||||
{
|
||||
Ref<Material> material = ResourceLoader::LoadMaterial(materialPath);
|
||||
m_Materials[path] = material;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Materials.find(path) == m_Materials.end())
|
||||
{
|
||||
m_Materials[path] = MaterialManager::Get()->GetMaterial(path);
|
||||
}
|
||||
}
|
||||
|
||||
currentMaterial = m_Materials[path];
|
||||
texture->height = currentMaterial->m_Albedo->GetHeight();
|
||||
texture->width = currentMaterial->m_Albedo->GetWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
|
||||
currentMaterial = MaterialManager::Get()->GetMaterial("resources/Textures/default/Default.png");
|
||||
texture->height = texture->width = 1;
|
||||
}
|
||||
|
||||
face_geometry* face_geo_inst = &brush_geo_inst->faces[f];
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
for (int i = 0; i < face_geo_inst->vertex_count; ++i)
|
||||
{
|
||||
face_vertex vertex = face_geo_inst->vertices[i];
|
||||
vertex_uv vertex_uv;
|
||||
|
||||
if (face->is_valve_uv)
|
||||
vertex_uv = get_valve_uv(vertex.vertex, face, texture->width, texture->height);
|
||||
else
|
||||
vertex_uv = get_standard_uv(vertex.vertex, face, texture->width, texture->height);
|
||||
|
||||
Vector3 vertexPos = Vector3(
|
||||
(vertex.vertex.y - entity_inst->center.y) * quakeMapC.ScaleFactor,
|
||||
(vertex.vertex.z - entity_inst->center.z) * quakeMapC.ScaleFactor,
|
||||
(vertex.vertex.x - entity_inst->center.x) * quakeMapC.ScaleFactor
|
||||
);
|
||||
|
||||
// We need to push the hull points because the batching
|
||||
// will create 1 model per material, this prevents us from
|
||||
// having 1 collision shape per brush(convex).
|
||||
pointsInBrush.push_back(vertexPos * (1.0f / 64.0f));
|
||||
|
||||
Vector2 vertexUV = Vector2(vertex_uv.u, 1.0 - 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);
|
||||
Vector3 vertexBitangent = glm::cross(vertexNormal, vertexTangent) * (float)vertex.tangent.w;
|
||||
|
||||
vertices.push_back(Vertex{
|
||||
vertexPos * (1.0f / 64.0f),
|
||||
vertexUV,
|
||||
vertexNormal,
|
||||
vertexTangent,
|
||||
vertexBitangent
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < (face_geo_inst->vertex_count - 2) * 3; i += 3)
|
||||
{
|
||||
uint32_t i1 = face_geo_inst->indices[i];
|
||||
uint32_t i2 = face_geo_inst->indices[i + 1];
|
||||
uint32_t i3 = face_geo_inst->indices[i + 2];
|
||||
indices.push_back(i3);
|
||||
indices.push_back(i2);
|
||||
indices.push_back(i1);
|
||||
}
|
||||
|
||||
m_StaticWorld[currentMaterial].push_back({ vertices, indices });
|
||||
|
||||
vertices.clear();
|
||||
indices.clear();
|
||||
}
|
||||
|
||||
bsp.Hulls.push_back(std::move(pointsInBrush));
|
||||
}
|
||||
|
||||
//else
|
||||
// CreateBrush(brush_inst, brush_geo_inst, m_Scene, newEntity, target, targetname);
|
||||
}
|
||||
|
||||
// Batching process
|
||||
Ref<Model> model = CreateRef<Model>();
|
||||
for (auto& mat : m_StaticWorld)
|
||||
{
|
||||
std::vector<Vertex> batchedVertices;
|
||||
std::vector<uint32_t> batchedIndices;
|
||||
uint32_t indexOffset = 0;
|
||||
for (auto& pm : mat.second)
|
||||
{
|
||||
for (auto& vert : pm.Vertices)
|
||||
batchedVertices.push_back(vert);
|
||||
|
||||
for (auto& index : pm.Indices)
|
||||
batchedIndices.push_back(indexOffset + index);
|
||||
|
||||
indexOffset += static_cast<uint32_t>(pm.Vertices.size());
|
||||
}
|
||||
|
||||
Ref<Mesh> mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(batchedVertices, batchedIndices);
|
||||
mesh->SetMaterial(mat.first);
|
||||
model->AddMesh(mesh);
|
||||
}
|
||||
|
||||
if (!bsp.IsTrigger)
|
||||
{
|
||||
ModelComponent& modelComponent = currentNonWorldEntity.AddComponent<ModelComponent>();
|
||||
modelComponent.ModelResource = model;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -234,6 +234,7 @@ namespace Nuake {
|
||||
for (auto e : brushView)
|
||||
{
|
||||
BSPBrushComponent& brushComponent = brushView.get<BSPBrushComponent>(e);
|
||||
auto targets = brushComponent.Targets;
|
||||
if (brushComponent.TargetName == target)
|
||||
{
|
||||
Entity entity = { (entt::entity)(e), scene.get() };
|
||||
@@ -345,6 +346,29 @@ namespace Nuake {
|
||||
}
|
||||
}
|
||||
|
||||
float CameraGetFOV(int entityId)
|
||||
{
|
||||
Entity entity = { (entt::entity)(entityId), Engine::GetCurrentScene().get() };
|
||||
|
||||
if (entity.IsValid() && entity.HasComponent<CameraComponent>())
|
||||
{
|
||||
auto& component = entity.GetComponent<CameraComponent>();
|
||||
return component.CameraInstance->Fov;
|
||||
}
|
||||
}
|
||||
|
||||
void CameraSetFOV(int entityId, float fov)
|
||||
{
|
||||
float safeFov = glm::clamp(fov, 1.0f, 180.0f);
|
||||
Entity entity = { (entt::entity)(entityId), Engine::GetCurrentScene().get() };
|
||||
|
||||
if (entity.IsValid() && entity.HasComponent<CameraComponent>())
|
||||
{
|
||||
auto& component = entity.GetComponent<CameraComponent>();
|
||||
component.CameraInstance->Fov = safeFov;
|
||||
}
|
||||
}
|
||||
|
||||
void MoveAndSlide(int entityId, float vx, float vy, float vz)
|
||||
{
|
||||
Entity entity = { (entt::entity)(entityId), Engine::GetCurrentScene().get() };
|
||||
@@ -432,6 +456,30 @@ namespace Nuake {
|
||||
return {};
|
||||
}
|
||||
|
||||
bool AudioEmitterGetIsPlaying(int entityId)
|
||||
{
|
||||
Entity entity = Entity((entt::entity)(entityId), Engine::GetCurrentScene().get());
|
||||
|
||||
if (entity.IsValid() && entity.HasComponent<AudioEmitterComponent>())
|
||||
{
|
||||
auto& audioEmitter = entity.GetComponent<AudioEmitterComponent>();
|
||||
return audioEmitter.IsPlaying;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioEmitterSetIsPlaying(int entityId, Coral::Bool32 isPlaying)
|
||||
{
|
||||
Entity entity = Entity((entt::entity)(entityId), Engine::GetCurrentScene().get());
|
||||
|
||||
if (entity.IsValid() && entity.HasComponent<AudioEmitterComponent>())
|
||||
{
|
||||
auto& audioEmitter = entity.GetComponent<AudioEmitterComponent>();
|
||||
audioEmitter.IsPlaying = isPlaying;
|
||||
}
|
||||
}
|
||||
|
||||
void Nuake::SceneNetAPI::RegisterMethods()
|
||||
{
|
||||
// Entity
|
||||
@@ -443,6 +491,7 @@ namespace Nuake {
|
||||
RegisterMethod("Entity.EntityIsValidIcall", &EntityIsValid);
|
||||
RegisterMethod("Entity.EntityGetTargetsIcall", &EntityGetTargets);
|
||||
RegisterMethod("Entity.EntityGetTargetIcall", &EntityGetTarget);
|
||||
|
||||
// Prefab
|
||||
RegisterMethod("Prefab.PrefabInstanceIcall", &PrefabInstance);
|
||||
|
||||
@@ -465,6 +514,8 @@ namespace Nuake {
|
||||
|
||||
// Camera
|
||||
RegisterMethod("CameraComponent.GetDirectionIcall", &CameraGetDirection);
|
||||
RegisterMethod("CameraComponent.GetCameraFOVIcall", &CameraGetFOV);
|
||||
RegisterMethod("CameraComponent.SetCameraFOVIcall", &CameraSetFOV);
|
||||
|
||||
// Character Controller
|
||||
RegisterMethod("CharacterControllerComponent.MoveAndSlideIcall", &MoveAndSlide);
|
||||
@@ -475,6 +526,10 @@ namespace Nuake {
|
||||
|
||||
// Navigation Mesh
|
||||
RegisterMethod("NavMeshVolumeComponent.FindPathIcall", &NavMeshComponentFindPath);
|
||||
|
||||
// Audio Emitter
|
||||
RegisterMethod("AudioEmitterComponent.GetIsPlayingIcall", &AudioEmitterGetIsPlaying);
|
||||
RegisterMethod("AudioEmitterComponent.SetIsPlayingIcall", &AudioEmitterSetIsPlaying);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -95,26 +95,38 @@ namespace Nuake
|
||||
{
|
||||
auto lineCharNums = String::Split(numbersString[0], ',');
|
||||
|
||||
int lineNum = std::stoi(lineCharNums[0]);
|
||||
int charNum = std::stoi(lineCharNums[1]);
|
||||
|
||||
// error message
|
||||
std::string errMesg = "";
|
||||
int i = 0;
|
||||
for (auto s : String::Split(line, ':'))
|
||||
if (lineCharNums.size() == 1)
|
||||
{
|
||||
if (i >= 3)
|
||||
{
|
||||
errMesg += s;
|
||||
}
|
||||
i++;
|
||||
CompilationError compilationError;
|
||||
compilationError.message = "";
|
||||
compilationError.file = filePath;
|
||||
compilationError.line = 0;
|
||||
errors.push_back(compilationError);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lineNum = std::stoi(lineCharNums[0]);
|
||||
int charNum = std::stoi(lineCharNums[1]);
|
||||
|
||||
CompilationError compilationError;
|
||||
compilationError.message = errMesg;
|
||||
compilationError.file = filePath;
|
||||
compilationError.line = lineNum;
|
||||
errors.push_back(compilationError);
|
||||
// error message
|
||||
std::string errMesg = "";
|
||||
int i = 0;
|
||||
for (auto s : String::Split(line, ':'))
|
||||
{
|
||||
if (i >= 3)
|
||||
{
|
||||
errMesg += s;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
CompilationError compilationError;
|
||||
compilationError.message = errMesg;
|
||||
compilationError.file = filePath;
|
||||
compilationError.line = lineNum;
|
||||
errors.push_back(compilationError);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +185,7 @@ namespace Nuake
|
||||
}
|
||||
|
||||
Coral::GC::Collect();
|
||||
Coral::GC::WaitForPendingFinalizers();
|
||||
|
||||
GetHostInstance()->UnloadAssemblyLoadContext(m_LoadContext);
|
||||
|
||||
@@ -298,23 +311,33 @@ 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");
|
||||
auto& pointScriptAttributeType = m_GameAssembly.GetType("Nuake.Net.PointScript");
|
||||
|
||||
for (auto& type : m_GameAssembly.GetTypes())
|
||||
{
|
||||
// Brush
|
||||
bool isBrushScript = false;
|
||||
std::string brushDescription;
|
||||
bool isTrigger = false;
|
||||
|
||||
// Point
|
||||
bool isPointScript = false;
|
||||
std::string pointDescription;
|
||||
|
||||
for (auto& attribute : type->GetAttributes())
|
||||
{
|
||||
if (attribute.GetType() != brushScriptAttributeType)
|
||||
if (attribute.GetType() == brushScriptAttributeType)
|
||||
{
|
||||
continue;
|
||||
brushDescription = attribute.GetFieldValue<Coral::String>("Description");
|
||||
isTrigger = attribute.GetFieldValue<Coral::Bool32>("IsTrigger");
|
||||
isBrushScript = true;
|
||||
}
|
||||
|
||||
brushDescription = attribute.GetFieldValue<Coral::String>("Description");
|
||||
isTrigger = attribute.GetFieldValue<Coral::Bool32>("IsTrigger");
|
||||
|
||||
isBrushScript = true;
|
||||
if (attribute.GetType() == pointScriptAttributeType)
|
||||
{
|
||||
pointDescription = attribute.GetFieldValue<Coral::String>("Description");
|
||||
isPointScript = true;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string baseTypeName = std::string(type->GetBaseType().GetFullName());
|
||||
@@ -395,6 +418,11 @@ namespace Nuake
|
||||
m_BrushEntityTypes[shortenedTypeName] = gameScriptObject;
|
||||
}
|
||||
|
||||
if (isPointScript)
|
||||
{
|
||||
gameScriptObject.Description = pointDescription;
|
||||
m_PointEntityTypes[shortenedTypeName] = gameScriptObject;
|
||||
}
|
||||
m_GameEntityTypes[shortenedTypeName] = gameScriptObject;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ namespace Nuake {
|
||||
|
||||
bool isTrigger = false;
|
||||
std::string Description = "";
|
||||
AABB aabb = AABB({0, 0, 0}, { 1, 1, 1 });
|
||||
};
|
||||
|
||||
struct CompilationError
|
||||
@@ -86,6 +87,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<std::string, NetGameScriptObject> m_PointEntityTypes;
|
||||
std::unordered_map<uint32_t, Coral::ManagedObject> m_EntityToManagedObjects;
|
||||
|
||||
ScriptingEngineNet();
|
||||
@@ -126,6 +128,7 @@ namespace Nuake {
|
||||
Coral::ManagedAssembly GetNuakeAssembly() const { return m_NuakeAssembly; }
|
||||
|
||||
std::unordered_map<std::string, NetGameScriptObject> GetBrushEntities() const { return m_BrushEntityTypes; }
|
||||
std::unordered_map<std::string, NetGameScriptObject> GetPointEntities() const { return m_PointEntityTypes; }
|
||||
private:
|
||||
std::string GenerateGUID();
|
||||
};
|
||||
|
||||
@@ -157,13 +157,25 @@ namespace Nuake.Net
|
||||
public class CameraComponent : IComponent
|
||||
{
|
||||
internal static unsafe delegate*<int, NativeArray<float>> GetDirectionIcall;
|
||||
internal static unsafe delegate*<int, float, void> SetCameraFOVIcall;
|
||||
internal static unsafe delegate*<int, float> GetCameraFOVIcall;
|
||||
|
||||
public CameraComponent(int entityId)
|
||||
{
|
||||
EntityID = entityId;
|
||||
}
|
||||
|
||||
public float FOV { get; set; }
|
||||
public float FOV
|
||||
{
|
||||
get
|
||||
{
|
||||
unsafe { return GetCameraFOVIcall(EntityID); }
|
||||
}
|
||||
set
|
||||
{
|
||||
unsafe { SetCameraFOVIcall(EntityID, value); }
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Direction
|
||||
{
|
||||
@@ -181,6 +193,9 @@ namespace Nuake.Net
|
||||
|
||||
public class AudioEmitterComponent : IComponent
|
||||
{
|
||||
internal static unsafe delegate*<int, bool> GetIsPlayingIcall;
|
||||
internal static unsafe delegate*<int, bool, void> SetIsPlayingIcall;
|
||||
|
||||
public AudioEmitterComponent(int entityId)
|
||||
{
|
||||
EntityID = entityId;
|
||||
@@ -190,7 +205,11 @@ namespace Nuake.Net
|
||||
|
||||
public bool Loop { get; set; }
|
||||
public bool Spatialized { get; set; }
|
||||
public bool Playing { get; set; }
|
||||
public bool Playing
|
||||
{
|
||||
get { unsafe { return GetIsPlayingIcall(EntityID); } }
|
||||
set { unsafe { SetIsPlayingIcall(EntityID, value); } }
|
||||
}
|
||||
}
|
||||
|
||||
public class ModelComponent : IComponent
|
||||
|
||||
@@ -30,6 +30,23 @@ namespace Nuake.Net
|
||||
}
|
||||
}
|
||||
|
||||
public struct AABB
|
||||
{
|
||||
public Vector3 A;
|
||||
public Vector3 B;
|
||||
|
||||
public AABB(Vector3 a, Vector3 b)
|
||||
{
|
||||
A = a;
|
||||
B = b;
|
||||
}
|
||||
|
||||
public AABB(float ax, float ay, float az, float bx, float by, float bz)
|
||||
{
|
||||
A = new Vector3(ax, ay, az);
|
||||
B = new Vector3(bx, by, bz);
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public sealed class ExposedAttribute : Attribute
|
||||
@@ -53,12 +70,30 @@ namespace Nuake.Net
|
||||
public sealed class PointScript : Attribute
|
||||
{
|
||||
public string Description = "";
|
||||
public bool IsTrigger = false;
|
||||
public Vector3 AABBA;
|
||||
public Vector2 AABBB;
|
||||
|
||||
public List<float> AABBData = new();
|
||||
public List<float> ColorData = new();
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get { return Color; }
|
||||
set
|
||||
{
|
||||
ColorData.Add(value.R);
|
||||
ColorData.Add(value.G);
|
||||
ColorData.Add(value.B);
|
||||
}
|
||||
}
|
||||
|
||||
string Model;
|
||||
float ModelScale = 1.0f;
|
||||
string Sprite;
|
||||
|
||||
public PointScript(string description = "")
|
||||
{
|
||||
Description = description;
|
||||
IsTrigger = isTrigger;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user