Explorar o código

Adds the Systems for the Entity-Component-Systems setup.

Areloch %!s(int64=7) %!d(string=hai) anos
pai
achega
57284507f2

+ 30 - 0
Engine/source/T3D/systems/componentSystem.h

@@ -0,0 +1,30 @@
+#pragma once
+#include "console/engineAPI.h"
+
+template<typename T>
+class SystemInterface
+{
+public:
+   bool mIsEnabled;
+   bool mIsServer;
+
+   static Vector<T*> all;
+
+   SystemInterface()
+   {
+      all.push_back((T*)this);
+   }
+
+   virtual ~SystemInterface()
+   {
+      for (U32 i = 0; i < all.size(); i++)
+      {
+         if (all[i] == (T*)this)
+         {
+            all.erase(i);
+            return;
+         }
+      }
+   }
+};
+template<typename T> Vector<T*> SystemInterface<T>::all(0);

+ 375 - 0
Engine/source/T3D/systems/render/meshRenderSystem.cpp

@@ -0,0 +1,375 @@
+#include "T3D/systems/render/meshRenderSystem.h"
+#include "gfx/gfxTransformSaver.h"
+#include "lighting/lightQuery.h"
+
+#include "renderInstance/renderPassManager.h"
+#include "materials/materialManager.h"
+#include "materials/baseMatInstance.h"
+
+Vector<MeshRenderSystem::BufferMaterials> MeshRenderSystem::mBufferMaterials(0);
+Vector<MeshRenderSystem::BufferSet> MeshRenderSystem::mStaticBuffers(0);
+
+void MeshRenderSystem::render(SceneManager *sceneManager, SceneRenderState* state)
+{
+   Frustum viewFrustum = state->getCullingFrustum();
+   MatrixF camTransform = state->getCameraTransform();
+
+   U32 count = MeshRenderSystemInterface::all.size();
+   for (U32 i = 0; i < count; i++)
+   {
+      //Server side items exist for data, but we don't actually render them
+      bool isClient = MeshRenderSystemInterface::all[i]->mIsClient;
+      if (!MeshRenderSystemInterface::all[i]->mIsClient)
+         continue;
+
+      bool isStatic = MeshRenderSystemInterface::all[i]->mStatic;
+      if (MeshRenderSystemInterface::all[i]->mStatic)
+         continue;
+
+      //First, do frustum culling
+      if (viewFrustum.isCulled(MeshRenderSystemInterface::all[i]->mBounds))
+         continue;
+
+      // Set the query box for the container query.  Never
+      // make it larger than the frustum's AABB.  In the editor,
+      // always query the full frustum as that gives objects
+      // the opportunity to render editor visualizations even if
+      // they are otherwise not in view.
+      if (!state->getCullingFrustum().getBounds().isOverlapped(state->getRenderArea()))
+      {
+         // This handles fringe cases like flying backwards into a zone where you
+         // end up pretty much standing on a zone border and looking directly into
+         // its "walls".  In that case the traversal area will be behind the frustum
+         // (remember that the camera isn't where visibility starts, it's the near
+         // distance).
+
+         continue;
+      }
+
+      //We can then sort our objects by range since we have it already, so we can do occlusion culling be rendering front-to-back
+
+      //if we've made it this far, call down to the render function to actually display our stuff
+      renderInterface(i, state);
+   }
+
+   //Static Batch rendering
+   if ( /*!mMaterialInst ||*/ !state)
+      return;
+
+   BaseMatInstance *matInst = MATMGR->getWarningMatInstance();
+
+   // Get a handy pointer to our RenderPassmanager
+   RenderPassManager *renderPass = state->getRenderPass();
+
+   for (U32 i = 0; i < mStaticBuffers.size(); i++)
+   {
+      for (U32 b = 0; b < mStaticBuffers[i].buffers.size(); b++)
+      {
+         if (mStaticBuffers[i].buffers[b].vertData.empty())
+            continue;
+
+         MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();
+
+         // Set our RenderInst as a standard mesh render
+         ri->type = RenderPassManager::RIT_Mesh;
+
+         //If our material has transparency set on this will redirect it to proper render bin
+         if (matInst->getMaterial()->isTranslucent())
+         {
+            ri->type = RenderPassManager::RIT_Translucent;
+            ri->translucentSort = true;
+         }
+
+         // Calculate our sorting point
+         if (state)
+         {
+            // Calculate our sort point manually.
+            const Box3F& rBox = Box3F(1000);// getRenderWorldBox();
+            ri->sortDistSq = rBox.getSqDistanceToPoint(state->getCameraPosition());
+         }
+         else
+            ri->sortDistSq = 0.0f;
+
+         // Set up our transforms
+         MatrixF objectToWorld = MatrixF::Identity;//getRenderTransform();
+                                                   //objectToWorld.scale(getScale());
+
+         ri->objectToWorld = renderPass->allocUniqueXform(objectToWorld);
+         ri->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);
+         ri->projection = renderPass->allocSharedXform(RenderPassManager::Projection);
+
+         // If our material needs lights then fill the RIs 
+         // light vector with the best lights.
+         /*if (matInst->isForwardLit())
+         {
+         LightQuery query;
+         query.init(getWorldSphere());
+         query.getLights(ri->lights, 8);
+         }*/
+
+         // Make sure we have an up-to-date backbuffer in case
+         // our Material would like to make use of it
+         // NOTICE: SFXBB is removed and refraction is disabled!
+         //ri->backBuffTex = GFX->getSfxBackBuffer();
+
+         // Set our Material
+         ri->matInst = matInst;
+
+         // Set up our vertex buffer and primitive buffer
+         ri->vertBuff = &mStaticBuffers[i].buffers[b].vertexBuffer;
+         ri->primBuff = &mStaticBuffers[i].buffers[b].primitiveBuffer;
+
+         ri->prim = renderPass->allocPrim();
+         ri->prim->type = GFXTriangleList;
+         ri->prim->minIndex = 0;
+         ri->prim->startIndex = 0;
+         ri->prim->numPrimitives = mStaticBuffers[i].buffers[b].primData.size();
+         ri->prim->startVertex = 0;
+         ri->prim->numVertices = mStaticBuffers[i].buffers[b].vertData.size();
+
+         // We sort by the material then vertex buffer
+         ri->defaultKey = matInst->getStateHint();
+         ri->defaultKey2 = (uintptr_t)ri->vertBuff; // Not 64bit safe!
+
+                                                    // Submit our RenderInst to the RenderPassManager
+         state->getRenderPass()->addInst(ri);
+      }
+   }
+}
+
+void MeshRenderSystem::renderInterface(U32 interfaceIndex, SceneRenderState* state)
+{
+   //Fetch
+   MeshRenderSystemInterface* interface = MeshRenderSystemInterface::all[interfaceIndex];
+
+   if (interface->mShapeInstance == nullptr)
+      return;
+
+   Point3F cameraOffset;
+   interface->mTransform.getColumn(3, &cameraOffset);
+   cameraOffset -= state->getDiffuseCameraPosition();
+   F32 dist = cameraOffset.len();
+   if (dist < 0.01f)
+      dist = 0.01f;
+
+   Point3F objScale = interface->mScale;
+   F32 invScale = (1.0f / getMax(getMax(objScale.x, objScale.y), objScale.z));
+
+   interface->mShapeInstance->setDetailFromDistance(state, dist * invScale);
+
+   if (interface->mShapeInstance->getCurrentDetail() < 0)
+      return;
+
+   GFXTransformSaver saver;
+
+   // Set up our TS render state.
+   TSRenderState rdata;
+   rdata.setSceneState(state);
+   rdata.setFadeOverride(1.0f);
+   rdata.setOriginSort(false);
+
+   // We might have some forward lit materials
+   // so pass down a query to gather lights.
+   LightQuery query;
+   query.init(interface->mSphere);
+   rdata.setLightQuery(&query);
+
+   MatrixF mat = interface->mTransform;
+
+   mat.scale(objScale);
+   GFX->setWorldMatrix(mat);
+
+   interface->mShapeInstance->render(rdata);
+}
+
+void MeshRenderSystem::rebuildBuffers()
+{
+   U32 BUFFER_SIZE = 65000;
+   Vector<U32> tempIndices;
+   tempIndices.reserve(4);
+
+   Box3F newBounds = Box3F::Zero;
+
+   mStaticBuffers.clear();
+
+   for (U32 i = 0; i < MeshRenderSystemInterface::all.size(); i++)
+   {
+      if (!MeshRenderSystemInterface::all[i]->mIsEnabled)
+         continue;
+
+      if (!MeshRenderSystemInterface::all[i]->mIsClient || !MeshRenderSystemInterface::all[i]->mStatic)
+         continue;
+
+      //TODO: Properly re-implement StaticElements to container owner interfaces and buffer sets
+      for (U32 j = 0; j < MeshRenderSystemInterface::all[i]->mGeometry.mPolyList.size(); j++)
+      {
+         const OptimizedPolyList::Poly& poly = MeshRenderSystemInterface::all[i]->mGeometry.mPolyList[j];
+
+         if (poly.vertexCount < 3)
+            continue;
+
+         tempIndices.setSize(poly.vertexCount);
+         dMemset(tempIndices.address(), 0, poly.vertexCount);
+
+         if (poly.type == OptimizedPolyList::TriangleStrip ||
+            poly.type == OptimizedPolyList::TriangleFan)
+         {
+            tempIndices[0] = 0;
+            U32 idx = 1;
+
+            for (U32 k = 1; k < poly.vertexCount; k += 2)
+               tempIndices[idx++] = k;
+
+            for (U32 k = ((poly.vertexCount - 1) & (~0x1)); k > 0; k -= 2)
+               tempIndices[idx++] = k;
+         }
+         else if (poly.type == OptimizedPolyList::TriangleList)
+         {
+            for (U32 k = 0; k < poly.vertexCount; k++)
+               tempIndices[k] = k;
+         }
+         else
+            continue;
+
+         //got our data, now insert it into the correct buffer!
+         S32 bufferId = findBufferSetByMaterial(poly.material);
+
+         if (bufferId == -1)
+         {
+            //add a new buffer set if we didn't get a match!
+            BufferSet newSet;
+            newSet.surfaceMaterialId = poly.material;
+
+            mStaticBuffers.push_back(newSet);
+
+            bufferId = mStaticBuffers.size() - 1;
+         }
+
+         //see if this would push us over our buffer size limit, if it is, make a new buffer for this set
+         if (mStaticBuffers[bufferId].buffers.last().vertData.size() + 3 > BUFFER_SIZE
+            || mStaticBuffers[bufferId].buffers.last().primData.size() + 1 > BUFFER_SIZE)
+         {
+            //yep, we'll overstep with this, so spool up a new buffer in this set
+            BufferSet::Buffers newBuffer = BufferSet::Buffers();
+            mStaticBuffers[bufferId].buffers.push_back(newBuffer);
+         }
+
+         const U32& firstIdx = MeshRenderSystemInterface::all[i]->mGeometry.mIndexList[poly.vertexStart];
+         const OptimizedPolyList::VertIndex& firstVertIdx = MeshRenderSystemInterface::all[i]->mGeometry.mVertexList[firstIdx];
+
+         //Vector<Point3F> geomPoints = MeshRenderSystemInterface::all[i]->mGeometry.mPoints;
+         //Vector<Point3F> geomNormals = MeshRenderSystemInterface::all[i]->mGeometry.mNormals;
+         //Vector<Point2F> geoUVs = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s;
+
+         for (U32 k = 1; k < poly.vertexCount - 1; k++)
+         {
+            const U32& secondIdx = MeshRenderSystemInterface::all[i]->mGeometry.mIndexList[poly.vertexStart + tempIndices[k]];
+            const U32& thirdIdx = MeshRenderSystemInterface::all[i]->mGeometry.mIndexList[poly.vertexStart + tempIndices[k + 1]];
+
+            const OptimizedPolyList::VertIndex& secondVertIdx = MeshRenderSystemInterface::all[i]->mGeometry.mVertexList[secondIdx];
+            const OptimizedPolyList::VertIndex& thirdVertIdx = MeshRenderSystemInterface::all[i]->mGeometry.mVertexList[thirdIdx];
+
+            Point3F points[3];
+            points[0] = MeshRenderSystemInterface::all[i]->mGeometry.mPoints[firstVertIdx.vertIdx];
+            points[1] = MeshRenderSystemInterface::all[i]->mGeometry.mPoints[secondVertIdx.vertIdx];
+            points[2] = MeshRenderSystemInterface::all[i]->mGeometry.mPoints[thirdVertIdx.vertIdx];
+
+            Point3F normals[3];
+            normals[0] = MeshRenderSystemInterface::all[i]->mGeometry.mNormals[firstVertIdx.normalIdx];
+            normals[1] = MeshRenderSystemInterface::all[i]->mGeometry.mNormals[secondVertIdx.normalIdx];
+            normals[2] = MeshRenderSystemInterface::all[i]->mGeometry.mNormals[thirdVertIdx.normalIdx];
+
+            Point3F tangents[3];
+            tangents[0] = mCross(points[1] - points[0], normals[0]);
+            tangents[1] = mCross(points[2] - points[1], normals[1]);
+            tangents[2] = mCross(points[0] - points[2], normals[2]);
+
+            Point2F uvs[3];
+            uvs[0] = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s[firstVertIdx.uv0Idx];
+            uvs[1] = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s[secondVertIdx.uv0Idx];
+            uvs[2] = MeshRenderSystemInterface::all[i]->mGeometry.mUV0s[thirdVertIdx.uv0Idx];
+
+            mStaticBuffers[bufferId].vertCount += 3;
+            mStaticBuffers[bufferId].primCount += 1;
+
+            for (U32 v = 0; v < 3; ++v)
+            {
+               //Build the vert and store it to the buffers!
+               GFXVertexPNTT bufVert;
+               bufVert.point = points[v];
+               bufVert.normal = normals[v];
+               bufVert.tangent = tangents[v];
+               bufVert.texCoord = uvs[v];
+
+               newBounds.extend(points[v]);
+
+               mStaticBuffers[bufferId].buffers.last().vertData.push_back(bufVert);
+
+               U32 vertPrimId = mStaticBuffers[bufferId].buffers.last().vertData.size() - 1;
+               mStaticBuffers[bufferId].buffers.last().primData.push_back(vertPrimId);
+
+               mStaticBuffers[bufferId].center += points[v];
+            }
+         }
+      }
+   }
+
+   //Now, iterate through the organized data and turn them into renderable buffers
+   for (U32 i = 0; i < mStaticBuffers.size(); i++)
+   {
+      for (U32 b = 0; b < mStaticBuffers[i].buffers.size(); b++)
+      {
+         BufferSet::Buffers& buffers = mStaticBuffers[i].buffers[b];
+
+         //if there's no data to be had in this buffer, just skip it
+         if (buffers.vertData.empty())
+            continue;
+
+         buffers.vertexBuffer.set(GFX, buffers.vertData.size(), GFXBufferTypeStatic);
+         GFXVertexPNTT *pVert = buffers.vertexBuffer.lock();
+
+         for (U32 v = 0; v < buffers.vertData.size(); v++)
+         {
+            pVert->normal = buffers.vertData[v].normal;
+            pVert->tangent = buffers.vertData[v].tangent;
+            //pVert->color = buffers.vertData[v].color;
+            pVert->point = buffers.vertData[v].point;
+            pVert->texCoord = buffers.vertData[v].texCoord;
+
+            pVert++;
+         }
+
+         buffers.vertexBuffer.unlock();
+
+         // Allocate PB
+         buffers.primitiveBuffer.set(GFX, buffers.primData.size(), buffers.primData.size() / 3, GFXBufferTypeStatic);
+
+         U16 *pIndex;
+         buffers.primitiveBuffer.lock(&pIndex);
+
+         for (U16 i = 0; i < buffers.primData.size(); i++)
+         {
+            *pIndex = i;
+            pIndex++;
+         }
+
+         buffers.primitiveBuffer.unlock();
+      }
+
+      mStaticBuffers[i].center /= mStaticBuffers[i].vertCount;
+   }
+
+   //mObjBox = newBounds;
+   //resetWorldBox();
+}
+
+U32 MeshRenderSystem::findBufferSetByMaterial(U32 matId)
+{
+   for (U32 i = 0; i < mStaticBuffers.size(); i++)
+   {
+      if (mStaticBuffers[i].surfaceMaterialId == matId)
+         return i;
+   }
+
+   return -1;
+}

