Compare commits

...

9 Commits

19 changed files with 133 additions and 56 deletions
@@ -24,6 +24,7 @@ public:
private:
Octree<EntityAABB>* m_Octree;
std::vector<EntityAABB> m_OctreeResult;
std::unordered_map<EntityWrapper, glm::vec3> m_PrevPositions;
};
#endif
+2
View File
@@ -29,6 +29,7 @@ struct EntityWrapper
EntityWrapper Parent();
EntityWrapper FirstChildByName(const std::string& name);
EntityWrapper FirstParentWithComponent(const std::string& componentType);
EntityWrapper Clone(EntityWrapper parent = EntityWrapper::Invalid);
bool IsChildOf(EntityWrapper potentialParent);
bool Valid() const;
@@ -39,6 +40,7 @@ struct EntityWrapper
private:
EntityWrapper firstChildByNameRecursive(const std::string& name, EntityID parent);
EntityWrapper cloneRecursive(EntityWrapper entity, EntityWrapper parent);
};
namespace std
+1 -1
View File
@@ -40,7 +40,7 @@ public:
// Change the parent of an entity
void SetParent(EntityID entity, EntityID parent);
// Get children of an entity
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> GetChildren(EntityID entity);
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> GetDirectChildren(EntityID entity);
// Get all component pools
const std::unordered_map<std::string, ComponentPool*>& GetComponentPools() const { return m_ComponentPools; }
// Get the entity children map
+8
View File
@@ -73,6 +73,12 @@ public:
// Called when the user means to rename an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnEntityChangeName_t;
void SetEntityChangeNameCallback(OnEntityChangeName_t f) { m_OnEntityChangeName = f; }
// Called when the user pastes an entity previously "copied"
// @param EntityWrapper The entity to copy
// @param EntityWrapper The entity to parent the new copy to
// @return The new copy of the entity
typedef std::function<EntityWrapper(EntityWrapper, EntityWrapper)> OnEntityPaste_t;
void SetEntityPasteCallback(OnEntityPaste_t f) { m_OnEntityPaste = f; }
// Called when the user means to attach a new component to an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentAttach_t;
void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; }
@@ -111,6 +117,7 @@ private:
std::string m_DroppedFile = "";
bool m_Paused = false;
bool m_MouseLocked = false;
EntityWrapper m_CopyTarget = EntityWrapper::Invalid;
// Callbacks
OnEntitySelectedCallback_t m_OnEntitySelected = nullptr;
@@ -124,6 +131,7 @@ private:
OnComponentDelete_t m_OnComponentDelete = nullptr;
OnWidgetMode_t m_OnWidgetMode = nullptr;
OnWidgetSpace_t m_OnWidgetSpace = nullptr;
OnEntityPaste_t m_OnEntityPaste = nullptr;
// Events
EventRelay<EditorGUI, Events::KeyDown> m_EKeyDown;
+1
View File
@@ -56,6 +56,7 @@ private:
void OnEntityDelete(EntityWrapper entity);
void OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent);
void OnEntityChangeName(EntityWrapper entity, const std::string& name);
EntityWrapper OnEntityPaste(EntityWrapper entityToCopy, EntityWrapper parent);
void OnComponentAttach(EntityWrapper entity, const std::string& componentType);
void OnComponentDelete(EntityWrapper entity, const std::string& componentType);
void OnWidgetSpace(EditorGUI::WidgetSpace widgetSpace);
+1
View File
@@ -19,6 +19,7 @@
#include "Core/World.h"
#include "Core/EventBroker.h"
#include "Core/ConfigFile.h"
#include "Core/EPlayerDeath.h"
#include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
#include "../Game/Events/EDoubleJump.h"
-1
View File
@@ -2,7 +2,6 @@
<Physics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Physics.xsd">
<Velocity X="0" Y="0" Z="0"/>
<Gravity>true</Gravity>
<PrevOrigin X="-9876.5" Y="-9876.5" Z="-9876.5"/>
<IsOnGround>false</IsOnGround>
<VerticalStepHeight>0.33</VerticalStepHeight>
</Physics>
-1
View File
@@ -13,7 +13,6 @@
<xs:annotation><xs:documentation>m/s^2</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Gravity" type="t:bool" minOccurs="0"/>
<xs:element name="PrevOrigin" type="t:Vector" minOccurs="0"/>
<xs:element name="IsOnGround" type="t:bool" minOccurs="0"/>
<xs:element name="VerticalStepHeight" type="t:double" minOccurs="0">
<xs:annotation><xs:documentation>The largest height of a "stair-step" that can be walked over</xs:documentation></xs:annotation>
-1
View File
@@ -13,7 +13,6 @@
<c:DashAbility/>
<c:Health/>
<c:Physics>
<PrevOrigin X="0" Y="0.772000015" Z="0"/>
<Velocity X="2.30999646e-23" Y="0" Z="1.05272533e-23"/>
</c:Physics>
<c:Player>
-1
View File
@@ -13,7 +13,6 @@
<c:DashAbility/>
<c:Health/>
<c:Physics>
<PrevOrigin X="0" Y="0.772000015" Z="0"/>
<Velocity X="2.30999646e-23" Y="0" Z="1.05272533e-23"/>
</c:Physics>
<c:Player>
+45 -43
View File
@@ -16,51 +16,51 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
EntityAABB& boxA = *boundingBox;
bool everHitTheGround = false;
glm::vec3 size = boxA.Size();
float diameter = std::min(size.x, size.z);
glm::vec3 prevOrigin = (glm::vec3)cPhysics["PrevOrigin"];
glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin;
float rayLength = glm::length(toCurrentPos) + 0.5f*diameter;
//If the entity has moved farther than the size of its box, we need to handle it specially.
bool traceCollision = rayLength > diameter;
//hack solution: If prevOrigin is less than -9000 in all dimensions,
//then it means it is not set, i.e. this is the first collision check for the entity.
if (traceCollision && glm::any(glm::greaterThan((glm::vec3)cPhysics["PrevOrigin"], glm::vec3(-9000.f)))) {
Ray ray(prevOrigin, toCurrentPos);
m_OctreeResult.clear();
m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult);
for (auto& boxB : m_OctreeResult) {
if (boxA.Entity == boxB.Entity) {
continue;
}
bool hit;
float dist;
if (boxB.Entity.HasComponent("Model")) {
RawModel* model;
std::string res = (std::string)boxB.Entity["Model"]["Resource"];
try {
model = ResourceManager::Load<RawModel, true>(res);
} catch (const std::exception&) {
auto prevPosIt = m_PrevPositions.find(entity);
if (prevPosIt != m_PrevPositions.end()) {
glm::vec3 size = boxA.Size();
float diameter = std::min(size.x, size.z);
glm::vec3 prevOrigin = prevPosIt->second;
glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin;
float rayLength = glm::length(toCurrentPos) + 0.5f*diameter;
//If the entity has moved farther than the size of its box, we need to handle it specially.
if (rayLength > diameter) {
Ray ray(prevOrigin, toCurrentPos);
m_OctreeResult.clear();
m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult);
for (auto& boxB : m_OctreeResult) {
if (boxA.Entity == boxB.Entity) {
continue;
}
float u, v;
hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v);
} else {
hit = Collision::RayVsAABB(ray, boxB, dist);
}
if (hit && dist < rayLength) {
//Set the entity to where it was colliding, minus the maximum box size.
//TODO: Perhaps this should be done slightly more properly.
glm::vec3 newOriginPos = ray.Origin() + (dist - 0.707107f*diameter) * ray.Direction();
glm::vec3 resolve = newOriginPos - boxA.Origin();
(glm::vec3&)cTransform["Position"] += resolve;
boxA = *Collision::EntityAbsoluteAABB(entity);
if (resolve.y > 0) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
bool hit;
float dist;
if (boxB.Entity.HasComponent("Model")) {
RawModel* model;
std::string res = (std::string)boxB.Entity["Model"]["Resource"];
try {
model = ResourceManager::Load<RawModel, true>(res);
} catch (const std::exception&) {
continue;
}
float u, v;
hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v);
} else {
hit = Collision::RayVsAABB(ray, boxB, dist);
}
if (hit && dist < rayLength) {
//Set the entity to where it was colliding, minus the maximum box size.
//TODO: Perhaps this should be done slightly more properly.
glm::vec3 newOriginPos = ray.Origin() + (dist - 0.707107f*diameter) * ray.Direction();
glm::vec3 resolve = newOriginPos - boxA.Origin();
(glm::vec3&)cTransform["Position"] += resolve;
boxA = *Collision::EntityAbsoluteAABB(entity);
if (resolve.y > 0) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
((glm::vec3&)cPhysics["Velocity"]).y = 0.f;
}
break;
}
break;
}
}
}
@@ -90,6 +90,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
float verticalStepHeight = (float)(double)cPhysics["VerticalStepHeight"];
if (Collision::AABBvsTriangles(boxA, model->Vertices(), model->m_Indices, modelMatrix, inOutVelocity, verticalStepHeight, isOnGround, resolutionVector)) {
(glm::vec3&)cTransform["Position"] += resolutionVector;
boxA = *Collision::EntityAbsoluteAABB(entity);
cPhysics["Velocity"] = inOutVelocity;
if (isOnGround) {
everHitTheGround = true;
@@ -99,6 +100,7 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
} else if (Collision::AABBVsAABB(boxA, boxB, resolutionVector)) {
//Enter here if boxB has no Model.
(glm::vec3&)cTransform["Position"] += resolutionVector;
boxA = *Collision::EntityAbsoluteAABB(entity);
if (resolutionVector.y > 0) {
everHitTheGround = true;
(bool)cPhysics["IsOnGround"] = true;
@@ -112,5 +114,5 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c
(bool)cPhysics["IsOnGround"] = false;
}
(glm::vec3&)cPhysics["PrevOrigin"] = boxA.Origin();
m_PrevPositions[entity] = boxA.Origin();
}
+36 -1
View File
@@ -51,6 +51,17 @@ EntityWrapper EntityWrapper::FirstParentWithComponent(const std::string& compone
return EntityWrapper::Invalid;
}
EntityWrapper EntityWrapper::Clone(EntityWrapper parent /*= Invalid*/)
{
if (!Valid()) {
return EntityWrapper::Invalid;
}
EntityWrapper clone = cloneRecursive(*this, EntityWrapper::Invalid);
this->World->SetParent(clone.ID, parent.ID);
return clone;
}
bool EntityWrapper::IsChildOf(EntityWrapper potentialParent)
{
EntityWrapper entity = *this;
@@ -111,7 +122,7 @@ EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name,
return EntityWrapper::Invalid;
}
auto itPair = this->World->GetChildren(parent);
auto itPair = this->World->GetDirectChildren(parent);
if (itPair.first == itPair.second) {
return EntityWrapper::Invalid;
}
@@ -131,3 +142,27 @@ EntityWrapper EntityWrapper::firstChildByNameRecursive(const std::string& name,
return EntityWrapper::Invalid;
}
EntityWrapper EntityWrapper::cloneRecursive(EntityWrapper entity, EntityWrapper parent)
{
EntityWrapper clone = EntityWrapper(entity.World, entity.World->CreateEntity(parent.ID));
entity.World->SetName(clone.ID, entity.Name());
// Clone components
for (auto& kv : entity.World->GetComponentPools()) {
if (kv.second->KnowsEntity(entity.ID)) {
ComponentWrapper c1 = kv.second->GetByEntity(entity.ID);
ComponentWrapper c2 = entity.World->AttachComponent(clone.ID, kv.first);
c1.Copy(c2);
}
}
// Clone children
auto children = entity.World->GetDirectChildren(entity.ID);
for (auto it = children.first; it != children.second; ++it) {
EntityWrapper child(entity.World, it->second);
cloneRecursive(child, clone);
}
return clone;
}
+1 -1
View File
@@ -127,7 +127,7 @@ void World::SetParent(EntityID entity, EntityID parent)
m_EntityChildren.insert(std::make_pair(parent, entity));
}
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> World::GetChildren(EntityID entity)
const std::pair<std::unordered_multimap<EntityID, EntityID>::const_iterator, std::unordered_multimap<EntityID, EntityID>::const_iterator> World::GetDirectChildren(EntityID entity)
{
return m_EntityChildren.equal_range(entity);
}
+18
View File
@@ -580,6 +580,11 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode)
bool EditorGUI::OnKeyDown(const Events::KeyDown& e)
{
ImGuiIO& io = ImGui::GetIO();
if (io.WantCaptureKeyboard) {
return false;
}
if (e.ModCtrl && e.KeyCode == GLFW_KEY_S) {
if (m_CurrentSelection.Valid()) {
EntityWrapper baseParent = m_CurrentSelection;
@@ -598,6 +603,19 @@ bool EditorGUI::OnKeyDown(const Events::KeyDown& e)
entityImport(m_World);
}
if (e.ModCtrl && e.KeyCode == GLFW_KEY_C) {
m_CopyTarget = m_CurrentSelection;
}
if (e.ModCtrl && e.KeyCode == GLFW_KEY_V) {
if (m_OnEntityPaste != nullptr) {
EntityWrapper copy = m_OnEntityPaste(m_CopyTarget, m_CurrentSelection);
if (copy != EntityWrapper::Invalid) {
SelectEntity(copy);
}
}
}
if (e.KeyCode == GLFW_KEY_DELETE) {
if (m_CurrentSelection.Valid()) {
entityDelete(m_CurrentSelection);
+6
View File
@@ -28,6 +28,7 @@ EditorSystem::EditorSystem(SystemParams params, IRenderer* renderer, RenderFrame
m_EditorGUI->SetEntityDeleteCallback(std::bind(&EditorSystem::OnEntityDelete, this, std::placeholders::_1));
m_EditorGUI->SetEntityChangeParentCallback(std::bind(&EditorSystem::OnEntityChangeParent, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetEntityChangeNameCallback(std::bind(&EditorSystem::OnEntityChangeName, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetEntityPasteCallback(std::bind(&EditorSystem::OnEntityPaste, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1));
@@ -160,6 +161,11 @@ void EditorSystem::OnEntityChangeName(EntityWrapper entity, const std::string& n
}
}
EntityWrapper EditorSystem::OnEntityPaste(EntityWrapper entityToCopy, EntityWrapper parent)
{
return entityToCopy.Clone(parent);
}
void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType)
{
if (entity.Valid()) {
+8 -2
View File
@@ -261,8 +261,14 @@ void Client::parseEntityDeletion(Packet & packet)
if (m_ServerIDToClientID.find(entityToDelete) != m_ServerIDToClientID.end()) {
EntityID localEntity = m_ServerIDToClientID.at(entityToDelete);
if (m_World->ValidEntity(localEntity)) {
m_World->DeleteEntity(localEntity);
deleteFromServerClientMaps(entityToDelete, localEntity);
if (m_World->HasComponent(localEntity,"Player")) {
Events::PlayerDeath e;
e.Player = EntityWrapper(m_World, localEntity);
m_EventBroker->Publish(e);
} else {
m_World->DeleteEntity(localEntity);
deleteFromServerClientMaps(entityToDelete, localEntity);
}
}
}
}
+3 -3
View File
@@ -186,7 +186,7 @@ void Server::addInputCommandsToPacket(Packet& packet)
void Server::addPlayersToPacket(Packet & packet, EntityID entityID)
{
auto itPair = m_World->GetChildren(entityID);
auto itPair = m_World->GetDirectChildren(entityID);
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
// Loop through every child
for (auto it = itPair.first; it != itPair.second; it++) {
@@ -234,7 +234,7 @@ void Server::addPlayersToPacket(Packet & packet, EntityID entityID)
void Server::addChildrenToPacket(Packet & packet, EntityID entityID)
{
auto itPair = m_World->GetChildren(entityID);
auto itPair = m_World->GetDirectChildren(entityID);
std::unordered_map<std::string, ComponentPool*> worldComponentPools = m_World->GetComponentPools();
// Loop through every child
for (auto it = itPair.first; it != itPair.second; it++) {
@@ -601,7 +601,7 @@ void Server::parsePlayerTransform(Packet& packet)
bool Server::shouldSendToClient(EntityWrapper childEntity)
{
auto children = m_World->GetChildren(childEntity.ID);
auto children = m_World->GetDirectChildren(childEntity.ID);
for (auto it = children.first; it != children.second; it++) {
EntityWrapper child(m_World, it->second);
if(child.HasComponent("CapturePoint")) {
+1
View File
@@ -17,6 +17,7 @@ void CubeMapPass::LoadTextures(std::string input)
m_CubeMapTextures.push_back(img);
}
GenerateCubeMapTexture();
m_PreviusCubeMapTexture = input;
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /
}
// Find any SpawnPoints existing as children of spawner
auto children = spawner.World->GetChildren(spawner.ID);
auto children = spawner.World->GetDirectChildren(spawner.ID);
std::vector<EntityWrapper> spawnPoints;
for (auto kv = children.first; kv != children.second; ++kv) {
const EntityID& child = kv->second;