Compare commits

...

144 Commits

Author SHA1 Message Date
verysecrethero deb6ff1b16 Changed some files so it works with the changes in master. (weaponsystem,capturepoint,some tests) 2016-01-21 17:36:47 +01:00
William Moberg 4d60f387ed Merge pull request #44 from teamfisk/EditorUsefulness
Editor refactoring
2016-01-21 17:03:52 +01:00
Jace f740d46683 Merge branch 'EditorUsefulness' of github.com:teamfisk/TacticalZ into EditorUsefulness 2016-01-21 17:01:06 +01:00
Jace 75dcdcec41 Fixed inconsistent editor input controls. Left mouse = select and move. Right mouse = camera. 2016-01-21 17:00:47 +01:00
viktorljung 254caf9e5d Picking depthbuffer fix 2016-01-21 16:49:20 +01:00
Jace 1c6750f5b0 Fixed uniform scale on editor widgets 2016-01-21 16:37:35 +01:00
William Moberg 3548cfa248 Merge pull request #27 from teamfisk/ShootEvent
Shoot event
2016-01-21 16:35:55 +01:00
verysecrethero 973ccd34c9 Removed unnecessary string in EPlayerDamage (TypeOfDamage). Renamed a variable in WeaponSystem 2016-01-21 16:30:07 +01:00
Jace 43b8fd29f6 Fixed widget world movement 2016-01-21 16:21:20 +01:00
Jace a6548a72b3 Merge remote-tracking branch 'origin/master' into EditorUsefulness
# Conflicts:
#	include/Engine/Collision/CollidableOctreeSystem.h
#	include/Engine/Collision/CollisionSystem.h
#	include/Engine/Collision/TriggerSystem.h
#	include/Engine/Rendering/RenderSystem.h
#	include/Game/Systems/PlayerSystem.h
#	resources/Schema/Components/Physics.xsd
#	resources/Schema/Types/Entity.xsd
#	src/Engine/Rendering/RenderSystem.cpp
#	src/Engine/Rendering/Renderer.cpp
#	src/Game/Game.cpp
#	src/Game/Systems/HealthSystem.cpp
#	src/Game/Systems/PlayerSystem.cpp
#	src/Tests/OctTreeTestGameClass.cpp
2016-01-21 16:16:35 +01:00
verysecrethero 7deb32431e Removed Color TestCode in WeaponSystem 2016-01-21 16:03:30 +01:00
Jace fc06a4babc Editor keyboard shortcuts:
Ctrl+S to save the currently selected entity file (iterates to the base parent)
Ctrl+N to create a new empty entity under the selection
Ctrl+O to import an entity file
Del to delete an entity
2016-01-21 15:58:27 +01:00
Tobias Dahl c6e9aad0c7 Merge pull request #42 from teamfisk/SpawnMiniBranch
HealthSystem now deletes the entity after publishing the PlayerDeath …
2016-01-21 15:10:16 +01:00
verysecrethero 2381f01d12 HealthSystem now deletes the entity after publishing the PlayerDeath event 2016-01-21 14:25:01 +01:00
Jace b9147344e1 Semi-working translation widget 2016-01-21 14:14:22 +01:00
Jace 0183e1bdb7 Fixed enum string parsing bug that would ignore parsing additional fields in a component after it encountered the first enum. 2016-01-21 12:24:08 +01:00
verysecrethero bdebc9de62 WeaponSystem now handles "PrimaryFire" input events. It sends out ePlayerDamage event if it hits a player. Included some tests 2016-01-21 11:55:51 +01:00
Jace f1345419b6 EditorWidgetSystem that takes care of moving widgets around 2016-01-21 10:30:19 +01:00
Jace 5e70d6eef6 EntityWrapper::Parent helper function 2016-01-21 10:29:48 +01:00
Jace 4aa9100c69 Camera::WorldToScreen helper function 2016-01-21 10:29:36 +01:00
verysecrethero 7b34e001ba Merge remote-tracking branch 'origin/master' into ShootEvent 2016-01-21 10:26:42 +01:00
verysecrethero c2e05de89f Deleted some components, etc for ShootEvent that will likely be used in a WeaponSystem instead 2016-01-21 10:24:34 +01:00
Jace 70cab9ef30 Merge pull request #40 from teamfisk/Networking
Networking
2016-01-21 10:03:44 +01:00
Jace f1a54a89b3 Merge pull request #37 from teamfisk/OctTree
Oct tree
2016-01-21 09:57:46 +01:00
verysecrethero b098bd2bd3 Merge remote-tracking branch 'origin/master' into ShootEvent
# Conflicts:
#	include/Engine/Core/ComponentWrapper.h
#	include/Game/PlayerSystem.h
#	include/Game/Systems/HealthSystem.h
#	resources/Schema/Components.xsd
#	resources/Schema/Components/Player.xml
#	resources/Schema/Types/Entity.xsd
#	src/Game/PlayerSystem.cpp
#	src/Tests/HealthSystemTest.cpp
#	src/Tests/OctTreeTestAnders.cpp
#	src/Tests/OctTreeTestGameClass.cpp
#	src/Tests/OctTreeTestGameClass.h
#	src/Tests/OctTreeTestHardCodedTestWorld.h
2016-01-20 17:53:33 +01:00
William Moberg 60037c2849 Merge pull request #31 from teamfisk/CapturePointTake
Capture point take
2016-01-20 17:43:20 +01:00
Jocke cd67253173 Added logic to go from spectator to player. 2016-01-20 17:41:16 +01:00
verysecrethero a596b8746b CapturePointTimers are now reset for "inactive" CapturePoints after a capture. 2016-01-20 17:32:20 +01:00
verysecrethero 35876f6425 Removed membervariable m_NextPossibleCapturePointand added it as local instead 2016-01-20 16:37:10 +01:00
verysecrethero f6ce98249e Merge remote-tracking branch 'origin/master' into CapturePointTake 2016-01-20 16:32:14 +01:00
Jocke 00588b07c5 Merge branch 'Networking' of github.com:teamfisk/TacticalZ into Networking
# Conflicts:
#	src/Engine/Network/Client.cpp
#	src/Engine/Network/Server.cpp
2016-01-20 16:30:12 +01:00
stiffly 3376f4a16e Added server has timed out logic to client. (>'')> 2016-01-20 16:27:53 +01:00
Jocke 25d2aa3464 "Supporting" spectators. Using a vector for connected units as we do not interpret as players. ““”̿ ̿ ̿ ̿ ̿’̿’̵͇̿̿з=(•̪●)=ε/̵͇̿̿/̿ ̿ ̿ ̿ ̿’““ 2016-01-20 16:27:23 +01:00
verysecrethero 29aefc5af2 Added some more visual CaptureTestState xml files 2016-01-20 16:06:35 +01:00
verysecrethero 39ae83efd4 Fixed all tests in CapturePointTest and cleaned up some comments 2016-01-20 15:40:56 +01:00
verysecrethero 8189e3c00c Logic in CapturePointSystem is working again. Need to update all Tests! 2016-01-20 14:59:18 +01:00
Jocke 4d01cdf895 Merge branch 'Networking' of github.com:teamfisk/TacticalZ into Networking
# Conflicts:
#	src/Engine/Network/Client.cpp
2016-01-20 14:33:17 +01:00
stiffly 7e7ca7edcf Listening to "DisconnectFromServer" 2016-01-20 14:32:04 +01:00
Jocke e9a576341e Started on server disconnect logic. 2016-01-20 14:31:50 +01:00
Jocke f52cddb445 Added packet loss logic for multiple clients.
Changed packet class to fit our needs.
2016-01-20 13:43:11 +01:00
stiffly 85523343b2 Merge remote-tracking branch 'origin/master' into Networking 2016-01-20 10:24:53 +01:00
William Moberg 410e349329 Added test map for capture points and some debug code. 2016-01-19 18:27:58 +01:00
verysecrethero b45de542da CapturePointSystem updated, all tests are green 2016-01-19 17:19:58 +01:00
Joachim Pettersson dfa96f74e1 Merge pull request #39 from teamfisk/Forward+
Forward+
2016-01-19 16:53:07 +01:00
Tleety 5d6d0f82b9 Removed some debug code 2016-01-19 16:48:59 +01:00
Tleety a124ab2400 Some asset shit.
Fixed testworld to use the right model.
2016-01-19 16:11:56 +01:00
Tleety d2263b0c90 Assets added 2016-01-19 16:09:30 +01:00
Tleety a8ffb24040 latest commit fix 2016-01-19 16:08:09 +01:00
Tleety 893ef38237 Removed world from renderer and moved depth-calculation code to modeljob 2016-01-19 15:41:17 +01:00
verysecrethero f197993beb Changed CapturePointSystem in light of new enums in the components and a teamcomponent. Half the tests are currently working 2016-01-19 15:31:15 +01:00
stiffly ad9bb5fba4 Added an extra interpolation point. 2016-01-19 15:03:10 +01:00
Tleety 982837052a DirectionalLight now correctly getting directions 2016-01-19 14:44:17 +01:00
Jace 8854794cbc fixup! Editor widget selection and creation 2016-01-19 14:31:56 +01:00
stiffly e0c4394f20 Merge. Also fixed interpolation for scale and rotation.
Merge remote-tracking branch 'origin/master' into Networking

# Conflicts:
#	include/Game/Game.h
#	src/Game/CMakeLists.txt
#	src/Game/Game.cpp
2016-01-19 14:04:25 +01:00
Jace 260203fa4d Annotation on physics component 2016-01-19 13:28:16 +01:00
Jace d030e8f699 Editor widget selection and creation 2016-01-19 13:28:02 +01:00
Jace 61984d2c4a Removed lots of slowing debug output from entity parsing pipeline 2016-01-19 13:27:29 +01:00
Jace cfe023cc1d Created ComponentInfo::EnumType which defines which native type to use for enums. 2016-01-19 12:33:53 +01:00
Tleety 4cafb2fc4c Merge remote-tracking branch 'origin/master' into Forward+ 2016-01-19 12:33:08 +01:00
Tleety 46e17b7e0d Working directional light 2016-01-19 12:32:34 +01:00
Jace a6445c65aa Fixed EntityParser to handle string enums properly. 2016-01-19 12:15:20 +01:00
Jace 162523d3ca Made EntityFileWriter store enums as strings instead of integer values to be resistant to enum value changes! 2016-01-19 11:55:27 +01:00
Jace 3fb975a8d9 Editor widget entities 2016-01-19 11:44:03 +01:00
Jace 267a60ef30 Better loading of editor toolbox icons 2016-01-19 11:43:38 +01:00
Jace 68af853a03 Editor entity naming 2016-01-19 11:43:03 +01:00
stiffly 3142c701e3 WIP interpolating scale and orientation 2016-01-19 11:42:30 +01:00
Jace b62e42567c Fixed editor enum selection 2016-01-19 11:35:31 +01:00
Jace 9e3dfff7b6 WIP world pausing 2016-01-19 00:52:17 +01:00
Jace 79eaa7364c Editor toolbox buttons 2016-01-18 23:59:46 +01:00
Jace 51979d7f0c Changed System to take World through constructor and store it instead, cause it makes more sense. 2016-01-18 23:59:33 +01:00
Jace 3fc44e944c Editor entity reparenting. 2016-01-18 21:20:20 +01:00
Jace 1760f9dfb1 Added inequality operator to EntityWrapper 2016-01-18 21:17:52 +01:00
Jace d4242bbead Editor entity create and delete. 2016-01-18 19:26:00 +01:00
Jace 631dd57eeb Editor entity import, save, delete, component attach, component delete. 2016-01-18 18:55:19 +01:00
Jace 9cb5f4bd2f Added a stats window 2016-01-18 18:54:57 +01:00
stiffly a6425160fd Merge branch 'Networking' of github.com:teamfisk/TacticalZ into Networking
# Conflicts:
#	include/Game/InterpolationSystem.h
#	src/Game/InterpolationSystem.cpp
2016-01-18 18:13:19 +01:00
stiffly 88eb3ca2db Scraping queues for interpolation 2016-01-18 18:07:59 +01:00
Jocke 3e90ed564c Moved Struct in InterpolationSystem.h and fixed bug. 2016-01-18 18:07:39 +01:00
Tleety 4b29d48f27 WIP 2016-01-18 17:57:45 +01:00
Jocke 14b1d541dc Merge remote-tracking branch 'origin/Networking' into Networking 2016-01-18 17:34:32 +01:00
stiffly 765509b510 Added interpolationsystem to pipeline. 2016-01-18 17:34:17 +01:00
Jocke 8952c1a7e4 Merge remote-tracking branch 'origin/Networking' into Networking 2016-01-18 17:28:09 +01:00
Jocke fc305f8bf4 Merge remote-tracking branch 'origin/Networking' into Networking 2016-01-18 17:27:55 +01:00
stiffly 62c3f72355 Fixed cmake for interpolationsystem. 2016-01-18 17:27:37 +01:00
Jocke 70cbb02cb2 Merge remote-tracking branch 'origin/Networking' into Networking 2016-01-18 17:13:10 +01:00
Jocke 0c7f2c5198 WIP implemented Interpolation (server logic) 2016-01-18 17:12:42 +01:00
stiffly d7780d8248 WIP implementing interpolation 2016-01-18 17:11:37 +01:00
Tleety 601ce85c05 WIP 2016-01-18 16:50:41 +01:00
verysecrethero 4c1a49a8a4 Merge remote-tracking branch 'origin/master' into CapturePointTake
# Conflicts:
#	include/Engine/Core/ComponentWrapper.h
#	include/Game/PlayerSystem.h
#	include/Game/Systems/HealthSystem.h
#	resources/Schema/Components.xsd
#	resources/Schema/Components/Player.xml
#	resources/Schema/Types/Entity.xsd
#	src/Game/CMakeLists.txt
#	src/Game/PlayerSystem.cpp
#	src/Game/Systems/HealthSystem.cpp
#	src/Tests/OctTreeTestGameClass.cpp
#	src/Tests/OctTreeTestGameClass.h
#	src/Tests/OctTreeTestGameMain.cpp
#	src/Tests/OctTreeTestHardCodedTestWorld.h
2016-01-18 16:48:49 +01:00
Tleety 01a164847c Directional light now fully added to all lists. 2016-01-18 15:15:33 +01:00
Tleety 794635b6a1 Added DirectionalLights to renderqueue jobs 2016-01-18 14:58:19 +01:00
Tleety 0a3b6f4da1 Added DirectionalLightJob 2016-01-18 14:57:55 +01:00
Jace 3bc7dceca5 Made EntityWrapper hashable 2016-01-18 14:55:49 +01:00
verysecrethero e0410d4345 Small logicfix in CapturePointSystem. Readded CapturePointSystem in Game. Added 2 tests. Tests have been refined a lot. 2016-01-18 14:41:16 +01:00
Tleety 6f1fd19ac7 Directional lights now being filled into m_LightSources 2016-01-18 14:30:28 +01:00
Tleety 6680f6863f DirectionalLight component added. 2016-01-18 14:30:22 +01:00
Tleety 4092f6b4d4 New Lightstruct working. 2016-01-18 14:20:28 +01:00
Jace 504f301e4d Added refactored property sheet for components 2016-01-18 13:51:22 +01:00
Jocke 6ba6deb863 Removed some debug spam. 2016-01-18 11:35:35 +01:00
stiffly cc604f8e9a Merge remote-tracking branch 'origin/Networking' into Networking 2016-01-18 11:06:51 +01:00
stiffly e97f4a3563 Merge remote-tracking branch 'origin/Networking' into Networking
# Conflicts:
#	src/Engine/Network/Client.cpp
#	src/Engine/Network/Server.cpp
#	src/Game/Game.cpp
2016-01-18 11:06:27 +01:00
Jocke d995713d3b Added input queue to Client and Input Listener debug code in server. 2016-01-18 11:06:02 +01:00
Jace e39e4064f2 Entity tree button mockup 2016-01-17 23:06:32 +01:00
Jace 0d50ede6f5 Base work on reimplementing editor GUI 2016-01-17 07:34:20 +01:00
Jace 4786986abd Rendering pipeline fixes across the board and base work on refactored editor 2016-01-17 06:29:25 +01:00
Jace e34856468a Removed DrawScenePass, since it doesn't seem to be used 2016-01-17 06:27:45 +01:00
Jace e2357b8625 Fixed absolute position not taking scale into account 2016-01-17 06:23:13 +01:00
Jace 6ec2258758 Added UniformScale component which keeps an entity's scale at a uniform value relative to the screen. 2016-01-17 06:22:35 +01:00
Jace 9f447afbdb Added EntityWrapper::Valid and bool overload to be check if an entity is valid and still exists in the world more easily 2016-01-17 06:20:27 +01:00
Jocke db62d767ac Fixed bug in Client::parseSnapshot(). 2016-01-15 12:06:20 +01:00
verysecrethero e7da11fda4 Removed OctTreeTests since its too annoying to update them each time RenderSystem gets updated 2016-01-15 11:31:21 +01:00
verysecrethero 8f257b9a58 Merge remote-tracking branch 'origin/master' into CapturePointTake
# Conflicts:
#	src/Game/Game.cpp
#	src/Tests/ResourceManagerTest.cpp
2016-01-15 11:24:20 +01:00
verysecrethero c8fe6853c0 Removed ShootEvent from CapturePoint 2016-01-15 11:17:22 +01:00
verysecrethero 76a8b43ca3 Fixed logic for CapturePointSystem 2016-01-15 11:04:00 +01:00
Jocke 0bf756dc08 Merge remote-tracking branch 'origin/master' into Networking 2016-01-15 10:22:21 +01:00
Jocke 696f44a673 Added logic for mapping between ServerEntityIDs and LocalEntityIDs removed old code that wasn't used.
Added 1 map to Client and renamed m_ServerToClientMap to m_ServerIDToClientID.