+ 207 - 0
Engine/source/T3D/systems/render/meshRenderSystem.h

@@ -0,0 +1,207 @@
+#pragma once
+#include "scene/sceneRenderState.h"
+#include "T3D/systems/componentSystem.h"
+#include "ts/tsShape.h"
+#include "ts/tsShapeInstance.h"
+#include "T3D/assets/ShapeAsset.h"
+#include "T3D/assets/MaterialAsset.h"
+
+#ifndef _GFXVERTEXBUFFER_H_
+#include "gfx/gfxVertexBuffer.h"
+#endif
+#ifndef _GFXPRIMITIVEBUFFER_H_
+#include "gfx/gfxPrimitiveBuffer.h"
+#endif
+#ifndef _OPTIMIZEDPOLYLIST_H_
+#include "collision/optimizedPolyList.h"
+#endif
+
+class MeshRenderSystemInterface : public SystemInterface<MeshRenderSystemInterface>
+{
+public:
+   TSShapeInstance * mShapeInstance;
+
+   MatrixF                 mTransform;
+   Point3F                 mScale;
+   Box3F						   mBounds;
+   SphereF                 mSphere;
+
+   bool                    mIsClient;
+
+   struct matMap
+   {
+      //MaterialAsset* matAsset;
+      String assetId;
+      U32 slot;
+   };
+
+   Vector<matMap>  mChangingMaterials;
+   Vector<matMap>  mMaterials;
+
+   //Static geometry stuff
+   bool                    mStatic;
+
+   OptimizedPolyList       mGeometry;
+
+   MeshRenderSystemInterface() : SystemInterface(), mShapeInstance(nullptr), mTransform(MatrixF::Identity), mScale(Point3F::One), mIsClient(false), mStatic(false)
+   {
+      mBounds = Box3F(1);
+      mSphere = SphereF();
+   }
+
+   ~MeshRenderSystemInterface()
+   {
+      //SAFE_DELETE(mShape);
+      SAFE_DELETE(mShapeInstance);
+   }
+};
+
+class MeshRenderSystem
+{
+protected:
+   /*struct StaticBatchElement
+   {
+      SimObject* owner;
+      OptimizedPolyList geometry;
+      String batchName;
+   };
+
+   static Vector<StaticBatchElement> mStaticElements;*/
+
+   //We retain the pushed geometry data for rendering here. It's static(unless forced to change through editing or whatnot)
+   //so rendering the batches is real fast
+   struct BufferMaterials
+   {
+      // The name of the Material we will use for rendering
+      String            mMaterialName;
+      // The actual Material instance
+      BaseMatInstance*  mMaterialInst;
+
+      BufferMaterials()
+      {
+         mMaterialName = "";
+         mMaterialInst = NULL;
+      }
+   };
+
+   static Vector<BufferMaterials> mBufferMaterials;
+
+   struct BufferSet
+   {
+      U32 surfaceMaterialId;
+
+      U32 vertCount;
+      U32 primCount;
+
+      Point3F center;
+
+      struct Buffers
+      {
+         U32 vertStart;
+         U32 primStart;
+         U32 vertCount;
+         U32 primCount;
+
+         Vector<GFXVertexPNTT> vertData;
+         Vector<U32> primData;
+
+         GFXVertexBufferHandle< GFXVertexPNTT > vertexBuffer;
+         GFXPrimitiveBufferHandle            primitiveBuffer;
+
+         Buffers()
+         {
+            vertStart = 0;
+            primStart = 0;
+            vertCount = 0;
+            primCount = 0;
+
+            vertexBuffer = NULL;
+            primitiveBuffer = NULL;
+         }
+      };
+
+      Vector<Buffers> buffers;
+
+      BufferSet()
+      {
+         Buffers newBuffer;
+         buffers.push_back(newBuffer);
+
+         surfaceMaterialId = 0;
+
+         vertCount = 0;
+         primCount = 0;
+
+         center = Point3F::Zero;
+      }
+   };
+
+   static Vector<BufferSet> mStaticBuffers;
+
+public:
+   /*virtual void prepRenderImage(SceneRenderState *state);
+
+   bool setMeshAsset(const char* assetName);
+
+   virtual TSShape* getShape() { if (mMeshAsset)  return mMeshAsset->getShape(); else return NULL; }
+   virtual TSShapeInstance* getShapeInstance() { return mShapeInstance; }
+
+   Resource<TSShape> getShapeResource() { return mMeshAsset->getShapeResource(); }
+
+   void _onResourceChanged(const Torque::Path &path);
+
+   virtual bool castRayRendered(const Point3F &start, const Point3F &end, RayInfo *info);
+
+   void mountObjectToNode(SceneObject* objB, String node, MatrixF txfm);
+
+   virtual void onDynamicModified(const char* slotName, const char* newValue);
+
+   void changeMaterial(U32 slot, MaterialAsset* newMat);
+   bool setMatInstField(U32 slot, const char* field, const char* value);
+
+   virtual void onInspect();
+   virtual void onEndInspect();
+
+   virtual Vector<MatrixF> getNodeTransforms()
+   {
+      Vector<MatrixF> bob;
+      return bob;
+   }
+
+   virtual void setNodeTransforms(Vector<MatrixF> transforms)
+   {
+      return;
+   }*/
+
+   /*MeshRenderSystem()
+   {
+
+   }
+   virtual ~MeshRenderSystem()
+   {
+      smInterfaceList.clear();
+   }
+
+   static MeshComponentInterface* GetNewInterface()
+   {
+      smInterfaceList.increment();
+
+      return &smInterfaceList.last();
+   }
+
+   static void RemoveInterface(T* q)
+   {
+      smInterfaceList.erase(q);
+   }*/
+
+   //Core render function, which does all the real work
+   static void render(SceneManager *sceneManager, SceneRenderState* state);
+
+   //Render our particular interface's data
+   static void renderInterface(U32 interfaceIndex, SceneRenderState* state);
+
+   //Static Batch rendering
+   static void rebuildBuffers();
+
+   static U32 findBufferSetByMaterial(U32 matId);
+};

