Compare commits

...

63 Commits

Author SHA1 Message Date
verysecrethero 6f739e22f3 Crash fix for: if you delete a team component in editor. 2016-01-22 10:10:39 +01:00
Jace 8cf83454d7 Fixed input going through editor UI 2016-01-21 17:45:20 +01:00
William Moberg 41f0daaf3f Merge pull request #45 from teamfisk/ShootEvent
Changed some files so it works with the changes in master. (weaponsys…
2016-01-21 17:40:57 +01:00
verysecrethero deb6ff1b16 Changed some files so it works with the changes in master. (weaponsystem,capturepoint,some tests) 2016-01-21 17:36:47 +01:00
William Moberg 4d60f387ed Merge pull request #44 from teamfisk/EditorUsefulness
Editor refactoring
2016-01-21 17:03:52 +01:00
Jace f740d46683 Merge branch 'EditorUsefulness' of github.com:teamfisk/TacticalZ into EditorUsefulness 2016-01-21 17:01:06 +01:00
Jace 75dcdcec41 Fixed inconsistent editor input controls. Left mouse = select and move. Right mouse = camera. 2016-01-21 17:00:47 +01:00
viktorljung 254caf9e5d Picking depthbuffer fix 2016-01-21 16:49:20 +01:00
Jace 1c6750f5b0 Fixed uniform scale on editor widgets 2016-01-21 16:37:35 +01:00
William Moberg 3548cfa248 Merge pull request #27 from teamfisk/ShootEvent
Shoot event
2016-01-21 16:35:55 +01:00
verysecrethero 973ccd34c9 Removed unnecessary string in EPlayerDamage (TypeOfDamage). Renamed a variable in WeaponSystem 2016-01-21 16:30:07 +01:00
Jace 43b8fd29f6 Fixed widget world movement 2016-01-21 16:21:20 +01:00
Jace a6548a72b3 Merge remote-tracking branch 'origin/master' into EditorUsefulness
# Conflicts:
#	include/Engine/Collision/CollidableOctreeSystem.h
#	include/Engine/Collision/CollisionSystem.h
#	include/Engine/Collision/TriggerSystem.h
#	include/Engine/Rendering/RenderSystem.h
#	include/Game/Systems/PlayerSystem.h
#	resources/Schema/Components/Physics.xsd
#	resources/Schema/Types/Entity.xsd
#	src/Engine/Rendering/RenderSystem.cpp
#	src/Engine/Rendering/Renderer.cpp
#	src/Game/Game.cpp
#	src/Game/Systems/HealthSystem.cpp
#	src/Game/Systems/PlayerSystem.cpp
#	src/Tests/OctTreeTestGameClass.cpp
2016-01-21 16:16:35 +01:00
verysecrethero 7deb32431e Removed Color TestCode in WeaponSystem 2016-01-21 16:03:30 +01:00
Jace fc06a4babc Editor keyboard shortcuts:
Ctrl+S to save the currently selected entity file (iterates to the base parent)
Ctrl+N to create a new empty entity under the selection
Ctrl+O to import an entity file
Del to delete an entity
2016-01-21 15:58:27 +01:00
Tobias Dahl c6e9aad0c7 Merge pull request #42 from teamfisk/SpawnMiniBranch
HealthSystem now deletes the entity after publishing the PlayerDeath …
2016-01-21 15:10:16 +01:00
Jace b9147344e1 Semi-working translation widget 2016-01-21 14:14:22 +01:00
Jace 0183e1bdb7 Fixed enum string parsing bug that would ignore parsing additional fields in a component after it encountered the first enum. 2016-01-21 12:24:08 +01:00
verysecrethero bdebc9de62 WeaponSystem now handles "PrimaryFire" input events. It sends out ePlayerDamage event if it hits a player. Included some tests 2016-01-21 11:55:51 +01:00
Jace f1345419b6 EditorWidgetSystem that takes care of moving widgets around 2016-01-21 10:30:19 +01:00
Jace 5e70d6eef6 EntityWrapper::Parent helper function 2016-01-21 10:29:48 +01:00
Jace 4aa9100c69 Camera::WorldToScreen helper function 2016-01-21 10:29:36 +01:00
verysecrethero 7b34e001ba Merge remote-tracking branch 'origin/master' into ShootEvent 2016-01-21 10:26:42 +01:00
verysecrethero c2e05de89f Deleted some components, etc for ShootEvent that will likely be used in a WeaponSystem instead 2016-01-21 10:24:34 +01:00
verysecrethero b098bd2bd3 Merge remote-tracking branch 'origin/master' into ShootEvent
# Conflicts:
#	include/Engine/Core/ComponentWrapper.h
#	include/Game/PlayerSystem.h
#	include/Game/Systems/HealthSystem.h
#	resources/Schema/Components.xsd
#	resources/Schema/Components/Player.xml
#	resources/Schema/Types/Entity.xsd
#	src/Game/PlayerSystem.cpp
#	src/Tests/HealthSystemTest.cpp
#	src/Tests/OctTreeTestAnders.cpp
#	src/Tests/OctTreeTestGameClass.cpp
#	src/Tests/OctTreeTestGameClass.h
#	src/Tests/OctTreeTestHardCodedTestWorld.h
2016-01-20 17:53:33 +01:00
Jace 8854794cbc fixup! Editor widget selection and creation 2016-01-19 14:31:56 +01:00
Jace 260203fa4d Annotation on physics component 2016-01-19 13:28:16 +01:00
Jace d030e8f699 Editor widget selection and creation 2016-01-19 13:28:02 +01:00
Jace 61984d2c4a Removed lots of slowing debug output from entity parsing pipeline 2016-01-19 13:27:29 +01:00
Jace cfe023cc1d Created ComponentInfo::EnumType which defines which native type to use for enums. 2016-01-19 12:33:53 +01:00
Jace a6445c65aa Fixed EntityParser to handle string enums properly. 2016-01-19 12:15:20 +01:00
Jace 162523d3ca Made EntityFileWriter store enums as strings instead of integer values to be resistant to enum value changes! 2016-01-19 11:55:27 +01:00
Jace 3fb975a8d9 Editor widget entities 2016-01-19 11:44:03 +01:00
Jace 267a60ef30 Better loading of editor toolbox icons 2016-01-19 11:43:38 +01:00
Jace 68af853a03 Editor entity naming 2016-01-19 11:43:03 +01:00
Jace b62e42567c Fixed editor enum selection 2016-01-19 11:35:31 +01:00
Jace 9e3dfff7b6 WIP world pausing 2016-01-19 00:52:17 +01:00
Jace 79eaa7364c Editor toolbox buttons 2016-01-18 23:59:46 +01:00
Jace 51979d7f0c Changed System to take World through constructor and store it instead, cause it makes more sense. 2016-01-18 23:59:33 +01:00
Jace 3fc44e944c Editor entity reparenting. 2016-01-18 21:20:20 +01:00
Jace 1760f9dfb1 Added inequality operator to EntityWrapper 2016-01-18 21:17:52 +01:00
Jace d4242bbead Editor entity create and delete. 2016-01-18 19:26:00 +01:00
Jace 631dd57eeb Editor entity import, save, delete, component attach, component delete. 2016-01-18 18:55:19 +01:00
Jace 9cb5f4bd2f Added a stats window 2016-01-18 18:54:57 +01:00
Jace 3bc7dceca5 Made EntityWrapper hashable 2016-01-18 14:55:49 +01:00
Jace 504f301e4d Added refactored property sheet for components 2016-01-18 13:51:22 +01:00
Jace e39e4064f2 Entity tree button mockup 2016-01-17 23:06:32 +01:00
Jace 0d50ede6f5 Base work on reimplementing editor GUI 2016-01-17 07:34:20 +01:00
Jace 4786986abd Rendering pipeline fixes across the board and base work on refactored editor 2016-01-17 06:29:25 +01:00
Jace e34856468a Removed DrawScenePass, since it doesn't seem to be used 2016-01-17 06:27:45 +01:00
Jace e2357b8625 Fixed absolute position not taking scale into account 2016-01-17 06:23:13 +01:00
Jace 6ec2258758 Added UniformScale component which keeps an entity's scale at a uniform value relative to the screen. 2016-01-17 06:22:35 +01:00
Jace 9f447afbdb Added EntityWrapper::Valid and bool overload to be check if an entity is valid and still exists in the world more easily 2016-01-17 06:20:27 +01:00
verysecrethero e6527196ed Modified a few files according to the current CodeStandards 2016-01-13 15:50:30 +01:00
verysecrethero c14f3789f7 PlayerSystem now counts down the CoolDownTimer on both HeldItems for the player. Updated ShootEventTest to verify this 2016-01-13 15:26:10 +01:00
verysecrethero a20ca49d53 Fixed typo backslash instead of slash in various classes (the includes) 2016-01-12 10:46:34 +01:00
verysecrethero 774bb8ce56 Simplified PlayerSystem branches a lot! Thanks William! 2016-01-11 17:36:23 +01:00
verysecrethero 0cc58f088a EquippedItem,Ammo got changed to int instead of double. Loading entities from map the new way in Tests. ComponentWrapper:s Name is now Type 2016-01-11 17:15:49 +01:00
verysecrethero 00805d30d0 Merge remote-tracking branch 'origin/master' into ShootEvent 2016-01-11 17:06:48 +01:00
verysecrethero 2f6261dfbf EShoot: changed to string weaponType to int currentlyEquippedItem
PlayerSystem.h: added HeldItem enum
PlayerSystem.cpp: simplified writing doubles, uses HeldItem enum
ShootEventTest.cpp: simplified writing doubles
2016-01-11 15:49:33 +01:00
verysecrethero 2cd0e94a60 Changed the comparison method in PlayerSystem since its currently using doubles 2016-01-11 15:49:33 +01:00
verysecrethero 8f92de3683 xml/xsd files changed type to double. fixed cooldownbug in PlayerSystem. Added 4 tests in ShootEventTest and generalized it a lot 2016-01-11 15:49:33 +01:00
verysecrethero 31c1c0ac8d New Event: EShoot. New Components: PrimaryItem,SecondaryItem. New Test: ShootEventTest. Added LeftMouseRelease->Shoot in PlayerSystem
TODO: generalize the test
2016-01-11 15:49:33 +01:00
95 changed files with 2516 additions and 1280 deletions
@@ -8,14 +8,14 @@
class CollidableOctreeSystem : public ImpureSystem, public PureSystem
{
public:
CollidableOctreeSystem(EventBroker* eventBroker, Octree<AABB>* octree)
: System(eventBroker)
CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker)
, PureSystem("Collidable")
, m_Octree(octree)
{ }
virtual void Update(World* world, double dt) override;
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<AABB>* m_Octree;
+3 -3
View File
@@ -13,8 +13,8 @@
class CollisionSystem : public PureSystem
{
public:
CollisionSystem(EventBroker* eventBroker, Octree<AABB>* octree)
: System(eventBroker)
CollisionSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker)
, PureSystem("Collidable")
, m_Octree(octree)
, zPress(false)
@@ -23,7 +23,7 @@ public:
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp);
}
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<AABB>* m_Octree;
+3 -3
View File
@@ -14,8 +14,8 @@ class AABB;
class TriggerSystem : public PureSystem
{
public:
TriggerSystem(EventBroker* eventBroker, Octree<AABB>* octree)
: System(eventBroker)
TriggerSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker)
, PureSystem("Trigger")
, m_Octree(octree)
{
@@ -24,7 +24,7 @@ public:
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &TriggerSystem::OnLeave);
}
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<AABB>* m_Octree;
+1
View File
@@ -4,6 +4,7 @@
#include <vector>
#include <map>
#include <unordered_map>
#include <algorithm>
#include "Core/Util/Logging.h"
#include "Core/Util/IfDebug.h"
+3 -1
View File
@@ -5,12 +5,14 @@
struct ComponentInfo
{
typedef int EnumType;
struct Meta_t
{
std::string Annotation;
unsigned int Allocation = 0;
std::map<std::string, std::string> FieldAnnotations;
std::map<std::string, std::map<std::string, int>> FieldEnumDefinitions;
std::map<std::string, std::map<std::string, EnumType>> FieldEnumDefinitions;
};
struct Field_t
+2 -2
View File
@@ -18,7 +18,7 @@ struct ComponentWrapper
const ::EntityID EntityID;
char* Data;
int Enum(const char* fieldName, const char* enumKey)
ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey)
{
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey);
}
@@ -58,7 +58,7 @@ struct ComponentWrapper
public:
// Return the integer value of an enum type key for this field
int Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); }
ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); }
template <typename T>
operator T&() { return m_Component->Field<T>(m_PropertyName); }
+3
View File
@@ -11,6 +11,9 @@ struct KeyDown : Event
{
/** GLFW key code */
int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
};
}
+3
View File
@@ -11,6 +11,9 @@ struct KeyUp : Event
{
/** GLFW key code */
int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
};
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef EPause_h__
#define EPause_h__
#include "EventBroker.h"
#include "World.h"
namespace Events
{
struct Pause : Event
{
::World* World;
};
struct Resume : Event
{
::World* World;
};
}
#endif
-2
View File
@@ -11,8 +11,6 @@ struct PlayerDamage : Event
{
double DamageAmount;
EntityID PlayerDamagedID;
//optional TypeOfDamage
std::string TypeOfDamage;
};
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef EShoot_h__
#define EShoot_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
struct Shoot : Event
{
//ID for who made the shot
EntityID shooter;
};
}
#endif
+22 -3
View File
@@ -2,6 +2,7 @@
#define EntityWrapper_h__
#include <boost/optional.hpp>
#include <boost/functional/hash.hpp>
#include "ComponentWrapper.h"
class World;
@@ -23,10 +24,28 @@ struct EntityWrapper
static const EntityWrapper Invalid;
bool HasComponent(const std::string& componentName);
EntityWrapper Parent();
bool Valid();
ComponentWrapper operator[](const std::string& componentName);
bool operator==(const EntityWrapper& e);
explicit operator EntityID();
ComponentWrapper operator[](const char* componentName);
bool operator==(const EntityWrapper& e) const;
bool operator!=(const EntityWrapper& e) const;
explicit operator EntityID() const;
operator bool();
};
namespace std
{
template<> struct hash<EntityWrapper>
{
std::size_t operator()(const EntityWrapper& e) const
{
std::size_t seed = 0;
boost::hash_combine(seed, e.World);
boost::hash_combine(seed, e.ID);
return seed;
}
};
}
#endif
+7 -7
View File
@@ -11,14 +11,14 @@ class System
friend class SystemPipeline;
protected:
System()
: m_EventBroker(nullptr)
{ }
System(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
System(World* world, EventBroker) { }
System(World* world, EventBroker* eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{ }
virtual ~System() = default;
World* m_World;
EventBroker* m_EventBroker;
};
@@ -34,7 +34,7 @@ protected:
const std::string m_ComponentType;
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) = 0;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0;
};
class ImpureSystem : public virtual System
@@ -45,7 +45,7 @@ protected:
ImpureSystem() = default;
virtual ~ImpureSystem() = default;
virtual void Update(World* world, double dt) = 0;
virtual void Update(double dt) = 0;
};
#endif
+36 -8
View File
@@ -5,13 +5,19 @@
#include "EventBroker.h"
#include "System.h"
#include "World.h"
#include "EPause.h"
class SystemPipeline
{
public:
SystemPipeline(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
SystemPipeline(World* world, EventBroker* eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_EPause, &SystemPipeline::OnPause);
EVENT_SUBSCRIBE_MEMBER(m_EResume, &SystemPipeline::OnResume);
}
~SystemPipeline()
{
for (UnorderedSystems& group : m_OrderedSystemGroups) {
@@ -29,7 +35,7 @@ public:
m_OrderedSystemGroups.resize(updateOrderLevel + 1);
}
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
System* system = new T(m_EventBroker, args...);
System* system = new T(m_World, m_EventBroker, args...);
group.Systems[typeid(T).name()] = system;
PureSystem* pureSystem = dynamic_cast<PureSystem*>(system);
@@ -47,8 +53,12 @@ public:
}
}
void Update(World* world, double dt)
void Update(double dt)
{
if (m_Paused) {
dt = 0.0;
}
for (UnorderedSystems& group : m_OrderedSystemGroups) {
// Process events
for (auto& pair : group.Systems) {
@@ -57,18 +67,18 @@ public:
// Update
for (auto& system : group.ImpureSystems) {
system->Update(world, dt);
system->Update(dt);
}
for (auto& pair : group.PureSystems) {
const std::string& componentName = pair.first;
auto& systems = pair.second;
const ComponentPool* pool = world->GetComponents(componentName);
const ComponentPool* pool = m_World->GetComponents(componentName);
if (pool == nullptr) {
continue;
}
for (auto& component : *pool) {
for (auto& system : systems) {
system->UpdateComponent(world, EntityWrapper(world, component.EntityID), component, dt);
system->UpdateComponent(EntityWrapper(m_World, component.EntityID), component, dt);
}
}
}
@@ -76,7 +86,10 @@ public:
}
private:
World* m_World;
EventBroker* m_EventBroker;
bool m_Paused = false;
struct UnorderedSystems
{
std::map<std::string, System*> Systems;
@@ -84,6 +97,21 @@ private:
std::vector<ImpureSystem*> ImpureSystems;
};
std::vector<UnorderedSystems> m_OrderedSystemGroups;
EventRelay<SystemPipeline, Events::Pause> m_EPause;
bool OnPause(const Events::Pause& e) {
if (e.World == m_World) {
m_Paused = true;
}
return true;
}
EventRelay<SystemPipeline, Events::Resume> m_EResume;
bool OnResume(const Events::Resume& e) {
if (e.World == m_World) {
m_Paused = false;
}
return true;
}
};
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef UniformScaleSystem_h__
#define UniformScaleSystem_h__
#include "../GLM.h"
#include "System.h"
#include "../Rendering/ESetCamera.h"
class UniformScaleSystem : public PureSystem
{
public:
UniformScaleSystem(World* world, EventBroker* eventBroker);
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override;
private:
EntityWrapper m_Camera = EntityWrapper::Invalid;
EventRelay<UniformScaleSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(const Events::SetCamera& e);
};
#endif
+153
View File
@@ -0,0 +1,153 @@
#ifndef EditorGUI_h__
#define EditorGUI_h__
#include <imgui/imgui.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui/imgui_internal.h>
#include <nativefiledialog/nfd.h>
#include <boost/filesystem.hpp>
#include <boost/any.hpp>
#include "../Common.h"
#include "../GLM.h"
#include <glm/gtx/common.hpp>
#include "EditorWidgetSystem.h"
#include "../Core/EventBroker.h"
#include "../Core/World.h"
#include "../Core/EntityWrapper.h"
#include "../Core/ResourceManager.h"
#include "../Core/EPause.h"
#include "../Core/EKeyDown.h"
#include "../Rendering/Texture.h"
class EditorGUI
{
public:
EditorGUI(World* world, EventBroker* eventBroker);
enum class WidgetMode
{
Translate,
Rotate,
Scale
};
void Draw();
void SelectEntity(EntityWrapper entity);
void SetDirty(EntityWrapper entity);
// Called when an entity is selected in the entity tree
typedef std::function<void(EntityWrapper)> OnEntitySelectedCallback_t;
void SetEntitySelectedCallback(OnEntitySelectedCallback_t f) { m_OnEntitySelected = f; }
// Called when the user means to import an entity file.
// @param EntityWrapper The entity to parent the imported entity to. The entity will be imported into the world of this entity.
// @param boost::filesystem::path The path to the entity to import
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper, boost::filesystem::path)> OnEntityImport_t;
void SetEntityImportCallback(OnEntityImport_t f) { m_OnEntityImport = f; }
// Called when the user means to save an entity to file.
// Permitted to throw exceptions on save failure.
typedef std::function<void(EntityWrapper, boost::filesystem::path)> OnEntitySave_t;
void SetEntitySaveCallback(OnEntitySave_t f) { m_OnEntitySave = f; }
// Called when the user means to create a new entity.
// @param EntityWrapper The parent of the entity to be created
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper)> OnEntityCreate_t;
void SetEntityCreateCallback(OnEntityCreate_t f) { m_OnEntityCreate = f; }
// Called when the user means to delete an entity.
typedef std::function<void(EntityWrapper)> OnEntityDelete_t;
void SetEntityDeleteCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; }
// Called when the user means to change the parent of an entity.
typedef std::function<void(EntityWrapper, EntityWrapper)> OnEntityChangeParent_t;
void SetEntityChangeParentCallback(OnEntityChangeParent_t f) { m_OnEntityChangeParent = f; }
// 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 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; }
// Called when the user means to delete a component off an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentDelete_t;
void SetComponentDeleteCallback(OnComponentDelete_t f) { m_OnComponentDelete = f; }
// Called when the user selects a widget mode.
typedef std::function<void(WidgetMode)> OnWidgetMode_t;
void SetWidgetModeCallback(OnWidgetMode_t f) { m_OnWidgetMode = f; }
private:
World* m_World;
EventBroker* m_EventBroker;
struct EntityFileInfo
{
boost::filesystem::path Path;
bool Dirty = false;
};
// Config variables
const boost::filesystem::path m_DefaultEntityPath = boost::filesystem::path("Schema") / boost::filesystem::path("Entities");
// State
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
std::unordered_map<EntityWrapper, EntityFileInfo> m_EntityFiles;
EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid;
std::string m_LastErrorMessage;
WidgetMode m_CurrentWidgetMode = WidgetMode::Translate;
std::set<std::string> m_ModalsToOpen;
std::map<std::string, boost::any> m_ModalData;
// Callbacks
OnEntitySelectedCallback_t m_OnEntitySelected = nullptr;
OnEntityImport_t m_OnEntityImport = nullptr;
OnEntitySave_t m_OnEntitySave = nullptr;
OnEntityCreate_t m_OnEntityCreate = nullptr;
OnEntityDelete_t m_OnEntityDelete = nullptr;
OnEntityChangeParent_t m_OnEntityChangeParent = nullptr;
OnEntityChangeName_t m_OnEntityChangeName = nullptr;
OnComponentAttach_t m_OnComponentAttach = nullptr;
OnComponentDelete_t m_OnComponentDelete = nullptr;
OnWidgetMode_t m_OnWidgetMode = nullptr;
// Events
EventRelay<EditorGUI, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e);
// Utility functions
boost::filesystem::path fileOpenDialog();
boost::filesystem::path fileSaveDialog();
const std::string formatEntityName(EntityWrapper entity);
GLuint tryLoadTexture(std::string filePath);
void openModal(const std::string& modal);
// Entity file handling methods
void entityImport(World* world);
void entitySave(EntityWrapper entity, bool saveAs = false);
void entityCreate(World* world, EntityWrapper parent);
void entityDelete(EntityWrapper entity);
void entityChangeParent(EntityWrapper entity, EntityWrapper parent);
// UI drawing methods
void drawMenu();
void drawTools();
void drawEntities(World* world);
void drawEntitiesRecursive(World* world, EntityID parent);
bool drawEntityNode(EntityWrapper entity);
void drawComponents(EntityWrapper entity);
bool drawComponentNode(EntityWrapper entity, const ComponentInfo& componentType);
bool drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field);
bool drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field);
void drawModals();
// Custom UI elements
bool createDeleteButton(const std::string& componentType);
void createWidgetToolButton(WidgetMode mode);
};
#endif
@@ -0,0 +1,27 @@
#ifndef EditorRenderSystem_h__
#define EditorRenderSystem_h__
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/ModelJob.h"
#include "../Rendering/Camera.h"
#include "../Rendering/ESetCamera.h"
class EditorRenderSystem : public ImpureSystem
{
public:
EditorRenderSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
virtual void Update(double dt) override;
private:
IRenderer* m_Renderer;
RenderFrame* m_RenderFrame;
Camera* m_EditorCamera;
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
EventRelay<EditorRenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(Events::SetCamera& e);
};
#endif
+29
View File
@@ -0,0 +1,29 @@
#include <numeric>
#include <iomanip>
#include <imgui/imgui.h>
#include "../Common.h"
#include "../GLM.h"
#include "../OpenGL.h"
class EditorStats
{
public:
EditorStats();
void Draw(double dt);
private:
// FPS graph
const unsigned int m_SampleSize = 100;
unsigned int m_FrameCount = 0;
std::vector<double> m_FrameTimes;
double m_TimeAccumulator = 0.0;
double m_AveragedSamplesPerSecond = 10.0;
const unsigned int m_AveragedSampleSize = 100;
unsigned int m_CurrentAveragedSampleIndex = 0;
std::vector<double> m_AveragedSamples;
void drawFPSGraph(double dt);
void drawRAMUsage(double dt);
void drawVRAMStats(double dt);
};
+39 -74
View File
@@ -1,94 +1,59 @@
#include <imgui/imgui.h>
#include <glm/gtx/common.hpp>
#include <boost/filesystem/path.hpp>
#include <nativefiledialog/nfd.h>
#include "../Core/System.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
#include "../Core/EMouseMove.h"
#include "../Core/ConfigFile.h"
#include "../Input/EInputCommand.h"
#include "../Rendering/IRenderer.h"
#include "../Core/Transform.h"
#include "../Core/EFileDropped.h"
#include "../Rendering/Camera.h"
#include "../Rendering/DebugCameraInputController.h"
#include "../Rendering/ESetCamera.h"
#include "../Core/World.h"
#include "../Core/SystemPipeline.h"
#include "../Core/ResourceManager.h"
#include "../Core/EntityFilePreprocessor.h"
#include "../Core/EntityFileParser.h"
#include "../Core/EntityFileWriter.h"
#include "../Core/EMousePress.h"
#include "EditorGUI.h"
#include "EditorStats.h"
class EditorSystem : public ImpureSystem
{
public:
EditorSystem(EventBroker* eventBroker, IRenderer* renderer);
EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
~EditorSystem();
virtual void Update(World* world, double dt) override;
void Update(double dt);
private:
IRenderer* m_Renderer;
World* m_World = nullptr;
Camera* m_Camera = nullptr;
RenderFrame* m_RenderFrame;
World* m_EditorWorld;
SystemPipeline* m_EditorWorldSystemPipeline;
Camera* m_EditorCamera;
EntityWrapper m_Camera = EntityWrapper::Invalid;
DebugCameraInputController<EditorSystem>* m_DebugCameraInputController;
EditorGUI* m_EditorGUI;
EditorStats* m_EditorStats;
bool m_Enabled;
bool m_Visible;
boost::filesystem::path m_DefaultEntityDir;
boost::filesystem::path m_CurrentFile;
std::vector<glm::vec2> m_PickingQueue;
// State
EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate;
EntityWrapper m_Widget = EntityWrapper::Invalid;
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
enum class WidgetMode
{
None,
Translate,
Rotate,
Scale
} m_WidgetMode = WidgetMode::None;
// Utility functions
EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath);
void setWidgetMode(EditorGUI::WidgetMode mode);
enum class WidgetSpace
{
Local,
Global
} m_WidgetSpace = WidgetSpace::Global;
// GUI callbacks
void OnEntitySelected(EntityWrapper entity);
void OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath);
EntityWrapper OnEntityCreate(EntityWrapper parent);
void OnEntityDelete(EntityWrapper entity);
void OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent);
void OnEntityChangeName(EntityWrapper entity, const std::string& name);
void OnComponentAttach(EntityWrapper entity, const std::string& componentType);
void OnComponentDelete(EntityWrapper entity, const std::string& componentType);
EntityID m_Widget = EntityID_Invalid;
EntityID m_WidgetX = EntityID_Invalid;
EntityID m_WidgetPlaneX = EntityID_Invalid;
EntityID m_WidgetY = EntityID_Invalid;
EntityID m_WidgetPlaneY = EntityID_Invalid;
EntityID m_WidgetZ = EntityID_Invalid;
EntityID m_WidgetPlaneZ = EntityID_Invalid;
EntityID m_WidgetOrigin = EntityID_Invalid;
glm::vec3 m_WidgetCurrentAxis;
float m_WidgetPickingDepth = 0.f;
glm::vec3 m_WidgetPickingPosition = glm::vec3(0);
EntityID m_Selection = EntityID_Invalid;
EntityID m_LastSelection = EntityID_Invalid;
EntityID m_UIDraggingEntity = EntityID_Invalid;
glm::vec3 m_Position;
std::string m_LastDroppedFile;
static boost::filesystem::path openDialog(boost::filesystem::path defaultPath);
static boost::filesystem::path saveDialog(boost::filesystem::path defaultPath);
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
EventRelay<EditorSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
// Events
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorSystem, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorSystem, Events::FileDropped> m_EFileDropped;
bool OnFileDropped(const Events::FileDropped& e);
void Picking();
void createWidget();
void updateWidget();
void setWidgetMode(WidgetMode newMode);
void setWidgetSpace(WidgetSpace space);
void drawUI(World* world, double dt);
bool createDeleteButton(std::string componentType);
bool createEntityNode(World* world, EntityID entity);
void changeParent(EntityID entity, EntityID newParent);
void fileImport(World* world);
void fileSave(World* world);
void fileSaveAs(World* world);
EventRelay<EditorSystem, Events::WidgetDelta> m_EWidgetDelta;
bool OnWidgetDelta(const Events::WidgetDelta& e);
};
@@ -0,0 +1,49 @@
#ifndef EditorWidgetSystem_h__
#define EditorWidgetSystem_h__
#include <imgui/imgui.h>
#include "../GLM.h"
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/Util/ScreenCoords.h"
#include "../Core/EMouseMove.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
namespace Events
{
struct WidgetDelta : Event
{
glm::vec3 Translation;
glm::vec3 Rotation;
glm::vec3 Scale;
};
}
class EditorWidgetSystem : public ImpureSystem, PureSystem
{
public:
EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override;
private:
IRenderer* m_Renderer;
// State
EntityWrapper m_PickEntity = EntityWrapper::Invalid;
PickData m_PickData;
glm::vec2 m_MouseDelta;
EventRelay<EditorWidgetSystem, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorWidgetSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorWidgetSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
};
#endif
+2 -1
View File
@@ -7,4 +7,5 @@
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/projection.hpp>
+3 -1
View File
@@ -2,6 +2,7 @@
#define Camera_h__
#include "../GLM.h"
#include "../Core/Util/Rectangle.h"
class Camera
{
@@ -32,7 +33,6 @@ public:
glm::mat4 ViewMatrix() const { return m_ViewMatrix; }
void SetViewMatrix(glm::mat4 val);
float AspectRatio() const { return m_AspectRatio; }
void SetAspectRatio(float val);
@@ -48,6 +48,8 @@ public:
void UpdateViewMatrix();
void UpdateProjectionMatrix();
glm::vec2 WorldToScreen(glm::vec3 worldCoord, Rectangle resolution);
private:
glm::vec3 m_Position;
@@ -1,5 +1,10 @@
#ifndef DebugCameraInputController_h__
#define DebugCameraInputController_h__
#include <imgui/imgui.h>
#include "../Input/FirstPersonInputController.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
template <typename EventContext>
class DebugCameraInputController : public FirstPersonInputController<EventContext>
@@ -7,7 +12,10 @@ class DebugCameraInputController : public FirstPersonInputController<EventContex
public:
DebugCameraInputController(EventBroker* eventBroker, unsigned int playerID)
: FirstPersonInputController(eventBroker, playerID)
{ }
{
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &DebugCameraInputController::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &DebugCameraInputController::OnMouseRelease);
}
void SetPosition(const glm::vec3 position) { m_Position = position; }
void SetOrientation(const glm::quat orientation) { m_Orientation = orientation; }
@@ -19,17 +27,6 @@ public:
{
ImGuiIO& io = ImGui::GetIO();
if (e.Command == "PrimaryFire") {
if (e.Value > 0) {
if (!io.WantCaptureMouse) {
LockMouse();
}
} else {
UnlockMouse();
}
return false;
}
if (!io.WantCaptureKeyboard) {
if (e.Command == "Right") {
float value = std::max(-1.f, std::min(e.Value, 1.f));
@@ -63,4 +60,25 @@ protected:
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
float m_BaseSpeed = 2.0f;
float m_Speed = m_BaseSpeed;
};
EventRelay<EventContext, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e)
{
if (e.Button == GLFW_MOUSE_BUTTON_2) {
ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureMouse) {
LockMouse();
}
}
return true;
}
EventRelay<EventContext, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e)
{
if (e.Button == GLFW_MOUSE_BUTTON_2) {
UnlockMouse();
}
return true;
}
};
#endif
-1
View File
@@ -32,7 +32,6 @@ private:
const LightCullingPass* m_LightCullingPass;
ShaderProgram* m_ForwardPlusProgram;
};
#endif
-42
View File
@@ -1,42 +0,0 @@
#ifndef DrawScenePass_h__
#define DrawScenePass_h__
#include "IRenderer.h"
#include "DrawScenePassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawScenePass
{
public:
DrawScenePass(IRenderer* renderer);
~DrawScenePass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderScene& scene);
//Getters
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j)
{
return (i->Depth < j->Depth);
};
Texture* m_WhiteTexture;
const IRenderer* m_Renderer;
ShaderProgram* m_BasicForwardProgram;
};
#endif
@@ -1,15 +0,0 @@
#ifndef DrawScenePassState_h__
#define DrawScenePassState_h__
#include "Rendering/RenderState.h"
class DrawScenePassState : public RenderState
{
public:
DrawScenePassState();
~DrawScenePassState();
private:
};
#endif
+2 -8
View File
@@ -2,20 +2,14 @@
#define Events_SetCamera_h__
#include "../Core/EventBroker.h"
#include "../Core/Entity.h"
#include <string.h>
#include "../Core/EntityWrapper.h"
namespace Events
{
struct SetCamera : Event
{
public:
SetCamera() { };
std::string Name;
private:
EntityWrapper CameraEntity;
};
}
-11
View File
@@ -31,15 +31,6 @@ public:
void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; }
bool VSYNC() const { return m_VSYNC; }
void SetVSYNC(bool vsync) { m_VSYNC = vsync; }
::Camera* Camera() const { return m_Camera; }
void SetCamera(::Camera* camera)
{
if (camera == nullptr) {
m_Camera = m_DefaultCamera;
} else {
m_Camera = camera;
}
}
virtual void Initialize() = 0;
virtual void Update(double dt) = 0;
virtual void Draw(RenderFrame& rq) = 0;
@@ -54,8 +45,6 @@ protected:
int m_GLVersion[2];
std::string m_GLVendor;
GLFWwindow* m_Window = nullptr;
::Camera* m_DefaultCamera;
::Camera* m_Camera = nullptr;
};
#endif // Renderer_h__
-1
View File
@@ -14,7 +14,6 @@ struct RenderJob
friend class RenderQueue;
public:
float Depth;
protected:
+2 -1
View File
@@ -51,11 +51,12 @@ struct PointLightJob : RenderJob
struct RenderScene
{
::Camera* Camera;
::Camera* Camera = nullptr;
std::list<std::shared_ptr<RenderJob>> ForwardJobs;
std::list<std::shared_ptr<RenderJob>> PointLightJobs;
std::list<std::shared_ptr<RenderJob>> DirectionalLightJobs;
Rectangle Viewport;
bool ClearDepth = false;
void Clear()
{
+1 -1
View File
@@ -16,10 +16,10 @@ public:
bool Disable(GLenum cap);
bool CullFace(GLenum mode);
bool ClearColor(glm::vec4 color);
bool Clear(GLbitfield mask);
bool BindFramebuffer(GLint framebuffer);
bool BlendEquation(GLenum mode);
bool BlendFunc(GLenum sfactor, GLenum dfactor);
bool DepthMask(GLboolean flag);
private:
std::vector<std::function<void(void)>> m_ResetFunctions;
+7 -18
View File
@@ -20,37 +20,26 @@
class RenderSystem : public ImpureSystem
{
public:
RenderSystem(EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame);
RenderSystem(World* world, EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame);
~RenderSystem();
virtual void Update(World* world, double dt) override;
virtual void Update(double dt) override;
private:
World* m_World = nullptr;
const IRenderer* m_Renderer;
RenderFrame* m_RenderFrame;
bool m_SwitchCamera = false;
Camera* m_Camera;
DebugCameraInputController<RenderSystem>* m_DebugCameraInputController;
std::list<ComponentWrapper> m_CameraComponents;
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(const Events::SetCamera &event);
EntityID m_CurrentCamera = EntityID_Invalid;
void switchCamera(EntityID entity);
void updateCamera(World* world, double dt);
void updateProjectionMatrix(ComponentWrapper& cameraComponent);
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
bool OnSetCamera(Events::SetCamera &event);
void fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
void fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs);
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs);
};
#endif
-2
View File
@@ -11,7 +11,6 @@
#include "FrameBuffer.h"
#include "../Core/World.h"
#include "PickingPass.h"
#include "DrawScenePass.h"
#include "LightCullingPass.h"
#include "DrawFinalPass.h"
#include "../Core/EventBroker.h"
@@ -43,7 +42,6 @@ private:
Model* m_UnitQuad;
Model* m_UnitSphere;
DrawScenePass* m_DrawScenePass;
PickingPass* m_PickingPass;
LightCullingPass* m_LightCullingPass;
ImGuiRenderPass* m_ImGuiRenderPass;
+2 -2
View File
@@ -17,10 +17,10 @@ class CapturePointSystem : public PureSystem
{
public:
//WARNING: on new map, destroy all info in the vectors, as well as reset all variables (just make new?)
CapturePointSystem(EventBroker* eventBroker);
CapturePointSystem(World* world, EventBroker* eventBroker);
//updatecomponent
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override;
private:
//methods which will take care of specific events
+2 -2
View File
@@ -16,10 +16,10 @@
class HealthSystem : public PureSystem
{
public:
HealthSystem(EventBroker* eventBroker);
HealthSystem(World* world, EventBroker* eventBroker);
//updatecomponent
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
//methods which will take care of specific events
+3 -3
View File
@@ -25,14 +25,14 @@ class InterpolationSystem : public PureSystem
double interpolationTime;
};
public:
InterpolationSystem(EventBroker* eventBroker)
: System(eventBroker)
InterpolationSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Transform")
{
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
}
~InterpolationSystem() { }
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
private:
std::unordered_map<EntityID, Transform> m_NextTransform;
std::unordered_map<EntityID, Transform> m_LastReceivedTransform;
+3 -3
View File
@@ -5,10 +5,10 @@
class PlayerMovementSystem : public PureSystem
{
public:
PlayerMovementSystem(EventBroker* eventBroker)
: System(eventBroker)
PlayerMovementSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Player")
{ }
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt);
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt);
};
+2 -2
View File
@@ -6,9 +6,9 @@
class PlayerSpawnSystem : public ImpureSystem
{
public:
PlayerSpawnSystem(EventBroker* eventBroker);
PlayerSpawnSystem(World* world, EventBroker* eventBroker);
virtual void Update(World* world, double dt) override;
virtual void Update(double dt) override;
private:
EventRelay<PlayerSpawnSystem, Events::InputCommand> m_OnInputCommand;
+4 -4
View File
@@ -4,14 +4,14 @@
class RaptorCopterSystem : public PureSystem
{
public:
RaptorCopterSystem(EventBroker* eventBroker)
: System(eventBroker)
RaptorCopterSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("RaptorCopter")
{ }
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override
{
ComponentWrapper& transform = world->GetComponent(component.EntityID, "Transform");
ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform");
(glm::vec3&)transform["Orientation"] += (float)(double)component["Speed"] * (float)dt * (glm::vec3)component["Axis"];
}
};
+1 -1
View File
@@ -13,7 +13,7 @@
class SpawnerSystem : public System
{
public:
SpawnerSystem(EventBroker* eventBroker);
SpawnerSystem(World* world, EventBroker* eventBroker);
static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid);
+38
View File
@@ -0,0 +1,38 @@
#ifndef WeaponSystem_h__
#define WeaponSystem_h__
//#include <GLFW/glfw3.h>
//#include <glm/common.hpp>
#include "Rendering/IRenderer.h"
#include "Common.h"
#include "Core/System.h"
#include "Core/EPlayerDamage.h"
#include "Core/EShoot.h"
#include "Input/EInputCommand.h"
#include <tuple>
#include <vector>
class WeaponSystem : public ImpureSystem
{
public:
WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
virtual void Update(double dt) override;
private:
//methods which will take care of specific events
EventRelay<WeaponSystem, Events::Shoot> m_EShoot;
bool WeaponSystem::OnShoot(const Events::Shoot& e);
EventRelay<WeaponSystem, Events::InputCommand> m_EInputCommand;
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e);
IRenderer* m_Renderer;
std::vector<std::tuple<EntityID, glm::vec2>> m_EShootVector;
};
#endif
+2
View File
@@ -20,4 +20,6 @@
<xs:include schemaLocation="Components/SpawnPoint.xsd"/>
<xs:include schemaLocation="Components/PlayerSpawn.xsd"/>
<xs:include schemaLocation="Components/Team.xsd"/>
<xs:include schemaLocation="Components/UniformScale.xsd"/>
<xs:include schemaLocation="Components/EditorWidget.xsd"/>
</xs:schema>
-1
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Camera xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Camera.xsd">
<Name>cam</Name>
<FOV>45</FOV>
<NearClip>0.01</NearClip>
<FarClip>5000</FarClip>
-1
View File
@@ -9,7 +9,6 @@
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Name" type="t:string" minOccurs="0"/>
<xs:element name="FOV" type="t:double" minOccurs="0">
<xs:annotation><xs:documentation>Vertical Field of View in degrees</xs:documentation></xs:annotation>
</xs:element>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<EditorWidget xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="EditorWidget.xsd">
<Type><Translate/></Type>
<Axis X="0" Y="0" Z="0"/>
</EditorWidget>
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:complexType name="WidgetEnum" mixed="true">
<xs:complexContent>
<xs:extension base="t:enum">
<xs:choice>
<xs:element name="Translate" type="xs:integer" fixed="0" minOccurs="0"/>
<xs:element name="Rotate" type="xs:integer" fixed="1" minOccurs="0"/>
<xs:element name="Scale" type="xs:integer" fixed="2" minOccurs="0"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="EditorWidget">
<xs:complexType>
<xs:all>
<xs:element name="Type" type="WidgetEnum" minOccurs="0"/>
<xs:element name="Axis" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+3 -1
View File
@@ -9,7 +9,9 @@
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
<xs:element name="Velocity" type="t:Vector" minOccurs="0">
<xs:annotation><xs:documentation>m/s^2</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Gravity" type="t:bool" minOccurs="0"/>
</xs:all>
</xs:complexType>
+1 -1
View File
@@ -12,7 +12,7 @@
<xs:element name="Color" type="t:Color" minOccurs="0"/>
<xs:element name="Radius" type="t:double" minOccurs="0"/>
<xs:element name="Intensity" type="t:double" minOccurs="0"/>
<xs:element name="Falloff">
<xs:element name="Falloff" minOccurs="0">
<xs:simpleType>
<xs:restriction base="t:double">
<xs:minInclusive value="0"/>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<UniformScale xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="UniformScale.xsd">
<Scale X="1" Y="1" Z="1"/>
</UniformScale>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="UniformScale">
<xs:annotation>
<xs:documentation>Keeps an entity at an uniform scale relative to the camera</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Scale" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity name="WidgetRotate" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
<c:UniformScale>
<Scale X="0.200000003" Y="0.200000003" Z="0.200000003"/>
</c:UniformScale>
</Components>
<Children>
<Entity name="X">
<Components>
<c:EditorWidget>
<Type>
<Rotate/>
</Type>
<Axis X="1" Y="0" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/RotationWidgetX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Y">
<Components>
<c:EditorWidget>
<Type>
<Rotate/>
</Type>
<Axis X="0" Y="1" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/RotationWidgetY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Z">
<Components>
<c:EditorWidget>
<Type>
<Rotate/>
</Type>
<Axis X="0" Y="0" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/RotationWidgetZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Light">
<Components>
<c:PointLight>
<Intensity>-1</Intensity>
<Falloff>0</Falloff>
</c:PointLight>
<c:Transform/>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity name="WidgetScale" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Model>
<Resource>Models/ScaleWidgetOrigin.obj</Resource>
</c:Model>
<c:Transform/>
<c:UniformScale>
<Scale X="0.200000003" Y="0.200000003" Z="0.200000003"/>
</c:UniformScale>
</Components>
<Children>
<Entity name="X">
<Components>
<c:EditorWidget>
<Type>
<Scale/>
</Type>
</c:EditorWidget>
<c:Model>
<Resource>Models/ScaleWidgetX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Y">
<Components>
<c:EditorWidget>
<Type>
<Scale/>
</Type>
</c:EditorWidget>
<c:Model>
<Resource>Models/ScaleWidgetY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Z">
<Components>
<c:EditorWidget>
<Type>
<Scale/>
</Type>
</c:EditorWidget>
<c:Model>
<Resource>Models/ScaleWidgetZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Light">
<Components>
<c:PointLight/>
<c:Transform>
<Position X="0.300000012" Y="0.300000012" Z="0.300000012"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity name="WidgetTranslate" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Model>
<Resource>Models/TranslationWidgetOrigin.obj</Resource>
</c:Model>
<c:Transform/>
<c:UniformScale>
<Scale X="0.200000003" Y="0.200000003" Z="0.200000003"/>
</c:UniformScale>
</Components>
<Children>
<Entity name="X">
<Components>
<c:EditorWidget>
<Axis X="1" Y="0" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/TranslationWidgetX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Y">
<Components>
<c:EditorWidget>
<Axis X="0" Y="1" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/TranslationWidgetY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Z">
<Components>
<c:EditorWidget>
<Axis X="0" Y="0" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/TranslationWidgetZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="XPlane">
<Components>
<c:EditorWidget>
<Axis X="0" Y="1" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/WidgetPlaneX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="YPlane">
<Components>
<c:EditorWidget>
<Axis X="1" Y="0" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/WidgetPlaneY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="ZPlane">
<Components>
<c:EditorWidget>
<Axis X="1" Y="1" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/WidgetPlaneZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Light">
<Components>
<c:PointLight/>
<c:Transform>
<Position X="0.400000006" Y="0.400000006" Z="0.400000006"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,209 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.7693491" Y="2.00600648" Z="2.02424884"/>
<Orientation X="0.157079354" Y="-0.872667432" Z="1.15912746e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.39647007" Y="2.36802292" Z="0.0546064377"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="3.68890452" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="1.98802853" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="0.196968079" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>4</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.82539892" Y="1.96172595" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-7.44269609" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-5.74354839" Y="2.23822045" Z="1.40012479"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>0</Health>
</c:Health>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0" G="0" R="2.25"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="1.9484092"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>0</Health>
</c:Health>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0" G="0" R="4.5"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="7.70311165" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
+3 -2
View File
@@ -9,12 +9,11 @@
<Resource>Models/DummyScene.obj</Resource>
</c:Model>
</Components>
</Entity>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="-0"/>
<Position X="0" Y="0" Z="-2"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<c:Camera>
@@ -24,4 +23,6 @@
</c:Model>
</Components>
</Entity>
<EntityRef file="Schema/Entities/EditorWidget.xml"/>
</Children>
</Entity>
+2 -2
View File
@@ -29,6 +29,8 @@
<xs:element ref="c:PlayerSpawn" minOccurs="0"/>
<xs:element ref="c:Team" minOccurs="0"/>
<xs:element ref="c:DirectionalLight" minOccurs="0"/>
<xs:element ref="c:UniformScale" minOccurs="0"/>
<xs:element ref="c:EditorWidget" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
@@ -39,9 +41,7 @@
<xs:element ref="Entity" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="EntityRef" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:attribute name="file" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
@@ -1,11 +1,11 @@
#include "Collision/CollidableOctreeSystem.h"
void CollidableOctreeSystem::Update(World* world, double dt)
void CollidableOctreeSystem::Update(double dt)
{
m_Octree->ClearDynamicObjects();
}
void CollidableOctreeSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
if (entity.HasComponent("AABB")) {
boost::optional<AABB> absoluteAABB = Collision::EntityAbsoluteAABB(entity);
+1 -1
View File
@@ -2,7 +2,7 @@
#include "Collision/CollisionSystem.h"
#include "Core/AABB.h"
void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
if (!entity.HasComponent("Physics")) {
return;
+3 -3
View File
@@ -3,10 +3,10 @@
#include "Core/AABB.h"
#include "Rendering/Model.h"
void TriggerSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void TriggerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
//Currently only players can trigger things.
auto players = world->GetComponents("Player");
auto players = m_World->GetComponents("Player");
if (players == nullptr) {
return;
}
@@ -18,7 +18,7 @@ void TriggerSystem::UpdateComponent(World* world, EntityWrapper& entity, Compone
}
for (auto& pc : *players) {
EntityID pId = pc.EntityID;
boost::optional<AABB> playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(world, pId));
boost::optional<AABB> playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(m_World, pId));
//The player can't trigger anything without an AABB.
if (!playerBox) {
continue;
-1
View File
@@ -50,7 +50,6 @@ ComponentWrapper ComponentPool::GetByEntity(EntityID ent)
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
}
bool ComponentPool::KnowsEntity(EntityID ent)
{
return m_EntityToComponent.find(ent) != m_EntityToComponent.end();
+25 -19
View File
@@ -47,7 +47,7 @@ std::size_t EntityFile::GetTypeStride(std::string typeName)
{ "float", sizeof(float) },
{ "double", sizeof(double) },
{ "string", sizeof(std::string) },
{ "enum", sizeof(int) },
{ "enum", sizeof(ComponentInfo::EnumType) },
{ "Vector", sizeof(glm::vec3) },
{ "Quaternion", sizeof(glm::quat) },
{ "Color", sizeof(glm::vec4) }
@@ -86,23 +86,29 @@ void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t&
void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData)
{
if (field.Type == "int" || field.Type == "enum") {
int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "float") {
float value = boost::lexical_cast<float>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "double") {
double value = boost::lexical_cast<double>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "bool") {
bool value = (valueData[0] == 't'); // Lazy bool evaluation
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "string") {
new (outData) std::string(valueData);
} else {
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
}
// Catch and ignore casting errors so whitespace around string enums won't mess anything up
try {
if (field.Type == "int") {
int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "enum") {
ComponentInfo::EnumType value = boost::lexical_cast<ComponentInfo::EnumType>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "float") {
float value = boost::lexical_cast<float>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "double") {
double value = boost::lexical_cast<double>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "bool") {
bool value = (valueData[0] == 't'); // Lazy bool evaluation
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "string") {
new (outData) std::string(valueData);
} else {
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
}
} catch (const boost::bad_lexical_cast&) { }
}
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) : m_Handler(handler)
@@ -165,7 +171,7 @@ void EntityFileSAXHandler::endElement(const XMLCh* const _uri, const XMLCh* cons
//}
}
if (m_StateStack.top() == State::ComponentField) {
if (m_StateStack.top() == State::ComponentField && name == m_CurrentField) {
m_StateStack.pop();
onEndComponentField(name);
return;
+7 -7
View File
@@ -28,14 +28,14 @@ void EntityFileParser::onStartEntity(EntityID entity, EntityID parent, const std
m_World->SetName(realEntity, name);
}
m_EntityIDMapper[entity] = realEntity;
LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent);
//LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent);
}
void EntityFileParser::onStartComponent(EntityID entity, const std::string& component)
{
EntityID realEntity = m_EntityIDMapper.at(entity);
m_World->AttachComponent(realEntity, component);
LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity);
//LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity);
}
void EntityFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map<std::string, std::string>& attributes)
@@ -49,11 +49,11 @@ void EntityFileParser::onStartComponentField(EntityID entity, const std::string&
}
auto& field = fieldIt->second;
LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str());
LOG_DEBUG("Attributes:");
for (auto& kv : attributes) {
LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str());
}
//LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str());
//LOG_DEBUG("Attributes:");
//for (auto& kv : attributes) {
// LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str());
//}
char* data = component.Data + field.Offset;
EntityFile::WriteAttributeData(data, field, attributes);
+21 -22
View File
@@ -7,23 +7,23 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
handler.SetStartComponentCallback(std::bind(&EntityFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
m_EntityFile->Parse(&handler);
LOG_DEBUG("___ COMPONENT DEFINITIONS ___");
for (auto& kv : m_ComponentCounts) {
LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second);
}
//LOG_DEBUG("___ COMPONENT DEFINITIONS ___");
//for (auto& kv : m_ComponentCounts) {
// LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second);
//}
parseComponentInfo();
for (auto& kv : m_ComponentInfo) {
auto& info = kv.second;
LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str());
LOG_DEBUG("Stride: %i", info.Stride);
LOG_DEBUG("Allocation: %i", info.Meta->Allocation);
for (auto& kv : info.Fields) {
auto& field = kv.second;
LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type.c_str(), kv.first.c_str());
}
}
//for (auto& kv : m_ComponentInfo) {
// auto& info = kv.second;
// LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str());
// LOG_DEBUG("Stride: %i", info.Stride);
// LOG_DEBUG("Allocation: %i", info.Meta->Allocation);
// for (auto& kv : info.Fields) {
// auto& field = kv.second;
// LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type.c_str(), kv.first.c_str());
// }
//}
parseDefaults();
}
@@ -50,7 +50,6 @@ void EntityFilePreprocessor::parseComponentInfo()
auto xsModel = grammarPool->getXSModel(whateverTheFuckThisIs);
// Find component xsd element declarations
std::cout << "Enumerating components..." << std::endl;
// <xs:element name="ComponentName">
auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION);
for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) {
@@ -73,7 +72,7 @@ void EntityFilePreprocessor::parseComponentInfo()
if (componentAnnotation != nullptr) {
compInfo.Meta->Annotation = parseAnnotationXML(componentAnnotation->getAnnotationString());
} else {
LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str());
//LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str());
}
// <xs:complexType>
@@ -91,7 +90,7 @@ void EntityFilePreprocessor::parseComponentInfo()
// <xs:all>
auto modelGroupParticle = complexTypeDefinition->getParticle();
if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
//LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
continue;
}
auto modelGroup = modelGroupParticle->getModelGroupTerm();
@@ -103,7 +102,7 @@ void EntityFilePreprocessor::parseComponentInfo()
for (unsigned int i = 0; i < particles->size(); ++i) {
auto particle = particles->elementAt(i);
if (particle->getTermType() != XSParticle::TERM_ELEMENT) {
LOG_ERROR("Failed to parse a field definition in component \"%s\": Particle wasn't TERM_ELEMENT! Skipping.", compInfo.Name.c_str());
//LOG_ERROR("Failed to parse a field definition in component \"%s\": Particle wasn't TERM_ELEMENT! Skipping.", compInfo.Name.c_str());
continue;
}
auto elementDeclaration = particle->getElementTerm();
@@ -129,7 +128,7 @@ void EntityFilePreprocessor::parseComponentInfo()
if (fieldAnnotation != nullptr) {
compInfo.Meta->FieldAnnotations[name] = parseAnnotationXML(fieldAnnotation->getAnnotationString());
} else {
LOG_WARNING("Component field \"%s.%s\" is missing an annotation!", compInfo.Name.c_str(), name.c_str());
//LOG_WARNING("Component field \"%s.%s\" is missing an annotation!", compInfo.Name.c_str(), name.c_str());
}
if (effectiveType == "enum") {
@@ -146,8 +145,8 @@ void EntityFilePreprocessor::parseComponentInfo()
auto enumElement = xsChoiceParticles->elementAt(i)->getElementTerm();
std::string enumName = XS::ToString(enumElement->getName());
std::string enumValue = XS::ToString(enumElement->getConstraintValue());
compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast<int>(enumValue);
LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str());
compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast<ComponentInfo::EnumType>(enumValue);
//LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str());
}
}
}
@@ -190,7 +189,7 @@ void EntityFilePreprocessor::parseDefaults()
//std::string namespaceSchema = schemaLocation.string();
//parser.setExternalNoNamespaceSchemaLocation("Teamasdasdasdasd.xsd");
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
//LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
parser.parse(defaultsFile.string().c_str());
+10 -1
View File
@@ -114,9 +114,18 @@ void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(q.y)));
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(q.z)));
fieldElement->setAttribute(X("W"), X(boost::lexical_cast<std::string>(q.w)));
} else if (field.Type == "int" || field.Type == "enum") {
} else if (field.Type == "int") {
const int& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
} else if (field.Type == "enum") {
const ComponentInfo::EnumType& value = c[fieldName];
auto& enumDef = c.Info.Meta->FieldEnumDefinitions.at(fieldName);
for (auto& kv : enumDef) {
if (kv.second == value) {
fieldElement->appendChild(doc->createElement(X(kv.first)));
break;
}
}
} else if (field.Type == "float") {
const float& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
+45 -8
View File
@@ -3,28 +3,65 @@
const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid);
bool EntityWrapper::operator==(const EntityWrapper& e)
{
return (this->World == e.World) && (this->ID == e.ID);
}
bool EntityWrapper::HasComponent(const std::string& componentName)
{
return World->HasComponent(ID, componentName);
}
ComponentWrapper EntityWrapper::operator[](const std::string& componentName)
EntityWrapper EntityWrapper::Parent()
{
if (this->World == nullptr || this->ID == EntityID_Invalid) {
return EntityWrapper::Invalid;
} else {
return EntityWrapper(this->World, this->World->GetParent(this->ID));
}
}
bool EntityWrapper::Valid()
{
if (this->World == nullptr) {
return false;
}
if (this->ID == EntityID_Invalid) {
return false;
}
if (!this->World->ValidEntity(this->ID)) {
this->ID = EntityID_Invalid;
return false;
}
return true;
}
ComponentWrapper EntityWrapper::operator[](const char* componentName)
{
if (World->HasComponent(ID, componentName)) {
return World->GetComponent(ID, componentName);
} else {
LOG_WARNING("EntityWrapper implicitly attached \"%s\" component to #%i as a result of a fetch request!", componentName.c_str(), ID);
LOG_WARNING("EntityWrapper implicitly attached \"%s\" component to #%i as a result of a fetch request!", componentName, ID);
return World->AttachComponent(ID, componentName);
}
}
EntityWrapper::operator EntityID()
bool EntityWrapper::operator==(const EntityWrapper& e) const
{
return (this->ID == e.ID) && (this->World == e.World);
}
bool EntityWrapper::operator!=(const EntityWrapper& e) const
{
return !this->operator==(e);
}
EntityWrapper::operator EntityID() const
{
return this->ID;
}
EntityWrapper::operator bool()
{
return this->Valid();
}
+6
View File
@@ -34,10 +34,16 @@ void InputManager::Update(double dt)
if (m_CurrentKeyState[i]) {
Events::KeyDown e;
e.KeyCode = i;
e.ModCtrl = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_CONTROL);
e.ModAlt = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_ALT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_ALT);
e.ModShift = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_SHIFT);
m_EventBroker->Publish(e);
} else {
Events::KeyUp e;
e.KeyCode = i;
e.ModCtrl = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_CONTROL);
e.ModAlt = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_ALT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_ALT);
e.ModShift = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_SHIFT);
m_EventBroker->Publish(e);
}
}
+24
View File
@@ -0,0 +1,24 @@
#include "Core/UniformScaleSystem.h"
UniformScaleSystem::UniformScaleSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("UniformScale")
{
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &UniformScaleSystem::OnSetCamera);
}
void UniformScaleSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt)
{
if (!m_Camera.Valid()) {
return;
}
float distance = glm::length((glm::vec3)entity["Transform"]["Position"] - (glm::vec3&)m_Camera["Transform"]["Position"]);
entity["Transform"]["Scale"] = (glm::vec3&)cUniformScale["Scale"] * distance;
}
bool UniformScaleSystem::OnSetCamera(const Events::SetCamera& e)
{
m_Camera = e.CameraEntity;
return false;
}
+734
View File
@@ -0,0 +1,734 @@
#include "Editor/EditorGUI.h"
EditorGUI::EditorGUI(World* world, EventBroker* eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &EditorGUI::OnKeyDown);
}
void EditorGUI::Draw()
{
ImGui::ShowTestWindow();
drawMenu();
drawTools();
drawEntities(m_World);
drawComponents(m_CurrentSelection);
drawModals();
}
void EditorGUI::SelectEntity(EntityWrapper entity)
{
m_CurrentSelection = entity;
if (m_OnEntitySelected != nullptr) {
m_OnEntitySelected(entity);
}
}
void EditorGUI::drawMenu()
{
}
void EditorGUI::drawTools()
{
if (!ImGui::Begin("Tools", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize)) {
return;
}
createWidgetToolButton(WidgetMode::Translate);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Translate");
}
ImGui::SameLine();
createWidgetToolButton(WidgetMode::Rotate);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Rotate");
}
ImGui::SameLine();
createWidgetToolButton(WidgetMode::Scale);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Scale");
}
ImGui::SameLine();
ImGui::ItemSize(ImVec2(5, 0));
// Play button
ImGui::SameLine();
static bool paused = false;
if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Play.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
Events::Resume e;
e.World = m_World;
m_EventBroker->Publish(e);
paused = false;
}
// Pause button
ImGui::SameLine();
if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Pause.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
Events::Pause e;
e.World = m_World;
m_EventBroker->Publish(e);
paused = true;
}
ImGui::End();
}
void EditorGUI::drawEntities(World* world)
{
if (!ImGui::Begin("Entities")) {
ImGui::End();
return;
}
float buttonWidth = (ImGui::GetContentRegionAvailWidth() - 10.f) / 3.f ;
if (ImGui::Button("Create", ImVec2(buttonWidth, 0))) {
entityCreate(world, m_CurrentSelection);
}
ImGui::SameLine(0.f, 5.f);
if (ImGui::Button("Import", ImVec2(buttonWidth, 0))) {
entityImport(world);
}
ImGui::SameLine(0.f, 5.f);
ImGui::ButtonEx("Reference", ImVec2(buttonWidth, 0), ImGuiButtonFlags_Disabled);
// Naming
char buffer[256];
buffer[0] = '\0';
buffer[255] = '\0';
std::size_t nameLength = 0;
ImGuiInputTextFlags flags = ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll;
if (m_CurrentSelection.Valid()) {
std::string name = world->GetName(m_CurrentSelection.ID);
nameLength = name.length();
if (!name.empty()) {
memcpy(buffer, name.c_str(), std::min(sizeof(buffer) - 1, name.length() + 1));
}
} else {
flags |= ImGuiInputTextFlags_ReadOnly;
}
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 7.f);
if (ImGui::InputText("", &buffer[0], sizeof(buffer), flags)) {
if (m_CurrentSelection.Valid()) {
if (m_OnEntityChangeName != nullptr) {
m_OnEntityChangeName(m_CurrentSelection, std::string(buffer));
SetDirty(m_CurrentSelection);
}
}
}
ImGui::PopItemWidth();
ImGui::ItemSize(ImVec2(0, 3));
drawEntitiesRecursive(world, EntityID_Invalid);
ImGui::End();
}
void EditorGUI::drawEntitiesRecursive(World* world, EntityID parent)
{
auto entityChildren = world->GetEntityChildren();
auto range = entityChildren.equal_range(parent);
for (auto it = range.first; it != range.second; it++) {
if (EditorGUI::drawEntityNode(EntityWrapper(world, it->second))) {
drawEntitiesRecursive(world, it->second);
ImGui::TreePop();
}
}
}
bool EditorGUI::drawEntityNode(EntityWrapper entity)
{
// Custom button hitbox to select entities on top of tree node
ImVec2 pos = ImGui::GetCursorScreenPos();
float width = ImGui::GetContentRegionAvailWidth();
ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 14));
auto window = ImGui::GetCurrentWindow();
if (m_CurrentSelection == entity) {
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
window->DrawList->AddRectFilled(bb.Min, bb.Max, col);
}
ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(entity.ID)).c_str());
bool hovered = false;
bool held = false;
if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) {
SelectEntity(entity);
}
// Handle entity dragging
if (held) {
ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0);
if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) {
if (m_CurrentlyDragging == EntityWrapper::Invalid) {
m_CurrentlyDragging = entity;
LOG_DEBUG("Started dragging %i", entity.ID);
}
ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0));
ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings);
ImGui::Text(formatEntityName(entity).c_str());
ImGui::End();
}
}/* else if (m_CurrentlyDragging == entity) {
LOG_DEBUG("Stopped dragging %i", entity.ID);
m_CurrentlyDragging = EntityWrapper::Invalid;
}*/
// Entity context menu
std::string contextMenuUniqueID = std::string("EntityContextMenu") + std::to_string(entity.ID);
if (hovered && ImGui::IsMouseClicked(1)) {
ImGui::OpenPopup(contextMenuUniqueID.c_str());
}
if (ImGui::BeginPopup(contextMenuUniqueID.c_str())) {
ImGui::TextDisabled(formatEntityName(entity).c_str());
if (ImGui::MenuItem("Save", "Ctrl+S")) {
entitySave(entity);
} else
if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) {
entitySave(entity, true);
} else
if (ImGui::MenuItem("Delete", "Del")) {
entityDelete(entity);
} else
if (ImGui::MenuItem("Move to root")) {
entityChangeParent(entity, EntityWrapper::Invalid);
}
ImGui::EndPopup();
}
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
if (ImGui::TreeNode(formatEntityName(entity).c_str())) {
// Handle drop events for reparenting
if (m_CurrentlyDragging != EntityWrapper::Invalid && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) {
entityChangeParent(m_CurrentlyDragging, entity);
m_CurrentlyDragging = EntityWrapper::Invalid;
}
return true;
} else {
return false;
}
}
void EditorGUI::drawComponents(EntityWrapper entity)
{
std::stringstream title;
title << "Components";
if (entity.Valid()) {
title << " " << formatEntityName(entity);
}
title << "###Components";
if (!ImGui::Begin(title.str().c_str())) {
ImGui::End();
return;
}
if (!entity.Valid()) {
ImGui::End();
return;
}
auto& pools = entity.World->GetComponentPools();
// Create list of component types available to be added
std::vector<const char*> componentTypes;
for (auto& pair : pools) {
// Don't list components the entity already has attached
if (!entity.HasComponent(pair.first)) {
componentTypes.push_back(pair.first.c_str());
}
}
// Draw combo box
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 10.f);
int selectedItem = -1;
if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size())) {
if (selectedItem != -1) {
if (m_OnComponentAttach != nullptr) {
std::string chosenComponentType(componentTypes.at(selectedItem));
m_OnComponentAttach(entity, chosenComponentType);
SetDirty(entity);
}
}
}
ImGui::PopItemWidth();
for (auto& pair : pools) {
const std::string& componentType = pair.first;
auto pool = pair.second;
// Don't show components the entity doesn't have attached
if (!entity.HasComponent(componentType)) {
continue;
}
// Handle deletion with early out
if (createDeleteButton(componentType)) {
if (m_OnComponentDelete != nullptr) {
m_OnComponentDelete(entity, componentType);
continue;
}
}
// Draw the actual component node
drawComponentNode(entity, pool->ComponentInfo());
}
ImGui::End();
}
bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci)
{
if (!ImGui::CollapsingHeader(ci.Name.c_str(), nullptr, true, true)) {
return false;
}
// Show component annotation
const std::string annotation = ci.Meta->Annotation;
if (!annotation.empty()) {
ImGui::TextWrapped(annotation.c_str());
}
// Draw component fields
ComponentWrapper& component = entity.World->GetComponent(entity.ID, ci.Name);
for (auto& kv : ci.Fields) {
const std::string& fieldName = kv.first;
const ComponentInfo::Field_t& field = kv.second;
// Draw the field widget based on its type
bool dirty = drawComponentField(component, field);
if (dirty) {
SetDirty(entity);
}
ImGui::SameLine();
// Draw field name
ImGui::Text(fieldName.c_str());
// Draw potential field annotation
auto fieldAnnotationIt = ci.Meta->FieldAnnotations.find(fieldName);
if (fieldAnnotationIt != ci.Meta->FieldAnnotations.end()) {
ImGui::SameLine();
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(fieldAnnotationIt->second.c_str());
}
}
}
return true;
}
bool EditorGUI::drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field)
{
// Push an unique widget id so different components with fields with equal names are still counted as different
ImGui::PushID((c.Info.Name + field.Name).c_str());
bool dirty = false;
if (field.Type == "Vector") {
dirty = drawComponentField_Vector(c, field);
} else if (field.Type == "Color") {
dirty = drawComponentField_Color(c, field);
//} else if (field.Type == "Quaternion") {
} else if (field.Type == "int") {
dirty = drawComponentField_int(c, field);
} else if (field.Type == "enum") {
dirty = drawComponentField_enum(c, field);
} else if (field.Type == "float") {
dirty = drawComponentField_float(c, field);
} else if (field.Type == "double") {
dirty = drawComponentField_double(c, field);
} else if (field.Type == "bool") {
dirty = drawComponentField_bool(c, field);
} else if (field.Type == "string") {
dirty = drawComponentField_string(c, field);
} else {
ImGui::TextDisabled(field.Type.c_str());
}
ImGui::PopID();
return dirty;
}
bool EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<glm::vec3>(field.Name);
if (field.Name == "Scale") {
// Limit scale values to a minimum of 0
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
} else if (field.Name == "Orientation") {
// Make orentations have a period of 2*Pi
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
val = tempVal;
return true;
} else {
return false;
}
} else {
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
}
}
bool EditorGUI::drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<glm::vec4>(field.Name);
return ImGui::ColorEdit4("", glm::value_ptr(val), true);
}
bool EditorGUI::drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<int>(field.Name);
return ImGui::InputInt("", &val);
}
bool EditorGUI::drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto fieldEnumDefIt = c.Info.Meta->FieldEnumDefinitions.find(field.Name);
if (fieldEnumDefIt == c.Info.Meta->FieldEnumDefinitions.end()) {
return drawComponentField_int(c, field);
}
auto& val = c.Field<int>(field.Name);
int selectedItem = -1;
std::stringstream enumKeys;
std::vector<int> enumValues;
int i = 0;
for (auto& kv : fieldEnumDefIt->second) {
enumKeys << kv.first << " (" << kv.second << ")" << '\0';
enumValues.push_back(kv.second);
if (val == kv.second) {
selectedItem = i;
}
i++;
}
if (ImGui::Combo("", &selectedItem, enumKeys.str().c_str())) {
val = enumValues.at(selectedItem);
return true;
} else {
return false;
}
}
bool EditorGUI::drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<float>(field.Name);
return ImGui::InputFloat("", &val, 0.01f, 1.f);
}
bool EditorGUI::drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
float tempVal = static_cast<float>(c.Field<double>(field.Name));
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
c.SetField(field.Name, static_cast<double>(tempVal));
return true;
} else {
return false;
}
}
bool EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<bool>(field.Name);
return ImGui::Checkbox("", &val);
}
bool EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<std::string>(field.Name);
char tempString[1024]; // Let's just hope this is an sufficiently large buffer for strings :)
tempString[1023] = '\0'; // Null terminator just in case the string is larger than the buffer
// Copy the string into the buffer, taking the null terminator into account
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString) - 1));
if (ImGui::InputText("", tempString, sizeof(tempString))) {
val = std::string(tempString);
return true;
} else {
return false;
}
// TODO: Handle drag and drop of files
}
void EditorGUI::drawModals()
{
for (auto& modal : m_ModalsToOpen) {
ImGui::OpenPopup(modal.c_str());
}
m_ModalsToOpen.clear();
if (ImGui::BeginPopupModal("Import failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Entity import failed. Check console for more information.\n\n");
ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120);
if (ImGui::Button("OK", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal("Save failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Entity save failed on an exception.\nMessage: %s\n\n", m_LastErrorMessage.c_str());
ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120);
if (ImGui::Button("OK", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal("Confirm deletion", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
if (m_ModalData.count("Confirm deletion") == 0) {
ImGui::CloseCurrentPopup();
}
ImGui::Text("Are you sure you want to delete entity \"%s\"?", formatEntityName(m_CurrentSelection).c_str());
ImGui::ItemSize(ImVec2(5.f, 0.f));
ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 2*60);
if (ImGui::Button("Delete (Del)", ImVec2(60, 0))) {
entityDelete(boost::any_cast<EntityWrapper>(m_ModalData.at("Confirm deletion")));
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(60, 0))) {
m_ModalData.erase("Confirm deletion");
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
bool EditorGUI::createDeleteButton(const std::string& componentType)
{
float width = ImGui::GetContentRegionAvailWidth();
ImGuiWindow* window = ImGui::GetCurrentWindow();
auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1);
ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f));
std::string idString = "#DELETE";
idString += componentType;
ImGuiID id = window->GetID(idString.c_str());
bool hovered;
bool held;
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
//ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
return pressed;
}
void EditorGUI::createWidgetToolButton(WidgetMode mode)
{
GLuint texture = 0;
switch (mode) {
case WidgetMode::Translate:
texture = tryLoadTexture("Textures/Icons/Translate.png");
break;
case WidgetMode::Rotate:
texture = tryLoadTexture("Textures/Icons/Rotate.png");
break;
case WidgetMode::Scale:
texture = tryLoadTexture("Textures/Icons/Scale.png");
break;
}
if (ImGui::ImageButton(
(void*)texture,
ImVec2(24, 24),
ImVec2(0, 1),
ImVec2(1, 0),
-1,
ImVec4(0, 0, 0, 0),
(m_CurrentWidgetMode == mode) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1)
)
) {
if (m_OnWidgetMode != nullptr) {
m_OnWidgetMode(mode);
}
m_CurrentWidgetMode = mode;
}
}
bool EditorGUI::OnKeyDown(const Events::KeyDown& e)
{
if (e.ModCtrl && e.KeyCode == GLFW_KEY_S) {
if (m_CurrentSelection.Valid()) {
EntityWrapper baseParent = m_CurrentSelection;
while (baseParent.Parent().Valid()) {
baseParent = baseParent.Parent();
}
entitySave(baseParent);
}
}
if (e.ModCtrl && e.KeyCode == GLFW_KEY_N) {
entityCreate(m_World, m_CurrentSelection);
}
if (e.ModCtrl && e.KeyCode == GLFW_KEY_O) {
entityImport(m_World);
}
if (e.KeyCode == GLFW_KEY_DELETE) {
if (m_CurrentSelection.Valid()) {
entityDelete(m_CurrentSelection);
}
}
return true;
}
boost::filesystem::path EditorGUI::fileOpenDialog()
{
namespace bfs = boost::filesystem;
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_OpenDialog("xml", bfs::absolute(m_DefaultEntityPath).string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
} else if (result == NFD_CANCEL) {
return bfs::path();
} else {
return bfs::absolute(outPath);
}
}
boost::filesystem::path EditorGUI::fileSaveDialog()
{
namespace bfs = boost::filesystem;
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_SaveDialog("xml", bfs::absolute(m_DefaultEntityPath).string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
} else if (result == NFD_CANCEL) {
return bfs::path();
} else {
return bfs::absolute(outPath);
}
}
const std::string EditorGUI::formatEntityName(EntityWrapper entity)
{
if (!entity.Valid()) {
return "EntityID_Invalid";
}
std::stringstream name;
std::string entityName = entity.World->GetName(entity.ID);
if (!entityName.empty()) {
name << entityName;
} else {
name << "#" << entity.ID;
}
if (m_EntityFiles.count(entity) == 1) {
name << " (" << m_EntityFiles.at(entity).Path.filename().string() << ")";
if (m_EntityFiles.at(entity).Dirty) {
name << "*";
}
}
return name.str();
}
GLuint EditorGUI::tryLoadTexture(std::string filePath)
{
GLuint texture = 0;
try {
texture = ResourceManager::Load<Texture>(filePath)->m_Texture;
} catch (const std::exception&) { }
return texture;
}
void EditorGUI::openModal(const std::string& modal)
{
m_ModalsToOpen.insert(modal);
}
void EditorGUI::SetDirty(EntityWrapper entity)
{
EntityWrapper baseParent = entity;
while (baseParent.Parent().Valid()) {
baseParent = baseParent.Parent();
}
if (m_EntityFiles.find(baseParent) != m_EntityFiles.end()) {
m_EntityFiles.at(baseParent).Dirty = true;
}
}
void EditorGUI::entityImport(World* world)
{
boost::filesystem::path filePath = fileOpenDialog();
if (filePath.empty()) {
return;
}
EntityWrapper entity = m_OnEntityImport(EntityWrapper(world, EntityID_Invalid), filePath);
if (entity.Valid()) {
m_EntityFiles[entity].Path = filePath;
SelectEntity(entity);
} else {
openModal("Import failed");
}
}
void EditorGUI::entitySave(EntityWrapper entity, bool saveAs /* = false */)
{
boost::filesystem::path filePath;
if (!saveAs && m_EntityFiles.count(entity) == 1) {
filePath = m_EntityFiles.at(entity).Path;
} else {
filePath = fileSaveDialog();
}
if (filePath.empty()) {
return;
}
try {
m_OnEntitySave(entity, filePath);
m_EntityFiles[entity].Path = filePath;
m_EntityFiles[entity].Dirty = false;
} catch (const std::exception& e) {
m_LastErrorMessage = e.what();
openModal("Save failed");
}
}
void EditorGUI::entityCreate(World* world, EntityWrapper parent)
{
if (m_OnEntityCreate != nullptr) {
// Create the new entity in the world we're drawing for
if (parent.World == nullptr) {
parent.World = world;
}
EntityWrapper newEntity = m_OnEntityCreate(parent);
SelectEntity(newEntity);
}
}
void EditorGUI::entityDelete(EntityWrapper entity)
{
std::string modalName = "Confirm deletion";
if (m_ModalData.count(modalName) == 0) {
m_ModalData[modalName] = entity;
openModal(modalName);
} else {
if (boost::any_cast<EntityWrapper>(m_ModalData[modalName]) == entity) {
EntityWrapper parent = entity.Parent();
if (m_OnEntityDelete != nullptr) {
SetDirty(entity);
m_OnEntityDelete(entity);
m_EntityFiles.erase(entity);
}
if (!m_CurrentSelection.Valid()) {
SelectEntity(parent);
}
}
m_ModalData.erase(modalName);
}
}
void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent)
{
if (entity == parent) {
return;
}
if (m_OnEntityChangeParent != nullptr) {
SetDirty(entity);
m_OnEntityChangeParent(entity, parent);
LOG_DEBUG("Changed parent of %i to %i", entity.ID, parent.ID);
}
}
+87
View File
@@ -0,0 +1,87 @@
#include "Editor/EditorRenderSystem.h"
EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
: System(m_World, eventBroker)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
{
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &EditorRenderSystem::OnSetCamera);
auto resolution = Rectangle::Rectangle(1280, 720);
m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.01f, 5000.f);
}
void EditorRenderSystem::Update(double dt)
{
if (m_CurrentCamera) {
ComponentWrapper cameraTransform = m_CurrentCamera["Transform"];
m_EditorCamera->SetPosition(cameraTransform["Position"]);
m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"]));
}
RenderScene scene;
scene.ClearDepth = true;
scene.Camera = m_EditorCamera;
scene.Viewport = Rectangle(1920, 1080);
auto models = m_World->GetComponents("Model");
if (models != nullptr) {
for (auto& cModel : *models) {
if (!(bool)cModel["Visible"]) {
continue;
}
const std::string& resource = cModel["Resource"];
Model* model;
try {
model = ResourceManager::Load<::Model, true>(resource);
} catch (const Resource::StillLoadingException&) {
continue;
} catch (const std::exception&) {
try {
model = ResourceManager::Load<::Model>("Models/Core/Error.obj");
} catch (const std::exception&) {
continue;
}
}
EntityWrapper entity(m_World, cModel.EntityID);
glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World);
for (auto matGroup : model->MaterialGroups()) {
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World);
scene.ForwardJobs.push_back(modelJob);
}
}
}
auto pointLights = m_World->GetComponents("PointLight");
if (pointLights != nullptr) {
for (auto& cPointLight : *pointLights) {
bool visible = cPointLight["Visible"];
if (!visible) {
continue;
}
EntityWrapper entity(m_World, cPointLight.EntityID);
ComponentWrapper& cTransform = entity["Transform"];
std::shared_ptr<PointLightJob> pointLightJob = std::make_shared<PointLightJob>(cTransform, cPointLight, entity.World);
scene.PointLightJobs.push_back(pointLightJob);
}
}
m_RenderFrame->Add(scene);
}
bool EditorRenderSystem::OnSetCamera(Events::SetCamera& e)
{
ComponentWrapper cTransform = e.CameraEntity["Transform"];
ComponentWrapper cCamera = e.CameraEntity["Camera"];
m_EditorCamera->SetFOV((double)cCamera["FOV"]);
m_EditorCamera->SetNearClip((double)cCamera["NearClip"]);
m_EditorCamera->SetFarClip((double)cCamera["FarClip"]);
m_EditorCamera->SetPosition(cTransform["Position"]);
m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"]));
m_CurrentCamera = e.CameraEntity;
return true;
}
+115
View File
@@ -0,0 +1,115 @@
#include "Editor/EditorStats.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <psapi.h>
#endif
#include <GL/wglew.h>
EditorStats::EditorStats()
{
m_AveragedSamples.push_back(0.0);
m_CurrentAveragedSampleIndex = 1;
}
void EditorStats::Draw(double dt)
{
if (ImGui::Begin("Stats")) {
drawFPSGraph(dt);
drawRAMUsage(dt);
drawVRAMStats(dt);
}
ImGui::End();
}
void EditorStats::drawFPSGraph(double dt)
{
if (m_FrameCount < m_SampleSize) {
m_FrameTimes.push_back(dt);
} else {
m_FrameTimes[m_FrameCount % m_SampleSize] = dt;
}
m_FrameCount++;
double average = 0.0;
double max = 0.0;
for (double t : m_FrameTimes) {
average += t;
max = std::max(max, t);
}
average /= m_FrameTimes.size();
m_TimeAccumulator += dt;
if (m_TimeAccumulator >= 1.0/m_AveragedSamplesPerSecond) {
if (m_CurrentAveragedSampleIndex < m_AveragedSampleSize) {
m_AveragedSamples.push_back(1.0/average);
} else {
m_AveragedSamples[m_CurrentAveragedSampleIndex % m_AveragedSampleSize] = 1.0/average;
}
m_CurrentAveragedSampleIndex++;
m_TimeAccumulator = 0.0;
}
float maxFPS = 0.f;
ImVector<float> values;
int values_offset = m_CurrentAveragedSampleIndex % m_AveragedSampleSize;
for (double d : m_AveragedSamples) {
values.push_back(static_cast<float>(d));
maxFPS = std::max(maxFPS, static_cast<float>(d));
}
std::stringstream header;
header << std::round(1.0/average) << " FPS (" << std::setprecision(5) << average << " ms)";
ImGui::PlotLines("##FPSGraph", values.Data, values.Size, values_offset, header.str().c_str(), 0.f, maxFPS + maxFPS/5.f, ImVec2(0, 100));
}
void EditorStats::drawRAMUsage(double dt)
{
#ifdef WIN32
PROCESS_MEMORY_COUNTERS_EX ppm;
GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&ppm, sizeof(ppm));
float megabytes = ppm.WorkingSetSize / (float)std::pow(1024, 2);
ImGui::Text("Memory: ~%f MiB", megabytes);
#endif
}
void EditorStats::drawVRAMStats(double dt)
{
//const unsigned int GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049;
//const unsigned int GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048;
//glm::ivec4 total;
//glGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, glm::value_ptr(total));
//if (glGetError() == GL_NO_ERROR) {
// glm::ivec4 available;
// glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, glm::value_ptr(available));
// float megabytes = (total.x - available.x) / 1024.f; // NVidia returns in KiB
// ImGui::Text("VRAM: %f", megabytes);
//}
//GLuint uNoOfGPUs = wglGetGPUIDsAMD(0, 0);
//if (!GLERROR("")) {
// GLuint* uGPUIDs = new GLuint[uNoOfGPUs];
// wglGetGPUIDsAMD(uNoOfGPUs, uGPUIDs);
// GLuint uTotalMemoryInMB = 0;
// wglGetGPUInfoAMD(uGPUIDs[0],
// WGL_GPU_RAM_AMD,
// GL_UNSIGNED_INT,
// sizeof(GLuint),
// &uTotalMemoryInMB);
// GLint nCurAvailMemoryInKB[4];
// glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,
// &nCurAvailMemoryInKB[0]);
// float usedTexture = (nCurAvailMemoryInKB[0] / 1024.f);
// glGetIntegerv(GL_VBO_FREE_MEMORY_ATI,
// &nCurAvailMemoryInKB[0]);
// float usedVBO = (nCurAvailMemoryInKB[0] / 1024.f);
// glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI,
// &nCurAvailMemoryInKB[0]);
// float usedFB = (nCurAvailMemoryInKB[0] / 1024.f);
// ImGui::Text("VRAM: %f MiB ", (float)uTotalMemoryInMB - usedTexture - usedVBO - usedFB);
// ImGui::Text(" Texture: %f MiB", usedTexture);
// ImGui::Text(" VBO: %f MiB", usedVBO);
// ImGui::Text(" Framebuffer: %f MiB", usedFB);
// delete[] uGPUIDs;
//}
}
+140 -678
View File
@@ -1,738 +1,200 @@
#include "Editor/EditorSystem.h"
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui/imgui_internal.h>
#include "Core/UniformScaleSystem.h"
#include "Editor/EditorRenderSystem.h"
#include "Editor/EditorWidgetSystem.h"
EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer)
: System(eventBroker)
, ImpureSystem()
EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
: System(world, eventBroker)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
{
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
m_Enabled = config->Get<bool>("Debug.EditorEnabled", false);
m_Visible = m_Enabled;
m_DefaultEntityDir = boost::filesystem::path("Schema") / boost::filesystem::path("Entities");
m_EditorWorld = new World();
m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, eventBroker);
m_EditorWorldSystemPipeline->AddSystem<UniformScaleSystem>(0);
m_EditorWorldSystemPipeline->AddSystem<EditorWidgetSystem>(0, m_Renderer);
m_EditorWorldSystemPipeline->AddSystem<EditorRenderSystem>(1, m_Renderer, m_RenderFrame);
m_Camera = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/Empty.xml");
m_EditorWorld->AttachComponent(m_Camera.ID, "Transform");
m_EditorWorld->AttachComponent(m_Camera.ID, "Camera");
m_DebugCameraInputController = new DebugCameraInputController<EditorSystem>(m_EventBroker, -1);
if (!m_Enabled) {
return;
}
m_EditorGUI = new EditorGUI(m_World, m_EventBroker);
m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1));
m_EditorGUI->SetEntityImportCallback(std::bind(&EditorSystem::importEntity, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetEntitySaveCallback(std::bind(&EditorSystem::OnEntitySave, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetEntityCreateCallback(std::bind(&EditorSystem::OnEntityCreate, this, std::placeholders::_1));
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->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));
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease);
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove);
EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystem::OnFileDropped);
EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta);
m_EditorStats = new EditorStats();
Events::SetCamera e;
e.CameraEntity = m_Camera;
m_EventBroker->Publish(e);
}
void EditorSystem::Update(World* world, double dt)
EditorSystem::~EditorSystem()
{
m_World = world;
delete m_EditorStats;
delete m_EditorGUI;
delete m_DebugCameraInputController;
delete m_EditorWorldSystemPipeline;
delete m_EditorWorld;
}
if (!m_Enabled) {
return;
void EditorSystem::Update(double dt)
{
m_EventBroker->Process<EditorGUI>();
m_EditorGUI->Draw();
m_EditorStats->Draw(dt);
if (m_CurrentSelection.Valid() && m_Widget.Valid()) {
(glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID);
}
if (!m_Visible) {
return;
}
Picking();
updateWidget();
m_EditorWorldSystemPipeline->Update(dt);
drawUI(world, dt);
m_DebugCameraInputController->Update(dt);
m_Camera["Transform"]["Position"] = m_DebugCameraInputController->Position();
m_Camera["Transform"]["Orientation"] = glm::eulerAngles(m_DebugCameraInputController->Orientation());
}
// Clear drop queue if it wasn't handled by any UI element
if (!m_LastDroppedFile.empty()) {
m_LastDroppedFile = "";
void EditorSystem::OnEntitySelected(EntityWrapper entity)
{
m_CurrentSelection = entity;
setWidgetMode(m_WidgetMode);
}
void EditorSystem::OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath)
{
EntityFileWriter writer(filePath);
writer.WriteEntity(entity.World, entity.ID);
}
EntityWrapper EditorSystem::OnEntityCreate(EntityWrapper parent)
{
EntityID entity = parent.World->CreateEntity(parent.ID);
parent.World->AttachComponent(entity, "Transform");
return EntityWrapper(parent.World, entity);
}
void EditorSystem::OnEntityDelete(EntityWrapper entity)
{
if (entity.Valid()) {
entity.World->DeleteEntity(entity.ID);
}
}
boost::filesystem::path EditorSystem::openDialog(boost::filesystem::path defaultPath)
void EditorSystem::OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent)
{
namespace bfs = boost::filesystem;
auto absolutePath = bfs::absolute(defaultPath);
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_OpenDialog(NULL, absolutePath.string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
if (entity.Valid()) {
entity.World->SetParent(entity.ID, parent.ID);
}
return bfs::absolute(outPath);
}
boost::filesystem::path EditorSystem::saveDialog(boost::filesystem::path defaultPath)
void EditorSystem::OnEntityChangeName(EntityWrapper entity, const std::string& name)
{
namespace bfs = boost::filesystem;
auto absolutePath = bfs::absolute(defaultPath);
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_SaveDialog(NULL, absolutePath.string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
if (entity.Valid()) {
entity.World->SetName(entity.ID, name);
}
return bfs::absolute(outPath);
}
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType)
{
if (e.Command == "ToggleEditor" && e.Value > 0) {
m_Visible = !m_Visible;
if (entity.Valid()) {
entity.World->AttachComponent(entity.ID, componentType);
}
}
if (e.Command == "EditorToolMove" && e.Value > 0) {
setWidgetMode(WidgetMode::Translate);
void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& componentType)
{
if (entity.Valid()) {
entity.World->DeleteComponent(entity.ID, componentType);
}
if (e.Command == "EditorToolRotate" && e.Value > 0) {
setWidgetMode(WidgetMode::Rotate);
}
if (e.Command == "EditorToolScale" && e.Value > 0) {
setWidgetMode(WidgetMode::Scale);
}
if (e.Command == "EditorToggleTransformSpace" && e.Value > 0) {
if (m_WidgetSpace == WidgetSpace::Global) {
setWidgetSpace(WidgetSpace::Local);
} else if (m_WidgetSpace == WidgetSpace::Local) {
setWidgetSpace(WidgetSpace::Global);
}
}
return true;
}
bool EditorSystem::OnMousePress(const Events::MousePress& e)
{
if (e.Button == GLFW_MOUSE_BUTTON_RIGHT) {
m_PickingQueue.push_back(glm::vec2((int)e.X, (int)e.Y));
ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureMouse && !io.WantCaptureKeyboard && e.Button == GLFW_MOUSE_BUTTON_1) {
PickData pick = m_Renderer->Pick(glm::vec2(e.X, e.Y));
if (pick.World == m_World) {
m_CurrentSelection = EntityWrapper(m_World, pick.Entity);
m_EditorGUI->SelectEntity(m_CurrentSelection);
}
}
return true;
}
bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e)
{
if (m_Widget == EntityID_Invalid) {
return false;
}
if (m_Selection == EntityID_Invalid) {
return false;
}
if (m_Selection == m_Widget) {
return false;
}
// TODO: No widgets for root entity until widgets reside in thier own world,
// or the widgets will move relative to the root entity being moved, which is WEEEIRD.
if (m_Selection == 0) {
return false;
}
if (m_Camera == nullptr) {
return false;
}
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
glm::vec3 widgetOrientation = widgetTransform["Orientation"];
glm::quat totalOrientation = m_Camera->Orientation() * glm::inverse(glm::quat(widgetOrientation));
int width;
int height;
glfwGetFramebufferSize(m_Renderer->Window(), &width, &height);
Rectangle res(width, height);
glm::vec2 delta2(res.Width / 2.f + e.DeltaX, res.Height / 2.f + -e.DeltaY);
glm::vec3 deltaWorld = ScreenCoords::ToWorldPos(
delta2,
m_WidgetPickingDepth,
res,
m_Camera->ProjectionMatrix(),
glm::toMat4(glm::inverse(totalOrientation))
);
glm::vec3 origin = ScreenCoords::ToWorldPos(
glm::vec2(res.Width / 2.f, res.Height / 2.f),
m_WidgetPickingDepth,
res,
m_Camera->ProjectionMatrix(),
glm::toMat4(glm::inverse(totalOrientation))
);
deltaWorld = deltaWorld - origin;
glm::vec3 movement = deltaWorld * m_WidgetCurrentAxis;
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
if (m_WidgetMode == WidgetMode::Translate) {
if (m_WidgetSpace == WidgetSpace::Global) {
EntityID parent = m_World->GetParent(m_Selection);
glm::quat inverseParentOrientation;
//if (parent != 0) {
inverseParentOrientation = glm::inverse(Transform::AbsoluteOrientation(m_World, parent));
//}
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += inverseParentOrientation * movement;
} else if (m_WidgetSpace == WidgetSpace::Local) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
(glm::vec3&)selectionTransform["Position"] += glm::quat((glm::vec3)selectionTransform["Orientation"]) * movement;
}
} else if (m_WidgetMode == WidgetMode::Rotate) {
glm::vec3 finalMovement;
finalMovement.x = -deltaWorld.y * m_WidgetCurrentAxis.x;
finalMovement.y = deltaWorld.x * m_WidgetCurrentAxis.y;
finalMovement.z = deltaWorld.y * m_WidgetCurrentAxis.z;
if (m_WidgetSpace == WidgetSpace::Global) {
EntityID parent = m_World->GetParent(m_Selection);
glm::quat parentOrientation;
//if (parent != 0) {
// parentOrientation = RenderSystem::AbsoluteOrientation(m_World, parent);
//}
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
glm::quat currentOrientation = Transform::AbsoluteOrientation(m_World, m_Selection);
//glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation);
glm::quat deltaOrientation(finalMovement);
selectionOrientation = glm::eulerAngles(glm::inverse(parentOrientation) * (deltaOrientation * currentOrientation));
} else if (m_WidgetSpace == WidgetSpace::Local) {
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
glm::quat currentOrientation(selectionOrientation);
glm::quat deltaOrientation(finalMovement);
selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation);
}
} else if (m_WidgetMode == WidgetMode::Scale) {
glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"];
glm::vec3& scaleY = m_World->GetComponent(m_WidgetY, "Transform")["Scale"];
glm::vec3& scaleZ = m_World->GetComponent(m_WidgetZ, "Transform")["Scale"];
if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) {
float movementLength = glm::length(movement);
float dot = glm::dot((glm::vec3)widgetOrientation, movement);
movement = glm::vec3(movementLength) * glm::sign(dot);
(glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] += movement;
}
if (m_WidgetCurrentAxis.x > 0) {
scaleX.x += movement.x;
}
if (m_WidgetCurrentAxis.y > 0) {
scaleY.y += movement.y;
}
if (m_WidgetCurrentAxis.z > 0) {
scaleZ.z += movement.z;
}
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Scale"] += movement;
if (m_CurrentSelection.Valid()) {
glm::quat parentOrientation;
EntityWrapper parent = m_CurrentSelection.Parent();
if (parent.Valid()) {
parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent.World, parent.ID));
}
(glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation;
m_EditorGUI->SetDirty(m_CurrentSelection);
}
/*LOG_DEBUG("DELTA %f", e.DeltaX);
if (e.X < 0) {
glfwSetCursorPos(m_Renderer->Window(), width - 1, e.Y);
}
if (e.X >= width) {
glfwSetCursorPos(m_Renderer->Window(), 0, e.Y);
}*/
return true;
}
bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e)
EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem::path filePath)
{
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
m_WidgetCurrentAxis = glm::vec3(0.f);
//setWidgetMode(m_WidgetMode);
if (parent.World == nullptr) {
LOG_ERROR("Tried to import entity \"%s\" into null world!", filePath.string().c_str());
return EntityWrapper::Invalid;
}
return true;
}
void EditorSystem::Picking()
{
for (auto& pos : m_PickingQueue) {
auto result = m_Renderer->Pick(pos);
EntityID entity = result.Entity;
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
// ???
} else {
LOG_INFO("Selected %i", entity);
if (entity != EntityID_Invalid) {
EntityID parent = m_World->GetParent(entity);
m_Camera = result.Camera;
if (parent == m_Widget) {
m_WidgetCurrentAxis = glm::vec3(
(entity == m_WidgetX) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneY || entity == m_WidgetPlaneZ),
(entity == m_WidgetY) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneZ),
(entity == m_WidgetZ) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneY)
);
m_WidgetPickingDepth = result.Depth;
//auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
//auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
//widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"];
} else {
ImGui::SetActiveID(0, nullptr);
if (m_WidgetMode == WidgetMode::None) {
m_WidgetMode = WidgetMode::Translate;
}
setWidgetMode(m_WidgetMode);
m_Selection = entity;
}
}
}
}
m_PickingQueue.clear();
};
bool EditorSystem::OnFileDropped(const Events::FileDropped& e)
{
m_LastDroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string();
std::replace(m_LastDroppedFile.begin(), m_LastDroppedFile.end(), '\\', '/');
return true;
}
void EditorSystem::createWidget()
{
if (m_Widget == EntityID_Invalid) {
m_Widget = m_World->CreateEntity();
m_World->AttachComponent(m_Widget, "Transform");
m_WidgetX = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetX, "Transform");
m_World->AttachComponent(m_WidgetX, "Model");
m_WidgetPlaneX = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetPlaneX, "Transform");
m_World->AttachComponent(m_WidgetPlaneX, "Model");
m_World->GetComponent(m_WidgetPlaneX, "Model")["Resource"] = "Models/WidgetPlaneX.obj";
m_WidgetY = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetY, "Transform");
m_World->AttachComponent(m_WidgetY, "Model");
m_WidgetPlaneY = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetPlaneY, "Transform");
m_World->AttachComponent(m_WidgetPlaneY, "Model");
m_World->GetComponent(m_WidgetPlaneY, "Model")["Resource"] = "Models/WidgetPlaneY.obj";
m_WidgetZ = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetZ, "Transform");
m_World->AttachComponent(m_WidgetZ, "Model");
m_WidgetPlaneZ = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetPlaneZ, "Transform");
m_World->AttachComponent(m_WidgetPlaneZ, "Model");
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Resource"] = "Models/WidgetPlaneZ.obj";
m_WidgetOrigin = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetOrigin, "Transform");
m_World->AttachComponent(m_WidgetOrigin, "Model");
setWidgetMode(WidgetMode::None);
try {
auto entityFile = ResourceManager::Load<EntityFile>(filePath.string());
EntityFilePreprocessor fpp(entityFile);
fpp.RegisterComponents(parent.World);
EntityFileParser fp(entityFile);
EntityID newEntity = fp.MergeEntities(parent.World, parent.ID);
return EntityWrapper(parent.World, newEntity);
} catch (const std::exception&) {
return EntityWrapper::Invalid;
}
}
void EditorSystem::updateWidget()
void EditorSystem::setWidgetMode(EditorGUI::WidgetMode mode)
{
if (m_Widget == EntityID_Invalid) {
return;
}
if (m_Selection == m_Widget) {
if (mode == m_WidgetMode && m_Widget.Valid() && m_CurrentSelection.Valid()) {
return;
}
if (m_Selection != EntityID_Invalid) {
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
glm::vec3 selectionPosition = Transform::AbsolutePosition(m_World, m_Selection);
widgetTransform["Position"] = selectionPosition;
if (m_WidgetSpace == WidgetSpace::Local) {
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
}
m_WidgetMode = mode;
void EditorSystem::setWidgetMode(WidgetMode newMode)
{
if (m_Widget == EntityID_Invalid) {
if (m_Widget.Valid()) {
m_Widget.World->DeleteEntity(m_Widget.ID);
m_Widget = EntityWrapper::Invalid;
}
if (!m_CurrentSelection.Valid()) {
return;
}
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
widgetTransform["Orientation"] = glm::vec3(0.f);
m_World->GetComponent(m_WidgetX, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = false;
m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = false;
m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = false;
m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false;
if (newMode == WidgetMode::Translate) {
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/TranslationWidgetX.obj";
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/TranslationWidgetY.obj";
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/TranslationWidgetZ.obj";
// Temporarily disabled for local space until I can figure out what's wrong with the math
if (m_WidgetSpace != WidgetSpace::Local) {
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = true;
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = true;
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = true;
}
if (m_Selection != EntityID_Invalid) {
if (m_WidgetSpace == WidgetSpace::Local) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
} else if (newMode == WidgetMode::Scale) {
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/ScaleWidgetX.obj";
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/ScaleWidgetY.obj";
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/ScaleWidgetZ.obj";
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = true;
m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj";
if (m_Selection != EntityID_Invalid) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
} else if (newMode == WidgetMode::Rotate) {
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj";
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/RotationWidgetY.obj";
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/RotationWidgetZ.obj";
if (m_Selection != EntityID_Invalid) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
if (m_WidgetSpace == WidgetSpace::Local) {
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
switch (mode) {
case EditorGUI::WidgetMode::Translate:
m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetTranslate.xml");
break;
case EditorGUI::WidgetMode::Rotate:
m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetRotate.xml");
break;
case EditorGUI::WidgetMode::Scale:
m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetScale.xml");
break;
}
m_WidgetMode = newMode;
}
void EditorSystem::setWidgetSpace(WidgetSpace space)
{
m_WidgetSpace = space;
setWidgetMode(m_WidgetMode);
}
void EditorSystem::drawUI(World* world, double dt)
{
namespace bfs = boost::filesystem;
ImGui::ShowTestWindow();
//ImGui::ShowStyleEditor();
if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("File")) {
//if (ImGui::MenuItem("New")) { }
if (ImGui::MenuItem("Import", "Ctrl+O")) {
fileImport(world);
}
if (ImGui::MenuItem("Save", "Ctrl+S")) {
fileSave(world);
}
if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) {
fileSaveAs(world);
}
ImGui::Separator();
if (ImGui::MenuItem("Close Editor", "F1")) { }
ImGui::EndMenu();
}
ImGui::SameLine();
if (ImGui::Button("Move")) {
setWidgetMode(WidgetMode::Translate);
}
ImGui::SameLine();
if (ImGui::Button("Rotate")) {
setWidgetMode(WidgetMode::Rotate);
}
ImGui::SameLine();
if (ImGui::Button("Scale")) {
setWidgetMode(WidgetMode::Scale);
}
ImGui::SameLine();
if (m_WidgetSpace == WidgetSpace::Global) {
if (ImGui::Button("(Global)")) {
setWidgetSpace(WidgetSpace::Local);
}
} else if (m_WidgetSpace == WidgetSpace::Local) {
if (ImGui::Button("(Local)")) {
setWidgetSpace(WidgetSpace::Global);
}
}
ImGui::EndMainMenuBar();
}
std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components");
if (ImGui::Begin(title.c_str())) {
if (m_Selection != EntityID_Invalid) {
auto& pools = world->GetComponentPools();
std::vector<const char*> componentTypes;
for (auto& pair : pools) {
// Only add components the entity doesn't already have
if (!pair.second->KnowsEntity(m_Selection)) {
componentTypes.push_back(pair.first.c_str());
}
}
int item = -1;
ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 5.f);
if (ImGui::Combo("", &item, componentTypes.data(), componentTypes.size())) {
if (item != -1) {
std::string chosenType = std::string(componentTypes.at(item));
world->AttachComponent(m_Selection, chosenType);
}
}
ImGui::PopItemWidth();
for (auto& pair : pools) {
const std::string& componentType = pair.first;
auto pool = pair.second;
if (!pool->KnowsEntity(m_Selection)) {
continue;
}
auto& ci = pool->ComponentInfo();
bool deletePressed = createDeleteButton(componentType);
if (deletePressed) {
world->DeleteComponent(m_Selection, componentType);
continue;
}
if (ImGui::CollapsingHeader(componentType.c_str())) {
if (!ci.Meta->Annotation.empty()) {
ImGui::Text(ci.Meta->Annotation.c_str());
}
auto& component = world->GetComponent(m_Selection, componentType);
for (auto& kv : ci.Fields) {
const std::string& fieldName = kv.first;
auto& field = kv.second;
std::string uniqueID = componentType + fieldName;
ImGui::PushID(uniqueID.c_str());
if (field.Type == "Vector") {
auto& val = component.Field<glm::vec3>(fieldName);
if (fieldName == "Scale") {
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
} else if (fieldName == "Orientation") {
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
val = tempVal;
}
} else {
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
}
} else if (field.Type == "Color") {
auto& val = component.Field<glm::vec4>(fieldName);
ImGui::ColorEdit4("", glm::value_ptr(val), true);
} else if (field.Type == "string") {
std::string& val = component.Field<std::string>(fieldName);
char tempString[1024];
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString)));
if (ImGui::InputText("", tempString, sizeof(tempString))) {
val = std::string(tempString);
LOG_DEBUG("%s::%s changed!", componentType.c_str(), fieldName.c_str());
}
// DROP STUFF
if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) {
val = m_LastDroppedFile;
m_LastDroppedFile = "";
}
} else if (field.Type == "double") {
float tempVal = static_cast<float>(component.Field<double>(fieldName));
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
component.SetField(fieldName, static_cast<double>(tempVal));
}
} else if (field.Type == "int") {
int val = component.Field<int>(fieldName);
ImGui::InputInt("", &val);
} else if (field.Type == "enum") {
int currentValue = component.Field<int>(fieldName);
int item = -1;
std::stringstream enumKeys;
std::vector<int> enumValues;
int i = 0;
for (auto& kv : ci.Meta->FieldEnumDefinitions.at(fieldName)) {
enumKeys << kv.first << " (" << kv.second << ")" << '\0';
enumValues.push_back(kv.second);
if (currentValue == kv.second) {
item = i;
}
i++;
}
if (ImGui::Combo("", &item, enumKeys.str().c_str())) {
component.SetField(fieldName, enumValues.at(item));
}
} else if (field.Type == "bool") {
auto& val = component.Field<bool>(fieldName);
ImGui::Checkbox("", &val);
} else {
ImGui::TextDisabled(field.Type.c_str());
}
ImGui::PopID();
ImGui::SameLine();
ImGui::Text(fieldName.c_str());
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("field annotation goes here");
}
}
}
}
}
}
ImGui::End();
if (ImGui::Begin("Entities")) {
auto entityChildren = world->GetEntityChildren();
std::function<void(EntityID)> recurse = [&](EntityID parent) {
auto range = entityChildren.equal_range(parent);
for (auto it = range.first; it != range.second; it++) {
if (createEntityNode(world, it->second)) {
recurse(it->second);
ImGui::TreePop();
}
}
};
recurse(EntityID_Invalid);
}
ImGui::End();
}
bool EditorSystem::createEntityNode(World* world, EntityID entity)
{
// HACK: Don't show the widget entities in the entity tree
if (entity == m_Widget) {
return false;
}
ImVec2 pos = ImGui::GetCursorScreenPos();
float width = ImGui::GetContentRegionAvailWidth();
ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13));
auto window = ImGui::GetCurrentWindow();
if (m_Selection == entity) {
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
window->DrawList->AddRectFilled(bb.Min, bb.Max, col);
}
ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(entity)).c_str());
bool hovered = false;
bool held = false;
if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) {
m_Selection = entity;
}
if (held) {
ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0);
if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) {
if (m_UIDraggingEntity == EntityID_Invalid) {
m_UIDraggingEntity = entity;
LOG_DEBUG("Started drag of entity %i", m_UIDraggingEntity);
}
ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0));
ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings);
ImGui::Text("#%i", m_UIDraggingEntity);
ImGui::End();
}
}
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
std::string nodeTitle;
const std::string& entityName = world->GetName(entity);
if (!entityName.empty()) {
nodeTitle = entityName;
} else {
nodeTitle = std::string("#") + std::to_string(entity);
}
if (ImGui::TreeNode(nodeTitle.c_str())) {
if (m_UIDraggingEntity != EntityID_Invalid && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) {
LOG_DEBUG("Changed parent of %i to %i", m_UIDraggingEntity, entity);
changeParent(m_UIDraggingEntity, entity);
m_UIDraggingEntity = EntityID_Invalid;
}
if (ImGui::BeginPopupContextItem("item context menu")) {
if (ImGui::Button("Add")) {
EntityID newEntity = world->CreateEntity(entity);
world->AttachComponent(newEntity, "Transform");
}
ImGui::SameLine();
if (ImGui::Button("Delete")) {
world->DeleteEntity(entity);
ImGui::CloseCurrentPopup();
if (!world->ValidEntity(m_Selection)) {
m_Selection = EntityID_Invalid;
}
}
ImGui::EndPopup();
}
return true;
} else {
return false;
}
}
bool EditorSystem::createDeleteButton(std::string componentType)
{
float width = ImGui::GetContentRegionAvailWidth();
ImGuiWindow* window = ImGui::GetCurrentWindow();
auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1);
ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f));
std::string idString = "#DELETE";
idString += componentType;
ImGuiID id = window->GetID(idString.c_str());
bool hovered;
bool held;
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
//ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
return pressed;
}
void EditorSystem::changeParent(EntityID entity, EntityID newParent)
{
if (entity == newParent) {
return;
}
// An entity can't be a child to one of its own children
auto children = m_World->GetEntityChildren().equal_range(entity);
for (auto it = children.first; it != children.second; it++) {
if (it->second == newParent) {
return;
}
}
m_World->SetParent(entity, newParent);
}
void EditorSystem::fileImport(World* world)
{
m_CurrentFile = openDialog(m_DefaultEntityDir);
auto file = ResourceManager::Load<EntityFile>(m_CurrentFile.string());
EntityFilePreprocessor fpp(file);
fpp.RegisterComponents(world);
EntityFileParser fp(file);
fp.MergeEntities(world);
createWidget();
updateWidget();
}
void EditorSystem::fileSave(World* world)
{
if (boost::filesystem::exists(m_CurrentFile)) {
// HACK: Delete the widgets so they don't appear in the saved file
world->DeleteEntity(m_Widget);
m_Widget = EntityID_Invalid;
EntityFileWriter writer(m_CurrentFile.string());
writer.WriteWorld(world);
createWidget();
} else {
fileSaveAs(world);
}
}
void EditorSystem::fileSaveAs(World* world)
{
auto filePath = saveDialog(m_DefaultEntityDir);
if (filePath.empty()) {
return;
}
// HACK: Delete the widgets so they don't appear in the saved file
world->DeleteEntity(m_Widget);
m_Widget = EntityID_Invalid;
EntityFileWriter writer(filePath.string());
writer.WriteWorld(world);
createWidget();
m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID);
}
+75
View File
@@ -0,0 +1,75 @@
#include "Editor/EditorWidgetSystem.h"
EditorWidgetSystem::EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer)
: System(world, eventBroker)
, PureSystem("EditorWidget")
, m_Renderer(renderer)
{
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorWidgetSystem::OnMouseMove);
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorWidgetSystem::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorWidgetSystem::OnMouseRelease);
}
void EditorWidgetSystem::Update(double dt)
{
// Pick at current mouse position
}
void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt)
{
if (!m_PickEntity.Valid() || m_PickEntity != entity) {
return;
}
Events::WidgetDelta e;
EntityWrapper moveEntity = entity.Parent();
if (!moveEntity.Valid()) {
moveEntity = entity;
}
auto camera = m_PickData.Camera;
glm::vec3 axis = cEditorWidget["Axis"];
glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->Resolution()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->Resolution());
float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen);
glm::vec3 worldMovement = dot * axis;
ComponentWrapper::SubscriptProxy& type = cEditorWidget["Type"];
if ((ComponentInfo::EnumType)type == type.Enum("Translate")) {
e.Translation += worldMovement;
m_EventBroker->Publish(e);
} else if ((ComponentInfo::EnumType)type == type.Enum("Rotate")) {
//if (glm::length(worldMovement) > 0) {
// glm::vec3& orientation = moveEntity["Transform"]["Orientation"];
// glm::quat q = glm::quat(orientation);
// q *= glm::quat(glm::vec3(worldMovement));
// orientation = glm::eulerAngles(q);
//}
}
m_MouseDelta = glm::vec2(0);
}
bool EditorWidgetSystem::OnMouseMove(const Events::MouseMove& e)
{
m_MouseDelta = glm::vec2((float)e.DeltaX, (float)-e.DeltaY);
return false;
}
bool EditorWidgetSystem::OnMousePress(const Events::MousePress & e)
{
ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureMouse && !io.WantCaptureKeyboard && e.Button == GLFW_MOUSE_BUTTON_1) {
m_PickData = m_Renderer->Pick(glm::vec2(e.X, e.Y));
if (m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) {
m_PickEntity = EntityWrapper(m_World, m_PickData.Entity);
}
}
return true;
}
bool EditorWidgetSystem::OnMouseRelease(const Events::MouseRelease& e)
{
m_PickEntity = EntityWrapper::Invalid;
return true;
}
-1
View File
@@ -288,7 +288,6 @@ bool Client::OnPlayerDamage(const Events::PlayerDamage & e)
Packet packet(MessageType::OnInputCommand, m_SendPacketID);
packet.WritePrimitive(e.DamageAmount);
packet.WritePrimitive(e.PlayerDamagedID);
packet.WriteString(e.TypeOfDamage);
send(packet);
return false;
}
-1
View File
@@ -240,7 +240,6 @@ void Server::parseOnPlayerDamage(Packet & packet)
Events::PlayerDamage e;
e.DamageAmount = packet.ReadPrimitive<double>();
e.PlayerDamagedID = packet.ReadPrimitive<EntityID>();
e.TypeOfDamage = packet.ReadString();
m_EventBroker->Publish(e);
//LOG_DEBUG("Server::parseOnPlayerDamage: Command is %s. Value is %f. PlayerID is %i.", e.DamageAmount, e.PlayerDamagedID, e.TypeOfDamage.c_str());
}
+13
View File
@@ -79,6 +79,19 @@ void Camera::UpdateProjectionMatrix()
m_ProjectionMatrix = glm::perspective(m_FOV, m_AspectRatio, m_NearClip, m_FarClip);
}
glm::vec2 Camera::WorldToScreen(glm::vec3 worldCoord, Rectangle resolution)
{
glm::vec4 screenCoord = m_ProjectionMatrix * m_ViewMatrix * glm::vec4(worldCoord, 1.f);
if (screenCoord.w != 0) {
screenCoord.x /= screenCoord.w;
screenCoord.y /= screenCoord.w;
screenCoord.z /= screenCoord.w;
}
screenCoord.x = screenCoord.x * (resolution.Width / 2.f);
screenCoord.y = screenCoord.y * (resolution.Height / 2.f);
return glm::vec2(screenCoord);
}
void Camera::UpdateViewMatrix()
{
m_ViewMatrix = glm::toMat4(glm::inverse(m_Orientation))
+7 -2
View File
@@ -27,15 +27,20 @@ void DrawFinalPass::Draw(RenderScene& scene)
GLERROR("DrawFinalPass::Draw: Pre");
DrawFinalPassState state;
m_ForwardPlusProgram->Bind();
GLuint shaderHandle = m_ForwardPlusProgram->GetHandle();
if (scene.ClearDepth) {
glClear(GL_DEPTH_BUFFER_BIT);
}
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO());
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO());
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO());
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix()));
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height);
//TODO: Render: Add code for more jobs than modeljobs.
@@ -9,7 +9,6 @@ DrawFinalPassState::DrawFinalPassState()
Enable(GL_DEPTH_TEST);
Enable(GL_CULL_FACE);
ClearColor(glm::vec4(200.f / 255, 0.f / 255, 200.f / 255, 0.f));
Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
DrawFinalPassState::~DrawFinalPassState()
-62
View File
@@ -1,62 +0,0 @@
#include "Rendering/DrawScenePass.h"
DrawScenePass::DrawScenePass(IRenderer* renderer)
{
m_Renderer = renderer;
InitializeTextures();
InitializeShaderPrograms();
}
void DrawScenePass::InitializeTextures()
{
m_WhiteTexture = ResourceManager::Load<Texture>("Textures/Core/Blank.png");
}
void DrawScenePass::InitializeShaderPrograms()
{
m_BasicForwardProgram = ResourceManager::Load<ShaderProgram>("#BasicForwardProgram");
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new VertexShader("Shaders/BasicForward.vert.glsl")));
m_BasicForwardProgram->AddShader(std::shared_ptr<Shader>(new FragmentShader("Shaders/BasicForward.frag.glsl")));
m_BasicForwardProgram->Compile();
m_BasicForwardProgram->Link();
}
void DrawScenePass::Draw(RenderScene& scene)
{
//glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLERROR("DrawScenePass::Draw: Pre");
DrawScenePassState state = DrawScenePassState();
m_BasicForwardProgram->Bind();
for (auto &job : scene.ForwardJobs) {
auto modelJob = std::dynamic_pointer_cast<ModelJob>(job);
if (modelJob) {
GLuint ShaderHandle = m_BasicForwardProgram->GetHandle();
//TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix()));
glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix()));
glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color));
//TODO: Renderer: bättre textur felhantering samt fler texturer stöd
if (modelJob->DiffuseTexture != nullptr) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture);
} else {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
}
glBindVertexArray(modelJob->Model->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer);
glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex);
//continue;
}
}
GLERROR("DrawScenePass::Draw: End");
}
@@ -1,20 +0,0 @@
#include "Rendering/DrawScenePassState.h"
DrawScenePassState::DrawScenePassState()
{
GLERROR("---");
BindFramebuffer(0);
GLERROR("---");
Enable(GL_DEPTH_TEST);
Enable(GL_CULL_FACE);
Enable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// ClearColor(glm::vec4(255.f / 255, 163.f / 255, 176.f / 255, 0.f));
// Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
DrawScenePassState::~DrawScenePassState()
{
}
+4 -4
View File
@@ -105,7 +105,7 @@ void ImGuiRenderPass::Draw()
if (pcmd->UserCallback) {
pcmd->UserCallback(cmd_list, pcmd);
} else {
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
glBindTexture(GL_TEXTURE_2D, (GLuint)pcmd->TextureId);
glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
}
@@ -190,7 +190,7 @@ bool ImGuiRenderPass::createDeviceObjects()
"{\n"
" Frag_UV = UV;\n"
" Frag_Color = Color;\n"
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
" gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n"
"}\n";
const GLchar* fragment_shader =
@@ -201,7 +201,7 @@ bool ImGuiRenderPass::createDeviceObjects()
"out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";
g_ShaderHandle = glCreateProgram();
@@ -271,7 +271,7 @@ bool ImGuiRenderPass::createFontsTexture()
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// Store our identifier
io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;
io.Fonts->TexID = (void*)g_FontTexture;
// Restore state
glBindTexture(GL_TEXTURE_2D, last_texture);
+3 -1
View File
@@ -53,7 +53,9 @@ void PickingPass::Draw(RenderScene& scene)
GLuint ShaderHandle = m_PickingProgram->GetHandle();
m_PickingProgram->Bind();
if (scene.ClearDepth) {
glClear(GL_DEPTH_BUFFER_BIT);
}
m_Camera = scene.Camera;
+9 -6
View File
@@ -44,12 +44,6 @@ bool RenderState::ClearColor(glm::vec4 color)
return !GLERROR("RenderState::ClearColor");
}
bool RenderState::Clear(GLbitfield mask)
{
glClear(mask);
return !GLERROR("RenderState::Clear");
}
bool RenderState::BindFramebuffer(GLint framebuffer)
{
GLint originalRead;
@@ -91,6 +85,15 @@ bool RenderState::BlendFunc(GLenum sfactor, GLenum dfactor)
return !GLERROR("RenderState::BlendFunc");
}
bool RenderState::DepthMask(GLboolean flag)
{
GLboolean original;
glGetBooleanv(GL_DEPTH_WRITEMASK, &original);
m_ResetFunctions.push_back(std::bind(glDepthMask, original));
glDepthMask(flag);
return !GLERROR("RenderState::DepthMask");
}
RenderState::~RenderState()
{
for (auto& f : m_ResetFunctions) {
+26 -142
View File
@@ -1,7 +1,7 @@
#include "Rendering/RenderSystem.h"
RenderSystem::RenderSystem(EventBroker* eventBroker, const IRenderer* renderer, RenderFrame* renderFrame)
: System(eventBroker)
RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRenderer* renderer, RenderFrame* renderFrame)
: System(world, eventBroker)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
{
@@ -9,74 +9,29 @@ RenderSystem::RenderSystem(EventBroker* eventBroker, const IRenderer* renderer,
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand);
m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 5000.f);
m_DebugCameraInputController = new DebugCameraInputController<RenderSystem>(eventBroker, -1);
}
RenderSystem::~RenderSystem()
{
delete m_Camera;
delete m_DebugCameraInputController;
}
bool RenderSystem::OnSetCamera(const Events::SetCamera &event)
bool RenderSystem::OnSetCamera(Events::SetCamera& e)
{
auto cameras = m_World->GetComponents("Camera");
if (cameras != nullptr) {
for (auto it = cameras->begin(); it != cameras->end(); it++) {
if ((std::string)(*it)["Name"] == event.Name) {
switchCamera((*it).EntityID);
}
}
}
ComponentWrapper cTransform = e.CameraEntity["Transform"];
ComponentWrapper cCamera = e.CameraEntity["Camera"];
m_Camera->SetFOV((double)cCamera["FOV"]);
m_Camera->SetNearClip((double)cCamera["NearClip"]);
m_Camera->SetFarClip((double)cCamera["FarClip"]);
m_Camera->SetPosition(cTransform["Position"]);
m_Camera->SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"]));
m_CurrentCamera = e.CameraEntity;
return true;
}
void RenderSystem::switchCamera(EntityID entity)
void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs)
{
if(m_World->HasComponent(entity, "Camera")) {
if (m_CurrentCamera != EntityID_Invalid) {
if (m_World->HasComponent(m_CurrentCamera, "Model")) {
m_World->GetComponent(m_CurrentCamera, "Model")["Visible"] = true;
}
if (m_World->HasComponent(m_CurrentCamera, "Listener")) {
m_World->DeleteComponent(m_CurrentCamera, "Listener");
}
}
if (m_World->HasComponent(entity, "Model")) {
m_World->GetComponent(entity, "Model")["Visible"] = false;
}
if (!m_World->HasComponent(entity, "Listener")) {
m_World->AttachComponent(entity, "Listener");
}
m_CurrentCamera = entity;
m_SwitchCamera = false;
} else {
LOG_ERROR("Entity %i does not have a CameraComponent", entity);
m_SwitchCamera = false;
}
}
void RenderSystem::updateProjectionMatrix(ComponentWrapper& cameraComponent)
{
double fov = cameraComponent["FOV"];
double aspectRatio = (float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height;
double nearClip = cameraComponent["NearClip"];
double farClip = cameraComponent["FarClip"];
m_Camera->SetFOV(glm::radians(fov));
m_Camera->SetAspectRatio(aspectRatio);
m_Camera->SetNearClip(nearClip);
m_Camera->SetFarClip(farClip);
m_Camera->UpdateProjectionMatrix();
}
void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs, World* world)
{
auto models = world->GetComponents("Model");
auto models = m_World->GetComponents("Model");
if (models == nullptr) {
return;
}
@@ -105,18 +60,17 @@ void RenderSystem::fillModels(std::list<std::shared_ptr<RenderJob>>& jobs, World
}
}
glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, world);
glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, m_World);
for (auto matGroup : model->MaterialGroups()) {
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, world));
std::shared_ptr<ModelJob> modelJob = std::shared_ptr<ModelJob>(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, m_World));
jobs.push_back(modelJob);
}
}
}
void RenderSystem::fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world)
{
auto pointLights = world->GetComponents("PointLight");
auto pointLights = m_World->GetComponents("PointLight");
if (pointLights != nullptr) {
for (auto& pointlightC : *pointLights) {
bool visible = pointlightC["Visible"];
@@ -158,96 +112,26 @@ void RenderSystem::fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>&
bool RenderSystem::OnInputCommand(const Events::InputCommand& e)
{
if (e.Command == "SwitchCamera" && e.Value > 0) {
m_SwitchCamera = true;
return true;
} else {
return false;
}
return false;
}
void RenderSystem::Update(World* world, double dt)
void RenderSystem::Update(double dt)
{
m_World = world;
m_EventBroker->Process<RenderSystem>();
updateCamera(world, dt);
if (m_CurrentCamera) {
ComponentWrapper cameraTransform = m_CurrentCamera["Transform"];
m_Camera->SetPosition(cameraTransform["Position"]);
m_Camera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"]));
}
//Only supports opaque geometry atm
m_RenderFrame->Clear();
RenderScene scene;
scene.Camera = m_Camera;
scene.Viewport = Rectangle(1280, 720);
fillModels(scene.ForwardJobs, world);
fillPointLights(scene.PointLightJobs, world);
fillDirectionalLights(scene.DirectionalLightJobs, world);
fillModels(scene.ForwardJobs);
fillPointLights(scene.PointLightJobs, m_World);
fillDirectionalLights(scene.DirectionalLightJobs, m_World);
m_RenderFrame->Add(scene);
}
void RenderSystem::updateCamera(World* world, double dt)
{
if (m_SwitchCamera) {
auto cameras = world->GetComponents("Camera");
if (cameras == nullptr) {
return;
}
for (auto it = cameras->begin(); it != cameras->end(); it++) {
if ((*it).EntityID == m_CurrentCamera) {
it++;
if (it != cameras->end()) {
switchCamera((*it).EntityID);
} else {
switchCamera((*cameras->begin()).EntityID);
}
break;
}
}
if (m_World->HasComponent(m_CurrentCamera, "Camera")) {
ComponentWrapper& cameraComponent = world->GetComponent(m_CurrentCamera, "Camera");
ComponentWrapper& cameraTransform = world->GetComponent(m_CurrentCamera, "Transform");
m_DebugCameraInputController->SetOrientation(glm::quat((glm::vec3)cameraTransform["Orientation"]));
m_DebugCameraInputController->SetPosition(cameraTransform["Position"]);
}
}
if (m_World->ValidEntity(m_CurrentCamera)) {
if (world->HasComponent(m_CurrentCamera, "Camera") && world->HasComponent(m_CurrentCamera, "Transform")) {
ComponentWrapper& cameraComponent = world->GetComponent(m_CurrentCamera, "Camera");
ComponentWrapper& cameraTransform = world->GetComponent(m_CurrentCamera, "Transform");
m_DebugCameraInputController->Update(dt);
(glm::vec3&)cameraTransform["Orientation"] = glm::eulerAngles(m_DebugCameraInputController->Orientation());
(glm::vec3&)cameraTransform["Position"] = m_DebugCameraInputController->Position();
glm::vec3 position = Transform::AbsolutePosition(world, m_CurrentCamera);
glm::quat orientation = Transform::AbsoluteOrientation(world, m_CurrentCamera);
m_Camera->SetPosition(position);
m_Camera->SetOrientation(orientation);
updateProjectionMatrix(cameraComponent);
}
} else {
m_Camera = m_Camera;
auto cameras = world->GetComponents("Camera");
if (cameras != nullptr) {
if (cameras->begin() != cameras->end()) {
ComponentWrapper& cameraC = *cameras->begin();
switchCamera(cameraC.EntityID);
ComponentWrapper& cameraComponent = world->GetComponent(m_CurrentCamera, "Camera");
ComponentWrapper& cameraTransform = world->GetComponent(m_CurrentCamera, "Transform");
m_DebugCameraInputController->SetOrientation(glm::quat((glm::vec3)cameraTransform["Orientation"]));
m_DebugCameraInputController->SetPosition(cameraTransform["Position"]);
}
}
}
m_Camera->UpdateViewMatrix();
}
+2 -14
View File
@@ -15,15 +15,6 @@ void Renderer::Initialize()
m_UnitSphere = ResourceManager::Load<Model>("Models/Core/UnitSphere.obj");
m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker);
// Create default camera
m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f);
m_DefaultCamera->SetPosition(glm::vec3(0, 0, 10));
if (m_Camera == nullptr) {
m_Camera = m_DefaultCamera;
}
}
void Renderer::InitializeWindow()
@@ -92,13 +83,11 @@ void Renderer::Update(double dt)
void Renderer::Draw(RenderFrame& frame)
{
glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
m_PickingPass->ClearPicking();
for (auto scene : frame.RenderScenes){
m_Camera = scene->Camera; // remove renderer camera when Editor uses the render scene cameras.
SortRenderJobsByDepth(*scene);
m_PickingPass->Draw(*scene);
m_LightCullingPass->GenerateNewFrustum(*scene);
@@ -167,8 +156,7 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin
void Renderer::InitializeRenderPasses()
{
m_DrawScenePass = new DrawScenePass(this);
m_PickingPass = new PickingPass(this, m_EventBroker);
m_LightCullingPass = new LightCullingPass(this);
m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass);
}
}
+8 -4
View File
@@ -9,6 +9,7 @@
#include "Systems/PlayerSpawnSystem.h"
#include "Core/EntityFileWriter.h"
#include "Game/Systems/CapturePointSystem.h"
#include "Game/Systems/WeaponSystem.h"
Game::Game(int argc, char* argv[])
{
@@ -28,7 +29,6 @@ Game::Game(int argc, char* argv[])
// Create the core event broker
m_EventBroker = new EventBroker();
// Create the renderer
m_Renderer = new Renderer(m_EventBroker);
m_Renderer->SetFullscreen(m_Config->Get<bool>("Video.Fullscreen", false));
@@ -71,17 +71,17 @@ Game::Game(int argc, char* argv[])
m_OctreeCollision = new Octree<AABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
m_OctreeFrustrumCulling = new Octree<AABB>(AABB(glm::vec3(-100), glm::vec3(100)), 4);
// Create system pipeline
m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker);
// All systems with orderlevel 0 will be updated first.
unsigned int updateOrderLevel = 0;
m_SystemPipeline->AddSystem<RaptorCopterSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer);
m_SystemPipeline->AddSystem<HealthSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerMovementSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<InterpolationSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<SpawnerSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<PlayerSpawnSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<WeaponSystem>(updateOrderLevel, m_Renderer);
// Populate Octree with collidables
++updateOrderLevel;
m_SystemPipeline->AddSystem<CollidableOctreeSystem>(updateOrderLevel, m_OctreeCollision);
@@ -92,6 +92,8 @@ Game::Game(int argc, char* argv[])
++updateOrderLevel;
m_SystemPipeline->AddSystem<CapturePointSystem>(updateOrderLevel);
m_SystemPipeline->AddSystem<RenderSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
++updateOrderLevel;
m_SystemPipeline->AddSystem<EditorSystem>(updateOrderLevel, m_Renderer, m_RenderFrame);
// Invoke network
if (m_Config->Get<bool>("Networking.StartNetwork", false)) {
@@ -143,12 +145,14 @@ void Game::Tick()
m_ClientOrServer->Update();
}
// Iterate through systems and update world!
m_SystemPipeline->Update(m_World, dt);
m_EventBroker->Process<SystemPipeline>();
m_SystemPipeline->Update(dt);
debugTick(dt);
m_Renderer->Update(dt);
m_SoundSystem->Update(dt);
GLERROR("Game::Tick m_RenderQueueFactory->Update");
m_Renderer->Draw(*m_RenderFrame);
m_RenderFrame->Clear();
GLERROR("Game::Tick m_Renderer->Draw");
m_EventBroker->Swap();
m_EventBroker->Clear();
+21 -15
View File
@@ -1,9 +1,9 @@
#include "Systems/CapturePointSystem.h"
#include <algorithm>
CapturePointSystem::CapturePointSystem(EventBroker* eventBroker)
: System(eventBroker),
PureSystem("CapturePoint")
CapturePointSystem::CapturePointSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("CapturePoint")
{
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
EVENT_SUBSCRIBE_MEMBER(m_ETriggerTouch, &CapturePointSystem::OnTriggerTouch);
@@ -13,22 +13,22 @@ CapturePointSystem::CapturePointSystem(EventBroker* eventBroker)
//here all capturepoints will update their component
//NOTE: needs to run each frame, since we're possibly modifying the captureTimer for the capturePoints by dt
void CapturePointSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& capturePoint, double dt)
void CapturePointSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt)
{
if (m_WinnerWasFound) {
return;
}
const int capturePointNumber = capturePoint["CapturePointNumber"];
const bool hasTeamComponent = world->HasComponent(capturePoint.EntityID, "Team");
const bool hasTeamComponent = m_World->HasComponent(capturePoint.EntityID, "Team");
//if point doesnt have a teamComponent yet, add one. since:
//what if capture point has no team -> we cant get/use the team enum from it...
if (!hasTeamComponent) {
world->AttachComponent(capturePoint.EntityID, "Team");
ComponentWrapper& teamComponent = world->GetComponent(capturePoint.EntityID, "Team");
m_World->AttachComponent(capturePoint.EntityID, "Team");
ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team");
teamComponent["Team"] = (int)teamComponent["Team"].Enum("Spectator");
}
ComponentWrapper& teamComponent = world->GetComponent(capturePoint.EntityID, "Team");
ComponentWrapper& teamComponent = m_World->GetComponent(capturePoint.EntityID, "Team");
const int redTeam = (int)teamComponent["Team"].Enum("Red");
const int blueTeam = (int)teamComponent["Team"].Enum("Blue");
const int spectatorTeam = (int)teamComponent["Team"].Enum("Spectator");
@@ -66,7 +66,10 @@ void CapturePointSystem::UpdateComponent(World* world, EntityWrapper& entity, Co
nextPossibleCapturePoint["Blue"] = -1;
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
{
ComponentWrapper& capturePointOwnedBy = world->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) {
continue;
}
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint == 0) {
nextPossibleCapturePoint["Red"] = i + 1;
}
@@ -76,7 +79,10 @@ void CapturePointSystem::UpdateComponent(World* world, EntityWrapper& entity, Co
}
for (int i = m_NumberOfCapturePoints - 1; i >= 0; i--)
{
ComponentWrapper& capturePointOwnedBy = world->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
if (!m_World->HasComponent(m_CapturePointNumberToEntityIDMap[i], "Team")) {
continue;
}
ComponentWrapper& capturePointOwnedBy = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "Team");
if ((int)capturePointOwnedBy["Team"] == redTeam && m_RedTeamHomeCapturePoint != 0) {
nextPossibleCapturePoint["Red"] = i - 1;
}
@@ -89,7 +95,7 @@ void CapturePointSystem::UpdateComponent(World* world, EntityWrapper& entity, Co
if (m_ResetTimers) {
for (size_t i = 0; i < m_NumberOfCapturePoints; i++)
{
ComponentWrapper& capturePoint = world->GetComponent(m_CapturePointNumberToEntityIDMap[i], "CapturePoint");
ComponentWrapper& capturePoint = m_World->GetComponent(m_CapturePointNumberToEntityIDMap[i], "CapturePoint");
if ((int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Red"] &&
(int)capturePoint["CapturePointNumber"] != nextPossibleCapturePoint["Blue"]) {
capturePoint["CaptureTimer"] = 0.0;
@@ -113,21 +119,21 @@ void CapturePointSystem::UpdateComponent(World* world, EntityWrapper& entity, Co
if (std::get<1>(triggerTouched) == capturePoint.EntityID) {
//some player has touched this - lets figure out: what team, health
EntityID playerID = std::get<0>(triggerTouched);
if (!world->HasComponent(playerID, "Player")) {
if (!m_World->HasComponent(playerID, "Player")) {
//if a non-player has entered the capturePoint, just erase that event and continue
m_ETriggerTouchVector.erase(m_ETriggerTouchVector.begin() + i - 1);
continue;
}
bool hasHealthComponent = world->HasComponent(playerID, "Health");
bool hasHealthComponent = m_World->HasComponent(playerID, "Health");
if (hasHealthComponent) {
double currentHealth = world->GetComponent(playerID, "Health")["Health"];
double currentHealth = m_World->GetComponent(playerID, "Health")["Health"];
//check if player is dead
if ((int)currentHealth == 0) {
continue;
}
}
//check team - spectatorNumber = "no team"
int teamNumber = world->GetComponent(playerID, "Team")["Team"];
int teamNumber = m_World->GetComponent(playerID, "Team")["Team"];
if (teamNumber == redTeam) {
redTeamPlayersStandingInside++;
} else if (teamNumber == blueTeam) {
+5 -4
View File
@@ -1,7 +1,7 @@
#include "Systems/HealthSystem.h"
HealthSystem::HealthSystem(EventBroker* eventBroker)
: System(eventBroker)
HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker)
: System(m_World, eventBroker)
, PureSystem("Health")
{
//subscribe/listenTo playerdamage,healthpickup events (using the eventBroker)
@@ -9,9 +9,10 @@ HealthSystem::HealthSystem(EventBroker* eventBroker)
EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup);
}
void HealthSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
//if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity)
ComponentWrapper player = m_World->GetComponent(component.EntityID, "Player");
double maxHealth = (double)component["MaxHealth"];
//process the DeltaHealthVector and change the entitys health accordingly
@@ -38,7 +39,7 @@ void HealthSystem::UpdateComponent(World* world, EntityWrapper& entity, Componen
m_DeltaHealthVector.erase(m_DeltaHealthVector.begin() + j - 1);
}
//delete the player and break the loop
world->DeleteEntity(entity.ID);
m_World->DeleteEntity(entity.ID);
break;
}
}
+1 -1
View File
@@ -20,7 +20,7 @@
// }
//}
void InterpolationSystem::UpdateComponent(World * world, EntityWrapper& entity, ComponentWrapper & transform, double dt)
void InterpolationSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt)
{
if (m_NextTransform.find(transform.EntityID) != m_NextTransform.end()) { // Exists in map
m_NextTransform[transform.EntityID].interpolationTime += dt;
+1 -1
View File
@@ -1,6 +1,6 @@
#include "Systems/PlayerMovementSystem.h"
void PlayerMovementSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
ComponentWrapper& cTransform = entity["Transform"];
if (!entity.HasComponent("Physics")) {
+5 -5
View File
@@ -1,21 +1,21 @@
#include "Systems/PlayerSpawnSystem.h"
PlayerSpawnSystem::PlayerSpawnSystem(EventBroker* eventBroker)
: System(eventBroker)
PlayerSpawnSystem::PlayerSpawnSystem(World* m_World, EventBroker* eventBroker)
: System(m_World, eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand);
}
void PlayerSpawnSystem::Update(World* world, double dt)
void PlayerSpawnSystem::Update(double dt)
{
auto playerSpawns = world->GetComponents("PlayerSpawn");
auto playerSpawns = m_World->GetComponents("PlayerSpawn");
if (playerSpawns == nullptr) {
return;
}
for (auto& team : m_SpawnRequests) {
for (auto& cPlayerSpawn : *playerSpawns) {
EntityWrapper spawner(world, cPlayerSpawn.EntityID);
EntityWrapper spawner(m_World, cPlayerSpawn.EntityID);
if (!spawner.HasComponent("Spawner")) {
continue;
}
+2 -1
View File
@@ -1,6 +1,7 @@
#include "Systems/SpawnerSystem.h"
SpawnerSystem::SpawnerSystem(EventBroker* eventBroker) : System(eventBroker)
SpawnerSystem::SpawnerSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_OnSpawnerSpawn, &SpawnerSystem::OnSpawnerSpawn);
}
+53
View File
@@ -0,0 +1,53 @@
#include "Systems/WeaponSystem.h"
WeaponSystem::WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer)
: System(world, eventBroker)
, ImpureSystem()
, m_Renderer(renderer)
{
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponSystem::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EShoot, &WeaponSystem::OnShoot);
}
void WeaponSystem::Update(double dt)
{
for (int i = m_EShootVector.size(); i > 0; i--)
{
//TODO: check if player has enough ammo and if weapon has a cooldown or not
//pick the object
PickData pickDataFromShot = m_Renderer->Pick(std::get<1>(m_EShootVector[i - 1]));
if (pickDataFromShot.Entity == EntityID_Invalid) {
m_EShootVector.erase(m_EShootVector.begin() + i - 1);
continue;
}
//if its a player, do PlayerDamage event
const bool hasPlayerComponent = m_World->HasComponent(pickDataFromShot.Entity, "Player");
if (hasPlayerComponent) {
Events::PlayerDamage ePlayerDamage;
//TODO: damage based on weapontype/class?
//TODO: multiple shots at the same time? (shotgunner)
ePlayerDamage.DamageAmount = 25;
ePlayerDamage.PlayerDamagedID = pickDataFromShot.Entity;
m_EventBroker->Publish(ePlayerDamage);
}
m_EShootVector.erase(m_EShootVector.begin() + i - 1);
}
}
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e)
{
if (e.Command == "PrimaryFire" && e.Value > 0) {
Events::Shoot eShoot;
eShoot.shooter = e.PlayerID;
m_EventBroker->Publish(eShoot);
}
return true;
}
bool WeaponSystem::OnShoot(const Events::Shoot& e) {
//screen center, based on current resolution!
Rectangle screenResolution = m_Renderer->Resolution();
glm::vec2 centerScreen = glm::vec2(screenResolution.Width / 2, screenResolution.Height / 2);
m_EShootVector.push_back(std::make_pair(e.shooter, centerScreen));
return true;
}
+2 -2
View File
@@ -94,7 +94,7 @@ CapturePointTest::CapturePointTest(int runTestNumber)
m_World = new World();
// Create system pipeline
m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline = new SystemPipeline(m_World,m_EventBroker);
m_SystemPipeline->AddSystem<HealthSystem>(0);
m_SystemPipeline->AddSystem<CapturePointSystem>(1);
@@ -405,7 +405,7 @@ void CapturePointTest::Tick()
double dt = 10.0;
// Iterate through systems and update world!
m_SystemPipeline->Update(m_World, dt);
m_SystemPipeline->Update(dt);
m_EventBroker->Swap();
m_EventBroker->Clear();
+2 -2
View File
@@ -48,7 +48,7 @@ GameHealthSystemTest::GameHealthSystemTest()
fp.MergeEntities(m_World);
// Create system pipeline
m_SystemPipeline = new SystemPipeline(m_EventBroker);
m_SystemPipeline = new SystemPipeline(m_World,m_EventBroker);
m_SystemPipeline->AddSystem<HealthSystem>(0);
//The Test
@@ -103,7 +103,7 @@ void GameHealthSystemTest::Tick()
m_LastTime = currentTime;
// Iterate through systems and update world!
m_SystemPipeline->Update(m_World, dt);
m_SystemPipeline->Update(dt);
m_EventBroker->Swap();
m_EventBroker->Clear();
+1 -2
View File
@@ -52,8 +52,7 @@ void RegionTestOld(Tree& tree)
template<typename Tree>
void RegionTest(Tree& tree)
{
AABB aabb;
aabb.CreateFromCenter(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS),
AABB aabb = AABB::FromOriginSize(glm::vec3(rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS, rand() % LEVEL_BOUNDS),
glm::vec3(rand() % MAXSIZE, rand() % MAXSIZE, rand() % MAXSIZE));
std::vector<AABB> outVec;
tree.ObjectsInSameRegion(aabb, outVec);