From 2d5f71e442270b416a9ec08f758a4135bea91e97 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 10 Feb 2016 16:25:47 +0100 Subject: [PATCH 01/28] Added 3 PickupSpawnSystem tests. --- src/Tests/PickupSpawnTest.cpp | 205 ++++++++++++++++++++++++++++++++++ src/Tests/PickupSpawnTest.h | 73 ++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 src/Tests/PickupSpawnTest.cpp create mode 100644 src/Tests/PickupSpawnTest.h diff --git a/src/Tests/PickupSpawnTest.cpp b/src/Tests/PickupSpawnTest.cpp new file mode 100644 index 00000000..ebddb71f --- /dev/null +++ b/src/Tests/PickupSpawnTest.cpp @@ -0,0 +1,205 @@ +#include +using boost::unit_test_framework::test_suite; +using boost::unit_test_framework::test_case; + +#include "PickupSpawnTest.h" + + +BOOST_AUTO_TEST_SUITE(PickupSpawnTestSuite) + +//dont use the same name as the classname in test cases... +BOOST_AUTO_TEST_CASE(PickupSpawnTest_HealthPickupRespawns_PlayerHealthPickupEventTriggers) +{ + PickupSpawnTest game(1); + bool success = game.Game_Loop_OneHundredTimes(); + BOOST_TEST(success); +} +BOOST_AUTO_TEST_CASE(PickupSpawnTest_APlayerAtMaxHealth_CantTakeHealthPickup) +{ + PickupSpawnTest game(2); + bool success = game.Game_Loop_OneHundredTimes(); + BOOST_TEST(success); +} +BOOST_AUTO_TEST_CASE(PickupSpawnTest_APickupCanRespawnSlowly) +{ + PickupSpawnTest game(3); + bool success = game.Game_Loop_OneHundredTimes(); + BOOST_TEST(success); +} +BOOST_AUTO_TEST_SUITE_END() + +PickupSpawnTest::PickupSpawnTest(int runTestNumber) +{ + ResourceManager::RegisterType("ConfigFile"); + ResourceManager::RegisterType("EntityFile"); + + m_Config = ResourceManager::Load("Config.ini"); + LOG_LEVEL = static_cast<_LOG_LEVEL>(m_Config->Get("Debug.LogLevel", 1)); + + m_EventBroker = new EventBroker(); + m_World = new World(); + + // Create system pipeline + m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); + m_SystemPipeline->AddSystem(0); + m_SystemPipeline->AddSystem(1); + + //must register components (Components.xsd), else you cant create entities. Easiest done by loading a test xsd file + auto file = ResourceManager::Load("Schema/Entities/HealthPickup.xml"); + EntityFilePreprocessor fpp(file); + fpp.RegisterComponents(m_World); + EntityFileParser fp(file); + //connect the healthpickup to the world + m_HealthPickupID = fp.MergeEntities(m_World); + + //create a player + m_PlayerID = m_World->CreateEntity(); + auto& player = m_World->AttachComponent(m_PlayerID, "Player"); + + m_RunTestNumber = runTestNumber; + + //further testsetups + TestSetup(m_RunTestNumber); + + //init glfw so dt works + glfwInit(); + + //listen to the 2 events that are related to PickupSpawn + EVENT_SUBSCRIBE_MEMBER(m_HP, &PickupSpawnTest::OnHealthPickup); + EVENT_SUBSCRIBE_MEMBER(m_PS, &PickupSpawnTest::OnPickupSpawned); +} + +bool PickupSpawnTest::OnHealthPickup(Events::PlayerHealthPickup& e) { + //very that the event has the correct healthgain number and playerid + if (m_RunTestNumber == 1) { + if (e.HealthAmount == 22.0 && e.Player.ID == m_PlayerID) { + testStage1Success = true; + } + } + if (m_RunTestNumber == 2) { + testStage1Success = false; + } + if (m_RunTestNumber == 3) { + if (e.HealthAmount == 50.0 && e.Player.ID == m_PlayerID) { + testStage1Success = true; + } + } + return true; +} +bool PickupSpawnTest::OnPickupSpawned(Events::PickupSpawned& e) { + //verify that the newly spawned pickup has the same variable values as the original one + if (m_RunTestNumber == 1) { + if ((double)e.Pickup["HealthPickup"]["HealthGain"] == 22.0 && (double)e.Pickup["HealthPickup"]["RespawnTimer"] == 2.0) { + testStage2Success = true; + } + } + if (m_RunTestNumber == 2) { + testStage2Success = false; + } + if (m_RunTestNumber == 3) { + testStage2Success = false; + } + return true; +} + +void PickupSpawnTest::TestSetup(int testNumber) +{ + //cant use switch here, since each case might initialize different variables + if (m_RunTestNumber == 1) { + //PickupSpawnTest_HealthPickupRespawns_PlayerHealthPickupEventTriggers + auto& healthPickupEW = EntityWrapper(m_World, m_HealthPickupID); + healthPickupEW["HealthPickup"]["RespawnTimer"] = 2.0; + healthPickupEW["HealthPickup"]["HealthGain"] = 22.0; + + //create a player + auto& health = m_World->AttachComponent(m_PlayerID, "Health"); + health["Health"] = 20.0; + health["MaxHealth"] = 100.0; + + Events::TriggerTouch eTriggerTouch; + DoTouchEvent(m_PlayerID, m_HealthPickupID); + } + if (m_RunTestNumber == 2) { + //PickupSpawnTest_APlayerAtMaxHealth_CantTakeHealthPickup + auto& healthPickupEW = EntityWrapper(m_World, m_HealthPickupID); + healthPickupEW["HealthPickup"]["RespawnTimer"] = 1.0; + healthPickupEW["HealthPickup"]["HealthGain"] = 50.0; + + //create a player at max health + auto& health = m_World->AttachComponent(m_PlayerID, "Health"); + health["Health"] = 100.0; + health["MaxHealth"] = 100.0; + + Events::TriggerTouch eTriggerTouch; + DoTouchEvent(m_PlayerID, m_HealthPickupID); + } + if (m_RunTestNumber == 3) { + //PickupSpawnTest_APickupCanRespawnSlowly + auto& healthPickupEW = EntityWrapper(m_World, m_HealthPickupID); + healthPickupEW["HealthPickup"]["RespawnTimer"] = 100.0; + healthPickupEW["HealthPickup"]["HealthGain"] = 50.0; + + //create a player + auto& health = m_World->AttachComponent(m_PlayerID, "Health"); + health["Health"] = 1.0; + health["MaxHealth"] = 100.0; + + Events::TriggerTouch eTriggerTouch; + DoTouchEvent(m_PlayerID, m_HealthPickupID); + } +} + +//generic stuff +void PickupSpawnTest::Tick() +{ + glfwPollEvents(); + + //just set dt to 1.0 since we want fast testing + double dt = 1.0; + + // Iterate through systems and update world! + m_SystemPipeline->Update(dt); + + m_EventBroker->Swap(); + m_EventBroker->Clear(); + + //verify that healthgain event has been published and pickup has respawned + if (m_RunTestNumber == 1 && testStage1Success && testStage2Success) { + m_TestSucceeded = true; + } + //verify that no healthgain event has been published and that no pickup has respawned + if (m_NumLoops > 90 && m_RunTestNumber == 2 && !testStage1Success && !testStage2Success) { + m_TestSucceeded = true; + } + //3: verify that the pickup hasnt spawned + if (m_NumLoops > 90 && m_RunTestNumber == 3 && testStage1Success && !testStage2Success) { + m_TestSucceeded = true; + } +} +bool PickupSpawnTest::Game_Loop_OneHundredTimes() { + //100 loops will be more than enough to do the test + int loops = 100; + bool success = false; + while (loops > 0) { + Tick(); + m_NumLoops++; + if (m_TestSucceeded) { + success = true; + break; + } + loops--; + } + return success; +} +PickupSpawnTest::~PickupSpawnTest() +{ + delete m_SystemPipeline; + delete m_World; + //delete m_EventBroker; +} +void PickupSpawnTest::DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject) { + Events::TriggerTouch touchEvent; + touchEvent.Entity = EntityWrapper(m_World, whoDidSomething); + touchEvent.Trigger = EntityWrapper(m_World, onWhatObject); + m_EventBroker->Publish(touchEvent); +} diff --git a/src/Tests/PickupSpawnTest.h b/src/Tests/PickupSpawnTest.h new file mode 100644 index 00000000..2869c119 --- /dev/null +++ b/src/Tests/PickupSpawnTest.h @@ -0,0 +1,73 @@ +#ifndef PickupSpawnTest_h__ +#define PickupSpawnTest_h__ + +#include "Core/ResourceManager.h" +#include "Core/ConfigFile.h" +#include "Core/EventBroker.h" +#include "Core/World.h" +#include "Input/InputProxy.h" +#include "Input/KeyboardInputHandler.h" +#include "Input/MouseInputHandler.h" +#include "Core/EKeyDown.h" +#include "Core/EntityFile.h" +#include "Core/SystemPipeline.h" + +#include "Core/EntityFilePreprocessor.h" +#include "Core/EntityFileParser.h" +#include "Core/EntityFileWriter.h" + +#include "Engine/Collision/ETrigger.h" + +//#include "Core/System.h" +//#include "Core/Transform.h" +//#include "Core/ResourceManager.h" +//#include "Core/EntityFileParser.h" +//#include "Core/EPickupSpawned.h" +//#include "Core/EPlayerHealthPickup.h" +#include "Engine/Collision/ETrigger.h" +//#include "Common.h" +//#include +#include "Collision/TriggerSystem.h" +#include "Collision/CollisionSystem.h" +#include "Core/EntityFileWriter.h" +#include "Game/Systems/HealthSystem.h" +#include "Game/Systems/PickupSpawnSystem.h" + +#include "Core/ResourceManager.h" + +class PickupSpawnTest +{ +public: + PickupSpawnTest(int runTestNumber); + ~PickupSpawnTest(); + + void Tick(); + bool m_TestSucceeded = false; + int m_NumLoops = 0; + + bool Game_Loop_OneHundredTimes(); + + void TestSetup(int testNumber); + void DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject); + +private: + double m_LastTime; + ConfigFile* m_Config = nullptr; + EventBroker* m_EventBroker; + World* m_World; + SystemPipeline* m_SystemPipeline; + EntityID m_PlayerID, m_HealthPickupID; + int m_RunTestNumber; + + EventRelay m_HP; + bool OnHealthPickup(Events::PlayerHealthPickup& e); + EventRelay m_PS; + bool OnPickupSpawned(Events::PickupSpawned& e); + + bool testStage1Success = false; + bool testStage2Success = false; + + +}; + +#endif From f7756ff60fc850c44ab93d156a14dd9763fd57d3 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 10 Feb 2016 16:51:00 +0100 Subject: [PATCH 02/28] Tiny refactoring of PickupSpawnTest. Updated and fixed HealthSystemTest. --- src/Tests/HealthSystemTest.cpp | 28 +++++++++------- src/Tests/HealthSystemTest.h | 4 ++- src/Tests/PickupSpawnTest.cpp | 59 ++++++++++++++++++---------------- src/Tests/PickupSpawnTest.h | 8 ++--- 4 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index 36608f8f..7d06bba3 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -55,19 +55,14 @@ GameHealthSystemTest::GameHealthSystemTest() //create entity which has transform,player,model,health in it. i.e. is a player EntityID playerID = m_World->CreateEntity(); ComponentWrapper player = m_World->AttachComponent(playerID, "Player"); - ComponentWrapper health = m_World->AttachComponent(playerID, "Health"); - healthsID = playerID; + ComponentWrapper& health = m_World->AttachComponent(playerID, "Health"); + health["Health"] = 100.0; + m_PlayersID = playerID; EntityID playerID2 = m_World->CreateEntity(); ComponentWrapper player2 = m_World->AttachComponent(playerID2, "Player"); ComponentWrapper health2 = m_World->AttachComponent(playerID2, "Health"); - //heal player with 40 - Events::PlayerHealthPickup e3; - e3.HealthAmount = 40.0f; - e3.Player = EntityWrapper(m_World, player.EntityID); - m_EventBroker->Publish(e3); - //damage player with 50 Events::PlayerDamage e; e.Damage = 50.0f; @@ -103,9 +98,18 @@ void GameHealthSystemTest::Tick() m_EventBroker->Swap(); m_EventBroker->Clear(); - - //if health reaches 90 then we know the test has succeeded (start with 100hp, remove 50hp, add 40hp) - double currentHealth = (double)m_World->GetComponent(healthsID, "Health")["Health"]; - if (currentHealth == 90) + + double currentHealth = (double)m_World->GetComponent(m_PlayersID, "Health")["Health"]; + //if players health reach 50 means he got damaged by 50 + if (currentHealth == 50) { + m_TestStage1Success = true; + //heal player with 40 + Events::PlayerHealthPickup e3; + e3.HealthAmount = 40.0f; + e3.Player = EntityWrapper(m_World, m_PlayersID); + m_EventBroker->Publish(e3); + } + if (m_TestStage1Success && currentHealth == 90.0f) { TestSucceeded = true; + } } diff --git a/src/Tests/HealthSystemTest.h b/src/Tests/HealthSystemTest.h index 62c5f55b..685a06dd 100644 --- a/src/Tests/HealthSystemTest.h +++ b/src/Tests/HealthSystemTest.h @@ -31,7 +31,9 @@ private: EventBroker* m_EventBroker; World* m_World; SystemPipeline* m_SystemPipeline; - int healthsID; + int m_PlayersID; + bool m_TestStage1Success = false; + }; #endif diff --git a/src/Tests/PickupSpawnTest.cpp b/src/Tests/PickupSpawnTest.cpp index ebddb71f..2de9e459 100644 --- a/src/Tests/PickupSpawnTest.cpp +++ b/src/Tests/PickupSpawnTest.cpp @@ -4,7 +4,6 @@ using boost::unit_test_framework::test_case; #include "PickupSpawnTest.h" - BOOST_AUTO_TEST_SUITE(PickupSpawnTestSuite) //dont use the same name as the classname in test cases... @@ -73,15 +72,15 @@ bool PickupSpawnTest::OnHealthPickup(Events::PlayerHealthPickup& e) { //very that the event has the correct healthgain number and playerid if (m_RunTestNumber == 1) { if (e.HealthAmount == 22.0 && e.Player.ID == m_PlayerID) { - testStage1Success = true; + m_TestStage1Success = true; } } if (m_RunTestNumber == 2) { - testStage1Success = false; + m_TestStage1Success = false; } if (m_RunTestNumber == 3) { if (e.HealthAmount == 50.0 && e.Player.ID == m_PlayerID) { - testStage1Success = true; + m_TestStage1Success = true; } } return true; @@ -90,22 +89,24 @@ bool PickupSpawnTest::OnPickupSpawned(Events::PickupSpawned& e) { //verify that the newly spawned pickup has the same variable values as the original one if (m_RunTestNumber == 1) { if ((double)e.Pickup["HealthPickup"]["HealthGain"] == 22.0 && (double)e.Pickup["HealthPickup"]["RespawnTimer"] == 2.0) { - testStage2Success = true; + m_TestStage2Success = true; } } if (m_RunTestNumber == 2) { - testStage2Success = false; + m_TestStage2Success = false; } if (m_RunTestNumber == 3) { - testStage2Success = false; + m_TestStage2Success = false; } return true; } void PickupSpawnTest::TestSetup(int testNumber) { - //cant use switch here, since each case might initialize different variables - if (m_RunTestNumber == 1) { + switch (m_RunTestNumber) + { + case 1: + { //PickupSpawnTest_HealthPickupRespawns_PlayerHealthPickupEventTriggers auto& healthPickupEW = EntityWrapper(m_World, m_HealthPickupID); healthPickupEW["HealthPickup"]["RespawnTimer"] = 2.0; @@ -115,11 +116,10 @@ void PickupSpawnTest::TestSetup(int testNumber) auto& health = m_World->AttachComponent(m_PlayerID, "Health"); health["Health"] = 20.0; health["MaxHealth"] = 100.0; - - Events::TriggerTouch eTriggerTouch; - DoTouchEvent(m_PlayerID, m_HealthPickupID); } - if (m_RunTestNumber == 2) { + break; + case 2: + { //PickupSpawnTest_APlayerAtMaxHealth_CantTakeHealthPickup auto& healthPickupEW = EntityWrapper(m_World, m_HealthPickupID); healthPickupEW["HealthPickup"]["RespawnTimer"] = 1.0; @@ -129,11 +129,10 @@ void PickupSpawnTest::TestSetup(int testNumber) auto& health = m_World->AttachComponent(m_PlayerID, "Health"); health["Health"] = 100.0; health["MaxHealth"] = 100.0; - - Events::TriggerTouch eTriggerTouch; - DoTouchEvent(m_PlayerID, m_HealthPickupID); } - if (m_RunTestNumber == 3) { + break; + case 3: + { //PickupSpawnTest_APickupCanRespawnSlowly auto& healthPickupEW = EntityWrapper(m_World, m_HealthPickupID); healthPickupEW["HealthPickup"]["RespawnTimer"] = 100.0; @@ -143,10 +142,14 @@ void PickupSpawnTest::TestSetup(int testNumber) auto& health = m_World->AttachComponent(m_PlayerID, "Health"); health["Health"] = 1.0; health["MaxHealth"] = 100.0; - - Events::TriggerTouch eTriggerTouch; - DoTouchEvent(m_PlayerID, m_HealthPickupID); } + break; + default: + break; + } + //do the triggerTouch event to get the pickupSpawnTest started + Events::TriggerTouch eTriggerTouch; + DoTouchEvent(m_PlayerID, m_HealthPickupID); } //generic stuff @@ -164,16 +167,16 @@ void PickupSpawnTest::Tick() m_EventBroker->Clear(); //verify that healthgain event has been published and pickup has respawned - if (m_RunTestNumber == 1 && testStage1Success && testStage2Success) { - m_TestSucceeded = true; + if (m_RunTestNumber == 1 && m_TestStage1Success && m_TestStage2Success) { + TestSucceeded = true; } //verify that no healthgain event has been published and that no pickup has respawned - if (m_NumLoops > 90 && m_RunTestNumber == 2 && !testStage1Success && !testStage2Success) { - m_TestSucceeded = true; + if (NumLoops > 90 && m_RunTestNumber == 2 && !m_TestStage1Success && !m_TestStage2Success) { + TestSucceeded = true; } //3: verify that the pickup hasnt spawned - if (m_NumLoops > 90 && m_RunTestNumber == 3 && testStage1Success && !testStage2Success) { - m_TestSucceeded = true; + if (NumLoops > 90 && m_RunTestNumber == 3 && m_TestStage1Success && !m_TestStage2Success) { + TestSucceeded = true; } } bool PickupSpawnTest::Game_Loop_OneHundredTimes() { @@ -182,8 +185,8 @@ bool PickupSpawnTest::Game_Loop_OneHundredTimes() { bool success = false; while (loops > 0) { Tick(); - m_NumLoops++; - if (m_TestSucceeded) { + NumLoops++; + if (TestSucceeded) { success = true; break; } diff --git a/src/Tests/PickupSpawnTest.h b/src/Tests/PickupSpawnTest.h index 2869c119..fdb18b12 100644 --- a/src/Tests/PickupSpawnTest.h +++ b/src/Tests/PickupSpawnTest.h @@ -42,8 +42,8 @@ public: ~PickupSpawnTest(); void Tick(); - bool m_TestSucceeded = false; - int m_NumLoops = 0; + bool TestSucceeded = false; + int NumLoops = 0; bool Game_Loop_OneHundredTimes(); @@ -64,8 +64,8 @@ private: EventRelay m_PS; bool OnPickupSpawned(Events::PickupSpawned& e); - bool testStage1Success = false; - bool testStage2Success = false; + bool m_TestStage1Success = false; + bool m_TestStage2Success = false; }; From 02cd822cf198295c01835ef7a1a445c469272e00 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 10 Feb 2016 17:04:05 +0100 Subject: [PATCH 03/28] Tiny test refactoring --- src/Tests/HealthSystemTest.cpp | 2 +- src/Tests/PickupSpawnTest.cpp | 46 +++++++++++++++++++--------------- src/Tests/PickupSpawnTest.h | 5 ++-- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index 7d06bba3..fa88d815 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -101,7 +101,7 @@ void GameHealthSystemTest::Tick() double currentHealth = (double)m_World->GetComponent(m_PlayersID, "Health")["Health"]; //if players health reach 50 means he got damaged by 50 - if (currentHealth == 50) { + if (currentHealth == 50.0) { m_TestStage1Success = true; //heal player with 40 Events::PlayerHealthPickup e3; diff --git a/src/Tests/PickupSpawnTest.cpp b/src/Tests/PickupSpawnTest.cpp index 2de9e459..7cbed85f 100644 --- a/src/Tests/PickupSpawnTest.cpp +++ b/src/Tests/PickupSpawnTest.cpp @@ -69,34 +69,41 @@ PickupSpawnTest::PickupSpawnTest(int runTestNumber) } bool PickupSpawnTest::OnHealthPickup(Events::PlayerHealthPickup& e) { - //very that the event has the correct healthgain number and playerid - if (m_RunTestNumber == 1) { + switch (m_RunTestNumber) + { + case 1: + //verify that the event has the correct healthgain number and playerid if (e.HealthAmount == 22.0 && e.Player.ID == m_PlayerID) { m_TestStage1Success = true; } - } - if (m_RunTestNumber == 2) { + break; + case 2: m_TestStage1Success = false; - } - if (m_RunTestNumber == 3) { + break; + case 3: + //verify that the event has the correct healthgain number and playerid if (e.HealthAmount == 50.0 && e.Player.ID == m_PlayerID) { m_TestStage1Success = true; } + break; } return true; } bool PickupSpawnTest::OnPickupSpawned(Events::PickupSpawned& e) { - //verify that the newly spawned pickup has the same variable values as the original one - if (m_RunTestNumber == 1) { + switch (m_RunTestNumber) + { + case 1: + //verify that the newly spawned pickup has the same variable values as the original one if ((double)e.Pickup["HealthPickup"]["HealthGain"] == 22.0 && (double)e.Pickup["HealthPickup"]["RespawnTimer"] == 2.0) { m_TestStage2Success = true; } - } - if (m_RunTestNumber == 2) { + break; + case 2: m_TestStage2Success = false; - } - if (m_RunTestNumber == 3) { + break; + case 3: m_TestStage2Success = false; + break; } return true; } @@ -168,15 +175,15 @@ void PickupSpawnTest::Tick() //verify that healthgain event has been published and pickup has respawned if (m_RunTestNumber == 1 && m_TestStage1Success && m_TestStage2Success) { - TestSucceeded = true; + m_TestSucceeded = true; } //verify that no healthgain event has been published and that no pickup has respawned - if (NumLoops > 90 && m_RunTestNumber == 2 && !m_TestStage1Success && !m_TestStage2Success) { - TestSucceeded = true; + if (m_NumLoops > 90 && m_RunTestNumber == 2 && !m_TestStage1Success && !m_TestStage2Success) { + m_TestSucceeded = true; } //3: verify that the pickup hasnt spawned - if (NumLoops > 90 && m_RunTestNumber == 3 && m_TestStage1Success && !m_TestStage2Success) { - TestSucceeded = true; + if (m_NumLoops > 90 && m_RunTestNumber == 3 && m_TestStage1Success && !m_TestStage2Success) { + m_TestSucceeded = true; } } bool PickupSpawnTest::Game_Loop_OneHundredTimes() { @@ -185,8 +192,8 @@ bool PickupSpawnTest::Game_Loop_OneHundredTimes() { bool success = false; while (loops > 0) { Tick(); - NumLoops++; - if (TestSucceeded) { + m_NumLoops++; + if (m_TestSucceeded) { success = true; break; } @@ -198,7 +205,6 @@ PickupSpawnTest::~PickupSpawnTest() { delete m_SystemPipeline; delete m_World; - //delete m_EventBroker; } void PickupSpawnTest::DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject) { Events::TriggerTouch touchEvent; diff --git a/src/Tests/PickupSpawnTest.h b/src/Tests/PickupSpawnTest.h index fdb18b12..b9d5483a 100644 --- a/src/Tests/PickupSpawnTest.h +++ b/src/Tests/PickupSpawnTest.h @@ -42,11 +42,8 @@ public: ~PickupSpawnTest(); void Tick(); - bool TestSucceeded = false; - int NumLoops = 0; bool Game_Loop_OneHundredTimes(); - void TestSetup(int testNumber); void DoTouchEvent(EntityID whoDidSomething, EntityID onWhatObject); @@ -67,6 +64,8 @@ private: bool m_TestStage1Success = false; bool m_TestStage2Success = false; + bool m_TestSucceeded = false; + int m_NumLoops = 0; }; From 4214bf10a102be4f276637abcf75f45798e32629 Mon Sep 17 00:00:00 2001 From: Tleety Date: Tue, 16 Feb 2016 14:05:57 +0100 Subject: [PATCH 04/28] Components for menu/buttons --- resources/Schema/Components.xsd | 3 +++ resources/Schema/Components/Button.xml | 3 +++ resources/Schema/Components/Button.xsd | 9 +++++++++ resources/Schema/Components/Menu.xml | 3 +++ resources/Schema/Components/Menu.xsd | 9 +++++++++ resources/Schema/Components/Page.xml | 4 ++++ resources/Schema/Components/Page.xsd | 14 ++++++++++++++ resources/Schema/Types/Entity.xsd | 3 +++ 8 files changed, 48 insertions(+) create mode 100644 resources/Schema/Components/Button.xml create mode 100644 resources/Schema/Components/Button.xsd create mode 100644 resources/Schema/Components/Menu.xml create mode 100644 resources/Schema/Components/Menu.xsd create mode 100644 resources/Schema/Components/Page.xml create mode 100644 resources/Schema/Components/Page.xsd diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 61e49ae3..74423f56 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -41,5 +41,8 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Button.xml b/resources/Schema/Components/Button.xml new file mode 100644 index 00000000..cbfd80d4 --- /dev/null +++ b/resources/Schema/Components/Button.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/resources/Schema/Components/Button.xsd b/resources/Schema/Components/Button.xsd new file mode 100644 index 00000000..07f2eafc --- /dev/null +++ b/resources/Schema/Components/Button.xsd @@ -0,0 +1,9 @@ + + + + + + Makes sprites klickable. + + + \ No newline at end of file diff --git a/resources/Schema/Components/Menu.xml b/resources/Schema/Components/Menu.xml new file mode 100644 index 00000000..f17427b8 --- /dev/null +++ b/resources/Schema/Components/Menu.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/resources/Schema/Components/Menu.xsd b/resources/Schema/Components/Menu.xsd new file mode 100644 index 00000000..18ea8565 --- /dev/null +++ b/resources/Schema/Components/Menu.xsd @@ -0,0 +1,9 @@ + + + + + + Attach this to the center point of a menu that uses several pages. + + + \ No newline at end of file diff --git a/resources/Schema/Components/Page.xml b/resources/Schema/Components/Page.xml new file mode 100644 index 00000000..db7b9cc2 --- /dev/null +++ b/resources/Schema/Components/Page.xml @@ -0,0 +1,4 @@ + + + 0 + \ No newline at end of file diff --git a/resources/Schema/Components/Page.xsd b/resources/Schema/Components/Page.xsd new file mode 100644 index 00000000..777124a2 --- /dev/null +++ b/resources/Schema/Components/Page.xsd @@ -0,0 +1,14 @@ + + + + + + Use this on a child to a Menu entity and make sure that ID is not the same as other pages. + + + + + + + + \ No newline at end of file diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 9ea264d1..a9c5f641 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -47,6 +47,9 @@ + + + From 6bc713129016cae091acee7dd7e0fcd9a60fec49 Mon Sep 17 00:00:00 2001 From: Tleety Date: Tue, 16 Feb 2016 14:57:21 +0100 Subject: [PATCH 05/28] Glow Intencity can now be changed in the model component. --- include/Engine/Rendering/ModelJob.h | 3 ++- resources/Schema/Components/Model.xml | 1 + resources/Schema/Components/Model.xsd | 3 +++ resources/Shaders/ForwardPlus.frag.glsl | 3 ++- src/Engine/Rendering/DrawFinalPass.cpp | 7 +++++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index ba801f60..ccd0e093 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -108,6 +108,7 @@ struct ModelJob : RenderJob EndIndex = matGroup->EndIndex; Matrix = matrix; Color = modelComponent["Color"]; + GlowIntencity = ((double)modelComponent["GlowIntensity"]); Entity = modelComponent.EntityID; glm::vec3 abspos = Transform::AbsolutePosition(world, modelComponent.EntityID); glm::vec3 worldpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1)); @@ -170,7 +171,7 @@ struct ModelJob : RenderJob ::Skeleton::AnimationOffset AnimationOffset; - + float GlowIntencity = 8.0; glm::vec4 DiffuseColor; glm::vec4 SpecularColor; glm::vec4 IncandescenceColor; diff --git a/resources/Schema/Components/Model.xml b/resources/Schema/Components/Model.xml index 4b77dacb..f81c8210 100644 --- a/resources/Schema/Components/Model.xml +++ b/resources/Schema/Components/Model.xml @@ -8,4 +8,5 @@ true true true + 3.0 \ No newline at end of file diff --git a/resources/Schema/Components/Model.xsd b/resources/Schema/Components/Model.xsd index 9c0cd519..31203ff6 100644 --- a/resources/Schema/Components/Model.xsd +++ b/resources/Schema/Components/Model.xsd @@ -33,6 +33,9 @@ Whether the model should use the Glowmap or not + + Intensity of the glow map + diff --git a/resources/Shaders/ForwardPlus.frag.glsl b/resources/Shaders/ForwardPlus.frag.glsl index 471ee20b..d757ff36 100644 --- a/resources/Shaders/ForwardPlus.frag.glsl +++ b/resources/Shaders/ForwardPlus.frag.glsl @@ -9,6 +9,7 @@ uniform vec2 ScreenDimensions; uniform vec4 FillColor; uniform vec4 AmbientColor; uniform float FillPercentage; +uniform float GlowIntensity = 10; uniform vec2 DiffuseUVRepeat; uniform vec2 NormalUVRepeat; @@ -166,7 +167,7 @@ void main() color_result += FillColor; } sceneColor = vec4(color_result.xyz, clamp(color_result.a, 0, 1)); - color_result += glowTexel*3; + color_result += glowTexel*GlowIntensity; bloomColor = vec4(clamp(color_result.xyz - 1.0, 0, 100), 1.0); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 11db71f0..c98fb1f5 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -738,6 +738,8 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrFillPercentage); GLERROR("Bind 19 uniform"); glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor)); + GLERROR("Bind 20 uniform"); + glUniform1f(glGetUniformLocation(shaderHandle, "GlowIntensity"), job->GlowIntencity); GLERROR("END"); } @@ -773,6 +775,11 @@ void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptrGlowIntencity); + GLERROR("END"); } From 8f84a5ddd673ba8fcd5fb94f20872aa8bbd7c24e Mon Sep 17 00:00:00 2001 From: Tleety Date: Tue, 16 Feb 2016 16:28:19 +0100 Subject: [PATCH 06/28] Buttons are now clickable --- include/Engine/Rendering/PickingPass.h | 2 +- include/Engine/Rendering/SpriteJob.h | 4 +- resources/Schema/Entities/Button.xml | 32 ++ .../Schema/Entities/QualityAssurance.xml | 373 ++++++++++++++++-- resources/Schema/Entities/TestMenu.xml | 299 ++++++++++++++ src/Engine/Rendering/DrawFinalPass.cpp | 3 - src/Engine/Rendering/PickingPass.cpp | 48 ++- 7 files changed, 722 insertions(+), 39 deletions(-) create mode 100644 resources/Schema/Entities/Button.xml create mode 100644 resources/Schema/Entities/TestMenu.xml diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h index 2ce2e78d..d7a340f1 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -40,7 +40,7 @@ private: const IRenderer* m_Renderer; ShaderProgram* m_PickingProgram; - ShaderProgram* m_PickingSkinnedProgram; + ShaderProgram* m_PickingSkinnedProgram; Camera* m_Camera; struct PickingInfo diff --git a/include/Engine/Rendering/SpriteJob.h b/include/Engine/Rendering/SpriteJob.h index 3bb43a1c..4fe19dca 100644 --- a/include/Engine/Rendering/SpriteJob.h +++ b/include/Engine/Rendering/SpriteJob.h @@ -40,7 +40,8 @@ struct SpriteJob : RenderJob Depth = viewpos.z; } World = world; - + Pickable = world->HasComponent(cSprite.EntityID, "Button"); + FillColor = fillColor; FillPercentage = fillPercentage; }; @@ -60,6 +61,7 @@ struct SpriteJob : RenderJob unsigned int StartIndex = 0; unsigned int EndIndex = 0; World* World; + bool Pickable; glm::vec4 FillColor = glm::vec4(0); float FillPercentage = 0.0; diff --git a/resources/Schema/Entities/Button.xml b/resources/Schema/Entities/Button.xml new file mode 100644 index 00000000..21f64334 --- /dev/null +++ b/resources/Schema/Entities/Button.xml @@ -0,0 +1,32 @@ + + + + + + + Textures/Core/White.png + + + + + + + + + + + + Play + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml index 40951468..30fb915b 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -40,7 +40,7 @@ - + @@ -105,7 +105,7 @@ - + @@ -180,7 +180,7 @@ - + @@ -225,7 +225,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -321,7 +321,7 @@ - + @@ -671,7 +671,7 @@ - + @@ -718,7 +718,7 @@ - + @@ -778,7 +778,7 @@ - + @@ -825,7 +825,7 @@ - + @@ -871,7 +871,7 @@ - + @@ -918,7 +918,7 @@ - + @@ -965,7 +965,7 @@ - + @@ -1027,7 +1027,7 @@ Models/Core/UnitCube.mesh - + true @@ -1077,7 +1077,7 @@ Models/Core/UnitCube.mesh - + true @@ -1167,7 +1167,7 @@ Models/Core/UnitCube.mesh - + true @@ -1217,7 +1217,7 @@ Models/Core/UnitCube.mesh - + true @@ -1379,7 +1379,7 @@ - + @@ -1388,7 +1388,7 @@ true - 0.75205058136495551 + 2.5166344949826396 3.7999999523162842 true @@ -1435,7 +1435,7 @@ - + @@ -1444,7 +1444,7 @@ - 1.2019563319790627 + 0.35000808291962926 Models/Characters/Assault/AssaultTPose.mesh @@ -1487,7 +1487,7 @@ - + @@ -1498,7 +1498,7 @@ true - 0.68540211563899389 + 0.35000808291962926 true @@ -1543,7 +1543,7 @@ - + @@ -1553,7 +1553,7 @@ true - 0.95150063648635763 + 9.4833086749886775 10 3 @@ -1601,7 +1601,7 @@ - + @@ -1611,7 +1611,7 @@ true - 1.3515288978624223 + 4.0667207575903603 true 5 true @@ -1678,10 +1678,10 @@ + Models/Core/UnitCube.mesh - @@ -1792,7 +1792,7 @@ true - 1.3682019578975679 + 2.5166344949826396 3.7999999523162842 true @@ -1836,12 +1836,12 @@ + Models/AssaultAnimated.mesh - @@ -2095,7 +2095,7 @@ Textures/Core/UnitHexagon.png - + @@ -2107,7 +2107,7 @@ 1 - + Textures/Core/UnitHexagon_Rotated.png @@ -2145,6 +2145,315 @@ + + + + + + + + + + + + Models/Widgets/Camera.mesh + false + + + + + + + + + + + + + + + + + + + + + Textures/Core/ErrorTexture.png + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Play + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Host + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Connect + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Settings + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Quit + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + Textures/Core/ErrorTexture.png + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Resolution + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Option2 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Butts + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + + Menu test area + Fonts/DroidSans.ttf,64 + + + + + + + + + + diff --git a/resources/Schema/Entities/TestMenu.xml b/resources/Schema/Entities/TestMenu.xml new file mode 100644 index 00000000..73678601 --- /dev/null +++ b/resources/Schema/Entities/TestMenu.xml @@ -0,0 +1,299 @@ + + + + + + + + + + + + + + + Models/Widgets/Camera.mesh + + + + + + + + + + + + + + + + + + + + + Textures/Core/ErrorTexture.png + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Play + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Host + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Connect + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Settings + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Quit + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + 1 + + + + + + + + + + Textures/Core/ErrorTexture.png + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Resolution + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Option2 + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + Textures/Core/White.png + + + + + + + + + + + Butts + Fonts/DroidSans.ttf,64 + + + + + + + + + + + + + + + + + + + + diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index c98fb1f5..fd95ecee 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -689,9 +689,6 @@ void DrawFinalPass::DrawSprites(std::list>&jobs, Rend glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex*sizeof(unsigned int))); } } - - - // m_SpriteProgram->Unbind(); } diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index ecd0a4b8..a979eb0e 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -234,6 +234,52 @@ void PickingPass::Draw(RenderScene& scene) } } + for (auto& job : scene.Jobs.SpriteJob) { + auto spriteJob = std::dynamic_pointer_cast(job); + if (!spriteJob->Pickable) { + continue; + } + RenderState jobState; + + if (spriteJob) { + if (spriteJob->Depth == 0) { + jobState.Disable(GL_DEPTH_TEST); + } + int pickColor[2] = { m_ColorCounter[0], m_ColorCounter[1] }; + + PickingInfo pickInfo; + pickInfo.Entity = spriteJob->Entity; + pickInfo.World = spriteJob->World; + pickInfo.Camera = scene.Camera; + + auto color = m_EntityColors.find(std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)); + if (color != m_EntityColors.end()) { + pickColor[0] = color->second[0]; + pickColor[1] = color->second[1]; + } else { + m_EntityColors[std::make_tuple(pickInfo.Entity, pickInfo.World, pickInfo.Camera)] = glm::ivec2(pickColor[0], pickColor[1]); + if (m_ColorCounter[0] > 255) { + m_ColorCounter[0] = 0; + m_ColorCounter[1] += 1; + } else { + m_ColorCounter[0] += 1; + } + } + + m_PickingColorsToEntity[glm::ivec2(pickColor[0], pickColor[1])] = pickInfo; + + m_PickingProgram->Bind(); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(spriteJob->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())); + glUniform2fv(glGetUniformLocation(shaderHandle, "PickingColor"), 1, glm::value_ptr(glm::vec2(pickColor[0], pickColor[1]))); + + glBindVertexArray(spriteJob->Model->VAO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, spriteJob->Model->ElementBuffer); + glDrawElements(GL_TRIANGLES, spriteJob->EndIndex - spriteJob->StartIndex + 1, GL_UNSIGNED_INT, (void*)(spriteJob->StartIndex * sizeof(unsigned int))); + } + } + /* for (auto &job : scene.Jobs.TransparentShieldedObjects) { auto modelJob = std::dynamic_pointer_cast(job); @@ -306,8 +352,6 @@ void PickingPass::Draw(RenderScene& scene) delete state; } - - void PickingPass::ClearPicking() { m_PickingColorsToEntity.clear(); From 4b8f1d95a355d54c570e70153d8c341542062c4b Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 16 Feb 2016 16:57:46 +0100 Subject: [PATCH 07/28] Added static class PerformanceTimer. Changed CMakeLists for engine to include boost timer. Added F2,F3 functions in editor. Added some timing, more to be added --- include/Engine/Core/PerformanceTimer.h | 36 +++++++++++ include/Engine/Core/SystemPipeline.h | 13 +++- include/Game/Game.h | 3 + resources/DefaultInput.ini | 4 +- src/Engine/CMakeLists.txt | 2 +- src/Engine/Core/PerformanceTimer.cpp | 87 ++++++++++++++++++++++++++ src/Engine/Editor/EditorSystem.cpp | 6 ++ src/Game/Game.cpp | 8 +++ 8 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 include/Engine/Core/PerformanceTimer.h create mode 100644 src/Engine/Core/PerformanceTimer.cpp diff --git a/include/Engine/Core/PerformanceTimer.h b/include/Engine/Core/PerformanceTimer.h new file mode 100644 index 00000000..6fb5c4a5 --- /dev/null +++ b/include/Engine/Core/PerformanceTimer.h @@ -0,0 +1,36 @@ +#ifndef PerformanceTimer_h__ +#define PerformanceTimer_h__ + +#include +#include +#include "../Common.h" + +#include +using boost::timer::cpu_timer; + +class PerformanceTimer +{ +public: + static void StartTimer(std::string nameOfTimer); + static void StartTimerAndStopPrevious(std::string nameOfTimer); + static void StopTimer(std::string nameOfTimer); + static void SetFrameNumber(int frameNumber); + + static void ResetAllTimers(); + static void CreateExcelData(); + + //set timer/start + //get performance excel nånting + +private: + static std::map timers; + static double m_TimeElapsed; + static cpu_timer m_Timer; + static std::string currentTimerRunning; + static bool active; + //static map + + +}; + +#endif diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index 5f7aee0b..c4801fde 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -6,6 +6,7 @@ #include "System.h" #include "World.h" #include "EPause.h" +#include "PerformanceTimer.h" class SystemPipeline { @@ -72,7 +73,10 @@ public: // Update for (auto& system : group.ImpureSystems) { + auto className = (std::string)typeid(*system).name(); + PerformanceTimer::StartTimer(className); system->Update(dt); + PerformanceTimer::StopTimer(className); } for (auto& pair : group.PureSystems) { const std::string& componentName = pair.first; @@ -83,7 +87,10 @@ public: } for (auto& component : *pool) { for (auto& system : systems) { + auto className = (std::string)typeid(*system).name(); + PerformanceTimer::StartTimer(className); system->UpdateComponent(EntityWrapper(m_World, component.EntityID), component, dt); + PerformanceTimer::StopTimer(className); } } } @@ -106,9 +113,9 @@ private: std::vector m_OrderedSystemGroups; EventRelay m_EPause; - bool OnPause(const Events::Pause& e) { - if (e.World == m_World) { - m_Paused = true; + bool OnPause(const Events::Pause& e) { + if (e.World == m_World) { + m_Paused = true; } return true; } diff --git a/include/Game/Game.h b/include/Game/Game.h index baf15656..5a53c15c 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -35,6 +35,9 @@ #include "Sound/SoundManager.h" #include "Systems/SoundSystem.h" +//Performance +#include "Core/PerformanceTimer.h" + class Game { public: diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index d5489c3a..776cbecd 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -25,4 +25,6 @@ C=ConnectToServer N=SwitchToServer M=SwitchToClient P=SwitchToPlayer -K=TakeDamage,1500 \ No newline at end of file +K=TakeDamage,1500 +F2=PerformanceTimingResetAllTimers +F3=PerformanceTimingCreateExcelData \ No newline at end of file diff --git a/src/Engine/CMakeLists.txt b/src/Engine/CMakeLists.txt index 19763310..e74214cf 100644 --- a/src/Engine/CMakeLists.txt +++ b/src/Engine/CMakeLists.txt @@ -3,7 +3,7 @@ project(TacticalZ-Engine) find_package(OpenGL REQUIRED) find_package(GLEW REQUIRED) find_package(GLFW REQUIRED) -find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono program_options) +find_package(Boost REQUIRED COMPONENTS system filesystem thread chrono timer program_options) find_package(assimp REQUIRED) find_package(ZLIB REQUIRED) find_package(PNG REQUIRED) diff --git a/src/Engine/Core/PerformanceTimer.cpp b/src/Engine/Core/PerformanceTimer.cpp new file mode 100644 index 00000000..a7a437c2 --- /dev/null +++ b/src/Engine/Core/PerformanceTimer.cpp @@ -0,0 +1,87 @@ +#include "Core/PerformanceTimer.h" +#include +#include +#include +#include + +cpu_timer PerformanceTimer::m_Timer; +double PerformanceTimer::m_TimeElapsed; +std::map PerformanceTimer::timers; +std::string PerformanceTimer::currentTimerRunning = ""; + +void PerformanceTimer::StartTimer(std::string nameOfTimer) +{ + timers[nameOfTimer].stop(); + timers[nameOfTimer].start(); + currentTimerRunning = nameOfTimer; +} + +void PerformanceTimer::StartTimerAndStopPrevious(std::string nameOfTimer) +{ + //stop the current timer and start some other - useful to not have to stop timers all the time + if (currentTimerRunning != "") { + timers[currentTimerRunning].stop(); + } + timers[nameOfTimer].stop(); + timers[nameOfTimer].start(); + currentTimerRunning = nameOfTimer; +} + + + +void PerformanceTimer::StopTimer(std::string nameOfTimer) +{ + timers[nameOfTimer].stop(); + currentTimerRunning = nameOfTimer; +} + + + +void PerformanceTimer::SetFrameNumber(int frameNumber) +{ +} + +void PerformanceTimer::ResetAllTimers() +{ + //stop all timers + for (auto aTimer : timers) + { + aTimer.second.stop(); + } + currentTimerRunning = ""; + timers.clear(); +} + +void PerformanceTimer::CreateExcelData() +{ + //wall = http://theboostcpplibraries.com/boost.timer + //http://www.boost.org/doc/libs/1_48_0/libs/timer/doc/cpu_timers.html + + //get path,time + char Dump_Path[MAX_PATH]; + GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); //path of current process + std::time_t t = std::time(NULL); + char tStr[16]; + std::strftime(tStr, 32, " %a %H-%M-%S", std::localtime(&t)); + std::string time(tStr); + std::string path(Dump_Path); + path = path.substr(0, path.length() - 4); + path += time + ".xls"; + std::ofstream someFileStream; + someFileStream.open(path, std::ofstream::out); + someFileStream << "classname" << ',' << "walltime" << ',' << "userTime" << ',' << "systemTime" << '\n'; + for (auto aTimer : timers) + { + //remove the "class" name in front of the string + auto className = aTimer.first; + if (className.find("class ") != std::string::npos) { + className.replace(0, 6, ""); + } + auto wallTime = (double)aTimer.second.elapsed().wall*1e-3; + auto userTime = (double)aTimer.second.elapsed().user*1e-3; + auto systemTime = (double)aTimer.second.elapsed().system*1e-3; + + someFileStream << className << "," << wallTime << ',' << userTime << ',' << systemTime << '\n'; + } + someFileStream.close(); +} diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 4899519d..eedc7c22 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -223,6 +223,12 @@ bool EditorSystem::OnInputCommand(const Events::InputCommand& e) Enable(); } } + if (e.Command == "PerformanceTimingResetAllTimers" && e.Value > 0) { + PerformanceTimer::ResetAllTimers(); + } + if (e.Command == "PerformanceTimingCreateExcelData" && e.Value > 0) { + PerformanceTimer::CreateExcelData(); + } return true; } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 49b1a963..d2535518 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -187,16 +187,20 @@ void Game::Tick() // Handle input in a weird looking but responsive way m_EventBroker->Process(); m_EventBroker->Swap(); + PerformanceTimer::StartTimer("InputManager"); m_InputManager->Update(dt); m_EventBroker->Swap(); + PerformanceTimer::StartTimerAndStopPrevious("InputProxy"); m_InputProxy->Update(dt); m_EventBroker->Swap(); m_InputProxy->Process(); m_EventBroker->Swap(); + PerformanceTimer::StartTimerAndStopPrevious("SoundManager"); m_SoundManager->Update(dt); // Update network + PerformanceTimer::StartTimerAndStopPrevious("Network"); m_EventBroker->Process(); if (m_NetworkClient != nullptr) { m_NetworkClient->Update(); @@ -207,10 +211,14 @@ void Game::Tick() //m_SoundManager->Update(dt); // Iterate through systems and update world! + PerformanceTimer::StartTimerAndStopPrevious("SystemPipeline"); m_EventBroker->Process(); m_SystemPipeline->Update(dt); + PerformanceTimer::StartTimerAndStopPrevious("RendererUpdate"); m_Renderer->Update(dt); + PerformanceTimer::StartTimerAndStopPrevious("RendererDraw"); m_Renderer->Draw(*m_RenderFrame); + PerformanceTimer::StopTimer("RendererDraw"); m_RenderFrame->Clear(); m_EventBroker->Swap(); m_EventBroker->Clear(); From 42b49f9dba92e054a246c7c3d56814d82f4129d5 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 16 Feb 2016 17:51:39 +0100 Subject: [PATCH 08/28] Added more timers to Rendering. --- include/Engine/Rendering/Renderer.h | 1 + resources/Schema/Entities/GameMap.xml | 8 +++++--- src/Engine/Rendering/Renderer.cpp | 19 ++++++++++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 04754514..936b0359 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -23,6 +23,7 @@ #include "imgui/imgui.h" #include "TextPass.h" #include "Util/CommonFunctions.h" +#include "Core/PerformanceTimer.h" class Renderer : public IRenderer { diff --git a/resources/Schema/Entities/GameMap.xml b/resources/Schema/Entities/GameMap.xml index 84a1e363..c3a16361 100644 --- a/resources/Schema/Entities/GameMap.xml +++ b/resources/Schema/Entities/GameMap.xml @@ -144,7 +144,7 @@ - + @@ -206,14 +206,16 @@ - + - + + + diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index be84160c..85687bf5 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -99,34 +99,48 @@ void Renderer::Draw(RenderFrame& frame) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear other buffers + PerformanceTimer::StartTimer("Renderer-ClearBuffers"); m_PickingPass->ClearPicking(); m_DrawFinalPass->ClearBuffer(); m_DrawBloomPass->ClearBuffer(); + PerformanceTimer::StopTimer("Renderer-ClearBuffers"); for (auto scene : frame.RenderScenes){ + PerformanceTimer::StartTimer("Renderer-Depth"); SortRenderJobsByDepth(*scene); GLERROR("SortByDepth"); + PerformanceTimer::StartTimerAndStopPrevious("Renderer-Drawing PickingPass"); m_PickingPass->Draw(*scene); GLERROR("Drawing pickingpass"); + PerformanceTimer::StartTimerAndStopPrevious("Renderer-Generate Frustrums"); m_LightCullingPass->GenerateNewFrustum(*scene); GLERROR("Generate frustums"); + PerformanceTimer::StartTimerAndStopPrevious("Renderer-Filling Light List"); m_LightCullingPass->FillLightList(*scene); GLERROR("Filling light list"); + PerformanceTimer::StartTimerAndStopPrevious("Renderer-Light Culling"); m_LightCullingPass->CullLights(*scene); GLERROR("LightCulling"); + PerformanceTimer::StartTimerAndStopPrevious("Renderer-Draw Geometry+Light"); m_DrawFinalPass->Draw(*scene); GLERROR("Draw Geometry+Light"); //m_DrawScenePass->Draw(*scene); + PerformanceTimer::StartTimerAndStopPrevious("Renderer-Draw Text"); m_TextPass->Draw(*scene, *m_DrawFinalPass->FinalPassFrameBuffer()); GLERROR("Draw Text"); - + PerformanceTimer::StopTimer("Renderer-Draw Text"); } + PerformanceTimer::StartTimer("Renderer-Draw Bloom"); m_DrawBloomPass->Draw(m_DrawFinalPass->BloomTexture()); + PerformanceTimer::StopTimer("Renderer-Draw Bloom"); if (m_DebugTextureToDraw == 0) { + PerformanceTimer::StartTimer("Renderer-Color Correction Pass"); m_DrawColorCorrectionPass->Draw(m_DrawFinalPass->SceneTexture(), m_DrawBloomPass->GaussianTexture(), m_DrawFinalPass->SceneTextureLowRes(), m_DrawFinalPass->BloomTextureLowRes(), frame.Gamma, frame.Exposure); + PerformanceTimer::StopTimer("Renderer-Color Correction Pass"); } + PerformanceTimer::StartTimer("Renderer-Misc Debug Draws"); if (m_DebugTextureToDraw == 1) { m_DrawScreenQuadPass->Draw(m_DrawFinalPass->SceneTexture()); } @@ -145,10 +159,13 @@ void Renderer::Draw(RenderFrame& frame) if (m_DebugTextureToDraw == 6) { m_DrawScreenQuadPass->Draw(m_PickingPass->PickingTexture()); } + PerformanceTimer::StopTimer("Renderer-Misc Debug Draws"); + PerformanceTimer::StartTimer("Renderer-ImGuiRenderPass"); m_ImGuiRenderPass->Draw(); GLERROR("Imgui draw"); glfwSwapBuffers(m_Window); + PerformanceTimer::StopTimer("Renderer-ImGuiRenderPass"); } PickData Renderer::Pick(glm::vec2 screenCoord) From b2a437731ec8e5a85029b8f3132717bd0162f110 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Tue, 16 Feb 2016 17:58:27 +0100 Subject: [PATCH 09/28] Small cleanup in the code --- include/Engine/Core/PerformanceTimer.h | 7 ------- src/Engine/Core/PerformanceTimer.cpp | 9 ++------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/include/Engine/Core/PerformanceTimer.h b/include/Engine/Core/PerformanceTimer.h index 6fb5c4a5..9f2c3d66 100644 --- a/include/Engine/Core/PerformanceTimer.h +++ b/include/Engine/Core/PerformanceTimer.h @@ -19,18 +19,11 @@ public: static void ResetAllTimers(); static void CreateExcelData(); - //set timer/start - //get performance excel nånting - private: static std::map timers; static double m_TimeElapsed; static cpu_timer m_Timer; static std::string currentTimerRunning; - static bool active; - //static map - - }; #endif diff --git a/src/Engine/Core/PerformanceTimer.cpp b/src/Engine/Core/PerformanceTimer.cpp index a7a437c2..05ac221a 100644 --- a/src/Engine/Core/PerformanceTimer.cpp +++ b/src/Engine/Core/PerformanceTimer.cpp @@ -27,16 +27,12 @@ void PerformanceTimer::StartTimerAndStopPrevious(std::string nameOfTimer) currentTimerRunning = nameOfTimer; } - - void PerformanceTimer::StopTimer(std::string nameOfTimer) { timers[nameOfTimer].stop(); currentTimerRunning = nameOfTimer; } - - void PerformanceTimer::SetFrameNumber(int frameNumber) { } @@ -54,9 +50,6 @@ void PerformanceTimer::ResetAllTimers() void PerformanceTimer::CreateExcelData() { - //wall = http://theboostcpplibraries.com/boost.timer - //http://www.boost.org/doc/libs/1_48_0/libs/timer/doc/cpu_timers.html - //get path,time char Dump_Path[MAX_PATH]; GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); //path of current process @@ -70,6 +63,8 @@ void PerformanceTimer::CreateExcelData() std::ofstream someFileStream; someFileStream.open(path, std::ofstream::out); someFileStream << "classname" << ',' << "walltime" << ',' << "userTime" << ',' << "systemTime" << '\n'; + + //write all timers to file for (auto aTimer : timers) { //remove the "class" name in front of the string From 657125b46913faa268ec020181ff17010168d511 Mon Sep 17 00:00:00 2001 From: Tleety Date: Wed, 17 Feb 2016 13:44:11 +0100 Subject: [PATCH 10/28] Moved menu code into GUI Button events are now sent when you click. --- include/Engine/GUI/Button.h | 165 ----------- include/Engine/GUI/ButtonSystem.h | 44 +++ include/Engine/GUI/EButtonClicked.h | 15 + include/Engine/GUI/EButtonEnter.h | 17 -- include/Engine/GUI/EButtonLeave.h | 17 -- include/Engine/GUI/EButtonPress.h | 20 -- include/Engine/GUI/EButtonPressed.h | 15 + include/Engine/GUI/EButtonRelease.h | 20 -- include/Engine/GUI/EButtonReleased.h | 13 + include/Engine/GUI/Frame.h | 261 ------------------ include/Engine/GUI/MainMenuSystem.h | 32 +++ include/Engine/GUI/TextureFrame.h | 112 -------- include/Game/Game.h | 2 - include/Game/Systems/HealthSystem.h | 5 +- resources/Schema/Components/Button.xsd | 1 + .../Schema/Entities/QualityAssurance.xml | 64 ++--- src/Engine/GUI/ButtonSystem.cpp | 78 ++++++ src/Engine/GUI/MainMenuSystem.cpp | 37 +++ src/Game/Game.cpp | 10 +- 19 files changed, 273 insertions(+), 655 deletions(-) delete mode 100644 include/Engine/GUI/Button.h create mode 100644 include/Engine/GUI/ButtonSystem.h create mode 100644 include/Engine/GUI/EButtonClicked.h delete mode 100644 include/Engine/GUI/EButtonEnter.h delete mode 100644 include/Engine/GUI/EButtonLeave.h delete mode 100644 include/Engine/GUI/EButtonPress.h create mode 100644 include/Engine/GUI/EButtonPressed.h delete mode 100644 include/Engine/GUI/EButtonRelease.h create mode 100644 include/Engine/GUI/EButtonReleased.h delete mode 100644 include/Engine/GUI/Frame.h create mode 100644 include/Engine/GUI/MainMenuSystem.h delete mode 100644 include/Engine/GUI/TextureFrame.h create mode 100644 src/Engine/GUI/ButtonSystem.cpp create mode 100644 src/Engine/GUI/MainMenuSystem.cpp diff --git a/include/Engine/GUI/Button.h b/include/Engine/GUI/Button.h deleted file mode 100644 index 80845cb7..00000000 --- a/include/Engine/GUI/Button.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef GUI_BUTTON_H__ -#define GUI_BUTTON_H__ - -#include "GUI/TextureFrame.h" -#include "GUI/EButtonEnter.h" -#include "GUI/EButtonLeave.h" -#include "GUI/EButtonPress.h" -#include "GUI/EButtonRelease.h" -#include "Core/EMouseMove.h" -#include "Core/EMousePress.h" -#include "Core/EMouseRelease.h" - -namespace dd -{ -namespace GUI -{ - -class Button : public TextureFrame -{ -public: - Button(Frame* parent, std::string name) - : TextureFrame(parent, name) - { - EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &Button::OnMouseMove); - EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &Button::OnMousePress); - EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &Button::OnMouseRelease); - } - - void SetTextureHover(std::string resourceName) - { - m_TextureHover = resourceName; - } - void SetTextureReleased(std::string resourceName) - { - m_TextureReleased = resourceName; - SetTexture(resourceName); - } - void SetTexturePressed(std::string resourceName) - { - m_TexturePressed = resourceName; - } - - void Draw(RenderScene& rq) override - { - if (m_Texture == nullptr && !m_TextureReleased.empty()) { - SetTexture(m_TextureReleased); - } - - TextureFrame::Draw(rq); - } - - virtual void OnEnter() { } - virtual void OnLeave() { } - virtual void OnPress() { } - virtual void OnRelease() { } - -protected: - bool m_MouseIsOver = false; - bool m_IsDown = false; - - virtual bool OnMouseMove(const Events::MouseMove& event) - { - if (Hidden()) { - return false; - } - - bool isOver = Rectangle::Intersects(AbsoluteRectangle(), Rectangle(event.X, event.Y, 1, 1)); - if (isOver && !m_MouseIsOver) { // Enter - if (!m_IsDown) { - if (!m_TextureHover.empty()) { - SetTexture(m_TextureHover); - } - } - OnEnter(); - Events::ButtonEnter e; - e.FrameName = m_Name; - EventBroker->Publish(e); - Events::PlaySound soundEvent; - soundEvent.FilePath = "Sounds/GUI/hover-n.wav"; - EventBroker->Publish(soundEvent); - - } else if (!isOver && m_MouseIsOver) { // Leave - if (!m_IsDown) { - if (!m_TextureReleased.empty()) { - SetTexture(m_TextureReleased); - } - } - OnLeave(); - Events::ButtonLeave e; - e.FrameName = m_Name; - EventBroker->Publish(e); - } - m_MouseIsOver = isOver; - - return true; - } - virtual bool OnMousePress(const Events::MousePress& event) - { - if (Hidden()) { - //LOG_DEBUG("Pressed hidden button"); - return false; - } - - if (!Rectangle::Intersects(AbsoluteRectangle(), Rectangle(event.X, event.Y, 1, 1))) { - return false; - } - - if (!m_TexturePressed.empty()) { - SetTexture(m_TexturePressed); - } - - m_IsDown = true; - OnPress(); - Events::ButtonPress e; - e.FrameName = m_Name; - e.Button = this; - EventBroker->Publish(e); - - return true; - } - virtual bool OnMouseRelease(const Events::MouseRelease& event) - { - if (Hidden()) { - //LOG_DEBUG("Released hidden button"); - return false; - } - - bool isOver = Rectangle::Intersects(AbsoluteRectangle(), Rectangle(event.X, event.Y, 1, 1)); - if (!isOver && !m_IsDown) { - return false; - } - - if (m_MouseIsOver) { - if (!m_TextureHover.empty()) { - SetTexture(m_TextureHover); - } - } else { - if (!m_TextureReleased.empty()) { - SetTexture(m_TextureReleased); - } - } - - m_IsDown = false; - OnRelease(); - Events::ButtonRelease e; - e.FrameName = m_Name; - e.Button = this; - EventBroker->Publish(e); - - return true; - } - -private: - EventRelay m_EMouseMove; - EventRelay m_EMousePress; - EventRelay m_EMouseRelease; - - std::string m_TextureHover; - std::string m_TexturePressed; - std::string m_TextureReleased; -}; - -} -} -#endif diff --git a/include/Engine/GUI/ButtonSystem.h b/include/Engine/GUI/ButtonSystem.h new file mode 100644 index 00000000..7dfe6b48 --- /dev/null +++ b/include/Engine/GUI/ButtonSystem.h @@ -0,0 +1,44 @@ +#ifndef ButtonSystem_h__ +#define ButtonSystem_h__ + +#include "../Rendering/IRenderer.h" +#include "../Core/ConfigFile.h" +#include "../Rendering/PickingPass.h" +#include "../Core/ResourceManager.h" +#include "../Core/System.h" +#include "../Core/Event.h" +#include "../Core/EMousePress.h" +#include "../Core/EMouseRelease.h" +#include "../Core/ELockMouse.h" + +#include "EButtonPressed.h" +#include "EButtonReleased.h" +#include "EButtonClicked.h" + + +class ButtonSystem : public PureSystem +{ +public: + ButtonSystem(SystemParams params, IRenderer* renderer); + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; +private: + IRenderer* m_Renderer; + bool m_MouseIsLocked = false; + + EntityWrapper m_PickEntity = EntityWrapper::Invalid; + PickData m_PickData; + + EventRelay m_EMouseLock; + bool OnMouseLock(const Events::LockMouse& e); + EventRelay m_EMouseUnlock; + bool OnMouseUnlock(const Events::UnlockMouse& e); + + EventRelay m_EMousePress; + bool OnMousePress(const Events::MousePress& e); + EventRelay m_EMouseRelease; + bool OnMouseRelease(const Events::MouseRelease& e); +}; + + + +#endif \ No newline at end of file diff --git a/include/Engine/GUI/EButtonClicked.h b/include/Engine/GUI/EButtonClicked.h new file mode 100644 index 00000000..f34d6b3d --- /dev/null +++ b/include/Engine/GUI/EButtonClicked.h @@ -0,0 +1,15 @@ +#ifndef Events_ButtonClicked_h__ +#define Events_ButtonClicked_h__ + +#include "Core/Event.h" + +namespace Events +{ + +struct ButtonClicked : public Event { + std::string EntityName = "DEFAULT STRING USED"; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/GUI/EButtonEnter.h b/include/Engine/GUI/EButtonEnter.h deleted file mode 100644 index 13a78383..00000000 --- a/include/Engine/GUI/EButtonEnter.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef Events_ButtonEnter_h__ -#define Events_ButtonEnter_h__ - -#include "../Core/EventBroker.h" - -namespace Events -{ - -/** Thrown on GUI button hover. */ -struct ButtonEnter : Event -{ - std::string FrameName; -}; - -} - -#endif \ No newline at end of file diff --git a/include/Engine/GUI/EButtonLeave.h b/include/Engine/GUI/EButtonLeave.h deleted file mode 100644 index 789e5aec..00000000 --- a/include/Engine/GUI/EButtonLeave.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef Events_ButtonLeave_h__ -#define Events_ButtonLeave_h__ - -#include "../Core/EventBroker.h" - -namespace Events -{ - -/** Thrown on GUI button hover. */ -struct ButtonLeave : Event -{ - std::string FrameName; -}; - -} - -#endif \ No newline at end of file diff --git a/include/Engine/GUI/EButtonPress.h b/include/Engine/GUI/EButtonPress.h deleted file mode 100644 index 6f925b2b..00000000 --- a/include/Engine/GUI/EButtonPress.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef Events_ButtonPress_h__ -#define Events_ButtonPress_h__ - -#include "../Core/EventBroker.h" - -namespace GUI { class Button; } - -namespace Events -{ - -/** Thrown on GUI button press. */ -struct ButtonPress : Event -{ - std::string FrameName; - GUI::Button* Button; -}; - -} - -#endif \ No newline at end of file diff --git a/include/Engine/GUI/EButtonPressed.h b/include/Engine/GUI/EButtonPressed.h new file mode 100644 index 00000000..04d50978 --- /dev/null +++ b/include/Engine/GUI/EButtonPressed.h @@ -0,0 +1,15 @@ +#ifndef Events_ButtonPressed_h__ +#define Events_ButtonPressed_h__ + +#include "Core/Event.h" + +namespace Events +{ + +struct ButtonPressed : public Event { + std::string EntityName = "DEFAULT STRING USED"; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/GUI/EButtonRelease.h b/include/Engine/GUI/EButtonRelease.h deleted file mode 100644 index d13a8ad6..00000000 --- a/include/Engine/GUI/EButtonRelease.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef Events_ButtonRelease_h__ -#define Events_ButtonRelease_h__ - -#include "../Core/EventBroker.h" - -namespace GUI { class Button; } - -namespace Events -{ - -/** Thrown on GUI button release. */ -struct ButtonRelease : Event -{ - std::string FrameName; - GUI::Button* Button; -}; - -} - -#endif \ No newline at end of file diff --git a/include/Engine/GUI/EButtonReleased.h b/include/Engine/GUI/EButtonReleased.h new file mode 100644 index 00000000..14736ca0 --- /dev/null +++ b/include/Engine/GUI/EButtonReleased.h @@ -0,0 +1,13 @@ +#ifndef Events_ButtonReleased_h__ +#define Events_ButtonReleased_h__ + +#include "Core/Event.h" + +namespace Events +{ + +struct ButtonReleased : public Event { }; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/GUI/Frame.h b/include/Engine/GUI/Frame.h deleted file mode 100644 index 4c5f2eb9..00000000 --- a/include/Engine/GUI/Frame.h +++ /dev/null @@ -1,261 +0,0 @@ -#ifndef GUI_Frame_h__ -#define GUI_Frame_h__ - -#include "../Common.h" -#include "../Core/Util/Rectangle.h" -#include "../Core/EventBroker.h" -#include "../Core/EKeyDown.h" -#include "../Core/EKeyUp.h" -#include "../Core/ResourceManager.h" -#include "../Rendering/RenderQueue.h" -#include "../Rendering/Texture.h" -#include "../Input/EInputCommand.h" - -namespace GUI -{ - -class Frame : public Rectangle -{ -public: - enum class Anchor - { - Left, - Right, - Top, - Bottom - }; - - static const int BaseWidth = 1280; - static const int BaseHeight = 720; - - // Set up a base frame with an event broker - Frame(EventBroker* eventBroker) - : m_EventBroker(eventBroker) - , BaseFrame(this) - , m_Name("UIParent") - , Rectangle() { } - - // Create a frame as a child - Frame(Frame* parent, std::string name) - : m_Name(name) - { - SetParent(parent); - Width = parent->Width; - Height = parent->Height; - EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &Frame::OnKeyDown); - EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &Frame::OnKeyUp); - EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &Frame::OnCommand); - } - - ~Frame() - { - /*for (auto layer : m_Children) - { - for (auto child : layer.second) - { - delete child.second; - } - } - - if (m_Parent) - { - m_Parent->RemoveChild(this); - }*/ - } - - Frame* Parent() const { return m_Parent; } - - void SetParent(Frame* parent) - { - if (parent == nullptr) { - LOG_ERROR("Failed to parent frame \"%s\": Invalid parent", m_Name.c_str()); - return; - } - - m_Layer = parent->Layer() + 1; - parent->AddChild(this); - m_Parent = parent; - m_EventBroker = parent->m_EventBroker; - BaseFrame = parent->BaseFrame; - } - - void AddChild(Frame* child) - { - m_Children[child->m_Layer].insert(std::make_pair(child->Name(), child)); - if (m_Parent) { - m_Parent->AddChild(child); - } - } - - void RemoveChild(Frame* child) - { - auto it = m_Children.find(child->m_Layer); - if (it != m_Children.end()) { - m_Children.erase(it); - } - - if (m_Parent) { - m_Parent->RemoveChild(child); - } - } - - std::string Name() const { return m_Name; } - void SetName(std::string val) { m_Name = val; } - - int Layer() const { return m_Layer; } - - bool Hidden() const - { - if (m_Parent) - return m_Parent->Hidden() || m_Hidden; - else - return m_Hidden; - } - bool Visible() const - { - return !Hidden(); - } - - virtual void Hide() { m_Hidden = true; } - virtual void Show() { m_Hidden = false; } - - int Left() const override - { - if (m_Parent) - return m_Parent->Left() + X; - else - return X; - } - void SetLeft(int absLeft) override - { - if (m_Parent) { - X = absLeft - m_Parent->Left(); - } else { - X = absLeft; - } - } - int Right() const override - { - return Left() + Width; - } - void SetRight(int absRight) override - { - if (m_Parent) { - X = absRight - Width - m_Parent->Left(); - } else { - X = absRight - Width; - } - } - int Top() const override - { - if (m_Parent) - return m_Parent->Top() + Y; - else - return Y; - } - void SetTop(int absTop) override - { - if (m_Parent) { - Y = absTop - m_Parent->Top(); - } else { - Y = absTop; - } - } - int Bottom() const override - { - return Top() + Height; - } - void SetBottom(int absBottom) override - { - if (m_Parent) { - Y = absBottom - Height - m_Parent->Top(); - } else { - Y = absBottom - Height; - } - } - - glm::vec2 Scale() - { - if (m_Parent) - return m_Parent->Scale(); - else - return glm::vec2(Width, Height) / glm::vec2(BaseWidth, BaseHeight); - } - - Rectangle AbsoluteRectangle() - { - int left = Left(); - if (m_Parent) - left = std::max(left, m_Parent->Left()); - int top = Top(); - if (m_Parent) - top = std::max(top, m_Parent->Top()); - int width = Right() - left; - int height = Bottom() - top; - return Rectangle(left, top, width, height); - } - - void UpdateLayered(double dt) - { - // Update ourselves - this->Update(dt); - - // Update children - for (auto& pairLayer : m_Children) { - auto children = pairLayer.second; - for (auto& pairChild : children) { - auto child = pairChild.second; - child->Update(dt); - } - } - } - - virtual void Update(double dt) { } - - void DrawLayered(RenderScene& rq) - { - if (this->Hidden()) - return; - - // Draw ourselves - this->Draw(rq); - - // Draw children - for (auto& pairLayer : m_Children) { - auto children = pairLayer.second; - for (auto& pairChild : children) { - auto child = pairChild.second; - if (child->Hidden()) - continue; - child->Draw(rq); - } - } - } - - virtual void Draw(RenderScene& rq) { } - -protected: - ::EventBroker* m_EventBroker; - Frame* BaseFrame = nullptr; - - std::string m_Name = "Unnamed"; - int m_Layer = 0; - bool m_Hidden = false; - - Frame* m_Parent = nullptr; - typedef std::multimap Children_t; // name -> frame - std::map m_Children; // layer -> Children_t - - virtual bool OnKeyDown(const Events::KeyDown& event) { return false; } - virtual bool OnKeyUp(const Events::KeyUp& event) { return false; } - virtual bool OnCommand(const Events::InputCommand& event) { return false; } - -private: - EventRelay m_EKeyDown; - EventRelay m_EKeyUp; - EventRelay m_EInputCommand; -}; - -} - -#endif diff --git a/include/Engine/GUI/MainMenuSystem.h b/include/Engine/GUI/MainMenuSystem.h new file mode 100644 index 00000000..45400d1d --- /dev/null +++ b/include/Engine/GUI/MainMenuSystem.h @@ -0,0 +1,32 @@ +#ifndef MainMenuSystem_h__ +#define MainMenuSystem_h__ + +#include "../Core/System.h" +#include "../Rendering/IRenderer.h" +#include "../Core/ResourceManager.h" +#include "../Core/Event.h" + +#include "EButtonClicked.h" +#include "EButtonPressed.h" +#include "EButtonReleased.h" + + +class MainMenuSystem : public ImpureSystem +{ +public: + MainMenuSystem(SystemParams params, IRenderer* renderer); + virtual void Update(double dt) override; + +private: + IRenderer* m_Renderer; + + EventRelay m_EClicked; + bool OnButtonClick(const Events::ButtonClicked& e); + EventRelay m_EReleased; + bool OnButtonRelease(const Events::ButtonReleased& e); + EventRelay m_EPressed; + bool OnButtonPress(const Events::ButtonPressed& e); + +}; + +#endif \ No newline at end of file diff --git a/include/Engine/GUI/TextureFrame.h b/include/Engine/GUI/TextureFrame.h deleted file mode 100644 index 77967b4d..00000000 --- a/include/Engine/GUI/TextureFrame.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef GUI_TextureFrame_h__ -#define GUI_TextureFrame_h__ - -#include "Frame.h" -#include "../Rendering/Texture.h" -#include "../Rendering/Util/CommonFunctions.h" - -namespace GUI -{ - -class TextureFrame : public Frame -{ -public: - TextureFrame(Frame* parent, std::string name) - : Frame(parent, name) { } - - void EnableScissor() { m_ScissorEnabled = true; } - void DisableScissor() { m_ScissorEnabled = false; } - - void Draw(RenderScene& rq) override - { - if (m_Texture == nullptr) - return; - - // Texture while fading - if (m_FadeTexture && m_CurrentFade < 1) { - FrameJob job; - job.Scissor = (m_ScissorEnabled) ? m_Parent->AbsoluteRectangle() : Rectangle(); - job.Viewport = Rectangle(Left(), Top(), Width, Height); - job.TextureID = m_FadeTexture->ResourceID; - job.DiffuseTexture = m_FadeTexture; - job.Color = glm::vec4(m_Color.r, m_Color.g, m_Color.b, m_Color.a); - job.Name = Name(); - rq.GUI.Add(job); - } - - // Main texture - { - FrameJob job; - job.Scissor = (m_ScissorEnabled) ? m_Parent->AbsoluteRectangle() : Rectangle(); - job.Viewport = Rectangle(Left(), Top(), Width, Height); - job.TextureID = m_Texture->ResourceID; - job.DiffuseTexture = m_Texture; - job.Color = glm::vec4(m_Color.r, m_Color.g, m_Color.b, m_Color.a * m_CurrentFade); - job.Name = Name(); - rq.GUI.Add(job); - } - } - - std::string Texture() const { return m_TextureName; } - - void SetTexture(std::string resourceName) - { - if (resourceName.empty()) { - m_Texture = nullptr; - return; - } - - m_Texture = CommonFunctions::LoadTexture(resourceName, false); - m_TextureName = resourceName; - if (m_Texture == nullptr) { - m_Texture = CommonFunctions::LoadTexture("Textures/Core/ErrorTexture.png", false); - } - - SizeToTexture(); - } - - void SizeToTexture() - { - if (m_Texture != nullptr) { - this->Width = m_Texture->Width; - this->Height = m_Texture->Height; - } - } - - void FadeToTexture(std::string resourceName, double duration) - { - m_FadeTexture = m_Texture; - SetTexture(resourceName); - m_FadeDuration = duration; - m_CurrentFade = 0.f; - } - - void Update(double dt) override - { - if (m_CurrentFade < 1) { - m_CurrentFade += dt / m_FadeDuration; - if (m_CurrentFade > 1) { - m_FadeTexture = nullptr; - m_CurrentFade = 1; - m_FadeDuration = 0; - } - } - } - - glm::vec4 Color() const { return m_Color; } - void SetColor(glm::vec4 val) { m_Color = val; } - -protected: - bool m_ScissorEnabled = true; - Texture* m_Texture = nullptr; - std::string m_TextureName; - Texture* m_FadeTexture = nullptr; - glm::vec4 m_Color = glm::vec4(1.f, 1.f, 1.f, 1.f); - float m_FadeDuration = 0.f; - float m_CurrentFade = 1.f; - -}; - -} - -#endif diff --git a/include/Game/Game.h b/include/Game/Game.h index baf15656..d13efec0 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -8,7 +8,6 @@ #include "Core/EventBroker.h" #include "Rendering/Renderer.h" #include "Core/InputManager.h" -#include "GUI/Frame.h" #include "Core/World.h" #include "Input/InputProxy.h" #include "Input/KeyboardInputHandler.h" @@ -53,7 +52,6 @@ private: IRenderer* m_Renderer; InputManager* m_InputManager; InputProxy* m_InputProxy; - GUI::Frame* m_FrameStack; World* m_World; Octree* m_OctreeCollision; Octree* m_OctreeTrigger; diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index 56f2f838..962e3737 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -27,17 +27,16 @@ public: private: bool m_NetworkEnabled; - //methods which will take care of specific events + // methods which will take care of specific events EventRelay m_EPlayerDamage; bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e); EventRelay m_EPlayerHealthPickup; bool HealthSystem::OnPlayerHealthPickup(Events::PlayerHealthPickup& e); EventRelay m_InputCommand; bool HealthSystem::OnInputCommand(Events::InputCommand& e); - + //vector which will keep track of health changes std::vector> m_DeltaHealthVector; - }; #endif \ No newline at end of file diff --git a/resources/Schema/Components/Button.xsd b/resources/Schema/Components/Button.xsd index 07f2eafc..7d97fef1 100644 --- a/resources/Schema/Components/Button.xsd +++ b/resources/Schema/Components/Button.xsd @@ -1,6 +1,7 @@ + Makes sprites klickable. diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml index 30fb915b..6bd8a25a 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -40,7 +40,7 @@ - + @@ -105,7 +105,7 @@ - + @@ -180,7 +180,7 @@ - + @@ -225,7 +225,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -321,7 +321,7 @@ - + @@ -671,7 +671,7 @@ - + @@ -718,7 +718,7 @@ - + @@ -778,7 +778,7 @@ - + @@ -825,7 +825,7 @@ - + @@ -871,7 +871,7 @@ - + @@ -918,7 +918,7 @@ - + @@ -965,7 +965,7 @@ - + @@ -1379,7 +1379,7 @@ - + @@ -1388,7 +1388,7 @@ true - 2.5166344949826396 + 2.5333333077342104 3.7999999523162842 true @@ -1435,7 +1435,7 @@ - + @@ -1444,7 +1444,7 @@ - 0.35000808291962926 + 0.70455028055985736 Models/Characters/Assault/AssaultTPose.mesh @@ -1487,7 +1487,7 @@ - + @@ -1498,7 +1498,7 @@ true - 0.35000808291962926 + 0.70455028055985736 true @@ -1543,7 +1543,7 @@ - + @@ -1553,7 +1553,7 @@ true - 9.4833086749886775 + 9.1832418997049956 10 3 @@ -1601,7 +1601,7 @@ - + @@ -1611,7 +1611,7 @@ true - 4.0667207575903603 + 1.007708532606415 true 5 true @@ -1792,7 +1792,7 @@ true - 2.5166344949826396 + 2.5333333077342104 3.7999999523162842 true @@ -2185,7 +2185,7 @@ - + @@ -2213,7 +2213,7 @@ - + @@ -2241,7 +2241,7 @@ - + @@ -2269,7 +2269,7 @@ - + @@ -2297,7 +2297,7 @@ - + @@ -2349,7 +2349,7 @@ - + @@ -2377,7 +2377,7 @@ - + @@ -2405,7 +2405,7 @@ - + diff --git a/src/Engine/GUI/ButtonSystem.cpp b/src/Engine/GUI/ButtonSystem.cpp new file mode 100644 index 00000000..dbdc0e18 --- /dev/null +++ b/src/Engine/GUI/ButtonSystem.cpp @@ -0,0 +1,78 @@ +#include "GUI/ButtonSystem.h" + +ButtonSystem::ButtonSystem(SystemParams params, IRenderer* renderer) + : System(params) + , PureSystem("Button") + , m_Renderer(renderer) +{ + EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &ButtonSystem::OnMousePress); + EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &ButtonSystem::OnMouseRelease); + EVENT_SUBSCRIBE_MEMBER(m_EMouseLock, &ButtonSystem::OnMouseLock); + EVENT_SUBSCRIBE_MEMBER(m_EMouseUnlock, &ButtonSystem::OnMouseUnlock); +} + + +bool ButtonSystem::OnMouseLock(const Events::LockMouse& e) +{ + m_MouseIsLocked = true; + return true; +} + + +bool ButtonSystem::OnMouseUnlock(const Events::UnlockMouse& e) +{ + m_MouseIsLocked = false; + return true; +} + + +bool ButtonSystem::OnMousePress(const Events::MousePress& e) +{ + if (e.Button == GLFW_MOUSE_BUTTON_1 && !m_MouseIsLocked) { + m_PickData = m_Renderer->Pick(glm::vec2(e.X, e.Y)); + if (m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) { + if(m_World->HasComponent(m_PickData.Entity, "Button")) { + //Entity is a button, save it and send pressed event. + + m_PickEntity = EntityWrapper(m_World, m_PickData.Entity); + + //You have clicked on a button entity, send pressed event. + Events::ButtonPressed ePressed; + ePressed.EntityName = m_PickEntity.Name(); + m_EventBroker->Publish(ePressed); + } + } + } + return true; +} + +bool ButtonSystem::OnMouseRelease(const Events::MouseRelease& e) +{ + if(!m_MouseIsLocked) { + //Mouse is not locked, send release event. + Events::ButtonReleased eReleased; + m_EventBroker->Publish(eReleased); + m_PickData = m_Renderer->Pick(glm::vec2(e.X, e.Y)); + if(m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) { + if(m_World->HasComponent(m_PickData.Entity, "Button")) { + EntityWrapper ent = EntityWrapper(m_World, m_PickData.Entity); + if (ent == m_PickEntity) { + //The entity you released the mouse button on is the same as you pressed it on. "Clicked" + Events::ButtonClicked eClicked; + eClicked.EntityName = m_PickEntity.Name(); + m_EventBroker->Publish(eClicked); + } + } + } + } + return true; +} + +void ButtonSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cHealth, double dt) +{ + +} + + + + \ No newline at end of file diff --git a/src/Engine/GUI/MainMenuSystem.cpp b/src/Engine/GUI/MainMenuSystem.cpp new file mode 100644 index 00000000..3d6b6ced --- /dev/null +++ b/src/Engine/GUI/MainMenuSystem.cpp @@ -0,0 +1,37 @@ +#include "GUI/MainMenuSystem.h" + +MainMenuSystem::MainMenuSystem(SystemParams params, IRenderer* renderer) + : System(params) + , ImpureSystem() + , m_Renderer(renderer) +{ + EVENT_SUBSCRIBE_MEMBER(m_EPressed, &MainMenuSystem::OnButtonPress); + EVENT_SUBSCRIBE_MEMBER(m_EReleased, &MainMenuSystem::OnButtonRelease); + EVENT_SUBSCRIBE_MEMBER(m_EClicked, &MainMenuSystem::OnButtonClick); +} + +void MainMenuSystem::Update(double dt) +{ + +} + +bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) +{ + printf("\nClicked: %s", e.EntityName); + return true; +} + +bool MainMenuSystem::OnButtonRelease(const Events::ButtonReleased& e) +{ + printf("\nReleased"); + + return true; +} + +bool MainMenuSystem::OnButtonPress(const Events::ButtonPressed& e) +{ + printf("\nPressed: %s", e.EntityName); + + return true; +} + diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 49b1a963..45044937 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -26,6 +26,8 @@ #include "Network/MultiplayerSnapshotFilter.h" #include "Game/Systems/AmmunitionHUDSystem.h" #include "Game/Systems/KillFeedSystem.h" +#include "GUI/ButtonSystem.h" +#include "GUI/MainMenuSystem.h" Game::Game(int argc, char* argv[]) @@ -72,11 +74,6 @@ Game::Game(int argc, char* argv[]) m_InputProxy->AddHandler(); m_InputProxy->LoadBindings("Input.ini"); - // Create the root level GUI frame - m_FrameStack = new GUI::Frame(m_EventBroker); - m_FrameStack->Width = m_Renderer->Resolution().Width; - m_FrameStack->Height = m_Renderer->Resolution().Height; - // Create a world m_World = new World(m_EventBroker); std::string mapToLoad = m_Config->Get("Debug.LoadMap", ""); @@ -132,6 +129,8 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); // Populate Octree with collidables ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision, "Collidable"); @@ -168,7 +167,6 @@ Game::~Game() delete m_NetworkServer; } delete m_World; - delete m_FrameStack; delete m_InputProxy; delete m_InputManager; delete m_RenderFrame; From 833015f45e97ae173130abe67595c24f86bfa333 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Wed, 17 Feb 2016 13:44:41 +0100 Subject: [PATCH 11/28] Small code cleanup for PerformanceTimer --- include/Engine/Core/PerformanceTimer.h | 4 ---- resources/Schema/Entities/NewMap.xml | 20 ++++++++++---------- src/Engine/Core/PerformanceTimer.cpp | 12 +++--------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/include/Engine/Core/PerformanceTimer.h b/include/Engine/Core/PerformanceTimer.h index 9f2c3d66..a3cdfa92 100644 --- a/include/Engine/Core/PerformanceTimer.h +++ b/include/Engine/Core/PerformanceTimer.h @@ -1,10 +1,7 @@ #ifndef PerformanceTimer_h__ #define PerformanceTimer_h__ -#include -#include #include "../Common.h" - #include using boost::timer::cpu_timer; @@ -21,7 +18,6 @@ public: private: static std::map timers; - static double m_TimeElapsed; static cpu_timer m_Timer; static std::string currentTimerRunning; }; diff --git a/resources/Schema/Entities/NewMap.xml b/resources/Schema/Entities/NewMap.xml index dcdb7bec..f5b975b8 100644 --- a/resources/Schema/Entities/NewMap.xml +++ b/resources/Schema/Entities/NewMap.xml @@ -5019,7 +5019,7 @@ - + @@ -5089,7 +5089,7 @@ - + @@ -5165,7 +5165,7 @@ - + @@ -5184,7 +5184,7 @@ - + @@ -5203,7 +5203,7 @@ - + @@ -5222,7 +5222,7 @@ - + @@ -5241,7 +5241,7 @@ - + @@ -5260,7 +5260,7 @@ - + @@ -5279,7 +5279,7 @@ - + @@ -5298,7 +5298,7 @@ - + diff --git a/src/Engine/Core/PerformanceTimer.cpp b/src/Engine/Core/PerformanceTimer.cpp index 05ac221a..50983e79 100644 --- a/src/Engine/Core/PerformanceTimer.cpp +++ b/src/Engine/Core/PerformanceTimer.cpp @@ -1,11 +1,8 @@ #include "Core/PerformanceTimer.h" -#include #include #include -#include cpu_timer PerformanceTimer::m_Timer; -double PerformanceTimer::m_TimeElapsed; std::map PerformanceTimer::timers; std::string PerformanceTimer::currentTimerRunning = ""; @@ -50,16 +47,13 @@ void PerformanceTimer::ResetAllTimers() void PerformanceTimer::CreateExcelData() { - //get path,time - char Dump_Path[MAX_PATH]; - GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); //path of current process + //get time std::time_t t = std::time(NULL); char tStr[16]; std::strftime(tStr, 32, " %a %H-%M-%S", std::localtime(&t)); std::string time(tStr); - std::string path(Dump_Path); - path = path.substr(0, path.length() - 4); - path += time + ".xls"; + std::string path("TacticalZ"); + path += time + ".csv"; std::ofstream someFileStream; someFileStream.open(path, std::ofstream::out); someFileStream << "classname" << ',' << "walltime" << ',' << "userTime" << ',' << "systemTime" << '\n'; From a6c30100afcb64335aebf75c7bb2060c3b5ff4d1 Mon Sep 17 00:00:00 2001 From: Tleety Date: Wed, 17 Feb 2016 14:16:17 +0100 Subject: [PATCH 12/28] FrameWork for menu buttons --- src/Engine/GUI/MainMenuSystem.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Engine/GUI/MainMenuSystem.cpp b/src/Engine/GUI/MainMenuSystem.cpp index 3d6b6ced..36d4a173 100644 --- a/src/Engine/GUI/MainMenuSystem.cpp +++ b/src/Engine/GUI/MainMenuSystem.cpp @@ -17,20 +17,27 @@ void MainMenuSystem::Update(double dt) bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) { - printf("\nClicked: %s", e.EntityName); + if(e.EntityName == "Play") { + //Run play code + } else if(e.EntityName == "Connect") { + //Run connect code + } else if(e.EntityName == "Host") { + //Run host code + } else if(e.EntityName == "Quit") { + printf("No, you stay"); + } + return true; } bool MainMenuSystem::OnButtonRelease(const Events::ButtonReleased& e) { - printf("\nReleased"); return true; } bool MainMenuSystem::OnButtonPress(const Events::ButtonPressed& e) { - printf("\nPressed: %s", e.EntityName); return true; } From 23bb1a64057fc3f5f9c21b0206b2daf3e384217b Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 17 Feb 2016 14:54:59 +0100 Subject: [PATCH 13/28] Cannot respawn inside other players, unless all are blocked. --- include/Engine/Collision/Collision.h | 10 ++- include/Game/Systems/SpawnerSystem.h | 7 +- src/Engine/Collision/Collision.cpp | 53 +++++++++++++-- src/Game/Systems/PlayerSpawnSystem.cpp | 4 +- src/Game/Systems/SpawnerSystem.cpp | 93 +++++++++++++++++++++----- 5 files changed, 143 insertions(+), 24 deletions(-) diff --git a/include/Engine/Collision/Collision.h b/include/Engine/Collision/Collision.h index 546d03f5..9e1a81db 100644 --- a/include/Engine/Collision/Collision.h +++ b/include/Engine/Collision/Collision.h @@ -78,13 +78,21 @@ bool AABBvsTriangles(const AABB& box, bool& isOnGround, glm::vec3& outResolutionVector); +//Detects collision, but does not resolve. +bool AABBvsTriangles(const AABB& box, + const RawModel::Vertex* modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix); + //Return true if the boxes are intersecting. bool AABBVsAABB(const AABB& a, const AABB& b); //Return true if the boxes are intersecting. //Also outputs the minimum translation that box [a] would need in order to resolve collision. bool AABBVsAABB(const AABB& a, const AABB& b, glm::vec3& minimumTranslation); -// Calculates an absolute AABB from an entity AABB component +// Calculates an absolute AABB from an entity AABB component or Model component. +// if takeModelBox is true, the AABB component will be ignored and box is calculated from Model. +// if takeModelBox is false, the AABB component will be prefered, if it exists. boost::optional EntityAbsoluteAABB(EntityWrapper& entity, bool takeModelBox = false); boost::optional AbsoluteAABBExplosionEffect(EntityWrapper& entity); //Returns the first entity hit by the input ray. entitiesPotentiallyHitSorted needs to be sorted diff --git a/include/Game/Systems/SpawnerSystem.h b/include/Game/Systems/SpawnerSystem.h index 9cb4bd06..e4a44738 100644 --- a/include/Game/Systems/SpawnerSystem.h +++ b/include/Game/Systems/SpawnerSystem.h @@ -15,11 +15,16 @@ class SpawnerSystem : public System public: SpawnerSystem(SystemParams params); - static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid); + // If dontCollideComponent is set, to e.g. "Player", then all the spawner + // will try to pick a spawn location so that the spawned entity doesn't + // collide with anything that has that component and is collidable. + static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid, const std::string& dontCollideComponent = ""); private: EventRelay m_OnSpawnerSpawn; bool OnSpawnerSpawn(Events::SpawnerSpawn& e); + static void transformEntityToSpawnPoint(EntityWrapper spawnedEntity, EntityWrapper spawnPoint); + static bool spawnedEntityIsColliding(EntityWrapper spawnedEntity, EntityWrapper spawnPoint, const std::string& dontCollideComponent); }; #endif \ No newline at end of file diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index ab2098b7..87d8bf26 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -366,7 +366,8 @@ bool AABBvsTriangle(const AABB& box, float verticalStepHeight, bool& isOnGround, glm::vec3& boxVelocity, - glm::vec3& outResolution) + glm::vec3& outResolution, + bool resolveCollision) { //Check so we don't have a zero area triangle when calculating the normal. //Also, don't check a triangle facing away from the player. @@ -426,7 +427,7 @@ bool AABBvsTriangle(const AABB& box, //if projections don't overlap, return false. if (!rectangleVsTriangle(boxMin, boxMax, t2D, resolutionVector, resolutionDist, pushedFromTriangleLine)) { return false; - } else { + } else if (resolveCollision) { //Overwrite the smallest resolution if this is smaller. if (resolutionDist < resolveShortest.DistanceSq) { resolveShortest.Vector = glm::vec3(0.f); @@ -463,6 +464,11 @@ bool AABBvsTriangle(const AABB& box, if (glm::abs(t) > 1) { return false; } + + if (!resolveCollision) { + return true; + } + glm::vec3 cornerResolution = (1+t) * diagonal; //Overwrite the smallest resolution if cornerResolution is smaller. float lenSq = glm::length2(cornerResolution); @@ -537,7 +543,8 @@ bool AABBvsTriangles(const AABB& box, glm::vec3& boxVelocity, float verticalStepHeight, bool& isOnGround, - glm::vec3& outResolutionVector) + glm::vec3& outResolutionVector, + bool resolveCollision) { bool hit = false; @@ -553,7 +560,7 @@ bool AABBvsTriangles(const AABB& box, }; glm::vec3 outVec; bool collideWithGround = isOnGround; - if (AABBvsTriangle(newBox, triVertices, originalBoxVelocity, verticalStepHeight, collideWithGround, boxVelocity, outVec)) { + if (AABBvsTriangle(newBox, triVertices, originalBoxVelocity, verticalStepHeight, collideWithGround, boxVelocity, outVec, resolveCollision)) { hit = true; outResolutionVector += outVec; newBox = AABB::FromOriginSize(newBox.Origin() + outVec, newBox.Size()); @@ -569,6 +576,44 @@ bool AABBvsTriangles(const AABB& box, return hit; } +bool AABBvsTriangles(const AABB& box, + const RawModel::Vertex* modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix, + glm::vec3& boxVelocity, + float verticalStepHeight, + bool& isOnGround, + glm::vec3& outResolutionVector) +{ + return AABBvsTriangles(box, + modelVertices, + modelIndices, + modelMatrix, + boxVelocity, + verticalStepHeight, + isOnGround, + outResolutionVector, + true); +} + +bool AABBvsTriangles(const AABB& box, + const RawModel::Vertex* modelVertices, + const std::vector& modelIndices, + const glm::mat4& modelMatrix) +{ + glm::vec3 vel, outres; + bool g; + return AABBvsTriangles(box, + modelVertices, + modelIndices, + modelMatrix, + vel, + 0.f, + g, + outres, + false); +} + boost::optional EntityAbsoluteAABB(EntityWrapper& entity, bool takeModelBox) { AABB modelSpaceBox; diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 5f53a1fc..6254c674 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -3,7 +3,7 @@ //This should be set by the config anyway. float PlayerSpawnSystem::m_RespawnTime = 15.0f; -PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params) +PlayerSpawnSystem::PlayerSpawnSystem(SystemParams params) : System(params) , m_Timer(0.f) { @@ -49,7 +49,7 @@ void PlayerSpawnSystem::Update(double dt) } // Spawn the player! - EntityWrapper player = SpawnerSystem::Spawn(spawner); + EntityWrapper player = SpawnerSystem::Spawn(spawner, EntityWrapper::Invalid, "Player"); // Set the player team affiliation player["Team"]["Team"] = req.Team; diff --git a/src/Game/Systems/SpawnerSystem.cpp b/src/Game/Systems/SpawnerSystem.cpp index b3c556f1..90f677fe 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -1,12 +1,13 @@ #include "Systems/SpawnerSystem.h" +#include "Collision/Collision.h" -SpawnerSystem::SpawnerSystem(SystemParams params) +SpawnerSystem::SpawnerSystem(SystemParams params) : System(params) { EVENT_SUBSCRIBE_MEMBER(m_OnSpawnerSpawn, &SpawnerSystem::OnSpawnerSpawn); } -EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /*= EntityWrapper::Invalid*/) +EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent /*= EntityWrapper::Invalid*/, const std::string& dontCollideComponent) { // Spawn the entity in the parent's world if it exists, otherwise in the spawner's world World* world = parent.World; @@ -14,17 +15,41 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / world = spawner.World; } + // Load the entity file and parse it + const std::string& entityFilePath = spawner["Spawner"]["EntityFile"]; + auto entityFile = ResourceManager::Load(entityFilePath); + if (entityFile == nullptr) { + return EntityWrapper::Invalid; + } + EntityFileParser parser(entityFile); + EntityWrapper spawnedEntity(world, parser.MergeEntities(world, parent.ID)); + + //If the spawned entity is collideable, then we must not spawn it where it collides with something that + //has a dontCollideComponent attached. + bool spawnOnCollidable = dontCollideComponent.empty() || !spawnedEntity.HasComponent("Collidable"); + if (!spawnOnCollidable) { + boost::optional optBox = Collision::EntityAbsoluteAABB(spawnedEntity); + //If we can't calculate the box for some reason, then just spawn somewhere anyway. + if (!optBox) { + spawnOnCollidable = true; + } + } + // Find any SpawnPoints existing as children of spawner auto children = spawner.World->GetChildren(spawner.ID); std::vector spawnPoints; for (auto kv = children.first; kv != children.second; ++kv) { const EntityID& child = kv->second; if (spawner.World->HasComponent(child, "SpawnPoint")) { - spawnPoints.push_back(EntityWrapper(spawner.World, child)); + EntityWrapper spawnPoint = EntityWrapper(spawner.World, child); + if (spawnOnCollidable || !spawnedEntityIsColliding(spawnedEntity, spawnPoint, dontCollideComponent)) { + spawnPoints.push_back(spawnPoint); + } } } // Choose a random SpawnPoint + // If there are no children, or if they are all blocked, then the entity will be spawned at the spawner itself. EntityWrapper spawnPoint = spawner; if (!spawnPoints.empty()) { if (spawnPoints.size() > 1) { @@ -39,25 +64,61 @@ EntityWrapper SpawnerSystem::Spawn(EntityWrapper spawner, EntityWrapper parent / } } - // Load the entity file and parse it - const std::string& entityFilePath = spawner["Spawner"]["EntityFile"]; - auto entityFile = ResourceManager::Load(entityFilePath); - if (entityFile == nullptr) { - return EntityWrapper::Invalid; - } - EntityFileParser parser(entityFile); - EntityWrapper spawnedEntity(world, parser.MergeEntities(world, parent.ID)); - if (spawnPoint != parent) { - // Set its position and orientation to that of the SpawnPoint - spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID); - // TODO: Quaternions, bitch - spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint)); + transformEntityToSpawnPoint(spawnedEntity, spawnPoint); } return spawnedEntity; } +void SpawnerSystem::transformEntityToSpawnPoint(EntityWrapper spawnedEntity, EntityWrapper spawnPoint) +{ + // Set its position and orientation to that of the SpawnPoint + spawnedEntity["Transform"]["Position"] = Transform::AbsolutePosition(spawnPoint.World, spawnPoint.ID); + // TODO: Quaternions, bitch + spawnedEntity["Transform"]["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(spawnPoint)); +} + +bool SpawnerSystem::spawnedEntityIsColliding(EntityWrapper spawnedEntity, EntityWrapper spawnPoint, const std::string& dontCollideComponent) +{ + transformEntityToSpawnPoint(spawnedEntity, spawnPoint); + //Check if the spawned entity collides with anything, and if so, continue to the next spawnpoint. + EntityAABB spawnedBox = *Collision::EntityAbsoluteAABB(spawnedEntity); + const ComponentPool* otherSpawnedEntities = spawnPoint.World->GetComponents(dontCollideComponent); + for (const auto& obj : *otherSpawnedEntities) { + if (spawnedEntity.ID == obj.EntityID) { + continue; + } + EntityWrapper otherEntity = EntityWrapper(spawnPoint.World, obj.EntityID); + if (!otherEntity.HasComponent("Collidable")) { + continue; + } + auto otherBox = Collision::EntityAbsoluteAABB(otherEntity); + if (!otherBox) { + continue; + } + if (Collision::AABBVsAABB(spawnedBox, *otherBox)) { + if (!spawnedBox.Entity.HasComponent("Model")) { + return true; + } + RawModel* model = nullptr; + try { + model = ResourceManager::Load(otherEntity["Model"]["Resource"]); + } catch (const std::exception&) { + } + + if (model != nullptr && Collision::AABBvsTriangles( + spawnedBox, + model->Vertices(), + model->m_Indices, + Transform::ModelMatrix(otherEntity))) { + return true; + } + } + } + return false; +} + bool SpawnerSystem::OnSpawnerSpawn(Events::SpawnerSpawn& e) { EntityWrapper spawnedEntity = Spawn(e.Spawner, e.Parent); From 72db672dbf55bf207df7aef8a7ccf3a41d2f50dd Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 17 Feb 2016 16:06:35 +0100 Subject: [PATCH 14/28] Ray will not hit objects in octree if they are transparent or invisible. --- src/Engine/Collision/Collision.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index 87d8bf26..99566404 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -693,8 +693,9 @@ boost::optional EntityFirstHitByRay(const Ray& ray, std::vector Date: Wed, 17 Feb 2016 17:44:33 +0100 Subject: [PATCH 15/28] You can now change resolution by pressing buttons. --- include/Engine/GUI/MainMenuSystem.h | 1 + .../Schema/Entities/QualityAssurance.xml | 84 +++++++++---------- src/Engine/GUI/MainMenuSystem.cpp | 11 +++ src/Engine/Rendering/Renderer.cpp | 2 +- 4 files changed, 55 insertions(+), 43 deletions(-) diff --git a/include/Engine/GUI/MainMenuSystem.h b/include/Engine/GUI/MainMenuSystem.h index 45400d1d..ba69ff0d 100644 --- a/include/Engine/GUI/MainMenuSystem.h +++ b/include/Engine/GUI/MainMenuSystem.h @@ -6,6 +6,7 @@ #include "../Core/ResourceManager.h" #include "../Core/Event.h" + #include "EButtonClicked.h" #include "EButtonPressed.h" #include "EButtonReleased.h" diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml index 6bd8a25a..762da931 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -40,7 +40,7 @@ - + @@ -77,18 +77,6 @@ - - - - Sound Test - Fonts/DroidSans.ttf,64 - - - - - - - @@ -105,7 +93,7 @@ - + @@ -180,7 +168,7 @@ - + @@ -225,7 +213,7 @@ - + @@ -289,7 +277,7 @@ - + @@ -321,7 +309,7 @@ - + @@ -671,7 +659,7 @@ - + @@ -718,7 +706,7 @@ - + @@ -778,7 +766,7 @@ - + @@ -825,7 +813,7 @@ - + @@ -871,7 +859,7 @@ - + @@ -918,7 +906,7 @@ - + @@ -965,7 +953,7 @@ - + @@ -1379,7 +1367,7 @@ - + @@ -1388,7 +1376,7 @@ true - 2.5333333077342104 + 2.6831806538294813 3.7999999523162842 true @@ -1435,7 +1423,7 @@ - + @@ -1444,7 +1432,7 @@ - 0.70455028055985736 + 1.9833111709021125 Models/Characters/Assault/AssaultTPose.mesh @@ -1487,7 +1475,7 @@ - + @@ -1498,7 +1486,7 @@ true - 0.70455028055985736 + 1.9833111709021125 true @@ -1543,7 +1531,7 @@ - + @@ -1553,7 +1541,7 @@ true - 9.1832418997049956 + 1.05003269646582 10 3 @@ -1601,7 +1589,7 @@ - + @@ -1611,7 +1599,7 @@ true - 1.007708532606415 + 0.75001660742393028 true 5 true @@ -1792,7 +1780,7 @@ true - 2.5333333077342104 + 2.6831806538294813 3.7999999523162842 true @@ -2349,7 +2337,7 @@ - + @@ -2364,7 +2352,7 @@ - Resolution + 1920x1080 Fonts/DroidSans.ttf,64 @@ -2377,7 +2365,7 @@ - + @@ -2392,7 +2380,7 @@ - Option2 + 1280x720 Fonts/DroidSans.ttf,64 @@ -2405,7 +2393,7 @@ - + @@ -2420,7 +2408,7 @@ - Butts + 854x480 Fonts/DroidSans.ttf,64 @@ -2454,6 +2442,18 @@ + + + + Sound Test + Fonts/DroidSans.ttf,64 + + + + + + + diff --git a/src/Engine/GUI/MainMenuSystem.cpp b/src/Engine/GUI/MainMenuSystem.cpp index 36d4a173..68db7b60 100644 --- a/src/Engine/GUI/MainMenuSystem.cpp +++ b/src/Engine/GUI/MainMenuSystem.cpp @@ -25,6 +25,17 @@ bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) //Run host code } else if(e.EntityName == "Quit") { printf("No, you stay"); + } else if (e.EntityName == "Res1080") { + glfwSetWindowSize(m_Renderer->Window(), 1920, 1080); + printf("1080"); + } else if (e.EntityName == "Res720") { + glfwSetWindowSize(m_Renderer->Window(), 1280, 720); + glViewport(0, 0, 1280, 720); + printf("720"); + } else if (e.EntityName == "Res480") { + glfwSetWindowSize(m_Renderer->Window(), 854, 480); + glViewport(0, 0, 854, 480); + printf("480"); } return true; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index be84160c..0ba25128 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -60,7 +60,7 @@ void Renderer::InitializeWindow() } int windowSize[2]; - glfwGetWindowSize(m_Window, &windowSize[0], &windowSize[1]); + glfwGetFramebufferSize(m_Window, &windowSize[0], &windowSize[1]); m_ViewportSize = Rectangle(windowSize[0], windowSize[1]); } From 64610e3c03b4ebe99b824b40b3f66ce51cef3f60 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 18 Feb 2016 11:27:07 +0100 Subject: [PATCH 16/28] Fixed so some of the tests are working again. Also removed the test errors --- src/Tests/CapturePointTest.cpp | 2 +- src/Tests/CollisionTest.cpp | 18 +++++++++--------- src/Tests/HealthSystemTest.cpp | 2 +- src/Tests/PickupSpawnTest.cpp | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Tests/CapturePointTest.cpp b/src/Tests/CapturePointTest.cpp index 2c7bf430..8a9baf40 100644 --- a/src/Tests/CapturePointTest.cpp +++ b/src/Tests/CapturePointTest.cpp @@ -94,7 +94,7 @@ CapturePointTest::CapturePointTest(int runTestNumber) m_World = new World(); // Create system pipeline - m_SystemPipeline = new SystemPipeline(m_World,m_EventBroker); + m_SystemPipeline = new SystemPipeline(m_World,m_EventBroker, true, false); m_SystemPipeline->AddSystem(0); m_SystemPipeline->AddSystem(1); diff --git a/src/Tests/CollisionTest.cpp b/src/Tests/CollisionTest.cpp index 6cb6c88b..b5ba8245 100644 --- a/src/Tests/CollisionTest.cpp +++ b/src/Tests/CollisionTest.cpp @@ -33,10 +33,10 @@ void RayTest(std::string fileName) { ResourceManager::RegisterType("RawModel"); auto unitBox = ResourceManager::Load(fileName); BOOST_REQUIRE(unitBox != nullptr); - bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + bool hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices, glm::mat4(1)); BOOST_CHECK(hit); ray.SetDirection(glm::vec3(-1, 0, 0)); - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices, glm::mat4(1)); BOOST_CHECK(!hit); } @@ -146,12 +146,12 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) z = Collision::RayVsAABB(ray, someAABB); if (z) { //hit - bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + bool hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices,glm::mat4(1)); if (!hit) { //if rayvsaabb hit but rayvvmodel didnt hit, we get to here - glm::vec3 outtttttttt; - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + glm::mat4 outtttttttt; + hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices, glm::mat4(1)); + hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices, glm::mat4(1)); } else { hit = hit; @@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) // z = z; //} // - bool hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + bool hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices, glm::mat4(1)); ////breakpoint test //if (!hit) { // hit = hit; @@ -175,8 +175,8 @@ BOOST_AUTO_TEST_CASE(rayVsModelTest2) //if rayvsmodel hit but rayvsaabb didnt hit then we get to here z = Collision::RayVsAABB(ray, someAABB); glm::vec3 outtttttttt; - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices, outtttttttt); - hit = Collision::RayVsModel(ray, unitBox->m_Vertices, unitBox->m_Indices); + hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices, glm::mat4(1)); + hit = Collision::RayVsModel(ray, unitBox->Vertices(), unitBox->m_Indices, glm::mat4(1)); } else { z = z; diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index 8c084070..bf2650a3 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -48,7 +48,7 @@ GameHealthSystemTest::GameHealthSystemTest() fp.MergeEntities(m_World); // Create system pipeline - m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); + m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker, false, false); m_SystemPipeline->AddSystem(0); //The Test diff --git a/src/Tests/PickupSpawnTest.cpp b/src/Tests/PickupSpawnTest.cpp index 7cbed85f..4acd897e 100644 --- a/src/Tests/PickupSpawnTest.cpp +++ b/src/Tests/PickupSpawnTest.cpp @@ -39,7 +39,7 @@ PickupSpawnTest::PickupSpawnTest(int runTestNumber) m_World = new World(); // Create system pipeline - m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); + m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker, false, false); m_SystemPipeline->AddSystem(0); m_SystemPipeline->AddSystem(1); From 97499f1c28d04b01d510b3e30b3fbab88ad8a41e Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 18 Feb 2016 11:37:03 +0100 Subject: [PATCH 17/28] Made ComponentPool copyable by making sure string fields are handled properly --- include/Engine/Core/ComponentInfo.h | 1 + include/Engine/Core/ComponentPool.h | 4 +- include/Engine/Core/ComponentWrapper.h | 72 ++++++++++------------ include/Engine/Core/MemoryPool.h | 21 ++++++- src/Engine/Core/ComponentPool.cpp | 35 ++++++++++- src/Engine/Core/EntityFilePreprocessor.cpp | 3 + src/Engine/Core/World.cpp | 1 + 7 files changed, 89 insertions(+), 48 deletions(-) diff --git a/include/Engine/Core/ComponentInfo.h b/include/Engine/Core/ComponentInfo.h index d9799059..3383f297 100644 --- a/include/Engine/Core/ComponentInfo.h +++ b/include/Engine/Core/ComponentInfo.h @@ -27,6 +27,7 @@ struct ComponentInfo std::string Name; std::unordered_map Fields; std::vector FieldsInOrder; + std::vector StringFields; unsigned int Stride = 0; std::shared_ptr Defaults = nullptr; std::shared_ptr Meta = nullptr; diff --git a/include/Engine/Core/ComponentPool.h b/include/Engine/Core/ComponentPool.h index 957b8756..aedfd06b 100644 --- a/include/Engine/Core/ComponentPool.h +++ b/include/Engine/Core/ComponentPool.h @@ -1,6 +1,7 @@ #ifndef ComponentPool_h__ #define ComponentPool_h__ +#include #include "MemoryPool.h" #include "ComponentInfo.h" #include "ComponentWrapper.h" @@ -45,7 +46,8 @@ public: : m_ComponentInfo(ci) , m_Pool(ci.Meta->Allocation, sizeof(EntityID) + ci.Stride) { } - ComponentPool(const ComponentPool& other) = delete; + ~ComponentPool(); + ComponentPool(const ComponentPool& other); ComponentPool(const ComponentPool&& other) = delete; const ::ComponentInfo& ComponentInfo() const { return m_ComponentInfo; } diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index 0b9f7357..3ebad94a 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -7,6 +7,23 @@ #include "ComponentInfo.h" #include "Util/Any.h" +template +struct ComponentField { }; + +template +struct ComponentField::value>::type> +{ + static T& Get(const ComponentInfo::Field_t& info, char* data) { return *reinterpret_cast(data); } + static void Set(const ComponentInfo::Field_t& info, char* data, const T& value) { Get(data) = value; } +}; + +template <> +struct ComponentField +{ + static std::string& Get(const ComponentInfo::Field_t& info, char* data) { return **reinterpret_cast(data); } + static void Set(const ComponentInfo::Field_t& info, char* data, const std::string& value) { Get(info, data) = value; } +}; + struct ComponentWrapper { ComponentWrapper(const ComponentInfo& componentInfo, char* data) @@ -47,7 +64,20 @@ struct ComponentWrapper void Copy(ComponentWrapper& destination) { - memcpy(destination.Data, this->Data, Info.Stride); + // Copy trivial data + memcpy(destination.Data, Data, Info.Stride); + // Duplicate strings + SolidifyStrings(destination); + } + + // When component data has been copied, strings need to be reconstructed or they'll refer to the same data! + static void SolidifyStrings(ComponentWrapper& component) + { + for (auto& name : component.Info.StringFields) { + std::size_t offset = component.Info.Fields.at(name).Offset; + auto& value = *reinterpret_cast(component.Data + offset); + new (component.Data + offset) std::string(value); + } } struct SubscriptProxy @@ -94,44 +124,4 @@ private: boost::shared_array m_DataReference; }; -// TODO: Move this to Tests once entity importing is finished -class ComponentWrapperFactory -{ -public: - ComponentWrapperFactory() = default; - ComponentWrapperFactory(std::string componentTypeName, unsigned int allocation = 0) - { - m_ComponentInfo.Name = componentTypeName; - m_ComponentInfo.Meta->Allocation = allocation; - } - - template - void AddProperty(std::string fieldName, T defaultValue) - { - m_DefaultValues.push_back(defaultValue); - m_ComponentInfo.Fields[fieldName].Type = typeid(T).name(); - m_ComponentInfo.Fields[fieldName].Offset = m_ComponentInfo.Stride; - m_ComponentInfo.Fields[fieldName].Stride = sizeof(T); - m_ComponentInfo.Stride += sizeof(T); - } - - ComponentInfo& Finalize() - { - m_ComponentInfo.Defaults = std::shared_ptr(new char[m_ComponentInfo.Stride]); - std::size_t offset = 0; - for (auto& val : m_DefaultValues) { - memcpy(m_ComponentInfo.Defaults.get() + offset, val.Data.get(), val.Size); - offset += val.Size; - } - - return m_ComponentInfo; - } - - operator ComponentInfo&() { return Finalize(); } - -private: - ComponentInfo m_ComponentInfo; - std::vector m_DefaultValues; -}; - #endif diff --git a/include/Engine/Core/MemoryPool.h b/include/Engine/Core/MemoryPool.h index f4073294..0cf7b6bf 100644 --- a/include/Engine/Core/MemoryPool.h +++ b/include/Engine/Core/MemoryPool.h @@ -66,9 +66,24 @@ public: , m_LowestAllocatedSlot(m_NumSlots) { } - //We may get problems with memory being released - //prematurely, etc. if we allow copies. - MemoryPool(const MemoryPool& other) = delete; + MemoryPool(const MemoryPool& other) + : m_StartAddress(new char[other.m_NumSlots*other.m_Stride]) + , m_SlotIsAllocated(other.m_NumSlots, false) + , m_NumSlots(other.m_NumSlots) + , m_Stride(other.m_Stride) + , m_NumAllocatedSlots(0) + , m_CurrentAllocSlot(0) + , m_LowestAllocatedSlot(m_NumSlots) + { + // Copy statically allocated pool + memcpy(m_StartAddress, other.m_StartAddress, m_NumSlots*m_Stride); + // Copy dynamically allocated memory + for (char* otherAddr : other.m_ExtraMemory) { + char* addr = (char*)malloc(m_Stride); + memcpy(addr, otherAddr, m_Stride); + m_ExtraMemory.push_back(addr); + } + } MemoryPool(const MemoryPool&& other) = delete; //Free all memory that has been allocated. diff --git a/src/Engine/Core/ComponentPool.cpp b/src/Engine/Core/ComponentPool.cpp index 7b465fbc..bc4aab7e 100644 --- a/src/Engine/Core/ComponentPool.cpp +++ b/src/Engine/Core/ComponentPool.cpp @@ -1,7 +1,5 @@ #include "Core/ComponentPool.h" - - ComponentWrapper ComponentPoolForwardIterator::operator*() const { char* data = &(*m_MemoryPoolIterator); @@ -32,6 +30,28 @@ ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++() return *this; } +ComponentPool::ComponentPool(const ComponentPool& other) + : m_ComponentInfo(other.m_ComponentInfo) + , m_Pool(other.m_Pool) +{ + // Duplicate strings + for (auto& name : m_ComponentInfo.StringFields) { + for (auto& c : *this) { + ComponentWrapper::SolidifyStrings(c); + } + } +} + +ComponentPool::~ComponentPool() +{ + // Call std::string destructors + for (auto& name : m_ComponentInfo.StringFields) { + for (auto& c : *this) { + c.Field(name).~basic_string(); + } + } +} + //const ::ComponentInfo& ComponentPool::ComponentInfo() const //{ // return m_ComponentInfo; @@ -39,10 +59,19 @@ ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++() ComponentWrapper ComponentPool::Allocate(EntityID entity) { + // Allocate pool data char* data = m_Pool.Allocate(); + // Copy EntityID memcpy(data, &entity, sizeof(EntityID)); + m_EntityToComponent[entity] = data; - return ComponentWrapper(m_ComponentInfo, data); + ComponentWrapper component(m_ComponentInfo, data); + + // Copy defaults + memcpy(component.Data, m_ComponentInfo.Defaults.get(), m_ComponentInfo.Stride); + ComponentWrapper::SolidifyStrings(component); + + return component; } ComponentWrapper ComponentPool::GetByEntity(EntityID ent) diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index a1370dd2..c3a90c29 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -185,6 +185,9 @@ void EntityFilePreprocessor::parseComponentInfo() field.Offset = fieldOffset; field.Stride = stride; compInfo.FieldsInOrder.push_back(name); + if (field.Type == "string") { + compInfo.StringFields.push_back(name); + } fieldOffset += stride; } diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 69c25f61..79f210ea 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -48,6 +48,7 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp ComponentWrapper c = pool->Allocate(entity); // Write default values memcpy(c.Data, ci.Defaults.get(), ci.Stride); + ComponentWrapper::SolidifyStrings(c); return c; } From ca907b912e69488023aa589dfe0f43c564a4b908 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 18 Feb 2016 13:54:32 +0100 Subject: [PATCH 18/28] Copy constructor for deep copy of World. --- include/Engine/Core/World.h | 1 + src/Engine/Core/World.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/Engine/Core/World.h b/include/Engine/Core/World.h index 35394b9f..1604df37 100644 --- a/include/Engine/Core/World.h +++ b/include/Engine/Core/World.h @@ -15,6 +15,7 @@ public: : m_EventBroker(eventBroker) { } ~World(); + World(const World& other); // Create empty entity EntityID CreateEntity(EntityID parent = 0); diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 79f210ea..a0223e02 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -9,6 +9,15 @@ World::~World() } } +World::World(const World& other) + : m_EventBroker(other.m_EventBroker) +{ + // Deep copy component pools + for (auto& kv : m_ComponentPools) { + m_ComponentPools[kv.first] = new ComponentPool(*kv.second); + } +} + EntityID World::CreateEntity(EntityID parent /*= 0*/) { EntityID newEntity = generateEntityID(); From e15a7b9485474d999769efe5a64d6b2abe052cf9 Mon Sep 17 00:00:00 2001 From: Tleety Date: Thu, 18 Feb 2016 18:00:26 +0100 Subject: [PATCH 19/28] You can now change resolution without any apparent bugs. --- include/Engine/Rendering/DrawFinalPass.h | 2 +- include/Engine/Rendering/LightCullingPass.h | 1 + include/Engine/Rendering/PickingPass.h | 2 + include/Engine/Rendering/Renderer.h | 7 ++ .../Schema/Entities/QualityAssurance.xml | 76 +++++++++++++------ src/Engine/GUI/MainMenuSystem.cpp | 8 +- src/Engine/Rendering/DrawFinalPass.cpp | 10 ++- src/Engine/Rendering/FrameBuffer.cpp | 4 +- src/Engine/Rendering/LightCullingPass.cpp | 7 ++ src/Engine/Rendering/PickingPass.cpp | 9 +++ src/Engine/Rendering/Renderer.cpp | 16 +++- 11 files changed, 108 insertions(+), 34 deletions(-) diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index bf8d4d76..1d91f6a2 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -20,6 +20,7 @@ public: void InitializeShaderPrograms(); void Draw(RenderScene& scene); void ClearBuffer(); + void OnWindowResize(); //Return the texture that is used in later stages to apply the bloom effect GLuint BloomTexture() const { return m_BloomTexture; } @@ -31,7 +32,6 @@ public: FrameBuffer* FinalPassFrameBuffer() { return &m_FinalPassFrameBuffer; } FrameBuffer* FinalPassFrameBufferLowRes() { return &m_FinalPassFrameBufferLowRes; } - private: void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; void GenerateMipMapTexture(GLuint* texture, GLenum wrapping, glm::vec2 dimensions, GLint format, GLenum type, GLint numMipMaps) const; diff --git a/include/Engine/Rendering/LightCullingPass.h b/include/Engine/Rendering/LightCullingPass.h index d8852df0..914fb8bb 100644 --- a/include/Engine/Rendering/LightCullingPass.h +++ b/include/Engine/Rendering/LightCullingPass.h @@ -21,6 +21,7 @@ public: void SetSSBOSizes(); void CullLights(RenderScene& scene); void FillLightList(RenderScene& scene); + void OnWindowResize(); GLuint FrustumSSBO() const { return m_FrustumSSBO; } GLuint LightSSBO() const { return m_LightSSBO; } diff --git a/include/Engine/Rendering/PickingPass.h b/include/Engine/Rendering/PickingPass.h index d7a340f1..f6434781 100644 --- a/include/Engine/Rendering/PickingPass.h +++ b/include/Engine/Rendering/PickingPass.h @@ -22,6 +22,8 @@ public: void Draw(RenderScene& scene); void ClearPicking(); + void OnWindowResize(); + //Getters const ShaderProgram& PickingProgram() const { return *m_PickingProgram; } //const std::unordered_map& PickingColorsToEntity() const { return m_PickingColorsToEntity; } diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 04754514..fc1b6939 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -26,6 +26,8 @@ class Renderer : public IRenderer { + static void glfwFrameBufferCallback(GLFWwindow* window, int width, int height); + public: Renderer(EventBroker* eventBroker) : m_EventBroker(eventBroker) @@ -37,8 +39,12 @@ public: virtual PickData Pick(glm::vec2 screenCoord) override; + private: //----------------------Variables----------------------// + + static std::unordered_map m_WindowToRenderer; + EventBroker* m_EventBroker; TextPass* m_TextPass; @@ -50,6 +56,7 @@ private: Model* m_UnitSphere; int m_DebugTextureToDraw = 0; + bool m_ResizeWindow = false; PickingPass* m_PickingPass; LightCullingPass* m_LightCullingPass; diff --git a/resources/Schema/Entities/QualityAssurance.xml b/resources/Schema/Entities/QualityAssurance.xml index 762da931..0aa2fbe7 100644 --- a/resources/Schema/Entities/QualityAssurance.xml +++ b/resources/Schema/Entities/QualityAssurance.xml @@ -40,7 +40,7 @@ - + @@ -93,7 +93,7 @@ - + @@ -168,7 +168,7 @@ - + @@ -213,7 +213,7 @@ - + @@ -277,7 +277,7 @@ - + @@ -309,7 +309,7 @@ - + @@ -659,7 +659,7 @@ - + @@ -706,7 +706,7 @@ - + @@ -766,7 +766,7 @@ - + @@ -813,7 +813,7 @@ - + @@ -859,7 +859,7 @@ - + @@ -906,7 +906,7 @@ - + @@ -953,7 +953,7 @@ - + @@ -1367,7 +1367,7 @@ - + @@ -1376,7 +1376,7 @@ true - 2.6831806538294813 + 0.8256214817261025 3.7999999523162842 true @@ -1423,7 +1423,7 @@ - + @@ -1432,7 +1432,7 @@ - 1.9833111709021125 + 1.8641349174045843 Models/Characters/Assault/AssaultTPose.mesh @@ -1475,7 +1475,7 @@ - + @@ -1486,7 +1486,7 @@ true - 1.9833111709021125 + 1.8641349174045843 true @@ -1531,7 +1531,7 @@ - + @@ -1541,7 +1541,7 @@ true - 1.05003269646582 + 1.2301962937648341 10 3 @@ -1589,7 +1589,7 @@ - + @@ -1599,7 +1599,7 @@ true - 0.75001660742393028 + 3.4214855659573402 true 5 true @@ -1780,7 +1780,7 @@ true - 2.6831806538294813 + 0.8256214817261025 3.7999999523162842 true @@ -2421,6 +2421,34 @@ + + + + + Textures/Core/White.png + + + + + + + + + + + FullScreen + Fonts/DroidSans.ttf,64 + + + + + + + + + + + diff --git a/src/Engine/GUI/MainMenuSystem.cpp b/src/Engine/GUI/MainMenuSystem.cpp index 68db7b60..f8bf032b 100644 --- a/src/Engine/GUI/MainMenuSystem.cpp +++ b/src/Engine/GUI/MainMenuSystem.cpp @@ -27,15 +27,17 @@ bool MainMenuSystem::OnButtonClick(const Events::ButtonClicked& e) printf("No, you stay"); } else if (e.EntityName == "Res1080") { glfwSetWindowSize(m_Renderer->Window(), 1920, 1080); - printf("1080"); + printf("\n1080"); } else if (e.EntityName == "Res720") { glfwSetWindowSize(m_Renderer->Window(), 1280, 720); glViewport(0, 0, 1280, 720); - printf("720"); + printf("\n720"); } else if (e.EntityName == "Res480") { glfwSetWindowSize(m_Renderer->Window(), 854, 480); glViewport(0, 0, 854, 480); - printf("480"); + printf("\n480"); + } else if (e.EntityName == "FullScreen") { + printf("No fullscreen for now"); } return true; diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index fd95ecee..e907c6de 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -274,6 +274,12 @@ void DrawFinalPass::ClearBuffer() m_FinalPassFrameBuffer.Unbind(); } + +void DrawFinalPass::OnWindowResize() +{ + InitializeFrameBuffers(); +} + void DrawFinalPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const { glGenTextures(1, texture); @@ -702,7 +708,7 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrProjectionMatrix())); GLERROR("Bind 4 uniform"); - glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); + glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); GLERROR("Bind 5 uniform"); glUniform3fv(glGetUniformLocation(shaderHandle, "ExplosionOrigin"), 1, glm::value_ptr(job->ExplosionOrigin)); @@ -754,7 +760,7 @@ void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptrResolution().Width, m_Renderer->Resolution().Height); + glUniform2f(Location_ScreenDimensions, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); GLERROR("Bind 5 uniform"); GLint Location_FillPercentage = glGetUniformLocation(shaderHandle, "FillPercentage"); diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index c0be4cb1..09ca6161 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -72,9 +72,7 @@ void FrameBuffer::Generate() GLenum* bufferTextures = &attachments[0]; glDrawBuffers(attachments.size(), bufferTextures); - if(GLERROR("4")) { - printf("hello"); - } + GLERROR("GLBufferAttachement error"); if (GLenum frameBufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { GLERROR("Framebuffer incomplete"); diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index 0ae359db..d7a577a4 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -110,6 +110,13 @@ void LightCullingPass::FillLightList(RenderScene& scene) } } + +void LightCullingPass::OnWindowResize() +{ + SetSSBOSizes(); + InitializeSSBOs(); +} + void LightCullingPass::InitializeSSBOs() { glGenBuffers(1, &m_FrustumSSBO); diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index a979eb0e..88b18ecb 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -15,6 +15,8 @@ PickingPass::~PickingPass() } + + void PickingPass::InitializeTextures() { GenerateTexture(&m_PickingTexture, GL_CLAMP_TO_BORDER, GL_LINEAR, @@ -365,6 +367,13 @@ void PickingPass::ClearPicking() m_PickingBuffer.Unbind(); } + +void PickingPass::OnWindowResize() +{ + InitializeTextures(); + InitializeFrameBuffers(); +} + PickData PickingPass::Pick(glm::vec2 screenCoord) { int fbWidth; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 0ba25128..8f9d37ec 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -1,5 +1,7 @@ #include "Rendering/Renderer.h" +std::unordered_map Renderer::m_WindowToRenderer; + void Renderer::Initialize() { InitializeWindow(); @@ -12,7 +14,6 @@ void Renderer::Initialize() m_TextPass = new TextPass(); m_TextPass->Initialize(); - /* m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); m_UnitSphere = ResourceManager::Load("Models/Core/UnitSphere.obj");*/ @@ -20,6 +21,16 @@ void Renderer::Initialize() m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker); } +void Renderer::glfwFrameBufferCallback(GLFWwindow* window, int width, int height) +{ + glViewport(0, 0, width, height); + Renderer* currentRenderer = m_WindowToRenderer[window]; + currentRenderer->m_ViewportSize = Rectangle(width, height); + currentRenderer->m_DrawFinalPass->OnWindowResize(); + currentRenderer->m_LightCullingPass->OnWindowResize(); + currentRenderer->m_PickingPass->OnWindowResize(); +} + void Renderer::InitializeWindow() { // Initialize GLFW @@ -39,6 +50,7 @@ void Renderer::InitializeWindow() LOG_ERROR("GLFW: Failed to create window"); exit(EXIT_FAILURE); } + glfwSetFramebufferSizeCallback(m_Window, &glfwFrameBufferCallback); glfwMakeContextCurrent(m_Window); // GL version info @@ -59,6 +71,8 @@ void Renderer::InitializeWindow() exit(EXIT_FAILURE); } + m_WindowToRenderer[m_Window] = this; + int windowSize[2]; glfwGetFramebufferSize(m_Window, &windowSize[0], &windowSize[1]); m_ViewportSize = Rectangle(windowSize[0], windowSize[1]); From 8c9f4bb84b47ea075bbaa3e3ca83045d036df861 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 19 Feb 2016 11:42:52 +0100 Subject: [PATCH 20/28] Resize should now be working correctly. --- include/Engine/Rendering/DrawBloomPass.h | 2 ++ src/Engine/Rendering/DrawBloomPass.cpp | 9 +++++++++ src/Engine/Rendering/DrawFinalPass.cpp | 17 ++++++++++++++++- src/Engine/Rendering/FrameBuffer.cpp | 4 +++- src/Engine/Rendering/LightCullingPass.cpp | 23 ++++++++++++++++++++++- src/Engine/Rendering/PickingPass.cpp | 4 +++- src/Engine/Rendering/Renderer.cpp | 1 + 7 files changed, 56 insertions(+), 4 deletions(-) diff --git a/include/Engine/Rendering/DrawBloomPass.h b/include/Engine/Rendering/DrawBloomPass.h index 539d6957..a5d6b578 100644 --- a/include/Engine/Rendering/DrawBloomPass.h +++ b/include/Engine/Rendering/DrawBloomPass.h @@ -24,6 +24,8 @@ public: void Draw(GLuint texture); + void OnWindowRezise(); + //Getters //Return the blurred result of the texture that was sent into draw GLuint GaussianTexture() const { return m_GaussianTexture_vert; } diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 46612d5e..23080a52 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -121,6 +121,15 @@ void DrawBloomPass::Draw(GLuint texture) GLERROR("DrawBloomPass::Draw: END"); } + +void DrawBloomPass::OnWindowRezise() +{ + GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + m_GaussianFrameBuffer_vert.Generate(); + GenerateTexture(&m_GaussianTexture_horiz, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + m_GaussianFrameBuffer_horiz.Generate(); +} + void DrawBloomPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const { glGenTextures(1, texture); diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index e907c6de..4cb85deb 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -277,7 +277,22 @@ void DrawFinalPass::ClearBuffer() void DrawFinalPass::OnWindowResize() { - InitializeFrameBuffers(); + //InitializeFrameBuffers(); + glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + + GenerateTexture(&m_SceneTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + GenerateTexture(&m_BloomTexture, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); + m_FinalPassFrameBuffer.Generate(); + + + glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBufferLowRes); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)); + + GenerateTexture(&m_SceneTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), GL_RGB16F, GL_RGB, GL_FLOAT); + GenerateTexture(&m_BloomTextureLowRes, GL_CLAMP_TO_EDGE, GL_NEAREST, glm::vec2((int)(m_Renderer->GetViewportSize().Width/m_ShieldPixelRate), (int)(m_Renderer->GetViewportSize().Height/m_ShieldPixelRate)), GL_RGB16F, GL_RGB, GL_FLOAT); + m_FinalPassFrameBufferLowRes.Generate(); + GLERROR("Error changing texture resolutions"); } void DrawFinalPass::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const diff --git a/src/Engine/Rendering/FrameBuffer.cpp b/src/Engine/Rendering/FrameBuffer.cpp index 09ca6161..794fb84e 100644 --- a/src/Engine/Rendering/FrameBuffer.cpp +++ b/src/Engine/Rendering/FrameBuffer.cpp @@ -72,7 +72,9 @@ void FrameBuffer::Generate() GLenum* bufferTextures = &attachments[0]; glDrawBuffers(attachments.size(), bufferTextures); - GLERROR("GLBufferAttachement error"); + if (GLERROR("GLBufferAttachement error")) { + printf(": AttachmentSize %i", attachments.size()); + } if (GLenum frameBufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { GLERROR("Framebuffer incomplete"); diff --git a/src/Engine/Rendering/LightCullingPass.cpp b/src/Engine/Rendering/LightCullingPass.cpp index d7a577a4..1ce1f88c 100644 --- a/src/Engine/Rendering/LightCullingPass.cpp +++ b/src/Engine/Rendering/LightCullingPass.cpp @@ -114,7 +114,28 @@ void LightCullingPass::FillLightList(RenderScene& scene) void LightCullingPass::OnWindowResize() { SetSSBOSizes(); - InitializeSSBOs(); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_FrustumSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Frustum)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY); + GLERROR("m_FrustumSSBO"); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightSource) * 200, nullptr, GL_DYNAMIC_COPY); + GLERROR("m_LightSSBO"); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightGridSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(LightGrid)*m_NumberOfTiles, nullptr, GL_DYNAMIC_COPY); + GLERROR("m_LightGridSSBO"); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightOffsetSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(m_LightOffset), &m_LightOffset, GL_DYNAMIC_COPY); + GLERROR("m_LightOffsetSSBO"); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_LightIndexSSBO); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float)*m_NumberOfTiles*MAX_LIGHTS_PER_TILE, m_LightIndex, GL_DYNAMIC_COPY); + GLERROR("m_LightIndexSSBO"); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); } void LightCullingPass::InitializeSSBOs() diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 88b18ecb..40509d0c 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -371,7 +371,9 @@ void PickingPass::ClearPicking() void PickingPass::OnWindowResize() { InitializeTextures(); - InitializeFrameBuffers(); + glBindRenderbuffer(GL_RENDERBUFFER, m_DepthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height); + m_PickingBuffer.Generate(); } PickData PickingPass::Pick(glm::vec2 screenCoord) diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 8f9d37ec..e4627f01 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -29,6 +29,7 @@ void Renderer::glfwFrameBufferCallback(GLFWwindow* window, int width, int height currentRenderer->m_DrawFinalPass->OnWindowResize(); currentRenderer->m_LightCullingPass->OnWindowResize(); currentRenderer->m_PickingPass->OnWindowResize(); + currentRenderer->m_DrawBloomPass->OnWindowRezise(); } void Renderer::InitializeWindow() From fc5d054cb2bc9a7a6a5f08fca25f2f50eca9a4ba Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 19 Feb 2016 12:49:07 +0100 Subject: [PATCH 21/28] Entity is now sent with the click events. Fixed small things --- include/Engine/GUI/EButtonClicked.h | 3 ++- include/Engine/GUI/EButtonPressed.h | 3 ++- include/Engine/GUI/EButtonReleased.h | 4 +++- include/Engine/Rendering/ModelJob.h | 4 ++-- src/Engine/GUI/ButtonSystem.cpp | 11 ++++++++--- src/Engine/Rendering/DrawFinalPass.cpp | 4 ++-- 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/include/Engine/GUI/EButtonClicked.h b/include/Engine/GUI/EButtonClicked.h index f34d6b3d..e4fe7abe 100644 --- a/include/Engine/GUI/EButtonClicked.h +++ b/include/Engine/GUI/EButtonClicked.h @@ -7,7 +7,8 @@ namespace Events { struct ButtonClicked : public Event { - std::string EntityName = "DEFAULT STRING USED"; + std::string EntityName; + EntityWrapper Entity; }; } diff --git a/include/Engine/GUI/EButtonPressed.h b/include/Engine/GUI/EButtonPressed.h index 04d50978..3615ac8a 100644 --- a/include/Engine/GUI/EButtonPressed.h +++ b/include/Engine/GUI/EButtonPressed.h @@ -7,7 +7,8 @@ namespace Events { struct ButtonPressed : public Event { - std::string EntityName = "DEFAULT STRING USED"; + std::string EntityName; + EntityWrapper Entity; }; } diff --git a/include/Engine/GUI/EButtonReleased.h b/include/Engine/GUI/EButtonReleased.h index 14736ca0..90170518 100644 --- a/include/Engine/GUI/EButtonReleased.h +++ b/include/Engine/GUI/EButtonReleased.h @@ -6,7 +6,9 @@ namespace Events { -struct ButtonReleased : public Event { }; +struct ButtonReleased : public Event { + EntityWrapper Entity; +}; } diff --git a/include/Engine/Rendering/ModelJob.h b/include/Engine/Rendering/ModelJob.h index ccd0e093..8801d2eb 100644 --- a/include/Engine/Rendering/ModelJob.h +++ b/include/Engine/Rendering/ModelJob.h @@ -108,7 +108,7 @@ struct ModelJob : RenderJob EndIndex = matGroup->EndIndex; Matrix = matrix; Color = modelComponent["Color"]; - GlowIntencity = ((double)modelComponent["GlowIntensity"]); + GlowIntensity = ((double)modelComponent["GlowIntensity"]); Entity = modelComponent.EntityID; glm::vec3 abspos = Transform::AbsolutePosition(world, modelComponent.EntityID); glm::vec3 worldpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1)); @@ -171,7 +171,7 @@ struct ModelJob : RenderJob ::Skeleton::AnimationOffset AnimationOffset; - float GlowIntencity = 8.0; + float GlowIntensity = 8.0; glm::vec4 DiffuseColor; glm::vec4 SpecularColor; glm::vec4 IncandescenceColor; diff --git a/src/Engine/GUI/ButtonSystem.cpp b/src/Engine/GUI/ButtonSystem.cpp index dbdc0e18..7c66e456 100644 --- a/src/Engine/GUI/ButtonSystem.cpp +++ b/src/Engine/GUI/ButtonSystem.cpp @@ -38,6 +38,7 @@ bool ButtonSystem::OnMousePress(const Events::MousePress& e) //You have clicked on a button entity, send pressed event. Events::ButtonPressed ePressed; + ePressed.Entity = m_PickEntity; ePressed.EntityName = m_PickEntity.Name(); m_EventBroker->Publish(ePressed); } @@ -50,15 +51,19 @@ bool ButtonSystem::OnMouseRelease(const Events::MouseRelease& e) { if(!m_MouseIsLocked) { //Mouse is not locked, send release event. - Events::ButtonReleased eReleased; - m_EventBroker->Publish(eReleased); m_PickData = m_Renderer->Pick(glm::vec2(e.X, e.Y)); if(m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) { + EntityWrapper ent = EntityWrapper(m_World, m_PickData.Entity); + + Events::ButtonReleased eReleased; + eReleased.Entity = ent; + m_EventBroker->Publish(eReleased); + if(m_World->HasComponent(m_PickData.Entity, "Button")) { - EntityWrapper ent = EntityWrapper(m_World, m_PickData.Entity); if (ent == m_PickEntity) { //The entity you released the mouse button on is the same as you pressed it on. "Clicked" Events::ButtonClicked eClicked; + eClicked.Entity = m_PickEntity; eClicked.EntityName = m_PickEntity.Name(); m_EventBroker->Publish(eClicked); } diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index fd95ecee..54a523be 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -736,7 +736,7 @@ void DrawFinalPass::BindExplosionUniforms(GLuint shaderHandle, std::shared_ptrGlowIntencity); + glUniform1f(glGetUniformLocation(shaderHandle, "GlowIntensity"), job->GlowIntensity); GLERROR("END"); } @@ -775,7 +775,7 @@ void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptrGlowIntencity); + glUniform1f(Location_GlowIntensity, job->GlowIntensity); GLERROR("END"); } From 6e5335a266afa82a4a2a64e8d2b8244b93dae200 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 19 Feb 2016 13:16:26 +0100 Subject: [PATCH 22/28] Release now return name and entity of the entity that was previously klicked. --- include/Engine/GUI/EButtonReleased.h | 1 + src/Engine/GUI/ButtonSystem.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/Engine/GUI/EButtonReleased.h b/include/Engine/GUI/EButtonReleased.h index 90170518..ecd8dde2 100644 --- a/include/Engine/GUI/EButtonReleased.h +++ b/include/Engine/GUI/EButtonReleased.h @@ -7,6 +7,7 @@ namespace Events { struct ButtonReleased : public Event { + std::string EntityName; EntityWrapper Entity; }; diff --git a/src/Engine/GUI/ButtonSystem.cpp b/src/Engine/GUI/ButtonSystem.cpp index 7c66e456..93ae1811 100644 --- a/src/Engine/GUI/ButtonSystem.cpp +++ b/src/Engine/GUI/ButtonSystem.cpp @@ -56,7 +56,8 @@ bool ButtonSystem::OnMouseRelease(const Events::MouseRelease& e) EntityWrapper ent = EntityWrapper(m_World, m_PickData.Entity); Events::ButtonReleased eReleased; - eReleased.Entity = ent; + eReleased.EntityName = m_PickEntity.Name(); + eReleased.Entity = m_PickEntity; m_EventBroker->Publish(eReleased); if(m_World->HasComponent(m_PickData.Entity, "Button")) { From 722b795d3717cdfd8d087b18f79f2abda2fb9702 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 19 Feb 2016 13:30:41 +0100 Subject: [PATCH 23/28] Fixed spelling --- include/Engine/Rendering/DrawBloomPass.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Engine/Rendering/DrawBloomPass.h b/include/Engine/Rendering/DrawBloomPass.h index a5d6b578..07c90e23 100644 --- a/include/Engine/Rendering/DrawBloomPass.h +++ b/include/Engine/Rendering/DrawBloomPass.h @@ -24,7 +24,7 @@ public: void Draw(GLuint texture); - void OnWindowRezise(); + void OnWindowResize(); //Getters //Return the blurred result of the texture that was sent into draw From d135ea2da6cf7ccc2ee62a9272b30e2e476f22f5 Mon Sep 17 00:00:00 2001 From: Tleety Date: Fri, 19 Feb 2016 13:53:43 +0100 Subject: [PATCH 24/28] Small fix --- src/Engine/Rendering/DrawBloomPass.cpp | 2 +- src/Engine/Rendering/Renderer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Engine/Rendering/DrawBloomPass.cpp b/src/Engine/Rendering/DrawBloomPass.cpp index 23080a52..1855a653 100644 --- a/src/Engine/Rendering/DrawBloomPass.cpp +++ b/src/Engine/Rendering/DrawBloomPass.cpp @@ -122,7 +122,7 @@ void DrawBloomPass::Draw(GLuint texture) } -void DrawBloomPass::OnWindowRezise() +void DrawBloomPass::OnWindowResize() { GenerateTexture(&m_GaussianTexture_vert, GL_CLAMP_TO_EDGE, GL_LINEAR, glm::vec2(m_Renderer->GetViewportSize().Width, m_Renderer->GetViewportSize().Height), GL_RGB16F, GL_RGB, GL_FLOAT); m_GaussianFrameBuffer_vert.Generate(); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index d0c06ea0..b8665fce 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -29,7 +29,7 @@ void Renderer::glfwFrameBufferCallback(GLFWwindow* window, int width, int height currentRenderer->m_DrawFinalPass->OnWindowResize(); currentRenderer->m_LightCullingPass->OnWindowResize(); currentRenderer->m_PickingPass->OnWindowResize(); - currentRenderer->m_DrawBloomPass->OnWindowRezise(); + currentRenderer->m_DrawBloomPass->OnWindowResize(); } void Renderer::InitializeWindow() From 22664848dc44ab481a3dbe601c70132202262edf Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 19 Feb 2016 14:16:22 +0100 Subject: [PATCH 25/28] You should not be able to fall through ground or dash thru walls. Very thin objects may still be possible to go through, e.g. the grid border walls in GameMap.xml. --- include/Engine/Collision/CollisionSystem.h | 4 +- resources/Schema/Components/Physics.xml | 1 + resources/Schema/Components/Physics.xsd | 1 + src/Engine/Collision/Collision.cpp | 2 +- src/Engine/Collision/CollisionSystem.cpp | 59 ++++++++++++++++++++-- 5 files changed, 59 insertions(+), 8 deletions(-) diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index c963e6b8..9cd2fe63 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -15,11 +15,11 @@ class CollisionSystem : public PureSystem public: CollisionSystem(SystemParams params, Octree* octree) : System(params) - , PureSystem("Collidable") + , PureSystem("Physics") , m_Octree(octree) { } - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPhysics, double dt) override; private: Octree* m_Octree; diff --git a/resources/Schema/Components/Physics.xml b/resources/Schema/Components/Physics.xml index 6cb73c75..84b6aba3 100644 --- a/resources/Schema/Components/Physics.xml +++ b/resources/Schema/Components/Physics.xml @@ -2,6 +2,7 @@ true + false 0.33 diff --git a/resources/Schema/Components/Physics.xsd b/resources/Schema/Components/Physics.xsd index 7fed1fb5..206e2a23 100644 --- a/resources/Schema/Components/Physics.xsd +++ b/resources/Schema/Components/Physics.xsd @@ -13,6 +13,7 @@ m/s^2 + The largest height of a "stair-step" that can be walked over diff --git a/src/Engine/Collision/Collision.cpp b/src/Engine/Collision/Collision.cpp index ab2098b7..3aadf9fe 100644 --- a/src/Engine/Collision/Collision.cpp +++ b/src/Engine/Collision/Collision.cpp @@ -207,7 +207,7 @@ bool RayVsModel(const Ray& ray, glm::vec3 v0 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v1 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); glm::vec3 v2 = Transform::TransformPoint(modelVertices[modelIndices[i++]].Position, modelMatrix); - float dist = INFINITY; + float dist = outDistance; float u; float v; if (RayVsTriangle(ray, v0, v1, v2, dist, u, v)) { diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index afd09022..fcc3665f 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -3,24 +3,71 @@ #include "Core/AABB.h" #include "Rendering/Model.h" -void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) +void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cPhysics, double dt) { - if (!entity.HasComponent("Physics")) { + if (!entity.HasComponent("Collidable")) { return; } - ComponentWrapper& cPhysics = entity["Physics"]; - boost::optional boundingBox = Collision::EntityAbsoluteAABB(entity); if (!boundingBox) { return; } ComponentWrapper& cTransform = entity["Transform"]; EntityAABB& boxA = *boundingBox; + bool everHitTheGround = false; + + glm::vec3 size = boxA.Size(); + float diameter = std::min(size.x, size.z); + glm::vec3 prevOrigin = (glm::vec3)cPhysics["PrevOrigin"]; + glm::vec3 toCurrentPos = boxA.Origin() - prevOrigin; + float rayLength = glm::length(toCurrentPos) + 0.5f*diameter; + //If the entity has moved farther than the size of its box, we need to handle it specially. + bool traceCollision = rayLength > diameter; + //hack solution: If prevOrigin is less than -9000 in all dimensions, + //then it means it is not set, i.e. this is the first collision check for the entity. + if (traceCollision && glm::any(glm::greaterThan((glm::vec3)cPhysics["PrevOrigin"], glm::vec3(-9000.f)))) { + Ray ray(prevOrigin, toCurrentPos); + m_OctreeResult.clear(); + m_Octree->ObjectsPossiblyHitByRay(ray, m_OctreeResult); + for (auto& boxB : m_OctreeResult) { + if (boxA.Entity == boxB.Entity) { + continue; + } + bool hit; + float dist; + if (boxB.Entity.HasComponent("Model")) { + RawModel* model; + std::string res = (std::string)boxB.Entity["Model"]["Resource"]; + try { + model = ResourceManager::Load(res); + } catch (const std::exception&) { + continue; + } + float u, v; + hit = Collision::RayVsModel(ray, model->Vertices(), model->m_Indices, Transform::ModelMatrix(boxB.Entity), dist, u, v); + } else { + hit = Collision::RayVsAABB(ray, boxB, dist); + } + if (hit && dist < rayLength) { + //Set the entity to where it was colliding, minus the maximum box size. + //TODO: Perhaps this should be done slightly more properly. + glm::vec3 newOriginPos = ray.Origin() + (dist - 0.707107f*diameter) * ray.Direction(); + glm::vec3 resolve = newOriginPos - boxA.Origin(); + (glm::vec3&)cTransform["Position"] += resolve; + boxA = *Collision::EntityAbsoluteAABB(entity); + if (resolve.y > 0) { + everHitTheGround = true; + (bool)cPhysics["IsOnGround"] = true; + ((glm::vec3&)cPhysics["Velocity"]).y = 0.f; + } + break; + } + } + } // Collide against octree items m_OctreeResult.clear(); m_Octree->ObjectsInSameRegion(*boundingBox, m_OctreeResult); - bool everHitTheGround = false; for (auto& boxB : m_OctreeResult) { glm::vec3 resolutionVector; if (boxA.Entity == boxB.Entity) { @@ -64,4 +111,6 @@ void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& c if (!everHitTheGround) { (bool)cPhysics["IsOnGround"] = false; } + + (glm::vec3&)cPhysics["PrevOrigin"] = boxA.Origin(); } From 881ce7b02fc7ed0c67cd84544ea6069437c815d8 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Fri, 19 Feb 2016 14:37:14 +0100 Subject: [PATCH 26/28] Proper string handling without nasty memory leaks. PHEW. --- include/Engine/Core/ComponentInfo.h | 3 +- include/Engine/Core/ComponentWrapper.h | 66 +++++++++++++++++++++- include/Engine/Core/MemoryPool.h | 14 +++-- include/Engine/Core/Util/Any.h | 7 ++- src/Engine/Core/ComponentPool.cpp | 19 +++++-- src/Engine/Core/EntityFilePreprocessor.cpp | 2 +- src/Engine/Core/World.cpp | 13 +++-- src/Tests/WorldTest.cpp | 44 +++++++++++++++ 8 files changed, 144 insertions(+), 24 deletions(-) diff --git a/include/Engine/Core/ComponentInfo.h b/include/Engine/Core/ComponentInfo.h index 3383f297..137a44d8 100644 --- a/include/Engine/Core/ComponentInfo.h +++ b/include/Engine/Core/ComponentInfo.h @@ -2,6 +2,7 @@ #define ComponentInfo_h__ #include "../Common.h" +#include struct ComponentInfo { @@ -29,7 +30,7 @@ struct ComponentInfo std::vector FieldsInOrder; std::vector StringFields; unsigned int Stride = 0; - std::shared_ptr Defaults = nullptr; + boost::shared_array Defaults = nullptr; std::shared_ptr Meta = nullptr; }; diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index 3ebad94a..7897e874 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -2,6 +2,7 @@ #define ComponentWrapper_h__ #include +#include #include "../Common.h" #include "Entity.h" #include "ComponentInfo.h" @@ -75,10 +76,21 @@ struct ComponentWrapper { for (auto& name : component.Info.StringFields) { std::size_t offset = component.Info.Fields.at(name).Offset; - auto& value = *reinterpret_cast(component.Data + offset); + std::string value = *reinterpret_cast(component.Data + offset); new (component.Data + offset) std::string(value); } } + + // This needs to be called to properly free component data, because strings. + static void Destroy(ComponentInfo info, char* data) + { + // Call std::string destructors + for (auto& name : info.StringFields) { + std::size_t offset = info.Fields.at(name).Offset; + auto field = reinterpret_cast(data + offset); + field->~basic_string(); + } + } struct SubscriptProxy { @@ -124,4 +136,56 @@ private: boost::shared_array m_DataReference; }; +// TODO: Move this to Tests once entity importing is finished +class ComponentWrapperFactory +{ +public: + ComponentWrapperFactory() = default; + ComponentWrapperFactory(std::string componentTypeName, unsigned int allocation = 0) + { + m_ComponentInfo.Name = componentTypeName; + m_ComponentInfo.Meta = std::make_shared(); + m_ComponentInfo.Meta->Allocation = allocation; + } + + template + void AddProperty(std::string fieldName, T defaultValue) + { + auto& field = m_ComponentInfo.Fields[fieldName]; + field.Name = fieldName; + field.Type = typeid(T).name(); + field.Offset = m_ComponentInfo.Stride; + field.Stride = sizeof(T); + m_ComponentInfo.FieldsInOrder.push_back(field.Name); + if (field.Type == typeid(std::string).name()) { + field.Type = "string"; + m_ComponentInfo.StringFields.push_back(field.Name); + } + m_ComponentInfo.Stride += sizeof(T); + m_DefaultValues.push_back(std::make_pair(field, defaultValue)); + } + + ComponentInfo& Finalize() + { + m_ComponentInfo.Defaults = boost::shared_array(new char[m_ComponentInfo.Stride]); + std::size_t offset = 0; + for (auto& pair : m_DefaultValues) { + if (pair.first.Type == "string") { + new (m_ComponentInfo.Defaults.get() + offset) std::string(*reinterpret_cast(pair.second.Data.get())); + } else { + memcpy(m_ComponentInfo.Defaults.get() + offset, pair.second.Data.get(), pair.second.Size); + } + offset += pair.second.Size; + } + + return m_ComponentInfo; + } + + operator ComponentInfo&() { return Finalize(); } + +private: + ComponentInfo m_ComponentInfo; + std::vector> m_DefaultValues; +}; + #endif diff --git a/include/Engine/Core/MemoryPool.h b/include/Engine/Core/MemoryPool.h index 0cf7b6bf..053e75aa 100644 --- a/include/Engine/Core/MemoryPool.h +++ b/include/Engine/Core/MemoryPool.h @@ -68,12 +68,13 @@ public: MemoryPool(const MemoryPool& other) : m_StartAddress(new char[other.m_NumSlots*other.m_Stride]) - , m_SlotIsAllocated(other.m_NumSlots, false) + , m_SlotIsAllocated(other.m_SlotIsAllocated) + , m_ExtraMemory() , m_NumSlots(other.m_NumSlots) + , m_LowestAllocatedSlot(other.m_LowestAllocatedSlot) + , m_NumAllocatedSlots(other.m_NumAllocatedSlots) , m_Stride(other.m_Stride) - , m_NumAllocatedSlots(0) - , m_CurrentAllocSlot(0) - , m_LowestAllocatedSlot(m_NumSlots) + , m_CurrentAllocSlot(other.m_CurrentAllocSlot) { // Copy statically allocated pool memcpy(m_StartAddress, other.m_StartAddress, m_NumSlots*m_Stride); @@ -93,8 +94,9 @@ public: delete[] m_StartAddress; m_StartAddress = nullptr; } - for (char* addr : m_ExtraMemory) - free(addr); + for (char* addr : m_ExtraMemory) { + free(addr); + } m_ExtraMemory.clear(); } diff --git a/include/Engine/Core/Util/Any.h b/include/Engine/Core/Util/Any.h index f0f90737..e7b93dfb 100644 --- a/include/Engine/Core/Util/Any.h +++ b/include/Engine/Core/Util/Any.h @@ -2,6 +2,7 @@ #define Util_Any_h__ #include +#include struct Any { @@ -10,7 +11,7 @@ struct Any template Any(const T& value) { - Data = std::shared_ptr(new char[sizeof(T)]); + Data = boost::shared_array(new char[sizeof(T)]); Size = sizeof(T); memcpy(Data.get(), &value, Size); } @@ -18,7 +19,7 @@ struct Any template Any(T&& value) { - Data = std::shared_ptr(new char[sizeof(T)]); + Data = boost::shared_array(new char[sizeof(T)]); Size = sizeof(T); memcpy(Data.get(), &value, Size); } @@ -35,7 +36,7 @@ struct Any return Any(value); } - std::shared_ptr Data = nullptr; + boost::shared_array Data = nullptr; std::size_t Size = 0; }; diff --git a/src/Engine/Core/ComponentPool.cpp b/src/Engine/Core/ComponentPool.cpp index bc4aab7e..059b2e38 100644 --- a/src/Engine/Core/ComponentPool.cpp +++ b/src/Engine/Core/ComponentPool.cpp @@ -32,11 +32,19 @@ ComponentPoolForwardIterator& ComponentPoolForwardIterator::operator++() ComponentPool::ComponentPool(const ComponentPool& other) : m_ComponentInfo(other.m_ComponentInfo) - , m_Pool(other.m_Pool) + , m_Pool(other.m_Pool) + , m_EntityToComponent() { + // Update EntityToComponent pointers + for (char& ptr : m_Pool) { + EntityID entity = *reinterpret_cast(&ptr); + m_EntityToComponent[entity] = &ptr; + } + // Duplicate strings for (auto& name : m_ComponentInfo.StringFields) { for (auto& c : *this) { + std::string& val = c[name]; ComponentWrapper::SolidifyStrings(c); } } @@ -44,11 +52,9 @@ ComponentPool::ComponentPool(const ComponentPool& other) ComponentPool::~ComponentPool() { - // Call std::string destructors - for (auto& name : m_ComponentInfo.StringFields) { - for (auto& c : *this) { - c.Field(name).~basic_string(); - } + // Destroy component data + for (auto& c : *this) { + ComponentWrapper::Destroy(c.Info, c.Data); } } @@ -86,6 +92,7 @@ bool ComponentPool::KnowsEntity(EntityID ent) void ComponentPool::Delete(ComponentWrapper& wrapper) { + ComponentWrapper::Destroy(wrapper.Info, wrapper.Data); m_EntityToComponent.erase(wrapper.EntityID); m_Pool.Free(wrapper.Data - sizeof(EntityID)); } diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index c3a90c29..592daedb 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -204,7 +204,7 @@ void EntityFilePreprocessor::parseDefaults() for (auto& ci : m_ComponentInfo) { // Allocate memory for default values - ci.second.Defaults = std::shared_ptr(new char[ci.second.Stride]); + ci.second.Defaults = boost::shared_array(new char[ci.second.Stride], std::bind(&ComponentWrapper::Destroy, ci.second, std::placeholders::_1)); memset(ci.second.Defaults.get(), 0, ci.second.Stride); std::string componentName = ci.first; diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index a0223e02..8788a92e 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -11,14 +11,18 @@ World::~World() World::World(const World& other) : m_EventBroker(other.m_EventBroker) + , m_CurrentEntityID(other.m_CurrentEntityID) + , m_EntityParents(other.m_EntityParents) + , m_EntityChildren(other.m_EntityChildren) + , m_EntityNames(other.m_EntityNames) { // Deep copy component pools - for (auto& kv : m_ComponentPools) { + for (auto& kv : other.m_ComponentPools) { m_ComponentPools[kv.first] = new ComponentPool(*kv.second); } } -EntityID World::CreateEntity(EntityID parent /*= 0*/) +EntityID World::CreateEntity(EntityID parent /*= EntityID_Invalid*/) { EntityID newEntity = generateEntityID(); if (newEntity == parent) { @@ -53,11 +57,8 @@ ComponentWrapper World::AttachComponent(EntityID entity, const std::string& comp ComponentPool* pool = m_ComponentPools.at(componentType); const ComponentInfo& ci = pool->ComponentInfo(); - // Allocate space for the component + // Allocate component with default values ComponentWrapper c = pool->Allocate(entity); - // Write default values - memcpy(c.Data, ci.Defaults.get(), ci.Stride); - ComponentWrapper::SolidifyStrings(c); return c; } diff --git a/src/Tests/WorldTest.cpp b/src/Tests/WorldTest.cpp index 03008562..633e617a 100644 --- a/src/Tests/WorldTest.cpp +++ b/src/Tests/WorldTest.cpp @@ -69,3 +69,47 @@ BOOST_AUTO_TEST_CASE(WorldTestMultipleAllocations, * utf::tolerance(0.00001)) i++; } } + +BOOST_AUTO_TEST_CASE(WorldCopy, *utf::tolerance(0.00001)) +{ + World w1; + + // Create a test component + auto testComponent = ComponentWrapperFactory("Test", 2); + testComponent.AddProperty("TestInteger", 1337); + testComponent.AddProperty("TestDouble", 13.37); + testComponent.AddProperty("TestString", std::string("DefaultString")); + testComponent.AddProperty("TestVec3", glm::vec3(1.f, 2.f, 3.f)); + w1.RegisterComponent(testComponent); + + // Create a test entity + EntityID w1_e1 = w1.CreateEntity(); + auto w1_c1 = w1.AttachComponent(w1_e1, "Test"); + + // Create a child + EntityID w1_e2 = w1.CreateEntity(w1_e1); + auto w1_c2 = w1.AttachComponent(w1_e2, "Test"); + w1_c2["TestString"] = "NonDefaultString"; + + // Copy the world! + World w2 = w1; + + // Fetch the components + auto w2_c1 = w2.GetComponent(w1_e1, "Test"); + auto w2_c2 = w2.GetComponent(w1_e2, "Test"); + + // Check that built-in types are copied but don't reside in the same memory + BOOST_CHECK((int)w1_c1["TestInteger"] == (int)w2_c1["TestInteger"]); + BOOST_CHECK(&(int&)w1_c1["TestInteger"] != &(int&)w2_c1["TestInteger"]); + BOOST_CHECK((double)w1_c1["TestDouble"] == (double)w2_c1["TestDouble"]); + BOOST_CHECK(&(int&)w1_c1["TestDouble"] != &(int&)w2_c1["TestDouble"]); + BOOST_CHECK((int)w1_c2["TestInteger"] == (int)w2_c2["TestInteger"]); + BOOST_CHECK(&(int&)w1_c2["TestInteger"] != &(int&)w2_c2["TestInteger"]); + BOOST_CHECK((double)w1_c2["TestDouble"] == (double)w2_c2["TestDouble"]); + BOOST_CHECK(&(int&)w1_c2["TestDouble"] != &(int&)w2_c2["TestDouble"]); + // Check that specially handled strings are fine + BOOST_CHECK((std::string)w1_c1["TestString"] == (std::string)w2_c1["TestString"]); + BOOST_CHECK(&(std::string&)w1_c1["TestString"] != &(std::string&)w2_c1["TestString"]); + BOOST_CHECK((std::string)w1_c2["TestString"] == (std::string)w2_c2["TestString"]); + BOOST_CHECK(&(std::string&)w1_c2["TestString"] != &(std::string&)w2_c2["TestString"]); +} From 2263fd2ad66d546874e3ac1faf3045974162d4ec Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 19 Feb 2016 16:18:16 +0100 Subject: [PATCH 27/28] Fixed crash in Client::parsePlayerDamage. --- src/Engine/Network/Client.cpp | 5 +++-- src/Engine/Network/Server.cpp | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index 3406535a..a2f52adb 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -437,11 +437,12 @@ void Client::parsePlayerDamage(Packet& packet) { Events::PlayerDamage e; PlayerID victimID = packet.ReadPrimitive(); - if(serverClientMapsHasEntity(victimID)){ + PlayerID inflictorID = packet.ReadPrimitive(); + if(!serverClientMapsHasEntity(victimID) || !serverClientMapsHasEntity(inflictorID)){ return; } e.Inflictor = EntityWrapper(m_World, m_ServerIDToClientID.at(victimID)); - e.Victim = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive())); + e.Victim = EntityWrapper(m_World, m_ServerIDToClientID.at(inflictorID)); e.Damage = packet.ReadPrimitive(); // Don't rebroadcast our own player damage events or we'll have an infinite loop! if (e.Inflictor != m_LocalPlayer) { diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index 082849c7..aa66433b 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -84,7 +84,6 @@ void Server::Update() if (isReadingData) { Network::Update(); } - } void Server::parseMessageType(Packet& packet) From 68f2d5327d10338fac0a957e806853dc6ea05570 Mon Sep 17 00:00:00 2001 From: Jocke Date: Fri, 19 Feb 2016 16:37:26 +0100 Subject: [PATCH 28/28] added extra check in HealthSystem --- src/Game/Systems/HealthSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index 7f5089c4..94f23c67 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -24,7 +24,7 @@ void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cHea bool HealthSystem::OnPlayerDamaged(Events::PlayerDamage& e) { - if (!IsServer && m_NetworkEnabled) { + if (!IsServer && m_NetworkEnabled || !e.Victim.Valid()) { return false; }