+ 34 - 0
Engine/source/T3D/systems/updateSystem.cpp

@@ -0,0 +1,34 @@
+#include "T3D/systems/updateSystem.h"
+
+void UpdateSystem::processTick()
+{
+   for (U32 i = 0; i < UpdateSystemInterface::all.size(); i++)
+   {
+      if (UpdateSystemInterface::all[i]->mIsEnabled)
+      {
+         //do work
+      }
+   }
+}
+
+void UpdateSystem::advanceTime(U32 _tickMS)
+{
+   for (U32 i = 0; i < UpdateSystemInterface::all.size(); i++)
+   {
+      if (UpdateSystemInterface::all[i]->mIsEnabled)
+      {
+         //do work
+      }
+   }
+}
+
+void UpdateSystem::interpolateTick(U32 _deltaMS)
+{
+   for (U32 i = 0; i < UpdateSystemInterface::all.size(); i++)
+   {
+      if (UpdateSystemInterface::all[i]->mIsEnabled)
+      {
+         //do work
+      }
+   }
+}

+ 16 - 0
Engine/source/T3D/systems/updateSystem.h

@@ -0,0 +1,16 @@
+#pragma once
+#include "componentSystem.h"
+
+class UpdateSystemInterface : public SystemInterface<UpdateSystemInterface>
+{
+public:
+   bool mIsEnabled;
+};
+
+class UpdateSystem
+{
+public:
+   static void processTick();
+   static void advanceTime(U32 _tickMS);
+   static void interpolateTick(U32 _deltaMS);
+};