// Good to know
To keep this structure please use insertIntoServerClientMaps() when adding items to them.
m_ServerIDToClientID and m_ClientIDToServerID maps between server EntityIDs and local EntityIDs.
To see if a local EntityID exist in m_ClientIDToServerID use clientServerMapsHasEntity(EntityID clientEntityID);
To see if server EntityID exist in m_ServerIDToClientID use serverClientMapsHasEntity(EntityID serverEntityID);
2016-01-14 17:11:54 +01:00
verysecrethero 5e9a3774ab CapturePointSystem code has been refactored and some branches "optimized" 2016-01-14 10:23:27 +01:00
Jocke db18a45368 We are now sending EPlayerDamage events.
Client now listens to EPlayerDamage events and send them to Server.
Server publishes EPlayerDamage events received from Client.
2016-01-14 10:16:11 +01:00
Jocke a060640da3 Removed unnecessary unnecessary if in Client::OnInputCommand.
Change name from Server::parseEvent to Server::parseOnInputCommand
2016-01-13 18:00:12 +01:00
verysecrethero b8a41b7c13 Updated some CapturePointLogic in CapturePointSystem: reset timer on capture, being able to take back the progress the other team did on your capturepoint. TODO: refactor! 2016-01-13 17:07:49 +01:00
verysecrethero 9533920684 Fixed a few CodeStandard mistakes. Added CapturePointSystem to CMakeLists.txt since branch is no longer based on ShootEvent-branch 2016-01-13 16:13:57 +01:00
Jocke f47f913bf5 Added logic for sending input from Client to Server.
Fixed so that snapshots set their parent correctly. Will get problems if we have more components
than unsigned int max size, but that was already a problem.
Client now maps Entitys received from server with local Entitys by mapping their EntityIDs.
2016-01-13 16:09:16 +01:00
verysecrethero ed5ac2e923 6 new tests for CapturePointSystem have been created!
TODO: refactor CapturePointSystem
2016-01-13 15:58:52 +01:00
verysecrethero 7a8604bf2b CapturePointSystem now tracks and verifies if a capturePoint can be taken over. Also the time is changed faster the more players stand on the capturepoint (number*dt). Also took care of the problem when both teams have the same contested capturepoint.
Added variable in the CapturePoint component:  CapturePointNumber. This is needed since we cant know what capturepoint is next to be taken over otherwise.
Updated the CapturePointTest according to current CapturePointSystem
TODO: try to refactor code in CapturePointSystem
2016-01-13 15:58:52 +01:00
verysecrethero 3a1056a2c3 2 new Events: ECaptured, EWin
Added new variable in CapturePoint: IsHomeCapturePointForTeam
CapturePointSystem updated so -5 = team 2 owns it, +5 = team 1 owns it. Its also looking for a winner each update
Updated Test. TODO: better Tests
2016-01-13 15:58:52 +01:00
verysecrethero 59be714fdc 1 Component added: CapturePoint
1 System added: CapturePointSystem
1 Test added: CapturePointTest
added 1 variable in PlayerComponent (TeamNumber)
added 2 variables in CapturePoint (CaptureTimer,OwnedBy)
CapturePointSystem is now handling 2 events: OnTriggerTouch,OnTriggerLeave
Added the CapturePointSystem to Game.cpp
2016-01-13 15:58:52 +01:00
verysecrethero 147b116f20 Fixed typo backslash instead of slash in various classes (the includes) 2016-01-13 15:58:52 +01:00
verysecrethero f0b425614d Simplified PlayerSystem branches a lot! Thanks William! 2016-01-13 15:58:52 +01:00
verysecrethero 4b672b11e7 EquippedItem,Ammo got changed to int instead of double. Loading entities from map the new way in Tests. ComponentWrapper:s Name is now Type 2016-01-13 15:58:52 +01:00
verysecrethero e865971fdd EShoot: changed to string weaponType to int currentlyEquippedItem
PlayerSystem.h: added HeldItem enum
PlayerSystem.cpp: simplified writing doubles, uses HeldItem enum
ShootEventTest.cpp: simplified writing doubles
2016-01-13 15:58:52 +01:00
verysecrethero 878c71b56a Changed the comparison method in PlayerSystem since its currently using doubles 2016-01-13 15:58:52 +01:00
verysecrethero ec4d5fbfa8 xml/xsd files changed type to double. fixed cooldownbug in PlayerSystem. Added 4 tests in ShootEventTest and generalized it a lot 2016-01-13 15:58:52 +01:00
verysecrethero 184af95507 New Event: EShoot. New Components: PrimaryItem,SecondaryItem. New Test: ShootEventTest. Added LeftMouseRelease->Shoot in PlayerSystem
TODO: generalize the test
2016-01-13 15:58:52 +01:00
verysecrethero e6527196ed Modified a few files according to the current CodeStandards 2016-01-13 15:50:30 +01:00
verysecrethero c14f3789f7 PlayerSystem now counts down the CoolDownTimer on both HeldItems for the player. Updated ShootEventTest to verify this 2016-01-13 15:26:10 +01:00
verysecrethero a20ca49d53 Fixed typo backslash instead of slash in various classes (the includes) 2016-01-12 10:46:34 +01:00
verysecrethero 774bb8ce56 Simplified PlayerSystem branches a lot! Thanks William! 2016-01-11 17:36:23 +01:00
verysecrethero 0cc58f088a EquippedItem,Ammo got changed to int instead of double. Loading entities from map the new way in Tests. ComponentWrapper:s Name is now Type 2016-01-11 17:15:49 +01:00
verysecrethero 00805d30d0 Merge remote-tracking branch 'origin/master' into ShootEvent 2016-01-11 17:06:48 +01:00
verysecrethero 2f6261dfbf EShoot: changed to string weaponType to int currentlyEquippedItem
PlayerSystem.h: added HeldItem enum
PlayerSystem.cpp: simplified writing doubles, uses HeldItem enum
ShootEventTest.cpp: simplified writing doubles
2016-01-11 15:49:33 +01:00
verysecrethero 2cd0e94a60 Changed the comparison method in PlayerSystem since its currently using doubles 2016-01-11 15:49:33 +01:00
verysecrethero 8f92de3683 xml/xsd files changed type to double. fixed cooldownbug in PlayerSystem. Added 4 tests in ShootEventTest and generalized it a lot 2016-01-11 15:49:33 +01:00
verysecrethero 31c1c0ac8d New Event: EShoot. New Components: PrimaryItem,SecondaryItem. New Test: ShootEventTest. Added LeftMouseRelease->Shoot in PlayerSystem
TODO: generalize the test
2016-01-11 15:49:33 +01:00
stiffly 7ae42a5bf7 Removed some comments. Basically did nothing 2016-01-06 11:39:32 +01:00
142 changed files with 5109 additions and 2156 deletions
+1 -1
Submodule assets updated: a3c92ac876...6ffb46e155
@@ -8,14 +8,14 @@
class CollidableOctreeSystem : public ImpureSystem, public PureSystem
{
public:
CollidableOctreeSystem(EventBroker* eventBroker, Octree<AABB>* octree)
: System(eventBroker)
CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker)
, PureSystem("Collidable")
, m_Octree(octree)
{ }
virtual void Update(World* world, double dt) override;
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<AABB>* m_Octree;
+3 -3
View File
@@ -13,8 +13,8 @@
class CollisionSystem : public PureSystem
{
public:
CollisionSystem(EventBroker* eventBroker, Octree<AABB>* octree)
: System(eventBroker)
CollisionSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker)
, PureSystem("Collidable")
, m_Octree(octree)
, zPress(false)
@@ -23,7 +23,7 @@ public:
EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp);
}
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<AABB>* m_Octree;
+3 -3
View File
@@ -14,8 +14,8 @@ class AABB;
class TriggerSystem : public PureSystem
{
public:
TriggerSystem(EventBroker* eventBroker, Octree<AABB>* octree)
: System(eventBroker)
TriggerSystem(World* world, EventBroker* eventBroker, Octree<AABB>* octree)
: System(world, eventBroker)
, PureSystem("Trigger")
, m_Octree(octree)
{
@@ -24,7 +24,7 @@ public:
EVENT_SUBSCRIBE_MEMBER(m_ELeave, &TriggerSystem::OnLeave);
}
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
Octree<AABB>* m_Octree;
+1
View File
@@ -4,6 +4,7 @@
#include <vector>
#include <map>
#include <unordered_map>
#include <algorithm>
#include "Core/Util/Logging.h"
#include "Core/Util/IfDebug.h"
+3 -1
View File
@@ -5,12 +5,14 @@
struct ComponentInfo
{
typedef int EnumType;
struct Meta_t
{
std::string Annotation;
unsigned int Allocation = 0;
std::map<std::string, std::string> FieldAnnotations;
std::map<std::string, std::map<std::string, int>> FieldEnumDefinitions;
std::map<std::string, std::map<std::string, EnumType>> FieldEnumDefinitions;
};
struct Field_t
+1
View File
@@ -61,6 +61,7 @@ public:
iterator begin() const;
iterator end() const;
size_t size() const;
//Dumps information about what the pool memory looks like right now
//into an output stream (e.g. file/std::cout, anything that has an operator<<)
+3 -3
View File
@@ -18,7 +18,7 @@ struct ComponentWrapper
const ::EntityID EntityID;
char* Data;
int Enum(const char* fieldName, const char* enumKey)
ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey)
{
return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey);
}
@@ -58,7 +58,7 @@ struct ComponentWrapper
public:
// Return the integer value of an enum type key for this field
int Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); }
ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); }
template <typename T>
operator T&() { return m_Component->Field<T>(m_PropertyName); }
@@ -91,7 +91,7 @@ public:
void AddProperty(std::string fieldName, T defaultValue)
{
m_DefaultValues.push_back(defaultValue);
m_ComponentInfo.Fields[fieldName].Name = typeid(T).name();
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);
+20
View File
@@ -0,0 +1,20 @@
#ifndef ECaptured_h__
#define ECaptured_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a capturePoint has been taken over
struct Captured : Event
{
int TeamNumberThatCapturedCapturePoint;
EntityID CapturePointID;
};
}
#endif
+3
View File
@@ -11,6 +11,9 @@ struct KeyDown : Event
{
/** GLFW key code */
int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
};
}
+3
View File
@@ -11,6 +11,9 @@ struct KeyUp : Event
{
/** GLFW key code */
int KeyCode;
bool ModCtrl;
bool ModAlt;
bool ModShift;
};
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef EPause_h__
#define EPause_h__
#include "EventBroker.h"
#include "World.h"
namespace Events
{
struct Pause : Event
{
::World* World;
};
struct Resume : Event
{
::World* World;
};
}
#endif
-2
View File
@@ -11,8 +11,6 @@ struct PlayerDamage : Event
{
double DamageAmount;
EntityID PlayerDamagedID;
//optional TypeOfDamage
std::string TypeOfDamage;
};
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef EShoot_h__
#define EShoot_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
struct Shoot : Event
{
//ID for who made the shot
EntityID shooter;
};
}
#endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef EWin_h__
#define EWin_h__
#include "EventBroker.h"
#include "../Core/Entity.h"
#include "Engine/GLM.h"
namespace Events
{
//triggers when a team has captured all capturePoints
struct Win : Event
{
//can be 0 = none, 1,2
int TeamThatWon;
};
}
#endif
+22 -3
View File
@@ -2,6 +2,7 @@
#define EntityWrapper_h__
#include <boost/optional.hpp>
#include <boost/functional/hash.hpp>
#include "ComponentWrapper.h"
class World;
@@ -23,10 +24,28 @@ struct EntityWrapper
static const EntityWrapper Invalid;
bool HasComponent(const std::string& componentName);
EntityWrapper Parent();
bool Valid();
ComponentWrapper operator[](const std::string& componentName);
bool operator==(const EntityWrapper& e);
explicit operator EntityID();
ComponentWrapper operator[](const char* componentName);
bool operator==(const EntityWrapper& e) const;
bool operator!=(const EntityWrapper& e) const;
explicit operator EntityID() const;
operator bool();
};
namespace std
{
template<> struct hash<EntityWrapper>
{
std::size_t operator()(const EntityWrapper& e) const
{
std::size_t seed = 0;
boost::hash_combine(seed, e.World);
boost::hash_combine(seed, e.ID);
return seed;
}
};
}
#endif
+7 -7
View File
@@ -11,14 +11,14 @@ class System
friend class SystemPipeline;
protected:
System()
: m_EventBroker(nullptr)
{ }
System(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
System(World* world, EventBroker) { }
System(World* world, EventBroker* eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{ }
virtual ~System() = default;
World* m_World;
EventBroker* m_EventBroker;
};
@@ -34,7 +34,7 @@ protected:
const std::string m_ComponentType;
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) = 0;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0;
};
class ImpureSystem : public virtual System
@@ -45,7 +45,7 @@ protected:
ImpureSystem() = default;
virtual ~ImpureSystem() = default;
virtual void Update(World* world, double dt) = 0;
virtual void Update(double dt) = 0;
};
#endif
+36 -8
View File
@@ -5,13 +5,19 @@
#include "EventBroker.h"
#include "System.h"
#include "World.h"
#include "EPause.h"
class SystemPipeline
{
public:
SystemPipeline(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
{ }
SystemPipeline(World* world, EventBroker* eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_EPause, &SystemPipeline::OnPause);
EVENT_SUBSCRIBE_MEMBER(m_EResume, &SystemPipeline::OnResume);
}
~SystemPipeline()
{
for (UnorderedSystems& group : m_OrderedSystemGroups) {
@@ -29,7 +35,7 @@ public:
m_OrderedSystemGroups.resize(updateOrderLevel + 1);
}
UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel];
System* system = new T(m_EventBroker, args...);
System* system = new T(m_World, m_EventBroker, args...);
group.Systems[typeid(T).name()] = system;
PureSystem* pureSystem = dynamic_cast<PureSystem*>(system);
@@ -47,8 +53,12 @@ public:
}
}
void Update(World* world, double dt)
void Update(double dt)
{
if (m_Paused) {
dt = 0.0;
}
for (UnorderedSystems& group : m_OrderedSystemGroups) {
// Process events
for (auto& pair : group.Systems) {
@@ -57,18 +67,18 @@ public:
// Update
for (auto& system : group.ImpureSystems) {
system->Update(world, dt);
system->Update(dt);
}
for (auto& pair : group.PureSystems) {
const std::string& componentName = pair.first;
auto& systems = pair.second;
const ComponentPool* pool = world->GetComponents(componentName);
const ComponentPool* pool = m_World->GetComponents(componentName);
if (pool == nullptr) {
continue;
}
for (auto& component : *pool) {
for (auto& system : systems) {
system->UpdateComponent(world, EntityWrapper(world, component.EntityID), component, dt);
system->UpdateComponent(EntityWrapper(m_World, component.EntityID), component, dt);
}
}
}
@@ -76,7 +86,10 @@ public:
}
private:
World* m_World;
EventBroker* m_EventBroker;
bool m_Paused = false;
struct UnorderedSystems
{
std::map<std::string, System*> Systems;
@@ -84,6 +97,21 @@ private:
std::vector<ImpureSystem*> ImpureSystems;
};
std::vector<UnorderedSystems> m_OrderedSystemGroups;
EventRelay<SystemPipeline, Events::Pause> m_EPause;
bool OnPause(const Events::Pause& e) {
if (e.World == m_World) {
m_Paused = true;
}
return true;
}
EventRelay<SystemPipeline, Events::Resume> m_EResume;
bool OnResume(const Events::Resume& e) {
if (e.World == m_World) {
m_Paused = false;
}
return true;
}
};
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef UniformScaleSystem_h__
#define UniformScaleSystem_h__
#include "../GLM.h"
#include "System.h"
#include "../Rendering/ESetCamera.h"
class UniformScaleSystem : public PureSystem
{
public:
UniformScaleSystem(World* world, EventBroker* eventBroker);
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override;
private:
EntityWrapper m_Camera = EntityWrapper::Invalid;
EventRelay<UniformScaleSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(const Events::SetCamera& e);
};
#endif
+153
View File
@@ -0,0 +1,153 @@
#ifndef EditorGUI_h__
#define EditorGUI_h__
#include <imgui/imgui.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui/imgui_internal.h>
#include <nativefiledialog/nfd.h>
#include <boost/filesystem.hpp>
#include <boost/any.hpp>
#include "../Common.h"
#include "../GLM.h"
#include <glm/gtx/common.hpp>
#include "EditorWidgetSystem.h"
#include "../Core/EventBroker.h"
#include "../Core/World.h"
#include "../Core/EntityWrapper.h"
#include "../Core/ResourceManager.h"
#include "../Core/EPause.h"
#include "../Core/EKeyDown.h"
#include "../Rendering/Texture.h"
class EditorGUI
{
public:
EditorGUI(World* world, EventBroker* eventBroker);
enum class WidgetMode
{
Translate,
Rotate,
Scale
};
void Draw();
void SelectEntity(EntityWrapper entity);
void SetDirty(EntityWrapper entity);
// Called when an entity is selected in the entity tree
typedef std::function<void(EntityWrapper)> OnEntitySelectedCallback_t;
void SetEntitySelectedCallback(OnEntitySelectedCallback_t f) { m_OnEntitySelected = f; }
// Called when the user means to import an entity file.
// @param EntityWrapper The entity to parent the imported entity to. The entity will be imported into the world of this entity.
// @param boost::filesystem::path The path to the entity to import
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper, boost::filesystem::path)> OnEntityImport_t;
void SetEntityImportCallback(OnEntityImport_t f) { m_OnEntityImport = f; }
// Called when the user means to save an entity to file.
// Permitted to throw exceptions on save failure.
typedef std::function<void(EntityWrapper, boost::filesystem::path)> OnEntitySave_t;
void SetEntitySaveCallback(OnEntitySave_t f) { m_OnEntitySave = f; }
// Called when the user means to create a new entity.
// @param EntityWrapper The parent of the entity to be created
// @return EntityWrapper The newly created entity
typedef std::function<EntityWrapper(EntityWrapper)> OnEntityCreate_t;
void SetEntityCreateCallback(OnEntityCreate_t f) { m_OnEntityCreate = f; }
// Called when the user means to delete an entity.
typedef std::function<void(EntityWrapper)> OnEntityDelete_t;
void SetEntityDeleteCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; }
// Called when the user means to change the parent of an entity.
typedef std::function<void(EntityWrapper, EntityWrapper)> OnEntityChangeParent_t;
void SetEntityChangeParentCallback(OnEntityChangeParent_t f) { m_OnEntityChangeParent = f; }
// Called when the user means to rename an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnEntityChangeName_t;
void SetEntityChangeNameCallback(OnEntityChangeName_t f) { m_OnEntityChangeName = f; }
// Called when the user means to attach a new component to an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentAttach_t;
void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; }
// Called when the user means to delete a component off an entity.
typedef std::function<void(EntityWrapper, const std::string&)> OnComponentDelete_t;
void SetComponentDeleteCallback(OnComponentDelete_t f) { m_OnComponentDelete = f; }
// Called when the user selects a widget mode.
typedef std::function<void(WidgetMode)> OnWidgetMode_t;
void SetWidgetModeCallback(OnWidgetMode_t f) { m_OnWidgetMode = f; }
private:
World* m_World;
EventBroker* m_EventBroker;
struct EntityFileInfo
{
boost::filesystem::path Path;
bool Dirty = false;
};
// Config variables
const boost::filesystem::path m_DefaultEntityPath = boost::filesystem::path("Schema") / boost::filesystem::path("Entities");
// State
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
std::unordered_map<EntityWrapper, EntityFileInfo> m_EntityFiles;
EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid;
std::string m_LastErrorMessage;
WidgetMode m_CurrentWidgetMode = WidgetMode::Translate;
std::set<std::string> m_ModalsToOpen;
std::map<std::string, boost::any> m_ModalData;
// Callbacks
OnEntitySelectedCallback_t m_OnEntitySelected = nullptr;
OnEntityImport_t m_OnEntityImport = nullptr;
OnEntitySave_t m_OnEntitySave = nullptr;
OnEntityCreate_t m_OnEntityCreate = nullptr;
OnEntityDelete_t m_OnEntityDelete = nullptr;
OnEntityChangeParent_t m_OnEntityChangeParent = nullptr;
OnEntityChangeName_t m_OnEntityChangeName = nullptr;
OnComponentAttach_t m_OnComponentAttach = nullptr;
OnComponentDelete_t m_OnComponentDelete = nullptr;
OnWidgetMode_t m_OnWidgetMode = nullptr;
// Events
EventRelay<EditorGUI, Events::KeyDown> m_EKeyDown;
bool OnKeyDown(const Events::KeyDown& e);
// Utility functions
boost::filesystem::path fileOpenDialog();
boost::filesystem::path fileSaveDialog();
const std::string formatEntityName(EntityWrapper entity);
GLuint tryLoadTexture(std::string filePath);
void openModal(const std::string& modal);
// Entity file handling methods
void entityImport(World* world);
void entitySave(EntityWrapper entity, bool saveAs = false);
void entityCreate(World* world, EntityWrapper parent);
void entityDelete(EntityWrapper entity);
void entityChangeParent(EntityWrapper entity, EntityWrapper parent);
// UI drawing methods
void drawMenu();
void drawTools();
void drawEntities(World* world);
void drawEntitiesRecursive(World* world, EntityID parent);
bool drawEntityNode(EntityWrapper entity);
void drawComponents(EntityWrapper entity);
bool drawComponentNode(EntityWrapper entity, const ComponentInfo& componentType);
bool drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field);
bool drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field);
bool drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field);
void drawModals();
// Custom UI elements
bool createDeleteButton(const std::string& componentType);
void createWidgetToolButton(WidgetMode mode);
};
#endif
@@ -0,0 +1,27 @@
#ifndef EditorRenderSystem_h__
#define EditorRenderSystem_h__
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/ModelJob.h"
#include "../Rendering/Camera.h"
#include "../Rendering/ESetCamera.h"
class EditorRenderSystem : public ImpureSystem
{
public:
EditorRenderSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
virtual void Update(double dt) override;
private:
IRenderer* m_Renderer;
RenderFrame* m_RenderFrame;
Camera* m_EditorCamera;
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
EventRelay<EditorRenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(Events::SetCamera& e);
};
#endif
+29
View File
@@ -0,0 +1,29 @@
#include <numeric>
#include <iomanip>
#include <imgui/imgui.h>
#include "../Common.h"
#include "../GLM.h"
#include "../OpenGL.h"
class EditorStats
{
public:
EditorStats();
void Draw(double dt);
private:
// FPS graph
const unsigned int m_SampleSize = 100;
unsigned int m_FrameCount = 0;
std::vector<double> m_FrameTimes;
double m_TimeAccumulator = 0.0;
double m_AveragedSamplesPerSecond = 10.0;
const unsigned int m_AveragedSampleSize = 100;
unsigned int m_CurrentAveragedSampleIndex = 0;
std::vector<double> m_AveragedSamples;
void drawFPSGraph(double dt);
void drawRAMUsage(double dt);
void drawVRAMStats(double dt);
};
+39 -74
View File
@@ -1,94 +1,59 @@
#include <imgui/imgui.h>
#include <glm/gtx/common.hpp>
#include <boost/filesystem/path.hpp>
#include <nativefiledialog/nfd.h>
#include "../Core/System.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
#include "../Core/EMouseMove.h"
#include "../Core/ConfigFile.h"
#include "../Input/EInputCommand.h"
#include "../Rendering/IRenderer.h"
#include "../Core/Transform.h"
#include "../Core/EFileDropped.h"
#include "../Rendering/Camera.h"
#include "../Rendering/DebugCameraInputController.h"
#include "../Rendering/ESetCamera.h"
#include "../Core/World.h"
#include "../Core/SystemPipeline.h"
#include "../Core/ResourceManager.h"
#include "../Core/EntityFilePreprocessor.h"
#include "../Core/EntityFileParser.h"
#include "../Core/EntityFileWriter.h"
#include "../Core/EMouseRelease.h"
#include "EditorGUI.h"
#include "EditorStats.h"
class EditorSystem : public ImpureSystem
{
public:
EditorSystem(EventBroker* eventBroker, IRenderer* renderer);
EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame);
~EditorSystem();
virtual void Update(World* world, double dt) override;
void Update(double dt);
private:
IRenderer* m_Renderer;
World* m_World = nullptr;
Camera* m_Camera = nullptr;
RenderFrame* m_RenderFrame;
World* m_EditorWorld;
SystemPipeline* m_EditorWorldSystemPipeline;
Camera* m_EditorCamera;
EntityWrapper m_Camera = EntityWrapper::Invalid;
DebugCameraInputController<EditorSystem>* m_DebugCameraInputController;
EditorGUI* m_EditorGUI;
EditorStats* m_EditorStats;
bool m_Enabled;
bool m_Visible;
boost::filesystem::path m_DefaultEntityDir;
boost::filesystem::path m_CurrentFile;
std::vector<glm::vec2> m_PickingQueue;
// State
EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate;
EntityWrapper m_Widget = EntityWrapper::Invalid;
EntityWrapper m_CurrentSelection = EntityWrapper::Invalid;
enum class WidgetMode
{
None,
Translate,
Rotate,
Scale
} m_WidgetMode = WidgetMode::None;
// Utility functions
EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath);
void setWidgetMode(EditorGUI::WidgetMode mode);
enum class WidgetSpace
{
Local,
Global
} m_WidgetSpace = WidgetSpace::Global;
// GUI callbacks
void OnEntitySelected(EntityWrapper entity);
void OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath);
EntityWrapper OnEntityCreate(EntityWrapper parent);
void OnEntityDelete(EntityWrapper entity);
void OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent);
void OnEntityChangeName(EntityWrapper entity, const std::string& name);
void OnComponentAttach(EntityWrapper entity, const std::string& componentType);
void OnComponentDelete(EntityWrapper entity, const std::string& componentType);
EntityID m_Widget = EntityID_Invalid;
EntityID m_WidgetX = EntityID_Invalid;
EntityID m_WidgetPlaneX = EntityID_Invalid;
EntityID m_WidgetY = EntityID_Invalid;
EntityID m_WidgetPlaneY = EntityID_Invalid;
EntityID m_WidgetZ = EntityID_Invalid;
EntityID m_WidgetPlaneZ = EntityID_Invalid;
EntityID m_WidgetOrigin = EntityID_Invalid;
glm::vec3 m_WidgetCurrentAxis;
float m_WidgetPickingDepth = 0.f;
glm::vec3 m_WidgetPickingPosition = glm::vec3(0);
EntityID m_Selection = EntityID_Invalid;
EntityID m_LastSelection = EntityID_Invalid;
EntityID m_UIDraggingEntity = EntityID_Invalid;
glm::vec3 m_Position;
std::string m_LastDroppedFile;
static boost::filesystem::path openDialog(boost::filesystem::path defaultPath);
static boost::filesystem::path saveDialog(boost::filesystem::path defaultPath);
EventRelay<EditorSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
// Events
EventRelay<EditorSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
EventRelay<EditorSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorSystem, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorSystem, Events::FileDropped> m_EFileDropped;
bool OnFileDropped(const Events::FileDropped& e);
void Picking();
void createWidget();
void updateWidget();
void setWidgetMode(WidgetMode newMode);
void setWidgetSpace(WidgetSpace space);
void drawUI(World* world, double dt);
bool createDeleteButton(std::string componentType);
bool createEntityNode(World* world, EntityID entity);
void changeParent(EntityID entity, EntityID newParent);
void fileImport(World* world);
void fileSave(World* world);
void fileSaveAs(World* world);
EventRelay<EditorSystem, Events::WidgetDelta> m_EWidgetDelta;
bool OnWidgetDelta(const Events::WidgetDelta& e);
};
@@ -0,0 +1,49 @@
#ifndef EditorWidgetSystem_h__
#define EditorWidgetSystem_h__
#include <imgui/imgui.h>
#include "../GLM.h"
#include "../Core/System.h"
#include "../Rendering/IRenderer.h"
#include "../Rendering/Util/ScreenCoords.h"
#include "../Core/EMouseMove.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
namespace Events
{
struct WidgetDelta : Event
{
glm::vec3 Translation;
glm::vec3 Rotation;
glm::vec3 Scale;
};
}
class EditorWidgetSystem : public ImpureSystem, PureSystem
{
public:
EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
virtual void Update(double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override;
private:
IRenderer* m_Renderer;
// State
EntityWrapper m_PickEntity = EntityWrapper::Invalid;
PickData m_PickData;
glm::vec2 m_MouseDelta;
EventRelay<EditorWidgetSystem, Events::MouseMove> m_EMouseMove;
bool OnMouseMove(const Events::MouseMove& e);
EventRelay<EditorWidgetSystem, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e);
EventRelay<EditorWidgetSystem, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e);
};
#endif
+1
View File
@@ -8,3 +8,4 @@
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/projection.hpp>
+28 -10
View File
@@ -3,9 +3,12 @@
#include <string>
#include <ctime>
#include <limits>
#include <queue>
#include <glm/common.hpp>
#include <boost/asio.hpp>
#include <boost/shared_array.hpp>
#include "Network/Network.h"
#include "Network/MessageType.h"
@@ -15,6 +18,8 @@
#include "Core/EventBroker.h"
#include "Core/ConfigFile.h"
#include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
#include "Network/EInterpolate.h"
class Client : public Network
{
@@ -32,8 +37,6 @@ private:
// Sending message to server logic
int bytesRead = -1;
char readBuf[INPUTSIZE] = { 0 };
int snapshotInterval = 33;
std::clock_t previousSnapshotMessage = std::clock();
// Packet loss logic
unsigned int m_PacketID = 0;
@@ -44,40 +47,55 @@ private:
World* m_World;
std::string m_PlayerName;
int m_PlayerID = -1;
EntityID m_ServerEntityID = std::numeric_limits<EntityID>::max();
bool m_IsConnected = false;
// Server Client Lookup map
// Assumes that root node for client and server is EntityID 0.
// Don't Add items to these two maps with insert, use insertIntoServerClientMaps(EntityID, EntityID)!!!!
std::unordered_map<EntityID, EntityID> m_ServerIDToClientID;
std::unordered_map<EntityID, EntityID> m_ClientIDToServerID;
// Network logic
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
SnapshotDefinitions m_NextSnapshot;
double m_DurationOfPingTime;
std::clock_t m_StartPingTime;
// Use to check if we should send disconnect message
// if game is turned of by closing window.
bool m_WasStarted = false;
std::vector<Events::InputCommand> m_InputCommandBuffer;
// Private member functions
void readFromServer();
void sendSnapshotToServer();
int receive(char* data, size_t length);
void send(Packet& packet);
void connect();
void disconnect();
void ping();
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void parseMessageType(Packet& packet);
void parseEventMessage(Packet& packet);
void updateFields(Packet& packet, const ComponentInfo& componentInfo, const EntityID& entityID, const std::string& componentType);
void parseConnect(Packet& packet);
void parsePlayerConnected(Packet& packet);
void parsePing();
void parseServerPing();
void InterpolateFields(Packet & packet, const ComponentInfo & componentInfo, const EntityID & entityID, const std::string & componentType);
void parseSnapshot(Packet& packet);
void identifyPacketLoss();
bool isConnected();
bool hasServerTimedOut();
EntityID createPlayer();
void sendInputCommands();
void becomePlayer();
// Mapping Logic
// Returns if local EntityID exist in map
bool clientServerMapsHasEntity(EntityID clientEntityID);
// Returns if server EntityID exist in map
bool serverClientMapsHasEntity(EntityID serverEntityID);
void insertIntoServerClientMaps(EntityID serverEntityID, EntityID clientEntityID);
// Events
EventBroker* m_EventBroker;
EventRelay<Client, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand &e);
bool OnInputCommand(const Events::InputCommand& e);
EventRelay<Client, Events::PlayerDamage> m_EPlayeDamage;
bool OnPlayerDamage(const Events::PlayerDamage& e);
};
#endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef Events_Interpolate_h__
#define Events_Interpolate_h__
#include <boost/shared_array.hpp>
#include "Core/EventBroker.h"
#include "Core/Entity.h"
namespace Events
{
struct Interpolate : Event
{
EntityID Entity;
boost::shared_array<char> DataArray;
};
}
#endif
+4 -1
View File
@@ -11,7 +11,10 @@ enum class MessageType
ServerPing,
Message,
Snapshot,
Event,
OnInputCommand,
OnPlayerDamage,
PlayerConnected,
BecomePlayer
};
#endif
+1
View File
@@ -7,6 +7,7 @@
#define MAXCONNECTIONS 8
#define INPUTSIZE 4097
#define TIMEOUTMS 15000
class Network
{
+2 -1
View File
@@ -14,6 +14,7 @@ public:
Packet(MessageType type, unsigned int& packetID);
// Used to create packet from already existing data buffer.
Packet(char* data, const int sizeOfPacket);
Packet(MessageType type);
~Packet();
void Init(MessageType type, unsigned int& packetID);
@@ -49,7 +50,7 @@ public:
// Pops the first element as if it was a string.
std::string ReadString();
char* ReadData(int SizeOfData);
void ChangePacketID(unsigned int& packetID);
int Size() { return m_Offset; };
char* Data() { return m_Data; };
unsigned int DataReadSize() { return m_ReturnDataOffset; }
@@ -6,6 +6,8 @@ struct PlayerDefinition {
int EntityID = -1;
std::string Name = "";
boost::asio::ip::udp::endpoint Endpoint;
unsigned int PacketID;
std::clock_t StopTime;
};
#endif
+14 -13
View File
@@ -11,7 +11,9 @@
#include "Network/PlayerDefinition.h"
#include "Core/World.h"
#include "Core/EventBroker.h"
#include "Network/Network.h"
#include "../Network/Network.h"
#include "Input/EInputCommand.h"
#include "Core/EPlayerDamage.h"
class Server : public Network
{
@@ -25,9 +27,10 @@ private:
boost::asio::ip::udp::endpoint m_ReceiverEndpoint;
boost::asio::io_service m_IOService;
boost::asio::ip::udp::socket m_Socket;
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
// Sending messages to client logic
PlayerDefinition m_PlayerDefinitions[MAXCONNECTIONS];
std::vector<PlayerDefinition> m_ConnectedUsers;
char readBuffer[INPUTSIZE] = { 0 };
int bytesRead = 0;
// time for previouse message
@@ -41,40 +44,38 @@ private:
//Timers
std::clock_t m_StartPingTime;
std::clock_t m_StopTimes[8];
// Game logic
World* m_World;
EventBroker* m_EventBroker;
// vec.size() = ammount of players to create, stores playerID's
std::vector<unsigned int> m_PlayersToCreate;
// Packet loss logic
unsigned int m_PacketID;
unsigned int m_PreviousPacketID;
unsigned int m_SendPacketID;
unsigned int m_PacketID = 0;
unsigned int m_PreviousPacketID = 0;
// Private member functions
int receive(char* data, size_t length);
void readFromClients();
void send(Packet& packet, int playerID);
void send(Packet& packet);
void moveMessageHead(char*& data, size_t& length, size_t stepSize);
void broadcast(std::string message);
void broadcast(Packet& packet);
void sendSnapshot();
void sendPing();
void checkForTimeOuts();
void disconnect(int i);
void parseMessageType(Packet& packet);
void parseEvent(Packet& packet);
void parseOnInputCommand(Packet& packet);
void parseOnPlayerDamage(Packet& packet);
void parseConnect(Packet& packet);
void parseDisconnect();
void parseClientPing();
void parseServerPing();
void parseSnapshot(Packet& packet);
void identifyPacketLoss();
EntityID createPlayer();
void createPlayer();
int GetPlayerIDFromEndpoint(boost::asio::ip::udp::endpoint endpoint);
// Debug event
EventRelay<Server, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
};
#endif
+3 -1
View File
@@ -2,6 +2,7 @@
#define Camera_h__
#include "../GLM.h"
#include "../Core/Util/Rectangle.h"
class Camera
{
@@ -32,7 +33,6 @@ public:
glm::mat4 ViewMatrix() const { return m_ViewMatrix; }
void SetViewMatrix(glm::mat4 val);
float AspectRatio() const { return m_AspectRatio; }
void SetAspectRatio(float val);
@@ -48,6 +48,8 @@ public:
void UpdateViewMatrix();
void UpdateProjectionMatrix();
glm::vec2 WorldToScreen(glm::vec3 worldCoord, Rectangle resolution);
private:
glm::vec3 m_Position;
@@ -1,5 +1,10 @@
#ifndef DebugCameraInputController_h__
#define DebugCameraInputController_h__
#include <imgui/imgui.h>
#include "../Input/FirstPersonInputController.h"
#include "../Core/EMousePress.h"
#include "../Core/EMouseRelease.h"
template <typename EventContext>
class DebugCameraInputController : public FirstPersonInputController<EventContext>
@@ -7,7 +12,10 @@ class DebugCameraInputController : public FirstPersonInputController<EventContex
public:
DebugCameraInputController(EventBroker* eventBroker, unsigned int playerID)
: FirstPersonInputController(eventBroker, playerID)
{ }
{
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &DebugCameraInputController::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &DebugCameraInputController::OnMouseRelease);
}
void SetPosition(const glm::vec3 position) { m_Position = position; }
void SetOrientation(const glm::quat orientation) { m_Orientation = orientation; }
@@ -19,17 +27,6 @@ public:
{
ImGuiIO& io = ImGui::GetIO();
if (e.Command == "PrimaryFire") {
if (e.Value > 0) {
if (!io.WantCaptureMouse) {
LockMouse();
}
} else {
UnlockMouse();
}
return false;
}
if (!io.WantCaptureKeyboard) {
if (e.Command == "Right") {
float value = std::max(-1.f, std::min(e.Value, 1.f));
@@ -63,4 +60,25 @@ protected:
glm::vec3 m_Velocity = glm::vec3(0, 0, 0);
float m_BaseSpeed = 2.0f;
float m_Speed = m_BaseSpeed;
EventRelay<EventContext, Events::MousePress> m_EMousePress;
bool OnMousePress(const Events::MousePress& e)
{
if (e.Button == GLFW_MOUSE_BUTTON_2) {
ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureMouse) {
LockMouse();
}
}
return true;
}
EventRelay<EventContext, Events::MouseRelease> m_EMouseRelease;
bool OnMouseRelease(const Events::MouseRelease& e)
{
if (e.Button == GLFW_MOUSE_BUTTON_2) {
UnlockMouse();
}
return true;
}
};
#endif
@@ -0,0 +1,35 @@
#ifndef DirectionalLightJob_h__
#define DirectionalLightJob_h__
#include <cstdint>
#include "../Common.h"
#include "../GLM.h"
#include "../Core/ComponentWrapper.h"
#include "RenderJob.h"
#include "../Core/Transform.h"
#include "../Core/World.h"
struct DirectionalLightJob : RenderJob
{
DirectionalLightJob(ComponentWrapper transformComponent, ComponentWrapper directionalLightComponent, World* m_World)
: RenderJob()
{
Direction = glm::vec4(0,0,-1,0) * glm::inverse(Transform::AbsoluteOrientation(m_World, transformComponent.EntityID));
//Direction = glm::vec4((glm::vec3)directionalLightComponent["Direction"], 0.f);
Color = (glm::vec4)directionalLightComponent["Color"];
Intensity = (double)directionalLightComponent["Intensity"];
};
glm::vec4 Direction;
glm::vec4 Color;
float Intensity;
void CalculateHash() override
{
Hash = 0;
}
};
#endif
-1
View File
@@ -32,7 +32,6 @@ private:
const LightCullingPass* m_LightCullingPass;
ShaderProgram* m_ForwardPlusProgram;
};
#endif
-42
View File
@@ -1,42 +0,0 @@
#ifndef DrawScenePass_h__
#define DrawScenePass_h__
#include "IRenderer.h"
#include "DrawScenePassState.h"
#include "FrameBuffer.h"
#include "ShaderProgram.h"
#include "Util/UnorderedMapVec2.h"
#include "Texture.h"
class DrawScenePass
{
public:
DrawScenePass(IRenderer* renderer);
~DrawScenePass() { }
void InitializeTextures();
void InitializeFrameBuffers();
void InitializeShaderPrograms();
void Draw(RenderScene& scene);
//Getters
private:
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const;
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j)
{
return (i->Depth < j->Depth);
};
Texture* m_WhiteTexture;
const IRenderer* m_Renderer;
ShaderProgram* m_BasicForwardProgram;
};
#endif
@@ -1,15 +0,0 @@
#ifndef DrawScenePassState_h__
#define DrawScenePassState_h__
#include "Rendering/RenderState.h"
class DrawScenePassState : public RenderState
{
public:
DrawScenePassState();
~DrawScenePassState();
private:
};
#endif
+2 -8
View File
@@ -2,20 +2,14 @@
#define Events_SetCamera_h__
#include "../Core/EventBroker.h"
#include "../Core/Entity.h"
#include <string.h>
#include "../Core/EntityWrapper.h"
namespace Events
{
struct SetCamera : Event
{
public:
SetCamera() { };
std::string Name;
private:
EntityWrapper CameraEntity;
};
}
-11
View File
@@ -31,15 +31,6 @@ public:
void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; }
bool VSYNC() const { return m_VSYNC; }
void SetVSYNC(bool vsync) { m_VSYNC = vsync; }
::Camera* Camera() const { return m_Camera; }
void SetCamera(::Camera* camera)
{
if (camera == nullptr) {
m_Camera = m_DefaultCamera;
} else {
m_Camera = camera;
}
}
virtual void Initialize() = 0;
virtual void Update(double dt) = 0;
virtual void Draw(RenderFrame& rq) = 0;
@@ -54,8 +45,6 @@ protected:
int m_GLVersion[2];
std::string m_GLVendor;
GLFWwindow* m_Window = nullptr;
::Camera* m_DefaultCamera;
::Camera* m_Camera = nullptr;
};
#endif // Renderer_h__
+9 -8
View File
@@ -46,8 +46,8 @@ private:
int m_NumberOfTiles = 0;
struct Plane {
glm::vec3 Normal;
float d;
glm::vec3 Normal = glm::vec3(0.f);
float d = 0;
};
struct Frustum {
@@ -56,20 +56,21 @@ private:
Frustum* m_Frustums;
//This should be a component
struct PointLight {
struct LightSource {
glm::vec4 Position = glm::vec4(0.f);
glm::vec4 Direction = glm::vec4(10.f);
glm::vec4 Color = glm::vec4(1.f);
float Radius = 5.f;
float Intensity = 0.8f;
float Falloff = 0.3f;
float Padding = 1337;
enum Type_t { Zero, Point, Directional, Spot } Type;
};
std::vector<PointLight> m_PointLights;
std::vector<LightSource> m_LightSources;
struct LightGrid {
float Start;
float Amount;
glm::vec2 Padding;
float Start = 0;
float Amount = 0;
glm::vec2 Padding = glm::vec2(1.f, 2.f);
};
LightGrid* m_LightGrid;
+4
View File
@@ -12,6 +12,7 @@
#include "../Core/ResourceManager.h"
#include "Camera.h"
#include "../Core/World.h"
#include "../Core/Transform.h"
struct ModelJob : RenderJob
{
@@ -28,6 +29,9 @@ struct ModelJob : RenderJob
Matrix = matrix;
Color = modelComponent["Color"];
Entity = modelComponent.EntityID;
glm::vec3 abspos = Transform::AbsolutePosition(world, modelComponent.EntityID);
glm::vec3 worldpos = glm::vec3(camera->ViewMatrix() * glm::vec4(abspos, 1));
Depth = worldpos.z;
World = world;
};
-1
View File
@@ -14,7 +14,6 @@ struct RenderJob
friend class RenderQueue;
public:
float Depth;
protected:
+5 -1
View File
@@ -12,6 +12,7 @@
#include "RenderJob.h"
#include "ModelJob.h"
#include "PointLightJob.h"
#include "DirectionalLightJob.h"
/*
@@ -50,15 +51,18 @@ struct PointLightJob : RenderJob
struct RenderScene
{
::Camera* Camera;
::Camera* Camera = nullptr;
std::list<std::shared_ptr<RenderJob>> ForwardJobs;
std::list<std::shared_ptr<RenderJob>> PointLightJobs;
std::list<std::shared_ptr<RenderJob>> DirectionalLightJobs;
Rectangle Viewport;
bool ClearDepth = false;
void Clear()
{
ForwardJobs.clear();
PointLightJobs.clear();
DirectionalLightJobs.clear();
}
};
+1 -1
View File
@@ -16,10 +16,10 @@ public:
bool Disable(GLenum cap);
bool CullFace(GLenum mode);
bool ClearColor(glm::vec4 color);
bool Clear(GLbitfield mask);
bool BindFramebuffer(GLint framebuffer);
bool BlendEquation(GLenum mode);
bool BlendFunc(GLenum sfactor, GLenum dfactor);
bool DepthMask(GLboolean flag);
private:
std::vector<std::function<void(void)>> m_ResetFunctions;
+9 -19
View File
@@ -20,36 +20,26 @@
class RenderSystem : public ImpureSystem
{
public:
RenderSystem(EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame);
RenderSystem(World* world, EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame);
~RenderSystem();
virtual void Update(World* world, double dt) override;
virtual void Update(double dt) override;
private:
World* m_World = nullptr;
const IRenderer* m_Renderer;
RenderFrame* m_RenderFrame;
bool m_SwitchCamera = false;
Camera* m_Camera;
DebugCameraInputController<RenderSystem>* m_DebugCameraInputController;
std::list<ComponentWrapper> m_CameraComponents;
EntityWrapper m_CurrentCamera = EntityWrapper::Invalid;
EventRelay<RenderSystem, Events::SetCamera> m_ESetCamera;
bool OnSetCamera(const Events::SetCamera &event);
EntityID m_CurrentCamera = EntityID_Invalid;
void switchCamera(EntityID entity);
void updateCamera(World* world, double dt);
void updateProjectionMatrix(ComponentWrapper& cameraComponent);
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
bool OnSetCamera(Events::SetCamera &event);
void fillPointLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
void fillDirectionalLights(std::list<std::shared_ptr<RenderJob>>& jobs, World* world);
EventRelay<RenderSystem, Events::InputCommand> m_EInputCommand;
bool OnInputCommand(const Events::InputCommand& e);
void fillModels(std::list<std::shared_ptr<RenderJob>>& jobs);
void fillLight(std::list<std::shared_ptr<RenderJob>>& jobs);
};
#endif
+2 -6
View File
@@ -11,7 +11,6 @@
#include "FrameBuffer.h"
#include "../Core/World.h"
#include "PickingPass.h"
#include "DrawScenePass.h"
#include "LightCullingPass.h"
#include "DrawFinalPass.h"
#include "../Core/EventBroker.h"
@@ -22,9 +21,8 @@
class Renderer : public IRenderer
{
public:
Renderer(EventBroker* eventBroker, World* world)
Renderer(EventBroker* eventBroker)
: m_EventBroker(eventBroker)
, m_World(world)
{ }
virtual void Initialize() override;
@@ -36,7 +34,6 @@ public:
private:
//----------------------Variables----------------------//
EventBroker* m_EventBroker;
World* m_World;
Texture* m_ErrorTexture;
Texture* m_WhiteTexture;
@@ -45,7 +42,6 @@ private:
Model* m_UnitQuad;
Model* m_UnitSphere;
DrawScenePass* m_DrawScenePass;
PickingPass* m_PickingPass;
LightCullingPass* m_LightCullingPass;
ImGuiRenderPass* m_ImGuiRenderPass;
@@ -62,7 +58,7 @@ private:
void DrawScreenQuad(GLuint textureToDraw);
static bool DepthSort(const std::shared_ptr<RenderJob> &i, const std::shared_ptr<RenderJob> &j) { return (i->Depth < j->Depth); }
void FillDepth(RenderScene& scene);
void SortRenderJobsByDepth(RenderScene &scene);
void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type);
//--------------------ShaderPrograms-------------------//
ShaderProgram* m_BasicForwardProgram;
+1 -1
View File
@@ -19,7 +19,7 @@
#include "Rendering/RenderSystem.h"
#include "Core/EntityFileParser.h"
#include "Core/Octree.h"
#include "Systems/InterpolationSystem.h"
// Network
#include <boost/thread.hpp>
#include "Network/Network.h"
+55
View File
@@ -0,0 +1,55 @@
#ifndef CapturePointSystem_h__
#define CapturePointSystem_h__
#include <GLFW/glfw3.h>
#include <glm/common.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Engine/Collision/ETrigger.h"
#include "Core/ECaptured.h"
#include "Core/EWin.h"
#include <tuple>
#include <vector>
class CapturePointSystem : public PureSystem
{
public:
//WARNING: on new map, destroy all info in the vectors, as well as reset all variables (just make new?)
CapturePointSystem(World* world, EventBroker* eventBroker);
//updatecomponent
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& capturePoint, double dt) override;
private:
//methods which will take care of specific events
EventRelay<CapturePointSystem, Events::TriggerTouch> m_ETriggerTouch;
bool CapturePointSystem::OnTriggerTouch(const Events::TriggerTouch& e);
EventRelay<CapturePointSystem, Events::TriggerLeave> m_ETriggerLeave;
bool CapturePointSystem::OnTriggerLeave(const Events::TriggerLeave& e);
EventRelay<CapturePointSystem, Events::Captured> m_ECaptured;
bool CapturePointSystem::OnCaptured(const Events::Captured& e);
bool m_WinnerWasFound = false;
//need to track these variables for the captureSystem to work as per design!
const int m_NotACapturePoint = 999;
int m_RedTeamNextPossibleCapturePoint = m_NotACapturePoint;
int m_BlueTeamNextPossibleCapturePoint = m_NotACapturePoint;
int m_RedTeamHomeCapturePoint = m_NotACapturePoint;
int m_BlueTeamHomeCapturePoint = m_NotACapturePoint;
int m_NumberOfCapturePoints = 0;
std::map<int, EntityID> m_CapturePointNumberToEntityIDMap;
//std::vector<ComponentWrapper>
const double m_CaptureTimeToTakeOver = 15.0;
bool m_ResetTimers = false;
//vectors which will keep track of enter/leave changes
std::vector<std::tuple<EntityID, EntityID>> m_ETriggerTouchVector;
std::vector<std::tuple<EntityID, EntityID>> m_ETriggerLeaveVector;
};
#endif
+2 -2
View File
@@ -16,10 +16,10 @@
class HealthSystem : public PureSystem
{
public:
HealthSystem(EventBroker* eventBroker);
HealthSystem(World* world, EventBroker* eventBroker);
//updatecomponent
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override;
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override;
private:
//methods which will take care of specific events
@@ -0,0 +1,53 @@
#ifndef Systems_InterpolationSystem_h__
#define Systems_InterpolationSystem_h__
#include <queue>
#include <unordered_map>
#include <boost/shared_array.hpp>
#include <glm/common.hpp>
#include <glm/gtc/quaternion.hpp>
#include "Common.h"
#include "Core/System.h"
#include "Core/EventBroker.h"
#include "Network/EInterpolate.h"
#define SNAPSHOTINTERVAL 0.05f
class InterpolationSystem : public PureSystem
{
struct Transform
{
glm::vec3 Position;
glm::vec3 Scale;
glm::quat Orientation;
double interpolationTime;
};
public:
InterpolationSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Transform")
{
EVENT_SUBSCRIBE_MEMBER(m_EInterpolate, &InterpolationSystem::OnInterpolate);
}
~InterpolationSystem() { }
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& transform, double dt) override;
private:
std::unordered_map<EntityID, Transform> m_NextTransform;
std::unordered_map<EntityID, Transform> m_LastReceivedTransform;
//glm::vec3 vectorInterpolation(glm::vec3 prev, glm::vec3 next, double currentTime);
template <typename T>
T vectorInterpolation(T prev, T next, double currentTime)
{
T difference = next - prev;
T vector = (difference / SNAPSHOTINTERVAL) * static_cast<float>(currentTime);
return vector;
}
EventRelay<InterpolationSystem, Events::Interpolate> m_EInterpolate;
bool InterpolationSystem::OnInterpolate(const Events::Interpolate& e);
};
#endif
+3 -3
View File
@@ -5,10 +5,10 @@
class PlayerMovementSystem : public PureSystem
{
public:
PlayerMovementSystem(EventBroker* eventBroker)
: System(eventBroker)
PlayerMovementSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("Player")
{ }
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt);
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt);
};
+2 -2
View File
@@ -6,9 +6,9 @@
class PlayerSpawnSystem : public ImpureSystem
{
public:
PlayerSpawnSystem(EventBroker* eventBroker);
PlayerSpawnSystem(World* world, EventBroker* eventBroker);
virtual void Update(World* world, double dt) override;
virtual void Update(double dt) override;
private:
EventRelay<PlayerSpawnSystem, Events::InputCommand> m_OnInputCommand;
+4 -4
View File
@@ -4,14 +4,14 @@
class RaptorCopterSystem : public PureSystem
{
public:
RaptorCopterSystem(EventBroker* eventBroker)
: System(eventBroker)
RaptorCopterSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("RaptorCopter")
{ }
virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override
virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override
{
ComponentWrapper& transform = world->GetComponent(component.EntityID, "Transform");
ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform");
(glm::vec3&)transform["Orientation"] += (float)(double)component["Speed"] * (float)dt * (glm::vec3)component["Axis"];
}
};
+1 -1
View File
@@ -13,7 +13,7 @@
class SpawnerSystem : public System
{
public:
SpawnerSystem(EventBroker* eventBroker);
SpawnerSystem(World* world, EventBroker* eventBroker);
static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid);
+38
View File
@@ -0,0 +1,38 @@
#ifndef WeaponSystem_h__
#define WeaponSystem_h__
//#include <GLFW/glfw3.h>
//#include <glm/common.hpp>
#include "Rendering/IRenderer.h"
#include "Common.h"
#include "Core/System.h"
#include "Core/EPlayerDamage.h"
#include "Core/EShoot.h"
#include "Input/EInputCommand.h"
#include <tuple>
#include <vector>
class WeaponSystem : public ImpureSystem
{
public:
WeaponSystem(World* world, EventBroker* eventBroker, IRenderer* renderer);
virtual void Update(double dt) override;
private:
//methods which will take care of specific events
EventRelay<WeaponSystem, Events::Shoot> m_EShoot;
bool WeaponSystem::OnShoot(const Events::Shoot& e);
EventRelay<WeaponSystem, Events::InputCommand> m_EInputCommand;
bool WeaponSystem::OnInputCommand(const Events::InputCommand& e);
IRenderer* m_Renderer;
std::vector<std::tuple<EntityID, glm::vec2>> m_EShootVector;
};
#endif
+4
View File
@@ -9,8 +9,10 @@
<xs:include schemaLocation="Components/Camera.xsd"/>
<xs:include schemaLocation="Components/AABB.xsd"/>
<xs:include schemaLocation="Components/PointLight.xsd"/>
<xs:include schemaLocation="Components/DirectionalLight.xsd"/>
<xs:include schemaLocation="Components/Trigger.xsd"/>
<xs:include schemaLocation="Components/Health.xsd"/>
<xs:include schemaLocation="Components/CapturePoint.xsd"/>
<xs:include schemaLocation="Components/Listener.xsd"/>
<xs:include schemaLocation="Components/SoundEmitter.xsd"/>
<xs:include schemaLocation="Components/Collidable.xsd"/>
@@ -18,4 +20,6 @@
<xs:include schemaLocation="Components/SpawnPoint.xsd"/>
<xs:include schemaLocation="Components/PlayerSpawn.xsd"/>
<xs:include schemaLocation="Components/Team.xsd"/>
<xs:include schemaLocation="Components/UniformScale.xsd"/>
<xs:include schemaLocation="Components/EditorWidget.xsd"/>
</xs:schema>
-1
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Camera xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Camera.xsd">
<Name>cam</Name>
<FOV>45</FOV>
<NearClip>0.01</NearClip>
<FarClip>5000</FarClip>
-1
View File
@@ -9,7 +9,6 @@
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Name" type="t:string" minOccurs="0"/>
<xs:element name="FOV" type="t:double" minOccurs="0">
<xs:annotation><xs:documentation>Vertical Field of View in degrees</xs:documentation></xs:annotation>
</xs:element>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<CapturePoint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="CapturePoint.xsd">
<CapturePointNumber>0</CapturePointNumber>
<CaptureTimer>0</CaptureTimer>
<HomePointForTeam><Spectator/></HomePointForTeam>
</CapturePoint>
@@ -0,0 +1,44 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:complexType name="TeamEnum" mixed="true">
<xs:complexContent>
<xs:extension base="t:enum">
<xs:choice>
<xs:element name="Spectator" type="xs:integer" fixed="1" minOccurs="0"/>
<xs:element name="Red" type="xs:integer" fixed="2" minOccurs="0"/>
<xs:element name="Blue" type="xs:integer" fixed="3" minOccurs="0"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="CapturePoint">
<xs:annotation>
<xs:documentation>A Capture Point. Add a Team Component to specify who currently owns it</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="CaptureTimer" type="t:double" minOccurs="0">
<xs:annotation>
<xs:documentation>CaptureTimer handled by Capture Point System</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="CapturePointNumber" type="t:int" minOccurs="0">
<xs:annotation>
<xs:documentation>CapturePointNumber specify an int number for this</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="HomePointForTeam" type="TeamEnum" minOccurs="0">
<xs:annotation>
<xs:documentation>Specify if this is a HomePoint for either team</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<DirectionalLight xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="DirectionalLight.xsd">
<Color R="1" G="1" B="1" A="1"/>
<Intensity>0.8</Intensity>
<Visible>true</Visible>
</DirectionalLight>
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="DirectionalLight">
<xs:annotation>
<xs:documentation>A directional light that shines bright like the future.</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Color" type="t:Color" minOccurs="0"/>
<xs:element name="Intensity" type="t:double" minOccurs="0"/>
<xs:element name="Visible" type="t:bool" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<EditorWidget xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="EditorWidget.xsd">
<Type><Translate/></Type>
<Axis X="0" Y="0" Z="0"/>
</EditorWidget>
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:complexType name="WidgetEnum" mixed="true">
<xs:complexContent>
<xs:extension base="t:enum">
<xs:choice>
<xs:element name="Translate" type="xs:integer" fixed="0" minOccurs="0"/>
<xs:element name="Rotate" type="xs:integer" fixed="1" minOccurs="0"/>
<xs:element name="Scale" type="xs:integer" fixed="2" minOccurs="0"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="EditorWidget">
<xs:complexType>
<xs:all>
<xs:element name="Type" type="WidgetEnum" minOccurs="0"/>
<xs:element name="Axis" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+3 -1
View File
@@ -9,7 +9,9 @@
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
<xs:element name="Velocity" type="t:Vector" minOccurs="0">
<xs:annotation><xs:documentation>m/s^2</xs:documentation></xs:annotation>
</xs:element>
<xs:element name="Gravity" type="t:bool" minOccurs="0"/>
</xs:all>
</xs:complexType>
+3
View File
@@ -4,6 +4,9 @@
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="Player">
<xs:annotation>
<xs:documentation>The player charachter</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Velocity" type="t:Vector" minOccurs="0"/>
+1 -1
View File
@@ -12,7 +12,7 @@
<xs:element name="Color" type="t:Color" minOccurs="0"/>
<xs:element name="Radius" type="t:double" minOccurs="0"/>
<xs:element name="Intensity" type="t:double" minOccurs="0"/>
<xs:element name="Falloff">
<xs:element name="Falloff" minOccurs="0">
<xs:simpleType>
<xs:restriction base="t:double">
<xs:minInclusive value="0"/>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<UniformScale xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="UniformScale.xsd">
<Scale X="1" Y="1" Z="1"/>
</UniformScale>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="types">
<xs:import schemaLocation="../Types.xsd" namespace="types"/>
<xs:element name="UniformScale">
<xs:annotation>
<xs:documentation>Keeps an entity at an uniform scale relative to the camera</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:all>
<xs:element name="Scale" type="t:Vector" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
+156
View File
@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.872664392" Y="0.157068729" Z="4.90324332e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.48757935" Y="2.62824345" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="1.91470337" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.31178355" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-4.27947044" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.67672658" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="2.40398169" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-2.38960934" Y="11.7122087" Z="11.4659815"/>
<Orientation X="-0.645771146" Y="-1.17512627e-05" Z="1.76718231e-07"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
<CaptureTimer>6.9158446328696002</CaptureTimer>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.48757935" Y="2.62824345" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CaptureTimer>-13.234195338196177</CaptureTimer>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="1.38422918" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.79222715" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-4.27947044" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="4.99647331" Y="2.23822045" Z="1.80651212"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="2.7091608" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.872664511" Y="0.157068729" Z="3.01738083e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.48757935" Y="2.62824345" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="1.91470337" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="-1.31178355" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-4.27947044" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-5.74354839" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.942477643" Y="0.157067701" Z="-1.50870125e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.39647007" Y="2.36802292" Z="0.0546064377"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="4.21088505" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="2.30499458" Y="2.04659939" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="0.196968079" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>4</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.82539892" Y="1.96172595" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="1.15194035" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-0.266237378" Y="2.23822045" Z="0.344228983"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="1.9484092"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="3.63076782" Y="2.5672617" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="-0.151326105" Y="13.5594187" Z="12.5957394"/>
<Orientation X="-0.62831825" Y="0.0872534811" Z="-7.47903606e-09"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.39647007" Y="2.36802292" Z="0.0546064377"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="3.68890452" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="1.98802853" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="0.196968079" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>4</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.82539892" Y="1.96172595" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-7.44269609" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-5.74354839" Y="2.23822045" Z="1.40012479"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="1.9484092"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="1" G="0.196078435" R="0.196078435"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="7.70311165" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
+52 -2
View File
@@ -13,6 +13,7 @@
</c:Model>
<c:Transform>
<Scale X="100" Y="1" Z="100"/>
<Orientation X="0" Y="2.59200001" Z="0"/>
</c:Transform>
</Components>
<Children/>
@@ -45,9 +46,58 @@
<Entity>
<Components>
<c:Camera/>
<c:Listener/>
<c:Transform>
<Position X="5.85247707" Y="3.8454349" Z="-1.14486957"/>
<Orientation X="2.51327395" Y="1.23916209" Z="-3.1415925"/>
<Position X="1.36896265" Y="4.4259491" Z="10.6640663"/>
<Orientation X="-0.0349078141" Y="0.157154545" Z="-2.60252193e-07"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:DirectionalLight/>
<c:Model>
<Resource>Models/DirectionalLightWidget.obj</Resource>
</c:Model>
<c:Transform>
<Position X="2.1529963" Y="6.59221172" Z="0.169116676"/>
<Orientation X="4.32000017" Y="4.6340003" Z="0"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Model>
<Resource>Models/Assault.obj</Resource>
</c:Model>
<c:Transform>
<Position X="-2.00568962" Y="0.527161121" Z="0"/>
</c:Transform>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>Models/SecondaryWeapon.fbx</Resource>
</c:Model>
<c:Transform>
<Position X="-0.546139359" Y="0.853016734" Z="0.177482292"/>
<Orientation X="1.47266471" Y="0.524984181" Z="1.243698"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
<Entity>
<Components>
<c:Model>
<Resource>Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Transform>
<Position X="0" Y="3.70000029" Z="0"/>
</c:Transform>
</Components>
<Children/>
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity name="WidgetRotate" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
<c:UniformScale>
<Scale X="0.200000003" Y="0.200000003" Z="0.200000003"/>
</c:UniformScale>
</Components>
<Children>
<Entity name="X">
<Components>
<c:EditorWidget>
<Type>
<Rotate/>
</Type>
<Axis X="1" Y="0" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/RotationWidgetX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Y">
<Components>
<c:EditorWidget>
<Type>
<Rotate/>
</Type>
<Axis X="0" Y="1" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/RotationWidgetY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Z">
<Components>
<c:EditorWidget>
<Type>
<Rotate/>
</Type>
<Axis X="0" Y="0" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/RotationWidgetZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Light">
<Components>
<c:PointLight>
<Intensity>-1</Intensity>
<Falloff>0</Falloff>
</c:PointLight>
<c:Transform/>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity name="WidgetScale" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Model>
<Resource>Models/ScaleWidgetOrigin.obj</Resource>
</c:Model>
<c:Transform/>
<c:UniformScale>
<Scale X="0.200000003" Y="0.200000003" Z="0.200000003"/>
</c:UniformScale>
</Components>
<Children>
<Entity name="X">
<Components>
<c:EditorWidget>
<Type>
<Scale/>
</Type>
</c:EditorWidget>
<c:Model>
<Resource>Models/ScaleWidgetX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Y">
<Components>
<c:EditorWidget>
<Type>
<Scale/>
</Type>
</c:EditorWidget>
<c:Model>
<Resource>Models/ScaleWidgetY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Z">
<Components>
<c:EditorWidget>
<Type>
<Scale/>
</Type>
</c:EditorWidget>
<c:Model>
<Resource>Models/ScaleWidgetZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Light">
<Components>
<c:PointLight/>
<c:Transform>
<Position X="0.300000012" Y="0.300000012" Z="0.300000012"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity name="WidgetTranslate" xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Model>
<Resource>Models/TranslationWidgetOrigin.obj</Resource>
</c:Model>
<c:Transform/>
<c:UniformScale>
<Scale X="0.200000003" Y="0.200000003" Z="0.200000003"/>
</c:UniformScale>
</Components>
<Children>
<Entity name="X">
<Components>
<c:EditorWidget>
<Axis X="1" Y="0" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/TranslationWidgetX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Y">
<Components>
<c:EditorWidget>
<Axis X="0" Y="1" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/TranslationWidgetY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Z">
<Components>
<c:EditorWidget>
<Axis X="0" Y="0" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/TranslationWidgetZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="XPlane">
<Components>
<c:EditorWidget>
<Axis X="0" Y="1" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/WidgetPlaneX.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="YPlane">
<Components>
<c:EditorWidget>
<Axis X="1" Y="0" Z="1"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/WidgetPlaneY.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="ZPlane">
<Components>
<c:EditorWidget>
<Axis X="1" Y="1" Z="0"/>
</c:EditorWidget>
<c:Model>
<Resource>Models/WidgetPlaneZ.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity name="Light">
<Components>
<c:PointLight/>
<c:Transform>
<Position X="0.400000006" Y="0.400000006" Z="0.400000006"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
@@ -0,0 +1,209 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Entity xmlns:c="components" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Types/Entity.xsd">
<Components>
<c:Transform/>
</Components>
<Children>
<Entity>
<Components>
<c:Model>
<Resource>../assets/Models/DummyScene.obj</Resource>
</c:Model>
<c:Transform/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>60</Health>
</c:Health>
<c:AABB/>
<c:Camera/>
<c:Listener/>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.7693491" Y="2.00600648" Z="2.02424884"/>
<Orientation X="0.157079354" Y="-0.872667432" Z="1.15912746e-08"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>3</HomePointForTeam>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="0.200000003" R="0"/>
</c:Model>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="5.39647007" Y="2.36802292" Z="0.0546064377"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>1</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="1" G="1" R="0"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="3.68890452" Y="2.32191443" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>2</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="1.98802853" Y="2.16289616" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<CapturePointNumber>3</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="1" R="1"/>
</c:Model>
<c:Team/>
<c:Transform>
<Position X="0.196968079" Y="1.99913001" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:AABB/>
<c:CapturePoint>
<HomePointForTeam>2</HomePointForTeam>
<CapturePointNumber>4</CapturePointNumber>
</c:CapturePoint>
<c:Model>
<Resource>../assets/Models/Core/UnitSphere.obj</Resource>
<Color A="1" B="0" G="0.200000003" R="1"/>
</c:Model>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-1.82539892" Y="1.96172595" Z="0"/>
</c:Transform>
<c:Trigger/>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-7.44269609" Y="2.23822045" Z="-0.0577065349"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health/>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0.482352942" G="0.490196079" R="1"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>2</Team>
</c:Team>
<c:Transform>
<Position X="-5.74354839" Y="2.23822045" Z="1.40012479"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>0</Health>
</c:Health>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0" G="0" R="2.25"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="6.96941662" Y="2.02053547" Z="1.9484092"/>
</c:Transform>
</Components>
<Children/>
</Entity>
<Entity>
<Components>
<c:Health>
<Health>0</Health>
</c:Health>
<c:AABB/>
<c:Model>
<Resource>../assets/Models/Core/UnitCube.obj</Resource>
<Color A="1" B="0" G="0" R="4.5"/>
</c:Model>
<c:Player/>
<c:Team>
<Team>3</Team>
</c:Team>
<c:Transform>
<Position X="7.70311165" Y="2.02053547" Z="-0.0348547697"/>
</c:Transform>
</Components>
<Children/>
</Entity>
</Children>
</Entity>
+3 -2
View File
@@ -9,12 +9,11 @@
<Resource>Models/DummyScene.obj</Resource>
</c:Model>
</Components>
</Entity>
<Children>
<Entity>
<Components>
<c:Transform>
<Position X="0" Y="-0"/>
<Position X="0" Y="0" Z="-2"/>
<Scale X="1" Y="1" Z="1"/>
</c:Transform>
<c:Camera>
@@ -24,4 +23,6 @@
</c:Model>
</Components>
</Entity>
<EntityRef file="Schema/Entities/EditorWidget.xml"/>
</Children>
</Entity>
+4 -2
View File
@@ -19,6 +19,7 @@
<xs:element ref="c:AABB" minOccurs="0"/>
<xs:element ref="c:Trigger" minOccurs="0"/>
<xs:element ref="c:Health" minOccurs="0"/>
<xs:element ref="c:CapturePoint" minOccurs="0"/>
<xs:element ref="c:PointLight" minOccurs="0"/>
<xs:element ref="c:Listener" minOccurs="0"/>
<xs:element ref="c:SoundEmitter" minOccurs="0"/>
@@ -27,6 +28,9 @@
<xs:element ref="c:SpawnPoint" minOccurs="0"/>
<xs:element ref="c:PlayerSpawn" minOccurs="0"/>
<xs:element ref="c:Team" minOccurs="0"/>
<xs:element ref="c:DirectionalLight" minOccurs="0"/>
<xs:element ref="c:UniformScale" minOccurs="0"/>
<xs:element ref="c:EditorWidget" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
@@ -37,9 +41,7 @@
<xs:element ref="Entity" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="EntityRef" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:attribute name="file" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
+16 -13
View File
@@ -27,19 +27,20 @@ layout (std430, binding = 0) buffer FrustumBuffer
Frustum Data[];
} Frustums;
struct PointLight {
struct LightSource {
vec4 Position;
vec4 Direction;
vec4 Color;
float Radius;
float Intensity;
float Falloff;
float Padding;
int Type;
};
layout (std430, binding = 1) buffer LightBuffer
{
PointLight List[];
} PointLights;
LightSource List[];
} LightSources;
struct LightGrid {
float Start;
@@ -106,8 +107,7 @@ layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main ()
{
GroupIndex = int(gl_WorkGroupID.x + (gl_WorkGroupID.y * int(ScreenDimensions.x/TILE_SIZE)));
if(gl_LocalInvocationIndex == 0)
{
if(gl_LocalInvocationIndex == 0) {
GroupLightCount = 0;
GroupFrustum = Frustums.Data[GroupIndex];
}
@@ -115,22 +115,25 @@ void main ()
barrier();
memoryBarrierShared();
for(int i = int(gl_LocalInvocationIndex); i < PointLights.List.length(); i += TILE_SIZE*TILE_SIZE)
{
PointLight light = PointLights.List[i];
for(int i = int(gl_LocalInvocationIndex); i < LightSources.List.length(); i += TILE_SIZE*TILE_SIZE) {
LightSource light = LightSources.List[i];
//if pointlight
//Pos i view antagligen
if(SphereInsideFrustrum( vec3(V * light.Position), light.Radius, GroupFrustum))
{
//TODO: Fix transparent and opaque list, and depth test.
AppendLight( i );
if(light.Type == 1) {
if(SphereInsideFrustrum( vec3(V * light.Position), light.Radius, GroupFrustum)) {
//TODO: Fix transparent and opaque list, and depth test.
AppendLight( i );
}
}
//if conelight
//if directional
if(light.Type == 2) {
AppendLight( i );
}
}
+39 -20
View File
@@ -9,19 +9,20 @@ uniform sampler2D texture0;
#define TILE_SIZE 16
struct PointLight {
struct LightSource {
vec4 Position;
vec4 Direction;
vec4 Color;
float Radius;
float Intensity;
float Falloff;
float Padding;
int Type;
};
layout (std430, binding = 1) buffer LightBuffer
{
PointLight List[];
} PointLights;
LightSource List[];
} LightSources;
struct LightGrid {
float Start;
@@ -71,7 +72,7 @@ vec4 CalcDiffuse(vec4 lightColor, vec4 lightVec, vec4 normal) {
return lightColor * power;
}
LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff)
LightResult CalcPointLightSource(vec4 lightPos, float lightRadius, vec4 lightColor, float intensity, vec4 viewVec, vec4 position, vec4 normal, float falloff)
{
vec4 L = lightPos - position;
float dist = length(L);
@@ -85,6 +86,16 @@ LightResult CalcPointLight(vec4 lightPos, float lightRadius, vec4 lightColor, fl
return result;
}
LightResult CalcDirectionalLightSource(vec4 direction, vec4 color, float intensity, vec4 viewVec, vec4 vertNormal)
{
vec4 L = normalize( -vec4(direction.xyz, 0) );
LightResult result;
result.Diffuse = CalcDiffuse(color, L, vertNormal) * intensity;
result.Specular = CalcSpecular(color, viewVec, L, vertNormal) * intensity;
return result;
}
void main()
{
@@ -94,8 +105,8 @@ void main()
vec4 viewVec = normalize(-position);
vec2 tilePos;
tilePos.x = int(gl_FragCoord.x/16);
tilePos.y = int(gl_FragCoord.y/16);
tilePos.x = int(gl_FragCoord.x/TILE_SIZE);
tilePos.y = int(gl_FragCoord.y/TILE_SIZE);
LightResult totalLighting;
totalLighting.Diffuse = scene_ambient;
@@ -103,30 +114,38 @@ void main()
int start = int(LightGrids.Data[currentTile].Start);
int amount = int(LightGrids.Data[currentTile].Amount);
//for(int i = 0; i < 3; i++)
for(int i = start; i < start + amount; i++)
{
for(int i = start; i < start + amount; i++) {
int l = int(LightIndex[i]);
LightSource light = LightSources.List[l];
LightResult result = CalcPointLight(V * PointLights.List[l].Position, PointLights.List[l].Radius, PointLights.List[l].Color, PointLights.List[l].Intensity, viewVec, position, normal, PointLights.List[i].Falloff);
LightResult result;
if(light.Type == 1) { // point
result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff);
} else if (light.Type == 2) { //Directional
result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal);
}
totalLighting.Diffuse += result.Diffuse;
totalLighting.Specular += result.Specular;
}
//fragmentColor += Input.DiffuseColor;
fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse + totalLighting.Specular) * texel * Color;
//fragmentColor += Input.DiffuseColor * (totalLighting.Diffuse) * texel * Color;
//fragmentColor += vec4(0.0, LightGrids.Data[currentTile].Amount/3.0, 0, 1);
//fragmentColor += Input.DiffuseColor + vec4(0.0, LightGrids.Data[currentTile].Amount/3, 0, 1);
//fragmentColor = texel * Input.DiffuseColor * Color;
if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 )
{
//fragmentColor += vec4(0.5, 0, 0, 0);
//fragmentColor += vec4(currentTile/3600.f, 0, 0, 1);
//Tiled Debug Code
/*
if(int(gl_FragCoord.x)%16 == 0 || int(gl_FragCoord.y)%16 == 0 ) {
fragmentColor += vec4(0.5, 0, 0, 0);
} else {
//fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/3.0, 0, 0, 1);
fragmentColor += vec4(LightGrids.Data[int(tilePos.x + tilePos.y*80)].Amount/LightSources.List.length(), 0, 0, 1);
}
*/
}
+1 -1
View File
@@ -29,6 +29,6 @@ void main()
Output.Position = Position;
Output.TextureCoordinate = TextureCoords;
Output.Normal = Normal;
Output.Normal = vec3(M * vec4(Normal, 0.0));
Output.DiffuseColor = DiffuseVertexColor;
}
@@ -1,11 +1,11 @@
#include "Collision/CollidableOctreeSystem.h"
void CollidableOctreeSystem::Update(World* world, double dt)
void CollidableOctreeSystem::Update(double dt)
{
m_Octree->ClearDynamicObjects();
}
void CollidableOctreeSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
if (entity.HasComponent("AABB")) {
boost::optional<AABB> absoluteAABB = Collision::EntityAbsoluteAABB(entity);
+1 -1
View File
@@ -2,7 +2,7 @@
#include "Collision/CollisionSystem.h"
#include "Core/AABB.h"
void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
if (!entity.HasComponent("Physics")) {
return;
+3 -3
View File
@@ -3,10 +3,10 @@
#include "Core/AABB.h"
#include "Rendering/Model.h"
void TriggerSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt)
void TriggerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt)
{
//Currently only players can trigger things.
auto players = world->GetComponents("Player");
auto players = m_World->GetComponents("Player");
if (players == nullptr) {
return;
}
@@ -18,7 +18,7 @@ void TriggerSystem::UpdateComponent(World* world, EntityWrapper& entity, Compone
}
for (auto& pc : *players) {
EntityID pId = pc.EntityID;
boost::optional<AABB> playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(world, pId));
boost::optional<AABB> playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(m_World, pId));
//The player can't trigger anything without an AABB.
if (!playerBox) {
continue;
+5 -1
View File
@@ -50,7 +50,6 @@ ComponentWrapper ComponentPool::GetByEntity(EntityID ent)
return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent));
}
bool ComponentPool::KnowsEntity(EntityID ent)
{
return m_EntityToComponent.find(ent) != m_EntityToComponent.end();
@@ -72,6 +71,11 @@ ComponentPool::iterator ComponentPool::end() const
return iterator(m_ComponentInfo, m_Pool.end(), m_Pool.end());
}
size_t ComponentPool::size() const
{
return m_Pool.size();
}
template <typename InterpretType /*= char*/>
void ComponentPool::Dump() const
{
+25 -19
View File
@@ -47,7 +47,7 @@ std::size_t EntityFile::GetTypeStride(std::string typeName)
{ "float", sizeof(float) },
{ "double", sizeof(double) },
{ "string", sizeof(std::string) },
{ "enum", sizeof(int) },
{ "enum", sizeof(ComponentInfo::EnumType) },
{ "Vector", sizeof(glm::vec3) },
{ "Quaternion", sizeof(glm::quat) },
{ "Color", sizeof(glm::vec4) }
@@ -86,23 +86,29 @@ void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t&
void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData)
{
if (field.Type == "int" || field.Type == "enum") {
int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "float") {
float value = boost::lexical_cast<float>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "double") {
double value = boost::lexical_cast<double>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "bool") {
bool value = (valueData[0] == 't'); // Lazy bool evaluation
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "string") {
new (outData) std::string(valueData);
} else {
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
}
// Catch and ignore casting errors so whitespace around string enums won't mess anything up
try {
if (field.Type == "int") {
int value = boost::lexical_cast<int>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "enum") {
ComponentInfo::EnumType value = boost::lexical_cast<ComponentInfo::EnumType>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "float") {
float value = boost::lexical_cast<float>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "double") {
double value = boost::lexical_cast<double>(valueData);
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "bool") {
bool value = (valueData[0] == 't'); // Lazy bool evaluation
memcpy(outData, reinterpret_cast<char*>(&value), field.Stride);
} else if (field.Type == "string") {
new (outData) std::string(valueData);
} else {
LOG_WARNING("Unknown value data type: %s", field.Type.c_str());
}
} catch (const boost::bad_lexical_cast&) { }
}
EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) : m_Handler(handler)
@@ -165,7 +171,7 @@ void EntityFileSAXHandler::endElement(const XMLCh* const _uri, const XMLCh* cons
//}
}
if (m_StateStack.top() == State::ComponentField) {
if (m_StateStack.top() == State::ComponentField && name == m_CurrentField) {
m_StateStack.pop();
onEndComponentField(name);
return;
+7 -7
View File
@@ -28,14 +28,14 @@ void EntityFileParser::onStartEntity(EntityID entity, EntityID parent, const std
m_World->SetName(realEntity, name);
}
m_EntityIDMapper[entity] = realEntity;
LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent);
//LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent);
}
void EntityFileParser::onStartComponent(EntityID entity, const std::string& component)
{
EntityID realEntity = m_EntityIDMapper.at(entity);
m_World->AttachComponent(realEntity, component);
LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity);
//LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity);
}
void EntityFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map<std::string, std::string>& attributes)
@@ -49,11 +49,11 @@ void EntityFileParser::onStartComponentField(EntityID entity, const std::string&
}
auto& field = fieldIt->second;
LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str());
LOG_DEBUG("Attributes:");
for (auto& kv : attributes) {
LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str());
}
//LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str());
//LOG_DEBUG("Attributes:");
//for (auto& kv : attributes) {
// LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str());
//}
char* data = component.Data + field.Offset;
EntityFile::WriteAttributeData(data, field, attributes);
+21 -22
View File
@@ -7,23 +7,23 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile)
handler.SetStartComponentCallback(std::bind(&EntityFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2));
m_EntityFile->Parse(&handler);
LOG_DEBUG("___ COMPONENT DEFINITIONS ___");
for (auto& kv : m_ComponentCounts) {
LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second);
}
//LOG_DEBUG("___ COMPONENT DEFINITIONS ___");
//for (auto& kv : m_ComponentCounts) {
// LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second);
//}
parseComponentInfo();
for (auto& kv : m_ComponentInfo) {
auto& info = kv.second;
LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str());
LOG_DEBUG("Stride: %i", info.Stride);
LOG_DEBUG("Allocation: %i", info.Meta->Allocation);
for (auto& kv : info.Fields) {
auto& field = kv.second;
LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type.c_str(), kv.first.c_str());
}
}
//for (auto& kv : m_ComponentInfo) {
// auto& info = kv.second;
// LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str());
// LOG_DEBUG("Stride: %i", info.Stride);
// LOG_DEBUG("Allocation: %i", info.Meta->Allocation);
// for (auto& kv : info.Fields) {
// auto& field = kv.second;
// LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type.c_str(), kv.first.c_str());
// }
//}
parseDefaults();
}
@@ -50,7 +50,6 @@ void EntityFilePreprocessor::parseComponentInfo()
auto xsModel = grammarPool->getXSModel(whateverTheFuckThisIs);
// Find component xsd element declarations
std::cout << "Enumerating components..." << std::endl;
// <xs:element name="ComponentName">
auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION);
for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) {
@@ -73,7 +72,7 @@ void EntityFilePreprocessor::parseComponentInfo()
if (componentAnnotation != nullptr) {
compInfo.Meta->Annotation = parseAnnotationXML(componentAnnotation->getAnnotationString());
} else {
LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str());
//LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str());
}
// <xs:complexType>
@@ -91,7 +90,7 @@ void EntityFilePreprocessor::parseComponentInfo()
// <xs:all>
auto modelGroupParticle = complexTypeDefinition->getParticle();
if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) {
LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
//LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str());
continue;
}
auto modelGroup = modelGroupParticle->getModelGroupTerm();
@@ -103,7 +102,7 @@ void EntityFilePreprocessor::parseComponentInfo()
for (unsigned int i = 0; i < particles->size(); ++i) {
auto particle = particles->elementAt(i);
if (particle->getTermType() != XSParticle::TERM_ELEMENT) {
LOG_ERROR("Failed to parse a field definition in component \"%s\": Particle wasn't TERM_ELEMENT! Skipping.", compInfo.Name.c_str());
//LOG_ERROR("Failed to parse a field definition in component \"%s\": Particle wasn't TERM_ELEMENT! Skipping.", compInfo.Name.c_str());
continue;
}
auto elementDeclaration = particle->getElementTerm();
@@ -129,7 +128,7 @@ void EntityFilePreprocessor::parseComponentInfo()
if (fieldAnnotation != nullptr) {
compInfo.Meta->FieldAnnotations[name] = parseAnnotationXML(fieldAnnotation->getAnnotationString());
} else {
LOG_WARNING("Component field \"%s.%s\" is missing an annotation!", compInfo.Name.c_str(), name.c_str());
//LOG_WARNING("Component field \"%s.%s\" is missing an annotation!", compInfo.Name.c_str(), name.c_str());
}
if (effectiveType == "enum") {
@@ -146,8 +145,8 @@ void EntityFilePreprocessor::parseComponentInfo()
auto enumElement = xsChoiceParticles->elementAt(i)->getElementTerm();
std::string enumName = XS::ToString(enumElement->getName());
std::string enumValue = XS::ToString(enumElement->getConstraintValue());
compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast<int>(enumValue);
LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str());
compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast<ComponentInfo::EnumType>(enumValue);
//LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str());
}
}
}
@@ -190,7 +189,7 @@ void EntityFilePreprocessor::parseDefaults()
//std::string namespaceSchema = schemaLocation.string();
//parser.setExternalNoNamespaceSchemaLocation("Teamasdasdasdasd.xsd");
LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
//LOG_DEBUG("Parsing defaults for component %s", componentName.c_str());
boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml";
parser.parse(defaultsFile.string().c_str());
+10 -1
View File
@@ -114,9 +114,18 @@ void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement
fieldElement->setAttribute(X("Y"), X(boost::lexical_cast<std::string>(q.y)));
fieldElement->setAttribute(X("Z"), X(boost::lexical_cast<std::string>(q.z)));
fieldElement->setAttribute(X("W"), X(boost::lexical_cast<std::string>(q.w)));
} else if (field.Type == "int" || field.Type == "enum") {
} else if (field.Type == "int") {
const int& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
} else if (field.Type == "enum") {
const ComponentInfo::EnumType& value = c[fieldName];
auto& enumDef = c.Info.Meta->FieldEnumDefinitions.at(fieldName);
for (auto& kv : enumDef) {
if (kv.second == value) {
fieldElement->appendChild(doc->createElement(X(kv.first)));
break;
}
}
} else if (field.Type == "float") {
const float& value = c[fieldName];
fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast<std::string>(value))));
+45 -8
View File
@@ -3,28 +3,65 @@
const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid);
bool EntityWrapper::operator==(const EntityWrapper& e)
{
return (this->World == e.World) && (this->ID == e.ID);
}
bool EntityWrapper::HasComponent(const std::string& componentName)
{
return World->HasComponent(ID, componentName);
}
ComponentWrapper EntityWrapper::operator[](const std::string& componentName)
EntityWrapper EntityWrapper::Parent()
{
if (this->World == nullptr || this->ID == EntityID_Invalid) {
return EntityWrapper::Invalid;
} else {
return EntityWrapper(this->World, this->World->GetParent(this->ID));
}
}
bool EntityWrapper::Valid()
{
if (this->World == nullptr) {
return false;
}
if (this->ID == EntityID_Invalid) {
return false;
}
if (!this->World->ValidEntity(this->ID)) {
this->ID = EntityID_Invalid;
return false;
}
return true;
}
ComponentWrapper EntityWrapper::operator[](const char* componentName)
{
if (World->HasComponent(ID, componentName)) {
return World->GetComponent(ID, componentName);
} else {
LOG_WARNING("EntityWrapper implicitly attached \"%s\" component to #%i as a result of a fetch request!", componentName.c_str(), ID);
LOG_WARNING("EntityWrapper implicitly attached \"%s\" component to #%i as a result of a fetch request!", componentName, ID);
return World->AttachComponent(ID, componentName);
}
}
EntityWrapper::operator EntityID()
bool EntityWrapper::operator==(const EntityWrapper& e) const
{
return (this->ID == e.ID) && (this->World == e.World);
}
bool EntityWrapper::operator!=(const EntityWrapper& e) const
{
return !this->operator==(e);
}
EntityWrapper::operator EntityID() const
{
return this->ID;
}
EntityWrapper::operator bool()
{
return this->Valid();
}
+6
View File
@@ -34,10 +34,16 @@ void InputManager::Update(double dt)
if (m_CurrentKeyState[i]) {
Events::KeyDown e;
e.KeyCode = i;
e.ModCtrl = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_CONTROL);
e.ModAlt = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_ALT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_ALT);
e.ModShift = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_SHIFT);
m_EventBroker->Publish(e);
} else {
Events::KeyUp e;
e.KeyCode = i;
e.ModCtrl = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_CONTROL);
e.ModAlt = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_ALT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_ALT);
e.ModShift = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_SHIFT);
m_EventBroker->Publish(e);
}
}
+24
View File
@@ -0,0 +1,24 @@
#include "Core/UniformScaleSystem.h"
UniformScaleSystem::UniformScaleSystem(World* world, EventBroker* eventBroker)
: System(world, eventBroker)
, PureSystem("UniformScale")
{
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &UniformScaleSystem::OnSetCamera);
}
void UniformScaleSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt)
{
if (!m_Camera.Valid()) {
return;
}
float distance = glm::length((glm::vec3)entity["Transform"]["Position"] - (glm::vec3&)m_Camera["Transform"]["Position"]);
entity["Transform"]["Scale"] = (glm::vec3&)cUniformScale["Scale"] * distance;
}
bool UniformScaleSystem::OnSetCamera(const Events::SetCamera& e)
{
m_Camera = e.CameraEntity;
return false;
}
+734
View File
@@ -0,0 +1,734 @@
#include "Editor/EditorGUI.h"
EditorGUI::EditorGUI(World* world, EventBroker* eventBroker)
: m_World(world)
, m_EventBroker(eventBroker)
{
EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &EditorGUI::OnKeyDown);
}
void EditorGUI::Draw()
{
ImGui::ShowTestWindow();
drawMenu();
drawTools();
drawEntities(m_World);
drawComponents(m_CurrentSelection);
drawModals();
}
void EditorGUI::SelectEntity(EntityWrapper entity)
{
m_CurrentSelection = entity;
if (m_OnEntitySelected != nullptr) {
m_OnEntitySelected(entity);
}
}
void EditorGUI::drawMenu()
{
}
void EditorGUI::drawTools()
{
if (!ImGui::Begin("Tools", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize)) {
return;
}
createWidgetToolButton(WidgetMode::Translate);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Translate");
}
ImGui::SameLine();
createWidgetToolButton(WidgetMode::Rotate);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Rotate");
}
ImGui::SameLine();
createWidgetToolButton(WidgetMode::Scale);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Scale");
}
ImGui::SameLine();
ImGui::ItemSize(ImVec2(5, 0));
// Play button
ImGui::SameLine();
static bool paused = false;
if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Play.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
Events::Resume e;
e.World = m_World;
m_EventBroker->Publish(e);
paused = false;
}
// Pause button
ImGui::SameLine();
if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Pause.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) {
Events::Pause e;
e.World = m_World;
m_EventBroker->Publish(e);
paused = true;
}
ImGui::End();
}
void EditorGUI::drawEntities(World* world)
{
if (!ImGui::Begin("Entities")) {
ImGui::End();
return;
}
float buttonWidth = (ImGui::GetContentRegionAvailWidth() - 10.f) / 3.f ;
if (ImGui::Button("Create", ImVec2(buttonWidth, 0))) {
entityCreate(world, m_CurrentSelection);
}
ImGui::SameLine(0.f, 5.f);
if (ImGui::Button("Import", ImVec2(buttonWidth, 0))) {
entityImport(world);
}
ImGui::SameLine(0.f, 5.f);
ImGui::ButtonEx("Reference", ImVec2(buttonWidth, 0), ImGuiButtonFlags_Disabled);
// Naming
char buffer[256];
buffer[0] = '\0';
buffer[255] = '\0';
std::size_t nameLength = 0;
ImGuiInputTextFlags flags = ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll;
if (m_CurrentSelection.Valid()) {
std::string name = world->GetName(m_CurrentSelection.ID);
nameLength = name.length();
if (!name.empty()) {
memcpy(buffer, name.c_str(), std::min(sizeof(buffer) - 1, name.length() + 1));
}
} else {
flags |= ImGuiInputTextFlags_ReadOnly;
}
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 7.f);
if (ImGui::InputText("", &buffer[0], sizeof(buffer), flags)) {
if (m_CurrentSelection.Valid()) {
if (m_OnEntityChangeName != nullptr) {
m_OnEntityChangeName(m_CurrentSelection, std::string(buffer));
SetDirty(m_CurrentSelection);
}
}
}
ImGui::PopItemWidth();
ImGui::ItemSize(ImVec2(0, 3));
drawEntitiesRecursive(world, EntityID_Invalid);
ImGui::End();
}
void EditorGUI::drawEntitiesRecursive(World* world, EntityID parent)
{
auto entityChildren = world->GetEntityChildren();
auto range = entityChildren.equal_range(parent);
for (auto it = range.first; it != range.second; it++) {
if (EditorGUI::drawEntityNode(EntityWrapper(world, it->second))) {
drawEntitiesRecursive(world, it->second);
ImGui::TreePop();
}
}
}
bool EditorGUI::drawEntityNode(EntityWrapper entity)
{
// Custom button hitbox to select entities on top of tree node
ImVec2 pos = ImGui::GetCursorScreenPos();
float width = ImGui::GetContentRegionAvailWidth();
ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 14));
auto window = ImGui::GetCurrentWindow();
if (m_CurrentSelection == entity) {
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
window->DrawList->AddRectFilled(bb.Min, bb.Max, col);
}
ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(entity.ID)).c_str());
bool hovered = false;
bool held = false;
if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) {
SelectEntity(entity);
}
// Handle entity dragging
if (held) {
ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0);
if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) {
if (m_CurrentlyDragging == EntityWrapper::Invalid) {
m_CurrentlyDragging = entity;
LOG_DEBUG("Started dragging %i", entity.ID);
}
ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0));
ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings);
ImGui::Text(formatEntityName(entity).c_str());
ImGui::End();
}
}/* else if (m_CurrentlyDragging == entity) {
LOG_DEBUG("Stopped dragging %i", entity.ID);
m_CurrentlyDragging = EntityWrapper::Invalid;
}*/
// Entity context menu
std::string contextMenuUniqueID = std::string("EntityContextMenu") + std::to_string(entity.ID);
if (hovered && ImGui::IsMouseClicked(1)) {
ImGui::OpenPopup(contextMenuUniqueID.c_str());
}
if (ImGui::BeginPopup(contextMenuUniqueID.c_str())) {
ImGui::TextDisabled(formatEntityName(entity).c_str());
if (ImGui::MenuItem("Save", "Ctrl+S")) {
entitySave(entity);
} else
if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) {
entitySave(entity, true);
} else
if (ImGui::MenuItem("Delete", "Del")) {
entityDelete(entity);
} else
if (ImGui::MenuItem("Move to root")) {
entityChangeParent(entity, EntityWrapper::Invalid);
}
ImGui::EndPopup();
}
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
if (ImGui::TreeNode(formatEntityName(entity).c_str())) {
// Handle drop events for reparenting
if (m_CurrentlyDragging != EntityWrapper::Invalid && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) {
entityChangeParent(m_CurrentlyDragging, entity);
m_CurrentlyDragging = EntityWrapper::Invalid;
}
return true;
} else {
return false;
}
}
void EditorGUI::drawComponents(EntityWrapper entity)
{
std::stringstream title;
title << "Components";
if (entity.Valid()) {
title << " " << formatEntityName(entity);
}
title << "###Components";
if (!ImGui::Begin(title.str().c_str())) {
ImGui::End();
return;
}
if (!entity.Valid()) {
ImGui::End();
return;
}
auto& pools = entity.World->GetComponentPools();
// Create list of component types available to be added
std::vector<const char*> componentTypes;
for (auto& pair : pools) {
// Don't list components the entity already has attached
if (!entity.HasComponent(pair.first)) {
componentTypes.push_back(pair.first.c_str());
}
}
// Draw combo box
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 10.f);
int selectedItem = -1;
if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size())) {
if (selectedItem != -1) {
if (m_OnComponentAttach != nullptr) {
std::string chosenComponentType(componentTypes.at(selectedItem));
m_OnComponentAttach(entity, chosenComponentType);
SetDirty(entity);
}
}
}
ImGui::PopItemWidth();
for (auto& pair : pools) {
const std::string& componentType = pair.first;
auto pool = pair.second;
// Don't show components the entity doesn't have attached
if (!entity.HasComponent(componentType)) {
continue;
}
// Handle deletion with early out
if (createDeleteButton(componentType)) {
if (m_OnComponentDelete != nullptr) {
m_OnComponentDelete(entity, componentType);
continue;
}
}
// Draw the actual component node
drawComponentNode(entity, pool->ComponentInfo());
}
ImGui::End();
}
bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci)
{
if (!ImGui::CollapsingHeader(ci.Name.c_str(), nullptr, true, true)) {
return false;
}
// Show component annotation
const std::string annotation = ci.Meta->Annotation;
if (!annotation.empty()) {
ImGui::TextWrapped(annotation.c_str());
}
// Draw component fields
ComponentWrapper& component = entity.World->GetComponent(entity.ID, ci.Name);
for (auto& kv : ci.Fields) {
const std::string& fieldName = kv.first;
const ComponentInfo::Field_t& field = kv.second;
// Draw the field widget based on its type
bool dirty = drawComponentField(component, field);
if (dirty) {
SetDirty(entity);
}
ImGui::SameLine();
// Draw field name
ImGui::Text(fieldName.c_str());
// Draw potential field annotation
auto fieldAnnotationIt = ci.Meta->FieldAnnotations.find(fieldName);
if (fieldAnnotationIt != ci.Meta->FieldAnnotations.end()) {
ImGui::SameLine();
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(fieldAnnotationIt->second.c_str());
}
}
}
return true;
}
bool EditorGUI::drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field)
{
// Push an unique widget id so different components with fields with equal names are still counted as different
ImGui::PushID((c.Info.Name + field.Name).c_str());
bool dirty = false;
if (field.Type == "Vector") {
dirty = drawComponentField_Vector(c, field);
} else if (field.Type == "Color") {
dirty = drawComponentField_Color(c, field);
//} else if (field.Type == "Quaternion") {
} else if (field.Type == "int") {
dirty = drawComponentField_int(c, field);
} else if (field.Type == "enum") {
dirty = drawComponentField_enum(c, field);
} else if (field.Type == "float") {
dirty = drawComponentField_float(c, field);
} else if (field.Type == "double") {
dirty = drawComponentField_double(c, field);
} else if (field.Type == "bool") {
dirty = drawComponentField_bool(c, field);
} else if (field.Type == "string") {
dirty = drawComponentField_string(c, field);
} else {
ImGui::TextDisabled(field.Type.c_str());
}
ImGui::PopID();
return dirty;
}
bool EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<glm::vec3>(field.Name);
if (field.Name == "Scale") {
// Limit scale values to a minimum of 0
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
} else if (field.Name == "Orientation") {
// Make orentations have a period of 2*Pi
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
val = tempVal;
return true;
} else {
return false;
}
} else {
return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
}
}
bool EditorGUI::drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<glm::vec4>(field.Name);
return ImGui::ColorEdit4("", glm::value_ptr(val), true);
}
bool EditorGUI::drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<int>(field.Name);
return ImGui::InputInt("", &val);
}
bool EditorGUI::drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto fieldEnumDefIt = c.Info.Meta->FieldEnumDefinitions.find(field.Name);
if (fieldEnumDefIt == c.Info.Meta->FieldEnumDefinitions.end()) {
return drawComponentField_int(c, field);
}
auto& val = c.Field<int>(field.Name);
int selectedItem = -1;
std::stringstream enumKeys;
std::vector<int> enumValues;
int i = 0;
for (auto& kv : fieldEnumDefIt->second) {
enumKeys << kv.first << " (" << kv.second << ")" << '\0';
enumValues.push_back(kv.second);
if (val == kv.second) {
selectedItem = i;
}
i++;
}
if (ImGui::Combo("", &selectedItem, enumKeys.str().c_str())) {
val = enumValues.at(selectedItem);
return true;
} else {
return false;
}
}
bool EditorGUI::drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<float>(field.Name);
return ImGui::InputFloat("", &val, 0.01f, 1.f);
}
bool EditorGUI::drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
float tempVal = static_cast<float>(c.Field<double>(field.Name));
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
c.SetField(field.Name, static_cast<double>(tempVal));
return true;
} else {
return false;
}
}
bool EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<bool>(field.Name);
return ImGui::Checkbox("", &val);
}
bool EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field)
{
auto& val = c.Field<std::string>(field.Name);
char tempString[1024]; // Let's just hope this is an sufficiently large buffer for strings :)
tempString[1023] = '\0'; // Null terminator just in case the string is larger than the buffer
// Copy the string into the buffer, taking the null terminator into account
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString) - 1));
if (ImGui::InputText("", tempString, sizeof(tempString))) {
val = std::string(tempString);
return true;
} else {
return false;
}
// TODO: Handle drag and drop of files
}
void EditorGUI::drawModals()
{
for (auto& modal : m_ModalsToOpen) {
ImGui::OpenPopup(modal.c_str());
}
m_ModalsToOpen.clear();
if (ImGui::BeginPopupModal("Import failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Entity import failed. Check console for more information.\n\n");
ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120);
if (ImGui::Button("OK", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal("Save failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Entity save failed on an exception.\nMessage: %s\n\n", m_LastErrorMessage.c_str());
ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120);
if (ImGui::Button("OK", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal("Confirm deletion", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
if (m_ModalData.count("Confirm deletion") == 0) {
ImGui::CloseCurrentPopup();
}
ImGui::Text("Are you sure you want to delete entity \"%s\"?", formatEntityName(m_CurrentSelection).c_str());
ImGui::ItemSize(ImVec2(5.f, 0.f));
ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 2*60);
if (ImGui::Button("Delete (Del)", ImVec2(60, 0))) {
entityDelete(boost::any_cast<EntityWrapper>(m_ModalData.at("Confirm deletion")));
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(60, 0))) {
m_ModalData.erase("Confirm deletion");
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
bool EditorGUI::createDeleteButton(const std::string& componentType)
{
float width = ImGui::GetContentRegionAvailWidth();
ImGuiWindow* window = ImGui::GetCurrentWindow();
auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1);
ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f));
std::string idString = "#DELETE";
idString += componentType;
ImGuiID id = window->GetID(idString.c_str());
bool hovered;
bool held;
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
//ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
return pressed;
}
void EditorGUI::createWidgetToolButton(WidgetMode mode)
{
GLuint texture = 0;
switch (mode) {
case WidgetMode::Translate:
texture = tryLoadTexture("Textures/Icons/Translate.png");
break;
case WidgetMode::Rotate:
texture = tryLoadTexture("Textures/Icons/Rotate.png");
break;
case WidgetMode::Scale:
texture = tryLoadTexture("Textures/Icons/Scale.png");
break;
}
if (ImGui::ImageButton(
(void*)texture,
ImVec2(24, 24),
ImVec2(0, 1),
ImVec2(1, 0),
-1,
ImVec4(0, 0, 0, 0),
(m_CurrentWidgetMode == mode) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1)
)
) {
if (m_OnWidgetMode != nullptr) {
m_OnWidgetMode(mode);
}
m_CurrentWidgetMode = mode;
}
}
bool EditorGUI::OnKeyDown(const Events::KeyDown& e)
{
if (e.ModCtrl && e.KeyCode == GLFW_KEY_S) {
if (m_CurrentSelection.Valid()) {
EntityWrapper baseParent = m_CurrentSelection;
while (baseParent.Parent().Valid()) {
baseParent = baseParent.Parent();
}
entitySave(baseParent);
}
}
if (e.ModCtrl && e.KeyCode == GLFW_KEY_N) {
entityCreate(m_World, m_CurrentSelection);
}
if (e.ModCtrl && e.KeyCode == GLFW_KEY_O) {
entityImport(m_World);
}
if (e.KeyCode == GLFW_KEY_DELETE) {
if (m_CurrentSelection.Valid()) {
entityDelete(m_CurrentSelection);
}
}
return true;
}
boost::filesystem::path EditorGUI::fileOpenDialog()
{
namespace bfs = boost::filesystem;
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_OpenDialog("xml", bfs::absolute(m_DefaultEntityPath).string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
} else if (result == NFD_CANCEL) {
return bfs::path();
} else {
return bfs::absolute(outPath);
}
}
boost::filesystem::path EditorGUI::fileSaveDialog()
{
namespace bfs = boost::filesystem;
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_SaveDialog("xml", bfs::absolute(m_DefaultEntityPath).string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
} else if (result == NFD_CANCEL) {
return bfs::path();
} else {
return bfs::absolute(outPath);
}
}
const std::string EditorGUI::formatEntityName(EntityWrapper entity)
{
if (!entity.Valid()) {
return "EntityID_Invalid";
}
std::stringstream name;
std::string entityName = entity.World->GetName(entity.ID);
if (!entityName.empty()) {
name << entityName;
} else {
name << "#" << entity.ID;
}
if (m_EntityFiles.count(entity) == 1) {
name << " (" << m_EntityFiles.at(entity).Path.filename().string() << ")";
if (m_EntityFiles.at(entity).Dirty) {
name << "*";
}
}
return name.str();
}
GLuint EditorGUI::tryLoadTexture(std::string filePath)
{
GLuint texture = 0;
try {
texture = ResourceManager::Load<Texture>(filePath)->m_Texture;
} catch (const std::exception&) { }
return texture;
}
void EditorGUI::openModal(const std::string& modal)
{
m_ModalsToOpen.insert(modal);
}
void EditorGUI::SetDirty(EntityWrapper entity)
{
EntityWrapper baseParent = entity;
while (baseParent.Parent().Valid()) {
baseParent = baseParent.Parent();
}
if (m_EntityFiles.find(baseParent) != m_EntityFiles.end()) {
m_EntityFiles.at(baseParent).Dirty = true;
}
}
void EditorGUI::entityImport(World* world)
{
boost::filesystem::path filePath = fileOpenDialog();
if (filePath.empty()) {
return;
}
EntityWrapper entity = m_OnEntityImport(EntityWrapper(world, EntityID_Invalid), filePath);
if (entity.Valid()) {
m_EntityFiles[entity].Path = filePath;
SelectEntity(entity);
} else {
openModal("Import failed");
}
}
void EditorGUI::entitySave(EntityWrapper entity, bool saveAs /* = false */)
{
boost::filesystem::path filePath;
if (!saveAs && m_EntityFiles.count(entity) == 1) {
filePath = m_EntityFiles.at(entity).Path;
} else {
filePath = fileSaveDialog();
}
if (filePath.empty()) {
return;
}
try {
m_OnEntitySave(entity, filePath);
m_EntityFiles[entity].Path = filePath;
m_EntityFiles[entity].Dirty = false;
} catch (const std::exception& e) {
m_LastErrorMessage = e.what();
openModal("Save failed");
}
}
void EditorGUI::entityCreate(World* world, EntityWrapper parent)
{
if (m_OnEntityCreate != nullptr) {
// Create the new entity in the world we're drawing for
if (parent.World == nullptr) {
parent.World = world;
}
EntityWrapper newEntity = m_OnEntityCreate(parent);
SelectEntity(newEntity);
}
}
void EditorGUI::entityDelete(EntityWrapper entity)
{
std::string modalName = "Confirm deletion";
if (m_ModalData.count(modalName) == 0) {
m_ModalData[modalName] = entity;
openModal(modalName);
} else {
if (boost::any_cast<EntityWrapper>(m_ModalData[modalName]) == entity) {
EntityWrapper parent = entity.Parent();
if (m_OnEntityDelete != nullptr) {
SetDirty(entity);
m_OnEntityDelete(entity);
m_EntityFiles.erase(entity);
}
if (!m_CurrentSelection.Valid()) {
SelectEntity(parent);
}
}
m_ModalData.erase(modalName);
}
}
void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent)
{
if (entity == parent) {
return;
}
if (m_OnEntityChangeParent != nullptr) {
SetDirty(entity);
m_OnEntityChangeParent(entity, parent);
LOG_DEBUG("Changed parent of %i to %i", entity.ID, parent.ID);
}
}
+87
View File
@@ -0,0 +1,87 @@
#include "Editor/EditorRenderSystem.h"
EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
: System(m_World, eventBroker)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
{
EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &EditorRenderSystem::OnSetCamera);
auto resolution = Rectangle::Rectangle(1280, 720);
m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.01f, 5000.f);
}
void EditorRenderSystem::Update(double dt)
{
if (m_CurrentCamera) {
ComponentWrapper cameraTransform = m_CurrentCamera["Transform"];
m_EditorCamera->SetPosition(cameraTransform["Position"]);
m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"]));
}
RenderScene scene;
scene.ClearDepth = true;
scene.Camera = m_EditorCamera;
scene.Viewport = Rectangle(1920, 1080);
auto models = m_World->GetComponents("Model");
if (models != nullptr) {
for (auto& cModel : *models) {
if (!(bool)cModel["Visible"]) {
continue;
}
const std::string& resource = cModel["Resource"];
Model* model;
try {
model = ResourceManager::Load<::Model, true>(resource);
} catch (const Resource::StillLoadingException&) {
continue;
} catch (const std::exception&) {
try {
model = ResourceManager::Load<::Model>("Models/Core/Error.obj");
} catch (const std::exception&) {
continue;
}
}
EntityWrapper entity(m_World, cModel.EntityID);
glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World);
for (auto matGroup : model->MaterialGroups()) {
std::shared_ptr<ModelJob> modelJob = std::make_shared<ModelJob>(model, scene.Camera, modelMatrix, matGroup, cModel, entity.World);
scene.ForwardJobs.push_back(modelJob);
}
}
}
auto pointLights = m_World->GetComponents("PointLight");
if (pointLights != nullptr) {
for (auto& cPointLight : *pointLights) {
bool visible = cPointLight["Visible"];
if (!visible) {
continue;
}
EntityWrapper entity(m_World, cPointLight.EntityID);
ComponentWrapper& cTransform = entity["Transform"];
std::shared_ptr<PointLightJob> pointLightJob = std::make_shared<PointLightJob>(cTransform, cPointLight, entity.World);
scene.PointLightJobs.push_back(pointLightJob);
}
}
m_RenderFrame->Add(scene);
}
bool EditorRenderSystem::OnSetCamera(Events::SetCamera& e)
{
ComponentWrapper cTransform = e.CameraEntity["Transform"];
ComponentWrapper cCamera = e.CameraEntity["Camera"];
m_EditorCamera->SetFOV((double)cCamera["FOV"]);
m_EditorCamera->SetNearClip((double)cCamera["NearClip"]);
m_EditorCamera->SetFarClip((double)cCamera["FarClip"]);
m_EditorCamera->SetPosition(cTransform["Position"]);
m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"]));
m_CurrentCamera = e.CameraEntity;
return true;
}
+115
View File
@@ -0,0 +1,115 @@
#include "Editor/EditorStats.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <psapi.h>
#endif
#include <GL/wglew.h>
EditorStats::EditorStats()
{
m_AveragedSamples.push_back(0.0);
m_CurrentAveragedSampleIndex = 1;
}
void EditorStats::Draw(double dt)
{
if (ImGui::Begin("Stats")) {
drawFPSGraph(dt);
drawRAMUsage(dt);
drawVRAMStats(dt);
}
ImGui::End();
}
void EditorStats::drawFPSGraph(double dt)
{
if (m_FrameCount < m_SampleSize) {
m_FrameTimes.push_back(dt);
} else {
m_FrameTimes[m_FrameCount % m_SampleSize] = dt;
}
m_FrameCount++;
double average = 0.0;
double max = 0.0;
for (double t : m_FrameTimes) {
average += t;
max = std::max(max, t);
}
average /= m_FrameTimes.size();
m_TimeAccumulator += dt;
if (m_TimeAccumulator >= 1.0/m_AveragedSamplesPerSecond) {
if (m_CurrentAveragedSampleIndex < m_AveragedSampleSize) {
m_AveragedSamples.push_back(1.0/average);
} else {
m_AveragedSamples[m_CurrentAveragedSampleIndex % m_AveragedSampleSize] = 1.0/average;
}
m_CurrentAveragedSampleIndex++;
m_TimeAccumulator = 0.0;
}
float maxFPS = 0.f;
ImVector<float> values;
int values_offset = m_CurrentAveragedSampleIndex % m_AveragedSampleSize;
for (double d : m_AveragedSamples) {
values.push_back(static_cast<float>(d));
maxFPS = std::max(maxFPS, static_cast<float>(d));
}
std::stringstream header;
header << std::round(1.0/average) << " FPS (" << std::setprecision(5) << average << " ms)";
ImGui::PlotLines("##FPSGraph", values.Data, values.Size, values_offset, header.str().c_str(), 0.f, maxFPS + maxFPS/5.f, ImVec2(0, 100));
}
void EditorStats::drawRAMUsage(double dt)
{
#ifdef WIN32
PROCESS_MEMORY_COUNTERS_EX ppm;
GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&ppm, sizeof(ppm));
float megabytes = ppm.WorkingSetSize / (float)std::pow(1024, 2);
ImGui::Text("Memory: ~%f MiB", megabytes);
#endif
}
void EditorStats::drawVRAMStats(double dt)
{
//const unsigned int GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049;
//const unsigned int GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048;
//glm::ivec4 total;
//glGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, glm::value_ptr(total));
//if (glGetError() == GL_NO_ERROR) {
// glm::ivec4 available;
// glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, glm::value_ptr(available));
// float megabytes = (total.x - available.x) / 1024.f; // NVidia returns in KiB
// ImGui::Text("VRAM: %f", megabytes);
//}
//GLuint uNoOfGPUs = wglGetGPUIDsAMD(0, 0);
//if (!GLERROR("")) {
// GLuint* uGPUIDs = new GLuint[uNoOfGPUs];
// wglGetGPUIDsAMD(uNoOfGPUs, uGPUIDs);
// GLuint uTotalMemoryInMB = 0;
// wglGetGPUInfoAMD(uGPUIDs[0],
// WGL_GPU_RAM_AMD,
// GL_UNSIGNED_INT,
// sizeof(GLuint),
// &uTotalMemoryInMB);
// GLint nCurAvailMemoryInKB[4];
// glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI,
// &nCurAvailMemoryInKB[0]);
// float usedTexture = (nCurAvailMemoryInKB[0] / 1024.f);
// glGetIntegerv(GL_VBO_FREE_MEMORY_ATI,
// &nCurAvailMemoryInKB[0]);
// float usedVBO = (nCurAvailMemoryInKB[0] / 1024.f);
// glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI,
// &nCurAvailMemoryInKB[0]);
// float usedFB = (nCurAvailMemoryInKB[0] / 1024.f);
// ImGui::Text("VRAM: %f MiB ", (float)uTotalMemoryInMB - usedTexture - usedVBO - usedFB);
// ImGui::Text(" Texture: %f MiB", usedTexture);
// ImGui::Text(" VBO: %f MiB", usedVBO);
// ImGui::Text(" Framebuffer: %f MiB", usedFB);
// delete[] uGPUIDs;
//}
}
+139 -678
View File
@@ -1,738 +1,199 @@
#include "Editor/EditorSystem.h"
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui/imgui_internal.h>
#include "Core/UniformScaleSystem.h"
#include "Editor/EditorRenderSystem.h"
#include "Editor/EditorWidgetSystem.h"
EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer)
: System(eventBroker)
, ImpureSystem()
EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame)
: System(world, eventBroker)
, m_Renderer(renderer)
, m_RenderFrame(renderFrame)
{
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
m_Enabled = config->Get<bool>("Debug.EditorEnabled", false);
m_Visible = m_Enabled;
m_DefaultEntityDir = boost::filesystem::path("Schema") / boost::filesystem::path("Entities");
m_EditorWorld = new World();
m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, eventBroker);
m_EditorWorldSystemPipeline->AddSystem<UniformScaleSystem>(0);
m_EditorWorldSystemPipeline->AddSystem<EditorWidgetSystem>(0, m_Renderer);
m_EditorWorldSystemPipeline->AddSystem<EditorRenderSystem>(1, m_Renderer, m_RenderFrame);
if (!m_Enabled) {
return;
}
m_Camera = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/Empty.xml");
m_EditorWorld->AttachComponent(m_Camera.ID, "Transform");
m_EditorWorld->AttachComponent(m_Camera.ID, "Camera");
m_DebugCameraInputController = new DebugCameraInputController<EditorSystem>(m_EventBroker, -1);
m_EditorGUI = new EditorGUI(m_World, m_EventBroker);
m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1));
m_EditorGUI->SetEntityImportCallback(std::bind(&EditorSystem::importEntity, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetEntitySaveCallback(std::bind(&EditorSystem::OnEntitySave, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetEntityCreateCallback(std::bind(&EditorSystem::OnEntityCreate, this, std::placeholders::_1));
m_EditorGUI->SetEntityDeleteCallback(std::bind(&EditorSystem::OnEntityDelete, this, std::placeholders::_1));
m_EditorGUI->SetEntityChangeParentCallback(std::bind(&EditorSystem::OnEntityChangeParent, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetEntityChangeNameCallback(std::bind(&EditorSystem::OnEntityChangeName, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2));
m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1));
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease);
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove);
EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystem::OnFileDropped);
EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta);
m_EditorStats = new EditorStats();
Events::SetCamera e;
e.CameraEntity = m_Camera;
m_EventBroker->Publish(e);
}
void EditorSystem::Update(World* world, double dt)
EditorSystem::~EditorSystem()
{
m_World = world;
delete m_EditorStats;
delete m_EditorGUI;
delete m_DebugCameraInputController;
delete m_EditorWorldSystemPipeline;
delete m_EditorWorld;
}
if (!m_Enabled) {
return;
void EditorSystem::Update(double dt)
{
m_EventBroker->Process<EditorGUI>();
m_EditorGUI->Draw();
m_EditorStats->Draw(dt);
if (m_CurrentSelection.Valid() && m_Widget.Valid()) {
(glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID);
}
if (!m_Visible) {
return;
}
Picking();
updateWidget();
m_EditorWorldSystemPipeline->Update(dt);
drawUI(world, dt);
m_DebugCameraInputController->Update(dt);
m_Camera["Transform"]["Position"] = m_DebugCameraInputController->Position();
m_Camera["Transform"]["Orientation"] = glm::eulerAngles(m_DebugCameraInputController->Orientation());
}
// Clear drop queue if it wasn't handled by any UI element
if (!m_LastDroppedFile.empty()) {
m_LastDroppedFile = "";
void EditorSystem::OnEntitySelected(EntityWrapper entity)
{
m_CurrentSelection = entity;
setWidgetMode(m_WidgetMode);
}
void EditorSystem::OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath)
{
EntityFileWriter writer(filePath);
writer.WriteEntity(entity.World, entity.ID);
}
EntityWrapper EditorSystem::OnEntityCreate(EntityWrapper parent)
{
EntityID entity = parent.World->CreateEntity(parent.ID);
parent.World->AttachComponent(entity, "Transform");
return EntityWrapper(parent.World, entity);
}
void EditorSystem::OnEntityDelete(EntityWrapper entity)
{
if (entity.Valid()) {
entity.World->DeleteEntity(entity.ID);
}
}
boost::filesystem::path EditorSystem::openDialog(boost::filesystem::path defaultPath)
void EditorSystem::OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent)
{
namespace bfs = boost::filesystem;
auto absolutePath = bfs::absolute(defaultPath);
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_OpenDialog(NULL, absolutePath.string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
if (entity.Valid()) {
entity.World->SetParent(entity.ID, parent.ID);
}
return bfs::absolute(outPath);
}
boost::filesystem::path EditorSystem::saveDialog(boost::filesystem::path defaultPath)
void EditorSystem::OnEntityChangeName(EntityWrapper entity, const std::string& name)
{
namespace bfs = boost::filesystem;
auto absolutePath = bfs::absolute(defaultPath);
nfdchar_t* outPath = nullptr;
nfdresult_t result = NFD_SaveDialog(NULL, absolutePath.string().c_str(), &outPath);
if (result == NFD_ERROR) {
LOG_ERROR("NFD Error: %s", NFD_GetError());
return bfs::path();
if (entity.Valid()) {
entity.World->SetName(entity.ID, name);
}
return bfs::absolute(outPath);
}
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType)
{
if (e.Command == "ToggleEditor" && e.Value > 0) {
m_Visible = !m_Visible;
if (entity.Valid()) {
entity.World->AttachComponent(entity.ID, componentType);
}
if (e.Command == "EditorToolMove" && e.Value > 0) {
setWidgetMode(WidgetMode::Translate);
}
if (e.Command == "EditorToolRotate" && e.Value > 0) {
setWidgetMode(WidgetMode::Rotate);
}
if (e.Command == "EditorToolScale" && e.Value > 0) {
setWidgetMode(WidgetMode::Scale);
}
if (e.Command == "EditorToggleTransformSpace" && e.Value > 0) {
if (m_WidgetSpace == WidgetSpace::Global) {
setWidgetSpace(WidgetSpace::Local);
} else if (m_WidgetSpace == WidgetSpace::Local) {
setWidgetSpace(WidgetSpace::Global);
}
}
return true;
}
bool EditorSystem::OnMousePress(const Events::MousePress& e)
void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& componentType)
{
if (e.Button == GLFW_MOUSE_BUTTON_RIGHT) {
m_PickingQueue.push_back(glm::vec2((int)e.X, (int)e.Y));
if (entity.Valid()) {
entity.World->DeleteComponent(entity.ID, componentType);
}
return true;
}
bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
{
if (m_Widget == EntityID_Invalid) {
return false;
}
if (m_Selection == EntityID_Invalid) {
return false;
}
if (m_Selection == m_Widget) {
return false;
}
// TODO: No widgets for root entity until widgets reside in thier own world,
// or the widgets will move relative to the root entity being moved, which is WEEEIRD.
if (m_Selection == 0) {
return false;
}
if (m_Camera == nullptr) {
return false;
}
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
glm::vec3 widgetOrientation = widgetTransform["Orientation"];
glm::quat totalOrientation = m_Camera->Orientation() * glm::inverse(glm::quat(widgetOrientation));
int width;
int height;
glfwGetFramebufferSize(m_Renderer->Window(), &width, &height);
Rectangle res(width, height);
glm::vec2 delta2(res.Width / 2.f + e.DeltaX, res.Height / 2.f + -e.DeltaY);
glm::vec3 deltaWorld = ScreenCoords::ToWorldPos(
delta2,
m_WidgetPickingDepth,
res,
m_Camera->ProjectionMatrix(),
glm::toMat4(glm::inverse(totalOrientation))
);
glm::vec3 origin = ScreenCoords::ToWorldPos(
glm::vec2(res.Width / 2.f, res.Height / 2.f),
m_WidgetPickingDepth,
res,
m_Camera->ProjectionMatrix(),
glm::toMat4(glm::inverse(totalOrientation))
);
deltaWorld = deltaWorld - origin;
glm::vec3 movement = deltaWorld * m_WidgetCurrentAxis;
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
if (m_WidgetMode == WidgetMode::Translate) {
if (m_WidgetSpace == WidgetSpace::Global) {
EntityID parent = m_World->GetParent(m_Selection);
glm::quat inverseParentOrientation;
//if (parent != 0) {
inverseParentOrientation = glm::inverse(Transform::AbsoluteOrientation(m_World, parent));
//}
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += inverseParentOrientation * movement;
} else if (m_WidgetSpace == WidgetSpace::Local) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
(glm::vec3&)selectionTransform["Position"] += glm::quat((glm::vec3)selectionTransform["Orientation"]) * movement;
}
} else if (m_WidgetMode == WidgetMode::Rotate) {
glm::vec3 finalMovement;
finalMovement.x = -deltaWorld.y * m_WidgetCurrentAxis.x;
finalMovement.y = deltaWorld.x * m_WidgetCurrentAxis.y;
finalMovement.z = deltaWorld.y * m_WidgetCurrentAxis.z;
if (m_WidgetSpace == WidgetSpace::Global) {
EntityID parent = m_World->GetParent(m_Selection);
glm::quat parentOrientation;
//if (parent != 0) {
// parentOrientation = RenderSystem::AbsoluteOrientation(m_World, parent);
//}
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
glm::quat currentOrientation = Transform::AbsoluteOrientation(m_World, m_Selection);
//glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation);
glm::quat deltaOrientation(finalMovement);
selectionOrientation = glm::eulerAngles(glm::inverse(parentOrientation) * (deltaOrientation * currentOrientation));
} else if (m_WidgetSpace == WidgetSpace::Local) {
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
glm::quat currentOrientation(selectionOrientation);
glm::quat deltaOrientation(finalMovement);
selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation);
}
} else if (m_WidgetMode == WidgetMode::Scale) {
glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"];
glm::vec3& scaleY = m_World->GetComponent(m_WidgetY, "Transform")["Scale"];
glm::vec3& scaleZ = m_World->GetComponent(m_WidgetZ, "Transform")["Scale"];
if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) {
float movementLength = glm::length(movement);
float dot = glm::dot((glm::vec3)widgetOrientation, movement);
movement = glm::vec3(movementLength) * glm::sign(dot);
(glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] += movement;
}
if (m_WidgetCurrentAxis.x > 0) {
scaleX.x += movement.x;
}
if (m_WidgetCurrentAxis.y > 0) {
scaleY.y += movement.y;
}
if (m_WidgetCurrentAxis.z > 0) {
scaleZ.z += movement.z;
}
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Scale"] += movement;
}
}
/*LOG_DEBUG("DELTA %f", e.DeltaX);
if (e.X < 0) {
glfwSetCursorPos(m_Renderer->Window(), width - 1, e.Y);
}
if (e.X >= width) {
glfwSetCursorPos(m_Renderer->Window(), 0, e.Y);
}*/
return true;
}
bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e)
{
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
m_WidgetCurrentAxis = glm::vec3(0.f);
//setWidgetMode(m_WidgetMode);
if (e.Button == GLFW_MOUSE_BUTTON_1) {
PickData pick = m_Renderer->Pick(glm::vec2(e.X, e.Y));
if (pick.World == m_World) {
m_CurrentSelection = EntityWrapper(m_World, pick.Entity);
m_EditorGUI->SelectEntity(m_CurrentSelection);
}
}
return true;
}
void EditorSystem::Picking()
bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e)
{
for (auto& pos : m_PickingQueue) {
auto result = m_Renderer->Pick(pos);
EntityID entity = result.Entity;
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
// ???
} else {
LOG_INFO("Selected %i", entity);
if (entity != EntityID_Invalid) {
EntityID parent = m_World->GetParent(entity);
m_Camera = result.Camera;
if (parent == m_Widget) {
m_WidgetCurrentAxis = glm::vec3(
(entity == m_WidgetX) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneY || entity == m_WidgetPlaneZ),
(entity == m_WidgetY) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneZ),
(entity == m_WidgetZ) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneY)
);
m_WidgetPickingDepth = result.Depth;
//auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
//auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
//widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"];
} else {
ImGui::SetActiveID(0, nullptr);
if (m_WidgetMode == WidgetMode::None) {
m_WidgetMode = WidgetMode::Translate;
}
setWidgetMode(m_WidgetMode);
m_Selection = entity;
}
}
if (m_CurrentSelection.Valid()) {
glm::quat parentOrientation;
EntityWrapper parent = m_CurrentSelection.Parent();
if (parent.Valid()) {
parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent.World, parent.ID));
}
(glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation;
m_EditorGUI->SetDirty(m_CurrentSelection);
}
m_PickingQueue.clear();
};
bool EditorSystem::OnFileDropped(const Events::FileDropped& e)
{
m_LastDroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string();
std::replace(m_LastDroppedFile.begin(), m_LastDroppedFile.end(), '\\', '/');
return true;
}
void EditorSystem::createWidget()
EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem::path filePath)
{
if (m_Widget == EntityID_Invalid) {
m_Widget = m_World->CreateEntity();
m_World->AttachComponent(m_Widget, "Transform");
m_WidgetX = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetX, "Transform");
m_World->AttachComponent(m_WidgetX, "Model");
m_WidgetPlaneX = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetPlaneX, "Transform");
m_World->AttachComponent(m_WidgetPlaneX, "Model");
m_World->GetComponent(m_WidgetPlaneX, "Model")["Resource"] = "Models/WidgetPlaneX.obj";
m_WidgetY = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetY, "Transform");
m_World->AttachComponent(m_WidgetY, "Model");
m_WidgetPlaneY = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetPlaneY, "Transform");
m_World->AttachComponent(m_WidgetPlaneY, "Model");
m_World->GetComponent(m_WidgetPlaneY, "Model")["Resource"] = "Models/WidgetPlaneY.obj";
m_WidgetZ = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetZ, "Transform");
m_World->AttachComponent(m_WidgetZ, "Model");
m_WidgetPlaneZ = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetPlaneZ, "Transform");
m_World->AttachComponent(m_WidgetPlaneZ, "Model");
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Resource"] = "Models/WidgetPlaneZ.obj";
m_WidgetOrigin = m_World->CreateEntity(m_Widget);
m_World->AttachComponent(m_WidgetOrigin, "Transform");
m_World->AttachComponent(m_WidgetOrigin, "Model");
setWidgetMode(WidgetMode::None);
if (parent.World == nullptr) {
LOG_ERROR("Tried to import entity \"%s\" into null world!", filePath.string().c_str());
return EntityWrapper::Invalid;
}
try {
auto entityFile = ResourceManager::Load<EntityFile>(filePath.string());
EntityFilePreprocessor fpp(entityFile);
fpp.RegisterComponents(parent.World);
EntityFileParser fp(entityFile);
EntityID newEntity = fp.MergeEntities(parent.World, parent.ID);
return EntityWrapper(parent.World, newEntity);
} catch (const std::exception&) {
return EntityWrapper::Invalid;
}
}
void EditorSystem::updateWidget()
void EditorSystem::setWidgetMode(EditorGUI::WidgetMode mode)
{
if (m_Widget == EntityID_Invalid) {
return;
}
if (m_Selection == m_Widget) {
if (mode == m_WidgetMode && m_Widget.Valid() && m_CurrentSelection.Valid()) {
return;
}
if (m_Selection != EntityID_Invalid) {
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
glm::vec3 selectionPosition = Transform::AbsolutePosition(m_World, m_Selection);
widgetTransform["Position"] = selectionPosition;
if (m_WidgetSpace == WidgetSpace::Local) {
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
}
m_WidgetMode = mode;
void EditorSystem::setWidgetMode(WidgetMode newMode)
{
if (m_Widget == EntityID_Invalid) {
if (m_Widget.Valid()) {
m_Widget.World->DeleteEntity(m_Widget.ID);
m_Widget = EntityWrapper::Invalid;
}
if (!m_CurrentSelection.Valid()) {
return;
}
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
widgetTransform["Orientation"] = glm::vec3(0.f);
m_World->GetComponent(m_WidgetX, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = false;
m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = false;
m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = false;
m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f);
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false;
if (newMode == WidgetMode::Translate) {
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/TranslationWidgetX.obj";
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/TranslationWidgetY.obj";
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/TranslationWidgetZ.obj";
// Temporarily disabled for local space until I can figure out what's wrong with the math
if (m_WidgetSpace != WidgetSpace::Local) {
m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = true;
m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = true;
m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = true;
}
if (m_Selection != EntityID_Invalid) {
if (m_WidgetSpace == WidgetSpace::Local) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
} else if (newMode == WidgetMode::Scale) {
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/ScaleWidgetX.obj";
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/ScaleWidgetY.obj";
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/ScaleWidgetZ.obj";
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = true;
m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj";
if (m_Selection != EntityID_Invalid) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
} else if (newMode == WidgetMode::Rotate) {
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj";
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/RotationWidgetY.obj";
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/RotationWidgetZ.obj";
if (m_Selection != EntityID_Invalid) {
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
if (m_WidgetSpace == WidgetSpace::Local) {
widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection));
}
}
switch (mode) {
case EditorGUI::WidgetMode::Translate:
m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetTranslate.xml");
break;
case EditorGUI::WidgetMode::Rotate:
m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetRotate.xml");
break;
case EditorGUI::WidgetMode::Scale:
m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetScale.xml");
break;
}
m_WidgetMode = newMode;
}
void EditorSystem::setWidgetSpace(WidgetSpace space)
{
m_WidgetSpace = space;
setWidgetMode(m_WidgetMode);
}
void EditorSystem::drawUI(World* world, double dt)
{
namespace bfs = boost::filesystem;
ImGui::ShowTestWindow();
//ImGui::ShowStyleEditor();
if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("File")) {
//if (ImGui::MenuItem("New")) { }
if (ImGui::MenuItem("Import", "Ctrl+O")) {
fileImport(world);
}
if (ImGui::MenuItem("Save", "Ctrl+S")) {
fileSave(world);
}
if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) {
fileSaveAs(world);
}
ImGui::Separator();
if (ImGui::MenuItem("Close Editor", "F1")) { }
ImGui::EndMenu();
}
ImGui::SameLine();
if (ImGui::Button("Move")) {
setWidgetMode(WidgetMode::Translate);
}
ImGui::SameLine();
if (ImGui::Button("Rotate")) {
setWidgetMode(WidgetMode::Rotate);
}
ImGui::SameLine();
if (ImGui::Button("Scale")) {
setWidgetMode(WidgetMode::Scale);
}
ImGui::SameLine();
if (m_WidgetSpace == WidgetSpace::Global) {
if (ImGui::Button("(Global)")) {
setWidgetSpace(WidgetSpace::Local);
}
} else if (m_WidgetSpace == WidgetSpace::Local) {
if (ImGui::Button("(Local)")) {
setWidgetSpace(WidgetSpace::Global);
}
}
ImGui::EndMainMenuBar();
}
std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components");
if (ImGui::Begin(title.c_str())) {
if (m_Selection != EntityID_Invalid) {
auto& pools = world->GetComponentPools();
std::vector<const char*> componentTypes;
for (auto& pair : pools) {
// Only add components the entity doesn't already have
if (!pair.second->KnowsEntity(m_Selection)) {
componentTypes.push_back(pair.first.c_str());
}
}
int item = -1;
ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 5.f);
if (ImGui::Combo("", &item, componentTypes.data(), componentTypes.size())) {
if (item != -1) {
std::string chosenType = std::string(componentTypes.at(item));
world->AttachComponent(m_Selection, chosenType);
}
}
ImGui::PopItemWidth();
for (auto& pair : pools) {
const std::string& componentType = pair.first;
auto pool = pair.second;
if (!pool->KnowsEntity(m_Selection)) {
continue;
}
auto& ci = pool->ComponentInfo();
bool deletePressed = createDeleteButton(componentType);
if (deletePressed) {
world->DeleteComponent(m_Selection, componentType);
continue;
}
if (ImGui::CollapsingHeader(componentType.c_str())) {
if (!ci.Meta->Annotation.empty()) {
ImGui::Text(ci.Meta->Annotation.c_str());
}
auto& component = world->GetComponent(m_Selection, componentType);
for (auto& kv : ci.Fields) {
const std::string& fieldName = kv.first;
auto& field = kv.second;
std::string uniqueID = componentType + fieldName;
ImGui::PushID(uniqueID.c_str());
if (field.Type == "Vector") {
auto& val = component.Field<glm::vec3>(fieldName);
if (fieldName == "Scale") {
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits<float>::max());
} else if (fieldName == "Orientation") {
glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi<float>()));
if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi<float>())) {
val = tempVal;
}
} else {
ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max());
}
} else if (field.Type == "Color") {
auto& val = component.Field<glm::vec4>(fieldName);
ImGui::ColorEdit4("", glm::value_ptr(val), true);
} else if (field.Type == "string") {
std::string& val = component.Field<std::string>(fieldName);
char tempString[1024];
memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString)));
if (ImGui::InputText("", tempString, sizeof(tempString))) {
val = std::string(tempString);
LOG_DEBUG("%s::%s changed!", componentType.c_str(), fieldName.c_str());
}
// DROP STUFF
if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) {
val = m_LastDroppedFile;
m_LastDroppedFile = "";
}
} else if (field.Type == "double") {
float tempVal = static_cast<float>(component.Field<double>(fieldName));
if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) {
component.SetField(fieldName, static_cast<double>(tempVal));
}
} else if (field.Type == "int") {
int val = component.Field<int>(fieldName);
ImGui::InputInt("", &val);
} else if (field.Type == "enum") {
int currentValue = component.Field<int>(fieldName);
int item = -1;
std::stringstream enumKeys;
std::vector<int> enumValues;
int i = 0;
for (auto& kv : ci.Meta->FieldEnumDefinitions.at(fieldName)) {
enumKeys << kv.first << " (" << kv.second << ")" << '\0';
enumValues.push_back(kv.second);
if (currentValue == kv.second) {
item = i;
}
i++;
}
if (ImGui::Combo("", &item, enumKeys.str().c_str())) {
component.SetField(fieldName, enumValues.at(item));
}
} else if (field.Type == "bool") {
auto& val = component.Field<bool>(fieldName);
ImGui::Checkbox("", &val);
} else {
ImGui::TextDisabled(field.Type.c_str());
}
ImGui::PopID();
ImGui::SameLine();
ImGui::Text(fieldName.c_str());
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("field annotation goes here");
}
}
}
}
}
}
ImGui::End();
if (ImGui::Begin("Entities")) {
auto entityChildren = world->GetEntityChildren();
std::function<void(EntityID)> recurse = [&](EntityID parent) {
auto range = entityChildren.equal_range(parent);
for (auto it = range.first; it != range.second; it++) {
if (createEntityNode(world, it->second)) {
recurse(it->second);
ImGui::TreePop();
}
}
};
recurse(EntityID_Invalid);
}
ImGui::End();
}
bool EditorSystem::createEntityNode(World* world, EntityID entity)
{
// HACK: Don't show the widget entities in the entity tree
if (entity == m_Widget) {
return false;
}
ImVec2 pos = ImGui::GetCursorScreenPos();
float width = ImGui::GetContentRegionAvailWidth();
ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13));
auto window = ImGui::GetCurrentWindow();
if (m_Selection == entity) {
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
window->DrawList->AddRectFilled(bb.Min, bb.Max, col);
}
ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(entity)).c_str());
bool hovered = false;
bool held = false;
if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) {
m_Selection = entity;
}
if (held) {
ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0);
if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) {
if (m_UIDraggingEntity == EntityID_Invalid) {
m_UIDraggingEntity = entity;
LOG_DEBUG("Started drag of entity %i", m_UIDraggingEntity);
}
ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0));
ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings);
ImGui::Text("#%i", m_UIDraggingEntity);
ImGui::End();
}
}
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
std::string nodeTitle;
const std::string& entityName = world->GetName(entity);
if (!entityName.empty()) {
nodeTitle = entityName;
} else {
nodeTitle = std::string("#") + std::to_string(entity);
}
if (ImGui::TreeNode(nodeTitle.c_str())) {
if (m_UIDraggingEntity != EntityID_Invalid && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) {
LOG_DEBUG("Changed parent of %i to %i", m_UIDraggingEntity, entity);
changeParent(m_UIDraggingEntity, entity);
m_UIDraggingEntity = EntityID_Invalid;
}
if (ImGui::BeginPopupContextItem("item context menu")) {
if (ImGui::Button("Add")) {
EntityID newEntity = world->CreateEntity(entity);
world->AttachComponent(newEntity, "Transform");
}
ImGui::SameLine();
if (ImGui::Button("Delete")) {
world->DeleteEntity(entity);
ImGui::CloseCurrentPopup();
if (!world->ValidEntity(m_Selection)) {
m_Selection = EntityID_Invalid;
}
}
ImGui::EndPopup();
}
return true;
} else {
return false;
}
}
bool EditorSystem::createDeleteButton(std::string componentType)
{
float width = ImGui::GetContentRegionAvailWidth();
ImGuiWindow* window = ImGui::GetCurrentWindow();
auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1);
ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f));
std::string idString = "#DELETE";
idString += componentType;
ImGuiID id = window->GetID(idString.c_str());
bool hovered;
bool held;
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
//ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton);
ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
return pressed;
}
void EditorSystem::changeParent(EntityID entity, EntityID newParent)
{
if (entity == newParent) {
return;
}
// An entity can't be a child to one of its own children
auto children = m_World->GetEntityChildren().equal_range(entity);
for (auto it = children.first; it != children.second; it++) {
if (it->second == newParent) {
return;
}
}
m_World->SetParent(entity, newParent);
}
void EditorSystem::fileImport(World* world)
{
m_CurrentFile = openDialog(m_DefaultEntityDir);
auto file = ResourceManager::Load<EntityFile>(m_CurrentFile.string());
EntityFilePreprocessor fpp(file);
fpp.RegisterComponents(world);
EntityFileParser fp(file);
fp.MergeEntities(world);
createWidget();
updateWidget();
}
void EditorSystem::fileSave(World* world)
{
if (boost::filesystem::exists(m_CurrentFile)) {
// HACK: Delete the widgets so they don't appear in the saved file
world->DeleteEntity(m_Widget);
m_Widget = EntityID_Invalid;
EntityFileWriter writer(m_CurrentFile.string());
writer.WriteWorld(world);
createWidget();
} else {
fileSaveAs(world);
}
}
void EditorSystem::fileSaveAs(World* world)
{
auto filePath = saveDialog(m_DefaultEntityDir);
if (filePath.empty()) {
return;
}
// HACK: Delete the widgets so they don't appear in the saved file
world->DeleteEntity(m_Widget);
m_Widget = EntityID_Invalid;
EntityFileWriter writer(filePath.string());
writer.WriteWorld(world);
createWidget();
m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID);
}

Some files were not shown because too many files have changed in this diff Show More