+ 1 - 1
Engine/source/gui/containers/guiDragAndDropCtrl.h

@@ -67,7 +67,7 @@ class GuiDragAndDropControl : public GuiControl
 
    public:
    
-      GuiDragAndDropControl() {}
+      GuiDragAndDropControl();
 
       void startDragging(Point2I offset = Point2I(0, 0));
 

+ 3 - 8
Tools/CMake/torque3d.cmake

@@ -325,18 +325,13 @@ addPath("${srcDir}/T3D/decal")
 addPath("${srcDir}/T3D/sfx")
 addPath("${srcDir}/T3D/gameBase")
 addPath("${srcDir}/T3D/turret")
-addPath("${srcDir}/T3D/components/")
-addPath("${srcDir}/T3D/components/animation")
-addPath("${srcDir}/T3D/components/camera")
-addPath("${srcDir}/T3D/components/collision")
-addPath("${srcDir}/T3D/components/game")
-addPath("${srcDir}/T3D/components/physics")
-addPath("${srcDir}/T3D/components/render")
+addPathRec("${srcDir}/T3D/components/")
+addPathRec("${srcDir}/T3D/systems")
 
 addPath("${srcDir}/main/")
 addPath("${srcDir}/assets")
 addPath("${srcDir}/module")
-addPath("${srcDir}/T3D/assets")
+addPathRec("${srcDir}/T3D/assets")
 addPathRec("${srcDir}/persistence")
 addPathRec("${srcDir}/ts/collada")
 addPathRec("${srcDir}/ts/loader")